Mirror: A Node.js fetch shim using built-in Request, Response, and Headers (but without native fetch)

Compare changes

Choose any two refs to compare.

+1160 -254
+25
.github/workflows/mirror.yml
···
··· 1 + name: Mirror 2 + on: 3 + push: 4 + branches: 5 + - main 6 + jobs: 7 + mirror: 8 + runs-on: ubuntu-latest 9 + steps: 10 + - name: Checkout repository 11 + uses: actions/checkout@v4 12 + with: 13 + fetch-depth: 0 14 + fetch-tags: true 15 + - name: Mirror 16 + env: 17 + MIRROR_SSH_KEY: ${{ secrets.MIRROR_SSH_KEY }} 18 + GIT_SSH_COMMAND: 'ssh -o StrictHostKeyChecking=yes' 19 + run: | 20 + mkdir -p ~/.ssh 21 + echo "$MIRROR_SSH_KEY" > ~/.ssh/id_rsa 22 + chmod 600 ~/.ssh/id_rsa 23 + ssh-keyscan -H knot.kitten.sh >> ~/.ssh/known_hosts 24 + git remote add mirror "git@knot.kitten.sh:kitten.sh/${GITHUB_REPOSITORY#*/}" 25 + git push --mirror mirror
+7 -6
.github/workflows/release.yml
··· 7 jobs: 8 release: 9 name: Release 10 - runs-on: ubuntu-20.04 11 timeout-minutes: 20 12 permissions: 13 contents: write ··· 32 - name: Setup Node 33 uses: actions/setup-node@v4 34 with: 35 - node-version: 22 36 cache: 'pnpm' 37 38 - name: Install Dependencies 39 run: pnpm install --frozen-lockfile --prefer-offline 40 41 - name: PR or Publish 42 id: changesets 43 - uses: changesets/action@v1.4.5 44 with: 45 version: pnpm changeset:version 46 publish: pnpm changeset:publish 47 env: 48 - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 49 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 50 51 - name: Publish Prerelease 52 if: steps.changesets.outputs.published != 'true' 53 env: 54 - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 55 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 56 run: | 57 - npm config set "//registry.npmjs.org/:_authToken" "$NPM_TOKEN" 58 git reset --hard origin/main 59 pnpm changeset version --no-git-tag --snapshot canary 60 pnpm changeset publish --no-git-tag --snapshot canary --tag canary
··· 7 jobs: 8 release: 9 name: Release 10 + runs-on: ubuntu-latest 11 timeout-minutes: 20 12 permissions: 13 contents: write ··· 32 - name: Setup Node 33 uses: actions/setup-node@v4 34 with: 35 + node-version: 20 36 + registry-url: 'https://registry.npmjs.org' 37 cache: 'pnpm' 38 39 - name: Install Dependencies 40 run: pnpm install --frozen-lockfile --prefer-offline 41 42 + - name: Update npm 43 + run: npm install -g npm@11.6 44 + 45 - name: PR or Publish 46 id: changesets 47 + uses: changesets/action@v1.5.3 48 with: 49 version: pnpm changeset:version 50 publish: pnpm changeset:publish 51 env: 52 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 53 54 - name: Publish Prerelease 55 if: steps.changesets.outputs.published != 'true' 56 env: 57 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 58 run: | 59 git reset --hard origin/main 60 pnpm changeset version --no-git-tag --snapshot canary 61 pnpm changeset publish --no-git-tag --snapshot canary --tag canary
+86
CHANGELOG.md
··· 1 # minifetch 2 3 ## 0.2.0 4 5 ### Minor Changes
··· 1 # minifetch 2 3 + ## 0.4.6 4 + 5 + ### Patch Changes 6 + 7 + - Replace undici `Response` with `node:stream/consumers` in body helper 8 + Submitted by [@kitten](https://github.com/kitten) (See [#32](https://github.com/kitten/fetch-nodeshim/pull/32)) 9 + 10 + ## 0.4.5 11 + 12 + ### Patch Changes 13 + 14 + - โš ๏ธ Fix `Content-Type` being overridden for string inputs when it's already set 15 + Submitted by [@kitten](https://github.com/kitten) (See [#30](https://github.com/kitten/fetch-nodeshim/pull/30)) 16 + 17 + ## 0.4.4 18 + 19 + ### Patch Changes 20 + 21 + - Limit state in which `incoming.socket` is unrefed and instead `.ref()` it when the body is being read, and `.unref()` it again when reading stops 22 + Submitted by [@kitten](https://github.com/kitten) (See [#28](https://github.com/kitten/fetch-nodeshim/pull/28)) 23 + 24 + ## 0.4.3 25 + 26 + ### Patch Changes 27 + 28 + - โš ๏ธ Fix typo in `NO_PROXY` construction 29 + Submitted by [@kitten](https://github.com/kitten) (See [#18](https://github.com/kitten/fetch-nodeshim/pull/18)) 30 + - Set `Content-Length: 0` when `response.body` is `null` for `PATCH` as well 31 + Submitted by [@kitten](https://github.com/kitten) (See [#23](https://github.com/kitten/fetch-nodeshim/pull/23)) 32 + - Protect against invalid `Location` URI 33 + Submitted by [@kitten](https://github.com/kitten) (See [#26](https://github.com/kitten/fetch-nodeshim/pull/26)) 34 + - Issue an explicit `ETIMEDOUT` when the request times out 35 + Submitted by [@kitten](https://github.com/kitten) (See [#24](https://github.com/kitten/fetch-nodeshim/pull/24)) 36 + - โš ๏ธ Fix `Set-Cookie` list handling by capturing them with `Headers#append` 37 + Submitted by [@kitten](https://github.com/kitten) (See [#20](https://github.com/kitten/fetch-nodeshim/pull/20)) 38 + - Reset `requestOptions.agent` on retry/redirect 39 + Submitted by [@kitten](https://github.com/kitten) (See [#27](https://github.com/kitten/fetch-nodeshim/pull/27)) 40 + - โš ๏ธ Fix `_final` on `InflateStream` calling `callback` before full flush 41 + Submitted by [@kitten](https://github.com/kitten) (See [#25](https://github.com/kitten/fetch-nodeshim/pull/25)) 42 + - Propagate errors for duplex request/response streams, and ensure early errors propagate to the Response stream 43 + Submitted by [@kitten](https://github.com/kitten) (See [#16](https://github.com/kitten/fetch-nodeshim/pull/16)) 44 + - Protect against missing `Symbol.toStringTag` 45 + Submitted by [@kitten](https://github.com/kitten) (See [#19](https://github.com/kitten/fetch-nodeshim/pull/19)) 46 + 47 + ## 0.4.2 48 + 49 + ### Patch Changes 50 + 51 + - Unref the incoming socket when the timeout is disabled, to prevent body streams that never start from keeping processes alive 52 + Submitted by [@kitten](https://github.com/kitten) (See [#14](https://github.com/kitten/fetch-nodeshim/pull/14)) 53 + 54 + ## 0.4.1 55 + 56 + ### Patch Changes 57 + 58 + - Add sane default timeout to `http.request` 59 + Submitted by [@kitten](https://github.com/kitten) (See [#12](https://github.com/kitten/fetch-nodeshim/pull/12)) 60 + 61 + ## 0.4.0 62 + 63 + ### Minor Changes 64 + 65 + - Add automatic configuration for `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY` similar to the upcoming Node 24+ built-in support. Agents will automatically be created and used when these environment variables are set 66 + Submitted by [@kitten](https://github.com/kitten) (See [#8](https://github.com/kitten/fetch-nodeshim/pull/8)) 67 + 68 + ### Patch Changes 69 + 70 + - Prevent outright error when `--no-experimental-fetch` is set, which causes `Request`, `Response`, `FormData`, and `Headers` to not be available globally 71 + Submitted by [@kitten](https://github.com/kitten) (See [#11](https://github.com/kitten/fetch-nodeshim/pull/11)) 72 + - Update rollup config for reduced output and exclude sources from sourcemaps 73 + Submitted by [@kitten](https://github.com/kitten) (See [#9](https://github.com/kitten/fetch-nodeshim/pull/9)) 74 + 75 + ## 0.3.0 76 + 77 + ### Minor Changes 78 + 79 + - Add `Body` mixin as export 80 + Submitted by [@kitten](https://github.com/kitten) (See [#6](https://github.com/kitten/fetch-nodeshim/pull/6)) 81 + 82 + ## 0.2.1 83 + 84 + ### Patch Changes 85 + 86 + - Provenance Release 87 + Submitted by [@kitten](https://github.com/kitten) (See [#4](https://github.com/kitten/fetch-nodeshim/pull/4)) 88 + 89 ## 0.2.0 90 91 ### Minor Changes
+1
LICENSE.md
··· 1 MIT License 2 3 Copyright (c) Phil Pluckthun, 4 Copyright (c) 2016 - 2020 Node Fetch Team, 5 Copyright (c) Remix Software Inc. 2020-2021, 6 Copyright (c) Shopify Inc. 2022-2024
··· 1 MIT License 2 3 Copyright (c) Phil Pluckthun, 4 + Copyright (c) 650 Industries, Inc. (aka Expo), 5 Copyright (c) 2016 - 2020 Node Fetch Team, 6 Copyright (c) Remix Software Inc. 2020-2021, 7 Copyright (c) Shopify Inc. 2022-2024
+11 -2
package.json
··· 1 { 2 "name": "fetch-nodeshim", 3 - "version": "0.2.0", 4 "description": "A Node.js fetch shim using built-in Request, Response, and Headers (but without native fetch)", 5 "author": "Phil Pluckthun <phil@kitten.sh>", 6 "source": "./src/index.ts", ··· 47 }, 48 "keywords": [], 49 "license": "MIT", 50 "devDependencies": { 51 "@babel/plugin-transform-block-scoping": "^7.25.9", 52 "@babel/plugin-transform-typescript": "^7.26.7", 53 - "@changesets/cli": "^2.27.1", 54 "@changesets/get-github-info": "^0.6.0", 55 "@rollup/plugin-babel": "^6.0.4", 56 "@rollup/plugin-commonjs": "^28.0.2", ··· 65 "lint-staged": "^15.4.3", 66 "npm-run-all": "^4.1.5", 67 "prettier": "^3.4.2", 68 "rimraf": "^6.0.1", 69 "rollup": "^4.32.1", 70 "rollup-plugin-cjs-check": "^1.0.3", ··· 72 "typescript": "^5.7.3", 73 "undici-types": "^6.20.0", 74 "vitest": "^3.0.4" 75 } 76 }
··· 1 { 2 "name": "fetch-nodeshim", 3 + "version": "0.4.6", 4 "description": "A Node.js fetch shim using built-in Request, Response, and Headers (but without native fetch)", 5 "author": "Phil Pluckthun <phil@kitten.sh>", 6 "source": "./src/index.ts", ··· 47 }, 48 "keywords": [], 49 "license": "MIT", 50 + "repository": "https://github.com/kitten/fetch-nodeshim", 51 + "bugs": { 52 + "url": "https://github.com/kitten/fetch-nodeshim/issues" 53 + }, 54 "devDependencies": { 55 "@babel/plugin-transform-block-scoping": "^7.25.9", 56 "@babel/plugin-transform-typescript": "^7.26.7", 57 + "@changesets/cli": "^2.29.6", 58 "@changesets/get-github-info": "^0.6.0", 59 "@rollup/plugin-babel": "^6.0.4", 60 "@rollup/plugin-commonjs": "^28.0.2", ··· 69 "lint-staged": "^15.4.3", 70 "npm-run-all": "^4.1.5", 71 "prettier": "^3.4.2", 72 + "proxy-chain": "^2.7.1", 73 "rimraf": "^6.0.1", 74 "rollup": "^4.32.1", 75 "rollup-plugin-cjs-check": "^1.0.3", ··· 77 "typescript": "^5.7.3", 78 "undici-types": "^6.20.0", 79 "vitest": "^3.0.4" 80 + }, 81 + "publishConfig": { 82 + "access": "public", 83 + "provenance": true 84 } 85 }
+348 -165
pnpm-lock.yaml
··· 15 specifier: ^7.26.7 16 version: 7.26.7(@babel/core@7.26.7) 17 '@changesets/cli': 18 - specifier: ^2.27.1 19 - version: 2.27.12 20 '@changesets/get-github-info': 21 specifier: ^0.6.0 22 version: 0.6.0 ··· 59 prettier: 60 specifier: ^3.4.2 61 version: 3.4.2 62 rimraf: 63 specifier: ^6.0.1 64 version: 6.0.1 ··· 91 resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} 92 engines: {node: '>=6.9.0'} 93 94 - '@babel/compat-data@7.26.5': 95 - resolution: {integrity: sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg==} 96 engines: {node: '>=6.9.0'} 97 98 '@babel/core@7.26.7': ··· 103 resolution: {integrity: sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==} 104 engines: {node: '>=6.9.0'} 105 106 '@babel/helper-annotate-as-pure@7.25.9': 107 resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} 108 engines: {node: '>=6.9.0'} 109 110 - '@babel/helper-compilation-targets@7.26.5': 111 - resolution: {integrity: sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==} 112 engines: {node: '>=6.9.0'} 113 114 '@babel/helper-create-class-features-plugin@7.25.9': ··· 117 peerDependencies: 118 '@babel/core': ^7.0.0 119 120 '@babel/helper-member-expression-to-functions@7.25.9': 121 resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==} 122 engines: {node: '>=6.9.0'} ··· 125 resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} 126 engines: {node: '>=6.9.0'} 127 128 - '@babel/helper-module-transforms@7.26.0': 129 - resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} 130 engines: {node: '>=6.9.0'} 131 peerDependencies: 132 '@babel/core': ^7.0.0 ··· 153 resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} 154 engines: {node: '>=6.9.0'} 155 156 '@babel/helper-validator-identifier@7.25.9': 157 resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} 158 engines: {node: '>=6.9.0'} 159 160 - '@babel/helper-validator-option@7.25.9': 161 - resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} 162 engines: {node: '>=6.9.0'} 163 164 - '@babel/helpers@7.26.7': 165 - resolution: {integrity: sha512-8NHiL98vsi0mbPQmYAGWwfcFaOy4j2HY49fXJCfuDcdE7fMIsH9a7GdaeXpIBsbT7307WU8KCMp5pUVDNL4f9A==} 166 engines: {node: '>=6.9.0'} 167 168 '@babel/parser@7.26.7': 169 resolution: {integrity: sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==} 170 engines: {node: '>=6.0.0'} 171 hasBin: true 172 ··· 196 resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} 197 engines: {node: '>=6.9.0'} 198 199 '@babel/traverse@7.26.7': 200 resolution: {integrity: sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA==} 201 engines: {node: '>=6.9.0'} 202 203 '@babel/types@7.26.7': 204 resolution: {integrity: sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==} 205 engines: {node: '>=6.9.0'} 206 207 - '@changesets/apply-release-plan@7.0.8': 208 - resolution: {integrity: sha512-qjMUj4DYQ1Z6qHawsn7S71SujrExJ+nceyKKyI9iB+M5p9lCL55afuEd6uLBPRpLGWQwkwvWegDHtwHJb1UjpA==} 209 210 - '@changesets/assemble-release-plan@6.0.5': 211 - resolution: {integrity: sha512-IgvBWLNKZd6k4t72MBTBK3nkygi0j3t3zdC1zrfusYo0KpdsvnDjrMM9vPnTCLCMlfNs55jRL4gIMybxa64FCQ==} 212 213 - '@changesets/changelog-git@0.2.0': 214 - resolution: {integrity: sha512-bHOx97iFI4OClIT35Lok3sJAwM31VbUM++gnMBV16fdbtBhgYu4dxsphBF/0AZZsyAHMrnM0yFcj5gZM1py6uQ==} 215 216 - '@changesets/cli@2.27.12': 217 - resolution: {integrity: sha512-9o3fOfHYOvBnyEn0mcahB7wzaA3P4bGJf8PNqGit5PKaMEFdsRixik+txkrJWd2VX+O6wRFXpxQL8j/1ANKE9g==} 218 hasBin: true 219 220 - '@changesets/config@3.0.5': 221 - resolution: {integrity: sha512-QyXLSSd10GquX7hY0Mt4yQFMEeqnO5z/XLpbIr4PAkNNoQNKwDyiSrx4yd749WddusH1v3OSiA0NRAYmH/APpQ==} 222 223 '@changesets/errors@0.2.0': 224 resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} 225 226 - '@changesets/get-dependents-graph@2.1.2': 227 - resolution: {integrity: sha512-sgcHRkiBY9i4zWYBwlVyAjEM9sAzs4wYVwJUdnbDLnVG3QwAaia1Mk5P8M7kraTOZN+vBET7n8KyB0YXCbFRLQ==} 228 229 '@changesets/get-github-info@0.6.0': 230 resolution: {integrity: sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA==} 231 232 - '@changesets/get-release-plan@4.0.6': 233 - resolution: {integrity: sha512-FHRwBkY7Eili04Y5YMOZb0ezQzKikTka4wL753vfUA5COSebt7KThqiuCN9BewE4/qFGgF/5t3AuzXx1/UAY4w==} 234 235 '@changesets/get-version-range-type@0.4.0': 236 resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} 237 238 - '@changesets/git@3.0.2': 239 - resolution: {integrity: sha512-r1/Kju9Y8OxRRdvna+nxpQIsMsRQn9dhhAZt94FLDeu0Hij2hnOozW8iqnHBgvu+KdnJppCveQwK4odwfw/aWQ==} 240 241 '@changesets/logger@0.1.1': 242 resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==} 243 244 - '@changesets/parse@0.4.0': 245 - resolution: {integrity: sha512-TS/9KG2CdGXS27S+QxbZXgr8uPsP4yNJYb4BC2/NeFUj80Rni3TeD2qwWmabymxmrLo7JEsytXH1FbpKTbvivw==} 246 247 - '@changesets/pre@2.0.1': 248 - resolution: {integrity: sha512-vvBJ/If4jKM4tPz9JdY2kGOgWmCowUYOi5Ycv8dyLnEE8FgpYYUo1mgJZxcdtGGP3aG8rAQulGLyyXGSLkIMTQ==} 249 250 - '@changesets/read@0.6.2': 251 - resolution: {integrity: sha512-wjfQpJvryY3zD61p8jR87mJdyx2FIhEcdXhKUqkja87toMrP/3jtg/Yg29upN+N4Ckf525/uvV7a4tzBlpk6gg==} 252 253 - '@changesets/should-skip-package@0.1.1': 254 - resolution: {integrity: sha512-H9LjLbF6mMHLtJIc/eHR9Na+MifJ3VxtgP/Y+XLn4BF7tDTEN1HNYtH6QMcjP1uxp9sjaFYmW8xqloaCi/ckTg==} 255 256 '@changesets/types@4.1.0': 257 resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} 258 259 - '@changesets/types@6.0.0': 260 - resolution: {integrity: sha512-b1UkfNulgKoWfqyHtzKS5fOZYSJO+77adgL7DLRDr+/7jhChN+QcHnbjiQVOz/U+Ts3PGNySq7diAItzDgugfQ==} 261 262 - '@changesets/write@0.3.2': 263 - resolution: {integrity: sha512-kDxDrPNpUgsjDbWBvUo27PzKX4gqeKOlhibaOXDJA6kuBisGqNHv/HwGJrAu8U/dSf8ZEFIeHIPtvSlZI1kULw==} 264 265 '@esbuild/aix-ppc64@0.24.2': 266 resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} ··· 412 cpu: [x64] 413 os: [win32] 414 415 '@isaacs/cliui@8.0.2': 416 resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} 417 engines: {node: '>=12'} 418 419 '@jridgewell/gen-mapping@0.3.8': 420 resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} ··· 434 '@jridgewell/sourcemap-codec@1.5.0': 435 resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} 436 437 '@jridgewell/trace-mapping@0.3.25': 438 resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} 439 440 '@manypkg/find-root@1.1.0': 441 resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} ··· 651 engines: {node: '>=0.4.0'} 652 hasBin: true 653 654 ansi-colors@4.1.3: 655 resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} 656 engines: {node: '>=6'} ··· 726 resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 727 engines: {node: '>=8'} 728 729 - browserslist@4.24.4: 730 - resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} 731 engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 732 hasBin: true 733 ··· 754 resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==} 755 engines: {node: '>= 0.4'} 756 757 - caniuse-lite@1.0.30001696: 758 - resolution: {integrity: sha512-pDCPkvzfa39ehJtJ+OwGT/2yvT2SbjfHhiIW2LWOAcMQ7BzwxT/XuyUp4OTOd0XFWA6BKw0JalnBHgSi5DGJBQ==} 759 760 chai@5.1.2: 761 resolution: {integrity: sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==} ··· 769 resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} 770 engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} 771 772 - chardet@0.7.0: 773 - resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} 774 775 check-error@2.1.1: 776 resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} ··· 859 supports-color: 860 optional: true 861 862 deep-eql@5.0.2: 863 resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} 864 engines: {node: '>=6'} ··· 902 eastasianwidth@0.2.0: 903 resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} 904 905 - electron-to-chromium@1.5.90: 906 - resolution: {integrity: sha512-C3PN4aydfW91Natdyd449Kw+BzhLmof6tzy5W1pFC5SpQxVXT+oyiyOG9AgYYSN9OdA/ik3YkCrpwqI8ug5Tug==} 907 908 emoji-regex@10.4.0: 909 resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} ··· 989 990 extendable-error@0.1.7: 991 resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} 992 - 993 - external-editor@3.1.0: 994 - resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} 995 - engines: {node: '>=4'} 996 997 fast-glob@3.3.3: 998 resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} ··· 1134 hosted-git-info@2.8.9: 1135 resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} 1136 1137 - human-id@1.0.2: 1138 - resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} 1139 1140 human-signals@5.0.0: 1141 resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} 1142 engines: {node: '>=16.17.0'} 1143 1144 - iconv-lite@0.4.24: 1145 - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} 1146 engines: {node: '>=0.10.0'} 1147 1148 ignore@5.3.2: ··· 1152 internal-slot@1.1.0: 1153 resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} 1154 engines: {node: '>= 0.4'} 1155 1156 is-array-buffer@3.0.5: 1157 resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} ··· 1461 resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} 1462 engines: {node: '>=18'} 1463 1464 - os-tmpdir@1.0.2: 1465 - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} 1466 - engines: {node: '>=0.10.0'} 1467 - 1468 outdent@0.5.0: 1469 resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} 1470 ··· 1587 engines: {node: '>=14'} 1588 hasBin: true 1589 1590 queue-microtask@1.2.3: 1591 resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1592 ··· 1759 resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} 1760 engines: {node: '>=18'} 1761 1762 smob@1.5.0: 1763 resolution: {integrity: sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==} 1764 1765 source-map-js@1.2.1: 1766 resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} ··· 1884 resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} 1885 engines: {node: '>=14.0.0'} 1886 1887 - tmp@0.0.33: 1888 - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} 1889 - engines: {node: '>=0.6.0'} 1890 - 1891 to-regex-range@5.0.1: 1892 resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1893 engines: {node: '>=8.0'} 1894 1895 tr46@0.0.3: 1896 resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} 1897 1898 typed-array-buffer@1.0.3: 1899 resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} ··· 1933 resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} 1934 engines: {node: '>= 4.0.0'} 1935 1936 - update-browserslist-db@1.1.2: 1937 - resolution: {integrity: sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==} 1938 hasBin: true 1939 peerDependencies: 1940 browserslist: '>= 4.21.0' ··· 2075 2076 '@ampproject/remapping@2.3.0': 2077 dependencies: 2078 - '@jridgewell/gen-mapping': 0.3.8 2079 - '@jridgewell/trace-mapping': 0.3.25 2080 2081 '@babel/code-frame@7.26.2': 2082 dependencies: ··· 2084 js-tokens: 4.0.0 2085 picocolors: 1.1.1 2086 2087 - '@babel/compat-data@7.26.5': {} 2088 2089 '@babel/core@7.26.7': 2090 dependencies: 2091 '@ampproject/remapping': 2.3.0 2092 - '@babel/code-frame': 7.26.2 2093 - '@babel/generator': 7.26.5 2094 - '@babel/helper-compilation-targets': 7.26.5 2095 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.7) 2096 - '@babel/helpers': 7.26.7 2097 - '@babel/parser': 7.26.7 2098 - '@babel/template': 7.25.9 2099 - '@babel/traverse': 7.26.7 2100 - '@babel/types': 7.26.7 2101 convert-source-map: 2.0.0 2102 - debug: 4.4.0 2103 gensync: 1.0.0-beta.2 2104 json5: 2.2.3 2105 semver: 6.3.1 ··· 2114 '@jridgewell/trace-mapping': 0.3.25 2115 jsesc: 3.1.0 2116 2117 '@babel/helper-annotate-as-pure@7.25.9': 2118 dependencies: 2119 '@babel/types': 7.26.7 2120 2121 - '@babel/helper-compilation-targets@7.26.5': 2122 dependencies: 2123 - '@babel/compat-data': 7.26.5 2124 - '@babel/helper-validator-option': 7.25.9 2125 - browserslist: 4.24.4 2126 lru-cache: 5.1.1 2127 semver: 6.3.1 2128 ··· 2138 semver: 6.3.1 2139 transitivePeerDependencies: 2140 - supports-color 2141 2142 '@babel/helper-member-expression-to-functions@7.25.9': 2143 dependencies: ··· 2153 transitivePeerDependencies: 2154 - supports-color 2155 2156 - '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.7)': 2157 dependencies: 2158 '@babel/core': 7.26.7 2159 - '@babel/helper-module-imports': 7.25.9 2160 - '@babel/helper-validator-identifier': 7.25.9 2161 - '@babel/traverse': 7.26.7 2162 transitivePeerDependencies: 2163 - supports-color 2164 ··· 2186 2187 '@babel/helper-string-parser@7.25.9': {} 2188 2189 '@babel/helper-validator-identifier@7.25.9': {} 2190 2191 - '@babel/helper-validator-option@7.25.9': {} 2192 2193 - '@babel/helpers@7.26.7': 2194 dependencies: 2195 - '@babel/template': 7.25.9 2196 - '@babel/types': 7.26.7 2197 2198 '@babel/parser@7.26.7': 2199 dependencies: 2200 '@babel/types': 7.26.7 2201 2202 '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.7)': 2203 dependencies: ··· 2230 '@babel/parser': 7.26.7 2231 '@babel/types': 7.26.7 2232 2233 '@babel/traverse@7.26.7': 2234 dependencies: 2235 '@babel/code-frame': 7.26.2 ··· 2242 transitivePeerDependencies: 2243 - supports-color 2244 2245 '@babel/types@7.26.7': 2246 dependencies: 2247 '@babel/helper-string-parser': 7.25.9 2248 '@babel/helper-validator-identifier': 7.25.9 2249 2250 - '@changesets/apply-release-plan@7.0.8': 2251 dependencies: 2252 - '@changesets/config': 3.0.5 2253 '@changesets/get-version-range-type': 0.4.0 2254 - '@changesets/git': 3.0.2 2255 - '@changesets/should-skip-package': 0.1.1 2256 - '@changesets/types': 6.0.0 2257 '@manypkg/get-packages': 1.1.3 2258 detect-indent: 6.1.0 2259 fs-extra: 7.0.1 ··· 2263 resolve-from: 5.0.0 2264 semver: 7.7.0 2265 2266 - '@changesets/assemble-release-plan@6.0.5': 2267 dependencies: 2268 '@changesets/errors': 0.2.0 2269 - '@changesets/get-dependents-graph': 2.1.2 2270 - '@changesets/should-skip-package': 0.1.1 2271 - '@changesets/types': 6.0.0 2272 '@manypkg/get-packages': 1.1.3 2273 semver: 7.7.0 2274 2275 - '@changesets/changelog-git@0.2.0': 2276 dependencies: 2277 - '@changesets/types': 6.0.0 2278 2279 - '@changesets/cli@2.27.12': 2280 dependencies: 2281 - '@changesets/apply-release-plan': 7.0.8 2282 - '@changesets/assemble-release-plan': 6.0.5 2283 - '@changesets/changelog-git': 0.2.0 2284 - '@changesets/config': 3.0.5 2285 '@changesets/errors': 0.2.0 2286 - '@changesets/get-dependents-graph': 2.1.2 2287 - '@changesets/get-release-plan': 4.0.6 2288 - '@changesets/git': 3.0.2 2289 '@changesets/logger': 0.1.1 2290 - '@changesets/pre': 2.0.1 2291 - '@changesets/read': 0.6.2 2292 - '@changesets/should-skip-package': 0.1.1 2293 - '@changesets/types': 6.0.0 2294 - '@changesets/write': 0.3.2 2295 '@manypkg/get-packages': 1.1.3 2296 ansi-colors: 4.1.3 2297 ci-info: 3.9.0 2298 enquirer: 2.4.1 2299 - external-editor: 3.1.0 2300 fs-extra: 7.0.1 2301 mri: 1.2.0 2302 p-limit: 2.3.0 ··· 2306 semver: 7.7.0 2307 spawndamnit: 3.0.1 2308 term-size: 2.2.1 2309 2310 - '@changesets/config@3.0.5': 2311 dependencies: 2312 '@changesets/errors': 0.2.0 2313 - '@changesets/get-dependents-graph': 2.1.2 2314 '@changesets/logger': 0.1.1 2315 - '@changesets/types': 6.0.0 2316 '@manypkg/get-packages': 1.1.3 2317 fs-extra: 7.0.1 2318 micromatch: 4.0.8 ··· 2321 dependencies: 2322 extendable-error: 0.1.7 2323 2324 - '@changesets/get-dependents-graph@2.1.2': 2325 dependencies: 2326 - '@changesets/types': 6.0.0 2327 '@manypkg/get-packages': 1.1.3 2328 picocolors: 1.1.1 2329 semver: 7.7.0 ··· 2335 transitivePeerDependencies: 2336 - encoding 2337 2338 - '@changesets/get-release-plan@4.0.6': 2339 dependencies: 2340 - '@changesets/assemble-release-plan': 6.0.5 2341 - '@changesets/config': 3.0.5 2342 - '@changesets/pre': 2.0.1 2343 - '@changesets/read': 0.6.2 2344 - '@changesets/types': 6.0.0 2345 '@manypkg/get-packages': 1.1.3 2346 2347 '@changesets/get-version-range-type@0.4.0': {} 2348 2349 - '@changesets/git@3.0.2': 2350 dependencies: 2351 '@changesets/errors': 0.2.0 2352 '@manypkg/get-packages': 1.1.3 ··· 2358 dependencies: 2359 picocolors: 1.1.1 2360 2361 - '@changesets/parse@0.4.0': 2362 dependencies: 2363 - '@changesets/types': 6.0.0 2364 js-yaml: 3.14.1 2365 2366 - '@changesets/pre@2.0.1': 2367 dependencies: 2368 '@changesets/errors': 0.2.0 2369 - '@changesets/types': 6.0.0 2370 '@manypkg/get-packages': 1.1.3 2371 fs-extra: 7.0.1 2372 2373 - '@changesets/read@0.6.2': 2374 dependencies: 2375 - '@changesets/git': 3.0.2 2376 '@changesets/logger': 0.1.1 2377 - '@changesets/parse': 0.4.0 2378 - '@changesets/types': 6.0.0 2379 fs-extra: 7.0.1 2380 p-filter: 2.1.0 2381 picocolors: 1.1.1 2382 2383 - '@changesets/should-skip-package@0.1.1': 2384 dependencies: 2385 - '@changesets/types': 6.0.0 2386 '@manypkg/get-packages': 1.1.3 2387 2388 '@changesets/types@4.1.0': {} 2389 2390 - '@changesets/types@6.0.0': {} 2391 2392 - '@changesets/write@0.3.2': 2393 dependencies: 2394 - '@changesets/types': 6.0.0 2395 fs-extra: 7.0.1 2396 - human-id: 1.0.2 2397 prettier: 2.8.8 2398 2399 '@esbuild/aix-ppc64@0.24.2': ··· 2471 '@esbuild/win32-x64@0.24.2': 2472 optional: true 2473 2474 '@isaacs/cliui@8.0.2': 2475 dependencies: 2476 string-width: 5.1.2 ··· 2479 strip-ansi-cjs: strip-ansi@6.0.1 2480 wrap-ansi: 8.1.0 2481 wrap-ansi-cjs: wrap-ansi@7.0.0 2482 2483 '@jridgewell/gen-mapping@0.3.8': 2484 dependencies: ··· 2497 2498 '@jridgewell/sourcemap-codec@1.5.0': {} 2499 2500 '@jridgewell/trace-mapping@0.3.25': 2501 dependencies: 2502 '@jridgewell/resolve-uri': 3.1.2 2503 '@jridgewell/sourcemap-codec': 1.5.0 2504 2505 '@manypkg/find-root@1.1.0': 2506 dependencies: ··· 2695 2696 acorn@8.14.0: {} 2697 2698 ansi-colors@4.1.3: {} 2699 2700 ansi-escapes@7.0.0: ··· 2765 dependencies: 2766 fill-range: 7.1.1 2767 2768 - browserslist@4.24.4: 2769 dependencies: 2770 - caniuse-lite: 1.0.30001696 2771 - electron-to-chromium: 1.5.90 2772 node-releases: 2.0.19 2773 - update-browserslist-db: 1.1.2(browserslist@4.24.4) 2774 2775 buffer-from@1.1.2: {} 2776 ··· 2797 call-bind-apply-helpers: 1.0.1 2798 get-intrinsic: 1.2.7 2799 2800 - caniuse-lite@1.0.30001696: {} 2801 2802 chai@5.1.2: 2803 dependencies: ··· 2815 2816 chalk@5.4.1: {} 2817 2818 - chardet@0.7.0: {} 2819 2820 check-error@2.1.1: {} 2821 ··· 2898 dependencies: 2899 ms: 2.1.3 2900 2901 deep-eql@5.0.2: {} 2902 2903 deepmerge@4.3.1: {} ··· 2936 2937 eastasianwidth@0.2.0: {} 2938 2939 - electron-to-chromium@1.5.90: {} 2940 2941 emoji-regex@10.4.0: {} 2942 ··· 3090 3091 extendable-error@0.1.7: {} 3092 3093 - external-editor@3.1.0: 3094 - dependencies: 3095 - chardet: 0.7.0 3096 - iconv-lite: 0.4.24 3097 - tmp: 0.0.33 3098 - 3099 fast-glob@3.3.3: 3100 dependencies: 3101 '@nodelib/fs.stat': 2.0.5 ··· 3251 3252 hosted-git-info@2.8.9: {} 3253 3254 - human-id@1.0.2: {} 3255 3256 human-signals@5.0.0: {} 3257 3258 - iconv-lite@0.4.24: 3259 dependencies: 3260 safer-buffer: 2.1.2 3261 ··· 3266 es-errors: 1.3.0 3267 hasown: 2.0.2 3268 side-channel: 1.1.0 3269 3270 is-array-buffer@3.0.5: 3271 dependencies: ··· 3571 dependencies: 3572 mimic-function: 5.0.1 3573 3574 - os-tmpdir@1.0.2: {} 3575 - 3576 outdent@0.5.0: {} 3577 3578 own-keys@1.0.1: ··· 3657 3658 prettier@3.4.2: {} 3659 3660 queue-microtask@1.2.3: {} 3661 3662 randombytes@2.1.0: ··· 3876 ansi-styles: 6.2.1 3877 is-fullwidth-code-point: 5.0.0 3878 3879 smob@1.5.0: {} 3880 3881 source-map-js@1.2.1: {} 3882 ··· 4001 4002 tinyspy@3.0.2: {} 4003 4004 - tmp@0.0.33: 4005 - dependencies: 4006 - os-tmpdir: 1.0.2 4007 - 4008 to-regex-range@5.0.1: 4009 dependencies: 4010 is-number: 7.0.0 4011 4012 tr46@0.0.3: {} 4013 4014 typed-array-buffer@1.0.3: 4015 dependencies: ··· 4061 4062 universalify@0.1.2: {} 4063 4064 - update-browserslist-db@1.1.2(browserslist@4.24.4): 4065 dependencies: 4066 - browserslist: 4.24.4 4067 escalade: 3.2.0 4068 picocolors: 1.1.1 4069
··· 15 specifier: ^7.26.7 16 version: 7.26.7(@babel/core@7.26.7) 17 '@changesets/cli': 18 + specifier: ^2.29.6 19 + version: 2.29.6(@types/node@22.12.0) 20 '@changesets/get-github-info': 21 specifier: ^0.6.0 22 version: 0.6.0 ··· 59 prettier: 60 specifier: ^3.4.2 61 version: 3.4.2 62 + proxy-chain: 63 + specifier: ^2.7.1 64 + version: 2.7.1 65 rimraf: 66 specifier: ^6.0.1 67 version: 6.0.1 ··· 94 resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} 95 engines: {node: '>=6.9.0'} 96 97 + '@babel/code-frame@7.27.1': 98 + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} 99 + engines: {node: '>=6.9.0'} 100 + 101 + '@babel/compat-data@7.28.0': 102 + resolution: {integrity: sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==} 103 engines: {node: '>=6.9.0'} 104 105 '@babel/core@7.26.7': ··· 110 resolution: {integrity: sha512-2caSP6fN9I7HOe6nqhtft7V4g7/V/gfDsC3Ag4W7kEzzvRGKqiv0pu0HogPiZ3KaVSoNDhUws6IJjDjpfmYIXw==} 111 engines: {node: '>=6.9.0'} 112 113 + '@babel/generator@7.28.3': 114 + resolution: {integrity: sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==} 115 + engines: {node: '>=6.9.0'} 116 + 117 '@babel/helper-annotate-as-pure@7.25.9': 118 resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} 119 engines: {node: '>=6.9.0'} 120 121 + '@babel/helper-compilation-targets@7.27.2': 122 + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} 123 engines: {node: '>=6.9.0'} 124 125 '@babel/helper-create-class-features-plugin@7.25.9': ··· 128 peerDependencies: 129 '@babel/core': ^7.0.0 130 131 + '@babel/helper-globals@7.28.0': 132 + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} 133 + engines: {node: '>=6.9.0'} 134 + 135 '@babel/helper-member-expression-to-functions@7.25.9': 136 resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==} 137 engines: {node: '>=6.9.0'} ··· 140 resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} 141 engines: {node: '>=6.9.0'} 142 143 + '@babel/helper-module-imports@7.27.1': 144 + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} 145 + engines: {node: '>=6.9.0'} 146 + 147 + '@babel/helper-module-transforms@7.28.3': 148 + resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} 149 engines: {node: '>=6.9.0'} 150 peerDependencies: 151 '@babel/core': ^7.0.0 ··· 172 resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} 173 engines: {node: '>=6.9.0'} 174 175 + '@babel/helper-string-parser@7.27.1': 176 + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} 177 + engines: {node: '>=6.9.0'} 178 + 179 '@babel/helper-validator-identifier@7.25.9': 180 resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} 181 engines: {node: '>=6.9.0'} 182 183 + '@babel/helper-validator-identifier@7.27.1': 184 + resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} 185 engines: {node: '>=6.9.0'} 186 187 + '@babel/helper-validator-option@7.27.1': 188 + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} 189 + engines: {node: '>=6.9.0'} 190 + 191 + '@babel/helpers@7.28.3': 192 + resolution: {integrity: sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==} 193 engines: {node: '>=6.9.0'} 194 195 '@babel/parser@7.26.7': 196 resolution: {integrity: sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==} 197 + engines: {node: '>=6.0.0'} 198 + hasBin: true 199 + 200 + '@babel/parser@7.28.3': 201 + resolution: {integrity: sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==} 202 engines: {node: '>=6.0.0'} 203 hasBin: true 204 ··· 228 resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} 229 engines: {node: '>=6.9.0'} 230 231 + '@babel/template@7.27.2': 232 + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} 233 + engines: {node: '>=6.9.0'} 234 + 235 '@babel/traverse@7.26.7': 236 resolution: {integrity: sha512-1x1sgeyRLC3r5fQOM0/xtQKsYjyxmFjaOrLJNtZ81inNjyJHGIolTULPiSc/2qe1/qfpFLisLQYFnnZl7QoedA==} 237 engines: {node: '>=6.9.0'} 238 239 + '@babel/traverse@7.28.3': 240 + resolution: {integrity: sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==} 241 + engines: {node: '>=6.9.0'} 242 + 243 '@babel/types@7.26.7': 244 resolution: {integrity: sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==} 245 engines: {node: '>=6.9.0'} 246 247 + '@babel/types@7.28.2': 248 + resolution: {integrity: sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==} 249 + engines: {node: '>=6.9.0'} 250 251 + '@changesets/apply-release-plan@7.0.12': 252 + resolution: {integrity: sha512-EaET7As5CeuhTzvXTQCRZeBUcisoYPDDcXvgTE/2jmmypKp0RC7LxKj/yzqeh/1qFTZI7oDGFcL1PHRuQuketQ==} 253 254 + '@changesets/assemble-release-plan@6.0.9': 255 + resolution: {integrity: sha512-tPgeeqCHIwNo8sypKlS3gOPmsS3wP0zHt67JDuL20P4QcXiw/O4Hl7oXiuLnP9yg+rXLQ2sScdV1Kkzde61iSQ==} 256 257 + '@changesets/changelog-git@0.2.1': 258 + resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==} 259 + 260 + '@changesets/cli@2.29.6': 261 + resolution: {integrity: sha512-6qCcVsIG1KQLhpQ5zE8N0PckIx4+9QlHK3z6/lwKnw7Tir71Bjw8BeOZaxA/4Jt00pcgCnCSWZnyuZf5Il05QQ==} 262 hasBin: true 263 264 + '@changesets/config@3.1.1': 265 + resolution: {integrity: sha512-bd+3Ap2TKXxljCggI0mKPfzCQKeV/TU4yO2h2C6vAihIo8tzseAn2e7klSuiyYYXvgu53zMN1OeYMIQkaQoWnA==} 266 267 '@changesets/errors@0.2.0': 268 resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} 269 270 + '@changesets/get-dependents-graph@2.1.3': 271 + resolution: {integrity: sha512-gphr+v0mv2I3Oxt19VdWRRUxq3sseyUpX9DaHpTUmLj92Y10AGy+XOtV+kbM6L/fDcpx7/ISDFK6T8A/P3lOdQ==} 272 273 '@changesets/get-github-info@0.6.0': 274 resolution: {integrity: sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA==} 275 276 + '@changesets/get-release-plan@4.0.13': 277 + resolution: {integrity: sha512-DWG1pus72FcNeXkM12tx+xtExyH/c9I1z+2aXlObH3i9YA7+WZEVaiHzHl03thpvAgWTRaH64MpfHxozfF7Dvg==} 278 279 '@changesets/get-version-range-type@0.4.0': 280 resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} 281 282 + '@changesets/git@3.0.4': 283 + resolution: {integrity: sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==} 284 285 '@changesets/logger@0.1.1': 286 resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==} 287 288 + '@changesets/parse@0.4.1': 289 + resolution: {integrity: sha512-iwksMs5Bf/wUItfcg+OXrEpravm5rEd9Bf4oyIPL4kVTmJQ7PNDSd6MDYkpSJR1pn7tz/k8Zf2DhTCqX08Ou+Q==} 290 291 + '@changesets/pre@2.0.2': 292 + resolution: {integrity: sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==} 293 294 + '@changesets/read@0.6.5': 295 + resolution: {integrity: sha512-UPzNGhsSjHD3Veb0xO/MwvasGe8eMyNrR/sT9gR8Q3DhOQZirgKhhXv/8hVsI0QpPjR004Z9iFxoJU6in3uGMg==} 296 297 + '@changesets/should-skip-package@0.1.2': 298 + resolution: {integrity: sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==} 299 300 '@changesets/types@4.1.0': 301 resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} 302 303 + '@changesets/types@6.1.0': 304 + resolution: {integrity: sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==} 305 306 + '@changesets/write@0.4.0': 307 + resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} 308 309 '@esbuild/aix-ppc64@0.24.2': 310 resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} ··· 456 cpu: [x64] 457 os: [win32] 458 459 + '@inquirer/external-editor@1.0.1': 460 + resolution: {integrity: sha512-Oau4yL24d2B5IL4ma4UpbQigkVhzPDXLoqy1ggK4gnHg/stmkffJE4oOXHXF3uz0UEpywG68KcyXsyYpA1Re/Q==} 461 + engines: {node: '>=18'} 462 + peerDependencies: 463 + '@types/node': '>=18' 464 + peerDependenciesMeta: 465 + '@types/node': 466 + optional: true 467 + 468 '@isaacs/cliui@8.0.2': 469 resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} 470 engines: {node: '>=12'} 471 + 472 + '@jridgewell/gen-mapping@0.3.13': 473 + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} 474 475 '@jridgewell/gen-mapping@0.3.8': 476 resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} ··· 490 '@jridgewell/sourcemap-codec@1.5.0': 491 resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} 492 493 + '@jridgewell/sourcemap-codec@1.5.5': 494 + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} 495 + 496 '@jridgewell/trace-mapping@0.3.25': 497 resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} 498 + 499 + '@jridgewell/trace-mapping@0.3.30': 500 + resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==} 501 502 '@manypkg/find-root@1.1.0': 503 resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} ··· 713 engines: {node: '>=0.4.0'} 714 hasBin: true 715 716 + agent-base@7.1.4: 717 + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} 718 + engines: {node: '>= 14'} 719 + 720 ansi-colors@4.1.3: 721 resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} 722 engines: {node: '>=6'} ··· 792 resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 793 engines: {node: '>=8'} 794 795 + browserslist@4.25.4: 796 + resolution: {integrity: sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg==} 797 engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 798 hasBin: true 799 ··· 820 resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==} 821 engines: {node: '>= 0.4'} 822 823 + caniuse-lite@1.0.30001737: 824 + resolution: {integrity: sha512-BiloLiXtQNrY5UyF0+1nSJLXUENuhka2pzy2Fx5pGxqavdrxSCW4U6Pn/PoG3Efspi2frRbHpBV2XsrPE6EDlw==} 825 826 chai@5.1.2: 827 resolution: {integrity: sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==} ··· 835 resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} 836 engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} 837 838 + chardet@2.1.0: 839 + resolution: {integrity: sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==} 840 841 check-error@2.1.1: 842 resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} ··· 925 supports-color: 926 optional: true 927 928 + debug@4.4.1: 929 + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} 930 + engines: {node: '>=6.0'} 931 + peerDependencies: 932 + supports-color: '*' 933 + peerDependenciesMeta: 934 + supports-color: 935 + optional: true 936 + 937 deep-eql@5.0.2: 938 resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} 939 engines: {node: '>=6'} ··· 977 eastasianwidth@0.2.0: 978 resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} 979 980 + electron-to-chromium@1.5.211: 981 + resolution: {integrity: sha512-IGBvimJkotaLzFnwIVgW9/UD/AOJ2tByUmeOrtqBfACSbAw5b1G0XpvdaieKyc7ULmbwXVx+4e4Be8pOPBrYkw==} 982 983 emoji-regex@10.4.0: 984 resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} ··· 1064 1065 extendable-error@0.1.7: 1066 resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} 1067 1068 fast-glob@3.3.3: 1069 resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} ··· 1205 hosted-git-info@2.8.9: 1206 resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} 1207 1208 + human-id@4.1.1: 1209 + resolution: {integrity: sha512-3gKm/gCSUipeLsRYZbbdA1BD83lBoWUkZ7G9VFrhWPAU76KwYo5KR8V28bpoPm/ygy0x5/GCbpRQdY7VLYCoIg==} 1210 + hasBin: true 1211 1212 human-signals@5.0.0: 1213 resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} 1214 engines: {node: '>=16.17.0'} 1215 1216 + iconv-lite@0.6.3: 1217 + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} 1218 engines: {node: '>=0.10.0'} 1219 1220 ignore@5.3.2: ··· 1224 internal-slot@1.1.0: 1225 resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} 1226 engines: {node: '>= 0.4'} 1227 + 1228 + ip-address@10.1.0: 1229 + resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} 1230 + engines: {node: '>= 12'} 1231 1232 is-array-buffer@3.0.5: 1233 resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} ··· 1537 resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} 1538 engines: {node: '>=18'} 1539 1540 outdent@0.5.0: 1541 resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} 1542 ··· 1659 engines: {node: '>=14'} 1660 hasBin: true 1661 1662 + proxy-chain@2.7.1: 1663 + resolution: {integrity: sha512-LtXu0miohJYrHWJxv8wA6EoGreRcX1hxKb7qlE1pMFH+BXE7bqMvpyhzR/JvR6M5SzYKzyHFpvfmYJrZeMtwAg==} 1664 + engines: {node: '>=14'} 1665 + 1666 queue-microtask@1.2.3: 1667 resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1668 ··· 1835 resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} 1836 engines: {node: '>=18'} 1837 1838 + smart-buffer@4.2.0: 1839 + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} 1840 + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} 1841 + 1842 smob@1.5.0: 1843 resolution: {integrity: sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==} 1844 + 1845 + socks-proxy-agent@8.0.5: 1846 + resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} 1847 + engines: {node: '>= 14'} 1848 + 1849 + socks@2.8.7: 1850 + resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==} 1851 + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} 1852 1853 source-map-js@1.2.1: 1854 resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} ··· 1972 resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} 1973 engines: {node: '>=14.0.0'} 1974 1975 to-regex-range@5.0.1: 1976 resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1977 engines: {node: '>=8.0'} 1978 1979 tr46@0.0.3: 1980 resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} 1981 + 1982 + tslib@2.8.1: 1983 + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} 1984 1985 typed-array-buffer@1.0.3: 1986 resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} ··· 2020 resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} 2021 engines: {node: '>= 4.0.0'} 2022 2023 + update-browserslist-db@1.1.3: 2024 + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} 2025 hasBin: true 2026 peerDependencies: 2027 browserslist: '>= 4.21.0' ··· 2162 2163 '@ampproject/remapping@2.3.0': 2164 dependencies: 2165 + '@jridgewell/gen-mapping': 0.3.13 2166 + '@jridgewell/trace-mapping': 0.3.30 2167 2168 '@babel/code-frame@7.26.2': 2169 dependencies: ··· 2171 js-tokens: 4.0.0 2172 picocolors: 1.1.1 2173 2174 + '@babel/code-frame@7.27.1': 2175 + dependencies: 2176 + '@babel/helper-validator-identifier': 7.27.1 2177 + js-tokens: 4.0.0 2178 + picocolors: 1.1.1 2179 + 2180 + '@babel/compat-data@7.28.0': {} 2181 2182 '@babel/core@7.26.7': 2183 dependencies: 2184 '@ampproject/remapping': 2.3.0 2185 + '@babel/code-frame': 7.27.1 2186 + '@babel/generator': 7.28.3 2187 + '@babel/helper-compilation-targets': 7.27.2 2188 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.26.7) 2189 + '@babel/helpers': 7.28.3 2190 + '@babel/parser': 7.28.3 2191 + '@babel/template': 7.27.2 2192 + '@babel/traverse': 7.28.3 2193 + '@babel/types': 7.28.2 2194 convert-source-map: 2.0.0 2195 + debug: 4.4.1 2196 gensync: 1.0.0-beta.2 2197 json5: 2.2.3 2198 semver: 6.3.1 ··· 2207 '@jridgewell/trace-mapping': 0.3.25 2208 jsesc: 3.1.0 2209 2210 + '@babel/generator@7.28.3': 2211 + dependencies: 2212 + '@babel/parser': 7.28.3 2213 + '@babel/types': 7.28.2 2214 + '@jridgewell/gen-mapping': 0.3.13 2215 + '@jridgewell/trace-mapping': 0.3.30 2216 + jsesc: 3.1.0 2217 + 2218 '@babel/helper-annotate-as-pure@7.25.9': 2219 dependencies: 2220 '@babel/types': 7.26.7 2221 2222 + '@babel/helper-compilation-targets@7.27.2': 2223 dependencies: 2224 + '@babel/compat-data': 7.28.0 2225 + '@babel/helper-validator-option': 7.27.1 2226 + browserslist: 4.25.4 2227 lru-cache: 5.1.1 2228 semver: 6.3.1 2229 ··· 2239 semver: 6.3.1 2240 transitivePeerDependencies: 2241 - supports-color 2242 + 2243 + '@babel/helper-globals@7.28.0': {} 2244 2245 '@babel/helper-member-expression-to-functions@7.25.9': 2246 dependencies: ··· 2256 transitivePeerDependencies: 2257 - supports-color 2258 2259 + '@babel/helper-module-imports@7.27.1': 2260 + dependencies: 2261 + '@babel/traverse': 7.28.3 2262 + '@babel/types': 7.28.2 2263 + transitivePeerDependencies: 2264 + - supports-color 2265 + 2266 + '@babel/helper-module-transforms@7.28.3(@babel/core@7.26.7)': 2267 dependencies: 2268 '@babel/core': 7.26.7 2269 + '@babel/helper-module-imports': 7.27.1 2270 + '@babel/helper-validator-identifier': 7.27.1 2271 + '@babel/traverse': 7.28.3 2272 transitivePeerDependencies: 2273 - supports-color 2274 ··· 2296 2297 '@babel/helper-string-parser@7.25.9': {} 2298 2299 + '@babel/helper-string-parser@7.27.1': {} 2300 + 2301 '@babel/helper-validator-identifier@7.25.9': {} 2302 2303 + '@babel/helper-validator-identifier@7.27.1': {} 2304 2305 + '@babel/helper-validator-option@7.27.1': {} 2306 + 2307 + '@babel/helpers@7.28.3': 2308 dependencies: 2309 + '@babel/template': 7.27.2 2310 + '@babel/types': 7.28.2 2311 2312 '@babel/parser@7.26.7': 2313 dependencies: 2314 '@babel/types': 7.26.7 2315 + 2316 + '@babel/parser@7.28.3': 2317 + dependencies: 2318 + '@babel/types': 7.28.2 2319 2320 '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.7)': 2321 dependencies: ··· 2348 '@babel/parser': 7.26.7 2349 '@babel/types': 7.26.7 2350 2351 + '@babel/template@7.27.2': 2352 + dependencies: 2353 + '@babel/code-frame': 7.27.1 2354 + '@babel/parser': 7.28.3 2355 + '@babel/types': 7.28.2 2356 + 2357 '@babel/traverse@7.26.7': 2358 dependencies: 2359 '@babel/code-frame': 7.26.2 ··· 2366 transitivePeerDependencies: 2367 - supports-color 2368 2369 + '@babel/traverse@7.28.3': 2370 + dependencies: 2371 + '@babel/code-frame': 7.27.1 2372 + '@babel/generator': 7.28.3 2373 + '@babel/helper-globals': 7.28.0 2374 + '@babel/parser': 7.28.3 2375 + '@babel/template': 7.27.2 2376 + '@babel/types': 7.28.2 2377 + debug: 4.4.1 2378 + transitivePeerDependencies: 2379 + - supports-color 2380 + 2381 '@babel/types@7.26.7': 2382 dependencies: 2383 '@babel/helper-string-parser': 7.25.9 2384 '@babel/helper-validator-identifier': 7.25.9 2385 2386 + '@babel/types@7.28.2': 2387 dependencies: 2388 + '@babel/helper-string-parser': 7.27.1 2389 + '@babel/helper-validator-identifier': 7.27.1 2390 + 2391 + '@changesets/apply-release-plan@7.0.12': 2392 + dependencies: 2393 + '@changesets/config': 3.1.1 2394 '@changesets/get-version-range-type': 0.4.0 2395 + '@changesets/git': 3.0.4 2396 + '@changesets/should-skip-package': 0.1.2 2397 + '@changesets/types': 6.1.0 2398 '@manypkg/get-packages': 1.1.3 2399 detect-indent: 6.1.0 2400 fs-extra: 7.0.1 ··· 2404 resolve-from: 5.0.0 2405 semver: 7.7.0 2406 2407 + '@changesets/assemble-release-plan@6.0.9': 2408 dependencies: 2409 '@changesets/errors': 0.2.0 2410 + '@changesets/get-dependents-graph': 2.1.3 2411 + '@changesets/should-skip-package': 0.1.2 2412 + '@changesets/types': 6.1.0 2413 '@manypkg/get-packages': 1.1.3 2414 semver: 7.7.0 2415 2416 + '@changesets/changelog-git@0.2.1': 2417 dependencies: 2418 + '@changesets/types': 6.1.0 2419 2420 + '@changesets/cli@2.29.6(@types/node@22.12.0)': 2421 dependencies: 2422 + '@changesets/apply-release-plan': 7.0.12 2423 + '@changesets/assemble-release-plan': 6.0.9 2424 + '@changesets/changelog-git': 0.2.1 2425 + '@changesets/config': 3.1.1 2426 '@changesets/errors': 0.2.0 2427 + '@changesets/get-dependents-graph': 2.1.3 2428 + '@changesets/get-release-plan': 4.0.13 2429 + '@changesets/git': 3.0.4 2430 '@changesets/logger': 0.1.1 2431 + '@changesets/pre': 2.0.2 2432 + '@changesets/read': 0.6.5 2433 + '@changesets/should-skip-package': 0.1.2 2434 + '@changesets/types': 6.1.0 2435 + '@changesets/write': 0.4.0 2436 + '@inquirer/external-editor': 1.0.1(@types/node@22.12.0) 2437 '@manypkg/get-packages': 1.1.3 2438 ansi-colors: 4.1.3 2439 ci-info: 3.9.0 2440 enquirer: 2.4.1 2441 fs-extra: 7.0.1 2442 mri: 1.2.0 2443 p-limit: 2.3.0 ··· 2447 semver: 7.7.0 2448 spawndamnit: 3.0.1 2449 term-size: 2.2.1 2450 + transitivePeerDependencies: 2451 + - '@types/node' 2452 2453 + '@changesets/config@3.1.1': 2454 dependencies: 2455 '@changesets/errors': 0.2.0 2456 + '@changesets/get-dependents-graph': 2.1.3 2457 '@changesets/logger': 0.1.1 2458 + '@changesets/types': 6.1.0 2459 '@manypkg/get-packages': 1.1.3 2460 fs-extra: 7.0.1 2461 micromatch: 4.0.8 ··· 2464 dependencies: 2465 extendable-error: 0.1.7 2466 2467 + '@changesets/get-dependents-graph@2.1.3': 2468 dependencies: 2469 + '@changesets/types': 6.1.0 2470 '@manypkg/get-packages': 1.1.3 2471 picocolors: 1.1.1 2472 semver: 7.7.0 ··· 2478 transitivePeerDependencies: 2479 - encoding 2480 2481 + '@changesets/get-release-plan@4.0.13': 2482 dependencies: 2483 + '@changesets/assemble-release-plan': 6.0.9 2484 + '@changesets/config': 3.1.1 2485 + '@changesets/pre': 2.0.2 2486 + '@changesets/read': 0.6.5 2487 + '@changesets/types': 6.1.0 2488 '@manypkg/get-packages': 1.1.3 2489 2490 '@changesets/get-version-range-type@0.4.0': {} 2491 2492 + '@changesets/git@3.0.4': 2493 dependencies: 2494 '@changesets/errors': 0.2.0 2495 '@manypkg/get-packages': 1.1.3 ··· 2501 dependencies: 2502 picocolors: 1.1.1 2503 2504 + '@changesets/parse@0.4.1': 2505 dependencies: 2506 + '@changesets/types': 6.1.0 2507 js-yaml: 3.14.1 2508 2509 + '@changesets/pre@2.0.2': 2510 dependencies: 2511 '@changesets/errors': 0.2.0 2512 + '@changesets/types': 6.1.0 2513 '@manypkg/get-packages': 1.1.3 2514 fs-extra: 7.0.1 2515 2516 + '@changesets/read@0.6.5': 2517 dependencies: 2518 + '@changesets/git': 3.0.4 2519 '@changesets/logger': 0.1.1 2520 + '@changesets/parse': 0.4.1 2521 + '@changesets/types': 6.1.0 2522 fs-extra: 7.0.1 2523 p-filter: 2.1.0 2524 picocolors: 1.1.1 2525 2526 + '@changesets/should-skip-package@0.1.2': 2527 dependencies: 2528 + '@changesets/types': 6.1.0 2529 '@manypkg/get-packages': 1.1.3 2530 2531 '@changesets/types@4.1.0': {} 2532 2533 + '@changesets/types@6.1.0': {} 2534 2535 + '@changesets/write@0.4.0': 2536 dependencies: 2537 + '@changesets/types': 6.1.0 2538 fs-extra: 7.0.1 2539 + human-id: 4.1.1 2540 prettier: 2.8.8 2541 2542 '@esbuild/aix-ppc64@0.24.2': ··· 2614 '@esbuild/win32-x64@0.24.2': 2615 optional: true 2616 2617 + '@inquirer/external-editor@1.0.1(@types/node@22.12.0)': 2618 + dependencies: 2619 + chardet: 2.1.0 2620 + iconv-lite: 0.6.3 2621 + optionalDependencies: 2622 + '@types/node': 22.12.0 2623 + 2624 '@isaacs/cliui@8.0.2': 2625 dependencies: 2626 string-width: 5.1.2 ··· 2629 strip-ansi-cjs: strip-ansi@6.0.1 2630 wrap-ansi: 8.1.0 2631 wrap-ansi-cjs: wrap-ansi@7.0.0 2632 + 2633 + '@jridgewell/gen-mapping@0.3.13': 2634 + dependencies: 2635 + '@jridgewell/sourcemap-codec': 1.5.5 2636 + '@jridgewell/trace-mapping': 0.3.30 2637 2638 '@jridgewell/gen-mapping@0.3.8': 2639 dependencies: ··· 2652 2653 '@jridgewell/sourcemap-codec@1.5.0': {} 2654 2655 + '@jridgewell/sourcemap-codec@1.5.5': {} 2656 + 2657 '@jridgewell/trace-mapping@0.3.25': 2658 dependencies: 2659 '@jridgewell/resolve-uri': 3.1.2 2660 '@jridgewell/sourcemap-codec': 1.5.0 2661 + 2662 + '@jridgewell/trace-mapping@0.3.30': 2663 + dependencies: 2664 + '@jridgewell/resolve-uri': 3.1.2 2665 + '@jridgewell/sourcemap-codec': 1.5.5 2666 2667 '@manypkg/find-root@1.1.0': 2668 dependencies: ··· 2857 2858 acorn@8.14.0: {} 2859 2860 + agent-base@7.1.4: {} 2861 + 2862 ansi-colors@4.1.3: {} 2863 2864 ansi-escapes@7.0.0: ··· 2929 dependencies: 2930 fill-range: 7.1.1 2931 2932 + browserslist@4.25.4: 2933 dependencies: 2934 + caniuse-lite: 1.0.30001737 2935 + electron-to-chromium: 1.5.211 2936 node-releases: 2.0.19 2937 + update-browserslist-db: 1.1.3(browserslist@4.25.4) 2938 2939 buffer-from@1.1.2: {} 2940 ··· 2961 call-bind-apply-helpers: 1.0.1 2962 get-intrinsic: 1.2.7 2963 2964 + caniuse-lite@1.0.30001737: {} 2965 2966 chai@5.1.2: 2967 dependencies: ··· 2979 2980 chalk@5.4.1: {} 2981 2982 + chardet@2.1.0: {} 2983 2984 check-error@2.1.1: {} 2985 ··· 3062 dependencies: 3063 ms: 2.1.3 3064 3065 + debug@4.4.1: 3066 + dependencies: 3067 + ms: 2.1.3 3068 + 3069 deep-eql@5.0.2: {} 3070 3071 deepmerge@4.3.1: {} ··· 3104 3105 eastasianwidth@0.2.0: {} 3106 3107 + electron-to-chromium@1.5.211: {} 3108 3109 emoji-regex@10.4.0: {} 3110 ··· 3258 3259 extendable-error@0.1.7: {} 3260 3261 fast-glob@3.3.3: 3262 dependencies: 3263 '@nodelib/fs.stat': 2.0.5 ··· 3413 3414 hosted-git-info@2.8.9: {} 3415 3416 + human-id@4.1.1: {} 3417 3418 human-signals@5.0.0: {} 3419 3420 + iconv-lite@0.6.3: 3421 dependencies: 3422 safer-buffer: 2.1.2 3423 ··· 3428 es-errors: 1.3.0 3429 hasown: 2.0.2 3430 side-channel: 1.1.0 3431 + 3432 + ip-address@10.1.0: {} 3433 3434 is-array-buffer@3.0.5: 3435 dependencies: ··· 3735 dependencies: 3736 mimic-function: 5.0.1 3737 3738 outdent@0.5.0: {} 3739 3740 own-keys@1.0.1: ··· 3819 3820 prettier@3.4.2: {} 3821 3822 + proxy-chain@2.7.1: 3823 + dependencies: 3824 + socks: 2.8.7 3825 + socks-proxy-agent: 8.0.5 3826 + tslib: 2.8.1 3827 + transitivePeerDependencies: 3828 + - supports-color 3829 + 3830 queue-microtask@1.2.3: {} 3831 3832 randombytes@2.1.0: ··· 4046 ansi-styles: 6.2.1 4047 is-fullwidth-code-point: 5.0.0 4048 4049 + smart-buffer@4.2.0: {} 4050 + 4051 smob@1.5.0: {} 4052 + 4053 + socks-proxy-agent@8.0.5: 4054 + dependencies: 4055 + agent-base: 7.1.4 4056 + debug: 4.4.1 4057 + socks: 2.8.7 4058 + transitivePeerDependencies: 4059 + - supports-color 4060 + 4061 + socks@2.8.7: 4062 + dependencies: 4063 + ip-address: 10.1.0 4064 + smart-buffer: 4.2.0 4065 4066 source-map-js@1.2.1: {} 4067 ··· 4186 4187 tinyspy@3.0.2: {} 4188 4189 to-regex-range@5.0.1: 4190 dependencies: 4191 is-number: 7.0.0 4192 4193 tr46@0.0.3: {} 4194 + 4195 + tslib@2.8.1: {} 4196 4197 typed-array-buffer@1.0.3: 4198 dependencies: ··· 4244 4245 universalify@0.1.2: {} 4246 4247 + update-browserslist-db@1.1.3(browserslist@4.25.4): 4248 dependencies: 4249 + browserslist: 4.25.4 4250 escalade: 3.2.0 4251 picocolors: 1.1.1 4252
+6 -3
scripts/rollup.config.mjs
··· 93 dir: './', 94 exports: 'auto', 95 sourcemap: true, 96 - sourcemapExcludeSources: false, 97 hoistTransitiveImports: false, 98 indent: false, 99 freeze: false, ··· 188 keep_fnames: true, 189 ie8: false, 190 compress: { 191 pure_getters: true, 192 toplevel: true, 193 booleans_as_integers: false, ··· 199 loops: false, 200 conditionals: false, 201 join_vars: false, 202 }, 203 mangle: { 204 module: true, ··· 224 exclude: 'node_modules/**', 225 presets: [], 226 plugins: [ 227 - '@babel/plugin-transform-typescript', 228 - '@babel/plugin-transform-block-scoping', 229 ], 230 }), 231 ],
··· 93 dir: './', 94 exports: 'auto', 95 sourcemap: true, 96 + sourcemapExcludeSources: true, 97 hoistTransitiveImports: false, 98 indent: false, 99 freeze: false, ··· 188 keep_fnames: true, 189 ie8: false, 190 compress: { 191 + passes: 2, 192 pure_getters: true, 193 toplevel: true, 194 booleans_as_integers: false, ··· 200 loops: false, 201 conditionals: false, 202 join_vars: false, 203 + reduce_vars: true, 204 }, 205 mangle: { 206 module: true, ··· 226 exclude: 'node_modules/**', 227 presets: [], 228 plugins: [ 229 + ['@babel/plugin-transform-typescript', { 230 + optimizeConstEnums: true, 231 + }], 232 ], 233 }), 234 ],
+107
src/__tests__/fetch-errors.test.ts
···
··· 1 + import { describe, it, expect, beforeEach, afterEach } from 'vitest'; 2 + import { Readable } from 'node:stream'; 3 + 4 + import TestServer from './utils/server.js'; 5 + import { fetch } from '../fetch'; 6 + 7 + describe('fetch error handling', () => { 8 + const server = new TestServer(); 9 + 10 + beforeEach(() => server.start()); 11 + afterEach(() => server.stop()); 12 + 13 + describe('incoming stream errors', () => { 14 + it('should propagate error when connection resets mid-body', async () => { 15 + const url = server.mock((_req, res) => { 16 + res.writeHead(200, { 'Content-Length': '1000' }); 17 + res.write('partial'); 18 + setTimeout(() => res.destroy(), 10); 19 + }); 20 + 21 + const response = await fetch(url); 22 + expect(response.ok).toBe(true); 23 + await expect(response.text()).rejects.toThrow(); 24 + }); 25 + 26 + it('should not cause unhandled errors on incoming stream', async () => { 27 + const errors: Error[] = []; 28 + const handler = (e: Error) => errors.push(e); 29 + process.on('uncaughtException', handler); 30 + 31 + const url = server.mock((_req, res) => { 32 + res.writeHead(200, { 'Transfer-Encoding': 'chunked' }); 33 + res.write('data'); 34 + setTimeout(() => res.destroy(), 10); 35 + }); 36 + 37 + const response = await fetch(url); 38 + try { 39 + await response.text(); 40 + } catch {} 41 + await new Promise(r => setTimeout(r, 50)); 42 + 43 + process.off('uncaughtException', handler); 44 + expect(errors).toHaveLength(0); 45 + }); 46 + }); 47 + 48 + describe('request body pipeline errors', () => { 49 + it('should reject when request body stream errors', async () => { 50 + const body = new Readable({ 51 + read() { 52 + this.push('data'); 53 + setTimeout(() => this.destroy(new Error('stream error')), 10); 54 + }, 55 + }); 56 + 57 + const url = server.mock((req, res) => { 58 + req.on('data', () => {}); 59 + req.on('end', () => res.end('ok')); 60 + req.on('error', () => {}); 61 + }); 62 + 63 + await expect(fetch(url, { method: 'POST', body })).rejects.toThrow( 64 + 'stream error' 65 + ); 66 + }); 67 + }); 68 + 69 + describe('decompression errors', () => { 70 + it('should propagate gzip decompression errors', async () => { 71 + const url = server.mock((_req, res) => { 72 + res.writeHead(200, { 'Content-Encoding': 'gzip' }); 73 + res.end('not gzip'); 74 + }); 75 + 76 + const response = await fetch(url); 77 + expect(response.ok).toBe(true); 78 + await expect(response.text()).rejects.toThrow(); 79 + }); 80 + 81 + it('should propagate brotli decompression errors', async () => { 82 + const url = server.mock((_req, res) => { 83 + res.writeHead(200, { 'Content-Encoding': 'br' }); 84 + res.end('not brotli'); 85 + }); 86 + 87 + const response = await fetch(url); 88 + await expect(response.text()).rejects.toThrow(); 89 + }); 90 + }); 91 + 92 + describe('abort handling', () => { 93 + it('should abort during response streaming', async () => { 94 + const controller = new AbortController(); 95 + 96 + const url = server.mock((_req, res) => { 97 + res.writeHead(200, { 'Transfer-Encoding': 'chunked' }); 98 + const id = setInterval(() => res.write('x'), 10); 99 + res.on('close', () => clearInterval(id)); 100 + }); 101 + 102 + const response = await fetch(url, { signal: controller.signal }); 103 + setTimeout(() => controller.abort(), 30); 104 + await expect(response.text()).rejects.toThrow(); 105 + }); 106 + }); 107 + });
+77
src/__tests__/fetch-proxied.test.ts
···
··· 1 + import { describe, it, expect, beforeEach, afterEach, afterAll } from 'vitest'; 2 + import { Server as ProxyServer } from 'proxy-chain'; 3 + 4 + import TestServer from './utils/server.js'; 5 + import { fetch } from '../fetch'; 6 + 7 + async function startHttpProxy() { 8 + const server = new ProxyServer(); 9 + const port = await new Promise(resolve => { 10 + server.listen(() => { 11 + resolve(server.port); 12 + }); 13 + }); 14 + 15 + return { 16 + url: `http://localhost:${port}`, 17 + close() { 18 + return new Promise<void>((resolve, reject) => { 19 + server.close(true, err => { 20 + if (err) { 21 + reject(err); 22 + } else { 23 + resolve(); 24 + } 25 + }); 26 + }); 27 + }, 28 + }; 29 + } 30 + 31 + const proxy = await startHttpProxy(); 32 + const local = new TestServer(); 33 + let baseURL: string; 34 + 35 + beforeEach(async () => { 36 + await local.start(); 37 + baseURL = `http://${local.hostname}:${local.port}/`; 38 + }); 39 + 40 + afterEach(async () => { 41 + delete process.env.HTTP_PROXY; 42 + delete process.env.HTTPS_PROXY; 43 + await local.stop(); 44 + }); 45 + 46 + afterAll(async () => { 47 + await proxy.close(); 48 + }); 49 + 50 + const testCI = process.env.CI ? it : it.skip; 51 + 52 + describe('fetch via HTTP proxy', () => { 53 + it('performs an HTTP request when HTTP_PROXY is set (tunnel via CONNECT to HTTP)', async () => { 54 + process.env.HTTP_PROXY = proxy.url; 55 + const response = await fetch(new URL('inspect', baseURL)); 56 + expect(response.status).toBe(200); 57 + expect(await response.json()).toEqual({ 58 + body: '', 59 + headers: expect.objectContaining({ 60 + connection: 'keep-alive', 61 + }), 62 + inspect: true, 63 + method: 'GET', 64 + url: '/inspect', 65 + }); 66 + }); 67 + 68 + testCI( 69 + 'performs an HTTPs request when HTTPS_PROXY is set (tunnel via CONNECT to HTTPs)', 70 + async () => { 71 + process.env.HTTPS_PROXY = proxy.url; 72 + const response = await fetch('https://api.expo.dev'); 73 + expect(response.status).toBe(200); 74 + expect(await response.text()).toBe('OK'); 75 + } 76 + ); 77 + });
+34 -17
src/__tests__/fetch.test.ts
··· 122 }); 123 }); 124 125 it('should prefer init headers when Request is passed', async () => { 126 const request = new Request(new URL('inspect', baseURL), { 127 headers: { 'x-custom-header': 'abc' }, ··· 290 }); 291 }); 292 293 - it.each([['follow'], ['manual']] as const)( 294 - 'should treat broken redirect as ordinary response (%s)', 295 - async redirect => { 296 - const response = await fetch(new URL('redirect/no-location', baseURL), { 297 - redirect, 298 - }); 299 - expect(response.status).toBe(301); 300 - expect(response.headers.has('location')).toBe(false); 301 - } 302 - ); 303 304 it('should throw a TypeError on an invalid redirect option', async () => { 305 await expect(() => ··· 595 }); 596 setTimeout(() => controller.abort(), 100); 597 await expect(response$).rejects.toThrowErrorMatchingInlineSnapshot( 598 - `[AbortError: The operation was aborted]` 599 ); 600 }); 601 ··· 613 ]; 614 setTimeout(() => controller.abort(), 100); 615 await expect(fetches[0]).rejects.toThrowErrorMatchingInlineSnapshot( 616 - `[AbortError: The operation was aborted]` 617 ); 618 await expect(fetches[1]).rejects.toThrowErrorMatchingInlineSnapshot( 619 - `[AbortError: The operation was aborted]` 620 ); 621 }); 622 ··· 627 signal: controller.signal, 628 }); 629 }).rejects.toThrowErrorMatchingInlineSnapshot( 630 - `[AbortError: The operation was aborted]` 631 ); 632 }); 633 ··· 639 await expect(() => 640 fetch(request) 641 ).rejects.toThrowErrorMatchingInlineSnapshot( 642 - `[AbortError: The operation was aborted]` 643 ); 644 }); 645 ··· 672 }); 673 controller.abort(); 674 await expect(response$).rejects.toThrowErrorMatchingInlineSnapshot( 675 - `[AbortError: The operation was aborted]` 676 ); 677 }); 678 ··· 708 controller.abort(); 709 await bodyError$; 710 await expect(response$).rejects.toMatchInlineSnapshot( 711 - `[AbortError: The operation was aborted]` 712 ); 713 }); 714
··· 122 }); 123 }); 124 125 + it('should send custom Content-Type with body', async () => { 126 + const response = await fetch(new URL('inspect', baseURL), { 127 + headers: { 'content-type': 'some/magic' }, 128 + body: 'test', 129 + }); 130 + expect(await response.json()).toMatchObject({ 131 + headers: expect.objectContaining({ 'content-type': 'some/magic' }), 132 + }); 133 + }); 134 + 135 it('should prefer init headers when Request is passed', async () => { 136 const request = new Request(new URL('inspect', baseURL), { 137 headers: { 'x-custom-header': 'abc' }, ··· 300 }); 301 }); 302 303 + it('should treat broken redirect as ordinary response for redirect: "manual"', async () => { 304 + const response = await fetch(new URL('redirect/no-location', baseURL), { 305 + redirect: 'manual', 306 + }); 307 + expect(response.status).toBe(301); 308 + expect(response.headers.has('location')).toBe(false); 309 + }); 310 + 311 + it('should throw on broken redirects for redirect: "follow"', async () => { 312 + await expect(() => 313 + fetch(new URL('redirect/no-location', baseURL), { 314 + redirect: 'follow', 315 + }) 316 + ).rejects.toThrowErrorMatchingInlineSnapshot( 317 + `[Error: URI requested responds with an invalid redirect URL]` 318 + ); 319 + }); 320 321 it('should throw a TypeError on an invalid redirect option', async () => { 322 await expect(() => ··· 612 }); 613 setTimeout(() => controller.abort(), 100); 614 await expect(response$).rejects.toThrowErrorMatchingInlineSnapshot( 615 + `[AbortError: This operation was aborted]` 616 ); 617 }); 618 ··· 630 ]; 631 setTimeout(() => controller.abort(), 100); 632 await expect(fetches[0]).rejects.toThrowErrorMatchingInlineSnapshot( 633 + `[AbortError: This operation was aborted]` 634 ); 635 await expect(fetches[1]).rejects.toThrowErrorMatchingInlineSnapshot( 636 + `[AbortError: This operation was aborted]` 637 ); 638 }); 639 ··· 644 signal: controller.signal, 645 }); 646 }).rejects.toThrowErrorMatchingInlineSnapshot( 647 + `[AbortError: This operation was aborted]` 648 ); 649 }); 650 ··· 656 await expect(() => 657 fetch(request) 658 ).rejects.toThrowErrorMatchingInlineSnapshot( 659 + `[AbortError: This operation was aborted]` 660 ); 661 }); 662 ··· 689 }); 690 controller.abort(); 691 await expect(response$).rejects.toThrowErrorMatchingInlineSnapshot( 692 + `[AbortError: This operation was aborted]` 693 ); 694 }); 695 ··· 725 controller.abort(); 726 await bodyError$; 727 await expect(response$).rejects.toMatchInlineSnapshot( 728 + `[AbortError: This operation was aborted]` 729 ); 730 }); 731
+40 -28
src/__tests__/utils/server.js
··· 3 import http from 'http'; 4 import zlib from 'zlib'; 5 import Busboy from 'busboy'; 6 - import {once} from 'events'; 7 8 export default class TestServer { 9 constructor() { ··· 42 return `http://${this.hostname}:${this.port}/mocked`; 43 } 44 45 router(request, res) { 46 const p = request.url; 47 48 if (p === '/mocked') { 49 if (this.nextResponseHandler) { 50 - this.nextResponseHandler(res); 51 this.nextResponseHandler = undefined; 52 } else { 53 - throw new Error('No mocked response. Use โ€™TestServer.mockResponse()โ€™.'); 54 } 55 } 56 ··· 91 if (p === '/json') { 92 res.statusCode = 200; 93 res.setHeader('Content-Type', 'application/json'); 94 - res.end(JSON.stringify({ 95 - name: 'value' 96 - })); 97 } 98 99 if (p === '/gzip') { ··· 244 } 245 246 if (p === '/redirect/301/rn') { 247 - res.statusCode = 301 248 - res.setHeader('Location', '/403') 249 res.write('301 Permanently moved.\r\n'); 250 res.end(); 251 } ··· 321 if (p === '/redirect/chunked') { 322 res.writeHead(301, { 323 Location: '/inspect', 324 - 'Transfer-Encoding': 'chunked' 325 }); 326 setTimeout(() => res.end(), 10); 327 } ··· 349 } 350 351 if (p === '/error/premature') { 352 - res.writeHead(200, {'content-length': 50}); 353 res.write('foo'); 354 setTimeout(() => { 355 res.destroy(); ··· 359 if (p === '/error/premature/chunked') { 360 res.writeHead(200, { 361 'Content-Type': 'application/json', 362 - 'Transfer-Encoding': 'chunked' 363 }); 364 365 - res.write(`${JSON.stringify({data: 'hi'})}\n`); 366 367 setTimeout(() => { 368 - res.write(`${JSON.stringify({data: 'bye'})}\n`); 369 }, 50); 370 371 setTimeout(() => { ··· 435 body += c; 436 }); 437 request.on('end', () => { 438 - res.end(JSON.stringify({ 439 - inspect: true, 440 - method: request.method, 441 - url: request.url, 442 - headers: request.headers, 443 - body 444 - })); 445 }); 446 } 447 448 if (p === '/multipart') { 449 res.statusCode = 200; 450 res.setHeader('Content-Type', 'application/json'); 451 - const busboy = new Busboy({headers: request.headers}); 452 let body = ''; 453 busboy.on('file', async (fieldName, file, fileName) => { 454 body += `${fieldName}=${fileName}`; 455 // consume file data 456 // eslint-disable-next-line no-empty, no-unused-vars 457 - for await (const c of file) { } 458 }); 459 460 busboy.on('field', (fieldName, value) => { 461 body += `${fieldName}=${value}`; 462 }); 463 busboy.on('finish', () => { 464 - res.end(JSON.stringify({ 465 - method: request.method, 466 - url: request.url, 467 - headers: request.headers, 468 - body 469 - })); 470 }); 471 request.pipe(busboy); 472 }
··· 3 import http from 'http'; 4 import zlib from 'zlib'; 5 import Busboy from 'busboy'; 6 + import { once } from 'events'; 7 8 export default class TestServer { 9 constructor() { ··· 42 return `http://${this.hostname}:${this.port}/mocked`; 43 } 44 45 + mock(handler) { 46 + this.server.nextResponseHandler = handler; 47 + return `http://${this.hostname}:${this.port}/mocked`; 48 + } 49 + 50 router(request, res) { 51 const p = request.url; 52 53 if (p === '/mocked') { 54 if (this.nextResponseHandler) { 55 + this.nextResponseHandler(request, res); 56 this.nextResponseHandler = undefined; 57 } else { 58 + throw new Error("No mocked response. Use 'TestServer.mockResponse()'."); 59 } 60 } 61 ··· 96 if (p === '/json') { 97 res.statusCode = 200; 98 res.setHeader('Content-Type', 'application/json'); 99 + res.end( 100 + JSON.stringify({ 101 + name: 'value', 102 + }) 103 + ); 104 } 105 106 if (p === '/gzip') { ··· 251 } 252 253 if (p === '/redirect/301/rn') { 254 + res.statusCode = 301; 255 + res.setHeader('Location', '/403'); 256 res.write('301 Permanently moved.\r\n'); 257 res.end(); 258 } ··· 328 if (p === '/redirect/chunked') { 329 res.writeHead(301, { 330 Location: '/inspect', 331 + 'Transfer-Encoding': 'chunked', 332 }); 333 setTimeout(() => res.end(), 10); 334 } ··· 356 } 357 358 if (p === '/error/premature') { 359 + res.writeHead(200, { 'content-length': 50 }); 360 res.write('foo'); 361 setTimeout(() => { 362 res.destroy(); ··· 366 if (p === '/error/premature/chunked') { 367 res.writeHead(200, { 368 'Content-Type': 'application/json', 369 + 'Transfer-Encoding': 'chunked', 370 }); 371 372 + res.write(`${JSON.stringify({ data: 'hi' })}\n`); 373 374 setTimeout(() => { 375 + res.write(`${JSON.stringify({ data: 'bye' })}\n`); 376 }, 50); 377 378 setTimeout(() => { ··· 442 body += c; 443 }); 444 request.on('end', () => { 445 + res.end( 446 + JSON.stringify({ 447 + inspect: true, 448 + method: request.method, 449 + url: request.url, 450 + headers: request.headers, 451 + body, 452 + }) 453 + ); 454 }); 455 } 456 457 if (p === '/multipart') { 458 res.statusCode = 200; 459 res.setHeader('Content-Type', 'application/json'); 460 + const busboy = new Busboy({ headers: request.headers }); 461 let body = ''; 462 busboy.on('file', async (fieldName, file, fileName) => { 463 body += `${fieldName}=${fileName}`; 464 // consume file data 465 // eslint-disable-next-line no-empty, no-unused-vars 466 + for await (const c of file) { 467 + } 468 }); 469 470 busboy.on('field', (fieldName, value) => { 471 body += `${fieldName}=${value}`; 472 }); 473 busboy.on('finish', () => { 474 + res.end( 475 + JSON.stringify({ 476 + method: request.method, 477 + url: request.url, 478 + headers: request.headers, 479 + body, 480 + }) 481 + ); 482 }); 483 request.pipe(busboy); 484 }
+258
src/agent.ts
···
··· 1 + import * as https from 'node:https'; 2 + import * as http from 'node:http'; 3 + import * as net from 'node:net'; 4 + 5 + declare module 'https' { 6 + interface Agent { 7 + createConnection( 8 + opts: https.RequestOptions, 9 + callback?: (err: Error | null, socket: net.Socket | null) => void 10 + ): net.Socket | null; 11 + } 12 + } 13 + 14 + declare module 'net' { 15 + export function _normalizeArgs( 16 + options: unknown 17 + ): asserts options is net.NetConnectOpts; 18 + } 19 + 20 + const getHttpProxyUrl = () => process.env.HTTP_PROXY ?? process.env.http_proxy; 21 + const getHttpsProxyUrl = () => 22 + process.env.HTTPS_PROXY ?? process.env.https_proxy; 23 + const getNoProxy = () => process.env.NO_PROXY ?? process.env.no_proxy; 24 + 25 + const createProxyPattern = (pattern: string): RegExp | null => { 26 + pattern = pattern.trim(); 27 + if (!pattern.startsWith('.')) pattern = `^${pattern}`; 28 + if (!pattern.endsWith('.') || pattern.includes(':')) pattern += '$'; 29 + pattern = pattern.replace(/\./g, '\\.').replace(/\*/g, '[\\w.]+'); 30 + return pattern ? new RegExp(pattern, 'i') : null; 31 + }; 32 + 33 + const matchesNoProxy = (options: { 34 + host?: string | null; 35 + hostname?: string | null; 36 + port?: string | number | null; 37 + defaultPort?: string | number; 38 + }): boolean => { 39 + const NO_PROXY = getNoProxy(); 40 + if (NO_PROXY === '*' || NO_PROXY === '1' || NO_PROXY === 'true') { 41 + return true; 42 + } else if (NO_PROXY) { 43 + for (const noProxyPattern of NO_PROXY.split(',')) { 44 + const hostPattern = createProxyPattern(noProxyPattern); 45 + if (hostPattern) { 46 + const hostname = options.hostname || options.host; 47 + const origin = 48 + hostname && 49 + `${hostname}:${options.port || options.defaultPort || 80}`; 50 + if ( 51 + (hostname && hostPattern.test(hostname)) || 52 + (origin && hostPattern.test(origin)) 53 + ) { 54 + return true; 55 + } 56 + } 57 + } 58 + return false; 59 + } else { 60 + return false; 61 + } 62 + }; 63 + 64 + export const defaultAgentOpts = { 65 + keepAlive: true, 66 + keepAliveMsecs: 1000, 67 + }; 68 + 69 + let _httpAgentUrl: string | undefined; 70 + let _httpAgent: http.Agent | undefined; 71 + 72 + export const getHttpAgent = ( 73 + options: http.RequestOptions 74 + ): http.RequestOptions['agent'] => { 75 + const HTTP_PROXY = getHttpProxyUrl(); 76 + if (!HTTP_PROXY) { 77 + _httpAgent = undefined; 78 + return undefined; 79 + } else if (matchesNoProxy(options)) { 80 + return undefined; 81 + } else if (!_httpAgentUrl || _httpAgentUrl !== HTTP_PROXY) { 82 + _httpAgent = undefined; 83 + try { 84 + _httpAgentUrl = HTTP_PROXY; 85 + _httpAgent = new HttpProxyAgent(new URL(HTTP_PROXY), defaultAgentOpts); 86 + } catch (error: any) { 87 + const wrapped = new Error( 88 + `Invalid HTTP_PROXY URL: "${HTTP_PROXY}".\n` + error?.message || error 89 + ); 90 + (wrapped as any).cause = error; 91 + throw wrapped; 92 + } 93 + return _httpAgent; 94 + } else { 95 + return _httpAgent; 96 + } 97 + }; 98 + 99 + let _httpsAgentUrl: string | undefined; 100 + let _httpsAgent: https.Agent | undefined; 101 + 102 + export const getHttpsAgent = ( 103 + options: https.RequestOptions 104 + ): https.RequestOptions['agent'] => { 105 + const HTTPS_PROXY = getHttpsProxyUrl() ?? getHttpProxyUrl(); 106 + if (!HTTPS_PROXY) { 107 + _httpsAgent = undefined; 108 + return undefined; 109 + } else if (matchesNoProxy(options)) { 110 + return undefined; 111 + } else if (!_httpsAgentUrl || _httpsAgentUrl !== HTTPS_PROXY) { 112 + _httpsAgent = undefined; 113 + try { 114 + _httpsAgentUrl = HTTPS_PROXY; 115 + _httpsAgent = new HttpsProxyAgent(new URL(HTTPS_PROXY), defaultAgentOpts); 116 + } catch (error: any) { 117 + const wrapped = new Error( 118 + `Invalid HTTPS_PROXY URL: "${HTTPS_PROXY}".\n` + error?.message || error 119 + ); 120 + (wrapped as any).cause = error; 121 + throw wrapped; 122 + } 123 + return _httpsAgent; 124 + } else { 125 + return _httpsAgent; 126 + } 127 + }; 128 + 129 + const createRequestOptions = ( 130 + proxy: URL, 131 + keepAlive: boolean, 132 + options: http.RequestOptions 133 + ) => { 134 + const proxyHeaders: Record<string, string> = { 135 + host: `${options.host}:${options.port}`, 136 + connection: keepAlive ? 'keep-alive' : 'close', 137 + }; 138 + if (proxy.username || proxy.password) { 139 + const username = decodeURIComponent(proxy.username || ''); 140 + const password = decodeURIComponent(proxy.password || ''); 141 + const auth = Buffer.from(`${username}:${password}`).toString('base64'); 142 + proxyHeaders['proxy-authorization'] = `Basic ${auth}`; 143 + } 144 + return { 145 + method: 'CONNECT', 146 + host: proxy.hostname, 147 + port: proxy.port, 148 + path: `${options.host}:${options.port}`, 149 + setHost: false, 150 + agent: false, 151 + proxyEnv: {}, 152 + timeout: 5_000, 153 + headers: proxyHeaders, 154 + servername: proxy.protocol === 'https:' ? proxy.hostname : undefined, 155 + }; 156 + }; 157 + 158 + // See: https://github.com/delvedor/hpagent 159 + // `hpagent` served as a template for how to create proxy agents like below minimally 160 + // MIT License, Copyright (c) 2020 Tomas Della Vedova 161 + 162 + class HttpProxyAgent extends http.Agent { 163 + _keepAlive: boolean; 164 + _proxy: URL; 165 + 166 + constructor(proxy: URL, options: http.AgentOptions) { 167 + super(options); 168 + this._proxy = proxy; 169 + this._keepAlive = !!options.keepAlive; 170 + } 171 + 172 + createConnection( 173 + options: http.RequestOptions, 174 + callback: (err: Error | null, socket: net.Socket | null) => void 175 + ): void { 176 + const request = (this._proxy.protocol === 'http:' ? http : https).request( 177 + createRequestOptions(this._proxy, this._keepAlive, options) 178 + ); 179 + 180 + request.once('connect', (response, socket, _head) => { 181 + request.removeAllListeners(); 182 + socket.removeAllListeners(); 183 + if (response.statusCode === 200) { 184 + callback(null, socket); 185 + } else { 186 + socket.destroy(); 187 + callback( 188 + new Error( 189 + `HTTP Proxy Network Error: ${response.statusMessage || response.statusCode}` 190 + ), 191 + null 192 + ); 193 + } 194 + }); 195 + 196 + request.once('timeout', () => { 197 + request.destroy(new Error('HTTP Proxy timed out')); 198 + }); 199 + 200 + request.once('error', error => { 201 + request.removeAllListeners(); 202 + callback(error, null); 203 + }); 204 + 205 + request.end(); 206 + } 207 + } 208 + 209 + class HttpsProxyAgent extends https.Agent { 210 + _proxy: URL; 211 + _keepAlive: boolean; 212 + 213 + constructor(proxy: URL, options: https.AgentOptions) { 214 + super(options); 215 + this._proxy = proxy; 216 + this._keepAlive = !!options.keepAlive; 217 + } 218 + 219 + createConnection( 220 + options: https.RequestOptions, 221 + callback?: (err: Error | null, socket: net.Socket | null) => void 222 + ): net.Socket | null { 223 + const request = (this._proxy.protocol === 'http:' ? http : https).request( 224 + createRequestOptions(this._proxy, this._keepAlive, options) 225 + ); 226 + 227 + request.once('connect', (response, socket, _head) => { 228 + request.removeAllListeners(); 229 + socket.removeAllListeners(); 230 + if (response.statusCode === 200) { 231 + const netOpts = { ...options, socket }; 232 + net._normalizeArgs(netOpts); 233 + const secureSocket = super.createConnection(netOpts); 234 + callback?.(null, secureSocket); 235 + } else { 236 + socket.destroy(); 237 + callback?.( 238 + new Error( 239 + `HTTP Proxy Network Error: ${response.statusMessage || response.statusCode}` 240 + ), 241 + null 242 + ); 243 + } 244 + }); 245 + 246 + request.once('timeout', () => { 247 + request.destroy(new Error('HTTP Proxy timed out')); 248 + }); 249 + 250 + request.once('error', err => { 251 + request.removeAllListeners(); 252 + callback?.(err, null); 253 + }); 254 + 255 + request.end(); 256 + return request.socket; 257 + } 258 + }
+62 -3
src/body.ts
··· 1 import { Readable } from 'node:stream'; 2 import { isAnyArrayBuffer } from 'node:util/types'; 3 import { randomBytes } from 'node:crypto'; 4 - import { Blob, FormData, URLSearchParams } from './webstd'; 5 6 export type BodyInit = 7 | Exclude<RequestInit['body'], undefined | null> ··· 77 typeof object.stream === 'function' && 78 typeof object.constructor === 'function' 79 ) { 80 - const tag = object[Symbol.toStringTag]; 81 - return tag.startsWith('Blob') || tag.startsWith('File'); 82 } else { 83 return false; 84 } ··· 196 body, 197 }; 198 };
··· 1 import { Readable } from 'node:stream'; 2 + import { arrayBuffer, blob, text } from 'node:stream/consumers'; 3 import { isAnyArrayBuffer } from 'node:util/types'; 4 import { randomBytes } from 'node:crypto'; 5 + import { Response, Blob, FormData, URLSearchParams } from './webstd'; 6 7 export type BodyInit = 8 | Exclude<RequestInit['body'], undefined | null> ··· 78 typeof object.stream === 'function' && 79 typeof object.constructor === 'function' 80 ) { 81 + const tag = object[Symbol.toStringTag] as string | undefined; 82 + return !!tag && (tag.startsWith('Blob') || tag.startsWith('File')); 83 } else { 84 return false; 85 } ··· 197 body, 198 }; 199 }; 200 + 201 + const kBodyInternals = Symbol('kBodyInternals'); 202 + 203 + export class Body { 204 + private [kBodyInternals]: BodyState; 205 + 206 + constructor(init: BodyInit | null) { 207 + this[kBodyInternals] = extractBody(init); 208 + } 209 + 210 + get body() { 211 + return this[kBodyInternals].body; 212 + } 213 + 214 + get bodyUsed() { 215 + const { body } = this[kBodyInternals]; 216 + if (isReadable(body)) { 217 + return Readable.isDisturbed(body); 218 + } else if (isReadableStream(body)) { 219 + return body.locked; 220 + } else { 221 + return false; 222 + } 223 + } 224 + 225 + async arrayBuffer() { 226 + const { body } = this[kBodyInternals]; 227 + return body != null && !isAnyArrayBuffer(body) ? arrayBuffer(body) : body; 228 + } 229 + 230 + async formData() { 231 + const { body, contentLength, contentType } = this[kBodyInternals]; 232 + const headers = {}; 233 + if (contentLength) headers['Content-Length'] = contentLength; 234 + if (contentType) headers['Content-Type'] = contentType; 235 + return new Response(body, { headers }).formData(); 236 + } 237 + 238 + async blob() { 239 + const { body, contentType } = this[kBodyInternals]; 240 + const chunks = 241 + body !== null ? [!isAnyArrayBuffer(body) ? await blob(body) : body] : []; 242 + return new Blob(chunks, { 243 + type: contentType ?? undefined, 244 + }); 245 + } 246 + 247 + async json() { 248 + return JSON.parse(await this.text()); 249 + } 250 + 251 + async text() { 252 + const { body } = this[kBodyInternals]; 253 + return body == null || isAnyArrayBuffer(body) 254 + ? new TextDecoder().decode(await this.arrayBuffer()) 255 + : text(body); 256 + } 257 + }
+3 -1
src/encoding.ts
··· 37 38 _final(callback: TransformCallback) { 39 if (this._inflate) { 40 this._inflate.end(); 41 this._inflate = undefined; 42 } 43 - callback(); 44 } 45 } 46
··· 37 38 _final(callback: TransformCallback) { 39 if (this._inflate) { 40 + this._inflate.once('finish', callback); 41 this._inflate.end(); 42 this._inflate = undefined; 43 + } else { 44 + callback(); 45 } 46 } 47 } 48
+85 -25
src/fetch.ts
··· 1 import { Stream, Readable, pipeline } from 'node:stream'; 2 import * as https from 'node:https'; 3 import * as http from 'node:http'; 4 import * as url from 'node:url'; ··· 6 import { extractBody } from './body'; 7 import { createContentDecoder } from './encoding'; 8 import { URL, Request, RequestInit, Response } from './webstd'; 9 10 /** Maximum allowed redirects (matching Chromium's limit) */ 11 const MAX_REDIRECTS = 20; 12 13 /** Convert Node.js raw headers array to Headers */ 14 const headersOfRawHeaders = (rawHeaders: readonly string[]): Headers => { 15 const headers = new Headers(); 16 for (let i = 0; i < rawHeaders.length; i += 2) 17 - headers.set(rawHeaders[i], rawHeaders[i + 1]); 18 return headers; 19 }; 20 ··· 103 return response; 104 } 105 106 async function _fetch( 107 input: string | URL | Request, 108 requestInit?: RequestInit ··· 126 ); 127 const requestOptions = { 128 ...urlToHttpOptions(requestUrl), 129 method: methodToHttpOption( 130 initFromRequest ? input.method : requestInit?.method 131 ), ··· 136 resolve: (response: Response | Promise<Response>) => void, 137 reject: (reason?: any) => void 138 ) { 139 const method = requestOptions.method; 140 const protocol = requestOptions.protocol === 'https:' ? https : http; 141 const outgoing = protocol.request(requestOptions); 142 143 - outgoing.on('response', incoming => { 144 incoming.setTimeout(0); // Forcefully disable timeout 145 146 const init = { 147 status: incoming.statusCode, ··· 152 if (isRedirectCode(init.status)) { 153 const location = init.headers.get('Location'); 154 const locationURL = 155 - location != null ? new URL(location, requestUrl) : null; 156 if (redirect === 'error') { 157 - // TODO: do we need a special Error instance here? 158 reject( 159 new Error( 160 'URI requested responds with a redirect, redirect mode is set to error' 161 ) 162 ); 163 return; 164 - } else if (redirect === 'manual' && locationURL !== null) { 165 - init.headers.set('Location', locationURL.toString()); 166 - } else if (redirect === 'follow' && locationURL !== null) { 167 - if (++redirects > MAX_REDIRECTS) { 168 reject(new Error(`maximum redirect reached at: ${requestUrl}`)); 169 return; 170 } else if ( ··· 201 } 202 } 203 204 - const destroy = (reason?: any) => { 205 - signal?.removeEventListener('abort', destroy); 206 - if (reason) { 207 - incoming.destroy(signal?.aborted ? signal.reason : reason); 208 - reject(signal?.aborted ? signal.reason : reason); 209 - } 210 - }; 211 - 212 - signal?.addEventListener('abort', destroy); 213 - 214 let body: Readable | null = incoming; 215 const encoding = init.headers.get('Content-Encoding')?.toLowerCase(); 216 if (method === 'HEAD' || init.status === 204 || init.status === 304) { ··· 218 } else if (encoding != null) { 219 init.headers.set('Content-Encoding', encoding); 220 body = pipeline(body, createContentDecoder(encoding), destroy); 221 } 222 223 resolve( ··· 229 ); 230 }); 231 232 - outgoing.on('error', reject); 233 234 - if (!requestHeaders.has('Accept')) requestHeaders.set('Accept', '*/*'); 235 - if (requestBody.contentType) 236 requestHeaders.set('Content-Type', requestBody.contentType); 237 238 - if (requestBody.body == null && (method === 'POST' || method === 'PUT')) { 239 requestHeaders.set('Content-Length', '0'); 240 } else if (requestBody.body != null && requestBody.contentLength != null) { 241 requestHeaders.set('Content-Length', `${requestBody.contentLength}`); ··· 253 requestBody.body instanceof Stream 254 ? requestBody.body 255 : Readable.fromWeb(requestBody.body); 256 - pipeline(body, outgoing, error => { 257 - if (error) reject(error); 258 - }); 259 } 260 } 261
··· 1 import { Stream, Readable, pipeline } from 'node:stream'; 2 + import { Socket } from 'node:net'; 3 import * as https from 'node:https'; 4 import * as http from 'node:http'; 5 import * as url from 'node:url'; ··· 7 import { extractBody } from './body'; 8 import { createContentDecoder } from './encoding'; 9 import { URL, Request, RequestInit, Response } from './webstd'; 10 + import { getHttpsAgent, getHttpAgent } from './agent'; 11 12 /** Maximum allowed redirects (matching Chromium's limit) */ 13 const MAX_REDIRECTS = 20; 14 15 + const parseURL = (input: string, base?: string | URL): URL | null => { 16 + try { 17 + return new URL(input, base); 18 + } catch { 19 + return null; 20 + } 21 + }; 22 + 23 /** Convert Node.js raw headers array to Headers */ 24 const headersOfRawHeaders = (rawHeaders: readonly string[]): Headers => { 25 const headers = new Headers(); 26 for (let i = 0; i < rawHeaders.length; i += 2) 27 + headers.append(rawHeaders[i], rawHeaders[i + 1]); 28 return headers; 29 }; 30 ··· 113 return response; 114 } 115 116 + function attachRefLifetime(body: Readable, socket: Socket): void { 117 + const { _read } = body; 118 + body.on('close', () => { 119 + socket.unref(); 120 + }); 121 + body._read = function _readRef(...args: Parameters<Readable['_read']>) { 122 + body._read = _read; 123 + socket.ref(); 124 + return _read.apply(this, args); 125 + }; 126 + } 127 + 128 async function _fetch( 129 input: string | URL | Request, 130 requestInit?: RequestInit ··· 148 ); 149 const requestOptions = { 150 ...urlToHttpOptions(requestUrl), 151 + timeout: 5_000, 152 method: methodToHttpOption( 153 initFromRequest ? input.method : requestInit?.method 154 ), ··· 159 resolve: (response: Response | Promise<Response>) => void, 160 reject: (reason?: any) => void 161 ) { 162 + requestOptions.agent = 163 + requestOptions.protocol === 'https:' 164 + ? getHttpsAgent(requestOptions) 165 + : getHttpAgent(requestOptions); 166 const method = requestOptions.method; 167 const protocol = requestOptions.protocol === 'https:' ? https : http; 168 const outgoing = protocol.request(requestOptions); 169 170 + let incoming: http.IncomingMessage | undefined; 171 + 172 + const destroy = (reason?: any) => { 173 + if (reason) { 174 + outgoing?.destroy(signal?.aborted ? signal.reason : reason); 175 + incoming?.destroy(signal?.aborted ? signal.reason : reason); 176 + reject(signal?.aborted ? signal.reason : reason); 177 + } 178 + signal?.removeEventListener('abort', destroy); 179 + }; 180 + 181 + signal?.addEventListener('abort', destroy); 182 + 183 + outgoing.on('timeout', () => { 184 + if (!incoming) { 185 + const error = new Error('Request timed out') as NodeJS.ErrnoException; 186 + error.code = 'ETIMEDOUT'; 187 + destroy(error); 188 + } 189 + }); 190 + 191 + outgoing.on('response', _incoming => { 192 + if (signal?.aborted) { 193 + return; 194 + } 195 + 196 + incoming = _incoming; 197 incoming.setTimeout(0); // Forcefully disable timeout 198 + incoming.socket.unref(); 199 + incoming.on('error', destroy); 200 201 const init = { 202 status: incoming.statusCode, ··· 207 if (isRedirectCode(init.status)) { 208 const location = init.headers.get('Location'); 209 const locationURL = 210 + location != null ? parseURL(location, requestUrl) : null; 211 if (redirect === 'error') { 212 reject( 213 new Error( 214 'URI requested responds with a redirect, redirect mode is set to error' 215 ) 216 ); 217 return; 218 + } else if (redirect === 'manual' && location) { 219 + init.headers.set('Location', locationURL?.href ?? location); 220 + } else if (redirect === 'follow') { 221 + if (locationURL === null) { 222 + reject( 223 + new Error('URI requested responds with an invalid redirect URL') 224 + ); 225 + return; 226 + } else if (++redirects > MAX_REDIRECTS) { 227 reject(new Error(`maximum redirect reached at: ${requestUrl}`)); 228 return; 229 } else if ( ··· 260 } 261 } 262 263 let body: Readable | null = incoming; 264 const encoding = init.headers.get('Content-Encoding')?.toLowerCase(); 265 if (method === 'HEAD' || init.status === 204 || init.status === 304) { ··· 267 } else if (encoding != null) { 268 init.headers.set('Content-Encoding', encoding); 269 body = pipeline(body, createContentDecoder(encoding), destroy); 270 + outgoing.on('error', destroy); 271 + } 272 + 273 + // Re-ref the socket when the body starts being consumed to prevent 274 + // early process exit, then unref when done to allow normal exit. 275 + if (body != null) { 276 + attachRefLifetime(body, incoming.socket); 277 } 278 279 resolve( ··· 285 ); 286 }); 287 288 + outgoing.on('error', destroy); 289 290 + if (!requestHeaders.has('Accept')) { 291 + requestHeaders.set('Accept', '*/*'); 292 + } 293 + if (!requestHeaders.has('Content-Type') && requestBody.contentType) { 294 requestHeaders.set('Content-Type', requestBody.contentType); 295 + } 296 297 + if ( 298 + requestBody.body == null && 299 + (method === 'POST' || method === 'PUT' || method === 'PATCH') 300 + ) { 301 requestHeaders.set('Content-Length', '0'); 302 } else if (requestBody.body != null && requestBody.contentLength != null) { 303 requestHeaders.set('Content-Length', `${requestBody.contentLength}`); ··· 315 requestBody.body instanceof Stream 316 ? requestBody.body 317 : Readable.fromWeb(requestBody.body); 318 + pipeline(body, outgoing, destroy); 319 } 320 } 321
+1
src/index.ts
··· 1 export { fetch, fetch as default } from './fetch'; 2 export * from './webstd';
··· 1 export { fetch, fetch as default } from './fetch'; 2 + export { Body } from './body'; 3 export * from './webstd';
+9 -4
src/webstd.ts
··· 81 init?: _RequestInit | Or<RequestInit, globalThis.RequestInit> 82 ): _Request; 83 } 84 - const _Request: RequestClass = Request; 85 86 interface _Response extends Or<Response, globalThis.Response> {} 87 interface ResponseClass 88 extends Or<typeof Response, typeof globalThis.Response> { 89 new (body?: BodyInit, init?: _ResponseInit): _Response; 90 } 91 - const _Response: ResponseClass = Response; 92 93 interface _Headers extends Or<Headers, globalThis.Headers> {} 94 interface HeadersClass extends Or<typeof Headers, typeof globalThis.Headers> { 95 new (init?: HeadersInit): _Headers; 96 } 97 - const _Headers: HeadersClass = Headers; 98 99 interface _FormData 100 extends Or< ··· 103 > {} 104 interface FormDataClass 105 extends Or<typeof FormData, typeof globalThis.FormData> {} 106 - const _FormData: FormDataClass = FormData; 107 108 export { 109 type _RequestInit as RequestInit,
··· 81 init?: _RequestInit | Or<RequestInit, globalThis.RequestInit> 82 ): _Request; 83 } 84 85 interface _Response extends Or<Response, globalThis.Response> {} 86 interface ResponseClass 87 extends Or<typeof Response, typeof globalThis.Response> { 88 new (body?: BodyInit, init?: _ResponseInit): _Response; 89 } 90 91 interface _Headers extends Or<Headers, globalThis.Headers> {} 92 interface HeadersClass extends Or<typeof Headers, typeof globalThis.Headers> { 93 new (init?: HeadersInit): _Headers; 94 } 95 96 interface _FormData 97 extends Or< ··· 100 > {} 101 interface FormDataClass 102 extends Or<typeof FormData, typeof globalThis.FormData> {} 103 + 104 + let _Request: RequestClass; 105 + let _Response: ResponseClass; 106 + let _Headers: HeadersClass; 107 + let _FormData: FormDataClass; 108 + if (typeof Request !== 'undefined') _Request = Request; 109 + if (typeof Response !== 'undefined') _Response = Response; 110 + if (typeof Headers !== 'undefined') _Headers = Headers; 111 + if (typeof FormData !== 'undefined') _FormData = FormData; 112 113 export { 114 type _RequestInit as RequestInit,