hjr vor 1 Monat
Commit
6046cf292d
100 geänderte Dateien mit 32535 neuen und 0 gelöschten Zeilen
  1. 18 0
      App.vue
  2. 20 0
      index.html
  3. 26 0
      main.js
  4. 72 0
      manifest.json
  5. 16 0
      node_modules/.bin/detect-libc
  6. 17 0
      node_modules/.bin/detect-libc.cmd
  7. 28 0
      node_modules/.bin/detect-libc.ps1
  8. 16 0
      node_modules/.bin/sass
  9. 17 0
      node_modules/.bin/sass.cmd
  10. 28 0
      node_modules/.bin/sass.ps1
  11. 291 0
      node_modules/.package-lock.json
  12. 21 0
      node_modules/@parcel/watcher-win32-x64/LICENSE
  13. 1 0
      node_modules/@parcel/watcher-win32-x64/README.md
  14. 30 0
      node_modules/@parcel/watcher-win32-x64/package.json
  15. BIN
      node_modules/@parcel/watcher-win32-x64/watcher.node
  16. 21 0
      node_modules/@parcel/watcher/LICENSE
  17. 135 0
      node_modules/@parcel/watcher/README.md
  18. 93 0
      node_modules/@parcel/watcher/binding.gyp
  19. 49 0
      node_modules/@parcel/watcher/index.d.ts
  20. 41 0
      node_modules/@parcel/watcher/index.js
  21. 48 0
      node_modules/@parcel/watcher/index.js.flow
  22. 88 0
      node_modules/@parcel/watcher/package.json
  23. 13 0
      node_modules/@parcel/watcher/scripts/build-from-source.js
  24. 182 0
      node_modules/@parcel/watcher/src/Backend.cc
  25. 37 0
      node_modules/@parcel/watcher/src/Backend.hh
  26. 113 0
      node_modules/@parcel/watcher/src/Debounce.cc
  27. 49 0
      node_modules/@parcel/watcher/src/Debounce.hh
  28. 152 0
      node_modules/@parcel/watcher/src/DirTree.cc
  29. 50 0
      node_modules/@parcel/watcher/src/DirTree.hh
  30. 109 0
      node_modules/@parcel/watcher/src/Event.hh
  31. 22 0
      node_modules/@parcel/watcher/src/Glob.cc
  32. 34 0
      node_modules/@parcel/watcher/src/Glob.hh
  33. 101 0
      node_modules/@parcel/watcher/src/PromiseRunner.hh
  34. 46 0
      node_modules/@parcel/watcher/src/Signal.hh
  35. 237 0
      node_modules/@parcel/watcher/src/Watcher.cc
  36. 73 0
      node_modules/@parcel/watcher/src/Watcher.hh
  37. 268 0
      node_modules/@parcel/watcher/src/binding.cc
  38. 306 0
      node_modules/@parcel/watcher/src/kqueue/KqueueBackend.cc
  39. 35 0
      node_modules/@parcel/watcher/src/kqueue/KqueueBackend.hh
  40. 232 0
      node_modules/@parcel/watcher/src/linux/InotifyBackend.cc
  41. 34 0
      node_modules/@parcel/watcher/src/linux/InotifyBackend.hh
  42. 338 0
      node_modules/@parcel/watcher/src/macos/FSEventsBackend.cc
  43. 20 0
      node_modules/@parcel/watcher/src/macos/FSEventsBackend.hh
  44. 41 0
      node_modules/@parcel/watcher/src/shared/BruteForceBackend.cc
  45. 25 0
      node_modules/@parcel/watcher/src/shared/BruteForceBackend.hh
  46. 50 0
      node_modules/@parcel/watcher/src/unix/fts.cc
  47. 77 0
      node_modules/@parcel/watcher/src/unix/legacy.cc
  48. 132 0
      node_modules/@parcel/watcher/src/wasm/WasmBackend.cc
  49. 34 0
      node_modules/@parcel/watcher/src/wasm/WasmBackend.hh
  50. 74 0
      node_modules/@parcel/watcher/src/wasm/include.h
  51. 302 0
      node_modules/@parcel/watcher/src/watchman/BSER.cc
  52. 69 0
      node_modules/@parcel/watcher/src/watchman/BSER.hh
  53. 175 0
      node_modules/@parcel/watcher/src/watchman/IPC.hh
  54. 338 0
      node_modules/@parcel/watcher/src/watchman/WatchmanBackend.cc
  55. 35 0
      node_modules/@parcel/watcher/src/watchman/WatchmanBackend.hh
  56. 282 0
      node_modules/@parcel/watcher/src/windows/WindowsBackend.cc
  57. 18 0
      node_modules/@parcel/watcher/src/windows/WindowsBackend.hh
  58. 44 0
      node_modules/@parcel/watcher/src/windows/win_utils.cc
  59. 11 0
      node_modules/@parcel/watcher/src/windows/win_utils.hh
  60. 77 0
      node_modules/@parcel/watcher/wrapper.js
  61. 21 0
      node_modules/braces/LICENSE
  62. 586 0
      node_modules/braces/README.md
  63. 170 0
      node_modules/braces/index.js
  64. 60 0
      node_modules/braces/lib/compile.js
  65. 57 0
      node_modules/braces/lib/constants.js
  66. 113 0
      node_modules/braces/lib/expand.js
  67. 331 0
      node_modules/braces/lib/parse.js
  68. 32 0
      node_modules/braces/lib/stringify.js
  69. 122 0
      node_modules/braces/lib/utils.js
  70. 77 0
      node_modules/braces/package.json
  71. 21 0
      node_modules/chokidar/LICENSE
  72. 305 0
      node_modules/chokidar/README.md
  73. 90 0
      node_modules/chokidar/esm/handler.d.ts
  74. 629 0
      node_modules/chokidar/esm/handler.js
  75. 215 0
      node_modules/chokidar/esm/index.d.ts
  76. 798 0
      node_modules/chokidar/esm/index.js
  77. 1 0
      node_modules/chokidar/esm/package.json
  78. 90 0
      node_modules/chokidar/handler.d.ts
  79. 635 0
      node_modules/chokidar/handler.js
  80. 215 0
      node_modules/chokidar/index.d.ts
  81. 804 0
      node_modules/chokidar/index.js
  82. 69 0
      node_modules/chokidar/package.json
  83. 7 0
      node_modules/detect-libc/.npmignore
  84. 201 0
      node_modules/detect-libc/LICENSE
  85. 78 0
      node_modules/detect-libc/README.md
  86. 18 0
      node_modules/detect-libc/bin/detect-libc.js
  87. 92 0
      node_modules/detect-libc/lib/detect-libc.js
  88. 35 0
      node_modules/detect-libc/package.json
  89. 21 0
      node_modules/fill-range/LICENSE
  90. 237 0
      node_modules/fill-range/README.md
  91. 248 0
      node_modules/fill-range/index.js
  92. 74 0
      node_modules/fill-range/package.json
  93. 21 0
      node_modules/immutable/LICENSE
  94. 731 0
      node_modules/immutable/README.md
  95. 5126 0
      node_modules/immutable/dist/immutable.d.ts
  96. 6182 0
      node_modules/immutable/dist/immutable.es.js
  97. 6236 0
      node_modules/immutable/dist/immutable.js
  98. 2414 0
      node_modules/immutable/dist/immutable.js.flow
  99. 24 0
      node_modules/immutable/dist/immutable.min.js
  100. 38 0
      node_modules/immutable/package.json

+ 18 - 0
App.vue

@@ -0,0 +1,18 @@
+<script>
+	export default {
+		onLaunch: function() {
+			console.log('App Launch')
+		},
+		onShow: function() {
+			console.log('App Show')
+		},
+		onHide: function() {
+			console.log('App Hide')
+		}
+	}
+</script>
+
+<style lang="scss">
+	/*每个页面公共css */
+	@import "@/uni_modules/uview-ui/index.scss";
+</style>

+ 20 - 0
index.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <script>
+      var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
+        CSS.supports('top: constant(a)'))
+      document.write(
+        '<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
+        (coverSupport ? ', viewport-fit=cover' : '') + '" />')
+    </script>
+    <title></title>
+    <!--preload-links-->
+    <!--app-context-->
+  </head>
+  <body>
+    <div id="app"><!--app-html--></div>
+    <script type="module" src="/main.js"></script>
+  </body>
+</html>

+ 26 - 0
main.js

@@ -0,0 +1,26 @@
+import App from './App'
+import uView from '@/uni_modules/uview-ui'
+import '@/static/css/fui.css'
+import '@/static/css/flex.css'
+import '@/static/css/uflex.css'
+// #ifndef VUE3
+import Vue from 'vue'
+import './uni.promisify.adaptor'
+Vue.config.productionTip = false
+App.mpType = 'app'
+Vue.use(uView)
+const app = new Vue({
+  ...App
+})
+app.$mount()
+// #endif
+
+// #ifdef VUE3
+import { createSSRApp } from 'vue'
+export function createApp() {
+  const app = createSSRApp(App)
+  return {
+    app
+  }
+}
+// #endif

+ 72 - 0
manifest.json

@@ -0,0 +1,72 @@
+{
+    "name" : "crowdfundingGang_APP",
+    "appid" : "__UNI__44DFB8B",
+    "description" : "",
+    "versionName" : "1.0.0",
+    "versionCode" : "100",
+    "transformPx" : false,
+    /* 5+App特有相关 */
+    "app-plus" : {
+        "usingComponents" : true,
+        "nvueStyleCompiler" : "uni-app",
+        "compilerVersion" : 3,
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        /* 模块配置 */
+        "modules" : {},
+        /* 应用发布信息 */
+        "distribute" : {
+            /* android打包配置 */
+            "android" : {
+                "permissions" : [
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+                ]
+            },
+            /* ios打包配置 */
+            "ios" : {},
+            /* SDK配置 */
+            "sdkConfigs" : {}
+        }
+    },
+    /* 快应用特有相关 */
+    "quickapp" : {},
+    /* 小程序特有相关 */
+    "mp-weixin" : {
+        "appid" : "",
+        "setting" : {
+            "urlCheck" : false
+        },
+        "usingComponents" : true
+    },
+    "mp-alipay" : {
+        "usingComponents" : true
+    },
+    "mp-baidu" : {
+        "usingComponents" : true
+    },
+    "mp-toutiao" : {
+        "usingComponents" : true
+    },
+    "uniStatistics" : {
+        "enable" : false
+    },
+    "vueVersion" : "2"
+}

+ 16 - 0
node_modules/.bin/detect-libc

@@ -0,0 +1,16 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+    *CYGWIN*|*MINGW*|*MSYS*)
+        if command -v cygpath > /dev/null 2>&1; then
+            basedir=`cygpath -w "$basedir"`
+        fi
+    ;;
+esac
+
+if [ -x "$basedir/node" ]; then
+  exec "$basedir/node"  "$basedir/../detect-libc/bin/detect-libc.js" "$@"
+else 
+  exec node  "$basedir/../detect-libc/bin/detect-libc.js" "$@"
+fi

+ 17 - 0
node_modules/.bin/detect-libc.cmd

@@ -0,0 +1,17 @@
+@ECHO off
+GOTO start
+:find_dp0
+SET dp0=%~dp0
+EXIT /b
+:start
+SETLOCAL
+CALL :find_dp0
+
+IF EXIST "%dp0%\node.exe" (
+  SET "_prog=%dp0%\node.exe"
+) ELSE (
+  SET "_prog=node"
+  SET PATHEXT=%PATHEXT:;.JS;=;%
+)
+
+endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%"  "%dp0%\..\detect-libc\bin\detect-libc.js" %*

+ 28 - 0
node_modules/.bin/detect-libc.ps1

@@ -0,0 +1,28 @@
+#!/usr/bin/env pwsh
+$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
+
+$exe=""
+if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
+  # Fix case when both the Windows and Linux builds of Node
+  # are installed in the same directory
+  $exe=".exe"
+}
+$ret=0
+if (Test-Path "$basedir/node$exe") {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "$basedir/node$exe"  "$basedir/../detect-libc/bin/detect-libc.js" $args
+  } else {
+    & "$basedir/node$exe"  "$basedir/../detect-libc/bin/detect-libc.js" $args
+  }
+  $ret=$LASTEXITCODE
+} else {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "node$exe"  "$basedir/../detect-libc/bin/detect-libc.js" $args
+  } else {
+    & "node$exe"  "$basedir/../detect-libc/bin/detect-libc.js" $args
+  }
+  $ret=$LASTEXITCODE
+}
+exit $ret

+ 16 - 0
node_modules/.bin/sass

@@ -0,0 +1,16 @@
+#!/bin/sh
+basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
+
+case `uname` in
+    *CYGWIN*|*MINGW*|*MSYS*)
+        if command -v cygpath > /dev/null 2>&1; then
+            basedir=`cygpath -w "$basedir"`
+        fi
+    ;;
+esac
+
+if [ -x "$basedir/node" ]; then
+  exec "$basedir/node"  "$basedir/../sass/sass.js" "$@"
+else 
+  exec node  "$basedir/../sass/sass.js" "$@"
+fi

+ 17 - 0
node_modules/.bin/sass.cmd

@@ -0,0 +1,17 @@
+@ECHO off
+GOTO start
+:find_dp0
+SET dp0=%~dp0
+EXIT /b
+:start
+SETLOCAL
+CALL :find_dp0
+
+IF EXIST "%dp0%\node.exe" (
+  SET "_prog=%dp0%\node.exe"
+) ELSE (
+  SET "_prog=node"
+  SET PATHEXT=%PATHEXT:;.JS;=;%
+)
+
+endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%"  "%dp0%\..\sass\sass.js" %*

+ 28 - 0
node_modules/.bin/sass.ps1

@@ -0,0 +1,28 @@
+#!/usr/bin/env pwsh
+$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
+
+$exe=""
+if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
+  # Fix case when both the Windows and Linux builds of Node
+  # are installed in the same directory
+  $exe=".exe"
+}
+$ret=0
+if (Test-Path "$basedir/node$exe") {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "$basedir/node$exe"  "$basedir/../sass/sass.js" $args
+  } else {
+    & "$basedir/node$exe"  "$basedir/../sass/sass.js" $args
+  }
+  $ret=$LASTEXITCODE
+} else {
+  # Support pipeline input
+  if ($MyInvocation.ExpectingInput) {
+    $input | & "node$exe"  "$basedir/../sass/sass.js" $args
+  } else {
+    & "node$exe"  "$basedir/../sass/sass.js" $args
+  }
+  $ret=$LASTEXITCODE
+}
+exit $ret

+ 291 - 0
node_modules/.package-lock.json

@@ -0,0 +1,291 @@
+{
+  "name": "crowdfundingGang_APP",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "node_modules/@parcel/watcher": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher/-/watcher-2.5.1.tgz",
+      "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==",
+      "dev": true,
+      "hasInstallScript": true,
+      "optional": true,
+      "dependencies": {
+        "detect-libc": "^1.0.3",
+        "is-glob": "^4.0.3",
+        "micromatch": "^4.0.5",
+        "node-addon-api": "^7.0.0"
+      },
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      },
+      "optionalDependencies": {
+        "@parcel/watcher-android-arm64": "2.5.1",
+        "@parcel/watcher-darwin-arm64": "2.5.1",
+        "@parcel/watcher-darwin-x64": "2.5.1",
+        "@parcel/watcher-freebsd-x64": "2.5.1",
+        "@parcel/watcher-linux-arm-glibc": "2.5.1",
+        "@parcel/watcher-linux-arm-musl": "2.5.1",
+        "@parcel/watcher-linux-arm64-glibc": "2.5.1",
+        "@parcel/watcher-linux-arm64-musl": "2.5.1",
+        "@parcel/watcher-linux-x64-glibc": "2.5.1",
+        "@parcel/watcher-linux-x64-musl": "2.5.1",
+        "@parcel/watcher-win32-arm64": "2.5.1",
+        "@parcel/watcher-win32-ia32": "2.5.1",
+        "@parcel/watcher-win32-x64": "2.5.1"
+      }
+    },
+    "node_modules/@parcel/watcher-win32-x64": {
+      "version": "2.5.1",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz",
+      "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/braces": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz",
+      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+      "dev": true,
+      "optional": true,
+      "dependencies": {
+        "fill-range": "^7.1.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/chokidar": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-4.0.3.tgz",
+      "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
+      "dev": true,
+      "dependencies": {
+        "readdirp": "^4.0.1"
+      },
+      "engines": {
+        "node": ">= 14.16.0"
+      },
+      "funding": {
+        "url": "https://paulmillr.com/funding/"
+      }
+    },
+    "node_modules/detect-libc": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-1.0.3.tgz",
+      "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
+      "dev": true,
+      "optional": true,
+      "bin": {
+        "detect-libc": "bin/detect-libc.js"
+      },
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/fill-range": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz",
+      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+      "dev": true,
+      "optional": true,
+      "dependencies": {
+        "to-regex-range": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/immutable": {
+      "version": "5.1.3",
+      "resolved": "https://registry.npmmirror.com/immutable/-/immutable-5.1.3.tgz",
+      "integrity": "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==",
+      "dev": true
+    },
+    "node_modules/is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+      "dev": true,
+      "optional": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-glob": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz",
+      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+      "dev": true,
+      "optional": true,
+      "dependencies": {
+        "is-extglob": "^2.1.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+      "dev": true,
+      "optional": true,
+      "engines": {
+        "node": ">=0.12.0"
+      }
+    },
+    "node_modules/micromatch": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.8.tgz",
+      "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+      "dev": true,
+      "optional": true,
+      "dependencies": {
+        "braces": "^3.0.3",
+        "picomatch": "^2.3.1"
+      },
+      "engines": {
+        "node": ">=8.6"
+      }
+    },
+    "node_modules/neo-async": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz",
+      "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
+      "dev": true
+    },
+    "node_modules/node-addon-api": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-7.1.1.tgz",
+      "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
+      "dev": true,
+      "optional": true
+    },
+    "node_modules/picomatch": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz",
+      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+      "dev": true,
+      "optional": true,
+      "engines": {
+        "node": ">=8.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/readdirp": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-4.1.2.tgz",
+      "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 14.18.0"
+      },
+      "funding": {
+        "type": "individual",
+        "url": "https://paulmillr.com/funding/"
+      }
+    },
+    "node_modules/sass": {
+      "version": "1.93.0",
+      "resolved": "https://registry.npmmirror.com/sass/-/sass-1.93.0.tgz",
+      "integrity": "sha512-CQi5/AzCwiubU3dSqRDJ93RfOfg/hhpW1l6wCIvolmehfwgCI35R/0QDs1+R+Ygrl8jFawwwIojE2w47/mf94A==",
+      "dev": true,
+      "dependencies": {
+        "chokidar": "^4.0.0",
+        "immutable": "^5.0.2",
+        "source-map-js": ">=0.6.2 <2.0.0"
+      },
+      "bin": {
+        "sass": "sass.js"
+      },
+      "engines": {
+        "node": ">=14.0.0"
+      },
+      "optionalDependencies": {
+        "@parcel/watcher": "^2.4.1"
+      }
+    },
+    "node_modules/sass-loader": {
+      "version": "16.0.5",
+      "resolved": "https://registry.npmmirror.com/sass-loader/-/sass-loader-16.0.5.tgz",
+      "integrity": "sha512-oL+CMBXrj6BZ/zOq4os+UECPL+bWqt6OAC6DWS8Ln8GZRcMDjlJ4JC3FBDuHJdYaFWIdKNIBYmtZtK2MaMkNIw==",
+      "dev": true,
+      "dependencies": {
+        "neo-async": "^2.6.2"
+      },
+      "engines": {
+        "node": ">= 18.12.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      },
+      "peerDependencies": {
+        "@rspack/core": "0.x || 1.x",
+        "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
+        "sass": "^1.3.0",
+        "sass-embedded": "*",
+        "webpack": "^5.0.0"
+      },
+      "peerDependenciesMeta": {
+        "@rspack/core": {
+          "optional": true
+        },
+        "node-sass": {
+          "optional": true
+        },
+        "sass": {
+          "optional": true
+        },
+        "sass-embedded": {
+          "optional": true
+        },
+        "webpack": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/source-map-js": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
+      "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "dev": true,
+      "optional": true,
+      "dependencies": {
+        "is-number": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=8.0"
+      }
+    }
+  }
+}

+ 21 - 0
node_modules/@parcel/watcher-win32-x64/LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017-present Devon Govett
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 1 - 0
node_modules/@parcel/watcher-win32-x64/README.md

@@ -0,0 +1 @@
+This is the win32-x64 build of @parcel/watcher. See https://github.com/parcel-bundler/watcher for details.

+ 30 - 0
node_modules/@parcel/watcher-win32-x64/package.json

@@ -0,0 +1,30 @@
+{
+  "name": "@parcel/watcher-win32-x64",
+  "version": "2.5.1",
+  "main": "watcher.node",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/parcel-bundler/watcher.git"
+  },
+  "description": "A native C++ Node module for querying and subscribing to filesystem events. Used by Parcel 2.",
+  "license": "MIT",
+  "publishConfig": {
+    "access": "public"
+  },
+  "funding": {
+    "type": "opencollective",
+    "url": "https://opencollective.com/parcel"
+  },
+  "files": [
+    "watcher.node"
+  ],
+  "engines": {
+    "node": ">= 10.0.0"
+  },
+  "os": [
+    "win32"
+  ],
+  "cpu": [
+    "x64"
+  ]
+}

BIN
node_modules/@parcel/watcher-win32-x64/watcher.node


+ 21 - 0
node_modules/@parcel/watcher/LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017-present Devon Govett
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 135 - 0
node_modules/@parcel/watcher/README.md

@@ -0,0 +1,135 @@
+# @parcel/watcher
+
+A native C++ Node module for querying and subscribing to filesystem events. Used by [Parcel 2](https://github.com/parcel-bundler/parcel).
+
+## Features
+
+- **Watch** - subscribe to realtime recursive directory change notifications when files or directories are created, updated, or deleted.
+- **Query** - performantly query for historical change events in a directory, even when your program is not running.
+- **Native** - implemented in C++ for performance and low-level integration with the operating system.
+- **Cross platform** - includes backends for macOS, Linux, Windows, FreeBSD, and Watchman.
+- **Performant** - events are throttled in C++ so the JavaScript thread is not overwhelmed during large filesystem changes (e.g. `git checkout` or `npm install`).
+- **Scalable** - tens of thousands of files can be watched or queried at once with good performance.
+
+## Example
+
+```javascript
+const watcher = require('@parcel/watcher');
+const path = require('path');
+
+// Subscribe to events
+let subscription = await watcher.subscribe(process.cwd(), (err, events) => {
+  console.log(events);
+});
+
+// later on...
+await subscription.unsubscribe();
+
+// Get events since some saved snapshot in the past
+let snapshotPath = path.join(process.cwd(), 'snapshot.txt');
+let events = await watcher.getEventsSince(process.cwd(), snapshotPath);
+
+// Save a snapshot for later
+await watcher.writeSnapshot(process.cwd(), snapshotPath);
+```
+
+## Watching
+
+`@parcel/watcher` supports subscribing to realtime notifications of changes in a directory. It works recursively, so changes in sub-directories will also be emitted.
+
+Events are throttled and coalesced for performance during large changes like `git checkout` or `npm install`, and a single notification will be emitted with all of the events at the end.
+
+Only one notification will be emitted per file. For example, if a file was both created and updated since the last event, you'll get only a `create` event. If a file is both created and deleted, you will not be notifed of that file. Renames cause two events: a `delete` for the old name, and a `create` for the new name.
+
+```javascript
+let subscription = await watcher.subscribe(process.cwd(), (err, events) => {
+  console.log(events);
+});
+```
+
+Events have two properties:
+
+- `type` - the event type: `create`, `update`, or `delete`.
+- `path` - the absolute path to the file or directory.
+
+To unsubscribe from change notifications, call the `unsubscribe` method on the returned subscription object.
+
+```javascript
+await subscription.unsubscribe();
+```
+
+`@parcel/watcher` has the following watcher backends, listed in priority order:
+
+- [FSEvents](https://developer.apple.com/documentation/coreservices/file_system_events) on macOS
+- [Watchman](https://facebook.github.io/watchman/) if installed
+- [inotify](http://man7.org/linux/man-pages/man7/inotify.7.html) on Linux
+- [ReadDirectoryChangesW](https://msdn.microsoft.com/en-us/library/windows/desktop/aa365465%28v%3Dvs.85%29.aspx) on Windows
+- [kqueue](https://man.freebsd.org/cgi/man.cgi?kqueue) on FreeBSD, or as an alternative to FSEvents on macOS
+
+You can specify the exact backend you wish to use by passing the `backend` option. If that backend is not available on the current platform, the default backend will be used instead. See below for the list of backend names that can be passed to the options.
+
+## Querying
+
+`@parcel/watcher` also supports querying for historical changes made in a directory, even when your program is not running. This makes it easy to invalidate a cache and re-build only the files that have changed, for example. It can be **significantly** faster than traversing the entire filesystem to determine what files changed, depending on the platform.
+
+In order to query for historical changes, you first need a previous snapshot to compare to. This can be saved to a file with the `writeSnapshot` function, e.g. just before your program exits.
+
+```javascript
+await watcher.writeSnapshot(dirPath, snapshotPath);
+```
+
+When your program starts up, you can query for changes that have occurred since that snapshot using the `getEventsSince` function.
+
+```javascript
+let events = await watcher.getEventsSince(dirPath, snapshotPath);
+```
+
+The events returned are exactly the same as the events that would be passed to the `subscribe` callback (see above).
+
+`@parcel/watcher` has the following watcher backends, listed in priority order:
+
+- [FSEvents](https://developer.apple.com/documentation/coreservices/file_system_events) on macOS
+- [Watchman](https://facebook.github.io/watchman/) if installed
+- [fts](http://man7.org/linux/man-pages/man3/fts.3.html) (brute force) on Linux and FreeBSD
+- [FindFirstFile](https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-findfirstfilea) (brute force) on Windows
+
+The FSEvents (macOS) and Watchman backends are significantly more performant than the brute force backends used by default on Linux and Windows, for example returning results in miliseconds instead of seconds for large directory trees. This is because a background daemon monitoring filesystem changes on those platforms allows us to query cached data rather than traversing the filesystem manually (brute force).
+
+macOS has good performance with FSEvents by default. For the best performance on other platforms, install [Watchman](https://facebook.github.io/watchman/) and it will be used by `@parcel/watcher` automatically.
+
+You can specify the exact backend you wish to use by passing the `backend` option. If that backend is not available on the current platform, the default backend will be used instead. See below for the list of backend names that can be passed to the options.
+
+## Options
+
+All of the APIs in `@parcel/watcher` support the following options, which are passed as an object as the last function argument.
+
+- `ignore` - an array of paths or glob patterns to ignore. uses [`is-glob`](https://github.com/micromatch/is-glob) to distinguish paths from globs. glob patterns are parsed with [`micromatch`](https://github.com/micromatch/micromatch) (see [features](https://github.com/micromatch/micromatch#matching-features)).
+  - paths can be relative or absolute and can either be files or directories. No events will be emitted about these files or directories or their children.
+  - glob patterns match on relative paths from the root that is watched. No events will be emitted for matching paths.
+- `backend` - the name of an explicitly chosen backend to use. Allowed options are `"fs-events"`, `"watchman"`, `"inotify"`, `"kqueue"`, `"windows"`, or `"brute-force"` (only for querying). If the specified backend is not available on the current platform, the default backend will be used instead.
+
+## WASM
+
+The `@parcel/watcher-wasm` package can be used in place of `@parcel/watcher` on unsupported platforms. It relies on the Node `fs` module, so in non-Node environments such as browsers, an `fs` polyfill will be needed.
+
+**Note**: the WASM implementation is significantly less efficient than the native implementations because it must crawl the file system to watch each directory individually. Use the native `@parcel/watcher` package wherever possible.
+
+```js
+import {subscribe} from '@parcel/watcher-wasm';
+
+// Use the module as documented above.
+subscribe(/* ... */);
+```
+
+## Who is using this?
+
+- [Parcel 2](https://parceljs.org/)
+- [VSCode](https://code.visualstudio.com/updates/v1_62#_file-watching-changes)
+- [Tailwind CSS Intellisense](https://github.com/tailwindlabs/tailwindcss-intellisense)
+- [Gatsby Cloud](https://twitter.com/chatsidhartha/status/1435647412828196867)
+- [Nx](https://nx.dev)
+- [Nuxt](https://nuxt.com)
+
+## License
+
+MIT

+ 93 - 0
node_modules/@parcel/watcher/binding.gyp

@@ -0,0 +1,93 @@
+{
+  "targets": [
+    {
+      "target_name": "watcher",
+      "defines": [ "NAPI_DISABLE_CPP_EXCEPTIONS" ],
+      "sources": [ "src/binding.cc", "src/Watcher.cc", "src/Backend.cc", "src/DirTree.cc", "src/Glob.cc", "src/Debounce.cc" ],
+      "include_dirs" : ["<!(node -p \"require('node-addon-api').include_dir\")"],
+      'cflags!': [ '-fno-exceptions', '-std=c++17' ],
+      'cflags_cc!': [ '-fno-exceptions', '-std=c++17' ],
+      "conditions": [
+        ['OS=="mac"', {
+          "sources": [
+            "src/watchman/BSER.cc",
+            "src/watchman/WatchmanBackend.cc",
+            "src/shared/BruteForceBackend.cc",
+            "src/unix/fts.cc",
+            "src/macos/FSEventsBackend.cc",
+            "src/kqueue/KqueueBackend.cc"
+          ],
+          "link_settings": {
+            "libraries": ["CoreServices.framework"]
+          },
+          "defines": [
+            "WATCHMAN",
+            "BRUTE_FORCE",
+            "FS_EVENTS",
+            "KQUEUE"
+          ],
+          "xcode_settings": {
+            "GCC_ENABLE_CPP_EXCEPTIONS": "YES"
+          }
+        }],
+        ['OS=="mac" and target_arch=="arm64"', {
+          "xcode_settings": {
+            "ARCHS": ["arm64"]
+          }
+        }],
+        ['OS=="linux" or OS=="android"', {
+          "sources": [
+            "src/watchman/BSER.cc",
+            "src/watchman/WatchmanBackend.cc",
+            "src/shared/BruteForceBackend.cc",
+            "src/linux/InotifyBackend.cc",
+            "src/unix/legacy.cc"
+          ],
+          "defines": [
+            "WATCHMAN",
+            "INOTIFY",
+            "BRUTE_FORCE"
+          ]
+        }],
+        ['OS=="win"', {
+          "sources": [
+            "src/watchman/BSER.cc",
+            "src/watchman/WatchmanBackend.cc",
+            "src/shared/BruteForceBackend.cc",
+            "src/windows/WindowsBackend.cc",
+            "src/windows/win_utils.cc"
+          ],
+          "defines": [
+            "WATCHMAN",
+            "WINDOWS",
+            "BRUTE_FORCE"
+          ],
+          "msvs_settings": {
+            "VCCLCompilerTool": {
+              "ExceptionHandling": 1,  # /EHsc
+              "AdditionalOptions": ['-std:c++17']
+            }
+          }
+        }],
+        ['OS=="freebsd"', {
+          "sources": [
+            "src/watchman/BSER.cc",
+            "src/watchman/WatchmanBackend.cc",
+            "src/shared/BruteForceBackend.cc",
+            "src/unix/fts.cc",
+            "src/kqueue/KqueueBackend.cc"
+          ],
+          "defines": [
+            "WATCHMAN",
+            "BRUTE_FORCE",
+            "KQUEUE"
+          ]
+        }]
+      ]
+    }
+  ],
+  "variables": {
+    "openssl_fips": "",
+    "node_use_dtrace": "false"
+  }
+}

+ 49 - 0
node_modules/@parcel/watcher/index.d.ts

@@ -0,0 +1,49 @@
+declare type FilePath = string;
+declare type GlobPattern = string;
+
+declare namespace ParcelWatcher {
+  export type BackendType = 
+    | 'fs-events'
+    | 'watchman'
+    | 'inotify'
+    | 'windows'
+    | 'brute-force';
+  export type EventType = 'create' | 'update' | 'delete';
+  export interface Options {
+    ignore?: (FilePath|GlobPattern)[];
+    backend?: BackendType;
+  }
+  export type SubscribeCallback = (
+    err: Error | null,
+    events: Event[]
+  ) => unknown;
+  export interface AsyncSubscription {
+    unsubscribe(): Promise<void>;
+  }
+  export interface Event {
+    path: FilePath;
+    type: EventType;
+  }
+  export function getEventsSince(
+    dir: FilePath,
+    snapshot: FilePath,
+    opts?: Options
+  ): Promise<Event[]>;
+  export function subscribe(
+    dir: FilePath,
+    fn: SubscribeCallback,
+    opts?: Options
+  ): Promise<AsyncSubscription>;
+  export function unsubscribe(
+    dir: FilePath,
+    fn: SubscribeCallback,
+    opts?: Options
+  ): Promise<void>;
+  export function writeSnapshot(
+    dir: FilePath,
+    snapshot: FilePath,
+    opts?: Options
+  ): Promise<FilePath>;
+}
+
+export = ParcelWatcher;

+ 41 - 0
node_modules/@parcel/watcher/index.js

@@ -0,0 +1,41 @@
+const {createWrapper} = require('./wrapper');
+
+let name = `@parcel/watcher-${process.platform}-${process.arch}`;
+if (process.platform === 'linux') {
+  const { MUSL, family } = require('detect-libc');
+  if (family === MUSL) {
+    name += '-musl';
+  } else {
+    name += '-glibc';
+  }
+}
+
+let binding;
+try {
+  binding = require(name);
+} catch (err) {
+  handleError(err);
+  try {
+    binding = require('./build/Release/watcher.node');
+  } catch (err) {
+    handleError(err);
+    try {
+      binding = require('./build/Debug/watcher.node');
+    } catch (err) {
+      handleError(err);
+      throw new Error(`No prebuild or local build of @parcel/watcher found. Tried ${name}. Please ensure it is installed (don't use --no-optional when installing with npm). Otherwise it is possible we don't support your platform yet. If this is the case, please report an issue to https://github.com/parcel-bundler/watcher.`);
+    }
+  }
+}
+
+function handleError(err) {
+  if (err?.code !== 'MODULE_NOT_FOUND') {
+    throw err;
+  }
+}
+
+const wrapper = createWrapper(binding);
+exports.writeSnapshot = wrapper.writeSnapshot;
+exports.getEventsSince = wrapper.getEventsSince;
+exports.subscribe = wrapper.subscribe;
+exports.unsubscribe = wrapper.unsubscribe;

+ 48 - 0
node_modules/@parcel/watcher/index.js.flow

@@ -0,0 +1,48 @@
+// @flow
+declare type FilePath = string;
+declare type GlobPattern = string;
+
+export type BackendType = 
+  | 'fs-events'
+  | 'watchman'
+  | 'inotify'
+  | 'windows'
+  | 'brute-force';
+export type EventType = 'create' | 'update' | 'delete';
+export interface Options {
+  ignore?: Array<FilePath | GlobPattern>,
+  backend?: BackendType
+}
+export type SubscribeCallback = (
+  err: ?Error,
+  events: Array<Event>
+) => mixed;
+export interface AsyncSubscription {
+  unsubscribe(): Promise<void>
+}
+export interface Event {
+  path: FilePath,
+  type: EventType
+}
+declare module.exports: {
+  getEventsSince(
+    dir: FilePath,
+    snapshot: FilePath,
+    opts?: Options
+  ): Promise<Array<Event>>,
+  subscribe(
+    dir: FilePath,
+    fn: SubscribeCallback,
+    opts?: Options
+  ): Promise<AsyncSubscription>,
+  unsubscribe(
+    dir: FilePath,
+    fn: SubscribeCallback,
+    opts?: Options
+  ): Promise<void>,
+  writeSnapshot(
+    dir: FilePath,
+    snapshot: FilePath,
+    opts?: Options
+  ): Promise<FilePath>
+}

+ 88 - 0
node_modules/@parcel/watcher/package.json

@@ -0,0 +1,88 @@
+{
+  "name": "@parcel/watcher",
+  "version": "2.5.1",
+  "main": "index.js",
+  "types": "index.d.ts",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/parcel-bundler/watcher.git"
+  },
+  "description": "A native C++ Node module for querying and subscribing to filesystem events. Used by Parcel 2.",
+  "license": "MIT",
+  "publishConfig": {
+    "access": "public"
+  },
+  "funding": {
+    "type": "opencollective",
+    "url": "https://opencollective.com/parcel"
+  },
+  "files": [
+    "index.js",
+    "index.js.flow",
+    "index.d.ts",
+    "wrapper.js",
+    "package.json",
+    "README.md",
+    "LICENSE",
+    "src",
+    "scripts/build-from-source.js",
+    "binding.gyp"
+  ],
+  "scripts": {
+    "prebuild": "prebuildify --napi --strip --tag-libc",
+    "format": "prettier --write \"./**/*.{js,json,md}\"",
+    "build": "node-gyp rebuild",
+    "install": "node scripts/build-from-source.js",
+    "test": "mocha"
+  },
+  "engines": {
+    "node": ">= 10.0.0"
+  },
+  "husky": {
+    "hooks": {
+      "pre-commit": "lint-staged"
+    }
+  },
+  "lint-staged": {
+    "*.{js,json,md}": [
+      "prettier --write",
+      "git add"
+    ]
+  },
+  "dependencies": {
+    "detect-libc": "^1.0.3",
+    "is-glob": "^4.0.3",
+    "micromatch": "^4.0.5",
+    "node-addon-api": "^7.0.0"
+  },
+  "devDependencies": {
+    "esbuild": "^0.19.8",
+    "fs-extra": "^10.0.0",
+    "husky": "^7.0.2",
+    "lint-staged": "^11.1.2",
+    "mocha": "^9.1.1",
+    "napi-wasm": "^1.1.0",
+    "prebuildify": "^6.0.1",
+    "prettier": "^2.3.2"
+  },
+  "binary": {
+    "napi_versions": [
+      3
+    ]
+  },
+  "optionalDependencies": {
+    "@parcel/watcher-darwin-x64": "2.5.1",
+    "@parcel/watcher-darwin-arm64": "2.5.1",
+    "@parcel/watcher-win32-x64": "2.5.1",
+    "@parcel/watcher-win32-arm64": "2.5.1",
+    "@parcel/watcher-win32-ia32": "2.5.1",
+    "@parcel/watcher-linux-x64-glibc": "2.5.1",
+    "@parcel/watcher-linux-x64-musl": "2.5.1",
+    "@parcel/watcher-linux-arm64-glibc": "2.5.1",
+    "@parcel/watcher-linux-arm64-musl": "2.5.1",
+    "@parcel/watcher-linux-arm-glibc": "2.5.1",
+    "@parcel/watcher-linux-arm-musl": "2.5.1",
+    "@parcel/watcher-android-arm64": "2.5.1",
+    "@parcel/watcher-freebsd-x64": "2.5.1"
+  }
+}

+ 13 - 0
node_modules/@parcel/watcher/scripts/build-from-source.js

@@ -0,0 +1,13 @@
+#!/usr/bin/env node
+
+const {spawn} = require('child_process');
+
+if (process.env.npm_config_build_from_source === 'true') {
+  build();
+}
+
+function build() {
+  spawn('node-gyp', ['rebuild'], { stdio: 'inherit', shell: true }).on('exit', function (code) {
+    process.exit(code);
+  });
+}

+ 182 - 0
node_modules/@parcel/watcher/src/Backend.cc

@@ -0,0 +1,182 @@
+#ifdef FS_EVENTS
+#include "macos/FSEventsBackend.hh"
+#endif
+#ifdef WATCHMAN
+#include "watchman/WatchmanBackend.hh"
+#endif
+#ifdef WINDOWS
+#include "windows/WindowsBackend.hh"
+#endif
+#ifdef INOTIFY
+#include "linux/InotifyBackend.hh"
+#endif
+#ifdef KQUEUE
+#include "kqueue/KqueueBackend.hh"
+#endif
+#ifdef __wasm32__
+#include "wasm/WasmBackend.hh"
+#endif
+#include "shared/BruteForceBackend.hh"
+
+#include "Backend.hh"
+#include <unordered_map>
+
+static std::unordered_map<std::string, std::shared_ptr<Backend>> sharedBackends;
+
+std::shared_ptr<Backend> getBackend(std::string backend) {
+  // Use FSEvents on macOS by default.
+  // Use watchman by default if available on other platforms.
+  // Fall back to brute force.
+  #ifdef FS_EVENTS
+    if (backend == "fs-events" || backend == "default") {
+      return std::make_shared<FSEventsBackend>();
+    }
+  #endif
+  #ifdef WATCHMAN
+    if ((backend == "watchman" || backend == "default") && WatchmanBackend::checkAvailable()) {
+      return std::make_shared<WatchmanBackend>();
+    }
+  #endif
+  #ifdef WINDOWS
+    if (backend == "windows" || backend == "default") {
+      return std::make_shared<WindowsBackend>();
+    }
+  #endif
+  #ifdef INOTIFY
+    if (backend == "inotify" || backend == "default") {
+      return std::make_shared<InotifyBackend>();
+    }
+  #endif
+  #ifdef KQUEUE
+    if (backend == "kqueue" || backend == "default") {
+      return std::make_shared<KqueueBackend>();
+    }
+  #endif
+  #ifdef __wasm32__
+    if (backend == "wasm" || backend == "default") {
+      return std::make_shared<WasmBackend>();
+    }
+  #endif
+  if (backend == "brute-force" || backend == "default") {
+    return std::make_shared<BruteForceBackend>();
+  }
+
+  return nullptr;
+}
+
+std::shared_ptr<Backend> Backend::getShared(std::string backend) {
+  auto found = sharedBackends.find(backend);
+  if (found != sharedBackends.end()) {
+    return found->second;
+  }
+
+  auto result = getBackend(backend);
+  if (!result) {
+    return getShared("default");
+  }
+
+  result->run();
+  sharedBackends.emplace(backend, result);
+  return result;
+}
+
+void removeShared(Backend *backend) {
+  for (auto it = sharedBackends.begin(); it != sharedBackends.end(); it++) {
+    if (it->second.get() == backend) {
+      sharedBackends.erase(it);
+      break;
+    }
+  }
+
+  // Free up memory.
+  if (sharedBackends.size() == 0) {
+    sharedBackends.rehash(0);
+  }
+}
+
+void Backend::run() {
+  #ifndef __wasm32__
+    mThread = std::thread([this] () {
+      try {
+        start();
+      } catch (std::exception &err) {
+        handleError(err);
+      }
+    });
+
+    if (mThread.joinable()) {
+      mStartedSignal.wait();
+    }
+  #else
+    try {
+      start();
+    } catch (std::exception &err) {
+      handleError(err);
+    }
+  #endif
+}
+
+void Backend::notifyStarted() {
+  mStartedSignal.notify();
+}
+
+void Backend::start() {
+  notifyStarted();
+}
+
+Backend::~Backend() {
+  #ifndef __wasm32__
+    // Wait for thread to stop
+    if (mThread.joinable()) {
+      // If the backend is being destroyed from the thread itself, detach, otherwise join.
+      if (mThread.get_id() == std::this_thread::get_id()) {
+        mThread.detach();
+      } else {
+        mThread.join();
+      }
+    }
+  #endif
+}
+
+void Backend::watch(WatcherRef watcher) {
+  std::unique_lock<std::mutex> lock(mMutex);
+  auto res = mSubscriptions.find(watcher);
+  if (res == mSubscriptions.end()) {
+    try {
+      this->subscribe(watcher);
+      mSubscriptions.insert(watcher);
+    } catch (std::exception &err) {
+      unref();
+      throw;
+    }
+  }
+}
+
+void Backend::unwatch(WatcherRef watcher) {
+  std::unique_lock<std::mutex> lock(mMutex);
+  size_t deleted = mSubscriptions.erase(watcher);
+  if (deleted > 0) {
+    this->unsubscribe(watcher);
+    unref();
+  }
+}
+
+void Backend::unref() {
+  if (mSubscriptions.size() == 0) {
+    removeShared(this);
+  }
+}
+
+void Backend::handleWatcherError(WatcherError &err) {
+  unwatch(err.mWatcher);
+  err.mWatcher->notifyError(err);
+}
+
+void Backend::handleError(std::exception &err) {
+  std::unique_lock<std::mutex> lock(mMutex);
+  for (auto it = mSubscriptions.begin(); it != mSubscriptions.end(); it++) {
+    (*it)->notifyError(err);
+  }
+
+  removeShared(this);
+}

+ 37 - 0
node_modules/@parcel/watcher/src/Backend.hh

@@ -0,0 +1,37 @@
+#ifndef BACKEND_H
+#define BACKEND_H
+
+#include "Event.hh"
+#include "Watcher.hh"
+#include "Signal.hh"
+#include <thread>
+
+class Backend {
+public:
+  virtual ~Backend();
+  void run();
+  void notifyStarted();
+
+  virtual void start();
+  virtual void writeSnapshot(WatcherRef watcher, std::string *snapshotPath) = 0;
+  virtual void getEventsSince(WatcherRef watcher, std::string *snapshotPath) = 0;
+  virtual void subscribe(WatcherRef watcher) = 0;
+  virtual void unsubscribe(WatcherRef watcher) = 0;
+
+  static std::shared_ptr<Backend> getShared(std::string backend);
+
+  void watch(WatcherRef watcher);
+  void unwatch(WatcherRef watcher);
+  void unref();
+  void handleWatcherError(WatcherError &err);
+
+  std::mutex mMutex;
+  std::thread mThread;
+private:
+  std::unordered_set<WatcherRef> mSubscriptions;
+  Signal mStartedSignal;
+
+  void handleError(std::exception &err);
+};
+
+#endif

+ 113 - 0
node_modules/@parcel/watcher/src/Debounce.cc

@@ -0,0 +1,113 @@
+#include "Debounce.hh"
+
+#ifdef __wasm32__
+extern "C" void on_timeout(void *ctx) {
+  Debounce *debounce = (Debounce *)ctx;
+  debounce->notify();
+}
+#endif
+
+std::shared_ptr<Debounce> Debounce::getShared() {
+  static std::weak_ptr<Debounce> sharedInstance;
+  std::shared_ptr<Debounce> shared = sharedInstance.lock();
+  if (!shared) {
+    shared = std::make_shared<Debounce>();
+    sharedInstance = shared;
+  }
+
+  return shared;
+}
+
+Debounce::Debounce() {
+  mRunning = true;
+  #ifndef __wasm32__
+    mThread = std::thread([this] () {
+      loop();
+    });
+  #endif
+}
+
+Debounce::~Debounce() {
+  mRunning = false;
+  #ifndef __wasm32__
+    mWaitSignal.notify();
+    mThread.join();
+  #endif
+}
+
+void Debounce::add(void *key, std::function<void()> cb) {
+  std::unique_lock<std::mutex> lock(mMutex);
+  mCallbacks.emplace(key, cb);
+}
+
+void Debounce::remove(void *key) {
+  std::unique_lock<std::mutex> lock(mMutex);
+  mCallbacks.erase(key);
+}
+
+void Debounce::trigger() {
+  std::unique_lock<std::mutex> lock(mMutex);
+  #ifdef __wasm32__
+    notifyIfReady();
+  #else
+    mWaitSignal.notify();
+  #endif
+}
+
+#ifndef __wasm32__
+void Debounce::loop() {
+  while (mRunning) {
+    mWaitSignal.wait();
+    if (!mRunning) {
+      break;
+    }
+
+    notifyIfReady();
+  }
+}
+#endif
+
+void Debounce::notifyIfReady() {
+  if (!mRunning) {
+    return;
+  }
+
+  // If we haven't seen an event in more than the maximum wait time, notify callbacks immediately
+  // to ensure that we don't wait forever. Otherwise, wait for the minimum wait time and batch
+  // subsequent fast changes. This also means the first file change in a batch is notified immediately,
+  // separately from the rest of the batch. This seems like an acceptable tradeoff if the common case
+  // is that only a single file was updated at a time.
+  auto time = std::chrono::steady_clock::now();
+  if ((time - mLastTime) > std::chrono::milliseconds(MAX_WAIT_TIME)) {
+    mLastTime = time;
+    notify();
+  } else {
+    wait();
+  }
+}
+
+void Debounce::wait() {
+  #ifdef __wasm32__
+    clear_timeout(mTimeout);
+    mTimeout = set_timeout(MIN_WAIT_TIME, this);
+  #else
+    auto status = mWaitSignal.waitFor(std::chrono::milliseconds(MIN_WAIT_TIME));
+    if (mRunning && (status == std::cv_status::timeout)) {
+      notify();
+    }
+  #endif
+}
+
+void Debounce::notify() {
+  std::unique_lock<std::mutex> lock(mMutex);
+
+  mLastTime = std::chrono::steady_clock::now();
+  for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
+    auto cb = it->second;
+    cb();
+  }
+
+  #ifndef __wasm32__
+    mWaitSignal.reset();
+  #endif
+}

+ 49 - 0
node_modules/@parcel/watcher/src/Debounce.hh

@@ -0,0 +1,49 @@
+#ifndef DEBOUNCE_H
+#define DEBOUNCE_H
+
+#include <thread>
+#include <unordered_map>
+#include <functional>
+#include "Signal.hh"
+
+#define MIN_WAIT_TIME 50
+#define MAX_WAIT_TIME 500
+
+#ifdef __wasm32__
+extern "C" {
+  int set_timeout(int ms, void *ctx);
+  void clear_timeout(int timeout);
+  void on_timeout(void *ctx);
+};
+#endif
+
+class Debounce {
+public:
+  static std::shared_ptr<Debounce> getShared();
+
+  Debounce();
+  ~Debounce();
+
+  void add(void *key, std::function<void()> cb);
+  void remove(void *key);
+  void trigger();
+  void notify();
+
+private:
+  bool mRunning;
+  std::mutex mMutex;
+  #ifdef __wasm32__
+    int mTimeout;
+  #else
+    Signal mWaitSignal;
+    std::thread mThread;
+  #endif
+  std::unordered_map<void *, std::function<void()>> mCallbacks;
+  std::chrono::time_point<std::chrono::steady_clock> mLastTime;
+
+  void loop();
+  void notifyIfReady();
+  void wait();
+};
+
+#endif

+ 152 - 0
node_modules/@parcel/watcher/src/DirTree.cc

@@ -0,0 +1,152 @@
+#include "DirTree.hh"
+#include <inttypes.h>
+
+static std::mutex mDirCacheMutex;
+static std::unordered_map<std::string, std::weak_ptr<DirTree>> dirTreeCache;
+
+struct DirTreeDeleter {
+  void operator()(DirTree *tree) {
+    std::lock_guard<std::mutex> lock(mDirCacheMutex);
+    dirTreeCache.erase(tree->root);
+    delete tree;
+
+    // Free up memory.
+    if (dirTreeCache.size() == 0) {
+      dirTreeCache.rehash(0);
+    }
+  }
+};
+
+std::shared_ptr<DirTree> DirTree::getCached(std::string root) {
+  std::lock_guard<std::mutex> lock(mDirCacheMutex);
+
+  auto found = dirTreeCache.find(root);
+  std::shared_ptr<DirTree> tree;
+
+  // Use cached tree, or create an empty one.
+  if (found != dirTreeCache.end()) {
+    tree = found->second.lock();
+  } else {
+    tree = std::shared_ptr<DirTree>(new DirTree(root), DirTreeDeleter());
+    dirTreeCache.emplace(root, tree);
+  }
+
+  return tree;
+}
+
+DirTree::DirTree(std::string root, FILE *f) : root(root), isComplete(true) {
+  size_t size;
+  if (fscanf(f, "%zu", &size)) {
+    for (size_t i = 0; i < size; i++) {
+      DirEntry entry(f);
+      entries.emplace(entry.path, entry);
+    }
+  }
+}
+
+// Internal find method that has no lock
+DirEntry *DirTree::_find(std::string path) {
+  auto found = entries.find(path);
+  if (found == entries.end()) {
+    return NULL;
+  }
+
+  return &found->second;
+}
+
+DirEntry *DirTree::add(std::string path, uint64_t mtime, bool isDir) {
+  std::lock_guard<std::mutex> lock(mMutex);
+
+  DirEntry entry(path, mtime, isDir);
+  auto it = entries.emplace(entry.path, entry);
+  return &it.first->second;
+}
+
+DirEntry *DirTree::find(std::string path) {
+  std::lock_guard<std::mutex> lock(mMutex);
+  return _find(path);
+}
+
+DirEntry *DirTree::update(std::string path, uint64_t mtime) {
+  std::lock_guard<std::mutex> lock(mMutex);
+
+  DirEntry *found = _find(path);
+  if (found) {
+    found->mtime = mtime;
+  }
+
+  return found;
+}
+
+void DirTree::remove(std::string path) {
+  std::lock_guard<std::mutex> lock(mMutex);
+
+  DirEntry *found = _find(path);
+
+  // Remove all sub-entries if this is a directory
+  if (found && found->isDir) {
+    std::string pathStart = path + DIR_SEP;
+    for (auto it = entries.begin(); it != entries.end();) {
+      if (it->first.rfind(pathStart, 0) == 0) {
+        it = entries.erase(it);
+      } else {
+        it++;
+      }
+    }
+  }
+
+  entries.erase(path);
+}
+
+void DirTree::write(FILE *f) {
+  std::lock_guard<std::mutex> lock(mMutex);
+
+  fprintf(f, "%zu\n", entries.size());
+  for (auto it = entries.begin(); it != entries.end(); it++) {
+    it->second.write(f);
+  }
+}
+
+void DirTree::getChanges(DirTree *snapshot, EventList &events) {
+  std::lock_guard<std::mutex> lock(mMutex);
+  std::lock_guard<std::mutex> snapshotLock(snapshot->mMutex);
+
+  for (auto it = entries.begin(); it != entries.end(); it++) {
+    auto found = snapshot->entries.find(it->first);
+    if (found == snapshot->entries.end()) {
+      events.create(it->second.path);
+    } else if (found->second.mtime != it->second.mtime && !found->second.isDir && !it->second.isDir) {
+      events.update(it->second.path);
+    }
+  }
+
+  for (auto it = snapshot->entries.begin(); it != snapshot->entries.end(); it++) {
+    size_t count = entries.count(it->first);
+    if (count == 0) {
+      events.remove(it->second.path);
+    }
+  }
+}
+
+DirEntry::DirEntry(std::string p, uint64_t t, bool d) {
+  path = p;
+  mtime = t;
+  isDir = d;
+  state = NULL;
+}
+
+DirEntry::DirEntry(FILE *f) {
+  size_t size;
+  if (fscanf(f, "%zu", &size)) {
+    path.resize(size);
+    if (fread(&path[0], sizeof(char), size, f)) {
+      int d = 0;
+      fscanf(f, "%" PRIu64 " %d\n", &mtime, &d);
+      isDir = d == 1;
+    }
+  }
+}
+
+void DirEntry::write(FILE *f) const {
+  fprintf(f, "%zu%s%" PRIu64 " %d\n", path.size(), path.c_str(), mtime, isDir);
+}

+ 50 - 0
node_modules/@parcel/watcher/src/DirTree.hh

@@ -0,0 +1,50 @@
+#ifndef DIR_TREE_H
+#define DIR_TREE_H
+
+#include <string>
+#include <unordered_map>
+#include <memory>
+#include "Event.hh"
+
+#ifdef _WIN32
+#define DIR_SEP "\\"
+#else
+#define DIR_SEP "/"
+#endif
+
+struct DirEntry {
+  std::string path;
+  uint64_t mtime;
+  bool isDir;
+  mutable void *state;
+
+  DirEntry(std::string p, uint64_t t, bool d);
+  DirEntry(FILE *f);
+  void write(FILE *f) const;
+  bool operator==(const DirEntry &other) const {
+    return path == other.path;
+  }
+};
+
+class DirTree {
+public:
+  static std::shared_ptr<DirTree> getCached(std::string root);
+  DirTree(std::string root) : root(root), isComplete(false) {}
+  DirTree(std::string root, FILE *f);
+  DirEntry *add(std::string path, uint64_t mtime, bool isDir);
+  DirEntry *find(std::string path);
+  DirEntry *update(std::string path, uint64_t mtime);
+  void remove(std::string path);
+  void write(FILE *f);
+  void getChanges(DirTree *snapshot, EventList &events);
+
+  std::mutex mMutex;
+  std::string root;
+  bool isComplete;
+  std::unordered_map<std::string, DirEntry> entries;
+
+private:
+  DirEntry *_find(std::string path);
+};
+
+#endif

+ 109 - 0
node_modules/@parcel/watcher/src/Event.hh

@@ -0,0 +1,109 @@
+#ifndef EVENT_H
+#define EVENT_H
+
+#include <string>
+#include <node_api.h>
+#include "wasm/include.h"
+#include <napi.h>
+#include <mutex>
+#include <map>
+#include <optional>
+
+using namespace Napi;
+
+struct Event {
+  std::string path;
+  bool isCreated;
+  bool isDeleted;
+  Event(std::string path) : path(path), isCreated(false), isDeleted(false) {}
+
+  Value toJS(const Env& env) {
+    EscapableHandleScope scope(env);
+    Object res = Object::New(env);
+    std::string type = isCreated ? "create" : isDeleted ? "delete" : "update";
+    res.Set(String::New(env, "path"), String::New(env, path.c_str()));
+    res.Set(String::New(env, "type"), String::New(env, type.c_str()));
+    return scope.Escape(res);
+  }
+};
+
+class EventList {
+public:
+  void create(std::string path) {
+    std::lock_guard<std::mutex> l(mMutex);
+    Event *event = internalUpdate(path);
+    if (event->isDeleted) {
+      // Assume update event when rapidly removed and created
+      // https://github.com/parcel-bundler/watcher/issues/72
+      event->isDeleted = false;
+    } else {
+      event->isCreated = true;
+    }
+  }
+
+  Event *update(std::string path) {
+    std::lock_guard<std::mutex> l(mMutex);
+    return internalUpdate(path);
+  }
+
+  void remove(std::string path) {
+    std::lock_guard<std::mutex> l(mMutex);
+    Event *event = internalUpdate(path);
+    event->isDeleted = true;
+  }
+
+  size_t size() {
+    std::lock_guard<std::mutex> l(mMutex);
+    return mEvents.size();
+  }
+
+  std::vector<Event> getEvents() {
+    std::lock_guard<std::mutex> l(mMutex);
+    std::vector<Event> eventsCloneVector;
+    for(auto it = mEvents.begin(); it != mEvents.end(); ++it) {
+      if (!(it->second.isCreated && it->second.isDeleted)) {
+        eventsCloneVector.push_back(it->second);
+      }
+    }
+    return eventsCloneVector;
+  }
+
+  void clear() {
+    std::lock_guard<std::mutex> l(mMutex);
+    mEvents.clear();
+    mError.reset();
+  }
+
+  void error(std::string err) {
+    std::lock_guard<std::mutex> l(mMutex);
+    if (!mError.has_value()) {
+      mError.emplace(err);
+    }
+  }
+
+  bool hasError() {
+    std::lock_guard<std::mutex> l(mMutex);
+    return mError.has_value();
+  }
+
+  std::string getError() {
+    std::lock_guard<std::mutex> l(mMutex);
+    return mError.value_or("");
+  }
+
+private:
+  mutable std::mutex mMutex;
+  std::map<std::string, Event> mEvents;
+  std::optional<std::string> mError;
+  Event *internalUpdate(std::string path) {
+    auto found = mEvents.find(path);
+    if (found == mEvents.end()) {
+      auto it = mEvents.emplace(path, Event(path));
+      return &it.first->second;
+    }
+
+    return &found->second;
+  }
+};
+
+#endif

+ 22 - 0
node_modules/@parcel/watcher/src/Glob.cc

@@ -0,0 +1,22 @@
+#include "Glob.hh"
+
+#ifdef __wasm32__
+extern "C" bool wasm_regex_match(const char *s, const char *regex);
+#endif
+
+Glob::Glob(std::string raw) {
+  mRaw = raw;
+  mHash = std::hash<std::string>()(raw);
+  #ifndef __wasm32__
+    mRegex = std::regex(raw);
+  #endif
+}
+
+bool Glob::isIgnored(std::string relative_path) const {
+  // Use native JS regex engine for wasm to reduce binary size.
+  #ifdef __wasm32__
+    return wasm_regex_match(relative_path.c_str(), mRaw.c_str());
+  #else
+    return std::regex_match(relative_path, mRegex);
+  #endif
+}

+ 34 - 0
node_modules/@parcel/watcher/src/Glob.hh

@@ -0,0 +1,34 @@
+#ifndef GLOB_H
+#define GLOB_H
+
+#include <unordered_set>
+#include <regex>
+
+struct Glob {
+  std::size_t mHash;
+  std::string mRaw;
+  #ifndef __wasm32__
+  std::regex mRegex;
+  #endif
+
+  Glob(std::string raw);
+
+  bool operator==(const Glob &other) const {
+    return mHash == other.mHash;
+  }
+
+  bool isIgnored(std::string relative_path) const;
+};
+
+namespace std
+{
+  template <>
+  struct hash<Glob>
+  {
+    size_t operator()(const Glob& g) const {
+      return g.mHash;
+    }
+  };
+}
+
+#endif

+ 101 - 0
node_modules/@parcel/watcher/src/PromiseRunner.hh

@@ -0,0 +1,101 @@
+#ifndef PROMISE_RUNNER_H
+#define PROMISE_RUNNER_H
+
+#include <node_api.h>
+#include "wasm/include.h"
+#include <napi.h>
+
+using namespace Napi;
+
+class PromiseRunner {
+public:
+  const Env env;
+  Promise::Deferred deferred;
+
+  PromiseRunner(Env env) : env(env), deferred(Promise::Deferred::New(env)) {
+    napi_status status = napi_create_async_work(env, nullptr, env.Undefined(),
+                                                onExecute, onWorkComplete, this, &work);
+    if (status != napi_ok) {
+      work = nullptr;
+      const napi_extended_error_info *error_info = 0;
+      napi_get_last_error_info(env, &error_info);
+      if (error_info->error_message) {
+        Error::New(env, error_info->error_message).ThrowAsJavaScriptException();
+      } else {
+        Error::New(env).ThrowAsJavaScriptException();
+      }
+    }
+  }
+
+  virtual ~PromiseRunner() {}
+
+  Value queue() {
+    if (work) {
+      napi_status status = napi_queue_async_work(env, work);
+      if (status != napi_ok) {
+        onError(Error::New(env));
+      }
+    }
+
+    return deferred.Promise();
+  }
+
+private:
+  napi_async_work work;
+  std::string error;
+
+  static void onExecute(napi_env env, void *this_pointer) {
+    PromiseRunner* self = (PromiseRunner*) this_pointer;
+    try {
+      self->execute();
+    } catch (std::exception &err) {
+      self->error = err.what();
+    }
+  }
+
+  static void onWorkComplete(napi_env env, napi_status status, void *this_pointer) {
+    PromiseRunner* self = (PromiseRunner*) this_pointer;
+    if (status != napi_cancelled) {
+      HandleScope scope(self->env);
+      if (status == napi_ok) {
+        status = napi_delete_async_work(self->env, self->work);
+        if (status == napi_ok) {
+          if (self->error.size() == 0) {
+            self->onOK();
+          } else {
+            self->onError(Error::New(self->env, self->error));
+          }
+          delete self;
+          return;
+        }
+      }
+    }
+
+    // fallthrough for error handling
+    const napi_extended_error_info *error_info = 0;
+    napi_get_last_error_info(env, &error_info);
+    if (error_info->error_message){
+      self->onError(Error::New(env, error_info->error_message));
+    } else {
+      self->onError(Error::New(env));
+    }
+    delete self;
+  }
+
+  virtual void execute() {}
+  virtual Value getResult() {
+    return env.Null();
+  }
+
+  void onOK() {
+    HandleScope scope(env);
+    Value result = getResult();
+    deferred.Resolve(result);
+  }
+
+  void onError(const Error &e) {
+    deferred.Reject(e.Value());
+  }
+};
+
+#endif

+ 46 - 0
node_modules/@parcel/watcher/src/Signal.hh

@@ -0,0 +1,46 @@
+#ifndef SIGNAL_H
+#define SIGNAL_H
+
+#include <mutex>
+#include <condition_variable>
+
+class Signal {
+public:
+  Signal() : mFlag(false), mWaiting(false) {}
+  void wait() {
+    std::unique_lock<std::mutex> lock(mMutex);
+    while (!mFlag) {
+      mWaiting = true;
+      mCond.wait(lock);
+    }
+  }
+
+  std::cv_status waitFor(std::chrono::milliseconds ms) {
+    std::unique_lock<std::mutex> lock(mMutex);
+    return mCond.wait_for(lock, ms);
+  }
+
+  void notify() {
+    std::unique_lock<std::mutex> lock(mMutex);
+    mFlag = true;
+    mCond.notify_all();
+  }
+
+  void reset() {
+    std::unique_lock<std::mutex> lock(mMutex);
+    mFlag = false;
+    mWaiting = false;
+  }
+  
+  bool isWaiting() {
+    return mWaiting;
+  }
+
+private:
+  bool mFlag;
+  bool mWaiting;
+  std::mutex mMutex;
+  std::condition_variable mCond;
+};
+
+#endif

+ 237 - 0
node_modules/@parcel/watcher/src/Watcher.cc

@@ -0,0 +1,237 @@
+#include "Watcher.hh"
+#include <unordered_set>
+
+using namespace Napi;
+
+struct WatcherHash {
+  std::size_t operator() (WatcherRef const &k) const {
+    return std::hash<std::string>()(k->mDir);
+  }
+};
+
+struct WatcherCompare {
+  size_t operator() (WatcherRef const &a, WatcherRef const &b) const {
+    return *a == *b;
+  }
+};
+
+static std::unordered_set<WatcherRef , WatcherHash, WatcherCompare> sharedWatchers;
+
+WatcherRef Watcher::getShared(std::string dir, std::unordered_set<std::string> ignorePaths, std::unordered_set<Glob> ignoreGlobs) {
+  WatcherRef watcher = std::make_shared<Watcher>(dir, ignorePaths, ignoreGlobs);
+  auto found = sharedWatchers.find(watcher);
+  if (found != sharedWatchers.end()) {
+    return *found;
+  }
+
+  sharedWatchers.insert(watcher);
+  return watcher;
+}
+
+void removeShared(Watcher *watcher) {
+  for (auto it = sharedWatchers.begin(); it != sharedWatchers.end(); it++) {
+    if (it->get() == watcher) {
+      sharedWatchers.erase(it);
+      break;
+    }
+  }
+
+  // Free up memory.
+  if (sharedWatchers.size() == 0) {
+    sharedWatchers.rehash(0);
+  }
+}
+
+Watcher::Watcher(std::string dir, std::unordered_set<std::string> ignorePaths, std::unordered_set<Glob> ignoreGlobs)
+  : mDir(dir),
+    mIgnorePaths(ignorePaths),
+    mIgnoreGlobs(ignoreGlobs) {
+      mDebounce = Debounce::getShared();
+      mDebounce->add(this, [this] () {
+        triggerCallbacks();
+      });
+    }
+
+Watcher::~Watcher() {
+  mDebounce->remove(this);
+}
+
+void Watcher::wait() {
+  std::unique_lock<std::mutex> lk(mMutex);
+  mCond.wait(lk);
+}
+
+void Watcher::notify() {
+  std::unique_lock<std::mutex> lk(mMutex);
+  mCond.notify_all();
+
+  if (mCallbacks.size() > 0 && mEvents.size() > 0) {
+    // We must release our lock before calling into the debouncer
+    // to avoid a deadlock: the debouncer thread itself will require
+    // our lock from its thread when calling into `triggerCallbacks`
+    // while holding its own debouncer lock.
+    lk.unlock();
+    mDebounce->trigger();
+  }
+}
+
+struct CallbackData {
+  std::string error;
+  std::vector<Event> events;
+  CallbackData(std::string error, std::vector<Event> events) : error(error), events(events) {}
+};
+
+Value callbackEventsToJS(const Env &env, std::vector<Event> &events) {
+  EscapableHandleScope scope(env);
+  Array arr = Array::New(env, events.size());
+  size_t currentEventIndex = 0;
+  for (auto eventIterator = events.begin(); eventIterator != events.end(); eventIterator++) {
+    arr.Set(currentEventIndex++, eventIterator->toJS(env));
+  }
+  return scope.Escape(arr);
+}
+
+void callJSFunction(Napi::Env env, Function jsCallback, CallbackData *data) {
+  HandleScope scope(env);
+  auto err = data->error.size() > 0 ? Error::New(env, data->error).Value() : env.Null();
+  auto events = callbackEventsToJS(env, data->events);
+  jsCallback.Call({err, events});
+  delete data;
+
+  // Throw errors from the callback as fatal exceptions
+  // If we don't handle these node segfaults...
+  if (env.IsExceptionPending()) {
+    Napi::Error err = env.GetAndClearPendingException();
+    napi_fatal_exception(env, err.Value());
+  }
+}
+
+void Watcher::notifyError(std::exception &err) {
+  std::unique_lock<std::mutex> lk(mMutex);
+  for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
+    CallbackData *data = new CallbackData(err.what(), {});
+    it->tsfn.BlockingCall(data, callJSFunction);
+  }
+
+  clearCallbacks();
+}
+
+// This function is called from the debounce thread.
+void Watcher::triggerCallbacks() {
+  std::unique_lock<std::mutex> lk(mMutex);
+  if (mCallbacks.size() > 0 && (mEvents.size() > 0 || mEvents.hasError())) {
+    auto error = mEvents.getError();
+    auto events = mEvents.getEvents();
+    mEvents.clear();
+
+    for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
+      it->tsfn.BlockingCall(new CallbackData(error, events), callJSFunction);
+    }
+  }
+}
+
+// This should be called from the JavaScript thread.
+bool Watcher::watch(Function callback) {
+  std::unique_lock<std::mutex> lk(mMutex);
+
+  auto it = findCallback(callback);
+  if (it != mCallbacks.end()) {
+    return false;
+  }
+
+  auto tsfn = ThreadSafeFunction::New(
+    callback.Env(),
+    callback,
+    "Watcher callback",
+    0, // Unlimited queue
+    1 // Initial thread count
+  );
+
+  mCallbacks.push_back(Callback {
+    tsfn,
+    Napi::Persistent(callback),
+    std::this_thread::get_id()
+  });
+
+  return true;
+}
+
+// This should be called from the JavaScript thread.
+std::vector<Callback>::iterator Watcher::findCallback(Function callback) {
+  for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
+    // Only consider callbacks created by the same thread, or V8 will panic.
+    if (it->threadId == std::this_thread::get_id() && it->ref.Value() == callback) {
+      return it;
+    }
+  }
+
+  return mCallbacks.end();
+}
+
+// This should be called from the JavaScript thread.
+bool Watcher::unwatch(Function callback) {
+  std::unique_lock<std::mutex> lk(mMutex);
+
+  bool removed = false;
+  auto it = findCallback(callback);
+  if (it != mCallbacks.end()) {
+    it->tsfn.Release();
+    it->ref.Unref();
+    mCallbacks.erase(it);
+    removed = true;
+  }
+
+  if (removed && mCallbacks.size() == 0) {
+    unref();
+    return true;
+  }
+
+  return false;
+}
+
+void Watcher::unref() {
+  if (mCallbacks.size() == 0) {
+    removeShared(this);
+  }
+}
+
+void Watcher::destroy() {
+  std::unique_lock<std::mutex> lk(mMutex);
+  clearCallbacks();
+}
+
+// Private because it doesn't lock.
+void Watcher::clearCallbacks() {
+  for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
+    it->tsfn.Release();
+    it->ref.Unref();
+  }
+
+  mCallbacks.clear();
+  unref();
+}
+
+bool Watcher::isIgnored(std::string path) {
+  for (auto it = mIgnorePaths.begin(); it != mIgnorePaths.end(); it++) {
+    auto dir = *it + DIR_SEP;
+    if (*it == path || path.compare(0, dir.size(), dir) == 0) {
+      return true;
+    }
+  }
+
+  auto basePath = mDir + DIR_SEP;
+
+  if (path.rfind(basePath, 0) != 0) {
+    return false;
+  }
+
+  auto relativePath = path.substr(basePath.size());
+
+  for (auto it = mIgnoreGlobs.begin(); it != mIgnoreGlobs.end(); it++) {
+    if (it->isIgnored(relativePath)) {
+      return true;
+    }
+  }
+
+  return false;
+}

+ 73 - 0
node_modules/@parcel/watcher/src/Watcher.hh

@@ -0,0 +1,73 @@
+#ifndef WATCHER_H
+#define WATCHER_H
+
+#include <condition_variable>
+#include <unordered_set>
+#include <set>
+#include <node_api.h>
+#include "Glob.hh"
+#include "Event.hh"
+#include "Debounce.hh"
+#include "DirTree.hh"
+#include "Signal.hh"
+
+using namespace Napi;
+
+struct Watcher;
+using WatcherRef = std::shared_ptr<Watcher>;
+
+struct Callback {
+  Napi::ThreadSafeFunction tsfn;
+  Napi::FunctionReference ref;
+  std::thread::id threadId;
+};
+
+class WatcherState {
+public:
+    virtual ~WatcherState() = default;
+};
+
+struct Watcher {
+  std::string mDir;
+  std::unordered_set<std::string> mIgnorePaths;
+  std::unordered_set<Glob> mIgnoreGlobs;
+  EventList mEvents;
+  std::shared_ptr<WatcherState> state;
+
+  Watcher(std::string dir, std::unordered_set<std::string> ignorePaths, std::unordered_set<Glob> ignoreGlobs);
+  ~Watcher();
+
+  bool operator==(const Watcher &other) const {
+    return mDir == other.mDir && mIgnorePaths == other.mIgnorePaths && mIgnoreGlobs == other.mIgnoreGlobs;
+  }
+
+  void wait();
+  void notify();
+  void notifyError(std::exception &err);
+  bool watch(Function callback);
+  bool unwatch(Function callback);
+  void unref();
+  bool isIgnored(std::string path);
+  void destroy();
+
+  static WatcherRef getShared(std::string dir, std::unordered_set<std::string> ignorePaths, std::unordered_set<Glob> ignoreGlobs);
+
+private:
+  std::mutex mMutex;
+  std::condition_variable mCond;
+  std::vector<Callback> mCallbacks;
+  std::shared_ptr<Debounce> mDebounce;
+
+  std::vector<Callback>::iterator findCallback(Function callback);
+  void clearCallbacks();
+  void triggerCallbacks();
+};
+
+class WatcherError : public std::runtime_error {
+public:
+  WatcherRef mWatcher;
+  WatcherError(std::string msg, WatcherRef watcher) : std::runtime_error(msg), mWatcher(watcher) {}
+  WatcherError(const char *msg, WatcherRef watcher) : std::runtime_error(msg), mWatcher(watcher) {}
+};
+
+#endif

+ 268 - 0
node_modules/@parcel/watcher/src/binding.cc

@@ -0,0 +1,268 @@
+#include <unordered_set>
+#include <node_api.h>
+#include "wasm/include.h"
+#include <napi.h>
+#include "Glob.hh"
+#include "Event.hh"
+#include "Backend.hh"
+#include "Watcher.hh"
+#include "PromiseRunner.hh"
+
+using namespace Napi;
+
+std::unordered_set<std::string> getIgnorePaths(Env env, Value opts) {
+  std::unordered_set<std::string> result;
+
+  if (opts.IsObject()) {
+    Value v = opts.As<Object>().Get(String::New(env, "ignorePaths"));
+    if (v.IsArray()) {
+      Array items = v.As<Array>();
+      for (size_t i = 0; i < items.Length(); i++) {
+        Value item = items.Get(Number::New(env, i));
+        if (item.IsString()) {
+          result.insert(std::string(item.As<String>().Utf8Value().c_str()));
+        }
+      }
+    }
+  }
+
+  return result;
+}
+
+std::unordered_set<Glob> getIgnoreGlobs(Env env, Value opts) {
+  std::unordered_set<Glob> result;
+
+  if (opts.IsObject()) {
+    Value v = opts.As<Object>().Get(String::New(env, "ignoreGlobs"));
+    if (v.IsArray()) {
+      Array items = v.As<Array>();
+      for (size_t i = 0; i < items.Length(); i++) {
+        Value item = items.Get(Number::New(env, i));
+        if (item.IsString()) {
+          auto key = item.As<String>().Utf8Value();
+          try {
+            result.emplace(key);
+          } catch (const std::regex_error& e) {
+            Error::New(env, e.what()).ThrowAsJavaScriptException();
+          }
+        }
+      }
+    }
+  }
+
+  return result;
+}
+
+std::shared_ptr<Backend> getBackend(Env env, Value opts) {
+  Value b = opts.As<Object>().Get(String::New(env, "backend"));
+  std::string backendName;
+  if (b.IsString()) {
+    backendName = std::string(b.As<String>().Utf8Value().c_str());
+  }
+
+  return Backend::getShared(backendName);
+}
+
+class WriteSnapshotRunner : public PromiseRunner {
+public:
+  WriteSnapshotRunner(Env env, Value dir, Value snap, Value opts)
+    : PromiseRunner(env),
+      snapshotPath(std::string(snap.As<String>().Utf8Value().c_str())) {
+    watcher = Watcher::getShared(
+      std::string(dir.As<String>().Utf8Value().c_str()),
+      getIgnorePaths(env, opts),
+      getIgnoreGlobs(env, opts)
+    );
+
+    backend = getBackend(env, opts);
+  }
+
+  ~WriteSnapshotRunner() {
+    watcher->unref();
+    backend->unref();
+  }
+private:
+  std::shared_ptr<Backend> backend;
+  WatcherRef watcher;
+  std::string snapshotPath;
+
+  void execute() override {
+    backend->writeSnapshot(watcher, &snapshotPath);
+  }
+};
+
+class GetEventsSinceRunner : public PromiseRunner {
+public:
+  GetEventsSinceRunner(Env env, Value dir, Value snap, Value opts)
+    : PromiseRunner(env),
+      snapshotPath(std::string(snap.As<String>().Utf8Value().c_str())) {
+    watcher = std::make_shared<Watcher>(
+      std::string(dir.As<String>().Utf8Value().c_str()),
+      getIgnorePaths(env, opts),
+      getIgnoreGlobs(env, opts)
+    );
+
+    backend = getBackend(env, opts);
+  }
+
+  ~GetEventsSinceRunner() {
+    watcher->unref();
+    backend->unref();
+  }
+private:
+  std::shared_ptr<Backend> backend;
+  WatcherRef watcher;
+  std::string snapshotPath;
+
+  void execute() override {
+    backend->getEventsSince(watcher, &snapshotPath);
+    if (watcher->mEvents.hasError()) {
+      throw std::runtime_error(watcher->mEvents.getError());
+    }
+  }
+
+  Value getResult() override {
+    std::vector<Event> events = watcher->mEvents.getEvents();
+    Array eventsArray = Array::New(env, events.size());
+    size_t i = 0;
+    for (auto it = events.begin(); it != events.end(); it++) {
+      eventsArray.Set(i++, it->toJS(env));
+    }
+    return eventsArray;
+  }
+};
+
+template<class Runner>
+Value queueSnapshotWork(const CallbackInfo& info) {
+  Env env = info.Env();
+  if (info.Length() < 1 || !info[0].IsString()) {
+    TypeError::New(env, "Expected a string").ThrowAsJavaScriptException();
+    return env.Null();
+  }
+
+  if (info.Length() < 2 || !info[1].IsString()) {
+    TypeError::New(env, "Expected a string").ThrowAsJavaScriptException();
+    return env.Null();
+  }
+
+  if (info.Length() >= 3 && !info[2].IsObject()) {
+    TypeError::New(env, "Expected an object").ThrowAsJavaScriptException();
+    return env.Null();
+  }
+
+  Runner *runner = new Runner(info.Env(), info[0], info[1], info[2]);
+  return runner->queue();
+}
+
+Value writeSnapshot(const CallbackInfo& info) {
+  return queueSnapshotWork<WriteSnapshotRunner>(info);
+}
+
+Value getEventsSince(const CallbackInfo& info) {
+  return queueSnapshotWork<GetEventsSinceRunner>(info);
+}
+
+class SubscribeRunner : public PromiseRunner {
+public:
+  SubscribeRunner(Env env, Value dir, Value fn, Value opts) : PromiseRunner(env) {
+    watcher = Watcher::getShared(
+      std::string(dir.As<String>().Utf8Value().c_str()),
+      getIgnorePaths(env, opts),
+      getIgnoreGlobs(env, opts)
+    );
+
+    backend = getBackend(env, opts);
+    watcher->watch(fn.As<Function>());
+  }
+
+private:
+  WatcherRef watcher;
+  std::shared_ptr<Backend> backend;
+  FunctionReference callback;
+
+  void execute() override {
+    try {
+      backend->watch(watcher);
+    } catch (std::exception &err) {
+      watcher->destroy();
+      throw;
+    }
+  }
+};
+
+class UnsubscribeRunner : public PromiseRunner {
+public:
+  UnsubscribeRunner(Env env, Value dir, Value fn, Value opts) : PromiseRunner(env) {
+    watcher = Watcher::getShared(
+      std::string(dir.As<String>().Utf8Value().c_str()),
+      getIgnorePaths(env, opts),
+      getIgnoreGlobs(env, opts)
+    );
+
+    backend = getBackend(env, opts);
+    shouldUnwatch = watcher->unwatch(fn.As<Function>());
+  }
+
+private:
+  WatcherRef watcher;
+  std::shared_ptr<Backend> backend;
+  bool shouldUnwatch;
+
+  void execute() override {
+    if (shouldUnwatch) {
+      backend->unwatch(watcher);
+    }
+  }
+};
+
+template<class Runner>
+Value queueSubscriptionWork(const CallbackInfo& info) {
+  Env env = info.Env();
+  if (info.Length() < 1 || !info[0].IsString()) {
+    TypeError::New(env, "Expected a string").ThrowAsJavaScriptException();
+    return env.Null();
+  }
+
+  if (info.Length() < 2 || !info[1].IsFunction()) {
+    TypeError::New(env, "Expected a function").ThrowAsJavaScriptException();
+    return env.Null();
+  }
+
+  if (info.Length() >= 3 && !info[2].IsObject()) {
+    TypeError::New(env, "Expected an object").ThrowAsJavaScriptException();
+    return env.Null();
+  }
+
+  Runner *runner = new Runner(info.Env(), info[0], info[1], info[2]);
+  return runner->queue();
+}
+
+Value subscribe(const CallbackInfo& info) {
+  return queueSubscriptionWork<SubscribeRunner>(info);
+}
+
+Value unsubscribe(const CallbackInfo& info) {
+  return queueSubscriptionWork<UnsubscribeRunner>(info);
+}
+
+Object Init(Env env, Object exports) {
+  exports.Set(
+    String::New(env, "writeSnapshot"),
+    Function::New(env, writeSnapshot)
+  );
+  exports.Set(
+    String::New(env, "getEventsSince"),
+    Function::New(env, getEventsSince)
+  );
+  exports.Set(
+    String::New(env, "subscribe"),
+    Function::New(env, subscribe)
+  );
+  exports.Set(
+    String::New(env, "unsubscribe"),
+    Function::New(env, unsubscribe)
+  );
+  return exports;
+}
+
+NODE_API_MODULE(watcher, Init)

+ 306 - 0
node_modules/@parcel/watcher/src/kqueue/KqueueBackend.cc

@@ -0,0 +1,306 @@
+#include <memory>
+#include <poll.h>
+#include <unistd.h>
+#include <libgen.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include "KqueueBackend.hh"
+
+#if __APPLE__
+#define st_mtim st_mtimespec
+#endif
+
+#if !defined(O_EVTONLY)
+#define O_EVTONLY O_RDONLY
+#endif
+
+#define CONVERT_TIME(ts) ((uint64_t)ts.tv_sec * 1000000000 + ts.tv_nsec)
+
+void KqueueBackend::start() {
+  if ((mKqueue = kqueue()) < 0) {
+    throw std::runtime_error(std::string("Unable to open kqueue: ") + strerror(errno));
+  }
+
+  // Create a pipe that we will write to when we want to end the thread.
+  int err = pipe(mPipe);
+  if (err == -1) {
+    throw std::runtime_error(std::string("Unable to open pipe: ") + strerror(errno));
+  }
+
+  // Subscribe kqueue to this pipe.
+  struct kevent ev;
+  EV_SET(
+    &ev,
+    mPipe[0],
+    EVFILT_READ,
+    EV_ADD | EV_CLEAR,
+    0,
+    0,
+    0
+  );
+
+  if (kevent(mKqueue, &ev, 1, NULL, 0, 0)) {
+    close(mPipe[0]);
+    close(mPipe[1]);
+    throw std::runtime_error(std::string("Unable to watch pipe: ") + strerror(errno));
+  }
+
+  notifyStarted();
+
+  struct kevent events[128];
+
+  while (true) {
+    int event_count = kevent(mKqueue, NULL, 0, events, 128, 0);
+    if (event_count < 0 || events[0].flags == EV_ERROR) {
+      throw std::runtime_error(std::string("kevent error: ") + strerror(errno));
+    }
+
+    // Track all of the watchers that are touched so we can notify them at the end of the events.
+    std::unordered_set<WatcherRef> watchers;
+
+    for (int i = 0; i < event_count; i++) {
+      int flags = events[i].fflags;
+      int fd = events[i].ident;
+      if (fd == mPipe[0]) {
+        // pipe was written to. break out of the loop.
+        goto done;
+      }
+
+      auto it = mFdToEntry.find(fd);
+      if (it == mFdToEntry.end()) {
+        // If fd wasn't in our map, we may have already stopped watching it. Ignore the event.
+        continue;
+      }
+
+      DirEntry *entry = it->second;
+
+      if (flags & NOTE_WRITE && entry && entry->isDir) {
+        // If a write occurred on a directory, we have to diff the contents of that
+        // directory to determine what file was added/deleted.
+        compareDir(fd, entry->path, watchers);
+      } else {
+        std::vector<KqueueSubscription *> subs = findSubscriptions(entry->path);
+        for (auto it = subs.begin(); it != subs.end(); it++) {
+          KqueueSubscription *sub = *it;
+          watchers.insert(sub->watcher);
+          if (flags & (NOTE_DELETE | NOTE_RENAME | NOTE_REVOKE)) {
+            sub->watcher->mEvents.remove(sub->path);
+            sub->tree->remove(sub->path);
+            mFdToEntry.erase((int)(size_t)entry->state);
+            mSubscriptions.erase(sub->path);
+          } else if (flags & (NOTE_WRITE | NOTE_ATTRIB | NOTE_EXTEND)) {
+            struct stat st;
+            lstat(sub->path.c_str(), &st);
+            if (entry->mtime != CONVERT_TIME(st.st_mtim)) {
+              entry->mtime = CONVERT_TIME(st.st_mtim);
+              sub->watcher->mEvents.update(sub->path);
+            }
+          }
+        }
+      }
+    }
+
+    for (auto it = watchers.begin(); it != watchers.end(); it++) {
+      (*it)->notify();
+    }
+  }
+
+done:
+  close(mPipe[0]);
+  close(mPipe[1]);
+  mEndedSignal.notify();
+}
+
+KqueueBackend::~KqueueBackend() {
+  write(mPipe[1], "X", 1);
+  mEndedSignal.wait();
+}
+
+void KqueueBackend::subscribe(WatcherRef watcher) {
+  // Build a full directory tree recursively, and watch each directory.
+  std::shared_ptr<DirTree> tree = getTree(watcher);
+
+  for (auto it = tree->entries.begin(); it != tree->entries.end(); it++) {
+    bool success = watchDir(watcher, it->second.path, tree);
+    if (!success) {
+      throw WatcherError(std::string("error watching " + watcher->mDir + ": " + strerror(errno)), watcher);
+    }
+  }
+}
+
+bool KqueueBackend::watchDir(WatcherRef watcher, std::string path, std::shared_ptr<DirTree> tree) {
+  if (watcher->isIgnored(path)) {
+    return false;
+  }
+
+  DirEntry *entry = tree->find(path);
+  if (!entry) {
+    return false;
+  }
+
+  KqueueSubscription sub = {
+    .watcher = watcher,
+    .path = path,
+    .tree = tree
+  };
+
+  if (!entry->state) {
+    int fd = open(path.c_str(), O_EVTONLY);
+    if (fd <= 0) {
+      return false;
+    }
+
+    struct kevent event;
+    EV_SET(
+      &event,
+      fd,
+      EVFILT_VNODE,
+      EV_ADD | EV_CLEAR | EV_ENABLE,
+      NOTE_DELETE | NOTE_WRITE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE,
+      0,
+      0
+    );
+
+    if (kevent(mKqueue, &event, 1, NULL, 0, 0)) {
+      close(fd);
+      return false;
+    }
+
+    entry->state = (void *)(size_t)fd;
+    mFdToEntry.emplace(fd, entry);
+  }
+
+  sub.fd = (int)(size_t)entry->state;
+  mSubscriptions.emplace(path, sub);
+  return true;
+}
+
+std::vector<KqueueSubscription *> KqueueBackend::findSubscriptions(std::string &path) {
+  // Find the subscriptions affected by this path.
+  // Copy pointers to them into a vector so that modifying mSubscriptions doesn't invalidate the iterator.
+  auto range = mSubscriptions.equal_range(path);
+  std::vector<KqueueSubscription *> subs;
+  for (auto it = range.first; it != range.second; it++) {
+    subs.push_back(&it->second);
+  }
+
+  return subs;
+}
+
+bool KqueueBackend::compareDir(int fd, std::string &path, std::unordered_set<WatcherRef> &watchers) {
+  // macOS doesn't support fdclosedir, so we have to duplicate the file descriptor
+  // to ensure the closedir doesn't also stop watching.
+  #if __APPLE__
+    fd = dup(fd);
+  #endif
+
+  DIR *dir = fdopendir(fd);
+  if (dir == NULL) {
+    return false;
+  }
+
+  // fdopendir doesn't rewind to the beginning.
+  rewinddir(dir);
+
+  std::vector<KqueueSubscription *> subs = findSubscriptions(path);
+  std::string dirStart = path + DIR_SEP;
+
+  std::unordered_set<std::shared_ptr<DirTree>> trees;
+  for (auto it = subs.begin(); it != subs.end(); it++) {
+    trees.emplace((*it)->tree);
+  }
+
+  std::unordered_set<std::string> entries;
+  struct dirent *entry;
+  while ((entry = readdir(dir))) {
+    if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
+      continue;
+    }
+
+    std::string fullpath = dirStart + entry->d_name;
+    entries.emplace(fullpath);
+
+    for (auto it = trees.begin(); it != trees.end(); it++) {
+      std::shared_ptr<DirTree> tree = *it;
+      if (!tree->find(fullpath)) {
+        struct stat st;
+        fstatat(fd, entry->d_name, &st, AT_SYMLINK_NOFOLLOW);
+        tree->add(fullpath, CONVERT_TIME(st.st_mtim), S_ISDIR(st.st_mode));
+
+        // Notify all watchers with the same tree.
+        for (auto i = subs.begin(); i != subs.end(); i++) {
+          KqueueSubscription *sub = *i;
+          if (sub->tree == tree) {
+            if (sub->watcher->isIgnored(fullpath)) {
+              continue;
+            }
+
+            sub->watcher->mEvents.create(fullpath);
+            watchers.emplace(sub->watcher);
+
+            bool success = watchDir(sub->watcher, fullpath, sub->tree);
+            if (!success) {
+              sub->tree->remove(fullpath);
+              return false;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  for (auto it = trees.begin(); it != trees.end(); it++) {
+    std::shared_ptr<DirTree> tree = *it;
+    for (auto entry = tree->entries.begin(); entry != tree->entries.end();) {
+
+      if (
+        entry->first.rfind(dirStart, 0) == 0 &&
+        entry->first.find(DIR_SEP, dirStart.length()) == std::string::npos &&
+        entries.count(entry->first) == 0
+      ) {
+        // Notify all watchers with the same tree.
+        for (auto i = subs.begin(); i != subs.end(); i++) {
+          if ((*i)->tree == tree) {
+            KqueueSubscription *sub = *i;
+            if (!sub->watcher->isIgnored(entry->first)) {
+              sub->watcher->mEvents.remove(entry->first);
+              watchers.emplace(sub->watcher);
+            }
+          }
+        }
+
+        mFdToEntry.erase((int)(size_t)entry->second.state);
+        mSubscriptions.erase(entry->first);
+        entry = tree->entries.erase(entry);
+      } else {
+        entry++;
+      }
+    }
+  }
+
+  #if __APPLE__
+    closedir(dir);
+  #else
+    fdclosedir(dir);
+  #endif
+
+  return true;
+}
+
+void KqueueBackend::unsubscribe(WatcherRef watcher) {
+  // Find any subscriptions pointing to this watcher, and remove them.
+  for (auto it = mSubscriptions.begin(); it != mSubscriptions.end();) {
+    if (it->second.watcher.get() == watcher.get()) {
+      if (mSubscriptions.count(it->first) == 1) {
+        // Closing the file descriptor automatically unwatches it in the kqueue.
+        close(it->second.fd);
+        mFdToEntry.erase(it->second.fd);
+      }
+
+      it = mSubscriptions.erase(it);
+    } else {
+      it++;
+    }
+  }
+}

+ 35 - 0
node_modules/@parcel/watcher/src/kqueue/KqueueBackend.hh

@@ -0,0 +1,35 @@
+#ifndef KQUEUE_H
+#define KQUEUE_H
+
+#include <unordered_map>
+#include <sys/event.h>
+#include "../shared/BruteForceBackend.hh"
+#include "../DirTree.hh"
+#include "../Signal.hh"
+
+struct KqueueSubscription {
+  WatcherRef watcher;
+  std::string path;
+  std::shared_ptr<DirTree> tree;
+  int fd;
+};
+
+class KqueueBackend : public BruteForceBackend {
+public:
+  void start() override;
+  ~KqueueBackend();
+  void subscribe(WatcherRef watcher) override;
+  void unsubscribe(WatcherRef watcher) override;
+private:
+  int mKqueue;
+  int mPipe[2];
+  std::unordered_multimap<std::string, KqueueSubscription> mSubscriptions;
+  std::unordered_map<int, DirEntry *> mFdToEntry;
+  Signal mEndedSignal;
+
+  bool watchDir(WatcherRef watcher, std::string path, std::shared_ptr<DirTree> tree);
+  bool compareDir(int fd, std::string &dir, std::unordered_set<WatcherRef> &watchers);
+  std::vector<KqueueSubscription *> findSubscriptions(std::string &path);
+};
+
+#endif

+ 232 - 0
node_modules/@parcel/watcher/src/linux/InotifyBackend.cc

@@ -0,0 +1,232 @@
+#include <memory>
+#include <poll.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include "InotifyBackend.hh"
+
+#define INOTIFY_MASK \
+  IN_ATTRIB | IN_CREATE | IN_DELETE | \
+  IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_MOVED_FROM | \
+  IN_MOVED_TO | IN_DONT_FOLLOW | IN_ONLYDIR | IN_EXCL_UNLINK
+#define BUFFER_SIZE 8192
+#define CONVERT_TIME(ts) ((uint64_t)ts.tv_sec * 1000000000 + ts.tv_nsec)
+
+void InotifyBackend::start() {
+  // Create a pipe that we will write to when we want to end the thread.
+  int err = pipe2(mPipe, O_CLOEXEC | O_NONBLOCK);
+  if (err == -1) {
+    throw std::runtime_error(std::string("Unable to open pipe: ") + strerror(errno));
+  }
+
+  // Init inotify file descriptor.
+  mInotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
+  if (mInotify == -1) {
+    throw std::runtime_error(std::string("Unable to initialize inotify: ") + strerror(errno));
+  }
+
+  pollfd pollfds[2];
+  pollfds[0].fd = mPipe[0];
+  pollfds[0].events = POLLIN;
+  pollfds[0].revents = 0;
+  pollfds[1].fd = mInotify;
+  pollfds[1].events = POLLIN;
+  pollfds[1].revents = 0;
+
+  notifyStarted();
+
+  // Loop until we get an event from the pipe.
+  while (true) {
+    int result = poll(pollfds, 2, 500);
+    if (result < 0) {
+      throw std::runtime_error(std::string("Unable to poll: ") + strerror(errno));
+    }
+
+    if (pollfds[0].revents) {
+      break;
+    }
+
+    if (pollfds[1].revents) {
+      handleEvents();
+    }
+  }
+
+  close(mPipe[0]);
+  close(mPipe[1]);
+  close(mInotify);
+
+  mEndedSignal.notify();
+}
+
+InotifyBackend::~InotifyBackend() {
+  write(mPipe[1], "X", 1);
+  mEndedSignal.wait();
+}
+
+// This function is called by Backend::watch which takes a lock on mMutex
+void InotifyBackend::subscribe(WatcherRef watcher) {
+  // Build a full directory tree recursively, and watch each directory.
+  std::shared_ptr<DirTree> tree = getTree(watcher);
+
+  for (auto it = tree->entries.begin(); it != tree->entries.end(); it++) {
+    if (it->second.isDir) {
+      bool success = watchDir(watcher, it->second.path, tree);
+      if (!success) {
+        throw WatcherError(std::string("inotify_add_watch on '") + it->second.path + std::string("' failed: ") + strerror(errno), watcher);
+      }
+    }
+  }
+}
+
+bool InotifyBackend::watchDir(WatcherRef watcher, std::string path, std::shared_ptr<DirTree> tree) {
+  int wd = inotify_add_watch(mInotify, path.c_str(), INOTIFY_MASK);
+  if (wd == -1) {
+    return false;
+  }
+
+  std::shared_ptr<InotifySubscription> sub = std::make_shared<InotifySubscription>();
+  sub->tree = tree;
+  sub->path = path;
+  sub->watcher = watcher;
+  mSubscriptions.emplace(wd, sub);
+
+  return true;
+}
+
+void InotifyBackend::handleEvents() {
+  char buf[BUFFER_SIZE] __attribute__ ((aligned(__alignof__(struct inotify_event))));;
+  struct inotify_event *event;
+
+  // Track all of the watchers that are touched so we can notify them at the end of the events.
+  std::unordered_set<WatcherRef> watchers;
+
+  while (true) {
+    int n = read(mInotify, &buf, BUFFER_SIZE);
+    if (n < 0) {
+      if (errno == EAGAIN || errno == EWOULDBLOCK) {
+        break;
+      }
+
+      throw std::runtime_error(std::string("Error reading from inotify: ") + strerror(errno));
+    }
+
+    if (n == 0) {
+      break;
+    }
+
+    for (char *ptr = buf; ptr < buf + n; ptr += sizeof(*event) + event->len) {
+      event = (struct inotify_event *)ptr;
+
+      if ((event->mask & IN_Q_OVERFLOW) == IN_Q_OVERFLOW) {
+        // overflow
+        continue;
+      }
+
+      handleEvent(event, watchers);
+    }
+  }
+
+  for (auto it = watchers.begin(); it != watchers.end(); it++) {
+    (*it)->notify();
+  }
+}
+
+void InotifyBackend::handleEvent(struct inotify_event *event, std::unordered_set<WatcherRef> &watchers) {
+  std::unique_lock<std::mutex> lock(mMutex);
+
+  // Find the subscriptions for this watch descriptor
+  auto range = mSubscriptions.equal_range(event->wd);
+  std::unordered_set<std::shared_ptr<InotifySubscription>> set;
+  for (auto it = range.first; it != range.second; it++) {
+    set.insert(it->second);
+  }
+
+  for (auto it = set.begin(); it != set.end(); it++) {
+    if (handleSubscription(event, *it)) {
+      watchers.insert((*it)->watcher);
+    }
+  }
+}
+
+bool InotifyBackend::handleSubscription(struct inotify_event *event, std::shared_ptr<InotifySubscription> sub) {
+  // Build full path and check if its in our ignore list.
+  std::shared_ptr<Watcher> watcher = sub->watcher;
+  std::string path = std::string(sub->path);
+  bool isDir = event->mask & IN_ISDIR;
+
+  if (event->len > 0) {
+    path += "/" + std::string(event->name);
+  }
+
+  if (watcher->isIgnored(path)) {
+    return false;
+  }
+
+  // If this is a create, check if it's a directory and start watching if it is.
+  // In any case, keep the directory tree up to date.
+  if (event->mask & (IN_CREATE | IN_MOVED_TO)) {
+    watcher->mEvents.create(path);
+
+    struct stat st;
+    // Use lstat to avoid resolving symbolic links that we cannot watch anyway
+    // https://github.com/parcel-bundler/watcher/issues/76
+    lstat(path.c_str(), &st);
+    DirEntry *entry = sub->tree->add(path, CONVERT_TIME(st.st_mtim), S_ISDIR(st.st_mode));
+
+    if (entry->isDir) {
+      bool success = watchDir(watcher, path, sub->tree);
+      if (!success) {
+        sub->tree->remove(path);
+        return false;
+      }
+    }
+  } else if (event->mask & (IN_MODIFY | IN_ATTRIB)) {
+    watcher->mEvents.update(path);
+
+    struct stat st;
+    stat(path.c_str(), &st);
+    sub->tree->update(path, CONVERT_TIME(st.st_mtim));
+  } else if (event->mask & (IN_DELETE | IN_DELETE_SELF | IN_MOVED_FROM | IN_MOVE_SELF)) {
+    bool isSelfEvent = (event->mask & (IN_DELETE_SELF | IN_MOVE_SELF));
+    // Ignore delete/move self events unless this is the recursive watch root
+    if (isSelfEvent && path != watcher->mDir) {
+      return false;
+    }
+
+    // If the entry being deleted/moved is a directory, remove it from the list of subscriptions
+    // XXX: self events don't have the IN_ISDIR mask
+    if (isSelfEvent || isDir) {
+      for (auto it = mSubscriptions.begin(); it != mSubscriptions.end();) {
+        if (it->second->path == path) {
+          it = mSubscriptions.erase(it);
+        } else {
+          ++it;
+        }
+      }
+    }
+
+    watcher->mEvents.remove(path);
+    sub->tree->remove(path);
+  }
+
+  return true;
+}
+
+// This function is called by Backend::unwatch which takes a lock on mMutex
+void InotifyBackend::unsubscribe(WatcherRef watcher) {
+  // Find any subscriptions pointing to this watcher, and remove them.
+  for (auto it = mSubscriptions.begin(); it != mSubscriptions.end();) {
+    if (it->second->watcher.get() == watcher.get()) {
+      if (mSubscriptions.count(it->first) == 1) {
+        int err = inotify_rm_watch(mInotify, it->first);
+        if (err == -1) {
+          throw WatcherError(std::string("Unable to remove watcher: ") + strerror(errno), watcher);
+        }
+      }
+
+      it = mSubscriptions.erase(it);
+    } else {
+      it++;
+    }
+  }
+}

+ 34 - 0
node_modules/@parcel/watcher/src/linux/InotifyBackend.hh

@@ -0,0 +1,34 @@
+#ifndef INOTIFY_H
+#define INOTIFY_H
+
+#include <unordered_map>
+#include <sys/inotify.h>
+#include "../shared/BruteForceBackend.hh"
+#include "../DirTree.hh"
+#include "../Signal.hh"
+
+struct InotifySubscription {
+  std::shared_ptr<DirTree> tree;
+  std::string path;
+  WatcherRef watcher;
+};
+
+class InotifyBackend : public BruteForceBackend {
+public:
+  void start() override;
+  ~InotifyBackend();
+  void subscribe(WatcherRef watcher) override;
+  void unsubscribe(WatcherRef watcher) override;
+private:
+  int mPipe[2];
+  int mInotify;
+  std::unordered_multimap<int, std::shared_ptr<InotifySubscription>> mSubscriptions;
+  Signal mEndedSignal;
+
+  bool watchDir(WatcherRef watcher, std::string path, std::shared_ptr<DirTree> tree);
+  void handleEvents();
+  void handleEvent(struct inotify_event *event, std::unordered_set<WatcherRef> &watchers);
+  bool handleSubscription(struct inotify_event *event, std::shared_ptr<InotifySubscription> sub);
+};
+
+#endif

+ 338 - 0
node_modules/@parcel/watcher/src/macos/FSEventsBackend.cc

@@ -0,0 +1,338 @@
+#include <CoreServices/CoreServices.h>
+#include <sys/stat.h>
+#include <string>
+#include <fstream>
+#include <unordered_set>
+#include "../Event.hh"
+#include "../Backend.hh"
+#include "./FSEventsBackend.hh"
+#include "../Watcher.hh"
+
+#define CONVERT_TIME(ts) ((uint64_t)ts.tv_sec * 1000000000 + ts.tv_nsec)
+#define IGNORED_FLAGS (kFSEventStreamEventFlagItemIsHardlink | kFSEventStreamEventFlagItemIsLastHardlink | kFSEventStreamEventFlagItemIsSymlink | kFSEventStreamEventFlagItemIsDir | kFSEventStreamEventFlagItemIsFile)
+
+void stopStream(FSEventStreamRef stream, CFRunLoopRef runLoop) {
+  FSEventStreamStop(stream);
+  FSEventStreamUnscheduleFromRunLoop(stream, runLoop, kCFRunLoopDefaultMode);
+  FSEventStreamInvalidate(stream);
+  FSEventStreamRelease(stream);
+}
+
+// macOS has a case insensitive file system by default. In order to detect
+// file renames that only affect case, we need to get the canonical path
+// and compare it with the input path to determine if a file was created or deleted.
+bool pathExists(char *path) {
+  int fd = open(path, O_RDONLY | O_SYMLINK);
+  if (fd == -1) {
+    return false;
+  }
+
+  char buf[PATH_MAX];
+  if (fcntl(fd, F_GETPATH, buf) == -1) {
+    close(fd);
+    return false;
+  }
+
+  bool res = strncmp(path, buf, PATH_MAX) == 0;
+  close(fd);
+  return res;
+}
+
+class State: public WatcherState {
+public:
+  FSEventStreamRef stream;
+  std::shared_ptr<DirTree> tree;
+  uint64_t since;
+};
+
+void FSEventsCallback(
+  ConstFSEventStreamRef streamRef,
+  void *clientCallBackInfo,
+  size_t numEvents,
+  void *eventPaths,
+  const FSEventStreamEventFlags eventFlags[],
+  const FSEventStreamEventId eventIds[]
+) {
+  char **paths = (char **)eventPaths;
+  std::shared_ptr<Watcher>& watcher = *static_cast<std::shared_ptr<Watcher> *>(clientCallBackInfo);
+
+  EventList& list = watcher->mEvents;
+  if (watcher->state == nullptr) {
+      return;
+  }
+
+  auto stateGuard = watcher->state;
+  auto* state = static_cast<State*>(stateGuard.get());
+  uint64_t since = state->since;
+  bool deletedRoot = false;
+
+  for (size_t i = 0; i < numEvents; ++i) {
+    bool isCreated = (eventFlags[i] & kFSEventStreamEventFlagItemCreated) == kFSEventStreamEventFlagItemCreated;
+    bool isRemoved = (eventFlags[i] & kFSEventStreamEventFlagItemRemoved) == kFSEventStreamEventFlagItemRemoved;
+    bool isModified = (eventFlags[i] & kFSEventStreamEventFlagItemModified) == kFSEventStreamEventFlagItemModified ||
+                      (eventFlags[i] & kFSEventStreamEventFlagItemInodeMetaMod) == kFSEventStreamEventFlagItemInodeMetaMod ||
+                      (eventFlags[i] & kFSEventStreamEventFlagItemFinderInfoMod) == kFSEventStreamEventFlagItemFinderInfoMod ||
+                      (eventFlags[i] & kFSEventStreamEventFlagItemChangeOwner) == kFSEventStreamEventFlagItemChangeOwner ||
+                      (eventFlags[i] & kFSEventStreamEventFlagItemXattrMod) == kFSEventStreamEventFlagItemXattrMod;
+    bool isRenamed = (eventFlags[i] & kFSEventStreamEventFlagItemRenamed) == kFSEventStreamEventFlagItemRenamed;
+    bool isDone = (eventFlags[i] & kFSEventStreamEventFlagHistoryDone) == kFSEventStreamEventFlagHistoryDone;
+    bool isDir = (eventFlags[i] & kFSEventStreamEventFlagItemIsDir) == kFSEventStreamEventFlagItemIsDir;
+
+
+    if (eventFlags[i] & kFSEventStreamEventFlagMustScanSubDirs) {
+      if (eventFlags[i] & kFSEventStreamEventFlagUserDropped) {
+        list.error("Events were dropped by the FSEvents client. File system must be re-scanned.");
+      } else if (eventFlags[i] & kFSEventStreamEventFlagKernelDropped) {
+        list.error("Events were dropped by the kernel. File system must be re-scanned.");
+      } else {
+        list.error("Too many events. File system must be re-scanned.");
+      }
+    }
+
+    if (isDone) {
+      watcher->notify();
+      break;
+    }
+
+    auto ignoredFlags = IGNORED_FLAGS;
+    if (__builtin_available(macOS 10.13, *)) {
+      ignoredFlags |= kFSEventStreamEventFlagItemCloned;
+    }
+
+    // If we don't care about any of the flags that are set, ignore this event.
+    if ((eventFlags[i] & ~ignoredFlags) == 0) {
+      continue;
+    }
+
+    // FSEvents exclusion paths only apply to files, not directories.
+    if (watcher->isIgnored(paths[i])) {
+      continue;
+    }
+
+    // Handle unambiguous events first
+    if (isCreated && !(isRemoved || isModified || isRenamed)) {
+      state->tree->add(paths[i], 0, isDir);
+      list.create(paths[i]);
+    } else if (isRemoved && !(isCreated || isModified || isRenamed)) {
+      state->tree->remove(paths[i]);
+      list.remove(paths[i]);
+      if (paths[i] == watcher->mDir) {
+        deletedRoot = true;
+      }
+    } else if (isModified && !(isCreated || isRemoved || isRenamed)) {
+      struct stat file;
+      if (stat(paths[i], &file)) {
+        continue;
+      }
+
+      // Ignore if mtime is the same as the last event.
+      // This prevents duplicate events from being emitted.
+      // If tv_nsec is zero, the file system probably only has second-level
+      // granularity so allow the even through in that case.
+      uint64_t mtime = CONVERT_TIME(file.st_mtimespec);
+      DirEntry *entry = state->tree->find(paths[i]);
+      if (entry && mtime == entry->mtime && file.st_mtimespec.tv_nsec != 0) {
+        continue;
+      }
+
+      if (entry) {
+        // Update mtime.
+        entry->mtime = mtime;
+      } else {
+        // Add to tree if this path has not been discovered yet.
+        state->tree->add(paths[i], mtime, S_ISDIR(file.st_mode));
+      }
+
+      list.update(paths[i]);
+    } else {
+      // If multiple flags were set, then we need to call `stat` to determine if the file really exists.
+      // This helps disambiguate creates, updates, and deletes.
+      struct stat file;
+      if (stat(paths[i], &file) || !pathExists(paths[i])) {
+        // File does not exist, so we have to assume it was removed. This is not exact since the
+        // flags set by fsevents get coalesced together (e.g. created & deleted), so there is no way to
+        // know whether the create and delete both happened since our snapshot (in which case
+        // we'd rather ignore this event completely). This will result in some extra delete events
+        // being emitted for files we don't know about, but that is the best we can do.
+        state->tree->remove(paths[i]);
+        list.remove(paths[i]);
+        if (paths[i] == watcher->mDir) {
+          deletedRoot = true;
+        }
+        continue;
+      }
+
+      // If the file was modified, and existed before, then this is an update, otherwise a create.
+      uint64_t ctime = CONVERT_TIME(file.st_birthtimespec);
+      uint64_t mtime = CONVERT_TIME(file.st_mtimespec);
+      DirEntry *entry = !since ? state->tree->find(paths[i]) : NULL;
+      if (entry && entry->mtime == mtime && file.st_mtimespec.tv_nsec != 0) {
+        continue;
+      }
+
+      // Some mounted file systems report a creation time of 0/unix epoch which we special case.
+      if (isModified && (entry || (ctime <= since && ctime != 0))) {
+        state->tree->update(paths[i], mtime);
+        list.update(paths[i]);
+      } else {
+        state->tree->add(paths[i], mtime, S_ISDIR(file.st_mode));
+        list.create(paths[i]);
+      }
+    }
+  }
+
+  if (!since) {
+    watcher->notify();
+  }
+
+  // Stop watching if the root directory was deleted.
+  if (deletedRoot) {
+    stopStream((FSEventStreamRef)streamRef, CFRunLoopGetCurrent());
+    watcher->state = nullptr;
+  }
+}
+
+void checkWatcher(WatcherRef watcher) {
+  struct stat file;
+  if (stat(watcher->mDir.c_str(), &file)) {
+    throw WatcherError(strerror(errno), watcher);
+  }
+
+  if (!S_ISDIR(file.st_mode)) {
+    throw WatcherError(strerror(ENOTDIR), watcher);
+  }
+}
+
+void FSEventsBackend::startStream(WatcherRef watcher, FSEventStreamEventId id) {
+  checkWatcher(watcher);
+
+  CFAbsoluteTime latency = 0.001;
+  CFStringRef fileWatchPath = CFStringCreateWithCString(
+    NULL,
+    watcher->mDir.c_str(),
+    kCFStringEncodingUTF8
+  );
+
+  CFArrayRef pathsToWatch = CFArrayCreate(
+    NULL,
+    (const void **)&fileWatchPath,
+    1,
+    NULL
+  );
+
+  // Make a watcher reference we can pass into the callback. This ensures bumped ref-count.
+  std::shared_ptr<Watcher>* callbackWatcher = new std::shared_ptr<Watcher> (watcher);
+  FSEventStreamContext callbackInfo {0, static_cast<void*> (callbackWatcher), nullptr, nullptr, nullptr};
+  FSEventStreamRef stream = FSEventStreamCreate(
+    NULL,
+    &FSEventsCallback,
+    &callbackInfo,
+    pathsToWatch,
+    id,
+    latency,
+    kFSEventStreamCreateFlagFileEvents
+  );
+
+  CFMutableArrayRef exclusions = CFArrayCreateMutable(NULL, watcher->mIgnorePaths.size(), NULL);
+  for (auto it = watcher->mIgnorePaths.begin(); it != watcher->mIgnorePaths.end(); it++) {
+    CFStringRef path = CFStringCreateWithCString(
+      NULL,
+      it->c_str(),
+      kCFStringEncodingUTF8
+    );
+
+    CFArrayAppendValue(exclusions, (const void *)path);
+  }
+
+  FSEventStreamSetExclusionPaths(stream, exclusions);
+
+  FSEventStreamScheduleWithRunLoop(stream, mRunLoop, kCFRunLoopDefaultMode);
+  bool started = FSEventStreamStart(stream);
+
+  CFRelease(pathsToWatch);
+  CFRelease(fileWatchPath);
+
+  if (!started) {
+    FSEventStreamRelease(stream);
+    throw WatcherError("Error starting FSEvents stream", watcher);
+  }
+
+  auto stateGuard = watcher->state;
+  State* s = static_cast<State*>(stateGuard.get());
+  s->tree = std::make_shared<DirTree>(watcher->mDir);
+  s->stream = stream;
+}
+
+void FSEventsBackend::start() {
+  mRunLoop = CFRunLoopGetCurrent();
+  CFRetain(mRunLoop);
+
+  // Unlock once run loop has started.
+  CFRunLoopPerformBlock(mRunLoop, kCFRunLoopDefaultMode, ^ {
+    notifyStarted();
+  });
+
+  CFRunLoopWakeUp(mRunLoop);
+  CFRunLoopRun();
+}
+
+FSEventsBackend::~FSEventsBackend() {
+  std::unique_lock<std::mutex> lock(mMutex);
+  CFRunLoopStop(mRunLoop);
+  CFRelease(mRunLoop);
+}
+
+void FSEventsBackend::writeSnapshot(WatcherRef watcher, std::string *snapshotPath) {
+  std::unique_lock<std::mutex> lock(mMutex);
+  checkWatcher(watcher);
+
+  FSEventStreamEventId id = FSEventsGetCurrentEventId();
+  std::ofstream ofs(*snapshotPath);
+  ofs << id;
+  ofs << "\n";
+
+  struct timespec now;
+  clock_gettime(CLOCK_REALTIME, &now);
+  ofs << CONVERT_TIME(now);
+}
+
+void FSEventsBackend::getEventsSince(WatcherRef watcher, std::string *snapshotPath) {
+  std::unique_lock<std::mutex> lock(mMutex);
+  std::ifstream ifs(*snapshotPath);
+  if (ifs.fail()) {
+    return;
+  }
+
+  FSEventStreamEventId id;
+  uint64_t since;
+  ifs >> id;
+  ifs >> since;
+
+  auto s = std::make_shared<State>();
+  s->since = since;
+  watcher->state = s;
+
+  startStream(watcher, id);
+  watcher->wait();
+  stopStream(s->stream, mRunLoop);
+
+  watcher->state = nullptr;
+}
+
+// This function is called by Backend::watch which takes a lock on mMutex
+void FSEventsBackend::subscribe(WatcherRef watcher) {
+  auto s = std::make_shared<State>();
+  s->since = 0;
+  watcher->state = s;
+  startStream(watcher, kFSEventStreamEventIdSinceNow);
+}
+
+// This function is called by Backend::unwatch which takes a lock on mMutex
+void FSEventsBackend::unsubscribe(WatcherRef watcher) {
+  auto stateGuard = watcher->state;
+  State* s = static_cast<State*>(stateGuard.get());
+  if (s != nullptr) {
+    stopStream(s->stream, mRunLoop);
+    watcher->state = nullptr;
+  }
+}

+ 20 - 0
node_modules/@parcel/watcher/src/macos/FSEventsBackend.hh

@@ -0,0 +1,20 @@
+#ifndef FS_EVENTS_H
+#define FS_EVENTS_H
+
+#include <CoreServices/CoreServices.h>
+#include "../Backend.hh"
+
+class FSEventsBackend : public Backend {
+public:
+  void start() override;
+  ~FSEventsBackend();
+  void writeSnapshot(WatcherRef watcher, std::string *snapshotPath) override;
+  void getEventsSince(WatcherRef watcher, std::string *snapshotPath) override;
+  void subscribe(WatcherRef watcher) override;
+  void unsubscribe(WatcherRef watcher) override;
+private:
+  void startStream(WatcherRef watcher, FSEventStreamEventId id);
+  CFRunLoopRef mRunLoop;
+};
+
+#endif

+ 41 - 0
node_modules/@parcel/watcher/src/shared/BruteForceBackend.cc

@@ -0,0 +1,41 @@
+#include <string>
+#include "../DirTree.hh"
+#include "../Event.hh"
+#include "./BruteForceBackend.hh"
+
+std::shared_ptr<DirTree> BruteForceBackend::getTree(WatcherRef watcher, bool shouldRead) {
+  auto tree = DirTree::getCached(watcher->mDir);
+
+  // If the tree is not complete, read it if needed.
+  if (!tree->isComplete && shouldRead) {
+    readTree(watcher, tree);
+    tree->isComplete = true;
+  }
+
+  return tree;
+}
+
+void BruteForceBackend::writeSnapshot(WatcherRef watcher, std::string *snapshotPath) {
+  std::unique_lock<std::mutex> lock(mMutex);
+  auto tree = getTree(watcher);
+  FILE *f = fopen(snapshotPath->c_str(), "w");
+  if (!f) {
+    throw std::runtime_error(std::string("Unable to open snapshot file: ") + strerror(errno));
+  }
+
+  tree->write(f);
+  fclose(f);
+}
+
+void BruteForceBackend::getEventsSince(WatcherRef watcher, std::string *snapshotPath) {
+  std::unique_lock<std::mutex> lock(mMutex);
+  FILE *f = fopen(snapshotPath->c_str(), "r");
+  if (!f) {
+    throw std::runtime_error(std::string("Unable to open snapshot file: ") + strerror(errno));
+  }
+
+  DirTree snapshot{watcher->mDir, f};
+  auto now = getTree(watcher);
+  now->getChanges(&snapshot, watcher->mEvents);
+  fclose(f);
+}

+ 25 - 0
node_modules/@parcel/watcher/src/shared/BruteForceBackend.hh

@@ -0,0 +1,25 @@
+#ifndef BRUTE_FORCE_H
+#define BRUTE_FORCE_H
+
+#include "../Backend.hh"
+#include "../DirTree.hh"
+#include "../Watcher.hh"
+
+class BruteForceBackend : public Backend {
+public:
+  void writeSnapshot(WatcherRef watcher, std::string *snapshotPath) override;
+  void getEventsSince(WatcherRef watcher, std::string *snapshotPath) override;
+  void subscribe(WatcherRef watcher) override {
+    throw "Brute force backend doesn't support subscriptions.";
+  }
+
+  void unsubscribe(WatcherRef watcher) override {
+    throw "Brute force backend doesn't support subscriptions.";
+  }
+
+  std::shared_ptr<DirTree> getTree(WatcherRef watcher, bool shouldRead = true);
+private:
+  void readTree(WatcherRef watcher, std::shared_ptr<DirTree> tree);
+};
+
+#endif

+ 50 - 0
node_modules/@parcel/watcher/src/unix/fts.cc

@@ -0,0 +1,50 @@
+#include <string>
+
+// weird error on linux
+#ifdef __THROW
+#undef __THROW
+#endif
+#define __THROW
+
+#include <fts.h>
+#include <sys/stat.h>
+#include "../DirTree.hh"
+#include "../shared/BruteForceBackend.hh"
+
+#define CONVERT_TIME(ts) ((uint64_t)ts.tv_sec * 1000000000 + ts.tv_nsec)
+#if __APPLE__
+#define st_mtim st_mtimespec
+#endif
+
+void BruteForceBackend::readTree(WatcherRef watcher, std::shared_ptr<DirTree> tree) {
+  char *paths[2] {(char *)watcher->mDir.c_str(), NULL};
+  FTS *fts = fts_open(paths, FTS_NOCHDIR | FTS_PHYSICAL, NULL);
+  if (!fts) {
+    throw WatcherError(strerror(errno), watcher);
+  }
+
+  FTSENT *node;
+  bool isRoot = true;
+
+  while ((node = fts_read(fts)) != NULL) {
+    if (node->fts_errno) {
+      fts_close(fts);
+      throw WatcherError(strerror(node->fts_errno), watcher);
+    }
+
+    if (isRoot && !(node->fts_info & FTS_D)) {
+      fts_close(fts);
+      throw WatcherError(strerror(ENOTDIR), watcher);
+    }
+
+    if (watcher->isIgnored(std::string(node->fts_path))) {
+      fts_set(fts, node, FTS_SKIP);
+      continue;
+    }
+
+    tree->add(node->fts_path, CONVERT_TIME(node->fts_statp->st_mtim), (node->fts_info & FTS_D) == FTS_D);
+    isRoot = false;
+  }
+
+  fts_close(fts);
+}

+ 77 - 0
node_modules/@parcel/watcher/src/unix/legacy.cc

@@ -0,0 +1,77 @@
+#include <string>
+
+// weird error on linux
+#ifdef __THROW
+#undef __THROW
+#endif
+#define __THROW
+
+#ifdef _LIBC
+# include <include/sys/stat.h>
+#else
+# include <sys/stat.h>
+#endif
+#include <dirent.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "../DirTree.hh"
+#include "../shared/BruteForceBackend.hh"
+
+#define CONVERT_TIME(ts) ((uint64_t)ts.tv_sec * 1000000000 + ts.tv_nsec)
+#if __APPLE__
+#define st_mtim st_mtimespec
+#endif
+#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
+
+void iterateDir(WatcherRef watcher, const std::shared_ptr <DirTree> tree, const char *relative, int parent_fd, const std::string &dirname) {
+    int open_flags = (O_RDONLY | O_CLOEXEC | O_DIRECTORY | O_NOCTTY | O_NONBLOCK | O_NOFOLLOW);
+    int new_fd = openat(parent_fd, relative, open_flags);
+    if (new_fd == -1) {
+        if (errno == EACCES) {
+            return; // ignore insufficient permissions
+        }
+
+        throw WatcherError(strerror(errno), watcher);
+    }
+
+    struct stat rootAttributes;
+    fstatat(new_fd, ".", &rootAttributes, AT_SYMLINK_NOFOLLOW);
+    tree->add(dirname, CONVERT_TIME(rootAttributes.st_mtim), true);
+
+    if (DIR *dir = fdopendir(new_fd)) {
+        while (struct dirent *ent = (errno = 0, readdir(dir))) {
+            if (ISDOT(ent->d_name)) continue;
+
+            std::string fullPath = dirname + "/" + ent->d_name;
+
+            if (!watcher->isIgnored(fullPath)) {
+                struct stat attrib;
+                fstatat(new_fd, ent->d_name, &attrib, AT_SYMLINK_NOFOLLOW);
+                bool isDir = ent->d_type == DT_DIR;
+
+                if (isDir) {
+                    iterateDir(watcher, tree, ent->d_name, new_fd, fullPath);
+                } else {
+                    tree->add(fullPath, CONVERT_TIME(attrib.st_mtim), isDir);
+                }
+            }
+        }
+
+        closedir(dir);
+    } else {
+        close(new_fd);
+    }
+
+    if (errno) {
+        throw WatcherError(strerror(errno), watcher);
+    }
+}
+
+void BruteForceBackend::readTree(WatcherRef watcher, std::shared_ptr <DirTree> tree) {
+    int fd = open(watcher->mDir.c_str(), O_RDONLY);
+    if (fd) {
+        iterateDir(watcher, tree, ".", fd, watcher->mDir);
+        close(fd);
+    }
+}

+ 132 - 0
node_modules/@parcel/watcher/src/wasm/WasmBackend.cc

@@ -0,0 +1,132 @@
+#include <sys/stat.h>
+#include "WasmBackend.hh"
+
+#define CONVERT_TIME(ts) ((uint64_t)ts.tv_sec * 1000000000 + ts.tv_nsec)
+
+void WasmBackend::start() {
+  notifyStarted();
+}
+
+void WasmBackend::subscribe(WatcherRef watcher) {
+  // Build a full directory tree recursively, and watch each directory.
+  std::shared_ptr<DirTree> tree = getTree(watcher);
+
+  for (auto it = tree->entries.begin(); it != tree->entries.end(); it++) {
+    if (it->second.isDir) {
+      watchDir(watcher, it->second.path, tree);
+    }
+  }
+}
+
+void WasmBackend::watchDir(WatcherRef watcher, std::string path, std::shared_ptr<DirTree> tree) {
+  int wd = wasm_backend_add_watch(path.c_str(), (void *)this);
+  std::shared_ptr<WasmSubscription> sub = std::make_shared<WasmSubscription>();
+  sub->tree = tree;
+  sub->path = path;
+  sub->watcher = watcher;
+  mSubscriptions.emplace(wd, sub);
+}
+
+extern "C" void wasm_backend_event_handler(void *backend, int wd, int type, char *filename) {
+  WasmBackend *b = (WasmBackend *)(backend);
+  b->handleEvent(wd, type, filename);
+}
+
+void WasmBackend::handleEvent(int wd, int type, char *filename) {
+  // Find the subscriptions for this watch descriptor
+  auto range = mSubscriptions.equal_range(wd);
+  std::unordered_set<std::shared_ptr<WasmSubscription>> set;
+  for (auto it = range.first; it != range.second; it++) {
+    set.insert(it->second);
+  }
+
+  for (auto it = set.begin(); it != set.end(); it++) {
+    if (handleSubscription(type, filename, *it)) {
+      (*it)->watcher->notify();
+    }
+  }
+}
+
+bool WasmBackend::handleSubscription(int type, char *filename, std::shared_ptr<WasmSubscription> sub) {
+  // Build full path and check if its in our ignore list.
+  WatcherRef watcher = sub->watcher;
+  std::string path = std::string(sub->path);
+
+  if (filename[0] != '\0') {
+    path += "/" + std::string(filename);
+  }
+
+  if (watcher->isIgnored(path)) {
+    return false;
+  }
+
+  if (type == 1) {
+    struct stat st;
+    stat(path.c_str(), &st);
+    sub->tree->update(path, CONVERT_TIME(st.st_mtim));
+    watcher->mEvents.update(path);
+  } else if (type == 2) {
+    // Determine if this is a create or delete depending on if the file exists or not.
+    struct stat st;
+    if (lstat(path.c_str(), &st)) {
+      // If the entry being deleted/moved is a directory, remove it from the list of subscriptions
+      DirEntry *entry = sub->tree->find(path);
+      if (!entry) {
+        return false;
+      }
+
+      if (entry->isDir) {
+        std::string pathStart = path + DIR_SEP;
+        for (auto it = mSubscriptions.begin(); it != mSubscriptions.end();) {
+          if (it->second->path == path || it->second->path.rfind(pathStart, 0) == 0) {
+            wasm_backend_remove_watch(it->first);
+            it = mSubscriptions.erase(it);
+          } else {
+            ++it;
+          }
+        }
+
+        // Remove all sub-entries
+        for (auto it = sub->tree->entries.begin(); it != sub->tree->entries.end();) {
+          if (it->first.rfind(pathStart, 0) == 0) {
+            watcher->mEvents.remove(it->first);
+            it = sub->tree->entries.erase(it);
+          } else {
+            it++;
+          }
+        }
+      }
+
+      watcher->mEvents.remove(path);
+      sub->tree->remove(path);
+    } else if (sub->tree->find(path)) {
+      sub->tree->update(path, CONVERT_TIME(st.st_mtim));
+      watcher->mEvents.update(path);
+    } else {
+      watcher->mEvents.create(path);
+
+      // If this is a create, check if it's a directory and start watching if it is.
+      DirEntry *entry = sub->tree->add(path, CONVERT_TIME(st.st_mtim), S_ISDIR(st.st_mode));
+      if (entry->isDir) {
+        watchDir(watcher, path, sub->tree);
+      }
+    }
+  }
+
+  return true;
+}
+
+void WasmBackend::unsubscribe(WatcherRef watcher) {
+  // Find any subscriptions pointing to this watcher, and remove them.
+  for (auto it = mSubscriptions.begin(); it != mSubscriptions.end();) {
+    if (it->second->watcher.get() == watcher.get()) {
+      if (mSubscriptions.count(it->first) == 1) {
+        wasm_backend_remove_watch(it->first);
+      }
+
+      it = mSubscriptions.erase(it);
+    } else {
+      it++;
+    }
+  }
+}

+ 34 - 0
node_modules/@parcel/watcher/src/wasm/WasmBackend.hh

@@ -0,0 +1,34 @@
+#ifndef WASM_H
+#define WASM_H
+
+#include <unordered_map>
+#include "../shared/BruteForceBackend.hh"
+#include "../DirTree.hh"
+
+extern "C" {
+  int wasm_backend_add_watch(const char *filename, void *backend);
+  void wasm_backend_remove_watch(int wd);
+  void wasm_backend_event_handler(void *backend, int wd, int type, char *filename);
+};
+
+struct WasmSubscription {
+  std::shared_ptr<DirTree> tree;
+  std::string path;
+  WatcherRef watcher;
+};
+
+class WasmBackend : public BruteForceBackend {
+public:
+  void start() override;
+  void subscribe(WatcherRef watcher) override;
+  void unsubscribe(WatcherRef watcher) override;
+  void handleEvent(int wd, int type, char *filename);
+private:
+  int mWasm;
+  std::unordered_multimap<int, std::shared_ptr<WasmSubscription>> mSubscriptions;
+
+  void watchDir(WatcherRef watcher, std::string path, std::shared_ptr<DirTree> tree);
+  bool handleSubscription(int type, char *filename, std::shared_ptr<WasmSubscription> sub);
+};
+
+#endif

+ 74 - 0
node_modules/@parcel/watcher/src/wasm/include.h

@@ -0,0 +1,74 @@
+/*
+Copyright Node.js contributors. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
+*/
+
+// Node does not include the headers for these functions when compiling for WASM, so add them here.
+#ifdef __wasm32__
+extern "C" {
+NAPI_EXTERN napi_status NAPI_CDECL
+napi_create_threadsafe_function(napi_env env,
+                                napi_value func,
+                                napi_value async_resource,
+                                napi_value async_resource_name,
+                                size_t max_queue_size,
+                                size_t initial_thread_count,
+                                void* thread_finalize_data,
+                                napi_finalize thread_finalize_cb,
+                                void* context,
+                                napi_threadsafe_function_call_js call_js_cb,
+                                napi_threadsafe_function* result);
+
+NAPI_EXTERN napi_status NAPI_CDECL napi_get_threadsafe_function_context(
+    napi_threadsafe_function func, void** result);
+
+NAPI_EXTERN napi_status NAPI_CDECL
+napi_call_threadsafe_function(napi_threadsafe_function func,
+                              void* data,
+                              napi_threadsafe_function_call_mode is_blocking);
+
+NAPI_EXTERN napi_status NAPI_CDECL
+napi_acquire_threadsafe_function(napi_threadsafe_function func);
+
+NAPI_EXTERN napi_status NAPI_CDECL napi_release_threadsafe_function(
+    napi_threadsafe_function func, napi_threadsafe_function_release_mode mode);
+
+NAPI_EXTERN napi_status NAPI_CDECL
+napi_unref_threadsafe_function(napi_env env, napi_threadsafe_function func);
+
+NAPI_EXTERN napi_status NAPI_CDECL
+napi_ref_threadsafe_function(napi_env env, napi_threadsafe_function func);
+
+NAPI_EXTERN napi_status NAPI_CDECL
+napi_create_async_work(napi_env env,
+                       napi_value async_resource,
+                       napi_value async_resource_name,
+                       napi_async_execute_callback execute,
+                       napi_async_complete_callback complete,
+                       void* data,
+                       napi_async_work* result);
+NAPI_EXTERN napi_status NAPI_CDECL napi_delete_async_work(napi_env env,
+                                                          napi_async_work work);
+NAPI_EXTERN napi_status NAPI_CDECL napi_queue_async_work(napi_env env,
+                                                         napi_async_work work);
+NAPI_EXTERN napi_status NAPI_CDECL napi_cancel_async_work(napi_env env,
+                                                          napi_async_work work);
+}
+#endif

+ 302 - 0
node_modules/@parcel/watcher/src/watchman/BSER.cc

@@ -0,0 +1,302 @@
+#include <stdint.h>
+#include "./BSER.hh"
+
+BSERType decodeType(std::istream &iss) {
+  int8_t type;
+  iss.read(reinterpret_cast<char*>(&type), sizeof(type));
+  return (BSERType) type;
+}
+
+void expectType(std::istream &iss, BSERType expected) {
+  BSERType got = decodeType(iss);
+  if (got != expected) {
+    throw std::runtime_error("Unexpected BSER type");
+  }
+}
+
+void encodeType(std::ostream &oss, BSERType type) {
+  int8_t t = (int8_t)type;
+  oss.write(reinterpret_cast<char*>(&t), sizeof(t));
+}
+
+template<typename T>
+class Value : public BSERValue {
+public:
+  T value;
+  Value(T val) {
+    value = val;
+  }
+
+  Value() {}
+};
+
+class BSERInteger : public Value<int64_t> {
+public:
+  BSERInteger(int64_t value) : Value(value) {}
+  BSERInteger(std::istream &iss) {
+    int8_t int8;
+    int16_t int16;
+    int32_t int32;
+    int64_t int64;
+
+    BSERType type = decodeType(iss);
+
+    switch (type) {
+      case BSER_INT8:
+        iss.read(reinterpret_cast<char*>(&int8), sizeof(int8));
+        value = int8;
+        break;
+      case BSER_INT16:
+        iss.read(reinterpret_cast<char*>(&int16), sizeof(int16));
+        value = int16;
+        break;
+      case BSER_INT32:
+        iss.read(reinterpret_cast<char*>(&int32), sizeof(int32));
+        value = int32;
+        break;
+      case BSER_INT64:
+        iss.read(reinterpret_cast<char*>(&int64), sizeof(int64));
+        value = int64;
+        break;
+      default:
+        throw std::runtime_error("Invalid BSER int type");
+    }
+  }
+
+  int64_t intValue() override {
+    return value;
+  }
+
+  void encode(std::ostream &oss) override {
+    if (value <= INT8_MAX) {
+      encodeType(oss, BSER_INT8);
+      int8_t v = (int8_t)value;
+      oss.write(reinterpret_cast<char*>(&v), sizeof(v));
+    } else if (value <= INT16_MAX) {
+      encodeType(oss, BSER_INT16);
+      int16_t v = (int16_t)value;
+      oss.write(reinterpret_cast<char*>(&v), sizeof(v));
+    } else if (value <= INT32_MAX) {
+      encodeType(oss, BSER_INT32);
+      int32_t v = (int32_t)value;
+      oss.write(reinterpret_cast<char*>(&v), sizeof(v));
+    } else {
+      encodeType(oss, BSER_INT64);
+      oss.write(reinterpret_cast<char*>(&value), sizeof(value));
+    }
+  }
+};
+
+class BSERArray : public Value<BSER::Array> {
+public:
+  BSERArray() : Value() {}
+  BSERArray(BSER::Array value) : Value(value) {}
+  BSERArray(std::istream &iss) {
+    expectType(iss, BSER_ARRAY);
+    int64_t len = BSERInteger(iss).intValue();
+    for (int64_t i = 0; i < len; i++) {
+      value.push_back(BSER(iss));
+    }
+  }
+  
+  BSER::Array arrayValue() override {
+    return value;
+  }
+
+  void encode(std::ostream &oss) override {
+    encodeType(oss, BSER_ARRAY);
+    BSERInteger(value.size()).encode(oss);
+    for (auto it = value.begin(); it != value.end(); it++) {
+      it->encode(oss);
+    }
+  }
+};
+
+class BSERString : public Value<std::string> {
+public:
+  BSERString(std::string value) : Value(value) {}
+  BSERString(std::istream &iss) {
+    expectType(iss, BSER_STRING);
+    int64_t len = BSERInteger(iss).intValue();
+    value.resize(len);
+    iss.read(&value[0], len);
+  }
+
+  std::string stringValue() override {
+    return value;
+  }
+
+  void encode(std::ostream &oss) override {
+    encodeType(oss, BSER_STRING);
+    BSERInteger(value.size()).encode(oss);
+    oss << value;
+  }
+};
+
+class BSERObject : public Value<BSER::Object> {
+public:
+  BSERObject() : Value() {}
+  BSERObject(BSER::Object value) : Value(value) {}
+  BSERObject(std::istream &iss) {
+    expectType(iss, BSER_OBJECT);
+    int64_t len = BSERInteger(iss).intValue();
+    for (int64_t i = 0; i < len; i++) {
+      auto key = BSERString(iss).stringValue();
+      auto val = BSER(iss);
+      value.emplace(key, val);
+    }
+  }
+
+  BSER::Object objectValue() override {
+    return value;
+  }
+
+  void encode(std::ostream &oss) override {
+    encodeType(oss, BSER_OBJECT);
+    BSERInteger(value.size()).encode(oss);
+    for (auto it = value.begin(); it != value.end(); it++) {
+      BSERString(it->first).encode(oss);
+      it->second.encode(oss);
+    }
+  }
+};
+
+class BSERDouble : public Value<double> {
+public:
+  BSERDouble(double value) : Value(value) {}
+  BSERDouble(std::istream &iss) {
+    expectType(iss, BSER_REAL);
+    iss.read(reinterpret_cast<char*>(&value), sizeof(value));
+  }
+
+  double doubleValue() override {
+    return value;
+  }
+
+  void encode(std::ostream &oss) override {
+    encodeType(oss, BSER_REAL);
+    oss.write(reinterpret_cast<char*>(&value), sizeof(value));
+  }
+};
+
+class BSERBoolean : public Value<bool> {
+public:
+  BSERBoolean(bool value) : Value(value) {}
+  bool boolValue() override { return value; }
+  void encode(std::ostream &oss) override {
+    int8_t t = value == true ? BSER_BOOL_TRUE : BSER_BOOL_FALSE;
+    oss.write(reinterpret_cast<char*>(&t), sizeof(t));
+  }
+};
+
+class BSERNull : public Value<bool> {
+public:
+  BSERNull() : Value(false) {}
+  void encode(std::ostream &oss) override {
+    encodeType(oss, BSER_NULL);
+  }
+};
+
+std::shared_ptr<BSERArray> decodeTemplate(std::istream &iss) {
+  expectType(iss, BSER_TEMPLATE);
+  auto keys = BSERArray(iss).arrayValue();
+  auto len = BSERInteger(iss).intValue();
+  std::shared_ptr<BSERArray> arr = std::make_shared<BSERArray>();
+  for (int64_t i = 0; i < len; i++) {
+    BSER::Object obj;
+    for (auto it = keys.begin(); it != keys.end(); it++) {
+      if (iss.peek() == 0x0c) {
+        iss.ignore(1);
+        continue;
+      }
+
+      auto val = BSER(iss);
+      obj.emplace(it->stringValue(), val);
+    }
+    arr->value.push_back(obj);
+  }
+  return arr;
+}
+
+BSER::BSER(std::istream &iss) {
+  BSERType type = decodeType(iss);
+  iss.unget();
+
+  switch (type) {
+    case BSER_ARRAY:
+      m_ptr = std::make_shared<BSERArray>(iss);
+      break;
+    case BSER_OBJECT:
+      m_ptr = std::make_shared<BSERObject>(iss);
+      break;
+    case BSER_STRING:
+      m_ptr = std::make_shared<BSERString>(iss);
+      break;
+    case BSER_INT8:
+    case BSER_INT16:
+    case BSER_INT32:
+    case BSER_INT64:
+      m_ptr = std::make_shared<BSERInteger>(iss);
+      break;
+    case BSER_REAL:
+      m_ptr = std::make_shared<BSERDouble>(iss);
+      break;
+    case BSER_BOOL_TRUE:
+      iss.ignore(1);
+      m_ptr = std::make_shared<BSERBoolean>(true);
+      break;
+    case BSER_BOOL_FALSE:
+      iss.ignore(1);
+      m_ptr = std::make_shared<BSERBoolean>(false);
+      break;
+    case BSER_NULL:
+      iss.ignore(1);
+      m_ptr = std::make_shared<BSERNull>();
+      break;
+    case BSER_TEMPLATE:
+      m_ptr = decodeTemplate(iss);
+      break;
+    default:
+      throw std::runtime_error("unknown BSER type");
+  }
+}
+
+BSER::BSER() : m_ptr(std::make_shared<BSERNull>()) {}
+BSER::BSER(BSER::Array value) : m_ptr(std::make_shared<BSERArray>(value)) {}
+BSER::BSER(BSER::Object value) : m_ptr(std::make_shared<BSERObject>(value)) {}
+BSER::BSER(const char *value) : m_ptr(std::make_shared<BSERString>(value)) {}
+BSER::BSER(std::string value) : m_ptr(std::make_shared<BSERString>(value)) {}
+BSER::BSER(int64_t value) : m_ptr(std::make_shared<BSERInteger>(value)) {}
+BSER::BSER(double value) : m_ptr(std::make_shared<BSERDouble>(value)) {}
+BSER::BSER(bool value) : m_ptr(std::make_shared<BSERBoolean>(value)) {}
+
+BSER::Array BSER::arrayValue() { return m_ptr->arrayValue(); }
+BSER::Object BSER::objectValue() { return m_ptr->objectValue(); }
+std::string BSER::stringValue() { return m_ptr->stringValue(); }
+int64_t BSER::intValue() { return m_ptr->intValue(); }
+double BSER::doubleValue() { return m_ptr->doubleValue(); }
+bool BSER::boolValue() { return m_ptr->boolValue(); }
+void BSER::encode(std::ostream &oss) {
+  m_ptr->encode(oss);
+}
+
+int64_t BSER::decodeLength(std::istream &iss) {
+  char pdu[2];
+  if (!iss.read(pdu, 2) || pdu[0] != 0 || pdu[1] != 1) {
+    throw std::runtime_error("Invalid BSER");
+  }
+
+  return BSERInteger(iss).intValue();
+}
+
+std::string BSER::encode() {
+  std::ostringstream oss(std::ios_base::binary);
+  encode(oss);
+
+  std::ostringstream res(std::ios_base::binary);
+  res.write("\x00\x01", 2);
+  
+  BSERInteger(oss.str().size()).encode(res);
+  res << oss.str();
+  return res.str();
+}

+ 69 - 0
node_modules/@parcel/watcher/src/watchman/BSER.hh

@@ -0,0 +1,69 @@
+#ifndef BSER_H
+#define BSER_H
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <unordered_map>
+#include <memory>
+
+enum BSERType {
+  BSER_ARRAY = 0x00,
+  BSER_OBJECT = 0x01,
+  BSER_STRING = 0x02,
+  BSER_INT8 = 0x03,
+  BSER_INT16 = 0x04,
+  BSER_INT32 = 0x05,
+  BSER_INT64 = 0x06,
+  BSER_REAL = 0x07,
+  BSER_BOOL_TRUE = 0x08,
+  BSER_BOOL_FALSE = 0x09,
+  BSER_NULL = 0x0a,
+  BSER_TEMPLATE = 0x0b
+};
+
+class BSERValue;
+
+class BSER {
+public:
+  typedef std::vector<BSER> Array;
+  typedef std::unordered_map<std::string, BSER> Object;
+
+  BSER();
+  BSER(BSER::Array value);
+  BSER(BSER::Object value);
+  BSER(std::string value);
+  BSER(const char *value);
+  BSER(int64_t value);
+  BSER(double value);
+  BSER(bool value);
+  BSER(std::istream &iss);
+
+  BSER::Array arrayValue();
+  BSER::Object objectValue();
+  std::string stringValue();
+  int64_t intValue();
+  double doubleValue();
+  bool boolValue();
+  void encode(std::ostream &oss);
+
+  static int64_t decodeLength(std::istream &iss);
+  std::string encode();
+private:
+  std::shared_ptr<BSERValue> m_ptr;
+};
+
+class BSERValue {
+protected:
+  friend class BSER;
+  virtual BSER::Array arrayValue() { return BSER::Array(); }
+  virtual BSER::Object objectValue() { return BSER::Object(); }
+  virtual std::string stringValue() { return std::string(); }
+  virtual int64_t intValue() { return 0; }
+  virtual double doubleValue() { return 0; }
+  virtual bool boolValue() { return false; }
+  virtual void encode(std::ostream &oss) {}
+  virtual ~BSERValue() {}
+};
+
+#endif

+ 175 - 0
node_modules/@parcel/watcher/src/watchman/IPC.hh

@@ -0,0 +1,175 @@
+#ifndef IPC_H
+#define IPC_H
+
+#include <string>
+#include <stdlib.h>
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <windows.h>
+#else
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#endif
+
+class IPC {
+public:
+  IPC(std::string path) {
+    mStopped = false;
+    #ifdef _WIN32
+      while (true) {
+        mPipe = CreateFile(
+          path.data(), // pipe name
+          GENERIC_READ | GENERIC_WRITE, // read and write access
+          0, // no sharing
+          NULL, // default security attributes
+          OPEN_EXISTING, // opens existing pipe
+          FILE_FLAG_OVERLAPPED, // attributes
+          NULL // no template file
+        );
+
+        if (mPipe != INVALID_HANDLE_VALUE) {
+          break;
+        }
+
+        if (GetLastError() != ERROR_PIPE_BUSY) {
+          throw std::runtime_error("Could not open pipe");
+        }
+
+        // Wait for pipe to become available if it is busy
+        if (!WaitNamedPipe(path.data(), 30000)) {
+          throw std::runtime_error("Error waiting for pipe");
+        }
+      }
+
+      mReader = CreateEvent(NULL, true, false, NULL);
+      mWriter = CreateEvent(NULL, true, false, NULL);
+    #else
+      struct sockaddr_un addr;
+      memset(&addr, 0, sizeof(addr));
+      addr.sun_family = AF_UNIX;
+      strncpy(addr.sun_path, path.c_str(), sizeof(addr.sun_path) - 1);
+
+      mSock = socket(AF_UNIX, SOCK_STREAM, 0);
+      if (connect(mSock, (struct sockaddr *) &addr, sizeof(struct sockaddr_un))) {
+        throw std::runtime_error("Error connecting to socket");
+      }
+    #endif
+  }
+
+  ~IPC() {
+    mStopped = true;
+    #ifdef _WIN32
+      CancelIo(mPipe);
+      CloseHandle(mPipe);
+      CloseHandle(mReader);
+      CloseHandle(mWriter);
+    #else
+      shutdown(mSock, SHUT_RDWR);
+    #endif
+  }
+
+  void write(std::string buf) {
+    #ifdef _WIN32
+      OVERLAPPED overlapped;
+      overlapped.hEvent = mWriter;
+      bool success = WriteFile(
+        mPipe, // pipe handle
+        buf.data(), // message
+        buf.size(), // message length
+        NULL, // bytes written
+        &overlapped // overlapped
+      );
+
+      if (mStopped) {
+        return;
+      }
+
+      if (!success) {
+        if (GetLastError() != ERROR_IO_PENDING) {
+          throw std::runtime_error("Write error");
+        }
+      }
+
+      DWORD written;
+      success = GetOverlappedResult(mPipe, &overlapped, &written, true);
+      if (!success) {
+        throw std::runtime_error("GetOverlappedResult failed");
+      }
+
+      if (written != buf.size()) {
+        throw std::runtime_error("Wrong number of bytes written");
+      }
+    #else
+      int r = 0;
+      for (unsigned int i = 0; i != buf.size(); i += r) {
+        r = ::write(mSock, &buf[i], buf.size() - i);
+        if (r == -1) {
+          if (errno == EAGAIN) {
+            r = 0;
+          } else if (mStopped) {
+            return;
+          } else {
+            throw std::runtime_error("Write error");
+          }
+        }
+      }
+    #endif
+  }
+
+  int read(char *buf, size_t len) {
+    #ifdef _WIN32
+      OVERLAPPED overlapped;
+      overlapped.hEvent = mReader;
+      bool success = ReadFile(
+        mPipe, // pipe handle
+        buf, // buffer to receive reply
+        len, // size of buffer
+        NULL, // number of bytes read
+        &overlapped // overlapped
+      );
+
+      if (!success && !mStopped) {
+        if (GetLastError() != ERROR_IO_PENDING) {
+          throw std::runtime_error("Read error");
+        }
+      }
+
+      DWORD read = 0;
+      success = GetOverlappedResult(mPipe, &overlapped, &read, true);
+      if (!success && !mStopped) {
+        throw std::runtime_error("GetOverlappedResult failed");
+      }
+
+      return read;
+    #else
+      int r = ::read(mSock, buf, len);
+      if (r == 0 && !mStopped) {
+        throw std::runtime_error("Socket ended unexpectedly");
+      }
+
+      if (r < 0) {
+        if (mStopped) {
+          return 0;
+        }
+
+        throw std::runtime_error(strerror(errno));
+      }
+
+      return r;
+    #endif
+  }
+
+private:
+  bool mStopped;
+  #ifdef _WIN32
+    HANDLE mPipe;
+    HANDLE mReader;
+    HANDLE mWriter;
+  #else
+    int mSock;
+  #endif
+};
+
+#endif

+ 338 - 0
node_modules/@parcel/watcher/src/watchman/WatchmanBackend.cc

@@ -0,0 +1,338 @@
+#include <string>
+#include <fstream>
+#include <stdlib.h>
+#include <algorithm>
+#include "../DirTree.hh"
+#include "../Event.hh"
+#include "./BSER.hh"
+#include "./WatchmanBackend.hh"
+
+#ifdef _WIN32
+#include "../windows/win_utils.hh"
+#define S_ISDIR(mode) ((mode & _S_IFDIR) == _S_IFDIR)
+#define popen _popen
+#define pclose _pclose
+#else
+#include <sys/stat.h>
+#define normalizePath(dir) dir
+#endif
+
+template<typename T>
+BSER readBSER(T &&do_read) {
+  std::stringstream oss;
+  char buffer[256];
+  int r;
+  int64_t len = -1;
+  do {
+    // Start by reading a minimal amount of data in order to decode the length.
+    // After that, attempt to read the remaining length, up to the buffer size.
+    r = do_read(buffer, len == -1 ? 20 : (len < 256 ? len : 256));
+    oss << std::string(buffer, r);
+
+    if (len == -1) {
+      uint64_t l = BSER::decodeLength(oss);
+      len = l + oss.tellg();
+    }
+
+    len -= r;
+  } while (len > 0);
+
+  return BSER(oss);
+}
+
+std::string getSockPath() {
+  auto var = getenv("WATCHMAN_SOCK");
+  if (var && *var) {
+    return std::string(var);
+  }
+
+  FILE *fp = popen("watchman --output-encoding=bser get-sockname", "r");
+  if (fp == NULL || errno == ECHILD) {
+    throw std::runtime_error("Failed to execute watchman");
+  }
+
+  BSER b = readBSER([fp] (char *buf, size_t len) {
+    return fread(buf, sizeof(char), len, fp);
+  });
+
+  pclose(fp);
+
+  auto objValue = b.objectValue();
+  auto foundSockname = objValue.find("sockname");
+  if (foundSockname == objValue.end()) {
+    throw std::runtime_error("sockname not found");
+  }
+  return foundSockname->second.stringValue();
+}
+
+std::unique_ptr<IPC> watchmanConnect() {
+  std::string path = getSockPath();
+  return std::unique_ptr<IPC>(new IPC(path));
+}
+
+BSER watchmanRead(IPC *ipc) {
+  return readBSER([ipc] (char *buf, size_t len) {
+    return ipc->read(buf, len);
+  });
+}
+
+BSER::Object WatchmanBackend::watchmanRequest(BSER b) {
+  std::string cmd = b.encode();
+  mIPC->write(cmd);
+  mRequestSignal.notify();
+
+  mResponseSignal.wait();
+  mResponseSignal.reset();
+
+  if (!mError.empty()) {
+    std::runtime_error err = std::runtime_error(mError);
+    mError = std::string();
+    throw err;
+  }
+
+  return mResponse;
+}
+
+void WatchmanBackend::watchmanWatch(std::string dir) {
+  std::vector<BSER> cmd;
+  cmd.push_back("watch");
+  cmd.push_back(normalizePath(dir));
+  watchmanRequest(cmd);
+}
+
+bool WatchmanBackend::checkAvailable() {
+  try {
+    watchmanConnect();
+    return true;
+  } catch (std::exception &err) {
+    return false;
+  }
+}
+
+void handleFiles(WatcherRef watcher, BSER::Object obj) {
+  auto found = obj.find("files");
+  if (found == obj.end()) {
+    throw WatcherError("Error reading changes from watchman", watcher);
+  }
+
+  auto files = found->second.arrayValue();
+  for (auto it = files.begin(); it != files.end(); it++) {
+    auto file = it->objectValue();
+    auto name = file.find("name")->second.stringValue();
+    #ifdef _WIN32
+      std::replace(name.begin(), name.end(), '/', '\\');
+    #endif
+    auto mode = file.find("mode")->second.intValue();
+    auto isNew = file.find("new")->second.boolValue();
+    auto exists = file.find("exists")->second.boolValue();
+    auto path = watcher->mDir + DIR_SEP + name;
+    if (watcher->isIgnored(path)) {
+      continue;
+    }
+
+    if (isNew && exists) {
+      watcher->mEvents.create(path);
+    } else if (exists && !S_ISDIR(mode)) {
+      watcher->mEvents.update(path);
+    } else if (!isNew && !exists) {
+      watcher->mEvents.remove(path);
+    }
+  }
+}
+
+void WatchmanBackend::handleSubscription(BSER::Object obj) {
+  std::unique_lock<std::mutex> lock(mMutex);
+  auto subscription = obj.find("subscription")->second.stringValue();
+  auto it = mSubscriptions.find(subscription);
+  if (it == mSubscriptions.end()) {
+    return;
+  }
+
+  auto watcher = it->second;
+  try {
+    handleFiles(watcher, obj);
+    watcher->notify();
+  } catch (WatcherError &err) {
+    handleWatcherError(err);
+  }
+}
+
+void WatchmanBackend::start() {
+  mIPC = watchmanConnect();
+  notifyStarted();
+
+  while (true) {
+    // If there are no subscriptions we are reading, wait for a request.
+    if (mSubscriptions.size() == 0) {
+      mRequestSignal.wait();
+      mRequestSignal.reset();
+    }
+
+    // Break out of loop if we are stopped.
+    if (mStopped) {
+      break;
+    }
+
+    // Attempt to read from the socket.
+    // If there is an error and we are stopped, break.
+    BSER b;
+    try {
+      b = watchmanRead(&*mIPC);
+    } catch (std::exception &err) {
+      if (mStopped) {
+        break;
+      } else if (mResponseSignal.isWaiting()) {
+        mError = err.what();
+        mResponseSignal.notify();
+      } else {
+        // Throwing causes the backend to be destroyed, but we never reach the code below to notify the signal
+        mEndedSignal.notify();
+        throw;
+      }
+    }
+
+    auto obj = b.objectValue();
+    auto error = obj.find("error");
+    if (error != obj.end()) {
+      mError = error->second.stringValue();
+      mResponseSignal.notify();
+      continue;
+    }
+
+    // If this message is for a subscription, handle it, otherwise notify the request.
+    auto subscription = obj.find("subscription");
+    if (subscription != obj.end()) {
+      handleSubscription(obj);
+    } else {
+      mResponse = obj;
+      mResponseSignal.notify();
+    }
+  }
+
+  mEndedSignal.notify();
+}
+
+WatchmanBackend::~WatchmanBackend() {
+  // Mark the watcher as stopped, close the socket, and trigger the lock.
+  // This will cause the read loop to be broken and the thread to exit.
+  mStopped = true;
+  mIPC.reset();
+  mRequestSignal.notify();
+
+  // If not ended yet, wait.
+  mEndedSignal.wait();
+}
+
+std::string WatchmanBackend::clock(WatcherRef watcher) {
+  BSER::Array cmd;
+  cmd.push_back("clock");
+  cmd.push_back(normalizePath(watcher->mDir));
+
+  BSER::Object obj = watchmanRequest(cmd);
+  auto found = obj.find("clock");
+  if (found == obj.end()) {
+    throw WatcherError("Error reading clock from watchman", watcher);
+  }
+
+  return found->second.stringValue();
+}
+
+void WatchmanBackend::writeSnapshot(WatcherRef watcher, std::string *snapshotPath) {
+  std::unique_lock<std::mutex> lock(mMutex);
+  watchmanWatch(watcher->mDir);
+
+  std::ofstream ofs(*snapshotPath);
+  ofs << clock(watcher);
+}
+
+void WatchmanBackend::getEventsSince(WatcherRef watcher, std::string *snapshotPath) {
+  std::unique_lock<std::mutex> lock(mMutex);
+  std::ifstream ifs(*snapshotPath);
+  if (ifs.fail()) {
+    return;
+  }
+
+  watchmanWatch(watcher->mDir);
+
+  std::string clock;
+  ifs >> clock;
+
+  BSER::Array cmd;
+  cmd.push_back("since");
+  cmd.push_back(normalizePath(watcher->mDir));
+  cmd.push_back(clock);
+
+  BSER::Object obj = watchmanRequest(cmd);
+  handleFiles(watcher, obj);
+}
+
+std::string getId(WatcherRef watcher) {
+  std::ostringstream id;
+  id << "parcel-";
+  id << static_cast<void*>(watcher.get());
+  return id.str();
+}
+
+// This function is called by Backend::watch which takes a lock on mMutex
+void WatchmanBackend::subscribe(WatcherRef watcher) {
+  watchmanWatch(watcher->mDir);
+
+  std::string id = getId(watcher);
+  BSER::Array cmd;
+  cmd.push_back("subscribe");
+  cmd.push_back(normalizePath(watcher->mDir));
+  cmd.push_back(id);
+
+  BSER::Array fields;
+  fields.push_back("name");
+  fields.push_back("mode");
+  fields.push_back("exists");
+  fields.push_back("new");
+
+  BSER::Object opts;
+  opts.emplace("fields", fields);
+  opts.emplace("since", clock(watcher));
+
+  if (watcher->mIgnorePaths.size() > 0) {
+    BSER::Array ignore;
+    BSER::Array anyOf;
+    anyOf.push_back("anyof");
+
+    for (auto it = watcher->mIgnorePaths.begin(); it != watcher->mIgnorePaths.end(); it++) {
+      std::string pathStart = watcher->mDir + DIR_SEP;
+      if (it->rfind(pathStart, 0) == 0) {
+        auto relative = it->substr(pathStart.size());
+        BSER::Array dirname;
+        dirname.push_back("dirname");
+        dirname.push_back(relative);
+        anyOf.push_back(dirname);
+      }
+    }
+
+    ignore.push_back("not");
+    ignore.push_back(anyOf);
+
+    opts.emplace("expression", ignore);
+  }
+
+  cmd.push_back(opts);
+  watchmanRequest(cmd);
+
+  mSubscriptions.emplace(id, watcher);
+  mRequestSignal.notify();
+}
+
+// This function is called by Backend::unwatch which takes a lock on mMutex
+void WatchmanBackend::unsubscribe(WatcherRef watcher) {
+  std::string id = getId(watcher);
+  auto erased = mSubscriptions.erase(id);
+
+  if (erased) {
+    BSER::Array cmd;
+    cmd.push_back("unsubscribe");
+    cmd.push_back(normalizePath(watcher->mDir));
+    cmd.push_back(id);
+
+    watchmanRequest(cmd);
+  }
+}

+ 35 - 0
node_modules/@parcel/watcher/src/watchman/WatchmanBackend.hh

@@ -0,0 +1,35 @@
+#ifndef WATCHMAN_H
+#define WATCHMAN_H
+
+#include "../Backend.hh"
+#include "./BSER.hh"
+#include "../Signal.hh"
+#include "./IPC.hh"
+
+class WatchmanBackend : public Backend {
+public:
+  static bool checkAvailable();
+  void start() override;
+  WatchmanBackend() : mStopped(false) {};
+  ~WatchmanBackend();
+  void writeSnapshot(WatcherRef watcher, std::string *snapshotPath) override;
+  void getEventsSince(WatcherRef watcher, std::string *snapshotPath) override;
+  void subscribe(WatcherRef watcher) override;
+  void unsubscribe(WatcherRef watcher) override;
+private:
+  std::unique_ptr<IPC> mIPC;
+  Signal mRequestSignal;
+  Signal mResponseSignal;
+  BSER::Object mResponse;
+  std::string mError;
+  std::unordered_map<std::string, WatcherRef> mSubscriptions;
+  bool mStopped;
+  Signal mEndedSignal;
+
+  std::string clock(WatcherRef watcher);
+  void watchmanWatch(std::string dir);
+  BSER::Object watchmanRequest(BSER cmd);
+  void handleSubscription(BSER::Object obj);
+};
+
+#endif

+ 282 - 0
node_modules/@parcel/watcher/src/windows/WindowsBackend.cc

@@ -0,0 +1,282 @@
+#include <string>
+#include <stack>
+#include "../DirTree.hh"
+#include "../shared/BruteForceBackend.hh"
+#include "./WindowsBackend.hh"
+#include "./win_utils.hh"
+
+#define DEFAULT_BUF_SIZE 1024 * 1024
+#define NETWORK_BUF_SIZE 64 * 1024
+#define CONVERT_TIME(ft) ULARGE_INTEGER{ft.dwLowDateTime, ft.dwHighDateTime}.QuadPart
+
+void BruteForceBackend::readTree(WatcherRef watcher, std::shared_ptr<DirTree> tree) {
+  std::stack<std::string> directories;
+
+  directories.push(watcher->mDir);
+
+  while (!directories.empty()) {
+    HANDLE hFind = INVALID_HANDLE_VALUE;
+
+    std::string path = directories.top();
+    std::string spec = path + "\\*";
+    directories.pop();
+
+    WIN32_FIND_DATA ffd;
+    hFind = FindFirstFile(spec.c_str(), &ffd);
+
+    if (hFind == INVALID_HANDLE_VALUE)  {
+      if (path == watcher->mDir) {
+        FindClose(hFind);
+        throw WatcherError("Error opening directory", watcher);
+      }
+
+      tree->remove(path);
+      continue;
+    }
+
+    do {
+      if (strcmp(ffd.cFileName, ".") != 0 && strcmp(ffd.cFileName, "..") != 0) {
+        std::string fullPath = path + "\\" + ffd.cFileName;
+        if (watcher->isIgnored(fullPath)) {
+          continue;
+        }
+
+        tree->add(fullPath, CONVERT_TIME(ffd.ftLastWriteTime), ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
+        if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+          directories.push(fullPath);
+        }
+      }
+    } while (FindNextFile(hFind, &ffd) != 0);
+
+    FindClose(hFind);
+  }
+}
+
+void WindowsBackend::start() {
+  mRunning = true;
+  notifyStarted();
+
+  while (mRunning) {
+    SleepEx(INFINITE, true);
+  }
+}
+
+WindowsBackend::~WindowsBackend() {
+  // Mark as stopped, and queue a noop function in the thread to break the loop
+  mRunning = false;
+  QueueUserAPC([](__in ULONG_PTR) {}, mThread.native_handle(), (ULONG_PTR)this);
+}
+
+class Subscription: public WatcherState {
+public:
+  Subscription(WindowsBackend *backend, WatcherRef watcher, std::shared_ptr<DirTree> tree) {
+    mRunning = true;
+    mBackend = backend;
+    mWatcher = watcher;
+    mTree = tree;
+    ZeroMemory(&mOverlapped, sizeof(OVERLAPPED));
+    mOverlapped.hEvent = this;
+    mReadBuffer.resize(DEFAULT_BUF_SIZE);
+    mWriteBuffer.resize(DEFAULT_BUF_SIZE);
+
+    mDirectoryHandle = CreateFileW(
+      utf8ToUtf16(watcher->mDir).data(),
+      FILE_LIST_DIRECTORY,
+      FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+      NULL,
+      OPEN_EXISTING,
+      FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
+      NULL
+    );
+
+    if (mDirectoryHandle == INVALID_HANDLE_VALUE) {
+      throw WatcherError("Invalid handle", mWatcher);
+    }
+
+    // Ensure that the path is a directory
+    BY_HANDLE_FILE_INFORMATION info;
+    bool success = GetFileInformationByHandle(
+      mDirectoryHandle,
+      &info
+    );
+
+    if (!success) {
+      throw WatcherError("Could not get file information", mWatcher);
+    }
+
+    if (!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+      throw WatcherError("Not a directory", mWatcher);
+    }
+  }
+
+  virtual ~Subscription() {
+    stop();
+  }
+
+  void run() {
+    try {
+      poll();
+    } catch (WatcherError &err) {
+      mBackend->handleWatcherError(err);
+    }
+  }
+
+  void stop() {
+    if (mRunning) {
+      mRunning = false;
+      CancelIo(mDirectoryHandle);
+      CloseHandle(mDirectoryHandle);
+    }
+  }
+
+  void poll() {
+    if (!mRunning) {
+      return;
+    }
+
+    // Asynchronously wait for changes.
+    int success = ReadDirectoryChangesW(
+      mDirectoryHandle,
+      mWriteBuffer.data(),
+      static_cast<DWORD>(mWriteBuffer.size()),
+      TRUE, // recursive
+      FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES
+        | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE,
+      NULL,
+      &mOverlapped,
+      [](DWORD errorCode, DWORD numBytes, LPOVERLAPPED overlapped) {
+        auto subscription = reinterpret_cast<Subscription *>(overlapped->hEvent);
+        try {
+          subscription->processEvents(errorCode);
+        } catch (WatcherError &err) {
+          subscription->mBackend->handleWatcherError(err);
+        }
+      }
+    );
+
+    if (!success) {
+      throw WatcherError("Failed to read changes", mWatcher);
+    }
+  }
+
+  void processEvents(DWORD errorCode) {
+    if (!mRunning) {
+      return;
+    }
+
+    switch (errorCode) {
+      case ERROR_OPERATION_ABORTED:
+        return;
+      case ERROR_INVALID_PARAMETER:
+        // resize buffers to network size (64kb), and try again
+        mReadBuffer.resize(NETWORK_BUF_SIZE);
+        mWriteBuffer.resize(NETWORK_BUF_SIZE);
+        poll();
+        return;
+      case ERROR_NOTIFY_ENUM_DIR:
+        throw WatcherError("Buffer overflow. Some events may have been lost.", mWatcher);
+      case ERROR_ACCESS_DENIED: {
+        // This can happen if the watched directory is deleted. Check if that is the case,
+        // and if so emit a delete event. Otherwise, fall through to default error case.
+        DWORD attrs = GetFileAttributesW(utf8ToUtf16(mWatcher->mDir).data());
+        bool isDir = attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY);
+        if (!isDir) {
+          mWatcher->mEvents.remove(mWatcher->mDir);
+          mTree->remove(mWatcher->mDir);
+          mWatcher->notify();
+          stop();
+          return;
+        }
+      }
+      default:
+        if (errorCode != ERROR_SUCCESS) {
+          throw WatcherError("Unknown error", mWatcher);
+        }
+    }
+
+    // Swap read and write buffers, and poll again
+    std::swap(mWriteBuffer, mReadBuffer);
+    poll();
+
+    // Read change events
+    BYTE *base = mReadBuffer.data();
+    while (true) {
+      PFILE_NOTIFY_INFORMATION info = (PFILE_NOTIFY_INFORMATION)base;
+      processEvent(info);
+
+      if (info->NextEntryOffset == 0) {
+        break;
+      }
+
+      base += info->NextEntryOffset;
+    }
+
+    mWatcher->notify();
+  }
+
+  void processEvent(PFILE_NOTIFY_INFORMATION info) {
+    std::string path = mWatcher->mDir + "\\" + utf16ToUtf8(info->FileName, info->FileNameLength / sizeof(WCHAR));
+    if (mWatcher->isIgnored(path)) {
+      return;
+    }
+
+    switch (info->Action) {
+      case FILE_ACTION_ADDED:
+      case FILE_ACTION_RENAMED_NEW_NAME: {
+        WIN32_FILE_ATTRIBUTE_DATA data;
+        if (GetFileAttributesExW(utf8ToUtf16(path).data(), GetFileExInfoStandard, &data)) {
+          mWatcher->mEvents.create(path);
+          mTree->add(path, CONVERT_TIME(data.ftLastWriteTime), data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
+        }
+        break;
+      }
+      case FILE_ACTION_MODIFIED: {
+        WIN32_FILE_ATTRIBUTE_DATA data;
+        if (GetFileAttributesExW(utf8ToUtf16(path).data(), GetFileExInfoStandard, &data)) {
+          mTree->update(path, CONVERT_TIME(data.ftLastWriteTime));
+          if (!(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+            mWatcher->mEvents.update(path);
+          }
+        }
+        break;
+      }
+      case FILE_ACTION_REMOVED:
+      case FILE_ACTION_RENAMED_OLD_NAME:
+        mWatcher->mEvents.remove(path);
+        mTree->remove(path);
+        break;
+    }
+  }
+
+private:
+  WindowsBackend *mBackend;
+  std::shared_ptr<Watcher> mWatcher;
+  std::shared_ptr<DirTree> mTree;
+  bool mRunning;
+  HANDLE mDirectoryHandle;
+  std::vector<BYTE> mReadBuffer;
+  std::vector<BYTE> mWriteBuffer;
+  OVERLAPPED mOverlapped;
+};
+
+// This function is called by Backend::watch which takes a lock on mMutex
+void WindowsBackend::subscribe(WatcherRef watcher) {
+  // Create a subscription for this watcher
+  auto sub = std::make_shared<Subscription>(this, watcher, getTree(watcher, false));
+  watcher->state = sub;
+
+  // Queue polling for this subscription in the correct thread.
+  bool success = QueueUserAPC([](__in ULONG_PTR ptr) {
+    Subscription *sub = (Subscription *)ptr;
+    sub->run();
+  }, mThread.native_handle(), (ULONG_PTR)sub.get());
+
+  if (!success) {
+    throw std::runtime_error("Unable to queue APC");
+  }
+}
+
+// This function is called by Backend::unwatch which takes a lock on mMutex
+void WindowsBackend::unsubscribe(WatcherRef watcher) {
+  watcher->state = nullptr;
+}

+ 18 - 0
node_modules/@parcel/watcher/src/windows/WindowsBackend.hh

@@ -0,0 +1,18 @@
+#ifndef WINDOWS_H
+#define WINDOWS_H
+
+#include <winsock2.h>
+#include <windows.h>
+#include "../shared/BruteForceBackend.hh"
+
+class WindowsBackend : public BruteForceBackend {
+public:
+  void start() override;
+  ~WindowsBackend();
+  void subscribe(WatcherRef watcher) override;
+  void unsubscribe(WatcherRef watcher) override;
+private:
+  bool mRunning;
+};
+
+#endif

+ 44 - 0
node_modules/@parcel/watcher/src/windows/win_utils.cc

@@ -0,0 +1,44 @@
+#include "./win_utils.hh"
+
+std::wstring utf8ToUtf16(std::string input) {
+  unsigned int len = MultiByteToWideChar(CP_UTF8, 0, input.c_str(), -1, NULL, 0);
+  WCHAR *output = new WCHAR[len];
+  MultiByteToWideChar(CP_UTF8, 0, input.c_str(), -1, output, len);
+  std::wstring res(output);
+  delete output;
+  return res;
+}
+
+std::string utf16ToUtf8(const WCHAR *input, size_t length) {
+  unsigned int len = WideCharToMultiByte(CP_UTF8, 0, input, length, NULL, 0, NULL, NULL);
+  char *output = new char[len + 1];
+  WideCharToMultiByte(CP_UTF8, 0, input, length, output, len, NULL, NULL);
+  output[len] = '\0';
+  std::string res(output);
+  delete output;
+  return res;
+}
+
+std::string normalizePath(std::string path) {
+  // Prevent truncation to MAX_PATH characters by adding the \\?\ prefix
+  std::wstring p = utf8ToUtf16("\\\\?\\" + path);
+
+  // Get the required length for the output
+  unsigned int len = GetLongPathNameW(p.data(), NULL, 0);
+  if (!len) {
+    return path;
+  }
+
+  // Allocate output array and get long path
+  WCHAR *output = new WCHAR[len];
+  len = GetLongPathNameW(p.data(), output, len);
+  if (!len) {
+    delete output;
+    return path;
+  }
+
+  // Convert back to utf8
+  std::string res = utf16ToUtf8(output + 4, len - 4);
+  delete output;
+  return res;
+}

+ 11 - 0
node_modules/@parcel/watcher/src/windows/win_utils.hh

@@ -0,0 +1,11 @@
+#ifndef WIN_UTILS_H
+#define WIN_UTILS_H
+
+#include <string>
+#include <windows.h>
+
+std::wstring utf8ToUtf16(std::string input);
+std::string utf16ToUtf8(const WCHAR *input, size_t length);
+std::string normalizePath(std::string path);
+
+#endif

+ 77 - 0
node_modules/@parcel/watcher/wrapper.js

@@ -0,0 +1,77 @@
+const path = require('path');
+const micromatch = require('micromatch');
+const isGlob = require('is-glob');
+
+function normalizeOptions(dir, opts = {}) {
+  const { ignore, ...rest } = opts;
+
+  if (Array.isArray(ignore)) {
+    opts = { ...rest };
+
+    for (const value of ignore) {
+      if (isGlob(value)) {
+        if (!opts.ignoreGlobs) {
+          opts.ignoreGlobs = [];
+        }
+
+        const regex = micromatch.makeRe(value, {
+          // We set `dot: true` to workaround an issue with the
+          // regular expression on Linux where the resulting
+          // negative lookahead `(?!(\\/|^)` was never matching
+          // in some cases. See also https://bit.ly/3UZlQDm
+          dot: true,
+          // C++ does not support lookbehind regex patterns, they
+          // were only added later to JavaScript engines
+          // (https://bit.ly/3V7S6UL)
+          lookbehinds: false
+        });
+        opts.ignoreGlobs.push(regex.source);
+      } else {
+        if (!opts.ignorePaths) {
+          opts.ignorePaths = [];
+        }
+
+        opts.ignorePaths.push(path.resolve(dir, value));
+      }
+    }
+  }
+
+  return opts;
+}
+
+exports.createWrapper = (binding) => {
+  return {
+    writeSnapshot(dir, snapshot, opts) {
+      return binding.writeSnapshot(
+        path.resolve(dir),
+        path.resolve(snapshot),
+        normalizeOptions(dir, opts),
+      );
+    },
+    getEventsSince(dir, snapshot, opts) {
+      return binding.getEventsSince(
+        path.resolve(dir),
+        path.resolve(snapshot),
+        normalizeOptions(dir, opts),
+      );
+    },
+    async subscribe(dir, fn, opts) {
+      dir = path.resolve(dir);
+      opts = normalizeOptions(dir, opts);
+      await binding.subscribe(dir, fn, opts);
+
+      return {
+        unsubscribe() {
+          return binding.unsubscribe(dir, fn, opts);
+        },
+      };
+    },
+    unsubscribe(dir, fn, opts) {
+      return binding.unsubscribe(
+        path.resolve(dir),
+        fn,
+        normalizeOptions(dir, opts),
+      );
+    }
+  };
+};

+ 21 - 0
node_modules/braces/LICENSE

@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-present, Jon Schlinkert.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 586 - 0
node_modules/braces/README.md

@@ -0,0 +1,586 @@
+# braces [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=W8YFZ425KND68) [![NPM version](https://img.shields.io/npm/v/braces.svg?style=flat)](https://www.npmjs.com/package/braces) [![NPM monthly downloads](https://img.shields.io/npm/dm/braces.svg?style=flat)](https://npmjs.org/package/braces) [![NPM total downloads](https://img.shields.io/npm/dt/braces.svg?style=flat)](https://npmjs.org/package/braces) [![Linux Build Status](https://img.shields.io/travis/micromatch/braces.svg?style=flat&label=Travis)](https://travis-ci.org/micromatch/braces)
+
+> Bash-like brace expansion, implemented in JavaScript. Safer than other brace expansion libs, with complete support for the Bash 4.3 braces specification, without sacrificing speed.
+
+Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save braces
+```
+
+## v3.0.0 Released!!
+
+See the [changelog](CHANGELOG.md) for details.
+
+## Why use braces?
+
+Brace patterns make globs more powerful by adding the ability to match specific ranges and sequences of characters.
+
+- **Accurate** - complete support for the [Bash 4.3 Brace Expansion](www.gnu.org/software/bash/) specification (passes all of the Bash braces tests)
+- **[fast and performant](#benchmarks)** - Starts fast, runs fast and [scales well](#performance) as patterns increase in complexity.
+- **Organized code base** - The parser and compiler are easy to maintain and update when edge cases crop up.
+- **Well-tested** - Thousands of test assertions, and passes all of the Bash, minimatch, and [brace-expansion](https://github.com/juliangruber/brace-expansion) unit tests (as of the date this was written).
+- **Safer** - You shouldn't have to worry about users defining aggressive or malicious brace patterns that can break your application. Braces takes measures to prevent malicious regex that can be used for DDoS attacks (see [catastrophic backtracking](https://www.regular-expressions.info/catastrophic.html)).
+- [Supports lists](#lists) - (aka "sets") `a/{b,c}/d` => `['a/b/d', 'a/c/d']`
+- [Supports sequences](#sequences) - (aka "ranges") `{01..03}` => `['01', '02', '03']`
+- [Supports steps](#steps) - (aka "increments") `{2..10..2}` => `['2', '4', '6', '8', '10']`
+- [Supports escaping](#escaping) - To prevent evaluation of special characters.
+
+## Usage
+
+The main export is a function that takes one or more brace `patterns` and `options`.
+
+```js
+const braces = require('braces');
+// braces(patterns[, options]);
+
+console.log(braces(['{01..05}', '{a..e}']));
+//=> ['(0[1-5])', '([a-e])']
+
+console.log(braces(['{01..05}', '{a..e}'], { expand: true }));
+//=> ['01', '02', '03', '04', '05', 'a', 'b', 'c', 'd', 'e']
+```
+
+### Brace Expansion vs. Compilation
+
+By default, brace patterns are compiled into strings that are optimized for creating regular expressions and matching.
+
+**Compiled**
+
+```js
+console.log(braces('a/{x,y,z}/b'));
+//=> ['a/(x|y|z)/b']
+console.log(braces(['a/{01..20}/b', 'a/{1..5}/b']));
+//=> [ 'a/(0[1-9]|1[0-9]|20)/b', 'a/([1-5])/b' ]
+```
+
+**Expanded**
+
+Enable brace expansion by setting the `expand` option to true, or by using [braces.expand()](#expand) (returns an array similar to what you'd expect from Bash, or `echo {1..5}`, or [minimatch](https://github.com/isaacs/minimatch)):
+
+```js
+console.log(braces('a/{x,y,z}/b', { expand: true }));
+//=> ['a/x/b', 'a/y/b', 'a/z/b']
+
+console.log(braces.expand('{01..10}'));
+//=> ['01','02','03','04','05','06','07','08','09','10']
+```
+
+### Lists
+
+Expand lists (like Bash "sets"):
+
+```js
+console.log(braces('a/{foo,bar,baz}/*.js'));
+//=> ['a/(foo|bar|baz)/*.js']
+
+console.log(braces.expand('a/{foo,bar,baz}/*.js'));
+//=> ['a/foo/*.js', 'a/bar/*.js', 'a/baz/*.js']
+```
+
+### Sequences
+
+Expand ranges of characters (like Bash "sequences"):
+
+```js
+console.log(braces.expand('{1..3}')); // ['1', '2', '3']
+console.log(braces.expand('a/{1..3}/b')); // ['a/1/b', 'a/2/b', 'a/3/b']
+console.log(braces('{a..c}', { expand: true })); // ['a', 'b', 'c']
+console.log(braces('foo/{a..c}', { expand: true })); // ['foo/a', 'foo/b', 'foo/c']
+
+// supports zero-padded ranges
+console.log(braces('a/{01..03}/b')); //=> ['a/(0[1-3])/b']
+console.log(braces('a/{001..300}/b')); //=> ['a/(0{2}[1-9]|0[1-9][0-9]|[12][0-9]{2}|300)/b']
+```
+
+See [fill-range](https://github.com/jonschlinkert/fill-range) for all available range-expansion options.
+
+### Steppped ranges
+
+Steps, or increments, may be used with ranges:
+
+```js
+console.log(braces.expand('{2..10..2}'));
+//=> ['2', '4', '6', '8', '10']
+
+console.log(braces('{2..10..2}'));
+//=> ['(2|4|6|8|10)']
+```
+
+When the [.optimize](#optimize) method is used, or [options.optimize](#optionsoptimize) is set to true, sequences are passed to [to-regex-range](https://github.com/jonschlinkert/to-regex-range) for expansion.
+
+### Nesting
+
+Brace patterns may be nested. The results of each expanded string are not sorted, and left to right order is preserved.
+
+**"Expanded" braces**
+
+```js
+console.log(braces.expand('a{b,c,/{x,y}}/e'));
+//=> ['ab/e', 'ac/e', 'a/x/e', 'a/y/e']
+
+console.log(braces.expand('a/{x,{1..5},y}/c'));
+//=> ['a/x/c', 'a/1/c', 'a/2/c', 'a/3/c', 'a/4/c', 'a/5/c', 'a/y/c']
+```
+
+**"Optimized" braces**
+
+```js
+console.log(braces('a{b,c,/{x,y}}/e'));
+//=> ['a(b|c|/(x|y))/e']
+
+console.log(braces('a/{x,{1..5},y}/c'));
+//=> ['a/(x|([1-5])|y)/c']
+```
+
+### Escaping
+
+**Escaping braces**
+
+A brace pattern will not be expanded or evaluted if _either the opening or closing brace is escaped_:
+
+```js
+console.log(braces.expand('a\\{d,c,b}e'));
+//=> ['a{d,c,b}e']
+
+console.log(braces.expand('a{d,c,b\\}e'));
+//=> ['a{d,c,b}e']
+```
+
+**Escaping commas**
+
+Commas inside braces may also be escaped:
+
+```js
+console.log(braces.expand('a{b\\,c}d'));
+//=> ['a{b,c}d']
+
+console.log(braces.expand('a{d\\,c,b}e'));
+//=> ['ad,ce', 'abe']
+```
+
+**Single items**
+
+Following bash conventions, a brace pattern is also not expanded when it contains a single character:
+
+```js
+console.log(braces.expand('a{b}c'));
+//=> ['a{b}c']
+```
+
+## Options
+
+### options.maxLength
+
+**Type**: `Number`
+
+**Default**: `10,000`
+
+**Description**: Limit the length of the input string. Useful when the input string is generated or your application allows users to pass a string, et cetera.
+
+```js
+console.log(braces('a/{b,c}/d', { maxLength: 3 })); //=> throws an error
+```
+
+### options.expand
+
+**Type**: `Boolean`
+
+**Default**: `undefined`
+
+**Description**: Generate an "expanded" brace pattern (alternatively you can use the `braces.expand()` method, which does the same thing).
+
+```js
+console.log(braces('a/{b,c}/d', { expand: true }));
+//=> [ 'a/b/d', 'a/c/d' ]
+```
+
+### options.nodupes
+
+**Type**: `Boolean`
+
+**Default**: `undefined`
+
+**Description**: Remove duplicates from the returned array.
+
+### options.rangeLimit
+
+**Type**: `Number`
+
+**Default**: `1000`
+
+**Description**: To prevent malicious patterns from being passed by users, an error is thrown when `braces.expand()` is used or `options.expand` is true and the generated range will exceed the `rangeLimit`.
+
+You can customize `options.rangeLimit` or set it to `Inifinity` to disable this altogether.
+
+**Examples**
+
+```js
+// pattern exceeds the "rangeLimit", so it's optimized automatically
+console.log(braces.expand('{1..1000}'));
+//=> ['([1-9]|[1-9][0-9]{1,2}|1000)']
+
+// pattern does not exceed "rangeLimit", so it's NOT optimized
+console.log(braces.expand('{1..100}'));
+//=> ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100']
+```
+
+### options.transform
+
+**Type**: `Function`
+
+**Default**: `undefined`
+
+**Description**: Customize range expansion.
+
+**Example: Transforming non-numeric values**
+
+```js
+const alpha = braces.expand('x/{a..e}/y', {
+  transform(value, index) {
+    // When non-numeric values are passed, "value" is a character code.
+    return 'foo/' + String.fromCharCode(value) + '-' + index;
+  },
+});
+console.log(alpha);
+//=> [ 'x/foo/a-0/y', 'x/foo/b-1/y', 'x/foo/c-2/y', 'x/foo/d-3/y', 'x/foo/e-4/y' ]
+```
+
+**Example: Transforming numeric values**
+
+```js
+const numeric = braces.expand('{1..5}', {
+  transform(value) {
+    // when numeric values are passed, "value" is a number
+    return 'foo/' + value * 2;
+  },
+});
+console.log(numeric);
+//=> [ 'foo/2', 'foo/4', 'foo/6', 'foo/8', 'foo/10' ]
+```
+
+### options.quantifiers
+
+**Type**: `Boolean`
+
+**Default**: `undefined`
+
+**Description**: In regular expressions, quanitifiers can be used to specify how many times a token can be repeated. For example, `a{1,3}` will match the letter `a` one to three times.
+
+Unfortunately, regex quantifiers happen to share the same syntax as [Bash lists](#lists)
+
+The `quantifiers` option tells braces to detect when [regex quantifiers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#quantifiers) are defined in the given pattern, and not to try to expand them as lists.
+
+**Examples**
+
+```js
+const braces = require('braces');
+console.log(braces('a/b{1,3}/{x,y,z}'));
+//=> [ 'a/b(1|3)/(x|y|z)' ]
+console.log(braces('a/b{1,3}/{x,y,z}', { quantifiers: true }));
+//=> [ 'a/b{1,3}/(x|y|z)' ]
+console.log(braces('a/b{1,3}/{x,y,z}', { quantifiers: true, expand: true }));
+//=> [ 'a/b{1,3}/x', 'a/b{1,3}/y', 'a/b{1,3}/z' ]
+```
+
+### options.keepEscaping
+
+**Type**: `Boolean`
+
+**Default**: `undefined`
+
+**Description**: Do not strip backslashes that were used for escaping from the result.
+
+## What is "brace expansion"?
+
+Brace expansion is a type of parameter expansion that was made popular by unix shells for generating lists of strings, as well as regex-like matching when used alongside wildcards (globs).
+
+In addition to "expansion", braces are also used for matching. In other words:
+
+- [brace expansion](#brace-expansion) is for generating new lists
+- [brace matching](#brace-matching) is for filtering existing lists
+
+<details>
+<summary><strong>More about brace expansion</strong> (click to expand)</summary>
+
+There are two main types of brace expansion:
+
+1. **lists**: which are defined using comma-separated values inside curly braces: `{a,b,c}`
+2. **sequences**: which are defined using a starting value and an ending value, separated by two dots: `a{1..3}b`. Optionally, a third argument may be passed to define a "step" or increment to use: `a{1..100..10}b`. These are also sometimes referred to as "ranges".
+
+Here are some example brace patterns to illustrate how they work:
+
+**Sets**
+
+```
+{a,b,c}       => a b c
+{a,b,c}{1,2}  => a1 a2 b1 b2 c1 c2
+```
+
+**Sequences**
+
+```
+{1..9}        => 1 2 3 4 5 6 7 8 9
+{4..-4}       => 4 3 2 1 0 -1 -2 -3 -4
+{1..20..3}    => 1 4 7 10 13 16 19
+{a..j}        => a b c d e f g h i j
+{j..a}        => j i h g f e d c b a
+{a..z..3}     => a d g j m p s v y
+```
+
+**Combination**
+
+Sets and sequences can be mixed together or used along with any other strings.
+
+```
+{a,b,c}{1..3}   => a1 a2 a3 b1 b2 b3 c1 c2 c3
+foo/{a,b,c}/bar => foo/a/bar foo/b/bar foo/c/bar
+```
+
+The fact that braces can be "expanded" from relatively simple patterns makes them ideal for quickly generating test fixtures, file paths, and similar use cases.
+
+## Brace matching
+
+In addition to _expansion_, brace patterns are also useful for performing regular-expression-like matching.
+
+For example, the pattern `foo/{1..3}/bar` would match any of following strings:
+
+```
+foo/1/bar
+foo/2/bar
+foo/3/bar
+```
+
+But not:
+
+```
+baz/1/qux
+baz/2/qux
+baz/3/qux
+```
+
+Braces can also be combined with [glob patterns](https://github.com/jonschlinkert/micromatch) to perform more advanced wildcard matching. For example, the pattern `*/{1..3}/*` would match any of following strings:
+
+```
+foo/1/bar
+foo/2/bar
+foo/3/bar
+baz/1/qux
+baz/2/qux
+baz/3/qux
+```
+
+## Brace matching pitfalls
+
+Although brace patterns offer a user-friendly way of matching ranges or sets of strings, there are also some major disadvantages and potential risks you should be aware of.
+
+### tldr
+
+**"brace bombs"**
+
+- brace expansion can eat up a huge amount of processing resources
+- as brace patterns increase _linearly in size_, the system resources required to expand the pattern increase exponentially
+- users can accidentally (or intentially) exhaust your system's resources resulting in the equivalent of a DoS attack (bonus: no programming knowledge is required!)
+
+For a more detailed explanation with examples, see the [geometric complexity](#geometric-complexity) section.
+
+### The solution
+
+Jump to the [performance section](#performance) to see how Braces solves this problem in comparison to other libraries.
+
+### Geometric complexity
+
+At minimum, brace patterns with sets limited to two elements have quadradic or `O(n^2)` complexity. But the complexity of the algorithm increases exponentially as the number of sets, _and elements per set_, increases, which is `O(n^c)`.
+
+For example, the following sets demonstrate quadratic (`O(n^2)`) complexity:
+
+```
+{1,2}{3,4}      => (2X2)    => 13 14 23 24
+{1,2}{3,4}{5,6} => (2X2X2)  => 135 136 145 146 235 236 245 246
+```
+
+But add an element to a set, and we get a n-fold Cartesian product with `O(n^c)` complexity:
+
+```
+{1,2,3}{4,5,6}{7,8,9} => (3X3X3) => 147 148 149 157 158 159 167 168 169 247 248
+                                    249 257 258 259 267 268 269 347 348 349 357
+                                    358 359 367 368 369
+```
+
+Now, imagine how this complexity grows given that each element is a n-tuple:
+
+```
+{1..100}{1..100}         => (100X100)     => 10,000 elements (38.4 kB)
+{1..100}{1..100}{1..100} => (100X100X100) => 1,000,000 elements (5.76 MB)
+```
+
+Although these examples are clearly contrived, they demonstrate how brace patterns can quickly grow out of control.
+
+**More information**
+
+Interested in learning more about brace expansion?
+
+- [linuxjournal/bash-brace-expansion](http://www.linuxjournal.com/content/bash-brace-expansion)
+- [rosettacode/Brace_expansion](https://rosettacode.org/wiki/Brace_expansion)
+- [cartesian product](https://en.wikipedia.org/wiki/Cartesian_product)
+
+</details>
+
+## Performance
+
+Braces is not only screaming fast, it's also more accurate the other brace expansion libraries.
+
+### Better algorithms
+
+Fortunately there is a solution to the ["brace bomb" problem](#brace-matching-pitfalls): _don't expand brace patterns into an array when they're used for matching_.
+
+Instead, convert the pattern into an optimized regular expression. This is easier said than done, and braces is the only library that does this currently.
+
+**The proof is in the numbers**
+
+Minimatch gets exponentially slower as patterns increase in complexity, braces does not. The following results were generated using `braces()` and `minimatch.braceExpand()`, respectively.
+
+| **Pattern**                 | **braces**          | **[minimatch][]**            |
+| --------------------------- | ------------------- | ---------------------------- |
+| `{1..9007199254740991}`[^1] | `298 B` (5ms 459μs) | N/A (freezes)                |
+| `{1..1000000000000000}`     | `41 B` (1ms 15μs)   | N/A (freezes)                |
+| `{1..100000000000000}`      | `40 B` (890μs)      | N/A (freezes)                |
+| `{1..10000000000000}`       | `39 B` (2ms 49μs)   | N/A (freezes)                |
+| `{1..1000000000000}`        | `38 B` (608μs)      | N/A (freezes)                |
+| `{1..100000000000}`         | `37 B` (397μs)      | N/A (freezes)                |
+| `{1..10000000000}`          | `35 B` (983μs)      | N/A (freezes)                |
+| `{1..1000000000}`           | `34 B` (798μs)      | N/A (freezes)                |
+| `{1..100000000}`            | `33 B` (733μs)      | N/A (freezes)                |
+| `{1..10000000}`             | `32 B` (5ms 632μs)  | `78.89 MB` (16s 388ms 569μs) |
+| `{1..1000000}`              | `31 B` (1ms 381μs)  | `6.89 MB` (1s 496ms 887μs)   |
+| `{1..100000}`               | `30 B` (950μs)      | `588.89 kB` (146ms 921μs)    |
+| `{1..10000}`                | `29 B` (1ms 114μs)  | `48.89 kB` (14ms 187μs)      |
+| `{1..1000}`                 | `28 B` (760μs)      | `3.89 kB` (1ms 453μs)        |
+| `{1..100}`                  | `22 B` (345μs)      | `291 B` (196μs)              |
+| `{1..10}`                   | `10 B` (533μs)      | `20 B` (37μs)                |
+| `{1..3}`                    | `7 B` (190μs)       | `5 B` (27μs)                 |
+
+### Faster algorithms
+
+When you need expansion, braces is still much faster.
+
+_(the following results were generated using `braces.expand()` and `minimatch.braceExpand()`, respectively)_
+
+| **Pattern**     | **braces**                  | **[minimatch][]**            |
+| --------------- | --------------------------- | ---------------------------- |
+| `{1..10000000}` | `78.89 MB` (2s 698ms 642μs) | `78.89 MB` (18s 601ms 974μs) |
+| `{1..1000000}`  | `6.89 MB` (458ms 576μs)     | `6.89 MB` (1s 491ms 621μs)   |
+| `{1..100000}`   | `588.89 kB` (20ms 728μs)    | `588.89 kB` (156ms 919μs)    |
+| `{1..10000}`    | `48.89 kB` (2ms 202μs)      | `48.89 kB` (13ms 641μs)      |
+| `{1..1000}`     | `3.89 kB` (1ms 796μs)       | `3.89 kB` (1ms 958μs)        |
+| `{1..100}`      | `291 B` (424μs)             | `291 B` (211μs)              |
+| `{1..10}`       | `20 B` (487μs)              | `20 B` (72μs)                |
+| `{1..3}`        | `5 B` (166μs)               | `5 B` (27μs)                 |
+
+If you'd like to run these comparisons yourself, see [test/support/generate.js](test/support/generate.js).
+
+## Benchmarks
+
+### Running benchmarks
+
+Install dev dependencies:
+
+```bash
+npm i -d && npm benchmark
+```
+
+### Latest results
+
+Braces is more accurate, without sacrificing performance.
+
+```bash
+● expand - range (expanded)
+     braces x 53,167 ops/sec ±0.12% (102 runs sampled)
+  minimatch x 11,378 ops/sec ±0.10% (102 runs sampled)
+● expand - range (optimized for regex)
+     braces x 373,442 ops/sec ±0.04% (100 runs sampled)
+  minimatch x 3,262 ops/sec ±0.18% (100 runs sampled)
+● expand - nested ranges (expanded)
+     braces x 33,921 ops/sec ±0.09% (99 runs sampled)
+  minimatch x 10,855 ops/sec ±0.28% (100 runs sampled)
+● expand - nested ranges (optimized for regex)
+     braces x 287,479 ops/sec ±0.52% (98 runs sampled)
+  minimatch x 3,219 ops/sec ±0.28% (101 runs sampled)
+● expand - set (expanded)
+     braces x 238,243 ops/sec ±0.19% (97 runs sampled)
+  minimatch x 538,268 ops/sec ±0.31% (96 runs sampled)
+● expand - set (optimized for regex)
+     braces x 321,844 ops/sec ±0.10% (97 runs sampled)
+  minimatch x 140,600 ops/sec ±0.15% (100 runs sampled)
+● expand - nested sets (expanded)
+     braces x 165,371 ops/sec ±0.42% (96 runs sampled)
+  minimatch x 337,720 ops/sec ±0.28% (100 runs sampled)
+● expand - nested sets (optimized for regex)
+     braces x 242,948 ops/sec ±0.12% (99 runs sampled)
+  minimatch x 87,403 ops/sec ±0.79% (96 runs sampled)
+```
+
+## About
+
+<details>
+<summary><strong>Contributing</strong></summary>
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+</details>
+
+<details>
+<summary><strong>Running Tests</strong></summary>
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+</details>
+
+<details>
+<summary><strong>Building docs</strong></summary>
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+</details>
+
+### Contributors
+
+| **Commits** | **Contributor**                                               |
+| ----------- | ------------------------------------------------------------- |
+| 197         | [jonschlinkert](https://github.com/jonschlinkert)             |
+| 4           | [doowb](https://github.com/doowb)                             |
+| 1           | [es128](https://github.com/es128)                             |
+| 1           | [eush77](https://github.com/eush77)                           |
+| 1           | [hemanth](https://github.com/hemanth)                         |
+| 1           | [wtgtybhertgeghgtwtg](https://github.com/wtgtybhertgeghgtwtg) |
+
+### Author
+
+**Jon Schlinkert**
+
+- [GitHub Profile](https://github.com/jonschlinkert)
+- [Twitter Profile](https://twitter.com/jonschlinkert)
+- [LinkedIn Profile](https://linkedin.com/in/jonschlinkert)
+
+### License
+
+Copyright © 2019, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+---
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.8.0, on April 08, 2019._

+ 170 - 0
node_modules/braces/index.js

@@ -0,0 +1,170 @@
+'use strict';
+
+const stringify = require('./lib/stringify');
+const compile = require('./lib/compile');
+const expand = require('./lib/expand');
+const parse = require('./lib/parse');
+
+/**
+ * Expand the given pattern or create a regex-compatible string.
+ *
+ * ```js
+ * const braces = require('braces');
+ * console.log(braces('{a,b,c}', { compile: true })); //=> ['(a|b|c)']
+ * console.log(braces('{a,b,c}')); //=> ['a', 'b', 'c']
+ * ```
+ * @param {String} `str`
+ * @param {Object} `options`
+ * @return {String}
+ * @api public
+ */
+
+const braces = (input, options = {}) => {
+  let output = [];
+
+  if (Array.isArray(input)) {
+    for (const pattern of input) {
+      const result = braces.create(pattern, options);
+      if (Array.isArray(result)) {
+        output.push(...result);
+      } else {
+        output.push(result);
+      }
+    }
+  } else {
+    output = [].concat(braces.create(input, options));
+  }
+
+  if (options && options.expand === true && options.nodupes === true) {
+    output = [...new Set(output)];
+  }
+  return output;
+};
+
+/**
+ * Parse the given `str` with the given `options`.
+ *
+ * ```js
+ * // braces.parse(pattern, [, options]);
+ * const ast = braces.parse('a/{b,c}/d');
+ * console.log(ast);
+ * ```
+ * @param {String} pattern Brace pattern to parse
+ * @param {Object} options
+ * @return {Object} Returns an AST
+ * @api public
+ */
+
+braces.parse = (input, options = {}) => parse(input, options);
+
+/**
+ * Creates a braces string from an AST, or an AST node.
+ *
+ * ```js
+ * const braces = require('braces');
+ * let ast = braces.parse('foo/{a,b}/bar');
+ * console.log(stringify(ast.nodes[2])); //=> '{a,b}'
+ * ```
+ * @param {String} `input` Brace pattern or AST.
+ * @param {Object} `options`
+ * @return {Array} Returns an array of expanded values.
+ * @api public
+ */
+
+braces.stringify = (input, options = {}) => {
+  if (typeof input === 'string') {
+    return stringify(braces.parse(input, options), options);
+  }
+  return stringify(input, options);
+};
+
+/**
+ * Compiles a brace pattern into a regex-compatible, optimized string.
+ * This method is called by the main [braces](#braces) function by default.
+ *
+ * ```js
+ * const braces = require('braces');
+ * console.log(braces.compile('a/{b,c}/d'));
+ * //=> ['a/(b|c)/d']
+ * ```
+ * @param {String} `input` Brace pattern or AST.
+ * @param {Object} `options`
+ * @return {Array} Returns an array of expanded values.
+ * @api public
+ */
+
+braces.compile = (input, options = {}) => {
+  if (typeof input === 'string') {
+    input = braces.parse(input, options);
+  }
+  return compile(input, options);
+};
+
+/**
+ * Expands a brace pattern into an array. This method is called by the
+ * main [braces](#braces) function when `options.expand` is true. Before
+ * using this method it's recommended that you read the [performance notes](#performance))
+ * and advantages of using [.compile](#compile) instead.
+ *
+ * ```js
+ * const braces = require('braces');
+ * console.log(braces.expand('a/{b,c}/d'));
+ * //=> ['a/b/d', 'a/c/d'];
+ * ```
+ * @param {String} `pattern` Brace pattern
+ * @param {Object} `options`
+ * @return {Array} Returns an array of expanded values.
+ * @api public
+ */
+
+braces.expand = (input, options = {}) => {
+  if (typeof input === 'string') {
+    input = braces.parse(input, options);
+  }
+
+  let result = expand(input, options);
+
+  // filter out empty strings if specified
+  if (options.noempty === true) {
+    result = result.filter(Boolean);
+  }
+
+  // filter out duplicates if specified
+  if (options.nodupes === true) {
+    result = [...new Set(result)];
+  }
+
+  return result;
+};
+
+/**
+ * Processes a brace pattern and returns either an expanded array
+ * (if `options.expand` is true), a highly optimized regex-compatible string.
+ * This method is called by the main [braces](#braces) function.
+ *
+ * ```js
+ * const braces = require('braces');
+ * console.log(braces.create('user-{200..300}/project-{a,b,c}-{1..10}'))
+ * //=> 'user-(20[0-9]|2[1-9][0-9]|300)/project-(a|b|c)-([1-9]|10)'
+ * ```
+ * @param {String} `pattern` Brace pattern
+ * @param {Object} `options`
+ * @return {Array} Returns an array of expanded values.
+ * @api public
+ */
+
+braces.create = (input, options = {}) => {
+  if (input === '' || input.length < 3) {
+    return [input];
+  }
+
+  return options.expand !== true
+    ? braces.compile(input, options)
+    : braces.expand(input, options);
+};
+
+/**
+ * Expose "braces"
+ */
+
+module.exports = braces;

+ 60 - 0
node_modules/braces/lib/compile.js

@@ -0,0 +1,60 @@
+'use strict';
+
+const fill = require('fill-range');
+const utils = require('./utils');
+
+const compile = (ast, options = {}) => {
+  const walk = (node, parent = {}) => {
+    const invalidBlock = utils.isInvalidBrace(parent);
+    const invalidNode = node.invalid === true && options.escapeInvalid === true;
+    const invalid = invalidBlock === true || invalidNode === true;
+    const prefix = options.escapeInvalid === true ? '\\' : '';
+    let output = '';
+
+    if (node.isOpen === true) {
+      return prefix + node.value;
+    }
+
+    if (node.isClose === true) {
+      console.log('node.isClose', prefix, node.value);
+      return prefix + node.value;
+    }
+
+    if (node.type === 'open') {
+      return invalid ? prefix + node.value : '(';
+    }
+
+    if (node.type === 'close') {
+      return invalid ? prefix + node.value : ')';
+    }
+
+    if (node.type === 'comma') {
+      return node.prev.type === 'comma' ? '' : invalid ? node.value : '|';
+    }
+
+    if (node.value) {
+      return node.value;
+    }
+
+    if (node.nodes && node.ranges > 0) {
+      const args = utils.reduce(node.nodes);
+      const range = fill(...args, { ...options, wrap: false, toRegex: true, strictZeros: true });
+
+      if (range.length !== 0) {
+        return args.length > 1 && range.length > 1 ? `(${range})` : range;
+      }
+    }
+
+    if (node.nodes) {
+      for (const child of node.nodes) {
+        output += walk(child, node);
+      }
+    }
+
+    return output;
+  };
+
+  return walk(ast);
+};
+
+module.exports = compile;

+ 57 - 0
node_modules/braces/lib/constants.js

@@ -0,0 +1,57 @@
+'use strict';
+
+module.exports = {
+  MAX_LENGTH: 10000,
+
+  // Digits
+  CHAR_0: '0', /* 0 */
+  CHAR_9: '9', /* 9 */
+
+  // Alphabet chars.
+  CHAR_UPPERCASE_A: 'A', /* A */
+  CHAR_LOWERCASE_A: 'a', /* a */
+  CHAR_UPPERCASE_Z: 'Z', /* Z */
+  CHAR_LOWERCASE_Z: 'z', /* z */
+
+  CHAR_LEFT_PARENTHESES: '(', /* ( */
+  CHAR_RIGHT_PARENTHESES: ')', /* ) */
+
+  CHAR_ASTERISK: '*', /* * */
+
+  // Non-alphabetic chars.
+  CHAR_AMPERSAND: '&', /* & */
+  CHAR_AT: '@', /* @ */
+  CHAR_BACKSLASH: '\\', /* \ */
+  CHAR_BACKTICK: '`', /* ` */
+  CHAR_CARRIAGE_RETURN: '\r', /* \r */
+  CHAR_CIRCUMFLEX_ACCENT: '^', /* ^ */
+  CHAR_COLON: ':', /* : */
+  CHAR_COMMA: ',', /* , */
+  CHAR_DOLLAR: '$', /* . */
+  CHAR_DOT: '.', /* . */
+  CHAR_DOUBLE_QUOTE: '"', /* " */
+  CHAR_EQUAL: '=', /* = */
+  CHAR_EXCLAMATION_MARK: '!', /* ! */
+  CHAR_FORM_FEED: '\f', /* \f */
+  CHAR_FORWARD_SLASH: '/', /* / */
+  CHAR_HASH: '#', /* # */
+  CHAR_HYPHEN_MINUS: '-', /* - */
+  CHAR_LEFT_ANGLE_BRACKET: '<', /* < */
+  CHAR_LEFT_CURLY_BRACE: '{', /* { */
+  CHAR_LEFT_SQUARE_BRACKET: '[', /* [ */
+  CHAR_LINE_FEED: '\n', /* \n */
+  CHAR_NO_BREAK_SPACE: '\u00A0', /* \u00A0 */
+  CHAR_PERCENT: '%', /* % */
+  CHAR_PLUS: '+', /* + */
+  CHAR_QUESTION_MARK: '?', /* ? */
+  CHAR_RIGHT_ANGLE_BRACKET: '>', /* > */
+  CHAR_RIGHT_CURLY_BRACE: '}', /* } */
+  CHAR_RIGHT_SQUARE_BRACKET: ']', /* ] */
+  CHAR_SEMICOLON: ';', /* ; */
+  CHAR_SINGLE_QUOTE: '\'', /* ' */
+  CHAR_SPACE: ' ', /*   */
+  CHAR_TAB: '\t', /* \t */
+  CHAR_UNDERSCORE: '_', /* _ */
+  CHAR_VERTICAL_LINE: '|', /* | */
+  CHAR_ZERO_WIDTH_NOBREAK_SPACE: '\uFEFF' /* \uFEFF */
+};

+ 113 - 0
node_modules/braces/lib/expand.js

@@ -0,0 +1,113 @@
+'use strict';
+
+const fill = require('fill-range');
+const stringify = require('./stringify');
+const utils = require('./utils');
+
+const append = (queue = '', stash = '', enclose = false) => {
+  const result = [];
+
+  queue = [].concat(queue);
+  stash = [].concat(stash);
+
+  if (!stash.length) return queue;
+  if (!queue.length) {
+    return enclose ? utils.flatten(stash).map(ele => `{${ele}}`) : stash;
+  }
+
+  for (const item of queue) {
+    if (Array.isArray(item)) {
+      for (const value of item) {
+        result.push(append(value, stash, enclose));
+      }
+    } else {
+      for (let ele of stash) {
+        if (enclose === true && typeof ele === 'string') ele = `{${ele}}`;
+        result.push(Array.isArray(ele) ? append(item, ele, enclose) : item + ele);
+      }
+    }
+  }
+  return utils.flatten(result);
+};
+
+const expand = (ast, options = {}) => {
+  const rangeLimit = options.rangeLimit === undefined ? 1000 : options.rangeLimit;
+
+  const walk = (node, parent = {}) => {
+    node.queue = [];
+
+    let p = parent;
+    let q = parent.queue;
+
+    while (p.type !== 'brace' && p.type !== 'root' && p.parent) {
+      p = p.parent;
+      q = p.queue;
+    }
+
+    if (node.invalid || node.dollar) {
+      q.push(append(q.pop(), stringify(node, options)));
+      return;
+    }
+
+    if (node.type === 'brace' && node.invalid !== true && node.nodes.length === 2) {
+      q.push(append(q.pop(), ['{}']));
+      return;
+    }
+
+    if (node.nodes && node.ranges > 0) {
+      const args = utils.reduce(node.nodes);
+
+      if (utils.exceedsLimit(...args, options.step, rangeLimit)) {
+        throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.');
+      }
+
+      let range = fill(...args, options);
+      if (range.length === 0) {
+        range = stringify(node, options);
+      }
+
+      q.push(append(q.pop(), range));
+      node.nodes = [];
+      return;
+    }
+
+    const enclose = utils.encloseBrace(node);
+    let queue = node.queue;
+    let block = node;
+
+    while (block.type !== 'brace' && block.type !== 'root' && block.parent) {
+      block = block.parent;
+      queue = block.queue;
+    }
+
+    for (let i = 0; i < node.nodes.length; i++) {
+      const child = node.nodes[i];
+
+      if (child.type === 'comma' && node.type === 'brace') {
+        if (i === 1) queue.push('');
+        queue.push('');
+        continue;
+      }
+
+      if (child.type === 'close') {
+        q.push(append(q.pop(), queue, enclose));
+        continue;
+      }
+
+      if (child.value && child.type !== 'open') {
+        queue.push(append(queue.pop(), child.value));
+        continue;
+      }
+
+      if (child.nodes) {
+        walk(child, node);
+      }
+    }
+
+    return queue;
+  };
+
+  return utils.flatten(walk(ast));
+};
+
+module.exports = expand;

+ 331 - 0
node_modules/braces/lib/parse.js

@@ -0,0 +1,331 @@
+'use strict';
+
+const stringify = require('./stringify');
+
+/**
+ * Constants
+ */
+
+const {
+  MAX_LENGTH,
+  CHAR_BACKSLASH, /* \ */
+  CHAR_BACKTICK, /* ` */
+  CHAR_COMMA, /* , */
+  CHAR_DOT, /* . */
+  CHAR_LEFT_PARENTHESES, /* ( */
+  CHAR_RIGHT_PARENTHESES, /* ) */
+  CHAR_LEFT_CURLY_BRACE, /* { */
+  CHAR_RIGHT_CURLY_BRACE, /* } */
+  CHAR_LEFT_SQUARE_BRACKET, /* [ */
+  CHAR_RIGHT_SQUARE_BRACKET, /* ] */
+  CHAR_DOUBLE_QUOTE, /* " */
+  CHAR_SINGLE_QUOTE, /* ' */
+  CHAR_NO_BREAK_SPACE,
+  CHAR_ZERO_WIDTH_NOBREAK_SPACE
+} = require('./constants');
+
+/**
+ * parse
+ */
+
+const parse = (input, options = {}) => {
+  if (typeof input !== 'string') {
+    throw new TypeError('Expected a string');
+  }
+
+  const opts = options || {};
+  const max = typeof opts.maxLength === 'number' ? Math.min(MAX_LENGTH, opts.maxLength) : MAX_LENGTH;
+  if (input.length > max) {
+    throw new SyntaxError(`Input length (${input.length}), exceeds max characters (${max})`);
+  }
+
+  const ast = { type: 'root', input, nodes: [] };
+  const stack = [ast];
+  let block = ast;
+  let prev = ast;
+  let brackets = 0;
+  const length = input.length;
+  let index = 0;
+  let depth = 0;
+  let value;
+
+  /**
+   * Helpers
+   */
+
+  const advance = () => input[index++];
+  const push = node => {
+    if (node.type === 'text' && prev.type === 'dot') {
+      prev.type = 'text';
+    }
+
+    if (prev && prev.type === 'text' && node.type === 'text') {
+      prev.value += node.value;
+      return;
+    }
+
+    block.nodes.push(node);
+    node.parent = block;
+    node.prev = prev;
+    prev = node;
+    return node;
+  };
+
+  push({ type: 'bos' });
+
+  while (index < length) {
+    block = stack[stack.length - 1];
+    value = advance();
+
+    /**
+     * Invalid chars
+     */
+
+    if (value === CHAR_ZERO_WIDTH_NOBREAK_SPACE || value === CHAR_NO_BREAK_SPACE) {
+      continue;
+    }
+
+    /**
+     * Escaped chars
+     */
+
+    if (value === CHAR_BACKSLASH) {
+      push({ type: 'text', value: (options.keepEscaping ? value : '') + advance() });
+      continue;
+    }
+
+    /**
+     * Right square bracket (literal): ']'
+     */
+
+    if (value === CHAR_RIGHT_SQUARE_BRACKET) {
+      push({ type: 'text', value: '\\' + value });
+      continue;
+    }
+
+    /**
+     * Left square bracket: '['
+     */
+
+    if (value === CHAR_LEFT_SQUARE_BRACKET) {
+      brackets++;
+
+      let next;
+
+      while (index < length && (next = advance())) {
+        value += next;
+
+        if (next === CHAR_LEFT_SQUARE_BRACKET) {
+          brackets++;
+          continue;
+        }
+
+        if (next === CHAR_BACKSLASH) {
+          value += advance();
+          continue;
+        }
+
+        if (next === CHAR_RIGHT_SQUARE_BRACKET) {
+          brackets--;
+
+          if (brackets === 0) {
+            break;
+          }
+        }
+      }
+
+      push({ type: 'text', value });
+      continue;
+    }
+
+    /**
+     * Parentheses
+     */
+
+    if (value === CHAR_LEFT_PARENTHESES) {
+      block = push({ type: 'paren', nodes: [] });
+      stack.push(block);
+      push({ type: 'text', value });
+      continue;
+    }
+
+    if (value === CHAR_RIGHT_PARENTHESES) {
+      if (block.type !== 'paren') {
+        push({ type: 'text', value });
+        continue;
+      }
+      block = stack.pop();
+      push({ type: 'text', value });
+      block = stack[stack.length - 1];
+      continue;
+    }
+
+    /**
+     * Quotes: '|"|`
+     */
+
+    if (value === CHAR_DOUBLE_QUOTE || value === CHAR_SINGLE_QUOTE || value === CHAR_BACKTICK) {
+      const open = value;
+      let next;
+
+      if (options.keepQuotes !== true) {
+        value = '';
+      }
+
+      while (index < length && (next = advance())) {
+        if (next === CHAR_BACKSLASH) {
+          value += next + advance();
+          continue;
+        }
+
+        if (next === open) {
+          if (options.keepQuotes === true) value += next;
+          break;
+        }
+
+        value += next;
+      }
+
+      push({ type: 'text', value });
+      continue;
+    }
+
+    /**
+     * Left curly brace: '{'
+     */
+
+    if (value === CHAR_LEFT_CURLY_BRACE) {
+      depth++;
+
+      const dollar = prev.value && prev.value.slice(-1) === '$' || block.dollar === true;
+      const brace = {
+        type: 'brace',
+        open: true,
+        close: false,
+        dollar,
+        depth,
+        commas: 0,
+        ranges: 0,
+        nodes: []
+      };
+
+      block = push(brace);
+      stack.push(block);
+      push({ type: 'open', value });
+      continue;
+    }
+
+    /**
+     * Right curly brace: '}'
+     */
+
+    if (value === CHAR_RIGHT_CURLY_BRACE) {
+      if (block.type !== 'brace') {
+        push({ type: 'text', value });
+        continue;
+      }
+
+      const type = 'close';
+      block = stack.pop();
+      block.close = true;
+
+      push({ type, value });
+      depth--;
+
+      block = stack[stack.length - 1];
+      continue;
+    }
+
+    /**
+     * Comma: ','
+     */
+
+    if (value === CHAR_COMMA && depth > 0) {
+      if (block.ranges > 0) {
+        block.ranges = 0;
+        const open = block.nodes.shift();
+        block.nodes = [open, { type: 'text', value: stringify(block) }];
+      }
+
+      push({ type: 'comma', value });
+      block.commas++;
+      continue;
+    }
+
+    /**
+     * Dot: '.'
+     */
+
+    if (value === CHAR_DOT && depth > 0 && block.commas === 0) {
+      const siblings = block.nodes;
+
+      if (depth === 0 || siblings.length === 0) {
+        push({ type: 'text', value });
+        continue;
+      }
+
+      if (prev.type === 'dot') {
+        block.range = [];
+        prev.value += value;
+        prev.type = 'range';
+
+        if (block.nodes.length !== 3 && block.nodes.length !== 5) {
+          block.invalid = true;
+          block.ranges = 0;
+          prev.type = 'text';
+          continue;
+        }
+
+        block.ranges++;
+        block.args = [];
+        continue;
+      }
+
+      if (prev.type === 'range') {
+        siblings.pop();
+
+        const before = siblings[siblings.length - 1];
+        before.value += prev.value + value;
+        prev = before;
+        block.ranges--;
+        continue;
+      }
+
+      push({ type: 'dot', value });
+      continue;
+    }
+
+    /**
+     * Text
+     */
+
+    push({ type: 'text', value });
+  }
+
+  // Mark imbalanced braces and brackets as invalid
+  do {
+    block = stack.pop();
+
+    if (block.type !== 'root') {
+      block.nodes.forEach(node => {
+        if (!node.nodes) {
+          if (node.type === 'open') node.isOpen = true;
+          if (node.type === 'close') node.isClose = true;
+          if (!node.nodes) node.type = 'text';
+          node.invalid = true;
+        }
+      });
+
+      // get the location of the block on parent.nodes (block's siblings)
+      const parent = stack[stack.length - 1];
+      const index = parent.nodes.indexOf(block);
+      // replace the (invalid) block with it's nodes
+      parent.nodes.splice(index, 1, ...block.nodes);
+    }
+  } while (stack.length > 0);
+
+  push({ type: 'eos' });
+  return ast;
+};
+
+module.exports = parse;

+ 32 - 0
node_modules/braces/lib/stringify.js

@@ -0,0 +1,32 @@
+'use strict';
+
+const utils = require('./utils');
+
+module.exports = (ast, options = {}) => {
+  const stringify = (node, parent = {}) => {
+    const invalidBlock = options.escapeInvalid && utils.isInvalidBrace(parent);
+    const invalidNode = node.invalid === true && options.escapeInvalid === true;
+    let output = '';
+
+    if (node.value) {
+      if ((invalidBlock || invalidNode) && utils.isOpenOrClose(node)) {
+        return '\\' + node.value;
+      }
+      return node.value;
+    }
+
+    if (node.value) {
+      return node.value;
+    }
+
+    if (node.nodes) {
+      for (const child of node.nodes) {
+        output += stringify(child);
+      }
+    }
+    return output;
+  };
+
+  return stringify(ast);
+};
+

+ 122 - 0
node_modules/braces/lib/utils.js

@@ -0,0 +1,122 @@
+'use strict';
+
+exports.isInteger = num => {
+  if (typeof num === 'number') {
+    return Number.isInteger(num);
+  }
+  if (typeof num === 'string' && num.trim() !== '') {
+    return Number.isInteger(Number(num));
+  }
+  return false;
+};
+
+/**
+ * Find a node of the given type
+ */
+
+exports.find = (node, type) => node.nodes.find(node => node.type === type);
+
+/**
+ * Find a node of the given type
+ */
+
+exports.exceedsLimit = (min, max, step = 1, limit) => {
+  if (limit === false) return false;
+  if (!exports.isInteger(min) || !exports.isInteger(max)) return false;
+  return ((Number(max) - Number(min)) / Number(step)) >= limit;
+};
+
+/**
+ * Escape the given node with '\\' before node.value
+ */
+
+exports.escapeNode = (block, n = 0, type) => {
+  const node = block.nodes[n];
+  if (!node) return;
+
+  if ((type && node.type === type) || node.type === 'open' || node.type === 'close') {
+    if (node.escaped !== true) {
+      node.value = '\\' + node.value;
+      node.escaped = true;
+    }
+  }
+};
+
+/**
+ * Returns true if the given brace node should be enclosed in literal braces
+ */
+
+exports.encloseBrace = node => {
+  if (node.type !== 'brace') return false;
+  if ((node.commas >> 0 + node.ranges >> 0) === 0) {
+    node.invalid = true;
+    return true;
+  }
+  return false;
+};
+
+/**
+ * Returns true if a brace node is invalid.
+ */
+
+exports.isInvalidBrace = block => {
+  if (block.type !== 'brace') return false;
+  if (block.invalid === true || block.dollar) return true;
+  if ((block.commas >> 0 + block.ranges >> 0) === 0) {
+    block.invalid = true;
+    return true;
+  }
+  if (block.open !== true || block.close !== true) {
+    block.invalid = true;
+    return true;
+  }
+  return false;
+};
+
+/**
+ * Returns true if a node is an open or close node
+ */
+
+exports.isOpenOrClose = node => {
+  if (node.type === 'open' || node.type === 'close') {
+    return true;
+  }
+  return node.open === true || node.close === true;
+};
+
+/**
+ * Reduce an array of text nodes.
+ */
+
+exports.reduce = nodes => nodes.reduce((acc, node) => {
+  if (node.type === 'text') acc.push(node.value);
+  if (node.type === 'range') node.type = 'text';
+  return acc;
+}, []);
+
+/**
+ * Flatten an array
+ */
+
+exports.flatten = (...args) => {
+  const result = [];
+
+  const flat = arr => {
+    for (let i = 0; i < arr.length; i++) {
+      const ele = arr[i];
+
+      if (Array.isArray(ele)) {
+        flat(ele);
+        continue;
+      }
+
+      if (ele !== undefined) {
+        result.push(ele);
+      }
+    }
+    return result;
+  };
+
+  flat(args);
+  return result;
+};

+ 77 - 0
node_modules/braces/package.json

@@ -0,0 +1,77 @@
+{
+  "name": "braces",
+  "description": "Bash-like brace expansion, implemented in JavaScript. Safer than other brace expansion libs, with complete support for the Bash 4.3 braces specification, without sacrificing speed.",
+  "version": "3.0.3",
+  "homepage": "https://github.com/micromatch/braces",
+  "author": "Jon Schlinkert (https://github.com/jonschlinkert)",
+  "contributors": [
+    "Brian Woodward (https://twitter.com/doowb)",
+    "Elan Shanker (https://github.com/es128)",
+    "Eugene Sharygin (https://github.com/eush77)",
+    "hemanth.hm (http://h3manth.com)",
+    "Jon Schlinkert (http://twitter.com/jonschlinkert)"
+  ],
+  "repository": "micromatch/braces",
+  "bugs": {
+    "url": "https://github.com/micromatch/braces/issues"
+  },
+  "license": "MIT",
+  "files": [
+    "index.js",
+    "lib"
+  ],
+  "main": "index.js",
+  "engines": {
+    "node": ">=8"
+  },
+  "scripts": {
+    "test": "mocha",
+    "benchmark": "node benchmark"
+  },
+  "dependencies": {
+    "fill-range": "^7.1.1"
+  },
+  "devDependencies": {
+    "ansi-colors": "^3.2.4",
+    "bash-path": "^2.0.1",
+    "gulp-format-md": "^2.0.0",
+    "mocha": "^6.1.1"
+  },
+  "keywords": [
+    "alpha",
+    "alphabetical",
+    "bash",
+    "brace",
+    "braces",
+    "expand",
+    "expansion",
+    "filepath",
+    "fill",
+    "fs",
+    "glob",
+    "globbing",
+    "letter",
+    "match",
+    "matches",
+    "matching",
+    "number",
+    "numerical",
+    "path",
+    "range",
+    "ranges",
+    "sh"
+  ],
+  "verb": {
+    "toc": false,
+    "layout": "default",
+    "tasks": [
+      "readme"
+    ],
+    "lint": {
+      "reflinks": true
+    },
+    "plugins": [
+      "gulp-format-md"
+    ]
+  }
+}

+ 21 - 0
node_modules/chokidar/LICENSE

@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2012 Paul Miller (https://paulmillr.com), Elan Shanker
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the “Software”), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 305 - 0
node_modules/chokidar/README.md

@@ -0,0 +1,305 @@
+# Chokidar [![Weekly downloads](https://img.shields.io/npm/dw/chokidar.svg)](https://github.com/paulmillr/chokidar)
+
+> Minimal and efficient cross-platform file watching library
+
+## Why?
+
+There are many reasons to prefer Chokidar to raw fs.watch / fs.watchFile in 2024:
+
+- Events are properly reported
+    - macOS events report filenames
+    - events are not reported twice
+    - changes are reported as add / change / unlink instead of useless `rename`
+- Atomic writes are supported, using `atomic` option
+    - Some file editors use them
+- Chunked writes are supported, using `awaitWriteFinish` option
+    - Large files are commonly written in chunks
+- File / dir filtering is supported
+- Symbolic links are supported
+- Recursive watching is always supported, instead of partial when using raw events
+    - Includes a way to limit recursion depth
+
+Chokidar relies on the Node.js core `fs` module, but when using
+`fs.watch` and `fs.watchFile` for watching, it normalizes the events it
+receives, often checking for truth by getting file stats and/or dir contents.
+The `fs.watch`-based implementation is the default, which
+avoids polling and keeps CPU usage down. Be advised that chokidar will initiate
+watchers recursively for everything within scope of the paths that have been
+specified, so be judicious about not wasting system resources by watching much
+more than needed. For some cases, `fs.watchFile`, which utilizes polling and uses more resources, is used.
+
+Made for [Brunch](https://brunch.io/) in 2012,
+it is now used in [~30 million repositories](https://www.npmjs.com/browse/depended/chokidar) and
+has proven itself in production environments.
+
+**Sep 2024 update:** v4 is out! It decreases dependency count from 13 to 1, removes
+support for globs, adds support for ESM / Common.js modules, and bumps minimum node.js version from v8 to v14.
+Check out [upgrading](#upgrading).
+
+## Getting started
+
+Install with npm:
+
+```sh
+npm install chokidar
+```
+
+Use it in your code:
+
+```javascript
+import chokidar from 'chokidar';
+
+// One-liner for current directory
+chokidar.watch('.').on('all', (event, path) => {
+  console.log(event, path);
+});
+
+
+// Extended options
+// ----------------
+
+// Initialize watcher.
+const watcher = chokidar.watch('file, dir, or array', {
+  ignored: (path, stats) => stats?.isFile() && !path.endsWith('.js'), // only watch js files
+  persistent: true
+});
+
+// Something to use when events are received.
+const log = console.log.bind(console);
+// Add event listeners.
+watcher
+  .on('add', path => log(`File ${path} has been added`))
+  .on('change', path => log(`File ${path} has been changed`))
+  .on('unlink', path => log(`File ${path} has been removed`));
+
+// More possible events.
+watcher
+  .on('addDir', path => log(`Directory ${path} has been added`))
+  .on('unlinkDir', path => log(`Directory ${path} has been removed`))
+  .on('error', error => log(`Watcher error: ${error}`))
+  .on('ready', () => log('Initial scan complete. Ready for changes'))
+  .on('raw', (event, path, details) => { // internal
+    log('Raw event info:', event, path, details);
+  });
+
+// 'add', 'addDir' and 'change' events also receive stat() results as second
+// argument when available: https://nodejs.org/api/fs.html#fs_class_fs_stats
+watcher.on('change', (path, stats) => {
+  if (stats) console.log(`File ${path} changed size to ${stats.size}`);
+});
+
+// Watch new files.
+watcher.add('new-file');
+watcher.add(['new-file-2', 'new-file-3']);
+
+// Get list of actual paths being watched on the filesystem
+let watchedPaths = watcher.getWatched();
+
+// Un-watch some files.
+await watcher.unwatch('new-file');
+
+// Stop watching. The method is async!
+await watcher.close().then(() => console.log('closed'));
+
+// Full list of options. See below for descriptions.
+// Do not use this example!
+chokidar.watch('file', {
+  persistent: true,
+
+  // ignore .txt files
+  ignored: (file) => file.endsWith('.txt'),
+  // watch only .txt files
+  // ignored: (file, _stats) => _stats?.isFile() && !file.endsWith('.txt'),
+
+  awaitWriteFinish: true, // emit single event when chunked writes are completed
+  atomic: true, // emit proper events when "atomic writes" (mv _tmp file) are used
+
+  // The options also allow specifying custom intervals in ms
+  // awaitWriteFinish: {
+  //   stabilityThreshold: 2000,
+  //   pollInterval: 100
+  // },
+  // atomic: 100,
+
+  interval: 100,
+  binaryInterval: 300,
+
+  cwd: '.',
+  depth: 99,
+
+  followSymlinks: true,
+  ignoreInitial: false,
+  ignorePermissionErrors: false,
+  usePolling: false,
+  alwaysStat: false,
+});
+
+```
+
+`chokidar.watch(paths, [options])`
+
+* `paths` (string or array of strings). Paths to files, dirs to be watched
+recursively.
+* `options` (object) Options object as defined below:
+
+#### Persistence
+
+* `persistent` (default: `true`). Indicates whether the process
+should continue to run as long as files are being watched.
+
+#### Path filtering
+
+* `ignored` function, regex, or path. Defines files/paths to be ignored.
+The whole relative or absolute path is tested, not just filename. If a function with two arguments
+is provided, it gets called twice per path - once with a single argument (the path), second
+time with two arguments (the path and the
+[`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats)
+object of that path).
+* `ignoreInitial` (default: `false`). If set to `false` then `add`/`addDir` events are also emitted for matching paths while
+instantiating the watching as chokidar discovers these file paths (before the `ready` event).
+* `followSymlinks` (default: `true`). When `false`, only the
+symlinks themselves will be watched for changes instead of following
+the link references and bubbling events through the link's path.
+* `cwd` (no default). The base directory from which watch `paths` are to be
+derived. Paths emitted with events will be relative to this.
+
+#### Performance
+
+* `usePolling` (default: `false`).
+Whether to use fs.watchFile (backed by polling), or fs.watch. If polling
+leads to high CPU utilization, consider setting this to `false`. It is
+typically necessary to **set this to `true` to successfully watch files over
+a network**, and it may be necessary to successfully watch files in other
+non-standard situations. Setting to `true` explicitly on MacOS overrides the
+`useFsEvents` default. You may also set the CHOKIDAR_USEPOLLING env variable
+to true (1) or false (0) in order to override this option.
+* _Polling-specific settings_ (effective when `usePolling: true`)
+  * `interval` (default: `100`). Interval of file system polling, in milliseconds. You may also
+    set the CHOKIDAR_INTERVAL env variable to override this option.
+  * `binaryInterval` (default: `300`). Interval of file system
+  polling for binary files.
+  ([see list of binary extensions](https://github.com/sindresorhus/binary-extensions/blob/master/binary-extensions.json))
+* `alwaysStat` (default: `false`). If relying upon the
+[`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats)
+object that may get passed with `add`, `addDir`, and `change` events, set
+this to `true` to ensure it is provided even in cases where it wasn't
+already available from the underlying watch events.
+* `depth` (default: `undefined`). If set, limits how many levels of
+subdirectories will be traversed.
+* `awaitWriteFinish` (default: `false`).
+By default, the `add` event will fire when a file first appears on disk, before
+the entire file has been written. Furthermore, in some cases some `change`
+events will be emitted while the file is being written. In some cases,
+especially when watching for large files there will be a need to wait for the
+write operation to finish before responding to a file creation or modification.
+Setting `awaitWriteFinish` to `true` (or a truthy value) will poll file size,
+holding its `add` and `change` events until the size does not change for a
+configurable amount of time. The appropriate duration setting is heavily
+dependent on the OS and hardware. For accurate detection this parameter should
+be relatively high, making file watching much less responsive.
+Use with caution.
+  * *`options.awaitWriteFinish` can be set to an object in order to adjust
+  timing params:*
+  * `awaitWriteFinish.stabilityThreshold` (default: 2000). Amount of time in
+  milliseconds for a file size to remain constant before emitting its event.
+  * `awaitWriteFinish.pollInterval` (default: 100). File size polling interval, in milliseconds.
+
+#### Errors
+
+* `ignorePermissionErrors` (default: `false`). Indicates whether to watch files
+that don't have read permissions if possible. If watching fails due to `EPERM`
+or `EACCES` with this set to `true`, the errors will be suppressed silently.
+* `atomic` (default: `true` if `useFsEvents` and `usePolling` are `false`).
+Automatically filters out artifacts that occur when using editors that use
+"atomic writes" instead of writing directly to the source file. If a file is
+re-added within 100 ms of being deleted, Chokidar emits a `change` event
+rather than `unlink` then `add`. If the default of 100 ms does not work well
+for you, you can override it by setting `atomic` to a custom value, in
+milliseconds.
+
+### Methods & Events
+
+`chokidar.watch()` produces an instance of `FSWatcher`. Methods of `FSWatcher`:
+
+* `.add(path / paths)`: Add files, directories for tracking.
+Takes an array of strings or just one string.
+* `.on(event, callback)`: Listen for an FS event.
+Available events: `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `ready`,
+`raw`, `error`.
+Additionally `all` is available which gets emitted with the underlying event
+name and path for every event other than `ready`, `raw`, and `error`.  `raw` is internal, use it carefully.
+* `.unwatch(path / paths)`: Stop watching files or directories.
+Takes an array of strings or just one string.
+* `.close()`: **async** Removes all listeners from watched files. Asynchronous, returns Promise. Use with `await` to ensure bugs don't happen.
+* `.getWatched()`: Returns an object representing all the paths on the file
+system being watched by this `FSWatcher` instance. The object's keys are all the
+directories (using absolute paths unless the `cwd` option was used), and the
+values are arrays of the names of the items contained in each directory.
+
+### CLI
+
+Check out third party [chokidar-cli](https://github.com/open-cli-tools/chokidar-cli),
+which allows to execute a command on each change, or get a stdio stream of change events.
+
+## Troubleshooting
+
+Sometimes, Chokidar runs out of file handles, causing `EMFILE` and `ENOSP` errors:
+
+* `bash: cannot set terminal process group (-1): Inappropriate ioctl for device bash: no job control in this shell`
+* `Error: watch /home/ ENOSPC`
+
+There are two things that can cause it.
+
+1. Exhausted file handles for generic fs operations
+    - Can be solved by using [graceful-fs](https://www.npmjs.com/package/graceful-fs),
+      which can monkey-patch native `fs` module used by chokidar: `let fs = require('fs'); let grfs = require('graceful-fs'); grfs.gracefulify(fs);`
+    - Can also be solved by tuning OS: `echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p`.
+2. Exhausted file handles for `fs.watch`
+    - Can't seem to be solved by graceful-fs or OS tuning
+    - It's possible to start using `usePolling: true`, which will switch backend to resource-intensive `fs.watchFile`
+
+All fsevents-related issues (`WARN optional dep failed`, `fsevents is not a constructor`) are solved by upgrading to v4+.
+
+## Changelog
+
+- **v4 (Sep 2024):** remove glob support and bundled fsevents. Decrease dependency count from 13 to 1. Rewrite in typescript. Bumps minimum node.js requirement to v14+
+- **v3 (Apr 2019):** massive CPU & RAM consumption improvements; reduces deps / package size by a factor of 17x and bumps Node.js requirement to v8.16+.
+- **v2 (Dec 2017):** globs are now posix-style-only. Tons of bugfixes.
+- **v1 (Apr 2015):** glob support, symlink support, tons of bugfixes. Node 0.8+ is supported
+- **v0.1 (Apr 2012):** Initial release, extracted from [Brunch](https://github.com/brunch/brunch/blob/9847a065aea300da99bd0753f90354cde9de1261/src/helpers.coffee#L66)
+
+### Upgrading
+
+If you've used globs before and want do replicate the functionality with v4:
+
+```js
+// v3
+chok.watch('**/*.js');
+chok.watch("./directory/**/*");
+
+// v4
+chok.watch('.', {
+  ignored: (path, stats) => stats?.isFile() && !path.endsWith('.js'), // only watch js files
+});
+chok.watch('./directory');
+
+// other way
+import { glob } from 'node:fs/promises';
+const watcher = watch(await Array.fromAsync(glob('**/*.js')));
+
+// unwatching
+// v3
+chok.unwatch('**/*.js');
+// v4
+chok.unwatch(await glob('**/*.js'));
+```
+
+## Also
+
+Why was chokidar named this way? What's the meaning behind it?
+
+>Chowkidar is a transliteration of a Hindi word meaning 'watchman, gatekeeper', चौकीदार. This ultimately comes from Sanskrit _ चतुष्क_ (crossway, quadrangle, consisting-of-four). This word is also used in other languages like Urdu as (چوکیدار) which is widely used in Pakistan and India. 
+
+## License
+
+MIT (c) Paul Miller (<https://paulmillr.com>), see [LICENSE](LICENSE) file.

+ 90 - 0
node_modules/chokidar/esm/handler.d.ts

@@ -0,0 +1,90 @@
+import type { WatchEventType, Stats, FSWatcher as NativeFsWatcher } from 'fs';
+import type { FSWatcher, WatchHelper, Throttler } from './index.js';
+import type { EntryInfo } from 'readdirp';
+export type Path = string;
+export declare const STR_DATA = "data";
+export declare const STR_END = "end";
+export declare const STR_CLOSE = "close";
+export declare const EMPTY_FN: () => void;
+export declare const IDENTITY_FN: (val: unknown) => unknown;
+export declare const isWindows: boolean;
+export declare const isMacos: boolean;
+export declare const isLinux: boolean;
+export declare const isFreeBSD: boolean;
+export declare const isIBMi: boolean;
+export declare const EVENTS: {
+    readonly ALL: "all";
+    readonly READY: "ready";
+    readonly ADD: "add";
+    readonly CHANGE: "change";
+    readonly ADD_DIR: "addDir";
+    readonly UNLINK: "unlink";
+    readonly UNLINK_DIR: "unlinkDir";
+    readonly RAW: "raw";
+    readonly ERROR: "error";
+};
+export type EventName = (typeof EVENTS)[keyof typeof EVENTS];
+export type FsWatchContainer = {
+    listeners: (path: string) => void | Set<any>;
+    errHandlers: (err: unknown) => void | Set<any>;
+    rawEmitters: (ev: WatchEventType, path: string, opts: unknown) => void | Set<any>;
+    watcher: NativeFsWatcher;
+    watcherUnusable?: boolean;
+};
+export interface WatchHandlers {
+    listener: (path: string) => void;
+    errHandler: (err: unknown) => void;
+    rawEmitter: (ev: WatchEventType, path: string, opts: unknown) => void;
+}
+/**
+ * @mixin
+ */
+export declare class NodeFsHandler {
+    fsw: FSWatcher;
+    _boundHandleError: (error: unknown) => void;
+    constructor(fsW: FSWatcher);
+    /**
+     * Watch file for changes with fs_watchFile or fs_watch.
+     * @param path to file or dir
+     * @param listener on fs change
+     * @returns closer for the watcher instance
+     */
+    _watchWithNodeFs(path: string, listener: (path: string, newStats?: any) => void | Promise<void>): (() => void) | undefined;
+    /**
+     * Watch a file and emit add event if warranted.
+     * @returns closer for the watcher instance
+     */
+    _handleFile(file: Path, stats: Stats, initialAdd: boolean): (() => void) | undefined;
+    /**
+     * Handle symlinks encountered while reading a dir.
+     * @param entry returned by readdirp
+     * @param directory path of dir being read
+     * @param path of this item
+     * @param item basename of this item
+     * @returns true if no more processing is needed for this entry.
+     */
+    _handleSymlink(entry: EntryInfo, directory: string, path: Path, item: string): Promise<boolean | undefined>;
+    _handleRead(directory: string, initialAdd: boolean, wh: WatchHelper, target: Path, dir: Path, depth: number, throttler: Throttler): Promise<unknown> | undefined;
+    /**
+     * Read directory to add / remove files from `@watched` list and re-read it on change.
+     * @param dir fs path
+     * @param stats
+     * @param initialAdd
+     * @param depth relative to user-supplied path
+     * @param target child path targeted for watch
+     * @param wh Common watch helpers for this path
+     * @param realpath
+     * @returns closer for the watcher instance.
+     */
+    _handleDir(dir: string, stats: Stats, initialAdd: boolean, depth: number, target: string, wh: WatchHelper, realpath: string): Promise<(() => void) | undefined>;
+    /**
+     * Handle added file, directory, or glob pattern.
+     * Delegates call to _handleFile / _handleDir after checks.
+     * @param path to file or ir
+     * @param initialAdd was the file added at watch instantiation?
+     * @param priorWh depth relative to user-supplied path
+     * @param depth Child path actually targeted for watch
+     * @param target Child path actually targeted for watch
+     */
+    _addToNodeFs(path: string, initialAdd: boolean, priorWh: WatchHelper | undefined, depth: number, target?: string): Promise<string | false | undefined>;
+}

+ 629 - 0
node_modules/chokidar/esm/handler.js

@@ -0,0 +1,629 @@
+import { watchFile, unwatchFile, watch as fs_watch } from 'fs';
+import { open, stat, lstat, realpath as fsrealpath } from 'fs/promises';
+import * as sysPath from 'path';
+import { type as osType } from 'os';
+export const STR_DATA = 'data';
+export const STR_END = 'end';
+export const STR_CLOSE = 'close';
+export const EMPTY_FN = () => { };
+export const IDENTITY_FN = (val) => val;
+const pl = process.platform;
+export const isWindows = pl === 'win32';
+export const isMacos = pl === 'darwin';
+export const isLinux = pl === 'linux';
+export const isFreeBSD = pl === 'freebsd';
+export const isIBMi = osType() === 'OS400';
+export const EVENTS = {
+    ALL: 'all',
+    READY: 'ready',
+    ADD: 'add',
+    CHANGE: 'change',
+    ADD_DIR: 'addDir',
+    UNLINK: 'unlink',
+    UNLINK_DIR: 'unlinkDir',
+    RAW: 'raw',
+    ERROR: 'error',
+};
+const EV = EVENTS;
+const THROTTLE_MODE_WATCH = 'watch';
+const statMethods = { lstat, stat };
+const KEY_LISTENERS = 'listeners';
+const KEY_ERR = 'errHandlers';
+const KEY_RAW = 'rawEmitters';
+const HANDLER_KEYS = [KEY_LISTENERS, KEY_ERR, KEY_RAW];
+// prettier-ignore
+const binaryExtensions = new Set([
+    '3dm', '3ds', '3g2', '3gp', '7z', 'a', 'aac', 'adp', 'afdesign', 'afphoto', 'afpub', 'ai',
+    'aif', 'aiff', 'alz', 'ape', 'apk', 'appimage', 'ar', 'arj', 'asf', 'au', 'avi',
+    'bak', 'baml', 'bh', 'bin', 'bk', 'bmp', 'btif', 'bz2', 'bzip2',
+    'cab', 'caf', 'cgm', 'class', 'cmx', 'cpio', 'cr2', 'cur', 'dat', 'dcm', 'deb', 'dex', 'djvu',
+    'dll', 'dmg', 'dng', 'doc', 'docm', 'docx', 'dot', 'dotm', 'dra', 'DS_Store', 'dsk', 'dts',
+    'dtshd', 'dvb', 'dwg', 'dxf',
+    'ecelp4800', 'ecelp7470', 'ecelp9600', 'egg', 'eol', 'eot', 'epub', 'exe',
+    'f4v', 'fbs', 'fh', 'fla', 'flac', 'flatpak', 'fli', 'flv', 'fpx', 'fst', 'fvt',
+    'g3', 'gh', 'gif', 'graffle', 'gz', 'gzip',
+    'h261', 'h263', 'h264', 'icns', 'ico', 'ief', 'img', 'ipa', 'iso',
+    'jar', 'jpeg', 'jpg', 'jpgv', 'jpm', 'jxr', 'key', 'ktx',
+    'lha', 'lib', 'lvp', 'lz', 'lzh', 'lzma', 'lzo',
+    'm3u', 'm4a', 'm4v', 'mar', 'mdi', 'mht', 'mid', 'midi', 'mj2', 'mka', 'mkv', 'mmr', 'mng',
+    'mobi', 'mov', 'movie', 'mp3',
+    'mp4', 'mp4a', 'mpeg', 'mpg', 'mpga', 'mxu',
+    'nef', 'npx', 'numbers', 'nupkg',
+    'o', 'odp', 'ods', 'odt', 'oga', 'ogg', 'ogv', 'otf', 'ott',
+    'pages', 'pbm', 'pcx', 'pdb', 'pdf', 'pea', 'pgm', 'pic', 'png', 'pnm', 'pot', 'potm',
+    'potx', 'ppa', 'ppam',
+    'ppm', 'pps', 'ppsm', 'ppsx', 'ppt', 'pptm', 'pptx', 'psd', 'pya', 'pyc', 'pyo', 'pyv',
+    'qt',
+    'rar', 'ras', 'raw', 'resources', 'rgb', 'rip', 'rlc', 'rmf', 'rmvb', 'rpm', 'rtf', 'rz',
+    's3m', 's7z', 'scpt', 'sgi', 'shar', 'snap', 'sil', 'sketch', 'slk', 'smv', 'snk', 'so',
+    'stl', 'suo', 'sub', 'swf',
+    'tar', 'tbz', 'tbz2', 'tga', 'tgz', 'thmx', 'tif', 'tiff', 'tlz', 'ttc', 'ttf', 'txz',
+    'udf', 'uvh', 'uvi', 'uvm', 'uvp', 'uvs', 'uvu',
+    'viv', 'vob',
+    'war', 'wav', 'wax', 'wbmp', 'wdp', 'weba', 'webm', 'webp', 'whl', 'wim', 'wm', 'wma',
+    'wmv', 'wmx', 'woff', 'woff2', 'wrm', 'wvx',
+    'xbm', 'xif', 'xla', 'xlam', 'xls', 'xlsb', 'xlsm', 'xlsx', 'xlt', 'xltm', 'xltx', 'xm',
+    'xmind', 'xpi', 'xpm', 'xwd', 'xz',
+    'z', 'zip', 'zipx',
+]);
+const isBinaryPath = (filePath) => binaryExtensions.has(sysPath.extname(filePath).slice(1).toLowerCase());
+// TODO: emit errors properly. Example: EMFILE on Macos.
+const foreach = (val, fn) => {
+    if (val instanceof Set) {
+        val.forEach(fn);
+    }
+    else {
+        fn(val);
+    }
+};
+const addAndConvert = (main, prop, item) => {
+    let container = main[prop];
+    if (!(container instanceof Set)) {
+        main[prop] = container = new Set([container]);
+    }
+    container.add(item);
+};
+const clearItem = (cont) => (key) => {
+    const set = cont[key];
+    if (set instanceof Set) {
+        set.clear();
+    }
+    else {
+        delete cont[key];
+    }
+};
+const delFromSet = (main, prop, item) => {
+    const container = main[prop];
+    if (container instanceof Set) {
+        container.delete(item);
+    }
+    else if (container === item) {
+        delete main[prop];
+    }
+};
+const isEmptySet = (val) => (val instanceof Set ? val.size === 0 : !val);
+const FsWatchInstances = new Map();
+/**
+ * Instantiates the fs_watch interface
+ * @param path to be watched
+ * @param options to be passed to fs_watch
+ * @param listener main event handler
+ * @param errHandler emits info about errors
+ * @param emitRaw emits raw event data
+ * @returns {NativeFsWatcher}
+ */
+function createFsWatchInstance(path, options, listener, errHandler, emitRaw) {
+    const handleEvent = (rawEvent, evPath) => {
+        listener(path);
+        emitRaw(rawEvent, evPath, { watchedPath: path });
+        // emit based on events occurring for files from a directory's watcher in
+        // case the file's watcher misses it (and rely on throttling to de-dupe)
+        if (evPath && path !== evPath) {
+            fsWatchBroadcast(sysPath.resolve(path, evPath), KEY_LISTENERS, sysPath.join(path, evPath));
+        }
+    };
+    try {
+        return fs_watch(path, {
+            persistent: options.persistent,
+        }, handleEvent);
+    }
+    catch (error) {
+        errHandler(error);
+        return undefined;
+    }
+}
+/**
+ * Helper for passing fs_watch event data to a collection of listeners
+ * @param fullPath absolute path bound to fs_watch instance
+ */
+const fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
+    const cont = FsWatchInstances.get(fullPath);
+    if (!cont)
+        return;
+    foreach(cont[listenerType], (listener) => {
+        listener(val1, val2, val3);
+    });
+};
+/**
+ * Instantiates the fs_watch interface or binds listeners
+ * to an existing one covering the same file system entry
+ * @param path
+ * @param fullPath absolute path
+ * @param options to be passed to fs_watch
+ * @param handlers container for event listener functions
+ */
+const setFsWatchListener = (path, fullPath, options, handlers) => {
+    const { listener, errHandler, rawEmitter } = handlers;
+    let cont = FsWatchInstances.get(fullPath);
+    let watcher;
+    if (!options.persistent) {
+        watcher = createFsWatchInstance(path, options, listener, errHandler, rawEmitter);
+        if (!watcher)
+            return;
+        return watcher.close.bind(watcher);
+    }
+    if (cont) {
+        addAndConvert(cont, KEY_LISTENERS, listener);
+        addAndConvert(cont, KEY_ERR, errHandler);
+        addAndConvert(cont, KEY_RAW, rawEmitter);
+    }
+    else {
+        watcher = createFsWatchInstance(path, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, // no need to use broadcast here
+        fsWatchBroadcast.bind(null, fullPath, KEY_RAW));
+        if (!watcher)
+            return;
+        watcher.on(EV.ERROR, async (error) => {
+            const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR);
+            if (cont)
+                cont.watcherUnusable = true; // documented since Node 10.4.1
+            // Workaround for https://github.com/joyent/node/issues/4337
+            if (isWindows && error.code === 'EPERM') {
+                try {
+                    const fd = await open(path, 'r');
+                    await fd.close();
+                    broadcastErr(error);
+                }
+                catch (err) {
+                    // do nothing
+                }
+            }
+            else {
+                broadcastErr(error);
+            }
+        });
+        cont = {
+            listeners: listener,
+            errHandlers: errHandler,
+            rawEmitters: rawEmitter,
+            watcher,
+        };
+        FsWatchInstances.set(fullPath, cont);
+    }
+    // const index = cont.listeners.indexOf(listener);
+    // removes this instance's listeners and closes the underlying fs_watch
+    // instance if there are no more listeners left
+    return () => {
+        delFromSet(cont, KEY_LISTENERS, listener);
+        delFromSet(cont, KEY_ERR, errHandler);
+        delFromSet(cont, KEY_RAW, rawEmitter);
+        if (isEmptySet(cont.listeners)) {
+            // Check to protect against issue gh-730.
+            // if (cont.watcherUnusable) {
+            cont.watcher.close();
+            // }
+            FsWatchInstances.delete(fullPath);
+            HANDLER_KEYS.forEach(clearItem(cont));
+            // @ts-ignore
+            cont.watcher = undefined;
+            Object.freeze(cont);
+        }
+    };
+};
+// fs_watchFile helpers
+// object to hold per-process fs_watchFile instances
+// (may be shared across chokidar FSWatcher instances)
+const FsWatchFileInstances = new Map();
+/**
+ * Instantiates the fs_watchFile interface or binds listeners
+ * to an existing one covering the same file system entry
+ * @param path to be watched
+ * @param fullPath absolute path
+ * @param options options to be passed to fs_watchFile
+ * @param handlers container for event listener functions
+ * @returns closer
+ */
+const setFsWatchFileListener = (path, fullPath, options, handlers) => {
+    const { listener, rawEmitter } = handlers;
+    let cont = FsWatchFileInstances.get(fullPath);
+    // let listeners = new Set();
+    // let rawEmitters = new Set();
+    const copts = cont && cont.options;
+    if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {
+        // "Upgrade" the watcher to persistence or a quicker interval.
+        // This creates some unlikely edge case issues if the user mixes
+        // settings in a very weird way, but solving for those cases
+        // doesn't seem worthwhile for the added complexity.
+        // listeners = cont.listeners;
+        // rawEmitters = cont.rawEmitters;
+        unwatchFile(fullPath);
+        cont = undefined;
+    }
+    if (cont) {
+        addAndConvert(cont, KEY_LISTENERS, listener);
+        addAndConvert(cont, KEY_RAW, rawEmitter);
+    }
+    else {
+        // TODO
+        // listeners.add(listener);
+        // rawEmitters.add(rawEmitter);
+        cont = {
+            listeners: listener,
+            rawEmitters: rawEmitter,
+            options,
+            watcher: watchFile(fullPath, options, (curr, prev) => {
+                foreach(cont.rawEmitters, (rawEmitter) => {
+                    rawEmitter(EV.CHANGE, fullPath, { curr, prev });
+                });
+                const currmtime = curr.mtimeMs;
+                if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
+                    foreach(cont.listeners, (listener) => listener(path, curr));
+                }
+            }),
+        };
+        FsWatchFileInstances.set(fullPath, cont);
+    }
+    // const index = cont.listeners.indexOf(listener);
+    // Removes this instance's listeners and closes the underlying fs_watchFile
+    // instance if there are no more listeners left.
+    return () => {
+        delFromSet(cont, KEY_LISTENERS, listener);
+        delFromSet(cont, KEY_RAW, rawEmitter);
+        if (isEmptySet(cont.listeners)) {
+            FsWatchFileInstances.delete(fullPath);
+            unwatchFile(fullPath);
+            cont.options = cont.watcher = undefined;
+            Object.freeze(cont);
+        }
+    };
+};
+/**
+ * @mixin
+ */
+export class NodeFsHandler {
+    constructor(fsW) {
+        this.fsw = fsW;
+        this._boundHandleError = (error) => fsW._handleError(error);
+    }
+    /**
+     * Watch file for changes with fs_watchFile or fs_watch.
+     * @param path to file or dir
+     * @param listener on fs change
+     * @returns closer for the watcher instance
+     */
+    _watchWithNodeFs(path, listener) {
+        const opts = this.fsw.options;
+        const directory = sysPath.dirname(path);
+        const basename = sysPath.basename(path);
+        const parent = this.fsw._getWatchedDir(directory);
+        parent.add(basename);
+        const absolutePath = sysPath.resolve(path);
+        const options = {
+            persistent: opts.persistent,
+        };
+        if (!listener)
+            listener = EMPTY_FN;
+        let closer;
+        if (opts.usePolling) {
+            const enableBin = opts.interval !== opts.binaryInterval;
+            options.interval = enableBin && isBinaryPath(basename) ? opts.binaryInterval : opts.interval;
+            closer = setFsWatchFileListener(path, absolutePath, options, {
+                listener,
+                rawEmitter: this.fsw._emitRaw,
+            });
+        }
+        else {
+            closer = setFsWatchListener(path, absolutePath, options, {
+                listener,
+                errHandler: this._boundHandleError,
+                rawEmitter: this.fsw._emitRaw,
+            });
+        }
+        return closer;
+    }
+    /**
+     * Watch a file and emit add event if warranted.
+     * @returns closer for the watcher instance
+     */
+    _handleFile(file, stats, initialAdd) {
+        if (this.fsw.closed) {
+            return;
+        }
+        const dirname = sysPath.dirname(file);
+        const basename = sysPath.basename(file);
+        const parent = this.fsw._getWatchedDir(dirname);
+        // stats is always present
+        let prevStats = stats;
+        // if the file is already being watched, do nothing
+        if (parent.has(basename))
+            return;
+        const listener = async (path, newStats) => {
+            if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
+                return;
+            if (!newStats || newStats.mtimeMs === 0) {
+                try {
+                    const newStats = await stat(file);
+                    if (this.fsw.closed)
+                        return;
+                    // Check that change event was not fired because of changed only accessTime.
+                    const at = newStats.atimeMs;
+                    const mt = newStats.mtimeMs;
+                    if (!at || at <= mt || mt !== prevStats.mtimeMs) {
+                        this.fsw._emit(EV.CHANGE, file, newStats);
+                    }
+                    if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats.ino) {
+                        this.fsw._closeFile(path);
+                        prevStats = newStats;
+                        const closer = this._watchWithNodeFs(file, listener);
+                        if (closer)
+                            this.fsw._addPathCloser(path, closer);
+                    }
+                    else {
+                        prevStats = newStats;
+                    }
+                }
+                catch (error) {
+                    // Fix issues where mtime is null but file is still present
+                    this.fsw._remove(dirname, basename);
+                }
+                // add is about to be emitted if file not already tracked in parent
+            }
+            else if (parent.has(basename)) {
+                // Check that change event was not fired because of changed only accessTime.
+                const at = newStats.atimeMs;
+                const mt = newStats.mtimeMs;
+                if (!at || at <= mt || mt !== prevStats.mtimeMs) {
+                    this.fsw._emit(EV.CHANGE, file, newStats);
+                }
+                prevStats = newStats;
+            }
+        };
+        // kick off the watcher
+        const closer = this._watchWithNodeFs(file, listener);
+        // emit an add event if we're supposed to
+        if (!(initialAdd && this.fsw.options.ignoreInitial) && this.fsw._isntIgnored(file)) {
+            if (!this.fsw._throttle(EV.ADD, file, 0))
+                return;
+            this.fsw._emit(EV.ADD, file, stats);
+        }
+        return closer;
+    }
+    /**
+     * Handle symlinks encountered while reading a dir.
+     * @param entry returned by readdirp
+     * @param directory path of dir being read
+     * @param path of this item
+     * @param item basename of this item
+     * @returns true if no more processing is needed for this entry.
+     */
+    async _handleSymlink(entry, directory, path, item) {
+        if (this.fsw.closed) {
+            return;
+        }
+        const full = entry.fullPath;
+        const dir = this.fsw._getWatchedDir(directory);
+        if (!this.fsw.options.followSymlinks) {
+            // watch symlink directly (don't follow) and detect changes
+            this.fsw._incrReadyCount();
+            let linkPath;
+            try {
+                linkPath = await fsrealpath(path);
+            }
+            catch (e) {
+                this.fsw._emitReady();
+                return true;
+            }
+            if (this.fsw.closed)
+                return;
+            if (dir.has(item)) {
+                if (this.fsw._symlinkPaths.get(full) !== linkPath) {
+                    this.fsw._symlinkPaths.set(full, linkPath);
+                    this.fsw._emit(EV.CHANGE, path, entry.stats);
+                }
+            }
+            else {
+                dir.add(item);
+                this.fsw._symlinkPaths.set(full, linkPath);
+                this.fsw._emit(EV.ADD, path, entry.stats);
+            }
+            this.fsw._emitReady();
+            return true;
+        }
+        // don't follow the same symlink more than once
+        if (this.fsw._symlinkPaths.has(full)) {
+            return true;
+        }
+        this.fsw._symlinkPaths.set(full, true);
+    }
+    _handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {
+        // Normalize the directory name on Windows
+        directory = sysPath.join(directory, '');
+        throttler = this.fsw._throttle('readdir', directory, 1000);
+        if (!throttler)
+            return;
+        const previous = this.fsw._getWatchedDir(wh.path);
+        const current = new Set();
+        let stream = this.fsw._readdirp(directory, {
+            fileFilter: (entry) => wh.filterPath(entry),
+            directoryFilter: (entry) => wh.filterDir(entry),
+        });
+        if (!stream)
+            return;
+        stream
+            .on(STR_DATA, async (entry) => {
+            if (this.fsw.closed) {
+                stream = undefined;
+                return;
+            }
+            const item = entry.path;
+            let path = sysPath.join(directory, item);
+            current.add(item);
+            if (entry.stats.isSymbolicLink() &&
+                (await this._handleSymlink(entry, directory, path, item))) {
+                return;
+            }
+            if (this.fsw.closed) {
+                stream = undefined;
+                return;
+            }
+            // Files that present in current directory snapshot
+            // but absent in previous are added to watch list and
+            // emit `add` event.
+            if (item === target || (!target && !previous.has(item))) {
+                this.fsw._incrReadyCount();
+                // ensure relativeness of path is preserved in case of watcher reuse
+                path = sysPath.join(dir, sysPath.relative(dir, path));
+                this._addToNodeFs(path, initialAdd, wh, depth + 1);
+            }
+        })
+            .on(EV.ERROR, this._boundHandleError);
+        return new Promise((resolve, reject) => {
+            if (!stream)
+                return reject();
+            stream.once(STR_END, () => {
+                if (this.fsw.closed) {
+                    stream = undefined;
+                    return;
+                }
+                const wasThrottled = throttler ? throttler.clear() : false;
+                resolve(undefined);
+                // Files that absent in current directory snapshot
+                // but present in previous emit `remove` event
+                // and are removed from @watched[directory].
+                previous
+                    .getChildren()
+                    .filter((item) => {
+                    return item !== directory && !current.has(item);
+                })
+                    .forEach((item) => {
+                    this.fsw._remove(directory, item);
+                });
+                stream = undefined;
+                // one more time for any missed in case changes came in extremely quickly
+                if (wasThrottled)
+                    this._handleRead(directory, false, wh, target, dir, depth, throttler);
+            });
+        });
+    }
+    /**
+     * Read directory to add / remove files from `@watched` list and re-read it on change.
+     * @param dir fs path
+     * @param stats
+     * @param initialAdd
+     * @param depth relative to user-supplied path
+     * @param target child path targeted for watch
+     * @param wh Common watch helpers for this path
+     * @param realpath
+     * @returns closer for the watcher instance.
+     */
+    async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath) {
+        const parentDir = this.fsw._getWatchedDir(sysPath.dirname(dir));
+        const tracked = parentDir.has(sysPath.basename(dir));
+        if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {
+            this.fsw._emit(EV.ADD_DIR, dir, stats);
+        }
+        // ensure dir is tracked (harmless if redundant)
+        parentDir.add(sysPath.basename(dir));
+        this.fsw._getWatchedDir(dir);
+        let throttler;
+        let closer;
+        const oDepth = this.fsw.options.depth;
+        if ((oDepth == null || depth <= oDepth) && !this.fsw._symlinkPaths.has(realpath)) {
+            if (!target) {
+                await this._handleRead(dir, initialAdd, wh, target, dir, depth, throttler);
+                if (this.fsw.closed)
+                    return;
+            }
+            closer = this._watchWithNodeFs(dir, (dirPath, stats) => {
+                // if current directory is removed, do nothing
+                if (stats && stats.mtimeMs === 0)
+                    return;
+                this._handleRead(dirPath, false, wh, target, dir, depth, throttler);
+            });
+        }
+        return closer;
+    }
+    /**
+     * Handle added file, directory, or glob pattern.
+     * Delegates call to _handleFile / _handleDir after checks.
+     * @param path to file or ir
+     * @param initialAdd was the file added at watch instantiation?
+     * @param priorWh depth relative to user-supplied path
+     * @param depth Child path actually targeted for watch
+     * @param target Child path actually targeted for watch
+     */
+    async _addToNodeFs(path, initialAdd, priorWh, depth, target) {
+        const ready = this.fsw._emitReady;
+        if (this.fsw._isIgnored(path) || this.fsw.closed) {
+            ready();
+            return false;
+        }
+        const wh = this.fsw._getWatchHelpers(path);
+        if (priorWh) {
+            wh.filterPath = (entry) => priorWh.filterPath(entry);
+            wh.filterDir = (entry) => priorWh.filterDir(entry);
+        }
+        // evaluate what is at the path we're being asked to watch
+        try {
+            const stats = await statMethods[wh.statMethod](wh.watchPath);
+            if (this.fsw.closed)
+                return;
+            if (this.fsw._isIgnored(wh.watchPath, stats)) {
+                ready();
+                return false;
+            }
+            const follow = this.fsw.options.followSymlinks;
+            let closer;
+            if (stats.isDirectory()) {
+                const absPath = sysPath.resolve(path);
+                const targetPath = follow ? await fsrealpath(path) : path;
+                if (this.fsw.closed)
+                    return;
+                closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
+                if (this.fsw.closed)
+                    return;
+                // preserve this symlink's target path
+                if (absPath !== targetPath && targetPath !== undefined) {
+                    this.fsw._symlinkPaths.set(absPath, targetPath);
+                }
+            }
+            else if (stats.isSymbolicLink()) {
+                const targetPath = follow ? await fsrealpath(path) : path;
+                if (this.fsw.closed)
+                    return;
+                const parent = sysPath.dirname(wh.watchPath);
+                this.fsw._getWatchedDir(parent).add(wh.watchPath);
+                this.fsw._emit(EV.ADD, wh.watchPath, stats);
+                closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath);
+                if (this.fsw.closed)
+                    return;
+                // preserve this symlink's target path
+                if (targetPath !== undefined) {
+                    this.fsw._symlinkPaths.set(sysPath.resolve(path), targetPath);
+                }
+            }
+            else {
+                closer = this._handleFile(wh.watchPath, stats, initialAdd);
+            }
+            ready();
+            if (closer)
+                this.fsw._addPathCloser(path, closer);
+            return false;
+        }
+        catch (error) {
+            if (this.fsw._handleError(error)) {
+                ready();
+                return path;
+            }
+        }
+    }
+}

+ 215 - 0
node_modules/chokidar/esm/index.d.ts

@@ -0,0 +1,215 @@
+/*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */
+import { Stats } from 'fs';
+import { EventEmitter } from 'events';
+import { ReaddirpStream, ReaddirpOptions, EntryInfo } from 'readdirp';
+import { NodeFsHandler, EventName, Path, EVENTS as EV, WatchHandlers } from './handler.js';
+type AWF = {
+    stabilityThreshold: number;
+    pollInterval: number;
+};
+type BasicOpts = {
+    persistent: boolean;
+    ignoreInitial: boolean;
+    followSymlinks: boolean;
+    cwd?: string;
+    usePolling: boolean;
+    interval: number;
+    binaryInterval: number;
+    alwaysStat?: boolean;
+    depth?: number;
+    ignorePermissionErrors: boolean;
+    atomic: boolean | number;
+};
+export type Throttler = {
+    timeoutObject: NodeJS.Timeout;
+    clear: () => void;
+    count: number;
+};
+export type ChokidarOptions = Partial<BasicOpts & {
+    ignored: Matcher | Matcher[];
+    awaitWriteFinish: boolean | Partial<AWF>;
+}>;
+export type FSWInstanceOptions = BasicOpts & {
+    ignored: Matcher[];
+    awaitWriteFinish: false | AWF;
+};
+export type ThrottleType = 'readdir' | 'watch' | 'add' | 'remove' | 'change';
+export type EmitArgs = [path: Path, stats?: Stats];
+export type EmitErrorArgs = [error: Error, stats?: Stats];
+export type EmitArgsWithName = [event: EventName, ...EmitArgs];
+export type MatchFunction = (val: string, stats?: Stats) => boolean;
+export interface MatcherObject {
+    path: string;
+    recursive?: boolean;
+}
+export type Matcher = string | RegExp | MatchFunction | MatcherObject;
+/**
+ * Directory entry.
+ */
+declare class DirEntry {
+    path: Path;
+    _removeWatcher: (dir: string, base: string) => void;
+    items: Set<Path>;
+    constructor(dir: Path, removeWatcher: (dir: string, base: string) => void);
+    add(item: string): void;
+    remove(item: string): Promise<void>;
+    has(item: string): boolean | undefined;
+    getChildren(): string[];
+    dispose(): void;
+}
+export declare class WatchHelper {
+    fsw: FSWatcher;
+    path: string;
+    watchPath: string;
+    fullWatchPath: string;
+    dirParts: string[][];
+    followSymlinks: boolean;
+    statMethod: 'stat' | 'lstat';
+    constructor(path: string, follow: boolean, fsw: FSWatcher);
+    entryPath(entry: EntryInfo): Path;
+    filterPath(entry: EntryInfo): boolean;
+    filterDir(entry: EntryInfo): boolean;
+}
+export interface FSWatcherKnownEventMap {
+    [EV.READY]: [];
+    [EV.RAW]: Parameters<WatchHandlers['rawEmitter']>;
+    [EV.ERROR]: Parameters<WatchHandlers['errHandler']>;
+    [EV.ALL]: [event: EventName, ...EmitArgs];
+}
+export type FSWatcherEventMap = FSWatcherKnownEventMap & {
+    [k in Exclude<EventName, keyof FSWatcherKnownEventMap>]: EmitArgs;
+};
+/**
+ * Watches files & directories for changes. Emitted events:
+ * `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `all`, `error`
+ *
+ *     new FSWatcher()
+ *       .add(directories)
+ *       .on('add', path => log('File', path, 'was added'))
+ */
+export declare class FSWatcher extends EventEmitter<FSWatcherEventMap> {
+    closed: boolean;
+    options: FSWInstanceOptions;
+    _closers: Map<string, Array<any>>;
+    _ignoredPaths: Set<Matcher>;
+    _throttled: Map<ThrottleType, Map<any, any>>;
+    _streams: Set<ReaddirpStream>;
+    _symlinkPaths: Map<Path, string | boolean>;
+    _watched: Map<string, DirEntry>;
+    _pendingWrites: Map<string, any>;
+    _pendingUnlinks: Map<string, EmitArgsWithName>;
+    _readyCount: number;
+    _emitReady: () => void;
+    _closePromise?: Promise<void>;
+    _userIgnored?: MatchFunction;
+    _readyEmitted: boolean;
+    _emitRaw: WatchHandlers['rawEmitter'];
+    _boundRemove: (dir: string, item: string) => void;
+    _nodeFsHandler: NodeFsHandler;
+    constructor(_opts?: ChokidarOptions);
+    _addIgnoredPath(matcher: Matcher): void;
+    _removeIgnoredPath(matcher: Matcher): void;
+    /**
+     * Adds paths to be watched on an existing FSWatcher instance.
+     * @param paths_ file or file list. Other arguments are unused
+     */
+    add(paths_: Path | Path[], _origAdd?: string, _internal?: boolean): FSWatcher;
+    /**
+     * Close watchers or start ignoring events from specified paths.
+     */
+    unwatch(paths_: Path | Path[]): FSWatcher;
+    /**
+     * Close watchers and remove all listeners from watched paths.
+     */
+    close(): Promise<void>;
+    /**
+     * Expose list of watched paths
+     * @returns for chaining
+     */
+    getWatched(): Record<string, string[]>;
+    emitWithAll(event: EventName, args: EmitArgs): void;
+    /**
+     * Normalize and emit events.
+     * Calling _emit DOES NOT MEAN emit() would be called!
+     * @param event Type of event
+     * @param path File or directory path
+     * @param stats arguments to be passed with event
+     * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
+     */
+    _emit(event: EventName, path: Path, stats?: Stats): Promise<this | undefined>;
+    /**
+     * Common handler for errors
+     * @returns The error if defined, otherwise the value of the FSWatcher instance's `closed` flag
+     */
+    _handleError(error: Error): Error | boolean;
+    /**
+     * Helper utility for throttling
+     * @param actionType type being throttled
+     * @param path being acted upon
+     * @param timeout duration of time to suppress duplicate actions
+     * @returns tracking object or false if action should be suppressed
+     */
+    _throttle(actionType: ThrottleType, path: Path, timeout: number): Throttler | false;
+    _incrReadyCount(): number;
+    /**
+     * Awaits write operation to finish.
+     * Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback.
+     * @param path being acted upon
+     * @param threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished
+     * @param event
+     * @param awfEmit Callback to be called when ready for event to be emitted.
+     */
+    _awaitWriteFinish(path: Path, threshold: number, event: EventName, awfEmit: (err?: Error, stat?: Stats) => void): void;
+    /**
+     * Determines whether user has asked to ignore this path.
+     */
+    _isIgnored(path: Path, stats?: Stats): boolean;
+    _isntIgnored(path: Path, stat?: Stats): boolean;
+    /**
+     * Provides a set of common helpers and properties relating to symlink handling.
+     * @param path file or directory pattern being watched
+     */
+    _getWatchHelpers(path: Path): WatchHelper;
+    /**
+     * Provides directory tracking objects
+     * @param directory path of the directory
+     */
+    _getWatchedDir(directory: string): DirEntry;
+    /**
+     * Check for read permissions: https://stackoverflow.com/a/11781404/1358405
+     */
+    _hasReadPermissions(stats: Stats): boolean;
+    /**
+     * Handles emitting unlink events for
+     * files and directories, and via recursion, for
+     * files and directories within directories that are unlinked
+     * @param directory within which the following item is located
+     * @param item      base path of item/directory
+     */
+    _remove(directory: string, item: string, isDirectory?: boolean): void;
+    /**
+     * Closes all watchers for a path
+     */
+    _closePath(path: Path): void;
+    /**
+     * Closes only file-specific watchers
+     */
+    _closeFile(path: Path): void;
+    _addPathCloser(path: Path, closer: () => void): void;
+    _readdirp(root: Path, opts?: Partial<ReaddirpOptions>): ReaddirpStream | undefined;
+}
+/**
+ * Instantiates watcher with paths to be tracked.
+ * @param paths file / directory paths
+ * @param options opts, such as `atomic`, `awaitWriteFinish`, `ignored`, and others
+ * @returns an instance of FSWatcher for chaining.
+ * @example
+ * const watcher = watch('.').on('all', (event, path) => { console.log(event, path); });
+ * watch('.', { atomic: true, awaitWriteFinish: true, ignored: (f, stats) => stats?.isFile() && !f.endsWith('.js') })
+ */
+export declare function watch(paths: string | string[], options?: ChokidarOptions): FSWatcher;
+declare const _default: {
+    watch: typeof watch;
+    FSWatcher: typeof FSWatcher;
+};
+export default _default;

+ 798 - 0
node_modules/chokidar/esm/index.js

@@ -0,0 +1,798 @@
+/*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */
+import { stat as statcb } from 'fs';
+import { stat, readdir } from 'fs/promises';
+import { EventEmitter } from 'events';
+import * as sysPath from 'path';
+import { readdirp } from 'readdirp';
+import { NodeFsHandler, EVENTS as EV, isWindows, isIBMi, EMPTY_FN, STR_CLOSE, STR_END, } from './handler.js';
+const SLASH = '/';
+const SLASH_SLASH = '//';
+const ONE_DOT = '.';
+const TWO_DOTS = '..';
+const STRING_TYPE = 'string';
+const BACK_SLASH_RE = /\\/g;
+const DOUBLE_SLASH_RE = /\/\//;
+const DOT_RE = /\..*\.(sw[px])$|~$|\.subl.*\.tmp/;
+const REPLACER_RE = /^\.[/\\]/;
+function arrify(item) {
+    return Array.isArray(item) ? item : [item];
+}
+const isMatcherObject = (matcher) => typeof matcher === 'object' && matcher !== null && !(matcher instanceof RegExp);
+function createPattern(matcher) {
+    if (typeof matcher === 'function')
+        return matcher;
+    if (typeof matcher === 'string')
+        return (string) => matcher === string;
+    if (matcher instanceof RegExp)
+        return (string) => matcher.test(string);
+    if (typeof matcher === 'object' && matcher !== null) {
+        return (string) => {
+            if (matcher.path === string)
+                return true;
+            if (matcher.recursive) {
+                const relative = sysPath.relative(matcher.path, string);
+                if (!relative) {
+                    return false;
+                }
+                return !relative.startsWith('..') && !sysPath.isAbsolute(relative);
+            }
+            return false;
+        };
+    }
+    return () => false;
+}
+function normalizePath(path) {
+    if (typeof path !== 'string')
+        throw new Error('string expected');
+    path = sysPath.normalize(path);
+    path = path.replace(/\\/g, '/');
+    let prepend = false;
+    if (path.startsWith('//'))
+        prepend = true;
+    const DOUBLE_SLASH_RE = /\/\//;
+    while (path.match(DOUBLE_SLASH_RE))
+        path = path.replace(DOUBLE_SLASH_RE, '/');
+    if (prepend)
+        path = '/' + path;
+    return path;
+}
+function matchPatterns(patterns, testString, stats) {
+    const path = normalizePath(testString);
+    for (let index = 0; index < patterns.length; index++) {
+        const pattern = patterns[index];
+        if (pattern(path, stats)) {
+            return true;
+        }
+    }
+    return false;
+}
+function anymatch(matchers, testString) {
+    if (matchers == null) {
+        throw new TypeError('anymatch: specify first argument');
+    }
+    // Early cache for matchers.
+    const matchersArray = arrify(matchers);
+    const patterns = matchersArray.map((matcher) => createPattern(matcher));
+    if (testString == null) {
+        return (testString, stats) => {
+            return matchPatterns(patterns, testString, stats);
+        };
+    }
+    return matchPatterns(patterns, testString);
+}
+const unifyPaths = (paths_) => {
+    const paths = arrify(paths_).flat();
+    if (!paths.every((p) => typeof p === STRING_TYPE)) {
+        throw new TypeError(`Non-string provided as watch path: ${paths}`);
+    }
+    return paths.map(normalizePathToUnix);
+};
+// If SLASH_SLASH occurs at the beginning of path, it is not replaced
+//     because "//StoragePC/DrivePool/Movies" is a valid network path
+const toUnix = (string) => {
+    let str = string.replace(BACK_SLASH_RE, SLASH);
+    let prepend = false;
+    if (str.startsWith(SLASH_SLASH)) {
+        prepend = true;
+    }
+    while (str.match(DOUBLE_SLASH_RE)) {
+        str = str.replace(DOUBLE_SLASH_RE, SLASH);
+    }
+    if (prepend) {
+        str = SLASH + str;
+    }
+    return str;
+};
+// Our version of upath.normalize
+// TODO: this is not equal to path-normalize module - investigate why
+const normalizePathToUnix = (path) => toUnix(sysPath.normalize(toUnix(path)));
+// TODO: refactor
+const normalizeIgnored = (cwd = '') => (path) => {
+    if (typeof path === 'string') {
+        return normalizePathToUnix(sysPath.isAbsolute(path) ? path : sysPath.join(cwd, path));
+    }
+    else {
+        return path;
+    }
+};
+const getAbsolutePath = (path, cwd) => {
+    if (sysPath.isAbsolute(path)) {
+        return path;
+    }
+    return sysPath.join(cwd, path);
+};
+const EMPTY_SET = Object.freeze(new Set());
+/**
+ * Directory entry.
+ */
+class DirEntry {
+    constructor(dir, removeWatcher) {
+        this.path = dir;
+        this._removeWatcher = removeWatcher;
+        this.items = new Set();
+    }
+    add(item) {
+        const { items } = this;
+        if (!items)
+            return;
+        if (item !== ONE_DOT && item !== TWO_DOTS)
+            items.add(item);
+    }
+    async remove(item) {
+        const { items } = this;
+        if (!items)
+            return;
+        items.delete(item);
+        if (items.size > 0)
+            return;
+        const dir = this.path;
+        try {
+            await readdir(dir);
+        }
+        catch (err) {
+            if (this._removeWatcher) {
+                this._removeWatcher(sysPath.dirname(dir), sysPath.basename(dir));
+            }
+        }
+    }
+    has(item) {
+        const { items } = this;
+        if (!items)
+            return;
+        return items.has(item);
+    }
+    getChildren() {
+        const { items } = this;
+        if (!items)
+            return [];
+        return [...items.values()];
+    }
+    dispose() {
+        this.items.clear();
+        this.path = '';
+        this._removeWatcher = EMPTY_FN;
+        this.items = EMPTY_SET;
+        Object.freeze(this);
+    }
+}
+const STAT_METHOD_F = 'stat';
+const STAT_METHOD_L = 'lstat';
+export class WatchHelper {
+    constructor(path, follow, fsw) {
+        this.fsw = fsw;
+        const watchPath = path;
+        this.path = path = path.replace(REPLACER_RE, '');
+        this.watchPath = watchPath;
+        this.fullWatchPath = sysPath.resolve(watchPath);
+        this.dirParts = [];
+        this.dirParts.forEach((parts) => {
+            if (parts.length > 1)
+                parts.pop();
+        });
+        this.followSymlinks = follow;
+        this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;
+    }
+    entryPath(entry) {
+        return sysPath.join(this.watchPath, sysPath.relative(this.watchPath, entry.fullPath));
+    }
+    filterPath(entry) {
+        const { stats } = entry;
+        if (stats && stats.isSymbolicLink())
+            return this.filterDir(entry);
+        const resolvedPath = this.entryPath(entry);
+        // TODO: what if stats is undefined? remove !
+        return this.fsw._isntIgnored(resolvedPath, stats) && this.fsw._hasReadPermissions(stats);
+    }
+    filterDir(entry) {
+        return this.fsw._isntIgnored(this.entryPath(entry), entry.stats);
+    }
+}
+/**
+ * Watches files & directories for changes. Emitted events:
+ * `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `all`, `error`
+ *
+ *     new FSWatcher()
+ *       .add(directories)
+ *       .on('add', path => log('File', path, 'was added'))
+ */
+export class FSWatcher extends EventEmitter {
+    // Not indenting methods for history sake; for now.
+    constructor(_opts = {}) {
+        super();
+        this.closed = false;
+        this._closers = new Map();
+        this._ignoredPaths = new Set();
+        this._throttled = new Map();
+        this._streams = new Set();
+        this._symlinkPaths = new Map();
+        this._watched = new Map();
+        this._pendingWrites = new Map();
+        this._pendingUnlinks = new Map();
+        this._readyCount = 0;
+        this._readyEmitted = false;
+        const awf = _opts.awaitWriteFinish;
+        const DEF_AWF = { stabilityThreshold: 2000, pollInterval: 100 };
+        const opts = {
+            // Defaults
+            persistent: true,
+            ignoreInitial: false,
+            ignorePermissionErrors: false,
+            interval: 100,
+            binaryInterval: 300,
+            followSymlinks: true,
+            usePolling: false,
+            // useAsync: false,
+            atomic: true, // NOTE: overwritten later (depends on usePolling)
+            ..._opts,
+            // Change format
+            ignored: _opts.ignored ? arrify(_opts.ignored) : arrify([]),
+            awaitWriteFinish: awf === true ? DEF_AWF : typeof awf === 'object' ? { ...DEF_AWF, ...awf } : false,
+        };
+        // Always default to polling on IBM i because fs.watch() is not available on IBM i.
+        if (isIBMi)
+            opts.usePolling = true;
+        // Editor atomic write normalization enabled by default with fs.watch
+        if (opts.atomic === undefined)
+            opts.atomic = !opts.usePolling;
+        // opts.atomic = typeof _opts.atomic === 'number' ? _opts.atomic : 100;
+        // Global override. Useful for developers, who need to force polling for all
+        // instances of chokidar, regardless of usage / dependency depth
+        const envPoll = process.env.CHOKIDAR_USEPOLLING;
+        if (envPoll !== undefined) {
+            const envLower = envPoll.toLowerCase();
+            if (envLower === 'false' || envLower === '0')
+                opts.usePolling = false;
+            else if (envLower === 'true' || envLower === '1')
+                opts.usePolling = true;
+            else
+                opts.usePolling = !!envLower;
+        }
+        const envInterval = process.env.CHOKIDAR_INTERVAL;
+        if (envInterval)
+            opts.interval = Number.parseInt(envInterval, 10);
+        // This is done to emit ready only once, but each 'add' will increase that?
+        let readyCalls = 0;
+        this._emitReady = () => {
+            readyCalls++;
+            if (readyCalls >= this._readyCount) {
+                this._emitReady = EMPTY_FN;
+                this._readyEmitted = true;
+                // use process.nextTick to allow time for listener to be bound
+                process.nextTick(() => this.emit(EV.READY));
+            }
+        };
+        this._emitRaw = (...args) => this.emit(EV.RAW, ...args);
+        this._boundRemove = this._remove.bind(this);
+        this.options = opts;
+        this._nodeFsHandler = new NodeFsHandler(this);
+        // You’re frozen when your heart’s not open.
+        Object.freeze(opts);
+    }
+    _addIgnoredPath(matcher) {
+        if (isMatcherObject(matcher)) {
+            // return early if we already have a deeply equal matcher object
+            for (const ignored of this._ignoredPaths) {
+                if (isMatcherObject(ignored) &&
+                    ignored.path === matcher.path &&
+                    ignored.recursive === matcher.recursive) {
+                    return;
+                }
+            }
+        }
+        this._ignoredPaths.add(matcher);
+    }
+    _removeIgnoredPath(matcher) {
+        this._ignoredPaths.delete(matcher);
+        // now find any matcher objects with the matcher as path
+        if (typeof matcher === 'string') {
+            for (const ignored of this._ignoredPaths) {
+                // TODO (43081j): make this more efficient.
+                // probably just make a `this._ignoredDirectories` or some
+                // such thing.
+                if (isMatcherObject(ignored) && ignored.path === matcher) {
+                    this._ignoredPaths.delete(ignored);
+                }
+            }
+        }
+    }
+    // Public methods
+    /**
+     * Adds paths to be watched on an existing FSWatcher instance.
+     * @param paths_ file or file list. Other arguments are unused
+     */
+    add(paths_, _origAdd, _internal) {
+        const { cwd } = this.options;
+        this.closed = false;
+        this._closePromise = undefined;
+        let paths = unifyPaths(paths_);
+        if (cwd) {
+            paths = paths.map((path) => {
+                const absPath = getAbsolutePath(path, cwd);
+                // Check `path` instead of `absPath` because the cwd portion can't be a glob
+                return absPath;
+            });
+        }
+        paths.forEach((path) => {
+            this._removeIgnoredPath(path);
+        });
+        this._userIgnored = undefined;
+        if (!this._readyCount)
+            this._readyCount = 0;
+        this._readyCount += paths.length;
+        Promise.all(paths.map(async (path) => {
+            const res = await this._nodeFsHandler._addToNodeFs(path, !_internal, undefined, 0, _origAdd);
+            if (res)
+                this._emitReady();
+            return res;
+        })).then((results) => {
+            if (this.closed)
+                return;
+            results.forEach((item) => {
+                if (item)
+                    this.add(sysPath.dirname(item), sysPath.basename(_origAdd || item));
+            });
+        });
+        return this;
+    }
+    /**
+     * Close watchers or start ignoring events from specified paths.
+     */
+    unwatch(paths_) {
+        if (this.closed)
+            return this;
+        const paths = unifyPaths(paths_);
+        const { cwd } = this.options;
+        paths.forEach((path) => {
+            // convert to absolute path unless relative path already matches
+            if (!sysPath.isAbsolute(path) && !this._closers.has(path)) {
+                if (cwd)
+                    path = sysPath.join(cwd, path);
+                path = sysPath.resolve(path);
+            }
+            this._closePath(path);
+            this._addIgnoredPath(path);
+            if (this._watched.has(path)) {
+                this._addIgnoredPath({
+                    path,
+                    recursive: true,
+                });
+            }
+            // reset the cached userIgnored anymatch fn
+            // to make ignoredPaths changes effective
+            this._userIgnored = undefined;
+        });
+        return this;
+    }
+    /**
+     * Close watchers and remove all listeners from watched paths.
+     */
+    close() {
+        if (this._closePromise) {
+            return this._closePromise;
+        }
+        this.closed = true;
+        // Memory management.
+        this.removeAllListeners();
+        const closers = [];
+        this._closers.forEach((closerList) => closerList.forEach((closer) => {
+            const promise = closer();
+            if (promise instanceof Promise)
+                closers.push(promise);
+        }));
+        this._streams.forEach((stream) => stream.destroy());
+        this._userIgnored = undefined;
+        this._readyCount = 0;
+        this._readyEmitted = false;
+        this._watched.forEach((dirent) => dirent.dispose());
+        this._closers.clear();
+        this._watched.clear();
+        this._streams.clear();
+        this._symlinkPaths.clear();
+        this._throttled.clear();
+        this._closePromise = closers.length
+            ? Promise.all(closers).then(() => undefined)
+            : Promise.resolve();
+        return this._closePromise;
+    }
+    /**
+     * Expose list of watched paths
+     * @returns for chaining
+     */
+    getWatched() {
+        const watchList = {};
+        this._watched.forEach((entry, dir) => {
+            const key = this.options.cwd ? sysPath.relative(this.options.cwd, dir) : dir;
+            const index = key || ONE_DOT;
+            watchList[index] = entry.getChildren().sort();
+        });
+        return watchList;
+    }
+    emitWithAll(event, args) {
+        this.emit(event, ...args);
+        if (event !== EV.ERROR)
+            this.emit(EV.ALL, event, ...args);
+    }
+    // Common helpers
+    // --------------
+    /**
+     * Normalize and emit events.
+     * Calling _emit DOES NOT MEAN emit() would be called!
+     * @param event Type of event
+     * @param path File or directory path
+     * @param stats arguments to be passed with event
+     * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
+     */
+    async _emit(event, path, stats) {
+        if (this.closed)
+            return;
+        const opts = this.options;
+        if (isWindows)
+            path = sysPath.normalize(path);
+        if (opts.cwd)
+            path = sysPath.relative(opts.cwd, path);
+        const args = [path];
+        if (stats != null)
+            args.push(stats);
+        const awf = opts.awaitWriteFinish;
+        let pw;
+        if (awf && (pw = this._pendingWrites.get(path))) {
+            pw.lastChange = new Date();
+            return this;
+        }
+        if (opts.atomic) {
+            if (event === EV.UNLINK) {
+                this._pendingUnlinks.set(path, [event, ...args]);
+                setTimeout(() => {
+                    this._pendingUnlinks.forEach((entry, path) => {
+                        this.emit(...entry);
+                        this.emit(EV.ALL, ...entry);
+                        this._pendingUnlinks.delete(path);
+                    });
+                }, typeof opts.atomic === 'number' ? opts.atomic : 100);
+                return this;
+            }
+            if (event === EV.ADD && this._pendingUnlinks.has(path)) {
+                event = EV.CHANGE;
+                this._pendingUnlinks.delete(path);
+            }
+        }
+        if (awf && (event === EV.ADD || event === EV.CHANGE) && this._readyEmitted) {
+            const awfEmit = (err, stats) => {
+                if (err) {
+                    event = EV.ERROR;
+                    args[0] = err;
+                    this.emitWithAll(event, args);
+                }
+                else if (stats) {
+                    // if stats doesn't exist the file must have been deleted
+                    if (args.length > 1) {
+                        args[1] = stats;
+                    }
+                    else {
+                        args.push(stats);
+                    }
+                    this.emitWithAll(event, args);
+                }
+            };
+            this._awaitWriteFinish(path, awf.stabilityThreshold, event, awfEmit);
+            return this;
+        }
+        if (event === EV.CHANGE) {
+            const isThrottled = !this._throttle(EV.CHANGE, path, 50);
+            if (isThrottled)
+                return this;
+        }
+        if (opts.alwaysStat &&
+            stats === undefined &&
+            (event === EV.ADD || event === EV.ADD_DIR || event === EV.CHANGE)) {
+            const fullPath = opts.cwd ? sysPath.join(opts.cwd, path) : path;
+            let stats;
+            try {
+                stats = await stat(fullPath);
+            }
+            catch (err) {
+                // do nothing
+            }
+            // Suppress event when fs_stat fails, to avoid sending undefined 'stat'
+            if (!stats || this.closed)
+                return;
+            args.push(stats);
+        }
+        this.emitWithAll(event, args);
+        return this;
+    }
+    /**
+     * Common handler for errors
+     * @returns The error if defined, otherwise the value of the FSWatcher instance's `closed` flag
+     */
+    _handleError(error) {
+        const code = error && error.code;
+        if (error &&
+            code !== 'ENOENT' &&
+            code !== 'ENOTDIR' &&
+            (!this.options.ignorePermissionErrors || (code !== 'EPERM' && code !== 'EACCES'))) {
+            this.emit(EV.ERROR, error);
+        }
+        return error || this.closed;
+    }
+    /**
+     * Helper utility for throttling
+     * @param actionType type being throttled
+     * @param path being acted upon
+     * @param timeout duration of time to suppress duplicate actions
+     * @returns tracking object or false if action should be suppressed
+     */
+    _throttle(actionType, path, timeout) {
+        if (!this._throttled.has(actionType)) {
+            this._throttled.set(actionType, new Map());
+        }
+        const action = this._throttled.get(actionType);
+        if (!action)
+            throw new Error('invalid throttle');
+        const actionPath = action.get(path);
+        if (actionPath) {
+            actionPath.count++;
+            return false;
+        }
+        // eslint-disable-next-line prefer-const
+        let timeoutObject;
+        const clear = () => {
+            const item = action.get(path);
+            const count = item ? item.count : 0;
+            action.delete(path);
+            clearTimeout(timeoutObject);
+            if (item)
+                clearTimeout(item.timeoutObject);
+            return count;
+        };
+        timeoutObject = setTimeout(clear, timeout);
+        const thr = { timeoutObject, clear, count: 0 };
+        action.set(path, thr);
+        return thr;
+    }
+    _incrReadyCount() {
+        return this._readyCount++;
+    }
+    /**
+     * Awaits write operation to finish.
+     * Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback.
+     * @param path being acted upon
+     * @param threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished
+     * @param event
+     * @param awfEmit Callback to be called when ready for event to be emitted.
+     */
+    _awaitWriteFinish(path, threshold, event, awfEmit) {
+        const awf = this.options.awaitWriteFinish;
+        if (typeof awf !== 'object')
+            return;
+        const pollInterval = awf.pollInterval;
+        let timeoutHandler;
+        let fullPath = path;
+        if (this.options.cwd && !sysPath.isAbsolute(path)) {
+            fullPath = sysPath.join(this.options.cwd, path);
+        }
+        const now = new Date();
+        const writes = this._pendingWrites;
+        function awaitWriteFinishFn(prevStat) {
+            statcb(fullPath, (err, curStat) => {
+                if (err || !writes.has(path)) {
+                    if (err && err.code !== 'ENOENT')
+                        awfEmit(err);
+                    return;
+                }
+                const now = Number(new Date());
+                if (prevStat && curStat.size !== prevStat.size) {
+                    writes.get(path).lastChange = now;
+                }
+                const pw = writes.get(path);
+                const df = now - pw.lastChange;
+                if (df >= threshold) {
+                    writes.delete(path);
+                    awfEmit(undefined, curStat);
+                }
+                else {
+                    timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
+                }
+            });
+        }
+        if (!writes.has(path)) {
+            writes.set(path, {
+                lastChange: now,
+                cancelWait: () => {
+                    writes.delete(path);
+                    clearTimeout(timeoutHandler);
+                    return event;
+                },
+            });
+            timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval);
+        }
+    }
+    /**
+     * Determines whether user has asked to ignore this path.
+     */
+    _isIgnored(path, stats) {
+        if (this.options.atomic && DOT_RE.test(path))
+            return true;
+        if (!this._userIgnored) {
+            const { cwd } = this.options;
+            const ign = this.options.ignored;
+            const ignored = (ign || []).map(normalizeIgnored(cwd));
+            const ignoredPaths = [...this._ignoredPaths];
+            const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
+            this._userIgnored = anymatch(list, undefined);
+        }
+        return this._userIgnored(path, stats);
+    }
+    _isntIgnored(path, stat) {
+        return !this._isIgnored(path, stat);
+    }
+    /**
+     * Provides a set of common helpers and properties relating to symlink handling.
+     * @param path file or directory pattern being watched
+     */
+    _getWatchHelpers(path) {
+        return new WatchHelper(path, this.options.followSymlinks, this);
+    }
+    // Directory helpers
+    // -----------------
+    /**
+     * Provides directory tracking objects
+     * @param directory path of the directory
+     */
+    _getWatchedDir(directory) {
+        const dir = sysPath.resolve(directory);
+        if (!this._watched.has(dir))
+            this._watched.set(dir, new DirEntry(dir, this._boundRemove));
+        return this._watched.get(dir);
+    }
+    // File helpers
+    // ------------
+    /**
+     * Check for read permissions: https://stackoverflow.com/a/11781404/1358405
+     */
+    _hasReadPermissions(stats) {
+        if (this.options.ignorePermissionErrors)
+            return true;
+        return Boolean(Number(stats.mode) & 0o400);
+    }
+    /**
+     * Handles emitting unlink events for
+     * files and directories, and via recursion, for
+     * files and directories within directories that are unlinked
+     * @param directory within which the following item is located
+     * @param item      base path of item/directory
+     */
+    _remove(directory, item, isDirectory) {
+        // if what is being deleted is a directory, get that directory's paths
+        // for recursive deleting and cleaning of watched object
+        // if it is not a directory, nestedDirectoryChildren will be empty array
+        const path = sysPath.join(directory, item);
+        const fullPath = sysPath.resolve(path);
+        isDirectory =
+            isDirectory != null ? isDirectory : this._watched.has(path) || this._watched.has(fullPath);
+        // prevent duplicate handling in case of arriving here nearly simultaneously
+        // via multiple paths (such as _handleFile and _handleDir)
+        if (!this._throttle('remove', path, 100))
+            return;
+        // if the only watched file is removed, watch for its return
+        if (!isDirectory && this._watched.size === 1) {
+            this.add(directory, item, true);
+        }
+        // This will create a new entry in the watched object in either case
+        // so we got to do the directory check beforehand
+        const wp = this._getWatchedDir(path);
+        const nestedDirectoryChildren = wp.getChildren();
+        // Recursively remove children directories / files.
+        nestedDirectoryChildren.forEach((nested) => this._remove(path, nested));
+        // Check if item was on the watched list and remove it
+        const parent = this._getWatchedDir(directory);
+        const wasTracked = parent.has(item);
+        parent.remove(item);
+        // Fixes issue #1042 -> Relative paths were detected and added as symlinks
+        // (https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L612),
+        // but never removed from the map in case the path was deleted.
+        // This leads to an incorrect state if the path was recreated:
+        // https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L553
+        if (this._symlinkPaths.has(fullPath)) {
+            this._symlinkPaths.delete(fullPath);
+        }
+        // If we wait for this file to be fully written, cancel the wait.
+        let relPath = path;
+        if (this.options.cwd)
+            relPath = sysPath.relative(this.options.cwd, path);
+        if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
+            const event = this._pendingWrites.get(relPath).cancelWait();
+            if (event === EV.ADD)
+                return;
+        }
+        // The Entry will either be a directory that just got removed
+        // or a bogus entry to a file, in either case we have to remove it
+        this._watched.delete(path);
+        this._watched.delete(fullPath);
+        const eventName = isDirectory ? EV.UNLINK_DIR : EV.UNLINK;
+        if (wasTracked && !this._isIgnored(path))
+            this._emit(eventName, path);
+        // Avoid conflicts if we later create another file with the same name
+        this._closePath(path);
+    }
+    /**
+     * Closes all watchers for a path
+     */
+    _closePath(path) {
+        this._closeFile(path);
+        const dir = sysPath.dirname(path);
+        this._getWatchedDir(dir).remove(sysPath.basename(path));
+    }
+    /**
+     * Closes only file-specific watchers
+     */
+    _closeFile(path) {
+        const closers = this._closers.get(path);
+        if (!closers)
+            return;
+        closers.forEach((closer) => closer());
+        this._closers.delete(path);
+    }
+    _addPathCloser(path, closer) {
+        if (!closer)
+            return;
+        let list = this._closers.get(path);
+        if (!list) {
+            list = [];
+            this._closers.set(path, list);
+        }
+        list.push(closer);
+    }
+    _readdirp(root, opts) {
+        if (this.closed)
+            return;
+        const options = { type: EV.ALL, alwaysStat: true, lstat: true, ...opts, depth: 0 };
+        let stream = readdirp(root, options);
+        this._streams.add(stream);
+        stream.once(STR_CLOSE, () => {
+            stream = undefined;
+        });
+        stream.once(STR_END, () => {
+            if (stream) {
+                this._streams.delete(stream);
+                stream = undefined;
+            }
+        });
+        return stream;
+    }
+}
+/**
+ * Instantiates watcher with paths to be tracked.
+ * @param paths file / directory paths
+ * @param options opts, such as `atomic`, `awaitWriteFinish`, `ignored`, and others
+ * @returns an instance of FSWatcher for chaining.
+ * @example
+ * const watcher = watch('.').on('all', (event, path) => { console.log(event, path); });
+ * watch('.', { atomic: true, awaitWriteFinish: true, ignored: (f, stats) => stats?.isFile() && !f.endsWith('.js') })
+ */
+export function watch(paths, options = {}) {
+    const watcher = new FSWatcher(options);
+    watcher.add(paths);
+    return watcher;
+}
+export default { watch, FSWatcher };

+ 1 - 0
node_modules/chokidar/esm/package.json

@@ -0,0 +1 @@
+{ "type": "module", "sideEffects": false }

+ 90 - 0
node_modules/chokidar/handler.d.ts

@@ -0,0 +1,90 @@
+import type { WatchEventType, Stats, FSWatcher as NativeFsWatcher } from 'fs';
+import type { FSWatcher, WatchHelper, Throttler } from './index.js';
+import type { EntryInfo } from 'readdirp';
+export type Path = string;
+export declare const STR_DATA = "data";
+export declare const STR_END = "end";
+export declare const STR_CLOSE = "close";
+export declare const EMPTY_FN: () => void;
+export declare const IDENTITY_FN: (val: unknown) => unknown;
+export declare const isWindows: boolean;
+export declare const isMacos: boolean;
+export declare const isLinux: boolean;
+export declare const isFreeBSD: boolean;
+export declare const isIBMi: boolean;
+export declare const EVENTS: {
+    readonly ALL: "all";
+    readonly READY: "ready";
+    readonly ADD: "add";
+    readonly CHANGE: "change";
+    readonly ADD_DIR: "addDir";
+    readonly UNLINK: "unlink";
+    readonly UNLINK_DIR: "unlinkDir";
+    readonly RAW: "raw";
+    readonly ERROR: "error";
+};
+export type EventName = (typeof EVENTS)[keyof typeof EVENTS];
+export type FsWatchContainer = {
+    listeners: (path: string) => void | Set<any>;
+    errHandlers: (err: unknown) => void | Set<any>;
+    rawEmitters: (ev: WatchEventType, path: string, opts: unknown) => void | Set<any>;
+    watcher: NativeFsWatcher;
+    watcherUnusable?: boolean;
+};
+export interface WatchHandlers {
+    listener: (path: string) => void;
+    errHandler: (err: unknown) => void;
+    rawEmitter: (ev: WatchEventType, path: string, opts: unknown) => void;
+}
+/**
+ * @mixin
+ */
+export declare class NodeFsHandler {
+    fsw: FSWatcher;
+    _boundHandleError: (error: unknown) => void;
+    constructor(fsW: FSWatcher);
+    /**
+     * Watch file for changes with fs_watchFile or fs_watch.
+     * @param path to file or dir
+     * @param listener on fs change
+     * @returns closer for the watcher instance
+     */
+    _watchWithNodeFs(path: string, listener: (path: string, newStats?: any) => void | Promise<void>): (() => void) | undefined;
+    /**
+     * Watch a file and emit add event if warranted.
+     * @returns closer for the watcher instance
+     */
+    _handleFile(file: Path, stats: Stats, initialAdd: boolean): (() => void) | undefined;
+    /**
+     * Handle symlinks encountered while reading a dir.
+     * @param entry returned by readdirp
+     * @param directory path of dir being read
+     * @param path of this item
+     * @param item basename of this item
+     * @returns true if no more processing is needed for this entry.
+     */
+    _handleSymlink(entry: EntryInfo, directory: string, path: Path, item: string): Promise<boolean | undefined>;
+    _handleRead(directory: string, initialAdd: boolean, wh: WatchHelper, target: Path, dir: Path, depth: number, throttler: Throttler): Promise<unknown> | undefined;
+    /**
+     * Read directory to add / remove files from `@watched` list and re-read it on change.
+     * @param dir fs path
+     * @param stats
+     * @param initialAdd
+     * @param depth relative to user-supplied path
+     * @param target child path targeted for watch
+     * @param wh Common watch helpers for this path
+     * @param realpath
+     * @returns closer for the watcher instance.
+     */
+    _handleDir(dir: string, stats: Stats, initialAdd: boolean, depth: number, target: string, wh: WatchHelper, realpath: string): Promise<(() => void) | undefined>;
+    /**
+     * Handle added file, directory, or glob pattern.
+     * Delegates call to _handleFile / _handleDir after checks.
+     * @param path to file or ir
+     * @param initialAdd was the file added at watch instantiation?
+     * @param priorWh depth relative to user-supplied path
+     * @param depth Child path actually targeted for watch
+     * @param target Child path actually targeted for watch
+     */
+    _addToNodeFs(path: string, initialAdd: boolean, priorWh: WatchHelper | undefined, depth: number, target?: string): Promise<string | false | undefined>;
+}

+ 635 - 0
node_modules/chokidar/handler.js

@@ -0,0 +1,635 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.NodeFsHandler = exports.EVENTS = exports.isIBMi = exports.isFreeBSD = exports.isLinux = exports.isMacos = exports.isWindows = exports.IDENTITY_FN = exports.EMPTY_FN = exports.STR_CLOSE = exports.STR_END = exports.STR_DATA = void 0;
+const fs_1 = require("fs");
+const promises_1 = require("fs/promises");
+const sysPath = require("path");
+const os_1 = require("os");
+exports.STR_DATA = 'data';
+exports.STR_END = 'end';
+exports.STR_CLOSE = 'close';
+const EMPTY_FN = () => { };
+exports.EMPTY_FN = EMPTY_FN;
+const IDENTITY_FN = (val) => val;
+exports.IDENTITY_FN = IDENTITY_FN;
+const pl = process.platform;
+exports.isWindows = pl === 'win32';
+exports.isMacos = pl === 'darwin';
+exports.isLinux = pl === 'linux';
+exports.isFreeBSD = pl === 'freebsd';
+exports.isIBMi = (0, os_1.type)() === 'OS400';
+exports.EVENTS = {
+    ALL: 'all',
+    READY: 'ready',
+    ADD: 'add',
+    CHANGE: 'change',
+    ADD_DIR: 'addDir',
+    UNLINK: 'unlink',
+    UNLINK_DIR: 'unlinkDir',
+    RAW: 'raw',
+    ERROR: 'error',
+};
+const EV = exports.EVENTS;
+const THROTTLE_MODE_WATCH = 'watch';
+const statMethods = { lstat: promises_1.lstat, stat: promises_1.stat };
+const KEY_LISTENERS = 'listeners';
+const KEY_ERR = 'errHandlers';
+const KEY_RAW = 'rawEmitters';
+const HANDLER_KEYS = [KEY_LISTENERS, KEY_ERR, KEY_RAW];
+// prettier-ignore
+const binaryExtensions = new Set([
+    '3dm', '3ds', '3g2', '3gp', '7z', 'a', 'aac', 'adp', 'afdesign', 'afphoto', 'afpub', 'ai',
+    'aif', 'aiff', 'alz', 'ape', 'apk', 'appimage', 'ar', 'arj', 'asf', 'au', 'avi',
+    'bak', 'baml', 'bh', 'bin', 'bk', 'bmp', 'btif', 'bz2', 'bzip2',
+    'cab', 'caf', 'cgm', 'class', 'cmx', 'cpio', 'cr2', 'cur', 'dat', 'dcm', 'deb', 'dex', 'djvu',
+    'dll', 'dmg', 'dng', 'doc', 'docm', 'docx', 'dot', 'dotm', 'dra', 'DS_Store', 'dsk', 'dts',
+    'dtshd', 'dvb', 'dwg', 'dxf',
+    'ecelp4800', 'ecelp7470', 'ecelp9600', 'egg', 'eol', 'eot', 'epub', 'exe',
+    'f4v', 'fbs', 'fh', 'fla', 'flac', 'flatpak', 'fli', 'flv', 'fpx', 'fst', 'fvt',
+    'g3', 'gh', 'gif', 'graffle', 'gz', 'gzip',
+    'h261', 'h263', 'h264', 'icns', 'ico', 'ief', 'img', 'ipa', 'iso',
+    'jar', 'jpeg', 'jpg', 'jpgv', 'jpm', 'jxr', 'key', 'ktx',
+    'lha', 'lib', 'lvp', 'lz', 'lzh', 'lzma', 'lzo',
+    'm3u', 'm4a', 'm4v', 'mar', 'mdi', 'mht', 'mid', 'midi', 'mj2', 'mka', 'mkv', 'mmr', 'mng',
+    'mobi', 'mov', 'movie', 'mp3',
+    'mp4', 'mp4a', 'mpeg', 'mpg', 'mpga', 'mxu',
+    'nef', 'npx', 'numbers', 'nupkg',
+    'o', 'odp', 'ods', 'odt', 'oga', 'ogg', 'ogv', 'otf', 'ott',
+    'pages', 'pbm', 'pcx', 'pdb', 'pdf', 'pea', 'pgm', 'pic', 'png', 'pnm', 'pot', 'potm',
+    'potx', 'ppa', 'ppam',
+    'ppm', 'pps', 'ppsm', 'ppsx', 'ppt', 'pptm', 'pptx', 'psd', 'pya', 'pyc', 'pyo', 'pyv',
+    'qt',
+    'rar', 'ras', 'raw', 'resources', 'rgb', 'rip', 'rlc', 'rmf', 'rmvb', 'rpm', 'rtf', 'rz',
+    's3m', 's7z', 'scpt', 'sgi', 'shar', 'snap', 'sil', 'sketch', 'slk', 'smv', 'snk', 'so',
+    'stl', 'suo', 'sub', 'swf',
+    'tar', 'tbz', 'tbz2', 'tga', 'tgz', 'thmx', 'tif', 'tiff', 'tlz', 'ttc', 'ttf', 'txz',
+    'udf', 'uvh', 'uvi', 'uvm', 'uvp', 'uvs', 'uvu',
+    'viv', 'vob',
+    'war', 'wav', 'wax', 'wbmp', 'wdp', 'weba', 'webm', 'webp', 'whl', 'wim', 'wm', 'wma',
+    'wmv', 'wmx', 'woff', 'woff2', 'wrm', 'wvx',
+    'xbm', 'xif', 'xla', 'xlam', 'xls', 'xlsb', 'xlsm', 'xlsx', 'xlt', 'xltm', 'xltx', 'xm',
+    'xmind', 'xpi', 'xpm', 'xwd', 'xz',
+    'z', 'zip', 'zipx',
+]);
+const isBinaryPath = (filePath) => binaryExtensions.has(sysPath.extname(filePath).slice(1).toLowerCase());
+// TODO: emit errors properly. Example: EMFILE on Macos.
+const foreach = (val, fn) => {
+    if (val instanceof Set) {
+        val.forEach(fn);
+    }
+    else {
+        fn(val);
+    }
+};
+const addAndConvert = (main, prop, item) => {
+    let container = main[prop];
+    if (!(container instanceof Set)) {
+        main[prop] = container = new Set([container]);
+    }
+    container.add(item);
+};
+const clearItem = (cont) => (key) => {
+    const set = cont[key];
+    if (set instanceof Set) {
+        set.clear();
+    }
+    else {
+        delete cont[key];
+    }
+};
+const delFromSet = (main, prop, item) => {
+    const container = main[prop];
+    if (container instanceof Set) {
+        container.delete(item);
+    }
+    else if (container === item) {
+        delete main[prop];
+    }
+};
+const isEmptySet = (val) => (val instanceof Set ? val.size === 0 : !val);
+const FsWatchInstances = new Map();
+/**
+ * Instantiates the fs_watch interface
+ * @param path to be watched
+ * @param options to be passed to fs_watch
+ * @param listener main event handler
+ * @param errHandler emits info about errors
+ * @param emitRaw emits raw event data
+ * @returns {NativeFsWatcher}
+ */
+function createFsWatchInstance(path, options, listener, errHandler, emitRaw) {
+    const handleEvent = (rawEvent, evPath) => {
+        listener(path);
+        emitRaw(rawEvent, evPath, { watchedPath: path });
+        // emit based on events occurring for files from a directory's watcher in
+        // case the file's watcher misses it (and rely on throttling to de-dupe)
+        if (evPath && path !== evPath) {
+            fsWatchBroadcast(sysPath.resolve(path, evPath), KEY_LISTENERS, sysPath.join(path, evPath));
+        }
+    };
+    try {
+        return (0, fs_1.watch)(path, {
+            persistent: options.persistent,
+        }, handleEvent);
+    }
+    catch (error) {
+        errHandler(error);
+        return undefined;
+    }
+}
+/**
+ * Helper for passing fs_watch event data to a collection of listeners
+ * @param fullPath absolute path bound to fs_watch instance
+ */
+const fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
+    const cont = FsWatchInstances.get(fullPath);
+    if (!cont)
+        return;
+    foreach(cont[listenerType], (listener) => {
+        listener(val1, val2, val3);
+    });
+};
+/**
+ * Instantiates the fs_watch interface or binds listeners
+ * to an existing one covering the same file system entry
+ * @param path
+ * @param fullPath absolute path
+ * @param options to be passed to fs_watch
+ * @param handlers container for event listener functions
+ */
+const setFsWatchListener = (path, fullPath, options, handlers) => {
+    const { listener, errHandler, rawEmitter } = handlers;
+    let cont = FsWatchInstances.get(fullPath);
+    let watcher;
+    if (!options.persistent) {
+        watcher = createFsWatchInstance(path, options, listener, errHandler, rawEmitter);
+        if (!watcher)
+            return;
+        return watcher.close.bind(watcher);
+    }
+    if (cont) {
+        addAndConvert(cont, KEY_LISTENERS, listener);
+        addAndConvert(cont, KEY_ERR, errHandler);
+        addAndConvert(cont, KEY_RAW, rawEmitter);
+    }
+    else {
+        watcher = createFsWatchInstance(path, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, // no need to use broadcast here
+        fsWatchBroadcast.bind(null, fullPath, KEY_RAW));
+        if (!watcher)
+            return;
+        watcher.on(EV.ERROR, async (error) => {
+            const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR);
+            if (cont)
+                cont.watcherUnusable = true; // documented since Node 10.4.1
+            // Workaround for https://github.com/joyent/node/issues/4337
+            if (exports.isWindows && error.code === 'EPERM') {
+                try {
+                    const fd = await (0, promises_1.open)(path, 'r');
+                    await fd.close();
+                    broadcastErr(error);
+                }
+                catch (err) {
+                    // do nothing
+                }
+            }
+            else {
+                broadcastErr(error);
+            }
+        });
+        cont = {
+            listeners: listener,
+            errHandlers: errHandler,
+            rawEmitters: rawEmitter,
+            watcher,
+        };
+        FsWatchInstances.set(fullPath, cont);
+    }
+    // const index = cont.listeners.indexOf(listener);
+    // removes this instance's listeners and closes the underlying fs_watch
+    // instance if there are no more listeners left
+    return () => {
+        delFromSet(cont, KEY_LISTENERS, listener);
+        delFromSet(cont, KEY_ERR, errHandler);
+        delFromSet(cont, KEY_RAW, rawEmitter);
+        if (isEmptySet(cont.listeners)) {
+            // Check to protect against issue gh-730.
+            // if (cont.watcherUnusable) {
+            cont.watcher.close();
+            // }
+            FsWatchInstances.delete(fullPath);
+            HANDLER_KEYS.forEach(clearItem(cont));
+            // @ts-ignore
+            cont.watcher = undefined;
+            Object.freeze(cont);
+        }
+    };
+};
+// fs_watchFile helpers
+// object to hold per-process fs_watchFile instances
+// (may be shared across chokidar FSWatcher instances)
+const FsWatchFileInstances = new Map();
+/**
+ * Instantiates the fs_watchFile interface or binds listeners
+ * to an existing one covering the same file system entry
+ * @param path to be watched
+ * @param fullPath absolute path
+ * @param options options to be passed to fs_watchFile
+ * @param handlers container for event listener functions
+ * @returns closer
+ */
+const setFsWatchFileListener = (path, fullPath, options, handlers) => {
+    const { listener, rawEmitter } = handlers;
+    let cont = FsWatchFileInstances.get(fullPath);
+    // let listeners = new Set();
+    // let rawEmitters = new Set();
+    const copts = cont && cont.options;
+    if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {
+        // "Upgrade" the watcher to persistence or a quicker interval.
+        // This creates some unlikely edge case issues if the user mixes
+        // settings in a very weird way, but solving for those cases
+        // doesn't seem worthwhile for the added complexity.
+        // listeners = cont.listeners;
+        // rawEmitters = cont.rawEmitters;
+        (0, fs_1.unwatchFile)(fullPath);
+        cont = undefined;
+    }
+    if (cont) {
+        addAndConvert(cont, KEY_LISTENERS, listener);
+        addAndConvert(cont, KEY_RAW, rawEmitter);
+    }
+    else {
+        // TODO
+        // listeners.add(listener);
+        // rawEmitters.add(rawEmitter);
+        cont = {
+            listeners: listener,
+            rawEmitters: rawEmitter,
+            options,
+            watcher: (0, fs_1.watchFile)(fullPath, options, (curr, prev) => {
+                foreach(cont.rawEmitters, (rawEmitter) => {
+                    rawEmitter(EV.CHANGE, fullPath, { curr, prev });
+                });
+                const currmtime = curr.mtimeMs;
+                if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
+                    foreach(cont.listeners, (listener) => listener(path, curr));
+                }
+            }),
+        };
+        FsWatchFileInstances.set(fullPath, cont);
+    }
+    // const index = cont.listeners.indexOf(listener);
+    // Removes this instance's listeners and closes the underlying fs_watchFile
+    // instance if there are no more listeners left.
+    return () => {
+        delFromSet(cont, KEY_LISTENERS, listener);
+        delFromSet(cont, KEY_RAW, rawEmitter);
+        if (isEmptySet(cont.listeners)) {
+            FsWatchFileInstances.delete(fullPath);
+            (0, fs_1.unwatchFile)(fullPath);
+            cont.options = cont.watcher = undefined;
+            Object.freeze(cont);
+        }
+    };
+};
+/**
+ * @mixin
+ */
+class NodeFsHandler {
+    constructor(fsW) {
+        this.fsw = fsW;
+        this._boundHandleError = (error) => fsW._handleError(error);
+    }
+    /**
+     * Watch file for changes with fs_watchFile or fs_watch.
+     * @param path to file or dir
+     * @param listener on fs change
+     * @returns closer for the watcher instance
+     */
+    _watchWithNodeFs(path, listener) {
+        const opts = this.fsw.options;
+        const directory = sysPath.dirname(path);
+        const basename = sysPath.basename(path);
+        const parent = this.fsw._getWatchedDir(directory);
+        parent.add(basename);
+        const absolutePath = sysPath.resolve(path);
+        const options = {
+            persistent: opts.persistent,
+        };
+        if (!listener)
+            listener = exports.EMPTY_FN;
+        let closer;
+        if (opts.usePolling) {
+            const enableBin = opts.interval !== opts.binaryInterval;
+            options.interval = enableBin && isBinaryPath(basename) ? opts.binaryInterval : opts.interval;
+            closer = setFsWatchFileListener(path, absolutePath, options, {
+                listener,
+                rawEmitter: this.fsw._emitRaw,
+            });
+        }
+        else {
+            closer = setFsWatchListener(path, absolutePath, options, {
+                listener,
+                errHandler: this._boundHandleError,
+                rawEmitter: this.fsw._emitRaw,
+            });
+        }
+        return closer;
+    }
+    /**
+     * Watch a file and emit add event if warranted.
+     * @returns closer for the watcher instance
+     */
+    _handleFile(file, stats, initialAdd) {
+        if (this.fsw.closed) {
+            return;
+        }
+        const dirname = sysPath.dirname(file);
+        const basename = sysPath.basename(file);
+        const parent = this.fsw._getWatchedDir(dirname);
+        // stats is always present
+        let prevStats = stats;
+        // if the file is already being watched, do nothing
+        if (parent.has(basename))
+            return;
+        const listener = async (path, newStats) => {
+            if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
+                return;
+            if (!newStats || newStats.mtimeMs === 0) {
+                try {
+                    const newStats = await (0, promises_1.stat)(file);
+                    if (this.fsw.closed)
+                        return;
+                    // Check that change event was not fired because of changed only accessTime.
+                    const at = newStats.atimeMs;
+                    const mt = newStats.mtimeMs;
+                    if (!at || at <= mt || mt !== prevStats.mtimeMs) {
+                        this.fsw._emit(EV.CHANGE, file, newStats);
+                    }
+                    if ((exports.isMacos || exports.isLinux || exports.isFreeBSD) && prevStats.ino !== newStats.ino) {
+                        this.fsw._closeFile(path);
+                        prevStats = newStats;
+                        const closer = this._watchWithNodeFs(file, listener);
+                        if (closer)
+                            this.fsw._addPathCloser(path, closer);
+                    }
+                    else {
+                        prevStats = newStats;
+                    }
+                }
+                catch (error) {
+                    // Fix issues where mtime is null but file is still present
+                    this.fsw._remove(dirname, basename);
+                }
+                // add is about to be emitted if file not already tracked in parent
+            }
+            else if (parent.has(basename)) {
+                // Check that change event was not fired because of changed only accessTime.
+                const at = newStats.atimeMs;
+                const mt = newStats.mtimeMs;
+                if (!at || at <= mt || mt !== prevStats.mtimeMs) {
+                    this.fsw._emit(EV.CHANGE, file, newStats);
+                }
+                prevStats = newStats;
+            }
+        };
+        // kick off the watcher
+        const closer = this._watchWithNodeFs(file, listener);
+        // emit an add event if we're supposed to
+        if (!(initialAdd && this.fsw.options.ignoreInitial) && this.fsw._isntIgnored(file)) {
+            if (!this.fsw._throttle(EV.ADD, file, 0))
+                return;
+            this.fsw._emit(EV.ADD, file, stats);
+        }
+        return closer;
+    }
+    /**
+     * Handle symlinks encountered while reading a dir.
+     * @param entry returned by readdirp
+     * @param directory path of dir being read
+     * @param path of this item
+     * @param item basename of this item
+     * @returns true if no more processing is needed for this entry.
+     */
+    async _handleSymlink(entry, directory, path, item) {
+        if (this.fsw.closed) {
+            return;
+        }
+        const full = entry.fullPath;
+        const dir = this.fsw._getWatchedDir(directory);
+        if (!this.fsw.options.followSymlinks) {
+            // watch symlink directly (don't follow) and detect changes
+            this.fsw._incrReadyCount();
+            let linkPath;
+            try {
+                linkPath = await (0, promises_1.realpath)(path);
+            }
+            catch (e) {
+                this.fsw._emitReady();
+                return true;
+            }
+            if (this.fsw.closed)
+                return;
+            if (dir.has(item)) {
+                if (this.fsw._symlinkPaths.get(full) !== linkPath) {
+                    this.fsw._symlinkPaths.set(full, linkPath);
+                    this.fsw._emit(EV.CHANGE, path, entry.stats);
+                }
+            }
+            else {
+                dir.add(item);
+                this.fsw._symlinkPaths.set(full, linkPath);
+                this.fsw._emit(EV.ADD, path, entry.stats);
+            }
+            this.fsw._emitReady();
+            return true;
+        }
+        // don't follow the same symlink more than once
+        if (this.fsw._symlinkPaths.has(full)) {
+            return true;
+        }
+        this.fsw._symlinkPaths.set(full, true);
+    }
+    _handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {
+        // Normalize the directory name on Windows
+        directory = sysPath.join(directory, '');
+        throttler = this.fsw._throttle('readdir', directory, 1000);
+        if (!throttler)
+            return;
+        const previous = this.fsw._getWatchedDir(wh.path);
+        const current = new Set();
+        let stream = this.fsw._readdirp(directory, {
+            fileFilter: (entry) => wh.filterPath(entry),
+            directoryFilter: (entry) => wh.filterDir(entry),
+        });
+        if (!stream)
+            return;
+        stream
+            .on(exports.STR_DATA, async (entry) => {
+            if (this.fsw.closed) {
+                stream = undefined;
+                return;
+            }
+            const item = entry.path;
+            let path = sysPath.join(directory, item);
+            current.add(item);
+            if (entry.stats.isSymbolicLink() &&
+                (await this._handleSymlink(entry, directory, path, item))) {
+                return;
+            }
+            if (this.fsw.closed) {
+                stream = undefined;
+                return;
+            }
+            // Files that present in current directory snapshot
+            // but absent in previous are added to watch list and
+            // emit `add` event.
+            if (item === target || (!target && !previous.has(item))) {
+                this.fsw._incrReadyCount();
+                // ensure relativeness of path is preserved in case of watcher reuse
+                path = sysPath.join(dir, sysPath.relative(dir, path));
+                this._addToNodeFs(path, initialAdd, wh, depth + 1);
+            }
+        })
+            .on(EV.ERROR, this._boundHandleError);
+        return new Promise((resolve, reject) => {
+            if (!stream)
+                return reject();
+            stream.once(exports.STR_END, () => {
+                if (this.fsw.closed) {
+                    stream = undefined;
+                    return;
+                }
+                const wasThrottled = throttler ? throttler.clear() : false;
+                resolve(undefined);
+                // Files that absent in current directory snapshot
+                // but present in previous emit `remove` event
+                // and are removed from @watched[directory].
+                previous
+                    .getChildren()
+                    .filter((item) => {
+                    return item !== directory && !current.has(item);
+                })
+                    .forEach((item) => {
+                    this.fsw._remove(directory, item);
+                });
+                stream = undefined;
+                // one more time for any missed in case changes came in extremely quickly
+                if (wasThrottled)
+                    this._handleRead(directory, false, wh, target, dir, depth, throttler);
+            });
+        });
+    }
+    /**
+     * Read directory to add / remove files from `@watched` list and re-read it on change.
+     * @param dir fs path
+     * @param stats
+     * @param initialAdd
+     * @param depth relative to user-supplied path
+     * @param target child path targeted for watch
+     * @param wh Common watch helpers for this path
+     * @param realpath
+     * @returns closer for the watcher instance.
+     */
+    async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath) {
+        const parentDir = this.fsw._getWatchedDir(sysPath.dirname(dir));
+        const tracked = parentDir.has(sysPath.basename(dir));
+        if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {
+            this.fsw._emit(EV.ADD_DIR, dir, stats);
+        }
+        // ensure dir is tracked (harmless if redundant)
+        parentDir.add(sysPath.basename(dir));
+        this.fsw._getWatchedDir(dir);
+        let throttler;
+        let closer;
+        const oDepth = this.fsw.options.depth;
+        if ((oDepth == null || depth <= oDepth) && !this.fsw._symlinkPaths.has(realpath)) {
+            if (!target) {
+                await this._handleRead(dir, initialAdd, wh, target, dir, depth, throttler);
+                if (this.fsw.closed)
+                    return;
+            }
+            closer = this._watchWithNodeFs(dir, (dirPath, stats) => {
+                // if current directory is removed, do nothing
+                if (stats && stats.mtimeMs === 0)
+                    return;
+                this._handleRead(dirPath, false, wh, target, dir, depth, throttler);
+            });
+        }
+        return closer;
+    }
+    /**
+     * Handle added file, directory, or glob pattern.
+     * Delegates call to _handleFile / _handleDir after checks.
+     * @param path to file or ir
+     * @param initialAdd was the file added at watch instantiation?
+     * @param priorWh depth relative to user-supplied path
+     * @param depth Child path actually targeted for watch
+     * @param target Child path actually targeted for watch
+     */
+    async _addToNodeFs(path, initialAdd, priorWh, depth, target) {
+        const ready = this.fsw._emitReady;
+        if (this.fsw._isIgnored(path) || this.fsw.closed) {
+            ready();
+            return false;
+        }
+        const wh = this.fsw._getWatchHelpers(path);
+        if (priorWh) {
+            wh.filterPath = (entry) => priorWh.filterPath(entry);
+            wh.filterDir = (entry) => priorWh.filterDir(entry);
+        }
+        // evaluate what is at the path we're being asked to watch
+        try {
+            const stats = await statMethods[wh.statMethod](wh.watchPath);
+            if (this.fsw.closed)
+                return;
+            if (this.fsw._isIgnored(wh.watchPath, stats)) {
+                ready();
+                return false;
+            }
+            const follow = this.fsw.options.followSymlinks;
+            let closer;
+            if (stats.isDirectory()) {
+                const absPath = sysPath.resolve(path);
+                const targetPath = follow ? await (0, promises_1.realpath)(path) : path;
+                if (this.fsw.closed)
+                    return;
+                closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
+                if (this.fsw.closed)
+                    return;
+                // preserve this symlink's target path
+                if (absPath !== targetPath && targetPath !== undefined) {
+                    this.fsw._symlinkPaths.set(absPath, targetPath);
+                }
+            }
+            else if (stats.isSymbolicLink()) {
+                const targetPath = follow ? await (0, promises_1.realpath)(path) : path;
+                if (this.fsw.closed)
+                    return;
+                const parent = sysPath.dirname(wh.watchPath);
+                this.fsw._getWatchedDir(parent).add(wh.watchPath);
+                this.fsw._emit(EV.ADD, wh.watchPath, stats);
+                closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath);
+                if (this.fsw.closed)
+                    return;
+                // preserve this symlink's target path
+                if (targetPath !== undefined) {
+                    this.fsw._symlinkPaths.set(sysPath.resolve(path), targetPath);
+                }
+            }
+            else {
+                closer = this._handleFile(wh.watchPath, stats, initialAdd);
+            }
+            ready();
+            if (closer)
+                this.fsw._addPathCloser(path, closer);
+            return false;
+        }
+        catch (error) {
+            if (this.fsw._handleError(error)) {
+                ready();
+                return path;
+            }
+        }
+    }
+}
+exports.NodeFsHandler = NodeFsHandler;

+ 215 - 0
node_modules/chokidar/index.d.ts

@@ -0,0 +1,215 @@
+/*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */
+import { Stats } from 'fs';
+import { EventEmitter } from 'events';
+import { ReaddirpStream, ReaddirpOptions, EntryInfo } from 'readdirp';
+import { NodeFsHandler, EventName, Path, EVENTS as EV, WatchHandlers } from './handler.js';
+type AWF = {
+    stabilityThreshold: number;
+    pollInterval: number;
+};
+type BasicOpts = {
+    persistent: boolean;
+    ignoreInitial: boolean;
+    followSymlinks: boolean;
+    cwd?: string;
+    usePolling: boolean;
+    interval: number;
+    binaryInterval: number;
+    alwaysStat?: boolean;
+    depth?: number;
+    ignorePermissionErrors: boolean;
+    atomic: boolean | number;
+};
+export type Throttler = {
+    timeoutObject: NodeJS.Timeout;
+    clear: () => void;
+    count: number;
+};
+export type ChokidarOptions = Partial<BasicOpts & {
+    ignored: Matcher | Matcher[];
+    awaitWriteFinish: boolean | Partial<AWF>;
+}>;
+export type FSWInstanceOptions = BasicOpts & {
+    ignored: Matcher[];
+    awaitWriteFinish: false | AWF;
+};
+export type ThrottleType = 'readdir' | 'watch' | 'add' | 'remove' | 'change';
+export type EmitArgs = [path: Path, stats?: Stats];
+export type EmitErrorArgs = [error: Error, stats?: Stats];
+export type EmitArgsWithName = [event: EventName, ...EmitArgs];
+export type MatchFunction = (val: string, stats?: Stats) => boolean;
+export interface MatcherObject {
+    path: string;
+    recursive?: boolean;
+}
+export type Matcher = string | RegExp | MatchFunction | MatcherObject;
+/**
+ * Directory entry.
+ */
+declare class DirEntry {
+    path: Path;
+    _removeWatcher: (dir: string, base: string) => void;
+    items: Set<Path>;
+    constructor(dir: Path, removeWatcher: (dir: string, base: string) => void);
+    add(item: string): void;
+    remove(item: string): Promise<void>;
+    has(item: string): boolean | undefined;
+    getChildren(): string[];
+    dispose(): void;
+}
+export declare class WatchHelper {
+    fsw: FSWatcher;
+    path: string;
+    watchPath: string;
+    fullWatchPath: string;
+    dirParts: string[][];
+    followSymlinks: boolean;
+    statMethod: 'stat' | 'lstat';
+    constructor(path: string, follow: boolean, fsw: FSWatcher);
+    entryPath(entry: EntryInfo): Path;
+    filterPath(entry: EntryInfo): boolean;
+    filterDir(entry: EntryInfo): boolean;
+}
+export interface FSWatcherKnownEventMap {
+    [EV.READY]: [];
+    [EV.RAW]: Parameters<WatchHandlers['rawEmitter']>;
+    [EV.ERROR]: Parameters<WatchHandlers['errHandler']>;
+    [EV.ALL]: [event: EventName, ...EmitArgs];
+}
+export type FSWatcherEventMap = FSWatcherKnownEventMap & {
+    [k in Exclude<EventName, keyof FSWatcherKnownEventMap>]: EmitArgs;
+};
+/**
+ * Watches files & directories for changes. Emitted events:
+ * `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `all`, `error`
+ *
+ *     new FSWatcher()
+ *       .add(directories)
+ *       .on('add', path => log('File', path, 'was added'))
+ */
+export declare class FSWatcher extends EventEmitter<FSWatcherEventMap> {
+    closed: boolean;
+    options: FSWInstanceOptions;
+    _closers: Map<string, Array<any>>;
+    _ignoredPaths: Set<Matcher>;
+    _throttled: Map<ThrottleType, Map<any, any>>;
+    _streams: Set<ReaddirpStream>;
+    _symlinkPaths: Map<Path, string | boolean>;
+    _watched: Map<string, DirEntry>;
+    _pendingWrites: Map<string, any>;
+    _pendingUnlinks: Map<string, EmitArgsWithName>;
+    _readyCount: number;
+    _emitReady: () => void;
+    _closePromise?: Promise<void>;
+    _userIgnored?: MatchFunction;
+    _readyEmitted: boolean;
+    _emitRaw: WatchHandlers['rawEmitter'];
+    _boundRemove: (dir: string, item: string) => void;
+    _nodeFsHandler: NodeFsHandler;
+    constructor(_opts?: ChokidarOptions);
+    _addIgnoredPath(matcher: Matcher): void;
+    _removeIgnoredPath(matcher: Matcher): void;
+    /**
+     * Adds paths to be watched on an existing FSWatcher instance.
+     * @param paths_ file or file list. Other arguments are unused
+     */
+    add(paths_: Path | Path[], _origAdd?: string, _internal?: boolean): FSWatcher;
+    /**
+     * Close watchers or start ignoring events from specified paths.
+     */
+    unwatch(paths_: Path | Path[]): FSWatcher;
+    /**
+     * Close watchers and remove all listeners from watched paths.
+     */
+    close(): Promise<void>;
+    /**
+     * Expose list of watched paths
+     * @returns for chaining
+     */
+    getWatched(): Record<string, string[]>;
+    emitWithAll(event: EventName, args: EmitArgs): void;
+    /**
+     * Normalize and emit events.
+     * Calling _emit DOES NOT MEAN emit() would be called!
+     * @param event Type of event
+     * @param path File or directory path
+     * @param stats arguments to be passed with event
+     * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
+     */
+    _emit(event: EventName, path: Path, stats?: Stats): Promise<this | undefined>;
+    /**
+     * Common handler for errors
+     * @returns The error if defined, otherwise the value of the FSWatcher instance's `closed` flag
+     */
+    _handleError(error: Error): Error | boolean;
+    /**
+     * Helper utility for throttling
+     * @param actionType type being throttled
+     * @param path being acted upon
+     * @param timeout duration of time to suppress duplicate actions
+     * @returns tracking object or false if action should be suppressed
+     */
+    _throttle(actionType: ThrottleType, path: Path, timeout: number): Throttler | false;
+    _incrReadyCount(): number;
+    /**
+     * Awaits write operation to finish.
+     * Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback.
+     * @param path being acted upon
+     * @param threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished
+     * @param event
+     * @param awfEmit Callback to be called when ready for event to be emitted.
+     */
+    _awaitWriteFinish(path: Path, threshold: number, event: EventName, awfEmit: (err?: Error, stat?: Stats) => void): void;
+    /**
+     * Determines whether user has asked to ignore this path.
+     */
+    _isIgnored(path: Path, stats?: Stats): boolean;
+    _isntIgnored(path: Path, stat?: Stats): boolean;
+    /**
+     * Provides a set of common helpers and properties relating to symlink handling.
+     * @param path file or directory pattern being watched
+     */
+    _getWatchHelpers(path: Path): WatchHelper;
+    /**
+     * Provides directory tracking objects
+     * @param directory path of the directory
+     */
+    _getWatchedDir(directory: string): DirEntry;
+    /**
+     * Check for read permissions: https://stackoverflow.com/a/11781404/1358405
+     */
+    _hasReadPermissions(stats: Stats): boolean;
+    /**
+     * Handles emitting unlink events for
+     * files and directories, and via recursion, for
+     * files and directories within directories that are unlinked
+     * @param directory within which the following item is located
+     * @param item      base path of item/directory
+     */
+    _remove(directory: string, item: string, isDirectory?: boolean): void;
+    /**
+     * Closes all watchers for a path
+     */
+    _closePath(path: Path): void;
+    /**
+     * Closes only file-specific watchers
+     */
+    _closeFile(path: Path): void;
+    _addPathCloser(path: Path, closer: () => void): void;
+    _readdirp(root: Path, opts?: Partial<ReaddirpOptions>): ReaddirpStream | undefined;
+}
+/**
+ * Instantiates watcher with paths to be tracked.
+ * @param paths file / directory paths
+ * @param options opts, such as `atomic`, `awaitWriteFinish`, `ignored`, and others
+ * @returns an instance of FSWatcher for chaining.
+ * @example
+ * const watcher = watch('.').on('all', (event, path) => { console.log(event, path); });
+ * watch('.', { atomic: true, awaitWriteFinish: true, ignored: (f, stats) => stats?.isFile() && !f.endsWith('.js') })
+ */
+export declare function watch(paths: string | string[], options?: ChokidarOptions): FSWatcher;
+declare const _default: {
+    watch: typeof watch;
+    FSWatcher: typeof FSWatcher;
+};
+export default _default;

+ 804 - 0
node_modules/chokidar/index.js

@@ -0,0 +1,804 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.FSWatcher = exports.WatchHelper = void 0;
+exports.watch = watch;
+/*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */
+const fs_1 = require("fs");
+const promises_1 = require("fs/promises");
+const events_1 = require("events");
+const sysPath = require("path");
+const readdirp_1 = require("readdirp");
+const handler_js_1 = require("./handler.js");
+const SLASH = '/';
+const SLASH_SLASH = '//';
+const ONE_DOT = '.';
+const TWO_DOTS = '..';
+const STRING_TYPE = 'string';
+const BACK_SLASH_RE = /\\/g;
+const DOUBLE_SLASH_RE = /\/\//;
+const DOT_RE = /\..*\.(sw[px])$|~$|\.subl.*\.tmp/;
+const REPLACER_RE = /^\.[/\\]/;
+function arrify(item) {
+    return Array.isArray(item) ? item : [item];
+}
+const isMatcherObject = (matcher) => typeof matcher === 'object' && matcher !== null && !(matcher instanceof RegExp);
+function createPattern(matcher) {
+    if (typeof matcher === 'function')
+        return matcher;
+    if (typeof matcher === 'string')
+        return (string) => matcher === string;
+    if (matcher instanceof RegExp)
+        return (string) => matcher.test(string);
+    if (typeof matcher === 'object' && matcher !== null) {
+        return (string) => {
+            if (matcher.path === string)
+                return true;
+            if (matcher.recursive) {
+                const relative = sysPath.relative(matcher.path, string);
+                if (!relative) {
+                    return false;
+                }
+                return !relative.startsWith('..') && !sysPath.isAbsolute(relative);
+            }
+            return false;
+        };
+    }
+    return () => false;
+}
+function normalizePath(path) {
+    if (typeof path !== 'string')
+        throw new Error('string expected');
+    path = sysPath.normalize(path);
+    path = path.replace(/\\/g, '/');
+    let prepend = false;
+    if (path.startsWith('//'))
+        prepend = true;
+    const DOUBLE_SLASH_RE = /\/\//;
+    while (path.match(DOUBLE_SLASH_RE))
+        path = path.replace(DOUBLE_SLASH_RE, '/');
+    if (prepend)
+        path = '/' + path;
+    return path;
+}
+function matchPatterns(patterns, testString, stats) {
+    const path = normalizePath(testString);
+    for (let index = 0; index < patterns.length; index++) {
+        const pattern = patterns[index];
+        if (pattern(path, stats)) {
+            return true;
+        }
+    }
+    return false;
+}
+function anymatch(matchers, testString) {
+    if (matchers == null) {
+        throw new TypeError('anymatch: specify first argument');
+    }
+    // Early cache for matchers.
+    const matchersArray = arrify(matchers);
+    const patterns = matchersArray.map((matcher) => createPattern(matcher));
+    if (testString == null) {
+        return (testString, stats) => {
+            return matchPatterns(patterns, testString, stats);
+        };
+    }
+    return matchPatterns(patterns, testString);
+}
+const unifyPaths = (paths_) => {
+    const paths = arrify(paths_).flat();
+    if (!paths.every((p) => typeof p === STRING_TYPE)) {
+        throw new TypeError(`Non-string provided as watch path: ${paths}`);
+    }
+    return paths.map(normalizePathToUnix);
+};
+// If SLASH_SLASH occurs at the beginning of path, it is not replaced
+//     because "//StoragePC/DrivePool/Movies" is a valid network path
+const toUnix = (string) => {
+    let str = string.replace(BACK_SLASH_RE, SLASH);
+    let prepend = false;
+    if (str.startsWith(SLASH_SLASH)) {
+        prepend = true;
+    }
+    while (str.match(DOUBLE_SLASH_RE)) {
+        str = str.replace(DOUBLE_SLASH_RE, SLASH);
+    }
+    if (prepend) {
+        str = SLASH + str;
+    }
+    return str;
+};
+// Our version of upath.normalize
+// TODO: this is not equal to path-normalize module - investigate why
+const normalizePathToUnix = (path) => toUnix(sysPath.normalize(toUnix(path)));
+// TODO: refactor
+const normalizeIgnored = (cwd = '') => (path) => {
+    if (typeof path === 'string') {
+        return normalizePathToUnix(sysPath.isAbsolute(path) ? path : sysPath.join(cwd, path));
+    }
+    else {
+        return path;
+    }
+};
+const getAbsolutePath = (path, cwd) => {
+    if (sysPath.isAbsolute(path)) {
+        return path;
+    }
+    return sysPath.join(cwd, path);
+};
+const EMPTY_SET = Object.freeze(new Set());
+/**
+ * Directory entry.
+ */
+class DirEntry {
+    constructor(dir, removeWatcher) {
+        this.path = dir;
+        this._removeWatcher = removeWatcher;
+        this.items = new Set();
+    }
+    add(item) {
+        const { items } = this;
+        if (!items)
+            return;
+        if (item !== ONE_DOT && item !== TWO_DOTS)
+            items.add(item);
+    }
+    async remove(item) {
+        const { items } = this;
+        if (!items)
+            return;
+        items.delete(item);
+        if (items.size > 0)
+            return;
+        const dir = this.path;
+        try {
+            await (0, promises_1.readdir)(dir);
+        }
+        catch (err) {
+            if (this._removeWatcher) {
+                this._removeWatcher(sysPath.dirname(dir), sysPath.basename(dir));
+            }
+        }
+    }
+    has(item) {
+        const { items } = this;
+        if (!items)
+            return;
+        return items.has(item);
+    }
+    getChildren() {
+        const { items } = this;
+        if (!items)
+            return [];
+        return [...items.values()];
+    }
+    dispose() {
+        this.items.clear();
+        this.path = '';
+        this._removeWatcher = handler_js_1.EMPTY_FN;
+        this.items = EMPTY_SET;
+        Object.freeze(this);
+    }
+}
+const STAT_METHOD_F = 'stat';
+const STAT_METHOD_L = 'lstat';
+class WatchHelper {
+    constructor(path, follow, fsw) {
+        this.fsw = fsw;
+        const watchPath = path;
+        this.path = path = path.replace(REPLACER_RE, '');
+        this.watchPath = watchPath;
+        this.fullWatchPath = sysPath.resolve(watchPath);
+        this.dirParts = [];
+        this.dirParts.forEach((parts) => {
+            if (parts.length > 1)
+                parts.pop();
+        });
+        this.followSymlinks = follow;
+        this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;
+    }
+    entryPath(entry) {
+        return sysPath.join(this.watchPath, sysPath.relative(this.watchPath, entry.fullPath));
+    }
+    filterPath(entry) {
+        const { stats } = entry;
+        if (stats && stats.isSymbolicLink())
+            return this.filterDir(entry);
+        const resolvedPath = this.entryPath(entry);
+        // TODO: what if stats is undefined? remove !
+        return this.fsw._isntIgnored(resolvedPath, stats) && this.fsw._hasReadPermissions(stats);
+    }
+    filterDir(entry) {
+        return this.fsw._isntIgnored(this.entryPath(entry), entry.stats);
+    }
+}
+exports.WatchHelper = WatchHelper;
+/**
+ * Watches files & directories for changes. Emitted events:
+ * `add`, `addDir`, `change`, `unlink`, `unlinkDir`, `all`, `error`
+ *
+ *     new FSWatcher()
+ *       .add(directories)
+ *       .on('add', path => log('File', path, 'was added'))
+ */
+class FSWatcher extends events_1.EventEmitter {
+    // Not indenting methods for history sake; for now.
+    constructor(_opts = {}) {
+        super();
+        this.closed = false;
+        this._closers = new Map();
+        this._ignoredPaths = new Set();
+        this._throttled = new Map();
+        this._streams = new Set();
+        this._symlinkPaths = new Map();
+        this._watched = new Map();
+        this._pendingWrites = new Map();
+        this._pendingUnlinks = new Map();
+        this._readyCount = 0;
+        this._readyEmitted = false;
+        const awf = _opts.awaitWriteFinish;
+        const DEF_AWF = { stabilityThreshold: 2000, pollInterval: 100 };
+        const opts = {
+            // Defaults
+            persistent: true,
+            ignoreInitial: false,
+            ignorePermissionErrors: false,
+            interval: 100,
+            binaryInterval: 300,
+            followSymlinks: true,
+            usePolling: false,
+            // useAsync: false,
+            atomic: true, // NOTE: overwritten later (depends on usePolling)
+            ..._opts,
+            // Change format
+            ignored: _opts.ignored ? arrify(_opts.ignored) : arrify([]),
+            awaitWriteFinish: awf === true ? DEF_AWF : typeof awf === 'object' ? { ...DEF_AWF, ...awf } : false,
+        };
+        // Always default to polling on IBM i because fs.watch() is not available on IBM i.
+        if (handler_js_1.isIBMi)
+            opts.usePolling = true;
+        // Editor atomic write normalization enabled by default with fs.watch
+        if (opts.atomic === undefined)
+            opts.atomic = !opts.usePolling;
+        // opts.atomic = typeof _opts.atomic === 'number' ? _opts.atomic : 100;
+        // Global override. Useful for developers, who need to force polling for all
+        // instances of chokidar, regardless of usage / dependency depth
+        const envPoll = process.env.CHOKIDAR_USEPOLLING;
+        if (envPoll !== undefined) {
+            const envLower = envPoll.toLowerCase();
+            if (envLower === 'false' || envLower === '0')
+                opts.usePolling = false;
+            else if (envLower === 'true' || envLower === '1')
+                opts.usePolling = true;
+            else
+                opts.usePolling = !!envLower;
+        }
+        const envInterval = process.env.CHOKIDAR_INTERVAL;
+        if (envInterval)
+            opts.interval = Number.parseInt(envInterval, 10);
+        // This is done to emit ready only once, but each 'add' will increase that?
+        let readyCalls = 0;
+        this._emitReady = () => {
+            readyCalls++;
+            if (readyCalls >= this._readyCount) {
+                this._emitReady = handler_js_1.EMPTY_FN;
+                this._readyEmitted = true;
+                // use process.nextTick to allow time for listener to be bound
+                process.nextTick(() => this.emit(handler_js_1.EVENTS.READY));
+            }
+        };
+        this._emitRaw = (...args) => this.emit(handler_js_1.EVENTS.RAW, ...args);
+        this._boundRemove = this._remove.bind(this);
+        this.options = opts;
+        this._nodeFsHandler = new handler_js_1.NodeFsHandler(this);
+        // You’re frozen when your heart’s not open.
+        Object.freeze(opts);
+    }
+    _addIgnoredPath(matcher) {
+        if (isMatcherObject(matcher)) {
+            // return early if we already have a deeply equal matcher object
+            for (const ignored of this._ignoredPaths) {
+                if (isMatcherObject(ignored) &&
+                    ignored.path === matcher.path &&
+                    ignored.recursive === matcher.recursive) {
+                    return;
+                }
+            }
+        }
+        this._ignoredPaths.add(matcher);
+    }
+    _removeIgnoredPath(matcher) {
+        this._ignoredPaths.delete(matcher);
+        // now find any matcher objects with the matcher as path
+        if (typeof matcher === 'string') {
+            for (const ignored of this._ignoredPaths) {
+                // TODO (43081j): make this more efficient.
+                // probably just make a `this._ignoredDirectories` or some
+                // such thing.
+                if (isMatcherObject(ignored) && ignored.path === matcher) {
+                    this._ignoredPaths.delete(ignored);
+                }
+            }
+        }
+    }
+    // Public methods
+    /**
+     * Adds paths to be watched on an existing FSWatcher instance.
+     * @param paths_ file or file list. Other arguments are unused
+     */
+    add(paths_, _origAdd, _internal) {
+        const { cwd } = this.options;
+        this.closed = false;
+        this._closePromise = undefined;
+        let paths = unifyPaths(paths_);
+        if (cwd) {
+            paths = paths.map((path) => {
+                const absPath = getAbsolutePath(path, cwd);
+                // Check `path` instead of `absPath` because the cwd portion can't be a glob
+                return absPath;
+            });
+        }
+        paths.forEach((path) => {
+            this._removeIgnoredPath(path);
+        });
+        this._userIgnored = undefined;
+        if (!this._readyCount)
+            this._readyCount = 0;
+        this._readyCount += paths.length;
+        Promise.all(paths.map(async (path) => {
+            const res = await this._nodeFsHandler._addToNodeFs(path, !_internal, undefined, 0, _origAdd);
+            if (res)
+                this._emitReady();
+            return res;
+        })).then((results) => {
+            if (this.closed)
+                return;
+            results.forEach((item) => {
+                if (item)
+                    this.add(sysPath.dirname(item), sysPath.basename(_origAdd || item));
+            });
+        });
+        return this;
+    }
+    /**
+     * Close watchers or start ignoring events from specified paths.
+     */
+    unwatch(paths_) {
+        if (this.closed)
+            return this;
+        const paths = unifyPaths(paths_);
+        const { cwd } = this.options;
+        paths.forEach((path) => {
+            // convert to absolute path unless relative path already matches
+            if (!sysPath.isAbsolute(path) && !this._closers.has(path)) {
+                if (cwd)
+                    path = sysPath.join(cwd, path);
+                path = sysPath.resolve(path);
+            }
+            this._closePath(path);
+            this._addIgnoredPath(path);
+            if (this._watched.has(path)) {
+                this._addIgnoredPath({
+                    path,
+                    recursive: true,
+                });
+            }
+            // reset the cached userIgnored anymatch fn
+            // to make ignoredPaths changes effective
+            this._userIgnored = undefined;
+        });
+        return this;
+    }
+    /**
+     * Close watchers and remove all listeners from watched paths.
+     */
+    close() {
+        if (this._closePromise) {
+            return this._closePromise;
+        }
+        this.closed = true;
+        // Memory management.
+        this.removeAllListeners();
+        const closers = [];
+        this._closers.forEach((closerList) => closerList.forEach((closer) => {
+            const promise = closer();
+            if (promise instanceof Promise)
+                closers.push(promise);
+        }));
+        this._streams.forEach((stream) => stream.destroy());
+        this._userIgnored = undefined;
+        this._readyCount = 0;
+        this._readyEmitted = false;
+        this._watched.forEach((dirent) => dirent.dispose());
+        this._closers.clear();
+        this._watched.clear();
+        this._streams.clear();
+        this._symlinkPaths.clear();
+        this._throttled.clear();
+        this._closePromise = closers.length
+            ? Promise.all(closers).then(() => undefined)
+            : Promise.resolve();
+        return this._closePromise;
+    }
+    /**
+     * Expose list of watched paths
+     * @returns for chaining
+     */
+    getWatched() {
+        const watchList = {};
+        this._watched.forEach((entry, dir) => {
+            const key = this.options.cwd ? sysPath.relative(this.options.cwd, dir) : dir;
+            const index = key || ONE_DOT;
+            watchList[index] = entry.getChildren().sort();
+        });
+        return watchList;
+    }
+    emitWithAll(event, args) {
+        this.emit(event, ...args);
+        if (event !== handler_js_1.EVENTS.ERROR)
+            this.emit(handler_js_1.EVENTS.ALL, event, ...args);
+    }
+    // Common helpers
+    // --------------
+    /**
+     * Normalize and emit events.
+     * Calling _emit DOES NOT MEAN emit() would be called!
+     * @param event Type of event
+     * @param path File or directory path
+     * @param stats arguments to be passed with event
+     * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
+     */
+    async _emit(event, path, stats) {
+        if (this.closed)
+            return;
+        const opts = this.options;
+        if (handler_js_1.isWindows)
+            path = sysPath.normalize(path);
+        if (opts.cwd)
+            path = sysPath.relative(opts.cwd, path);
+        const args = [path];
+        if (stats != null)
+            args.push(stats);
+        const awf = opts.awaitWriteFinish;
+        let pw;
+        if (awf && (pw = this._pendingWrites.get(path))) {
+            pw.lastChange = new Date();
+            return this;
+        }
+        if (opts.atomic) {
+            if (event === handler_js_1.EVENTS.UNLINK) {
+                this._pendingUnlinks.set(path, [event, ...args]);
+                setTimeout(() => {
+                    this._pendingUnlinks.forEach((entry, path) => {
+                        this.emit(...entry);
+                        this.emit(handler_js_1.EVENTS.ALL, ...entry);
+                        this._pendingUnlinks.delete(path);
+                    });
+                }, typeof opts.atomic === 'number' ? opts.atomic : 100);
+                return this;
+            }
+            if (event === handler_js_1.EVENTS.ADD && this._pendingUnlinks.has(path)) {
+                event = handler_js_1.EVENTS.CHANGE;
+                this._pendingUnlinks.delete(path);
+            }
+        }
+        if (awf && (event === handler_js_1.EVENTS.ADD || event === handler_js_1.EVENTS.CHANGE) && this._readyEmitted) {
+            const awfEmit = (err, stats) => {
+                if (err) {
+                    event = handler_js_1.EVENTS.ERROR;
+                    args[0] = err;
+                    this.emitWithAll(event, args);
+                }
+                else if (stats) {
+                    // if stats doesn't exist the file must have been deleted
+                    if (args.length > 1) {
+                        args[1] = stats;
+                    }
+                    else {
+                        args.push(stats);
+                    }
+                    this.emitWithAll(event, args);
+                }
+            };
+            this._awaitWriteFinish(path, awf.stabilityThreshold, event, awfEmit);
+            return this;
+        }
+        if (event === handler_js_1.EVENTS.CHANGE) {
+            const isThrottled = !this._throttle(handler_js_1.EVENTS.CHANGE, path, 50);
+            if (isThrottled)
+                return this;
+        }
+        if (opts.alwaysStat &&
+            stats === undefined &&
+            (event === handler_js_1.EVENTS.ADD || event === handler_js_1.EVENTS.ADD_DIR || event === handler_js_1.EVENTS.CHANGE)) {
+            const fullPath = opts.cwd ? sysPath.join(opts.cwd, path) : path;
+            let stats;
+            try {
+                stats = await (0, promises_1.stat)(fullPath);
+            }
+            catch (err) {
+                // do nothing
+            }
+            // Suppress event when fs_stat fails, to avoid sending undefined 'stat'
+            if (!stats || this.closed)
+                return;
+            args.push(stats);
+        }
+        this.emitWithAll(event, args);
+        return this;
+    }
+    /**
+     * Common handler for errors
+     * @returns The error if defined, otherwise the value of the FSWatcher instance's `closed` flag
+     */
+    _handleError(error) {
+        const code = error && error.code;
+        if (error &&
+            code !== 'ENOENT' &&
+            code !== 'ENOTDIR' &&
+            (!this.options.ignorePermissionErrors || (code !== 'EPERM' && code !== 'EACCES'))) {
+            this.emit(handler_js_1.EVENTS.ERROR, error);
+        }
+        return error || this.closed;
+    }
+    /**
+     * Helper utility for throttling
+     * @param actionType type being throttled
+     * @param path being acted upon
+     * @param timeout duration of time to suppress duplicate actions
+     * @returns tracking object or false if action should be suppressed
+     */
+    _throttle(actionType, path, timeout) {
+        if (!this._throttled.has(actionType)) {
+            this._throttled.set(actionType, new Map());
+        }
+        const action = this._throttled.get(actionType);
+        if (!action)
+            throw new Error('invalid throttle');
+        const actionPath = action.get(path);
+        if (actionPath) {
+            actionPath.count++;
+            return false;
+        }
+        // eslint-disable-next-line prefer-const
+        let timeoutObject;
+        const clear = () => {
+            const item = action.get(path);
+            const count = item ? item.count : 0;
+            action.delete(path);
+            clearTimeout(timeoutObject);
+            if (item)
+                clearTimeout(item.timeoutObject);
+            return count;
+        };
+        timeoutObject = setTimeout(clear, timeout);
+        const thr = { timeoutObject, clear, count: 0 };
+        action.set(path, thr);
+        return thr;
+    }
+    _incrReadyCount() {
+        return this._readyCount++;
+    }
+    /**
+     * Awaits write operation to finish.
+     * Polls a newly created file for size variations. When files size does not change for 'threshold' milliseconds calls callback.
+     * @param path being acted upon
+     * @param threshold Time in milliseconds a file size must be fixed before acknowledging write OP is finished
+     * @param event
+     * @param awfEmit Callback to be called when ready for event to be emitted.
+     */
+    _awaitWriteFinish(path, threshold, event, awfEmit) {
+        const awf = this.options.awaitWriteFinish;
+        if (typeof awf !== 'object')
+            return;
+        const pollInterval = awf.pollInterval;
+        let timeoutHandler;
+        let fullPath = path;
+        if (this.options.cwd && !sysPath.isAbsolute(path)) {
+            fullPath = sysPath.join(this.options.cwd, path);
+        }
+        const now = new Date();
+        const writes = this._pendingWrites;
+        function awaitWriteFinishFn(prevStat) {
+            (0, fs_1.stat)(fullPath, (err, curStat) => {
+                if (err || !writes.has(path)) {
+                    if (err && err.code !== 'ENOENT')
+                        awfEmit(err);
+                    return;
+                }
+                const now = Number(new Date());
+                if (prevStat && curStat.size !== prevStat.size) {
+                    writes.get(path).lastChange = now;
+                }
+                const pw = writes.get(path);
+                const df = now - pw.lastChange;
+                if (df >= threshold) {
+                    writes.delete(path);
+                    awfEmit(undefined, curStat);
+                }
+                else {
+                    timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
+                }
+            });
+        }
+        if (!writes.has(path)) {
+            writes.set(path, {
+                lastChange: now,
+                cancelWait: () => {
+                    writes.delete(path);
+                    clearTimeout(timeoutHandler);
+                    return event;
+                },
+            });
+            timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval);
+        }
+    }
+    /**
+     * Determines whether user has asked to ignore this path.
+     */
+    _isIgnored(path, stats) {
+        if (this.options.atomic && DOT_RE.test(path))
+            return true;
+        if (!this._userIgnored) {
+            const { cwd } = this.options;
+            const ign = this.options.ignored;
+            const ignored = (ign || []).map(normalizeIgnored(cwd));
+            const ignoredPaths = [...this._ignoredPaths];
+            const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
+            this._userIgnored = anymatch(list, undefined);
+        }
+        return this._userIgnored(path, stats);
+    }
+    _isntIgnored(path, stat) {
+        return !this._isIgnored(path, stat);
+    }
+    /**
+     * Provides a set of common helpers and properties relating to symlink handling.
+     * @param path file or directory pattern being watched
+     */
+    _getWatchHelpers(path) {
+        return new WatchHelper(path, this.options.followSymlinks, this);
+    }
+    // Directory helpers
+    // -----------------
+    /**
+     * Provides directory tracking objects
+     * @param directory path of the directory
+     */
+    _getWatchedDir(directory) {
+        const dir = sysPath.resolve(directory);
+        if (!this._watched.has(dir))
+            this._watched.set(dir, new DirEntry(dir, this._boundRemove));
+        return this._watched.get(dir);
+    }
+    // File helpers
+    // ------------
+    /**
+     * Check for read permissions: https://stackoverflow.com/a/11781404/1358405
+     */
+    _hasReadPermissions(stats) {
+        if (this.options.ignorePermissionErrors)
+            return true;
+        return Boolean(Number(stats.mode) & 0o400);
+    }
+    /**
+     * Handles emitting unlink events for
+     * files and directories, and via recursion, for
+     * files and directories within directories that are unlinked
+     * @param directory within which the following item is located
+     * @param item      base path of item/directory
+     */
+    _remove(directory, item, isDirectory) {
+        // if what is being deleted is a directory, get that directory's paths
+        // for recursive deleting and cleaning of watched object
+        // if it is not a directory, nestedDirectoryChildren will be empty array
+        const path = sysPath.join(directory, item);
+        const fullPath = sysPath.resolve(path);
+        isDirectory =
+            isDirectory != null ? isDirectory : this._watched.has(path) || this._watched.has(fullPath);
+        // prevent duplicate handling in case of arriving here nearly simultaneously
+        // via multiple paths (such as _handleFile and _handleDir)
+        if (!this._throttle('remove', path, 100))
+            return;
+        // if the only watched file is removed, watch for its return
+        if (!isDirectory && this._watched.size === 1) {
+            this.add(directory, item, true);
+        }
+        // This will create a new entry in the watched object in either case
+        // so we got to do the directory check beforehand
+        const wp = this._getWatchedDir(path);
+        const nestedDirectoryChildren = wp.getChildren();
+        // Recursively remove children directories / files.
+        nestedDirectoryChildren.forEach((nested) => this._remove(path, nested));
+        // Check if item was on the watched list and remove it
+        const parent = this._getWatchedDir(directory);
+        const wasTracked = parent.has(item);
+        parent.remove(item);
+        // Fixes issue #1042 -> Relative paths were detected and added as symlinks
+        // (https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L612),
+        // but never removed from the map in case the path was deleted.
+        // This leads to an incorrect state if the path was recreated:
+        // https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L553
+        if (this._symlinkPaths.has(fullPath)) {
+            this._symlinkPaths.delete(fullPath);
+        }
+        // If we wait for this file to be fully written, cancel the wait.
+        let relPath = path;
+        if (this.options.cwd)
+            relPath = sysPath.relative(this.options.cwd, path);
+        if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
+            const event = this._pendingWrites.get(relPath).cancelWait();
+            if (event === handler_js_1.EVENTS.ADD)
+                return;
+        }
+        // The Entry will either be a directory that just got removed
+        // or a bogus entry to a file, in either case we have to remove it
+        this._watched.delete(path);
+        this._watched.delete(fullPath);
+        const eventName = isDirectory ? handler_js_1.EVENTS.UNLINK_DIR : handler_js_1.EVENTS.UNLINK;
+        if (wasTracked && !this._isIgnored(path))
+            this._emit(eventName, path);
+        // Avoid conflicts if we later create another file with the same name
+        this._closePath(path);
+    }
+    /**
+     * Closes all watchers for a path
+     */
+    _closePath(path) {
+        this._closeFile(path);
+        const dir = sysPath.dirname(path);
+        this._getWatchedDir(dir).remove(sysPath.basename(path));
+    }
+    /**
+     * Closes only file-specific watchers
+     */
+    _closeFile(path) {
+        const closers = this._closers.get(path);
+        if (!closers)
+            return;
+        closers.forEach((closer) => closer());
+        this._closers.delete(path);
+    }
+    _addPathCloser(path, closer) {
+        if (!closer)
+            return;
+        let list = this._closers.get(path);
+        if (!list) {
+            list = [];
+            this._closers.set(path, list);
+        }
+        list.push(closer);
+    }
+    _readdirp(root, opts) {
+        if (this.closed)
+            return;
+        const options = { type: handler_js_1.EVENTS.ALL, alwaysStat: true, lstat: true, ...opts, depth: 0 };
+        let stream = (0, readdirp_1.readdirp)(root, options);
+        this._streams.add(stream);
+        stream.once(handler_js_1.STR_CLOSE, () => {
+            stream = undefined;
+        });
+        stream.once(handler_js_1.STR_END, () => {
+            if (stream) {
+                this._streams.delete(stream);
+                stream = undefined;
+            }
+        });
+        return stream;
+    }
+}
+exports.FSWatcher = FSWatcher;
+/**
+ * Instantiates watcher with paths to be tracked.
+ * @param paths file / directory paths
+ * @param options opts, such as `atomic`, `awaitWriteFinish`, `ignored`, and others
+ * @returns an instance of FSWatcher for chaining.
+ * @example
+ * const watcher = watch('.').on('all', (event, path) => { console.log(event, path); });
+ * watch('.', { atomic: true, awaitWriteFinish: true, ignored: (f, stats) => stats?.isFile() && !f.endsWith('.js') })
+ */
+function watch(paths, options = {}) {
+    const watcher = new FSWatcher(options);
+    watcher.add(paths);
+    return watcher;
+}
+exports.default = { watch, FSWatcher };

+ 69 - 0
node_modules/chokidar/package.json

@@ -0,0 +1,69 @@
+{
+  "name": "chokidar",
+  "description": "Minimal and efficient cross-platform file watching library",
+  "version": "4.0.3",
+  "homepage": "https://github.com/paulmillr/chokidar",
+  "author": "Paul Miller (https://paulmillr.com)",
+  "files": [
+    "index.js",
+    "index.d.ts",
+    "handler.js",
+    "handler.d.ts",
+    "esm"
+  ],
+  "main": "./index.js",
+  "module": "./esm/index.js",
+  "types": "./index.d.ts",
+  "exports": {
+    ".": {
+      "import": "./esm/index.js",
+      "require": "./index.js"
+    },
+    "./handler.js": {
+      "import": "./esm/handler.js",
+      "require": "./handler.js"
+    }
+  },
+  "dependencies": {
+    "readdirp": "^4.0.1"
+  },
+  "devDependencies": {
+    "@paulmillr/jsbt": "0.2.1",
+    "@types/node": "20.14.8",
+    "chai": "4.3.4",
+    "prettier": "3.1.1",
+    "rimraf": "5.0.5",
+    "sinon": "12.0.1",
+    "sinon-chai": "3.7.0",
+    "typescript": "5.5.2",
+    "upath": "2.0.1"
+  },
+  "sideEffects": false,
+  "engines": {
+    "node": ">= 14.16.0"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/paulmillr/chokidar.git"
+  },
+  "bugs": {
+    "url": "https://github.com/paulmillr/chokidar/issues"
+  },
+  "license": "MIT",
+  "scripts": {
+    "build": "tsc && tsc -p tsconfig.esm.json",
+    "lint": "prettier --check src",
+    "format": "prettier --write src",
+    "test": "node --test"
+  },
+  "keywords": [
+    "fs",
+    "watch",
+    "watchFile",
+    "watcher",
+    "watching",
+    "file",
+    "fsevents"
+  ],
+  "funding": "https://paulmillr.com/funding/"
+}

+ 7 - 0
node_modules/detect-libc/.npmignore

@@ -0,0 +1,7 @@
+.nyc_output
+.travis.yml
+coverage
+test.js
+node_modules
+/.circleci
+/tests/integration

+ 201 - 0
node_modules/detect-libc/LICENSE

@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 78 - 0
node_modules/detect-libc/README.md

@@ -0,0 +1,78 @@
+# detect-libc
+
+Node.js module to detect the C standard library (libc) implementation
+family and version in use on a given Linux system.
+
+Provides a value suitable for use with the `LIBC` option of
+[prebuild](https://www.npmjs.com/package/prebuild),
+[prebuild-ci](https://www.npmjs.com/package/prebuild-ci) and
+[prebuild-install](https://www.npmjs.com/package/prebuild-install),
+therefore allowing build and provision of pre-compiled binaries
+for musl-based Linux e.g. Alpine as well as glibc-based.
+
+Currently supports libc detection of `glibc` and `musl`.
+
+## Install
+
+```sh
+npm install detect-libc
+```
+
+## Usage
+
+### API
+
+```js
+const { GLIBC, MUSL, family, version, isNonGlibcLinux } = require('detect-libc');
+```
+
+* `GLIBC` is a String containing the value "glibc" for comparison with `family`.
+* `MUSL` is a String containing the value "musl" for comparison with `family`.
+* `family` is a String representing the system libc family.
+* `version` is a String representing the system libc version number.
+* `isNonGlibcLinux` is a Boolean representing whether the system is a non-glibc Linux, e.g. Alpine.
+
+### detect-libc command line tool
+
+When run on a Linux system with a non-glibc libc,
+the child command will be run with the `LIBC` environment variable
+set to the relevant value.
+
+On all other platforms will run the child command as-is.
+
+The command line feature requires `spawnSync` provided by Node v0.12+.
+
+```sh
+detect-libc child-command
+```
+
+## Integrating with prebuild
+
+```json
+  "scripts": {
+    "install": "detect-libc prebuild-install || node-gyp rebuild",
+    "test": "mocha && detect-libc prebuild-ci"
+  },
+  "dependencies": {
+    "detect-libc": "^1.0.2",
+    "prebuild-install": "^2.2.0"
+  },
+  "devDependencies": {
+    "prebuild": "^6.2.1",
+    "prebuild-ci": "^2.2.3"
+  }
+```
+
+## Licence
+
+Copyright 2017 Lovell Fuller
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0.html)
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.

+ 18 - 0
node_modules/detect-libc/bin/detect-libc.js

@@ -0,0 +1,18 @@
+#!/usr/bin/env node
+
+'use strict';
+
+var spawnSync = require('child_process').spawnSync;
+var libc = require('../');
+
+var spawnOptions = {
+  env: process.env,
+  shell: true,
+  stdio: 'inherit'
+};
+
+if (libc.isNonGlibcLinux) {
+  spawnOptions.env.LIBC = process.env.LIBC || libc.family;
+}
+
+process.exit(spawnSync(process.argv[2], process.argv.slice(3), spawnOptions).status);

+ 92 - 0
node_modules/detect-libc/lib/detect-libc.js

@@ -0,0 +1,92 @@
+'use strict';
+
+var platform = require('os').platform();
+var spawnSync = require('child_process').spawnSync;
+var readdirSync = require('fs').readdirSync;
+
+var GLIBC = 'glibc';
+var MUSL = 'musl';
+
+var spawnOptions = {
+  encoding: 'utf8',
+  env: process.env
+};
+
+if (!spawnSync) {
+  spawnSync = function () {
+    return { status: 126, stdout: '', stderr: '' };
+  };
+}
+
+function contains (needle) {
+  return function (haystack) {
+    return haystack.indexOf(needle) !== -1;
+  };
+}
+
+function versionFromMuslLdd (out) {
+  return out.split(/[\r\n]+/)[1].trim().split(/\s/)[1];
+}
+
+function safeReaddirSync (path) {
+  try {
+    return readdirSync(path);
+  } catch (e) {}
+  return [];
+}
+
+var family = '';
+var version = '';
+var method = '';
+
+if (platform === 'linux') {
+  // Try getconf
+  var glibc = spawnSync('getconf', ['GNU_LIBC_VERSION'], spawnOptions);
+  if (glibc.status === 0) {
+    family = GLIBC;
+    version = glibc.stdout.trim().split(' ')[1];
+    method = 'getconf';
+  } else {
+    // Try ldd
+    var ldd = spawnSync('ldd', ['--version'], spawnOptions);
+    if (ldd.status === 0 && ldd.stdout.indexOf(MUSL) !== -1) {
+      family = MUSL;
+      version = versionFromMuslLdd(ldd.stdout);
+      method = 'ldd';
+    } else if (ldd.status === 1 && ldd.stderr.indexOf(MUSL) !== -1) {
+      family = MUSL;
+      version = versionFromMuslLdd(ldd.stderr);
+      method = 'ldd';
+    } else {
+      // Try filesystem (family only)
+      var lib = safeReaddirSync('/lib');
+      if (lib.some(contains('-linux-gnu'))) {
+        family = GLIBC;
+        method = 'filesystem';
+      } else if (lib.some(contains('libc.musl-'))) {
+        family = MUSL;
+        method = 'filesystem';
+      } else if (lib.some(contains('ld-musl-'))) {
+        family = MUSL;
+        method = 'filesystem';
+      } else {
+        var usrSbin = safeReaddirSync('/usr/sbin');
+        if (usrSbin.some(contains('glibc'))) {
+          family = GLIBC;
+          method = 'filesystem';
+        }
+      }
+    }
+  }
+}
+
+var isNonGlibcLinux = (family !== '' && family !== GLIBC);
+
+module.exports = {
+  GLIBC: GLIBC,
+  MUSL: MUSL,
+  family: family,
+  version: version,
+  method: method,
+  isNonGlibcLinux: isNonGlibcLinux
+};

+ 35 - 0
node_modules/detect-libc/package.json

@@ -0,0 +1,35 @@
+{
+  "name": "detect-libc",
+  "version": "1.0.3",
+  "description": "Node.js module to detect the C standard library (libc) implementation family and version",
+  "main": "lib/detect-libc.js",
+  "bin": {
+    "detect-libc": "./bin/detect-libc.js"
+  },
+  "scripts": {
+    "test": "semistandard && nyc --reporter=lcov ava"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/lovell/detect-libc"
+  },
+  "keywords": [
+    "libc",
+    "glibc",
+    "musl"
+  ],
+  "author": "Lovell Fuller <npm@lovell.info>",
+  "contributors": [
+    "Niklas Salmoukas <niklas@salmoukas.com>"
+  ],
+  "license": "Apache-2.0",
+  "devDependencies": {
+    "ava": "^0.23.0",
+    "nyc": "^11.3.0",
+    "proxyquire": "^1.8.0",
+    "semistandard": "^11.0.0"
+  },
+  "engines": {
+    "node": ">=0.10"
+  }
+}

+ 21 - 0
node_modules/fill-range/LICENSE

@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-present, Jon Schlinkert.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 237 - 0
node_modules/fill-range/README.md

@@ -0,0 +1,237 @@
+# fill-range [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=W8YFZ425KND68) [![NPM version](https://img.shields.io/npm/v/fill-range.svg?style=flat)](https://www.npmjs.com/package/fill-range) [![NPM monthly downloads](https://img.shields.io/npm/dm/fill-range.svg?style=flat)](https://npmjs.org/package/fill-range) [![NPM total downloads](https://img.shields.io/npm/dt/fill-range.svg?style=flat)](https://npmjs.org/package/fill-range) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/fill-range.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/fill-range)
+
+> Fill in a range of numbers or letters, optionally passing an increment or `step` to use, or create a regex-compatible range with `options.toRegex`
+
+Please consider following this project's author, [Jon Schlinkert](https://github.com/jonschlinkert), and consider starring the project to show your :heart: and support.
+
+## Install
+
+Install with [npm](https://www.npmjs.com/):
+
+```sh
+$ npm install --save fill-range
+```
+
+## Usage
+
+Expands numbers and letters, optionally using a `step` as the last argument. _(Numbers may be defined as JavaScript numbers or strings)_.
+
+```js
+const fill = require('fill-range');
+// fill(from, to[, step, options]);
+
+console.log(fill('1', '10')); //=> ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']
+console.log(fill('1', '10', { toRegex: true })); //=> [1-9]|10
+```
+
+**Params**
+
+* `from`: **{String|Number}** the number or letter to start with
+* `to`: **{String|Number}** the number or letter to end with
+* `step`: **{String|Number|Object|Function}** Optionally pass a [step](#optionsstep) to use.
+* `options`: **{Object|Function}**: See all available [options](#options)
+
+## Examples
+
+By default, an array of values is returned.
+
+**Alphabetical ranges**
+
+```js
+console.log(fill('a', 'e')); //=> ['a', 'b', 'c', 'd', 'e']
+console.log(fill('A', 'E')); //=> [ 'A', 'B', 'C', 'D', 'E' ]
+```
+
+**Numerical ranges**
+
+Numbers can be defined as actual numbers or strings.
+
+```js
+console.log(fill(1, 5));     //=> [ 1, 2, 3, 4, 5 ]
+console.log(fill('1', '5')); //=> [ 1, 2, 3, 4, 5 ]
+```
+
+**Negative ranges**
+
+Numbers can be defined as actual numbers or strings.
+
+```js
+console.log(fill('-5', '-1')); //=> [ '-5', '-4', '-3', '-2', '-1' ]
+console.log(fill('-5', '5')); //=> [ '-5', '-4', '-3', '-2', '-1', '0', '1', '2', '3', '4', '5' ]
+```
+
+**Steps (increments)**
+
+```js
+// numerical ranges with increments
+console.log(fill('0', '25', 4)); //=> [ '0', '4', '8', '12', '16', '20', '24' ]
+console.log(fill('0', '25', 5)); //=> [ '0', '5', '10', '15', '20', '25' ]
+console.log(fill('0', '25', 6)); //=> [ '0', '6', '12', '18', '24' ]
+
+// alphabetical ranges with increments
+console.log(fill('a', 'z', 4)); //=> [ 'a', 'e', 'i', 'm', 'q', 'u', 'y' ]
+console.log(fill('a', 'z', 5)); //=> [ 'a', 'f', 'k', 'p', 'u', 'z' ]
+console.log(fill('a', 'z', 6)); //=> [ 'a', 'g', 'm', 's', 'y' ]
+```
+
+## Options
+
+### options.step
+
+**Type**: `number` (formatted as a string or number)
+
+**Default**: `undefined`
+
+**Description**: The increment to use for the range. Can be used with letters or numbers.
+
+**Example(s)**
+
+```js
+// numbers
+console.log(fill('1', '10', 2)); //=> [ '1', '3', '5', '7', '9' ]
+console.log(fill('1', '10', 3)); //=> [ '1', '4', '7', '10' ]
+console.log(fill('1', '10', 4)); //=> [ '1', '5', '9' ]
+
+// letters
+console.log(fill('a', 'z', 5)); //=> [ 'a', 'f', 'k', 'p', 'u', 'z' ]
+console.log(fill('a', 'z', 7)); //=> [ 'a', 'h', 'o', 'v' ]
+console.log(fill('a', 'z', 9)); //=> [ 'a', 'j', 's' ]
+```
+
+### options.strictRanges
+
+**Type**: `boolean`
+
+**Default**: `false`
+
+**Description**: By default, `null` is returned when an invalid range is passed. Enable this option to throw a `RangeError` on invalid ranges.
+
+**Example(s)**
+
+The following are all invalid:
+
+```js
+fill('1.1', '2');   // decimals not supported in ranges
+fill('a', '2');     // incompatible range values
+fill(1, 10, 'foo'); // invalid "step" argument
+```
+
+### options.stringify
+
+**Type**: `boolean`
+
+**Default**: `undefined`
+
+**Description**: Cast all returned values to strings. By default, integers are returned as numbers.
+
+**Example(s)**
+
+```js
+console.log(fill(1, 5));                    //=> [ 1, 2, 3, 4, 5 ]
+console.log(fill(1, 5, { stringify: true })); //=> [ '1', '2', '3', '4', '5' ]
+```
+
+### options.toRegex
+
+**Type**: `boolean`
+
+**Default**: `undefined`
+
+**Description**: Create a regex-compatible source string, instead of expanding values to an array.
+
+**Example(s)**
+
+```js
+// alphabetical range
+console.log(fill('a', 'e', { toRegex: true })); //=> '[a-e]'
+// alphabetical with step
+console.log(fill('a', 'z', 3, { toRegex: true })); //=> 'a|d|g|j|m|p|s|v|y'
+// numerical range
+console.log(fill('1', '100', { toRegex: true })); //=> '[1-9]|[1-9][0-9]|100'
+// numerical range with zero padding
+console.log(fill('000001', '100000', { toRegex: true }));
+//=> '0{5}[1-9]|0{4}[1-9][0-9]|0{3}[1-9][0-9]{2}|0{2}[1-9][0-9]{3}|0[1-9][0-9]{4}|100000'
+```
+
+### options.transform
+
+**Type**: `function`
+
+**Default**: `undefined`
+
+**Description**: Customize each value in the returned array (or [string](#optionstoRegex)). _(you can also pass this function as the last argument to `fill()`)_.
+
+**Example(s)**
+
+```js
+// add zero padding
+console.log(fill(1, 5, value => String(value).padStart(4, '0')));
+//=> ['0001', '0002', '0003', '0004', '0005']
+```
+
+## About
+
+<details>
+<summary><strong>Contributing</strong></summary>
+
+Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
+
+</details>
+
+<details>
+<summary><strong>Running Tests</strong></summary>
+
+Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
+
+```sh
+$ npm install && npm test
+```
+
+</details>
+
+<details>
+<summary><strong>Building docs</strong></summary>
+
+_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
+
+To generate the readme, run the following command:
+
+```sh
+$ npm install -g verbose/verb#dev verb-generate-readme && verb
+```
+
+</details>
+
+### Contributors
+
+| **Commits** | **Contributor** |  
+| --- | --- |  
+| 116 | [jonschlinkert](https://github.com/jonschlinkert) |  
+| 4   | [paulmillr](https://github.com/paulmillr) |  
+| 2   | [realityking](https://github.com/realityking) |  
+| 2   | [bluelovers](https://github.com/bluelovers) |  
+| 1   | [edorivai](https://github.com/edorivai) |  
+| 1   | [wtgtybhertgeghgtwtg](https://github.com/wtgtybhertgeghgtwtg) |  
+
+### Author
+
+**Jon Schlinkert**
+
+* [GitHub Profile](https://github.com/jonschlinkert)
+* [Twitter Profile](https://twitter.com/jonschlinkert)
+* [LinkedIn Profile](https://linkedin.com/in/jonschlinkert)
+
+Please consider supporting me on Patreon, or [start your own Patreon page](https://patreon.com/invite/bxpbvm)!
+
+<a href="https://www.patreon.com/jonschlinkert">
+<img src="https://c5.patreon.com/external/logo/become_a_patron_button@2x.png" height="50">
+</a>
+
+### License
+
+Copyright © 2019, [Jon Schlinkert](https://github.com/jonschlinkert).
+Released under the [MIT License](LICENSE).
+
+***
+
+_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.8.0, on April 08, 2019._

+ 248 - 0
node_modules/fill-range/index.js

@@ -0,0 +1,248 @@
+/*!
+ * fill-range <https://github.com/jonschlinkert/fill-range>
+ *
+ * Copyright (c) 2014-present, Jon Schlinkert.
+ * Licensed under the MIT License.
+ */
+
+'use strict';
+
+const util = require('util');
+const toRegexRange = require('to-regex-range');
+
+const isObject = val => val !== null && typeof val === 'object' && !Array.isArray(val);
+
+const transform = toNumber => {
+  return value => toNumber === true ? Number(value) : String(value);
+};
+
+const isValidValue = value => {
+  return typeof value === 'number' || (typeof value === 'string' && value !== '');
+};
+
+const isNumber = num => Number.isInteger(+num);
+
+const zeros = input => {
+  let value = `${input}`;
+  let index = -1;
+  if (value[0] === '-') value = value.slice(1);
+  if (value === '0') return false;
+  while (value[++index] === '0');
+  return index > 0;
+};
+
+const stringify = (start, end, options) => {
+  if (typeof start === 'string' || typeof end === 'string') {
+    return true;
+  }
+  return options.stringify === true;
+};
+
+const pad = (input, maxLength, toNumber) => {
+  if (maxLength > 0) {
+    let dash = input[0] === '-' ? '-' : '';
+    if (dash) input = input.slice(1);
+    input = (dash + input.padStart(dash ? maxLength - 1 : maxLength, '0'));
+  }
+  if (toNumber === false) {
+    return String(input);
+  }
+  return input;
+};
+
+const toMaxLen = (input, maxLength) => {
+  let negative = input[0] === '-' ? '-' : '';
+  if (negative) {
+    input = input.slice(1);
+    maxLength--;
+  }
+  while (input.length < maxLength) input = '0' + input;
+  return negative ? ('-' + input) : input;
+};
+
+const toSequence = (parts, options, maxLen) => {
+  parts.negatives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
+  parts.positives.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
+
+  let prefix = options.capture ? '' : '?:';
+  let positives = '';
+  let negatives = '';
+  let result;
+
+  if (parts.positives.length) {
+    positives = parts.positives.map(v => toMaxLen(String(v), maxLen)).join('|');
+  }
+
+  if (parts.negatives.length) {
+    negatives = `-(${prefix}${parts.negatives.map(v => toMaxLen(String(v), maxLen)).join('|')})`;
+  }
+
+  if (positives && negatives) {
+    result = `${positives}|${negatives}`;
+  } else {
+    result = positives || negatives;
+  }
+
+  if (options.wrap) {
+    return `(${prefix}${result})`;
+  }
+
+  return result;
+};
+
+const toRange = (a, b, isNumbers, options) => {
+  if (isNumbers) {
+    return toRegexRange(a, b, { wrap: false, ...options });
+  }
+
+  let start = String.fromCharCode(a);
+  if (a === b) return start;
+
+  let stop = String.fromCharCode(b);
+  return `[${start}-${stop}]`;
+};
+
+const toRegex = (start, end, options) => {
+  if (Array.isArray(start)) {
+    let wrap = options.wrap === true;
+    let prefix = options.capture ? '' : '?:';
+    return wrap ? `(${prefix}${start.join('|')})` : start.join('|');
+  }
+  return toRegexRange(start, end, options);
+};
+
+const rangeError = (...args) => {
+  return new RangeError('Invalid range arguments: ' + util.inspect(...args));
+};
+
+const invalidRange = (start, end, options) => {
+  if (options.strictRanges === true) throw rangeError([start, end]);
+  return [];
+};
+
+const invalidStep = (step, options) => {
+  if (options.strictRanges === true) {
+    throw new TypeError(`Expected step "${step}" to be a number`);
+  }
+  return [];
+};
+
+const fillNumbers = (start, end, step = 1, options = {}) => {
+  let a = Number(start);
+  let b = Number(end);
+
+  if (!Number.isInteger(a) || !Number.isInteger(b)) {
+    if (options.strictRanges === true) throw rangeError([start, end]);
+    return [];
+  }
+
+  // fix negative zero
+  if (a === 0) a = 0;
+  if (b === 0) b = 0;
+
+  let descending = a > b;
+  let startString = String(start);
+  let endString = String(end);
+  let stepString = String(step);
+  step = Math.max(Math.abs(step), 1);
+
+  let padded = zeros(startString) || zeros(endString) || zeros(stepString);
+  let maxLen = padded ? Math.max(startString.length, endString.length, stepString.length) : 0;
+  let toNumber = padded === false && stringify(start, end, options) === false;
+  let format = options.transform || transform(toNumber);
+
+  if (options.toRegex && step === 1) {
+    return toRange(toMaxLen(start, maxLen), toMaxLen(end, maxLen), true, options);
+  }
+
+  let parts = { negatives: [], positives: [] };
+  let push = num => parts[num < 0 ? 'negatives' : 'positives'].push(Math.abs(num));
+  let range = [];
+  let index = 0;
+
+  while (descending ? a >= b : a <= b) {
+    if (options.toRegex === true && step > 1) {
+      push(a);
+    } else {
+      range.push(pad(format(a, index), maxLen, toNumber));
+    }
+    a = descending ? a - step : a + step;
+    index++;
+  }
+
+  if (options.toRegex === true) {
+    return step > 1
+      ? toSequence(parts, options, maxLen)
+      : toRegex(range, null, { wrap: false, ...options });
+  }
+
+  return range;
+};
+
+const fillLetters = (start, end, step = 1, options = {}) => {
+  if ((!isNumber(start) && start.length > 1) || (!isNumber(end) && end.length > 1)) {
+    return invalidRange(start, end, options);
+  }
+
+  let format = options.transform || (val => String.fromCharCode(val));
+  let a = `${start}`.charCodeAt(0);
+  let b = `${end}`.charCodeAt(0);
+
+  let descending = a > b;
+  let min = Math.min(a, b);
+  let max = Math.max(a, b);
+
+  if (options.toRegex && step === 1) {
+    return toRange(min, max, false, options);
+  }
+
+  let range = [];
+  let index = 0;
+
+  while (descending ? a >= b : a <= b) {
+    range.push(format(a, index));
+    a = descending ? a - step : a + step;
+    index++;
+  }
+
+  if (options.toRegex === true) {
+    return toRegex(range, null, { wrap: false, options });
+  }
+
+  return range;
+};
+
+const fill = (start, end, step, options = {}) => {
+  if (end == null && isValidValue(start)) {
+    return [start];
+  }
+
+  if (!isValidValue(start) || !isValidValue(end)) {
+    return invalidRange(start, end, options);
+  }
+
+  if (typeof step === 'function') {
+    return fill(start, end, 1, { transform: step });
+  }
+
+  if (isObject(step)) {
+    return fill(start, end, 0, step);
+  }
+
+  let opts = { ...options };
+  if (opts.capture === true) opts.wrap = true;
+  step = step || opts.step || 1;
+
+  if (!isNumber(step)) {
+    if (step != null && !isObject(step)) return invalidStep(step, opts);
+    return fill(start, end, 1, step);
+  }
+
+  if (isNumber(start) && isNumber(end)) {
+    return fillNumbers(start, end, step, opts);
+  }
+
+  return fillLetters(start, end, Math.max(Math.abs(step), 1), opts);
+};
+
+module.exports = fill;

+ 74 - 0
node_modules/fill-range/package.json

@@ -0,0 +1,74 @@
+{
+  "name": "fill-range",
+  "description": "Fill in a range of numbers or letters, optionally passing an increment or `step` to use, or create a regex-compatible range with `options.toRegex`",
+  "version": "7.1.1",
+  "homepage": "https://github.com/jonschlinkert/fill-range",
+  "author": "Jon Schlinkert (https://github.com/jonschlinkert)",
+  "contributors": [
+    "Edo Rivai (edo.rivai.nl)",
+    "Jon Schlinkert (http://twitter.com/jonschlinkert)",
+    "Paul Miller (paulmillr.com)",
+    "Rouven Weßling (www.rouvenwessling.de)",
+    "(https://github.com/wtgtybhertgeghgtwtg)"
+  ],
+  "repository": "jonschlinkert/fill-range",
+  "bugs": {
+    "url": "https://github.com/jonschlinkert/fill-range/issues"
+  },
+  "license": "MIT",
+  "files": [
+    "index.js"
+  ],
+  "main": "index.js",
+  "engines": {
+    "node": ">=8"
+  },
+  "scripts": {
+    "lint": "eslint --cache --cache-location node_modules/.cache/.eslintcache --report-unused-disable-directives --ignore-path .gitignore .",
+    "mocha": "mocha --reporter dot",
+    "test": "npm run lint && npm run mocha",
+    "test:ci": "npm run test:cover",
+    "test:cover": "nyc npm run mocha"
+  },
+  "dependencies": {
+    "to-regex-range": "^5.0.1"
+  },
+  "devDependencies": {
+    "gulp-format-md": "^2.0.0",
+    "mocha": "^6.1.1",
+    "nyc": "^15.1.0"
+  },
+  "keywords": [
+    "alpha",
+    "alphabetical",
+    "array",
+    "bash",
+    "brace",
+    "expand",
+    "expansion",
+    "fill",
+    "glob",
+    "match",
+    "matches",
+    "matching",
+    "number",
+    "numerical",
+    "range",
+    "ranges",
+    "regex",
+    "sh"
+  ],
+  "verb": {
+    "toc": false,
+    "layout": "default",
+    "tasks": [
+      "readme"
+    ],
+    "plugins": [
+      "gulp-format-md"
+    ],
+    "lint": {
+      "reflinks": true
+    }
+  }
+}

+ 21 - 0
node_modules/immutable/LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2014-present, Lee Byron and other contributors.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 731 - 0
node_modules/immutable/README.md

@@ -0,0 +1,731 @@
+# Immutable collections for JavaScript
+
+[![Build Status](https://github.com/immutable-js/immutable-js/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/immutable-js/immutable-js/actions/workflows/ci.yml?query=branch%3Amain) [Chat on slack](https://immutable-js.slack.com)
+
+[Read the docs](https://immutable-js.com/docs/) and eat your vegetables.
+
+Docs are automatically generated from [README.md][] and [immutable.d.ts][].
+Please contribute! Also, don't miss the [wiki][] which contains articles on
+additional specific topics. Can't find something? Open an [issue][].
+
+**Table of contents:**
+
+- [Introduction](#introduction)
+- [Getting started](#getting-started)
+- [The case for Immutability](#the-case-for-immutability)
+- [JavaScript-first API](#javascript-first-api)
+- [Nested Structures](#nested-structures)
+- [Equality treats Collections as Values](#equality-treats-collections-as-values)
+- [Batching Mutations](#batching-mutations)
+- [Lazy Seq](#lazy-seq)
+- [Additional Tools and Resources](#additional-tools-and-resources)
+- [Contributing](#contributing)
+
+## Introduction
+
+[Immutable][] data cannot be changed once created, leading to much simpler
+application development, no defensive copying, and enabling advanced memoization
+and change detection techniques with simple logic. [Persistent][] data presents
+a mutative API which does not update the data in-place, but instead always
+yields new updated data.
+
+Immutable.js provides many Persistent Immutable data structures including:
+`List`, `Stack`, `Map`, `OrderedMap`, `Set`, `OrderedSet` and `Record`.
+
+These data structures are highly efficient on modern JavaScript VMs by using
+structural sharing via [hash maps tries][] and [vector tries][] as popularized
+by Clojure and Scala, minimizing the need to copy or cache data.
+
+Immutable.js also provides a lazy `Seq`, allowing efficient
+chaining of collection methods like `map` and `filter` without creating
+intermediate representations. Create some `Seq` with `Range` and `Repeat`.
+
+Want to hear more? Watch the presentation about Immutable.js:
+
+[![Immutable Data and React](website/public/Immutable-Data-and-React-YouTube.png)](https://youtu.be/I7IdS-PbEgI)
+
+[README.md]: https://github.com/immutable-js/immutable-js/blob/main/README.md
+[immutable.d.ts]: https://github.com/immutable-js/immutable-js/blob/main/type-definitions/immutable.d.ts
+[wiki]: https://github.com/immutable-js/immutable-js/wiki
+[issue]: https://github.com/immutable-js/immutable-js/issues
+[Persistent]: https://en.wikipedia.org/wiki/Persistent_data_structure
+[Immutable]: https://en.wikipedia.org/wiki/Immutable_object
+[hash maps tries]: https://en.wikipedia.org/wiki/Hash_array_mapped_trie
+[vector tries]: https://hypirion.com/musings/understanding-persistent-vector-pt-1
+
+## Getting started
+
+Install `immutable` using npm.
+
+```shell
+# using npm
+npm install immutable
+
+# using Yarn
+yarn add immutable
+
+# using pnpm
+pnpm add immutable
+
+# using Bun
+bun add immutable
+```
+
+Then require it into any module.
+
+```js
+import { Map } from 'immutable';
+const map1 = Map({ a: 1, b: 2, c: 3 });
+const map2 = map1.set('b', 50);
+map1.get('b') + ' vs. ' + map2.get('b'); // 2 vs. 50
+```
+
+### Browser
+
+Immutable.js has no dependencies, which makes it predictable to include in a Browser.
+
+It's highly recommended to use a module bundler like [webpack](https://webpack.js.org/),
+[rollup](https://rollupjs.org/), or
+[browserify](https://browserify.org/). The `immutable` npm module works
+without any additional consideration. All examples throughout the documentation
+will assume use of this kind of tool.
+
+Alternatively, Immutable.js may be directly included as a script tag. Download
+or link to a CDN such as [CDNJS](https://cdnjs.com/libraries/immutable)
+or [jsDelivr](https://www.jsdelivr.com/package/npm/immutable).
+
+Use a script tag to directly add `Immutable` to the global scope:
+
+```html
+<script src="immutable.min.js"></script>
+<script>
+  var map1 = Immutable.Map({ a: 1, b: 2, c: 3 });
+  var map2 = map1.set('b', 50);
+  map1.get('b'); // 2
+  map2.get('b'); // 50
+</script>
+```
+
+Or use an AMD-style loader (such as [RequireJS](https://requirejs.org/)):
+
+```js
+require(['./immutable.min.js'], function (Immutable) {
+  var map1 = Immutable.Map({ a: 1, b: 2, c: 3 });
+  var map2 = map1.set('b', 50);
+  map1.get('b'); // 2
+  map2.get('b'); // 50
+});
+```
+
+### Flow & TypeScript
+
+Use these Immutable collections and sequences as you would use native
+collections in your [Flowtype](https://flowtype.org/) or [TypeScript](https://typescriptlang.org) programs while still taking
+advantage of type generics, error detection, and auto-complete in your IDE.
+
+Installing `immutable` via npm brings with it type definitions for Flow (v0.55.0 or higher)
+and TypeScript (v4.5 or higher), so you shouldn't need to do anything at all!
+
+#### Using TypeScript with Immutable.js v4+
+
+Immutable.js type definitions embrace ES2015. While Immutable.js itself supports
+legacy browsers and environments, its type definitions require TypeScript's 2015
+lib. Include either `"target": "es2015"` or `"lib": "es2015"` in your
+`tsconfig.json`, or provide `--target es2015` or `--lib es2015` to the
+`tsc` command.
+
+```js
+import { Map } from 'immutable';
+const map1 = Map({ a: 1, b: 2, c: 3 });
+const map2 = map1.set('b', 50);
+map1.get('b') + ' vs. ' + map2.get('b'); // 2 vs. 50
+```
+
+#### Using TypeScript with Immutable.js v3 and earlier:
+
+Previous versions of Immutable.js include a reference file which you can include
+via relative path to the type definitions at the top of your file.
+
+```js
+///<reference path='./node_modules/immutable/dist/immutable.d.ts'/>
+import { Map } from 'immutable';
+var map1: Map<string, number>;
+map1 = Map({ a: 1, b: 2, c: 3 });
+var map2 = map1.set('b', 50);
+map1.get('b'); // 2
+map2.get('b'); // 50
+```
+
+## The case for Immutability
+
+Much of what makes application development difficult is tracking mutation and
+maintaining state. Developing with immutable data encourages you to think
+differently about how data flows through your application.
+
+Subscribing to data events throughout your application creates a huge overhead of
+book-keeping which can hurt performance, sometimes dramatically, and creates
+opportunities for areas of your application to get out of sync with each other
+due to easy to make programmer error. Since immutable data never changes,
+subscribing to changes throughout the model is a dead-end and new data can only
+ever be passed from above.
+
+This model of data flow aligns well with the architecture of [React][]
+and especially well with an application designed using the ideas of [Flux][].
+
+When data is passed from above rather than being subscribed to, and you're only
+interested in doing work when something has changed, you can use equality.
+
+Immutable collections should be treated as _values_ rather than _objects_. While
+objects represent some thing which could change over time, a value represents
+the state of that thing at a particular instance of time. This principle is most
+important to understanding the appropriate use of immutable data. In order to
+treat Immutable.js collections as values, it's important to use the
+`Immutable.is()` function or `.equals()` method to determine _value equality_
+instead of the `===` operator which determines object _reference identity_.
+
+```js
+import { Map } from 'immutable';
+const map1 = Map({ a: 1, b: 2, c: 3 });
+const map2 = Map({ a: 1, b: 2, c: 3 });
+map1.equals(map2); // true
+map1 === map2; // false
+```
+
+Note: As a performance optimization Immutable.js attempts to return the existing
+collection when an operation would result in an identical collection, allowing
+for using `===` reference equality to determine if something definitely has not
+changed. This can be extremely useful when used within a memoization function
+which would prefer to re-run the function if a deeper equality check could
+potentially be more costly. The `===` equality check is also used internally by
+`Immutable.is` and `.equals()` as a performance optimization.
+
+```js
+import { Map } from 'immutable';
+const map1 = Map({ a: 1, b: 2, c: 3 });
+const map2 = map1.set('b', 2); // Set to same value
+map1 === map2; // true
+```
+
+If an object is immutable, it can be "copied" simply by making another reference
+to it instead of copying the entire object. Because a reference is much smaller
+than the object itself, this results in memory savings and a potential boost in
+execution speed for programs which rely on copies (such as an undo-stack).
+
+```js
+import { Map } from 'immutable';
+const map = Map({ a: 1, b: 2, c: 3 });
+const mapCopy = map; // Look, "copies" are free!
+```
+
+[React]: https://reactjs.org/
+[Flux]: https://facebook.github.io/flux/docs/in-depth-overview/
+
+## JavaScript-first API
+
+While Immutable.js is inspired by Clojure, Scala, Haskell and other functional
+programming environments, it's designed to bring these powerful concepts to
+JavaScript, and therefore has an Object-Oriented API that closely mirrors that
+of [ES2015][] [Array][], [Map][], and [Set][].
+
+[es2015]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_6_support_in_Mozilla
+[array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
+[map]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
+[set]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
+
+The difference for the immutable collections is that methods which would mutate
+the collection, like `push`, `set`, `unshift` or `splice`, instead return a new
+immutable collection. Methods which return new arrays, like `slice` or `concat`,
+instead return new immutable collections.
+
+```js
+import { List } from 'immutable';
+const list1 = List([1, 2]);
+const list2 = list1.push(3, 4, 5);
+const list3 = list2.unshift(0);
+const list4 = list1.concat(list2, list3);
+assert.equal(list1.size, 2);
+assert.equal(list2.size, 5);
+assert.equal(list3.size, 6);
+assert.equal(list4.size, 13);
+assert.equal(list4.get(0), 1);
+```
+
+Almost all of the methods on [Array][] will be found in similar form on
+`Immutable.List`, those of [Map][] found on `Immutable.Map`, and those of [Set][]
+found on `Immutable.Set`, including collection operations like `forEach()`
+and `map()`.
+
+```js
+import { Map } from 'immutable';
+const alpha = Map({ a: 1, b: 2, c: 3, d: 4 });
+alpha.map((v, k) => k.toUpperCase()).join();
+// 'A,B,C,D'
+```
+
+### Convert from raw JavaScript objects and arrays.
+
+Designed to inter-operate with your existing JavaScript, Immutable.js
+accepts plain JavaScript Arrays and Objects anywhere a method expects a
+`Collection`.
+
+```js
+import { Map, List } from 'immutable';
+const map1 = Map({ a: 1, b: 2, c: 3, d: 4 });
+const map2 = Map({ c: 10, a: 20, t: 30 });
+const obj = { d: 100, o: 200, g: 300 };
+const map3 = map1.merge(map2, obj);
+// Map { a: 20, b: 2, c: 10, d: 100, t: 30, o: 200, g: 300 }
+const list1 = List([1, 2, 3]);
+const list2 = List([4, 5, 6]);
+const array = [7, 8, 9];
+const list3 = list1.concat(list2, array);
+// List [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
+```
+
+This is possible because Immutable.js can treat any JavaScript Array or Object
+as a Collection. You can take advantage of this in order to get sophisticated
+collection methods on JavaScript Objects, which otherwise have a very sparse
+native API. Because Seq evaluates lazily and does not cache intermediate
+results, these operations can be extremely efficient.
+
+```js
+import { Seq } from 'immutable';
+const myObject = { a: 1, b: 2, c: 3 };
+Seq(myObject)
+  .map((x) => x * x)
+  .toObject();
+// { a: 1, b: 4, c: 9 }
+```
+
+Keep in mind, when using JS objects to construct Immutable Maps, that
+JavaScript Object properties are always strings, even if written in a quote-less
+shorthand, while Immutable Maps accept keys of any type.
+
+```js
+import { fromJS } from 'immutable';
+
+const obj = { 1: 'one' };
+console.log(Object.keys(obj)); // [ "1" ]
+console.log(obj['1'], obj[1]); // "one", "one"
+
+const map = fromJS(obj);
+console.log(map.get('1'), map.get(1)); // "one", undefined
+```
+
+Property access for JavaScript Objects first converts the key to a string, but
+since Immutable Map keys can be of any type the argument to `get()` is
+not altered.
+
+### Converts back to raw JavaScript objects.
+
+All Immutable.js Collections can be converted to plain JavaScript Arrays and
+Objects shallowly with `toArray()` and `toObject()` or deeply with `toJS()`.
+All Immutable Collections also implement `toJSON()` allowing them to be passed
+to `JSON.stringify` directly. They also respect the custom `toJSON()` methods of
+nested objects.
+
+```js
+import { Map, List } from 'immutable';
+const deep = Map({ a: 1, b: 2, c: List([3, 4, 5]) });
+console.log(deep.toObject()); // { a: 1, b: 2, c: List [ 3, 4, 5 ] }
+console.log(deep.toArray()); // [ 1, 2, List [ 3, 4, 5 ] ]
+console.log(deep.toJS()); // { a: 1, b: 2, c: [ 3, 4, 5 ] }
+JSON.stringify(deep); // '{"a":1,"b":2,"c":[3,4,5]}'
+```
+
+### Embraces ES2015
+
+Immutable.js supports all JavaScript environments, including legacy
+browsers (even IE11). However it also takes advantage of features added to
+JavaScript in [ES2015][], the latest standard version of JavaScript, including
+[Iterators][], [Arrow Functions][], [Classes][], and [Modules][]. It's inspired
+by the native [Map][] and [Set][] collections added to ES2015.
+
+All examples in the Documentation are presented in ES2015. To run in all
+browsers, they need to be translated to ES5.
+
+```js
+// ES2015
+const mapped = foo.map((x) => x * x);
+// ES5
+var mapped = foo.map(function (x) {
+  return x * x;
+});
+```
+
+All Immutable.js collections are [Iterable][iterators], which allows them to be
+used anywhere an Iterable is expected, such as when spreading into an Array.
+
+```js
+import { List } from 'immutable';
+const aList = List([1, 2, 3]);
+const anArray = [0, ...aList, 4, 5]; // [ 0, 1, 2, 3, 4, 5 ]
+```
+
+Note: A Collection is always iterated in the same order, however that order may
+not always be well defined, as is the case for the `Map` and `Set`.
+
+[Iterators]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/The_Iterator_protocol
+[Arrow Functions]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
+[Classes]: https://wiki.ecmascript.org/doku.php?id=strawman:maximally_minimal_classes
+[Modules]: https://www.2ality.com/2014/09/es6-modules-final.html
+
+## Nested Structures
+
+The collections in Immutable.js are intended to be nested, allowing for deep
+trees of data, similar to JSON.
+
+```js
+import { fromJS } from 'immutable';
+const nested = fromJS({ a: { b: { c: [3, 4, 5] } } });
+// Map { a: Map { b: Map { c: List [ 3, 4, 5 ] } } }
+```
+
+A few power-tools allow for reading and operating on nested data. The
+most useful are `mergeDeep`, `getIn`, `setIn`, and `updateIn`, found on `List`,
+`Map` and `OrderedMap`.
+
+```js
+import { fromJS } from 'immutable';
+const nested = fromJS({ a: { b: { c: [3, 4, 5] } } });
+
+const nested2 = nested.mergeDeep({ a: { b: { d: 6 } } });
+// Map { a: Map { b: Map { c: List [ 3, 4, 5 ], d: 6 } } }
+
+console.log(nested2.getIn(['a', 'b', 'd'])); // 6
+
+const nested3 = nested2.updateIn(['a', 'b', 'd'], (value) => value + 1);
+console.log(nested3);
+// Map { a: Map { b: Map { c: List [ 3, 4, 5 ], d: 7 } } }
+
+const nested4 = nested3.updateIn(['a', 'b', 'c'], (list) => list.push(6));
+// Map { a: Map { b: Map { c: List [ 3, 4, 5, 6 ], d: 7 } } }
+```
+
+## Equality treats Collections as Values
+
+Immutable.js collections are treated as pure data _values_. Two immutable
+collections are considered _value equal_ (via `.equals()` or `is()`) if they
+represent the same collection of values. This differs from JavaScript's typical
+_reference equal_ (via `===` or `==`) for Objects and Arrays which only
+determines if two variables represent references to the same object instance.
+
+Consider the example below where two identical `Map` instances are not
+_reference equal_ but are _value equal_.
+
+```js
+// First consider:
+const obj1 = { a: 1, b: 2, c: 3 };
+const obj2 = { a: 1, b: 2, c: 3 };
+obj1 !== obj2; // two different instances are always not equal with ===
+
+import { Map, is } from 'immutable';
+const map1 = Map({ a: 1, b: 2, c: 3 });
+const map2 = Map({ a: 1, b: 2, c: 3 });
+map1 !== map2; // two different instances are not reference-equal
+map1.equals(map2); // but are value-equal if they have the same values
+is(map1, map2); // alternatively can use the is() function
+```
+
+Value equality allows Immutable.js collections to be used as keys in Maps or
+values in Sets, and retrieved with different but equivalent collections:
+
+```js
+import { Map, Set } from 'immutable';
+const map1 = Map({ a: 1, b: 2, c: 3 });
+const map2 = Map({ a: 1, b: 2, c: 3 });
+const set = Set().add(map1);
+set.has(map2); // true because these are value-equal
+```
+
+Note: `is()` uses the same measure of equality as [Object.is][] for scalar
+strings and numbers, but uses value equality for Immutable collections,
+determining if both are immutable and all keys and values are equal
+using the same measure of equality.
+
+[object.is]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
+
+#### Performance tradeoffs
+
+While value equality is useful in many circumstances, it has different
+performance characteristics than reference equality. Understanding these
+tradeoffs may help you decide which to use in each case, especially when used
+to memoize some operation.
+
+When comparing two collections, value equality may require considering every
+item in each collection, on an `O(N)` time complexity. For large collections of
+values, this could become a costly operation. Though if the two are not equal
+and hardly similar, the inequality is determined very quickly. In contrast, when
+comparing two collections with reference equality, only the initial references
+to memory need to be compared which is not based on the size of the collections,
+which has an `O(1)` time complexity. Checking reference equality is always very
+fast, however just because two collections are not reference-equal does not rule
+out the possibility that they may be value-equal.
+
+#### Return self on no-op optimization
+
+When possible, Immutable.js avoids creating new objects for updates where no
+change in _value_ occurred, to allow for efficient _reference equality_ checking
+to quickly determine if no change occurred.
+
+```js
+import { Map } from 'immutable';
+const originalMap = Map({ a: 1, b: 2, c: 3 });
+const updatedMap = originalMap.set('b', 2);
+updatedMap === originalMap; // No-op .set() returned the original reference.
+```
+
+However updates which do result in a change will return a new reference. Each
+of these operations occur independently, so two similar updates will not return
+the same reference:
+
+```js
+import { Map } from 'immutable';
+const originalMap = Map({ a: 1, b: 2, c: 3 });
+const updatedMap = originalMap.set('b', 1000);
+// New instance, leaving the original immutable.
+updatedMap !== originalMap;
+const anotherUpdatedMap = originalMap.set('b', 1000);
+// Despite both the results of the same operation, each created a new reference.
+anotherUpdatedMap !== updatedMap;
+// However the two are value equal.
+anotherUpdatedMap.equals(updatedMap);
+```
+
+## Batching Mutations
+
+> If a tree falls in the woods, does it make a sound?
+>
+> If a pure function mutates some local data in order to produce an immutable
+> return value, is that ok?
+>
+> — Rich Hickey, Clojure
+
+Applying a mutation to create a new immutable object results in some overhead,
+which can add up to a minor performance penalty. If you need to apply a series
+of mutations locally before returning, Immutable.js gives you the ability to
+create a temporary mutable (transient) copy of a collection and apply a batch of
+mutations in a performant manner by using `withMutations`. In fact, this is
+exactly how Immutable.js applies complex mutations itself.
+
+As an example, building `list2` results in the creation of 1, not 3, new
+immutable Lists.
+
+```js
+import { List } from 'immutable';
+const list1 = List([1, 2, 3]);
+const list2 = list1.withMutations(function (list) {
+  list.push(4).push(5).push(6);
+});
+assert.equal(list1.size, 3);
+assert.equal(list2.size, 6);
+```
+
+Note: Immutable.js also provides `asMutable` and `asImmutable`, but only
+encourages their use when `withMutations` will not suffice. Use caution to not
+return a mutable copy, which could result in undesired behavior.
+
+_Important!_: Only a select few methods can be used in `withMutations` including
+`set`, `push` and `pop`. These methods can be applied directly against a
+persistent data-structure where other methods like `map`, `filter`, `sort`,
+and `splice` will always return new immutable data-structures and never mutate
+a mutable collection.
+
+## Lazy Seq
+
+`Seq` describes a lazy operation, allowing them to efficiently chain
+use of all the higher-order collection methods (such as `map` and `filter`)
+by not creating intermediate collections.
+
+**Seq is immutable** — Once a Seq is created, it cannot be
+changed, appended to, rearranged or otherwise modified. Instead, any mutative
+method called on a `Seq` will return a new `Seq`.
+
+**Seq is lazy** — `Seq` does as little work as necessary to respond to any
+method call. Values are often created during iteration, including implicit
+iteration when reducing or converting to a concrete data structure such as
+a `List` or JavaScript `Array`.
+
+For example, the following performs no work, because the resulting
+`Seq`'s values are never iterated:
+
+```js
+import { Seq } from 'immutable';
+const oddSquares = Seq([1, 2, 3, 4, 5, 6, 7, 8])
+  .filter((x) => x % 2 !== 0)
+  .map((x) => x * x);
+```
+
+Once the `Seq` is used, it performs only the work necessary. In this
+example, no intermediate arrays are ever created, filter is called three
+times, and map is only called once:
+
+```js
+oddSquares.get(1); // 9
+```
+
+Any collection can be converted to a lazy Seq with `Seq()`.
+
+```js
+import { Map, Seq } from 'immutable';
+const map = Map({ a: 1, b: 2, c: 3 });
+const lazySeq = Seq(map);
+```
+
+`Seq` allows for the efficient chaining of operations, allowing for the
+expression of logic that can otherwise be very tedious:
+
+```js
+lazySeq
+  .flip()
+  .map((key) => key.toUpperCase())
+  .flip();
+// Seq { A: 1, B: 2, C: 3 }
+```
+
+As well as expressing logic that would otherwise seem memory or time
+limited, for example `Range` is a special kind of Lazy sequence.
+
+```js
+import { Range } from 'immutable';
+Range(1, Infinity)
+  .skip(1000)
+  .map((n) => -n)
+  .filter((n) => n % 2 === 0)
+  .take(2)
+  .reduce((r, n) => r * n, 1);
+// 1006008
+```
+
+## Comparison of filter(), groupBy(), and partition()
+
+The `filter()`, `groupBy()`, and `partition()` methods are similar in that they
+all divide a collection into parts based on applying a function to each element.
+All three call the predicate or grouping function once for each item in the
+input collection. All three return zero or more collections of the same type as
+their input. The returned collections are always distinct from the input
+(according to `===`), even if the contents are identical.
+
+Of these methods, `filter()` is the only one that is lazy and the only one which
+discards items from the input collection. It is the simplest to use, and the
+fact that it returns exactly one collection makes it easy to combine with other
+methods to form a pipeline of operations.
+
+The `partition()` method is similar to an eager version of `filter()`, but it
+returns two collections; the first contains the items that would have been
+discarded by `filter()`, and the second contains the items that would have been
+kept. It always returns an array of exactly two collections, which can make it
+easier to use than `groupBy()`. Compared to making two separate calls to
+`filter()`, `partition()` makes half as many calls it the predicate passed to
+it.
+
+The `groupBy()` method is a more generalized version of `partition()` that can
+group by an arbitrary function rather than just a predicate. It returns a map
+with zero or more entries, where the keys are the values returned by the
+grouping function, and the values are nonempty collections of the corresponding
+arguments. Although `groupBy()` is more powerful than `partition()`, it can be
+harder to use because it is not always possible predict in advance how many
+entries the returned map will have and what their keys will be.
+
+| Summary                       | `filter` | `partition` | `groupBy`      |
+| :---------------------------- | :------- | :---------- | :------------- |
+| ease of use                   | easiest  | moderate    | hardest        |
+| generality                    | least    | moderate    | most           |
+| laziness                      | lazy     | eager       | eager          |
+| # of returned sub-collections | 1        | 2           | 0 or more      |
+| sub-collections may be empty  | yes      | yes         | no             |
+| can discard items             | yes      | no          | no             |
+| wrapping container            | none     | array       | Map/OrderedMap |
+
+## Additional Tools and Resources
+
+- [Atom-store](https://github.com/jameshopkins/atom-store/)
+
+  - A Clojure-inspired atom implementation in Javascript with configurability
+    for external persistance.
+
+- [Chai Immutable](https://github.com/astorije/chai-immutable)
+
+  - If you are using the [Chai Assertion Library](https://chaijs.com/), this
+    provides a set of assertions to use against Immutable.js collections.
+
+- [Fantasy-land](https://github.com/fantasyland/fantasy-land)
+
+  - Specification for interoperability of common algebraic structures in JavaScript.
+
+- [Immutagen](https://github.com/pelotom/immutagen)
+
+  - A library for simulating immutable generators in JavaScript.
+
+- [Immutable-cursor](https://github.com/redbadger/immutable-cursor)
+
+  - Immutable cursors incorporating the Immutable.js interface over
+    Clojure-inspired atom.
+
+- [Immutable-ext](https://github.com/DrBoolean/immutable-ext)
+
+  - Fantasyland extensions for immutablejs
+
+- [Immutable-js-tools](https://github.com/madeinfree/immutable-js-tools)
+
+  - Util tools for immutable.js
+
+- [Immutable-Redux](https://github.com/gajus/redux-immutable)
+
+  - redux-immutable is used to create an equivalent function of Redux
+    combineReducers that works with Immutable.js state.
+
+- [Immutable-Treeutils](https://github.com/lukasbuenger/immutable-treeutils)
+
+  - Functional tree traversal helpers for ImmutableJS data structures.
+
+- [Irecord](https://github.com/ericelliott/irecord)
+
+  - An immutable store that exposes an RxJS observable. Great for React.
+
+- [Mudash](https://github.com/brianneisler/mudash)
+
+  - Lodash wrapper providing Immutable.JS support.
+
+- [React-Immutable-PropTypes](https://github.com/HurricaneJames/react-immutable-proptypes)
+
+  - PropType validators that work with Immutable.js.
+
+- [Redux-Immutablejs](https://github.com/indexiatech/redux-immutablejs)
+
+  - Redux Immutable facilities.
+
+- [Rxstate](https://github.com/yamalight/rxstate)
+
+  - Simple opinionated state management library based on RxJS and Immutable.js.
+
+- [Transit-Immutable-js](https://github.com/glenjamin/transit-immutable-js)
+  - Transit serialisation for Immutable.js.
+  - See also: [Transit-js](https://github.com/cognitect/transit-js)
+
+Have an additional tool designed to work with Immutable.js?
+Submit a PR to add it to this list in alphabetical order.
+
+## Contributing
+
+Use [Github issues](https://github.com/immutable-js/immutable-js/issues) for requests.
+
+We actively welcome pull requests, learn how to [contribute](https://github.com/immutable-js/immutable-js/blob/main/.github/CONTRIBUTING.md).
+
+Immutable.js is maintained within the [Contributor Covenant's Code of Conduct](https://www.contributor-covenant.org/version/2/0/code_of_conduct/).
+
+### Changelog
+
+Changes are tracked as [Github releases](https://github.com/immutable-js/immutable-js/releases).
+
+### License
+
+Immutable.js is [MIT-licensed](./LICENSE).
+
+### Thanks
+
+[Phil Bagwell](https://www.youtube.com/watch?v=K2NYwP90bNs), for his inspiration
+and research in persistent data structures.
+
+[Hugh Jackson](https://github.com/hughfdjackson/), for providing the npm package
+name. If you're looking for his unsupported package, see [this repository](https://github.com/hughfdjackson/immutable).

+ 5126 - 0
node_modules/immutable/dist/immutable.d.ts

@@ -0,0 +1,5126 @@
+/** @ignore we should disable this rules, but let's activate it to enable eslint first */
+/**
+ * Immutable data encourages pure functions (data-in, data-out) and lends itself
+ * to much simpler application development and enabling techniques from
+ * functional programming such as lazy evaluation.
+ *
+ * While designed to bring these powerful functional concepts to JavaScript, it
+ * presents an Object-Oriented API familiar to Javascript engineers and closely
+ * mirroring that of Array, Map, and Set. It is easy and efficient to convert to
+ * and from plain Javascript types.
+ *
+ * ## How to read these docs
+ *
+ * In order to better explain what kinds of values the Immutable.js API expects
+ * and produces, this documentation is presented in a statically typed dialect of
+ * JavaScript (like [Flow][] or [TypeScript][]). You *don't need* to use these
+ * type checking tools in order to use Immutable.js, however becoming familiar
+ * with their syntax will help you get a deeper understanding of this API.
+ *
+ * **A few examples and how to read them.**
+ *
+ * All methods describe the kinds of data they accept and the kinds of data
+ * they return. For example a function which accepts two numbers and returns
+ * a number would look like this:
+ *
+ * ```js
+ * sum(first: number, second: number): number
+ * ```
+ *
+ * Sometimes, methods can accept different kinds of data or return different
+ * kinds of data, and this is described with a *type variable*, which is
+ * typically in all-caps. For example, a function which always returns the same
+ * kind of data it was provided would look like this:
+ *
+ * ```js
+ * identity<T>(value: T): T
+ * ```
+ *
+ * Type variables are defined with classes and referred to in methods. For
+ * example, a class that holds onto a value for you might look like this:
+ *
+ * ```js
+ * class Box<T> {
+ *   constructor(value: T)
+ *   getValue(): T
+ * }
+ * ```
+ *
+ * In order to manipulate Immutable data, methods that we're used to affecting
+ * a Collection instead return a new Collection of the same type. The type
+ * `this` refers to the same kind of class. For example, a List which returns
+ * new Lists when you `push` a value onto it might look like:
+ *
+ * ```js
+ * class List<T> {
+ *   push(value: T): this
+ * }
+ * ```
+ *
+ * Many methods in Immutable.js accept values which implement the JavaScript
+ * [Iterable][] protocol, and might appear like `Iterable<string>` for something
+ * which represents sequence of strings. Typically in JavaScript we use plain
+ * Arrays (`[]`) when an Iterable is expected, but also all of the Immutable.js
+ * collections are iterable themselves!
+ *
+ * For example, to get a value deep within a structure of data, we might use
+ * `getIn` which expects an `Iterable` path:
+ *
+ * ```
+ * getIn(path: Iterable<string | number>): unknown
+ * ```
+ *
+ * To use this method, we could pass an array: `data.getIn([ "key", 2 ])`.
+ *
+ *
+ * Note: All examples are presented in the modern [ES2015][] version of
+ * JavaScript. Use tools like Babel to support older browsers.
+ *
+ * For example:
+ *
+ * ```js
+ * // ES2015
+ * const mappedFoo = foo.map(x => x * x);
+ * // ES5
+ * var mappedFoo = foo.map(function (x) { return x * x; });
+ * ```
+ *
+ * [ES2015]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_6_support_in_Mozilla
+ * [TypeScript]: https://www.typescriptlang.org/
+ * [Flow]: https://flowtype.org/
+ * [Iterable]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols
+ */
+
+declare namespace Immutable {
+  /** @ignore */
+  type OnlyObject<T> = Extract<T, object>;
+
+  /** @ignore */
+  type ContainObject<T> =
+    OnlyObject<T> extends object
+      ? OnlyObject<T> extends never
+        ? false
+        : true
+      : false;
+
+  /**
+   * @ignore
+   *
+   * Used to convert deeply all immutable types to a plain TS type.
+   * Using `unknown` on object instead of recursive call as we have a circular reference issue
+   */
+  export type DeepCopy<T> =
+    T extends Record<infer R>
+      ? // convert Record to DeepCopy plain JS object
+        {
+          [key in keyof R]: ContainObject<R[key]> extends true
+            ? unknown
+            : R[key];
+        }
+      : T extends MapOf<infer R>
+        ? // convert MapOf to DeepCopy plain JS object
+          {
+            [key in keyof R]: ContainObject<R[key]> extends true
+              ? unknown
+              : R[key];
+          }
+        : T extends Collection.Keyed<infer KeyedKey, infer V>
+          ? // convert KeyedCollection to DeepCopy plain JS object
+            {
+              [key in KeyedKey extends PropertyKey
+                ? KeyedKey
+                : string]: V extends object ? unknown : V;
+            }
+          : // convert IndexedCollection or Immutable.Set to DeepCopy plain JS array
+            // eslint-disable-next-line @typescript-eslint/no-unused-vars
+            T extends Collection<infer _, infer V>
+            ? Array<DeepCopy<V>>
+            : T extends string | number // Iterable scalar types : should be kept as is
+              ? T
+              : T extends Iterable<infer V> // Iterable are converted to plain JS array
+                ? Array<DeepCopy<V>>
+                : T extends object // plain JS object are converted deeply
+                  ? {
+                      [ObjectKey in keyof T]: ContainObject<
+                        T[ObjectKey]
+                      > extends true
+                        ? unknown
+                        : T[ObjectKey];
+                    }
+                  : // other case : should be kept as is
+                    T;
+
+  /**
+   * Describes which item in a pair should be placed first when sorting
+   *
+   * @ignore
+   */
+  export enum PairSorting {
+    LeftThenRight = -1,
+    RightThenLeft = +1,
+  }
+
+  /**
+   * Function comparing two items of the same type. It can return:
+   *
+   * * a PairSorting value, to indicate whether the left-hand item or the right-hand item should be placed before the other
+   *
+   * * the traditional numeric return value - especially -1, 0, or 1
+   *
+   * @ignore
+   */
+  export type Comparator<T> = (left: T, right: T) => PairSorting | number;
+
+  /**
+   * @ignore
+   *
+   * KeyPath allowed for `xxxIn` methods
+   */
+  export type KeyPath<K> = OrderedCollection<K> | ArrayLike<K>;
+
+  /**
+   * Lists are ordered indexed dense collections, much like a JavaScript
+   * Array.
+   *
+   * Lists are immutable and fully persistent with O(log32 N) gets and sets,
+   * and O(1) push and pop.
+   *
+   * Lists implement Deque, with efficient addition and removal from both the
+   * end (`push`, `pop`) and beginning (`unshift`, `shift`).
+   *
+   * Unlike a JavaScript Array, there is no distinction between an
+   * "unset" index and an index set to `undefined`. `List#forEach` visits all
+   * indices from 0 to size, regardless of whether they were explicitly defined.
+   */
+  namespace List {
+    /**
+     * True if the provided value is a List
+     */
+    function isList(maybeList: unknown): maybeList is List<unknown>;
+
+    /**
+     * Creates a new List containing `values`.
+     *
+     * Note: Values are not altered or converted in any way.
+     */
+    function of<T>(...values: Array<T>): List<T>;
+  }
+
+  /**
+   * Create a new immutable List containing the values of the provided
+   * collection-like.
+   *
+   * Note: `List` is a factory function and not a class, and does not use the
+   * `new` keyword during construction.
+   */
+  function List<T>(collection?: Iterable<T> | ArrayLike<T>): List<T>;
+
+  interface List<T> extends Collection.Indexed<T> {
+    /**
+     * The number of items in this List.
+     */
+    readonly size: number;
+
+    // Persistent changes
+
+    /**
+     * Returns a new List which includes `value` at `index`. If `index` already
+     * exists in this List, it will be replaced.
+     *
+     * `index` may be a negative number, which indexes back from the end of the
+     * List. `v.set(-1, "value")` sets the last item in the List.
+     *
+     * If `index` larger than `size`, the returned List's `size` will be large
+     * enough to include the `index`.
+     *
+     * Note: `set` can be used in `withMutations`.
+     */
+    set(index: number, value: T): List<T>;
+
+    /**
+     * Returns a new List which excludes this `index` and with a size 1 less
+     * than this List. Values at indices above `index` are shifted down by 1 to
+     * fill the position.
+     *
+     * This is synonymous with `list.splice(index, 1)`.
+     *
+     * `index` may be a negative number, which indexes back from the end of the
+     * List. `v.delete(-1)` deletes the last item in the List.
+     *
+     * Note: `delete` cannot be safely used in IE8
+     *
+     * Since `delete()` re-indexes values, it produces a complete copy, which
+     * has `O(N)` complexity.
+     *
+     * Note: `delete` *cannot* be used in `withMutations`.
+     *
+     * @alias remove
+     */
+    delete(index: number): List<T>;
+    remove(index: number): List<T>;
+
+    /**
+     * Returns a new List with `value` at `index` with a size 1 more than this
+     * List. Values at indices above `index` are shifted over by 1.
+     *
+     * This is synonymous with `list.splice(index, 0, value)`.
+     *
+     * Since `insert()` re-indexes values, it produces a complete copy, which
+     * has `O(N)` complexity.
+     *
+     * Note: `insert` *cannot* be used in `withMutations`.
+     */
+    insert(index: number, value: T): List<T>;
+
+    /**
+     * Returns a new List with 0 size and no values in constant time.
+     *
+     * Note: `clear` can be used in `withMutations`.
+     */
+    clear(): List<T>;
+
+    /**
+     * Returns a new List with the provided `values` appended, starting at this
+     * List's `size`.
+     *
+     * Note: `push` can be used in `withMutations`.
+     */
+    push(...values: Array<T>): List<T>;
+
+    /**
+     * Returns a new List with a size ones less than this List, excluding
+     * the last index in this List.
+     *
+     * Note: this differs from `Array#pop` because it returns a new
+     * List rather than the removed value. Use `last()` to get the last value
+     * in this List.
+     *
+     * ```js
+     * List([ 1, 2, 3, 4 ]).pop()
+     * // List[ 1, 2, 3 ]
+     * ```
+     *
+     * Note: `pop` can be used in `withMutations`.
+     */
+    pop(): List<T>;
+
+    /**
+     * Returns a new List with the provided `values` prepended, shifting other
+     * values ahead to higher indices.
+     *
+     * Note: `unshift` can be used in `withMutations`.
+     */
+    unshift(...values: Array<T>): List<T>;
+
+    /**
+     * Returns a new List with a size ones less than this List, excluding
+     * the first index in this List, shifting all other values to a lower index.
+     *
+     * Note: this differs from `Array#shift` because it returns a new
+     * List rather than the removed value. Use `first()` to get the first
+     * value in this List.
+     *
+     * Note: `shift` can be used in `withMutations`.
+     */
+    shift(): List<T>;
+
+    /**
+     * Returns a new List with an updated value at `index` with the return
+     * value of calling `updater` with the existing value, or `notSetValue` if
+     * `index` was not set. If called with a single argument, `updater` is
+     * called with the List itself.
+     *
+     * `index` may be a negative number, which indexes back from the end of the
+     * List. `v.update(-1)` updates the last item in the List.
+     *
+     * This can be very useful as a way to "chain" a normal function into a
+     * sequence of methods. RxJS calls this "let" and lodash calls it "thru".
+     *
+     * For example, to sum a List after mapping and filtering:
+     *
+     * Note: `update(index)` can be used in `withMutations`.
+     *
+     * @see `Map#update`
+     */
+    update(index: number, notSetValue: T, updater: (value: T) => T): this;
+    update(
+      index: number,
+      updater: (value: T | undefined) => T | undefined
+    ): this;
+    update<R>(updater: (value: this) => R): R;
+
+    /**
+     * Returns a new List with size `size`. If `size` is less than this
+     * List's size, the new List will exclude values at the higher indices.
+     * If `size` is greater than this List's size, the new List will have
+     * undefined values for the newly available indices.
+     *
+     * When building a new List and the final size is known up front, `setSize`
+     * used in conjunction with `withMutations` may result in the more
+     * performant construction.
+     */
+    setSize(size: number): List<T>;
+
+    // Deep persistent changes
+
+    /**
+     * Returns a new List having set `value` at this `keyPath`. If any keys in
+     * `keyPath` do not exist, a new immutable Map will be created at that key.
+     *
+     * Index numbers are used as keys to determine the path to follow in
+     * the List.
+     *
+     * Plain JavaScript Object or Arrays may be nested within an Immutable.js
+     * Collection, and setIn() can update those values as well, treating them
+     * immutably by creating new copies of those values with the changes applied.
+     *
+     * Note: `setIn` can be used in `withMutations`.
+     */
+    setIn(keyPath: Iterable<unknown>, value: unknown): this;
+
+    /**
+     * Returns a new List having removed the value at this `keyPath`. If any
+     * keys in `keyPath` do not exist, no change will occur.
+     *
+     * Plain JavaScript Object or Arrays may be nested within an Immutable.js
+     * Collection, and removeIn() can update those values as well, treating them
+     * immutably by creating new copies of those values with the changes applied.
+     *
+     * Note: `deleteIn` *cannot* be safely used in `withMutations`.
+     *
+     * @alias removeIn
+     */
+    deleteIn(keyPath: Iterable<unknown>): this;
+    removeIn(keyPath: Iterable<unknown>): this;
+
+    /**
+     * Note: `updateIn` can be used in `withMutations`.
+     *
+     * @see `Map#updateIn`
+     */
+    updateIn(
+      keyPath: Iterable<unknown>,
+      notSetValue: unknown,
+      updater: (value: unknown) => unknown
+    ): this;
+    updateIn(
+      keyPath: Iterable<unknown>,
+      updater: (value: unknown) => unknown
+    ): this;
+
+    /**
+     * Note: `mergeIn` can be used in `withMutations`.
+     *
+     * @see `Map#mergeIn`
+     */
+    mergeIn(keyPath: Iterable<unknown>, ...collections: Array<unknown>): this;
+
+    /**
+     * Note: `mergeDeepIn` can be used in `withMutations`.
+     *
+     * @see `Map#mergeDeepIn`
+     */
+    mergeDeepIn(
+      keyPath: Iterable<unknown>,
+      ...collections: Array<unknown>
+    ): this;
+
+    // Transient changes
+
+    /**
+     * Note: Not all methods can be safely used on a mutable collection or within
+     * `withMutations`! Check the documentation for each method to see if it
+     * allows being used in `withMutations`.
+     *
+     * @see `Map#withMutations`
+     */
+    withMutations(mutator: (mutable: this) => unknown): this;
+
+    /**
+     * An alternative API for withMutations()
+     *
+     * Note: Not all methods can be safely used on a mutable collection or within
+     * `withMutations`! Check the documentation for each method to see if it
+     * allows being used in `withMutations`.
+     *
+     * @see `Map#asMutable`
+     */
+    asMutable(): this;
+
+    /**
+     * @see `Map#wasAltered`
+     */
+    wasAltered(): boolean;
+
+    /**
+     * @see `Map#asImmutable`
+     */
+    asImmutable(): this;
+
+    // Sequence algorithms
+
+    /**
+     * Returns a new List with other values or collections concatenated to this one.
+     *
+     * Note: `concat` can be used in `withMutations`.
+     *
+     * @alias merge
+     */
+    concat<C>(...valuesOrCollections: Array<Iterable<C> | C>): List<T | C>;
+    merge<C>(...collections: Array<Iterable<C>>): List<T | C>;
+
+    /**
+     * Returns a new List with values passed through a
+     * `mapper` function.
+     */
+    map<M>(
+      mapper: (value: T, key: number, iter: this) => M,
+      context?: unknown
+    ): List<M>;
+
+    /**
+     * Flat-maps the List, returning a new List.
+     *
+     * Similar to `list.map(...).flatten(true)`.
+     */
+    flatMap<M>(
+      mapper: (value: T, key: number, iter: this) => Iterable<M>,
+      context?: unknown
+    ): List<M>;
+
+    /**
+     * Returns a new List with only the values for which the `predicate`
+     * function returns true.
+     *
+     * Note: `filter()` always returns a new instance, even if it results in
+     * not filtering out any values.
+     */
+    filter<F extends T>(
+      predicate: (value: T, index: number, iter: this) => value is F,
+      context?: unknown
+    ): List<F>;
+    filter(
+      predicate: (value: T, index: number, iter: this) => unknown,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new List with the values for which the `predicate`
+     * function returns false and another for which is returns true.
+     */
+    partition<F extends T, C>(
+      predicate: (this: C, value: T, index: number, iter: this) => value is F,
+      context?: C
+    ): [List<T>, List<F>];
+    partition<C>(
+      predicate: (this: C, value: T, index: number, iter: this) => unknown,
+      context?: C
+    ): [this, this];
+
+    /**
+     * Returns a List "zipped" with the provided collection.
+     *
+     * Like `zipWith`, but using the default `zipper`: creating an `Array`.
+     */
+    zip<U>(other: Collection<unknown, U>): List<[T, U]>;
+    zip<U, V>(
+      other: Collection<unknown, U>,
+      other2: Collection<unknown, V>
+    ): List<[T, U, V]>;
+    zip(...collections: Array<Collection<unknown, unknown>>): List<unknown>;
+
+    /**
+     * Returns a List "zipped" with the provided collections.
+     *
+     * Unlike `zip`, `zipAll` continues zipping until the longest collection is
+     * exhausted. Missing values from shorter collections are filled with `undefined`.
+     *
+     * Note: Since zipAll will return a collection as large as the largest
+     * input, some results may contain undefined values. TypeScript cannot
+     * account for these without cases (as of v2.5).
+     */
+    zipAll<U>(other: Collection<unknown, U>): List<[T, U]>;
+    zipAll<U, V>(
+      other: Collection<unknown, U>,
+      other2: Collection<unknown, V>
+    ): List<[T, U, V]>;
+    zipAll(...collections: Array<Collection<unknown, unknown>>): List<unknown>;
+
+    /**
+     * Returns a List "zipped" with the provided collections by using a
+     * custom `zipper` function.
+     */
+    zipWith<U, Z>(
+      zipper: (value: T, otherValue: U) => Z,
+      otherCollection: Collection<unknown, U>
+    ): List<Z>;
+    zipWith<U, V, Z>(
+      zipper: (value: T, otherValue: U, thirdValue: V) => Z,
+      otherCollection: Collection<unknown, U>,
+      thirdCollection: Collection<unknown, V>
+    ): List<Z>;
+    zipWith<Z>(
+      zipper: (...values: Array<unknown>) => Z,
+      ...collections: Array<Collection<unknown, unknown>>
+    ): List<Z>;
+
+    /**
+     * Returns a new List with its values shuffled thanks to the
+     * [Fisher–Yates](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle)
+     * algorithm.
+     * It uses Math.random, but you can provide your own random number generator.
+     */
+    shuffle(random?: () => number): this;
+  }
+
+  /**
+   * Immutable Map is an unordered Collection.Keyed of (key, value) pairs with
+   * `O(log32 N)` gets and `O(log32 N)` persistent sets.
+   *
+   * Iteration order of a Map is undefined, however is stable. Multiple
+   * iterations of the same Map will iterate in the same order.
+   *
+   * Map's keys can be of any type, and use `Immutable.is` to determine key
+   * equality. This allows the use of any value (including NaN) as a key.
+   *
+   * Because `Immutable.is` returns equality based on value semantics, and
+   * Immutable collections are treated as values, any Immutable collection may
+   * be used as a key.
+   *
+   * Any JavaScript object may be used as a key, however strict identity is used
+   * to evaluate key equality. Two similar looking objects will represent two
+   * different keys.
+   *
+   * Implemented by a hash-array mapped trie.
+   */
+  namespace Map {
+    /**
+     * True if the provided value is a Map
+     */
+    function isMap(maybeMap: unknown): maybeMap is Map<unknown, unknown>;
+  }
+
+  /**
+   * Creates a new Immutable Map.
+   *
+   * Created with the same key value pairs as the provided Collection.Keyed or
+   * JavaScript Object or expects a Collection of [K, V] tuple entries.
+   *
+   * Note: `Map` is a factory function and not a class, and does not use the
+   * `new` keyword during construction.
+   *
+   * Keep in mind, when using JS objects to construct Immutable Maps, that
+   * JavaScript Object properties are always strings, even if written in a
+   * quote-less shorthand, while Immutable Maps accept keys of any type.
+   *
+   * Property access for JavaScript Objects first converts the key to a string,
+   * but since Immutable Map keys can be of any type the argument to `get()` is
+   * not altered.
+   */
+  function Map<K, V>(collection?: Iterable<readonly [K, V]>): Map<K, V>;
+  function Map<R extends { [key in PropertyKey]: unknown }>(obj: R): MapOf<R>;
+  function Map<V>(obj: { [key: string]: V }): Map<string, V>;
+  function Map<K extends string | symbol, V>(obj: { [P in K]?: V }): Map<K, V>;
+
+  /**
+   * Represent a Map constructed by an object
+   *
+   * @ignore
+   */
+  interface MapOf<R extends { [key in PropertyKey]: unknown }>
+    extends Map<keyof R, R[keyof R]> {
+    /**
+     * Returns the value associated with the provided key, or notSetValue if
+     * the Collection does not contain this key.
+     *
+     * Note: it is possible a key may be associated with an `undefined` value,
+     * so if `notSetValue` is not provided and this method returns `undefined`,
+     * that does not guarantee the key was not found.
+     */
+    get<K extends keyof R>(key: K, notSetValue?: unknown): R[K];
+    get<NSV>(key: unknown, notSetValue: NSV): NSV;
+
+    // TODO `<const P extends ...>` can be used after dropping support for TypeScript 4.x
+    // reference: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html#const-type-parameters
+    // after this change, `as const` assertions can be remove from the type tests
+    getIn<P extends ReadonlyArray<PropertyKey>>(
+      searchKeyPath: [...P],
+      notSetValue?: unknown
+    ): RetrievePath<R, P>;
+
+    set<K extends keyof R>(key: K, value: R[K]): this;
+
+    update(updater: (value: this) => this): this;
+    update<K extends keyof R>(key: K, updater: (value: R[K]) => R[K]): this;
+    update<K extends keyof R, NSV extends R[K]>(
+      key: K,
+      notSetValue: NSV,
+      updater: (value: R[K]) => R[K]
+    ): this;
+
+    // Possible best type is MapOf<Omit<R, K>> but Omit seems to broke other function calls
+    // and generate recursion error with other methods (update, merge, etc.) until those functions are defined in MapOf
+    delete<K extends keyof R>(
+      key: K
+    ): Extract<R[K], undefined> extends never ? never : this;
+    remove<K extends keyof R>(
+      key: K
+    ): Extract<R[K], undefined> extends never ? never : this;
+
+    toJS(): { [K in keyof R]: DeepCopy<R[K]> };
+
+    toJSON(): { [K in keyof R]: R[K] };
+  }
+
+  // Loosely based off of this work.
+  // https://github.com/immutable-js/immutable-js/issues/1462#issuecomment-584123268
+
+  /**
+   * @ignore
+   * Convert an immutable type to the equivalent plain TS type
+   * - MapOf -> object
+   * - List -> Array
+   */
+  type GetNativeType<S> =
+    S extends MapOf<infer T> ? T : S extends List<infer I> ? Array<I> : S;
+
+  /** @ignore */
+  type Head<T extends ReadonlyArray<unknown>> = T extends [
+    infer H,
+    ...Array<unknown>,
+  ]
+    ? H
+    : never;
+  /** @ignore */
+  type Tail<T extends ReadonlyArray<unknown>> = T extends [unknown, ...infer I]
+    ? I
+    : Array<never>;
+  /** @ignore */
+  type RetrievePathReducer<
+    T,
+    C,
+    L extends ReadonlyArray<unknown>,
+    NT = GetNativeType<T>,
+  > =
+    // we can not retrieve a path from a primitive type
+    T extends string | number | boolean | null | undefined
+      ? never
+      : C extends keyof NT
+        ? L extends [] // L extends [] means we are at the end of the path, lets return the current type
+          ? NT[C]
+          : // we are not at the end of the path, lets continue with the next key
+            RetrievePathReducer<NT[C], Head<L>, Tail<L>>
+        : // C is not a "key" of NT, so the path is invalid
+          never;
+
+  /** @ignore */
+  type RetrievePath<R, P extends ReadonlyArray<unknown>> = P extends []
+    ? P
+    : RetrievePathReducer<R, Head<P>, Tail<P>>;
+
+  interface Map<K, V> extends Collection.Keyed<K, V> {
+    /**
+     * The number of entries in this Map.
+     */
+    readonly size: number;
+
+    // Persistent changes
+
+    /**
+     * Returns a new Map also containing the new key, value pair. If an equivalent
+     * key already exists in this Map, it will be replaced.
+     *
+     * Note: `set` can be used in `withMutations`.
+     */
+    set(key: K, value: V): this;
+
+    /**
+     * Returns a new Map which excludes this `key`.
+     *
+     * Note: `delete` cannot be safely used in IE8, but is provided to mirror
+     * the ES6 collection API.
+     *
+     * Note: `delete` can be used in `withMutations`.
+     *
+     * @alias remove
+     */
+    delete(key: K): this;
+    remove(key: K): this;
+
+    /**
+     * Returns a new Map which excludes the provided `keys`.
+     *
+     * Note: `deleteAll` can be used in `withMutations`.
+     *
+     * @alias removeAll
+     */
+    deleteAll(keys: Iterable<K>): this;
+    removeAll(keys: Iterable<K>): this;
+
+    /**
+     * Returns a new Map containing no keys or values.
+     *
+     * Note: `clear` can be used in `withMutations`.
+     */
+    clear(): this;
+
+    /**
+     * Returns a new Map having updated the value at this `key` with the return
+     * value of calling `updater` with the existing value.
+     *
+     * Similar to: `map.set(key, updater(map.get(key)))`.
+     *
+     * This is most commonly used to call methods on collections within a
+     * structure of data. For example, in order to `.push()` onto a nested `List`,
+     * `update` and `push` can be used together:
+     *
+     * When a `notSetValue` is provided, it is provided to the `updater`
+     * function when the value at the key does not exist in the Map.
+     *
+     * However, if the `updater` function returns the same value it was called
+     * with, then no change will occur. This is still true if `notSetValue`
+     * is provided.
+     *
+     * For code using ES2015 or later, using `notSetValue` is discourged in
+     * favor of function parameter default values. This helps to avoid any
+     * potential confusion with identify functions as described above.
+     *
+     * The previous example behaves differently when written with default values:
+     *
+     * If no key is provided, then the `updater` function return value is
+     * returned as well.
+     *
+     * This can be very useful as a way to "chain" a normal function into a
+     * sequence of methods. RxJS calls this "let" and lodash calls it "thru".
+     *
+     * For example, to sum the values in a Map
+     *
+     * Note: `update(key)` can be used in `withMutations`.
+     */
+    update(key: K, notSetValue: V, updater: (value: V) => V): this;
+    update(key: K, updater: (value: V | undefined) => V | undefined): this;
+    update<R>(updater: (value: this) => R): R;
+
+    /**
+     * Returns a new Map resulting from merging the provided Collections
+     * (or JS objects) into this Map. In other words, this takes each entry of
+     * each collection and sets it on this Map.
+     *
+     * Note: Values provided to `merge` are shallowly converted before being
+     * merged. No nested values are altered.
+     * ```
+     *
+     * Note: `merge` can be used in `withMutations`.
+     *
+     * @alias concat
+     */
+    merge<KC, VC>(
+      ...collections: Array<Iterable<[KC, VC]>>
+    ): Map<K | KC, Exclude<V, VC> | VC>;
+    merge<C>(
+      ...collections: Array<{ [key: string]: C }>
+    ): Map<K | string, Exclude<V, C> | C>;
+
+    concat<KC, VC>(
+      ...collections: Array<Iterable<[KC, VC]>>
+    ): Map<K | KC, Exclude<V, VC> | VC>;
+    concat<C>(
+      ...collections: Array<{ [key: string]: C }>
+    ): Map<K | string, Exclude<V, C> | C>;
+
+    /**
+     * Like `merge()`, `mergeWith()` returns a new Map resulting from merging
+     * the provided Collections (or JS objects) into this Map, but uses the
+     * `merger` function for dealing with conflicts.
+     *
+     * Note: `mergeWith` can be used in `withMutations`.
+     */
+    mergeWith<KC, VC, VCC>(
+      merger: (oldVal: V, newVal: VC, key: K) => VCC,
+      ...collections: Array<Iterable<[KC, VC]>>
+    ): Map<K | KC, V | VC | VCC>;
+    mergeWith<C, CC>(
+      merger: (oldVal: V, newVal: C, key: string) => CC,
+      ...collections: Array<{ [key: string]: C }>
+    ): Map<K | string, V | C | CC>;
+
+    /**
+     * Like `merge()`, but when two compatible collections are encountered with
+     * the same key, it merges them as well, recursing deeply through the nested
+     * data. Two collections are considered to be compatible (and thus will be
+     * merged together) if they both fall into one of three categories: keyed
+     * (e.g., `Map`s, `Record`s, and objects), indexed (e.g., `List`s and
+     * arrays), or set-like (e.g., `Set`s). If they fall into separate
+     * categories, `mergeDeep` will replace the existing collection with the
+     * collection being merged in. This behavior can be customized by using
+     * `mergeDeepWith()`.
+     *
+     * Note: Indexed and set-like collections are merged using
+     * `concat()`/`union()` and therefore do not recurse.
+     *
+     * Note: `mergeDeep` can be used in `withMutations`.
+     */
+    mergeDeep<KC, VC>(
+      ...collections: Array<Iterable<[KC, VC]>>
+    ): Map<K | KC, V | VC>;
+    mergeDeep<C>(
+      ...collections: Array<{ [key: string]: C }>
+    ): Map<K | string, V | C>;
+
+    /**
+     * Like `mergeDeep()`, but when two non-collections or incompatible
+     * collections are encountered at the same key, it uses the `merger`
+     * function to determine the resulting value. Collections are considered
+     * incompatible if they fall into separate categories between keyed,
+     * indexed, and set-like.
+     *
+     * Note: `mergeDeepWith` can be used in `withMutations`.
+     */
+    mergeDeepWith(
+      merger: (oldVal: unknown, newVal: unknown, key: unknown) => unknown,
+      ...collections: Array<Iterable<[K, V]> | { [key: string]: V }>
+    ): this;
+
+    // Deep persistent changes
+
+    /**
+     * Returns a new Map having set `value` at this `keyPath`. If any keys in
+     * `keyPath` do not exist, a new immutable Map will be created at that key.
+     *
+     * Plain JavaScript Object or Arrays may be nested within an Immutable.js
+     * Collection, and setIn() can update those values as well, treating them
+     * immutably by creating new copies of those values with the changes applied.
+     *
+     * If any key in the path exists but cannot be updated (such as a primitive
+     * like number or a custom Object like Date), an error will be thrown.
+     *
+     * Note: `setIn` can be used in `withMutations`.
+     */
+    setIn(keyPath: Iterable<unknown>, value: unknown): this;
+
+    /**
+     * Returns a new Map having removed the value at this `keyPath`. If any keys
+     * in `keyPath` do not exist, no change will occur.
+     *
+     * Note: `deleteIn` can be used in `withMutations`.
+     *
+     * @alias removeIn
+     */
+    deleteIn(keyPath: Iterable<unknown>): this;
+    removeIn(keyPath: Iterable<unknown>): this;
+
+    /**
+     * Returns a new Map having applied the `updater` to the entry found at the
+     * keyPath.
+     *
+     * This is most commonly used to call methods on collections nested within a
+     * structure of data. For example, in order to `.push()` onto a nested `List`,
+     * `updateIn` and `push` can be used together:
+
+     *
+     * If any keys in `keyPath` do not exist, new Immutable `Map`s will
+     * be created at those keys. If the `keyPath` does not already contain a
+     * value, the `updater` function will be called with `notSetValue`, if
+     * provided, otherwise `undefined`.
+     *
+     * If the `updater` function returns the same value it was called with, then
+     * no change will occur. This is still true if `notSetValue` is provided.
+     *
+     * For code using ES2015 or later, using `notSetValue` is discourged in
+     * favor of function parameter default values. This helps to avoid any
+     * potential confusion with identify functions as described above.
+     *
+     * The previous example behaves differently when written with default values:
+     *
+     * Plain JavaScript Object or Arrays may be nested within an Immutable.js
+     * Collection, and updateIn() can update those values as well, treating them
+     * immutably by creating new copies of those values with the changes applied.
+     *
+     * If any key in the path exists but cannot be updated (such as a primitive
+     * like number or a custom Object like Date), an error will be thrown.
+     *
+     * Note: `updateIn` can be used in `withMutations`.
+     */
+    updateIn(
+      keyPath: Iterable<unknown>,
+      notSetValue: unknown,
+      updater: (value: unknown) => unknown
+    ): this;
+    updateIn(
+      keyPath: Iterable<unknown>,
+      updater: (value: unknown) => unknown
+    ): this;
+
+    /**
+     * A combination of `updateIn` and `merge`, returning a new Map, but
+     * performing the merge at a point arrived at by following the keyPath.
+     * In other words, these two lines are equivalent:
+     *
+     * ```js
+     * map.updateIn(['a', 'b', 'c'], abc => abc.merge(y))
+     * map.mergeIn(['a', 'b', 'c'], y)
+     * ```
+     *
+     * Note: `mergeIn` can be used in `withMutations`.
+     */
+    mergeIn(keyPath: Iterable<unknown>, ...collections: Array<unknown>): this;
+
+    /**
+     * A combination of `updateIn` and `mergeDeep`, returning a new Map, but
+     * performing the deep merge at a point arrived at by following the keyPath.
+     * In other words, these two lines are equivalent:
+     *
+     * ```js
+     * map.updateIn(['a', 'b', 'c'], abc => abc.mergeDeep(y))
+     * map.mergeDeepIn(['a', 'b', 'c'], y)
+     * ```
+     *
+     * Note: `mergeDeepIn` can be used in `withMutations`.
+     */
+    mergeDeepIn(
+      keyPath: Iterable<unknown>,
+      ...collections: Array<unknown>
+    ): this;
+
+    // Transient changes
+
+    /**
+     * Every time you call one of the above functions, a new immutable Map is
+     * created. If a pure function calls a number of these to produce a final
+     * return value, then a penalty on performance and memory has been paid by
+     * creating all of the intermediate immutable Maps.
+     *
+     * If you need to apply a series of mutations to produce a new immutable
+     * Map, `withMutations()` creates a temporary mutable copy of the Map which
+     * can apply mutations in a highly performant manner. In fact, this is
+     * exactly how complex mutations like `merge` are done.
+     *
+     * As an example, this results in the creation of 2, not 4, new Maps:
+     *
+     * Note: Not all methods can be used on a mutable collection or within
+     * `withMutations`! Read the documentation for each method to see if it
+     * is safe to use in `withMutations`.
+     */
+    withMutations(mutator: (mutable: this) => unknown): this;
+
+    /**
+     * Another way to avoid creation of intermediate Immutable maps is to create
+     * a mutable copy of this collection. Mutable copies *always* return `this`,
+     * and thus shouldn't be used for equality. Your function should never return
+     * a mutable copy of a collection, only use it internally to create a new
+     * collection.
+     *
+     * If possible, use `withMutations` to work with temporary mutable copies as
+     * it provides an easier to use API and considers many common optimizations.
+     *
+     * Note: if the collection is already mutable, `asMutable` returns itself.
+     *
+     * Note: Not all methods can be used on a mutable collection or within
+     * `withMutations`! Read the documentation for each method to see if it
+     * is safe to use in `withMutations`.
+     *
+     * @see `Map#asImmutable`
+     */
+    asMutable(): this;
+
+    /**
+     * Returns true if this is a mutable copy (see `asMutable()`) and mutative
+     * alterations have been applied.
+     *
+     * @see `Map#asMutable`
+     */
+    wasAltered(): boolean;
+
+    /**
+     * The yin to `asMutable`'s yang. Because it applies to mutable collections,
+     * this operation is *mutable* and may return itself (though may not
+     * return itself, i.e. if the result is an empty collection). Once
+     * performed, the original mutable copy must no longer be mutated since it
+     * may be the immutable result.
+     *
+     * If possible, use `withMutations` to work with temporary mutable copies as
+     * it provides an easier to use API and considers many common optimizations.
+     *
+     * @see `Map#asMutable`
+     */
+    asImmutable(): this;
+
+    // Sequence algorithms
+
+    /**
+     * Returns a new Map with values passed through a
+     * `mapper` function.
+     *
+     *     Map({ a: 1, b: 2 }).map(x => 10 * x)
+     *     // Map { a: 10, b: 20 }
+     */
+    map<M>(
+      mapper: (value: V, key: K, iter: this) => M,
+      context?: unknown
+    ): Map<K, M>;
+
+    /**
+     * @see Collection.Keyed.mapKeys
+     */
+    mapKeys<M>(
+      mapper: (key: K, value: V, iter: this) => M,
+      context?: unknown
+    ): Map<M, V>;
+
+    /**
+     * @see Collection.Keyed.mapEntries
+     */
+    mapEntries<KM, VM>(
+      mapper: (
+        entry: [K, V],
+        index: number,
+        iter: this
+      ) => [KM, VM] | undefined,
+      context?: unknown
+    ): Map<KM, VM>;
+
+    /**
+     * Flat-maps the Map, returning a new Map.
+     *
+     * Similar to `data.map(...).flatten(true)`.
+     */
+    flatMap<KM, VM>(
+      mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>,
+      context?: unknown
+    ): Map<KM, VM>;
+
+    /**
+     * Returns a new Map with only the entries for which the `predicate`
+     * function returns true.
+     *
+     * Note: `filter()` always returns a new instance, even if it results in
+     * not filtering out any values.
+     */
+    filter<F extends V>(
+      predicate: (value: V, key: K, iter: this) => value is F,
+      context?: unknown
+    ): Map<K, F>;
+    filter(
+      predicate: (value: V, key: K, iter: this) => unknown,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new Map with the values for which the `predicate`
+     * function returns false and another for which is returns true.
+     */
+    partition<F extends V, C>(
+      predicate: (this: C, value: V, key: K, iter: this) => value is F,
+      context?: C
+    ): [Map<K, V>, Map<K, F>];
+    partition<C>(
+      predicate: (this: C, value: V, key: K, iter: this) => unknown,
+      context?: C
+    ): [this, this];
+
+    /**
+     * @see Collection.Keyed.flip
+     */
+    flip(): Map<V, K>;
+
+    /**
+     * Returns an OrderedMap of the same type which includes the same entries,
+     * stably sorted by using a `comparator`.
+     *
+     * If a `comparator` is not provided, a default comparator uses `<` and `>`.
+     *
+     * `comparator(valueA, valueB)`:
+     *
+     *   * Returns `0` if the elements should not be swapped.
+     *   * Returns `-1` (or any negative number) if `valueA` comes before `valueB`
+     *   * Returns `1` (or any positive number) if `valueA` comes after `valueB`
+     *   * Alternatively, can return a value of the `PairSorting` enum type
+     *   * Is pure, i.e. it must always return the same value for the same pair
+     *     of values.
+     *
+     * Note: `sort()` Always returns a new instance, even if the original was
+     * already sorted.
+     *
+     * Note: This is always an eager operation.
+     */
+    sort(comparator?: Comparator<V>): this & OrderedMap<K, V>;
+
+    /**
+     * Like `sort`, but also accepts a `comparatorValueMapper` which allows for
+     * sorting by more sophisticated means:
+     *
+     * Note: `sortBy()` Always returns a new instance, even if the original was
+     * already sorted.
+     *
+     * Note: This is always an eager operation.
+     */
+    sortBy<C>(
+      comparatorValueMapper: (value: V, key: K, iter: this) => C,
+      comparator?: (valueA: C, valueB: C) => number
+    ): this & OrderedMap<K, V>;
+  }
+
+  /**
+   * A type of Map that has the additional guarantee that the iteration order of
+   * entries will be the order in which they were set().
+   *
+   * The iteration behavior of OrderedMap is the same as native ES6 Map and
+   * JavaScript Object.
+   *
+   * Note that `OrderedMap` are more expensive than non-ordered `Map` and may
+   * consume more memory. `OrderedMap#set` is amortized O(log32 N), but not
+   * stable.
+   */
+  namespace OrderedMap {
+    /**
+     * True if the provided value is an OrderedMap.
+     */
+    function isOrderedMap(
+      maybeOrderedMap: unknown
+    ): maybeOrderedMap is OrderedMap<unknown, unknown>;
+  }
+
+  /**
+   * Creates a new Immutable OrderedMap.
+   *
+   * Created with the same key value pairs as the provided Collection.Keyed or
+   * JavaScript Object or expects a Collection of [K, V] tuple entries.
+   *
+   * The iteration order of key-value pairs provided to this constructor will
+   * be preserved in the OrderedMap.
+   *
+   *     let newOrderedMap = OrderedMap({key: "value"})
+   *     let newOrderedMap = OrderedMap([["key", "value"]])
+   *
+   * Note: `OrderedMap` is a factory function and not a class, and does not use
+   * the `new` keyword during construction.
+   */
+  function OrderedMap<K, V>(collection?: Iterable<[K, V]>): OrderedMap<K, V>;
+  function OrderedMap<V>(obj: { [key: string]: V }): OrderedMap<string, V>;
+
+  interface OrderedMap<K, V> extends Map<K, V>, OrderedCollection<[K, V]> {
+    /**
+     * The number of entries in this OrderedMap.
+     */
+    readonly size: number;
+
+    /**
+     * Returns a new OrderedMap also containing the new key, value pair. If an
+     * equivalent key already exists in this OrderedMap, it will be replaced
+     * while maintaining the existing order.
+     *
+     * Note: `set` can be used in `withMutations`.
+     */
+    set(key: K, value: V): this;
+
+    /**
+     * Returns a new OrderedMap resulting from merging the provided Collections
+     * (or JS objects) into this OrderedMap. In other words, this takes each
+     * entry of each collection and sets it on this OrderedMap.
+     *
+     * Note: Values provided to `merge` are shallowly converted before being
+     * merged. No nested values are altered.
+     *
+     * Note: `merge` can be used in `withMutations`.
+     *
+     * @alias concat
+     */
+    merge<KC, VC>(
+      ...collections: Array<Iterable<[KC, VC]>>
+    ): OrderedMap<K | KC, Exclude<V, VC> | VC>;
+    merge<C>(
+      ...collections: Array<{ [key: string]: C }>
+    ): OrderedMap<K | string, Exclude<V, C> | C>;
+
+    concat<KC, VC>(
+      ...collections: Array<Iterable<[KC, VC]>>
+    ): OrderedMap<K | KC, Exclude<V, VC> | VC>;
+    concat<C>(
+      ...collections: Array<{ [key: string]: C }>
+    ): OrderedMap<K | string, Exclude<V, C> | C>;
+
+    mergeWith<KC, VC, VCC>(
+      merger: (oldVal: V, newVal: VC, key: K) => VCC,
+      ...collections: Array<Iterable<[KC, VC]>>
+    ): OrderedMap<K | KC, V | VC | VCC>;
+    mergeWith<C, CC>(
+      merger: (oldVal: V, newVal: C, key: string) => CC,
+      ...collections: Array<{ [key: string]: C }>
+    ): OrderedMap<K | string, V | C | CC>;
+
+    mergeDeep<KC, VC>(
+      ...collections: Array<Iterable<[KC, VC]>>
+    ): OrderedMap<K | KC, V | VC>;
+    mergeDeep<C>(
+      ...collections: Array<{ [key: string]: C }>
+    ): OrderedMap<K | string, V | C>;
+
+    // Sequence algorithms
+
+    /**
+     * Returns a new OrderedMap with values passed through a
+     * `mapper` function.
+     *
+     *     OrderedMap({ a: 1, b: 2 }).map(x => 10 * x)
+     *     // OrderedMap { "a": 10, "b": 20 }
+     *
+     * Note: `map()` always returns a new instance, even if it produced the same
+     * value at every step.
+     */
+    map<M>(
+      mapper: (value: V, key: K, iter: this) => M,
+      context?: unknown
+    ): OrderedMap<K, M>;
+
+    /**
+     * @see Collection.Keyed.mapKeys
+     */
+    mapKeys<M>(
+      mapper: (key: K, value: V, iter: this) => M,
+      context?: unknown
+    ): OrderedMap<M, V>;
+
+    /**
+     * @see Collection.Keyed.mapEntries
+     */
+    mapEntries<KM, VM>(
+      mapper: (
+        entry: [K, V],
+        index: number,
+        iter: this
+      ) => [KM, VM] | undefined,
+      context?: unknown
+    ): OrderedMap<KM, VM>;
+
+    /**
+     * Flat-maps the OrderedMap, returning a new OrderedMap.
+     *
+     * Similar to `data.map(...).flatten(true)`.
+     */
+    flatMap<KM, VM>(
+      mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>,
+      context?: unknown
+    ): OrderedMap<KM, VM>;
+
+    /**
+     * Returns a new OrderedMap with only the entries for which the `predicate`
+     * function returns true.
+     *
+     * Note: `filter()` always returns a new instance, even if it results in
+     * not filtering out any values.
+     */
+    filter<F extends V>(
+      predicate: (value: V, key: K, iter: this) => value is F,
+      context?: unknown
+    ): OrderedMap<K, F>;
+    filter(
+      predicate: (value: V, key: K, iter: this) => unknown,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new OrderedMap with the values for which the `predicate`
+     * function returns false and another for which is returns true.
+     */
+    partition<F extends V, C>(
+      predicate: (this: C, value: V, key: K, iter: this) => value is F,
+      context?: C
+    ): [OrderedMap<K, V>, OrderedMap<K, F>];
+    partition<C>(
+      predicate: (this: C, value: V, key: K, iter: this) => unknown,
+      context?: C
+    ): [this, this];
+
+    /**
+     * @see Collection.Keyed.flip
+     */
+    flip(): OrderedMap<V, K>;
+  }
+
+  /**
+   * A Collection of unique values with `O(log32 N)` adds and has.
+   *
+   * When iterating a Set, the entries will be (value, value) pairs. Iteration
+   * order of a Set is undefined, however is stable. Multiple iterations of the
+   * same Set will iterate in the same order.
+   *
+   * Set values, like Map keys, may be of any type. Equality is determined using
+   * `Immutable.is`, enabling Sets to uniquely include other Immutable
+   * collections, custom value types, and NaN.
+   */
+  namespace Set {
+    /**
+     * True if the provided value is a Set
+     */
+    function isSet(maybeSet: unknown): maybeSet is Set<unknown>;
+
+    /**
+     * Creates a new Set containing `values`.
+     */
+    function of<T>(...values: Array<T>): Set<T>;
+
+    /**
+     * `Set.fromKeys()` creates a new immutable Set containing the keys from
+     * this Collection or JavaScript Object.
+     */
+    function fromKeys<T>(iter: Collection.Keyed<T, unknown>): Set<T>;
+    function fromKeys<T>(iter: Collection<T, unknown>): Set<T>;
+    function fromKeys(obj: { [key: string]: unknown }): Set<string>;
+
+    /**
+     * `Set.intersect()` creates a new immutable Set that is the intersection of
+     * a collection of other sets.
+     *
+     * ```js
+     * import { Set } from 'immutable'
+     * const intersected = Set.intersect([
+     *   Set([ 'a', 'b', 'c' ])
+     *   Set([ 'c', 'a', 't' ])
+     * ])
+     * // Set [ "a", "c" ]
+     * ```
+     */
+    function intersect<T>(sets: Iterable<Iterable<T>>): Set<T>;
+
+    /**
+     * `Set.union()` creates a new immutable Set that is the union of a
+     * collection of other sets.
+     *
+     * ```js
+     * import { Set } from 'immutable'
+     * const unioned = Set.union([
+     *   Set([ 'a', 'b', 'c' ])
+     *   Set([ 'c', 'a', 't' ])
+     * ])
+     * // Set [ "a", "b", "c", "t" ]
+     * ```
+     */
+    function union<T>(sets: Iterable<Iterable<T>>): Set<T>;
+  }
+
+  /**
+   * Create a new immutable Set containing the values of the provided
+   * collection-like.
+   *
+   * Note: `Set` is a factory function and not a class, and does not use the
+   * `new` keyword during construction.
+   */
+  function Set<T>(collection?: Iterable<T> | ArrayLike<T>): Set<T>;
+
+  interface Set<T> extends Collection.Set<T> {
+    /**
+     * The number of items in this Set.
+     */
+    readonly size: number;
+
+    // Persistent changes
+
+    /**
+     * Returns a new Set which also includes this value.
+     *
+     * Note: `add` can be used in `withMutations`.
+     */
+    add(value: T): this;
+
+    /**
+     * Returns a new Set which excludes this value.
+     *
+     * Note: `delete` can be used in `withMutations`.
+     *
+     * Note: `delete` **cannot** be safely used in IE8, use `remove` if
+     * supporting old browsers.
+     *
+     * @alias remove
+     */
+    delete(value: T): this;
+    remove(value: T): this;
+
+    /**
+     * Returns a new Set containing no values.
+     *
+     * Note: `clear` can be used in `withMutations`.
+     */
+    clear(): this;
+
+    /**
+     * Returns a Set including any value from `collections` that does not already
+     * exist in this Set.
+     *
+     * Note: `union` can be used in `withMutations`.
+     * @alias merge
+     * @alias concat
+     */
+    union<C>(...collections: Array<Iterable<C>>): Set<T | C>;
+    merge<C>(...collections: Array<Iterable<C>>): Set<T | C>;
+    concat<C>(...collections: Array<Iterable<C>>): Set<T | C>;
+
+    /**
+     * Returns a Set which has removed any values not also contained
+     * within `collections`.
+     *
+     * Note: `intersect` can be used in `withMutations`.
+     */
+    intersect(...collections: Array<Iterable<T>>): this;
+
+    /**
+     * Returns a Set excluding any values contained within `collections`.
+     *
+     * Note: `subtract` can be used in `withMutations`.
+     */
+    subtract(...collections: Array<Iterable<T>>): this;
+
+    // Transient changes
+
+    /**
+     * Note: Not all methods can be used on a mutable collection or within
+     * `withMutations`! Check the documentation for each method to see if it
+     * mentions being safe to use in `withMutations`.
+     *
+     * @see `Map#withMutations`
+     */
+    withMutations(mutator: (mutable: this) => unknown): this;
+
+    /**
+     * Note: Not all methods can be used on a mutable collection or within
+     * `withMutations`! Check the documentation for each method to see if it
+     * mentions being safe to use in `withMutations`.
+     *
+     * @see `Map#asMutable`
+     */
+    asMutable(): this;
+
+    /**
+     * @see `Map#wasAltered`
+     */
+    wasAltered(): boolean;
+
+    /**
+     * @see `Map#asImmutable`
+     */
+    asImmutable(): this;
+
+    // Sequence algorithms
+
+    /**
+     * Returns a new Set with values passed through a
+     * `mapper` function.
+     *
+     *     Set([1,2]).map(x => 10 * x)
+     *     // Set [10,20]
+     */
+    map<M>(
+      mapper: (value: T, key: T, iter: this) => M,
+      context?: unknown
+    ): Set<M>;
+
+    /**
+     * Flat-maps the Set, returning a new Set.
+     *
+     * Similar to `set.map(...).flatten(true)`.
+     */
+    flatMap<M>(
+      mapper: (value: T, key: T, iter: this) => Iterable<M>,
+      context?: unknown
+    ): Set<M>;
+
+    /**
+     * Returns a new Set with only the values for which the `predicate`
+     * function returns true.
+     *
+     * Note: `filter()` always returns a new instance, even if it results in
+     * not filtering out any values.
+     */
+    filter<F extends T>(
+      predicate: (value: T, key: T, iter: this) => value is F,
+      context?: unknown
+    ): Set<F>;
+    filter(
+      predicate: (value: T, key: T, iter: this) => unknown,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new Set with the values for which the `predicate` function
+     * returns false and another for which is returns true.
+     */
+    partition<F extends T, C>(
+      predicate: (this: C, value: T, key: T, iter: this) => value is F,
+      context?: C
+    ): [Set<T>, Set<F>];
+    partition<C>(
+      predicate: (this: C, value: T, key: T, iter: this) => unknown,
+      context?: C
+    ): [this, this];
+
+    /**
+     * Returns an OrderedSet of the same type which includes the same entries,
+     * stably sorted by using a `comparator`.
+     *
+     * If a `comparator` is not provided, a default comparator uses `<` and `>`.
+     *
+     * `comparator(valueA, valueB)`:
+     *
+     *   * Returns `0` if the elements should not be swapped.
+     *   * Returns `-1` (or any negative number) if `valueA` comes before `valueB`
+     *   * Returns `1` (or any positive number) if `valueA` comes after `valueB`
+     *   * Alternatively, can return a value of the `PairSorting` enum type
+     *   * Is pure, i.e. it must always return the same value for the same pair
+     *     of values.
+     *
+     * Note: `sort()` Always returns a new instance, even if the original was
+     * already sorted.
+     *
+     * Note: This is always an eager operation.
+     */
+    sort(comparator?: Comparator<T>): this & OrderedSet<T>;
+
+    /**
+     * Like `sort`, but also accepts a `comparatorValueMapper` which allows for
+     * sorting by more sophisticated means:
+     *
+     * Note: `sortBy()` Always returns a new instance, even if the original was
+     * already sorted.
+     *
+     * Note: This is always an eager operation.
+     */
+    sortBy<C>(
+      comparatorValueMapper: (value: T, key: T, iter: this) => C,
+      comparator?: (valueA: C, valueB: C) => number
+    ): this & OrderedSet<T>;
+  }
+
+  /**
+   * A type of Set that has the additional guarantee that the iteration order of
+   * values will be the order in which they were `add`ed.
+   *
+   * The iteration behavior of OrderedSet is the same as native ES6 Set.
+   *
+   * Note that `OrderedSet` are more expensive than non-ordered `Set` and may
+   * consume more memory. `OrderedSet#add` is amortized O(log32 N), but not
+   * stable.
+   */
+  namespace OrderedSet {
+    /**
+     * True if the provided value is an OrderedSet.
+     */
+    function isOrderedSet(
+      maybeOrderedSet: unknown
+    ): maybeOrderedSet is OrderedSet<unknown>;
+
+    /**
+     * Creates a new OrderedSet containing `values`.
+     */
+    function of<T>(...values: Array<T>): OrderedSet<T>;
+
+    /**
+     * `OrderedSet.fromKeys()` creates a new immutable OrderedSet containing
+     * the keys from this Collection or JavaScript Object.
+     */
+    function fromKeys<T>(iter: Collection.Keyed<T, unknown>): OrderedSet<T>;
+    function fromKeys<T>(iter: Collection<T, unknown>): OrderedSet<T>;
+    function fromKeys(obj: { [key: string]: unknown }): OrderedSet<string>;
+  }
+
+  /**
+   * Create a new immutable OrderedSet containing the values of the provided
+   * collection-like.
+   *
+   * Note: `OrderedSet` is a factory function and not a class, and does not use
+   * the `new` keyword during construction.
+   */
+  function OrderedSet<T>(
+    collection?: Iterable<T> | ArrayLike<T>
+  ): OrderedSet<T>;
+
+  interface OrderedSet<T> extends Set<T>, OrderedCollection<T> {
+    /**
+     * The number of items in this OrderedSet.
+     */
+    readonly size: number;
+
+    /**
+     * Returns an OrderedSet including any value from `collections` that does
+     * not already exist in this OrderedSet.
+     *
+     * Note: `union` can be used in `withMutations`.
+     * @alias merge
+     * @alias concat
+     */
+    union<C>(...collections: Array<Iterable<C>>): OrderedSet<T | C>;
+    merge<C>(...collections: Array<Iterable<C>>): OrderedSet<T | C>;
+    concat<C>(...collections: Array<Iterable<C>>): OrderedSet<T | C>;
+
+    // Sequence algorithms
+
+    /**
+     * Returns a new Set with values passed through a
+     * `mapper` function.
+     *
+     *     OrderedSet([ 1, 2 ]).map(x => 10 * x)
+     *     // OrderedSet [10, 20]
+     */
+    map<M>(
+      mapper: (value: T, key: T, iter: this) => M,
+      context?: unknown
+    ): OrderedSet<M>;
+
+    /**
+     * Flat-maps the OrderedSet, returning a new OrderedSet.
+     *
+     * Similar to `set.map(...).flatten(true)`.
+     */
+    flatMap<M>(
+      mapper: (value: T, key: T, iter: this) => Iterable<M>,
+      context?: unknown
+    ): OrderedSet<M>;
+
+    /**
+     * Returns a new OrderedSet with only the values for which the `predicate`
+     * function returns true.
+     *
+     * Note: `filter()` always returns a new instance, even if it results in
+     * not filtering out any values.
+     */
+    filter<F extends T>(
+      predicate: (value: T, key: T, iter: this) => value is F,
+      context?: unknown
+    ): OrderedSet<F>;
+    filter(
+      predicate: (value: T, key: T, iter: this) => unknown,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new OrderedSet with the values for which the `predicate`
+     * function returns false and another for which is returns true.
+     */
+    partition<F extends T, C>(
+      predicate: (this: C, value: T, key: T, iter: this) => value is F,
+      context?: C
+    ): [OrderedSet<T>, OrderedSet<F>];
+    partition<C>(
+      predicate: (this: C, value: T, key: T, iter: this) => unknown,
+      context?: C
+    ): [this, this];
+
+    /**
+     * Returns an OrderedSet of the same type "zipped" with the provided
+     * collections.
+     *
+     * Like `zipWith`, but using the default `zipper`: creating an `Array`.
+     *
+     * ```js
+     * const a = OrderedSet([ 1, 2, 3 ])
+     * const b = OrderedSet([ 4, 5, 6 ])
+     * const c = a.zip(b)
+     * // OrderedSet [ [ 1, 4 ], [ 2, 5 ], [ 3, 6 ] ]
+     * ```
+     */
+    zip<U>(other: Collection<unknown, U>): OrderedSet<[T, U]>;
+    zip<U, V>(
+      other1: Collection<unknown, U>,
+      other2: Collection<unknown, V>
+    ): OrderedSet<[T, U, V]>;
+    zip(
+      ...collections: Array<Collection<unknown, unknown>>
+    ): OrderedSet<unknown>;
+
+    /**
+     * Returns a OrderedSet of the same type "zipped" with the provided
+     * collections.
+     *
+     * Unlike `zip`, `zipAll` continues zipping until the longest collection is
+     * exhausted. Missing values from shorter collections are filled with `undefined`.
+     *
+     * ```js
+     * const a = OrderedSet([ 1, 2 ]);
+     * const b = OrderedSet([ 3, 4, 5 ]);
+     * const c = a.zipAll(b); // OrderedSet [ [ 1, 3 ], [ 2, 4 ], [ undefined, 5 ] ]
+     * ```
+     *
+     * Note: Since zipAll will return a collection as large as the largest
+     * input, some results may contain undefined values. TypeScript cannot
+     * account for these without cases (as of v2.5).
+     */
+    zipAll<U>(other: Collection<unknown, U>): OrderedSet<[T, U]>;
+    zipAll<U, V>(
+      other1: Collection<unknown, U>,
+      other2: Collection<unknown, V>
+    ): OrderedSet<[T, U, V]>;
+    zipAll(
+      ...collections: Array<Collection<unknown, unknown>>
+    ): OrderedSet<unknown>;
+
+    /**
+     * Returns an OrderedSet of the same type "zipped" with the provided
+     * collections by using a custom `zipper` function.
+     *
+     * @see Seq.Indexed.zipWith
+     */
+    zipWith<U, Z>(
+      zipper: (value: T, otherValue: U) => Z,
+      otherCollection: Collection<unknown, U>
+    ): OrderedSet<Z>;
+    zipWith<U, V, Z>(
+      zipper: (value: T, otherValue: U, thirdValue: V) => Z,
+      otherCollection: Collection<unknown, U>,
+      thirdCollection: Collection<unknown, V>
+    ): OrderedSet<Z>;
+    zipWith<Z>(
+      zipper: (...values: Array<unknown>) => Z,
+      ...collections: Array<Collection<unknown, unknown>>
+    ): OrderedSet<Z>;
+  }
+
+  /**
+   * Stacks are indexed collections which support very efficient O(1) addition
+   * and removal from the front using `unshift(v)` and `shift()`.
+   *
+   * For familiarity, Stack also provides `push(v)`, `pop()`, and `peek()`, but
+   * be aware that they also operate on the front of the list, unlike List or
+   * a JavaScript Array.
+   *
+   * Note: `reverse()` or any inherent reverse traversal (`reduceRight`,
+   * `lastIndexOf`, etc.) is not efficient with a Stack.
+   *
+   * Stack is implemented with a Single-Linked List.
+   */
+  namespace Stack {
+    /**
+     * True if the provided value is a Stack
+     */
+    function isStack(maybeStack: unknown): maybeStack is Stack<unknown>;
+
+    /**
+     * Creates a new Stack containing `values`.
+     */
+    function of<T>(...values: Array<T>): Stack<T>;
+  }
+
+  /**
+   * Create a new immutable Stack containing the values of the provided
+   * collection-like.
+   *
+   * The iteration order of the provided collection is preserved in the
+   * resulting `Stack`.
+   *
+   * Note: `Stack` is a factory function and not a class, and does not use the
+   * `new` keyword during construction.
+   */
+  function Stack<T>(collection?: Iterable<T> | ArrayLike<T>): Stack<T>;
+
+  interface Stack<T> extends Collection.Indexed<T> {
+    /**
+     * The number of items in this Stack.
+     */
+    readonly size: number;
+
+    // Reading values
+
+    /**
+     * Alias for `Stack.first()`.
+     */
+    peek(): T | undefined;
+
+    // Persistent changes
+
+    /**
+     * Returns a new Stack with 0 size and no values.
+     *
+     * Note: `clear` can be used in `withMutations`.
+     */
+    clear(): Stack<T>;
+
+    /**
+     * Returns a new Stack with the provided `values` prepended, shifting other
+     * values ahead to higher indices.
+     *
+     * This is very efficient for Stack.
+     *
+     * Note: `unshift` can be used in `withMutations`.
+     */
+    unshift(...values: Array<T>): Stack<T>;
+
+    /**
+     * Like `Stack#unshift`, but accepts a collection rather than varargs.
+     *
+     * Note: `unshiftAll` can be used in `withMutations`.
+     */
+    unshiftAll(iter: Iterable<T>): Stack<T>;
+
+    /**
+     * Returns a new Stack with a size ones less than this Stack, excluding
+     * the first item in this Stack, shifting all other values to a lower index.
+     *
+     * Note: this differs from `Array#shift` because it returns a new
+     * Stack rather than the removed value. Use `first()` or `peek()` to get the
+     * first value in this Stack.
+     *
+     * Note: `shift` can be used in `withMutations`.
+     */
+    shift(): Stack<T>;
+
+    /**
+     * Alias for `Stack#unshift` and is not equivalent to `List#push`.
+     */
+    push(...values: Array<T>): Stack<T>;
+
+    /**
+     * Alias for `Stack#unshiftAll`.
+     */
+    pushAll(iter: Iterable<T>): Stack<T>;
+
+    /**
+     * Alias for `Stack#shift` and is not equivalent to `List#pop`.
+     */
+    pop(): Stack<T>;
+
+    // Transient changes
+
+    /**
+     * Note: Not all methods can be used on a mutable collection or within
+     * `withMutations`! Check the documentation for each method to see if it
+     * mentions being safe to use in `withMutations`.
+     *
+     * @see `Map#withMutations`
+     */
+    withMutations(mutator: (mutable: this) => unknown): this;
+
+    /**
+     * Note: Not all methods can be used on a mutable collection or within
+     * `withMutations`! Check the documentation for each method to see if it
+     * mentions being safe to use in `withMutations`.
+     *
+     * @see `Map#asMutable`
+     */
+    asMutable(): this;
+
+    /**
+     * @see `Map#wasAltered`
+     */
+    wasAltered(): boolean;
+
+    /**
+     * @see `Map#asImmutable`
+     */
+    asImmutable(): this;
+
+    // Sequence algorithms
+
+    /**
+     * Returns a new Stack with other collections concatenated to this one.
+     */
+    concat<C>(...valuesOrCollections: Array<Iterable<C> | C>): Stack<T | C>;
+
+    /**
+     * Returns a new Stack with values passed through a
+     * `mapper` function.
+     *
+     *     Stack([ 1, 2 ]).map(x => 10 * x)
+     *     // Stack [ 10, 20 ]
+     *
+     * Note: `map()` always returns a new instance, even if it produced the same
+     * value at every step.
+     */
+    map<M>(
+      mapper: (value: T, key: number, iter: this) => M,
+      context?: unknown
+    ): Stack<M>;
+
+    /**
+     * Flat-maps the Stack, returning a new Stack.
+     *
+     * Similar to `stack.map(...).flatten(true)`.
+     */
+    flatMap<M>(
+      mapper: (value: T, key: number, iter: this) => Iterable<M>,
+      context?: unknown
+    ): Stack<M>;
+
+    /**
+     * Returns a new Set with only the values for which the `predicate`
+     * function returns true.
+     *
+     * Note: `filter()` always returns a new instance, even if it results in
+     * not filtering out any values.
+     */
+    filter<F extends T>(
+      predicate: (value: T, index: number, iter: this) => value is F,
+      context?: unknown
+    ): Set<F>;
+    filter(
+      predicate: (value: T, index: number, iter: this) => unknown,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a Stack "zipped" with the provided collections.
+     *
+     * Like `zipWith`, but using the default `zipper`: creating an `Array`.
+     *
+     * ```js
+     * const a = Stack([ 1, 2, 3 ]);
+     * const b = Stack([ 4, 5, 6 ]);
+     * const c = a.zip(b); // Stack [ [ 1, 4 ], [ 2, 5 ], [ 3, 6 ] ]
+     * ```
+     */
+    zip<U>(other: Collection<unknown, U>): Stack<[T, U]>;
+    zip<U, V>(
+      other: Collection<unknown, U>,
+      other2: Collection<unknown, V>
+    ): Stack<[T, U, V]>;
+    zip(...collections: Array<Collection<unknown, unknown>>): Stack<unknown>;
+
+    /**
+     * Returns a Stack "zipped" with the provided collections.
+     *
+     * Unlike `zip`, `zipAll` continues zipping until the longest collection is
+     * exhausted. Missing values from shorter collections are filled with `undefined`.
+     *
+     * ```js
+     * const a = Stack([ 1, 2 ]);
+     * const b = Stack([ 3, 4, 5 ]);
+     * const c = a.zipAll(b); // Stack [ [ 1, 3 ], [ 2, 4 ], [ undefined, 5 ] ]
+     * ```
+     *
+     * Note: Since zipAll will return a collection as large as the largest
+     * input, some results may contain undefined values. TypeScript cannot
+     * account for these without cases (as of v2.5).
+     */
+    zipAll<U>(other: Collection<unknown, U>): Stack<[T, U]>;
+    zipAll<U, V>(
+      other: Collection<unknown, U>,
+      other2: Collection<unknown, V>
+    ): Stack<[T, U, V]>;
+    zipAll(...collections: Array<Collection<unknown, unknown>>): Stack<unknown>;
+
+    /**
+     * Returns a Stack "zipped" with the provided collections by using a
+     * custom `zipper` function.
+     *
+     * ```js
+     * const a = Stack([ 1, 2, 3 ]);
+     * const b = Stack([ 4, 5, 6 ]);
+     * const c = a.zipWith((a, b) => a + b, b);
+     * // Stack [ 5, 7, 9 ]
+     * ```
+     */
+    zipWith<U, Z>(
+      zipper: (value: T, otherValue: U) => Z,
+      otherCollection: Collection<unknown, U>
+    ): Stack<Z>;
+    zipWith<U, V, Z>(
+      zipper: (value: T, otherValue: U, thirdValue: V) => Z,
+      otherCollection: Collection<unknown, U>,
+      thirdCollection: Collection<unknown, V>
+    ): Stack<Z>;
+    zipWith<Z>(
+      zipper: (...values: Array<unknown>) => Z,
+      ...collections: Array<Collection<unknown, unknown>>
+    ): Stack<Z>;
+  }
+
+  /**
+   * Returns a Seq.Indexed of numbers from `start` (inclusive) to `end`
+   * (exclusive), by `step`, where `start` defaults to 0, `step` to 1, and `end` to
+   * infinity. When `start` is equal to `end`, returns empty range.
+   *
+   * Note: `Range` is a factory function and not a class, and does not use the
+   * `new` keyword during construction.
+   *
+   * ```js
+   * import { Range } from 'immutable'
+   * Range(10, 15) // [ 10, 11, 12, 13, 14 ]
+   * Range(10, 30, 5) // [ 10, 15, 20, 25 ]
+   * Range(30, 10, 5) // [ 30, 25, 20, 15 ]
+   * Range(30, 30, 5) // []
+   * ```
+   */
+  function Range(
+    start: number,
+    end: number,
+    step?: number
+  ): Seq.Indexed<number>;
+
+  /**
+   * Returns a Seq.Indexed of `value` repeated `times` times. When `times` is
+   * not defined, returns an infinite `Seq` of `value`.
+   *
+   * Note: `Repeat` is a factory function and not a class, and does not use the
+   * `new` keyword during construction.
+   *
+   * ```js
+   * import { Repeat } from 'immutable'
+   * Repeat('foo') // [ 'foo', 'foo', 'foo', ... ]
+   * Repeat('bar', 4) // [ 'bar', 'bar', 'bar', 'bar' ]
+   * ```
+   */
+  function Repeat<T>(value: T, times?: number): Seq.Indexed<T>;
+
+  /**
+   * A record is similar to a JS object, but enforces a specific set of allowed
+   * string keys, and has default values.
+   *
+   * The `Record()` function produces new Record Factories, which when called
+   * create Record instances.
+   *
+   * ```js
+   * import { Record } from 'immutable'
+   * const ABRecord = Record({ a: 1, b: 2 })
+   * const myRecord = ABRecord({ b: 3 })
+   * ```
+   *
+   * Records always have a value for the keys they define. `remove`ing a key
+   * from a record simply resets it to the default value for that key.
+   *
+   * ```js
+   * myRecord.get('a') // 1
+   * myRecord.get('b') // 3
+   * const myRecordWithoutB = myRecord.remove('b')
+   * myRecordWithoutB.get('b') // 2
+   * ```
+   *
+   * Values provided to the constructor not found in the Record type will
+   * be ignored. For example, in this case, ABRecord is provided a key "x" even
+   * though only "a" and "b" have been defined. The value for "x" will be
+   * ignored for this record.
+   *
+   * ```js
+   * const myRecord = ABRecord({ b: 3, x: 10 })
+   * myRecord.get('x') // undefined
+   * ```
+   *
+   * Because Records have a known set of string keys, property get access works
+   * as expected, however property sets will throw an Error.
+   *
+   * Note: IE8 does not support property access. Only use `get()` when
+   * supporting IE8.
+   *
+   * ```js
+   * myRecord.b // 3
+   * myRecord.b = 5 // throws Error
+   * ```
+   *
+   * Record Types can be extended as well, allowing for custom methods on your
+   * Record. This is not a common pattern in functional environments, but is in
+   * many JS programs.
+   *
+   * However Record Types are more restricted than typical JavaScript classes.
+   * They do not use a class constructor, which also means they cannot use
+   * class properties (since those are technically part of a constructor).
+   *
+   * While Record Types can be syntactically created with the JavaScript `class`
+   * form, the resulting Record function is actually a factory function, not a
+   * class constructor. Even though Record Types are not classes, JavaScript
+   * currently requires the use of `new` when creating new Record instances if
+   * they are defined as a `class`.
+   *
+   * ```
+   * class ABRecord extends Record({ a: 1, b: 2 }) {
+   *   getAB() {
+   *     return this.a + this.b;
+   *   }
+   * }
+   *
+   * var myRecord = new ABRecord({b: 3})
+   * myRecord.getAB() // 4
+   * ```
+   *
+   *
+   * **Flow Typing Records:**
+   *
+   * Immutable.js exports two Flow types designed to make it easier to use
+   * Records with flow typed code, `RecordOf<TProps>` and `RecordFactory<TProps>`.
+   *
+   * When defining a new kind of Record factory function, use a flow type that
+   * describes the values the record contains along with `RecordFactory<TProps>`.
+   * To type instances of the Record (which the factory function returns),
+   * use `RecordOf<TProps>`.
+   *
+   * Typically, new Record definitions will export both the Record factory
+   * function as well as the Record instance type for use in other code.
+   *
+   * ```js
+   * import type { RecordFactory, RecordOf } from 'immutable';
+   *
+   * // Use RecordFactory<TProps> for defining new Record factory functions.
+   * type Point3DProps = { x: number, y: number, z: number };
+   * const defaultValues: Point3DProps = { x: 0, y: 0, z: 0 };
+   * const makePoint3D: RecordFactory<Point3DProps> = Record(defaultValues);
+   * export makePoint3D;
+   *
+   * // Use RecordOf<T> for defining new instances of that Record.
+   * export type Point3D = RecordOf<Point3DProps>;
+   * const some3DPoint: Point3D = makePoint3D({ x: 10, y: 20, z: 30 });
+   * ```
+   *
+   * **Flow Typing Record Subclasses:**
+   *
+   * Records can be subclassed as a means to add additional methods to Record
+   * instances. This is generally discouraged in favor of a more functional API,
+   * since Subclasses have some minor overhead. However the ability to create
+   * a rich API on Record types can be quite valuable.
+   *
+   * When using Flow to type Subclasses, do not use `RecordFactory<TProps>`,
+   * instead apply the props type when subclassing:
+   *
+   * ```js
+   * type PersonProps = {name: string, age: number};
+   * const defaultValues: PersonProps = {name: 'Aristotle', age: 2400};
+   * const PersonRecord = Record(defaultValues);
+   * class Person extends PersonRecord<PersonProps> {
+   *   getName(): string {
+   *     return this.get('name')
+   *   }
+   *
+   *   setName(name: string): this {
+   *     return this.set('name', name);
+   *   }
+   * }
+   * ```
+   *
+   * **Choosing Records vs plain JavaScript objects**
+   *
+   * Records offer a persistently immutable alternative to plain JavaScript
+   * objects, however they're not required to be used within Immutable.js
+   * collections. In fact, the deep-access and deep-updating functions
+   * like `getIn()` and `setIn()` work with plain JavaScript Objects as well.
+   *
+   * Deciding to use Records or Objects in your application should be informed
+   * by the tradeoffs and relative benefits of each:
+   *
+   * - *Runtime immutability*: plain JS objects may be carefully treated as
+   *   immutable, however Record instances will *throw* if attempted to be
+   *   mutated directly. Records provide this additional guarantee, however at
+   *   some marginal runtime cost. While JS objects are mutable by nature, the
+   *   use of type-checking tools like [Flow](https://medium.com/@gcanti/immutability-with-flow-faa050a1aef4)
+   *   can help gain confidence in code written to favor immutability.
+   *
+   * - *Value equality*: Records use value equality when compared with `is()`
+   *   or `record.equals()`. That is, two Records with the same keys and values
+   *   are equal. Plain objects use *reference equality*. Two objects with the
+   *   same keys and values are not equal since they are different objects.
+   *   This is important to consider when using objects as keys in a `Map` or
+   *   values in a `Set`, which use equality when retrieving values.
+   *
+   * - *API methods*: Records have a full featured API, with methods like
+   *   `.getIn()`, and `.equals()`. These can make working with these values
+   *   easier, but comes at the cost of not allowing keys with those names.
+   *
+   * - *Default values*: Records provide default values for every key, which
+   *   can be useful when constructing Records with often unchanging values.
+   *   However default values can make using Flow and TypeScript more laborious.
+   *
+   * - *Serialization*: Records use a custom internal representation to
+   *   efficiently store and update their values. Converting to and from this
+   *   form isn't free. If converting Records to plain objects is common,
+   *   consider sticking with plain objects to begin with.
+   */
+  namespace Record {
+    /**
+     * True if `maybeRecord` is an instance of a Record.
+     */
+    function isRecord(maybeRecord: unknown): maybeRecord is Record<object>;
+
+    /**
+     * Records allow passing a second parameter to supply a descriptive name
+     * that appears when converting a Record to a string or in any error
+     * messages. A descriptive name for any record can be accessed by using this
+     * method. If one was not provided, the string "Record" is returned.
+     *
+     * ```js
+     * import { Record } from 'immutable'
+     * const Person = Record({
+     *   name: null
+     * }, 'Person')
+     *
+     * var me = Person({ name: 'My Name' })
+     * me.toString() // "Person { "name": "My Name" }"
+     * Record.getDescriptiveName(me) // "Person"
+     * ```
+     */
+    function getDescriptiveName<TProps extends object>(
+      record: RecordOf<TProps>
+    ): string;
+
+    /**
+     * A Record.Factory is created by the `Record()` function. Record instances
+     * are created by passing it some of the accepted values for that Record
+     * type:
+     *
+     * Note that Record Factories return `Record<TProps> & Readonly<TProps>`,
+     * this allows use of both the Record instance API, and direct property
+     * access on the resulting instances:
+     */
+    namespace Factory {}
+
+    interface Factory<TProps extends object> {
+      (
+        values?: Partial<TProps> | Iterable<[string, unknown]>
+      ): RecordOf<TProps>;
+      new (
+        values?: Partial<TProps> | Iterable<[string, unknown]>
+      ): RecordOf<TProps>;
+
+      /**
+       * The name provided to `Record(values, name)` can be accessed with
+       * `displayName`.
+       */
+      displayName: string;
+    }
+
+    function Factory<TProps extends object>(
+      values?: Partial<TProps> | Iterable<[string, unknown]>
+    ): RecordOf<TProps>;
+  }
+
+  /**
+   * Unlike other types in Immutable.js, the `Record()` function creates a new
+   * Record Factory, which is a function that creates Record instances.
+   *
+   * See above for examples of using `Record()`.
+   *
+   * Note: `Record` is a factory function and not a class, and does not use the
+   * `new` keyword during construction.
+   */
+  function Record<TProps extends object>(
+    defaultValues: TProps,
+    name?: string
+  ): Record.Factory<TProps>;
+
+  interface Record<TProps extends object> {
+    // Reading values
+
+    has(key: string): key is keyof TProps & string;
+
+    /**
+     * Returns the value associated with the provided key, which may be the
+     * default value defined when creating the Record factory function.
+     *
+     * If the requested key is not defined by this Record type, then
+     * notSetValue will be returned if provided. Note that this scenario would
+     * produce an error when using Flow or TypeScript.
+     */
+    get<K extends keyof TProps>(key: K, notSetValue?: unknown): TProps[K];
+    get<T>(key: string, notSetValue: T): T;
+
+    // Reading deep values
+
+    hasIn(keyPath: Iterable<unknown>): boolean;
+    getIn(keyPath: Iterable<unknown>): unknown;
+
+    // Value equality
+
+    equals(other: unknown): boolean;
+    hashCode(): number;
+
+    // Persistent changes
+
+    set<K extends keyof TProps>(key: K, value: TProps[K]): this;
+    update<K extends keyof TProps>(
+      key: K,
+      updater: (value: TProps[K]) => TProps[K]
+    ): this;
+    merge(
+      ...collections: Array<Partial<TProps> | Iterable<[string, unknown]>>
+    ): this;
+    mergeDeep(
+      ...collections: Array<Partial<TProps> | Iterable<[string, unknown]>>
+    ): this;
+
+    mergeWith(
+      merger: (oldVal: unknown, newVal: unknown, key: keyof TProps) => unknown,
+      ...collections: Array<Partial<TProps> | Iterable<[string, unknown]>>
+    ): this;
+    mergeDeepWith(
+      merger: (oldVal: unknown, newVal: unknown, key: unknown) => unknown,
+      ...collections: Array<Partial<TProps> | Iterable<[string, unknown]>>
+    ): this;
+
+    /**
+     * Returns a new instance of this Record type with the value for the
+     * specific key set to its default value.
+     *
+     * @alias remove
+     */
+    delete<K extends keyof TProps>(key: K): this;
+    remove<K extends keyof TProps>(key: K): this;
+
+    /**
+     * Returns a new instance of this Record type with all values set
+     * to their default values.
+     */
+    clear(): this;
+
+    // Deep persistent changes
+
+    setIn(keyPath: Iterable<unknown>, value: unknown): this;
+    updateIn(
+      keyPath: Iterable<unknown>,
+      updater: (value: unknown) => unknown
+    ): this;
+    mergeIn(keyPath: Iterable<unknown>, ...collections: Array<unknown>): this;
+    mergeDeepIn(
+      keyPath: Iterable<unknown>,
+      ...collections: Array<unknown>
+    ): this;
+
+    /**
+     * @alias removeIn
+     */
+    deleteIn(keyPath: Iterable<unknown>): this;
+    removeIn(keyPath: Iterable<unknown>): this;
+
+    // Conversion to JavaScript types
+
+    /**
+     * Deeply converts this Record to equivalent native JavaScript Object.
+     *
+     * Note: This method may not be overridden. Objects with custom
+     * serialization to plain JS may override toJSON() instead.
+     */
+    toJS(): DeepCopy<TProps>;
+
+    /**
+     * Shallowly converts this Record to equivalent native JavaScript Object.
+     */
+    toJSON(): TProps;
+
+    /**
+     * Shallowly converts this Record to equivalent JavaScript Object.
+     */
+    toObject(): TProps;
+
+    // Transient changes
+
+    /**
+     * Note: Not all methods can be used on a mutable collection or within
+     * `withMutations`! Only `set` may be used mutatively.
+     *
+     * @see `Map#withMutations`
+     */
+    withMutations(mutator: (mutable: this) => unknown): this;
+
+    /**
+     * @see `Map#asMutable`
+     */
+    asMutable(): this;
+
+    /**
+     * @see `Map#wasAltered`
+     */
+    wasAltered(): boolean;
+
+    /**
+     * @see `Map#asImmutable`
+     */
+    asImmutable(): this;
+
+    // Sequence algorithms
+
+    toSeq(): Seq.Keyed<keyof TProps, TProps[keyof TProps]>;
+
+    [Symbol.iterator](): IterableIterator<[keyof TProps, TProps[keyof TProps]]>;
+  }
+
+  /**
+   * RecordOf<T> is used in TypeScript to define interfaces expecting an
+   * instance of record with type T.
+   *
+   * This is equivalent to an instance of a record created by a Record Factory.
+   */
+  type RecordOf<TProps extends object> = Record<TProps> & Readonly<TProps>;
+
+  /**
+   * `Seq` describes a lazy operation, allowing them to efficiently chain
+   * use of all the higher-order collection methods (such as `map` and `filter`)
+   * by not creating intermediate collections.
+   *
+   * **Seq is immutable** — Once a Seq is created, it cannot be
+   * changed, appended to, rearranged or otherwise modified. Instead, any
+   * mutative method called on a `Seq` will return a new `Seq`.
+   *
+   * **Seq is lazy** — `Seq` does as little work as necessary to respond to any
+   * method call. Values are often created during iteration, including implicit
+   * iteration when reducing or converting to a concrete data structure such as
+   * a `List` or JavaScript `Array`.
+   *
+   * For example, the following performs no work, because the resulting
+   * `Seq`'s values are never iterated:
+   *
+   * ```js
+   * import { Seq } from 'immutable'
+   * const oddSquares = Seq([ 1, 2, 3, 4, 5, 6, 7, 8 ])
+   *   .filter(x => x % 2 !== 0)
+   *   .map(x => x * x)
+   * ```
+   *
+   * Once the `Seq` is used, it performs only the work necessary. In this
+   * example, no intermediate arrays are ever created, filter is called three
+   * times, and map is only called once:
+   *
+   * ```js
+   * oddSquares.get(1); // 9
+   * ```
+   *
+   * Any collection can be converted to a lazy Seq with `Seq()`.
+   *
+   * `Seq` allows for the efficient chaining of operations, allowing for the
+   * expression of logic that can otherwise be very tedious:
+   *
+   * ```js
+   * lazySeq
+   *   .flip()
+   *   .map(key => key.toUpperCase())
+   *   .flip()
+   * // Seq { A: 1, B: 1, C: 1 }
+   * ```
+   *
+   * As well as expressing logic that would otherwise seem memory or time
+   * limited, for example `Range` is a special kind of Lazy sequence.
+   *
+   * Seq is often used to provide a rich collection API to JavaScript Object.
+   *
+   * ```js
+   * Seq({ x: 0, y: 1, z: 2 }).map(v => v * 2).toObject();
+   * // { x: 0, y: 2, z: 4 }
+   * ```
+   */
+
+  namespace Seq {
+    /**
+     * True if `maybeSeq` is a Seq, it is not backed by a concrete
+     * structure such as Map, List, or Set.
+     */
+    function isSeq(
+      maybeSeq: unknown
+    ): maybeSeq is
+      | Seq.Indexed<unknown>
+      | Seq.Keyed<unknown, unknown>
+      | Seq.Set<unknown>;
+
+    /**
+     * `Seq` which represents key-value pairs.
+     */
+    namespace Keyed {}
+
+    /**
+     * Always returns a Seq.Keyed, if input is not keyed, expects an
+     * collection of [K, V] tuples.
+     *
+     * Note: `Seq.Keyed` is a conversion function and not a class, and does not
+     * use the `new` keyword during construction.
+     */
+    function Keyed<K, V>(collection?: Iterable<[K, V]>): Seq.Keyed<K, V>;
+    function Keyed<V>(obj: { [key: string]: V }): Seq.Keyed<string, V>;
+
+    interface Keyed<K, V> extends Seq<K, V>, Collection.Keyed<K, V> {
+      /**
+       * Deeply converts this Keyed Seq to equivalent native JavaScript Object.
+       *
+       * Converts keys to Strings.
+       */
+      toJS(): { [key in PropertyKey]: DeepCopy<V> };
+
+      /**
+       * Shallowly converts this Keyed Seq to equivalent native JavaScript Object.
+       *
+       * Converts keys to Strings.
+       */
+      toJSON(): { [key in PropertyKey]: V };
+
+      /**
+       * Shallowly converts this collection to an Array.
+       */
+      toArray(): Array<[K, V]>;
+
+      /**
+       * Returns itself
+       */
+      toSeq(): this;
+
+      /**
+       * Returns a new Seq with other collections concatenated to this one.
+       *
+       * All entries will be present in the resulting Seq, even if they
+       * have the same key.
+       */
+      concat<KC, VC>(
+        ...collections: Array<Iterable<[KC, VC]>>
+      ): Seq.Keyed<K | KC, V | VC>;
+      concat<C>(
+        ...collections: Array<{ [key: string]: C }>
+      ): Seq.Keyed<K | string, V | C>;
+
+      /**
+       * Returns a new Seq.Keyed with values passed through a
+       * `mapper` function.
+       *
+       * ```js
+       * import { Seq } from 'immutable'
+       * Seq.Keyed({ a: 1, b: 2 }).map(x => 10 * x)
+       * // Seq { "a": 10, "b": 20 }
+       * ```
+       *
+       * Note: `map()` always returns a new instance, even if it produced the
+       * same value at every step.
+       */
+      map<M>(
+        mapper: (value: V, key: K, iter: this) => M,
+        context?: unknown
+      ): Seq.Keyed<K, M>;
+
+      /**
+       * @see Collection.Keyed.mapKeys
+       */
+      mapKeys<M>(
+        mapper: (key: K, value: V, iter: this) => M,
+        context?: unknown
+      ): Seq.Keyed<M, V>;
+
+      /**
+       * @see Collection.Keyed.mapEntries
+       */
+      mapEntries<KM, VM>(
+        mapper: (
+          entry: [K, V],
+          index: number,
+          iter: this
+        ) => [KM, VM] | undefined,
+        context?: unknown
+      ): Seq.Keyed<KM, VM>;
+
+      /**
+       * Flat-maps the Seq, returning a Seq of the same type.
+       *
+       * Similar to `seq.map(...).flatten(true)`.
+       */
+      flatMap<KM, VM>(
+        mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>,
+        context?: unknown
+      ): Seq.Keyed<KM, VM>;
+
+      /**
+       * Returns a new Seq with only the entries for which the `predicate`
+       * function returns true.
+       *
+       * Note: `filter()` always returns a new instance, even if it results in
+       * not filtering out any values.
+       */
+      filter<F extends V>(
+        predicate: (value: V, key: K, iter: this) => value is F,
+        context?: unknown
+      ): Seq.Keyed<K, F>;
+      filter(
+        predicate: (value: V, key: K, iter: this) => unknown,
+        context?: unknown
+      ): this;
+
+      /**
+       * Returns a new keyed Seq with the values for which the `predicate`
+       * function returns false and another for which is returns true.
+       */
+      partition<F extends V, C>(
+        predicate: (this: C, value: V, key: K, iter: this) => value is F,
+        context?: C
+      ): [Seq.Keyed<K, V>, Seq.Keyed<K, F>];
+      partition<C>(
+        predicate: (this: C, value: V, key: K, iter: this) => unknown,
+        context?: C
+      ): [this, this];
+
+      /**
+       * @see Collection.Keyed.flip
+       */
+      flip(): Seq.Keyed<V, K>;
+
+      [Symbol.iterator](): IterableIterator<[K, V]>;
+    }
+
+    /**
+     * `Seq` which represents an ordered indexed list of values.
+     */
+    namespace Indexed {
+      /**
+       * Provides an Seq.Indexed of the values provided.
+       */
+      function of<T>(...values: Array<T>): Seq.Indexed<T>;
+    }
+
+    /**
+     * Always returns Seq.Indexed, discarding associated keys and
+     * supplying incrementing indices.
+     *
+     * Note: `Seq.Indexed` is a conversion function and not a class, and does
+     * not use the `new` keyword during construction.
+     */
+    function Indexed<T>(
+      collection?: Iterable<T> | ArrayLike<T>
+    ): Seq.Indexed<T>;
+
+    interface Indexed<T> extends Seq<number, T>, Collection.Indexed<T> {
+      /**
+       * Deeply converts this Indexed Seq to equivalent native JavaScript Array.
+       */
+      toJS(): Array<DeepCopy<T>>;
+
+      /**
+       * Shallowly converts this Indexed Seq to equivalent native JavaScript Array.
+       */
+      toJSON(): Array<T>;
+
+      /**
+       * Shallowly converts this collection to an Array.
+       */
+      toArray(): Array<T>;
+
+      /**
+       * Returns itself
+       */
+      toSeq(): this;
+
+      /**
+       * Returns a new Seq with other collections concatenated to this one.
+       */
+      concat<C>(
+        ...valuesOrCollections: Array<Iterable<C> | C>
+      ): Seq.Indexed<T | C>;
+
+      /**
+       * Returns a new Seq.Indexed with values passed through a
+       * `mapper` function.
+       *
+       * ```js
+       * import { Seq } from 'immutable'
+       * Seq.Indexed([ 1, 2 ]).map(x => 10 * x)
+       * // Seq [ 10, 20 ]
+       * ```
+       *
+       * Note: `map()` always returns a new instance, even if it produced the
+       * same value at every step.
+       */
+      map<M>(
+        mapper: (value: T, key: number, iter: this) => M,
+        context?: unknown
+      ): Seq.Indexed<M>;
+
+      /**
+       * Flat-maps the Seq, returning a a Seq of the same type.
+       *
+       * Similar to `seq.map(...).flatten(true)`.
+       */
+      flatMap<M>(
+        mapper: (value: T, key: number, iter: this) => Iterable<M>,
+        context?: unknown
+      ): Seq.Indexed<M>;
+
+      /**
+       * Returns a new Seq with only the values for which the `predicate`
+       * function returns true.
+       *
+       * Note: `filter()` always returns a new instance, even if it results in
+       * not filtering out any values.
+       */
+      filter<F extends T>(
+        predicate: (value: T, index: number, iter: this) => value is F,
+        context?: unknown
+      ): Seq.Indexed<F>;
+      filter(
+        predicate: (value: T, index: number, iter: this) => unknown,
+        context?: unknown
+      ): this;
+
+      /**
+       * Returns a new indexed Seq with the values for which the `predicate`
+       * function returns false and another for which is returns true.
+       */
+      partition<F extends T, C>(
+        predicate: (this: C, value: T, index: number, iter: this) => value is F,
+        context?: C
+      ): [Seq.Indexed<T>, Seq.Indexed<F>];
+      partition<C>(
+        predicate: (this: C, value: T, index: number, iter: this) => unknown,
+        context?: C
+      ): [this, this];
+
+      /**
+       * Returns a Seq "zipped" with the provided collections.
+       *
+       * Like `zipWith`, but using the default `zipper`: creating an `Array`.
+       *
+       * ```js
+       * const a = Seq([ 1, 2, 3 ]);
+       * const b = Seq([ 4, 5, 6 ]);
+       * const c = a.zip(b); // Seq [ [ 1, 4 ], [ 2, 5 ], [ 3, 6 ] ]
+       * ```
+       */
+      zip<U>(other: Collection<unknown, U>): Seq.Indexed<[T, U]>;
+      zip<U, V>(
+        other: Collection<unknown, U>,
+        other2: Collection<unknown, V>
+      ): Seq.Indexed<[T, U, V]>;
+      zip(
+        ...collections: Array<Collection<unknown, unknown>>
+      ): Seq.Indexed<unknown>;
+
+      /**
+       * Returns a Seq "zipped" with the provided collections.
+       *
+       * Unlike `zip`, `zipAll` continues zipping until the longest collection is
+       * exhausted. Missing values from shorter collections are filled with `undefined`.
+       *
+       * ```js
+       * const a = Seq([ 1, 2 ]);
+       * const b = Seq([ 3, 4, 5 ]);
+       * const c = a.zipAll(b); // Seq [ [ 1, 3 ], [ 2, 4 ], [ undefined, 5 ] ]
+       * ```
+       */
+      zipAll<U>(other: Collection<unknown, U>): Seq.Indexed<[T, U]>;
+      zipAll<U, V>(
+        other: Collection<unknown, U>,
+        other2: Collection<unknown, V>
+      ): Seq.Indexed<[T, U, V]>;
+      zipAll(
+        ...collections: Array<Collection<unknown, unknown>>
+      ): Seq.Indexed<unknown>;
+
+      /**
+       * Returns a Seq "zipped" with the provided collections by using a
+       * custom `zipper` function.
+       *
+       * ```js
+       * const a = Seq([ 1, 2, 3 ]);
+       * const b = Seq([ 4, 5, 6 ]);
+       * const c = a.zipWith((a, b) => a + b, b);
+       * // Seq [ 5, 7, 9 ]
+       * ```
+       */
+      zipWith<U, Z>(
+        zipper: (value: T, otherValue: U) => Z,
+        otherCollection: Collection<unknown, U>
+      ): Seq.Indexed<Z>;
+      zipWith<U, V, Z>(
+        zipper: (value: T, otherValue: U, thirdValue: V) => Z,
+        otherCollection: Collection<unknown, U>,
+        thirdCollection: Collection<unknown, V>
+      ): Seq.Indexed<Z>;
+      zipWith<Z>(
+        zipper: (...values: Array<unknown>) => Z,
+        ...collections: Array<Collection<unknown, unknown>>
+      ): Seq.Indexed<Z>;
+
+      [Symbol.iterator](): IterableIterator<T>;
+    }
+
+    /**
+     * `Seq` which represents a set of values.
+     *
+     * Because `Seq` are often lazy, `Seq.Set` does not provide the same guarantee
+     * of value uniqueness as the concrete `Set`.
+     */
+    namespace Set {
+      /**
+       * Returns a Seq.Set of the provided values
+       */
+      function of<T>(...values: Array<T>): Seq.Set<T>;
+    }
+
+    /**
+     * Always returns a Seq.Set, discarding associated indices or keys.
+     *
+     * Note: `Seq.Set` is a conversion function and not a class, and does not
+     * use the `new` keyword during construction.
+     */
+    function Set<T>(collection?: Iterable<T> | ArrayLike<T>): Seq.Set<T>;
+
+    interface Set<T> extends Seq<T, T>, Collection.Set<T> {
+      /**
+       * Deeply converts this Set Seq to equivalent native JavaScript Array.
+       */
+      toJS(): Array<DeepCopy<T>>;
+
+      /**
+       * Shallowly converts this Set Seq to equivalent native JavaScript Array.
+       */
+      toJSON(): Array<T>;
+
+      /**
+       * Shallowly converts this collection to an Array.
+       */
+      toArray(): Array<T>;
+
+      /**
+       * Returns itself
+       */
+      toSeq(): this;
+
+      /**
+       * Returns a new Seq with other collections concatenated to this one.
+       *
+       * All entries will be present in the resulting Seq, even if they
+       * are duplicates.
+       */
+      concat<U>(...collections: Array<Iterable<U>>): Seq.Set<T | U>;
+
+      /**
+       * Returns a new Seq.Set with values passed through a
+       * `mapper` function.
+       *
+       * ```js
+       * Seq.Set([ 1, 2 ]).map(x => 10 * x)
+       * // Seq { 10, 20 }
+       * ```
+       *
+       * Note: `map()` always returns a new instance, even if it produced the
+       * same value at every step.
+       */
+      map<M>(
+        mapper: (value: T, key: T, iter: this) => M,
+        context?: unknown
+      ): Seq.Set<M>;
+
+      /**
+       * Flat-maps the Seq, returning a Seq of the same type.
+       *
+       * Similar to `seq.map(...).flatten(true)`.
+       */
+      flatMap<M>(
+        mapper: (value: T, key: T, iter: this) => Iterable<M>,
+        context?: unknown
+      ): Seq.Set<M>;
+
+      /**
+       * Returns a new Seq with only the values for which the `predicate`
+       * function returns true.
+       *
+       * Note: `filter()` always returns a new instance, even if it results in
+       * not filtering out any values.
+       */
+      filter<F extends T>(
+        predicate: (value: T, key: T, iter: this) => value is F,
+        context?: unknown
+      ): Seq.Set<F>;
+      filter(
+        predicate: (value: T, key: T, iter: this) => unknown,
+        context?: unknown
+      ): this;
+
+      /**
+       * Returns a new set Seq with the values for which the `predicate`
+       * function returns false and another for which is returns true.
+       */
+      partition<F extends T, C>(
+        predicate: (this: C, value: T, key: T, iter: this) => value is F,
+        context?: C
+      ): [Seq.Set<T>, Seq.Set<F>];
+      partition<C>(
+        predicate: (this: C, value: T, key: T, iter: this) => unknown,
+        context?: C
+      ): [this, this];
+
+      [Symbol.iterator](): IterableIterator<T>;
+    }
+  }
+
+  /**
+   * Creates a Seq.
+   *
+   * Returns a particular kind of `Seq` based on the input.
+   *
+   *   * If a `Seq`, that same `Seq`.
+   *   * If an `Collection`, a `Seq` of the same kind (Keyed, Indexed, or Set).
+   *   * If an Array-like, an `Seq.Indexed`.
+   *   * If an Iterable Object, an `Seq.Indexed`.
+   *   * If an Object, a `Seq.Keyed`.
+   *
+   * Note: An Iterator itself will be treated as an object, becoming a `Seq.Keyed`,
+   * which is usually not what you want. You should turn your Iterator Object into
+   * an iterable object by defining a Symbol.iterator (or @@iterator) method which
+   * returns `this`.
+   *
+   * Note: `Seq` is a conversion function and not a class, and does not use the
+   * `new` keyword during construction.
+   */
+  function Seq<S extends Seq<unknown, unknown>>(seq: S): S;
+  function Seq<K, V>(collection: Collection.Keyed<K, V>): Seq.Keyed<K, V>;
+  function Seq<T>(collection: Collection.Set<T>): Seq.Set<T>;
+  function Seq<T>(
+    collection: Collection.Indexed<T> | Iterable<T> | ArrayLike<T>
+  ): Seq.Indexed<T>;
+  function Seq<V>(obj: { [key: string]: V }): Seq.Keyed<string, V>;
+  function Seq<K = unknown, V = unknown>(): Seq<K, V>;
+
+  interface Seq<K, V> extends Collection<K, V> {
+    /**
+     * Some Seqs can describe their size lazily. When this is the case,
+     * size will be an integer. Otherwise it will be undefined.
+     *
+     * For example, Seqs returned from `map()` or `reverse()`
+     * preserve the size of the original `Seq` while `filter()` does not.
+     *
+     * Note: `Range`, `Repeat` and `Seq`s made from `Array`s and `Object`s will
+     * always have a size.
+     */
+    readonly size: number | undefined;
+
+    // Force evaluation
+
+    /**
+     * Because Sequences are lazy and designed to be chained together, they do
+     * not cache their results. For example, this map function is called a total
+     * of 6 times, as each `join` iterates the Seq of three values.
+     *
+     *     var squares = Seq([ 1, 2, 3 ]).map(x => x * x)
+     *     squares.join() + squares.join()
+     *
+     * If you know a `Seq` will be used multiple times, it may be more
+     * efficient to first cache it in memory. Here, the map function is called
+     * only 3 times.
+     *
+     *     var squares = Seq([ 1, 2, 3 ]).map(x => x * x).cacheResult()
+     *     squares.join() + squares.join()
+     *
+     * Use this method judiciously, as it must fully evaluate a Seq which can be
+     * a burden on memory and possibly performance.
+     *
+     * Note: after calling `cacheResult`, a Seq will always have a `size`.
+     */
+    cacheResult(): this;
+
+    // Sequence algorithms
+
+    /**
+     * Returns a new Seq with values passed through a
+     * `mapper` function.
+     *
+     * ```js
+     * import { Seq } from 'immutable'
+     * Seq([ 1, 2 ]).map(x => 10 * x)
+     * // Seq [ 10, 20 ]
+     * ```
+     *
+     * Note: `map()` always returns a new instance, even if it produced the same
+     * value at every step.
+     */
+    map<M>(
+      mapper: (value: V, key: K, iter: this) => M,
+      context?: unknown
+    ): Seq<K, M>;
+
+    /**
+     * Returns a new Seq with values passed through a
+     * `mapper` function.
+     *
+     * ```js
+     * import { Seq } from 'immutable'
+     * Seq([ 1, 2 ]).map(x => 10 * x)
+     * // Seq [ 10, 20 ]
+     * ```
+     *
+     * Note: `map()` always returns a new instance, even if it produced the same
+     * value at every step.
+     * Note: used only for sets.
+     */
+    map<M>(
+      mapper: (value: V, key: K, iter: this) => M,
+      context?: unknown
+    ): Seq<M, M>;
+
+    /**
+     * Flat-maps the Seq, returning a Seq of the same type.
+     *
+     * Similar to `seq.map(...).flatten(true)`.
+     */
+    flatMap<M>(
+      mapper: (value: V, key: K, iter: this) => Iterable<M>,
+      context?: unknown
+    ): Seq<K, M>;
+
+    /**
+     * Flat-maps the Seq, returning a Seq of the same type.
+     *
+     * Similar to `seq.map(...).flatten(true)`.
+     * Note: Used only for sets.
+     */
+    flatMap<M>(
+      mapper: (value: V, key: K, iter: this) => Iterable<M>,
+      context?: unknown
+    ): Seq<M, M>;
+
+    /**
+     * Returns a new Seq with only the values for which the `predicate`
+     * function returns true.
+     *
+     * Note: `filter()` always returns a new instance, even if it results in
+     * not filtering out any values.
+     */
+    filter<F extends V>(
+      predicate: (value: V, key: K, iter: this) => value is F,
+      context?: unknown
+    ): Seq<K, F>;
+    filter(
+      predicate: (value: V, key: K, iter: this) => unknown,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new Seq with the values for which the `predicate` function
+     * returns false and another for which is returns true.
+     */
+    partition<F extends V, C>(
+      predicate: (this: C, value: V, key: K, iter: this) => value is F,
+      context?: C
+    ): [Seq<K, V>, Seq<K, F>];
+    partition<C>(
+      predicate: (this: C, value: V, key: K, iter: this) => unknown,
+      context?: C
+    ): [this, this];
+
+    /**
+     * Returns a new Sequence of the same type with other values and
+     * collection-like concatenated to this one.
+     *
+     * All entries will be present in the resulting Seq, even if they
+     * have the same key.
+     */
+    concat(...valuesOrCollections: Array<unknown>): Seq<unknown, unknown>;
+  }
+
+  /**
+   * The `Collection` is a set of (key, value) entries which can be iterated, and
+   * is the base class for all collections in `immutable`, allowing them to
+   * make use of all the Collection methods (such as `map` and `filter`).
+   *
+   * Note: A collection is always iterated in the same order, however that order
+   * may not always be well defined, as is the case for the `Map` and `Set`.
+   *
+   * Collection is the abstract base class for concrete data structures. It
+   * cannot be constructed directly.
+   *
+   * Implementations should extend one of the subclasses, `Collection.Keyed`,
+   * `Collection.Indexed`, or `Collection.Set`.
+   */
+  namespace Collection {
+    /**
+     * Keyed Collections have discrete keys tied to each value.
+     *
+     * When iterating `Collection.Keyed`, each iteration will yield a `[K, V]`
+     * tuple, in other words, `Collection#entries` is the default iterator for
+     * Keyed Collections.
+     */
+    namespace Keyed {}
+
+    /**
+     * Creates a Collection.Keyed
+     *
+     * Similar to `Collection()`, however it expects collection-likes of [K, V]
+     * tuples if not constructed from a Collection.Keyed or JS Object.
+     *
+     * Note: `Collection.Keyed` is a conversion function and not a class, and
+     * does not use the `new` keyword during construction.
+     */
+    function Keyed<K, V>(collection?: Iterable<[K, V]>): Collection.Keyed<K, V>;
+    function Keyed<V>(obj: { [key: string]: V }): Collection.Keyed<string, V>;
+
+    interface Keyed<K, V> extends Collection<K, V> {
+      /**
+       * Deeply converts this Keyed collection to equivalent native JavaScript Object.
+       *
+       * Converts keys to Strings.
+       */
+      toJS(): { [key in PropertyKey]: DeepCopy<V> };
+
+      /**
+       * Shallowly converts this Keyed collection to equivalent native JavaScript Object.
+       *
+       * Converts keys to Strings.
+       */
+      toJSON(): { [key in PropertyKey]: V };
+
+      /**
+       * Shallowly converts this collection to an Array.
+       */
+      toArray(): Array<[K, V]>;
+
+      /**
+       * Returns Seq.Keyed.
+       * @override
+       */
+      toSeq(): Seq.Keyed<K, V>;
+
+      // Sequence functions
+
+      /**
+       * Returns a new Collection.Keyed of the same type where the keys and values
+       * have been flipped.
+       */
+      flip(): Collection.Keyed<V, K>;
+
+      /**
+       * Returns a new Collection with other collections concatenated to this one.
+       */
+      concat<KC, VC>(
+        ...collections: Array<Iterable<[KC, VC]>>
+      ): Collection.Keyed<K | KC, V | VC>;
+      concat<C>(
+        ...collections: Array<{ [key: string]: C }>
+      ): Collection.Keyed<K | string, V | C>;
+
+      /**
+       * Returns a new Collection.Keyed with values passed through a
+       * `mapper` function.
+       *
+       * ```js
+       * import { Collection } from 'immutable'
+       * Collection.Keyed({ a: 1, b: 2 }).map(x => 10 * x)
+       * // Seq { "a": 10, "b": 20 }
+       * ```
+       *
+       * Note: `map()` always returns a new instance, even if it produced the
+       * same value at every step.
+       */
+      map<M>(
+        mapper: (value: V, key: K, iter: this) => M,
+        context?: unknown
+      ): Collection.Keyed<K, M>;
+
+      /**
+       * Returns a new Collection.Keyed of the same type with keys passed through
+       * a `mapper` function.
+       *
+       * Note: `mapKeys()` always returns a new instance, even if it produced
+       * the same key at every step.
+       */
+      mapKeys<M>(
+        mapper: (key: K, value: V, iter: this) => M,
+        context?: unknown
+      ): Collection.Keyed<M, V>;
+
+      /**
+       * Returns a new Collection.Keyed of the same type with entries
+       * ([key, value] tuples) passed through a `mapper` function.
+       *
+       * Note: `mapEntries()` always returns a new instance, even if it produced
+       * the same entry at every step.
+       *
+       * If the mapper function returns `undefined`, then the entry will be filtered
+       */
+      mapEntries<KM, VM>(
+        mapper: (
+          entry: [K, V],
+          index: number,
+          iter: this
+        ) => [KM, VM] | undefined,
+        context?: unknown
+      ): Collection.Keyed<KM, VM>;
+
+      /**
+       * Flat-maps the Collection, returning a Collection of the same type.
+       *
+       * Similar to `collection.map(...).flatten(true)`.
+       */
+      flatMap<KM, VM>(
+        mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>,
+        context?: unknown
+      ): Collection.Keyed<KM, VM>;
+
+      /**
+       * Returns a new Collection with only the values for which the `predicate`
+       * function returns true.
+       *
+       * Note: `filter()` always returns a new instance, even if it results in
+       * not filtering out any values.
+       */
+      filter<F extends V>(
+        predicate: (value: V, key: K, iter: this) => value is F,
+        context?: unknown
+      ): Collection.Keyed<K, F>;
+      filter(
+        predicate: (value: V, key: K, iter: this) => unknown,
+        context?: unknown
+      ): this;
+
+      /**
+       * Returns a new keyed Collection with the values for which the
+       * `predicate` function returns false and another for which is returns
+       * true.
+       */
+      partition<F extends V, C>(
+        predicate: (this: C, value: V, key: K, iter: this) => value is F,
+        context?: C
+      ): [Collection.Keyed<K, V>, Collection.Keyed<K, F>];
+      partition<C>(
+        predicate: (this: C, value: V, key: K, iter: this) => unknown,
+        context?: C
+      ): [this, this];
+
+      [Symbol.iterator](): IterableIterator<[K, V]>;
+    }
+
+    /**
+     * Indexed Collections have incrementing numeric keys. They exhibit
+     * slightly different behavior than `Collection.Keyed` for some methods in order
+     * to better mirror the behavior of JavaScript's `Array`, and add methods
+     * which do not make sense on non-indexed Collections such as `indexOf`.
+     *
+     * Unlike JavaScript arrays, `Collection.Indexed`s are always dense. "Unset"
+     * indices and `undefined` indices are indistinguishable, and all indices from
+     * 0 to `size` are visited when iterated.
+     *
+     * All Collection.Indexed methods return re-indexed Collections. In other words,
+     * indices always start at 0 and increment until size. If you wish to
+     * preserve indices, using them as keys, convert to a Collection.Keyed by
+     * calling `toKeyedSeq`.
+     */
+    namespace Indexed {}
+
+    /**
+     * Creates a new Collection.Indexed.
+     *
+     * Note: `Collection.Indexed` is a conversion function and not a class, and
+     * does not use the `new` keyword during construction.
+     */
+    function Indexed<T>(
+      collection?: Iterable<T> | ArrayLike<T>
+    ): Collection.Indexed<T>;
+
+    interface Indexed<T> extends Collection<number, T>, OrderedCollection<T> {
+      /**
+       * Deeply converts this Indexed collection to equivalent native JavaScript Array.
+       */
+      toJS(): Array<DeepCopy<T>>;
+
+      /**
+       * Shallowly converts this Indexed collection to equivalent native JavaScript Array.
+       */
+      toJSON(): Array<T>;
+
+      /**
+       * Shallowly converts this collection to an Array.
+       */
+      toArray(): Array<T>;
+
+      // Reading values
+
+      /**
+       * Returns the value associated with the provided index, or notSetValue if
+       * the index is beyond the bounds of the Collection.
+       *
+       * `index` may be a negative number, which indexes back from the end of the
+       * Collection. `s.get(-1)` gets the last item in the Collection.
+       */
+      get<NSV>(index: number, notSetValue: NSV): T | NSV;
+      get(index: number): T | undefined;
+
+      // Conversion to Seq
+
+      /**
+       * Returns Seq.Indexed.
+       * @override
+       */
+      toSeq(): Seq.Indexed<T>;
+
+      /**
+       * If this is a collection of [key, value] entry tuples, it will return a
+       * Seq.Keyed of those entries.
+       */
+      fromEntrySeq(): Seq.Keyed<unknown, unknown>;
+
+      // Combination
+
+      /**
+       * Returns a Collection of the same type with `separator` between each item
+       * in this Collection.
+       */
+      interpose(separator: T): this;
+
+      /**
+       * Returns a Collection of the same type with the provided `collections`
+       * interleaved into this collection.
+       *
+       * The resulting Collection includes the first item from each, then the
+       * second from each, etc.
+       *
+       * The shortest Collection stops interleave.
+       *
+       * Since `interleave()` re-indexes values, it produces a complete copy,
+       * which has `O(N)` complexity.
+       *
+       * Note: `interleave` *cannot* be used in `withMutations`.
+       */
+      interleave(...collections: Array<Collection<unknown, T>>): this;
+
+      /**
+       * Splice returns a new indexed Collection by replacing a region of this
+       * Collection with new values. If values are not provided, it only skips the
+       * region to be removed.
+       *
+       * `index` may be a negative number, which indexes back from the end of the
+       * Collection. `s.splice(-2)` splices after the second to last item.
+       *
+       * Since `splice()` re-indexes values, it produces a complete copy, which
+       * has `O(N)` complexity.
+       *
+       * Note: `splice` *cannot* be used in `withMutations`.
+       */
+      splice(index: number, removeNum: number, ...values: Array<T>): this;
+
+      /**
+       * Returns a Collection of the same type "zipped" with the provided
+       * collections.
+       *
+       * Like `zipWith`, but using the default `zipper`: creating an `Array`.
+       */
+      zip<U>(other: Collection<unknown, U>): Collection.Indexed<[T, U]>;
+      zip<U, V>(
+        other: Collection<unknown, U>,
+        other2: Collection<unknown, V>
+      ): Collection.Indexed<[T, U, V]>;
+      zip(
+        ...collections: Array<Collection<unknown, unknown>>
+      ): Collection.Indexed<unknown>;
+
+      /**
+       * Returns a Collection "zipped" with the provided collections.
+       *
+       * Unlike `zip`, `zipAll` continues zipping until the longest collection is
+       * exhausted. Missing values from shorter collections are filled with `undefined`.
+       *
+       * ```js
+       * const a = List([ 1, 2 ]);
+       * const b = List([ 3, 4, 5 ]);
+       * const c = a.zipAll(b); // List [ [ 1, 3 ], [ 2, 4 ], [ undefined, 5 ] ]
+       * ```
+       */
+      zipAll<U>(other: Collection<unknown, U>): Collection.Indexed<[T, U]>;
+      zipAll<U, V>(
+        other: Collection<unknown, U>,
+        other2: Collection<unknown, V>
+      ): Collection.Indexed<[T, U, V]>;
+      zipAll(
+        ...collections: Array<Collection<unknown, unknown>>
+      ): Collection.Indexed<unknown>;
+
+      /**
+       * Returns a Collection of the same type "zipped" with the provided
+       * collections by using a custom `zipper` function.
+       */
+      zipWith<U, Z>(
+        zipper: (value: T, otherValue: U) => Z,
+        otherCollection: Collection<unknown, U>
+      ): Collection.Indexed<Z>;
+      zipWith<U, V, Z>(
+        zipper: (value: T, otherValue: U, thirdValue: V) => Z,
+        otherCollection: Collection<unknown, U>,
+        thirdCollection: Collection<unknown, V>
+      ): Collection.Indexed<Z>;
+      zipWith<Z>(
+        zipper: (...values: Array<unknown>) => Z,
+        ...collections: Array<Collection<unknown, unknown>>
+      ): Collection.Indexed<Z>;
+
+      // Search for value
+
+      /**
+       * Returns the first index at which a given value can be found in the
+       * Collection, or -1 if it is not present.
+       */
+      indexOf(searchValue: T): number;
+
+      /**
+       * Returns the last index at which a given value can be found in the
+       * Collection, or -1 if it is not present.
+       */
+      lastIndexOf(searchValue: T): number;
+
+      /**
+       * Returns the first index in the Collection where a value satisfies the
+       * provided predicate function. Otherwise -1 is returned.
+       */
+      findIndex(
+        predicate: (value: T, index: number, iter: this) => boolean,
+        context?: unknown
+      ): number;
+
+      /**
+       * Returns the last index in the Collection where a value satisfies the
+       * provided predicate function. Otherwise -1 is returned.
+       */
+      findLastIndex(
+        predicate: (value: T, index: number, iter: this) => boolean,
+        context?: unknown
+      ): number;
+
+      // Sequence algorithms
+
+      /**
+       * Returns a new Collection with other collections concatenated to this one.
+       */
+      concat<C>(
+        ...valuesOrCollections: Array<Iterable<C> | C>
+      ): Collection.Indexed<T | C>;
+
+      /**
+       * Returns a new Collection.Indexed with values passed through a
+       * `mapper` function.
+       *
+       * ```js
+       * import { Collection } from 'immutable'
+       * Collection.Indexed([1,2]).map(x => 10 * x)
+       * // Seq [ 1, 2 ]
+       * ```
+       *
+       * Note: `map()` always returns a new instance, even if it produced the
+       * same value at every step.
+       */
+      map<M>(
+        mapper: (value: T, key: number, iter: this) => M,
+        context?: unknown
+      ): Collection.Indexed<M>;
+
+      /**
+       * Flat-maps the Collection, returning a Collection of the same type.
+       *
+       * Similar to `collection.map(...).flatten(true)`.
+       */
+      flatMap<M>(
+        mapper: (value: T, key: number, iter: this) => Iterable<M>,
+        context?: unknown
+      ): Collection.Indexed<M>;
+
+      /**
+       * Returns a new Collection with only the values for which the `predicate`
+       * function returns true.
+       *
+       * Note: `filter()` always returns a new instance, even if it results in
+       * not filtering out any values.
+       */
+      filter<F extends T>(
+        predicate: (value: T, index: number, iter: this) => value is F,
+        context?: unknown
+      ): Collection.Indexed<F>;
+      filter(
+        predicate: (value: T, index: number, iter: this) => unknown,
+        context?: unknown
+      ): this;
+
+      /**
+       * Returns a new indexed Collection with the values for which the
+       * `predicate` function returns false and another for which is returns
+       * true.
+       */
+      partition<F extends T, C>(
+        predicate: (this: C, value: T, index: number, iter: this) => value is F,
+        context?: C
+      ): [Collection.Indexed<T>, Collection.Indexed<F>];
+      partition<C>(
+        predicate: (this: C, value: T, index: number, iter: this) => unknown,
+        context?: C
+      ): [this, this];
+
+      [Symbol.iterator](): IterableIterator<T>;
+    }
+
+    /**
+     * Set Collections only represent values. They have no associated keys or
+     * indices. Duplicate values are possible in the lazy `Seq.Set`s, however
+     * the concrete `Set` Collection does not allow duplicate values.
+     *
+     * Collection methods on Collection.Set such as `map` and `forEach` will provide
+     * the value as both the first and second arguments to the provided function.
+     *
+     * ```js
+     * import { Collection } from 'immutable'
+     * const seq = Collection.Set([ 'A', 'B', 'C' ])
+     * // Seq { "A", "B", "C" }
+     * seq.forEach((v, k) =>
+     *  assert.equal(v, k)
+     * )
+     * ```
+     */
+    namespace Set {}
+
+    /**
+     * Similar to `Collection()`, but always returns a Collection.Set.
+     *
+     * Note: `Collection.Set` is a factory function and not a class, and does
+     * not use the `new` keyword during construction.
+     */
+    function Set<T>(collection?: Iterable<T> | ArrayLike<T>): Collection.Set<T>;
+
+    interface Set<T> extends Collection<T, T> {
+      /**
+       * Deeply converts this Set collection to equivalent native JavaScript Array.
+       */
+      toJS(): Array<DeepCopy<T>>;
+
+      /**
+       * Shallowly converts this Set collection to equivalent native JavaScript Array.
+       */
+      toJSON(): Array<T>;
+
+      /**
+       * Shallowly converts this collection to an Array.
+       */
+      toArray(): Array<T>;
+
+      /**
+       * Returns Seq.Set.
+       * @override
+       */
+      toSeq(): Seq.Set<T>;
+
+      // Sequence algorithms
+
+      /**
+       * Returns a new Collection with other collections concatenated to this one.
+       */
+      concat<U>(...collections: Array<Iterable<U>>): Collection.Set<T | U>;
+
+      /**
+       * Returns a new Collection.Set with values passed through a
+       * `mapper` function.
+       *
+       * ```
+       * Collection.Set([ 1, 2 ]).map(x => 10 * x)
+       * // Seq { 1, 2 }
+       * ```
+       *
+       * Note: `map()` always returns a new instance, even if it produced the
+       * same value at every step.
+       */
+      map<M>(
+        mapper: (value: T, key: T, iter: this) => M,
+        context?: unknown
+      ): Collection.Set<M>;
+
+      /**
+       * Flat-maps the Collection, returning a Collection of the same type.
+       *
+       * Similar to `collection.map(...).flatten(true)`.
+       */
+      flatMap<M>(
+        mapper: (value: T, key: T, iter: this) => Iterable<M>,
+        context?: unknown
+      ): Collection.Set<M>;
+
+      /**
+       * Returns a new Collection with only the values for which the `predicate`
+       * function returns true.
+       *
+       * Note: `filter()` always returns a new instance, even if it results in
+       * not filtering out any values.
+       */
+      filter<F extends T>(
+        predicate: (value: T, key: T, iter: this) => value is F,
+        context?: unknown
+      ): Collection.Set<F>;
+      filter(
+        predicate: (value: T, key: T, iter: this) => unknown,
+        context?: unknown
+      ): this;
+
+      /**
+       * Returns a new set Collection with the values for which the
+       * `predicate` function returns false and another for which is returns
+       * true.
+       */
+      partition<F extends T, C>(
+        predicate: (this: C, value: T, key: T, iter: this) => value is F,
+        context?: C
+      ): [Collection.Set<T>, Collection.Set<F>];
+      partition<C>(
+        predicate: (this: C, value: T, key: T, iter: this) => unknown,
+        context?: C
+      ): [this, this];
+
+      [Symbol.iterator](): IterableIterator<T>;
+    }
+  }
+
+  /**
+   * Creates a Collection.
+   *
+   * The type of Collection created is based on the input.
+   *
+   *   * If an `Collection`, that same `Collection`.
+   *   * If an Array-like, an `Collection.Indexed`.
+   *   * If an Object with an Iterator defined, an `Collection.Indexed`.
+   *   * If an Object, an `Collection.Keyed`.
+   *
+   * This methods forces the conversion of Objects and Strings to Collections.
+   * If you want to ensure that a Collection of one item is returned, use
+   * `Seq.of`.
+   *
+   * Note: An Iterator itself will be treated as an object, becoming a `Seq.Keyed`,
+   * which is usually not what you want. You should turn your Iterator Object into
+   * an iterable object by defining a Symbol.iterator (or @@iterator) method which
+   * returns `this`.
+   *
+   * Note: `Collection` is a conversion function and not a class, and does not
+   * use the `new` keyword during construction.
+   */
+  function Collection<I extends Collection<unknown, unknown>>(collection: I): I;
+  function Collection<T>(
+    collection: Iterable<T> | ArrayLike<T>
+  ): Collection.Indexed<T>;
+  function Collection<V>(obj: {
+    [key: string]: V;
+  }): Collection.Keyed<string, V>;
+  function Collection<K = unknown, V = unknown>(): Collection<K, V>;
+
+  interface Collection<K, V> extends ValueObject {
+    // Value equality
+
+    /**
+     * True if this and the other Collection have value equality, as defined
+     * by `Immutable.is()`.
+     *
+     * Note: This is equivalent to `Immutable.is(this, other)`, but provided to
+     * allow for chained expressions.
+     */
+    equals(other: unknown): boolean;
+
+    /**
+     * Computes and returns the hashed identity for this Collection.
+     *
+     * The `hashCode` of a Collection is used to determine potential equality,
+     * and is used when adding this to a `Set` or as a key in a `Map`, enabling
+     * lookup via a different instance.
+     *
+     * If two values have the same `hashCode`, they are [not guaranteed
+     * to be equal][Hash Collision]. If two values have different `hashCode`s,
+     * they must not be equal.
+     *
+     * [Hash Collision]: https://en.wikipedia.org/wiki/Collision_(computer_science)
+     */
+    hashCode(): number;
+
+    // Reading values
+
+    /**
+     * Returns the value associated with the provided key, or notSetValue if
+     * the Collection does not contain this key.
+     *
+     * Note: it is possible a key may be associated with an `undefined` value,
+     * so if `notSetValue` is not provided and this method returns `undefined`,
+     * that does not guarantee the key was not found.
+     */
+    get<NSV>(key: K, notSetValue: NSV): V | NSV;
+    get(key: K): V | undefined;
+
+    /**
+     * True if a key exists within this `Collection`, using `Immutable.is`
+     * to determine equality
+     */
+    has(key: K): boolean;
+
+    /**
+     * True if a value exists within this `Collection`, using `Immutable.is`
+     * to determine equality
+     * @alias contains
+     */
+    includes(value: V): boolean;
+    contains(value: V): boolean;
+
+    /**
+     * In case the `Collection` is not empty returns the first element of the
+     * `Collection`.
+     * In case the `Collection` is empty returns the optional default
+     * value if provided, if no default value is provided returns undefined.
+     */
+    first<NSV>(notSetValue: NSV): V | NSV;
+    first(): V | undefined;
+
+    /**
+     * In case the `Collection` is not empty returns the last element of the
+     * `Collection`.
+     * In case the `Collection` is empty returns the optional default
+     * value if provided, if no default value is provided returns undefined.
+     */
+    last<NSV>(notSetValue: NSV): V | NSV;
+    last(): V | undefined;
+
+    // Reading deep values
+
+    /**
+     * Returns the value found by following a path of keys or indices through
+     * nested Collections.
+     *
+     * Plain JavaScript Object or Arrays may be nested within an Immutable.js
+     * Collection, and getIn() can access those values as well:
+     */
+    getIn(searchKeyPath: Iterable<unknown>, notSetValue?: unknown): unknown;
+
+    /**
+     * True if the result of following a path of keys or indices through nested
+     * Collections results in a set value.
+     */
+    hasIn(searchKeyPath: Iterable<unknown>): boolean;
+
+    // Persistent changes
+
+    /**
+     * This can be very useful as a way to "chain" a normal function into a
+     * sequence of methods. RxJS calls this "let" and lodash calls it "thru".
+     *
+     * For example, to sum a Seq after mapping and filtering:
+     */
+    update<R>(updater: (value: this) => R): R;
+
+    // Conversion to JavaScript types
+
+    /**
+     * Deeply converts this Collection to equivalent native JavaScript Array or Object.
+     *
+     * `Collection.Indexed`, and `Collection.Set` become `Array`, while
+     * `Collection.Keyed` become `Object`, converting keys to Strings.
+     */
+    toJS(): Array<DeepCopy<V>> | { [key in PropertyKey]: DeepCopy<V> };
+
+    /**
+     * Shallowly converts this Collection to equivalent native JavaScript Array or Object.
+     *
+     * `Collection.Indexed`, and `Collection.Set` become `Array`, while
+     * `Collection.Keyed` become `Object`, converting keys to Strings.
+     */
+    toJSON(): Array<V> | { [key in PropertyKey]: V };
+
+    /**
+     * Shallowly converts this collection to an Array.
+     *
+     * `Collection.Indexed`, and `Collection.Set` produce an Array of values.
+     * `Collection.Keyed` produce an Array of [key, value] tuples.
+     */
+    toArray(): Array<V> | Array<[K, V]>;
+
+    /**
+     * Shallowly converts this Collection to an Object.
+     *
+     * Converts keys to Strings.
+     */
+    toObject(): { [key: string]: V };
+
+    // Conversion to Collections
+
+    /**
+     * Converts this Collection to a Map, Throws if keys are not hashable.
+     *
+     * Note: This is equivalent to `Map(this.toKeyedSeq())`, but provided
+     * for convenience and to allow for chained expressions.
+     */
+    toMap(): Map<K, V>;
+
+    /**
+     * Converts this Collection to a Map, maintaining the order of iteration.
+     *
+     * Note: This is equivalent to `OrderedMap(this.toKeyedSeq())`, but
+     * provided for convenience and to allow for chained expressions.
+     */
+    toOrderedMap(): OrderedMap<K, V>;
+
+    /**
+     * Converts this Collection to a Set, discarding keys. Throws if values
+     * are not hashable.
+     *
+     * Note: This is equivalent to `Set(this)`, but provided to allow for
+     * chained expressions.
+     */
+    toSet(): Set<V>;
+
+    /**
+     * Converts this Collection to a Set, maintaining the order of iteration and
+     * discarding keys.
+     *
+     * Note: This is equivalent to `OrderedSet(this.valueSeq())`, but provided
+     * for convenience and to allow for chained expressions.
+     */
+    toOrderedSet(): OrderedSet<V>;
+
+    /**
+     * Converts this Collection to a List, discarding keys.
+     *
+     * This is similar to `List(collection)`, but provided to allow for chained
+     * expressions. However, when called on `Map` or other keyed collections,
+     * `collection.toList()` discards the keys and creates a list of only the
+     * values, whereas `List(collection)` creates a list of entry tuples.
+     */
+    toList(): List<V>;
+
+    /**
+     * Converts this Collection to a Stack, discarding keys. Throws if values
+     * are not hashable.
+     *
+     * Note: This is equivalent to `Stack(this)`, but provided to allow for
+     * chained expressions.
+     */
+    toStack(): Stack<V>;
+
+    // Conversion to Seq
+
+    /**
+     * Converts this Collection to a Seq of the same kind (indexed,
+     * keyed, or set).
+     */
+    toSeq(): Seq<K, V>;
+
+    /**
+     * Returns a Seq.Keyed from this Collection where indices are treated as keys.
+     *
+     * This is useful if you want to operate on an
+     * Collection.Indexed and preserve the [index, value] pairs.
+     *
+     * The returned Seq will have identical iteration order as
+     * this Collection.
+     */
+    toKeyedSeq(): Seq.Keyed<K, V>;
+
+    /**
+     * Returns an Seq.Indexed of the values of this Collection, discarding keys.
+     */
+    toIndexedSeq(): Seq.Indexed<V>;
+
+    /**
+     * Returns a Seq.Set of the values of this Collection, discarding keys.
+     */
+    toSetSeq(): Seq.Set<V>;
+
+    // Iterators
+
+    /**
+     * An iterator of this `Collection`'s keys.
+     *
+     * Note: this will return an ES6 iterator which does not support
+     * Immutable.js sequence algorithms. Use `keySeq` instead, if this is
+     * what you want.
+     */
+    keys(): IterableIterator<K>;
+
+    /**
+     * An iterator of this `Collection`'s values.
+     *
+     * Note: this will return an ES6 iterator which does not support
+     * Immutable.js sequence algorithms. Use `valueSeq` instead, if this is
+     * what you want.
+     */
+    values(): IterableIterator<V>;
+
+    /**
+     * An iterator of this `Collection`'s entries as `[ key, value ]` tuples.
+     *
+     * Note: this will return an ES6 iterator which does not support
+     * Immutable.js sequence algorithms. Use `entrySeq` instead, if this is
+     * what you want.
+     */
+    entries(): IterableIterator<[K, V]>;
+
+    [Symbol.iterator](): IterableIterator<unknown>;
+
+    // Collections (Seq)
+
+    /**
+     * Returns a new Seq.Indexed of the keys of this Collection,
+     * discarding values.
+     */
+    keySeq(): Seq.Indexed<K>;
+
+    /**
+     * Returns an Seq.Indexed of the values of this Collection, discarding keys.
+     */
+    valueSeq(): Seq.Indexed<V>;
+
+    /**
+     * Returns a new Seq.Indexed of [key, value] tuples.
+     */
+    entrySeq(): Seq.Indexed<[K, V]>;
+
+    // Sequence algorithms
+
+    /**
+     * Returns a new Collection of the same type with values passed through a
+     * `mapper` function.
+     *
+     * Note: `map()` always returns a new instance, even if it produced the same
+     * value at every step.
+     */
+    map<M>(
+      mapper: (value: V, key: K, iter: this) => M,
+      context?: unknown
+    ): Collection<K, M>;
+
+    /**
+     * Note: used only for sets, which return Collection<M, M> but are otherwise
+     * identical to normal `map()`.
+     *
+     * @ignore
+     */
+    map(...args: Array<never>): unknown;
+
+    /**
+     * Returns a new Collection of the same type with only the entries for which
+     * the `predicate` function returns true.
+     *
+     * Note: `filter()` always returns a new instance, even if it results in
+     * not filtering out any values.
+     */
+    filter<F extends V>(
+      predicate: (value: V, key: K, iter: this) => value is F,
+      context?: unknown
+    ): Collection<K, F>;
+    filter(
+      predicate: (value: V, key: K, iter: this) => unknown,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new Collection of the same type with only the entries for which
+     * the `predicate` function returns false.
+     *
+     * Note: `filterNot()` always returns a new instance, even if it results in
+     * not filtering out any values.
+     */
+    filterNot(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new Collection with the values for which the `predicate`
+     * function returns false and another for which is returns true.
+     */
+    partition<F extends V, C>(
+      predicate: (this: C, value: V, key: K, iter: this) => value is F,
+      context?: C
+    ): [Collection<K, V>, Collection<K, F>];
+    partition<C>(
+      predicate: (this: C, value: V, key: K, iter: this) => unknown,
+      context?: C
+    ): [this, this];
+
+    /**
+     * Returns a new Collection of the same type in reverse order.
+     */
+    reverse(): this;
+
+    /**
+     * Returns a new Collection of the same type which includes the same entries,
+     * stably sorted by using a `comparator`.
+     *
+     * If a `comparator` is not provided, a default comparator uses `<` and `>`.
+     *
+     * `comparator(valueA, valueB)`:
+     *
+     *   * Returns `0` if the elements should not be swapped.
+     *   * Returns `-1` (or any negative number) if `valueA` comes before `valueB`
+     *   * Returns `1` (or any positive number) if `valueA` comes after `valueB`
+     *   * Alternatively, can return a value of the `PairSorting` enum type
+     *   * Is pure, i.e. it must always return the same value for the same pair
+     *     of values.
+     *
+     * When sorting collections which have no defined order, their ordered
+     * equivalents will be returned. e.g. `map.sort()` returns OrderedMap.
+     *
+     * Note: `sort()` Always returns a new instance, even if the original was
+     * already sorted.
+     *
+     * Note: This is always an eager operation.
+     */
+    sort(comparator?: Comparator<V>): this;
+
+    /**
+     * Like `sort`, but also accepts a `comparatorValueMapper` which allows for
+     * sorting by more sophisticated means:
+     *
+     * Note: `sortBy()` Always returns a new instance, even if the original was
+     * already sorted.
+     *
+     * Note: This is always an eager operation.
+     */
+    sortBy<C>(
+      comparatorValueMapper: (value: V, key: K, iter: this) => C,
+      comparator?: Comparator<C>
+    ): this;
+
+    /**
+     * Returns a `Map` of `Collection`, grouped by the return
+     * value of the `grouper` function.
+     *
+     * Note: This is always an eager operation.
+     */
+    groupBy<G>(
+      grouper: (value: V, key: K, iter: this) => G,
+      context?: unknown
+    ): Map<G, this>;
+
+    // Side effects
+
+    /**
+     * The `sideEffect` is executed for every entry in the Collection.
+     *
+     * Unlike `Array#forEach`, if any call of `sideEffect` returns
+     * `false`, the iteration will stop. Returns the number of entries iterated
+     * (including the last iteration which returned false).
+     */
+    forEach(
+      sideEffect: (value: V, key: K, iter: this) => unknown,
+      context?: unknown
+    ): number;
+
+    // Creating subsets
+
+    /**
+     * Returns a new Collection of the same type representing a portion of this
+     * Collection from start up to but not including end.
+     *
+     * If begin is negative, it is offset from the end of the Collection. e.g.
+     * `slice(-2)` returns a Collection of the last two entries. If it is not
+     * provided the new Collection will begin at the beginning of this Collection.
+     *
+     * If end is negative, it is offset from the end of the Collection. e.g.
+     * `slice(0, -1)` returns a Collection of everything but the last entry. If
+     * it is not provided, the new Collection will continue through the end of
+     * this Collection.
+     *
+     * If the requested slice is equivalent to the current Collection, then it
+     * will return itself.
+     */
+    slice(begin?: number, end?: number): this;
+
+    /**
+     * Returns a new Collection of the same type containing all entries except
+     * the first.
+     */
+    rest(): this;
+
+    /**
+     * Returns a new Collection of the same type containing all entries except
+     * the last.
+     */
+    butLast(): this;
+
+    /**
+     * Returns a new Collection of the same type which excludes the first `amount`
+     * entries from this Collection.
+     */
+    skip(amount: number): this;
+
+    /**
+     * Returns a new Collection of the same type which excludes the last `amount`
+     * entries from this Collection.
+     */
+    skipLast(amount: number): this;
+
+    /**
+     * Returns a new Collection of the same type which includes entries starting
+     * from when `predicate` first returns false.
+     */
+    skipWhile(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new Collection of the same type which includes entries starting
+     * from when `predicate` first returns true.
+     */
+    skipUntil(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new Collection of the same type which includes the first `amount`
+     * entries from this Collection.
+     */
+    take(amount: number): this;
+
+    /**
+     * Returns a new Collection of the same type which includes the last `amount`
+     * entries from this Collection.
+     */
+    takeLast(amount: number): this;
+
+    /**
+     * Returns a new Collection of the same type which includes entries from this
+     * Collection as long as the `predicate` returns true.
+     */
+    takeWhile(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown
+    ): this;
+
+    /**
+     * Returns a new Collection of the same type which includes entries from this
+     * Collection as long as the `predicate` returns false.
+     */
+    takeUntil(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown
+    ): this;
+
+    // Combination
+
+    /**
+     * Returns a new Collection of the same type with other values and
+     * collection-like concatenated to this one.
+     *
+     * For Seqs, all entries will be present in the resulting Seq, even if they
+     * have the same key.
+     */
+    concat(
+      ...valuesOrCollections: Array<unknown>
+    ): Collection<unknown, unknown>;
+
+    /**
+     * Flattens nested Collections.
+     *
+     * Will deeply flatten the Collection by default, returning a Collection of the
+     * same type, but a `depth` can be provided in the form of a number or
+     * boolean (where true means to shallowly flatten one level). A depth of 0
+     * (or shallow: false) will deeply flatten.
+     *
+     * Flattens only others Collection, not Arrays or Objects.
+     *
+     * Note: `flatten(true)` operates on Collection<unknown, Collection<K, V>> and
+     * returns Collection<K, V>
+     */
+    flatten(depth?: number): Collection<unknown, unknown>;
+    flatten(shallow?: boolean): Collection<unknown, unknown>;
+
+    /**
+     * Flat-maps the Collection, returning a Collection of the same type.
+     *
+     * Similar to `collection.map(...).flatten(true)`.
+     */
+    flatMap<M>(
+      mapper: (value: V, key: K, iter: this) => Iterable<M>,
+      context?: unknown
+    ): Collection<K, M>;
+
+    /**
+     * Flat-maps the Collection, returning a Collection of the same type.
+     *
+     * Similar to `collection.map(...).flatten(true)`.
+     * Used for Dictionaries only.
+     */
+    flatMap<KM, VM>(
+      mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>,
+      context?: unknown
+    ): Collection<KM, VM>;
+
+    // Reducing a value
+
+    /**
+     * Reduces the Collection to a value by calling the `reducer` for every entry
+     * in the Collection and passing along the reduced value.
+     *
+     * If `initialReduction` is not provided, the first item in the
+     * Collection will be used.
+     *
+     * @see `Array#reduce`.
+     */
+    reduce<R>(
+      reducer: (reduction: R, value: V, key: K, iter: this) => R,
+      initialReduction: R,
+      context?: unknown
+    ): R;
+    reduce<R>(
+      reducer: (reduction: V | R, value: V, key: K, iter: this) => R
+    ): R;
+
+    /**
+     * Reduces the Collection in reverse (from the right side).
+     *
+     * Note: Similar to this.reverse().reduce(), and provided for parity
+     * with `Array#reduceRight`.
+     */
+    reduceRight<R>(
+      reducer: (reduction: R, value: V, key: K, iter: this) => R,
+      initialReduction: R,
+      context?: unknown
+    ): R;
+    reduceRight<R>(
+      reducer: (reduction: V | R, value: V, key: K, iter: this) => R
+    ): R;
+
+    /**
+     * True if `predicate` returns true for all entries in the Collection.
+     */
+    every(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown
+    ): boolean;
+
+    /**
+     * True if `predicate` returns true for any entry in the Collection.
+     */
+    some(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown
+    ): boolean;
+
+    /**
+     * Joins values together as a string, inserting a separator between each.
+     * The default separator is `","`.
+     */
+    join(separator?: string): string;
+
+    /**
+     * Returns true if this Collection includes no values.
+     *
+     * For some lazy `Seq`, `isEmpty` might need to iterate to determine
+     * emptiness. At most one iteration will occur.
+     */
+    isEmpty(): boolean;
+
+    /**
+     * Returns the size of this Collection.
+     *
+     * Regardless of if this Collection can describe its size lazily (some Seqs
+     * cannot), this method will always return the correct size. E.g. it
+     * evaluates a lazy `Seq` if necessary.
+     *
+     * If `predicate` is provided, then this returns the count of entries in the
+     * Collection for which the `predicate` returns true.
+     */
+    count(): number;
+    count(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown
+    ): number;
+
+    /**
+     * Returns a `Seq.Keyed` of counts, grouped by the return value of
+     * the `grouper` function.
+     *
+     * Note: This is not a lazy operation.
+     */
+    countBy<G>(
+      grouper: (value: V, key: K, iter: this) => G,
+      context?: unknown
+    ): Map<G, number>;
+
+    // Search for value
+
+    /**
+     * Returns the first value for which the `predicate` returns true.
+     */
+    find(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown,
+      notSetValue?: V
+    ): V | undefined;
+
+    /**
+     * Returns the last value for which the `predicate` returns true.
+     *
+     * Note: `predicate` will be called for each entry in reverse.
+     */
+    findLast(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown,
+      notSetValue?: V
+    ): V | undefined;
+
+    /**
+     * Returns the first [key, value] entry for which the `predicate` returns true.
+     */
+    findEntry(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown,
+      notSetValue?: V
+    ): [K, V] | undefined;
+
+    /**
+     * Returns the last [key, value] entry for which the `predicate`
+     * returns true.
+     *
+     * Note: `predicate` will be called for each entry in reverse.
+     */
+    findLastEntry(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown,
+      notSetValue?: V
+    ): [K, V] | undefined;
+
+    /**
+     * Returns the key for which the `predicate` returns true.
+     */
+    findKey(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown
+    ): K | undefined;
+
+    /**
+     * Returns the last key for which the `predicate` returns true.
+     *
+     * Note: `predicate` will be called for each entry in reverse.
+     */
+    findLastKey(
+      predicate: (value: V, key: K, iter: this) => boolean,
+      context?: unknown
+    ): K | undefined;
+
+    /**
+     * Returns the key associated with the search value, or undefined.
+     */
+    keyOf(searchValue: V): K | undefined;
+
+    /**
+     * Returns the last key associated with the search value, or undefined.
+     */
+    lastKeyOf(searchValue: V): K | undefined;
+
+    /**
+     * Returns the maximum value in this collection. If any values are
+     * comparatively equivalent, the first one found will be returned.
+     *
+     * The `comparator` is used in the same way as `Collection#sort`. If it is not
+     * provided, the default comparator is `>`.
+     *
+     * When two values are considered equivalent, the first encountered will be
+     * returned. Otherwise, `max` will operate independent of the order of input
+     * as long as the comparator is commutative. The default comparator `>` is
+     * commutative *only* when types do not differ.
+     *
+     * If `comparator` returns 0 and either value is NaN, undefined, or null,
+     * that value will be returned.
+     */
+    max(comparator?: Comparator<V>): V | undefined;
+
+    /**
+     * Like `max`, but also accepts a `comparatorValueMapper` which allows for
+     * comparing by more sophisticated means:
+     */
+    maxBy<C>(
+      comparatorValueMapper: (value: V, key: K, iter: this) => C,
+      comparator?: Comparator<C>
+    ): V | undefined;
+
+    /**
+     * Returns the minimum value in this collection. If any values are
+     * comparatively equivalent, the first one found will be returned.
+     *
+     * The `comparator` is used in the same way as `Collection#sort`. If it is not
+     * provided, the default comparator is `<`.
+     *
+     * When two values are considered equivalent, the first encountered will be
+     * returned. Otherwise, `min` will operate independent of the order of input
+     * as long as the comparator is commutative. The default comparator `<` is
+     * commutative *only* when types do not differ.
+     *
+     * If `comparator` returns 0 and either value is NaN, undefined, or null,
+     * that value will be returned.
+     */
+    min(comparator?: Comparator<V>): V | undefined;
+
+    /**
+     * Like `min`, but also accepts a `comparatorValueMapper` which allows for
+     * comparing by more sophisticated means:
+     */
+    minBy<C>(
+      comparatorValueMapper: (value: V, key: K, iter: this) => C,
+      comparator?: Comparator<C>
+    ): V | undefined;
+
+    // Comparison
+
+    /**
+     * True if `iter` includes every value in this Collection.
+     */
+    isSubset(iter: Iterable<V>): boolean;
+
+    /**
+     * True if this Collection includes every value in `iter`.
+     */
+    isSuperset(iter: Iterable<V>): boolean;
+  }
+
+  /**
+   * The interface to fulfill to qualify as a Value Object.
+   */
+  interface ValueObject {
+    /**
+     * True if this and the other Collection have value equality, as defined
+     * by `Immutable.is()`.
+     *
+     * Note: This is equivalent to `Immutable.is(this, other)`, but provided to
+     * allow for chained expressions.
+     */
+    equals(other: unknown): boolean;
+
+    /**
+     * Computes and returns the hashed identity for this Collection.
+     *
+     * The `hashCode` of a Collection is used to determine potential equality,
+     * and is used when adding this to a `Set` or as a key in a `Map`, enabling
+     * lookup via a different instance.
+     *
+     * Note: hashCode() MUST return a Uint32 number. The easiest way to
+     * guarantee this is to return `myHash | 0` from a custom implementation.
+     *
+     * If two values have the same `hashCode`, they are [not guaranteed
+     * to be equal][Hash Collision]. If two values have different `hashCode`s,
+     * they must not be equal.
+     *
+     * Note: `hashCode()` is not guaranteed to always be called before
+     * `equals()`. Most but not all Immutable.js collections use hash codes to
+     * organize their internal data structures, while all Immutable.js
+     * collections use equality during lookups.
+     *
+     * [Hash Collision]: https://en.wikipedia.org/wiki/Collision_(computer_science)
+     */
+    hashCode(): number;
+  }
+
+  /**
+   * Interface representing all oredered collections.
+   * This includes `List`, `Stack`, `Map`, `OrderedMap`, `Set`, and `OrderedSet`.
+   * return of `isOrdered()` return true in that case.
+   */
+  interface OrderedCollection<T> {
+    /**
+     * Shallowly converts this collection to an Array.
+     */
+    toArray(): Array<T>;
+
+    [Symbol.iterator](): IterableIterator<T>;
+  }
+
+  /**
+   * Deeply converts plain JS objects and arrays to Immutable Maps and Lists.
+   *
+   * `fromJS` will convert Arrays and [array-like objects][2] to a List, and
+   * plain objects (without a custom prototype) to a Map. [Iterable objects][3]
+   * may be converted to List, Map, or Set.
+   *
+   * If a `reviver` is optionally provided, it will be called with every
+   * collection as a Seq (beginning with the most nested collections
+   * and proceeding to the top-level collection itself), along with the key
+   * referring to each collection and the parent JS object provided as `this`.
+   * For the top level, object, the key will be `""`. This `reviver` is expected
+   * to return a new Immutable Collection, allowing for custom conversions from
+   * deep JS objects. Finally, a `path` is provided which is the sequence of
+   * keys to this value from the starting value.
+   *
+   * `reviver` acts similarly to the [same parameter in `JSON.parse`][1].
+   *
+   * If `reviver` is not provided, the default behavior will convert Objects
+   * into Maps and Arrays into Lists like so:
+   *
+   * Accordingly, this example converts native JS data to OrderedMap and List:
+   *
+   * Keep in mind, when using JS objects to construct Immutable Maps, that
+   * JavaScript Object properties are always strings, even if written in a
+   * quote-less shorthand, while Immutable Maps accept keys of any type.
+   *
+   * Property access for JavaScript Objects first converts the key to a string,
+   * but since Immutable Map keys can be of any type the argument to `get()` is
+   * not altered.
+   *
+   * [1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#Example.3A_Using_the_reviver_parameter
+   *      "Using the reviver parameter"
+   * [2]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections#working_with_array-like_objects
+   *      "Working with array-like objects"
+   * [3]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_iterable_protocol
+   *      "The iterable protocol"
+   */
+  function fromJS<JSValue>(
+    jsValue: JSValue,
+    reviver?: undefined
+  ): FromJS<JSValue>;
+  function fromJS(
+    jsValue: unknown,
+    reviver?: (
+      key: string | number,
+      sequence: Collection.Keyed<string, unknown> | Collection.Indexed<unknown>,
+      path?: Array<string | number>
+    ) => unknown
+  ): Collection<unknown, unknown>;
+
+  type FromJS<JSValue> = JSValue extends FromJSNoTransform
+    ? JSValue
+    : JSValue extends Array<unknown>
+      ? FromJSArray<JSValue>
+      : JSValue extends object
+        ? FromJSObject<JSValue>
+        : unknown;
+
+  type FromJSNoTransform =
+    | Collection<unknown, unknown>
+    | number
+    | string
+    | null
+    | undefined;
+
+  type FromJSArray<JSValue> =
+    JSValue extends Array<infer T> ? List<FromJS<T>> : never;
+
+  type FromJSObject<JSValue> = JSValue extends object
+    ? Map<keyof JSValue, FromJS<JSValue[keyof JSValue]>>
+    : never;
+
+  /**
+   * Value equality check with semantics similar to `Object.is`, but treats
+   * Immutable `Collection`s as values, equal if the second `Collection` includes
+   * equivalent values.
+   *
+   * It's used throughout Immutable when checking for equality, including `Map`
+   * key equality and `Set` membership.
+   *
+   * `is()` compares primitive types like strings and numbers, Immutable.js
+   * collections like `Map` and `List`, but also any custom object which
+   * implements `ValueObject` by providing `equals()` and `hashCode()` methods.
+   *
+   * Note: Unlike `Object.is`, `Immutable.is` assumes `0` and `-0` are the same
+   * value, matching the behavior of ES6 Map key equality.
+   */
+  function is(first: unknown, second: unknown): boolean;
+
+  /**
+   * The `hash()` function is an important part of how Immutable determines if
+   * two values are equivalent and is used to determine how to store those
+   * values. Provided with any value, `hash()` will return a 31-bit integer.
+   *
+   * When designing Objects which may be equal, it's important that when a
+   * `.equals()` method returns true, that both values `.hashCode()` method
+   * return the same value. `hash()` may be used to produce those values.
+   *
+   * For non-Immutable Objects that do not provide a `.hashCode()` functions
+   * (including plain Objects, plain Arrays, Date objects, etc), a unique hash
+   * value will be created for each *instance*. That is, the create hash
+   * represents referential equality, and not value equality for Objects. This
+   * ensures that if that Object is mutated over time that its hash code will
+   * remain consistent, allowing Objects to be used as keys and values in
+   * Immutable.js collections.
+   *
+   * Note that `hash()` attempts to balance between speed and avoiding
+   * collisions, however it makes no attempt to produce secure hashes.
+   *
+   * *New in Version 4.0*
+   */
+  function hash(value: unknown): number;
+
+  /**
+   * True if `maybeImmutable` is an Immutable Collection or Record.
+   *
+   * Note: Still returns true even if the collections is within a `withMutations()`.
+   */
+  function isImmutable(
+    maybeImmutable: unknown
+  ): maybeImmutable is Collection<unknown, unknown>;
+
+  /**
+   * True if `maybeCollection` is a Collection, or any of its subclasses.
+   */
+  function isCollection(
+    maybeCollection: unknown
+  ): maybeCollection is Collection<unknown, unknown>;
+
+  /**
+   * True if `maybeKeyed` is a Collection.Keyed, or any of its subclasses.
+   */
+  function isKeyed(
+    maybeKeyed: unknown
+  ): maybeKeyed is Collection.Keyed<unknown, unknown>;
+
+  /**
+   * True if `maybeIndexed` is a Collection.Indexed, or any of its subclasses.
+   */
+  function isIndexed(
+    maybeIndexed: unknown
+  ): maybeIndexed is Collection.Indexed<unknown>;
+
+  /**
+   * True if `maybeAssociative` is either a Keyed or Indexed Collection.
+   */
+  function isAssociative(
+    maybeAssociative: unknown
+  ): maybeAssociative is
+    | Collection.Keyed<unknown, unknown>
+    | Collection.Indexed<unknown>;
+
+  /**
+   * True if `maybeOrdered` is a Collection where iteration order is well
+   * defined. True for Collection.Indexed as well as OrderedMap and OrderedSet.
+   */
+  function isOrdered<T>(
+    maybeOrdered: Iterable<T>
+  ): maybeOrdered is OrderedCollection<T>;
+  function isOrdered(
+    maybeOrdered: unknown
+  ): maybeOrdered is OrderedCollection<unknown>;
+
+  /**
+   * True if `maybeValue` is a JavaScript Object which has *both* `equals()`
+   * and `hashCode()` methods.
+   *
+   * Any two instances of *value objects* can be compared for value equality with
+   * `Immutable.is()` and can be used as keys in a `Map` or members in a `Set`.
+   */
+  function isValueObject(maybeValue: unknown): maybeValue is ValueObject;
+
+  /**
+   * True if `maybeSeq` is a Seq.
+   */
+  function isSeq(
+    maybeSeq: unknown
+  ): maybeSeq is
+    | Seq.Indexed<unknown>
+    | Seq.Keyed<unknown, unknown>
+    | Seq.Set<unknown>;
+
+  /**
+   * True if `maybeList` is a List.
+   */
+  function isList(maybeList: unknown): maybeList is List<unknown>;
+
+  /**
+   * True if `maybeMap` is a Map.
+   *
+   * Also true for OrderedMaps.
+   */
+  function isMap(maybeMap: unknown): maybeMap is Map<unknown, unknown>;
+
+  /**
+   * True if `maybeOrderedMap` is an OrderedMap.
+   */
+  function isOrderedMap(
+    maybeOrderedMap: unknown
+  ): maybeOrderedMap is OrderedMap<unknown, unknown>;
+
+  /**
+   * True if `maybeStack` is a Stack.
+   */
+  function isStack(maybeStack: unknown): maybeStack is Stack<unknown>;
+
+  /**
+   * True if `maybeSet` is a Set.
+   *
+   * Also true for OrderedSets.
+   */
+  function isSet(maybeSet: unknown): maybeSet is Set<unknown>;
+
+  /**
+   * True if `maybeOrderedSet` is an OrderedSet.
+   */
+  function isOrderedSet(
+    maybeOrderedSet: unknown
+  ): maybeOrderedSet is OrderedSet<unknown>;
+
+  /**
+   * True if `maybeRecord` is a Record.
+   */
+  function isRecord(maybeRecord: unknown): maybeRecord is Record<object>;
+
+  /**
+   * Returns the value within the provided collection associated with the
+   * provided key, or notSetValue if the key is not defined in the collection.
+   *
+   * A functional alternative to `collection.get(key)` which will also work on
+   * plain Objects and Arrays as an alternative for `collection[key]`.
+   */
+  function get<K, V>(collection: Collection<K, V>, key: K): V | undefined;
+  function get<K, V, NSV>(
+    collection: Collection<K, V>,
+    key: K,
+    notSetValue: NSV
+  ): V | NSV;
+  function get<TProps extends object, K extends keyof TProps>(
+    record: Record<TProps>,
+    key: K,
+    notSetValue: unknown
+  ): TProps[K];
+  function get<V>(collection: Array<V>, key: number): V | undefined;
+  function get<V, NSV>(
+    collection: Array<V>,
+    key: number,
+    notSetValue: NSV
+  ): V | NSV;
+  function get<C extends object, K extends keyof C>(
+    object: C,
+    key: K,
+    notSetValue: unknown
+  ): C[K];
+  function get<V>(
+    collection: { [key: PropertyKey]: V },
+    key: string
+  ): V | undefined;
+  function get<V, NSV>(
+    collection: { [key: PropertyKey]: V },
+    key: string,
+    notSetValue: NSV
+  ): V | NSV;
+
+  /**
+   * Returns true if the key is defined in the provided collection.
+   *
+   * A functional alternative to `collection.has(key)` which will also work with
+   * plain Objects and Arrays as an alternative for
+   * `collection.hasOwnProperty(key)`.
+   */
+  function has(collection: object, key: unknown): boolean;
+
+  /**
+   * Returns a copy of the collection with the value at key removed.
+   *
+   * A functional alternative to `collection.remove(key)` which will also work
+   * with plain Objects and Arrays as an alternative for
+   * `delete collectionCopy[key]`.
+   */
+  function remove<K, C extends Collection<K, unknown>>(
+    collection: C,
+    key: K
+  ): C;
+  function remove<
+    TProps extends object,
+    C extends Record<TProps>,
+    K extends keyof TProps,
+  >(collection: C, key: K): C;
+  function remove<C extends Array<unknown>>(collection: C, key: number): C;
+  function remove<C, K extends keyof C>(collection: C, key: K): C;
+  function remove<C extends { [key: string]: unknown }, K extends keyof C>(
+    collection: C,
+    key: K
+  ): C;
+
+  /**
+   * Returns a copy of the collection with the value at key set to the provided
+   * value.
+   *
+   * A functional alternative to `collection.set(key, value)` which will also
+   * work with plain Objects and Arrays as an alternative for
+   * `collectionCopy[key] = value`.
+   */
+  function set<K, V, C extends Collection<K, V>>(
+    collection: C,
+    key: K,
+    value: V
+  ): C;
+  function set<
+    TProps extends object,
+    C extends Record<TProps>,
+    K extends keyof TProps,
+  >(record: C, key: K, value: TProps[K]): C;
+  function set<V, C extends Array<V>>(collection: C, key: number, value: V): C;
+  function set<C, K extends keyof C>(object: C, key: K, value: C[K]): C;
+  function set<V, C extends { [key: string]: V }>(
+    collection: C,
+    key: string,
+    value: V
+  ): C;
+
+  /**
+   * Returns a copy of the collection with the value at key set to the result of
+   * providing the existing value to the updating function.
+   *
+   * A functional alternative to `collection.update(key, fn)` which will also
+   * work with plain Objects and Arrays as an alternative for
+   * `collectionCopy[key] = fn(collection[key])`.
+   */
+  function update<K, V, C extends Collection<K, V>>(
+    collection: C,
+    key: K,
+    updater: (value: V | undefined) => V | undefined
+  ): C;
+  function update<K, V, C extends Collection<K, V>, NSV>(
+    collection: C,
+    key: K,
+    notSetValue: NSV,
+    updater: (value: V | NSV) => V
+  ): C;
+  function update<
+    TProps extends object,
+    C extends Record<TProps>,
+    K extends keyof TProps,
+  >(record: C, key: K, updater: (value: TProps[K]) => TProps[K]): C;
+  function update<
+    TProps extends object,
+    C extends Record<TProps>,
+    K extends keyof TProps,
+    NSV,
+  >(
+    record: C,
+    key: K,
+    notSetValue: NSV,
+    updater: (value: TProps[K] | NSV) => TProps[K]
+  ): C;
+  function update<V>(
+    collection: Array<V>,
+    key: number,
+    updater: (value: V | undefined) => V | undefined
+  ): Array<V>;
+  function update<V, NSV>(
+    collection: Array<V>,
+    key: number,
+    notSetValue: NSV,
+    updater: (value: V | NSV) => V
+  ): Array<V>;
+  function update<C, K extends keyof C>(
+    object: C,
+    key: K,
+    updater: (value: C[K]) => C[K]
+  ): C;
+  function update<C, K extends keyof C, NSV>(
+    object: C,
+    key: K,
+    notSetValue: NSV,
+    updater: (value: C[K] | NSV) => C[K]
+  ): C;
+  function update<V, C extends { [key: string]: V }, K extends keyof C>(
+    collection: C,
+    key: K,
+    updater: (value: V) => V
+  ): { [key: string]: V };
+  function update<V, C extends { [key: string]: V }, K extends keyof C, NSV>(
+    collection: C,
+    key: K,
+    notSetValue: NSV,
+    updater: (value: V | NSV) => V
+  ): { [key: string]: V };
+
+  // TODO `<const P extends ...>` can be used after dropping support for TypeScript 4.x
+  // reference: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html#const-type-parameters
+  // after this change, `as const` assertions can be remove from the type tests
+  /**
+   * Returns the value at the provided key path starting at the provided
+   * collection, or notSetValue if the key path is not defined.
+   *
+   * A functional alternative to `collection.getIn(keypath)` which will also
+   * work with plain Objects and Arrays.
+   */
+  function getIn<C, P extends ReadonlyArray<PropertyKey>>(
+    object: C,
+    keyPath: [...P]
+  ): RetrievePath<C, P>;
+  function getIn<C, P extends KeyPath<unknown>>(object: C, keyPath: P): unknown;
+  function getIn<C, P extends ReadonlyArray<PropertyKey>, NSV>(
+    collection: C,
+    keyPath: [...P],
+    notSetValue: NSV
+  ): RetrievePath<C, P> extends never ? NSV : RetrievePath<C, P>;
+  function getIn<C, P extends KeyPath<unknown>, NSV>(
+    object: C,
+    keyPath: P,
+    notSetValue: NSV
+  ): unknown;
+
+  /**
+   * Returns true if the key path is defined in the provided collection.
+   *
+   * A functional alternative to `collection.hasIn(keypath)` which will also
+   * work with plain Objects and Arrays.
+   */
+  function hasIn(
+    collection: string | boolean | number,
+    keyPath: KeyPath<unknown>
+  ): never;
+  function hasIn<K>(collection: unknown, keyPath: KeyPath<K>): boolean;
+
+  /**
+   * Returns a copy of the collection with the value at the key path removed.
+   *
+   * A functional alternative to `collection.removeIn(keypath)` which will also
+   * work with plain Objects and Arrays.
+   */
+  function removeIn<C>(collection: C, keyPath: Iterable<unknown>): C;
+
+  /**
+   * Returns a copy of the collection with the value at the key path set to the
+   * provided value.
+   *
+   * A functional alternative to `collection.setIn(keypath)` which will also
+   * work with plain Objects and Arrays.
+   */
+  function setIn<C>(
+    collection: C,
+    keyPath: Iterable<unknown>,
+    value: unknown
+  ): C;
+
+  /**
+   * Returns a copy of the collection with the value at key path set to the
+   * result of providing the existing value to the updating function.
+   *
+   * A functional alternative to `collection.updateIn(keypath)` which will also
+   * work with plain Objects and Arrays.
+   */
+  function updateIn<K extends PropertyKey, V, C extends Collection<K, V>>(
+    collection: C,
+    keyPath: KeyPath<K>,
+    updater: (
+      value: RetrievePath<C, Array<K>> | undefined
+    ) => unknown | undefined
+  ): C;
+  function updateIn<K extends PropertyKey, V, C extends Collection<K, V>, NSV>(
+    collection: C,
+    keyPath: KeyPath<K>,
+    notSetValue: NSV,
+    updater: (value: RetrievePath<C, Array<K>> | NSV) => unknown
+  ): C;
+  function updateIn<
+    TProps extends object,
+    C extends Record<TProps>,
+    K extends keyof TProps,
+  >(
+    record: C,
+    keyPath: KeyPath<K>,
+    updater: (value: RetrievePath<C, Array<K>>) => unknown
+  ): C;
+  function updateIn<
+    TProps extends object,
+    C extends Record<TProps>,
+    K extends keyof TProps,
+    NSV,
+  >(
+    record: C,
+    keyPath: KeyPath<K>,
+    notSetValue: NSV,
+    updater: (value: RetrievePath<C, Array<K>> | NSV) => unknown
+  ): C;
+  function updateIn<K extends PropertyKey, V, C extends Array<V>>(
+    collection: Array<V>,
+    keyPath: KeyPath<string | number>,
+    updater: (
+      value: RetrievePath<C, Array<K>> | undefined
+    ) => unknown | undefined
+  ): Array<V>;
+  function updateIn<K extends PropertyKey, V, C extends Array<V>, NSV>(
+    collection: Array<V>,
+    keyPath: KeyPath<K>,
+    notSetValue: NSV,
+    updater: (value: RetrievePath<C, Array<K>> | NSV) => unknown
+  ): Array<V>;
+  function updateIn<K extends PropertyKey, C>(
+    object: C,
+    keyPath: KeyPath<K>,
+    updater: (value: RetrievePath<C, Array<K>>) => unknown
+  ): C;
+  function updateIn<K extends PropertyKey, C, NSV>(
+    object: C,
+    keyPath: KeyPath<K>,
+    notSetValue: NSV,
+    updater: (value: RetrievePath<C, Array<K>> | NSV) => unknown
+  ): C;
+  function updateIn<
+    K extends PropertyKey,
+    V,
+    C extends { [key: PropertyKey]: V },
+  >(
+    collection: C,
+    keyPath: KeyPath<K>,
+    updater: (value: RetrievePath<C, Array<K>>) => unknown
+  ): { [key: PropertyKey]: V };
+  function updateIn<
+    K extends PropertyKey,
+    V,
+    C extends { [key: PropertyKey]: V },
+    NSV,
+  >(
+    collection: C,
+    keyPath: KeyPath<K>,
+    notSetValue: NSV,
+    updater: (value: RetrievePath<C, Array<K>> | NSV) => unknown
+  ): { [key: PropertyKey]: V };
+
+  /**
+   * Returns a copy of the collection with the remaining collections merged in.
+   *
+   * A functional alternative to `collection.merge()` which will also work with
+   * plain Objects and Arrays.
+   */
+  function merge<C>(
+    collection: C,
+    ...collections: Array<
+      | Iterable<unknown>
+      | Iterable<[unknown, unknown]>
+      | { [key: string]: unknown }
+    >
+  ): C;
+
+  /**
+   * Returns a copy of the collection with the remaining collections merged in,
+   * calling the `merger` function whenever an existing value is encountered.
+   *
+   * A functional alternative to `collection.mergeWith()` which will also work
+   * with plain Objects and Arrays.
+   */
+  function mergeWith<C>(
+    merger: (oldVal: unknown, newVal: unknown, key: unknown) => unknown,
+    collection: C,
+    ...collections: Array<
+      | Iterable<unknown>
+      | Iterable<[unknown, unknown]>
+      | { [key: string]: unknown }
+    >
+  ): C;
+
+  /**
+   * Like `merge()`, but when two compatible collections are encountered with
+   * the same key, it merges them as well, recursing deeply through the nested
+   * data. Two collections are considered to be compatible (and thus will be
+   * merged together) if they both fall into one of three categories: keyed
+   * (e.g., `Map`s, `Record`s, and objects), indexed (e.g., `List`s and
+   * arrays), or set-like (e.g., `Set`s). If they fall into separate
+   * categories, `mergeDeep` will replace the existing collection with the
+   * collection being merged in. This behavior can be customized by using
+   * `mergeDeepWith()`.
+   *
+   * Note: Indexed and set-like collections are merged using
+   * `concat()`/`union()` and therefore do not recurse.
+   *
+   * A functional alternative to `collection.mergeDeep()` which will also work
+   * with plain Objects and Arrays.
+   */
+  function mergeDeep<C>(
+    collection: C,
+    ...collections: Array<
+      | Iterable<unknown>
+      | Iterable<[unknown, unknown]>
+      | { [key: string]: unknown }
+    >
+  ): C;
+
+  /**
+   * Like `mergeDeep()`, but when two non-collections or incompatible
+   * collections are encountered at the same key, it uses the `merger` function
+   * to determine the resulting value. Collections are considered incompatible
+   * if they fall into separate categories between keyed, indexed, and set-like.
+   *
+   * A functional alternative to `collection.mergeDeepWith()` which will also
+   * work with plain Objects and Arrays.
+   */
+  function mergeDeepWith<C>(
+    merger: (oldVal: unknown, newVal: unknown, key: unknown) => unknown,
+    collection: C,
+    ...collections: Array<
+      | Iterable<unknown>
+      | Iterable<[unknown, unknown]>
+      | { [key: string]: unknown }
+    >
+  ): C;
+}
+
+/**
+ * Defines the main export of the immutable module to be the Immutable namespace
+ * This supports many common module import patterns:
+ *
+ *     const Immutable = require("immutable");
+ *     const { List } = require("immutable");
+ *     import Immutable from "immutable";
+ *     import * as Immutable from "immutable";
+ *     import { List } from "immutable";
+ *
+ */
+export = Immutable;
+
+/**
+ * A global "Immutable" namespace used by UMD modules which allows the use of
+ * the full Immutable API.
+ *
+ * If using Immutable as an imported module, prefer using:
+ *
+ *     import Immutable from 'immutable'
+ *
+ */
+export as namespace Immutable;

+ 6182 - 0
node_modules/immutable/dist/immutable.es.js

@@ -0,0 +1,6182 @@
+/**
+ * @license
+ * MIT License
+ * 
+ * Copyright (c) 2014-present, Lee Byron and other contributors.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+// Used for setting prototype methods that IE8 chokes on.
+var DELETE = 'delete';
+// Constants describing the size of trie nodes.
+var SHIFT = 5; // Resulted in best performance after ______?
+var SIZE = 1 << SHIFT;
+var MASK = SIZE - 1;
+// A consistent shared value representing "not set" which equals nothing other
+// than itself, and nothing that could be provided externally.
+var NOT_SET = {};
+// Boolean references, Rough equivalent of `bool &`.
+function MakeRef() {
+    return { value: false };
+}
+function SetRef(ref) {
+    if (ref) {
+        ref.value = true;
+    }
+}
+// A function which returns a value representing an "owner" for transient writes
+// to tries. The return value will only ever equal itself, and will not equal
+// the return of any subsequent call of this function.
+function OwnerID() { }
+function ensureSize(iter) {
+    // @ts-expect-error size should exists on Collection
+    if (iter.size === undefined) {
+        // @ts-expect-error size should exists on Collection, __iterate does exist on Collection
+        iter.size = iter.__iterate(returnTrue);
+    }
+    // @ts-expect-error size should exists on Collection
+    return iter.size;
+}
+function wrapIndex(iter, index) {
+    // This implements "is array index" which the ECMAString spec defines as:
+    //
+    //     A String property name P is an array index if and only if
+    //     ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal
+    //     to 2^32−1.
+    //
+    // http://www.ecma-international.org/ecma-262/6.0/#sec-array-exotic-objects
+    if (typeof index !== 'number') {
+        var uint32Index = index >>> 0; // N >>> 0 is shorthand for ToUint32
+        if ('' + uint32Index !== index || uint32Index === 4294967295) {
+            return NaN;
+        }
+        index = uint32Index;
+    }
+    return index < 0 ? ensureSize(iter) + index : index;
+}
+function returnTrue() {
+    return true;
+}
+function wholeSlice(begin, end, size) {
+    return (((begin === 0 && !isNeg(begin)) ||
+        (size !== undefined && begin <= -size)) &&
+        (end === undefined || (size !== undefined && end >= size)));
+}
+function resolveBegin(begin, size) {
+    return resolveIndex(begin, size, 0);
+}
+function resolveEnd(end, size) {
+    return resolveIndex(end, size, size);
+}
+function resolveIndex(index, size, defaultIndex) {
+    // Sanitize indices using this shorthand for ToInt32(argument)
+    // http://www.ecma-international.org/ecma-262/6.0/#sec-toint32
+    return index === undefined
+        ? defaultIndex
+        : isNeg(index)
+            ? size === Infinity
+                ? size
+                : Math.max(0, size + index) | 0
+            : size === undefined || size === index
+                ? index
+                : Math.min(size, index) | 0;
+}
+function isNeg(value) {
+    // Account for -0 which is negative, but not less than 0.
+    return value < 0 || (value === 0 && 1 / value === -Infinity);
+}
+
+// Note: value is unchanged to not break immutable-devtools.
+var IS_COLLECTION_SYMBOL = '@@__IMMUTABLE_ITERABLE__@@';
+/**
+ * True if `maybeCollection` is a Collection, or any of its subclasses.
+ *
+ * ```js
+ * import { isCollection, Map, List, Stack } from 'immutable';
+ *
+ * isCollection([]); // false
+ * isCollection({}); // false
+ * isCollection(Map()); // true
+ * isCollection(List()); // true
+ * isCollection(Stack()); // true
+ * ```
+ */
+function isCollection(maybeCollection) {
+    return Boolean(maybeCollection &&
+        // @ts-expect-error: maybeCollection is typed as `{}`, need to change in 6.0 to `maybeCollection && typeof maybeCollection === 'object' && IS_COLLECTION_SYMBOL in maybeCollection`
+        maybeCollection[IS_COLLECTION_SYMBOL]);
+}
+
+var IS_KEYED_SYMBOL = '@@__IMMUTABLE_KEYED__@@';
+/**
+ * True if `maybeKeyed` is a Collection.Keyed, or any of its subclasses.
+ *
+ * ```js
+ * import { isKeyed, Map, List, Stack } from 'immutable';
+ *
+ * isKeyed([]); // false
+ * isKeyed({}); // false
+ * isKeyed(Map()); // true
+ * isKeyed(List()); // false
+ * isKeyed(Stack()); // false
+ * ```
+ */
+function isKeyed(maybeKeyed) {
+    return Boolean(maybeKeyed &&
+        // @ts-expect-error: maybeKeyed is typed as `{}`, need to change in 6.0 to `maybeKeyed && typeof maybeKeyed === 'object' && IS_KEYED_SYMBOL in maybeKeyed`
+        maybeKeyed[IS_KEYED_SYMBOL]);
+}
+
+var IS_INDEXED_SYMBOL = '@@__IMMUTABLE_INDEXED__@@';
+/**
+ * True if `maybeIndexed` is a Collection.Indexed, or any of its subclasses.
+ *
+ * ```js
+ * import { isIndexed, Map, List, Stack, Set } from 'immutable';
+ *
+ * isIndexed([]); // false
+ * isIndexed({}); // false
+ * isIndexed(Map()); // false
+ * isIndexed(List()); // true
+ * isIndexed(Stack()); // true
+ * isIndexed(Set()); // false
+ * ```
+ */
+function isIndexed(maybeIndexed) {
+    return Boolean(maybeIndexed &&
+        // @ts-expect-error: maybeIndexed is typed as `{}`, need to change in 6.0 to `maybeIndexed && typeof maybeIndexed === 'object' && IS_INDEXED_SYMBOL in maybeIndexed`
+        maybeIndexed[IS_INDEXED_SYMBOL]);
+}
+
+/**
+ * True if `maybeAssociative` is either a Keyed or Indexed Collection.
+ *
+ * ```js
+ * import { isAssociative, Map, List, Stack, Set } from 'immutable';
+ *
+ * isAssociative([]); // false
+ * isAssociative({}); // false
+ * isAssociative(Map()); // true
+ * isAssociative(List()); // true
+ * isAssociative(Stack()); // true
+ * isAssociative(Set()); // false
+ * ```
+ */
+function isAssociative(maybeAssociative) {
+    return isKeyed(maybeAssociative) || isIndexed(maybeAssociative);
+}
+
+var Collection = function Collection(value) {
+  // eslint-disable-next-line no-constructor-return
+  return isCollection(value) ? value : Seq(value);
+};
+
+var KeyedCollection = /*@__PURE__*/(function (Collection) {
+  function KeyedCollection(value) {
+    // eslint-disable-next-line no-constructor-return
+    return isKeyed(value) ? value : KeyedSeq(value);
+  }
+
+  if ( Collection ) KeyedCollection.__proto__ = Collection;
+  KeyedCollection.prototype = Object.create( Collection && Collection.prototype );
+  KeyedCollection.prototype.constructor = KeyedCollection;
+
+  return KeyedCollection;
+}(Collection));
+
+var IndexedCollection = /*@__PURE__*/(function (Collection) {
+  function IndexedCollection(value) {
+    // eslint-disable-next-line no-constructor-return
+    return isIndexed(value) ? value : IndexedSeq(value);
+  }
+
+  if ( Collection ) IndexedCollection.__proto__ = Collection;
+  IndexedCollection.prototype = Object.create( Collection && Collection.prototype );
+  IndexedCollection.prototype.constructor = IndexedCollection;
+
+  return IndexedCollection;
+}(Collection));
+
+var SetCollection = /*@__PURE__*/(function (Collection) {
+  function SetCollection(value) {
+    // eslint-disable-next-line no-constructor-return
+    return isCollection(value) && !isAssociative(value) ? value : SetSeq(value);
+  }
+
+  if ( Collection ) SetCollection.__proto__ = Collection;
+  SetCollection.prototype = Object.create( Collection && Collection.prototype );
+  SetCollection.prototype.constructor = SetCollection;
+
+  return SetCollection;
+}(Collection));
+
+Collection.Keyed = KeyedCollection;
+Collection.Indexed = IndexedCollection;
+Collection.Set = SetCollection;
+
+var IS_SEQ_SYMBOL = '@@__IMMUTABLE_SEQ__@@';
+/**
+ * True if `maybeSeq` is a Seq.
+ */
+function isSeq(maybeSeq) {
+    return Boolean(maybeSeq &&
+        // @ts-expect-error: maybeSeq is typed as `{}`, need to change in 6.0 to `maybeSeq && typeof maybeSeq === 'object' && MAYBE_SEQ_SYMBOL in maybeSeq`
+        maybeSeq[IS_SEQ_SYMBOL]);
+}
+
+var IS_RECORD_SYMBOL = '@@__IMMUTABLE_RECORD__@@';
+/**
+ * True if `maybeRecord` is a Record.
+ */
+function isRecord(maybeRecord) {
+    return Boolean(maybeRecord &&
+        // @ts-expect-error: maybeRecord is typed as `{}`, need to change in 6.0 to `maybeRecord && typeof maybeRecord === 'object' && IS_RECORD_SYMBOL in maybeRecord`
+        maybeRecord[IS_RECORD_SYMBOL]);
+}
+
+/**
+ * True if `maybeImmutable` is an Immutable Collection or Record.
+ *
+ * Note: Still returns true even if the collections is within a `withMutations()`.
+ *
+ * ```js
+ * import { isImmutable, Map, List, Stack } from 'immutable';
+ * isImmutable([]); // false
+ * isImmutable({}); // false
+ * isImmutable(Map()); // true
+ * isImmutable(List()); // true
+ * isImmutable(Stack()); // true
+ * isImmutable(Map().asMutable()); // true
+ * ```
+ */
+function isImmutable(maybeImmutable) {
+    return isCollection(maybeImmutable) || isRecord(maybeImmutable);
+}
+
+var IS_ORDERED_SYMBOL = '@@__IMMUTABLE_ORDERED__@@';
+function isOrdered(maybeOrdered) {
+    return Boolean(maybeOrdered &&
+        // @ts-expect-error: maybeOrdered is typed as `{}`, need to change in 6.0 to `maybeOrdered && typeof maybeOrdered === 'object' && IS_ORDERED_SYMBOL in maybeOrdered`
+        maybeOrdered[IS_ORDERED_SYMBOL]);
+}
+
+var ITERATE_KEYS = 0;
+var ITERATE_VALUES = 1;
+var ITERATE_ENTRIES = 2;
+
+var REAL_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
+var FAUX_ITERATOR_SYMBOL = '@@iterator';
+
+var ITERATOR_SYMBOL = REAL_ITERATOR_SYMBOL || FAUX_ITERATOR_SYMBOL;
+
+var Iterator = function Iterator(next) {
+  this.next = next;
+};
+
+Iterator.prototype.toString = function toString () {
+  return '[Iterator]';
+};
+
+Iterator.KEYS = ITERATE_KEYS;
+Iterator.VALUES = ITERATE_VALUES;
+Iterator.ENTRIES = ITERATE_ENTRIES;
+
+Iterator.prototype.inspect = Iterator.prototype.toSource = function () {
+  return this.toString();
+};
+Iterator.prototype[ITERATOR_SYMBOL] = function () {
+  return this;
+};
+
+function iteratorValue(type, k, v, iteratorResult) {
+  var value =
+    type === ITERATE_KEYS ? k : type === ITERATE_VALUES ? v : [k, v];
+  // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+  iteratorResult
+    ? (iteratorResult.value = value)
+    : (iteratorResult = {
+        value: value,
+        done: false,
+      });
+  return iteratorResult;
+}
+
+function iteratorDone() {
+  return { value: undefined, done: true };
+}
+
+function hasIterator(maybeIterable) {
+  if (Array.isArray(maybeIterable)) {
+    // IE11 trick as it does not support `Symbol.iterator`
+    return true;
+  }
+
+  return !!getIteratorFn(maybeIterable);
+}
+
+function isIterator(maybeIterator) {
+  return maybeIterator && typeof maybeIterator.next === 'function';
+}
+
+function getIterator(iterable) {
+  var iteratorFn = getIteratorFn(iterable);
+  return iteratorFn && iteratorFn.call(iterable);
+}
+
+function getIteratorFn(iterable) {
+  var iteratorFn =
+    iterable &&
+    ((REAL_ITERATOR_SYMBOL && iterable[REAL_ITERATOR_SYMBOL]) ||
+      iterable[FAUX_ITERATOR_SYMBOL]);
+  if (typeof iteratorFn === 'function') {
+    return iteratorFn;
+  }
+}
+
+function isEntriesIterable(maybeIterable) {
+  var iteratorFn = getIteratorFn(maybeIterable);
+  return iteratorFn && iteratorFn === maybeIterable.entries;
+}
+
+function isKeysIterable(maybeIterable) {
+  var iteratorFn = getIteratorFn(maybeIterable);
+  return iteratorFn && iteratorFn === maybeIterable.keys;
+}
+
+var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+function isArrayLike(value) {
+    if (Array.isArray(value) || typeof value === 'string') {
+        return true;
+    }
+    // @ts-expect-error "Type 'unknown' is not assignable to type 'boolean'" : convert to Boolean
+    return (value &&
+        typeof value === 'object' &&
+        // @ts-expect-error check that `'length' in value &&`
+        Number.isInteger(value.length) &&
+        // @ts-expect-error check that `'length' in value &&`
+        value.length >= 0 &&
+        // @ts-expect-error check that `'length' in value &&`
+        (value.length === 0
+            ? // Only {length: 0} is considered Array-like.
+                Object.keys(value).length === 1
+            : // An object is only Array-like if it has a property where the last value
+                // in the array-like may be found (which could be undefined).
+                // @ts-expect-error check that `'length' in value &&`
+                value.hasOwnProperty(value.length - 1)));
+}
+
+var Seq = /*@__PURE__*/(function (Collection) {
+  function Seq(value) {
+    // eslint-disable-next-line no-constructor-return
+    return value === undefined || value === null
+      ? emptySequence()
+      : isImmutable(value)
+        ? value.toSeq()
+        : seqFromValue(value);
+  }
+
+  if ( Collection ) Seq.__proto__ = Collection;
+  Seq.prototype = Object.create( Collection && Collection.prototype );
+  Seq.prototype.constructor = Seq;
+
+  Seq.prototype.toSeq = function toSeq () {
+    return this;
+  };
+
+  Seq.prototype.toString = function toString () {
+    return this.__toString('Seq {', '}');
+  };
+
+  Seq.prototype.cacheResult = function cacheResult () {
+    if (!this._cache && this.__iterateUncached) {
+      this._cache = this.entrySeq().toArray();
+      this.size = this._cache.length;
+    }
+    return this;
+  };
+
+  // abstract __iterateUncached(fn, reverse)
+
+  Seq.prototype.__iterate = function __iterate (fn, reverse) {
+    var cache = this._cache;
+    if (cache) {
+      var size = cache.length;
+      var i = 0;
+      while (i !== size) {
+        var entry = cache[reverse ? size - ++i : i++];
+        if (fn(entry[1], entry[0], this) === false) {
+          break;
+        }
+      }
+      return i;
+    }
+    return this.__iterateUncached(fn, reverse);
+  };
+
+  // abstract __iteratorUncached(type, reverse)
+
+  Seq.prototype.__iterator = function __iterator (type, reverse) {
+    var cache = this._cache;
+    if (cache) {
+      var size = cache.length;
+      var i = 0;
+      return new Iterator(function () {
+        if (i === size) {
+          return iteratorDone();
+        }
+        var entry = cache[reverse ? size - ++i : i++];
+        return iteratorValue(type, entry[0], entry[1]);
+      });
+    }
+    return this.__iteratorUncached(type, reverse);
+  };
+
+  return Seq;
+}(Collection));
+
+var KeyedSeq = /*@__PURE__*/(function (Seq) {
+  function KeyedSeq(value) {
+    // eslint-disable-next-line no-constructor-return
+    return value === undefined || value === null
+      ? emptySequence().toKeyedSeq()
+      : isCollection(value)
+        ? isKeyed(value)
+          ? value.toSeq()
+          : value.fromEntrySeq()
+        : isRecord(value)
+          ? value.toSeq()
+          : keyedSeqFromValue(value);
+  }
+
+  if ( Seq ) KeyedSeq.__proto__ = Seq;
+  KeyedSeq.prototype = Object.create( Seq && Seq.prototype );
+  KeyedSeq.prototype.constructor = KeyedSeq;
+
+  KeyedSeq.prototype.toKeyedSeq = function toKeyedSeq () {
+    return this;
+  };
+
+  return KeyedSeq;
+}(Seq));
+
+var IndexedSeq = /*@__PURE__*/(function (Seq) {
+  function IndexedSeq(value) {
+    // eslint-disable-next-line no-constructor-return
+    return value === undefined || value === null
+      ? emptySequence()
+      : isCollection(value)
+        ? isKeyed(value)
+          ? value.entrySeq()
+          : value.toIndexedSeq()
+        : isRecord(value)
+          ? value.toSeq().entrySeq()
+          : indexedSeqFromValue(value);
+  }
+
+  if ( Seq ) IndexedSeq.__proto__ = Seq;
+  IndexedSeq.prototype = Object.create( Seq && Seq.prototype );
+  IndexedSeq.prototype.constructor = IndexedSeq;
+
+  IndexedSeq.of = function of (/*...values*/) {
+    return IndexedSeq(arguments);
+  };
+
+  IndexedSeq.prototype.toIndexedSeq = function toIndexedSeq () {
+    return this;
+  };
+
+  IndexedSeq.prototype.toString = function toString () {
+    return this.__toString('Seq [', ']');
+  };
+
+  return IndexedSeq;
+}(Seq));
+
+var SetSeq = /*@__PURE__*/(function (Seq) {
+  function SetSeq(value) {
+    // eslint-disable-next-line no-constructor-return
+    return (
+      isCollection(value) && !isAssociative(value) ? value : IndexedSeq(value)
+    ).toSetSeq();
+  }
+
+  if ( Seq ) SetSeq.__proto__ = Seq;
+  SetSeq.prototype = Object.create( Seq && Seq.prototype );
+  SetSeq.prototype.constructor = SetSeq;
+
+  SetSeq.of = function of (/*...values*/) {
+    return SetSeq(arguments);
+  };
+
+  SetSeq.prototype.toSetSeq = function toSetSeq () {
+    return this;
+  };
+
+  return SetSeq;
+}(Seq));
+
+Seq.isSeq = isSeq;
+Seq.Keyed = KeyedSeq;
+Seq.Set = SetSeq;
+Seq.Indexed = IndexedSeq;
+
+Seq.prototype[IS_SEQ_SYMBOL] = true;
+
+// #pragma Root Sequences
+
+var ArraySeq = /*@__PURE__*/(function (IndexedSeq) {
+  function ArraySeq(array) {
+    this._array = array;
+    this.size = array.length;
+  }
+
+  if ( IndexedSeq ) ArraySeq.__proto__ = IndexedSeq;
+  ArraySeq.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
+  ArraySeq.prototype.constructor = ArraySeq;
+
+  ArraySeq.prototype.get = function get (index, notSetValue) {
+    return this.has(index) ? this._array[wrapIndex(this, index)] : notSetValue;
+  };
+
+  ArraySeq.prototype.__iterate = function __iterate (fn, reverse) {
+    var array = this._array;
+    var size = array.length;
+    var i = 0;
+    while (i !== size) {
+      var ii = reverse ? size - ++i : i++;
+      if (fn(array[ii], ii, this) === false) {
+        break;
+      }
+    }
+    return i;
+  };
+
+  ArraySeq.prototype.__iterator = function __iterator (type, reverse) {
+    var array = this._array;
+    var size = array.length;
+    var i = 0;
+    return new Iterator(function () {
+      if (i === size) {
+        return iteratorDone();
+      }
+      var ii = reverse ? size - ++i : i++;
+      return iteratorValue(type, ii, array[ii]);
+    });
+  };
+
+  return ArraySeq;
+}(IndexedSeq));
+
+var ObjectSeq = /*@__PURE__*/(function (KeyedSeq) {
+  function ObjectSeq(object) {
+    var keys = Object.keys(object).concat(
+      Object.getOwnPropertySymbols ? Object.getOwnPropertySymbols(object) : []
+    );
+    this._object = object;
+    this._keys = keys;
+    this.size = keys.length;
+  }
+
+  if ( KeyedSeq ) ObjectSeq.__proto__ = KeyedSeq;
+  ObjectSeq.prototype = Object.create( KeyedSeq && KeyedSeq.prototype );
+  ObjectSeq.prototype.constructor = ObjectSeq;
+
+  ObjectSeq.prototype.get = function get (key, notSetValue) {
+    if (notSetValue !== undefined && !this.has(key)) {
+      return notSetValue;
+    }
+    return this._object[key];
+  };
+
+  ObjectSeq.prototype.has = function has (key) {
+    return hasOwnProperty.call(this._object, key);
+  };
+
+  ObjectSeq.prototype.__iterate = function __iterate (fn, reverse) {
+    var object = this._object;
+    var keys = this._keys;
+    var size = keys.length;
+    var i = 0;
+    while (i !== size) {
+      var key = keys[reverse ? size - ++i : i++];
+      if (fn(object[key], key, this) === false) {
+        break;
+      }
+    }
+    return i;
+  };
+
+  ObjectSeq.prototype.__iterator = function __iterator (type, reverse) {
+    var object = this._object;
+    var keys = this._keys;
+    var size = keys.length;
+    var i = 0;
+    return new Iterator(function () {
+      if (i === size) {
+        return iteratorDone();
+      }
+      var key = keys[reverse ? size - ++i : i++];
+      return iteratorValue(type, key, object[key]);
+    });
+  };
+
+  return ObjectSeq;
+}(KeyedSeq));
+ObjectSeq.prototype[IS_ORDERED_SYMBOL] = true;
+
+var CollectionSeq = /*@__PURE__*/(function (IndexedSeq) {
+  function CollectionSeq(collection) {
+    this._collection = collection;
+    this.size = collection.length || collection.size;
+  }
+
+  if ( IndexedSeq ) CollectionSeq.__proto__ = IndexedSeq;
+  CollectionSeq.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
+  CollectionSeq.prototype.constructor = CollectionSeq;
+
+  CollectionSeq.prototype.__iterateUncached = function __iterateUncached (fn, reverse) {
+    if (reverse) {
+      return this.cacheResult().__iterate(fn, reverse);
+    }
+    var collection = this._collection;
+    var iterator = getIterator(collection);
+    var iterations = 0;
+    if (isIterator(iterator)) {
+      var step;
+      while (!(step = iterator.next()).done) {
+        if (fn(step.value, iterations++, this) === false) {
+          break;
+        }
+      }
+    }
+    return iterations;
+  };
+
+  CollectionSeq.prototype.__iteratorUncached = function __iteratorUncached (type, reverse) {
+    if (reverse) {
+      return this.cacheResult().__iterator(type, reverse);
+    }
+    var collection = this._collection;
+    var iterator = getIterator(collection);
+    if (!isIterator(iterator)) {
+      return new Iterator(iteratorDone);
+    }
+    var iterations = 0;
+    return new Iterator(function () {
+      var step = iterator.next();
+      return step.done ? step : iteratorValue(type, iterations++, step.value);
+    });
+  };
+
+  return CollectionSeq;
+}(IndexedSeq));
+
+// # pragma Helper functions
+
+var EMPTY_SEQ;
+
+function emptySequence() {
+  return EMPTY_SEQ || (EMPTY_SEQ = new ArraySeq([]));
+}
+
+function keyedSeqFromValue(value) {
+  var seq = maybeIndexedSeqFromValue(value);
+  if (seq) {
+    return seq.fromEntrySeq();
+  }
+  if (typeof value === 'object') {
+    return new ObjectSeq(value);
+  }
+  throw new TypeError(
+    'Expected Array or collection object of [k, v] entries, or keyed object: ' +
+      value
+  );
+}
+
+function indexedSeqFromValue(value) {
+  var seq = maybeIndexedSeqFromValue(value);
+  if (seq) {
+    return seq;
+  }
+  throw new TypeError(
+    'Expected Array or collection object of values: ' + value
+  );
+}
+
+function seqFromValue(value) {
+  var seq = maybeIndexedSeqFromValue(value);
+  if (seq) {
+    return isEntriesIterable(value)
+      ? seq.fromEntrySeq()
+      : isKeysIterable(value)
+        ? seq.toSetSeq()
+        : seq;
+  }
+  if (typeof value === 'object') {
+    return new ObjectSeq(value);
+  }
+  throw new TypeError(
+    'Expected Array or collection object of values, or keyed object: ' + value
+  );
+}
+
+function maybeIndexedSeqFromValue(value) {
+  return isArrayLike(value)
+    ? new ArraySeq(value)
+    : hasIterator(value)
+      ? new CollectionSeq(value)
+      : undefined;
+}
+
+var IS_MAP_SYMBOL = '@@__IMMUTABLE_MAP__@@';
+/**
+ * True if `maybeMap` is a Map.
+ *
+ * Also true for OrderedMaps.
+ */
+function isMap(maybeMap) {
+    return Boolean(maybeMap &&
+        // @ts-expect-error: maybeMap is typed as `{}`, need to change in 6.0 to `maybeMap && typeof maybeMap === 'object' && IS_MAP_SYMBOL in maybeMap`
+        maybeMap[IS_MAP_SYMBOL]);
+}
+
+/**
+ * True if `maybeOrderedMap` is an OrderedMap.
+ */
+function isOrderedMap(maybeOrderedMap) {
+    return isMap(maybeOrderedMap) && isOrdered(maybeOrderedMap);
+}
+
+/**
+ * True if `maybeValue` is a JavaScript Object which has *both* `equals()`
+ * and `hashCode()` methods.
+ *
+ * Any two instances of *value objects* can be compared for value equality with
+ * `Immutable.is()` and can be used as keys in a `Map` or members in a `Set`.
+ */
+function isValueObject(maybeValue) {
+    return Boolean(maybeValue &&
+        // @ts-expect-error: maybeValue is typed as `{}`
+        typeof maybeValue.equals === 'function' &&
+        // @ts-expect-error: maybeValue is typed as `{}`
+        typeof maybeValue.hashCode === 'function');
+}
+
+/**
+ * An extension of the "same-value" algorithm as [described for use by ES6 Map
+ * and Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Key_equality)
+ *
+ * NaN is considered the same as NaN, however -0 and 0 are considered the same
+ * value, which is different from the algorithm described by
+ * [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is).
+ *
+ * This is extended further to allow Objects to describe the values they
+ * represent, by way of `valueOf` or `equals` (and `hashCode`).
+ *
+ * Note: because of this extension, the key equality of Immutable.Map and the
+ * value equality of Immutable.Set will differ from ES6 Map and Set.
+ *
+ * ### Defining custom values
+ *
+ * The easiest way to describe the value an object represents is by implementing
+ * `valueOf`. For example, `Date` represents a value by returning a unix
+ * timestamp for `valueOf`:
+ *
+ *     var date1 = new Date(1234567890000); // Fri Feb 13 2009 ...
+ *     var date2 = new Date(1234567890000);
+ *     date1.valueOf(); // 1234567890000
+ *     assert( date1 !== date2 );
+ *     assert( Immutable.is( date1, date2 ) );
+ *
+ * Note: overriding `valueOf` may have other implications if you use this object
+ * where JavaScript expects a primitive, such as implicit string coercion.
+ *
+ * For more complex types, especially collections, implementing `valueOf` may
+ * not be performant. An alternative is to implement `equals` and `hashCode`.
+ *
+ * `equals` takes another object, presumably of similar type, and returns true
+ * if it is equal. Equality is symmetrical, so the same result should be
+ * returned if this and the argument are flipped.
+ *
+ *     assert( a.equals(b) === b.equals(a) );
+ *
+ * `hashCode` returns a 32bit integer number representing the object which will
+ * be used to determine how to store the value object in a Map or Set. You must
+ * provide both or neither methods, one must not exist without the other.
+ *
+ * Also, an important relationship between these methods must be upheld: if two
+ * values are equal, they *must* return the same hashCode. If the values are not
+ * equal, they might have the same hashCode; this is called a hash collision,
+ * and while undesirable for performance reasons, it is acceptable.
+ *
+ *     if (a.equals(b)) {
+ *       assert( a.hashCode() === b.hashCode() );
+ *     }
+ *
+ * All Immutable collections are Value Objects: they implement `equals()`
+ * and `hashCode()`.
+ */
+function is(valueA, valueB) {
+    if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) {
+        return true;
+    }
+    if (!valueA || !valueB) {
+        return false;
+    }
+    if (typeof valueA.valueOf === 'function' &&
+        typeof valueB.valueOf === 'function') {
+        valueA = valueA.valueOf();
+        valueB = valueB.valueOf();
+        if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) {
+            return true;
+        }
+        if (!valueA || !valueB) {
+            return false;
+        }
+    }
+    return !!(isValueObject(valueA) &&
+        isValueObject(valueB) &&
+        valueA.equals(valueB));
+}
+
+var imul =
+  typeof Math.imul === 'function' && Math.imul(0xffffffff, 2) === -2
+    ? Math.imul
+    : function imul(a, b) {
+        a |= 0; // int
+        b |= 0; // int
+        var c = a & 0xffff;
+        var d = b & 0xffff;
+        // Shift by 0 fixes the sign on the high part.
+        return (c * d + ((((a >>> 16) * d + c * (b >>> 16)) << 16) >>> 0)) | 0; // int
+      };
+
+// v8 has an optimization for storing 31-bit signed numbers.
+// Values which have either 00 or 11 as the high order bits qualify.
+// This function drops the highest order bit in a signed number, maintaining
+// the sign bit.
+function smi(i32) {
+  return ((i32 >>> 1) & 0x40000000) | (i32 & 0xbfffffff);
+}
+
+var defaultValueOf = Object.prototype.valueOf;
+
+function hash(o) {
+  // eslint-disable-next-line eqeqeq
+  if (o == null) {
+    return hashNullish(o);
+  }
+
+  if (typeof o.hashCode === 'function') {
+    // Drop any high bits from accidentally long hash codes.
+    return smi(o.hashCode(o));
+  }
+
+  var v = valueOf(o);
+
+  // eslint-disable-next-line eqeqeq
+  if (v == null) {
+    return hashNullish(v);
+  }
+
+  switch (typeof v) {
+    case 'boolean':
+      // The hash values for built-in constants are a 1 value for each 5-byte
+      // shift region expect for the first, which encodes the value. This
+      // reduces the odds of a hash collision for these common values.
+      return v ? 0x42108421 : 0x42108420;
+    case 'number':
+      return hashNumber(v);
+    case 'string':
+      return v.length > STRING_HASH_CACHE_MIN_STRLEN
+        ? cachedHashString(v)
+        : hashString(v);
+    case 'object':
+    case 'function':
+      return hashJSObj(v);
+    case 'symbol':
+      return hashSymbol(v);
+    default:
+      if (typeof v.toString === 'function') {
+        return hashString(v.toString());
+      }
+      throw new Error('Value type ' + typeof v + ' cannot be hashed.');
+  }
+}
+
+function hashNullish(nullish) {
+  return nullish === null ? 0x42108422 : /* undefined */ 0x42108423;
+}
+
+// Compress arbitrarily large numbers into smi hashes.
+function hashNumber(n) {
+  if (n !== n || n === Infinity) {
+    return 0;
+  }
+  var hash = n | 0;
+  if (hash !== n) {
+    hash ^= n * 0xffffffff;
+  }
+  while (n > 0xffffffff) {
+    n /= 0xffffffff;
+    hash ^= n;
+  }
+  return smi(hash);
+}
+
+function cachedHashString(string) {
+  var hashed = stringHashCache[string];
+  if (hashed === undefined) {
+    hashed = hashString(string);
+    if (STRING_HASH_CACHE_SIZE === STRING_HASH_CACHE_MAX_SIZE) {
+      STRING_HASH_CACHE_SIZE = 0;
+      stringHashCache = {};
+    }
+    STRING_HASH_CACHE_SIZE++;
+    stringHashCache[string] = hashed;
+  }
+  return hashed;
+}
+
+// http://jsperf.com/hashing-strings
+function hashString(string) {
+  // This is the hash from JVM
+  // The hash code for a string is computed as
+  // s[0] * 31 ^ (n - 1) + s[1] * 31 ^ (n - 2) + ... + s[n - 1],
+  // where s[i] is the ith character of the string and n is the length of
+  // the string. We "mod" the result to make it between 0 (inclusive) and 2^31
+  // (exclusive) by dropping high bits.
+  var hashed = 0;
+  for (var ii = 0; ii < string.length; ii++) {
+    hashed = (31 * hashed + string.charCodeAt(ii)) | 0;
+  }
+  return smi(hashed);
+}
+
+function hashSymbol(sym) {
+  var hashed = symbolMap[sym];
+  if (hashed !== undefined) {
+    return hashed;
+  }
+
+  hashed = nextHash();
+
+  symbolMap[sym] = hashed;
+
+  return hashed;
+}
+
+function hashJSObj(obj) {
+  var hashed;
+  if (usingWeakMap) {
+    hashed = weakMap.get(obj);
+    if (hashed !== undefined) {
+      return hashed;
+    }
+  }
+
+  hashed = obj[UID_HASH_KEY];
+  if (hashed !== undefined) {
+    return hashed;
+  }
+
+  if (!canDefineProperty) {
+    hashed = obj.propertyIsEnumerable && obj.propertyIsEnumerable[UID_HASH_KEY];
+    if (hashed !== undefined) {
+      return hashed;
+    }
+
+    hashed = getIENodeHash(obj);
+    if (hashed !== undefined) {
+      return hashed;
+    }
+  }
+
+  hashed = nextHash();
+
+  if (usingWeakMap) {
+    weakMap.set(obj, hashed);
+  } else if (isExtensible !== undefined && isExtensible(obj) === false) {
+    throw new Error('Non-extensible objects are not allowed as keys.');
+  } else if (canDefineProperty) {
+    Object.defineProperty(obj, UID_HASH_KEY, {
+      enumerable: false,
+      configurable: false,
+      writable: false,
+      value: hashed,
+    });
+  } else if (
+    obj.propertyIsEnumerable !== undefined &&
+    obj.propertyIsEnumerable === obj.constructor.prototype.propertyIsEnumerable
+  ) {
+    // Since we can't define a non-enumerable property on the object
+    // we'll hijack one of the less-used non-enumerable properties to
+    // save our hash on it. Since this is a function it will not show up in
+    // `JSON.stringify` which is what we want.
+    obj.propertyIsEnumerable = function () {
+      return this.constructor.prototype.propertyIsEnumerable.apply(
+        this,
+        arguments
+      );
+    };
+    obj.propertyIsEnumerable[UID_HASH_KEY] = hashed;
+  } else if (obj.nodeType !== undefined) {
+    // At this point we couldn't get the IE `uniqueID` to use as a hash
+    // and we couldn't use a non-enumerable property to exploit the
+    // dontEnum bug so we simply add the `UID_HASH_KEY` on the node
+    // itself.
+    obj[UID_HASH_KEY] = hashed;
+  } else {
+    throw new Error('Unable to set a non-enumerable property on object.');
+  }
+
+  return hashed;
+}
+
+// Get references to ES5 object methods.
+var isExtensible = Object.isExtensible;
+
+// True if Object.defineProperty works as expected. IE8 fails this test.
+var canDefineProperty = (function () {
+  try {
+    Object.defineProperty({}, '@', {});
+    return true;
+    // eslint-disable-next-line @typescript-eslint/no-unused-vars
+  } catch (e) {
+    return false;
+  }
+})();
+
+// IE has a `uniqueID` property on DOM nodes. We can construct the hash from it
+// and avoid memory leaks from the IE cloneNode bug.
+function getIENodeHash(node) {
+  if (node && node.nodeType > 0) {
+    switch (node.nodeType) {
+      case 1: // Element
+        return node.uniqueID;
+      case 9: // Document
+        return node.documentElement && node.documentElement.uniqueID;
+    }
+  }
+}
+
+function valueOf(obj) {
+  return obj.valueOf !== defaultValueOf && typeof obj.valueOf === 'function'
+    ? obj.valueOf(obj)
+    : obj;
+}
+
+function nextHash() {
+  var nextHash = ++_objHashUID;
+  if (_objHashUID & 0x40000000) {
+    _objHashUID = 0;
+  }
+  return nextHash;
+}
+
+// If possible, use a WeakMap.
+var usingWeakMap = typeof WeakMap === 'function';
+var weakMap;
+if (usingWeakMap) {
+  weakMap = new WeakMap();
+}
+
+var symbolMap = Object.create(null);
+
+var _objHashUID = 0;
+
+var UID_HASH_KEY = '__immutablehash__';
+if (typeof Symbol === 'function') {
+  UID_HASH_KEY = Symbol(UID_HASH_KEY);
+}
+
+var STRING_HASH_CACHE_MIN_STRLEN = 16;
+var STRING_HASH_CACHE_MAX_SIZE = 255;
+var STRING_HASH_CACHE_SIZE = 0;
+var stringHashCache = {};
+
+var ToKeyedSequence = /*@__PURE__*/(function (KeyedSeq) {
+  function ToKeyedSequence(indexed, useKeys) {
+    this._iter = indexed;
+    this._useKeys = useKeys;
+    this.size = indexed.size;
+  }
+
+  if ( KeyedSeq ) ToKeyedSequence.__proto__ = KeyedSeq;
+  ToKeyedSequence.prototype = Object.create( KeyedSeq && KeyedSeq.prototype );
+  ToKeyedSequence.prototype.constructor = ToKeyedSequence;
+
+  ToKeyedSequence.prototype.get = function get (key, notSetValue) {
+    return this._iter.get(key, notSetValue);
+  };
+
+  ToKeyedSequence.prototype.has = function has (key) {
+    return this._iter.has(key);
+  };
+
+  ToKeyedSequence.prototype.valueSeq = function valueSeq () {
+    return this._iter.valueSeq();
+  };
+
+  ToKeyedSequence.prototype.reverse = function reverse () {
+    var this$1$1 = this;
+
+    var reversedSequence = reverseFactory(this, true);
+    if (!this._useKeys) {
+      reversedSequence.valueSeq = function () { return this$1$1._iter.toSeq().reverse(); };
+    }
+    return reversedSequence;
+  };
+
+  ToKeyedSequence.prototype.map = function map (mapper, context) {
+    var this$1$1 = this;
+
+    var mappedSequence = mapFactory(this, mapper, context);
+    if (!this._useKeys) {
+      mappedSequence.valueSeq = function () { return this$1$1._iter.toSeq().map(mapper, context); };
+    }
+    return mappedSequence;
+  };
+
+  ToKeyedSequence.prototype.__iterate = function __iterate (fn, reverse) {
+    var this$1$1 = this;
+
+    return this._iter.__iterate(function (v, k) { return fn(v, k, this$1$1); }, reverse);
+  };
+
+  ToKeyedSequence.prototype.__iterator = function __iterator (type, reverse) {
+    return this._iter.__iterator(type, reverse);
+  };
+
+  return ToKeyedSequence;
+}(KeyedSeq));
+ToKeyedSequence.prototype[IS_ORDERED_SYMBOL] = true;
+
+var ToIndexedSequence = /*@__PURE__*/(function (IndexedSeq) {
+  function ToIndexedSequence(iter) {
+    this._iter = iter;
+    this.size = iter.size;
+  }
+
+  if ( IndexedSeq ) ToIndexedSequence.__proto__ = IndexedSeq;
+  ToIndexedSequence.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
+  ToIndexedSequence.prototype.constructor = ToIndexedSequence;
+
+  ToIndexedSequence.prototype.includes = function includes (value) {
+    return this._iter.includes(value);
+  };
+
+  ToIndexedSequence.prototype.__iterate = function __iterate (fn, reverse) {
+    var this$1$1 = this;
+
+    var i = 0;
+    // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+    reverse && ensureSize(this);
+    return this._iter.__iterate(
+      function (v) { return fn(v, reverse ? this$1$1.size - ++i : i++, this$1$1); },
+      reverse
+    );
+  };
+
+  ToIndexedSequence.prototype.__iterator = function __iterator (type, reverse) {
+    var this$1$1 = this;
+
+    var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);
+    var i = 0;
+    // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+    reverse && ensureSize(this);
+    return new Iterator(function () {
+      var step = iterator.next();
+      return step.done
+        ? step
+        : iteratorValue(
+            type,
+            reverse ? this$1$1.size - ++i : i++,
+            step.value,
+            step
+          );
+    });
+  };
+
+  return ToIndexedSequence;
+}(IndexedSeq));
+
+var ToSetSequence = /*@__PURE__*/(function (SetSeq) {
+  function ToSetSequence(iter) {
+    this._iter = iter;
+    this.size = iter.size;
+  }
+
+  if ( SetSeq ) ToSetSequence.__proto__ = SetSeq;
+  ToSetSequence.prototype = Object.create( SetSeq && SetSeq.prototype );
+  ToSetSequence.prototype.constructor = ToSetSequence;
+
+  ToSetSequence.prototype.has = function has (key) {
+    return this._iter.includes(key);
+  };
+
+  ToSetSequence.prototype.__iterate = function __iterate (fn, reverse) {
+    var this$1$1 = this;
+
+    return this._iter.__iterate(function (v) { return fn(v, v, this$1$1); }, reverse);
+  };
+
+  ToSetSequence.prototype.__iterator = function __iterator (type, reverse) {
+    var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);
+    return new Iterator(function () {
+      var step = iterator.next();
+      return step.done
+        ? step
+        : iteratorValue(type, step.value, step.value, step);
+    });
+  };
+
+  return ToSetSequence;
+}(SetSeq));
+
+var FromEntriesSequence = /*@__PURE__*/(function (KeyedSeq) {
+  function FromEntriesSequence(entries) {
+    this._iter = entries;
+    this.size = entries.size;
+  }
+
+  if ( KeyedSeq ) FromEntriesSequence.__proto__ = KeyedSeq;
+  FromEntriesSequence.prototype = Object.create( KeyedSeq && KeyedSeq.prototype );
+  FromEntriesSequence.prototype.constructor = FromEntriesSequence;
+
+  FromEntriesSequence.prototype.entrySeq = function entrySeq () {
+    return this._iter.toSeq();
+  };
+
+  FromEntriesSequence.prototype.__iterate = function __iterate (fn, reverse) {
+    var this$1$1 = this;
+
+    return this._iter.__iterate(function (entry) {
+      // Check if entry exists first so array access doesn't throw for holes
+      // in the parent iteration.
+      if (entry) {
+        validateEntry(entry);
+        var indexedCollection = isCollection(entry);
+        return fn(
+          indexedCollection ? entry.get(1) : entry[1],
+          indexedCollection ? entry.get(0) : entry[0],
+          this$1$1
+        );
+      }
+    }, reverse);
+  };
+
+  FromEntriesSequence.prototype.__iterator = function __iterator (type, reverse) {
+    var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);
+    return new Iterator(function () {
+      while (true) {
+        var step = iterator.next();
+        if (step.done) {
+          return step;
+        }
+        var entry = step.value;
+        // Check if entry exists first so array access doesn't throw for holes
+        // in the parent iteration.
+        if (entry) {
+          validateEntry(entry);
+          var indexedCollection = isCollection(entry);
+          return iteratorValue(
+            type,
+            indexedCollection ? entry.get(0) : entry[0],
+            indexedCollection ? entry.get(1) : entry[1],
+            step
+          );
+        }
+      }
+    });
+  };
+
+  return FromEntriesSequence;
+}(KeyedSeq));
+
+ToIndexedSequence.prototype.cacheResult =
+  ToKeyedSequence.prototype.cacheResult =
+  ToSetSequence.prototype.cacheResult =
+  FromEntriesSequence.prototype.cacheResult =
+    cacheResultThrough;
+
+function flipFactory(collection) {
+  var flipSequence = makeSequence(collection);
+  flipSequence._iter = collection;
+  flipSequence.size = collection.size;
+  flipSequence.flip = function () { return collection; };
+  flipSequence.reverse = function () {
+    var reversedSequence = collection.reverse.apply(this); // super.reverse()
+    reversedSequence.flip = function () { return collection.reverse(); };
+    return reversedSequence;
+  };
+  flipSequence.has = function (key) { return collection.includes(key); };
+  flipSequence.includes = function (key) { return collection.has(key); };
+  flipSequence.cacheResult = cacheResultThrough;
+  flipSequence.__iterateUncached = function (fn, reverse) {
+    var this$1$1 = this;
+
+    return collection.__iterate(function (v, k) { return fn(k, v, this$1$1) !== false; }, reverse);
+  };
+  flipSequence.__iteratorUncached = function (type, reverse) {
+    if (type === ITERATE_ENTRIES) {
+      var iterator = collection.__iterator(type, reverse);
+      return new Iterator(function () {
+        var step = iterator.next();
+        if (!step.done) {
+          var k = step.value[0];
+          step.value[0] = step.value[1];
+          step.value[1] = k;
+        }
+        return step;
+      });
+    }
+    return collection.__iterator(
+      type === ITERATE_VALUES ? ITERATE_KEYS : ITERATE_VALUES,
+      reverse
+    );
+  };
+  return flipSequence;
+}
+
+function mapFactory(collection, mapper, context) {
+  var mappedSequence = makeSequence(collection);
+  mappedSequence.size = collection.size;
+  mappedSequence.has = function (key) { return collection.has(key); };
+  mappedSequence.get = function (key, notSetValue) {
+    var v = collection.get(key, NOT_SET);
+    return v === NOT_SET
+      ? notSetValue
+      : mapper.call(context, v, key, collection);
+  };
+  mappedSequence.__iterateUncached = function (fn, reverse) {
+    var this$1$1 = this;
+
+    return collection.__iterate(
+      function (v, k, c) { return fn(mapper.call(context, v, k, c), k, this$1$1) !== false; },
+      reverse
+    );
+  };
+  mappedSequence.__iteratorUncached = function (type, reverse) {
+    var iterator = collection.__iterator(ITERATE_ENTRIES, reverse);
+    return new Iterator(function () {
+      var step = iterator.next();
+      if (step.done) {
+        return step;
+      }
+      var entry = step.value;
+      var key = entry[0];
+      return iteratorValue(
+        type,
+        key,
+        mapper.call(context, entry[1], key, collection),
+        step
+      );
+    });
+  };
+  return mappedSequence;
+}
+
+function reverseFactory(collection, useKeys) {
+  var this$1$1 = this;
+
+  var reversedSequence = makeSequence(collection);
+  reversedSequence._iter = collection;
+  reversedSequence.size = collection.size;
+  reversedSequence.reverse = function () { return collection; };
+  if (collection.flip) {
+    reversedSequence.flip = function () {
+      var flipSequence = flipFactory(collection);
+      flipSequence.reverse = function () { return collection.flip(); };
+      return flipSequence;
+    };
+  }
+  reversedSequence.get = function (key, notSetValue) { return collection.get(useKeys ? key : -1 - key, notSetValue); };
+  reversedSequence.has = function (key) { return collection.has(useKeys ? key : -1 - key); };
+  reversedSequence.includes = function (value) { return collection.includes(value); };
+  reversedSequence.cacheResult = cacheResultThrough;
+  reversedSequence.__iterate = function (fn, reverse) {
+    var this$1$1 = this;
+
+    var i = 0;
+    // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+    reverse && ensureSize(collection);
+    return collection.__iterate(
+      function (v, k) { return fn(v, useKeys ? k : reverse ? this$1$1.size - ++i : i++, this$1$1); },
+      !reverse
+    );
+  };
+  reversedSequence.__iterator = function (type, reverse) {
+    var i = 0;
+    // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+    reverse && ensureSize(collection);
+    var iterator = collection.__iterator(ITERATE_ENTRIES, !reverse);
+    return new Iterator(function () {
+      var step = iterator.next();
+      if (step.done) {
+        return step;
+      }
+      var entry = step.value;
+      return iteratorValue(
+        type,
+        useKeys ? entry[0] : reverse ? this$1$1.size - ++i : i++,
+        entry[1],
+        step
+      );
+    });
+  };
+  return reversedSequence;
+}
+
+function filterFactory(collection, predicate, context, useKeys) {
+  var filterSequence = makeSequence(collection);
+  if (useKeys) {
+    filterSequence.has = function (key) {
+      var v = collection.get(key, NOT_SET);
+      return v !== NOT_SET && !!predicate.call(context, v, key, collection);
+    };
+    filterSequence.get = function (key, notSetValue) {
+      var v = collection.get(key, NOT_SET);
+      return v !== NOT_SET && predicate.call(context, v, key, collection)
+        ? v
+        : notSetValue;
+    };
+  }
+  filterSequence.__iterateUncached = function (fn, reverse) {
+    var this$1$1 = this;
+
+    var iterations = 0;
+    collection.__iterate(function (v, k, c) {
+      if (predicate.call(context, v, k, c)) {
+        iterations++;
+        return fn(v, useKeys ? k : iterations - 1, this$1$1);
+      }
+    }, reverse);
+    return iterations;
+  };
+  filterSequence.__iteratorUncached = function (type, reverse) {
+    var iterator = collection.__iterator(ITERATE_ENTRIES, reverse);
+    var iterations = 0;
+    return new Iterator(function () {
+      while (true) {
+        var step = iterator.next();
+        if (step.done) {
+          return step;
+        }
+        var entry = step.value;
+        var key = entry[0];
+        var value = entry[1];
+        if (predicate.call(context, value, key, collection)) {
+          return iteratorValue(type, useKeys ? key : iterations++, value, step);
+        }
+      }
+    });
+  };
+  return filterSequence;
+}
+
+function countByFactory(collection, grouper, context) {
+  var groups = Map().asMutable();
+  collection.__iterate(function (v, k) {
+    groups.update(grouper.call(context, v, k, collection), 0, function (a) { return a + 1; });
+  });
+  return groups.asImmutable();
+}
+
+function groupByFactory(collection, grouper, context) {
+  var isKeyedIter = isKeyed(collection);
+  var groups = (isOrdered(collection) ? OrderedMap() : Map()).asMutable();
+  collection.__iterate(function (v, k) {
+    groups.update(
+      grouper.call(context, v, k, collection),
+      function (a) { return ((a = a || []), a.push(isKeyedIter ? [k, v] : v), a); }
+    );
+  });
+  var coerce = collectionClass(collection);
+  return groups.map(function (arr) { return reify(collection, coerce(arr)); }).asImmutable();
+}
+
+function partitionFactory(collection, predicate, context) {
+  var isKeyedIter = isKeyed(collection);
+  var groups = [[], []];
+  collection.__iterate(function (v, k) {
+    groups[predicate.call(context, v, k, collection) ? 1 : 0].push(
+      isKeyedIter ? [k, v] : v
+    );
+  });
+  var coerce = collectionClass(collection);
+  return groups.map(function (arr) { return reify(collection, coerce(arr)); });
+}
+
+function sliceFactory(collection, begin, end, useKeys) {
+  var originalSize = collection.size;
+
+  if (wholeSlice(begin, end, originalSize)) {
+    return collection;
+  }
+
+  // begin or end can not be resolved if they were provided as negative numbers and
+  // this collection's size is unknown. In that case, cache first so there is
+  // a known size and these do not resolve to NaN.
+  if (typeof originalSize === 'undefined' && (begin < 0 || end < 0)) {
+    return sliceFactory(collection.toSeq().cacheResult(), begin, end, useKeys);
+  }
+
+  var resolvedBegin = resolveBegin(begin, originalSize);
+  var resolvedEnd = resolveEnd(end, originalSize);
+
+  // Note: resolvedEnd is undefined when the original sequence's length is
+  // unknown and this slice did not supply an end and should contain all
+  // elements after resolvedBegin.
+  // In that case, resolvedSize will be NaN and sliceSize will remain undefined.
+  var resolvedSize = resolvedEnd - resolvedBegin;
+  var sliceSize;
+  if (resolvedSize === resolvedSize) {
+    sliceSize = resolvedSize < 0 ? 0 : resolvedSize;
+  }
+
+  var sliceSeq = makeSequence(collection);
+
+  // If collection.size is undefined, the size of the realized sliceSeq is
+  // unknown at this point unless the number of items to slice is 0
+  sliceSeq.size =
+    sliceSize === 0 ? sliceSize : (collection.size && sliceSize) || undefined;
+
+  if (!useKeys && isSeq(collection) && sliceSize >= 0) {
+    sliceSeq.get = function (index, notSetValue) {
+      index = wrapIndex(this, index);
+      return index >= 0 && index < sliceSize
+        ? collection.get(index + resolvedBegin, notSetValue)
+        : notSetValue;
+    };
+  }
+
+  sliceSeq.__iterateUncached = function (fn, reverse) {
+    var this$1$1 = this;
+
+    if (sliceSize === 0) {
+      return 0;
+    }
+    if (reverse) {
+      return this.cacheResult().__iterate(fn, reverse);
+    }
+    var skipped = 0;
+    var isSkipping = true;
+    var iterations = 0;
+    collection.__iterate(function (v, k) {
+      if (!(isSkipping && (isSkipping = skipped++ < resolvedBegin))) {
+        iterations++;
+        return (
+          fn(v, useKeys ? k : iterations - 1, this$1$1) !== false &&
+          iterations !== sliceSize
+        );
+      }
+    });
+    return iterations;
+  };
+
+  sliceSeq.__iteratorUncached = function (type, reverse) {
+    if (sliceSize !== 0 && reverse) {
+      return this.cacheResult().__iterator(type, reverse);
+    }
+    // Don't bother instantiating parent iterator if taking 0.
+    if (sliceSize === 0) {
+      return new Iterator(iteratorDone);
+    }
+    var iterator = collection.__iterator(type, reverse);
+    var skipped = 0;
+    var iterations = 0;
+    return new Iterator(function () {
+      while (skipped++ < resolvedBegin) {
+        iterator.next();
+      }
+      if (++iterations > sliceSize) {
+        return iteratorDone();
+      }
+      var step = iterator.next();
+      if (useKeys || type === ITERATE_VALUES || step.done) {
+        return step;
+      }
+      if (type === ITERATE_KEYS) {
+        return iteratorValue(type, iterations - 1, undefined, step);
+      }
+      return iteratorValue(type, iterations - 1, step.value[1], step);
+    });
+  };
+
+  return sliceSeq;
+}
+
+function takeWhileFactory(collection, predicate, context) {
+  var takeSequence = makeSequence(collection);
+  takeSequence.__iterateUncached = function (fn, reverse) {
+    var this$1$1 = this;
+
+    if (reverse) {
+      return this.cacheResult().__iterate(fn, reverse);
+    }
+    var iterations = 0;
+    collection.__iterate(
+      function (v, k, c) { return predicate.call(context, v, k, c) && ++iterations && fn(v, k, this$1$1); }
+    );
+    return iterations;
+  };
+  takeSequence.__iteratorUncached = function (type, reverse) {
+    var this$1$1 = this;
+
+    if (reverse) {
+      return this.cacheResult().__iterator(type, reverse);
+    }
+    var iterator = collection.__iterator(ITERATE_ENTRIES, reverse);
+    var iterating = true;
+    return new Iterator(function () {
+      if (!iterating) {
+        return iteratorDone();
+      }
+      var step = iterator.next();
+      if (step.done) {
+        return step;
+      }
+      var entry = step.value;
+      var k = entry[0];
+      var v = entry[1];
+      if (!predicate.call(context, v, k, this$1$1)) {
+        iterating = false;
+        return iteratorDone();
+      }
+      return type === ITERATE_ENTRIES ? step : iteratorValue(type, k, v, step);
+    });
+  };
+  return takeSequence;
+}
+
+function skipWhileFactory(collection, predicate, context, useKeys) {
+  var skipSequence = makeSequence(collection);
+  skipSequence.__iterateUncached = function (fn, reverse) {
+    var this$1$1 = this;
+
+    if (reverse) {
+      return this.cacheResult().__iterate(fn, reverse);
+    }
+    var isSkipping = true;
+    var iterations = 0;
+    collection.__iterate(function (v, k, c) {
+      if (!(isSkipping && (isSkipping = predicate.call(context, v, k, c)))) {
+        iterations++;
+        return fn(v, useKeys ? k : iterations - 1, this$1$1);
+      }
+    });
+    return iterations;
+  };
+  skipSequence.__iteratorUncached = function (type, reverse) {
+    var this$1$1 = this;
+
+    if (reverse) {
+      return this.cacheResult().__iterator(type, reverse);
+    }
+    var iterator = collection.__iterator(ITERATE_ENTRIES, reverse);
+    var skipping = true;
+    var iterations = 0;
+    return new Iterator(function () {
+      var step;
+      var k;
+      var v;
+      do {
+        step = iterator.next();
+        if (step.done) {
+          if (useKeys || type === ITERATE_VALUES) {
+            return step;
+          }
+          if (type === ITERATE_KEYS) {
+            return iteratorValue(type, iterations++, undefined, step);
+          }
+          return iteratorValue(type, iterations++, step.value[1], step);
+        }
+        var entry = step.value;
+        k = entry[0];
+        v = entry[1];
+        // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+        skipping && (skipping = predicate.call(context, v, k, this$1$1));
+      } while (skipping);
+      return type === ITERATE_ENTRIES ? step : iteratorValue(type, k, v, step);
+    });
+  };
+  return skipSequence;
+}
+
+var ConcatSeq = /*@__PURE__*/(function (Seq) {
+  function ConcatSeq(iterables) {
+    this._wrappedIterables = iterables.flatMap(function (iterable) {
+      if (iterable._wrappedIterables) {
+        return iterable._wrappedIterables;
+      }
+      return [iterable];
+    });
+    this.size = this._wrappedIterables.reduce(function (sum, iterable) {
+      if (sum !== undefined) {
+        var size = iterable.size;
+        if (size !== undefined) {
+          return sum + size;
+        }
+      }
+    }, 0);
+    this[IS_KEYED_SYMBOL] = this._wrappedIterables[0][IS_KEYED_SYMBOL];
+    this[IS_INDEXED_SYMBOL] = this._wrappedIterables[0][IS_INDEXED_SYMBOL];
+    this[IS_ORDERED_SYMBOL] = this._wrappedIterables[0][IS_ORDERED_SYMBOL];
+  }
+
+  if ( Seq ) ConcatSeq.__proto__ = Seq;
+  ConcatSeq.prototype = Object.create( Seq && Seq.prototype );
+  ConcatSeq.prototype.constructor = ConcatSeq;
+
+  ConcatSeq.prototype.__iterateUncached = function __iterateUncached (fn, reverse) {
+    if (this._wrappedIterables.length === 0) {
+      return;
+    }
+
+    if (reverse) {
+      return this.cacheResult().__iterate(fn, reverse);
+    }
+
+    var iterableIndex = 0;
+    var useKeys = isKeyed(this);
+    var iteratorType = useKeys ? ITERATE_ENTRIES : ITERATE_VALUES;
+    var currentIterator = this._wrappedIterables[iterableIndex].__iterator(
+      iteratorType,
+      reverse
+    );
+
+    var keepGoing = true;
+    var index = 0;
+    while (keepGoing) {
+      var next = currentIterator.next();
+      while (next.done) {
+        iterableIndex++;
+        if (iterableIndex === this._wrappedIterables.length) {
+          return index;
+        }
+        currentIterator = this._wrappedIterables[iterableIndex].__iterator(
+          iteratorType,
+          reverse
+        );
+        next = currentIterator.next();
+      }
+      var fnResult = useKeys
+        ? fn(next.value[1], next.value[0], this)
+        : fn(next.value, index, this);
+      keepGoing = fnResult !== false;
+      index++;
+    }
+    return index;
+  };
+
+  ConcatSeq.prototype.__iteratorUncached = function __iteratorUncached (type, reverse) {
+    var this$1$1 = this;
+
+    if (this._wrappedIterables.length === 0) {
+      return new Iterator(iteratorDone);
+    }
+
+    if (reverse) {
+      return this.cacheResult().__iterator(type, reverse);
+    }
+
+    var iterableIndex = 0;
+    var currentIterator = this._wrappedIterables[iterableIndex].__iterator(
+      type,
+      reverse
+    );
+    return new Iterator(function () {
+      var next = currentIterator.next();
+      while (next.done) {
+        iterableIndex++;
+        if (iterableIndex === this$1$1._wrappedIterables.length) {
+          return next;
+        }
+        currentIterator = this$1$1._wrappedIterables[iterableIndex].__iterator(
+          type,
+          reverse
+        );
+        next = currentIterator.next();
+      }
+      return next;
+    });
+  };
+
+  return ConcatSeq;
+}(Seq));
+
+function concatFactory(collection, values) {
+  var isKeyedCollection = isKeyed(collection);
+  var iters = [collection]
+    .concat(values)
+    .map(function (v) {
+      if (!isCollection(v)) {
+        v = isKeyedCollection
+          ? keyedSeqFromValue(v)
+          : indexedSeqFromValue(Array.isArray(v) ? v : [v]);
+      } else if (isKeyedCollection) {
+        v = KeyedCollection(v);
+      }
+      return v;
+    })
+    .filter(function (v) { return v.size !== 0; });
+
+  if (iters.length === 0) {
+    return collection;
+  }
+
+  if (iters.length === 1) {
+    var singleton = iters[0];
+    if (
+      singleton === collection ||
+      (isKeyedCollection && isKeyed(singleton)) ||
+      (isIndexed(collection) && isIndexed(singleton))
+    ) {
+      return singleton;
+    }
+  }
+
+  return new ConcatSeq(iters);
+}
+
+function flattenFactory(collection, depth, useKeys) {
+  var flatSequence = makeSequence(collection);
+  flatSequence.__iterateUncached = function (fn, reverse) {
+    if (reverse) {
+      return this.cacheResult().__iterate(fn, reverse);
+    }
+    var iterations = 0;
+    var stopped = false;
+    function flatDeep(iter, currentDepth) {
+      iter.__iterate(function (v, k) {
+        if ((!depth || currentDepth < depth) && isCollection(v)) {
+          flatDeep(v, currentDepth + 1);
+        } else {
+          iterations++;
+          if (fn(v, useKeys ? k : iterations - 1, flatSequence) === false) {
+            stopped = true;
+          }
+        }
+        return !stopped;
+      }, reverse);
+    }
+    flatDeep(collection, 0);
+    return iterations;
+  };
+  flatSequence.__iteratorUncached = function (type, reverse) {
+    if (reverse) {
+      return this.cacheResult().__iterator(type, reverse);
+    }
+    var iterator = collection.__iterator(type, reverse);
+    var stack = [];
+    var iterations = 0;
+    return new Iterator(function () {
+      while (iterator) {
+        var step = iterator.next();
+        if (step.done !== false) {
+          iterator = stack.pop();
+          continue;
+        }
+        var v = step.value;
+        if (type === ITERATE_ENTRIES) {
+          v = v[1];
+        }
+        if ((!depth || stack.length < depth) && isCollection(v)) {
+          stack.push(iterator);
+          iterator = v.__iterator(type, reverse);
+        } else {
+          return useKeys ? step : iteratorValue(type, iterations++, v, step);
+        }
+      }
+      return iteratorDone();
+    });
+  };
+  return flatSequence;
+}
+
+function flatMapFactory(collection, mapper, context) {
+  var coerce = collectionClass(collection);
+  return collection
+    .toSeq()
+    .map(function (v, k) { return coerce(mapper.call(context, v, k, collection)); })
+    .flatten(true);
+}
+
+function interposeFactory(collection, separator) {
+  var interposedSequence = makeSequence(collection);
+  interposedSequence.size = collection.size && collection.size * 2 - 1;
+  interposedSequence.__iterateUncached = function (fn, reverse) {
+    var this$1$1 = this;
+
+    var iterations = 0;
+    collection.__iterate(
+      function (v) { return (!iterations || fn(separator, iterations++, this$1$1) !== false) &&
+        fn(v, iterations++, this$1$1) !== false; },
+      reverse
+    );
+    return iterations;
+  };
+  interposedSequence.__iteratorUncached = function (type, reverse) {
+    var iterator = collection.__iterator(ITERATE_VALUES, reverse);
+    var iterations = 0;
+    var step;
+    return new Iterator(function () {
+      if (!step || iterations % 2) {
+        step = iterator.next();
+        if (step.done) {
+          return step;
+        }
+      }
+      return iterations % 2
+        ? iteratorValue(type, iterations++, separator)
+        : iteratorValue(type, iterations++, step.value, step);
+    });
+  };
+  return interposedSequence;
+}
+
+function sortFactory(collection, comparator, mapper) {
+  if (!comparator) {
+    comparator = defaultComparator;
+  }
+  var isKeyedCollection = isKeyed(collection);
+  var index = 0;
+  var entries = collection
+    .toSeq()
+    .map(function (v, k) { return [k, v, index++, mapper ? mapper(v, k, collection) : v]; })
+    .valueSeq()
+    .toArray();
+  entries
+    .sort(function (a, b) { return comparator(a[3], b[3]) || a[2] - b[2]; })
+    .forEach(
+      isKeyedCollection
+        ? function (v, i) {
+            entries[i].length = 2;
+          }
+        : function (v, i) {
+            entries[i] = v[1];
+          }
+    );
+  return isKeyedCollection
+    ? KeyedSeq(entries)
+    : isIndexed(collection)
+      ? IndexedSeq(entries)
+      : SetSeq(entries);
+}
+
+function maxFactory(collection, comparator, mapper) {
+  if (!comparator) {
+    comparator = defaultComparator;
+  }
+  if (mapper) {
+    var entry = collection
+      .toSeq()
+      .map(function (v, k) { return [v, mapper(v, k, collection)]; })
+      .reduce(function (a, b) { return (maxCompare(comparator, a[1], b[1]) ? b : a); });
+    return entry && entry[0];
+  }
+  return collection.reduce(function (a, b) { return (maxCompare(comparator, a, b) ? b : a); });
+}
+
+function maxCompare(comparator, a, b) {
+  var comp = comparator(b, a);
+  // b is considered the new max if the comparator declares them equal, but
+  // they are not equal and b is in fact a nullish value.
+  return (
+    (comp === 0 && b !== a && (b === undefined || b === null || b !== b)) ||
+    comp > 0
+  );
+}
+
+function zipWithFactory(keyIter, zipper, iters, zipAll) {
+  var zipSequence = makeSequence(keyIter);
+  var sizes = new ArraySeq(iters).map(function (i) { return i.size; });
+  zipSequence.size = zipAll ? sizes.max() : sizes.min();
+  // Note: this a generic base implementation of __iterate in terms of
+  // __iterator which may be more generically useful in the future.
+  zipSequence.__iterate = function (fn, reverse) {
+    /* generic:
+    var iterator = this.__iterator(ITERATE_ENTRIES, reverse);
+    var step;
+    var iterations = 0;
+    while (!(step = iterator.next()).done) {
+      iterations++;
+      if (fn(step.value[1], step.value[0], this) === false) {
+        break;
+      }
+    }
+    return iterations;
+    */
+    // indexed:
+    var iterator = this.__iterator(ITERATE_VALUES, reverse);
+    var step;
+    var iterations = 0;
+    while (!(step = iterator.next()).done) {
+      if (fn(step.value, iterations++, this) === false) {
+        break;
+      }
+    }
+    return iterations;
+  };
+  zipSequence.__iteratorUncached = function (type, reverse) {
+    var iterators = iters.map(
+      function (i) { return ((i = Collection(i)), getIterator(reverse ? i.reverse() : i)); }
+    );
+    var iterations = 0;
+    var isDone = false;
+    return new Iterator(function () {
+      var steps;
+      if (!isDone) {
+        steps = iterators.map(function (i) { return i.next(); });
+        isDone = zipAll
+          ? steps.every(function (s) { return s.done; })
+          : steps.some(function (s) { return s.done; });
+      }
+      if (isDone) {
+        return iteratorDone();
+      }
+      return iteratorValue(
+        type,
+        iterations++,
+        zipper.apply(
+          null,
+          steps.map(function (s) { return s.value; })
+        )
+      );
+    });
+  };
+  return zipSequence;
+}
+
+// #pragma Helper Functions
+
+function reify(iter, seq) {
+  return iter === seq ? iter : isSeq(iter) ? seq : iter.constructor(seq);
+}
+
+function validateEntry(entry) {
+  if (entry !== Object(entry)) {
+    throw new TypeError('Expected [K, V] tuple: ' + entry);
+  }
+}
+
+function collectionClass(collection) {
+  return isKeyed(collection)
+    ? KeyedCollection
+    : isIndexed(collection)
+      ? IndexedCollection
+      : SetCollection;
+}
+
+function makeSequence(collection) {
+  return Object.create(
+    (isKeyed(collection)
+      ? KeyedSeq
+      : isIndexed(collection)
+        ? IndexedSeq
+        : SetSeq
+    ).prototype
+  );
+}
+
+function cacheResultThrough() {
+  if (this._iter.cacheResult) {
+    this._iter.cacheResult();
+    this.size = this._iter.size;
+    return this;
+  }
+  return Seq.prototype.cacheResult.call(this);
+}
+
+function defaultComparator(a, b) {
+  if (a === undefined && b === undefined) {
+    return 0;
+  }
+
+  if (a === undefined) {
+    return 1;
+  }
+
+  if (b === undefined) {
+    return -1;
+  }
+
+  return a > b ? 1 : a < b ? -1 : 0;
+}
+
+// http://jsperf.com/copy-array-inline
+function arrCopy(arr, offset) {
+    offset = offset || 0;
+    var len = Math.max(0, arr.length - offset);
+    var newArr = new Array(len);
+    for (var ii = 0; ii < len; ii++) {
+        // @ts-expect-error We may want to guard for undefined values with `if (arr[ii + offset] !== undefined`, but ths should not happen by design
+        newArr[ii] = arr[ii + offset];
+    }
+    return newArr;
+}
+
+function invariant(condition, error) {
+    if (!condition)
+        { throw new Error(error); }
+}
+
+function assertNotInfinite(size) {
+    invariant(size !== Infinity, 'Cannot perform this action with an infinite size.');
+}
+
+function coerceKeyPath(keyPath) {
+    if (isArrayLike(keyPath) && typeof keyPath !== 'string') {
+        return keyPath;
+    }
+    if (isOrdered(keyPath)) {
+        return keyPath.toArray();
+    }
+    throw new TypeError('Invalid keyPath: expected Ordered Collection or Array: ' + keyPath);
+}
+
+var toString = Object.prototype.toString;
+function isPlainObject(value) {
+    // The base prototype's toString deals with Argument objects and native namespaces like Math
+    if (!value ||
+        typeof value !== 'object' ||
+        toString.call(value) !== '[object Object]') {
+        return false;
+    }
+    var proto = Object.getPrototypeOf(value);
+    if (proto === null) {
+        return true;
+    }
+    // Iteratively going up the prototype chain is needed for cross-realm environments (differing contexts, iframes, etc)
+    var parentProto = proto;
+    var nextProto = Object.getPrototypeOf(proto);
+    while (nextProto !== null) {
+        parentProto = nextProto;
+        nextProto = Object.getPrototypeOf(parentProto);
+    }
+    return parentProto === proto;
+}
+
+/**
+ * Returns true if the value is a potentially-persistent data structure, either
+ * provided by Immutable.js or a plain Array or Object.
+ */
+function isDataStructure(value) {
+    return (typeof value === 'object' &&
+        (isImmutable(value) || Array.isArray(value) || isPlainObject(value)));
+}
+
+/**
+ * Converts a value to a string, adding quotes if a string was provided.
+ */
+function quoteString(value) {
+    try {
+        return typeof value === 'string' ? JSON.stringify(value) : String(value);
+        // eslint-disable-next-line @typescript-eslint/no-unused-vars
+    }
+    catch (_ignoreError) {
+        return JSON.stringify(value);
+    }
+}
+
+/**
+ * Returns true if the key is defined in the provided collection.
+ *
+ * A functional alternative to `collection.has(key)` which will also work with
+ * plain Objects and Arrays as an alternative for
+ * `collection.hasOwnProperty(key)`.
+ */
+function has(collection, key) {
+    return isImmutable(collection)
+        ? // @ts-expect-error key might be a number or symbol, which is not handled be Record key type
+            collection.has(key)
+        : // @ts-expect-error key might be anything else than PropertyKey, and will return false in that case but runtime is OK
+            isDataStructure(collection) && hasOwnProperty.call(collection, key);
+}
+
+function get(collection, key, notSetValue) {
+    return isImmutable(collection)
+        ? collection.get(key, notSetValue)
+        : !has(collection, key)
+            ? notSetValue
+            : // @ts-expect-error weird "get" here,
+                typeof collection.get === 'function'
+                    ? // @ts-expect-error weird "get" here,
+                        collection.get(key)
+                    : // @ts-expect-error key is unknown here,
+                        collection[key];
+}
+
+function shallowCopy(from) {
+    if (Array.isArray(from)) {
+        return arrCopy(from);
+    }
+    var to = {};
+    for (var key in from) {
+        if (hasOwnProperty.call(from, key)) {
+            to[key] = from[key];
+        }
+    }
+    return to;
+}
+
+function remove(collection, key) {
+    if (!isDataStructure(collection)) {
+        throw new TypeError('Cannot update non-data-structure value: ' + collection);
+    }
+    if (isImmutable(collection)) {
+        // @ts-expect-error weird "remove" here,
+        if (!collection.remove) {
+            throw new TypeError('Cannot update immutable value without .remove() method: ' + collection);
+        }
+        // @ts-expect-error weird "remove" here,
+        return collection.remove(key);
+    }
+    // @ts-expect-error assert that key is a string, a number or a symbol here
+    if (!hasOwnProperty.call(collection, key)) {
+        return collection;
+    }
+    var collectionCopy = shallowCopy(collection);
+    if (Array.isArray(collectionCopy)) {
+        // @ts-expect-error assert that key is a number here
+        collectionCopy.splice(key, 1);
+    }
+    else {
+        // @ts-expect-error assert that key is a string, a number or a symbol here
+        delete collectionCopy[key];
+    }
+    return collectionCopy;
+}
+
+function set(collection, key, value) {
+    if (!isDataStructure(collection)) {
+        throw new TypeError('Cannot update non-data-structure value: ' + collection);
+    }
+    if (isImmutable(collection)) {
+        // @ts-expect-error weird "set" here,
+        if (!collection.set) {
+            throw new TypeError('Cannot update immutable value without .set() method: ' + collection);
+        }
+        // @ts-expect-error weird "set" here,
+        return collection.set(key, value);
+    }
+    // @ts-expect-error mix of key and string here. Probably need a more fine type here
+    if (hasOwnProperty.call(collection, key) && value === collection[key]) {
+        return collection;
+    }
+    var collectionCopy = shallowCopy(collection);
+    // @ts-expect-error mix of key and string here. Probably need a more fine type here
+    collectionCopy[key] = value;
+    return collectionCopy;
+}
+
+function updateIn$1(collection, keyPath, notSetValue, updater) {
+    if (!updater) {
+        // handle the fact that `notSetValue` is optional here, in that case `updater` is the updater function
+        // @ts-expect-error updater is a function here
+        updater = notSetValue;
+        notSetValue = undefined;
+    }
+    var updatedValue = updateInDeeply(isImmutable(collection), 
+    // @ts-expect-error type issues with Record and mixed types
+    collection, coerceKeyPath(keyPath), 0, notSetValue, updater);
+    // @ts-expect-error mixed return type
+    return updatedValue === NOT_SET ? notSetValue : updatedValue;
+}
+function updateInDeeply(inImmutable, existing, keyPath, i, notSetValue, updater) {
+    var wasNotSet = existing === NOT_SET;
+    if (i === keyPath.length) {
+        var existingValue = wasNotSet ? notSetValue : existing;
+        // @ts-expect-error mixed type with optional value
+        var newValue = updater(existingValue);
+        // @ts-expect-error mixed type
+        return newValue === existingValue ? existing : newValue;
+    }
+    if (!wasNotSet && !isDataStructure(existing)) {
+        throw new TypeError('Cannot update within non-data-structure value in path [' +
+            Array.from(keyPath).slice(0, i).map(quoteString) +
+            ']: ' +
+            existing);
+    }
+    var key = keyPath[i];
+    var nextExisting = wasNotSet ? NOT_SET : get(existing, key, NOT_SET);
+    var nextUpdated = updateInDeeply(nextExisting === NOT_SET ? inImmutable : isImmutable(nextExisting), 
+    // @ts-expect-error mixed type
+    nextExisting, keyPath, i + 1, notSetValue, updater);
+    return nextUpdated === nextExisting
+        ? existing
+        : nextUpdated === NOT_SET
+            ? remove(existing, key)
+            : set(wasNotSet ? (inImmutable ? emptyMap() : {}) : existing, key, nextUpdated);
+}
+
+/**
+ * Returns a copy of the collection with the value at the key path set to the
+ * provided value.
+ *
+ * A functional alternative to `collection.setIn(keypath)` which will also
+ * work with plain Objects and Arrays.
+ */
+function setIn$1(collection, keyPath, value) {
+    return updateIn$1(collection, keyPath, NOT_SET, function () { return value; });
+}
+
+function setIn(keyPath, v) {
+  return setIn$1(this, keyPath, v);
+}
+
+/**
+ * Returns a copy of the collection with the value at the key path removed.
+ *
+ * A functional alternative to `collection.removeIn(keypath)` which will also
+ * work with plain Objects and Arrays.
+ */
+function removeIn(collection, keyPath) {
+    return updateIn$1(collection, keyPath, function () { return NOT_SET; });
+}
+
+function deleteIn(keyPath) {
+  return removeIn(this, keyPath);
+}
+
+function update$1(collection, key, notSetValue, updater) {
+    return updateIn$1(
+    // @ts-expect-error Index signature for type string is missing in type V[]
+    collection, [key], notSetValue, updater);
+}
+
+function update(key, notSetValue, updater) {
+  return arguments.length === 1
+    ? key(this)
+    : update$1(this, key, notSetValue, updater);
+}
+
+function updateIn(keyPath, notSetValue, updater) {
+  return updateIn$1(this, keyPath, notSetValue, updater);
+}
+
+function merge$1() {
+  var iters = [], len = arguments.length;
+  while ( len-- ) iters[ len ] = arguments[ len ];
+
+  return mergeIntoKeyedWith(this, iters);
+}
+
+function mergeWith$1(merger) {
+  var iters = [], len = arguments.length - 1;
+  while ( len-- > 0 ) iters[ len ] = arguments[ len + 1 ];
+
+  if (typeof merger !== 'function') {
+    throw new TypeError('Invalid merger function: ' + merger);
+  }
+  return mergeIntoKeyedWith(this, iters, merger);
+}
+
+function mergeIntoKeyedWith(collection, collections, merger) {
+  var iters = [];
+  for (var ii = 0; ii < collections.length; ii++) {
+    var collection$1 = KeyedCollection(collections[ii]);
+    if (collection$1.size !== 0) {
+      iters.push(collection$1);
+    }
+  }
+  if (iters.length === 0) {
+    return collection;
+  }
+  if (
+    collection.toSeq().size === 0 &&
+    !collection.__ownerID &&
+    iters.length === 1
+  ) {
+    return isRecord(collection)
+      ? collection // Record is empty and will not be updated: return the same instance
+      : collection.constructor(iters[0]);
+  }
+  return collection.withMutations(function (collection) {
+    var mergeIntoCollection = merger
+      ? function (value, key) {
+          update$1(collection, key, NOT_SET, function (oldVal) { return oldVal === NOT_SET ? value : merger(oldVal, value, key); }
+          );
+        }
+      : function (value, key) {
+          collection.set(key, value);
+        };
+    for (var ii = 0; ii < iters.length; ii++) {
+      iters[ii].forEach(mergeIntoCollection);
+    }
+  });
+}
+
+function merge(collection) {
+  var sources = [], len = arguments.length - 1;
+  while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ];
+
+  return mergeWithSources(collection, sources);
+}
+
+function mergeWith(merger, collection) {
+  var sources = [], len = arguments.length - 2;
+  while ( len-- > 0 ) sources[ len ] = arguments[ len + 2 ];
+
+  return mergeWithSources(collection, sources, merger);
+}
+
+function mergeDeep$1(collection) {
+  var sources = [], len = arguments.length - 1;
+  while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ];
+
+  return mergeDeepWithSources(collection, sources);
+}
+
+function mergeDeepWith$1(merger, collection) {
+  var sources = [], len = arguments.length - 2;
+  while ( len-- > 0 ) sources[ len ] = arguments[ len + 2 ];
+
+  return mergeDeepWithSources(collection, sources, merger);
+}
+
+function mergeDeepWithSources(collection, sources, merger) {
+  return mergeWithSources(collection, sources, deepMergerWith(merger));
+}
+
+function mergeWithSources(collection, sources, merger) {
+  if (!isDataStructure(collection)) {
+    throw new TypeError(
+      'Cannot merge into non-data-structure value: ' + collection
+    );
+  }
+  if (isImmutable(collection)) {
+    return typeof merger === 'function' && collection.mergeWith
+      ? collection.mergeWith.apply(collection, [ merger ].concat( sources ))
+      : collection.merge
+        ? collection.merge.apply(collection, sources)
+        : collection.concat.apply(collection, sources);
+  }
+  var isArray = Array.isArray(collection);
+  var merged = collection;
+  var Collection = isArray ? IndexedCollection : KeyedCollection;
+  var mergeItem = isArray
+    ? function (value) {
+        // Copy on write
+        if (merged === collection) {
+          merged = shallowCopy(merged);
+        }
+        merged.push(value);
+      }
+    : function (value, key) {
+        var hasVal = hasOwnProperty.call(merged, key);
+        var nextVal =
+          hasVal && merger ? merger(merged[key], value, key) : value;
+        if (!hasVal || nextVal !== merged[key]) {
+          // Copy on write
+          if (merged === collection) {
+            merged = shallowCopy(merged);
+          }
+          merged[key] = nextVal;
+        }
+      };
+  for (var i = 0; i < sources.length; i++) {
+    Collection(sources[i]).forEach(mergeItem);
+  }
+  return merged;
+}
+
+function deepMergerWith(merger) {
+  function deepMerger(oldValue, newValue, key) {
+    return isDataStructure(oldValue) &&
+      isDataStructure(newValue) &&
+      areMergeable(oldValue, newValue)
+      ? mergeWithSources(oldValue, [newValue], deepMerger)
+      : merger
+        ? merger(oldValue, newValue, key)
+        : newValue;
+  }
+  return deepMerger;
+}
+
+/**
+ * It's unclear what the desired behavior is for merging two collections that
+ * fall into separate categories between keyed, indexed, or set-like, so we only
+ * consider them mergeable if they fall into the same category.
+ */
+function areMergeable(oldDataStructure, newDataStructure) {
+  var oldSeq = Seq(oldDataStructure);
+  var newSeq = Seq(newDataStructure);
+  // This logic assumes that a sequence can only fall into one of the three
+  // categories mentioned above (since there's no `isSetLike()` method).
+  return (
+    isIndexed(oldSeq) === isIndexed(newSeq) &&
+    isKeyed(oldSeq) === isKeyed(newSeq)
+  );
+}
+
+function mergeDeep() {
+  var iters = [], len = arguments.length;
+  while ( len-- ) iters[ len ] = arguments[ len ];
+
+  return mergeDeepWithSources(this, iters);
+}
+
+function mergeDeepWith(merger) {
+  var iters = [], len = arguments.length - 1;
+  while ( len-- > 0 ) iters[ len ] = arguments[ len + 1 ];
+
+  return mergeDeepWithSources(this, iters, merger);
+}
+
+function mergeIn(keyPath) {
+  var iters = [], len = arguments.length - 1;
+  while ( len-- > 0 ) iters[ len ] = arguments[ len + 1 ];
+
+  return updateIn$1(this, keyPath, emptyMap(), function (m) { return mergeWithSources(m, iters); });
+}
+
+function mergeDeepIn(keyPath) {
+  var iters = [], len = arguments.length - 1;
+  while ( len-- > 0 ) iters[ len ] = arguments[ len + 1 ];
+
+  return updateIn$1(this, keyPath, emptyMap(), function (m) { return mergeDeepWithSources(m, iters); }
+  );
+}
+
+function withMutations(fn) {
+  var mutable = this.asMutable();
+  fn(mutable);
+  return mutable.wasAltered() ? mutable.__ensureOwner(this.__ownerID) : this;
+}
+
+function asMutable() {
+  return this.__ownerID ? this : this.__ensureOwner(new OwnerID());
+}
+
+function asImmutable() {
+  return this.__ensureOwner();
+}
+
+function wasAltered() {
+  return this.__altered;
+}
+
+var Map = /*@__PURE__*/(function (KeyedCollection) {
+  function Map(value) {
+    // eslint-disable-next-line no-constructor-return
+    return value === undefined || value === null
+      ? emptyMap()
+      : isMap(value) && !isOrdered(value)
+        ? value
+        : emptyMap().withMutations(function (map) {
+            var iter = KeyedCollection(value);
+            assertNotInfinite(iter.size);
+            iter.forEach(function (v, k) { return map.set(k, v); });
+          });
+  }
+
+  if ( KeyedCollection ) Map.__proto__ = KeyedCollection;
+  Map.prototype = Object.create( KeyedCollection && KeyedCollection.prototype );
+  Map.prototype.constructor = Map;
+
+  Map.prototype.toString = function toString () {
+    return this.__toString('Map {', '}');
+  };
+
+  // @pragma Access
+
+  Map.prototype.get = function get (k, notSetValue) {
+    return this._root
+      ? this._root.get(0, undefined, k, notSetValue)
+      : notSetValue;
+  };
+
+  // @pragma Modification
+
+  Map.prototype.set = function set (k, v) {
+    return updateMap(this, k, v);
+  };
+
+  Map.prototype.remove = function remove (k) {
+    return updateMap(this, k, NOT_SET);
+  };
+
+  Map.prototype.deleteAll = function deleteAll (keys) {
+    var collection = Collection(keys);
+
+    if (collection.size === 0) {
+      return this;
+    }
+
+    return this.withMutations(function (map) {
+      collection.forEach(function (key) { return map.remove(key); });
+    });
+  };
+
+  Map.prototype.clear = function clear () {
+    if (this.size === 0) {
+      return this;
+    }
+    if (this.__ownerID) {
+      this.size = 0;
+      this._root = null;
+      this.__hash = undefined;
+      this.__altered = true;
+      return this;
+    }
+    return emptyMap();
+  };
+
+  // @pragma Composition
+
+  Map.prototype.sort = function sort (comparator) {
+    // Late binding
+    return OrderedMap(sortFactory(this, comparator));
+  };
+
+  Map.prototype.sortBy = function sortBy (mapper, comparator) {
+    // Late binding
+    return OrderedMap(sortFactory(this, comparator, mapper));
+  };
+
+  Map.prototype.map = function map (mapper, context) {
+    var this$1$1 = this;
+
+    return this.withMutations(function (map) {
+      map.forEach(function (value, key) {
+        map.set(key, mapper.call(context, value, key, this$1$1));
+      });
+    });
+  };
+
+  // @pragma Mutability
+
+  Map.prototype.__iterator = function __iterator (type, reverse) {
+    return new MapIterator(this, type, reverse);
+  };
+
+  Map.prototype.__iterate = function __iterate (fn, reverse) {
+    var this$1$1 = this;
+
+    var iterations = 0;
+    // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+    this._root &&
+      this._root.iterate(function (entry) {
+        iterations++;
+        return fn(entry[1], entry[0], this$1$1);
+      }, reverse);
+    return iterations;
+  };
+
+  Map.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+    if (ownerID === this.__ownerID) {
+      return this;
+    }
+    if (!ownerID) {
+      if (this.size === 0) {
+        return emptyMap();
+      }
+      this.__ownerID = ownerID;
+      this.__altered = false;
+      return this;
+    }
+    return makeMap(this.size, this._root, ownerID, this.__hash);
+  };
+
+  return Map;
+}(KeyedCollection));
+
+Map.isMap = isMap;
+
+var MapPrototype = Map.prototype;
+MapPrototype[IS_MAP_SYMBOL] = true;
+MapPrototype[DELETE] = MapPrototype.remove;
+MapPrototype.removeAll = MapPrototype.deleteAll;
+MapPrototype.setIn = setIn;
+MapPrototype.removeIn = MapPrototype.deleteIn = deleteIn;
+MapPrototype.update = update;
+MapPrototype.updateIn = updateIn;
+MapPrototype.merge = MapPrototype.concat = merge$1;
+MapPrototype.mergeWith = mergeWith$1;
+MapPrototype.mergeDeep = mergeDeep;
+MapPrototype.mergeDeepWith = mergeDeepWith;
+MapPrototype.mergeIn = mergeIn;
+MapPrototype.mergeDeepIn = mergeDeepIn;
+MapPrototype.withMutations = withMutations;
+MapPrototype.wasAltered = wasAltered;
+MapPrototype.asImmutable = asImmutable;
+MapPrototype['@@transducer/init'] = MapPrototype.asMutable = asMutable;
+MapPrototype['@@transducer/step'] = function (result, arr) {
+  return result.set(arr[0], arr[1]);
+};
+MapPrototype['@@transducer/result'] = function (obj) {
+  return obj.asImmutable();
+};
+
+// #pragma Trie Nodes
+
+var ArrayMapNode = function ArrayMapNode(ownerID, entries) {
+  this.ownerID = ownerID;
+  this.entries = entries;
+};
+
+ArrayMapNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
+  var entries = this.entries;
+  for (var ii = 0, len = entries.length; ii < len; ii++) {
+    if (is(key, entries[ii][0])) {
+      return entries[ii][1];
+    }
+  }
+  return notSetValue;
+};
+
+ArrayMapNode.prototype.update = function update (ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
+  var removed = value === NOT_SET;
+
+  var entries = this.entries;
+  var idx = 0;
+  var len = entries.length;
+  for (; idx < len; idx++) {
+    if (is(key, entries[idx][0])) {
+      break;
+    }
+  }
+  var exists = idx < len;
+
+  if (exists ? entries[idx][1] === value : removed) {
+    return this;
+  }
+
+  SetRef(didAlter);
+  // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+  (removed || !exists) && SetRef(didChangeSize);
+
+  if (removed && entries.length === 1) {
+    return; // undefined
+  }
+
+  if (!exists && !removed && entries.length >= MAX_ARRAY_MAP_SIZE) {
+    return createNodes(ownerID, entries, key, value);
+  }
+
+  var isEditable = ownerID && ownerID === this.ownerID;
+  var newEntries = isEditable ? entries : arrCopy(entries);
+
+  if (exists) {
+    if (removed) {
+      // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+      idx === len - 1
+        ? newEntries.pop()
+        : (newEntries[idx] = newEntries.pop());
+    } else {
+      newEntries[idx] = [key, value];
+    }
+  } else {
+    newEntries.push([key, value]);
+  }
+
+  if (isEditable) {
+    this.entries = newEntries;
+    return this;
+  }
+
+  return new ArrayMapNode(ownerID, newEntries);
+};
+
+var BitmapIndexedNode = function BitmapIndexedNode(ownerID, bitmap, nodes) {
+  this.ownerID = ownerID;
+  this.bitmap = bitmap;
+  this.nodes = nodes;
+};
+
+BitmapIndexedNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
+  if (keyHash === undefined) {
+    keyHash = hash(key);
+  }
+  var bit = 1 << ((shift === 0 ? keyHash : keyHash >>> shift) & MASK);
+  var bitmap = this.bitmap;
+  return (bitmap & bit) === 0
+    ? notSetValue
+    : this.nodes[popCount(bitmap & (bit - 1))].get(
+        shift + SHIFT,
+        keyHash,
+        key,
+        notSetValue
+      );
+};
+
+BitmapIndexedNode.prototype.update = function update (ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
+  if (keyHash === undefined) {
+    keyHash = hash(key);
+  }
+  var keyHashFrag = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;
+  var bit = 1 << keyHashFrag;
+  var bitmap = this.bitmap;
+  var exists = (bitmap & bit) !== 0;
+
+  if (!exists && value === NOT_SET) {
+    return this;
+  }
+
+  var idx = popCount(bitmap & (bit - 1));
+  var nodes = this.nodes;
+  var node = exists ? nodes[idx] : undefined;
+  var newNode = updateNode(
+    node,
+    ownerID,
+    shift + SHIFT,
+    keyHash,
+    key,
+    value,
+    didChangeSize,
+    didAlter
+  );
+
+  if (newNode === node) {
+    return this;
+  }
+
+  if (!exists && newNode && nodes.length >= MAX_BITMAP_INDEXED_SIZE) {
+    return expandNodes(ownerID, nodes, bitmap, keyHashFrag, newNode);
+  }
+
+  if (
+    exists &&
+    !newNode &&
+    nodes.length === 2 &&
+    isLeafNode(nodes[idx ^ 1])
+  ) {
+    return nodes[idx ^ 1];
+  }
+
+  if (exists && newNode && nodes.length === 1 && isLeafNode(newNode)) {
+    return newNode;
+  }
+
+  var isEditable = ownerID && ownerID === this.ownerID;
+  var newBitmap = exists ? (newNode ? bitmap : bitmap ^ bit) : bitmap | bit;
+  var newNodes = exists
+    ? newNode
+      ? setAt(nodes, idx, newNode, isEditable)
+      : spliceOut(nodes, idx, isEditable)
+    : spliceIn(nodes, idx, newNode, isEditable);
+
+  if (isEditable) {
+    this.bitmap = newBitmap;
+    this.nodes = newNodes;
+    return this;
+  }
+
+  return new BitmapIndexedNode(ownerID, newBitmap, newNodes);
+};
+
+var HashArrayMapNode = function HashArrayMapNode(ownerID, count, nodes) {
+  this.ownerID = ownerID;
+  this.count = count;
+  this.nodes = nodes;
+};
+
+HashArrayMapNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
+  if (keyHash === undefined) {
+    keyHash = hash(key);
+  }
+  var idx = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;
+  var node = this.nodes[idx];
+  return node
+    ? node.get(shift + SHIFT, keyHash, key, notSetValue)
+    : notSetValue;
+};
+
+HashArrayMapNode.prototype.update = function update (ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
+  if (keyHash === undefined) {
+    keyHash = hash(key);
+  }
+  var idx = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;
+  var removed = value === NOT_SET;
+  var nodes = this.nodes;
+  var node = nodes[idx];
+
+  if (removed && !node) {
+    return this;
+  }
+
+  var newNode = updateNode(
+    node,
+    ownerID,
+    shift + SHIFT,
+    keyHash,
+    key,
+    value,
+    didChangeSize,
+    didAlter
+  );
+  if (newNode === node) {
+    return this;
+  }
+
+  var newCount = this.count;
+  if (!node) {
+    newCount++;
+  } else if (!newNode) {
+    newCount--;
+    if (newCount < MIN_HASH_ARRAY_MAP_SIZE) {
+      return packNodes(ownerID, nodes, newCount, idx);
+    }
+  }
+
+  var isEditable = ownerID && ownerID === this.ownerID;
+  var newNodes = setAt(nodes, idx, newNode, isEditable);
+
+  if (isEditable) {
+    this.count = newCount;
+    this.nodes = newNodes;
+    return this;
+  }
+
+  return new HashArrayMapNode(ownerID, newCount, newNodes);
+};
+
+var HashCollisionNode = function HashCollisionNode(ownerID, keyHash, entries) {
+  this.ownerID = ownerID;
+  this.keyHash = keyHash;
+  this.entries = entries;
+};
+
+HashCollisionNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
+  var entries = this.entries;
+  for (var ii = 0, len = entries.length; ii < len; ii++) {
+    if (is(key, entries[ii][0])) {
+      return entries[ii][1];
+    }
+  }
+  return notSetValue;
+};
+
+HashCollisionNode.prototype.update = function update (ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
+  if (keyHash === undefined) {
+    keyHash = hash(key);
+  }
+
+  var removed = value === NOT_SET;
+
+  if (keyHash !== this.keyHash) {
+    if (removed) {
+      return this;
+    }
+    SetRef(didAlter);
+    SetRef(didChangeSize);
+    return mergeIntoNode(this, ownerID, shift, keyHash, [key, value]);
+  }
+
+  var entries = this.entries;
+  var idx = 0;
+  var len = entries.length;
+  for (; idx < len; idx++) {
+    if (is(key, entries[idx][0])) {
+      break;
+    }
+  }
+  var exists = idx < len;
+
+  if (exists ? entries[idx][1] === value : removed) {
+    return this;
+  }
+
+  SetRef(didAlter);
+  // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+  (removed || !exists) && SetRef(didChangeSize);
+
+  if (removed && len === 2) {
+    return new ValueNode(ownerID, this.keyHash, entries[idx ^ 1]);
+  }
+
+  var isEditable = ownerID && ownerID === this.ownerID;
+  var newEntries = isEditable ? entries : arrCopy(entries);
+
+  if (exists) {
+    if (removed) {
+      // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+      idx === len - 1
+        ? newEntries.pop()
+        : (newEntries[idx] = newEntries.pop());
+    } else {
+      newEntries[idx] = [key, value];
+    }
+  } else {
+    newEntries.push([key, value]);
+  }
+
+  if (isEditable) {
+    this.entries = newEntries;
+    return this;
+  }
+
+  return new HashCollisionNode(ownerID, this.keyHash, newEntries);
+};
+
+var ValueNode = function ValueNode(ownerID, keyHash, entry) {
+  this.ownerID = ownerID;
+  this.keyHash = keyHash;
+  this.entry = entry;
+};
+
+ValueNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
+  return is(key, this.entry[0]) ? this.entry[1] : notSetValue;
+};
+
+ValueNode.prototype.update = function update (ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
+  var removed = value === NOT_SET;
+  var keyMatch = is(key, this.entry[0]);
+  if (keyMatch ? value === this.entry[1] : removed) {
+    return this;
+  }
+
+  SetRef(didAlter);
+
+  if (removed) {
+    SetRef(didChangeSize);
+    return; // undefined
+  }
+
+  if (keyMatch) {
+    if (ownerID && ownerID === this.ownerID) {
+      this.entry[1] = value;
+      return this;
+    }
+    return new ValueNode(ownerID, this.keyHash, [key, value]);
+  }
+
+  SetRef(didChangeSize);
+  return mergeIntoNode(this, ownerID, shift, hash(key), [key, value]);
+};
+
+// #pragma Iterators
+
+ArrayMapNode.prototype.iterate = HashCollisionNode.prototype.iterate =
+  function (fn, reverse) {
+    var entries = this.entries;
+    for (var ii = 0, maxIndex = entries.length - 1; ii <= maxIndex; ii++) {
+      if (fn(entries[reverse ? maxIndex - ii : ii]) === false) {
+        return false;
+      }
+    }
+  };
+
+BitmapIndexedNode.prototype.iterate = HashArrayMapNode.prototype.iterate =
+  function (fn, reverse) {
+    var nodes = this.nodes;
+    for (var ii = 0, maxIndex = nodes.length - 1; ii <= maxIndex; ii++) {
+      var node = nodes[reverse ? maxIndex - ii : ii];
+      if (node && node.iterate(fn, reverse) === false) {
+        return false;
+      }
+    }
+  };
+
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+ValueNode.prototype.iterate = function (fn, reverse) {
+  return fn(this.entry);
+};
+
+var MapIterator = /*@__PURE__*/(function (Iterator) {
+  function MapIterator(map, type, reverse) {
+    this._type = type;
+    this._reverse = reverse;
+    this._stack = map._root && mapIteratorFrame(map._root);
+  }
+
+  if ( Iterator ) MapIterator.__proto__ = Iterator;
+  MapIterator.prototype = Object.create( Iterator && Iterator.prototype );
+  MapIterator.prototype.constructor = MapIterator;
+
+  MapIterator.prototype.next = function next () {
+    var type = this._type;
+    var stack = this._stack;
+    while (stack) {
+      var node = stack.node;
+      var index = stack.index++;
+      var maxIndex = (void 0);
+      if (node.entry) {
+        if (index === 0) {
+          return mapIteratorValue(type, node.entry);
+        }
+      } else if (node.entries) {
+        maxIndex = node.entries.length - 1;
+        if (index <= maxIndex) {
+          return mapIteratorValue(
+            type,
+            node.entries[this._reverse ? maxIndex - index : index]
+          );
+        }
+      } else {
+        maxIndex = node.nodes.length - 1;
+        if (index <= maxIndex) {
+          var subNode = node.nodes[this._reverse ? maxIndex - index : index];
+          if (subNode) {
+            if (subNode.entry) {
+              return mapIteratorValue(type, subNode.entry);
+            }
+            stack = this._stack = mapIteratorFrame(subNode, stack);
+          }
+          continue;
+        }
+      }
+      stack = this._stack = this._stack.__prev;
+    }
+    return iteratorDone();
+  };
+
+  return MapIterator;
+}(Iterator));
+
+function mapIteratorValue(type, entry) {
+  return iteratorValue(type, entry[0], entry[1]);
+}
+
+function mapIteratorFrame(node, prev) {
+  return {
+    node: node,
+    index: 0,
+    __prev: prev,
+  };
+}
+
+function makeMap(size, root, ownerID, hash) {
+  var map = Object.create(MapPrototype);
+  map.size = size;
+  map._root = root;
+  map.__ownerID = ownerID;
+  map.__hash = hash;
+  map.__altered = false;
+  return map;
+}
+
+var EMPTY_MAP;
+function emptyMap() {
+  return EMPTY_MAP || (EMPTY_MAP = makeMap(0));
+}
+
+function updateMap(map, k, v) {
+  var newRoot;
+  var newSize;
+  if (!map._root) {
+    if (v === NOT_SET) {
+      return map;
+    }
+    newSize = 1;
+    newRoot = new ArrayMapNode(map.__ownerID, [[k, v]]);
+  } else {
+    var didChangeSize = MakeRef();
+    var didAlter = MakeRef();
+    newRoot = updateNode(
+      map._root,
+      map.__ownerID,
+      0,
+      undefined,
+      k,
+      v,
+      didChangeSize,
+      didAlter
+    );
+    if (!didAlter.value) {
+      return map;
+    }
+    newSize = map.size + (didChangeSize.value ? (v === NOT_SET ? -1 : 1) : 0);
+  }
+  if (map.__ownerID) {
+    map.size = newSize;
+    map._root = newRoot;
+    map.__hash = undefined;
+    map.__altered = true;
+    return map;
+  }
+  return newRoot ? makeMap(newSize, newRoot) : emptyMap();
+}
+
+function updateNode(
+  node,
+  ownerID,
+  shift,
+  keyHash,
+  key,
+  value,
+  didChangeSize,
+  didAlter
+) {
+  if (!node) {
+    if (value === NOT_SET) {
+      return node;
+    }
+    SetRef(didAlter);
+    SetRef(didChangeSize);
+    return new ValueNode(ownerID, keyHash, [key, value]);
+  }
+  return node.update(
+    ownerID,
+    shift,
+    keyHash,
+    key,
+    value,
+    didChangeSize,
+    didAlter
+  );
+}
+
+function isLeafNode(node) {
+  return (
+    node.constructor === ValueNode || node.constructor === HashCollisionNode
+  );
+}
+
+function mergeIntoNode(node, ownerID, shift, keyHash, entry) {
+  if (node.keyHash === keyHash) {
+    return new HashCollisionNode(ownerID, keyHash, [node.entry, entry]);
+  }
+
+  var idx1 = (shift === 0 ? node.keyHash : node.keyHash >>> shift) & MASK;
+  var idx2 = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;
+
+  var newNode;
+  var nodes =
+    idx1 === idx2
+      ? [mergeIntoNode(node, ownerID, shift + SHIFT, keyHash, entry)]
+      : ((newNode = new ValueNode(ownerID, keyHash, entry)),
+        idx1 < idx2 ? [node, newNode] : [newNode, node]);
+
+  return new BitmapIndexedNode(ownerID, (1 << idx1) | (1 << idx2), nodes);
+}
+
+function createNodes(ownerID, entries, key, value) {
+  if (!ownerID) {
+    ownerID = new OwnerID();
+  }
+  var node = new ValueNode(ownerID, hash(key), [key, value]);
+  for (var ii = 0; ii < entries.length; ii++) {
+    var entry = entries[ii];
+    node = node.update(ownerID, 0, undefined, entry[0], entry[1]);
+  }
+  return node;
+}
+
+function packNodes(ownerID, nodes, count, excluding) {
+  var bitmap = 0;
+  var packedII = 0;
+  var packedNodes = new Array(count);
+  for (var ii = 0, bit = 1, len = nodes.length; ii < len; ii++, bit <<= 1) {
+    var node = nodes[ii];
+    if (node !== undefined && ii !== excluding) {
+      bitmap |= bit;
+      packedNodes[packedII++] = node;
+    }
+  }
+  return new BitmapIndexedNode(ownerID, bitmap, packedNodes);
+}
+
+function expandNodes(ownerID, nodes, bitmap, including, node) {
+  var count = 0;
+  var expandedNodes = new Array(SIZE);
+  for (var ii = 0; bitmap !== 0; ii++, bitmap >>>= 1) {
+    expandedNodes[ii] = bitmap & 1 ? nodes[count++] : undefined;
+  }
+  expandedNodes[including] = node;
+  return new HashArrayMapNode(ownerID, count + 1, expandedNodes);
+}
+
+function popCount(x) {
+  x -= (x >> 1) & 0x55555555;
+  x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
+  x = (x + (x >> 4)) & 0x0f0f0f0f;
+  x += x >> 8;
+  x += x >> 16;
+  return x & 0x7f;
+}
+
+function setAt(array, idx, val, canEdit) {
+  var newArray = canEdit ? array : arrCopy(array);
+  newArray[idx] = val;
+  return newArray;
+}
+
+function spliceIn(array, idx, val, canEdit) {
+  var newLen = array.length + 1;
+  if (canEdit && idx + 1 === newLen) {
+    array[idx] = val;
+    return array;
+  }
+  var newArray = new Array(newLen);
+  var after = 0;
+  for (var ii = 0; ii < newLen; ii++) {
+    if (ii === idx) {
+      newArray[ii] = val;
+      after = -1;
+    } else {
+      newArray[ii] = array[ii + after];
+    }
+  }
+  return newArray;
+}
+
+function spliceOut(array, idx, canEdit) {
+  var newLen = array.length - 1;
+  if (canEdit && idx === newLen) {
+    array.pop();
+    return array;
+  }
+  var newArray = new Array(newLen);
+  var after = 0;
+  for (var ii = 0; ii < newLen; ii++) {
+    if (ii === idx) {
+      after = 1;
+    }
+    newArray[ii] = array[ii + after];
+  }
+  return newArray;
+}
+
+var MAX_ARRAY_MAP_SIZE = SIZE / 4;
+var MAX_BITMAP_INDEXED_SIZE = SIZE / 2;
+var MIN_HASH_ARRAY_MAP_SIZE = SIZE / 4;
+
+var IS_LIST_SYMBOL = '@@__IMMUTABLE_LIST__@@';
+/**
+ * True if `maybeList` is a List.
+ */
+function isList(maybeList) {
+    return Boolean(maybeList &&
+        // @ts-expect-error: maybeList is typed as `{}`, need to change in 6.0 to `maybeList && typeof maybeList === 'object' && IS_LIST_SYMBOL in maybeList`
+        maybeList[IS_LIST_SYMBOL]);
+}
+
+var List = /*@__PURE__*/(function (IndexedCollection) {
+  function List(value) {
+    var empty = emptyList();
+    if (value === undefined || value === null) {
+      // eslint-disable-next-line no-constructor-return
+      return empty;
+    }
+    if (isList(value)) {
+      // eslint-disable-next-line no-constructor-return
+      return value;
+    }
+    var iter = IndexedCollection(value);
+    var size = iter.size;
+    if (size === 0) {
+      // eslint-disable-next-line no-constructor-return
+      return empty;
+    }
+    assertNotInfinite(size);
+    if (size > 0 && size < SIZE) {
+      // eslint-disable-next-line no-constructor-return
+      return makeList(0, size, SHIFT, null, new VNode(iter.toArray()));
+    }
+    // eslint-disable-next-line no-constructor-return
+    return empty.withMutations(function (list) {
+      list.setSize(size);
+      iter.forEach(function (v, i) { return list.set(i, v); });
+    });
+  }
+
+  if ( IndexedCollection ) List.__proto__ = IndexedCollection;
+  List.prototype = Object.create( IndexedCollection && IndexedCollection.prototype );
+  List.prototype.constructor = List;
+
+  List.of = function of (/*...values*/) {
+    return this(arguments);
+  };
+
+  List.prototype.toString = function toString () {
+    return this.__toString('List [', ']');
+  };
+
+  // @pragma Access
+
+  List.prototype.get = function get (index, notSetValue) {
+    index = wrapIndex(this, index);
+    if (index >= 0 && index < this.size) {
+      index += this._origin;
+      var node = listNodeFor(this, index);
+      return node && node.array[index & MASK];
+    }
+    return notSetValue;
+  };
+
+  // @pragma Modification
+
+  List.prototype.set = function set (index, value) {
+    return updateList(this, index, value);
+  };
+
+  List.prototype.remove = function remove (index) {
+    return !this.has(index)
+      ? this
+      : index === 0
+        ? this.shift()
+        : index === this.size - 1
+          ? this.pop()
+          : this.splice(index, 1);
+  };
+
+  List.prototype.insert = function insert (index, value) {
+    return this.splice(index, 0, value);
+  };
+
+  List.prototype.clear = function clear () {
+    if (this.size === 0) {
+      return this;
+    }
+    if (this.__ownerID) {
+      this.size = this._origin = this._capacity = 0;
+      this._level = SHIFT;
+      this._root = this._tail = this.__hash = undefined;
+      this.__altered = true;
+      return this;
+    }
+    return emptyList();
+  };
+
+  List.prototype.push = function push (/*...values*/) {
+    var values = arguments;
+    var oldSize = this.size;
+    return this.withMutations(function (list) {
+      setListBounds(list, 0, oldSize + values.length);
+      for (var ii = 0; ii < values.length; ii++) {
+        list.set(oldSize + ii, values[ii]);
+      }
+    });
+  };
+
+  List.prototype.pop = function pop () {
+    return setListBounds(this, 0, -1);
+  };
+
+  List.prototype.unshift = function unshift (/*...values*/) {
+    var values = arguments;
+    return this.withMutations(function (list) {
+      setListBounds(list, -values.length);
+      for (var ii = 0; ii < values.length; ii++) {
+        list.set(ii, values[ii]);
+      }
+    });
+  };
+
+  List.prototype.shift = function shift () {
+    return setListBounds(this, 1);
+  };
+
+  List.prototype.shuffle = function shuffle (random) {
+    if ( random === void 0 ) random = Math.random;
+
+    return this.withMutations(function (mutable) {
+      // implementation of the Fisher-Yates shuffle: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
+      var current = mutable.size;
+      var destination;
+      var tmp;
+
+      while (current) {
+        destination = Math.floor(random() * current--);
+
+        tmp = mutable.get(destination);
+        mutable.set(destination, mutable.get(current));
+        mutable.set(current, tmp);
+      }
+    });
+  };
+
+  // @pragma Composition
+
+  List.prototype.concat = function concat (/*...collections*/) {
+    var arguments$1 = arguments;
+
+    var seqs = [];
+    for (var i = 0; i < arguments.length; i++) {
+      var argument = arguments$1[i];
+      var seq = IndexedCollection(
+        typeof argument !== 'string' && hasIterator(argument)
+          ? argument
+          : [argument]
+      );
+      if (seq.size !== 0) {
+        seqs.push(seq);
+      }
+    }
+    if (seqs.length === 0) {
+      return this;
+    }
+    if (this.size === 0 && !this.__ownerID && seqs.length === 1) {
+      return this.constructor(seqs[0]);
+    }
+    return this.withMutations(function (list) {
+      seqs.forEach(function (seq) { return seq.forEach(function (value) { return list.push(value); }); });
+    });
+  };
+
+  List.prototype.setSize = function setSize (size) {
+    return setListBounds(this, 0, size);
+  };
+
+  List.prototype.map = function map (mapper, context) {
+    var this$1$1 = this;
+
+    return this.withMutations(function (list) {
+      for (var i = 0; i < this$1$1.size; i++) {
+        list.set(i, mapper.call(context, list.get(i), i, this$1$1));
+      }
+    });
+  };
+
+  // @pragma Iteration
+
+  List.prototype.slice = function slice (begin, end) {
+    var size = this.size;
+    if (wholeSlice(begin, end, size)) {
+      return this;
+    }
+    return setListBounds(
+      this,
+      resolveBegin(begin, size),
+      resolveEnd(end, size)
+    );
+  };
+
+  List.prototype.__iterator = function __iterator (type, reverse) {
+    var index = reverse ? this.size : 0;
+    var values = iterateList(this, reverse);
+    return new Iterator(function () {
+      var value = values();
+      return value === DONE
+        ? iteratorDone()
+        : iteratorValue(type, reverse ? --index : index++, value);
+    });
+  };
+
+  List.prototype.__iterate = function __iterate (fn, reverse) {
+    var index = reverse ? this.size : 0;
+    var values = iterateList(this, reverse);
+    var value;
+    while ((value = values()) !== DONE) {
+      if (fn(value, reverse ? --index : index++, this) === false) {
+        break;
+      }
+    }
+    return index;
+  };
+
+  List.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+    if (ownerID === this.__ownerID) {
+      return this;
+    }
+    if (!ownerID) {
+      if (this.size === 0) {
+        return emptyList();
+      }
+      this.__ownerID = ownerID;
+      this.__altered = false;
+      return this;
+    }
+    return makeList(
+      this._origin,
+      this._capacity,
+      this._level,
+      this._root,
+      this._tail,
+      ownerID,
+      this.__hash
+    );
+  };
+
+  return List;
+}(IndexedCollection));
+
+List.isList = isList;
+
+var ListPrototype = List.prototype;
+ListPrototype[IS_LIST_SYMBOL] = true;
+ListPrototype[DELETE] = ListPrototype.remove;
+ListPrototype.merge = ListPrototype.concat;
+ListPrototype.setIn = setIn;
+ListPrototype.deleteIn = ListPrototype.removeIn = deleteIn;
+ListPrototype.update = update;
+ListPrototype.updateIn = updateIn;
+ListPrototype.mergeIn = mergeIn;
+ListPrototype.mergeDeepIn = mergeDeepIn;
+ListPrototype.withMutations = withMutations;
+ListPrototype.wasAltered = wasAltered;
+ListPrototype.asImmutable = asImmutable;
+ListPrototype['@@transducer/init'] = ListPrototype.asMutable = asMutable;
+ListPrototype['@@transducer/step'] = function (result, arr) {
+  return result.push(arr);
+};
+ListPrototype['@@transducer/result'] = function (obj) {
+  return obj.asImmutable();
+};
+
+var VNode = function VNode(array, ownerID) {
+  this.array = array;
+  this.ownerID = ownerID;
+};
+
+// TODO: seems like these methods are very similar
+
+VNode.prototype.removeBefore = function removeBefore (ownerID, level, index) {
+  if (
+    (index & ((1 << (level + SHIFT)) - 1)) === 0 ||
+    this.array.length === 0
+  ) {
+    return this;
+  }
+  var originIndex = (index >>> level) & MASK;
+  if (originIndex >= this.array.length) {
+    return new VNode([], ownerID);
+  }
+  var removingFirst = originIndex === 0;
+  var newChild;
+  if (level > 0) {
+    var oldChild = this.array[originIndex];
+    newChild =
+      oldChild && oldChild.removeBefore(ownerID, level - SHIFT, index);
+    if (newChild === oldChild && removingFirst) {
+      return this;
+    }
+  }
+  if (removingFirst && !newChild) {
+    return this;
+  }
+  var editable = editableVNode(this, ownerID);
+  if (!removingFirst) {
+    for (var ii = 0; ii < originIndex; ii++) {
+      editable.array[ii] = undefined;
+    }
+  }
+  if (newChild) {
+    editable.array[originIndex] = newChild;
+  }
+  return editable;
+};
+
+VNode.prototype.removeAfter = function removeAfter (ownerID, level, index) {
+  if (
+    index === (level ? 1 << (level + SHIFT) : SIZE) ||
+    this.array.length === 0
+  ) {
+    return this;
+  }
+  var sizeIndex = ((index - 1) >>> level) & MASK;
+  if (sizeIndex >= this.array.length) {
+    return this;
+  }
+
+  var newChild;
+  if (level > 0) {
+    var oldChild = this.array[sizeIndex];
+    newChild =
+      oldChild && oldChild.removeAfter(ownerID, level - SHIFT, index);
+    if (newChild === oldChild && sizeIndex === this.array.length - 1) {
+      return this;
+    }
+  }
+
+  var editable = editableVNode(this, ownerID);
+  editable.array.splice(sizeIndex + 1);
+  if (newChild) {
+    editable.array[sizeIndex] = newChild;
+  }
+  return editable;
+};
+
+var DONE = {};
+
+function iterateList(list, reverse) {
+  var left = list._origin;
+  var right = list._capacity;
+  var tailPos = getTailOffset(right);
+  var tail = list._tail;
+
+  return iterateNodeOrLeaf(list._root, list._level, 0);
+
+  function iterateNodeOrLeaf(node, level, offset) {
+    return level === 0
+      ? iterateLeaf(node, offset)
+      : iterateNode(node, level, offset);
+  }
+
+  function iterateLeaf(node, offset) {
+    var array = offset === tailPos ? tail && tail.array : node && node.array;
+    var from = offset > left ? 0 : left - offset;
+    var to = right - offset;
+    if (to > SIZE) {
+      to = SIZE;
+    }
+    return function () {
+      if (from === to) {
+        return DONE;
+      }
+      var idx = reverse ? --to : from++;
+      return array && array[idx];
+    };
+  }
+
+  function iterateNode(node, level, offset) {
+    var values;
+    var array = node && node.array;
+    var from = offset > left ? 0 : (left - offset) >> level;
+    var to = ((right - offset) >> level) + 1;
+    if (to > SIZE) {
+      to = SIZE;
+    }
+    return function () {
+      while (true) {
+        if (values) {
+          var value = values();
+          if (value !== DONE) {
+            return value;
+          }
+          values = null;
+        }
+        if (from === to) {
+          return DONE;
+        }
+        var idx = reverse ? --to : from++;
+        values = iterateNodeOrLeaf(
+          array && array[idx],
+          level - SHIFT,
+          offset + (idx << level)
+        );
+      }
+    };
+  }
+}
+
+function makeList(origin, capacity, level, root, tail, ownerID, hash) {
+  var list = Object.create(ListPrototype);
+  list.size = capacity - origin;
+  list._origin = origin;
+  list._capacity = capacity;
+  list._level = level;
+  list._root = root;
+  list._tail = tail;
+  list.__ownerID = ownerID;
+  list.__hash = hash;
+  list.__altered = false;
+  return list;
+}
+
+function emptyList() {
+  return makeList(0, 0, SHIFT);
+}
+
+function updateList(list, index, value) {
+  index = wrapIndex(list, index);
+
+  if (index !== index) {
+    return list;
+  }
+
+  if (index >= list.size || index < 0) {
+    return list.withMutations(function (list) {
+      // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+      index < 0
+        ? setListBounds(list, index).set(0, value)
+        : setListBounds(list, 0, index + 1).set(index, value);
+    });
+  }
+
+  index += list._origin;
+
+  var newTail = list._tail;
+  var newRoot = list._root;
+  var didAlter = MakeRef();
+  if (index >= getTailOffset(list._capacity)) {
+    newTail = updateVNode(newTail, list.__ownerID, 0, index, value, didAlter);
+  } else {
+    newRoot = updateVNode(
+      newRoot,
+      list.__ownerID,
+      list._level,
+      index,
+      value,
+      didAlter
+    );
+  }
+
+  if (!didAlter.value) {
+    return list;
+  }
+
+  if (list.__ownerID) {
+    list._root = newRoot;
+    list._tail = newTail;
+    list.__hash = undefined;
+    list.__altered = true;
+    return list;
+  }
+  return makeList(list._origin, list._capacity, list._level, newRoot, newTail);
+}
+
+function updateVNode(node, ownerID, level, index, value, didAlter) {
+  var idx = (index >>> level) & MASK;
+  var nodeHas = node && idx < node.array.length;
+  if (!nodeHas && value === undefined) {
+    return node;
+  }
+
+  var newNode;
+
+  if (level > 0) {
+    var lowerNode = node && node.array[idx];
+    var newLowerNode = updateVNode(
+      lowerNode,
+      ownerID,
+      level - SHIFT,
+      index,
+      value,
+      didAlter
+    );
+    if (newLowerNode === lowerNode) {
+      return node;
+    }
+    newNode = editableVNode(node, ownerID);
+    newNode.array[idx] = newLowerNode;
+    return newNode;
+  }
+
+  if (nodeHas && node.array[idx] === value) {
+    return node;
+  }
+
+  if (didAlter) {
+    SetRef(didAlter);
+  }
+
+  newNode = editableVNode(node, ownerID);
+  if (value === undefined && idx === newNode.array.length - 1) {
+    newNode.array.pop();
+  } else {
+    newNode.array[idx] = value;
+  }
+  return newNode;
+}
+
+function editableVNode(node, ownerID) {
+  if (ownerID && node && ownerID === node.ownerID) {
+    return node;
+  }
+  return new VNode(node ? node.array.slice() : [], ownerID);
+}
+
+function listNodeFor(list, rawIndex) {
+  if (rawIndex >= getTailOffset(list._capacity)) {
+    return list._tail;
+  }
+  if (rawIndex < 1 << (list._level + SHIFT)) {
+    var node = list._root;
+    var level = list._level;
+    while (node && level > 0) {
+      node = node.array[(rawIndex >>> level) & MASK];
+      level -= SHIFT;
+    }
+    return node;
+  }
+}
+
+function setListBounds(list, begin, end) {
+  // Sanitize begin & end using this shorthand for ToInt32(argument)
+  // http://www.ecma-international.org/ecma-262/6.0/#sec-toint32
+  if (begin !== undefined) {
+    begin |= 0;
+  }
+  if (end !== undefined) {
+    end |= 0;
+  }
+  var owner = list.__ownerID || new OwnerID();
+  var oldOrigin = list._origin;
+  var oldCapacity = list._capacity;
+  var newOrigin = oldOrigin + begin;
+  var newCapacity =
+    end === undefined
+      ? oldCapacity
+      : end < 0
+        ? oldCapacity + end
+        : oldOrigin + end;
+  if (newOrigin === oldOrigin && newCapacity === oldCapacity) {
+    return list;
+  }
+
+  // If it's going to end after it starts, it's empty.
+  if (newOrigin >= newCapacity) {
+    return list.clear();
+  }
+
+  var newLevel = list._level;
+  var newRoot = list._root;
+
+  // New origin might need creating a higher root.
+  var offsetShift = 0;
+  while (newOrigin + offsetShift < 0) {
+    newRoot = new VNode(
+      newRoot && newRoot.array.length ? [undefined, newRoot] : [],
+      owner
+    );
+    newLevel += SHIFT;
+    offsetShift += 1 << newLevel;
+  }
+  if (offsetShift) {
+    newOrigin += offsetShift;
+    oldOrigin += offsetShift;
+    newCapacity += offsetShift;
+    oldCapacity += offsetShift;
+  }
+
+  var oldTailOffset = getTailOffset(oldCapacity);
+  var newTailOffset = getTailOffset(newCapacity);
+
+  // New size might need creating a higher root.
+  while (newTailOffset >= 1 << (newLevel + SHIFT)) {
+    newRoot = new VNode(
+      newRoot && newRoot.array.length ? [newRoot] : [],
+      owner
+    );
+    newLevel += SHIFT;
+  }
+
+  // Locate or create the new tail.
+  var oldTail = list._tail;
+  var newTail =
+    newTailOffset < oldTailOffset
+      ? listNodeFor(list, newCapacity - 1)
+      : newTailOffset > oldTailOffset
+        ? new VNode([], owner)
+        : oldTail;
+
+  // Merge Tail into tree.
+  if (
+    oldTail &&
+    newTailOffset > oldTailOffset &&
+    newOrigin < oldCapacity &&
+    oldTail.array.length
+  ) {
+    newRoot = editableVNode(newRoot, owner);
+    var node = newRoot;
+    for (var level = newLevel; level > SHIFT; level -= SHIFT) {
+      var idx = (oldTailOffset >>> level) & MASK;
+      node = node.array[idx] = editableVNode(node.array[idx], owner);
+    }
+    node.array[(oldTailOffset >>> SHIFT) & MASK] = oldTail;
+  }
+
+  // If the size has been reduced, there's a chance the tail needs to be trimmed.
+  if (newCapacity < oldCapacity) {
+    newTail = newTail && newTail.removeAfter(owner, 0, newCapacity);
+  }
+
+  // If the new origin is within the tail, then we do not need a root.
+  if (newOrigin >= newTailOffset) {
+    newOrigin -= newTailOffset;
+    newCapacity -= newTailOffset;
+    newLevel = SHIFT;
+    newRoot = null;
+    newTail = newTail && newTail.removeBefore(owner, 0, newOrigin);
+
+    // Otherwise, if the root has been trimmed, garbage collect.
+  } else if (newOrigin > oldOrigin || newTailOffset < oldTailOffset) {
+    offsetShift = 0;
+
+    // Identify the new top root node of the subtree of the old root.
+    while (newRoot) {
+      var beginIndex = (newOrigin >>> newLevel) & MASK;
+      if ((beginIndex !== newTailOffset >>> newLevel) & MASK) {
+        break;
+      }
+      if (beginIndex) {
+        offsetShift += (1 << newLevel) * beginIndex;
+      }
+      newLevel -= SHIFT;
+      newRoot = newRoot.array[beginIndex];
+    }
+
+    // Trim the new sides of the new root.
+    if (newRoot && newOrigin > oldOrigin) {
+      newRoot = newRoot.removeBefore(owner, newLevel, newOrigin - offsetShift);
+    }
+    if (newRoot && newTailOffset < oldTailOffset) {
+      newRoot = newRoot.removeAfter(
+        owner,
+        newLevel,
+        newTailOffset - offsetShift
+      );
+    }
+    if (offsetShift) {
+      newOrigin -= offsetShift;
+      newCapacity -= offsetShift;
+    }
+  }
+
+  if (list.__ownerID) {
+    list.size = newCapacity - newOrigin;
+    list._origin = newOrigin;
+    list._capacity = newCapacity;
+    list._level = newLevel;
+    list._root = newRoot;
+    list._tail = newTail;
+    list.__hash = undefined;
+    list.__altered = true;
+    return list;
+  }
+  return makeList(newOrigin, newCapacity, newLevel, newRoot, newTail);
+}
+
+function getTailOffset(size) {
+  return size < SIZE ? 0 : ((size - 1) >>> SHIFT) << SHIFT;
+}
+
+var OrderedMap = /*@__PURE__*/(function (Map) {
+  function OrderedMap(value) {
+    // eslint-disable-next-line no-constructor-return
+    return value === undefined || value === null
+      ? emptyOrderedMap()
+      : isOrderedMap(value)
+        ? value
+        : emptyOrderedMap().withMutations(function (map) {
+            var iter = KeyedCollection(value);
+            assertNotInfinite(iter.size);
+            iter.forEach(function (v, k) { return map.set(k, v); });
+          });
+  }
+
+  if ( Map ) OrderedMap.__proto__ = Map;
+  OrderedMap.prototype = Object.create( Map && Map.prototype );
+  OrderedMap.prototype.constructor = OrderedMap;
+
+  OrderedMap.of = function of (/*...values*/) {
+    return this(arguments);
+  };
+
+  OrderedMap.prototype.toString = function toString () {
+    return this.__toString('OrderedMap {', '}');
+  };
+
+  // @pragma Access
+
+  OrderedMap.prototype.get = function get (k, notSetValue) {
+    var index = this._map.get(k);
+    return index !== undefined ? this._list.get(index)[1] : notSetValue;
+  };
+
+  // @pragma Modification
+
+  OrderedMap.prototype.clear = function clear () {
+    if (this.size === 0) {
+      return this;
+    }
+    if (this.__ownerID) {
+      this.size = 0;
+      this._map.clear();
+      this._list.clear();
+      this.__altered = true;
+      return this;
+    }
+    return emptyOrderedMap();
+  };
+
+  OrderedMap.prototype.set = function set (k, v) {
+    return updateOrderedMap(this, k, v);
+  };
+
+  OrderedMap.prototype.remove = function remove (k) {
+    return updateOrderedMap(this, k, NOT_SET);
+  };
+
+  OrderedMap.prototype.__iterate = function __iterate (fn, reverse) {
+    var this$1$1 = this;
+
+    return this._list.__iterate(
+      function (entry) { return entry && fn(entry[1], entry[0], this$1$1); },
+      reverse
+    );
+  };
+
+  OrderedMap.prototype.__iterator = function __iterator (type, reverse) {
+    return this._list.fromEntrySeq().__iterator(type, reverse);
+  };
+
+  OrderedMap.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+    if (ownerID === this.__ownerID) {
+      return this;
+    }
+    var newMap = this._map.__ensureOwner(ownerID);
+    var newList = this._list.__ensureOwner(ownerID);
+    if (!ownerID) {
+      if (this.size === 0) {
+        return emptyOrderedMap();
+      }
+      this.__ownerID = ownerID;
+      this.__altered = false;
+      this._map = newMap;
+      this._list = newList;
+      return this;
+    }
+    return makeOrderedMap(newMap, newList, ownerID, this.__hash);
+  };
+
+  return OrderedMap;
+}(Map));
+
+OrderedMap.isOrderedMap = isOrderedMap;
+
+OrderedMap.prototype[IS_ORDERED_SYMBOL] = true;
+OrderedMap.prototype[DELETE] = OrderedMap.prototype.remove;
+
+function makeOrderedMap(map, list, ownerID, hash) {
+  var omap = Object.create(OrderedMap.prototype);
+  omap.size = map ? map.size : 0;
+  omap._map = map;
+  omap._list = list;
+  omap.__ownerID = ownerID;
+  omap.__hash = hash;
+  omap.__altered = false;
+  return omap;
+}
+
+var EMPTY_ORDERED_MAP;
+function emptyOrderedMap() {
+  return (
+    EMPTY_ORDERED_MAP ||
+    (EMPTY_ORDERED_MAP = makeOrderedMap(emptyMap(), emptyList()))
+  );
+}
+
+function updateOrderedMap(omap, k, v) {
+  var map = omap._map;
+  var list = omap._list;
+  var i = map.get(k);
+  var has = i !== undefined;
+  var newMap;
+  var newList;
+  if (v === NOT_SET) {
+    // removed
+    if (!has) {
+      return omap;
+    }
+    if (list.size >= SIZE && list.size >= map.size * 2) {
+      newList = list.filter(function (entry, idx) { return entry !== undefined && i !== idx; });
+      newMap = newList
+        .toKeyedSeq()
+        .map(function (entry) { return entry[0]; })
+        .flip()
+        .toMap();
+      if (omap.__ownerID) {
+        newMap.__ownerID = newList.__ownerID = omap.__ownerID;
+      }
+    } else {
+      newMap = map.remove(k);
+      newList = i === list.size - 1 ? list.pop() : list.set(i, undefined);
+    }
+  } else if (has) {
+    if (v === list.get(i)[1]) {
+      return omap;
+    }
+    newMap = map;
+    newList = list.set(i, [k, v]);
+  } else {
+    newMap = map.set(k, list.size);
+    newList = list.set(list.size, [k, v]);
+  }
+  if (omap.__ownerID) {
+    omap.size = newMap.size;
+    omap._map = newMap;
+    omap._list = newList;
+    omap.__hash = undefined;
+    omap.__altered = true;
+    return omap;
+  }
+  return makeOrderedMap(newMap, newList);
+}
+
+var IS_STACK_SYMBOL = '@@__IMMUTABLE_STACK__@@';
+/**
+ * True if `maybeStack` is a Stack.
+ */
+function isStack(maybeStack) {
+    return Boolean(maybeStack &&
+        // @ts-expect-error: maybeStack is typed as `{}`, need to change in 6.0 to `maybeStack && typeof maybeStack === 'object' && MAYBE_STACK_SYMBOL in maybeStack`
+        maybeStack[IS_STACK_SYMBOL]);
+}
+
+var Stack = /*@__PURE__*/(function (IndexedCollection) {
+  function Stack(value) {
+    // eslint-disable-next-line no-constructor-return
+    return value === undefined || value === null
+      ? emptyStack()
+      : isStack(value)
+        ? value
+        : emptyStack().pushAll(value);
+  }
+
+  if ( IndexedCollection ) Stack.__proto__ = IndexedCollection;
+  Stack.prototype = Object.create( IndexedCollection && IndexedCollection.prototype );
+  Stack.prototype.constructor = Stack;
+
+  Stack.of = function of (/*...values*/) {
+    return this(arguments);
+  };
+
+  Stack.prototype.toString = function toString () {
+    return this.__toString('Stack [', ']');
+  };
+
+  // @pragma Access
+
+  Stack.prototype.get = function get (index, notSetValue) {
+    var head = this._head;
+    index = wrapIndex(this, index);
+    while (head && index--) {
+      head = head.next;
+    }
+    return head ? head.value : notSetValue;
+  };
+
+  Stack.prototype.peek = function peek () {
+    return this._head && this._head.value;
+  };
+
+  // @pragma Modification
+
+  Stack.prototype.push = function push (/*...values*/) {
+    var arguments$1 = arguments;
+
+    if (arguments.length === 0) {
+      return this;
+    }
+    var newSize = this.size + arguments.length;
+    var head = this._head;
+    for (var ii = arguments.length - 1; ii >= 0; ii--) {
+      head = {
+        value: arguments$1[ii],
+        next: head,
+      };
+    }
+    if (this.__ownerID) {
+      this.size = newSize;
+      this._head = head;
+      this.__hash = undefined;
+      this.__altered = true;
+      return this;
+    }
+    return makeStack(newSize, head);
+  };
+
+  Stack.prototype.pushAll = function pushAll (iter) {
+    iter = IndexedCollection(iter);
+    if (iter.size === 0) {
+      return this;
+    }
+    if (this.size === 0 && isStack(iter)) {
+      return iter;
+    }
+    assertNotInfinite(iter.size);
+    var newSize = this.size;
+    var head = this._head;
+    iter.__iterate(function (value) {
+      newSize++;
+      head = {
+        value: value,
+        next: head,
+      };
+    }, /* reverse */ true);
+    if (this.__ownerID) {
+      this.size = newSize;
+      this._head = head;
+      this.__hash = undefined;
+      this.__altered = true;
+      return this;
+    }
+    return makeStack(newSize, head);
+  };
+
+  Stack.prototype.pop = function pop () {
+    return this.slice(1);
+  };
+
+  Stack.prototype.clear = function clear () {
+    if (this.size === 0) {
+      return this;
+    }
+    if (this.__ownerID) {
+      this.size = 0;
+      this._head = undefined;
+      this.__hash = undefined;
+      this.__altered = true;
+      return this;
+    }
+    return emptyStack();
+  };
+
+  Stack.prototype.slice = function slice (begin, end) {
+    if (wholeSlice(begin, end, this.size)) {
+      return this;
+    }
+    var resolvedBegin = resolveBegin(begin, this.size);
+    var resolvedEnd = resolveEnd(end, this.size);
+    if (resolvedEnd !== this.size) {
+      // super.slice(begin, end);
+      return IndexedCollection.prototype.slice.call(this, begin, end);
+    }
+    var newSize = this.size - resolvedBegin;
+    var head = this._head;
+    while (resolvedBegin--) {
+      head = head.next;
+    }
+    if (this.__ownerID) {
+      this.size = newSize;
+      this._head = head;
+      this.__hash = undefined;
+      this.__altered = true;
+      return this;
+    }
+    return makeStack(newSize, head);
+  };
+
+  // @pragma Mutability
+
+  Stack.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+    if (ownerID === this.__ownerID) {
+      return this;
+    }
+    if (!ownerID) {
+      if (this.size === 0) {
+        return emptyStack();
+      }
+      this.__ownerID = ownerID;
+      this.__altered = false;
+      return this;
+    }
+    return makeStack(this.size, this._head, ownerID, this.__hash);
+  };
+
+  // @pragma Iteration
+
+  Stack.prototype.__iterate = function __iterate (fn, reverse) {
+    var this$1$1 = this;
+
+    if (reverse) {
+      return new ArraySeq(this.toArray()).__iterate(
+        function (v, k) { return fn(v, k, this$1$1); },
+        reverse
+      );
+    }
+    var iterations = 0;
+    var node = this._head;
+    while (node) {
+      if (fn(node.value, iterations++, this) === false) {
+        break;
+      }
+      node = node.next;
+    }
+    return iterations;
+  };
+
+  Stack.prototype.__iterator = function __iterator (type, reverse) {
+    if (reverse) {
+      return new ArraySeq(this.toArray()).__iterator(type, reverse);
+    }
+    var iterations = 0;
+    var node = this._head;
+    return new Iterator(function () {
+      if (node) {
+        var value = node.value;
+        node = node.next;
+        return iteratorValue(type, iterations++, value);
+      }
+      return iteratorDone();
+    });
+  };
+
+  return Stack;
+}(IndexedCollection));
+
+Stack.isStack = isStack;
+
+var StackPrototype = Stack.prototype;
+StackPrototype[IS_STACK_SYMBOL] = true;
+StackPrototype.shift = StackPrototype.pop;
+StackPrototype.unshift = StackPrototype.push;
+StackPrototype.unshiftAll = StackPrototype.pushAll;
+StackPrototype.withMutations = withMutations;
+StackPrototype.wasAltered = wasAltered;
+StackPrototype.asImmutable = asImmutable;
+StackPrototype['@@transducer/init'] = StackPrototype.asMutable = asMutable;
+StackPrototype['@@transducer/step'] = function (result, arr) {
+  return result.unshift(arr);
+};
+StackPrototype['@@transducer/result'] = function (obj) {
+  return obj.asImmutable();
+};
+
+function makeStack(size, head, ownerID, hash) {
+  var map = Object.create(StackPrototype);
+  map.size = size;
+  map._head = head;
+  map.__ownerID = ownerID;
+  map.__hash = hash;
+  map.__altered = false;
+  return map;
+}
+
+var EMPTY_STACK;
+function emptyStack() {
+  return EMPTY_STACK || (EMPTY_STACK = makeStack(0));
+}
+
+var IS_SET_SYMBOL = '@@__IMMUTABLE_SET__@@';
+/**
+ * True if `maybeSet` is a Set.
+ *
+ * Also true for OrderedSets.
+ */
+function isSet(maybeSet) {
+    return Boolean(maybeSet &&
+        // @ts-expect-error: maybeSet is typed as `{}`,  need to change in 6.0 to `maybeSeq && typeof maybeSet === 'object' && MAYBE_SET_SYMBOL in maybeSet`
+        maybeSet[IS_SET_SYMBOL]);
+}
+
+/**
+ * True if `maybeOrderedSet` is an OrderedSet.
+ */
+function isOrderedSet(maybeOrderedSet) {
+    return isSet(maybeOrderedSet) && isOrdered(maybeOrderedSet);
+}
+
+function deepEqual(a, b) {
+    if (a === b) {
+        return true;
+    }
+    if (!isCollection(b) ||
+        // @ts-expect-error size should exists on Collection
+        (a.size !== undefined && b.size !== undefined && a.size !== b.size) ||
+        // @ts-expect-error __hash exists on Collection
+        (a.__hash !== undefined &&
+            // @ts-expect-error __hash exists on Collection
+            b.__hash !== undefined &&
+            // @ts-expect-error __hash exists on Collection
+            a.__hash !== b.__hash) ||
+        isKeyed(a) !== isKeyed(b) ||
+        isIndexed(a) !== isIndexed(b) ||
+        // @ts-expect-error Range extends Collection, which implements [Symbol.iterator], so it is valid
+        isOrdered(a) !== isOrdered(b)) {
+        return false;
+    }
+    // @ts-expect-error size should exists on Collection
+    if (a.size === 0 && b.size === 0) {
+        return true;
+    }
+    var notAssociative = !isAssociative(a);
+    // @ts-expect-error Range extends Collection, which implements [Symbol.iterator], so it is valid
+    if (isOrdered(a)) {
+        var entries = a.entries();
+        // @ts-expect-error need to cast as boolean
+        return (b.every(function (v, k) {
+            var entry = entries.next().value;
+            return entry && is(entry[1], v) && (notAssociative || is(entry[0], k));
+        }) && entries.next().done);
+    }
+    var flipped = false;
+    if (a.size === undefined) {
+        // @ts-expect-error size should exists on Collection
+        if (b.size === undefined) {
+            if (typeof a.cacheResult === 'function') {
+                a.cacheResult();
+            }
+        }
+        else {
+            flipped = true;
+            var _ = a;
+            a = b;
+            b = _;
+        }
+    }
+    var allEqual = true;
+    var bSize = 
+    // @ts-expect-error b is Range | Repeat | Collection<unknown, unknown> as it may have been flipped, and __iterate is valid
+    b.__iterate(function (v, k) {
+        if (notAssociative
+            ? // @ts-expect-error has exists on Collection
+                !a.has(v)
+            : flipped
+                ? // @ts-expect-error type of `get` does not "catch" the version with `notSetValue`
+                    !is(v, a.get(k, NOT_SET))
+                : // @ts-expect-error type of `get` does not "catch" the version with `notSetValue`
+                    !is(a.get(k, NOT_SET), v)) {
+            allEqual = false;
+            return false;
+        }
+    });
+    return (allEqual &&
+        // @ts-expect-error size should exists on Collection
+        a.size === bSize);
+}
+
+/**
+ * Contributes additional methods to a constructor
+ */
+function mixin(ctor, 
+// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
+methods) {
+    var keyCopier = function (key) {
+        // @ts-expect-error how to handle symbol ?
+        ctor.prototype[key] = methods[key];
+    };
+    Object.keys(methods).forEach(keyCopier);
+    // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+    Object.getOwnPropertySymbols &&
+        Object.getOwnPropertySymbols(methods).forEach(keyCopier);
+    return ctor;
+}
+
+function toJS(value) {
+  if (!value || typeof value !== 'object') {
+    return value;
+  }
+  if (!isCollection(value)) {
+    if (!isDataStructure(value)) {
+      return value;
+    }
+    value = Seq(value);
+  }
+  if (isKeyed(value)) {
+    var result$1 = {};
+    value.__iterate(function (v, k) {
+      result$1[k] = toJS(v);
+    });
+    return result$1;
+  }
+  var result = [];
+  value.__iterate(function (v) {
+    result.push(toJS(v));
+  });
+  return result;
+}
+
+var Set = /*@__PURE__*/(function (SetCollection) {
+  function Set(value) {
+    // eslint-disable-next-line no-constructor-return
+    return value === undefined || value === null
+      ? emptySet()
+      : isSet(value) && !isOrdered(value)
+        ? value
+        : emptySet().withMutations(function (set) {
+            var iter = SetCollection(value);
+            assertNotInfinite(iter.size);
+            iter.forEach(function (v) { return set.add(v); });
+          });
+  }
+
+  if ( SetCollection ) Set.__proto__ = SetCollection;
+  Set.prototype = Object.create( SetCollection && SetCollection.prototype );
+  Set.prototype.constructor = Set;
+
+  Set.of = function of (/*...values*/) {
+    return this(arguments);
+  };
+
+  Set.fromKeys = function fromKeys (value) {
+    return this(KeyedCollection(value).keySeq());
+  };
+
+  Set.intersect = function intersect (sets) {
+    sets = Collection(sets).toArray();
+    return sets.length
+      ? SetPrototype.intersect.apply(Set(sets.pop()), sets)
+      : emptySet();
+  };
+
+  Set.union = function union (sets) {
+    sets = Collection(sets).toArray();
+    return sets.length
+      ? SetPrototype.union.apply(Set(sets.pop()), sets)
+      : emptySet();
+  };
+
+  Set.prototype.toString = function toString () {
+    return this.__toString('Set {', '}');
+  };
+
+  // @pragma Access
+
+  Set.prototype.has = function has (value) {
+    return this._map.has(value);
+  };
+
+  // @pragma Modification
+
+  Set.prototype.add = function add (value) {
+    return updateSet(this, this._map.set(value, value));
+  };
+
+  Set.prototype.remove = function remove (value) {
+    return updateSet(this, this._map.remove(value));
+  };
+
+  Set.prototype.clear = function clear () {
+    return updateSet(this, this._map.clear());
+  };
+
+  // @pragma Composition
+
+  Set.prototype.map = function map (mapper, context) {
+    var this$1$1 = this;
+
+    // keep track if the set is altered by the map function
+    var didChanges = false;
+
+    var newMap = updateSet(
+      this,
+      this._map.mapEntries(function (ref) {
+        var v = ref[1];
+
+        var mapped = mapper.call(context, v, v, this$1$1);
+
+        if (mapped !== v) {
+          didChanges = true;
+        }
+
+        return [mapped, mapped];
+      }, context)
+    );
+
+    return didChanges ? newMap : this;
+  };
+
+  Set.prototype.union = function union () {
+    var iters = [], len = arguments.length;
+    while ( len-- ) iters[ len ] = arguments[ len ];
+
+    iters = iters.filter(function (x) { return x.size !== 0; });
+    if (iters.length === 0) {
+      return this;
+    }
+    if (this.size === 0 && !this.__ownerID && iters.length === 1) {
+      return this.constructor(iters[0]);
+    }
+    return this.withMutations(function (set) {
+      for (var ii = 0; ii < iters.length; ii++) {
+        if (typeof iters[ii] === 'string') {
+          set.add(iters[ii]);
+        } else {
+          SetCollection(iters[ii]).forEach(function (value) { return set.add(value); });
+        }
+      }
+    });
+  };
+
+  Set.prototype.intersect = function intersect () {
+    var iters = [], len = arguments.length;
+    while ( len-- ) iters[ len ] = arguments[ len ];
+
+    if (iters.length === 0) {
+      return this;
+    }
+    iters = iters.map(function (iter) { return SetCollection(iter); });
+    var toRemove = [];
+    this.forEach(function (value) {
+      if (!iters.every(function (iter) { return iter.includes(value); })) {
+        toRemove.push(value);
+      }
+    });
+    return this.withMutations(function (set) {
+      toRemove.forEach(function (value) {
+        set.remove(value);
+      });
+    });
+  };
+
+  Set.prototype.subtract = function subtract () {
+    var iters = [], len = arguments.length;
+    while ( len-- ) iters[ len ] = arguments[ len ];
+
+    if (iters.length === 0) {
+      return this;
+    }
+    iters = iters.map(function (iter) { return SetCollection(iter); });
+    var toRemove = [];
+    this.forEach(function (value) {
+      if (iters.some(function (iter) { return iter.includes(value); })) {
+        toRemove.push(value);
+      }
+    });
+    return this.withMutations(function (set) {
+      toRemove.forEach(function (value) {
+        set.remove(value);
+      });
+    });
+  };
+
+  Set.prototype.sort = function sort (comparator) {
+    // Late binding
+    return OrderedSet(sortFactory(this, comparator));
+  };
+
+  Set.prototype.sortBy = function sortBy (mapper, comparator) {
+    // Late binding
+    return OrderedSet(sortFactory(this, comparator, mapper));
+  };
+
+  Set.prototype.wasAltered = function wasAltered () {
+    return this._map.wasAltered();
+  };
+
+  Set.prototype.__iterate = function __iterate (fn, reverse) {
+    var this$1$1 = this;
+
+    return this._map.__iterate(function (k) { return fn(k, k, this$1$1); }, reverse);
+  };
+
+  Set.prototype.__iterator = function __iterator (type, reverse) {
+    return this._map.__iterator(type, reverse);
+  };
+
+  Set.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+    if (ownerID === this.__ownerID) {
+      return this;
+    }
+    var newMap = this._map.__ensureOwner(ownerID);
+    if (!ownerID) {
+      if (this.size === 0) {
+        return this.__empty();
+      }
+      this.__ownerID = ownerID;
+      this._map = newMap;
+      return this;
+    }
+    return this.__make(newMap, ownerID);
+  };
+
+  return Set;
+}(SetCollection));
+
+Set.isSet = isSet;
+
+var SetPrototype = Set.prototype;
+SetPrototype[IS_SET_SYMBOL] = true;
+SetPrototype[DELETE] = SetPrototype.remove;
+SetPrototype.merge = SetPrototype.concat = SetPrototype.union;
+SetPrototype.withMutations = withMutations;
+SetPrototype.asImmutable = asImmutable;
+SetPrototype['@@transducer/init'] = SetPrototype.asMutable = asMutable;
+SetPrototype['@@transducer/step'] = function (result, arr) {
+  return result.add(arr);
+};
+SetPrototype['@@transducer/result'] = function (obj) {
+  return obj.asImmutable();
+};
+
+SetPrototype.__empty = emptySet;
+SetPrototype.__make = makeSet;
+
+function updateSet(set, newMap) {
+  if (set.__ownerID) {
+    set.size = newMap.size;
+    set._map = newMap;
+    return set;
+  }
+  return newMap === set._map
+    ? set
+    : newMap.size === 0
+      ? set.__empty()
+      : set.__make(newMap);
+}
+
+function makeSet(map, ownerID) {
+  var set = Object.create(SetPrototype);
+  set.size = map ? map.size : 0;
+  set._map = map;
+  set.__ownerID = ownerID;
+  return set;
+}
+
+var EMPTY_SET;
+function emptySet() {
+  return EMPTY_SET || (EMPTY_SET = makeSet(emptyMap()));
+}
+
+/**
+ * Returns a lazy seq of nums from start (inclusive) to end
+ * (exclusive), by step, where start defaults to 0, step to 1, and end to
+ * infinity. When start is equal to end, returns empty list.
+ */
+var Range = /*@__PURE__*/(function (IndexedSeq) {
+  function Range(start, end, step) {
+    if ( step === void 0 ) step = 1;
+
+    if (!(this instanceof Range)) {
+      // eslint-disable-next-line no-constructor-return
+      return new Range(start, end, step);
+    }
+    invariant(step !== 0, 'Cannot step a Range by 0');
+    invariant(
+      start !== undefined,
+      'You must define a start value when using Range'
+    );
+    invariant(
+      end !== undefined,
+      'You must define an end value when using Range'
+    );
+
+    step = Math.abs(step);
+    if (end < start) {
+      step = -step;
+    }
+    this._start = start;
+    this._end = end;
+    this._step = step;
+    this.size = Math.max(0, Math.ceil((end - start) / step - 1) + 1);
+    if (this.size === 0) {
+      if (EMPTY_RANGE) {
+        // eslint-disable-next-line no-constructor-return
+        return EMPTY_RANGE;
+      }
+      // eslint-disable-next-line @typescript-eslint/no-this-alias
+      EMPTY_RANGE = this;
+    }
+  }
+
+  if ( IndexedSeq ) Range.__proto__ = IndexedSeq;
+  Range.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
+  Range.prototype.constructor = Range;
+
+  Range.prototype.toString = function toString () {
+    return this.size === 0
+      ? 'Range []'
+      : ("Range [ " + (this._start) + "..." + (this._end) + (this._step !== 1 ? ' by ' + this._step : '') + " ]");
+  };
+
+  Range.prototype.get = function get (index, notSetValue) {
+    return this.has(index)
+      ? this._start + wrapIndex(this, index) * this._step
+      : notSetValue;
+  };
+
+  Range.prototype.includes = function includes (searchValue) {
+    var possibleIndex = (searchValue - this._start) / this._step;
+    return (
+      possibleIndex >= 0 &&
+      possibleIndex < this.size &&
+      possibleIndex === Math.floor(possibleIndex)
+    );
+  };
+
+  Range.prototype.slice = function slice (begin, end) {
+    if (wholeSlice(begin, end, this.size)) {
+      return this;
+    }
+    begin = resolveBegin(begin, this.size);
+    end = resolveEnd(end, this.size);
+    if (end <= begin) {
+      return new Range(0, 0);
+    }
+    return new Range(
+      this.get(begin, this._end),
+      this.get(end, this._end),
+      this._step
+    );
+  };
+
+  Range.prototype.indexOf = function indexOf (searchValue) {
+    var offsetValue = searchValue - this._start;
+    if (offsetValue % this._step === 0) {
+      var index = offsetValue / this._step;
+      if (index >= 0 && index < this.size) {
+        return index;
+      }
+    }
+    return -1;
+  };
+
+  Range.prototype.lastIndexOf = function lastIndexOf (searchValue) {
+    return this.indexOf(searchValue);
+  };
+
+  Range.prototype.__iterate = function __iterate (fn, reverse) {
+    var size = this.size;
+    var step = this._step;
+    var value = reverse ? this._start + (size - 1) * step : this._start;
+    var i = 0;
+    while (i !== size) {
+      if (fn(value, reverse ? size - ++i : i++, this) === false) {
+        break;
+      }
+      value += reverse ? -step : step;
+    }
+    return i;
+  };
+
+  Range.prototype.__iterator = function __iterator (type, reverse) {
+    var size = this.size;
+    var step = this._step;
+    var value = reverse ? this._start + (size - 1) * step : this._start;
+    var i = 0;
+    return new Iterator(function () {
+      if (i === size) {
+        return iteratorDone();
+      }
+      var v = value;
+      value += reverse ? -step : step;
+      return iteratorValue(type, reverse ? size - ++i : i++, v);
+    });
+  };
+
+  Range.prototype.equals = function equals (other) {
+    return other instanceof Range
+      ? this._start === other._start &&
+          this._end === other._end &&
+          this._step === other._step
+      : deepEqual(this, other);
+  };
+
+  return Range;
+}(IndexedSeq));
+
+var EMPTY_RANGE;
+
+/**
+ * Returns the value at the provided key path starting at the provided
+ * collection, or notSetValue if the key path is not defined.
+ *
+ * A functional alternative to `collection.getIn(keypath)` which will also
+ * work with plain Objects and Arrays.
+ */
+function getIn$1(collection, searchKeyPath, notSetValue) {
+    var keyPath = coerceKeyPath(searchKeyPath);
+    var i = 0;
+    while (i !== keyPath.length) {
+        // @ts-expect-error keyPath[i++] can not be undefined by design
+        collection = get(collection, keyPath[i++], NOT_SET);
+        if (collection === NOT_SET) {
+            return notSetValue;
+        }
+    }
+    return collection;
+}
+
+function getIn(searchKeyPath, notSetValue) {
+  return getIn$1(this, searchKeyPath, notSetValue);
+}
+
+/**
+ * Returns true if the key path is defined in the provided collection.
+ *
+ * A functional alternative to `collection.hasIn(keypath)` which will also
+ * work with plain Objects and Arrays.
+ */
+function hasIn$1(collection, keyPath) {
+    return getIn$1(collection, keyPath, NOT_SET) !== NOT_SET;
+}
+
+function hasIn(searchKeyPath) {
+  return hasIn$1(this, searchKeyPath);
+}
+
+function toObject() {
+  assertNotInfinite(this.size);
+  var object = {};
+  this.__iterate(function (v, k) {
+    object[k] = v;
+  });
+  return object;
+}
+
+Collection.Iterator = Iterator;
+
+mixin(Collection, {
+  // ### Conversion to other types
+
+  toArray: function toArray() {
+    assertNotInfinite(this.size);
+    var array = new Array(this.size || 0);
+    var useTuples = isKeyed(this);
+    var i = 0;
+    this.__iterate(function (v, k) {
+      // Keyed collections produce an array of tuples.
+      array[i++] = useTuples ? [k, v] : v;
+    });
+    return array;
+  },
+
+  toIndexedSeq: function toIndexedSeq() {
+    return new ToIndexedSequence(this);
+  },
+
+  toJS: function toJS$1() {
+    return toJS(this);
+  },
+
+  toKeyedSeq: function toKeyedSeq() {
+    return new ToKeyedSequence(this, true);
+  },
+
+  toMap: function toMap() {
+    // Use Late Binding here to solve the circular dependency.
+    return Map(this.toKeyedSeq());
+  },
+
+  toObject: toObject,
+
+  toOrderedMap: function toOrderedMap() {
+    // Use Late Binding here to solve the circular dependency.
+    return OrderedMap(this.toKeyedSeq());
+  },
+
+  toOrderedSet: function toOrderedSet() {
+    // Use Late Binding here to solve the circular dependency.
+    return OrderedSet(isKeyed(this) ? this.valueSeq() : this);
+  },
+
+  toSet: function toSet() {
+    // Use Late Binding here to solve the circular dependency.
+    return Set(isKeyed(this) ? this.valueSeq() : this);
+  },
+
+  toSetSeq: function toSetSeq() {
+    return new ToSetSequence(this);
+  },
+
+  toSeq: function toSeq() {
+    return isIndexed(this)
+      ? this.toIndexedSeq()
+      : isKeyed(this)
+        ? this.toKeyedSeq()
+        : this.toSetSeq();
+  },
+
+  toStack: function toStack() {
+    // Use Late Binding here to solve the circular dependency.
+    return Stack(isKeyed(this) ? this.valueSeq() : this);
+  },
+
+  toList: function toList() {
+    // Use Late Binding here to solve the circular dependency.
+    return List(isKeyed(this) ? this.valueSeq() : this);
+  },
+
+  // ### Common JavaScript methods and properties
+
+  toString: function toString() {
+    return '[Collection]';
+  },
+
+  __toString: function __toString(head, tail) {
+    if (this.size === 0) {
+      return head + tail;
+    }
+    return (
+      head +
+      ' ' +
+      this.toSeq().map(this.__toStringMapper).join(', ') +
+      ' ' +
+      tail
+    );
+  },
+
+  // ### ES6 Collection methods (ES6 Array and Map)
+
+  concat: function concat() {
+    var values = [], len = arguments.length;
+    while ( len-- ) values[ len ] = arguments[ len ];
+
+    return reify(this, concatFactory(this, values));
+  },
+
+  includes: function includes(searchValue) {
+    return this.some(function (value) { return is(value, searchValue); });
+  },
+
+  entries: function entries() {
+    return this.__iterator(ITERATE_ENTRIES);
+  },
+
+  every: function every(predicate, context) {
+    assertNotInfinite(this.size);
+    var returnValue = true;
+    this.__iterate(function (v, k, c) {
+      if (!predicate.call(context, v, k, c)) {
+        returnValue = false;
+        return false;
+      }
+    });
+    return returnValue;
+  },
+
+  filter: function filter(predicate, context) {
+    return reify(this, filterFactory(this, predicate, context, true));
+  },
+
+  partition: function partition(predicate, context) {
+    return partitionFactory(this, predicate, context);
+  },
+
+  find: function find(predicate, context, notSetValue) {
+    var entry = this.findEntry(predicate, context);
+    return entry ? entry[1] : notSetValue;
+  },
+
+  forEach: function forEach(sideEffect, context) {
+    assertNotInfinite(this.size);
+    return this.__iterate(context ? sideEffect.bind(context) : sideEffect);
+  },
+
+  join: function join(separator) {
+    assertNotInfinite(this.size);
+    separator = separator !== undefined ? '' + separator : ',';
+    var joined = '';
+    var isFirst = true;
+    this.__iterate(function (v) {
+      // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+      isFirst ? (isFirst = false) : (joined += separator);
+      joined += v !== null && v !== undefined ? v.toString() : '';
+    });
+    return joined;
+  },
+
+  keys: function keys() {
+    return this.__iterator(ITERATE_KEYS);
+  },
+
+  map: function map(mapper, context) {
+    return reify(this, mapFactory(this, mapper, context));
+  },
+
+  reduce: function reduce$1(reducer, initialReduction, context) {
+    return reduce(
+      this,
+      reducer,
+      initialReduction,
+      context,
+      arguments.length < 2,
+      false
+    );
+  },
+
+  reduceRight: function reduceRight(reducer, initialReduction, context) {
+    return reduce(
+      this,
+      reducer,
+      initialReduction,
+      context,
+      arguments.length < 2,
+      true
+    );
+  },
+
+  reverse: function reverse() {
+    return reify(this, reverseFactory(this, true));
+  },
+
+  slice: function slice(begin, end) {
+    return reify(this, sliceFactory(this, begin, end, true));
+  },
+
+  some: function some(predicate, context) {
+    assertNotInfinite(this.size);
+    var returnValue = false;
+    this.__iterate(function (v, k, c) {
+      if (predicate.call(context, v, k, c)) {
+        returnValue = true;
+        return false;
+      }
+    });
+    return returnValue;
+  },
+
+  sort: function sort(comparator) {
+    return reify(this, sortFactory(this, comparator));
+  },
+
+  values: function values() {
+    return this.__iterator(ITERATE_VALUES);
+  },
+
+  // ### More sequential methods
+
+  butLast: function butLast() {
+    return this.slice(0, -1);
+  },
+
+  isEmpty: function isEmpty() {
+    return this.size !== undefined ? this.size === 0 : !this.some(function () { return true; });
+  },
+
+  count: function count(predicate, context) {
+    return ensureSize(
+      predicate ? this.toSeq().filter(predicate, context) : this
+    );
+  },
+
+  countBy: function countBy(grouper, context) {
+    return countByFactory(this, grouper, context);
+  },
+
+  equals: function equals(other) {
+    return deepEqual(this, other);
+  },
+
+  entrySeq: function entrySeq() {
+    // eslint-disable-next-line @typescript-eslint/no-this-alias
+    var collection = this;
+    if (collection._cache) {
+      // We cache as an entries array, so we can just return the cache!
+      return new ArraySeq(collection._cache);
+    }
+    var entriesSequence = collection.toSeq().map(entryMapper).toIndexedSeq();
+    entriesSequence.fromEntrySeq = function () { return collection.toSeq(); };
+    return entriesSequence;
+  },
+
+  filterNot: function filterNot(predicate, context) {
+    return this.filter(not(predicate), context);
+  },
+
+  findEntry: function findEntry(predicate, context, notSetValue) {
+    var found = notSetValue;
+    this.__iterate(function (v, k, c) {
+      if (predicate.call(context, v, k, c)) {
+        found = [k, v];
+        return false;
+      }
+    });
+    return found;
+  },
+
+  findKey: function findKey(predicate, context) {
+    var entry = this.findEntry(predicate, context);
+    return entry && entry[0];
+  },
+
+  findLast: function findLast(predicate, context, notSetValue) {
+    return this.toKeyedSeq().reverse().find(predicate, context, notSetValue);
+  },
+
+  findLastEntry: function findLastEntry(predicate, context, notSetValue) {
+    return this.toKeyedSeq()
+      .reverse()
+      .findEntry(predicate, context, notSetValue);
+  },
+
+  findLastKey: function findLastKey(predicate, context) {
+    return this.toKeyedSeq().reverse().findKey(predicate, context);
+  },
+
+  first: function first(notSetValue) {
+    return this.find(returnTrue, null, notSetValue);
+  },
+
+  flatMap: function flatMap(mapper, context) {
+    return reify(this, flatMapFactory(this, mapper, context));
+  },
+
+  flatten: function flatten(depth) {
+    return reify(this, flattenFactory(this, depth, true));
+  },
+
+  fromEntrySeq: function fromEntrySeq() {
+    return new FromEntriesSequence(this);
+  },
+
+  get: function get(searchKey, notSetValue) {
+    return this.find(function (_, key) { return is(key, searchKey); }, undefined, notSetValue);
+  },
+
+  getIn: getIn,
+
+  groupBy: function groupBy(grouper, context) {
+    return groupByFactory(this, grouper, context);
+  },
+
+  has: function has(searchKey) {
+    return this.get(searchKey, NOT_SET) !== NOT_SET;
+  },
+
+  hasIn: hasIn,
+
+  isSubset: function isSubset(iter) {
+    iter = typeof iter.includes === 'function' ? iter : Collection(iter);
+    return this.every(function (value) { return iter.includes(value); });
+  },
+
+  isSuperset: function isSuperset(iter) {
+    iter = typeof iter.isSubset === 'function' ? iter : Collection(iter);
+    return iter.isSubset(this);
+  },
+
+  keyOf: function keyOf(searchValue) {
+    return this.findKey(function (value) { return is(value, searchValue); });
+  },
+
+  keySeq: function keySeq() {
+    return this.toSeq().map(keyMapper).toIndexedSeq();
+  },
+
+  last: function last(notSetValue) {
+    return this.toSeq().reverse().first(notSetValue);
+  },
+
+  lastKeyOf: function lastKeyOf(searchValue) {
+    return this.toKeyedSeq().reverse().keyOf(searchValue);
+  },
+
+  max: function max(comparator) {
+    return maxFactory(this, comparator);
+  },
+
+  maxBy: function maxBy(mapper, comparator) {
+    return maxFactory(this, comparator, mapper);
+  },
+
+  min: function min(comparator) {
+    return maxFactory(
+      this,
+      comparator ? neg(comparator) : defaultNegComparator
+    );
+  },
+
+  minBy: function minBy(mapper, comparator) {
+    return maxFactory(
+      this,
+      comparator ? neg(comparator) : defaultNegComparator,
+      mapper
+    );
+  },
+
+  rest: function rest() {
+    return this.slice(1);
+  },
+
+  skip: function skip(amount) {
+    return amount === 0 ? this : this.slice(Math.max(0, amount));
+  },
+
+  skipLast: function skipLast(amount) {
+    return amount === 0 ? this : this.slice(0, -Math.max(0, amount));
+  },
+
+  skipWhile: function skipWhile(predicate, context) {
+    return reify(this, skipWhileFactory(this, predicate, context, true));
+  },
+
+  skipUntil: function skipUntil(predicate, context) {
+    return this.skipWhile(not(predicate), context);
+  },
+
+  sortBy: function sortBy(mapper, comparator) {
+    return reify(this, sortFactory(this, comparator, mapper));
+  },
+
+  take: function take(amount) {
+    return this.slice(0, Math.max(0, amount));
+  },
+
+  takeLast: function takeLast(amount) {
+    return this.slice(-Math.max(0, amount));
+  },
+
+  takeWhile: function takeWhile(predicate, context) {
+    return reify(this, takeWhileFactory(this, predicate, context));
+  },
+
+  takeUntil: function takeUntil(predicate, context) {
+    return this.takeWhile(not(predicate), context);
+  },
+
+  update: function update(fn) {
+    return fn(this);
+  },
+
+  valueSeq: function valueSeq() {
+    return this.toIndexedSeq();
+  },
+
+  // ### Hashable Object
+
+  hashCode: function hashCode() {
+    return this.__hash || (this.__hash = hashCollection(this));
+  },
+
+  // ### Internal
+
+  // abstract __iterate(fn, reverse)
+
+  // abstract __iterator(type, reverse)
+});
+
+var CollectionPrototype = Collection.prototype;
+CollectionPrototype[IS_COLLECTION_SYMBOL] = true;
+CollectionPrototype[ITERATOR_SYMBOL] = CollectionPrototype.values;
+CollectionPrototype.toJSON = CollectionPrototype.toArray;
+CollectionPrototype.__toStringMapper = quoteString;
+CollectionPrototype.inspect = CollectionPrototype.toSource = function () {
+  return this.toString();
+};
+CollectionPrototype.chain = CollectionPrototype.flatMap;
+CollectionPrototype.contains = CollectionPrototype.includes;
+
+mixin(KeyedCollection, {
+  // ### More sequential methods
+
+  flip: function flip() {
+    return reify(this, flipFactory(this));
+  },
+
+  mapEntries: function mapEntries(mapper, context) {
+    var this$1$1 = this;
+
+    var iterations = 0;
+    return reify(
+      this,
+      this.toSeq()
+        .map(function (v, k) { return mapper.call(context, [k, v], iterations++, this$1$1); })
+        .fromEntrySeq()
+    );
+  },
+
+  mapKeys: function mapKeys(mapper, context) {
+    var this$1$1 = this;
+
+    return reify(
+      this,
+      this.toSeq()
+        .flip()
+        .map(function (k, v) { return mapper.call(context, k, v, this$1$1); })
+        .flip()
+    );
+  },
+});
+
+var KeyedCollectionPrototype = KeyedCollection.prototype;
+KeyedCollectionPrototype[IS_KEYED_SYMBOL] = true;
+KeyedCollectionPrototype[ITERATOR_SYMBOL] = CollectionPrototype.entries;
+KeyedCollectionPrototype.toJSON = toObject;
+KeyedCollectionPrototype.__toStringMapper = function (v, k) { return quoteString(k) + ': ' + quoteString(v); };
+
+mixin(IndexedCollection, {
+  // ### Conversion to other types
+
+  toKeyedSeq: function toKeyedSeq() {
+    return new ToKeyedSequence(this, false);
+  },
+
+  // ### ES6 Collection methods (ES6 Array and Map)
+
+  filter: function filter(predicate, context) {
+    return reify(this, filterFactory(this, predicate, context, false));
+  },
+
+  findIndex: function findIndex(predicate, context) {
+    var entry = this.findEntry(predicate, context);
+    return entry ? entry[0] : -1;
+  },
+
+  indexOf: function indexOf(searchValue) {
+    var key = this.keyOf(searchValue);
+    return key === undefined ? -1 : key;
+  },
+
+  lastIndexOf: function lastIndexOf(searchValue) {
+    var key = this.lastKeyOf(searchValue);
+    return key === undefined ? -1 : key;
+  },
+
+  reverse: function reverse() {
+    return reify(this, reverseFactory(this, false));
+  },
+
+  slice: function slice(begin, end) {
+    return reify(this, sliceFactory(this, begin, end, false));
+  },
+
+  splice: function splice(index, removeNum /*, ...values*/) {
+    var numArgs = arguments.length;
+    removeNum = Math.max(removeNum || 0, 0);
+    if (numArgs === 0 || (numArgs === 2 && !removeNum)) {
+      return this;
+    }
+    // If index is negative, it should resolve relative to the size of the
+    // collection. However size may be expensive to compute if not cached, so
+    // only call count() if the number is in fact negative.
+    index = resolveBegin(index, index < 0 ? this.count() : this.size);
+    var spliced = this.slice(0, index);
+    return reify(
+      this,
+      numArgs === 1
+        ? spliced
+        : spliced.concat(arrCopy(arguments, 2), this.slice(index + removeNum))
+    );
+  },
+
+  // ### More collection methods
+
+  findLastIndex: function findLastIndex(predicate, context) {
+    var entry = this.findLastEntry(predicate, context);
+    return entry ? entry[0] : -1;
+  },
+
+  first: function first(notSetValue) {
+    return this.get(0, notSetValue);
+  },
+
+  flatten: function flatten(depth) {
+    return reify(this, flattenFactory(this, depth, false));
+  },
+
+  get: function get(index, notSetValue) {
+    index = wrapIndex(this, index);
+    return index < 0 ||
+      this.size === Infinity ||
+      (this.size !== undefined && index > this.size)
+      ? notSetValue
+      : this.find(function (_, key) { return key === index; }, undefined, notSetValue);
+  },
+
+  has: function has(index) {
+    index = wrapIndex(this, index);
+    return (
+      index >= 0 &&
+      (this.size !== undefined
+        ? this.size === Infinity || index < this.size
+        : this.indexOf(index) !== -1)
+    );
+  },
+
+  interpose: function interpose(separator) {
+    return reify(this, interposeFactory(this, separator));
+  },
+
+  interleave: function interleave(/*...collections*/) {
+    var collections = [this].concat(arrCopy(arguments));
+    var zipped = zipWithFactory(this.toSeq(), IndexedSeq.of, collections);
+    var interleaved = zipped.flatten(true);
+    if (zipped.size) {
+      interleaved.size = zipped.size * collections.length;
+    }
+    return reify(this, interleaved);
+  },
+
+  keySeq: function keySeq() {
+    return Range(0, this.size);
+  },
+
+  last: function last(notSetValue) {
+    return this.get(-1, notSetValue);
+  },
+
+  skipWhile: function skipWhile(predicate, context) {
+    return reify(this, skipWhileFactory(this, predicate, context, false));
+  },
+
+  zip: function zip(/*, ...collections */) {
+    var collections = [this].concat(arrCopy(arguments));
+    return reify(this, zipWithFactory(this, defaultZipper, collections));
+  },
+
+  zipAll: function zipAll(/*, ...collections */) {
+    var collections = [this].concat(arrCopy(arguments));
+    return reify(this, zipWithFactory(this, defaultZipper, collections, true));
+  },
+
+  zipWith: function zipWith(zipper /*, ...collections */) {
+    var collections = arrCopy(arguments);
+    collections[0] = this;
+    return reify(this, zipWithFactory(this, zipper, collections));
+  },
+});
+
+var IndexedCollectionPrototype = IndexedCollection.prototype;
+IndexedCollectionPrototype[IS_INDEXED_SYMBOL] = true;
+IndexedCollectionPrototype[IS_ORDERED_SYMBOL] = true;
+
+mixin(SetCollection, {
+  // ### ES6 Collection methods (ES6 Array and Map)
+
+  get: function get(value, notSetValue) {
+    return this.has(value) ? value : notSetValue;
+  },
+
+  includes: function includes(value) {
+    return this.has(value);
+  },
+
+  // ### More sequential methods
+
+  keySeq: function keySeq() {
+    return this.valueSeq();
+  },
+});
+
+var SetCollectionPrototype = SetCollection.prototype;
+SetCollectionPrototype.has = CollectionPrototype.includes;
+SetCollectionPrototype.contains = SetCollectionPrototype.includes;
+SetCollectionPrototype.keys = SetCollectionPrototype.values;
+
+// Mixin subclasses
+
+mixin(KeyedSeq, KeyedCollectionPrototype);
+mixin(IndexedSeq, IndexedCollectionPrototype);
+mixin(SetSeq, SetCollectionPrototype);
+
+// #pragma Helper functions
+
+function reduce(collection, reducer, reduction, context, useFirst, reverse) {
+  assertNotInfinite(collection.size);
+  collection.__iterate(function (v, k, c) {
+    if (useFirst) {
+      useFirst = false;
+      reduction = v;
+    } else {
+      reduction = reducer.call(context, reduction, v, k, c);
+    }
+  }, reverse);
+  return reduction;
+}
+
+function keyMapper(v, k) {
+  return k;
+}
+
+function entryMapper(v, k) {
+  return [k, v];
+}
+
+function not(predicate) {
+  return function () {
+    return !predicate.apply(this, arguments);
+  };
+}
+
+function neg(predicate) {
+  return function () {
+    return -predicate.apply(this, arguments);
+  };
+}
+
+function defaultZipper() {
+  return arrCopy(arguments);
+}
+
+function defaultNegComparator(a, b) {
+  return a < b ? 1 : a > b ? -1 : 0;
+}
+
+function hashCollection(collection) {
+  if (collection.size === Infinity) {
+    return 0;
+  }
+  var ordered = isOrdered(collection);
+  var keyed = isKeyed(collection);
+  var h = ordered ? 1 : 0;
+
+  collection.__iterate(
+    keyed
+      ? ordered
+        ? function (v, k) {
+            h = (31 * h + hashMerge(hash(v), hash(k))) | 0;
+          }
+        : function (v, k) {
+            h = (h + hashMerge(hash(v), hash(k))) | 0;
+          }
+      : ordered
+        ? function (v) {
+            h = (31 * h + hash(v)) | 0;
+          }
+        : function (v) {
+            h = (h + hash(v)) | 0;
+          }
+  );
+
+  return murmurHashOfSize(collection.size, h);
+}
+
+function murmurHashOfSize(size, h) {
+  h = imul(h, 0xcc9e2d51);
+  h = imul((h << 15) | (h >>> -15), 0x1b873593);
+  h = imul((h << 13) | (h >>> -13), 5);
+  h = ((h + 0xe6546b64) | 0) ^ size;
+  h = imul(h ^ (h >>> 16), 0x85ebca6b);
+  h = imul(h ^ (h >>> 13), 0xc2b2ae35);
+  h = smi(h ^ (h >>> 16));
+  return h;
+}
+
+function hashMerge(a, b) {
+  return (a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2))) | 0; // int
+}
+
+var OrderedSet = /*@__PURE__*/(function (Set) {
+  function OrderedSet(value) {
+    // eslint-disable-next-line no-constructor-return
+    return value === undefined || value === null
+      ? emptyOrderedSet()
+      : isOrderedSet(value)
+        ? value
+        : emptyOrderedSet().withMutations(function (set) {
+            var iter = SetCollection(value);
+            assertNotInfinite(iter.size);
+            iter.forEach(function (v) { return set.add(v); });
+          });
+  }
+
+  if ( Set ) OrderedSet.__proto__ = Set;
+  OrderedSet.prototype = Object.create( Set && Set.prototype );
+  OrderedSet.prototype.constructor = OrderedSet;
+
+  OrderedSet.of = function of (/*...values*/) {
+    return this(arguments);
+  };
+
+  OrderedSet.fromKeys = function fromKeys (value) {
+    return this(KeyedCollection(value).keySeq());
+  };
+
+  OrderedSet.prototype.toString = function toString () {
+    return this.__toString('OrderedSet {', '}');
+  };
+
+  return OrderedSet;
+}(Set));
+
+OrderedSet.isOrderedSet = isOrderedSet;
+
+var OrderedSetPrototype = OrderedSet.prototype;
+OrderedSetPrototype[IS_ORDERED_SYMBOL] = true;
+OrderedSetPrototype.zip = IndexedCollectionPrototype.zip;
+OrderedSetPrototype.zipWith = IndexedCollectionPrototype.zipWith;
+OrderedSetPrototype.zipAll = IndexedCollectionPrototype.zipAll;
+
+OrderedSetPrototype.__empty = emptyOrderedSet;
+OrderedSetPrototype.__make = makeOrderedSet;
+
+function makeOrderedSet(map, ownerID) {
+  var set = Object.create(OrderedSetPrototype);
+  set.size = map ? map.size : 0;
+  set._map = map;
+  set.__ownerID = ownerID;
+  return set;
+}
+
+var EMPTY_ORDERED_SET;
+function emptyOrderedSet() {
+  return (
+    EMPTY_ORDERED_SET || (EMPTY_ORDERED_SET = makeOrderedSet(emptyOrderedMap()))
+  );
+}
+
+var PairSorting = {
+  LeftThenRight: -1,
+  RightThenLeft: 1,
+};
+
+function throwOnInvalidDefaultValues(defaultValues) {
+  if (isRecord(defaultValues)) {
+    throw new Error(
+      'Can not call `Record` with an immutable Record as default values. Use a plain javascript object instead.'
+    );
+  }
+
+  if (isImmutable(defaultValues)) {
+    throw new Error(
+      'Can not call `Record` with an immutable Collection as default values. Use a plain javascript object instead.'
+    );
+  }
+
+  if (defaultValues === null || typeof defaultValues !== 'object') {
+    throw new Error(
+      'Can not call `Record` with a non-object as default values. Use a plain javascript object instead.'
+    );
+  }
+}
+
+var Record = function Record(defaultValues, name) {
+  var hasInitialized;
+
+  throwOnInvalidDefaultValues(defaultValues);
+
+  var RecordType = function Record(values) {
+    var this$1$1 = this;
+
+    if (values instanceof RecordType) {
+      return values;
+    }
+    if (!(this instanceof RecordType)) {
+      return new RecordType(values);
+    }
+    if (!hasInitialized) {
+      hasInitialized = true;
+      var keys = Object.keys(defaultValues);
+      var indices = (RecordTypePrototype._indices = {});
+      // Deprecated: left to attempt not to break any external code which
+      // relies on a ._name property existing on record instances.
+      // Use Record.getDescriptiveName() instead
+      RecordTypePrototype._name = name;
+      RecordTypePrototype._keys = keys;
+      RecordTypePrototype._defaultValues = defaultValues;
+      for (var i = 0; i < keys.length; i++) {
+        var propName = keys[i];
+        indices[propName] = i;
+        if (RecordTypePrototype[propName]) {
+          /* eslint-disable no-console */
+          // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+          typeof console === 'object' &&
+            console.warn &&
+            console.warn(
+              'Cannot define ' +
+                recordName(this) +
+                ' with property "' +
+                propName +
+                '" since that property name is part of the Record API.'
+            );
+          /* eslint-enable no-console */
+        } else {
+          setProp(RecordTypePrototype, propName);
+        }
+      }
+    }
+    this.__ownerID = undefined;
+    this._values = List().withMutations(function (l) {
+      l.setSize(this$1$1._keys.length);
+      KeyedCollection(values).forEach(function (v, k) {
+        l.set(this$1$1._indices[k], v === this$1$1._defaultValues[k] ? undefined : v);
+      });
+    });
+    return this;
+  };
+
+  var RecordTypePrototype = (RecordType.prototype =
+    Object.create(RecordPrototype));
+  RecordTypePrototype.constructor = RecordType;
+
+  if (name) {
+    RecordType.displayName = name;
+  }
+
+  // eslint-disable-next-line no-constructor-return
+  return RecordType;
+};
+
+Record.prototype.toString = function toString () {
+  var str = recordName(this) + ' { ';
+  var keys = this._keys;
+  var k;
+  for (var i = 0, l = keys.length; i !== l; i++) {
+    k = keys[i];
+    str += (i ? ', ' : '') + k + ': ' + quoteString(this.get(k));
+  }
+  return str + ' }';
+};
+
+Record.prototype.equals = function equals (other) {
+  return (
+    this === other ||
+    (isRecord(other) && recordSeq(this).equals(recordSeq(other)))
+  );
+};
+
+Record.prototype.hashCode = function hashCode () {
+  return recordSeq(this).hashCode();
+};
+
+// @pragma Access
+
+Record.prototype.has = function has (k) {
+  return this._indices.hasOwnProperty(k);
+};
+
+Record.prototype.get = function get (k, notSetValue) {
+  if (!this.has(k)) {
+    return notSetValue;
+  }
+  var index = this._indices[k];
+  var value = this._values.get(index);
+  return value === undefined ? this._defaultValues[k] : value;
+};
+
+// @pragma Modification
+
+Record.prototype.set = function set (k, v) {
+  if (this.has(k)) {
+    var newValues = this._values.set(
+      this._indices[k],
+      v === this._defaultValues[k] ? undefined : v
+    );
+    if (newValues !== this._values && !this.__ownerID) {
+      return makeRecord(this, newValues);
+    }
+  }
+  return this;
+};
+
+Record.prototype.remove = function remove (k) {
+  return this.set(k);
+};
+
+Record.prototype.clear = function clear () {
+  var newValues = this._values.clear().setSize(this._keys.length);
+
+  return this.__ownerID ? this : makeRecord(this, newValues);
+};
+
+Record.prototype.wasAltered = function wasAltered () {
+  return this._values.wasAltered();
+};
+
+Record.prototype.toSeq = function toSeq () {
+  return recordSeq(this);
+};
+
+Record.prototype.toJS = function toJS$1 () {
+  return toJS(this);
+};
+
+Record.prototype.entries = function entries () {
+  return this.__iterator(ITERATE_ENTRIES);
+};
+
+Record.prototype.__iterator = function __iterator (type, reverse) {
+  return recordSeq(this).__iterator(type, reverse);
+};
+
+Record.prototype.__iterate = function __iterate (fn, reverse) {
+  return recordSeq(this).__iterate(fn, reverse);
+};
+
+Record.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+  if (ownerID === this.__ownerID) {
+    return this;
+  }
+  var newValues = this._values.__ensureOwner(ownerID);
+  if (!ownerID) {
+    this.__ownerID = ownerID;
+    this._values = newValues;
+    return this;
+  }
+  return makeRecord(this, newValues, ownerID);
+};
+
+Record.isRecord = isRecord;
+Record.getDescriptiveName = recordName;
+var RecordPrototype = Record.prototype;
+RecordPrototype[IS_RECORD_SYMBOL] = true;
+RecordPrototype[DELETE] = RecordPrototype.remove;
+RecordPrototype.deleteIn = RecordPrototype.removeIn = deleteIn;
+RecordPrototype.getIn = getIn;
+RecordPrototype.hasIn = CollectionPrototype.hasIn;
+RecordPrototype.merge = merge$1;
+RecordPrototype.mergeWith = mergeWith$1;
+RecordPrototype.mergeIn = mergeIn;
+RecordPrototype.mergeDeep = mergeDeep;
+RecordPrototype.mergeDeepWith = mergeDeepWith;
+RecordPrototype.mergeDeepIn = mergeDeepIn;
+RecordPrototype.setIn = setIn;
+RecordPrototype.update = update;
+RecordPrototype.updateIn = updateIn;
+RecordPrototype.withMutations = withMutations;
+RecordPrototype.asMutable = asMutable;
+RecordPrototype.asImmutable = asImmutable;
+RecordPrototype[ITERATOR_SYMBOL] = RecordPrototype.entries;
+RecordPrototype.toJSON = RecordPrototype.toObject =
+  CollectionPrototype.toObject;
+RecordPrototype.inspect = RecordPrototype.toSource = function () {
+  return this.toString();
+};
+
+function makeRecord(likeRecord, values, ownerID) {
+  var record = Object.create(Object.getPrototypeOf(likeRecord));
+  record._values = values;
+  record.__ownerID = ownerID;
+  return record;
+}
+
+function recordName(record) {
+  return record.constructor.displayName || record.constructor.name || 'Record';
+}
+
+function recordSeq(record) {
+  return keyedSeqFromValue(record._keys.map(function (k) { return [k, record.get(k)]; }));
+}
+
+function setProp(prototype, name) {
+  try {
+    Object.defineProperty(prototype, name, {
+      get: function () {
+        return this.get(name);
+      },
+      set: function (value) {
+        invariant(this.__ownerID, 'Cannot set on an immutable record.');
+        this.set(name, value);
+      },
+    });
+    // eslint-disable-next-line @typescript-eslint/no-unused-vars -- TODO enable eslint here
+  } catch (error) {
+    // Object.defineProperty failed. Probably IE8.
+  }
+}
+
+/**
+ * Returns a lazy Seq of `value` repeated `times` times. When `times` is
+ * undefined, returns an infinite sequence of `value`.
+ */
+var Repeat = /*@__PURE__*/(function (IndexedSeq) {
+  function Repeat(value, times) {
+    if (!(this instanceof Repeat)) {
+      // eslint-disable-next-line no-constructor-return
+      return new Repeat(value, times);
+    }
+    this._value = value;
+    this.size = times === undefined ? Infinity : Math.max(0, times);
+    if (this.size === 0) {
+      if (EMPTY_REPEAT) {
+        // eslint-disable-next-line no-constructor-return
+        return EMPTY_REPEAT;
+      }
+      // eslint-disable-next-line @typescript-eslint/no-this-alias
+      EMPTY_REPEAT = this;
+    }
+  }
+
+  if ( IndexedSeq ) Repeat.__proto__ = IndexedSeq;
+  Repeat.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
+  Repeat.prototype.constructor = Repeat;
+
+  Repeat.prototype.toString = function toString () {
+    if (this.size === 0) {
+      return 'Repeat []';
+    }
+    return 'Repeat [ ' + this._value + ' ' + this.size + ' times ]';
+  };
+
+  Repeat.prototype.get = function get (index, notSetValue) {
+    return this.has(index) ? this._value : notSetValue;
+  };
+
+  Repeat.prototype.includes = function includes (searchValue) {
+    return is(this._value, searchValue);
+  };
+
+  Repeat.prototype.slice = function slice (begin, end) {
+    var size = this.size;
+    return wholeSlice(begin, end, size)
+      ? this
+      : new Repeat(
+          this._value,
+          resolveEnd(end, size) - resolveBegin(begin, size)
+        );
+  };
+
+  Repeat.prototype.reverse = function reverse () {
+    return this;
+  };
+
+  Repeat.prototype.indexOf = function indexOf (searchValue) {
+    if (is(this._value, searchValue)) {
+      return 0;
+    }
+    return -1;
+  };
+
+  Repeat.prototype.lastIndexOf = function lastIndexOf (searchValue) {
+    if (is(this._value, searchValue)) {
+      return this.size;
+    }
+    return -1;
+  };
+
+  Repeat.prototype.__iterate = function __iterate (fn, reverse) {
+    var size = this.size;
+    var i = 0;
+    while (i !== size) {
+      if (fn(this._value, reverse ? size - ++i : i++, this) === false) {
+        break;
+      }
+    }
+    return i;
+  };
+
+  Repeat.prototype.__iterator = function __iterator (type, reverse) {
+    var this$1$1 = this;
+
+    var size = this.size;
+    var i = 0;
+    return new Iterator(function () { return i === size
+        ? iteratorDone()
+        : iteratorValue(type, reverse ? size - ++i : i++, this$1$1._value); }
+    );
+  };
+
+  Repeat.prototype.equals = function equals (other) {
+    return other instanceof Repeat
+      ? is(this._value, other._value)
+      : deepEqual(this, other);
+  };
+
+  return Repeat;
+}(IndexedSeq));
+
+var EMPTY_REPEAT;
+
+function fromJS(value, converter) {
+  return fromJSWith(
+    [],
+    converter || defaultConverter,
+    value,
+    '',
+    converter && converter.length > 2 ? [] : undefined,
+    { '': value }
+  );
+}
+
+function fromJSWith(stack, converter, value, key, keyPath, parentValue) {
+  if (
+    typeof value !== 'string' &&
+    !isImmutable(value) &&
+    (isArrayLike(value) || hasIterator(value) || isPlainObject(value))
+  ) {
+    if (~stack.indexOf(value)) {
+      throw new TypeError('Cannot convert circular structure to Immutable');
+    }
+    stack.push(value);
+    // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+    keyPath && key !== '' && keyPath.push(key);
+    var converted = converter.call(
+      parentValue,
+      key,
+      Seq(value).map(function (v, k) { return fromJSWith(stack, converter, v, k, keyPath, value); }
+      ),
+      keyPath && keyPath.slice()
+    );
+    stack.pop();
+    // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+    keyPath && keyPath.pop();
+    return converted;
+  }
+  return value;
+}
+
+function defaultConverter(k, v) {
+  // Effectively the opposite of "Collection.toSeq()"
+  return isIndexed(v) ? v.toList() : isKeyed(v) ? v.toMap() : v.toSet();
+}
+
+var version = "5.1.3";
+
+// Note: Iterable is deprecated
+var Iterable = Collection;
+
+export { Collection, Iterable, List, Map, OrderedMap, OrderedSet, PairSorting, Range, Record, Repeat, Seq, Set, Stack, fromJS, get, getIn$1 as getIn, has, hasIn$1 as hasIn, hash, is, isAssociative, isCollection, isImmutable, isIndexed, isKeyed, isList, isMap, isOrdered, isOrderedMap, isOrderedSet, isPlainObject, isRecord, isSeq, isSet, isStack, isValueObject, merge, mergeDeep$1 as mergeDeep, mergeDeepWith$1 as mergeDeepWith, mergeWith, remove, removeIn, set, setIn$1 as setIn, update$1 as update, updateIn$1 as updateIn, version };

+ 6236 - 0
node_modules/immutable/dist/immutable.js

@@ -0,0 +1,6236 @@
+/**
+ * @license
+ * MIT License
+ * 
+ * Copyright (c) 2014-present, Lee Byron and other contributors.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+(function (global, factory) {
+    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
+    typeof define === 'function' && define.amd ? define(['exports'], factory) :
+    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Immutable = {}));
+})(this, (function (exports) { 'use strict';
+
+    // Used for setting prototype methods that IE8 chokes on.
+    var DELETE = 'delete';
+    // Constants describing the size of trie nodes.
+    var SHIFT = 5; // Resulted in best performance after ______?
+    var SIZE = 1 << SHIFT;
+    var MASK = SIZE - 1;
+    // A consistent shared value representing "not set" which equals nothing other
+    // than itself, and nothing that could be provided externally.
+    var NOT_SET = {};
+    // Boolean references, Rough equivalent of `bool &`.
+    function MakeRef() {
+        return { value: false };
+    }
+    function SetRef(ref) {
+        if (ref) {
+            ref.value = true;
+        }
+    }
+    // A function which returns a value representing an "owner" for transient writes
+    // to tries. The return value will only ever equal itself, and will not equal
+    // the return of any subsequent call of this function.
+    function OwnerID() { }
+    function ensureSize(iter) {
+        // @ts-expect-error size should exists on Collection
+        if (iter.size === undefined) {
+            // @ts-expect-error size should exists on Collection, __iterate does exist on Collection
+            iter.size = iter.__iterate(returnTrue);
+        }
+        // @ts-expect-error size should exists on Collection
+        return iter.size;
+    }
+    function wrapIndex(iter, index) {
+        // This implements "is array index" which the ECMAString spec defines as:
+        //
+        //     A String property name P is an array index if and only if
+        //     ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal
+        //     to 2^32−1.
+        //
+        // http://www.ecma-international.org/ecma-262/6.0/#sec-array-exotic-objects
+        if (typeof index !== 'number') {
+            var uint32Index = index >>> 0; // N >>> 0 is shorthand for ToUint32
+            if ('' + uint32Index !== index || uint32Index === 4294967295) {
+                return NaN;
+            }
+            index = uint32Index;
+        }
+        return index < 0 ? ensureSize(iter) + index : index;
+    }
+    function returnTrue() {
+        return true;
+    }
+    function wholeSlice(begin, end, size) {
+        return (((begin === 0 && !isNeg(begin)) ||
+            (size !== undefined && begin <= -size)) &&
+            (end === undefined || (size !== undefined && end >= size)));
+    }
+    function resolveBegin(begin, size) {
+        return resolveIndex(begin, size, 0);
+    }
+    function resolveEnd(end, size) {
+        return resolveIndex(end, size, size);
+    }
+    function resolveIndex(index, size, defaultIndex) {
+        // Sanitize indices using this shorthand for ToInt32(argument)
+        // http://www.ecma-international.org/ecma-262/6.0/#sec-toint32
+        return index === undefined
+            ? defaultIndex
+            : isNeg(index)
+                ? size === Infinity
+                    ? size
+                    : Math.max(0, size + index) | 0
+                : size === undefined || size === index
+                    ? index
+                    : Math.min(size, index) | 0;
+    }
+    function isNeg(value) {
+        // Account for -0 which is negative, but not less than 0.
+        return value < 0 || (value === 0 && 1 / value === -Infinity);
+    }
+
+    // Note: value is unchanged to not break immutable-devtools.
+    var IS_COLLECTION_SYMBOL = '@@__IMMUTABLE_ITERABLE__@@';
+    /**
+     * True if `maybeCollection` is a Collection, or any of its subclasses.
+     *
+     * ```js
+     * import { isCollection, Map, List, Stack } from 'immutable';
+     *
+     * isCollection([]); // false
+     * isCollection({}); // false
+     * isCollection(Map()); // true
+     * isCollection(List()); // true
+     * isCollection(Stack()); // true
+     * ```
+     */
+    function isCollection(maybeCollection) {
+        return Boolean(maybeCollection &&
+            // @ts-expect-error: maybeCollection is typed as `{}`, need to change in 6.0 to `maybeCollection && typeof maybeCollection === 'object' && IS_COLLECTION_SYMBOL in maybeCollection`
+            maybeCollection[IS_COLLECTION_SYMBOL]);
+    }
+
+    var IS_KEYED_SYMBOL = '@@__IMMUTABLE_KEYED__@@';
+    /**
+     * True if `maybeKeyed` is a Collection.Keyed, or any of its subclasses.
+     *
+     * ```js
+     * import { isKeyed, Map, List, Stack } from 'immutable';
+     *
+     * isKeyed([]); // false
+     * isKeyed({}); // false
+     * isKeyed(Map()); // true
+     * isKeyed(List()); // false
+     * isKeyed(Stack()); // false
+     * ```
+     */
+    function isKeyed(maybeKeyed) {
+        return Boolean(maybeKeyed &&
+            // @ts-expect-error: maybeKeyed is typed as `{}`, need to change in 6.0 to `maybeKeyed && typeof maybeKeyed === 'object' && IS_KEYED_SYMBOL in maybeKeyed`
+            maybeKeyed[IS_KEYED_SYMBOL]);
+    }
+
+    var IS_INDEXED_SYMBOL = '@@__IMMUTABLE_INDEXED__@@';
+    /**
+     * True if `maybeIndexed` is a Collection.Indexed, or any of its subclasses.
+     *
+     * ```js
+     * import { isIndexed, Map, List, Stack, Set } from 'immutable';
+     *
+     * isIndexed([]); // false
+     * isIndexed({}); // false
+     * isIndexed(Map()); // false
+     * isIndexed(List()); // true
+     * isIndexed(Stack()); // true
+     * isIndexed(Set()); // false
+     * ```
+     */
+    function isIndexed(maybeIndexed) {
+        return Boolean(maybeIndexed &&
+            // @ts-expect-error: maybeIndexed is typed as `{}`, need to change in 6.0 to `maybeIndexed && typeof maybeIndexed === 'object' && IS_INDEXED_SYMBOL in maybeIndexed`
+            maybeIndexed[IS_INDEXED_SYMBOL]);
+    }
+
+    /**
+     * True if `maybeAssociative` is either a Keyed or Indexed Collection.
+     *
+     * ```js
+     * import { isAssociative, Map, List, Stack, Set } from 'immutable';
+     *
+     * isAssociative([]); // false
+     * isAssociative({}); // false
+     * isAssociative(Map()); // true
+     * isAssociative(List()); // true
+     * isAssociative(Stack()); // true
+     * isAssociative(Set()); // false
+     * ```
+     */
+    function isAssociative(maybeAssociative) {
+        return isKeyed(maybeAssociative) || isIndexed(maybeAssociative);
+    }
+
+    var Collection = function Collection(value) {
+      // eslint-disable-next-line no-constructor-return
+      return isCollection(value) ? value : Seq(value);
+    };
+
+    var KeyedCollection = /*@__PURE__*/(function (Collection) {
+      function KeyedCollection(value) {
+        // eslint-disable-next-line no-constructor-return
+        return isKeyed(value) ? value : KeyedSeq(value);
+      }
+
+      if ( Collection ) KeyedCollection.__proto__ = Collection;
+      KeyedCollection.prototype = Object.create( Collection && Collection.prototype );
+      KeyedCollection.prototype.constructor = KeyedCollection;
+
+      return KeyedCollection;
+    }(Collection));
+
+    var IndexedCollection = /*@__PURE__*/(function (Collection) {
+      function IndexedCollection(value) {
+        // eslint-disable-next-line no-constructor-return
+        return isIndexed(value) ? value : IndexedSeq(value);
+      }
+
+      if ( Collection ) IndexedCollection.__proto__ = Collection;
+      IndexedCollection.prototype = Object.create( Collection && Collection.prototype );
+      IndexedCollection.prototype.constructor = IndexedCollection;
+
+      return IndexedCollection;
+    }(Collection));
+
+    var SetCollection = /*@__PURE__*/(function (Collection) {
+      function SetCollection(value) {
+        // eslint-disable-next-line no-constructor-return
+        return isCollection(value) && !isAssociative(value) ? value : SetSeq(value);
+      }
+
+      if ( Collection ) SetCollection.__proto__ = Collection;
+      SetCollection.prototype = Object.create( Collection && Collection.prototype );
+      SetCollection.prototype.constructor = SetCollection;
+
+      return SetCollection;
+    }(Collection));
+
+    Collection.Keyed = KeyedCollection;
+    Collection.Indexed = IndexedCollection;
+    Collection.Set = SetCollection;
+
+    var IS_SEQ_SYMBOL = '@@__IMMUTABLE_SEQ__@@';
+    /**
+     * True if `maybeSeq` is a Seq.
+     */
+    function isSeq(maybeSeq) {
+        return Boolean(maybeSeq &&
+            // @ts-expect-error: maybeSeq is typed as `{}`, need to change in 6.0 to `maybeSeq && typeof maybeSeq === 'object' && MAYBE_SEQ_SYMBOL in maybeSeq`
+            maybeSeq[IS_SEQ_SYMBOL]);
+    }
+
+    var IS_RECORD_SYMBOL = '@@__IMMUTABLE_RECORD__@@';
+    /**
+     * True if `maybeRecord` is a Record.
+     */
+    function isRecord(maybeRecord) {
+        return Boolean(maybeRecord &&
+            // @ts-expect-error: maybeRecord is typed as `{}`, need to change in 6.0 to `maybeRecord && typeof maybeRecord === 'object' && IS_RECORD_SYMBOL in maybeRecord`
+            maybeRecord[IS_RECORD_SYMBOL]);
+    }
+
+    /**
+     * True if `maybeImmutable` is an Immutable Collection or Record.
+     *
+     * Note: Still returns true even if the collections is within a `withMutations()`.
+     *
+     * ```js
+     * import { isImmutable, Map, List, Stack } from 'immutable';
+     * isImmutable([]); // false
+     * isImmutable({}); // false
+     * isImmutable(Map()); // true
+     * isImmutable(List()); // true
+     * isImmutable(Stack()); // true
+     * isImmutable(Map().asMutable()); // true
+     * ```
+     */
+    function isImmutable(maybeImmutable) {
+        return isCollection(maybeImmutable) || isRecord(maybeImmutable);
+    }
+
+    var IS_ORDERED_SYMBOL = '@@__IMMUTABLE_ORDERED__@@';
+    function isOrdered(maybeOrdered) {
+        return Boolean(maybeOrdered &&
+            // @ts-expect-error: maybeOrdered is typed as `{}`, need to change in 6.0 to `maybeOrdered && typeof maybeOrdered === 'object' && IS_ORDERED_SYMBOL in maybeOrdered`
+            maybeOrdered[IS_ORDERED_SYMBOL]);
+    }
+
+    var ITERATE_KEYS = 0;
+    var ITERATE_VALUES = 1;
+    var ITERATE_ENTRIES = 2;
+
+    var REAL_ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
+    var FAUX_ITERATOR_SYMBOL = '@@iterator';
+
+    var ITERATOR_SYMBOL = REAL_ITERATOR_SYMBOL || FAUX_ITERATOR_SYMBOL;
+
+    var Iterator = function Iterator(next) {
+      this.next = next;
+    };
+
+    Iterator.prototype.toString = function toString () {
+      return '[Iterator]';
+    };
+
+    Iterator.KEYS = ITERATE_KEYS;
+    Iterator.VALUES = ITERATE_VALUES;
+    Iterator.ENTRIES = ITERATE_ENTRIES;
+
+    Iterator.prototype.inspect = Iterator.prototype.toSource = function () {
+      return this.toString();
+    };
+    Iterator.prototype[ITERATOR_SYMBOL] = function () {
+      return this;
+    };
+
+    function iteratorValue(type, k, v, iteratorResult) {
+      var value =
+        type === ITERATE_KEYS ? k : type === ITERATE_VALUES ? v : [k, v];
+      // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+      iteratorResult
+        ? (iteratorResult.value = value)
+        : (iteratorResult = {
+            value: value,
+            done: false,
+          });
+      return iteratorResult;
+    }
+
+    function iteratorDone() {
+      return { value: undefined, done: true };
+    }
+
+    function hasIterator(maybeIterable) {
+      if (Array.isArray(maybeIterable)) {
+        // IE11 trick as it does not support `Symbol.iterator`
+        return true;
+      }
+
+      return !!getIteratorFn(maybeIterable);
+    }
+
+    function isIterator(maybeIterator) {
+      return maybeIterator && typeof maybeIterator.next === 'function';
+    }
+
+    function getIterator(iterable) {
+      var iteratorFn = getIteratorFn(iterable);
+      return iteratorFn && iteratorFn.call(iterable);
+    }
+
+    function getIteratorFn(iterable) {
+      var iteratorFn =
+        iterable &&
+        ((REAL_ITERATOR_SYMBOL && iterable[REAL_ITERATOR_SYMBOL]) ||
+          iterable[FAUX_ITERATOR_SYMBOL]);
+      if (typeof iteratorFn === 'function') {
+        return iteratorFn;
+      }
+    }
+
+    function isEntriesIterable(maybeIterable) {
+      var iteratorFn = getIteratorFn(maybeIterable);
+      return iteratorFn && iteratorFn === maybeIterable.entries;
+    }
+
+    function isKeysIterable(maybeIterable) {
+      var iteratorFn = getIteratorFn(maybeIterable);
+      return iteratorFn && iteratorFn === maybeIterable.keys;
+    }
+
+    var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+    function isArrayLike(value) {
+        if (Array.isArray(value) || typeof value === 'string') {
+            return true;
+        }
+        // @ts-expect-error "Type 'unknown' is not assignable to type 'boolean'" : convert to Boolean
+        return (value &&
+            typeof value === 'object' &&
+            // @ts-expect-error check that `'length' in value &&`
+            Number.isInteger(value.length) &&
+            // @ts-expect-error check that `'length' in value &&`
+            value.length >= 0 &&
+            // @ts-expect-error check that `'length' in value &&`
+            (value.length === 0
+                ? // Only {length: 0} is considered Array-like.
+                    Object.keys(value).length === 1
+                : // An object is only Array-like if it has a property where the last value
+                    // in the array-like may be found (which could be undefined).
+                    // @ts-expect-error check that `'length' in value &&`
+                    value.hasOwnProperty(value.length - 1)));
+    }
+
+    var Seq = /*@__PURE__*/(function (Collection) {
+      function Seq(value) {
+        // eslint-disable-next-line no-constructor-return
+        return value === undefined || value === null
+          ? emptySequence()
+          : isImmutable(value)
+            ? value.toSeq()
+            : seqFromValue(value);
+      }
+
+      if ( Collection ) Seq.__proto__ = Collection;
+      Seq.prototype = Object.create( Collection && Collection.prototype );
+      Seq.prototype.constructor = Seq;
+
+      Seq.prototype.toSeq = function toSeq () {
+        return this;
+      };
+
+      Seq.prototype.toString = function toString () {
+        return this.__toString('Seq {', '}');
+      };
+
+      Seq.prototype.cacheResult = function cacheResult () {
+        if (!this._cache && this.__iterateUncached) {
+          this._cache = this.entrySeq().toArray();
+          this.size = this._cache.length;
+        }
+        return this;
+      };
+
+      // abstract __iterateUncached(fn, reverse)
+
+      Seq.prototype.__iterate = function __iterate (fn, reverse) {
+        var cache = this._cache;
+        if (cache) {
+          var size = cache.length;
+          var i = 0;
+          while (i !== size) {
+            var entry = cache[reverse ? size - ++i : i++];
+            if (fn(entry[1], entry[0], this) === false) {
+              break;
+            }
+          }
+          return i;
+        }
+        return this.__iterateUncached(fn, reverse);
+      };
+
+      // abstract __iteratorUncached(type, reverse)
+
+      Seq.prototype.__iterator = function __iterator (type, reverse) {
+        var cache = this._cache;
+        if (cache) {
+          var size = cache.length;
+          var i = 0;
+          return new Iterator(function () {
+            if (i === size) {
+              return iteratorDone();
+            }
+            var entry = cache[reverse ? size - ++i : i++];
+            return iteratorValue(type, entry[0], entry[1]);
+          });
+        }
+        return this.__iteratorUncached(type, reverse);
+      };
+
+      return Seq;
+    }(Collection));
+
+    var KeyedSeq = /*@__PURE__*/(function (Seq) {
+      function KeyedSeq(value) {
+        // eslint-disable-next-line no-constructor-return
+        return value === undefined || value === null
+          ? emptySequence().toKeyedSeq()
+          : isCollection(value)
+            ? isKeyed(value)
+              ? value.toSeq()
+              : value.fromEntrySeq()
+            : isRecord(value)
+              ? value.toSeq()
+              : keyedSeqFromValue(value);
+      }
+
+      if ( Seq ) KeyedSeq.__proto__ = Seq;
+      KeyedSeq.prototype = Object.create( Seq && Seq.prototype );
+      KeyedSeq.prototype.constructor = KeyedSeq;
+
+      KeyedSeq.prototype.toKeyedSeq = function toKeyedSeq () {
+        return this;
+      };
+
+      return KeyedSeq;
+    }(Seq));
+
+    var IndexedSeq = /*@__PURE__*/(function (Seq) {
+      function IndexedSeq(value) {
+        // eslint-disable-next-line no-constructor-return
+        return value === undefined || value === null
+          ? emptySequence()
+          : isCollection(value)
+            ? isKeyed(value)
+              ? value.entrySeq()
+              : value.toIndexedSeq()
+            : isRecord(value)
+              ? value.toSeq().entrySeq()
+              : indexedSeqFromValue(value);
+      }
+
+      if ( Seq ) IndexedSeq.__proto__ = Seq;
+      IndexedSeq.prototype = Object.create( Seq && Seq.prototype );
+      IndexedSeq.prototype.constructor = IndexedSeq;
+
+      IndexedSeq.of = function of (/*...values*/) {
+        return IndexedSeq(arguments);
+      };
+
+      IndexedSeq.prototype.toIndexedSeq = function toIndexedSeq () {
+        return this;
+      };
+
+      IndexedSeq.prototype.toString = function toString () {
+        return this.__toString('Seq [', ']');
+      };
+
+      return IndexedSeq;
+    }(Seq));
+
+    var SetSeq = /*@__PURE__*/(function (Seq) {
+      function SetSeq(value) {
+        // eslint-disable-next-line no-constructor-return
+        return (
+          isCollection(value) && !isAssociative(value) ? value : IndexedSeq(value)
+        ).toSetSeq();
+      }
+
+      if ( Seq ) SetSeq.__proto__ = Seq;
+      SetSeq.prototype = Object.create( Seq && Seq.prototype );
+      SetSeq.prototype.constructor = SetSeq;
+
+      SetSeq.of = function of (/*...values*/) {
+        return SetSeq(arguments);
+      };
+
+      SetSeq.prototype.toSetSeq = function toSetSeq () {
+        return this;
+      };
+
+      return SetSeq;
+    }(Seq));
+
+    Seq.isSeq = isSeq;
+    Seq.Keyed = KeyedSeq;
+    Seq.Set = SetSeq;
+    Seq.Indexed = IndexedSeq;
+
+    Seq.prototype[IS_SEQ_SYMBOL] = true;
+
+    // #pragma Root Sequences
+
+    var ArraySeq = /*@__PURE__*/(function (IndexedSeq) {
+      function ArraySeq(array) {
+        this._array = array;
+        this.size = array.length;
+      }
+
+      if ( IndexedSeq ) ArraySeq.__proto__ = IndexedSeq;
+      ArraySeq.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
+      ArraySeq.prototype.constructor = ArraySeq;
+
+      ArraySeq.prototype.get = function get (index, notSetValue) {
+        return this.has(index) ? this._array[wrapIndex(this, index)] : notSetValue;
+      };
+
+      ArraySeq.prototype.__iterate = function __iterate (fn, reverse) {
+        var array = this._array;
+        var size = array.length;
+        var i = 0;
+        while (i !== size) {
+          var ii = reverse ? size - ++i : i++;
+          if (fn(array[ii], ii, this) === false) {
+            break;
+          }
+        }
+        return i;
+      };
+
+      ArraySeq.prototype.__iterator = function __iterator (type, reverse) {
+        var array = this._array;
+        var size = array.length;
+        var i = 0;
+        return new Iterator(function () {
+          if (i === size) {
+            return iteratorDone();
+          }
+          var ii = reverse ? size - ++i : i++;
+          return iteratorValue(type, ii, array[ii]);
+        });
+      };
+
+      return ArraySeq;
+    }(IndexedSeq));
+
+    var ObjectSeq = /*@__PURE__*/(function (KeyedSeq) {
+      function ObjectSeq(object) {
+        var keys = Object.keys(object).concat(
+          Object.getOwnPropertySymbols ? Object.getOwnPropertySymbols(object) : []
+        );
+        this._object = object;
+        this._keys = keys;
+        this.size = keys.length;
+      }
+
+      if ( KeyedSeq ) ObjectSeq.__proto__ = KeyedSeq;
+      ObjectSeq.prototype = Object.create( KeyedSeq && KeyedSeq.prototype );
+      ObjectSeq.prototype.constructor = ObjectSeq;
+
+      ObjectSeq.prototype.get = function get (key, notSetValue) {
+        if (notSetValue !== undefined && !this.has(key)) {
+          return notSetValue;
+        }
+        return this._object[key];
+      };
+
+      ObjectSeq.prototype.has = function has (key) {
+        return hasOwnProperty.call(this._object, key);
+      };
+
+      ObjectSeq.prototype.__iterate = function __iterate (fn, reverse) {
+        var object = this._object;
+        var keys = this._keys;
+        var size = keys.length;
+        var i = 0;
+        while (i !== size) {
+          var key = keys[reverse ? size - ++i : i++];
+          if (fn(object[key], key, this) === false) {
+            break;
+          }
+        }
+        return i;
+      };
+
+      ObjectSeq.prototype.__iterator = function __iterator (type, reverse) {
+        var object = this._object;
+        var keys = this._keys;
+        var size = keys.length;
+        var i = 0;
+        return new Iterator(function () {
+          if (i === size) {
+            return iteratorDone();
+          }
+          var key = keys[reverse ? size - ++i : i++];
+          return iteratorValue(type, key, object[key]);
+        });
+      };
+
+      return ObjectSeq;
+    }(KeyedSeq));
+    ObjectSeq.prototype[IS_ORDERED_SYMBOL] = true;
+
+    var CollectionSeq = /*@__PURE__*/(function (IndexedSeq) {
+      function CollectionSeq(collection) {
+        this._collection = collection;
+        this.size = collection.length || collection.size;
+      }
+
+      if ( IndexedSeq ) CollectionSeq.__proto__ = IndexedSeq;
+      CollectionSeq.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
+      CollectionSeq.prototype.constructor = CollectionSeq;
+
+      CollectionSeq.prototype.__iterateUncached = function __iterateUncached (fn, reverse) {
+        if (reverse) {
+          return this.cacheResult().__iterate(fn, reverse);
+        }
+        var collection = this._collection;
+        var iterator = getIterator(collection);
+        var iterations = 0;
+        if (isIterator(iterator)) {
+          var step;
+          while (!(step = iterator.next()).done) {
+            if (fn(step.value, iterations++, this) === false) {
+              break;
+            }
+          }
+        }
+        return iterations;
+      };
+
+      CollectionSeq.prototype.__iteratorUncached = function __iteratorUncached (type, reverse) {
+        if (reverse) {
+          return this.cacheResult().__iterator(type, reverse);
+        }
+        var collection = this._collection;
+        var iterator = getIterator(collection);
+        if (!isIterator(iterator)) {
+          return new Iterator(iteratorDone);
+        }
+        var iterations = 0;
+        return new Iterator(function () {
+          var step = iterator.next();
+          return step.done ? step : iteratorValue(type, iterations++, step.value);
+        });
+      };
+
+      return CollectionSeq;
+    }(IndexedSeq));
+
+    // # pragma Helper functions
+
+    var EMPTY_SEQ;
+
+    function emptySequence() {
+      return EMPTY_SEQ || (EMPTY_SEQ = new ArraySeq([]));
+    }
+
+    function keyedSeqFromValue(value) {
+      var seq = maybeIndexedSeqFromValue(value);
+      if (seq) {
+        return seq.fromEntrySeq();
+      }
+      if (typeof value === 'object') {
+        return new ObjectSeq(value);
+      }
+      throw new TypeError(
+        'Expected Array or collection object of [k, v] entries, or keyed object: ' +
+          value
+      );
+    }
+
+    function indexedSeqFromValue(value) {
+      var seq = maybeIndexedSeqFromValue(value);
+      if (seq) {
+        return seq;
+      }
+      throw new TypeError(
+        'Expected Array or collection object of values: ' + value
+      );
+    }
+
+    function seqFromValue(value) {
+      var seq = maybeIndexedSeqFromValue(value);
+      if (seq) {
+        return isEntriesIterable(value)
+          ? seq.fromEntrySeq()
+          : isKeysIterable(value)
+            ? seq.toSetSeq()
+            : seq;
+      }
+      if (typeof value === 'object') {
+        return new ObjectSeq(value);
+      }
+      throw new TypeError(
+        'Expected Array or collection object of values, or keyed object: ' + value
+      );
+    }
+
+    function maybeIndexedSeqFromValue(value) {
+      return isArrayLike(value)
+        ? new ArraySeq(value)
+        : hasIterator(value)
+          ? new CollectionSeq(value)
+          : undefined;
+    }
+
+    var IS_MAP_SYMBOL = '@@__IMMUTABLE_MAP__@@';
+    /**
+     * True if `maybeMap` is a Map.
+     *
+     * Also true for OrderedMaps.
+     */
+    function isMap(maybeMap) {
+        return Boolean(maybeMap &&
+            // @ts-expect-error: maybeMap is typed as `{}`, need to change in 6.0 to `maybeMap && typeof maybeMap === 'object' && IS_MAP_SYMBOL in maybeMap`
+            maybeMap[IS_MAP_SYMBOL]);
+    }
+
+    /**
+     * True if `maybeOrderedMap` is an OrderedMap.
+     */
+    function isOrderedMap(maybeOrderedMap) {
+        return isMap(maybeOrderedMap) && isOrdered(maybeOrderedMap);
+    }
+
+    /**
+     * True if `maybeValue` is a JavaScript Object which has *both* `equals()`
+     * and `hashCode()` methods.
+     *
+     * Any two instances of *value objects* can be compared for value equality with
+     * `Immutable.is()` and can be used as keys in a `Map` or members in a `Set`.
+     */
+    function isValueObject(maybeValue) {
+        return Boolean(maybeValue &&
+            // @ts-expect-error: maybeValue is typed as `{}`
+            typeof maybeValue.equals === 'function' &&
+            // @ts-expect-error: maybeValue is typed as `{}`
+            typeof maybeValue.hashCode === 'function');
+    }
+
+    /**
+     * An extension of the "same-value" algorithm as [described for use by ES6 Map
+     * and Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#Key_equality)
+     *
+     * NaN is considered the same as NaN, however -0 and 0 are considered the same
+     * value, which is different from the algorithm described by
+     * [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is).
+     *
+     * This is extended further to allow Objects to describe the values they
+     * represent, by way of `valueOf` or `equals` (and `hashCode`).
+     *
+     * Note: because of this extension, the key equality of Immutable.Map and the
+     * value equality of Immutable.Set will differ from ES6 Map and Set.
+     *
+     * ### Defining custom values
+     *
+     * The easiest way to describe the value an object represents is by implementing
+     * `valueOf`. For example, `Date` represents a value by returning a unix
+     * timestamp for `valueOf`:
+     *
+     *     var date1 = new Date(1234567890000); // Fri Feb 13 2009 ...
+     *     var date2 = new Date(1234567890000);
+     *     date1.valueOf(); // 1234567890000
+     *     assert( date1 !== date2 );
+     *     assert( Immutable.is( date1, date2 ) );
+     *
+     * Note: overriding `valueOf` may have other implications if you use this object
+     * where JavaScript expects a primitive, such as implicit string coercion.
+     *
+     * For more complex types, especially collections, implementing `valueOf` may
+     * not be performant. An alternative is to implement `equals` and `hashCode`.
+     *
+     * `equals` takes another object, presumably of similar type, and returns true
+     * if it is equal. Equality is symmetrical, so the same result should be
+     * returned if this and the argument are flipped.
+     *
+     *     assert( a.equals(b) === b.equals(a) );
+     *
+     * `hashCode` returns a 32bit integer number representing the object which will
+     * be used to determine how to store the value object in a Map or Set. You must
+     * provide both or neither methods, one must not exist without the other.
+     *
+     * Also, an important relationship between these methods must be upheld: if two
+     * values are equal, they *must* return the same hashCode. If the values are not
+     * equal, they might have the same hashCode; this is called a hash collision,
+     * and while undesirable for performance reasons, it is acceptable.
+     *
+     *     if (a.equals(b)) {
+     *       assert( a.hashCode() === b.hashCode() );
+     *     }
+     *
+     * All Immutable collections are Value Objects: they implement `equals()`
+     * and `hashCode()`.
+     */
+    function is(valueA, valueB) {
+        if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) {
+            return true;
+        }
+        if (!valueA || !valueB) {
+            return false;
+        }
+        if (typeof valueA.valueOf === 'function' &&
+            typeof valueB.valueOf === 'function') {
+            valueA = valueA.valueOf();
+            valueB = valueB.valueOf();
+            if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) {
+                return true;
+            }
+            if (!valueA || !valueB) {
+                return false;
+            }
+        }
+        return !!(isValueObject(valueA) &&
+            isValueObject(valueB) &&
+            valueA.equals(valueB));
+    }
+
+    var imul =
+      typeof Math.imul === 'function' && Math.imul(0xffffffff, 2) === -2
+        ? Math.imul
+        : function imul(a, b) {
+            a |= 0; // int
+            b |= 0; // int
+            var c = a & 0xffff;
+            var d = b & 0xffff;
+            // Shift by 0 fixes the sign on the high part.
+            return (c * d + ((((a >>> 16) * d + c * (b >>> 16)) << 16) >>> 0)) | 0; // int
+          };
+
+    // v8 has an optimization for storing 31-bit signed numbers.
+    // Values which have either 00 or 11 as the high order bits qualify.
+    // This function drops the highest order bit in a signed number, maintaining
+    // the sign bit.
+    function smi(i32) {
+      return ((i32 >>> 1) & 0x40000000) | (i32 & 0xbfffffff);
+    }
+
+    var defaultValueOf = Object.prototype.valueOf;
+
+    function hash(o) {
+      // eslint-disable-next-line eqeqeq
+      if (o == null) {
+        return hashNullish(o);
+      }
+
+      if (typeof o.hashCode === 'function') {
+        // Drop any high bits from accidentally long hash codes.
+        return smi(o.hashCode(o));
+      }
+
+      var v = valueOf(o);
+
+      // eslint-disable-next-line eqeqeq
+      if (v == null) {
+        return hashNullish(v);
+      }
+
+      switch (typeof v) {
+        case 'boolean':
+          // The hash values for built-in constants are a 1 value for each 5-byte
+          // shift region expect for the first, which encodes the value. This
+          // reduces the odds of a hash collision for these common values.
+          return v ? 0x42108421 : 0x42108420;
+        case 'number':
+          return hashNumber(v);
+        case 'string':
+          return v.length > STRING_HASH_CACHE_MIN_STRLEN
+            ? cachedHashString(v)
+            : hashString(v);
+        case 'object':
+        case 'function':
+          return hashJSObj(v);
+        case 'symbol':
+          return hashSymbol(v);
+        default:
+          if (typeof v.toString === 'function') {
+            return hashString(v.toString());
+          }
+          throw new Error('Value type ' + typeof v + ' cannot be hashed.');
+      }
+    }
+
+    function hashNullish(nullish) {
+      return nullish === null ? 0x42108422 : /* undefined */ 0x42108423;
+    }
+
+    // Compress arbitrarily large numbers into smi hashes.
+    function hashNumber(n) {
+      if (n !== n || n === Infinity) {
+        return 0;
+      }
+      var hash = n | 0;
+      if (hash !== n) {
+        hash ^= n * 0xffffffff;
+      }
+      while (n > 0xffffffff) {
+        n /= 0xffffffff;
+        hash ^= n;
+      }
+      return smi(hash);
+    }
+
+    function cachedHashString(string) {
+      var hashed = stringHashCache[string];
+      if (hashed === undefined) {
+        hashed = hashString(string);
+        if (STRING_HASH_CACHE_SIZE === STRING_HASH_CACHE_MAX_SIZE) {
+          STRING_HASH_CACHE_SIZE = 0;
+          stringHashCache = {};
+        }
+        STRING_HASH_CACHE_SIZE++;
+        stringHashCache[string] = hashed;
+      }
+      return hashed;
+    }
+
+    // http://jsperf.com/hashing-strings
+    function hashString(string) {
+      // This is the hash from JVM
+      // The hash code for a string is computed as
+      // s[0] * 31 ^ (n - 1) + s[1] * 31 ^ (n - 2) + ... + s[n - 1],
+      // where s[i] is the ith character of the string and n is the length of
+      // the string. We "mod" the result to make it between 0 (inclusive) and 2^31
+      // (exclusive) by dropping high bits.
+      var hashed = 0;
+      for (var ii = 0; ii < string.length; ii++) {
+        hashed = (31 * hashed + string.charCodeAt(ii)) | 0;
+      }
+      return smi(hashed);
+    }
+
+    function hashSymbol(sym) {
+      var hashed = symbolMap[sym];
+      if (hashed !== undefined) {
+        return hashed;
+      }
+
+      hashed = nextHash();
+
+      symbolMap[sym] = hashed;
+
+      return hashed;
+    }
+
+    function hashJSObj(obj) {
+      var hashed;
+      if (usingWeakMap) {
+        hashed = weakMap.get(obj);
+        if (hashed !== undefined) {
+          return hashed;
+        }
+      }
+
+      hashed = obj[UID_HASH_KEY];
+      if (hashed !== undefined) {
+        return hashed;
+      }
+
+      if (!canDefineProperty) {
+        hashed = obj.propertyIsEnumerable && obj.propertyIsEnumerable[UID_HASH_KEY];
+        if (hashed !== undefined) {
+          return hashed;
+        }
+
+        hashed = getIENodeHash(obj);
+        if (hashed !== undefined) {
+          return hashed;
+        }
+      }
+
+      hashed = nextHash();
+
+      if (usingWeakMap) {
+        weakMap.set(obj, hashed);
+      } else if (isExtensible !== undefined && isExtensible(obj) === false) {
+        throw new Error('Non-extensible objects are not allowed as keys.');
+      } else if (canDefineProperty) {
+        Object.defineProperty(obj, UID_HASH_KEY, {
+          enumerable: false,
+          configurable: false,
+          writable: false,
+          value: hashed,
+        });
+      } else if (
+        obj.propertyIsEnumerable !== undefined &&
+        obj.propertyIsEnumerable === obj.constructor.prototype.propertyIsEnumerable
+      ) {
+        // Since we can't define a non-enumerable property on the object
+        // we'll hijack one of the less-used non-enumerable properties to
+        // save our hash on it. Since this is a function it will not show up in
+        // `JSON.stringify` which is what we want.
+        obj.propertyIsEnumerable = function () {
+          return this.constructor.prototype.propertyIsEnumerable.apply(
+            this,
+            arguments
+          );
+        };
+        obj.propertyIsEnumerable[UID_HASH_KEY] = hashed;
+      } else if (obj.nodeType !== undefined) {
+        // At this point we couldn't get the IE `uniqueID` to use as a hash
+        // and we couldn't use a non-enumerable property to exploit the
+        // dontEnum bug so we simply add the `UID_HASH_KEY` on the node
+        // itself.
+        obj[UID_HASH_KEY] = hashed;
+      } else {
+        throw new Error('Unable to set a non-enumerable property on object.');
+      }
+
+      return hashed;
+    }
+
+    // Get references to ES5 object methods.
+    var isExtensible = Object.isExtensible;
+
+    // True if Object.defineProperty works as expected. IE8 fails this test.
+    var canDefineProperty = (function () {
+      try {
+        Object.defineProperty({}, '@', {});
+        return true;
+        // eslint-disable-next-line @typescript-eslint/no-unused-vars
+      } catch (e) {
+        return false;
+      }
+    })();
+
+    // IE has a `uniqueID` property on DOM nodes. We can construct the hash from it
+    // and avoid memory leaks from the IE cloneNode bug.
+    function getIENodeHash(node) {
+      if (node && node.nodeType > 0) {
+        switch (node.nodeType) {
+          case 1: // Element
+            return node.uniqueID;
+          case 9: // Document
+            return node.documentElement && node.documentElement.uniqueID;
+        }
+      }
+    }
+
+    function valueOf(obj) {
+      return obj.valueOf !== defaultValueOf && typeof obj.valueOf === 'function'
+        ? obj.valueOf(obj)
+        : obj;
+    }
+
+    function nextHash() {
+      var nextHash = ++_objHashUID;
+      if (_objHashUID & 0x40000000) {
+        _objHashUID = 0;
+      }
+      return nextHash;
+    }
+
+    // If possible, use a WeakMap.
+    var usingWeakMap = typeof WeakMap === 'function';
+    var weakMap;
+    if (usingWeakMap) {
+      weakMap = new WeakMap();
+    }
+
+    var symbolMap = Object.create(null);
+
+    var _objHashUID = 0;
+
+    var UID_HASH_KEY = '__immutablehash__';
+    if (typeof Symbol === 'function') {
+      UID_HASH_KEY = Symbol(UID_HASH_KEY);
+    }
+
+    var STRING_HASH_CACHE_MIN_STRLEN = 16;
+    var STRING_HASH_CACHE_MAX_SIZE = 255;
+    var STRING_HASH_CACHE_SIZE = 0;
+    var stringHashCache = {};
+
+    var ToKeyedSequence = /*@__PURE__*/(function (KeyedSeq) {
+      function ToKeyedSequence(indexed, useKeys) {
+        this._iter = indexed;
+        this._useKeys = useKeys;
+        this.size = indexed.size;
+      }
+
+      if ( KeyedSeq ) ToKeyedSequence.__proto__ = KeyedSeq;
+      ToKeyedSequence.prototype = Object.create( KeyedSeq && KeyedSeq.prototype );
+      ToKeyedSequence.prototype.constructor = ToKeyedSequence;
+
+      ToKeyedSequence.prototype.get = function get (key, notSetValue) {
+        return this._iter.get(key, notSetValue);
+      };
+
+      ToKeyedSequence.prototype.has = function has (key) {
+        return this._iter.has(key);
+      };
+
+      ToKeyedSequence.prototype.valueSeq = function valueSeq () {
+        return this._iter.valueSeq();
+      };
+
+      ToKeyedSequence.prototype.reverse = function reverse () {
+        var this$1$1 = this;
+
+        var reversedSequence = reverseFactory(this, true);
+        if (!this._useKeys) {
+          reversedSequence.valueSeq = function () { return this$1$1._iter.toSeq().reverse(); };
+        }
+        return reversedSequence;
+      };
+
+      ToKeyedSequence.prototype.map = function map (mapper, context) {
+        var this$1$1 = this;
+
+        var mappedSequence = mapFactory(this, mapper, context);
+        if (!this._useKeys) {
+          mappedSequence.valueSeq = function () { return this$1$1._iter.toSeq().map(mapper, context); };
+        }
+        return mappedSequence;
+      };
+
+      ToKeyedSequence.prototype.__iterate = function __iterate (fn, reverse) {
+        var this$1$1 = this;
+
+        return this._iter.__iterate(function (v, k) { return fn(v, k, this$1$1); }, reverse);
+      };
+
+      ToKeyedSequence.prototype.__iterator = function __iterator (type, reverse) {
+        return this._iter.__iterator(type, reverse);
+      };
+
+      return ToKeyedSequence;
+    }(KeyedSeq));
+    ToKeyedSequence.prototype[IS_ORDERED_SYMBOL] = true;
+
+    var ToIndexedSequence = /*@__PURE__*/(function (IndexedSeq) {
+      function ToIndexedSequence(iter) {
+        this._iter = iter;
+        this.size = iter.size;
+      }
+
+      if ( IndexedSeq ) ToIndexedSequence.__proto__ = IndexedSeq;
+      ToIndexedSequence.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
+      ToIndexedSequence.prototype.constructor = ToIndexedSequence;
+
+      ToIndexedSequence.prototype.includes = function includes (value) {
+        return this._iter.includes(value);
+      };
+
+      ToIndexedSequence.prototype.__iterate = function __iterate (fn, reverse) {
+        var this$1$1 = this;
+
+        var i = 0;
+        // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+        reverse && ensureSize(this);
+        return this._iter.__iterate(
+          function (v) { return fn(v, reverse ? this$1$1.size - ++i : i++, this$1$1); },
+          reverse
+        );
+      };
+
+      ToIndexedSequence.prototype.__iterator = function __iterator (type, reverse) {
+        var this$1$1 = this;
+
+        var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);
+        var i = 0;
+        // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+        reverse && ensureSize(this);
+        return new Iterator(function () {
+          var step = iterator.next();
+          return step.done
+            ? step
+            : iteratorValue(
+                type,
+                reverse ? this$1$1.size - ++i : i++,
+                step.value,
+                step
+              );
+        });
+      };
+
+      return ToIndexedSequence;
+    }(IndexedSeq));
+
+    var ToSetSequence = /*@__PURE__*/(function (SetSeq) {
+      function ToSetSequence(iter) {
+        this._iter = iter;
+        this.size = iter.size;
+      }
+
+      if ( SetSeq ) ToSetSequence.__proto__ = SetSeq;
+      ToSetSequence.prototype = Object.create( SetSeq && SetSeq.prototype );
+      ToSetSequence.prototype.constructor = ToSetSequence;
+
+      ToSetSequence.prototype.has = function has (key) {
+        return this._iter.includes(key);
+      };
+
+      ToSetSequence.prototype.__iterate = function __iterate (fn, reverse) {
+        var this$1$1 = this;
+
+        return this._iter.__iterate(function (v) { return fn(v, v, this$1$1); }, reverse);
+      };
+
+      ToSetSequence.prototype.__iterator = function __iterator (type, reverse) {
+        var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);
+        return new Iterator(function () {
+          var step = iterator.next();
+          return step.done
+            ? step
+            : iteratorValue(type, step.value, step.value, step);
+        });
+      };
+
+      return ToSetSequence;
+    }(SetSeq));
+
+    var FromEntriesSequence = /*@__PURE__*/(function (KeyedSeq) {
+      function FromEntriesSequence(entries) {
+        this._iter = entries;
+        this.size = entries.size;
+      }
+
+      if ( KeyedSeq ) FromEntriesSequence.__proto__ = KeyedSeq;
+      FromEntriesSequence.prototype = Object.create( KeyedSeq && KeyedSeq.prototype );
+      FromEntriesSequence.prototype.constructor = FromEntriesSequence;
+
+      FromEntriesSequence.prototype.entrySeq = function entrySeq () {
+        return this._iter.toSeq();
+      };
+
+      FromEntriesSequence.prototype.__iterate = function __iterate (fn, reverse) {
+        var this$1$1 = this;
+
+        return this._iter.__iterate(function (entry) {
+          // Check if entry exists first so array access doesn't throw for holes
+          // in the parent iteration.
+          if (entry) {
+            validateEntry(entry);
+            var indexedCollection = isCollection(entry);
+            return fn(
+              indexedCollection ? entry.get(1) : entry[1],
+              indexedCollection ? entry.get(0) : entry[0],
+              this$1$1
+            );
+          }
+        }, reverse);
+      };
+
+      FromEntriesSequence.prototype.__iterator = function __iterator (type, reverse) {
+        var iterator = this._iter.__iterator(ITERATE_VALUES, reverse);
+        return new Iterator(function () {
+          while (true) {
+            var step = iterator.next();
+            if (step.done) {
+              return step;
+            }
+            var entry = step.value;
+            // Check if entry exists first so array access doesn't throw for holes
+            // in the parent iteration.
+            if (entry) {
+              validateEntry(entry);
+              var indexedCollection = isCollection(entry);
+              return iteratorValue(
+                type,
+                indexedCollection ? entry.get(0) : entry[0],
+                indexedCollection ? entry.get(1) : entry[1],
+                step
+              );
+            }
+          }
+        });
+      };
+
+      return FromEntriesSequence;
+    }(KeyedSeq));
+
+    ToIndexedSequence.prototype.cacheResult =
+      ToKeyedSequence.prototype.cacheResult =
+      ToSetSequence.prototype.cacheResult =
+      FromEntriesSequence.prototype.cacheResult =
+        cacheResultThrough;
+
+    function flipFactory(collection) {
+      var flipSequence = makeSequence(collection);
+      flipSequence._iter = collection;
+      flipSequence.size = collection.size;
+      flipSequence.flip = function () { return collection; };
+      flipSequence.reverse = function () {
+        var reversedSequence = collection.reverse.apply(this); // super.reverse()
+        reversedSequence.flip = function () { return collection.reverse(); };
+        return reversedSequence;
+      };
+      flipSequence.has = function (key) { return collection.includes(key); };
+      flipSequence.includes = function (key) { return collection.has(key); };
+      flipSequence.cacheResult = cacheResultThrough;
+      flipSequence.__iterateUncached = function (fn, reverse) {
+        var this$1$1 = this;
+
+        return collection.__iterate(function (v, k) { return fn(k, v, this$1$1) !== false; }, reverse);
+      };
+      flipSequence.__iteratorUncached = function (type, reverse) {
+        if (type === ITERATE_ENTRIES) {
+          var iterator = collection.__iterator(type, reverse);
+          return new Iterator(function () {
+            var step = iterator.next();
+            if (!step.done) {
+              var k = step.value[0];
+              step.value[0] = step.value[1];
+              step.value[1] = k;
+            }
+            return step;
+          });
+        }
+        return collection.__iterator(
+          type === ITERATE_VALUES ? ITERATE_KEYS : ITERATE_VALUES,
+          reverse
+        );
+      };
+      return flipSequence;
+    }
+
+    function mapFactory(collection, mapper, context) {
+      var mappedSequence = makeSequence(collection);
+      mappedSequence.size = collection.size;
+      mappedSequence.has = function (key) { return collection.has(key); };
+      mappedSequence.get = function (key, notSetValue) {
+        var v = collection.get(key, NOT_SET);
+        return v === NOT_SET
+          ? notSetValue
+          : mapper.call(context, v, key, collection);
+      };
+      mappedSequence.__iterateUncached = function (fn, reverse) {
+        var this$1$1 = this;
+
+        return collection.__iterate(
+          function (v, k, c) { return fn(mapper.call(context, v, k, c), k, this$1$1) !== false; },
+          reverse
+        );
+      };
+      mappedSequence.__iteratorUncached = function (type, reverse) {
+        var iterator = collection.__iterator(ITERATE_ENTRIES, reverse);
+        return new Iterator(function () {
+          var step = iterator.next();
+          if (step.done) {
+            return step;
+          }
+          var entry = step.value;
+          var key = entry[0];
+          return iteratorValue(
+            type,
+            key,
+            mapper.call(context, entry[1], key, collection),
+            step
+          );
+        });
+      };
+      return mappedSequence;
+    }
+
+    function reverseFactory(collection, useKeys) {
+      var this$1$1 = this;
+
+      var reversedSequence = makeSequence(collection);
+      reversedSequence._iter = collection;
+      reversedSequence.size = collection.size;
+      reversedSequence.reverse = function () { return collection; };
+      if (collection.flip) {
+        reversedSequence.flip = function () {
+          var flipSequence = flipFactory(collection);
+          flipSequence.reverse = function () { return collection.flip(); };
+          return flipSequence;
+        };
+      }
+      reversedSequence.get = function (key, notSetValue) { return collection.get(useKeys ? key : -1 - key, notSetValue); };
+      reversedSequence.has = function (key) { return collection.has(useKeys ? key : -1 - key); };
+      reversedSequence.includes = function (value) { return collection.includes(value); };
+      reversedSequence.cacheResult = cacheResultThrough;
+      reversedSequence.__iterate = function (fn, reverse) {
+        var this$1$1 = this;
+
+        var i = 0;
+        // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+        reverse && ensureSize(collection);
+        return collection.__iterate(
+          function (v, k) { return fn(v, useKeys ? k : reverse ? this$1$1.size - ++i : i++, this$1$1); },
+          !reverse
+        );
+      };
+      reversedSequence.__iterator = function (type, reverse) {
+        var i = 0;
+        // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+        reverse && ensureSize(collection);
+        var iterator = collection.__iterator(ITERATE_ENTRIES, !reverse);
+        return new Iterator(function () {
+          var step = iterator.next();
+          if (step.done) {
+            return step;
+          }
+          var entry = step.value;
+          return iteratorValue(
+            type,
+            useKeys ? entry[0] : reverse ? this$1$1.size - ++i : i++,
+            entry[1],
+            step
+          );
+        });
+      };
+      return reversedSequence;
+    }
+
+    function filterFactory(collection, predicate, context, useKeys) {
+      var filterSequence = makeSequence(collection);
+      if (useKeys) {
+        filterSequence.has = function (key) {
+          var v = collection.get(key, NOT_SET);
+          return v !== NOT_SET && !!predicate.call(context, v, key, collection);
+        };
+        filterSequence.get = function (key, notSetValue) {
+          var v = collection.get(key, NOT_SET);
+          return v !== NOT_SET && predicate.call(context, v, key, collection)
+            ? v
+            : notSetValue;
+        };
+      }
+      filterSequence.__iterateUncached = function (fn, reverse) {
+        var this$1$1 = this;
+
+        var iterations = 0;
+        collection.__iterate(function (v, k, c) {
+          if (predicate.call(context, v, k, c)) {
+            iterations++;
+            return fn(v, useKeys ? k : iterations - 1, this$1$1);
+          }
+        }, reverse);
+        return iterations;
+      };
+      filterSequence.__iteratorUncached = function (type, reverse) {
+        var iterator = collection.__iterator(ITERATE_ENTRIES, reverse);
+        var iterations = 0;
+        return new Iterator(function () {
+          while (true) {
+            var step = iterator.next();
+            if (step.done) {
+              return step;
+            }
+            var entry = step.value;
+            var key = entry[0];
+            var value = entry[1];
+            if (predicate.call(context, value, key, collection)) {
+              return iteratorValue(type, useKeys ? key : iterations++, value, step);
+            }
+          }
+        });
+      };
+      return filterSequence;
+    }
+
+    function countByFactory(collection, grouper, context) {
+      var groups = Map().asMutable();
+      collection.__iterate(function (v, k) {
+        groups.update(grouper.call(context, v, k, collection), 0, function (a) { return a + 1; });
+      });
+      return groups.asImmutable();
+    }
+
+    function groupByFactory(collection, grouper, context) {
+      var isKeyedIter = isKeyed(collection);
+      var groups = (isOrdered(collection) ? OrderedMap() : Map()).asMutable();
+      collection.__iterate(function (v, k) {
+        groups.update(
+          grouper.call(context, v, k, collection),
+          function (a) { return ((a = a || []), a.push(isKeyedIter ? [k, v] : v), a); }
+        );
+      });
+      var coerce = collectionClass(collection);
+      return groups.map(function (arr) { return reify(collection, coerce(arr)); }).asImmutable();
+    }
+
+    function partitionFactory(collection, predicate, context) {
+      var isKeyedIter = isKeyed(collection);
+      var groups = [[], []];
+      collection.__iterate(function (v, k) {
+        groups[predicate.call(context, v, k, collection) ? 1 : 0].push(
+          isKeyedIter ? [k, v] : v
+        );
+      });
+      var coerce = collectionClass(collection);
+      return groups.map(function (arr) { return reify(collection, coerce(arr)); });
+    }
+
+    function sliceFactory(collection, begin, end, useKeys) {
+      var originalSize = collection.size;
+
+      if (wholeSlice(begin, end, originalSize)) {
+        return collection;
+      }
+
+      // begin or end can not be resolved if they were provided as negative numbers and
+      // this collection's size is unknown. In that case, cache first so there is
+      // a known size and these do not resolve to NaN.
+      if (typeof originalSize === 'undefined' && (begin < 0 || end < 0)) {
+        return sliceFactory(collection.toSeq().cacheResult(), begin, end, useKeys);
+      }
+
+      var resolvedBegin = resolveBegin(begin, originalSize);
+      var resolvedEnd = resolveEnd(end, originalSize);
+
+      // Note: resolvedEnd is undefined when the original sequence's length is
+      // unknown and this slice did not supply an end and should contain all
+      // elements after resolvedBegin.
+      // In that case, resolvedSize will be NaN and sliceSize will remain undefined.
+      var resolvedSize = resolvedEnd - resolvedBegin;
+      var sliceSize;
+      if (resolvedSize === resolvedSize) {
+        sliceSize = resolvedSize < 0 ? 0 : resolvedSize;
+      }
+
+      var sliceSeq = makeSequence(collection);
+
+      // If collection.size is undefined, the size of the realized sliceSeq is
+      // unknown at this point unless the number of items to slice is 0
+      sliceSeq.size =
+        sliceSize === 0 ? sliceSize : (collection.size && sliceSize) || undefined;
+
+      if (!useKeys && isSeq(collection) && sliceSize >= 0) {
+        sliceSeq.get = function (index, notSetValue) {
+          index = wrapIndex(this, index);
+          return index >= 0 && index < sliceSize
+            ? collection.get(index + resolvedBegin, notSetValue)
+            : notSetValue;
+        };
+      }
+
+      sliceSeq.__iterateUncached = function (fn, reverse) {
+        var this$1$1 = this;
+
+        if (sliceSize === 0) {
+          return 0;
+        }
+        if (reverse) {
+          return this.cacheResult().__iterate(fn, reverse);
+        }
+        var skipped = 0;
+        var isSkipping = true;
+        var iterations = 0;
+        collection.__iterate(function (v, k) {
+          if (!(isSkipping && (isSkipping = skipped++ < resolvedBegin))) {
+            iterations++;
+            return (
+              fn(v, useKeys ? k : iterations - 1, this$1$1) !== false &&
+              iterations !== sliceSize
+            );
+          }
+        });
+        return iterations;
+      };
+
+      sliceSeq.__iteratorUncached = function (type, reverse) {
+        if (sliceSize !== 0 && reverse) {
+          return this.cacheResult().__iterator(type, reverse);
+        }
+        // Don't bother instantiating parent iterator if taking 0.
+        if (sliceSize === 0) {
+          return new Iterator(iteratorDone);
+        }
+        var iterator = collection.__iterator(type, reverse);
+        var skipped = 0;
+        var iterations = 0;
+        return new Iterator(function () {
+          while (skipped++ < resolvedBegin) {
+            iterator.next();
+          }
+          if (++iterations > sliceSize) {
+            return iteratorDone();
+          }
+          var step = iterator.next();
+          if (useKeys || type === ITERATE_VALUES || step.done) {
+            return step;
+          }
+          if (type === ITERATE_KEYS) {
+            return iteratorValue(type, iterations - 1, undefined, step);
+          }
+          return iteratorValue(type, iterations - 1, step.value[1], step);
+        });
+      };
+
+      return sliceSeq;
+    }
+
+    function takeWhileFactory(collection, predicate, context) {
+      var takeSequence = makeSequence(collection);
+      takeSequence.__iterateUncached = function (fn, reverse) {
+        var this$1$1 = this;
+
+        if (reverse) {
+          return this.cacheResult().__iterate(fn, reverse);
+        }
+        var iterations = 0;
+        collection.__iterate(
+          function (v, k, c) { return predicate.call(context, v, k, c) && ++iterations && fn(v, k, this$1$1); }
+        );
+        return iterations;
+      };
+      takeSequence.__iteratorUncached = function (type, reverse) {
+        var this$1$1 = this;
+
+        if (reverse) {
+          return this.cacheResult().__iterator(type, reverse);
+        }
+        var iterator = collection.__iterator(ITERATE_ENTRIES, reverse);
+        var iterating = true;
+        return new Iterator(function () {
+          if (!iterating) {
+            return iteratorDone();
+          }
+          var step = iterator.next();
+          if (step.done) {
+            return step;
+          }
+          var entry = step.value;
+          var k = entry[0];
+          var v = entry[1];
+          if (!predicate.call(context, v, k, this$1$1)) {
+            iterating = false;
+            return iteratorDone();
+          }
+          return type === ITERATE_ENTRIES ? step : iteratorValue(type, k, v, step);
+        });
+      };
+      return takeSequence;
+    }
+
+    function skipWhileFactory(collection, predicate, context, useKeys) {
+      var skipSequence = makeSequence(collection);
+      skipSequence.__iterateUncached = function (fn, reverse) {
+        var this$1$1 = this;
+
+        if (reverse) {
+          return this.cacheResult().__iterate(fn, reverse);
+        }
+        var isSkipping = true;
+        var iterations = 0;
+        collection.__iterate(function (v, k, c) {
+          if (!(isSkipping && (isSkipping = predicate.call(context, v, k, c)))) {
+            iterations++;
+            return fn(v, useKeys ? k : iterations - 1, this$1$1);
+          }
+        });
+        return iterations;
+      };
+      skipSequence.__iteratorUncached = function (type, reverse) {
+        var this$1$1 = this;
+
+        if (reverse) {
+          return this.cacheResult().__iterator(type, reverse);
+        }
+        var iterator = collection.__iterator(ITERATE_ENTRIES, reverse);
+        var skipping = true;
+        var iterations = 0;
+        return new Iterator(function () {
+          var step;
+          var k;
+          var v;
+          do {
+            step = iterator.next();
+            if (step.done) {
+              if (useKeys || type === ITERATE_VALUES) {
+                return step;
+              }
+              if (type === ITERATE_KEYS) {
+                return iteratorValue(type, iterations++, undefined, step);
+              }
+              return iteratorValue(type, iterations++, step.value[1], step);
+            }
+            var entry = step.value;
+            k = entry[0];
+            v = entry[1];
+            // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+            skipping && (skipping = predicate.call(context, v, k, this$1$1));
+          } while (skipping);
+          return type === ITERATE_ENTRIES ? step : iteratorValue(type, k, v, step);
+        });
+      };
+      return skipSequence;
+    }
+
+    var ConcatSeq = /*@__PURE__*/(function (Seq) {
+      function ConcatSeq(iterables) {
+        this._wrappedIterables = iterables.flatMap(function (iterable) {
+          if (iterable._wrappedIterables) {
+            return iterable._wrappedIterables;
+          }
+          return [iterable];
+        });
+        this.size = this._wrappedIterables.reduce(function (sum, iterable) {
+          if (sum !== undefined) {
+            var size = iterable.size;
+            if (size !== undefined) {
+              return sum + size;
+            }
+          }
+        }, 0);
+        this[IS_KEYED_SYMBOL] = this._wrappedIterables[0][IS_KEYED_SYMBOL];
+        this[IS_INDEXED_SYMBOL] = this._wrappedIterables[0][IS_INDEXED_SYMBOL];
+        this[IS_ORDERED_SYMBOL] = this._wrappedIterables[0][IS_ORDERED_SYMBOL];
+      }
+
+      if ( Seq ) ConcatSeq.__proto__ = Seq;
+      ConcatSeq.prototype = Object.create( Seq && Seq.prototype );
+      ConcatSeq.prototype.constructor = ConcatSeq;
+
+      ConcatSeq.prototype.__iterateUncached = function __iterateUncached (fn, reverse) {
+        if (this._wrappedIterables.length === 0) {
+          return;
+        }
+
+        if (reverse) {
+          return this.cacheResult().__iterate(fn, reverse);
+        }
+
+        var iterableIndex = 0;
+        var useKeys = isKeyed(this);
+        var iteratorType = useKeys ? ITERATE_ENTRIES : ITERATE_VALUES;
+        var currentIterator = this._wrappedIterables[iterableIndex].__iterator(
+          iteratorType,
+          reverse
+        );
+
+        var keepGoing = true;
+        var index = 0;
+        while (keepGoing) {
+          var next = currentIterator.next();
+          while (next.done) {
+            iterableIndex++;
+            if (iterableIndex === this._wrappedIterables.length) {
+              return index;
+            }
+            currentIterator = this._wrappedIterables[iterableIndex].__iterator(
+              iteratorType,
+              reverse
+            );
+            next = currentIterator.next();
+          }
+          var fnResult = useKeys
+            ? fn(next.value[1], next.value[0], this)
+            : fn(next.value, index, this);
+          keepGoing = fnResult !== false;
+          index++;
+        }
+        return index;
+      };
+
+      ConcatSeq.prototype.__iteratorUncached = function __iteratorUncached (type, reverse) {
+        var this$1$1 = this;
+
+        if (this._wrappedIterables.length === 0) {
+          return new Iterator(iteratorDone);
+        }
+
+        if (reverse) {
+          return this.cacheResult().__iterator(type, reverse);
+        }
+
+        var iterableIndex = 0;
+        var currentIterator = this._wrappedIterables[iterableIndex].__iterator(
+          type,
+          reverse
+        );
+        return new Iterator(function () {
+          var next = currentIterator.next();
+          while (next.done) {
+            iterableIndex++;
+            if (iterableIndex === this$1$1._wrappedIterables.length) {
+              return next;
+            }
+            currentIterator = this$1$1._wrappedIterables[iterableIndex].__iterator(
+              type,
+              reverse
+            );
+            next = currentIterator.next();
+          }
+          return next;
+        });
+      };
+
+      return ConcatSeq;
+    }(Seq));
+
+    function concatFactory(collection, values) {
+      var isKeyedCollection = isKeyed(collection);
+      var iters = [collection]
+        .concat(values)
+        .map(function (v) {
+          if (!isCollection(v)) {
+            v = isKeyedCollection
+              ? keyedSeqFromValue(v)
+              : indexedSeqFromValue(Array.isArray(v) ? v : [v]);
+          } else if (isKeyedCollection) {
+            v = KeyedCollection(v);
+          }
+          return v;
+        })
+        .filter(function (v) { return v.size !== 0; });
+
+      if (iters.length === 0) {
+        return collection;
+      }
+
+      if (iters.length === 1) {
+        var singleton = iters[0];
+        if (
+          singleton === collection ||
+          (isKeyedCollection && isKeyed(singleton)) ||
+          (isIndexed(collection) && isIndexed(singleton))
+        ) {
+          return singleton;
+        }
+      }
+
+      return new ConcatSeq(iters);
+    }
+
+    function flattenFactory(collection, depth, useKeys) {
+      var flatSequence = makeSequence(collection);
+      flatSequence.__iterateUncached = function (fn, reverse) {
+        if (reverse) {
+          return this.cacheResult().__iterate(fn, reverse);
+        }
+        var iterations = 0;
+        var stopped = false;
+        function flatDeep(iter, currentDepth) {
+          iter.__iterate(function (v, k) {
+            if ((!depth || currentDepth < depth) && isCollection(v)) {
+              flatDeep(v, currentDepth + 1);
+            } else {
+              iterations++;
+              if (fn(v, useKeys ? k : iterations - 1, flatSequence) === false) {
+                stopped = true;
+              }
+            }
+            return !stopped;
+          }, reverse);
+        }
+        flatDeep(collection, 0);
+        return iterations;
+      };
+      flatSequence.__iteratorUncached = function (type, reverse) {
+        if (reverse) {
+          return this.cacheResult().__iterator(type, reverse);
+        }
+        var iterator = collection.__iterator(type, reverse);
+        var stack = [];
+        var iterations = 0;
+        return new Iterator(function () {
+          while (iterator) {
+            var step = iterator.next();
+            if (step.done !== false) {
+              iterator = stack.pop();
+              continue;
+            }
+            var v = step.value;
+            if (type === ITERATE_ENTRIES) {
+              v = v[1];
+            }
+            if ((!depth || stack.length < depth) && isCollection(v)) {
+              stack.push(iterator);
+              iterator = v.__iterator(type, reverse);
+            } else {
+              return useKeys ? step : iteratorValue(type, iterations++, v, step);
+            }
+          }
+          return iteratorDone();
+        });
+      };
+      return flatSequence;
+    }
+
+    function flatMapFactory(collection, mapper, context) {
+      var coerce = collectionClass(collection);
+      return collection
+        .toSeq()
+        .map(function (v, k) { return coerce(mapper.call(context, v, k, collection)); })
+        .flatten(true);
+    }
+
+    function interposeFactory(collection, separator) {
+      var interposedSequence = makeSequence(collection);
+      interposedSequence.size = collection.size && collection.size * 2 - 1;
+      interposedSequence.__iterateUncached = function (fn, reverse) {
+        var this$1$1 = this;
+
+        var iterations = 0;
+        collection.__iterate(
+          function (v) { return (!iterations || fn(separator, iterations++, this$1$1) !== false) &&
+            fn(v, iterations++, this$1$1) !== false; },
+          reverse
+        );
+        return iterations;
+      };
+      interposedSequence.__iteratorUncached = function (type, reverse) {
+        var iterator = collection.__iterator(ITERATE_VALUES, reverse);
+        var iterations = 0;
+        var step;
+        return new Iterator(function () {
+          if (!step || iterations % 2) {
+            step = iterator.next();
+            if (step.done) {
+              return step;
+            }
+          }
+          return iterations % 2
+            ? iteratorValue(type, iterations++, separator)
+            : iteratorValue(type, iterations++, step.value, step);
+        });
+      };
+      return interposedSequence;
+    }
+
+    function sortFactory(collection, comparator, mapper) {
+      if (!comparator) {
+        comparator = defaultComparator;
+      }
+      var isKeyedCollection = isKeyed(collection);
+      var index = 0;
+      var entries = collection
+        .toSeq()
+        .map(function (v, k) { return [k, v, index++, mapper ? mapper(v, k, collection) : v]; })
+        .valueSeq()
+        .toArray();
+      entries
+        .sort(function (a, b) { return comparator(a[3], b[3]) || a[2] - b[2]; })
+        .forEach(
+          isKeyedCollection
+            ? function (v, i) {
+                entries[i].length = 2;
+              }
+            : function (v, i) {
+                entries[i] = v[1];
+              }
+        );
+      return isKeyedCollection
+        ? KeyedSeq(entries)
+        : isIndexed(collection)
+          ? IndexedSeq(entries)
+          : SetSeq(entries);
+    }
+
+    function maxFactory(collection, comparator, mapper) {
+      if (!comparator) {
+        comparator = defaultComparator;
+      }
+      if (mapper) {
+        var entry = collection
+          .toSeq()
+          .map(function (v, k) { return [v, mapper(v, k, collection)]; })
+          .reduce(function (a, b) { return (maxCompare(comparator, a[1], b[1]) ? b : a); });
+        return entry && entry[0];
+      }
+      return collection.reduce(function (a, b) { return (maxCompare(comparator, a, b) ? b : a); });
+    }
+
+    function maxCompare(comparator, a, b) {
+      var comp = comparator(b, a);
+      // b is considered the new max if the comparator declares them equal, but
+      // they are not equal and b is in fact a nullish value.
+      return (
+        (comp === 0 && b !== a && (b === undefined || b === null || b !== b)) ||
+        comp > 0
+      );
+    }
+
+    function zipWithFactory(keyIter, zipper, iters, zipAll) {
+      var zipSequence = makeSequence(keyIter);
+      var sizes = new ArraySeq(iters).map(function (i) { return i.size; });
+      zipSequence.size = zipAll ? sizes.max() : sizes.min();
+      // Note: this a generic base implementation of __iterate in terms of
+      // __iterator which may be more generically useful in the future.
+      zipSequence.__iterate = function (fn, reverse) {
+        /* generic:
+        var iterator = this.__iterator(ITERATE_ENTRIES, reverse);
+        var step;
+        var iterations = 0;
+        while (!(step = iterator.next()).done) {
+          iterations++;
+          if (fn(step.value[1], step.value[0], this) === false) {
+            break;
+          }
+        }
+        return iterations;
+        */
+        // indexed:
+        var iterator = this.__iterator(ITERATE_VALUES, reverse);
+        var step;
+        var iterations = 0;
+        while (!(step = iterator.next()).done) {
+          if (fn(step.value, iterations++, this) === false) {
+            break;
+          }
+        }
+        return iterations;
+      };
+      zipSequence.__iteratorUncached = function (type, reverse) {
+        var iterators = iters.map(
+          function (i) { return ((i = Collection(i)), getIterator(reverse ? i.reverse() : i)); }
+        );
+        var iterations = 0;
+        var isDone = false;
+        return new Iterator(function () {
+          var steps;
+          if (!isDone) {
+            steps = iterators.map(function (i) { return i.next(); });
+            isDone = zipAll
+              ? steps.every(function (s) { return s.done; })
+              : steps.some(function (s) { return s.done; });
+          }
+          if (isDone) {
+            return iteratorDone();
+          }
+          return iteratorValue(
+            type,
+            iterations++,
+            zipper.apply(
+              null,
+              steps.map(function (s) { return s.value; })
+            )
+          );
+        });
+      };
+      return zipSequence;
+    }
+
+    // #pragma Helper Functions
+
+    function reify(iter, seq) {
+      return iter === seq ? iter : isSeq(iter) ? seq : iter.constructor(seq);
+    }
+
+    function validateEntry(entry) {
+      if (entry !== Object(entry)) {
+        throw new TypeError('Expected [K, V] tuple: ' + entry);
+      }
+    }
+
+    function collectionClass(collection) {
+      return isKeyed(collection)
+        ? KeyedCollection
+        : isIndexed(collection)
+          ? IndexedCollection
+          : SetCollection;
+    }
+
+    function makeSequence(collection) {
+      return Object.create(
+        (isKeyed(collection)
+          ? KeyedSeq
+          : isIndexed(collection)
+            ? IndexedSeq
+            : SetSeq
+        ).prototype
+      );
+    }
+
+    function cacheResultThrough() {
+      if (this._iter.cacheResult) {
+        this._iter.cacheResult();
+        this.size = this._iter.size;
+        return this;
+      }
+      return Seq.prototype.cacheResult.call(this);
+    }
+
+    function defaultComparator(a, b) {
+      if (a === undefined && b === undefined) {
+        return 0;
+      }
+
+      if (a === undefined) {
+        return 1;
+      }
+
+      if (b === undefined) {
+        return -1;
+      }
+
+      return a > b ? 1 : a < b ? -1 : 0;
+    }
+
+    // http://jsperf.com/copy-array-inline
+    function arrCopy(arr, offset) {
+        offset = offset || 0;
+        var len = Math.max(0, arr.length - offset);
+        var newArr = new Array(len);
+        for (var ii = 0; ii < len; ii++) {
+            // @ts-expect-error We may want to guard for undefined values with `if (arr[ii + offset] !== undefined`, but ths should not happen by design
+            newArr[ii] = arr[ii + offset];
+        }
+        return newArr;
+    }
+
+    function invariant(condition, error) {
+        if (!condition)
+            { throw new Error(error); }
+    }
+
+    function assertNotInfinite(size) {
+        invariant(size !== Infinity, 'Cannot perform this action with an infinite size.');
+    }
+
+    function coerceKeyPath(keyPath) {
+        if (isArrayLike(keyPath) && typeof keyPath !== 'string') {
+            return keyPath;
+        }
+        if (isOrdered(keyPath)) {
+            return keyPath.toArray();
+        }
+        throw new TypeError('Invalid keyPath: expected Ordered Collection or Array: ' + keyPath);
+    }
+
+    var toString = Object.prototype.toString;
+    function isPlainObject(value) {
+        // The base prototype's toString deals with Argument objects and native namespaces like Math
+        if (!value ||
+            typeof value !== 'object' ||
+            toString.call(value) !== '[object Object]') {
+            return false;
+        }
+        var proto = Object.getPrototypeOf(value);
+        if (proto === null) {
+            return true;
+        }
+        // Iteratively going up the prototype chain is needed for cross-realm environments (differing contexts, iframes, etc)
+        var parentProto = proto;
+        var nextProto = Object.getPrototypeOf(proto);
+        while (nextProto !== null) {
+            parentProto = nextProto;
+            nextProto = Object.getPrototypeOf(parentProto);
+        }
+        return parentProto === proto;
+    }
+
+    /**
+     * Returns true if the value is a potentially-persistent data structure, either
+     * provided by Immutable.js or a plain Array or Object.
+     */
+    function isDataStructure(value) {
+        return (typeof value === 'object' &&
+            (isImmutable(value) || Array.isArray(value) || isPlainObject(value)));
+    }
+
+    /**
+     * Converts a value to a string, adding quotes if a string was provided.
+     */
+    function quoteString(value) {
+        try {
+            return typeof value === 'string' ? JSON.stringify(value) : String(value);
+            // eslint-disable-next-line @typescript-eslint/no-unused-vars
+        }
+        catch (_ignoreError) {
+            return JSON.stringify(value);
+        }
+    }
+
+    /**
+     * Returns true if the key is defined in the provided collection.
+     *
+     * A functional alternative to `collection.has(key)` which will also work with
+     * plain Objects and Arrays as an alternative for
+     * `collection.hasOwnProperty(key)`.
+     */
+    function has(collection, key) {
+        return isImmutable(collection)
+            ? // @ts-expect-error key might be a number or symbol, which is not handled be Record key type
+                collection.has(key)
+            : // @ts-expect-error key might be anything else than PropertyKey, and will return false in that case but runtime is OK
+                isDataStructure(collection) && hasOwnProperty.call(collection, key);
+    }
+
+    function get(collection, key, notSetValue) {
+        return isImmutable(collection)
+            ? collection.get(key, notSetValue)
+            : !has(collection, key)
+                ? notSetValue
+                : // @ts-expect-error weird "get" here,
+                    typeof collection.get === 'function'
+                        ? // @ts-expect-error weird "get" here,
+                            collection.get(key)
+                        : // @ts-expect-error key is unknown here,
+                            collection[key];
+    }
+
+    function shallowCopy(from) {
+        if (Array.isArray(from)) {
+            return arrCopy(from);
+        }
+        var to = {};
+        for (var key in from) {
+            if (hasOwnProperty.call(from, key)) {
+                to[key] = from[key];
+            }
+        }
+        return to;
+    }
+
+    function remove(collection, key) {
+        if (!isDataStructure(collection)) {
+            throw new TypeError('Cannot update non-data-structure value: ' + collection);
+        }
+        if (isImmutable(collection)) {
+            // @ts-expect-error weird "remove" here,
+            if (!collection.remove) {
+                throw new TypeError('Cannot update immutable value without .remove() method: ' + collection);
+            }
+            // @ts-expect-error weird "remove" here,
+            return collection.remove(key);
+        }
+        // @ts-expect-error assert that key is a string, a number or a symbol here
+        if (!hasOwnProperty.call(collection, key)) {
+            return collection;
+        }
+        var collectionCopy = shallowCopy(collection);
+        if (Array.isArray(collectionCopy)) {
+            // @ts-expect-error assert that key is a number here
+            collectionCopy.splice(key, 1);
+        }
+        else {
+            // @ts-expect-error assert that key is a string, a number or a symbol here
+            delete collectionCopy[key];
+        }
+        return collectionCopy;
+    }
+
+    function set(collection, key, value) {
+        if (!isDataStructure(collection)) {
+            throw new TypeError('Cannot update non-data-structure value: ' + collection);
+        }
+        if (isImmutable(collection)) {
+            // @ts-expect-error weird "set" here,
+            if (!collection.set) {
+                throw new TypeError('Cannot update immutable value without .set() method: ' + collection);
+            }
+            // @ts-expect-error weird "set" here,
+            return collection.set(key, value);
+        }
+        // @ts-expect-error mix of key and string here. Probably need a more fine type here
+        if (hasOwnProperty.call(collection, key) && value === collection[key]) {
+            return collection;
+        }
+        var collectionCopy = shallowCopy(collection);
+        // @ts-expect-error mix of key and string here. Probably need a more fine type here
+        collectionCopy[key] = value;
+        return collectionCopy;
+    }
+
+    function updateIn$1(collection, keyPath, notSetValue, updater) {
+        if (!updater) {
+            // handle the fact that `notSetValue` is optional here, in that case `updater` is the updater function
+            // @ts-expect-error updater is a function here
+            updater = notSetValue;
+            notSetValue = undefined;
+        }
+        var updatedValue = updateInDeeply(isImmutable(collection), 
+        // @ts-expect-error type issues with Record and mixed types
+        collection, coerceKeyPath(keyPath), 0, notSetValue, updater);
+        // @ts-expect-error mixed return type
+        return updatedValue === NOT_SET ? notSetValue : updatedValue;
+    }
+    function updateInDeeply(inImmutable, existing, keyPath, i, notSetValue, updater) {
+        var wasNotSet = existing === NOT_SET;
+        if (i === keyPath.length) {
+            var existingValue = wasNotSet ? notSetValue : existing;
+            // @ts-expect-error mixed type with optional value
+            var newValue = updater(existingValue);
+            // @ts-expect-error mixed type
+            return newValue === existingValue ? existing : newValue;
+        }
+        if (!wasNotSet && !isDataStructure(existing)) {
+            throw new TypeError('Cannot update within non-data-structure value in path [' +
+                Array.from(keyPath).slice(0, i).map(quoteString) +
+                ']: ' +
+                existing);
+        }
+        var key = keyPath[i];
+        var nextExisting = wasNotSet ? NOT_SET : get(existing, key, NOT_SET);
+        var nextUpdated = updateInDeeply(nextExisting === NOT_SET ? inImmutable : isImmutable(nextExisting), 
+        // @ts-expect-error mixed type
+        nextExisting, keyPath, i + 1, notSetValue, updater);
+        return nextUpdated === nextExisting
+            ? existing
+            : nextUpdated === NOT_SET
+                ? remove(existing, key)
+                : set(wasNotSet ? (inImmutable ? emptyMap() : {}) : existing, key, nextUpdated);
+    }
+
+    /**
+     * Returns a copy of the collection with the value at the key path set to the
+     * provided value.
+     *
+     * A functional alternative to `collection.setIn(keypath)` which will also
+     * work with plain Objects and Arrays.
+     */
+    function setIn$1(collection, keyPath, value) {
+        return updateIn$1(collection, keyPath, NOT_SET, function () { return value; });
+    }
+
+    function setIn(keyPath, v) {
+      return setIn$1(this, keyPath, v);
+    }
+
+    /**
+     * Returns a copy of the collection with the value at the key path removed.
+     *
+     * A functional alternative to `collection.removeIn(keypath)` which will also
+     * work with plain Objects and Arrays.
+     */
+    function removeIn(collection, keyPath) {
+        return updateIn$1(collection, keyPath, function () { return NOT_SET; });
+    }
+
+    function deleteIn(keyPath) {
+      return removeIn(this, keyPath);
+    }
+
+    function update$1(collection, key, notSetValue, updater) {
+        return updateIn$1(
+        // @ts-expect-error Index signature for type string is missing in type V[]
+        collection, [key], notSetValue, updater);
+    }
+
+    function update(key, notSetValue, updater) {
+      return arguments.length === 1
+        ? key(this)
+        : update$1(this, key, notSetValue, updater);
+    }
+
+    function updateIn(keyPath, notSetValue, updater) {
+      return updateIn$1(this, keyPath, notSetValue, updater);
+    }
+
+    function merge$1() {
+      var iters = [], len = arguments.length;
+      while ( len-- ) iters[ len ] = arguments[ len ];
+
+      return mergeIntoKeyedWith(this, iters);
+    }
+
+    function mergeWith$1(merger) {
+      var iters = [], len = arguments.length - 1;
+      while ( len-- > 0 ) iters[ len ] = arguments[ len + 1 ];
+
+      if (typeof merger !== 'function') {
+        throw new TypeError('Invalid merger function: ' + merger);
+      }
+      return mergeIntoKeyedWith(this, iters, merger);
+    }
+
+    function mergeIntoKeyedWith(collection, collections, merger) {
+      var iters = [];
+      for (var ii = 0; ii < collections.length; ii++) {
+        var collection$1 = KeyedCollection(collections[ii]);
+        if (collection$1.size !== 0) {
+          iters.push(collection$1);
+        }
+      }
+      if (iters.length === 0) {
+        return collection;
+      }
+      if (
+        collection.toSeq().size === 0 &&
+        !collection.__ownerID &&
+        iters.length === 1
+      ) {
+        return isRecord(collection)
+          ? collection // Record is empty and will not be updated: return the same instance
+          : collection.constructor(iters[0]);
+      }
+      return collection.withMutations(function (collection) {
+        var mergeIntoCollection = merger
+          ? function (value, key) {
+              update$1(collection, key, NOT_SET, function (oldVal) { return oldVal === NOT_SET ? value : merger(oldVal, value, key); }
+              );
+            }
+          : function (value, key) {
+              collection.set(key, value);
+            };
+        for (var ii = 0; ii < iters.length; ii++) {
+          iters[ii].forEach(mergeIntoCollection);
+        }
+      });
+    }
+
+    function merge(collection) {
+      var sources = [], len = arguments.length - 1;
+      while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ];
+
+      return mergeWithSources(collection, sources);
+    }
+
+    function mergeWith(merger, collection) {
+      var sources = [], len = arguments.length - 2;
+      while ( len-- > 0 ) sources[ len ] = arguments[ len + 2 ];
+
+      return mergeWithSources(collection, sources, merger);
+    }
+
+    function mergeDeep$1(collection) {
+      var sources = [], len = arguments.length - 1;
+      while ( len-- > 0 ) sources[ len ] = arguments[ len + 1 ];
+
+      return mergeDeepWithSources(collection, sources);
+    }
+
+    function mergeDeepWith$1(merger, collection) {
+      var sources = [], len = arguments.length - 2;
+      while ( len-- > 0 ) sources[ len ] = arguments[ len + 2 ];
+
+      return mergeDeepWithSources(collection, sources, merger);
+    }
+
+    function mergeDeepWithSources(collection, sources, merger) {
+      return mergeWithSources(collection, sources, deepMergerWith(merger));
+    }
+
+    function mergeWithSources(collection, sources, merger) {
+      if (!isDataStructure(collection)) {
+        throw new TypeError(
+          'Cannot merge into non-data-structure value: ' + collection
+        );
+      }
+      if (isImmutable(collection)) {
+        return typeof merger === 'function' && collection.mergeWith
+          ? collection.mergeWith.apply(collection, [ merger ].concat( sources ))
+          : collection.merge
+            ? collection.merge.apply(collection, sources)
+            : collection.concat.apply(collection, sources);
+      }
+      var isArray = Array.isArray(collection);
+      var merged = collection;
+      var Collection = isArray ? IndexedCollection : KeyedCollection;
+      var mergeItem = isArray
+        ? function (value) {
+            // Copy on write
+            if (merged === collection) {
+              merged = shallowCopy(merged);
+            }
+            merged.push(value);
+          }
+        : function (value, key) {
+            var hasVal = hasOwnProperty.call(merged, key);
+            var nextVal =
+              hasVal && merger ? merger(merged[key], value, key) : value;
+            if (!hasVal || nextVal !== merged[key]) {
+              // Copy on write
+              if (merged === collection) {
+                merged = shallowCopy(merged);
+              }
+              merged[key] = nextVal;
+            }
+          };
+      for (var i = 0; i < sources.length; i++) {
+        Collection(sources[i]).forEach(mergeItem);
+      }
+      return merged;
+    }
+
+    function deepMergerWith(merger) {
+      function deepMerger(oldValue, newValue, key) {
+        return isDataStructure(oldValue) &&
+          isDataStructure(newValue) &&
+          areMergeable(oldValue, newValue)
+          ? mergeWithSources(oldValue, [newValue], deepMerger)
+          : merger
+            ? merger(oldValue, newValue, key)
+            : newValue;
+      }
+      return deepMerger;
+    }
+
+    /**
+     * It's unclear what the desired behavior is for merging two collections that
+     * fall into separate categories between keyed, indexed, or set-like, so we only
+     * consider them mergeable if they fall into the same category.
+     */
+    function areMergeable(oldDataStructure, newDataStructure) {
+      var oldSeq = Seq(oldDataStructure);
+      var newSeq = Seq(newDataStructure);
+      // This logic assumes that a sequence can only fall into one of the three
+      // categories mentioned above (since there's no `isSetLike()` method).
+      return (
+        isIndexed(oldSeq) === isIndexed(newSeq) &&
+        isKeyed(oldSeq) === isKeyed(newSeq)
+      );
+    }
+
+    function mergeDeep() {
+      var iters = [], len = arguments.length;
+      while ( len-- ) iters[ len ] = arguments[ len ];
+
+      return mergeDeepWithSources(this, iters);
+    }
+
+    function mergeDeepWith(merger) {
+      var iters = [], len = arguments.length - 1;
+      while ( len-- > 0 ) iters[ len ] = arguments[ len + 1 ];
+
+      return mergeDeepWithSources(this, iters, merger);
+    }
+
+    function mergeIn(keyPath) {
+      var iters = [], len = arguments.length - 1;
+      while ( len-- > 0 ) iters[ len ] = arguments[ len + 1 ];
+
+      return updateIn$1(this, keyPath, emptyMap(), function (m) { return mergeWithSources(m, iters); });
+    }
+
+    function mergeDeepIn(keyPath) {
+      var iters = [], len = arguments.length - 1;
+      while ( len-- > 0 ) iters[ len ] = arguments[ len + 1 ];
+
+      return updateIn$1(this, keyPath, emptyMap(), function (m) { return mergeDeepWithSources(m, iters); }
+      );
+    }
+
+    function withMutations(fn) {
+      var mutable = this.asMutable();
+      fn(mutable);
+      return mutable.wasAltered() ? mutable.__ensureOwner(this.__ownerID) : this;
+    }
+
+    function asMutable() {
+      return this.__ownerID ? this : this.__ensureOwner(new OwnerID());
+    }
+
+    function asImmutable() {
+      return this.__ensureOwner();
+    }
+
+    function wasAltered() {
+      return this.__altered;
+    }
+
+    var Map = /*@__PURE__*/(function (KeyedCollection) {
+      function Map(value) {
+        // eslint-disable-next-line no-constructor-return
+        return value === undefined || value === null
+          ? emptyMap()
+          : isMap(value) && !isOrdered(value)
+            ? value
+            : emptyMap().withMutations(function (map) {
+                var iter = KeyedCollection(value);
+                assertNotInfinite(iter.size);
+                iter.forEach(function (v, k) { return map.set(k, v); });
+              });
+      }
+
+      if ( KeyedCollection ) Map.__proto__ = KeyedCollection;
+      Map.prototype = Object.create( KeyedCollection && KeyedCollection.prototype );
+      Map.prototype.constructor = Map;
+
+      Map.prototype.toString = function toString () {
+        return this.__toString('Map {', '}');
+      };
+
+      // @pragma Access
+
+      Map.prototype.get = function get (k, notSetValue) {
+        return this._root
+          ? this._root.get(0, undefined, k, notSetValue)
+          : notSetValue;
+      };
+
+      // @pragma Modification
+
+      Map.prototype.set = function set (k, v) {
+        return updateMap(this, k, v);
+      };
+
+      Map.prototype.remove = function remove (k) {
+        return updateMap(this, k, NOT_SET);
+      };
+
+      Map.prototype.deleteAll = function deleteAll (keys) {
+        var collection = Collection(keys);
+
+        if (collection.size === 0) {
+          return this;
+        }
+
+        return this.withMutations(function (map) {
+          collection.forEach(function (key) { return map.remove(key); });
+        });
+      };
+
+      Map.prototype.clear = function clear () {
+        if (this.size === 0) {
+          return this;
+        }
+        if (this.__ownerID) {
+          this.size = 0;
+          this._root = null;
+          this.__hash = undefined;
+          this.__altered = true;
+          return this;
+        }
+        return emptyMap();
+      };
+
+      // @pragma Composition
+
+      Map.prototype.sort = function sort (comparator) {
+        // Late binding
+        return OrderedMap(sortFactory(this, comparator));
+      };
+
+      Map.prototype.sortBy = function sortBy (mapper, comparator) {
+        // Late binding
+        return OrderedMap(sortFactory(this, comparator, mapper));
+      };
+
+      Map.prototype.map = function map (mapper, context) {
+        var this$1$1 = this;
+
+        return this.withMutations(function (map) {
+          map.forEach(function (value, key) {
+            map.set(key, mapper.call(context, value, key, this$1$1));
+          });
+        });
+      };
+
+      // @pragma Mutability
+
+      Map.prototype.__iterator = function __iterator (type, reverse) {
+        return new MapIterator(this, type, reverse);
+      };
+
+      Map.prototype.__iterate = function __iterate (fn, reverse) {
+        var this$1$1 = this;
+
+        var iterations = 0;
+        // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+        this._root &&
+          this._root.iterate(function (entry) {
+            iterations++;
+            return fn(entry[1], entry[0], this$1$1);
+          }, reverse);
+        return iterations;
+      };
+
+      Map.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+        if (ownerID === this.__ownerID) {
+          return this;
+        }
+        if (!ownerID) {
+          if (this.size === 0) {
+            return emptyMap();
+          }
+          this.__ownerID = ownerID;
+          this.__altered = false;
+          return this;
+        }
+        return makeMap(this.size, this._root, ownerID, this.__hash);
+      };
+
+      return Map;
+    }(KeyedCollection));
+
+    Map.isMap = isMap;
+
+    var MapPrototype = Map.prototype;
+    MapPrototype[IS_MAP_SYMBOL] = true;
+    MapPrototype[DELETE] = MapPrototype.remove;
+    MapPrototype.removeAll = MapPrototype.deleteAll;
+    MapPrototype.setIn = setIn;
+    MapPrototype.removeIn = MapPrototype.deleteIn = deleteIn;
+    MapPrototype.update = update;
+    MapPrototype.updateIn = updateIn;
+    MapPrototype.merge = MapPrototype.concat = merge$1;
+    MapPrototype.mergeWith = mergeWith$1;
+    MapPrototype.mergeDeep = mergeDeep;
+    MapPrototype.mergeDeepWith = mergeDeepWith;
+    MapPrototype.mergeIn = mergeIn;
+    MapPrototype.mergeDeepIn = mergeDeepIn;
+    MapPrototype.withMutations = withMutations;
+    MapPrototype.wasAltered = wasAltered;
+    MapPrototype.asImmutable = asImmutable;
+    MapPrototype['@@transducer/init'] = MapPrototype.asMutable = asMutable;
+    MapPrototype['@@transducer/step'] = function (result, arr) {
+      return result.set(arr[0], arr[1]);
+    };
+    MapPrototype['@@transducer/result'] = function (obj) {
+      return obj.asImmutable();
+    };
+
+    // #pragma Trie Nodes
+
+    var ArrayMapNode = function ArrayMapNode(ownerID, entries) {
+      this.ownerID = ownerID;
+      this.entries = entries;
+    };
+
+    ArrayMapNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
+      var entries = this.entries;
+      for (var ii = 0, len = entries.length; ii < len; ii++) {
+        if (is(key, entries[ii][0])) {
+          return entries[ii][1];
+        }
+      }
+      return notSetValue;
+    };
+
+    ArrayMapNode.prototype.update = function update (ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
+      var removed = value === NOT_SET;
+
+      var entries = this.entries;
+      var idx = 0;
+      var len = entries.length;
+      for (; idx < len; idx++) {
+        if (is(key, entries[idx][0])) {
+          break;
+        }
+      }
+      var exists = idx < len;
+
+      if (exists ? entries[idx][1] === value : removed) {
+        return this;
+      }
+
+      SetRef(didAlter);
+      // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+      (removed || !exists) && SetRef(didChangeSize);
+
+      if (removed && entries.length === 1) {
+        return; // undefined
+      }
+
+      if (!exists && !removed && entries.length >= MAX_ARRAY_MAP_SIZE) {
+        return createNodes(ownerID, entries, key, value);
+      }
+
+      var isEditable = ownerID && ownerID === this.ownerID;
+      var newEntries = isEditable ? entries : arrCopy(entries);
+
+      if (exists) {
+        if (removed) {
+          // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+          idx === len - 1
+            ? newEntries.pop()
+            : (newEntries[idx] = newEntries.pop());
+        } else {
+          newEntries[idx] = [key, value];
+        }
+      } else {
+        newEntries.push([key, value]);
+      }
+
+      if (isEditable) {
+        this.entries = newEntries;
+        return this;
+      }
+
+      return new ArrayMapNode(ownerID, newEntries);
+    };
+
+    var BitmapIndexedNode = function BitmapIndexedNode(ownerID, bitmap, nodes) {
+      this.ownerID = ownerID;
+      this.bitmap = bitmap;
+      this.nodes = nodes;
+    };
+
+    BitmapIndexedNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
+      if (keyHash === undefined) {
+        keyHash = hash(key);
+      }
+      var bit = 1 << ((shift === 0 ? keyHash : keyHash >>> shift) & MASK);
+      var bitmap = this.bitmap;
+      return (bitmap & bit) === 0
+        ? notSetValue
+        : this.nodes[popCount(bitmap & (bit - 1))].get(
+            shift + SHIFT,
+            keyHash,
+            key,
+            notSetValue
+          );
+    };
+
+    BitmapIndexedNode.prototype.update = function update (ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
+      if (keyHash === undefined) {
+        keyHash = hash(key);
+      }
+      var keyHashFrag = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;
+      var bit = 1 << keyHashFrag;
+      var bitmap = this.bitmap;
+      var exists = (bitmap & bit) !== 0;
+
+      if (!exists && value === NOT_SET) {
+        return this;
+      }
+
+      var idx = popCount(bitmap & (bit - 1));
+      var nodes = this.nodes;
+      var node = exists ? nodes[idx] : undefined;
+      var newNode = updateNode(
+        node,
+        ownerID,
+        shift + SHIFT,
+        keyHash,
+        key,
+        value,
+        didChangeSize,
+        didAlter
+      );
+
+      if (newNode === node) {
+        return this;
+      }
+
+      if (!exists && newNode && nodes.length >= MAX_BITMAP_INDEXED_SIZE) {
+        return expandNodes(ownerID, nodes, bitmap, keyHashFrag, newNode);
+      }
+
+      if (
+        exists &&
+        !newNode &&
+        nodes.length === 2 &&
+        isLeafNode(nodes[idx ^ 1])
+      ) {
+        return nodes[idx ^ 1];
+      }
+
+      if (exists && newNode && nodes.length === 1 && isLeafNode(newNode)) {
+        return newNode;
+      }
+
+      var isEditable = ownerID && ownerID === this.ownerID;
+      var newBitmap = exists ? (newNode ? bitmap : bitmap ^ bit) : bitmap | bit;
+      var newNodes = exists
+        ? newNode
+          ? setAt(nodes, idx, newNode, isEditable)
+          : spliceOut(nodes, idx, isEditable)
+        : spliceIn(nodes, idx, newNode, isEditable);
+
+      if (isEditable) {
+        this.bitmap = newBitmap;
+        this.nodes = newNodes;
+        return this;
+      }
+
+      return new BitmapIndexedNode(ownerID, newBitmap, newNodes);
+    };
+
+    var HashArrayMapNode = function HashArrayMapNode(ownerID, count, nodes) {
+      this.ownerID = ownerID;
+      this.count = count;
+      this.nodes = nodes;
+    };
+
+    HashArrayMapNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
+      if (keyHash === undefined) {
+        keyHash = hash(key);
+      }
+      var idx = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;
+      var node = this.nodes[idx];
+      return node
+        ? node.get(shift + SHIFT, keyHash, key, notSetValue)
+        : notSetValue;
+    };
+
+    HashArrayMapNode.prototype.update = function update (ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
+      if (keyHash === undefined) {
+        keyHash = hash(key);
+      }
+      var idx = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;
+      var removed = value === NOT_SET;
+      var nodes = this.nodes;
+      var node = nodes[idx];
+
+      if (removed && !node) {
+        return this;
+      }
+
+      var newNode = updateNode(
+        node,
+        ownerID,
+        shift + SHIFT,
+        keyHash,
+        key,
+        value,
+        didChangeSize,
+        didAlter
+      );
+      if (newNode === node) {
+        return this;
+      }
+
+      var newCount = this.count;
+      if (!node) {
+        newCount++;
+      } else if (!newNode) {
+        newCount--;
+        if (newCount < MIN_HASH_ARRAY_MAP_SIZE) {
+          return packNodes(ownerID, nodes, newCount, idx);
+        }
+      }
+
+      var isEditable = ownerID && ownerID === this.ownerID;
+      var newNodes = setAt(nodes, idx, newNode, isEditable);
+
+      if (isEditable) {
+        this.count = newCount;
+        this.nodes = newNodes;
+        return this;
+      }
+
+      return new HashArrayMapNode(ownerID, newCount, newNodes);
+    };
+
+    var HashCollisionNode = function HashCollisionNode(ownerID, keyHash, entries) {
+      this.ownerID = ownerID;
+      this.keyHash = keyHash;
+      this.entries = entries;
+    };
+
+    HashCollisionNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
+      var entries = this.entries;
+      for (var ii = 0, len = entries.length; ii < len; ii++) {
+        if (is(key, entries[ii][0])) {
+          return entries[ii][1];
+        }
+      }
+      return notSetValue;
+    };
+
+    HashCollisionNode.prototype.update = function update (ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
+      if (keyHash === undefined) {
+        keyHash = hash(key);
+      }
+
+      var removed = value === NOT_SET;
+
+      if (keyHash !== this.keyHash) {
+        if (removed) {
+          return this;
+        }
+        SetRef(didAlter);
+        SetRef(didChangeSize);
+        return mergeIntoNode(this, ownerID, shift, keyHash, [key, value]);
+      }
+
+      var entries = this.entries;
+      var idx = 0;
+      var len = entries.length;
+      for (; idx < len; idx++) {
+        if (is(key, entries[idx][0])) {
+          break;
+        }
+      }
+      var exists = idx < len;
+
+      if (exists ? entries[idx][1] === value : removed) {
+        return this;
+      }
+
+      SetRef(didAlter);
+      // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+      (removed || !exists) && SetRef(didChangeSize);
+
+      if (removed && len === 2) {
+        return new ValueNode(ownerID, this.keyHash, entries[idx ^ 1]);
+      }
+
+      var isEditable = ownerID && ownerID === this.ownerID;
+      var newEntries = isEditable ? entries : arrCopy(entries);
+
+      if (exists) {
+        if (removed) {
+          // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+          idx === len - 1
+            ? newEntries.pop()
+            : (newEntries[idx] = newEntries.pop());
+        } else {
+          newEntries[idx] = [key, value];
+        }
+      } else {
+        newEntries.push([key, value]);
+      }
+
+      if (isEditable) {
+        this.entries = newEntries;
+        return this;
+      }
+
+      return new HashCollisionNode(ownerID, this.keyHash, newEntries);
+    };
+
+    var ValueNode = function ValueNode(ownerID, keyHash, entry) {
+      this.ownerID = ownerID;
+      this.keyHash = keyHash;
+      this.entry = entry;
+    };
+
+    ValueNode.prototype.get = function get (shift, keyHash, key, notSetValue) {
+      return is(key, this.entry[0]) ? this.entry[1] : notSetValue;
+    };
+
+    ValueNode.prototype.update = function update (ownerID, shift, keyHash, key, value, didChangeSize, didAlter) {
+      var removed = value === NOT_SET;
+      var keyMatch = is(key, this.entry[0]);
+      if (keyMatch ? value === this.entry[1] : removed) {
+        return this;
+      }
+
+      SetRef(didAlter);
+
+      if (removed) {
+        SetRef(didChangeSize);
+        return; // undefined
+      }
+
+      if (keyMatch) {
+        if (ownerID && ownerID === this.ownerID) {
+          this.entry[1] = value;
+          return this;
+        }
+        return new ValueNode(ownerID, this.keyHash, [key, value]);
+      }
+
+      SetRef(didChangeSize);
+      return mergeIntoNode(this, ownerID, shift, hash(key), [key, value]);
+    };
+
+    // #pragma Iterators
+
+    ArrayMapNode.prototype.iterate = HashCollisionNode.prototype.iterate =
+      function (fn, reverse) {
+        var entries = this.entries;
+        for (var ii = 0, maxIndex = entries.length - 1; ii <= maxIndex; ii++) {
+          if (fn(entries[reverse ? maxIndex - ii : ii]) === false) {
+            return false;
+          }
+        }
+      };
+
+    BitmapIndexedNode.prototype.iterate = HashArrayMapNode.prototype.iterate =
+      function (fn, reverse) {
+        var nodes = this.nodes;
+        for (var ii = 0, maxIndex = nodes.length - 1; ii <= maxIndex; ii++) {
+          var node = nodes[reverse ? maxIndex - ii : ii];
+          if (node && node.iterate(fn, reverse) === false) {
+            return false;
+          }
+        }
+      };
+
+    // eslint-disable-next-line @typescript-eslint/no-unused-vars
+    ValueNode.prototype.iterate = function (fn, reverse) {
+      return fn(this.entry);
+    };
+
+    var MapIterator = /*@__PURE__*/(function (Iterator) {
+      function MapIterator(map, type, reverse) {
+        this._type = type;
+        this._reverse = reverse;
+        this._stack = map._root && mapIteratorFrame(map._root);
+      }
+
+      if ( Iterator ) MapIterator.__proto__ = Iterator;
+      MapIterator.prototype = Object.create( Iterator && Iterator.prototype );
+      MapIterator.prototype.constructor = MapIterator;
+
+      MapIterator.prototype.next = function next () {
+        var type = this._type;
+        var stack = this._stack;
+        while (stack) {
+          var node = stack.node;
+          var index = stack.index++;
+          var maxIndex = (void 0);
+          if (node.entry) {
+            if (index === 0) {
+              return mapIteratorValue(type, node.entry);
+            }
+          } else if (node.entries) {
+            maxIndex = node.entries.length - 1;
+            if (index <= maxIndex) {
+              return mapIteratorValue(
+                type,
+                node.entries[this._reverse ? maxIndex - index : index]
+              );
+            }
+          } else {
+            maxIndex = node.nodes.length - 1;
+            if (index <= maxIndex) {
+              var subNode = node.nodes[this._reverse ? maxIndex - index : index];
+              if (subNode) {
+                if (subNode.entry) {
+                  return mapIteratorValue(type, subNode.entry);
+                }
+                stack = this._stack = mapIteratorFrame(subNode, stack);
+              }
+              continue;
+            }
+          }
+          stack = this._stack = this._stack.__prev;
+        }
+        return iteratorDone();
+      };
+
+      return MapIterator;
+    }(Iterator));
+
+    function mapIteratorValue(type, entry) {
+      return iteratorValue(type, entry[0], entry[1]);
+    }
+
+    function mapIteratorFrame(node, prev) {
+      return {
+        node: node,
+        index: 0,
+        __prev: prev,
+      };
+    }
+
+    function makeMap(size, root, ownerID, hash) {
+      var map = Object.create(MapPrototype);
+      map.size = size;
+      map._root = root;
+      map.__ownerID = ownerID;
+      map.__hash = hash;
+      map.__altered = false;
+      return map;
+    }
+
+    var EMPTY_MAP;
+    function emptyMap() {
+      return EMPTY_MAP || (EMPTY_MAP = makeMap(0));
+    }
+
+    function updateMap(map, k, v) {
+      var newRoot;
+      var newSize;
+      if (!map._root) {
+        if (v === NOT_SET) {
+          return map;
+        }
+        newSize = 1;
+        newRoot = new ArrayMapNode(map.__ownerID, [[k, v]]);
+      } else {
+        var didChangeSize = MakeRef();
+        var didAlter = MakeRef();
+        newRoot = updateNode(
+          map._root,
+          map.__ownerID,
+          0,
+          undefined,
+          k,
+          v,
+          didChangeSize,
+          didAlter
+        );
+        if (!didAlter.value) {
+          return map;
+        }
+        newSize = map.size + (didChangeSize.value ? (v === NOT_SET ? -1 : 1) : 0);
+      }
+      if (map.__ownerID) {
+        map.size = newSize;
+        map._root = newRoot;
+        map.__hash = undefined;
+        map.__altered = true;
+        return map;
+      }
+      return newRoot ? makeMap(newSize, newRoot) : emptyMap();
+    }
+
+    function updateNode(
+      node,
+      ownerID,
+      shift,
+      keyHash,
+      key,
+      value,
+      didChangeSize,
+      didAlter
+    ) {
+      if (!node) {
+        if (value === NOT_SET) {
+          return node;
+        }
+        SetRef(didAlter);
+        SetRef(didChangeSize);
+        return new ValueNode(ownerID, keyHash, [key, value]);
+      }
+      return node.update(
+        ownerID,
+        shift,
+        keyHash,
+        key,
+        value,
+        didChangeSize,
+        didAlter
+      );
+    }
+
+    function isLeafNode(node) {
+      return (
+        node.constructor === ValueNode || node.constructor === HashCollisionNode
+      );
+    }
+
+    function mergeIntoNode(node, ownerID, shift, keyHash, entry) {
+      if (node.keyHash === keyHash) {
+        return new HashCollisionNode(ownerID, keyHash, [node.entry, entry]);
+      }
+
+      var idx1 = (shift === 0 ? node.keyHash : node.keyHash >>> shift) & MASK;
+      var idx2 = (shift === 0 ? keyHash : keyHash >>> shift) & MASK;
+
+      var newNode;
+      var nodes =
+        idx1 === idx2
+          ? [mergeIntoNode(node, ownerID, shift + SHIFT, keyHash, entry)]
+          : ((newNode = new ValueNode(ownerID, keyHash, entry)),
+            idx1 < idx2 ? [node, newNode] : [newNode, node]);
+
+      return new BitmapIndexedNode(ownerID, (1 << idx1) | (1 << idx2), nodes);
+    }
+
+    function createNodes(ownerID, entries, key, value) {
+      if (!ownerID) {
+        ownerID = new OwnerID();
+      }
+      var node = new ValueNode(ownerID, hash(key), [key, value]);
+      for (var ii = 0; ii < entries.length; ii++) {
+        var entry = entries[ii];
+        node = node.update(ownerID, 0, undefined, entry[0], entry[1]);
+      }
+      return node;
+    }
+
+    function packNodes(ownerID, nodes, count, excluding) {
+      var bitmap = 0;
+      var packedII = 0;
+      var packedNodes = new Array(count);
+      for (var ii = 0, bit = 1, len = nodes.length; ii < len; ii++, bit <<= 1) {
+        var node = nodes[ii];
+        if (node !== undefined && ii !== excluding) {
+          bitmap |= bit;
+          packedNodes[packedII++] = node;
+        }
+      }
+      return new BitmapIndexedNode(ownerID, bitmap, packedNodes);
+    }
+
+    function expandNodes(ownerID, nodes, bitmap, including, node) {
+      var count = 0;
+      var expandedNodes = new Array(SIZE);
+      for (var ii = 0; bitmap !== 0; ii++, bitmap >>>= 1) {
+        expandedNodes[ii] = bitmap & 1 ? nodes[count++] : undefined;
+      }
+      expandedNodes[including] = node;
+      return new HashArrayMapNode(ownerID, count + 1, expandedNodes);
+    }
+
+    function popCount(x) {
+      x -= (x >> 1) & 0x55555555;
+      x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
+      x = (x + (x >> 4)) & 0x0f0f0f0f;
+      x += x >> 8;
+      x += x >> 16;
+      return x & 0x7f;
+    }
+
+    function setAt(array, idx, val, canEdit) {
+      var newArray = canEdit ? array : arrCopy(array);
+      newArray[idx] = val;
+      return newArray;
+    }
+
+    function spliceIn(array, idx, val, canEdit) {
+      var newLen = array.length + 1;
+      if (canEdit && idx + 1 === newLen) {
+        array[idx] = val;
+        return array;
+      }
+      var newArray = new Array(newLen);
+      var after = 0;
+      for (var ii = 0; ii < newLen; ii++) {
+        if (ii === idx) {
+          newArray[ii] = val;
+          after = -1;
+        } else {
+          newArray[ii] = array[ii + after];
+        }
+      }
+      return newArray;
+    }
+
+    function spliceOut(array, idx, canEdit) {
+      var newLen = array.length - 1;
+      if (canEdit && idx === newLen) {
+        array.pop();
+        return array;
+      }
+      var newArray = new Array(newLen);
+      var after = 0;
+      for (var ii = 0; ii < newLen; ii++) {
+        if (ii === idx) {
+          after = 1;
+        }
+        newArray[ii] = array[ii + after];
+      }
+      return newArray;
+    }
+
+    var MAX_ARRAY_MAP_SIZE = SIZE / 4;
+    var MAX_BITMAP_INDEXED_SIZE = SIZE / 2;
+    var MIN_HASH_ARRAY_MAP_SIZE = SIZE / 4;
+
+    var IS_LIST_SYMBOL = '@@__IMMUTABLE_LIST__@@';
+    /**
+     * True if `maybeList` is a List.
+     */
+    function isList(maybeList) {
+        return Boolean(maybeList &&
+            // @ts-expect-error: maybeList is typed as `{}`, need to change in 6.0 to `maybeList && typeof maybeList === 'object' && IS_LIST_SYMBOL in maybeList`
+            maybeList[IS_LIST_SYMBOL]);
+    }
+
+    var List = /*@__PURE__*/(function (IndexedCollection) {
+      function List(value) {
+        var empty = emptyList();
+        if (value === undefined || value === null) {
+          // eslint-disable-next-line no-constructor-return
+          return empty;
+        }
+        if (isList(value)) {
+          // eslint-disable-next-line no-constructor-return
+          return value;
+        }
+        var iter = IndexedCollection(value);
+        var size = iter.size;
+        if (size === 0) {
+          // eslint-disable-next-line no-constructor-return
+          return empty;
+        }
+        assertNotInfinite(size);
+        if (size > 0 && size < SIZE) {
+          // eslint-disable-next-line no-constructor-return
+          return makeList(0, size, SHIFT, null, new VNode(iter.toArray()));
+        }
+        // eslint-disable-next-line no-constructor-return
+        return empty.withMutations(function (list) {
+          list.setSize(size);
+          iter.forEach(function (v, i) { return list.set(i, v); });
+        });
+      }
+
+      if ( IndexedCollection ) List.__proto__ = IndexedCollection;
+      List.prototype = Object.create( IndexedCollection && IndexedCollection.prototype );
+      List.prototype.constructor = List;
+
+      List.of = function of (/*...values*/) {
+        return this(arguments);
+      };
+
+      List.prototype.toString = function toString () {
+        return this.__toString('List [', ']');
+      };
+
+      // @pragma Access
+
+      List.prototype.get = function get (index, notSetValue) {
+        index = wrapIndex(this, index);
+        if (index >= 0 && index < this.size) {
+          index += this._origin;
+          var node = listNodeFor(this, index);
+          return node && node.array[index & MASK];
+        }
+        return notSetValue;
+      };
+
+      // @pragma Modification
+
+      List.prototype.set = function set (index, value) {
+        return updateList(this, index, value);
+      };
+
+      List.prototype.remove = function remove (index) {
+        return !this.has(index)
+          ? this
+          : index === 0
+            ? this.shift()
+            : index === this.size - 1
+              ? this.pop()
+              : this.splice(index, 1);
+      };
+
+      List.prototype.insert = function insert (index, value) {
+        return this.splice(index, 0, value);
+      };
+
+      List.prototype.clear = function clear () {
+        if (this.size === 0) {
+          return this;
+        }
+        if (this.__ownerID) {
+          this.size = this._origin = this._capacity = 0;
+          this._level = SHIFT;
+          this._root = this._tail = this.__hash = undefined;
+          this.__altered = true;
+          return this;
+        }
+        return emptyList();
+      };
+
+      List.prototype.push = function push (/*...values*/) {
+        var values = arguments;
+        var oldSize = this.size;
+        return this.withMutations(function (list) {
+          setListBounds(list, 0, oldSize + values.length);
+          for (var ii = 0; ii < values.length; ii++) {
+            list.set(oldSize + ii, values[ii]);
+          }
+        });
+      };
+
+      List.prototype.pop = function pop () {
+        return setListBounds(this, 0, -1);
+      };
+
+      List.prototype.unshift = function unshift (/*...values*/) {
+        var values = arguments;
+        return this.withMutations(function (list) {
+          setListBounds(list, -values.length);
+          for (var ii = 0; ii < values.length; ii++) {
+            list.set(ii, values[ii]);
+          }
+        });
+      };
+
+      List.prototype.shift = function shift () {
+        return setListBounds(this, 1);
+      };
+
+      List.prototype.shuffle = function shuffle (random) {
+        if ( random === void 0 ) random = Math.random;
+
+        return this.withMutations(function (mutable) {
+          // implementation of the Fisher-Yates shuffle: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
+          var current = mutable.size;
+          var destination;
+          var tmp;
+
+          while (current) {
+            destination = Math.floor(random() * current--);
+
+            tmp = mutable.get(destination);
+            mutable.set(destination, mutable.get(current));
+            mutable.set(current, tmp);
+          }
+        });
+      };
+
+      // @pragma Composition
+
+      List.prototype.concat = function concat (/*...collections*/) {
+        var arguments$1 = arguments;
+
+        var seqs = [];
+        for (var i = 0; i < arguments.length; i++) {
+          var argument = arguments$1[i];
+          var seq = IndexedCollection(
+            typeof argument !== 'string' && hasIterator(argument)
+              ? argument
+              : [argument]
+          );
+          if (seq.size !== 0) {
+            seqs.push(seq);
+          }
+        }
+        if (seqs.length === 0) {
+          return this;
+        }
+        if (this.size === 0 && !this.__ownerID && seqs.length === 1) {
+          return this.constructor(seqs[0]);
+        }
+        return this.withMutations(function (list) {
+          seqs.forEach(function (seq) { return seq.forEach(function (value) { return list.push(value); }); });
+        });
+      };
+
+      List.prototype.setSize = function setSize (size) {
+        return setListBounds(this, 0, size);
+      };
+
+      List.prototype.map = function map (mapper, context) {
+        var this$1$1 = this;
+
+        return this.withMutations(function (list) {
+          for (var i = 0; i < this$1$1.size; i++) {
+            list.set(i, mapper.call(context, list.get(i), i, this$1$1));
+          }
+        });
+      };
+
+      // @pragma Iteration
+
+      List.prototype.slice = function slice (begin, end) {
+        var size = this.size;
+        if (wholeSlice(begin, end, size)) {
+          return this;
+        }
+        return setListBounds(
+          this,
+          resolveBegin(begin, size),
+          resolveEnd(end, size)
+        );
+      };
+
+      List.prototype.__iterator = function __iterator (type, reverse) {
+        var index = reverse ? this.size : 0;
+        var values = iterateList(this, reverse);
+        return new Iterator(function () {
+          var value = values();
+          return value === DONE
+            ? iteratorDone()
+            : iteratorValue(type, reverse ? --index : index++, value);
+        });
+      };
+
+      List.prototype.__iterate = function __iterate (fn, reverse) {
+        var index = reverse ? this.size : 0;
+        var values = iterateList(this, reverse);
+        var value;
+        while ((value = values()) !== DONE) {
+          if (fn(value, reverse ? --index : index++, this) === false) {
+            break;
+          }
+        }
+        return index;
+      };
+
+      List.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+        if (ownerID === this.__ownerID) {
+          return this;
+        }
+        if (!ownerID) {
+          if (this.size === 0) {
+            return emptyList();
+          }
+          this.__ownerID = ownerID;
+          this.__altered = false;
+          return this;
+        }
+        return makeList(
+          this._origin,
+          this._capacity,
+          this._level,
+          this._root,
+          this._tail,
+          ownerID,
+          this.__hash
+        );
+      };
+
+      return List;
+    }(IndexedCollection));
+
+    List.isList = isList;
+
+    var ListPrototype = List.prototype;
+    ListPrototype[IS_LIST_SYMBOL] = true;
+    ListPrototype[DELETE] = ListPrototype.remove;
+    ListPrototype.merge = ListPrototype.concat;
+    ListPrototype.setIn = setIn;
+    ListPrototype.deleteIn = ListPrototype.removeIn = deleteIn;
+    ListPrototype.update = update;
+    ListPrototype.updateIn = updateIn;
+    ListPrototype.mergeIn = mergeIn;
+    ListPrototype.mergeDeepIn = mergeDeepIn;
+    ListPrototype.withMutations = withMutations;
+    ListPrototype.wasAltered = wasAltered;
+    ListPrototype.asImmutable = asImmutable;
+    ListPrototype['@@transducer/init'] = ListPrototype.asMutable = asMutable;
+    ListPrototype['@@transducer/step'] = function (result, arr) {
+      return result.push(arr);
+    };
+    ListPrototype['@@transducer/result'] = function (obj) {
+      return obj.asImmutable();
+    };
+
+    var VNode = function VNode(array, ownerID) {
+      this.array = array;
+      this.ownerID = ownerID;
+    };
+
+    // TODO: seems like these methods are very similar
+
+    VNode.prototype.removeBefore = function removeBefore (ownerID, level, index) {
+      if (
+        (index & ((1 << (level + SHIFT)) - 1)) === 0 ||
+        this.array.length === 0
+      ) {
+        return this;
+      }
+      var originIndex = (index >>> level) & MASK;
+      if (originIndex >= this.array.length) {
+        return new VNode([], ownerID);
+      }
+      var removingFirst = originIndex === 0;
+      var newChild;
+      if (level > 0) {
+        var oldChild = this.array[originIndex];
+        newChild =
+          oldChild && oldChild.removeBefore(ownerID, level - SHIFT, index);
+        if (newChild === oldChild && removingFirst) {
+          return this;
+        }
+      }
+      if (removingFirst && !newChild) {
+        return this;
+      }
+      var editable = editableVNode(this, ownerID);
+      if (!removingFirst) {
+        for (var ii = 0; ii < originIndex; ii++) {
+          editable.array[ii] = undefined;
+        }
+      }
+      if (newChild) {
+        editable.array[originIndex] = newChild;
+      }
+      return editable;
+    };
+
+    VNode.prototype.removeAfter = function removeAfter (ownerID, level, index) {
+      if (
+        index === (level ? 1 << (level + SHIFT) : SIZE) ||
+        this.array.length === 0
+      ) {
+        return this;
+      }
+      var sizeIndex = ((index - 1) >>> level) & MASK;
+      if (sizeIndex >= this.array.length) {
+        return this;
+      }
+
+      var newChild;
+      if (level > 0) {
+        var oldChild = this.array[sizeIndex];
+        newChild =
+          oldChild && oldChild.removeAfter(ownerID, level - SHIFT, index);
+        if (newChild === oldChild && sizeIndex === this.array.length - 1) {
+          return this;
+        }
+      }
+
+      var editable = editableVNode(this, ownerID);
+      editable.array.splice(sizeIndex + 1);
+      if (newChild) {
+        editable.array[sizeIndex] = newChild;
+      }
+      return editable;
+    };
+
+    var DONE = {};
+
+    function iterateList(list, reverse) {
+      var left = list._origin;
+      var right = list._capacity;
+      var tailPos = getTailOffset(right);
+      var tail = list._tail;
+
+      return iterateNodeOrLeaf(list._root, list._level, 0);
+
+      function iterateNodeOrLeaf(node, level, offset) {
+        return level === 0
+          ? iterateLeaf(node, offset)
+          : iterateNode(node, level, offset);
+      }
+
+      function iterateLeaf(node, offset) {
+        var array = offset === tailPos ? tail && tail.array : node && node.array;
+        var from = offset > left ? 0 : left - offset;
+        var to = right - offset;
+        if (to > SIZE) {
+          to = SIZE;
+        }
+        return function () {
+          if (from === to) {
+            return DONE;
+          }
+          var idx = reverse ? --to : from++;
+          return array && array[idx];
+        };
+      }
+
+      function iterateNode(node, level, offset) {
+        var values;
+        var array = node && node.array;
+        var from = offset > left ? 0 : (left - offset) >> level;
+        var to = ((right - offset) >> level) + 1;
+        if (to > SIZE) {
+          to = SIZE;
+        }
+        return function () {
+          while (true) {
+            if (values) {
+              var value = values();
+              if (value !== DONE) {
+                return value;
+              }
+              values = null;
+            }
+            if (from === to) {
+              return DONE;
+            }
+            var idx = reverse ? --to : from++;
+            values = iterateNodeOrLeaf(
+              array && array[idx],
+              level - SHIFT,
+              offset + (idx << level)
+            );
+          }
+        };
+      }
+    }
+
+    function makeList(origin, capacity, level, root, tail, ownerID, hash) {
+      var list = Object.create(ListPrototype);
+      list.size = capacity - origin;
+      list._origin = origin;
+      list._capacity = capacity;
+      list._level = level;
+      list._root = root;
+      list._tail = tail;
+      list.__ownerID = ownerID;
+      list.__hash = hash;
+      list.__altered = false;
+      return list;
+    }
+
+    function emptyList() {
+      return makeList(0, 0, SHIFT);
+    }
+
+    function updateList(list, index, value) {
+      index = wrapIndex(list, index);
+
+      if (index !== index) {
+        return list;
+      }
+
+      if (index >= list.size || index < 0) {
+        return list.withMutations(function (list) {
+          // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+          index < 0
+            ? setListBounds(list, index).set(0, value)
+            : setListBounds(list, 0, index + 1).set(index, value);
+        });
+      }
+
+      index += list._origin;
+
+      var newTail = list._tail;
+      var newRoot = list._root;
+      var didAlter = MakeRef();
+      if (index >= getTailOffset(list._capacity)) {
+        newTail = updateVNode(newTail, list.__ownerID, 0, index, value, didAlter);
+      } else {
+        newRoot = updateVNode(
+          newRoot,
+          list.__ownerID,
+          list._level,
+          index,
+          value,
+          didAlter
+        );
+      }
+
+      if (!didAlter.value) {
+        return list;
+      }
+
+      if (list.__ownerID) {
+        list._root = newRoot;
+        list._tail = newTail;
+        list.__hash = undefined;
+        list.__altered = true;
+        return list;
+      }
+      return makeList(list._origin, list._capacity, list._level, newRoot, newTail);
+    }
+
+    function updateVNode(node, ownerID, level, index, value, didAlter) {
+      var idx = (index >>> level) & MASK;
+      var nodeHas = node && idx < node.array.length;
+      if (!nodeHas && value === undefined) {
+        return node;
+      }
+
+      var newNode;
+
+      if (level > 0) {
+        var lowerNode = node && node.array[idx];
+        var newLowerNode = updateVNode(
+          lowerNode,
+          ownerID,
+          level - SHIFT,
+          index,
+          value,
+          didAlter
+        );
+        if (newLowerNode === lowerNode) {
+          return node;
+        }
+        newNode = editableVNode(node, ownerID);
+        newNode.array[idx] = newLowerNode;
+        return newNode;
+      }
+
+      if (nodeHas && node.array[idx] === value) {
+        return node;
+      }
+
+      if (didAlter) {
+        SetRef(didAlter);
+      }
+
+      newNode = editableVNode(node, ownerID);
+      if (value === undefined && idx === newNode.array.length - 1) {
+        newNode.array.pop();
+      } else {
+        newNode.array[idx] = value;
+      }
+      return newNode;
+    }
+
+    function editableVNode(node, ownerID) {
+      if (ownerID && node && ownerID === node.ownerID) {
+        return node;
+      }
+      return new VNode(node ? node.array.slice() : [], ownerID);
+    }
+
+    function listNodeFor(list, rawIndex) {
+      if (rawIndex >= getTailOffset(list._capacity)) {
+        return list._tail;
+      }
+      if (rawIndex < 1 << (list._level + SHIFT)) {
+        var node = list._root;
+        var level = list._level;
+        while (node && level > 0) {
+          node = node.array[(rawIndex >>> level) & MASK];
+          level -= SHIFT;
+        }
+        return node;
+      }
+    }
+
+    function setListBounds(list, begin, end) {
+      // Sanitize begin & end using this shorthand for ToInt32(argument)
+      // http://www.ecma-international.org/ecma-262/6.0/#sec-toint32
+      if (begin !== undefined) {
+        begin |= 0;
+      }
+      if (end !== undefined) {
+        end |= 0;
+      }
+      var owner = list.__ownerID || new OwnerID();
+      var oldOrigin = list._origin;
+      var oldCapacity = list._capacity;
+      var newOrigin = oldOrigin + begin;
+      var newCapacity =
+        end === undefined
+          ? oldCapacity
+          : end < 0
+            ? oldCapacity + end
+            : oldOrigin + end;
+      if (newOrigin === oldOrigin && newCapacity === oldCapacity) {
+        return list;
+      }
+
+      // If it's going to end after it starts, it's empty.
+      if (newOrigin >= newCapacity) {
+        return list.clear();
+      }
+
+      var newLevel = list._level;
+      var newRoot = list._root;
+
+      // New origin might need creating a higher root.
+      var offsetShift = 0;
+      while (newOrigin + offsetShift < 0) {
+        newRoot = new VNode(
+          newRoot && newRoot.array.length ? [undefined, newRoot] : [],
+          owner
+        );
+        newLevel += SHIFT;
+        offsetShift += 1 << newLevel;
+      }
+      if (offsetShift) {
+        newOrigin += offsetShift;
+        oldOrigin += offsetShift;
+        newCapacity += offsetShift;
+        oldCapacity += offsetShift;
+      }
+
+      var oldTailOffset = getTailOffset(oldCapacity);
+      var newTailOffset = getTailOffset(newCapacity);
+
+      // New size might need creating a higher root.
+      while (newTailOffset >= 1 << (newLevel + SHIFT)) {
+        newRoot = new VNode(
+          newRoot && newRoot.array.length ? [newRoot] : [],
+          owner
+        );
+        newLevel += SHIFT;
+      }
+
+      // Locate or create the new tail.
+      var oldTail = list._tail;
+      var newTail =
+        newTailOffset < oldTailOffset
+          ? listNodeFor(list, newCapacity - 1)
+          : newTailOffset > oldTailOffset
+            ? new VNode([], owner)
+            : oldTail;
+
+      // Merge Tail into tree.
+      if (
+        oldTail &&
+        newTailOffset > oldTailOffset &&
+        newOrigin < oldCapacity &&
+        oldTail.array.length
+      ) {
+        newRoot = editableVNode(newRoot, owner);
+        var node = newRoot;
+        for (var level = newLevel; level > SHIFT; level -= SHIFT) {
+          var idx = (oldTailOffset >>> level) & MASK;
+          node = node.array[idx] = editableVNode(node.array[idx], owner);
+        }
+        node.array[(oldTailOffset >>> SHIFT) & MASK] = oldTail;
+      }
+
+      // If the size has been reduced, there's a chance the tail needs to be trimmed.
+      if (newCapacity < oldCapacity) {
+        newTail = newTail && newTail.removeAfter(owner, 0, newCapacity);
+      }
+
+      // If the new origin is within the tail, then we do not need a root.
+      if (newOrigin >= newTailOffset) {
+        newOrigin -= newTailOffset;
+        newCapacity -= newTailOffset;
+        newLevel = SHIFT;
+        newRoot = null;
+        newTail = newTail && newTail.removeBefore(owner, 0, newOrigin);
+
+        // Otherwise, if the root has been trimmed, garbage collect.
+      } else if (newOrigin > oldOrigin || newTailOffset < oldTailOffset) {
+        offsetShift = 0;
+
+        // Identify the new top root node of the subtree of the old root.
+        while (newRoot) {
+          var beginIndex = (newOrigin >>> newLevel) & MASK;
+          if ((beginIndex !== newTailOffset >>> newLevel) & MASK) {
+            break;
+          }
+          if (beginIndex) {
+            offsetShift += (1 << newLevel) * beginIndex;
+          }
+          newLevel -= SHIFT;
+          newRoot = newRoot.array[beginIndex];
+        }
+
+        // Trim the new sides of the new root.
+        if (newRoot && newOrigin > oldOrigin) {
+          newRoot = newRoot.removeBefore(owner, newLevel, newOrigin - offsetShift);
+        }
+        if (newRoot && newTailOffset < oldTailOffset) {
+          newRoot = newRoot.removeAfter(
+            owner,
+            newLevel,
+            newTailOffset - offsetShift
+          );
+        }
+        if (offsetShift) {
+          newOrigin -= offsetShift;
+          newCapacity -= offsetShift;
+        }
+      }
+
+      if (list.__ownerID) {
+        list.size = newCapacity - newOrigin;
+        list._origin = newOrigin;
+        list._capacity = newCapacity;
+        list._level = newLevel;
+        list._root = newRoot;
+        list._tail = newTail;
+        list.__hash = undefined;
+        list.__altered = true;
+        return list;
+      }
+      return makeList(newOrigin, newCapacity, newLevel, newRoot, newTail);
+    }
+
+    function getTailOffset(size) {
+      return size < SIZE ? 0 : ((size - 1) >>> SHIFT) << SHIFT;
+    }
+
+    var OrderedMap = /*@__PURE__*/(function (Map) {
+      function OrderedMap(value) {
+        // eslint-disable-next-line no-constructor-return
+        return value === undefined || value === null
+          ? emptyOrderedMap()
+          : isOrderedMap(value)
+            ? value
+            : emptyOrderedMap().withMutations(function (map) {
+                var iter = KeyedCollection(value);
+                assertNotInfinite(iter.size);
+                iter.forEach(function (v, k) { return map.set(k, v); });
+              });
+      }
+
+      if ( Map ) OrderedMap.__proto__ = Map;
+      OrderedMap.prototype = Object.create( Map && Map.prototype );
+      OrderedMap.prototype.constructor = OrderedMap;
+
+      OrderedMap.of = function of (/*...values*/) {
+        return this(arguments);
+      };
+
+      OrderedMap.prototype.toString = function toString () {
+        return this.__toString('OrderedMap {', '}');
+      };
+
+      // @pragma Access
+
+      OrderedMap.prototype.get = function get (k, notSetValue) {
+        var index = this._map.get(k);
+        return index !== undefined ? this._list.get(index)[1] : notSetValue;
+      };
+
+      // @pragma Modification
+
+      OrderedMap.prototype.clear = function clear () {
+        if (this.size === 0) {
+          return this;
+        }
+        if (this.__ownerID) {
+          this.size = 0;
+          this._map.clear();
+          this._list.clear();
+          this.__altered = true;
+          return this;
+        }
+        return emptyOrderedMap();
+      };
+
+      OrderedMap.prototype.set = function set (k, v) {
+        return updateOrderedMap(this, k, v);
+      };
+
+      OrderedMap.prototype.remove = function remove (k) {
+        return updateOrderedMap(this, k, NOT_SET);
+      };
+
+      OrderedMap.prototype.__iterate = function __iterate (fn, reverse) {
+        var this$1$1 = this;
+
+        return this._list.__iterate(
+          function (entry) { return entry && fn(entry[1], entry[0], this$1$1); },
+          reverse
+        );
+      };
+
+      OrderedMap.prototype.__iterator = function __iterator (type, reverse) {
+        return this._list.fromEntrySeq().__iterator(type, reverse);
+      };
+
+      OrderedMap.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+        if (ownerID === this.__ownerID) {
+          return this;
+        }
+        var newMap = this._map.__ensureOwner(ownerID);
+        var newList = this._list.__ensureOwner(ownerID);
+        if (!ownerID) {
+          if (this.size === 0) {
+            return emptyOrderedMap();
+          }
+          this.__ownerID = ownerID;
+          this.__altered = false;
+          this._map = newMap;
+          this._list = newList;
+          return this;
+        }
+        return makeOrderedMap(newMap, newList, ownerID, this.__hash);
+      };
+
+      return OrderedMap;
+    }(Map));
+
+    OrderedMap.isOrderedMap = isOrderedMap;
+
+    OrderedMap.prototype[IS_ORDERED_SYMBOL] = true;
+    OrderedMap.prototype[DELETE] = OrderedMap.prototype.remove;
+
+    function makeOrderedMap(map, list, ownerID, hash) {
+      var omap = Object.create(OrderedMap.prototype);
+      omap.size = map ? map.size : 0;
+      omap._map = map;
+      omap._list = list;
+      omap.__ownerID = ownerID;
+      omap.__hash = hash;
+      omap.__altered = false;
+      return omap;
+    }
+
+    var EMPTY_ORDERED_MAP;
+    function emptyOrderedMap() {
+      return (
+        EMPTY_ORDERED_MAP ||
+        (EMPTY_ORDERED_MAP = makeOrderedMap(emptyMap(), emptyList()))
+      );
+    }
+
+    function updateOrderedMap(omap, k, v) {
+      var map = omap._map;
+      var list = omap._list;
+      var i = map.get(k);
+      var has = i !== undefined;
+      var newMap;
+      var newList;
+      if (v === NOT_SET) {
+        // removed
+        if (!has) {
+          return omap;
+        }
+        if (list.size >= SIZE && list.size >= map.size * 2) {
+          newList = list.filter(function (entry, idx) { return entry !== undefined && i !== idx; });
+          newMap = newList
+            .toKeyedSeq()
+            .map(function (entry) { return entry[0]; })
+            .flip()
+            .toMap();
+          if (omap.__ownerID) {
+            newMap.__ownerID = newList.__ownerID = omap.__ownerID;
+          }
+        } else {
+          newMap = map.remove(k);
+          newList = i === list.size - 1 ? list.pop() : list.set(i, undefined);
+        }
+      } else if (has) {
+        if (v === list.get(i)[1]) {
+          return omap;
+        }
+        newMap = map;
+        newList = list.set(i, [k, v]);
+      } else {
+        newMap = map.set(k, list.size);
+        newList = list.set(list.size, [k, v]);
+      }
+      if (omap.__ownerID) {
+        omap.size = newMap.size;
+        omap._map = newMap;
+        omap._list = newList;
+        omap.__hash = undefined;
+        omap.__altered = true;
+        return omap;
+      }
+      return makeOrderedMap(newMap, newList);
+    }
+
+    var IS_STACK_SYMBOL = '@@__IMMUTABLE_STACK__@@';
+    /**
+     * True if `maybeStack` is a Stack.
+     */
+    function isStack(maybeStack) {
+        return Boolean(maybeStack &&
+            // @ts-expect-error: maybeStack is typed as `{}`, need to change in 6.0 to `maybeStack && typeof maybeStack === 'object' && MAYBE_STACK_SYMBOL in maybeStack`
+            maybeStack[IS_STACK_SYMBOL]);
+    }
+
+    var Stack = /*@__PURE__*/(function (IndexedCollection) {
+      function Stack(value) {
+        // eslint-disable-next-line no-constructor-return
+        return value === undefined || value === null
+          ? emptyStack()
+          : isStack(value)
+            ? value
+            : emptyStack().pushAll(value);
+      }
+
+      if ( IndexedCollection ) Stack.__proto__ = IndexedCollection;
+      Stack.prototype = Object.create( IndexedCollection && IndexedCollection.prototype );
+      Stack.prototype.constructor = Stack;
+
+      Stack.of = function of (/*...values*/) {
+        return this(arguments);
+      };
+
+      Stack.prototype.toString = function toString () {
+        return this.__toString('Stack [', ']');
+      };
+
+      // @pragma Access
+
+      Stack.prototype.get = function get (index, notSetValue) {
+        var head = this._head;
+        index = wrapIndex(this, index);
+        while (head && index--) {
+          head = head.next;
+        }
+        return head ? head.value : notSetValue;
+      };
+
+      Stack.prototype.peek = function peek () {
+        return this._head && this._head.value;
+      };
+
+      // @pragma Modification
+
+      Stack.prototype.push = function push (/*...values*/) {
+        var arguments$1 = arguments;
+
+        if (arguments.length === 0) {
+          return this;
+        }
+        var newSize = this.size + arguments.length;
+        var head = this._head;
+        for (var ii = arguments.length - 1; ii >= 0; ii--) {
+          head = {
+            value: arguments$1[ii],
+            next: head,
+          };
+        }
+        if (this.__ownerID) {
+          this.size = newSize;
+          this._head = head;
+          this.__hash = undefined;
+          this.__altered = true;
+          return this;
+        }
+        return makeStack(newSize, head);
+      };
+
+      Stack.prototype.pushAll = function pushAll (iter) {
+        iter = IndexedCollection(iter);
+        if (iter.size === 0) {
+          return this;
+        }
+        if (this.size === 0 && isStack(iter)) {
+          return iter;
+        }
+        assertNotInfinite(iter.size);
+        var newSize = this.size;
+        var head = this._head;
+        iter.__iterate(function (value) {
+          newSize++;
+          head = {
+            value: value,
+            next: head,
+          };
+        }, /* reverse */ true);
+        if (this.__ownerID) {
+          this.size = newSize;
+          this._head = head;
+          this.__hash = undefined;
+          this.__altered = true;
+          return this;
+        }
+        return makeStack(newSize, head);
+      };
+
+      Stack.prototype.pop = function pop () {
+        return this.slice(1);
+      };
+
+      Stack.prototype.clear = function clear () {
+        if (this.size === 0) {
+          return this;
+        }
+        if (this.__ownerID) {
+          this.size = 0;
+          this._head = undefined;
+          this.__hash = undefined;
+          this.__altered = true;
+          return this;
+        }
+        return emptyStack();
+      };
+
+      Stack.prototype.slice = function slice (begin, end) {
+        if (wholeSlice(begin, end, this.size)) {
+          return this;
+        }
+        var resolvedBegin = resolveBegin(begin, this.size);
+        var resolvedEnd = resolveEnd(end, this.size);
+        if (resolvedEnd !== this.size) {
+          // super.slice(begin, end);
+          return IndexedCollection.prototype.slice.call(this, begin, end);
+        }
+        var newSize = this.size - resolvedBegin;
+        var head = this._head;
+        while (resolvedBegin--) {
+          head = head.next;
+        }
+        if (this.__ownerID) {
+          this.size = newSize;
+          this._head = head;
+          this.__hash = undefined;
+          this.__altered = true;
+          return this;
+        }
+        return makeStack(newSize, head);
+      };
+
+      // @pragma Mutability
+
+      Stack.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+        if (ownerID === this.__ownerID) {
+          return this;
+        }
+        if (!ownerID) {
+          if (this.size === 0) {
+            return emptyStack();
+          }
+          this.__ownerID = ownerID;
+          this.__altered = false;
+          return this;
+        }
+        return makeStack(this.size, this._head, ownerID, this.__hash);
+      };
+
+      // @pragma Iteration
+
+      Stack.prototype.__iterate = function __iterate (fn, reverse) {
+        var this$1$1 = this;
+
+        if (reverse) {
+          return new ArraySeq(this.toArray()).__iterate(
+            function (v, k) { return fn(v, k, this$1$1); },
+            reverse
+          );
+        }
+        var iterations = 0;
+        var node = this._head;
+        while (node) {
+          if (fn(node.value, iterations++, this) === false) {
+            break;
+          }
+          node = node.next;
+        }
+        return iterations;
+      };
+
+      Stack.prototype.__iterator = function __iterator (type, reverse) {
+        if (reverse) {
+          return new ArraySeq(this.toArray()).__iterator(type, reverse);
+        }
+        var iterations = 0;
+        var node = this._head;
+        return new Iterator(function () {
+          if (node) {
+            var value = node.value;
+            node = node.next;
+            return iteratorValue(type, iterations++, value);
+          }
+          return iteratorDone();
+        });
+      };
+
+      return Stack;
+    }(IndexedCollection));
+
+    Stack.isStack = isStack;
+
+    var StackPrototype = Stack.prototype;
+    StackPrototype[IS_STACK_SYMBOL] = true;
+    StackPrototype.shift = StackPrototype.pop;
+    StackPrototype.unshift = StackPrototype.push;
+    StackPrototype.unshiftAll = StackPrototype.pushAll;
+    StackPrototype.withMutations = withMutations;
+    StackPrototype.wasAltered = wasAltered;
+    StackPrototype.asImmutable = asImmutable;
+    StackPrototype['@@transducer/init'] = StackPrototype.asMutable = asMutable;
+    StackPrototype['@@transducer/step'] = function (result, arr) {
+      return result.unshift(arr);
+    };
+    StackPrototype['@@transducer/result'] = function (obj) {
+      return obj.asImmutable();
+    };
+
+    function makeStack(size, head, ownerID, hash) {
+      var map = Object.create(StackPrototype);
+      map.size = size;
+      map._head = head;
+      map.__ownerID = ownerID;
+      map.__hash = hash;
+      map.__altered = false;
+      return map;
+    }
+
+    var EMPTY_STACK;
+    function emptyStack() {
+      return EMPTY_STACK || (EMPTY_STACK = makeStack(0));
+    }
+
+    var IS_SET_SYMBOL = '@@__IMMUTABLE_SET__@@';
+    /**
+     * True if `maybeSet` is a Set.
+     *
+     * Also true for OrderedSets.
+     */
+    function isSet(maybeSet) {
+        return Boolean(maybeSet &&
+            // @ts-expect-error: maybeSet is typed as `{}`,  need to change in 6.0 to `maybeSeq && typeof maybeSet === 'object' && MAYBE_SET_SYMBOL in maybeSet`
+            maybeSet[IS_SET_SYMBOL]);
+    }
+
+    /**
+     * True if `maybeOrderedSet` is an OrderedSet.
+     */
+    function isOrderedSet(maybeOrderedSet) {
+        return isSet(maybeOrderedSet) && isOrdered(maybeOrderedSet);
+    }
+
+    function deepEqual(a, b) {
+        if (a === b) {
+            return true;
+        }
+        if (!isCollection(b) ||
+            // @ts-expect-error size should exists on Collection
+            (a.size !== undefined && b.size !== undefined && a.size !== b.size) ||
+            // @ts-expect-error __hash exists on Collection
+            (a.__hash !== undefined &&
+                // @ts-expect-error __hash exists on Collection
+                b.__hash !== undefined &&
+                // @ts-expect-error __hash exists on Collection
+                a.__hash !== b.__hash) ||
+            isKeyed(a) !== isKeyed(b) ||
+            isIndexed(a) !== isIndexed(b) ||
+            // @ts-expect-error Range extends Collection, which implements [Symbol.iterator], so it is valid
+            isOrdered(a) !== isOrdered(b)) {
+            return false;
+        }
+        // @ts-expect-error size should exists on Collection
+        if (a.size === 0 && b.size === 0) {
+            return true;
+        }
+        var notAssociative = !isAssociative(a);
+        // @ts-expect-error Range extends Collection, which implements [Symbol.iterator], so it is valid
+        if (isOrdered(a)) {
+            var entries = a.entries();
+            // @ts-expect-error need to cast as boolean
+            return (b.every(function (v, k) {
+                var entry = entries.next().value;
+                return entry && is(entry[1], v) && (notAssociative || is(entry[0], k));
+            }) && entries.next().done);
+        }
+        var flipped = false;
+        if (a.size === undefined) {
+            // @ts-expect-error size should exists on Collection
+            if (b.size === undefined) {
+                if (typeof a.cacheResult === 'function') {
+                    a.cacheResult();
+                }
+            }
+            else {
+                flipped = true;
+                var _ = a;
+                a = b;
+                b = _;
+            }
+        }
+        var allEqual = true;
+        var bSize = 
+        // @ts-expect-error b is Range | Repeat | Collection<unknown, unknown> as it may have been flipped, and __iterate is valid
+        b.__iterate(function (v, k) {
+            if (notAssociative
+                ? // @ts-expect-error has exists on Collection
+                    !a.has(v)
+                : flipped
+                    ? // @ts-expect-error type of `get` does not "catch" the version with `notSetValue`
+                        !is(v, a.get(k, NOT_SET))
+                    : // @ts-expect-error type of `get` does not "catch" the version with `notSetValue`
+                        !is(a.get(k, NOT_SET), v)) {
+                allEqual = false;
+                return false;
+            }
+        });
+        return (allEqual &&
+            // @ts-expect-error size should exists on Collection
+            a.size === bSize);
+    }
+
+    /**
+     * Contributes additional methods to a constructor
+     */
+    function mixin(ctor, 
+    // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
+    methods) {
+        var keyCopier = function (key) {
+            // @ts-expect-error how to handle symbol ?
+            ctor.prototype[key] = methods[key];
+        };
+        Object.keys(methods).forEach(keyCopier);
+        // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+        Object.getOwnPropertySymbols &&
+            Object.getOwnPropertySymbols(methods).forEach(keyCopier);
+        return ctor;
+    }
+
+    function toJS(value) {
+      if (!value || typeof value !== 'object') {
+        return value;
+      }
+      if (!isCollection(value)) {
+        if (!isDataStructure(value)) {
+          return value;
+        }
+        value = Seq(value);
+      }
+      if (isKeyed(value)) {
+        var result$1 = {};
+        value.__iterate(function (v, k) {
+          result$1[k] = toJS(v);
+        });
+        return result$1;
+      }
+      var result = [];
+      value.__iterate(function (v) {
+        result.push(toJS(v));
+      });
+      return result;
+    }
+
+    var Set = /*@__PURE__*/(function (SetCollection) {
+      function Set(value) {
+        // eslint-disable-next-line no-constructor-return
+        return value === undefined || value === null
+          ? emptySet()
+          : isSet(value) && !isOrdered(value)
+            ? value
+            : emptySet().withMutations(function (set) {
+                var iter = SetCollection(value);
+                assertNotInfinite(iter.size);
+                iter.forEach(function (v) { return set.add(v); });
+              });
+      }
+
+      if ( SetCollection ) Set.__proto__ = SetCollection;
+      Set.prototype = Object.create( SetCollection && SetCollection.prototype );
+      Set.prototype.constructor = Set;
+
+      Set.of = function of (/*...values*/) {
+        return this(arguments);
+      };
+
+      Set.fromKeys = function fromKeys (value) {
+        return this(KeyedCollection(value).keySeq());
+      };
+
+      Set.intersect = function intersect (sets) {
+        sets = Collection(sets).toArray();
+        return sets.length
+          ? SetPrototype.intersect.apply(Set(sets.pop()), sets)
+          : emptySet();
+      };
+
+      Set.union = function union (sets) {
+        sets = Collection(sets).toArray();
+        return sets.length
+          ? SetPrototype.union.apply(Set(sets.pop()), sets)
+          : emptySet();
+      };
+
+      Set.prototype.toString = function toString () {
+        return this.__toString('Set {', '}');
+      };
+
+      // @pragma Access
+
+      Set.prototype.has = function has (value) {
+        return this._map.has(value);
+      };
+
+      // @pragma Modification
+
+      Set.prototype.add = function add (value) {
+        return updateSet(this, this._map.set(value, value));
+      };
+
+      Set.prototype.remove = function remove (value) {
+        return updateSet(this, this._map.remove(value));
+      };
+
+      Set.prototype.clear = function clear () {
+        return updateSet(this, this._map.clear());
+      };
+
+      // @pragma Composition
+
+      Set.prototype.map = function map (mapper, context) {
+        var this$1$1 = this;
+
+        // keep track if the set is altered by the map function
+        var didChanges = false;
+
+        var newMap = updateSet(
+          this,
+          this._map.mapEntries(function (ref) {
+            var v = ref[1];
+
+            var mapped = mapper.call(context, v, v, this$1$1);
+
+            if (mapped !== v) {
+              didChanges = true;
+            }
+
+            return [mapped, mapped];
+          }, context)
+        );
+
+        return didChanges ? newMap : this;
+      };
+
+      Set.prototype.union = function union () {
+        var iters = [], len = arguments.length;
+        while ( len-- ) iters[ len ] = arguments[ len ];
+
+        iters = iters.filter(function (x) { return x.size !== 0; });
+        if (iters.length === 0) {
+          return this;
+        }
+        if (this.size === 0 && !this.__ownerID && iters.length === 1) {
+          return this.constructor(iters[0]);
+        }
+        return this.withMutations(function (set) {
+          for (var ii = 0; ii < iters.length; ii++) {
+            if (typeof iters[ii] === 'string') {
+              set.add(iters[ii]);
+            } else {
+              SetCollection(iters[ii]).forEach(function (value) { return set.add(value); });
+            }
+          }
+        });
+      };
+
+      Set.prototype.intersect = function intersect () {
+        var iters = [], len = arguments.length;
+        while ( len-- ) iters[ len ] = arguments[ len ];
+
+        if (iters.length === 0) {
+          return this;
+        }
+        iters = iters.map(function (iter) { return SetCollection(iter); });
+        var toRemove = [];
+        this.forEach(function (value) {
+          if (!iters.every(function (iter) { return iter.includes(value); })) {
+            toRemove.push(value);
+          }
+        });
+        return this.withMutations(function (set) {
+          toRemove.forEach(function (value) {
+            set.remove(value);
+          });
+        });
+      };
+
+      Set.prototype.subtract = function subtract () {
+        var iters = [], len = arguments.length;
+        while ( len-- ) iters[ len ] = arguments[ len ];
+
+        if (iters.length === 0) {
+          return this;
+        }
+        iters = iters.map(function (iter) { return SetCollection(iter); });
+        var toRemove = [];
+        this.forEach(function (value) {
+          if (iters.some(function (iter) { return iter.includes(value); })) {
+            toRemove.push(value);
+          }
+        });
+        return this.withMutations(function (set) {
+          toRemove.forEach(function (value) {
+            set.remove(value);
+          });
+        });
+      };
+
+      Set.prototype.sort = function sort (comparator) {
+        // Late binding
+        return OrderedSet(sortFactory(this, comparator));
+      };
+
+      Set.prototype.sortBy = function sortBy (mapper, comparator) {
+        // Late binding
+        return OrderedSet(sortFactory(this, comparator, mapper));
+      };
+
+      Set.prototype.wasAltered = function wasAltered () {
+        return this._map.wasAltered();
+      };
+
+      Set.prototype.__iterate = function __iterate (fn, reverse) {
+        var this$1$1 = this;
+
+        return this._map.__iterate(function (k) { return fn(k, k, this$1$1); }, reverse);
+      };
+
+      Set.prototype.__iterator = function __iterator (type, reverse) {
+        return this._map.__iterator(type, reverse);
+      };
+
+      Set.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+        if (ownerID === this.__ownerID) {
+          return this;
+        }
+        var newMap = this._map.__ensureOwner(ownerID);
+        if (!ownerID) {
+          if (this.size === 0) {
+            return this.__empty();
+          }
+          this.__ownerID = ownerID;
+          this._map = newMap;
+          return this;
+        }
+        return this.__make(newMap, ownerID);
+      };
+
+      return Set;
+    }(SetCollection));
+
+    Set.isSet = isSet;
+
+    var SetPrototype = Set.prototype;
+    SetPrototype[IS_SET_SYMBOL] = true;
+    SetPrototype[DELETE] = SetPrototype.remove;
+    SetPrototype.merge = SetPrototype.concat = SetPrototype.union;
+    SetPrototype.withMutations = withMutations;
+    SetPrototype.asImmutable = asImmutable;
+    SetPrototype['@@transducer/init'] = SetPrototype.asMutable = asMutable;
+    SetPrototype['@@transducer/step'] = function (result, arr) {
+      return result.add(arr);
+    };
+    SetPrototype['@@transducer/result'] = function (obj) {
+      return obj.asImmutable();
+    };
+
+    SetPrototype.__empty = emptySet;
+    SetPrototype.__make = makeSet;
+
+    function updateSet(set, newMap) {
+      if (set.__ownerID) {
+        set.size = newMap.size;
+        set._map = newMap;
+        return set;
+      }
+      return newMap === set._map
+        ? set
+        : newMap.size === 0
+          ? set.__empty()
+          : set.__make(newMap);
+    }
+
+    function makeSet(map, ownerID) {
+      var set = Object.create(SetPrototype);
+      set.size = map ? map.size : 0;
+      set._map = map;
+      set.__ownerID = ownerID;
+      return set;
+    }
+
+    var EMPTY_SET;
+    function emptySet() {
+      return EMPTY_SET || (EMPTY_SET = makeSet(emptyMap()));
+    }
+
+    /**
+     * Returns a lazy seq of nums from start (inclusive) to end
+     * (exclusive), by step, where start defaults to 0, step to 1, and end to
+     * infinity. When start is equal to end, returns empty list.
+     */
+    var Range = /*@__PURE__*/(function (IndexedSeq) {
+      function Range(start, end, step) {
+        if ( step === void 0 ) step = 1;
+
+        if (!(this instanceof Range)) {
+          // eslint-disable-next-line no-constructor-return
+          return new Range(start, end, step);
+        }
+        invariant(step !== 0, 'Cannot step a Range by 0');
+        invariant(
+          start !== undefined,
+          'You must define a start value when using Range'
+        );
+        invariant(
+          end !== undefined,
+          'You must define an end value when using Range'
+        );
+
+        step = Math.abs(step);
+        if (end < start) {
+          step = -step;
+        }
+        this._start = start;
+        this._end = end;
+        this._step = step;
+        this.size = Math.max(0, Math.ceil((end - start) / step - 1) + 1);
+        if (this.size === 0) {
+          if (EMPTY_RANGE) {
+            // eslint-disable-next-line no-constructor-return
+            return EMPTY_RANGE;
+          }
+          // eslint-disable-next-line @typescript-eslint/no-this-alias
+          EMPTY_RANGE = this;
+        }
+      }
+
+      if ( IndexedSeq ) Range.__proto__ = IndexedSeq;
+      Range.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
+      Range.prototype.constructor = Range;
+
+      Range.prototype.toString = function toString () {
+        return this.size === 0
+          ? 'Range []'
+          : ("Range [ " + (this._start) + "..." + (this._end) + (this._step !== 1 ? ' by ' + this._step : '') + " ]");
+      };
+
+      Range.prototype.get = function get (index, notSetValue) {
+        return this.has(index)
+          ? this._start + wrapIndex(this, index) * this._step
+          : notSetValue;
+      };
+
+      Range.prototype.includes = function includes (searchValue) {
+        var possibleIndex = (searchValue - this._start) / this._step;
+        return (
+          possibleIndex >= 0 &&
+          possibleIndex < this.size &&
+          possibleIndex === Math.floor(possibleIndex)
+        );
+      };
+
+      Range.prototype.slice = function slice (begin, end) {
+        if (wholeSlice(begin, end, this.size)) {
+          return this;
+        }
+        begin = resolveBegin(begin, this.size);
+        end = resolveEnd(end, this.size);
+        if (end <= begin) {
+          return new Range(0, 0);
+        }
+        return new Range(
+          this.get(begin, this._end),
+          this.get(end, this._end),
+          this._step
+        );
+      };
+
+      Range.prototype.indexOf = function indexOf (searchValue) {
+        var offsetValue = searchValue - this._start;
+        if (offsetValue % this._step === 0) {
+          var index = offsetValue / this._step;
+          if (index >= 0 && index < this.size) {
+            return index;
+          }
+        }
+        return -1;
+      };
+
+      Range.prototype.lastIndexOf = function lastIndexOf (searchValue) {
+        return this.indexOf(searchValue);
+      };
+
+      Range.prototype.__iterate = function __iterate (fn, reverse) {
+        var size = this.size;
+        var step = this._step;
+        var value = reverse ? this._start + (size - 1) * step : this._start;
+        var i = 0;
+        while (i !== size) {
+          if (fn(value, reverse ? size - ++i : i++, this) === false) {
+            break;
+          }
+          value += reverse ? -step : step;
+        }
+        return i;
+      };
+
+      Range.prototype.__iterator = function __iterator (type, reverse) {
+        var size = this.size;
+        var step = this._step;
+        var value = reverse ? this._start + (size - 1) * step : this._start;
+        var i = 0;
+        return new Iterator(function () {
+          if (i === size) {
+            return iteratorDone();
+          }
+          var v = value;
+          value += reverse ? -step : step;
+          return iteratorValue(type, reverse ? size - ++i : i++, v);
+        });
+      };
+
+      Range.prototype.equals = function equals (other) {
+        return other instanceof Range
+          ? this._start === other._start &&
+              this._end === other._end &&
+              this._step === other._step
+          : deepEqual(this, other);
+      };
+
+      return Range;
+    }(IndexedSeq));
+
+    var EMPTY_RANGE;
+
+    /**
+     * Returns the value at the provided key path starting at the provided
+     * collection, or notSetValue if the key path is not defined.
+     *
+     * A functional alternative to `collection.getIn(keypath)` which will also
+     * work with plain Objects and Arrays.
+     */
+    function getIn$1(collection, searchKeyPath, notSetValue) {
+        var keyPath = coerceKeyPath(searchKeyPath);
+        var i = 0;
+        while (i !== keyPath.length) {
+            // @ts-expect-error keyPath[i++] can not be undefined by design
+            collection = get(collection, keyPath[i++], NOT_SET);
+            if (collection === NOT_SET) {
+                return notSetValue;
+            }
+        }
+        return collection;
+    }
+
+    function getIn(searchKeyPath, notSetValue) {
+      return getIn$1(this, searchKeyPath, notSetValue);
+    }
+
+    /**
+     * Returns true if the key path is defined in the provided collection.
+     *
+     * A functional alternative to `collection.hasIn(keypath)` which will also
+     * work with plain Objects and Arrays.
+     */
+    function hasIn$1(collection, keyPath) {
+        return getIn$1(collection, keyPath, NOT_SET) !== NOT_SET;
+    }
+
+    function hasIn(searchKeyPath) {
+      return hasIn$1(this, searchKeyPath);
+    }
+
+    function toObject() {
+      assertNotInfinite(this.size);
+      var object = {};
+      this.__iterate(function (v, k) {
+        object[k] = v;
+      });
+      return object;
+    }
+
+    Collection.Iterator = Iterator;
+
+    mixin(Collection, {
+      // ### Conversion to other types
+
+      toArray: function toArray() {
+        assertNotInfinite(this.size);
+        var array = new Array(this.size || 0);
+        var useTuples = isKeyed(this);
+        var i = 0;
+        this.__iterate(function (v, k) {
+          // Keyed collections produce an array of tuples.
+          array[i++] = useTuples ? [k, v] : v;
+        });
+        return array;
+      },
+
+      toIndexedSeq: function toIndexedSeq() {
+        return new ToIndexedSequence(this);
+      },
+
+      toJS: function toJS$1() {
+        return toJS(this);
+      },
+
+      toKeyedSeq: function toKeyedSeq() {
+        return new ToKeyedSequence(this, true);
+      },
+
+      toMap: function toMap() {
+        // Use Late Binding here to solve the circular dependency.
+        return Map(this.toKeyedSeq());
+      },
+
+      toObject: toObject,
+
+      toOrderedMap: function toOrderedMap() {
+        // Use Late Binding here to solve the circular dependency.
+        return OrderedMap(this.toKeyedSeq());
+      },
+
+      toOrderedSet: function toOrderedSet() {
+        // Use Late Binding here to solve the circular dependency.
+        return OrderedSet(isKeyed(this) ? this.valueSeq() : this);
+      },
+
+      toSet: function toSet() {
+        // Use Late Binding here to solve the circular dependency.
+        return Set(isKeyed(this) ? this.valueSeq() : this);
+      },
+
+      toSetSeq: function toSetSeq() {
+        return new ToSetSequence(this);
+      },
+
+      toSeq: function toSeq() {
+        return isIndexed(this)
+          ? this.toIndexedSeq()
+          : isKeyed(this)
+            ? this.toKeyedSeq()
+            : this.toSetSeq();
+      },
+
+      toStack: function toStack() {
+        // Use Late Binding here to solve the circular dependency.
+        return Stack(isKeyed(this) ? this.valueSeq() : this);
+      },
+
+      toList: function toList() {
+        // Use Late Binding here to solve the circular dependency.
+        return List(isKeyed(this) ? this.valueSeq() : this);
+      },
+
+      // ### Common JavaScript methods and properties
+
+      toString: function toString() {
+        return '[Collection]';
+      },
+
+      __toString: function __toString(head, tail) {
+        if (this.size === 0) {
+          return head + tail;
+        }
+        return (
+          head +
+          ' ' +
+          this.toSeq().map(this.__toStringMapper).join(', ') +
+          ' ' +
+          tail
+        );
+      },
+
+      // ### ES6 Collection methods (ES6 Array and Map)
+
+      concat: function concat() {
+        var values = [], len = arguments.length;
+        while ( len-- ) values[ len ] = arguments[ len ];
+
+        return reify(this, concatFactory(this, values));
+      },
+
+      includes: function includes(searchValue) {
+        return this.some(function (value) { return is(value, searchValue); });
+      },
+
+      entries: function entries() {
+        return this.__iterator(ITERATE_ENTRIES);
+      },
+
+      every: function every(predicate, context) {
+        assertNotInfinite(this.size);
+        var returnValue = true;
+        this.__iterate(function (v, k, c) {
+          if (!predicate.call(context, v, k, c)) {
+            returnValue = false;
+            return false;
+          }
+        });
+        return returnValue;
+      },
+
+      filter: function filter(predicate, context) {
+        return reify(this, filterFactory(this, predicate, context, true));
+      },
+
+      partition: function partition(predicate, context) {
+        return partitionFactory(this, predicate, context);
+      },
+
+      find: function find(predicate, context, notSetValue) {
+        var entry = this.findEntry(predicate, context);
+        return entry ? entry[1] : notSetValue;
+      },
+
+      forEach: function forEach(sideEffect, context) {
+        assertNotInfinite(this.size);
+        return this.__iterate(context ? sideEffect.bind(context) : sideEffect);
+      },
+
+      join: function join(separator) {
+        assertNotInfinite(this.size);
+        separator = separator !== undefined ? '' + separator : ',';
+        var joined = '';
+        var isFirst = true;
+        this.__iterate(function (v) {
+          // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+          isFirst ? (isFirst = false) : (joined += separator);
+          joined += v !== null && v !== undefined ? v.toString() : '';
+        });
+        return joined;
+      },
+
+      keys: function keys() {
+        return this.__iterator(ITERATE_KEYS);
+      },
+
+      map: function map(mapper, context) {
+        return reify(this, mapFactory(this, mapper, context));
+      },
+
+      reduce: function reduce$1(reducer, initialReduction, context) {
+        return reduce(
+          this,
+          reducer,
+          initialReduction,
+          context,
+          arguments.length < 2,
+          false
+        );
+      },
+
+      reduceRight: function reduceRight(reducer, initialReduction, context) {
+        return reduce(
+          this,
+          reducer,
+          initialReduction,
+          context,
+          arguments.length < 2,
+          true
+        );
+      },
+
+      reverse: function reverse() {
+        return reify(this, reverseFactory(this, true));
+      },
+
+      slice: function slice(begin, end) {
+        return reify(this, sliceFactory(this, begin, end, true));
+      },
+
+      some: function some(predicate, context) {
+        assertNotInfinite(this.size);
+        var returnValue = false;
+        this.__iterate(function (v, k, c) {
+          if (predicate.call(context, v, k, c)) {
+            returnValue = true;
+            return false;
+          }
+        });
+        return returnValue;
+      },
+
+      sort: function sort(comparator) {
+        return reify(this, sortFactory(this, comparator));
+      },
+
+      values: function values() {
+        return this.__iterator(ITERATE_VALUES);
+      },
+
+      // ### More sequential methods
+
+      butLast: function butLast() {
+        return this.slice(0, -1);
+      },
+
+      isEmpty: function isEmpty() {
+        return this.size !== undefined ? this.size === 0 : !this.some(function () { return true; });
+      },
+
+      count: function count(predicate, context) {
+        return ensureSize(
+          predicate ? this.toSeq().filter(predicate, context) : this
+        );
+      },
+
+      countBy: function countBy(grouper, context) {
+        return countByFactory(this, grouper, context);
+      },
+
+      equals: function equals(other) {
+        return deepEqual(this, other);
+      },
+
+      entrySeq: function entrySeq() {
+        // eslint-disable-next-line @typescript-eslint/no-this-alias
+        var collection = this;
+        if (collection._cache) {
+          // We cache as an entries array, so we can just return the cache!
+          return new ArraySeq(collection._cache);
+        }
+        var entriesSequence = collection.toSeq().map(entryMapper).toIndexedSeq();
+        entriesSequence.fromEntrySeq = function () { return collection.toSeq(); };
+        return entriesSequence;
+      },
+
+      filterNot: function filterNot(predicate, context) {
+        return this.filter(not(predicate), context);
+      },
+
+      findEntry: function findEntry(predicate, context, notSetValue) {
+        var found = notSetValue;
+        this.__iterate(function (v, k, c) {
+          if (predicate.call(context, v, k, c)) {
+            found = [k, v];
+            return false;
+          }
+        });
+        return found;
+      },
+
+      findKey: function findKey(predicate, context) {
+        var entry = this.findEntry(predicate, context);
+        return entry && entry[0];
+      },
+
+      findLast: function findLast(predicate, context, notSetValue) {
+        return this.toKeyedSeq().reverse().find(predicate, context, notSetValue);
+      },
+
+      findLastEntry: function findLastEntry(predicate, context, notSetValue) {
+        return this.toKeyedSeq()
+          .reverse()
+          .findEntry(predicate, context, notSetValue);
+      },
+
+      findLastKey: function findLastKey(predicate, context) {
+        return this.toKeyedSeq().reverse().findKey(predicate, context);
+      },
+
+      first: function first(notSetValue) {
+        return this.find(returnTrue, null, notSetValue);
+      },
+
+      flatMap: function flatMap(mapper, context) {
+        return reify(this, flatMapFactory(this, mapper, context));
+      },
+
+      flatten: function flatten(depth) {
+        return reify(this, flattenFactory(this, depth, true));
+      },
+
+      fromEntrySeq: function fromEntrySeq() {
+        return new FromEntriesSequence(this);
+      },
+
+      get: function get(searchKey, notSetValue) {
+        return this.find(function (_, key) { return is(key, searchKey); }, undefined, notSetValue);
+      },
+
+      getIn: getIn,
+
+      groupBy: function groupBy(grouper, context) {
+        return groupByFactory(this, grouper, context);
+      },
+
+      has: function has(searchKey) {
+        return this.get(searchKey, NOT_SET) !== NOT_SET;
+      },
+
+      hasIn: hasIn,
+
+      isSubset: function isSubset(iter) {
+        iter = typeof iter.includes === 'function' ? iter : Collection(iter);
+        return this.every(function (value) { return iter.includes(value); });
+      },
+
+      isSuperset: function isSuperset(iter) {
+        iter = typeof iter.isSubset === 'function' ? iter : Collection(iter);
+        return iter.isSubset(this);
+      },
+
+      keyOf: function keyOf(searchValue) {
+        return this.findKey(function (value) { return is(value, searchValue); });
+      },
+
+      keySeq: function keySeq() {
+        return this.toSeq().map(keyMapper).toIndexedSeq();
+      },
+
+      last: function last(notSetValue) {
+        return this.toSeq().reverse().first(notSetValue);
+      },
+
+      lastKeyOf: function lastKeyOf(searchValue) {
+        return this.toKeyedSeq().reverse().keyOf(searchValue);
+      },
+
+      max: function max(comparator) {
+        return maxFactory(this, comparator);
+      },
+
+      maxBy: function maxBy(mapper, comparator) {
+        return maxFactory(this, comparator, mapper);
+      },
+
+      min: function min(comparator) {
+        return maxFactory(
+          this,
+          comparator ? neg(comparator) : defaultNegComparator
+        );
+      },
+
+      minBy: function minBy(mapper, comparator) {
+        return maxFactory(
+          this,
+          comparator ? neg(comparator) : defaultNegComparator,
+          mapper
+        );
+      },
+
+      rest: function rest() {
+        return this.slice(1);
+      },
+
+      skip: function skip(amount) {
+        return amount === 0 ? this : this.slice(Math.max(0, amount));
+      },
+
+      skipLast: function skipLast(amount) {
+        return amount === 0 ? this : this.slice(0, -Math.max(0, amount));
+      },
+
+      skipWhile: function skipWhile(predicate, context) {
+        return reify(this, skipWhileFactory(this, predicate, context, true));
+      },
+
+      skipUntil: function skipUntil(predicate, context) {
+        return this.skipWhile(not(predicate), context);
+      },
+
+      sortBy: function sortBy(mapper, comparator) {
+        return reify(this, sortFactory(this, comparator, mapper));
+      },
+
+      take: function take(amount) {
+        return this.slice(0, Math.max(0, amount));
+      },
+
+      takeLast: function takeLast(amount) {
+        return this.slice(-Math.max(0, amount));
+      },
+
+      takeWhile: function takeWhile(predicate, context) {
+        return reify(this, takeWhileFactory(this, predicate, context));
+      },
+
+      takeUntil: function takeUntil(predicate, context) {
+        return this.takeWhile(not(predicate), context);
+      },
+
+      update: function update(fn) {
+        return fn(this);
+      },
+
+      valueSeq: function valueSeq() {
+        return this.toIndexedSeq();
+      },
+
+      // ### Hashable Object
+
+      hashCode: function hashCode() {
+        return this.__hash || (this.__hash = hashCollection(this));
+      },
+
+      // ### Internal
+
+      // abstract __iterate(fn, reverse)
+
+      // abstract __iterator(type, reverse)
+    });
+
+    var CollectionPrototype = Collection.prototype;
+    CollectionPrototype[IS_COLLECTION_SYMBOL] = true;
+    CollectionPrototype[ITERATOR_SYMBOL] = CollectionPrototype.values;
+    CollectionPrototype.toJSON = CollectionPrototype.toArray;
+    CollectionPrototype.__toStringMapper = quoteString;
+    CollectionPrototype.inspect = CollectionPrototype.toSource = function () {
+      return this.toString();
+    };
+    CollectionPrototype.chain = CollectionPrototype.flatMap;
+    CollectionPrototype.contains = CollectionPrototype.includes;
+
+    mixin(KeyedCollection, {
+      // ### More sequential methods
+
+      flip: function flip() {
+        return reify(this, flipFactory(this));
+      },
+
+      mapEntries: function mapEntries(mapper, context) {
+        var this$1$1 = this;
+
+        var iterations = 0;
+        return reify(
+          this,
+          this.toSeq()
+            .map(function (v, k) { return mapper.call(context, [k, v], iterations++, this$1$1); })
+            .fromEntrySeq()
+        );
+      },
+
+      mapKeys: function mapKeys(mapper, context) {
+        var this$1$1 = this;
+
+        return reify(
+          this,
+          this.toSeq()
+            .flip()
+            .map(function (k, v) { return mapper.call(context, k, v, this$1$1); })
+            .flip()
+        );
+      },
+    });
+
+    var KeyedCollectionPrototype = KeyedCollection.prototype;
+    KeyedCollectionPrototype[IS_KEYED_SYMBOL] = true;
+    KeyedCollectionPrototype[ITERATOR_SYMBOL] = CollectionPrototype.entries;
+    KeyedCollectionPrototype.toJSON = toObject;
+    KeyedCollectionPrototype.__toStringMapper = function (v, k) { return quoteString(k) + ': ' + quoteString(v); };
+
+    mixin(IndexedCollection, {
+      // ### Conversion to other types
+
+      toKeyedSeq: function toKeyedSeq() {
+        return new ToKeyedSequence(this, false);
+      },
+
+      // ### ES6 Collection methods (ES6 Array and Map)
+
+      filter: function filter(predicate, context) {
+        return reify(this, filterFactory(this, predicate, context, false));
+      },
+
+      findIndex: function findIndex(predicate, context) {
+        var entry = this.findEntry(predicate, context);
+        return entry ? entry[0] : -1;
+      },
+
+      indexOf: function indexOf(searchValue) {
+        var key = this.keyOf(searchValue);
+        return key === undefined ? -1 : key;
+      },
+
+      lastIndexOf: function lastIndexOf(searchValue) {
+        var key = this.lastKeyOf(searchValue);
+        return key === undefined ? -1 : key;
+      },
+
+      reverse: function reverse() {
+        return reify(this, reverseFactory(this, false));
+      },
+
+      slice: function slice(begin, end) {
+        return reify(this, sliceFactory(this, begin, end, false));
+      },
+
+      splice: function splice(index, removeNum /*, ...values*/) {
+        var numArgs = arguments.length;
+        removeNum = Math.max(removeNum || 0, 0);
+        if (numArgs === 0 || (numArgs === 2 && !removeNum)) {
+          return this;
+        }
+        // If index is negative, it should resolve relative to the size of the
+        // collection. However size may be expensive to compute if not cached, so
+        // only call count() if the number is in fact negative.
+        index = resolveBegin(index, index < 0 ? this.count() : this.size);
+        var spliced = this.slice(0, index);
+        return reify(
+          this,
+          numArgs === 1
+            ? spliced
+            : spliced.concat(arrCopy(arguments, 2), this.slice(index + removeNum))
+        );
+      },
+
+      // ### More collection methods
+
+      findLastIndex: function findLastIndex(predicate, context) {
+        var entry = this.findLastEntry(predicate, context);
+        return entry ? entry[0] : -1;
+      },
+
+      first: function first(notSetValue) {
+        return this.get(0, notSetValue);
+      },
+
+      flatten: function flatten(depth) {
+        return reify(this, flattenFactory(this, depth, false));
+      },
+
+      get: function get(index, notSetValue) {
+        index = wrapIndex(this, index);
+        return index < 0 ||
+          this.size === Infinity ||
+          (this.size !== undefined && index > this.size)
+          ? notSetValue
+          : this.find(function (_, key) { return key === index; }, undefined, notSetValue);
+      },
+
+      has: function has(index) {
+        index = wrapIndex(this, index);
+        return (
+          index >= 0 &&
+          (this.size !== undefined
+            ? this.size === Infinity || index < this.size
+            : this.indexOf(index) !== -1)
+        );
+      },
+
+      interpose: function interpose(separator) {
+        return reify(this, interposeFactory(this, separator));
+      },
+
+      interleave: function interleave(/*...collections*/) {
+        var collections = [this].concat(arrCopy(arguments));
+        var zipped = zipWithFactory(this.toSeq(), IndexedSeq.of, collections);
+        var interleaved = zipped.flatten(true);
+        if (zipped.size) {
+          interleaved.size = zipped.size * collections.length;
+        }
+        return reify(this, interleaved);
+      },
+
+      keySeq: function keySeq() {
+        return Range(0, this.size);
+      },
+
+      last: function last(notSetValue) {
+        return this.get(-1, notSetValue);
+      },
+
+      skipWhile: function skipWhile(predicate, context) {
+        return reify(this, skipWhileFactory(this, predicate, context, false));
+      },
+
+      zip: function zip(/*, ...collections */) {
+        var collections = [this].concat(arrCopy(arguments));
+        return reify(this, zipWithFactory(this, defaultZipper, collections));
+      },
+
+      zipAll: function zipAll(/*, ...collections */) {
+        var collections = [this].concat(arrCopy(arguments));
+        return reify(this, zipWithFactory(this, defaultZipper, collections, true));
+      },
+
+      zipWith: function zipWith(zipper /*, ...collections */) {
+        var collections = arrCopy(arguments);
+        collections[0] = this;
+        return reify(this, zipWithFactory(this, zipper, collections));
+      },
+    });
+
+    var IndexedCollectionPrototype = IndexedCollection.prototype;
+    IndexedCollectionPrototype[IS_INDEXED_SYMBOL] = true;
+    IndexedCollectionPrototype[IS_ORDERED_SYMBOL] = true;
+
+    mixin(SetCollection, {
+      // ### ES6 Collection methods (ES6 Array and Map)
+
+      get: function get(value, notSetValue) {
+        return this.has(value) ? value : notSetValue;
+      },
+
+      includes: function includes(value) {
+        return this.has(value);
+      },
+
+      // ### More sequential methods
+
+      keySeq: function keySeq() {
+        return this.valueSeq();
+      },
+    });
+
+    var SetCollectionPrototype = SetCollection.prototype;
+    SetCollectionPrototype.has = CollectionPrototype.includes;
+    SetCollectionPrototype.contains = SetCollectionPrototype.includes;
+    SetCollectionPrototype.keys = SetCollectionPrototype.values;
+
+    // Mixin subclasses
+
+    mixin(KeyedSeq, KeyedCollectionPrototype);
+    mixin(IndexedSeq, IndexedCollectionPrototype);
+    mixin(SetSeq, SetCollectionPrototype);
+
+    // #pragma Helper functions
+
+    function reduce(collection, reducer, reduction, context, useFirst, reverse) {
+      assertNotInfinite(collection.size);
+      collection.__iterate(function (v, k, c) {
+        if (useFirst) {
+          useFirst = false;
+          reduction = v;
+        } else {
+          reduction = reducer.call(context, reduction, v, k, c);
+        }
+      }, reverse);
+      return reduction;
+    }
+
+    function keyMapper(v, k) {
+      return k;
+    }
+
+    function entryMapper(v, k) {
+      return [k, v];
+    }
+
+    function not(predicate) {
+      return function () {
+        return !predicate.apply(this, arguments);
+      };
+    }
+
+    function neg(predicate) {
+      return function () {
+        return -predicate.apply(this, arguments);
+      };
+    }
+
+    function defaultZipper() {
+      return arrCopy(arguments);
+    }
+
+    function defaultNegComparator(a, b) {
+      return a < b ? 1 : a > b ? -1 : 0;
+    }
+
+    function hashCollection(collection) {
+      if (collection.size === Infinity) {
+        return 0;
+      }
+      var ordered = isOrdered(collection);
+      var keyed = isKeyed(collection);
+      var h = ordered ? 1 : 0;
+
+      collection.__iterate(
+        keyed
+          ? ordered
+            ? function (v, k) {
+                h = (31 * h + hashMerge(hash(v), hash(k))) | 0;
+              }
+            : function (v, k) {
+                h = (h + hashMerge(hash(v), hash(k))) | 0;
+              }
+          : ordered
+            ? function (v) {
+                h = (31 * h + hash(v)) | 0;
+              }
+            : function (v) {
+                h = (h + hash(v)) | 0;
+              }
+      );
+
+      return murmurHashOfSize(collection.size, h);
+    }
+
+    function murmurHashOfSize(size, h) {
+      h = imul(h, 0xcc9e2d51);
+      h = imul((h << 15) | (h >>> -15), 0x1b873593);
+      h = imul((h << 13) | (h >>> -13), 5);
+      h = ((h + 0xe6546b64) | 0) ^ size;
+      h = imul(h ^ (h >>> 16), 0x85ebca6b);
+      h = imul(h ^ (h >>> 13), 0xc2b2ae35);
+      h = smi(h ^ (h >>> 16));
+      return h;
+    }
+
+    function hashMerge(a, b) {
+      return (a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2))) | 0; // int
+    }
+
+    var OrderedSet = /*@__PURE__*/(function (Set) {
+      function OrderedSet(value) {
+        // eslint-disable-next-line no-constructor-return
+        return value === undefined || value === null
+          ? emptyOrderedSet()
+          : isOrderedSet(value)
+            ? value
+            : emptyOrderedSet().withMutations(function (set) {
+                var iter = SetCollection(value);
+                assertNotInfinite(iter.size);
+                iter.forEach(function (v) { return set.add(v); });
+              });
+      }
+
+      if ( Set ) OrderedSet.__proto__ = Set;
+      OrderedSet.prototype = Object.create( Set && Set.prototype );
+      OrderedSet.prototype.constructor = OrderedSet;
+
+      OrderedSet.of = function of (/*...values*/) {
+        return this(arguments);
+      };
+
+      OrderedSet.fromKeys = function fromKeys (value) {
+        return this(KeyedCollection(value).keySeq());
+      };
+
+      OrderedSet.prototype.toString = function toString () {
+        return this.__toString('OrderedSet {', '}');
+      };
+
+      return OrderedSet;
+    }(Set));
+
+    OrderedSet.isOrderedSet = isOrderedSet;
+
+    var OrderedSetPrototype = OrderedSet.prototype;
+    OrderedSetPrototype[IS_ORDERED_SYMBOL] = true;
+    OrderedSetPrototype.zip = IndexedCollectionPrototype.zip;
+    OrderedSetPrototype.zipWith = IndexedCollectionPrototype.zipWith;
+    OrderedSetPrototype.zipAll = IndexedCollectionPrototype.zipAll;
+
+    OrderedSetPrototype.__empty = emptyOrderedSet;
+    OrderedSetPrototype.__make = makeOrderedSet;
+
+    function makeOrderedSet(map, ownerID) {
+      var set = Object.create(OrderedSetPrototype);
+      set.size = map ? map.size : 0;
+      set._map = map;
+      set.__ownerID = ownerID;
+      return set;
+    }
+
+    var EMPTY_ORDERED_SET;
+    function emptyOrderedSet() {
+      return (
+        EMPTY_ORDERED_SET || (EMPTY_ORDERED_SET = makeOrderedSet(emptyOrderedMap()))
+      );
+    }
+
+    var PairSorting = {
+      LeftThenRight: -1,
+      RightThenLeft: 1,
+    };
+
+    function throwOnInvalidDefaultValues(defaultValues) {
+      if (isRecord(defaultValues)) {
+        throw new Error(
+          'Can not call `Record` with an immutable Record as default values. Use a plain javascript object instead.'
+        );
+      }
+
+      if (isImmutable(defaultValues)) {
+        throw new Error(
+          'Can not call `Record` with an immutable Collection as default values. Use a plain javascript object instead.'
+        );
+      }
+
+      if (defaultValues === null || typeof defaultValues !== 'object') {
+        throw new Error(
+          'Can not call `Record` with a non-object as default values. Use a plain javascript object instead.'
+        );
+      }
+    }
+
+    var Record = function Record(defaultValues, name) {
+      var hasInitialized;
+
+      throwOnInvalidDefaultValues(defaultValues);
+
+      var RecordType = function Record(values) {
+        var this$1$1 = this;
+
+        if (values instanceof RecordType) {
+          return values;
+        }
+        if (!(this instanceof RecordType)) {
+          return new RecordType(values);
+        }
+        if (!hasInitialized) {
+          hasInitialized = true;
+          var keys = Object.keys(defaultValues);
+          var indices = (RecordTypePrototype._indices = {});
+          // Deprecated: left to attempt not to break any external code which
+          // relies on a ._name property existing on record instances.
+          // Use Record.getDescriptiveName() instead
+          RecordTypePrototype._name = name;
+          RecordTypePrototype._keys = keys;
+          RecordTypePrototype._defaultValues = defaultValues;
+          for (var i = 0; i < keys.length; i++) {
+            var propName = keys[i];
+            indices[propName] = i;
+            if (RecordTypePrototype[propName]) {
+              /* eslint-disable no-console */
+              // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+              typeof console === 'object' &&
+                console.warn &&
+                console.warn(
+                  'Cannot define ' +
+                    recordName(this) +
+                    ' with property "' +
+                    propName +
+                    '" since that property name is part of the Record API.'
+                );
+              /* eslint-enable no-console */
+            } else {
+              setProp(RecordTypePrototype, propName);
+            }
+          }
+        }
+        this.__ownerID = undefined;
+        this._values = List().withMutations(function (l) {
+          l.setSize(this$1$1._keys.length);
+          KeyedCollection(values).forEach(function (v, k) {
+            l.set(this$1$1._indices[k], v === this$1$1._defaultValues[k] ? undefined : v);
+          });
+        });
+        return this;
+      };
+
+      var RecordTypePrototype = (RecordType.prototype =
+        Object.create(RecordPrototype));
+      RecordTypePrototype.constructor = RecordType;
+
+      if (name) {
+        RecordType.displayName = name;
+      }
+
+      // eslint-disable-next-line no-constructor-return
+      return RecordType;
+    };
+
+    Record.prototype.toString = function toString () {
+      var str = recordName(this) + ' { ';
+      var keys = this._keys;
+      var k;
+      for (var i = 0, l = keys.length; i !== l; i++) {
+        k = keys[i];
+        str += (i ? ', ' : '') + k + ': ' + quoteString(this.get(k));
+      }
+      return str + ' }';
+    };
+
+    Record.prototype.equals = function equals (other) {
+      return (
+        this === other ||
+        (isRecord(other) && recordSeq(this).equals(recordSeq(other)))
+      );
+    };
+
+    Record.prototype.hashCode = function hashCode () {
+      return recordSeq(this).hashCode();
+    };
+
+    // @pragma Access
+
+    Record.prototype.has = function has (k) {
+      return this._indices.hasOwnProperty(k);
+    };
+
+    Record.prototype.get = function get (k, notSetValue) {
+      if (!this.has(k)) {
+        return notSetValue;
+      }
+      var index = this._indices[k];
+      var value = this._values.get(index);
+      return value === undefined ? this._defaultValues[k] : value;
+    };
+
+    // @pragma Modification
+
+    Record.prototype.set = function set (k, v) {
+      if (this.has(k)) {
+        var newValues = this._values.set(
+          this._indices[k],
+          v === this._defaultValues[k] ? undefined : v
+        );
+        if (newValues !== this._values && !this.__ownerID) {
+          return makeRecord(this, newValues);
+        }
+      }
+      return this;
+    };
+
+    Record.prototype.remove = function remove (k) {
+      return this.set(k);
+    };
+
+    Record.prototype.clear = function clear () {
+      var newValues = this._values.clear().setSize(this._keys.length);
+
+      return this.__ownerID ? this : makeRecord(this, newValues);
+    };
+
+    Record.prototype.wasAltered = function wasAltered () {
+      return this._values.wasAltered();
+    };
+
+    Record.prototype.toSeq = function toSeq () {
+      return recordSeq(this);
+    };
+
+    Record.prototype.toJS = function toJS$1 () {
+      return toJS(this);
+    };
+
+    Record.prototype.entries = function entries () {
+      return this.__iterator(ITERATE_ENTRIES);
+    };
+
+    Record.prototype.__iterator = function __iterator (type, reverse) {
+      return recordSeq(this).__iterator(type, reverse);
+    };
+
+    Record.prototype.__iterate = function __iterate (fn, reverse) {
+      return recordSeq(this).__iterate(fn, reverse);
+    };
+
+    Record.prototype.__ensureOwner = function __ensureOwner (ownerID) {
+      if (ownerID === this.__ownerID) {
+        return this;
+      }
+      var newValues = this._values.__ensureOwner(ownerID);
+      if (!ownerID) {
+        this.__ownerID = ownerID;
+        this._values = newValues;
+        return this;
+      }
+      return makeRecord(this, newValues, ownerID);
+    };
+
+    Record.isRecord = isRecord;
+    Record.getDescriptiveName = recordName;
+    var RecordPrototype = Record.prototype;
+    RecordPrototype[IS_RECORD_SYMBOL] = true;
+    RecordPrototype[DELETE] = RecordPrototype.remove;
+    RecordPrototype.deleteIn = RecordPrototype.removeIn = deleteIn;
+    RecordPrototype.getIn = getIn;
+    RecordPrototype.hasIn = CollectionPrototype.hasIn;
+    RecordPrototype.merge = merge$1;
+    RecordPrototype.mergeWith = mergeWith$1;
+    RecordPrototype.mergeIn = mergeIn;
+    RecordPrototype.mergeDeep = mergeDeep;
+    RecordPrototype.mergeDeepWith = mergeDeepWith;
+    RecordPrototype.mergeDeepIn = mergeDeepIn;
+    RecordPrototype.setIn = setIn;
+    RecordPrototype.update = update;
+    RecordPrototype.updateIn = updateIn;
+    RecordPrototype.withMutations = withMutations;
+    RecordPrototype.asMutable = asMutable;
+    RecordPrototype.asImmutable = asImmutable;
+    RecordPrototype[ITERATOR_SYMBOL] = RecordPrototype.entries;
+    RecordPrototype.toJSON = RecordPrototype.toObject =
+      CollectionPrototype.toObject;
+    RecordPrototype.inspect = RecordPrototype.toSource = function () {
+      return this.toString();
+    };
+
+    function makeRecord(likeRecord, values, ownerID) {
+      var record = Object.create(Object.getPrototypeOf(likeRecord));
+      record._values = values;
+      record.__ownerID = ownerID;
+      return record;
+    }
+
+    function recordName(record) {
+      return record.constructor.displayName || record.constructor.name || 'Record';
+    }
+
+    function recordSeq(record) {
+      return keyedSeqFromValue(record._keys.map(function (k) { return [k, record.get(k)]; }));
+    }
+
+    function setProp(prototype, name) {
+      try {
+        Object.defineProperty(prototype, name, {
+          get: function () {
+            return this.get(name);
+          },
+          set: function (value) {
+            invariant(this.__ownerID, 'Cannot set on an immutable record.');
+            this.set(name, value);
+          },
+        });
+        // eslint-disable-next-line @typescript-eslint/no-unused-vars -- TODO enable eslint here
+      } catch (error) {
+        // Object.defineProperty failed. Probably IE8.
+      }
+    }
+
+    /**
+     * Returns a lazy Seq of `value` repeated `times` times. When `times` is
+     * undefined, returns an infinite sequence of `value`.
+     */
+    var Repeat = /*@__PURE__*/(function (IndexedSeq) {
+      function Repeat(value, times) {
+        if (!(this instanceof Repeat)) {
+          // eslint-disable-next-line no-constructor-return
+          return new Repeat(value, times);
+        }
+        this._value = value;
+        this.size = times === undefined ? Infinity : Math.max(0, times);
+        if (this.size === 0) {
+          if (EMPTY_REPEAT) {
+            // eslint-disable-next-line no-constructor-return
+            return EMPTY_REPEAT;
+          }
+          // eslint-disable-next-line @typescript-eslint/no-this-alias
+          EMPTY_REPEAT = this;
+        }
+      }
+
+      if ( IndexedSeq ) Repeat.__proto__ = IndexedSeq;
+      Repeat.prototype = Object.create( IndexedSeq && IndexedSeq.prototype );
+      Repeat.prototype.constructor = Repeat;
+
+      Repeat.prototype.toString = function toString () {
+        if (this.size === 0) {
+          return 'Repeat []';
+        }
+        return 'Repeat [ ' + this._value + ' ' + this.size + ' times ]';
+      };
+
+      Repeat.prototype.get = function get (index, notSetValue) {
+        return this.has(index) ? this._value : notSetValue;
+      };
+
+      Repeat.prototype.includes = function includes (searchValue) {
+        return is(this._value, searchValue);
+      };
+
+      Repeat.prototype.slice = function slice (begin, end) {
+        var size = this.size;
+        return wholeSlice(begin, end, size)
+          ? this
+          : new Repeat(
+              this._value,
+              resolveEnd(end, size) - resolveBegin(begin, size)
+            );
+      };
+
+      Repeat.prototype.reverse = function reverse () {
+        return this;
+      };
+
+      Repeat.prototype.indexOf = function indexOf (searchValue) {
+        if (is(this._value, searchValue)) {
+          return 0;
+        }
+        return -1;
+      };
+
+      Repeat.prototype.lastIndexOf = function lastIndexOf (searchValue) {
+        if (is(this._value, searchValue)) {
+          return this.size;
+        }
+        return -1;
+      };
+
+      Repeat.prototype.__iterate = function __iterate (fn, reverse) {
+        var size = this.size;
+        var i = 0;
+        while (i !== size) {
+          if (fn(this._value, reverse ? size - ++i : i++, this) === false) {
+            break;
+          }
+        }
+        return i;
+      };
+
+      Repeat.prototype.__iterator = function __iterator (type, reverse) {
+        var this$1$1 = this;
+
+        var size = this.size;
+        var i = 0;
+        return new Iterator(function () { return i === size
+            ? iteratorDone()
+            : iteratorValue(type, reverse ? size - ++i : i++, this$1$1._value); }
+        );
+      };
+
+      Repeat.prototype.equals = function equals (other) {
+        return other instanceof Repeat
+          ? is(this._value, other._value)
+          : deepEqual(this, other);
+      };
+
+      return Repeat;
+    }(IndexedSeq));
+
+    var EMPTY_REPEAT;
+
+    function fromJS(value, converter) {
+      return fromJSWith(
+        [],
+        converter || defaultConverter,
+        value,
+        '',
+        converter && converter.length > 2 ? [] : undefined,
+        { '': value }
+      );
+    }
+
+    function fromJSWith(stack, converter, value, key, keyPath, parentValue) {
+      if (
+        typeof value !== 'string' &&
+        !isImmutable(value) &&
+        (isArrayLike(value) || hasIterator(value) || isPlainObject(value))
+      ) {
+        if (~stack.indexOf(value)) {
+          throw new TypeError('Cannot convert circular structure to Immutable');
+        }
+        stack.push(value);
+        // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+        keyPath && key !== '' && keyPath.push(key);
+        var converted = converter.call(
+          parentValue,
+          key,
+          Seq(value).map(function (v, k) { return fromJSWith(stack, converter, v, k, keyPath, value); }
+          ),
+          keyPath && keyPath.slice()
+        );
+        stack.pop();
+        // eslint-disable-next-line @typescript-eslint/no-unused-expressions -- TODO enable eslint here
+        keyPath && keyPath.pop();
+        return converted;
+      }
+      return value;
+    }
+
+    function defaultConverter(k, v) {
+      // Effectively the opposite of "Collection.toSeq()"
+      return isIndexed(v) ? v.toList() : isKeyed(v) ? v.toMap() : v.toSet();
+    }
+
+    var version = "5.1.3";
+
+    // Note: Iterable is deprecated
+    var Iterable = Collection;
+
+    exports.Collection = Collection;
+    exports.Iterable = Iterable;
+    exports.List = List;
+    exports.Map = Map;
+    exports.OrderedMap = OrderedMap;
+    exports.OrderedSet = OrderedSet;
+    exports.PairSorting = PairSorting;
+    exports.Range = Range;
+    exports.Record = Record;
+    exports.Repeat = Repeat;
+    exports.Seq = Seq;
+    exports.Set = Set;
+    exports.Stack = Stack;
+    exports.fromJS = fromJS;
+    exports.get = get;
+    exports.getIn = getIn$1;
+    exports.has = has;
+    exports.hasIn = hasIn$1;
+    exports.hash = hash;
+    exports.is = is;
+    exports.isAssociative = isAssociative;
+    exports.isCollection = isCollection;
+    exports.isImmutable = isImmutable;
+    exports.isIndexed = isIndexed;
+    exports.isKeyed = isKeyed;
+    exports.isList = isList;
+    exports.isMap = isMap;
+    exports.isOrdered = isOrdered;
+    exports.isOrderedMap = isOrderedMap;
+    exports.isOrderedSet = isOrderedSet;
+    exports.isPlainObject = isPlainObject;
+    exports.isRecord = isRecord;
+    exports.isSeq = isSeq;
+    exports.isSet = isSet;
+    exports.isStack = isStack;
+    exports.isValueObject = isValueObject;
+    exports.merge = merge;
+    exports.mergeDeep = mergeDeep$1;
+    exports.mergeDeepWith = mergeDeepWith$1;
+    exports.mergeWith = mergeWith;
+    exports.remove = remove;
+    exports.removeIn = removeIn;
+    exports.set = set;
+    exports.setIn = setIn$1;
+    exports.update = update$1;
+    exports.updateIn = updateIn$1;
+    exports.version = version;
+
+}));

+ 2414 - 0
node_modules/immutable/dist/immutable.js.flow

@@ -0,0 +1,2414 @@
+/**
+ * This file provides type definitions for use with the Flow type checker.
+ *
+ * An important caveat when using these definitions is that the types for
+ * `Collection.Keyed`, `Collection.Indexed`, `Seq.Keyed`, and so on are stubs.
+ * When referring to those types, you can get the proper definitions by
+ * importing the types `KeyedCollection`, `IndexedCollection`, `KeyedSeq`, etc.
+ * For example,
+ *
+ *     import { Seq } from 'immutable'
+ *     import type { IndexedCollection, IndexedSeq } from 'immutable'
+ *
+ *     const someSeq: IndexedSeq<number> = Seq.Indexed.of(1, 2, 3)
+ *
+ *     function takesASeq<T, TS: IndexedCollection<T>>(iter: TS): TS {
+ *       return iter.butLast()
+ *     }
+ *
+ *     takesASeq(someSeq)
+ *
+ * @flow strict
+ */
+
+// Helper type that represents plain objects allowed as arguments to
+// some constructors and functions.
+type PlainObjInput<K, V> = { +[key: K]: V, __proto__: null };
+
+type K<T> = $Keys<T>;
+
+// Helper types to extract the "keys" and "values" use by the *In() methods.
+type $KeyOf<C> = $Call<
+  (<K>(?_Collection<K, mixed>) => K) &
+    (<T>(?$ReadOnlyArray<T>) => number) &
+    (<T>(?RecordInstance<T> | T) => $Keys<T>) &
+    (<T: Object>(T) => $Keys<T>),
+  C,
+>;
+
+type $ValOf<C, K = $KeyOf<C>> = $Call<
+  (<V>(?_Collection<any, V>) => V) &
+    (<T>(?$ReadOnlyArray<T>) => T) &
+    (<T, K: $Keys<T>>(?RecordInstance<T> | T, K) => $ElementType<T, K>) &
+    (<T: Object>(T) => $Values<T>),
+  C,
+  K,
+>;
+
+type $IterableOf<C> = $Call<
+  (<V: Array<any> | IndexedCollection<any> | SetCollection<any>>(
+    V
+  ) => Iterable<$ValOf<V>>) &
+    (<
+      V:
+        | KeyedCollection<any, any>
+        | RecordInstance<any>
+        | PlainObjInput<any, any>,
+    >(
+      V
+    ) => Iterable<[$KeyOf<V>, $ValOf<V>]>),
+  C,
+>;
+
+const PairSorting: $ReadOnly<{ LeftThenRight: number, RightThenLeft: number }> =
+  {
+    LeftThenRight: -1,
+    RightThenLeft: +1,
+  };
+
+type Comparator<T> = (left: T, right: T) => number;
+
+declare class _Collection<K, +V> implements ValueObject {
+  equals(other: mixed): boolean;
+  hashCode(): number;
+  get(key: K, ..._: []): V | void;
+  get<NSV>(key: K, notSetValue: NSV): V | NSV;
+  has(key: K): boolean;
+  includes(value: V): boolean;
+  contains(value: V): boolean;
+  first(): V | void;
+  first<NSV>(notSetValue: NSV): V | NSV;
+  last(): V | void;
+  last<NSV>(notSetValue: NSV): V | NSV;
+
+  hasIn(keyPath: Iterable<mixed>): boolean;
+
+  getIn(keyPath: [], notSetValue?: mixed): this;
+  getIn<NSV>(keyPath: [K], notSetValue: NSV): V | NSV;
+  getIn<NSV, K2: $KeyOf<V>>(
+    keyPath: [K, K2],
+    notSetValue: NSV
+  ): $ValOf<V, K2> | NSV;
+  getIn<NSV, K2: $KeyOf<V>, K3: $KeyOf<$ValOf<V, K2>>>(
+    keyPath: [K, K2, K3],
+    notSetValue: NSV
+  ): $ValOf<$ValOf<V, K2>, K3> | NSV;
+  getIn<
+    NSV,
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>,
+  >(
+    keyPath: [K, K2, K3, K4],
+    notSetValue: NSV
+  ): $ValOf<$ValOf<$ValOf<V, K2>, K3>, K4> | NSV;
+  getIn<
+    NSV,
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>>,
+  >(
+    keyPath: [K, K2, K3, K4, K5],
+    notSetValue: NSV
+  ): $ValOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>, K5> | NSV;
+
+  update<U>(updater: (value: this) => U): U;
+
+  toJS(): Array<any> | { [key: string]: mixed };
+  toJSON(): Array<V> | { [key: string]: V };
+  toArray(): Array<V> | Array<[K, V]>;
+  toObject(): { [key: string]: V };
+  toMap(): Map<K, V>;
+  toOrderedMap(): OrderedMap<K, V>;
+  toSet(): Set<V>;
+  toOrderedSet(): OrderedSet<V>;
+  toList(): List<V>;
+  toStack(): Stack<V>;
+  toSeq(): Seq<K, V>;
+  toKeyedSeq(): KeyedSeq<K, V>;
+  toIndexedSeq(): IndexedSeq<V>;
+  toSetSeq(): SetSeq<V>;
+
+  keys(): Iterator<K>;
+  values(): Iterator<V>;
+  entries(): Iterator<[K, V]>;
+
+  keySeq(): IndexedSeq<K>;
+  valueSeq(): IndexedSeq<V>;
+  entrySeq(): IndexedSeq<[K, V]>;
+
+  reverse(): this;
+  sort(comparator?: Comparator<V>): this;
+
+  sortBy<C>(
+    comparatorValueMapper: (value: V, key: K, iter: this) => C,
+    comparator?: Comparator<C>
+  ): this;
+
+  groupBy<G>(
+    grouper: (value: V, key: K, iter: this) => G,
+    context?: mixed
+  ): KeyedSeq<G, this>;
+
+  forEach(
+    sideEffect: (value: V, key: K, iter: this) => any,
+    context?: mixed
+  ): number;
+
+  slice(begin?: number, end?: number): this;
+  rest(): this;
+  butLast(): this;
+  skip(amount: number): this;
+  skipLast(amount: number): this;
+  skipWhile(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): this;
+  skipUntil(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): this;
+  take(amount: number): this;
+  takeLast(amount: number): this;
+  takeWhile(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): this;
+  takeUntil(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): this;
+
+  filterNot(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): this;
+
+  reduce<R>(
+    reducer: (reduction: R, value: V, key: K, iter: this) => R,
+    initialReduction: R,
+    context?: mixed
+  ): R;
+  reduce<R>(reducer: (reduction: V | R, value: V, key: K, iter: this) => R): R;
+
+  reduceRight<R>(
+    reducer: (reduction: R, value: V, key: K, iter: this) => R,
+    initialReduction: R,
+    context?: mixed
+  ): R;
+  reduceRight<R>(
+    reducer: (reduction: V | R, value: V, key: K, iter: this) => R
+  ): R;
+
+  every(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): boolean;
+  some(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): boolean;
+  join(separator?: string): string;
+  isEmpty(): boolean;
+  count(
+    predicate?: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): number;
+  countBy<G>(
+    grouper: (value: V, key: K, iter: this) => G,
+    context?: mixed
+  ): Map<G, number>;
+
+  find(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed,
+    notSetValue?: V
+  ): V | void;
+  findLast(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed,
+    notSetValue?: V
+  ): V | void;
+
+  findEntry(predicate: (value: V, key: K, iter: this) => mixed): [K, V] | void;
+  findLastEntry(
+    predicate: (value: V, key: K, iter: this) => mixed
+  ): [K, V] | void;
+
+  findKey(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): K | void;
+  findLastKey(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): K | void;
+
+  keyOf(searchValue: V): K | void;
+  lastKeyOf(searchValue: V): K | void;
+
+  max(comparator?: Comparator<V>): V;
+  maxBy<C>(
+    comparatorValueMapper: (value: V, key: K, iter: this) => C,
+    comparator?: Comparator<C>
+  ): V;
+  min(comparator?: Comparator<V>): V;
+  minBy<C>(
+    comparatorValueMapper: (value: V, key: K, iter: this) => C,
+    comparator?: Comparator<C>
+  ): V;
+
+  isSubset(iter: Iterable<V>): boolean;
+  isSuperset(iter: Iterable<V>): boolean;
+}
+
+declare function isImmutable(
+  maybeImmutable: mixed
+): boolean %checks(maybeImmutable instanceof Collection);
+declare function isCollection(
+  maybeCollection: mixed
+): boolean %checks(maybeCollection instanceof Collection);
+declare function isKeyed(
+  maybeKeyed: mixed
+): boolean %checks(maybeKeyed instanceof KeyedCollection);
+declare function isIndexed(
+  maybeIndexed: mixed
+): boolean %checks(maybeIndexed instanceof IndexedCollection);
+declare function isAssociative(
+  maybeAssociative: mixed
+): boolean %checks(maybeAssociative instanceof KeyedCollection ||
+  maybeAssociative instanceof IndexedCollection);
+declare function isOrdered(
+  maybeOrdered: mixed
+): boolean %checks(maybeOrdered instanceof IndexedCollection ||
+  maybeOrdered instanceof OrderedMap ||
+  maybeOrdered instanceof OrderedSet);
+declare function isValueObject(maybeValue: mixed): boolean;
+
+declare function isSeq(maybeSeq: any): boolean %checks(maybeSeq instanceof Seq);
+declare function isList(maybeList: any): boolean %checks(maybeList instanceof
+  List);
+declare function isMap(maybeMap: any): boolean %checks(maybeMap instanceof Map);
+declare function isOrderedMap(
+  maybeOrderedMap: any
+): boolean %checks(maybeOrderedMap instanceof OrderedMap);
+declare function isStack(maybeStack: any): boolean %checks(maybeStack instanceof
+  Stack);
+declare function isSet(maybeSet: any): boolean %checks(maybeSet instanceof Set);
+declare function isOrderedSet(
+  maybeOrderedSet: any
+): boolean %checks(maybeOrderedSet instanceof OrderedSet);
+declare function isRecord(
+  maybeRecord: any
+): boolean %checks(maybeRecord instanceof Record);
+
+declare interface ValueObject {
+  equals(other: mixed): boolean;
+  hashCode(): number;
+}
+
+declare class Collection<K, +V> extends _Collection<K, V> {
+  static Keyed: typeof KeyedCollection;
+  static Indexed: typeof IndexedCollection;
+  static Set: typeof SetCollection;
+
+  static isCollection: typeof isCollection;
+  static isKeyed: typeof isKeyed;
+  static isIndexed: typeof isIndexed;
+  static isAssociative: typeof isAssociative;
+  static isOrdered: typeof isOrdered;
+}
+
+declare class KeyedCollection<K, +V> extends Collection<K, V> {
+  static <K, V>(
+    values?: Iterable<[K, V]> | PlainObjInput<K, V>
+  ): KeyedCollection<K, V>;
+
+  toJS(): { [key: string]: mixed };
+  toJSON(): { [key: string]: V };
+  toArray(): Array<[K, V]>;
+  @@iterator(): Iterator<[K, V]>;
+  toSeq(): KeyedSeq<K, V>;
+  flip(): KeyedCollection<V, K>;
+
+  concat<KC, VC>(
+    ...iters: Array<Iterable<[KC, VC]> | PlainObjInput<KC, VC>>
+  ): KeyedCollection<K | KC, V | VC>;
+
+  filter(predicate: typeof Boolean): KeyedCollection<K, $NonMaybeType<V>>;
+  filter(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): KeyedCollection<K, V>;
+
+  partition(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: V, key: K, iter: this) => M,
+    context?: mixed
+  ): KeyedCollection<K, M>;
+
+  mapKeys<M>(
+    mapper: (key: K, value: V, iter: this) => M,
+    context?: mixed
+  ): KeyedCollection<M, V>;
+
+  mapEntries<KM, VM>(
+    mapper: (entry: [K, V], index: number, iter: this) => [KM, VM],
+    context?: mixed
+  ): KeyedCollection<KM, VM>;
+
+  flatMap<KM, VM>(
+    mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>,
+    context?: mixed
+  ): KeyedCollection<KM, VM>;
+
+  flatten(depth?: number): KeyedCollection<any, any>;
+  flatten(shallow?: boolean): KeyedCollection<any, any>;
+}
+
+Collection.Keyed = KeyedCollection;
+
+declare class IndexedCollection<+T> extends Collection<number, T> {
+  static <T>(iter?: Iterable<T>): IndexedCollection<T>;
+
+  toJS(): Array<mixed>;
+  toJSON(): Array<T>;
+  toArray(): Array<T>;
+  @@iterator(): Iterator<T>;
+  toSeq(): IndexedSeq<T>;
+  fromEntrySeq<K, V>(): KeyedSeq<K, V>;
+  interpose(separator: T): this;
+  interleave(...collections: Iterable<T>[]): this;
+  splice(index: number, removeNum: number, ...values: T[]): this;
+
+  zip<A>(a: Iterable<A>, ..._: []): IndexedCollection<[T, A]>;
+  zip<A, B>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): IndexedCollection<[T, A, B]>;
+  zip<A, B, C>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): IndexedCollection<[T, A, B, C]>;
+  zip<A, B, C, D>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): IndexedCollection<[T, A, B, C, D]>;
+  zip<A, B, C, D, E>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): IndexedCollection<[T, A, B, C, D, E]>;
+
+  zipAll<A>(a: Iterable<A>, ..._: []): IndexedCollection<[T | void, A | void]>;
+  zipAll<A, B>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): IndexedCollection<[T | void, A | void, B | void]>;
+  zipAll<A, B, C>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): IndexedCollection<[T | void, A | void, B | void, C | void]>;
+  zipAll<A, B, C, D>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): IndexedCollection<[T | void, A | void, B | void, C | void, D | void]>;
+  zipAll<A, B, C, D, E>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): IndexedCollection<
+    [T | void, A | void, B | void, C | void, D | void, E | void],
+  >;
+
+  zipWith<A, R>(
+    zipper: (value: T, a: A) => R,
+    a: Iterable<A>,
+    ..._: []
+  ): IndexedCollection<R>;
+  zipWith<A, B, R>(
+    zipper: (value: T, a: A, b: B) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): IndexedCollection<R>;
+  zipWith<A, B, C, R>(
+    zipper: (value: T, a: A, b: B, c: C) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): IndexedCollection<R>;
+  zipWith<A, B, C, D, R>(
+    zipper: (value: T, a: A, b: B, c: C, d: D) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): IndexedCollection<R>;
+  zipWith<A, B, C, D, E, R>(
+    zipper: (value: T, a: A, b: B, c: C, d: D, e: E) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): IndexedCollection<R>;
+
+  indexOf(searchValue: T): number;
+  lastIndexOf(searchValue: T): number;
+  findIndex(
+    predicate: (value: T, index: number, iter: this) => mixed,
+    context?: mixed
+  ): number;
+  findLastIndex(
+    predicate: (value: T, index: number, iter: this) => mixed,
+    context?: mixed
+  ): number;
+
+  concat<C>(...iters: Array<Iterable<C> | C>): IndexedCollection<T | C>;
+
+  filter(predicate: typeof Boolean): IndexedCollection<$NonMaybeType<T>>;
+  filter(
+    predicate: (value: T, index: number, iter: this) => mixed,
+    context?: mixed
+  ): IndexedCollection<T>;
+
+  partition(
+    predicate: (value: T, index: number, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: T, index: number, iter: this) => M,
+    context?: mixed
+  ): IndexedCollection<M>;
+
+  flatMap<M>(
+    mapper: (value: T, index: number, iter: this) => Iterable<M>,
+    context?: mixed
+  ): IndexedCollection<M>;
+
+  flatten(depth?: number): IndexedCollection<any>;
+  flatten(shallow?: boolean): IndexedCollection<any>;
+}
+
+declare class SetCollection<+T> extends Collection<T, T> {
+  static <T>(iter?: Iterable<T>): SetCollection<T>;
+
+  toJS(): Array<mixed>;
+  toJSON(): Array<T>;
+  toArray(): Array<T>;
+  @@iterator(): Iterator<T>;
+  toSeq(): SetSeq<T>;
+
+  concat<U>(...collections: Iterable<U>[]): SetCollection<T | U>;
+
+  // `filter`, `map` and `flatMap` cannot be defined further up the hierarchy,
+  // because the implementation for `KeyedCollection` allows the value type to
+  // change without constraining the key type. That does not work for
+  // `SetCollection` - the value and key types *must* match.
+  filter(predicate: typeof Boolean): SetCollection<$NonMaybeType<T>>;
+  filter(
+    predicate: (value: T, value: T, iter: this) => mixed,
+    context?: mixed
+  ): SetCollection<T>;
+
+  partition(
+    predicate: (value: T, value: T, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: T, value: T, iter: this) => M,
+    context?: mixed
+  ): SetCollection<M>;
+
+  flatMap<M>(
+    mapper: (value: T, value: T, iter: this) => Iterable<M>,
+    context?: mixed
+  ): SetCollection<M>;
+
+  flatten(depth?: number): SetCollection<any>;
+  flatten(shallow?: boolean): SetCollection<any>;
+}
+
+declare function isSeq(maybeSeq: mixed): boolean %checks(maybeSeq instanceof
+  Seq);
+declare class Seq<K, +V> extends _Collection<K, V> {
+  static Keyed: typeof KeyedSeq;
+  static Indexed: typeof IndexedSeq;
+  static Set: typeof SetSeq;
+
+  static <K, V>(values: KeyedSeq<K, V>): KeyedSeq<K, V>;
+  static <T>(values: SetSeq<T>): SetSeq<K, V>;
+  static <T>(values: Iterable<T>): IndexedSeq<T>;
+  static <K, V>(values?: PlainObjInput<K, V>): KeyedSeq<K, V>;
+
+  static isSeq: typeof isSeq;
+
+  size: number | void;
+  cacheResult(): this;
+  toSeq(): this;
+}
+
+declare class KeyedSeq<K, +V> extends Seq<K, V> mixins KeyedCollection<K, V> {
+  static <K, V>(
+    values?: Iterable<[K, V]> | PlainObjInput<K, V>
+  ): KeyedSeq<K, V>;
+
+  // Override specialized return types
+  flip(): KeyedSeq<V, K>;
+
+  concat<KC, VC>(
+    ...iters: Array<Iterable<[KC, VC]> | PlainObjInput<KC, VC>>
+  ): KeyedSeq<K | KC, V | VC>;
+
+  filter(predicate: typeof Boolean): KeyedSeq<K, $NonMaybeType<V>>;
+  filter(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): KeyedSeq<K, V>;
+
+  partition(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: V, key: K, iter: this) => M,
+    context?: mixed
+  ): KeyedSeq<K, M>;
+
+  mapKeys<M>(
+    mapper: (key: K, value: V, iter: this) => M,
+    context?: mixed
+  ): KeyedSeq<M, V>;
+
+  mapEntries<KM, VM>(
+    mapper: (entry: [K, V], index: number, iter: this) => [KM, VM],
+    context?: mixed
+  ): KeyedSeq<KM, VM>;
+
+  flatMap<KM, VM>(
+    mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>,
+    context?: mixed
+  ): KeyedSeq<KM, VM>;
+
+  flatten(depth?: number): KeyedSeq<any, any>;
+  flatten(shallow?: boolean): KeyedSeq<any, any>;
+}
+
+declare class IndexedSeq<+T>
+  extends Seq<number, T>
+  mixins IndexedCollection<T>
+{
+  static <T>(values?: Iterable<T>): IndexedSeq<T>;
+
+  static of<T>(...values: T[]): IndexedSeq<T>;
+
+  // Override specialized return types
+
+  concat<C>(...iters: Array<Iterable<C> | C>): IndexedSeq<T | C>;
+
+  filter(predicate: typeof Boolean): IndexedSeq<$NonMaybeType<T>>;
+  filter(
+    predicate: (value: T, index: number, iter: this) => mixed,
+    context?: mixed
+  ): IndexedSeq<T>;
+
+  partition(
+    predicate: (value: T, index: number, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: T, index: number, iter: this) => M,
+    context?: mixed
+  ): IndexedSeq<M>;
+
+  flatMap<M>(
+    mapper: (value: T, index: number, iter: this) => Iterable<M>,
+    context?: mixed
+  ): IndexedSeq<M>;
+
+  flatten(depth?: number): IndexedSeq<any>;
+  flatten(shallow?: boolean): IndexedSeq<any>;
+
+  zip<A>(a: Iterable<A>, ..._: []): IndexedSeq<[T, A]>;
+  zip<A, B>(a: Iterable<A>, b: Iterable<B>, ..._: []): IndexedSeq<[T, A, B]>;
+  zip<A, B, C>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): IndexedSeq<[T, A, B, C]>;
+  zip<A, B, C, D>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): IndexedSeq<[T, A, B, C, D]>;
+  zip<A, B, C, D, E>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): IndexedSeq<[T, A, B, C, D, E]>;
+
+  zipAll<A>(a: Iterable<A>, ..._: []): IndexedSeq<[T | void, A | void]>;
+  zipAll<A, B>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): IndexedSeq<[T | void, A | void, B | void]>;
+  zipAll<A, B, C>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): IndexedSeq<[T | void, A | void, B | void, C | void]>;
+  zipAll<A, B, C, D>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): IndexedSeq<[T | void, A | void, B | void, C | void, D | void]>;
+  zipAll<A, B, C, D, E>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): IndexedSeq<[T | void, A | void, B | void, C | void, D | void, E | void]>;
+
+  zipWith<A, R>(
+    zipper: (value: T, a: A) => R,
+    a: Iterable<A>,
+    ..._: []
+  ): IndexedSeq<R>;
+  zipWith<A, B, R>(
+    zipper: (value: T, a: A, b: B) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): IndexedSeq<R>;
+  zipWith<A, B, C, R>(
+    zipper: (value: T, a: A, b: B, c: C) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): IndexedSeq<R>;
+  zipWith<A, B, C, D, R>(
+    zipper: (value: T, a: A, b: B, c: C, d: D) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): IndexedSeq<R>;
+  zipWith<A, B, C, D, E, R>(
+    zipper: (value: T, a: A, b: B, c: C, d: D, e: E) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): IndexedSeq<R>;
+}
+
+declare class SetSeq<+T> extends Seq<T, T> mixins SetCollection<T> {
+  static <T>(values?: Iterable<T>): SetSeq<T>;
+
+  static of<T>(...values: T[]): SetSeq<T>;
+
+  // Override specialized return types
+
+  concat<U>(...collections: Iterable<U>[]): SetSeq<T | U>;
+
+  filter(predicate: typeof Boolean): SetSeq<$NonMaybeType<T>>;
+  filter(
+    predicate: (value: T, value: T, iter: this) => mixed,
+    context?: mixed
+  ): SetSeq<T>;
+
+  partition(
+    predicate: (value: T, value: T, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: T, value: T, iter: this) => M,
+    context?: mixed
+  ): SetSeq<M>;
+
+  flatMap<M>(
+    mapper: (value: T, value: T, iter: this) => Iterable<M>,
+    context?: mixed
+  ): SetSeq<M>;
+
+  flatten(depth?: number): SetSeq<any>;
+  flatten(shallow?: boolean): SetSeq<any>;
+}
+
+declare class UpdatableInCollection<K, +V> {
+  setIn<S>(keyPath: [], value: S): S;
+  setIn(keyPath: [K], value: V): this;
+  setIn<K2: $KeyOf<V>, S: $ValOf<V, K2>>(keyPath: [K, K2], value: S): this;
+  setIn<K2: $KeyOf<V>, K3: $KeyOf<$ValOf<V, K2>>, S: $ValOf<$ValOf<V, K2>, K3>>(
+    keyPath: [K, K2, K3],
+    value: S
+  ): this;
+  setIn<
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>,
+    S: $ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>,
+  >(
+    keyPath: [K, K2, K3, K4],
+    value: S
+  ): this;
+  setIn<
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>>,
+    S: $ValOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>, K5>,
+  >(
+    keyPath: [K, K2, K3, K4, K5],
+    value: S
+  ): this;
+
+  deleteIn(keyPath: []): void;
+  deleteIn(keyPath: [K]): this;
+  deleteIn<K2: $KeyOf<V>>(keyPath: [K, K2]): this;
+  deleteIn<K2: $KeyOf<V>, K3: $KeyOf<$ValOf<V, K2>>>(
+    keyPath: [K, K2, K3]
+  ): this;
+  deleteIn<
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>,
+  >(
+    keyPath: [K, K2, K3, K4]
+  ): this;
+  deleteIn<
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>>,
+  >(
+    keyPath: [K, K2, K3, K4, K5]
+  ): this;
+
+  removeIn(keyPath: []): void;
+  removeIn(keyPath: [K]): this;
+  removeIn<K2: $KeyOf<V>>(keyPath: [K, K2]): this;
+  removeIn<K2: $KeyOf<V>, K3: $KeyOf<$ValOf<V, K2>>>(
+    keyPath: [K, K2, K3]
+  ): this;
+  removeIn<
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>,
+  >(
+    keyPath: [K, K2, K3, K4]
+  ): this;
+  removeIn<
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>>,
+  >(
+    keyPath: [K, K2, K3, K4, K5]
+  ): this;
+
+  updateIn<U>(keyPath: [], notSetValue: mixed, updater: (value: this) => U): U;
+  updateIn<U>(keyPath: [], updater: (value: this) => U): U;
+  updateIn<NSV>(keyPath: [K], notSetValue: NSV, updater: (value: V) => V): this;
+  updateIn(keyPath: [K], updater: (value: V) => V): this;
+  updateIn<NSV, K2: $KeyOf<V>, S: $ValOf<V, K2>>(
+    keyPath: [K, K2],
+    notSetValue: NSV,
+    updater: (value: $ValOf<V, K2> | NSV) => S
+  ): this;
+  updateIn<K2: $KeyOf<V>, S: $ValOf<V, K2>>(
+    keyPath: [K, K2],
+    updater: (value: $ValOf<V, K2>) => S
+  ): this;
+  updateIn<
+    NSV,
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    S: $ValOf<$ValOf<V, K2>, K3>,
+  >(
+    keyPath: [K, K2, K3],
+    notSetValue: NSV,
+    updater: (value: $ValOf<$ValOf<V, K2>, K3> | NSV) => S
+  ): this;
+  updateIn<
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    S: $ValOf<$ValOf<V, K2>, K3>,
+  >(
+    keyPath: [K, K2, K3],
+    updater: (value: $ValOf<$ValOf<V, K2>, K3>) => S
+  ): this;
+  updateIn<
+    NSV,
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>,
+    S: $ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>,
+  >(
+    keyPath: [K, K2, K3, K4],
+    notSetValue: NSV,
+    updater: (value: $ValOf<$ValOf<$ValOf<V, K2>, K3>, K4> | NSV) => S
+  ): this;
+  updateIn<
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>,
+    S: $ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>,
+  >(
+    keyPath: [K, K2, K3, K4],
+    updater: (value: $ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>) => S
+  ): this;
+  updateIn<
+    NSV,
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>>,
+    S: $ValOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>, K5>,
+  >(
+    keyPath: [K, K2, K3, K4, K5],
+    notSetValue: NSV,
+    updater: (
+      value: $ValOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>, K5> | NSV
+    ) => S
+  ): this;
+  updateIn<
+    K2: $KeyOf<V>,
+    K3: $KeyOf<$ValOf<V, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<V, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>>,
+    S: $ValOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>, K5>,
+  >(
+    keyPath: [K, K2, K3, K4, K5],
+    updater: (value: $ValOf<$ValOf<$ValOf<$ValOf<V, K2>, K3>, K4>, K5>) => S
+  ): this;
+}
+
+declare function isList(maybeList: mixed): boolean %checks(maybeList instanceof
+  List);
+declare class List<+T>
+  extends IndexedCollection<T>
+  mixins UpdatableInCollection<number, T>
+{
+  static <T>(collection?: Iterable<T>): List<T>;
+
+  static of<T>(...values: T[]): List<T>;
+
+  static isList: typeof isList;
+
+  size: number;
+
+  set<U>(index: number, value: U): List<T | U>;
+  delete(index: number): this;
+  remove(index: number): this;
+  insert<U>(index: number, value: U): List<T | U>;
+  clear(): this;
+  push<U>(...values: U[]): List<T | U>;
+  pop(): this;
+  unshift<U>(...values: U[]): List<T | U>;
+  shift(): this;
+
+  update<U>(updater: (value: this) => U): U;
+  update<U>(index: number, updater: (value: T) => U): List<T | U>;
+  update<U>(
+    index: number,
+    notSetValue: U,
+    updater: (value: T) => U
+  ): List<T | U>;
+
+  merge<U>(...collections: Iterable<U>[]): List<T | U>;
+
+  setSize(size: number): this;
+
+  mergeIn(keyPath: Iterable<mixed>, ...collections: Iterable<mixed>[]): this;
+  mergeDeepIn(
+    keyPath: Iterable<mixed>,
+    ...collections: Iterable<mixed>[]
+  ): this;
+
+  withMutations(mutator: (mutable: this) => mixed): this;
+  asMutable(): this;
+  wasAltered(): boolean;
+  asImmutable(): this;
+
+  // Override specialized return types
+
+  concat<C>(...iters: Array<Iterable<C> | C>): List<T | C>;
+
+  filter(predicate: typeof Boolean): List<$NonMaybeType<T>>;
+  filter(
+    predicate: (value: T, index: number, iter: this) => mixed,
+    context?: mixed
+  ): List<T>;
+
+  partition(
+    predicate: (value: T, index: number, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: T, index: number, iter: this) => M,
+    context?: mixed
+  ): List<M>;
+
+  flatMap<M>(
+    mapper: (value: T, index: number, iter: this) => Iterable<M>,
+    context?: mixed
+  ): List<M>;
+
+  flatten(depth?: number): List<any>;
+  flatten(shallow?: boolean): List<any>;
+
+  zip<A>(a: Iterable<A>, ..._: []): List<[T, A]>;
+  zip<A, B>(a: Iterable<A>, b: Iterable<B>, ..._: []): List<[T, A, B]>;
+  zip<A, B, C>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): List<[T, A, B, C]>;
+  zip<A, B, C, D>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): List<[T, A, B, C, D]>;
+  zip<A, B, C, D, E>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): List<[T, A, B, C, D, E]>;
+
+  zipAll<A>(a: Iterable<A>, ..._: []): List<[T | void, A | void]>;
+  zipAll<A, B>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): List<[T | void, A | void, B | void]>;
+  zipAll<A, B, C>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): List<[T | void, A | void, B | void, C | void]>;
+  zipAll<A, B, C, D>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): List<[T | void, A | void, B | void, C | void, D | void]>;
+  zipAll<A, B, C, D, E>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): List<[T | void, A | void, B | void, C | void, D | void, E | void]>;
+
+  zipWith<A, R>(
+    zipper: (value: T, a: A) => R,
+    a: Iterable<A>,
+    ..._: []
+  ): List<R>;
+  zipWith<A, B, R>(
+    zipper: (value: T, a: A, b: B) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): List<R>;
+  zipWith<A, B, C, R>(
+    zipper: (value: T, a: A, b: B, c: C) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): List<R>;
+  zipWith<A, B, C, D, R>(
+    zipper: (value: T, a: A, b: B, c: C, d: D) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): List<R>;
+  zipWith<A, B, C, D, E, R>(
+    zipper: (value: T, a: A, b: B, c: C, d: D, e: E) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): List<R>;
+}
+
+declare function isMap(maybeMap: mixed): boolean %checks(maybeMap instanceof
+  Map);
+declare class Map<K, +V>
+  extends KeyedCollection<K, V>
+  mixins UpdatableInCollection<K, V>
+{
+  static <K, V>(values?: Iterable<[K, V]> | PlainObjInput<K, V>): Map<K, V>;
+
+  static isMap: typeof isMap;
+
+  size: number;
+
+  set<K_, V_>(key: K_, value: V_): Map<K | K_, V | V_>;
+  delete(key: K): this;
+  remove(key: K): this;
+  clear(): this;
+
+  deleteAll(keys: Iterable<K>): Map<K, V>;
+  removeAll(keys: Iterable<K>): Map<K, V>;
+
+  update<U>(updater: (value: this) => U): U;
+  update<V_>(key: K, updater: (value: V) => V_): Map<K, V | V_>;
+  update<V_>(
+    key: K,
+    notSetValue: V_,
+    updater: (value: V) => V_
+  ): Map<K, V | V_>;
+
+  merge<K_, V_>(
+    ...collections: (Iterable<[K_, V_]> | PlainObjInput<K_, V_>)[]
+  ): Map<K | K_, V | V_>;
+  concat<K_, V_>(
+    ...collections: (Iterable<[K_, V_]> | PlainObjInput<K_, V_>)[]
+  ): Map<K | K_, V | V_>;
+
+  mergeWith<K_, W, X>(
+    merger: (oldVal: V, newVal: W, key: K) => X,
+    ...collections: (Iterable<[K_, W]> | PlainObjInput<K_, W>)[]
+  ): Map<K | K_, V | W | X>;
+
+  mergeDeep<K_, V_>(
+    ...collections: (Iterable<[K_, V_]> | PlainObjInput<K_, V_>)[]
+  ): Map<K | K_, V | V_>;
+
+  mergeDeepWith<K_, V_>(
+    merger: (oldVal: any, newVal: any, key: any) => mixed,
+    ...collections: (Iterable<[K_, V_]> | PlainObjInput<K_, V_>)[]
+  ): Map<K | K_, V | V_>;
+
+  mergeIn(
+    keyPath: Iterable<mixed>,
+    ...collections: (Iterable<mixed> | PlainObjInput<mixed, mixed>)[]
+  ): this;
+  mergeDeepIn(
+    keyPath: Iterable<mixed>,
+    ...collections: (Iterable<mixed> | PlainObjInput<mixed, mixed>)[]
+  ): this;
+
+  withMutations(mutator: (mutable: this) => mixed): this;
+  asMutable(): this;
+  wasAltered(): boolean;
+  asImmutable(): this;
+
+  // Override specialized return types
+
+  flip(): Map<V, K>;
+
+  filter(predicate: typeof Boolean): Map<K, $NonMaybeType<V>>;
+  filter(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): Map<K, V>;
+
+  partition(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: V, key: K, iter: this) => M,
+    context?: mixed
+  ): Map<K, M>;
+
+  mapKeys<M>(
+    mapper: (key: K, value: V, iter: this) => M,
+    context?: mixed
+  ): Map<M, V>;
+
+  mapEntries<KM, VM>(
+    mapper: (entry: [K, V], index: number, iter: this) => [KM, VM],
+    context?: mixed
+  ): Map<KM, VM>;
+
+  flatMap<KM, VM>(
+    mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>,
+    context?: mixed
+  ): Map<KM, VM>;
+
+  flatten(depth?: number): Map<any, any>;
+  flatten(shallow?: boolean): Map<any, any>;
+}
+
+declare function isOrderedMap(
+  maybeOrderedMap: mixed
+): boolean %checks(maybeOrderedMap instanceof OrderedMap);
+declare class OrderedMap<K, +V>
+  extends Map<K, V>
+  mixins UpdatableInCollection<K, V>
+{
+  static <K, V>(
+    values?: Iterable<[K, V]> | PlainObjInput<K, V>
+  ): OrderedMap<K, V>;
+
+  static isOrderedMap: typeof isOrderedMap;
+
+  size: number;
+
+  set<K_, V_>(key: K_, value: V_): OrderedMap<K | K_, V | V_>;
+  delete(key: K): this;
+  remove(key: K): this;
+  clear(): this;
+
+  update<U>(updater: (value: this) => U): U;
+  update<V_>(key: K, updater: (value: V) => V_): OrderedMap<K, V | V_>;
+  update<V_>(
+    key: K,
+    notSetValue: V_,
+    updater: (value: V) => V_
+  ): OrderedMap<K, V | V_>;
+
+  merge<K_, V_>(
+    ...collections: (Iterable<[K_, V_]> | PlainObjInput<K_, V_>)[]
+  ): OrderedMap<K | K_, V | V_>;
+  concat<K_, V_>(
+    ...collections: (Iterable<[K_, V_]> | PlainObjInput<K_, V_>)[]
+  ): OrderedMap<K | K_, V | V_>;
+
+  mergeWith<K_, W, X>(
+    merger: (oldVal: V, newVal: W, key: K) => X,
+    ...collections: (Iterable<[K_, W]> | PlainObjInput<K_, W>)[]
+  ): OrderedMap<K | K_, V | W | X>;
+
+  mergeDeep<K_, V_>(
+    ...collections: (Iterable<[K_, V_]> | PlainObjInput<K_, V_>)[]
+  ): OrderedMap<K | K_, V | V_>;
+
+  mergeDeepWith<K_, V_>(
+    merger: (oldVal: any, newVal: any, key: any) => mixed,
+    ...collections: (Iterable<[K_, V_]> | PlainObjInput<K_, V_>)[]
+  ): OrderedMap<K | K_, V | V_>;
+
+  mergeIn(
+    keyPath: Iterable<mixed>,
+    ...collections: (Iterable<mixed> | PlainObjInput<mixed, mixed>)[]
+  ): this;
+  mergeDeepIn(
+    keyPath: Iterable<mixed>,
+    ...collections: (Iterable<mixed> | PlainObjInput<mixed, mixed>)[]
+  ): this;
+
+  withMutations(mutator: (mutable: this) => mixed): this;
+  asMutable(): this;
+  wasAltered(): boolean;
+  asImmutable(): this;
+
+  // Override specialized return types
+
+  flip(): OrderedMap<V, K>;
+
+  filter(predicate: typeof Boolean): OrderedMap<K, $NonMaybeType<V>>;
+  filter(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): OrderedMap<K, V>;
+
+  partition(
+    predicate: (value: V, key: K, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: V, key: K, iter: this) => M,
+    context?: mixed
+  ): OrderedMap<K, M>;
+
+  mapKeys<M>(
+    mapper: (key: K, value: V, iter: this) => M,
+    context?: mixed
+  ): OrderedMap<M, V>;
+
+  mapEntries<KM, VM>(
+    mapper: (entry: [K, V], index: number, iter: this) => [KM, VM],
+    context?: mixed
+  ): OrderedMap<KM, VM>;
+
+  flatMap<KM, VM>(
+    mapper: (value: V, key: K, iter: this) => Iterable<[KM, VM]>,
+    context?: mixed
+  ): OrderedMap<KM, VM>;
+
+  flatten(depth?: number): OrderedMap<any, any>;
+  flatten(shallow?: boolean): OrderedMap<any, any>;
+}
+
+declare function isSet(maybeSet: mixed): boolean %checks(maybeSet instanceof
+  Set);
+declare class Set<+T> extends SetCollection<T> {
+  static <T>(values?: Iterable<T>): Set<T>;
+
+  static of<T>(...values: T[]): Set<T>;
+  static fromKeys<T>(
+    values: Iterable<[T, mixed]> | PlainObjInput<T, mixed>
+  ): Set<T>;
+
+  static intersect<T>(sets: Iterable<Iterable<T>>): Set<T>;
+  static union<T>(sets: Iterable<Iterable<T>>): Set<T>;
+
+  static isSet: typeof isSet;
+
+  size: number;
+
+  add<U>(value: U): Set<T | U>;
+  delete(value: T): this;
+  remove(value: T): this;
+  clear(): this;
+  union<U>(...collections: Iterable<U>[]): Set<T | U>;
+  merge<U>(...collections: Iterable<U>[]): Set<T | U>;
+  concat<U>(...collections: Iterable<U>[]): Set<T | U>;
+  intersect<U>(...collections: Iterable<U>[]): Set<T & U>;
+  subtract(...collections: Iterable<mixed>[]): this;
+
+  withMutations(mutator: (mutable: this) => mixed): this;
+  asMutable(): this;
+  wasAltered(): boolean;
+  asImmutable(): this;
+
+  // Override specialized return types
+
+  filter(predicate: typeof Boolean): Set<$NonMaybeType<T>>;
+  filter(
+    predicate: (value: T, value: T, iter: this) => mixed,
+    context?: mixed
+  ): Set<T>;
+
+  partition(
+    predicate: (value: T, value: T, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: T, value: T, iter: this) => M,
+    context?: mixed
+  ): Set<M>;
+
+  flatMap<M>(
+    mapper: (value: T, value: T, iter: this) => Iterable<M>,
+    context?: mixed
+  ): Set<M>;
+
+  flatten(depth?: number): Set<any>;
+  flatten(shallow?: boolean): Set<any>;
+}
+
+// Overrides except for `isOrderedSet` are for specialized return types
+declare function isOrderedSet(
+  maybeOrderedSet: mixed
+): boolean %checks(maybeOrderedSet instanceof OrderedSet);
+declare class OrderedSet<+T> extends Set<T> {
+  static <T>(values?: Iterable<T>): OrderedSet<T>;
+
+  static of<T>(...values: T[]): OrderedSet<T>;
+  static fromKeys<T>(
+    values: Iterable<[T, mixed]> | PlainObjInput<T, mixed>
+  ): OrderedSet<T>;
+
+  static isOrderedSet: typeof isOrderedSet;
+
+  size: number;
+
+  add<U>(value: U): OrderedSet<T | U>;
+  union<U>(...collections: Iterable<U>[]): OrderedSet<T | U>;
+  merge<U>(...collections: Iterable<U>[]): OrderedSet<T | U>;
+  concat<U>(...collections: Iterable<U>[]): OrderedSet<T | U>;
+  intersect<U>(...collections: Iterable<U>[]): OrderedSet<T & U>;
+
+  filter(predicate: typeof Boolean): OrderedSet<$NonMaybeType<T>>;
+  filter(
+    predicate: (value: T, value: T, iter: this) => mixed,
+    context?: mixed
+  ): OrderedSet<T>;
+
+  partition(
+    predicate: (value: T, value: T, iter: this) => mixed,
+    context?: mixed
+  ): [this, this];
+
+  map<M>(
+    mapper: (value: T, value: T, iter: this) => M,
+    context?: mixed
+  ): OrderedSet<M>;
+
+  flatMap<M>(
+    mapper: (value: T, value: T, iter: this) => Iterable<M>,
+    context?: mixed
+  ): OrderedSet<M>;
+
+  flatten(depth?: number): OrderedSet<any>;
+  flatten(shallow?: boolean): OrderedSet<any>;
+
+  zip<A>(a: Iterable<A>, ..._: []): OrderedSet<[T, A]>;
+  zip<A, B>(a: Iterable<A>, b: Iterable<B>, ..._: []): OrderedSet<[T, A, B]>;
+  zip<A, B, C>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): OrderedSet<[T, A, B, C]>;
+  zip<A, B, C, D>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): OrderedSet<[T, A, B, C, D]>;
+  zip<A, B, C, D, E>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): OrderedSet<[T, A, B, C, D, E]>;
+
+  zipAll<A>(a: Iterable<A>, ..._: []): OrderedSet<[T | void, A | void]>;
+  zipAll<A, B>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): OrderedSet<[T | void, A | void, B | void]>;
+  zipAll<A, B, C>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): OrderedSet<[T | void, A | void, B | void, C | void]>;
+  zipAll<A, B, C, D>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): OrderedSet<[T | void, A | void, B | void, C | void, D | void]>;
+  zipAll<A, B, C, D, E>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): OrderedSet<[T | void, A | void, B | void, C | void, D | void, E | void]>;
+
+  zipWith<A, R>(
+    zipper: (value: T, a: A) => R,
+    a: Iterable<A>,
+    ..._: []
+  ): OrderedSet<R>;
+  zipWith<A, B, R>(
+    zipper: (value: T, a: A, b: B) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): OrderedSet<R>;
+  zipWith<A, B, C, R>(
+    zipper: (value: T, a: A, b: B, c: C) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): OrderedSet<R>;
+  zipWith<A, B, C, D, R>(
+    zipper: (value: T, a: A, b: B, c: C, d: D) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): OrderedSet<R>;
+  zipWith<A, B, C, D, E, R>(
+    zipper: (value: T, a: A, b: B, c: C, d: D, e: E) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): OrderedSet<R>;
+}
+
+declare function isStack(
+  maybeStack: mixed
+): boolean %checks(maybeStack instanceof Stack);
+declare class Stack<+T> extends IndexedCollection<T> {
+  static <T>(collection?: Iterable<T>): Stack<T>;
+
+  static isStack(maybeStack: mixed): boolean;
+  static of<T>(...values: T[]): Stack<T>;
+
+  static isStack: typeof isStack;
+
+  size: number;
+
+  peek(): T;
+  clear(): this;
+  unshift<U>(...values: U[]): Stack<T | U>;
+  unshiftAll<U>(iter: Iterable<U>): Stack<T | U>;
+  shift(): this;
+  push<U>(...values: U[]): Stack<T | U>;
+  pushAll<U>(iter: Iterable<U>): Stack<T | U>;
+  pop(): this;
+
+  withMutations(mutator: (mutable: this) => mixed): this;
+  asMutable(): this;
+  wasAltered(): boolean;
+  asImmutable(): this;
+
+  // Override specialized return types
+
+  concat<C>(...iters: Array<Iterable<C> | C>): Stack<T | C>;
+
+  filter(predicate: typeof Boolean): Stack<$NonMaybeType<T>>;
+  filter(
+    predicate: (value: T, index: number, iter: this) => mixed,
+    context?: mixed
+  ): Stack<T>;
+
+  map<M>(
+    mapper: (value: T, index: number, iter: this) => M,
+    context?: mixed
+  ): Stack<M>;
+
+  flatMap<M>(
+    mapper: (value: T, index: number, iter: this) => Iterable<M>,
+    context?: mixed
+  ): Stack<M>;
+
+  flatten(depth?: number): Stack<any>;
+  flatten(shallow?: boolean): Stack<any>;
+
+  zip<A>(a: Iterable<A>, ..._: []): Stack<[T, A]>;
+  zip<A, B>(a: Iterable<A>, b: Iterable<B>, ..._: []): Stack<[T, A, B]>;
+  zip<A, B, C>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): Stack<[T, A, B, C]>;
+  zip<A, B, C, D>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): Stack<[T, A, B, C, D]>;
+  zip<A, B, C, D, E>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): Stack<[T, A, B, C, D, E]>;
+
+  zipAll<A>(a: Iterable<A>, ..._: []): Stack<[T | void, A | void]>;
+  zipAll<A, B>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): Stack<[T | void, A | void, B | void]>;
+  zipAll<A, B, C>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): Stack<[T | void, A | void, B | void, C | void]>;
+  zipAll<A, B, C, D>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): Stack<[T | void, A | void, B | void, C | void, D | void]>;
+  zipAll<A, B, C, D, E>(
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): Stack<[T | void, A | void, B | void, C | void, D | void, E | void]>;
+
+  zipWith<A, R>(
+    zipper: (value: T, a: A) => R,
+    a: Iterable<A>,
+    ..._: []
+  ): Stack<R>;
+  zipWith<A, B, R>(
+    zipper: (value: T, a: A, b: B) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    ..._: []
+  ): Stack<R>;
+  zipWith<A, B, C, R>(
+    zipper: (value: T, a: A, b: B, c: C) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    ..._: []
+  ): Stack<R>;
+  zipWith<A, B, C, D, R>(
+    zipper: (value: T, a: A, b: B, c: C, d: D) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    ..._: []
+  ): Stack<R>;
+  zipWith<A, B, C, D, E, R>(
+    zipper: (value: T, a: A, b: B, c: C, d: D, e: E) => R,
+    a: Iterable<A>,
+    b: Iterable<B>,
+    c: Iterable<C>,
+    d: Iterable<D>,
+    e: Iterable<E>,
+    ..._: []
+  ): Stack<R>;
+}
+
+declare function Range(
+  start?: number,
+  end?: number,
+  step?: number
+): IndexedSeq<number>;
+declare function Repeat<T>(value: T, times?: number): IndexedSeq<T>;
+
+// The type of a Record factory function.
+type RecordFactory<Values: Object> = Class<RecordInstance<Values>>;
+
+// The type of runtime Record instances.
+type RecordOf<Values: Object> = RecordInstance<Values> & $ReadOnly<Values>;
+
+// The values of a Record instance.
+type _RecordValues<T, R: RecordInstance<T> | T> = R;
+type RecordValues<R> = _RecordValues<*, R>;
+
+declare function isRecord(
+  maybeRecord: any
+): boolean %checks(maybeRecord instanceof RecordInstance);
+declare class Record {
+  static <Values: Object>(spec: Values, name?: string): typeof RecordInstance;
+  constructor<Values: Object>(
+    spec: Values,
+    name?: string
+  ): typeof RecordInstance;
+
+  static isRecord: typeof isRecord;
+
+  static getDescriptiveName(record: RecordInstance<any>): string;
+}
+
+declare class RecordInstance<T: Object = Object> {
+  static (values?: Iterable<[$Keys<T>, $ValOf<T>]> | $Shape<T>): RecordOf<T>;
+  // Note: a constructor can only create an instance of RecordInstance<T>,
+  // it's encouraged to not use `new` when creating Records.
+  constructor(values?: Iterable<[$Keys<T>, $ValOf<T>]> | $Shape<T>): void;
+
+  size: number;
+
+  has(key: string): boolean;
+
+  get<K: $Keys<T>>(key: K, ..._: []): $ElementType<T, K>;
+  get<K: $Keys<T>, NSV>(key: K, notSetValue: NSV): $ElementType<T, K> | NSV;
+
+  hasIn(keyPath: Iterable<mixed>): boolean;
+
+  getIn(keyPath: [], notSetValue?: mixed): this & $ReadOnly<T>;
+  getIn<K: $Keys<T>>(keyPath: [K], notSetValue?: mixed): $ElementType<T, K>;
+  getIn<NSV, K: $Keys<T>, K2: $KeyOf<$ValOf<T, K>>>(
+    keyPath: [K, K2],
+    notSetValue: NSV
+  ): $ValOf<$ValOf<T, K>, K2> | NSV;
+  getIn<
+    NSV,
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+  >(
+    keyPath: [K, K2, K3],
+    notSetValue: NSV
+  ): $ValOf<$ValOf<$ValOf<T, K>, K2>, K3> | NSV;
+  getIn<
+    NSV,
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>,
+  >(
+    keyPath: [K, K2, K3, K4],
+    notSetValue: NSV
+  ): $ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4> | NSV;
+  getIn<
+    NSV,
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>>,
+  >(
+    keyPath: [K, K2, K3, K4, K5],
+    notSetValue: NSV
+  ): $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>, K5> | NSV;
+
+  equals(other: any): boolean;
+  hashCode(): number;
+
+  set<K: $Keys<T>>(key: K, value: $ElementType<T, K>): this & $ReadOnly<T>;
+  update<K: $Keys<T>>(
+    key: K,
+    updater: (value: $ElementType<T, K>) => $ElementType<T, K>
+  ): this & $ReadOnly<T>;
+  merge(
+    ...collections: Array<Iterable<[$Keys<T>, $ValOf<T>]> | $Shape<T>>
+  ): this & $ReadOnly<T>;
+  mergeDeep(
+    ...collections: Array<Iterable<[$Keys<T>, $ValOf<T>]> | $Shape<T>>
+  ): this & $ReadOnly<T>;
+
+  mergeWith(
+    merger: (oldVal: $ValOf<T>, newVal: $ValOf<T>, key: $Keys<T>) => $ValOf<T>,
+    ...collections: Array<Iterable<[$Keys<T>, $ValOf<T>]> | $Shape<T>>
+  ): this & $ReadOnly<T>;
+  mergeDeepWith(
+    merger: (oldVal: any, newVal: any, key: any) => any,
+    ...collections: Array<Iterable<[$Keys<T>, $ValOf<T>]> | $Shape<T>>
+  ): this & $ReadOnly<T>;
+
+  delete<K: $Keys<T>>(key: K): this & $ReadOnly<T>;
+  remove<K: $Keys<T>>(key: K): this & $ReadOnly<T>;
+  clear(): this & $ReadOnly<T>;
+
+  setIn<S>(keyPath: [], value: S): S;
+  setIn<K: $Keys<T>, S: $ValOf<T, K>>(
+    keyPath: [K],
+    value: S
+  ): this & $ReadOnly<T>;
+  setIn<K: $Keys<T>, K2: $KeyOf<$ValOf<T, K>>, S: $ValOf<$ValOf<T, K>, K2>>(
+    keyPath: [K, K2],
+    value: S
+  ): this & $ReadOnly<T>;
+  setIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    S: $ValOf<$ValOf<$ValOf<T, K>, K2>, K3>,
+  >(
+    keyPath: [K, K2, K3],
+    value: S
+  ): this & $ReadOnly<T>;
+  setIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>,
+    S: $ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>,
+  >(
+    keyPath: [K, K2, K3, K4],
+    value: S
+  ): this & $ReadOnly<T>;
+  setIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>>,
+    S: $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>, K5>,
+  >(
+    keyPath: [K, K2, K3, K4, K5],
+    value: S
+  ): this & $ReadOnly<T>;
+
+  deleteIn(keyPath: []): void;
+  deleteIn<K: $Keys<T>>(keyPath: [K]): this & $ReadOnly<T>;
+  deleteIn<K: $Keys<T>, K2: $KeyOf<$ValOf<T, K>>>(
+    keyPath: [K, K2]
+  ): this & $ReadOnly<T>;
+  deleteIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+  >(
+    keyPath: [K, K2, K3]
+  ): this & $ReadOnly<T>;
+  deleteIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>,
+  >(
+    keyPath: [K, K2, K3, K4]
+  ): this & $ReadOnly<T>;
+  deleteIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>>,
+  >(
+    keyPath: [K, K2, K3, K4, K5]
+  ): this & $ReadOnly<T>;
+
+  removeIn(keyPath: []): void;
+  removeIn<K: $Keys<T>>(keyPath: [K]): this & $ReadOnly<T>;
+  removeIn<K: $Keys<T>, K2: $KeyOf<$ValOf<T, K>>>(
+    keyPath: [K, K2]
+  ): this & $ReadOnly<T>;
+  removeIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+  >(
+    keyPath: [K, K2, K3]
+  ): this & $ReadOnly<T>;
+  removeIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>,
+  >(
+    keyPath: [K, K2, K3, K4]
+  ): this & $ReadOnly<T>;
+  removeIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>>,
+  >(
+    keyPath: [K, K2, K3, K4, K5]
+  ): this & $ReadOnly<T>;
+
+  updateIn<U>(
+    keyPath: [],
+    notSetValue: mixed,
+    updater: (value: this & T) => U
+  ): U;
+  updateIn<U>(keyPath: [], updater: (value: this & T) => U): U;
+  updateIn<NSV, K: $Keys<T>, S: $ValOf<T, K>>(
+    keyPath: [K],
+    notSetValue: NSV,
+    updater: (value: $ValOf<T, K>) => S
+  ): this & $ReadOnly<T>;
+  updateIn<K: $Keys<T>, S: $ValOf<T, K>>(
+    keyPath: [K],
+    updater: (value: $ValOf<T, K>) => S
+  ): this & $ReadOnly<T>;
+  updateIn<
+    NSV,
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    S: $ValOf<$ValOf<T, K>, K2>,
+  >(
+    keyPath: [K, K2],
+    notSetValue: NSV,
+    updater: (value: $ValOf<$ValOf<T, K>, K2> | NSV) => S
+  ): this & $ReadOnly<T>;
+  updateIn<K: $Keys<T>, K2: $KeyOf<$ValOf<T, K>>, S: $ValOf<$ValOf<T, K>, K2>>(
+    keyPath: [K, K2],
+    updater: (value: $ValOf<$ValOf<T, K>, K2>) => S
+  ): this & $ReadOnly<T>;
+  updateIn<
+    NSV,
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    S: $ValOf<$ValOf<$ValOf<T, K>, K2>, K3>,
+  >(
+    keyPath: [K, K2, K3],
+    notSetValue: NSV,
+    updater: (value: $ValOf<$ValOf<$ValOf<T, K>, K2>, K3> | NSV) => S
+  ): this & $ReadOnly<T>;
+  updateIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    S: $ValOf<$ValOf<$ValOf<T, K>, K2>, K3>,
+  >(
+    keyPath: [K, K2, K3],
+    updater: (value: $ValOf<$ValOf<$ValOf<T, K>, K2>, K3>) => S
+  ): this & $ReadOnly<T>;
+  updateIn<
+    NSV,
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>,
+    S: $ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>,
+  >(
+    keyPath: [K, K2, K3, K4],
+    notSetValue: NSV,
+    updater: (
+      value: $ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4> | NSV
+    ) => S
+  ): this & $ReadOnly<T>;
+  updateIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>,
+    S: $ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>,
+  >(
+    keyPath: [K, K2, K3, K4],
+    updater: (value: $ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>) => S
+  ): this & $ReadOnly<T>;
+  updateIn<
+    NSV,
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>>,
+    S: $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>, K5>,
+  >(
+    keyPath: [K, K2, K3, K4, K5],
+    notSetValue: NSV,
+    updater: (
+      value: $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>, K5> | NSV
+    ) => S
+  ): this & $ReadOnly<T>;
+  updateIn<
+    K: $Keys<T>,
+    K2: $KeyOf<$ValOf<T, K>>,
+    K3: $KeyOf<$ValOf<$ValOf<T, K>, K2>>,
+    K4: $KeyOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>>,
+    K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>>,
+    S: $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>, K5>,
+  >(
+    keyPath: [K, K2, K3, K4, K5],
+    updater: (
+      value: $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<T, K>, K2>, K3>, K4>, K5>
+    ) => S
+  ): this & $ReadOnly<T>;
+
+  mergeIn(
+    keyPath: Iterable<mixed>,
+    ...collections: Array<any>
+  ): this & $ReadOnly<T>;
+  mergeDeepIn(
+    keyPath: Iterable<mixed>,
+    ...collections: Array<any>
+  ): this & $ReadOnly<T>;
+
+  toSeq(): KeyedSeq<$Keys<T>, any>;
+
+  toJS(): { [key: $Keys<T>]: mixed };
+  toJSON(): T;
+  toObject(): T;
+
+  withMutations(mutator: (mutable: this & T) => mixed): this & $ReadOnly<T>;
+  asMutable(): this & $ReadOnly<T>;
+  wasAltered(): boolean;
+  asImmutable(): this & $ReadOnly<T>;
+
+  @@iterator(): Iterator<[$Keys<T>, $ValOf<T>]>;
+}
+
+declare function fromJS(
+  jsValue: mixed,
+  reviver?: (
+    key: string | number,
+    sequence: KeyedCollection<string, mixed> | IndexedCollection<mixed>,
+    path?: Array<string | number>
+  ) => mixed
+): Collection<mixed, mixed>;
+
+declare function is(first: mixed, second: mixed): boolean;
+declare function hash(value: mixed): number;
+
+declare function get<C: Object, K: $Keys<C>>(
+  collection: C,
+  key: K,
+  notSetValue: mixed
+): $ValOf<C, K>;
+declare function get<C, K: $KeyOf<C>, NSV>(
+  collection: C,
+  key: K,
+  notSetValue: NSV
+): $ValOf<C, K> | NSV;
+
+declare function has(collection: Object, key: mixed): boolean;
+declare function remove<C>(collection: C, key: $KeyOf<C>): C;
+declare function set<C, K: $KeyOf<C>, V: $ValOf<C, K>>(
+  collection: C,
+  key: K,
+  value: V
+): C;
+declare function update<C, K: $KeyOf<C>, V: $ValOf<C, K>, NSV>(
+  collection: C,
+  key: K,
+  notSetValue: NSV,
+  updater: ($ValOf<C, K> | NSV) => V
+): C;
+declare function update<C, K: $KeyOf<C>, V: $ValOf<C, K>>(
+  collection: C,
+  key: K,
+  updater: ($ValOf<C, K>) => V
+): C;
+
+declare function getIn<C>(collection: C, keyPath: [], notSetValue?: mixed): C;
+declare function getIn<C, K: $KeyOf<C>, NSV>(
+  collection: C,
+  keyPath: [K],
+  notSetValue: NSV
+): $ValOf<C, K> | NSV;
+declare function getIn<C, K: $KeyOf<C>, K2: $KeyOf<$ValOf<C, K>>, NSV>(
+  collection: C,
+  keyPath: [K, K2],
+  notSetValue: NSV
+): $ValOf<$ValOf<C, K>, K2> | NSV;
+declare function getIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  NSV,
+>(
+  collection: C,
+  keyPath: [K, K2, K3],
+  notSetValue: NSV
+): $ValOf<$ValOf<$ValOf<C, K>, K2>, K3> | NSV;
+declare function getIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  K4: $KeyOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>>,
+  NSV,
+>(
+  collection: C,
+  keyPath: [K, K2, K3, K4],
+  notSetValue: NSV
+): $ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4> | NSV;
+declare function getIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  K4: $KeyOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>>,
+  K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>>,
+  NSV,
+>(
+  collection: C,
+  keyPath: [K, K2, K3, K4, K5],
+  notSetValue: NSV
+): $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>, K5> | NSV;
+
+declare function hasIn(collection: Object, keyPath: Iterable<mixed>): boolean;
+
+declare function removeIn<C>(collection: C, keyPath: []): void;
+declare function removeIn<C, K: $KeyOf<C>>(collection: C, keyPath: [K]): C;
+declare function removeIn<C, K: $KeyOf<C>, K2: $KeyOf<$ValOf<C, K>>>(
+  collection: C,
+  keyPath: [K, K2]
+): C;
+declare function removeIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+>(
+  collection: C,
+  keyPath: [K, K2, K3]
+): C;
+declare function removeIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  K4: $KeyOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>>,
+>(
+  collection: C,
+  keyPath: [K, K2, K3, K4]
+): C;
+declare function removeIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  K4: $KeyOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>>,
+  K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>>,
+>(
+  collection: C,
+  keyPath: [K, K2, K3, K4, K5]
+): C;
+
+declare function setIn<S>(collection: Object, keyPath: [], value: S): S;
+declare function setIn<C, K: $KeyOf<C>, S: $ValOf<C, K>>(
+  collection: C,
+  keyPath: [K],
+  value: S
+): C;
+declare function setIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  S: $ValOf<$ValOf<C, K>, K2>,
+>(
+  collection: C,
+  keyPath: [K, K2],
+  value: S
+): C;
+declare function setIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  S: $ValOf<$ValOf<$ValOf<C, K>, K2>, K3>,
+>(
+  collection: C,
+  keyPath: [K, K2, K3],
+  value: S
+): C;
+declare function setIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  K4: $KeyOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>>,
+  S: $ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>,
+>(
+  collection: C,
+  keyPath: [K, K2, K3, K4],
+  value: S
+): C;
+declare function setIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  K4: $KeyOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>>,
+  K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>>,
+  S: $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>, K5>,
+>(
+  collection: C,
+  keyPath: [K, K2, K3, K4, K5],
+  value: S
+): C;
+
+declare function updateIn<C, S>(
+  collection: C,
+  keyPath: [],
+  notSetValue: mixed,
+  updater: (value: C) => S
+): S;
+declare function updateIn<C, S>(
+  collection: C,
+  keyPath: [],
+  updater: (value: C) => S
+): S;
+declare function updateIn<C, K: $KeyOf<C>, S: $ValOf<C, K>, NSV>(
+  collection: C,
+  keyPath: [K],
+  notSetValue: NSV,
+  updater: (value: $ValOf<C, K> | NSV) => S
+): C;
+declare function updateIn<C, K: $KeyOf<C>, S: $ValOf<C, K>>(
+  collection: C,
+  keyPath: [K],
+  updater: (value: $ValOf<C, K>) => S
+): C;
+declare function updateIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  S: $ValOf<$ValOf<C, K>, K2>,
+  NSV,
+>(
+  collection: C,
+  keyPath: [K, K2],
+  notSetValue: NSV,
+  updater: (value: $ValOf<$ValOf<C, K>, K2> | NSV) => S
+): C;
+declare function updateIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  S: $ValOf<$ValOf<C, K>, K2>,
+>(
+  collection: C,
+  keyPath: [K, K2],
+  updater: (value: $ValOf<$ValOf<C, K>, K2>) => S
+): C;
+declare function updateIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  S: $ValOf<$ValOf<$ValOf<C, K>, K2>, K3>,
+  NSV,
+>(
+  collection: C,
+  keyPath: [K, K2, K3],
+  notSetValue: NSV,
+  updater: (value: $ValOf<$ValOf<$ValOf<C, K>, K2>, K3> | NSV) => S
+): C;
+declare function updateIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  S: $ValOf<$ValOf<$ValOf<C, K>, K2>, K3>,
+>(
+  collection: C,
+  keyPath: [K, K2, K3],
+  updater: (value: $ValOf<$ValOf<$ValOf<C, K>, K2>, K3>) => S
+): C;
+declare function updateIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  K4: $KeyOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>>,
+  S: $ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>,
+  NSV,
+>(
+  collection: C,
+  keyPath: [K, K2, K3, K4],
+  notSetValue: NSV,
+  updater: (value: $ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4> | NSV) => S
+): C;
+declare function updateIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  K4: $KeyOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>>,
+  S: $ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>,
+>(
+  collection: C,
+  keyPath: [K, K2, K3, K4],
+  updater: (value: $ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>) => S
+): C;
+declare function updateIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  K4: $KeyOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>>,
+  K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>>,
+  S: $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>, K5>,
+  NSV,
+>(
+  collection: C,
+  keyPath: [K, K2, K3, K4, K5],
+  notSetValue: NSV,
+  updater: (
+    value: $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>, K5> | NSV
+  ) => S
+): C;
+declare function updateIn<
+  C,
+  K: $KeyOf<C>,
+  K2: $KeyOf<$ValOf<C, K>>,
+  K3: $KeyOf<$ValOf<$ValOf<C, K>, K2>>,
+  K4: $KeyOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>>,
+  K5: $KeyOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>>,
+  S: $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>, K5>,
+>(
+  collection: C,
+  keyPath: [K, K2, K3, K4, K5],
+  updater: (
+    value: $ValOf<$ValOf<$ValOf<$ValOf<$ValOf<C, K>, K2>, K3>, K4>, K5>
+  ) => S
+): C;
+
+declare function merge<C>(
+  collection: C,
+  ...collections: Array<
+    | $IterableOf<C>
+    | $Shape<RecordValues<C>>
+    | PlainObjInput<$KeyOf<C>, $ValOf<C>>,
+  >
+): C;
+declare function mergeWith<C>(
+  merger: (oldVal: $ValOf<C>, newVal: $ValOf<C>, key: $KeyOf<C>) => $ValOf<C>,
+  collection: C,
+  ...collections: Array<
+    | $IterableOf<C>
+    | $Shape<RecordValues<C>>
+    | PlainObjInput<$KeyOf<C>, $ValOf<C>>,
+  >
+): C;
+declare function mergeDeep<C>(
+  collection: C,
+  ...collections: Array<
+    | $IterableOf<C>
+    | $Shape<RecordValues<C>>
+    | PlainObjInput<$KeyOf<C>, $ValOf<C>>,
+  >
+): C;
+declare function mergeDeepWith<C>(
+  merger: (oldVal: any, newVal: any, key: any) => mixed,
+  collection: C,
+  ...collections: Array<
+    | $IterableOf<C>
+    | $Shape<RecordValues<C>>
+    | PlainObjInput<$KeyOf<C>, $ValOf<C>>,
+  >
+): C;
+
+export {
+  Collection,
+  Seq,
+  List,
+  Map,
+  OrderedMap,
+  OrderedSet,
+  Range,
+  Repeat,
+  Record,
+  Set,
+  Stack,
+  fromJS,
+  is,
+  hash,
+  isImmutable,
+  isCollection,
+  isKeyed,
+  isIndexed,
+  isAssociative,
+  isOrdered,
+  isRecord,
+  isValueObject,
+  get,
+  has,
+  remove,
+  set,
+  update,
+  getIn,
+  hasIn,
+  removeIn,
+  setIn,
+  updateIn,
+  merge,
+  mergeWith,
+  mergeDeep,
+  mergeDeepWith,
+};
+
+export default {
+  Collection,
+  Seq,
+
+  List,
+  Map,
+  OrderedMap,
+  OrderedSet,
+  PairSorting,
+  Range,
+  Repeat,
+  Record,
+  Set,
+  Stack,
+
+  fromJS,
+  is,
+  hash,
+
+  isImmutable,
+  isCollection,
+  isKeyed,
+  isIndexed,
+  isAssociative,
+  isOrdered,
+  isRecord,
+  isValueObject,
+
+  get,
+  has,
+  remove,
+  set,
+  update,
+  getIn,
+  hasIn,
+  removeIn,
+  setIn,
+  updateIn,
+  merge,
+  mergeWith,
+  mergeDeep,
+  mergeDeepWith,
+};
+
+export type {
+  Comparator,
+  KeyedCollection,
+  IndexedCollection,
+  SetCollection,
+  KeyedSeq,
+  IndexedSeq,
+  SetSeq,
+  RecordFactory,
+  RecordOf,
+  RecordInstance,
+  ValueObject,
+  $KeyOf,
+  $ValOf,
+};

Datei-Diff unterdrückt, da er zu groß ist
+ 24 - 0
node_modules/immutable/dist/immutable.min.js


+ 38 - 0
node_modules/immutable/package.json

@@ -0,0 +1,38 @@
+{
+  "name": "immutable",
+  "version": "5.1.3",
+  "description": "Immutable Data Collections",
+  "license": "MIT",
+  "homepage": "https://immutable-js.com",
+  "author": {
+    "name": "Lee Byron",
+    "url": "https://github.com/leebyron"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://github.com/immutable-js/immutable-js.git"
+  },
+  "bugs": {
+    "url": "https://github.com/immutable-js/immutable-js/issues"
+  },
+  "main": "dist/immutable.js",
+  "module": "dist/immutable.es.js",
+  "types": "dist/immutable.d.ts",
+  "files": [
+    "dist",
+    "README.md",
+    "LICENSE"
+  ],
+  "keywords": [
+    "immutable",
+    "persistent",
+    "lazy",
+    "data",
+    "datastructure",
+    "functional",
+    "collection",
+    "stateless",
+    "sequence",
+    "iteration"
+  ]
+}

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.