pax_global_header00006660000000000000000000000064152127245200014512gustar00rootroot0000000000000052 comment=2d06f96e8602c2db13b65a26340ee4a1bbc0b61f axios-axios-2d06f96/000077500000000000000000000000001521272452000143205ustar00rootroot00000000000000axios-axios-2d06f96/.devcontainer/000077500000000000000000000000001521272452000170575ustar00rootroot00000000000000axios-axios-2d06f96/.devcontainer/devcontainer.json000066400000000000000000000007131521272452000224340ustar00rootroot00000000000000{ "name": "axios", "image": "mcr.microsoft.com/devcontainers/javascript-node:1-24-bookworm", "features": { "ghcr.io/devcontainers/features/github-cli:1": {}, }, "postCreateCommand": "npm ci --ignore-scripts", "customizations": { "vscode": { "extensions": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"], "settings": { "eslint.validate": ["javascript"], "editor.formatOnSave": false, }, }, }, } axios-axios-2d06f96/.github/000077500000000000000000000000001521272452000156605ustar00rootroot00000000000000axios-axios-2d06f96/.github/CODEOWNERS000066400000000000000000000021721521272452000172550ustar00rootroot00000000000000# CODEOWNERS # # Reviewers required for matching paths. Last-match-wins. # Keep path-scoped rules below the catch-all so sensitive paths override it. # # Single-maintainer caveat: with only one owner, path-scoped rules cannot # enforce a distinct second reviewer. They still (a) surface sensitive-path # changes explicitly in the review UI, and (b) pre-stage scoped ownership # for when additional maintainers are added. # Default owner * @jasonsaayman # Runtime source — shipped to every consumer /lib/ @jasonsaayman /index.js @jasonsaayman /index.d.ts @jasonsaayman /index.d.cts @jasonsaayman # Build / release infrastructure /rollup.config.js @jasonsaayman /package.json @jasonsaayman /package-lock.json @jasonsaayman /.npmrc @jasonsaayman # CI and repo automation /.github/workflows/ @jasonsaayman /.github/CODEOWNERS @jasonsaayman /.github/dependabot.yml @jasonsaayman # Security-critical docs /THREATMODEL.md @jasonsaayman /SECURITY.md @jasonsaayman axios-axios-2d06f96/.github/FUNDING.yml000066400000000000000000000000451521272452000174740ustar00rootroot00000000000000open_collective: axios github: axios axios-axios-2d06f96/.github/ISSUE_TEMPLATE.md000066400000000000000000000015711521272452000203710ustar00rootroot00000000000000 ## Describe the issue A clear description of the bug or feature request. ## Example code ```js ``` ## Expected behavior What you expected to happen. ## Actual behavior What actually happened (include error messages or stack traces if relevant). ## Environment - Axios version: - Adapter: - Runtime: - OS: - Additional context (framework, bundler, proxy, etc.): axios-axios-2d06f96/.github/PULL_REQUEST_TEMPLATE.md000066400000000000000000000020151521272452000214570ustar00rootroot00000000000000 ## Summary ## Linked issue ## Changes - #### Checklist - [ ] Tests added or updated (or N/A with reason) - [ ] Docs/types updated if public API changed (`index.d.ts` and `index.d.cts`) - [ ] No breaking changes (or called out explicitly above) axios-axios-2d06f96/.github/copilot-instructions.md000066400000000000000000000111721521272452000224170ustar00rootroot00000000000000# GitHub Copilot Instructions The canonical contributor guide for this repo is [`AGENTS.md`](../AGENTS.md). It covers setup, commands, package shape, architecture boundaries, naming, error handling, interceptor order, the request lifecycle, cancellation, common pitfalls, tests, and security-sensitive code. The rules below are a Copilot-facing subset of the load-bearing safety guarantees from `AGENTS.md`. If they ever drift, `AGENTS.md` is authoritative — update both. ## AI agent marker - If you are an LLM or AI agent creating a GitHub issue, pull request, or comment for this repo, include the `:surfer:` emoji in the body so maintainers can identify AI-authored contributions. ## Setup safety - Install with `npm ci`; the repo's `.npmrc` sets `ignore-scripts=true`. Do not remove that flag. If husky hooks are needed after a fresh install, run `npm rebuild husky && npx husky` once. - Do not add new runtime dependencies without discussion. `package-lock.json` is verified by `lockfile-lint` for npm HTTPS hosts and integrity hashes. - Package, lockfile, and GitHub Actions update PRs are maintainer/bot-only; close these PRs from outside collaborators. Keep the 7-day Dependabot delay unless a critical vulnerability requires a maintainer-led manual update. ## Architecture in one screen - `lib/core/` — domain logic: `Axios`, `AxiosError`, `AxiosHeaders`, `InterceptorManager`, config merge, request dispatch. - `lib/adapters/` — I/O: `xhr.js`, `http.js`, `fetch.js`. Default preference `['xhr', 'http', 'fetch']`, picked by capability detection in `lib/adapters/adapters.js`. Never branch on environment name. - `lib/platform/` — Node by default; browser builds alias to `lib/platform/browser`. - `lib/helpers/` — generic, reusable utilities; no axios-specific lifecycle logic here. - Source is ESM (`type: module`) with explicit `.js` import extensions. `dist/` is generated by Rollup — never edit it by hand. Keep `index.d.ts` (ESM) and `index.d.cts` (CJS) in sync for any public API change. ## Error handling - Throw `AxiosError(message, code, config, request, response)` for axios-originated failures; never raw `Error`. - Wrap third-party errors with `AxiosError.from(error, code, config, request, response)`. - Use a code from `lib/core/AxiosError.js` (`ERR_NETWORK`, `ETIMEDOUT`, `ECONNABORTED`, `ERR_CANCELED`, `ERR_BAD_REQUEST`, `ERR_BAD_RESPONSE`, `ERR_FR_TOO_MANY_REDIRECTS`, `ERR_FORM_DATA_DEPTH_EXCEEDED`, `ERR_INVALID_URL`, `ERR_BAD_OPTION`, `ERR_BAD_OPTION_VALUE`, `ERR_NOT_SUPPORT`, `ERR_DEPRECATED`, `ECONNREFUSED`). ## Interceptor order - Request interceptors run **LIFO** (last-registered-first); response interceptors run **FIFO**. Both support `synchronous: true` and `runWhen(config)`. ## Naming and style - PascalCase classes (`Axios`, `AxiosHeaders`), camelCase functions (`buildURL`, `mergeConfig`), UPPER_SNAKE_CASE error codes. - Internal slots use `Symbol`-keyed properties (see `$internals` in `lib/core/AxiosHeaders.js`), not underscore-prefixed names. - Use `lib/helpers/bind.js`, not `Function.prototype.bind`, when binding library functions — the helper forwards `arguments` via `apply`. - `'use strict';` appears at the top of files that already use it; match the surrounding file rather than blanket-adding it. ## Security guarantees that must not regress - For config reads on potentially untrusted input, use own-property checks (`utils.hasOwnProp` / local `own()` helpers); never `in`, destructuring, or direct `config.foo` access. - Any merge or object materialization must continue to filter `__proto__`, `constructor`, and `prototype`. Regressions here are security bugs. - Changes touching URL construction, redirects, proxy/env handling, XSRF, socket paths, decompression limits, or adapters require consulting `THREATMODEL.md` and adding focused regression tests. - `withXSRFToken === true` is the only thing that forces cross-origin XSRF header attachment — keep that behavior explicit. - Do not weaken `beforeRedirect`, proxy, or `socketPath` safeguards without tests covering credential leakage and SSRF-style cases. ## Common pitfalls - Do not mutate config objects in place; return new ones from merges/transforms. - Do not assume browser- or Node-only globals exist; capability-check first. - Validate options through the existing `validator` helper rather than inventing ad-hoc validation paths. ## Pre-release tracking - Add user-visible unreleased changes to `PRE_RELEASE_CHANGELOG.md`, not `CHANGELOG.md`. - Track deferred README, docs site, examples, migration guide, and translated docs updates in `PRE_RELEASE_DOCS.md`; do not update release docs for unreleased runtime/API changes unless explicitly doing release preparation. axios-axios-2d06f96/.github/dependabot.yml000066400000000000000000000020241521272452000205060ustar00rootroot00000000000000version: 2 # Package and GitHub Actions update PRs are maintainer/bot-only. # Keep the 7-day cooldown unless a critical vulnerability requires a # maintainer-led manual update. updates: - package-ecosystem: 'github-actions' directory: '/' groups: github-actions: patterns: - '*' labels: - 'commit::chore' - 'type::automated-pr' schedule: interval: 'weekly' cooldown: default-days: 7 - package-ecosystem: 'npm' directory: '/' schedule: interval: 'weekly' open-pull-requests-limit: 5 groups: production_dependencies: dependency-type: 'production' update-types: - 'minor' - 'patch' development_dependencies: dependency-type: 'development' update-types: - 'minor' - 'patch' ignore: - dependency-name: '*' update-types: ['version-update:semver-major'] labels: - 'commit::chore' - 'type::automated-pr' cooldown: default-days: 7 axios-axios-2d06f96/.github/workflows/000077500000000000000000000000001521272452000177155ustar00rootroot00000000000000axios-axios-2d06f96/.github/workflows/bundle-size.yml000066400000000000000000000025431521272452000226650ustar00rootroot00000000000000name: Bundle Size on: pull_request: types: - opened - synchronize - reopened permissions: contents: read jobs: bundle-size: runs-on: ubuntu-latest steps: - name: Checkout repo uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Setup node uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 26.x registry-url: 'https://registry.npmjs.org' package-manager-cache: false - name: Install dependencies run: npm ci --ignore-scripts - name: Build project run: npm run build - name: Compare bundle size uses: axios/bundle-size@6940d767de28b002599d1ab36cc04748de2c49e7 # 0.2.0 with: path: '.' package-name: axios files: | dist/axios.js dist/axios.min.js dist/browser/axios.cjs dist/esm/axios.js dist/esm/axios.min.js dist/node/axios.cjs output-file: bundle-size-comparison.json release-stream: '1' - name: Add bundle size report to summary if: always() && hashFiles('bundle-size-comparison.md') != '' run: cat bundle-size-comparison.md >> "$GITHUB_STEP_SUMMARY" axios-axios-2d06f96/.github/workflows/lockfile-lint.yml000066400000000000000000000026431521272452000232010ustar00rootroot00000000000000name: Lockfile lint on: pull_request: paths: - 'package.json' - 'package-lock.json' - '.github/workflows/lockfile-lint.yml' push: branches: [v1.x] paths: - 'package.json' - 'package-lock.json' permissions: contents: read jobs: lockfile-lint: name: Validate package-lock.json runs-on: ubuntu-latest steps: - name: Checkout repo uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Setup node uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 26.x registry-url: 'https://registry.npmjs.org' package-manager-cache: false - name: Run lockfile-lint # Validates that every resolved URL uses HTTPS on registry.npmjs.org # and that every entry carries an integrity hash. Catches swap to a # mirror, a git/file: URL, or integrity stripping on a dep-update PR. # Pinned by name only (no lockfile-lint in devDependencies) so that a # compromised dev tree cannot suppress this check. run: > npx --yes lockfile-lint@4.14.0 --type npm --path package-lock.json --validate-https --allowed-hosts npm --validate-integrity --validate-package-names --empty-hostname false axios-axios-2d06f96/.github/workflows/moderator.yml000066400000000000000000000015741521272452000224430ustar00rootroot00000000000000name: AI Moderator on: issues: types: [opened] issue_comment: types: [created] pull_request_review_comment: types: [created] jobs: spam-detection: name: AI Moderator runs-on: ubuntu-latest permissions: issues: write pull-requests: write models: read contents: read steps: - name: Checkout repo uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Run AI Moderator uses: github/ai-moderator@81159c370785e295c97461ade67d7c33576e9319 # v1.1.4 with: token: ${{ secrets.GITHUB_TOKEN }} spam-label: 'spam' ai-label: 'ai-generated' minimize-detected-comments: true enable-spam-detection: true enable-link-spam-detection: true enable-ai-detection: true axios-axios-2d06f96/.github/workflows/publish.yml000066400000000000000000000021141521272452000221040ustar00rootroot00000000000000name: Publish package to NPM on: push: tags: - 'v1.*.*' permissions: contents: read id-token: write jobs: publish: runs-on: ubuntu-latest environment: npm-publish steps: - name: Checkout repo uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Setup Node.js uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 26.x registry-url: 'https://registry.npmjs.org' package-manager-cache: false # `npm stage publish` requires npm >= 11.15.0, newer than the npm bundled with # this workflow's Node. Remove this step once Node bundles npm >= 11.15.0 by default. - name: Pin npm with staged-publishing support run: npm install -g npm@11.15.0 - name: Install dependencies run: npm ci --ignore-scripts - name: Build project run: npm run build - name: Publish to NPM run: npm stage publish --provenance --access public axios-axios-2d06f96/.github/workflows/release-branch.yml000066400000000000000000000261171521272452000233220ustar00rootroot00000000000000name: Create release branch on: workflow_dispatch: inputs: type: type: choice description: Choose release type options: - patch - minor - major default: patch beta: type: boolean description: Prerelease default: false permissions: contents: read jobs: build-and-run-vitest: name: Build and run vitest runs-on: ubuntu-latest steps: - name: Checkout repo uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Setup node uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 26.x registry-url: 'https://registry.npmjs.org' package-manager-cache: false - name: Install dependencies run: npm ci --ignore-scripts - name: Build project run: npm run build - name: Install Playwright with deps run: npx playwright install --with-deps - name: Run unit tests run: npm run test:vitest:unit - name: Run browser tests run: npm run test:vitest:browser:headless - name: Pack npm tarball run: npm pack - name: Upload npm pack artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: axios-tarball path: axios-*.tgz if-no-files-found: error retention-days: 1 cjs-smoke-tests: name: CJS smoke tests (Node ${{ matrix.node-version }}) needs: build-and-run-vitest runs-on: ubuntu-latest strategy: fail-fast: false matrix: node-version: [12, 14, 16, 18] steps: - name: Checkout repo uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Setup node uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: ${{ matrix.node-version }} registry-url: 'https://registry.npmjs.org' package-manager-cache: false - name: Download npm pack artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: axios-tarball path: artifacts - name: Install CJS smoke test dependencies working-directory: tests/smoke/cjs run: npm install --ignore-scripts - name: Install packed axios working-directory: tests/smoke/cjs run: npm install --no-save ../../../artifacts/axios-*.tgz - name: Run CJS smoke tests working-directory: tests/smoke/cjs run: npm run test:smoke:cjs:mocha esm-smoke-tests: name: ESM smoke tests (Node ${{ matrix.node-version }}) needs: build-and-run-vitest runs-on: ubuntu-latest strategy: fail-fast: false matrix: node-version: [20, 22, 24, 26] steps: - name: Checkout repo uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Setup node uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: ${{ matrix.node-version }} registry-url: 'https://registry.npmjs.org' package-manager-cache: false - name: Download npm pack artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: axios-tarball path: artifacts - name: Install ESM smoke test dependencies working-directory: tests/smoke/esm run: npm install --ignore-scripts - name: Install packed axios working-directory: tests/smoke/esm run: npm install --no-save ../../../artifacts/axios-*.tgz - name: Run ESM smoke tests working-directory: tests/smoke/esm run: npm run test:smoke:esm:vitest cjs-module-tests: name: CJS module tests (Node ${{ matrix.node-version }}) needs: build-and-run-vitest runs-on: ubuntu-latest strategy: fail-fast: false matrix: node-version: [12, 14, 16, 18] steps: - name: Checkout repo uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Setup node uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: ${{ matrix.node-version }} registry-url: 'https://registry.npmjs.org' package-manager-cache: false - name: Download npm pack artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: axios-tarball path: artifacts - name: Install CJS module test dependencies working-directory: tests/module/cjs run: npm install --ignore-scripts - name: Install packed axios working-directory: tests/module/cjs run: npm install --no-save ../../../artifacts/axios-*.tgz - name: Run CJS module tests working-directory: tests/module/cjs run: npm run test:module:cjs esm-module-tests: name: ESM module tests (Node ${{ matrix.node-version }}) needs: build-and-run-vitest runs-on: ubuntu-latest strategy: fail-fast: false matrix: node-version: [20, 22, 24, 26] steps: - name: Checkout repo uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Setup node uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: ${{ matrix.node-version }} registry-url: 'https://registry.npmjs.org' package-manager-cache: false - name: Download npm pack artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: axios-tarball path: artifacts - name: Install ESM module test dependencies working-directory: tests/module/esm run: npm install --ignore-scripts - name: Install packed axios working-directory: tests/module/esm run: npm install --no-save ../../../artifacts/axios-*.tgz - name: Run ESM module tests working-directory: tests/module/esm run: npm run test:module:esm bun-smoke-tests: name: Bun smoke tests needs: build-and-run-vitest runs-on: ubuntu-latest steps: - name: Checkout repo uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Setup bun uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: no-cache: true - name: Download npm pack artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: axios-tarball path: artifacts - name: Install packed axios env: TMPDIR: ${{ runner.temp }} BUN_INSTALL_CACHE_DIR: ${{ runner.temp }}/bun-cache run: | mkdir -p "$BUN_INSTALL_CACHE_DIR" mv artifacts/axios-*.tgz artifacts/axios.tgz cd tests/smoke/bun bun add file:../../../artifacts/axios.tgz - name: Run Bun smoke tests working-directory: tests/smoke/bun run: bun test deno-smoke-tests: name: Deno smoke tests needs: build-and-run-vitest runs-on: ubuntu-latest steps: - name: Checkout repo uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Setup deno uses: denoland/setup-deno@667a34cdef165d8d2b2e98dde39547c9daac7282 # v2.0.4 with: cache: false - name: Download npm pack artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: axios-tarball path: artifacts - name: Prepare packed axios dist run: mkdir -p dist && tar -xzf artifacts/axios-*.tgz -C artifacts && cp -R artifacts/package/dist/. ./dist - name: Install Deno smoke test dependencies working-directory: tests/smoke/deno run: deno install - name: Run Deno smoke tests working-directory: tests/smoke/deno run: deno task test bump-version-and-create-pr: name: Bump version and create PR needs: [build-and-run-vitest, cjs-smoke-tests, esm-smoke-tests, bun-smoke-tests, deno-smoke-tests] runs-on: ubuntu-latest permissions: contents: write pull-requests: write steps: - name: Checkout repo uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Setup Node.js uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 26.x registry-url: 'https://registry.npmjs.org' package-manager-cache: false - name: Install dependencies run: npm ci --ignore-scripts - name: Configure git identity run: | git config --global user.name "github-actions[bot]" git config --global user.email "github-actions[bot]@users.noreply.github.com" - name: Bump version with NPM version env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} INPUT_TYPE: ${{ github.event.inputs.type }} INPUT_BETA: ${{ github.event.inputs.beta }} id: bump-version run: | TYPE="${INPUT_TYPE}" BETA="${INPUT_BETA}" if [ "$TYPE" = "auto" ]; then npm version $(npm version | grep -Eo 'patch|minor|major' | head -1) else if [ "$BETA" = "true" ]; then npm version $TYPE --preid=beta else npm version $TYPE fi fi VERSION=$(node -p "require('./package.json').version") echo "newTag=$VERSION" >> "$GITHUB_OUTPUT" echo "newBranch=release-v1x/version-$VERSION" >> "$GITHUB_OUTPUT" - name: Run preversion env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: npm run preversion - name: Build project run: npm run build - name: Create Pull Request uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 with: branch: ${{ steps.bump-version.outputs.newBranch }} base: v1.x commit-message: 'chore(release): prepare release ${{ steps.bump-version.outputs.newTag }}' body: 'This PR prepares the release ${{ steps.bump-version.outputs.newTag }}.' title: 'chore(release): prepare release ${{ steps.bump-version.outputs.newTag }}' maintainer-can-modify: true draft: false labels: | type::automated-pr priority::high commit::chore axios-axios-2d06f96/.github/workflows/run-ci.yml000066400000000000000000000210511521272452000216340ustar00rootroot00000000000000name: Continuous integration on: pull_request: types: [opened, synchronize, reopened] permissions: contents: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: build-and-run-vitest: name: Build and run vitest runs-on: ubuntu-latest steps: - name: Checkout repo uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Setup node uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 26.x registry-url: 'https://registry.npmjs.org' package-manager-cache: false - name: Install dependencies run: npm ci --ignore-scripts - name: Lint run: npm run lint - name: Build project run: npm run build - name: Install Playwright with deps run: npx playwright install --with-deps - name: Run unit tests run: npm run test:vitest:unit - name: Run browser tests run: npm run test:vitest:browser:headless - name: Pack npm tarball run: npm pack - name: Dependency Review uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0 - name: Upload npm pack artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: axios-tarball path: axios-*.tgz if-no-files-found: error retention-days: 1 cjs-smoke-tests: name: CJS smoke tests (Node ${{ matrix.node-version }}) needs: build-and-run-vitest runs-on: ubuntu-latest strategy: fail-fast: false matrix: node-version: [12, 14, 16, 18] steps: - name: Checkout repo uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Setup node uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: ${{ matrix.node-version }} registry-url: 'https://registry.npmjs.org' package-manager-cache: false - name: Download npm pack artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: axios-tarball path: artifacts - name: Install CJS smoke test dependencies working-directory: tests/smoke/cjs run: npm install --ignore-scripts - name: Install packed axios working-directory: tests/smoke/cjs run: npm install --no-save ../../../artifacts/axios-*.tgz - name: Run CJS smoke tests working-directory: tests/smoke/cjs run: npm run test:smoke:cjs:mocha esm-smoke-tests: name: ESM smoke tests (Node ${{ matrix.node-version }}) needs: build-and-run-vitest runs-on: ubuntu-latest strategy: fail-fast: false matrix: node-version: [20, 22, 24, 26] steps: - name: Checkout repo uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Setup node uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: ${{ matrix.node-version }} registry-url: 'https://registry.npmjs.org' package-manager-cache: false - name: Download npm pack artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: axios-tarball path: artifacts - name: Install ESM smoke test dependencies working-directory: tests/smoke/esm run: npm install --ignore-scripts - name: Install packed axios working-directory: tests/smoke/esm run: npm install --no-save ../../../artifacts/axios-*.tgz - name: Run ESM smoke tests working-directory: tests/smoke/esm run: npm run test:smoke:esm:vitest cjs-module-tests: name: CJS module tests (Node ${{ matrix.node-version }}) needs: build-and-run-vitest runs-on: ubuntu-latest strategy: fail-fast: false matrix: node-version: [12, 14, 16, 18] steps: - name: Checkout repo uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Setup node uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: ${{ matrix.node-version }} registry-url: 'https://registry.npmjs.org' package-manager-cache: false - name: Download npm pack artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: axios-tarball path: artifacts - name: Install CJS module test dependencies working-directory: tests/module/cjs run: npm install --ignore-scripts - name: Install packed axios working-directory: tests/module/cjs run: npm install --no-save ../../../artifacts/axios-*.tgz - name: Run CJS module tests working-directory: tests/module/cjs run: npm run test:module:cjs esm-module-tests: name: ESM module tests (Node ${{ matrix.node-version }}) needs: build-and-run-vitest runs-on: ubuntu-latest strategy: fail-fast: false matrix: node-version: [20, 22, 24, 26] steps: - name: Checkout repo uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Setup node uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: ${{ matrix.node-version }} registry-url: 'https://registry.npmjs.org' package-manager-cache: false - name: Download npm pack artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: axios-tarball path: artifacts - name: Install ESM module test dependencies working-directory: tests/module/esm run: npm install --ignore-scripts - name: Install packed axios working-directory: tests/module/esm run: npm install --no-save ../../../artifacts/axios-*.tgz - name: Run ESM module tests working-directory: tests/module/esm run: npm run test:module:esm bun-smoke-tests: name: Bun smoke tests needs: build-and-run-vitest runs-on: ubuntu-latest steps: - name: Checkout repo uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Setup bun uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: no-cache: true - name: Download npm pack artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: axios-tarball path: artifacts - name: Install packed axios env: TMPDIR: ${{ runner.temp }} BUN_INSTALL_CACHE_DIR: ${{ runner.temp }}/bun-cache run: | mkdir -p "$BUN_INSTALL_CACHE_DIR" mv artifacts/axios-*.tgz artifacts/axios.tgz cd tests/smoke/bun bun add file:../../../artifacts/axios.tgz - name: Run Bun smoke tests working-directory: tests/smoke/bun run: bun test deno-smoke-tests: name: Deno smoke tests needs: build-and-run-vitest runs-on: ubuntu-latest steps: - name: Checkout repo uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Setup deno uses: denoland/setup-deno@667a34cdef165d8d2b2e98dde39547c9daac7282 # v2.0.4 with: cache: false - name: Download npm pack artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: axios-tarball path: artifacts - name: Prepare packed axios dist run: mkdir -p dist && tar -xzf artifacts/axios-*.tgz -C artifacts && cp -R artifacts/package/dist/. ./dist - name: Install Deno smoke test dependencies working-directory: tests/smoke/deno run: deno install - name: Run Deno smoke tests working-directory: tests/smoke/deno run: deno task test axios-axios-2d06f96/.github/workflows/verify-build-reproducibility.yml000066400000000000000000000050041521272452000262470ustar00rootroot00000000000000name: Verify build reproducibility on: pull_request: paths: - 'lib/**' - 'rollup.config.js' - 'package.json' - 'package-lock.json' - '.github/workflows/verify-build-reproducibility.yml' push: branches: [v1.x] permissions: contents: read jobs: verify-reproducible-build: name: Two-pass build and diff runs-on: ubuntu-latest # Non-blocking until divergence is eliminated. Surfaces regressions in # the build's determinism without gating merges. Remove this line to # promote to a hard gate once the build is byte-identical across runs. continue-on-error: true steps: - name: Checkout repo uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Setup node uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 26.x registry-url: 'https://registry.npmjs.org' package-manager-cache: false - name: Install (pass 1) run: npm ci --ignore-scripts - name: Build (pass 1) run: npm run build - name: Snapshot pass 1 run: | mv dist dist-pass1 find dist-pass1 -type f -exec sha256sum {} + | sort -k2 > pass1.sha256 echo "--- pass 1 hashes ---" cat pass1.sha256 - name: Clean and reinstall (pass 2) run: | rm -rf node_modules npm ci --ignore-scripts - name: Build (pass 2) run: npm run build - name: Snapshot pass 2 and diff run: | find dist -type f -exec sha256sum {} + | sort -k2 | sed 's| dist/| dist-pass1/|' > pass2.sha256 echo "--- pass 2 hashes (path-normalised) ---" cat pass2.sha256 if ! diff -u pass1.sha256 pass2.sha256; then echo "::warning::Build is not reproducible — dist/ differs between passes." echo "This does not fail the job (continue-on-error: true) but is visible in the run summary." echo "See THREATMODEL.md §T-S5 for context." exit 1 fi echo "Build is byte-identical across passes." - name: Upload diff artifact on divergence if: failure() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: reproducibility-diff path: | pass1.sha256 pass2.sha256 dist-pass1 dist retention-days: 7 axios-axios-2d06f96/.github/workflows/zizmor.yml000066400000000000000000000010041521272452000217650ustar00rootroot00000000000000name: GitHub Actions Security Analysis with zizmor on: push: branches: [v1.x] pull_request: branches: ['**'] permissions: {} jobs: zizmor: runs-on: ubuntu-latest permissions: security-events: write steps: - name: Checkout repo uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false - name: Run zizmor uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6 axios-axios-2d06f96/.gitignore000066400000000000000000000003211521272452000163040ustar00rootroot00000000000000*.iml .idea .tscache .DS_Store node_modules/ coverage/ temp/ test/typescript/axios.js* sauce_connect.log test/module/**/package-lock.json backup/ .env dist/ .vscode/ docs/.vitepress/dist docs/.vitepress/cache axios-axios-2d06f96/.husky/000077500000000000000000000000001521272452000155415ustar00rootroot00000000000000axios-axios-2d06f96/.husky/commit-msg000077500000000000000000000000331521272452000175370ustar00rootroot00000000000000npx commitlint --edit "$1" axios-axios-2d06f96/.npmrc000066400000000000000000000000241521272452000154340ustar00rootroot00000000000000ignore-scripts=true axios-axios-2d06f96/.prettierignore000066400000000000000000000003351521272452000173640ustar00rootroot00000000000000# Dependencies node_modules/ # Build output dist/ coverage/ # Lock files package-lock.json **/package-lock.json # Generated / vendored *.min.js test/typescript/axios.js* # Misc *.iml .idea .DS_Store sauce_connect.log axios-axios-2d06f96/.prettierrc000066400000000000000000000001511521272452000165010ustar00rootroot00000000000000{ "semi": true, "singleQuote": true, "tabWidth": 2, "trailingComma": "es5", "printWidth": 100 }axios-axios-2d06f96/AGENTS.md000066400000000000000000000217551521272452000156350ustar00rootroot00000000000000# AGENTS.md axios is a promise-based HTTP client for the browser and Node.js. The default instance is exported from `lib/axios.js` via `index.js`. Browser builds use the XHR or Fetch adapter; Node uses the HTTP/HTTPS adapter. Platform selection lives in `lib/platform/`. This file is the canonical contributor guide for both human and AI agents working in this repo. `.github/copilot-instructions.md` is a thin stub that points back here — keep it in sync with the load-bearing safety rules below if you change them. ## AI Agent Marker - If you are an LLM or AI agent creating a GitHub issue, pull request, or comment for this repo, include the `:surfer:` emoji in the body so maintainers can identify AI-authored contributions. ## Setup And Safety - Use `npm ci`; repo `.npmrc` sets `ignore-scripts=true`, and CI also uses `npm ci --ignore-scripts`. - Do not remove `ignore-scripts=true`; if git hooks are needed after a fresh install, run `npm rebuild husky && npx husky` once. - Adding or updating dependencies is security-sensitive; `package-lock.json` is checked by `lockfile-lint` for npm HTTPS hosts and integrity hashes. - Package, lockfile, and GitHub Actions update PRs are maintainer/bot-only; close these PRs from outside collaborators. Keep the 7-day Dependabot delay unless a critical vulnerability requires a maintainer-led manual update. - Build/test/lint tools still execute dependency code despite `ignore-scripts`; avoid unnecessary full builds when a focused check proves the change. - Do not add new runtime dependencies without discussion; the dependency surface is intentionally tiny. ## Commands - Build published artifacts: `npm run build` (`gulp clear` deletes `dist/`, then Rollup writes browser ESM/UMD/CJS and Node CJS bundles). - Lint source only: `npm run lint`; focused lint: `npx eslint lib/path/to/file.js`. - Unit tests: `npm run test:vitest:unit`; focused unit test: `npm run test:vitest:unit -- tests/unit/path.test.js`. - Browser tests need Playwright installed first (`npx playwright install` locally; CI uses `npx playwright install --with-deps`); run `npm run test:vitest:browser:headless` for CI parity. - Smoke/module compatibility suites test the packed package, not the source tree: run `npm run build`, `npm pack`, install the tarball into the relevant `tests/smoke/*` or `tests/module/*` package, then run that suite's npm script. - CI order is install -> build -> Playwright install -> unit -> browser headless -> pack -> CJS/ESM module and smoke tests -> Bun/Deno smoke tests. ## Package Shape - Source is ESM (`type: module`); public ESM entry is `index.js`, which re-exports the default instance from `lib/axios.js`. - Do not edit `dist/` by hand; it is ignored and generated from `lib/` by Rollup. - Runtime package exports are split by environment: browser/react-native map Node HTTP/platform files to browser/null replacements, while Node CJS ships as `dist/node/axios.cjs`. - Keep public runtime exports, `index.d.ts` (ESM types), and `index.d.cts` (CJS `export = axios` types) in sync for API changes. - `lib/env/data.js` is version-generated by `gulp version`; do not edit it for normal feature work. ## Pre-Release Notes - Add user-visible unreleased changes to `PRE_RELEASE_CHANGELOG.md`, not `CHANGELOG.md`. `CHANGELOG.md` is release-owned and should only be updated as part of preparing an actual release. - Track deferred README, docs site, examples, migration guide, and translated docs updates in `PRE_RELEASE_DOCS.md`. Use enough context for release preparation; do not store brittle diffs or line-number-only notes. - Do not update `README.md` or the docs site for unreleased runtime/API changes unless the task is explicitly release preparation. During feature/fix work, record what docs need to say in `PRE_RELEASE_DOCS.md` so it can be applied during release work. ## Architecture Boundaries - `lib/core/` is axios domain logic: request dispatch, config merge, interceptors, headers, errors. Key classes: `Axios` (request dispatch + interceptor chains), `AxiosError` (standardized error codes), `AxiosHeaders` (case-insensitive header normalization), `InterceptorManager` (sync/async interceptor registration). - `lib/adapters/` performs I/O; default adapter preference is `['xhr', 'http', 'fetch']`, with capability selection in `lib/adapters/adapters.js`. Detect by capability, not environment name. - `lib/platform/` selects Node by default; browser builds rely on package/rollup aliasing to `lib/platform/browser`. - `lib/helpers/` should stay generic and reusable outside axios; do not put axios-specific request lifecycle logic there. - New `lib/**/*.js` files should match existing source style: ESM imports with explicit `.js` extensions, `'use strict';` where current library files use it, and `AxiosError` for axios-originated failures. ## Naming Conventions - Classes: PascalCase (`Axios`, `AxiosError`, `InterceptorManager`). - Functions: camelCase (`buildURL`, `mergeConfig`, `dispatchRequest`). - Error codes: UPPER_SNAKE_CASE constants on `AxiosError` (`ERR_NETWORK`, `ETIMEDOUT`). - Internal class slots: `Symbol`-keyed (e.g. `const $internals = Symbol('internals')` in `lib/core/AxiosHeaders.js`) rather than underscore-prefixed properties. ## Error Handling - Throw `AxiosError` for axios-originated failures; never raw `Error`. Pass `(message, code, config, request, response)` so consumers can introspect. - Wrap third-party errors with `AxiosError.from(error, code, config, request, response)`. - Canonical code list lives in `lib/core/AxiosError.js`; current codes include `ERR_BAD_OPTION_VALUE`, `ERR_BAD_OPTION`, `ECONNABORTED`, `ETIMEDOUT`, `ECONNREFUSED`, `ERR_NETWORK`, `ERR_FR_TOO_MANY_REDIRECTS`, `ERR_DEPRECATED`, `ERR_BAD_RESPONSE`, `ERR_BAD_REQUEST`, `ERR_CANCELED`, `ERR_NOT_SUPPORT`, `ERR_INVALID_URL`, `ERR_FORM_DATA_DEPTH_EXCEEDED`. - Validate config options through the `validator` helper; do not invent ad-hoc validation paths. ## Interceptor Execution Order - Request interceptors run **last-registered-first** (LIFO). - Response interceptors run **first-registered-first** (FIFO). - Both support `synchronous: true` (avoids Promise wrapping when no async handler is in the chain) and `runWhen: (config) => boolean` for conditional execution. - Order matters for both behavior and tests; document it when adding new built-in interceptors. ## Request Lifecycle 1. User calls `axios()` or a method alias. 2. Merge instance defaults with request config via `mergeConfig`. 3. Run request interceptors (LIFO). 4. Select adapter via `lib/adapters/adapters.js` capability check. 5. Apply `transformRequest` functions. 6. Adapter performs the HTTP request. 7. Apply `transformResponse` functions. 8. Run response interceptors (FIFO). 9. Resolve promise with `AxiosResponse` or reject with `AxiosError`. ## Cancellation - Both `CancelToken` (legacy) and `AbortSignal` (modern) are supported simultaneously; do not break either path. - Cancellation must work at any lifecycle stage, including mid-flight body reads. - Always remove signal listeners on settlement or cancellation to prevent memory leaks. ## Common Pitfalls - Do not mutate config objects in-place; return new objects from merges/transforms. - Do not assume browser- or Node-specific globals exist; capability-check first. - Do not use `Function.prototype.bind` directly — use `lib/helpers/bind.js`, which forwards `arguments` via `apply` and is what the rest of the library relies on. - Do not throw raw `Error` from library code; use `AxiosError` with an appropriate code (see Error Handling). ## Tests - Test layout is runtime-first: `tests/unit/**/*.test.js`, `tests/browser/**/*.browser.test.js`, `tests/smoke/esm/**/*.smoke.test.js`, `tests/smoke/cjs/**/*.smoke.test.cjs`. - Use `tests/setup/server.js` for local HTTP servers and cleanup with `try/finally`; leaking servers causes Vitest hangs. - Keep CJS and ESM smoke coverage aligned when behavior is packaging/import related. - Type compatibility is exercised through `tests/module/cjs` with TypeScript 4.9 and `tests/module/esm` with TypeScript 5.x; run the matching module suite for declaration changes. - Browser tests replace globals such as XHR; restore globals and reset spies in cleanup hooks. ## Security-Sensitive Code - For config reads that affect behavior, do not use prototype-walking reads (`in`, destructuring, or direct `config.foo` on untrusted config); guard with own-property checks as in `utils.hasOwnProp` / local `own()` helpers. - New merge or object materialization code must continue filtering `__proto__`, `constructor`, and `prototype`; regressions here are security bugs. - Changes touching URL construction, redirects, proxy/env handling, XSRF, socket paths, decompression limits, or adapters should consult `THREATMODEL.md` and add focused regression tests. - Keep `withXSRFToken` cross-origin behavior explicit: only `true` forces cross-origin XSRF header attachment. - Do not weaken `beforeRedirect`, proxy, or `socketPath` safeguards without tests covering credential leakage or SSRF-style cases. axios-axios-2d06f96/CHANGELOG.md000066400000000000000000004065171521272452000161460ustar00rootroot00000000000000# Changelog ## v1.17.0 — June 1, 2026 This release adds Node HTTP zstd decompression, hardens config and release workflows, and fixes authentication, header, proxy, and type-handling regressions. ## 🔒 Security Fixes * **Config Hardening:** Guarded `socketPath`, `params`, and `paramsSerializer` reads with own-property checks to prevent inherited prototype values from affecting request behavior, including SSRF-sensitive paths. (__#10901__, __#10922__) * **Release Publishing:** Switched the publish workflow to npm staged publishing for safer, auditable package releases with provenance. (__#10926__) ## 🚀 New Features * **HTTP Compression:** Added Node HTTP adapter support for zstd response decompression, with `transitional.advertiseZstdAcceptEncoding` controlling whether `zstd` is advertised in `Accept-Encoding`. (__#6792__, __#10920__) ## 🐛 Bug Fixes * **Authentication Handling:** Restored Basic auth on same-origin Node redirects while continuing to strip credentials cross-origin, and aligned the fetch adapter with HTTP adapter behavior for URL-embedded Basic auth. (__#10929__, __#10896__) * **Proxy TLS:** Preserved user `httpsAgent` TLS options when tunneling HTTPS requests through HTTP CONNECT proxies. (__#10957__) * **React Native FormData:** Cleared default `Content-Type` for React Native `FormData` so multipart boundaries can be generated correctly. (__#10898__) * **Headers:** Silently skipped empty or whitespace-only header names instead of throwing, matching parsed-header behavior and avoiding React Native response crashes. (__#10875__) * **Request Data Merging:** Preserved enumerable symbol keys when cloning plain request data through axios merge logic. (__#10812__) * **Bundler Compatibility:** Converted `resolveConfig` from an arrow default export to a named function export to avoid webpack and Babel transform interop failures. (__#10891__) * **Types:** Corrected `AxiosHeaders.toJSON()` return types and updated CommonJS `isCancel` typings to narrow to `CanceledError`. (__#10956__, __#10952__) * **Build Tooling:** Avoided emitting a null `Authorization` header from the GitHub build helper when `GITHUB_TOKEN` is unset. (__#10931__) ## 🔧 Maintenance & Chores * **HTTP/2 Internals:** Extracted `Http2Sessions` into its own helper module and added direct unit coverage for session pooling, timeout, and cleanup behavior. (__#10861__) * **Package Publishing:** Reduced published package size by switching to a `files` allowlist and dropping unneeded unminified bundle source maps. (__#10939__) * **CI and Release Automation:** Added bundle-size reporting, moved reports to the job summary, fixed bundle-size comparison coverage, added Node 26 to the matrix, pinned npm for staged publishing, and prepared the 1.17.0 release. (__#10907__, __#10911__, __#10916__, __#10927__, __#10935__, __#10983__) * **Developer Workflow:** Added a dev container and iterated on OpenSpec workflow files before removing them from the release branch. (__#10925__, __#10914__, __#10958__) * **Documentation and Policy:** Updated disclosure, contributor, collaboration, threat-model, advanced docs, README badges, release notes, moderator configuration, and project metadata. (__#10890__, __#10889__, __#10921__, __#10945__, __#10905__, __#10933__, __#10915__, __#10887__, __#10955__) * **Dependencies:** Bumped Babel tooling, Commitlint, ESLint, Rollup, Globals, Vitest, Playwright, `fs-extra`, `qs`, docs dependencies, and GitHub Actions dependencies including `actions/dependency-review-action` and `zizmorcore/zizmor-action`. (__#10871__, __#10879__, __#10918__, __#10919__, __#10934__, __#10947__, __#10954__, __#10960__) ## 🌟 New Contributors We are thrilled to welcome our new contributors. Thank you for helping improve axios: * __@BasixKOR__ (__#6792__) * __@carladams1299-lab__ (__#10861__) * __@LaplaceYoung__ (__#10812__) * __@JamieMagee__ (__#10939__) * __@RonGamzu__ (__#10905__) * __@sapirbaruch__ (__#10891__) * __@nezukoagent__ (__#10901__) * __@devareddy05__ (__#10929__) * __@Mohammad-Faiz-Cloud-Engineer__ (__#10922__) * __@azandabot__ (__#10931__) * __@niksy__ (__#10896__) [Full Changelog](https://github.com/axios/axios/compare/v1.16.1...v1.17.0) ## v1.16.1 — May 13, 2026 This release ships a defence-in-depth fix for prototype pollution in `formDataToJSON`, hardens proxy and CI workflows, restores Webpack 4 compatibility for the fetch adapter, and includes several small bug fixes and maintenance improvements. ## 🔒 Security Fixes * **Prototype Pollution Defence-in-Depth:** Hardened `formDataToJSON` against already-polluted `Object.prototype` by walking own properties only, so attacker-controlled keys inherited from a poisoned prototype cannot propagate through deserialization. (__#7413__) * **Proxy Cleartext Leak:** Fixed an issue where HTTPS request data could be transmitted in cleartext to an HTTP proxy under certain configurations. (__#10858__) * **CI Cache Removal:** Removed all GitHub Actions caches as a defence-in-depth measure against cache poisoning vectors in the build pipeline. (__#10882__) ## 🐛 Bug Fixes * **Data URI Parsing:** Updated the `fromDataURI` regex to match RFC 2397 more strictly, fixing edge cases in `data:` URL handling. (__#10829__) * **Unicode Headers:** Preserved Unicode header values when running through request interceptors, so non-ASCII header content is no longer corrupted before dispatch. (__#10850__) * **XHR Upload Progress:** Guarded against malformed `ProgressEvent` payloads emitted by some environments during XHR upload, preventing crashes when `loaded` / `total` are missing or invalid. (__#10868__) * **Webpack 4 Fetch Adapter:** Fixed an "unexpected token" error caused by syntax in the fetch adapter that Webpack 4 could not parse, restoring compatibility for legacy bundler users. (__#10864__) * **Type Definitions:** Made `parseReviver` `context.source` optional in the type definitions to align with the ES2023 specification. (__#10837__) * **URL Object Support Reverted:** Reverted the change that allowed passing a `URL` object as `config.url` (originally __#10866__) due to regressions; this support will be reintroduced in a later release once the underlying issues are addressed. (__#10874__) ## 🔧 Maintenance & Chores * **Cycle Detection Refactor:** Replaced the array-based cycle tracker in `toJSONObject` with a `WeakSet`, improving performance and memory behaviour on large nested structures. (__#10832__) * **composeSignals Cleanup:** Refactored `composeSignals` to use a clearer early-return structure, simplifying the cancellation/abort composition path. (__#10844__) * **AI Readiness & Repo Docs:** Added `AGENTS.md` and related contributor-guide updates for both human and AI agents, plus post-release documentation improvements. (__#10835__, __#10841__) * **Docs Improvements:** Clarified the GET request example, fixed the interceptor `eject` example to reference the correct instance, and corrected the Buzzoid sponsor description in the README. (__#10836__, __#10853__, __#10856__) * **Sponsorship Tooling:** Fixed empty sponsor arrays in the sponsor processing script, added the ability to inject additional sponsors, updated the sponsorship link, and added a Twicsy advertisement entry. (__#10843__, __#10859__, __#10869__) * **Dependencies:** Bumped `@commitlint/cli` from 20.5.0 to 20.5.2. (__#10846__) ## 🌟 New Contributors We are thrilled to welcome our new contributors. Thank you for helping improve axios: * __@hpinmetaverse__ (__#10836__) * __@tommyhgunz14__ (__#7413__) * __@abhu85__ (__#10829__) * __@divyanshuraj1095__ (__#10853__) * __@sagodi97__ (__#10856__) * __@rkdfx__ (__#10868__) * __@Liuwei1125__ (__#10866__) [Full Changelog](https://github.com/axios/axios/compare/v1.16.0...v1.16.1) ## v1.16.0 — May 2, 2026 This release adds support for the QUERY HTTP method and a new `ECONNREFUSED` error constant, lands a substantial wave of HTTP, fetch, and XHR adapter bug fixes around redirects, aborts, headers, and timeouts, and welcomes 23 new contributors. ## ⚠️ Notable Changes A handful of fixes in this release are either security-adjacent or change observable behaviour. Please review before upgrading: - **Fetch adapter now enforces `maxBodyLength` and `maxContentLength`.** These limits were silently ignored on the fetch adapter prior to 1.16.0 — anyone relying on them as a safety net (DoS protection, accidental large uploads) had no protection. (**#10795**) - **Proxy requests now preserve user-supplied `Host` headers.** Previously, the proxy path could overwrite a custom `Host`. Virtual-host-style routing through a proxy will now behave correctly. (**#10822**) - **Basic auth credentials embedded in URLs are now URL-decoded.** If you have percent-encoded credentials in a URL (e.g. `https://user:p%40ss@host`), the decoded value is what now goes on the wire. (**#10825**) - **`parseProtocol` now strictly requires a colon in the protocol separator.** Strings that loosely parsed as protocols before may no longer match. (**#10729**) - **Deprecated `unescape()` replaced with modern UTF-8 encoding.** Non-ASCII URL handling is now spec-correct; consumers depending on legacy `unescape()` quirks may see different output bytes. (**#7378**) - **`transformRequest` input typing change was reverted.** The typing change introduced in #10745 was reverted in #10810 after follow-up review — net behavior is unchanged from 1.15.2. (**#10745**, **#10810**) ## 🚀 New Features - **QUERY HTTP Method:** Added support for the QUERY HTTP method across adapters and type definitions. (**#10802**) - **ECONNREFUSED Error Constant:** Exposed `ECONNREFUSED` as a constant on `AxiosError` so callers can match connection-refused failures without comparing string literals (closes #6485). (**#10680**) - **Encode Helper Export:** Exported the internal `encode` helper from `buildURL` so userland param serializers can reuse the same encoding logic that axios uses internally. (**#6897**) ## 🐛 Bug Fixes - **HTTP Adapter — Redirects & Headers:** Cleared stale headers when a redirect targets a no-proxy host, fixed the redirect listener chain so listeners no longer stack across hops, restored the missing `requestDetails` argument on `beforeRedirect`, preserved user-supplied `Host` headers when forwarding through a proxy, and properly URL-decoded basic auth credentials. (**#10794**, **#10800**, **#6241**, **#10822**, **#10825**) - **HTTP Adapter — Streams & Timeouts:** Preserved the partial response object on `AxiosError` when a stream is aborted after headers arrive, honoured the `timeout` option during the connect phase when redirects are disabled, and resolved an unsettled-promise hang when an aborted request was combined with compression and `maxRedirects: 0`. (**#10708**, **#10819**, **#7149**) - **Fetch Adapter:** Enforced `maxBodyLength` / `maxContentLength` in the fetch adapter, set the `User-Agent` header to match the HTTP adapter, preserved the original abort reason instead of replacing it with a generic error, and deferred global access so importing the module no longer throws a `TypeError` in restricted environments. (**#10795**, **#10772**, **#10806**, **#7260**) - **XHR Adapter:** Unsubscribed the `cancelToken` and `AbortSignal` listeners on the error, timeout, and abort code paths to prevent leaked subscriptions. (**#10787**) - **Error Handling:** Attached the parsed response to `AxiosError` when `JSON.parse` fails inside `dispatchRequest`, prevented `settle` from emitting `undefined` error codes, and tightened the `parseProtocol` regex to require a colon in the protocol separator. (**#10724**, **#7276**, **#10729**) - **Types & Exports:** Aligned the CommonJS `CancelToken` typings with the ESM build, fixed a compiler error caused by `RawAxiosHeaders`, and re-exported `create` from the package index. (**#7414**, **#6389**, **#6460**) - **UTF-8 Encoding:** Replaced the deprecated `unescape()` call with a modern UTF-8 encoding implementation. (**#7378**) - **Misc Cleanup:** Resolved a batch of small inconsistencies and gadget-level issues across the codebase. (**#10833**) ## 🔧 Maintenance & Chores - **Refactor — ES6 Modernisation:** Modernised the `utils` module and XHR adapter to use ES6 features, and tidied the multipart boundary error message. (**#10588**, **#7419**) - **Tests:** Hardened the HTTP test server lifecycle to fix flaky `FormData` EPIPE failures, fixed Win32 platform support for the pipe tests, and corrected an incorrect test assumption. (**#10820**, **#10791**, **#10796**) - **Docs:** Documented `paramsSerializer.encode` for strict RFC 3986 query encoding, updated the `parseReviver` TypeScript definitions and configuration docs for ES2023, added timeout guidance to the README's first async example, and expanded notes around the recent type changes. (**#10821**, **#10782**, **#10759**, **#10804**) - **Reverted:** Reverted the `transformRequest` input typing change from #10745 after follow-up review. (**#10745**, **#10810**) - **Dependencies:** Bumped `actions/setup-node`, the `github-actions` group, and `postcss` (in `/docs`) to their latest versions. (**#10785**, **#10813**, **#10814**) - **Release:** Updated changelog and packages, and prepared the 1.16.0 release. (**#10790**, **#10834**) ## 🌟 New Contributors We are thrilled to welcome our new contributors. Thank you for helping improve axios: - **@singhankit001** (**#10588**) - **@cuiweixie** (**#7419**) - **@iruizsalinas** (**#10787**) - **@MarcosNocetti** (**#10680**) - **@deepview-autofix** (**#10729**) - **@atharvasingh7007** (**#10745**) - **@OfekDanny** (**#10772**) - **@mnahkies** (**#7414**) - **@tboyila** (**#10759**) - **@Kingo64** (**#6897**) - **@ramram1048** (**#6389**) - **@FLNacif** (**#6460**) - **@zozo123** (**#10806**) - **@pierluigilenoci** (**#10802**) - **@afurm** (**#10708**) - **@karan-lrn** (**#7378**) - **@ebeigarts** (**#7149**) - **@Raymondo97** (**#10782**) - **@mixelburg** (**#10821**) - **@ashishkr96** (**#10822**) - **@cyphercodes** (**#10819**) - **@Jye10032** (**#7260**) - **@VeerShah41** (**#7276**) [Full Changelog](https://github.com/axios/axios/compare/v1.15.2...v1.16.0) ## v1.15.2 - April 21, 2026 This release delivers prototype-pollution hardening for the Node HTTP adapter, adds an opt-in `allowedSocketPaths` allowlist to mitigate SSRF via Unix domain sockets, fixes a keep-alive socket memory leak, and ships supply-chain hardening across CI and security docs. ## 🔒 Security Fixes - **Prototype Pollution Hardening (HTTP Adapter):** Hardened the Node HTTP adapter and `resolveConfig`/`mergeConfig`/validator paths to read only own properties and use null-prototype config objects, preventing polluted `auth`, `baseURL`, `socketPath`, `beforeRedirect`, and `insecureHTTPParser` from influencing requests. (**#10779**) - **SSRF via `socketPath`:** Rejects non-string `socketPath` values and adds an opt-in `allowedSocketPaths` config option to restrict permitted Unix domain socket paths, returning `AxiosError` `ERR_BAD_OPTION_VALUE` on mismatch. (**#10777**) - **Supply-chain Hardening:** Added `.npmrc` with `ignore-scripts=true`, lockfile lint CI, non-blocking reproducible build diff, scoped CODEOWNERS, expanded `SECURITY.md`/`THREATMODEL.md` with provenance verification (`npm audit signatures`), 60-day resolution policy, and maintainer incident-response runbook. (**#10776**) ## 🚀 New Features - **`allowedSocketPaths` Config Option:** New request config option (and TypeScript types) to allowlist Unix domain socket paths used by the Node http adapter; backwards compatible when unset. (**#10777**) ## 🐛 Bug Fixes - **Keep-alive Socket Memory Leak:** Installs a single per-socket `error` listener tracking the active request via `kAxiosSocketListener`/`kAxiosCurrentReq`, eliminating per-request listener accumulation, `MaxListenersExceededWarning`, and linear heap growth under concurrent or long-running keep-alive workloads (fixes #10780). (**#10788**) ## 🔧 Maintenance & Chores - **Changelog:** Updated `CHANGELOG.md` with v1.15.1 release notes. (**#10781**) [Full Changelog](https://github.com/axios/axios/compare/v1.15.1...v1.15.2) --- ## v1.15.1 - April 19, 2026 This release ships a coordinated set of security hardening fixes across headers, body/redirect limits, multipart handling, and XSRF/prototype-pollution vectors, alongside a broad sweep of bug fixes, test migrations, and threat-model documentation updates. ## 🔒 Security Fixes - **Header Injection Hardening:** Tightened validation and sanitisation across request header construction to close the header-injection attack surface. (**#10749**) - **CRLF Stripping in Multipart Headers:** Correctly strips CR/LF from multipart header values to prevent injection via field names and filenames. (**#10758**) - **Prototype Pollution / Auth Bypass:** Replaced unsafe `in` checks with `hasOwnProperty` to prevent authentication bypass via prototype pollution on config objects, with additional regression tests. (**#10761**, **#10760**) - **`withXSRFToken` Truthy Bypass:** Short-circuits on any truthy non-boolean value, so an ambiguous config no longer silently leaks the XSRF token cross-origin. (**#10762**) - **`maxBodyLength` With Zero Redirects:** Enforces `maxBodyLength` even when `maxRedirects` is set to `0`, closing a bypass path for oversized request bodies. (**#10753**) - **Streamed Response `maxContentLength` Bypass:** Applies `maxContentLength` to streamed responses that previously bypassed the cap. (**#10754**) - **Follow-up CVE Completion:** Completes an earlier incomplete CVE fix to fully close the regression window. (**#10755**) ## 🚀 New Features - **AI-Based Docs Translations:** Initial scaffold for AI-assisted translations of the documentation site. (**#10705**) - **`Location` Request Header Type:** Adds `Location` to `CommonRequestHeadersList` for accurate typing of redirect-aware requests. (**#7528**) ## 🐛 Bug Fixes - **FormData Handling:** Removes `Content-Type` when no boundary is present on `FormData` fetch requests, supports multi-select fields, cancels `request.body` instead of the source stream on fetch abort, and fixes a recursion bug in form-data serialisation. (**#7314**, **#10676**, **#10702**, **#10726**) - **HTTP Adapter:** Handles socket-only request errors without leaking keep-alive listeners. (**#10576**) - **Progress Events:** Clamps `loaded` to `total` for computable upload/download progress events. (**#7458**) - **Types:** Aligns `runWhen` type with the runtime behaviour in `InterceptorManager` and makes response header keys case-insensitive. (**#7529**, **#10677**) - **`buildFullPath`:** Uses strict equality in the base/relative URL check. (**#7252**) - **`AxiosURLSearchParams` Regex:** Improves the regex used for param serialisation to avoid edge-case mismatches. (**#10736**) - **Resilient Value Parsing:** Parses out header/config values instead of throwing on malformed input. (**#10687**) - **Docs Artefact Cleanup:** Removes the docs content that was incorrectly committed. (**#10727**) ## 🔧 Maintenance & Chores - **Threat Model & Security Docs:** Ongoing refinement of `THREATMODEL.md`, including Hopper security update, TLS and tag-replay wording, mitigation descriptions, decompression-bomb guidance, and further cleanup. (**#10672**, **#10715**, **#10718**, **#10722**, **#10763**, **#10765**) - **Test Coverage & Migration:** Expanded `shouldBypassProxy` coverage for wildcard/IPv6/edge cases, documented and tested `AxiosError.status`, and migrated `progressEventReducer` tests to Vitest. (**#10723**, **#10725**, **#10741**) - **Type Refactor:** Uses TypeScript utility types to deduplicate literal unions. (**#7520**) - **Repo & CI:** Adds `CODEOWNERS`, switches v1.x releases to an ephemeral release branch, and removes orphaned Bower support. (**#10739**, **#10738**, **#10746**) ## 🌟 New Contributors We are thrilled to welcome our new contributors. Thank you for helping improve axios: - **@curiouscoder-cmd** (**#7252**) - **@tryonelove** (**#7520**) - **@darwin808** (**#7314**) - **@zoontek** (**#10702**) - **@AKIB473** (**#10725**) [Full Changelog](https://github.com/axios/axios/compare/v1.15.0...v1.15.1) --- ## v1.15.0 - April 7, 2026 This release delivers two critical security patches targeting header injection and SSRF via proxy bypass, adds official runtime support for Deno and Bun, and includes significant CI security hardening. ## 🔒 Security Fixes - **Header Injection (CRLF):** Rejects any header value containing `\r` or `\n` characters to block CRLF injection chains that could be used to exfiltrate cloud metadata (IMDS). Behavior change: headers with CR/LF now throw `"Invalid character in header content"`. (**#10660**) - **SSRF via `no_proxy` Bypass:** Introduces a `shouldBypassProxy` helper that normalises hostnames (strips trailing dots, handles bracketed IPv6) before evaluating `no_proxy`/`NO_PROXY` rules, closing a gap that could cause loopback or internal hosts to be inadvertently proxied. (**#10661**) ## 🚀 New Features - **Deno & Bun Runtime Support:** Added full smoke test suites for Deno and Bun, with CI workflows that run both runtimes before any release is cut. (**#10652**) ## 🐛 Bug Fixes - **Node.js v22 Compatibility:** Replaced deprecated `url.parse()` calls with the WHATWG `URL`/`URLSearchParams` API across examples, sandbox, and tests, eliminating `DEP0169` deprecation warnings on Node.js v22+. (**#10625**) ## 🔧 Maintenance & Chores - **CI Security Hardening:** Added [zizmor](https://github.com/zizmorcore/zizmor) GitHub Actions security scanner; switched npm publish to OIDC Trusted Publishing (removing the long-lived `NODE_AUTH_TOKEN`); pinned all action references to full commit SHAs; narrowed workflow permissions to least privilege; gated the publish step behind a dedicated `npm-publish` environment; and blocked the sponsor-block workflow from running on forks. (**#10618**, **#10619**, **#10627**, **#10637**, **#10641**, **#10666**) - **Docs:** Clarified HTTP/2 support and the unsupported `httpVersion` option; added documentation for header case preservation; improved the `beforeRedirect` example to prevent accidental credential leakage. (**#10644**, **#10654**, **#10624**) - **Dependencies:** Bumped `picomatch`, `handlebars`, `serialize-javascript`, `vite` (×3), `denoland/setup-deno`, and 4 additional dev dependencies to latest versions. (**#10564**, **#10565**, **#10567**, **#10568**, **#10572**, **#10574**, **#10663**, **#10664**, **#10665**, **#10669**, **#10670**) ## 🌟 New Contributors We are thrilled to welcome our new contributors. Thank you for helping improve axios: - **@Kilros0817** (**#10625**) - **@shaanmajid** (**#10616**, **#10617**, **#10618**, **#10619**, **#10637**, **#10641**, **#10666**) - **@ashstrc** (**#10624**, **#10644**) - **@Abhi3975** (**#10589**) - **@raashish1601** (**#10573**) [Full Changelog](https://github.com/axios/axios/compare/v1.14.0...v1.15.0) --- ## v1.14.0 - March 27, 2026 This release fixes a security vulnerability in the `formidable` dependency, resolves a CommonJS compatibility regression, hardens proxy and HTTP/2 handling, and modernises the build and test toolchain. ## 🔒 Security Fixes - **Formidable Vulnerability:** Upgraded `formidable` from v2 to v3 to address a reported arbitrary-file vulnerability. Updated test server and assertions to align with the v3 API. (**#7533**) ## 🐛 Bug Fixes - **CommonJS Compatibility:** Restored `require('axios')` in Node.js by correcting the `main` field in `package.json` to point to the built CJS bundle. (**#7532**) - **Fetch Adapter:** Cancel the `ReadableStream` body after the request stream capability probe to prevent resource leaks. (**#7515**) - **Proxy:** Upgraded `proxy-from-env` to v2 and switched to the named `getProxyForUrl` export, fixing proxy detection from environment variables and resolving CJS bundling errors. (**#7499**) - **HTTP/2:** Close detached HTTP/2 sessions on timeout to free resources when no new requests arrive. (**#7457**) - **Headers:** Trim trailing CRLF characters from normalised header values. (**#7456**) ## 🔧 Maintenance & Chores - **Toolchain Modernisation:** Migrated test suite to Vitest, updated ESLint to v10, upgraded Rollup and `@rollup/plugin-babel`, migrated to Husky 9, upgraded TypeScript to latest, and modernised the Express test harness. (**#7484**, **#7489**, **#7498**, **#7505**, **#7506**, **#7507**, **#7508**, **#7509**, **#7510**, **#7516**, **#7522**) - **Dependencies:** Bumped `multer` to v2, `minimatch`, `tar`, `pacote`, `@babel/preset-env`, and additional dev dependencies. (**#7453**, **#7480**, **#7491**, **#7504**, **#7517**, **#7531**) ## 🌟 New Contributors We are thrilled to welcome our new contributors. Thank you for helping improve axios: - **@penkzhou** (**#7515**) - **@aviu16** (**#7456**) - **@fedotov** (**#7457**) [Full Changelog](https://github.com/axios/axios/compare/v1.13.6...v1.14.0) --- ## v1.13.6 - February 27, 2026 This release adds React Native Blob support, fixes several enumeration and export regressions, and patches FormData detection for WeChat Mini Program environments. ## 🚀 New Features - **React Native Blob Support:** Axios now correctly handles native Blob objects in React Native environments. (**#5764**) ## 🐛 Bug Fixes - **AxiosError:** Fixed `AxiosError.from` not copying the `status` field from the source error. (**#7403**) - **AxiosError:** Made the `message` property enumerable so it appears in `JSON.stringify` output and `Object.keys`. (**#7392**) - **FormData Detection:** Corrected safe FormData detection for WeChat Mini Program environments. (**#7324**) - **React Native / Browserify Export:** Fixed broken module export that caused import failures in React Native and Browserify. (**#7386**) ## 🔧 Maintenance & Chores - **Dependencies:** Migrated `@rollup/plugin-babel` from v5 to v6 and bumped the development dependencies group. (**#7424**, **#7432**) ## 🌟 New Contributors We are thrilled to welcome our new contributors. Thank you for helping improve axios: - **@moh3n9595** (**#5764**) - **@skrtheboss** (**#7403**) - **@ybbus** (**#7392**) - **@Shiwaangee** (**#7324**) - **@Gudahtt** (**#7386**) [Full Changelog](https://github.com/axios/axios/compare/v1.13.5...v1.13.6) --- ## v1.13.5 - February 8, 2026 This release patches a prototype pollution denial-of-service vulnerability, fixes a missing `status` field regression in `AxiosError`, adds interceptor ordering control, and introduces URL validation for `isAbsoluteURL`. ## 🔒 Security Fixes - **Prototype Pollution (DoS):** Hardened `mergeConfig` to ignore `__proto__`, `constructor`, and `prototype` keys, preventing denial-of-service via prototype pollution when merging user-supplied config. (**#7369**) ## 🚀 New Features - **`isAbsoluteURL` Validation:** Added input validation to `isAbsoluteURL` to handle malformed or unexpected input gracefully. (**#7326**) ## 🐛 Bug Fixes - **AxiosError `status`:** Restored the `status` field on `AxiosError` instances, which was missing in v1.13.3 and later. (**#7368**) - **Interceptor Ordering:** Added a `useLegacyInterceptorOrder` option to restore pre-v1.13 interceptor execution order for applications relying on the previous behaviour. ([569f028](https://github.com/axios/axios/commit/569f028a5878faaec8d7d138ba686aac407bda4c)) ## 🔧 Maintenance & Chores - **CI:** Fixed run conditions and updated workflow YAMLs. (**#7372**, **#7373**) - **Dependencies:** Bumped `karma-sourcemap-loader` and minor package versions. (**#7356**, **#7360**) ## 🌟 New Contributors We are thrilled to welcome our new contributors. Thank you for helping improve axios: - **@asmitha-16** (**#7326**) [Full Changelog](https://github.com/axios/axios/compare/v1.13.4...v1.13.5) --- ## v1.13.4 - January 27, 2026 Patch release fixing regressions introduced in v1.13.3, including TypeScript export compatibility and CI/build stability. ## 🐛 Bug Fixes - **v1.13.3 Regressions:** Fixed multiple issues introduced by the v1.13.3 release, including broken merge configs. (**#7352**) - **TypeScript Exports:** Corrected TypeScript export declarations to restore proper type resolution. (**#4884**) ## 🔧 Maintenance & Chores - **CI & Build:** Refactored CI pipeline and build configuration for stability. (**#7340**) [Full Changelog](https://github.com/axios/axios/compare/v1.13.3...v1.13.4) --- ## [1.13.3](https://github.com/axios/axios/compare/v1.13.2...v1.13.3) (2026-01-20) ### Bug Fixes - **http2:** Use port 443 for HTTPS connections by default. ([#7256](https://github.com/axios/axios/issues/7256)) ([d7e6065](https://github.com/axios/axios/commit/d7e60653460480ffacecf85383012ca1baa6263e)) - **interceptor:** handle the error in the same interceptor ([#6269](https://github.com/axios/axios/issues/6269)) ([5945e40](https://github.com/axios/axios/commit/5945e40bb171d4ac4fc195df276cf952244f0f89)) - main field in package.json should correspond to cjs artifacts ([#5756](https://github.com/axios/axios/issues/5756)) ([7373fbf](https://github.com/axios/axios/commit/7373fbff24cd92ce650d99ff6f7fe08c2e2a0a04)) - **package.json:** add 'bun' package.json 'exports' condition. Load the Node.js build in Bun instead of the browser build ([#5754](https://github.com/axios/axios/issues/5754)) ([b89217e](https://github.com/axios/axios/commit/b89217e3e91de17a3d55e2b8f39ceb0e9d8aeda8)) - silentJSONParsing=false should throw on invalid JSON ([#7253](https://github.com/axios/axios/issues/7253)) ([#7257](https://github.com/axios/axios/issues/7257)) ([7d19335](https://github.com/axios/axios/commit/7d19335e43d6754a1a9a66e424f7f7da259895bf)) - turn AxiosError into a native error ([#5394](https://github.com/axios/axios/issues/5394)) ([#5558](https://github.com/axios/axios/issues/5558)) ([1c6a86d](https://github.com/axios/axios/commit/1c6a86dd2c0623ee1af043a8491dbc96d40e883b)) - **types:** add handlers to AxiosInterceptorManager interface ([#5551](https://github.com/axios/axios/issues/5551)) ([8d1271b](https://github.com/axios/axios/commit/8d1271b49fc226ed7defd07cd577bd69a55bb13a)) - **types:** restore AxiosError.cause type from unknown to Error ([#7327](https://github.com/axios/axios/issues/7327)) ([d8233d9](https://github.com/axios/axios/commit/d8233d9e8e9a64bfba9bbe01d475ba417510b82b)) - unclear error message is thrown when specifying an empty proxy authorization ([#6314](https://github.com/axios/axios/issues/6314)) ([6ef867e](https://github.com/axios/axios/commit/6ef867e684adf7fb2343e3b29a79078a3c76dc29)) ### Features - add `undefined` as a value in AxiosRequestConfig ([#5560](https://github.com/axios/axios/issues/5560)) ([095033c](https://github.com/axios/axios/commit/095033c626895ecdcda2288050b63dcf948db3bd)) - add automatic minor and patch upgrades to dependabot ([#6053](https://github.com/axios/axios/issues/6053)) ([65a7584](https://github.com/axios/axios/commit/65a7584eda6164980ddb8cf5372f0afa2a04c1ed)) - add Node.js coverage script using c8 (closes [#7289](https://github.com/axios/axios/issues/7289)) ([#7294](https://github.com/axios/axios/issues/7294)) ([ec9d94e](https://github.com/axios/axios/commit/ec9d94e9f88da13e9219acadf65061fb38ce080a)) - added copilot instructions ([3f83143](https://github.com/axios/axios/commit/3f83143bfe617eec17f9d7dcf8bafafeeae74c26)) - compatibility with frozen prototypes ([#6265](https://github.com/axios/axios/issues/6265)) ([860e033](https://github.com/axios/axios/commit/860e03396a536e9b926dacb6570732489c9d7012)) - enhance pipeFileToResponse with error handling ([#7169](https://github.com/axios/axios/issues/7169)) ([88d7884](https://github.com/axios/axios/commit/88d78842541610692a04282233933d078a8a2552)) - **types:** Intellisense for string literals in a widened union ([#6134](https://github.com/axios/axios/issues/6134)) ([f73474d](https://github.com/axios/axios/commit/f73474d02c5aa957b2daeecee65508557fd3c6e5)), closes [/github.com/microsoft/TypeScript/issues/33471#issuecomment-1376364329](https://github.com//github.com/microsoft/TypeScript/issues/33471/issues/issuecomment-1376364329) ### Reverts - Revert "fix: silentJSONParsing=false should throw on invalid JSON (#7253) (#7…" (#7298) ([a4230f5](https://github.com/axios/axios/commit/a4230f5581b3f58b6ff531b6dbac377a4fd7942a)), closes [#7253](https://github.com/axios/axios/issues/7253) [#7](https://github.com/axios/axios/issues/7) [#7298](https://github.com/axios/axios/issues/7298) - **deps:** bump peter-evans/create-pull-request from 7 to 8 in the github-actions group ([#7334](https://github.com/axios/axios/issues/7334)) ([2d6ad5e](https://github.com/axios/axios/commit/2d6ad5e48bd29b0b2b5e7e95fb473df98301543a)) ### Contributors to this release - avatar [Ashvin Tiwari](https://github.com/ashvin2005 '+1752/-4 (#7218 #7218 )') - avatar [Nikunj Mochi](https://github.com/mochinikunj '+940/-12 (#7294 #7294 )') - avatar [Anchal Singh](https://github.com/imanchalsingh '+544/-102 (#7169 #7185 )') - avatar [jasonsaayman](https://github.com/jasonsaayman '+317/-73 (#7334 #7298 )') - avatar [Julian Dax](https://github.com/brodo '+99/-120 (#5558 )') - avatar [Akash Dhar Dubey](https://github.com/AKASHDHARDUBEY '+167/-0 (#7287 #7288 )') - avatar [Madhumita](https://github.com/madhumitaaa '+20/-68 (#7198 )') - avatar [Tackoil](https://github.com/Tackoil '+80/-2 (#6269 )') - avatar [Justin Dhillon](https://github.com/justindhillon '+41/-41 (#6324 #6315 )') - avatar [Rudransh](https://github.com/Rudrxxx '+71/-2 (#7257 )') - avatar [WuMingDao](https://github.com/WuMingDao '+36/-36 (#7215 )') - avatar [codenomnom](https://github.com/codenomnom '+70/-0 (#7201 #7201 )') - avatar [Nandan Acharya](https://github.com/Nandann018-ux '+60/-10 (#7272 )') - avatar [Eric Dubé](https://github.com/KernelDeimos '+22/-40 (#7042 )') - avatar [Tibor Pilz](https://github.com/tiborpilz '+40/-4 (#5551 )') - avatar [Gabriel Quaresma](https://github.com/joaoGabriel55 '+31/-4 (#6314 )') - avatar [Turadg Aleahmad](https://github.com/turadg '+23/-6 (#6265 )') - avatar [JohnTitor](https://github.com/kiritosan '+14/-14 (#6155 )') - avatar [rohit miryala](https://github.com/rohitmiryala '+22/-0 (#7250 )') - avatar [Wilson Mun](https://github.com/wmundev '+20/-0 (#6053 )') - avatar [techcodie](https://github.com/techcodie '+7/-7 (#7236 )') - avatar [Ved Vadnere](https://github.com/Archis009 '+5/-6 (#7283 )') - avatar [svihpinc](https://github.com/svihpinc '+5/-3 (#6134 )') - avatar [SANDESH LENDVE](https://github.com/mrsandy1965 '+3/-3 (#7246 )') - avatar [Lubos](https://github.com/mrlubos '+5/-1 (#7312 )') - avatar [Jarred Sumner](https://github.com/Jarred-Sumner '+5/-1 (#5754 )') - avatar [Adam Hines](https://github.com/thebanjomatic '+2/-1 (#5756 )') - avatar [Subhan Kumar Rai](https://github.com/Subhan030 '+2/-1 (#7256 )') - avatar [Joseph Frazier](https://github.com/josephfrazier '+1/-1 (#7311 )') - avatar [KT0803](https://github.com/KT0803 '+0/-2 (#7229 )') - avatar [Albie](https://github.com/AlbertoSadoc '+1/-1 (#5560 )') - avatar [Jake Hayes](https://github.com/thejayhaykid '+1/-0 (#5999 )') ## [1.13.2](https://github.com/axios/axios/compare/v1.13.1...v1.13.2) (2025-11-04) ### Bug Fixes - **http:** fix 'socket hang up' bug for keep-alive requests when using timeouts; ([#7206](https://github.com/axios/axios/issues/7206)) ([8d37233](https://github.com/axios/axios/commit/8d372335f5c50ecd01e8615f2468a9eb19703117)) - **http:** use default export for http2 module to support stubs; ([#7196](https://github.com/axios/axios/issues/7196)) ([0588880](https://github.com/axios/axios/commit/0588880ac7ddba7594ef179930493884b7e90bf5)) ### Performance Improvements - **http:** fix early loop exit; ([#7202](https://github.com/axios/axios/issues/7202)) ([12c314b](https://github.com/axios/axios/commit/12c314b603e7852a157e93e47edb626a471ba6c5)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+28/-9 (#7206 #7202 )') - avatar [Kasper Isager Dalsgarð](https://github.com/kasperisager '+9/-9 (#7196 )') ## [1.13.1](https://github.com/axios/axios/compare/v1.13.0...v1.13.1) (2025-10-28) ### Bug Fixes - **http:** fixed a regression that caused the data stream to be interrupted for responses with non-OK HTTP statuses; ([#7193](https://github.com/axios/axios/issues/7193)) ([bcd5581](https://github.com/axios/axios/commit/bcd5581d208cd372055afdcb2fd10b68ca40613c)) ### Contributors to this release - avatar [Anchal Singh](https://github.com/imanchalsingh '+220/-111 (#7173 )') - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+18/-1 (#7193 )') # [1.13.0](https://github.com/axios/axios/compare/v1.12.2...v1.13.0) (2025-10-27) ### Bug Fixes - **fetch:** prevent TypeError when config.env is undefined ([#7155](https://github.com/axios/axios/issues/7155)) ([015faec](https://github.com/axios/axios/commit/015faeca9f26db76f9562760f04bb9f8229f4db1)) - resolve issue [#7131](https://github.com/axios/axios/issues/7131) (added spacing in mergeConfig.js) ([#7133](https://github.com/axios/axios/issues/7133)) ([9b9ec98](https://github.com/axios/axios/commit/9b9ec98548d93e9f2204deea10a5f1528bf3ce62)) ### Features - **http:** add HTTP2 support; ([#7150](https://github.com/axios/axios/issues/7150)) ([d676df7](https://github.com/axios/axios/commit/d676df772244726533ca320f42e967f5af056bac)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+794/-180 (#7186 #7150 #7039 )') - avatar [Noritaka Kobayashi](https://github.com/noritaka1166 '+24/-509 (#7032 )') - avatar [Aviraj2929](https://github.com/Aviraj2929 '+211/-93 (#7136 #7135 #7134 #7112 )') - avatar [prasoon patel](https://github.com/Prasoon52 '+167/-6 (#7099 )') - avatar [Samyak Dandge](https://github.com/Samy-in '+134/-0 (#7171 )') - avatar [Anchal Singh](https://github.com/imanchalsingh '+53/-56 (#7170 )') - avatar [Rahul Kumar](https://github.com/jaiyankargupta '+28/-28 (#7073 )') - avatar [Amit Verma](https://github.com/Amitverma0509 '+24/-13 (#7129 )') - avatar [Abhishek3880](https://github.com/abhishekmaniy '+23/-4 (#7119 #7117 #7116 #7115 )') - avatar [Dhvani Maktuporia](https://github.com/Dhvani365 '+14/-5 (#7175 )') - avatar [Usama Ayoub](https://github.com/sam3690 '+4/-4 (#7133 )') - avatar [ikuy1203](https://github.com/ikuy1203 '+3/-3 (#7166 )') - avatar [Nikhil Simon Toppo](https://github.com/Kirito-Excalibur '+1/-1 (#7172 )') - avatar [Jane Wangari](https://github.com/Wangarijane '+1/-1 (#7155 )') - avatar [Supakorn Ieamgomol](https://github.com/Supakornn '+1/-1 (#7065 )') - avatar [Kian-Meng Ang](https://github.com/kianmeng '+1/-1 (#7046 )') - avatar [UTSUMI Keiji](https://github.com/k-utsumi '+1/-1 (#7037 )') ## [1.12.2](https://github.com/axios/axios/compare/v1.12.1...v1.12.2) (2025-09-14) ### Bug Fixes - **fetch:** use current global fetch instead of cached one when env fetch is not specified to keep MSW support; ([#7030](https://github.com/axios/axios/issues/7030)) ([cf78825](https://github.com/axios/axios/commit/cf78825e1229b60d1629ad0bbc8a752ff43c3f53)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+247/-16 (#7030 #7022 #7024 )') - avatar [Noritaka Kobayashi](https://github.com/noritaka1166 '+2/-6 (#7028 #7029 )') ## [1.12.1](https://github.com/axios/axios/compare/v1.12.0...v1.12.1) (2025-09-12) ### Bug Fixes - **types:** fixed env config types; ([#7020](https://github.com/axios/axios/issues/7020)) ([b5f26b7](https://github.com/axios/axios/commit/b5f26b75bdd9afa95016fb67d0cab15fc74cbf05)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+10/-4 (#7020 )') # [1.12.0](https://github.com/axios/axios/compare/v1.11.0...v1.12.0) (2025-09-11) ### Bug Fixes - adding build artifacts ([9ec86de](https://github.com/axios/axios/commit/9ec86de257bfa33856571036279169f385ed92bd)) - dont add dist on release ([a2edc36](https://github.com/axios/axios/commit/a2edc3606a4f775d868a67bb3461ff18ce7ecd11)) - **fetch-adapter:** set correct Content-Type for Node FormData ([#6998](https://github.com/axios/axios/issues/6998)) ([a9f47af](https://github.com/axios/axios/commit/a9f47afbf3224d2ca987dbd8188789c7ea853c5d)) - **node:** enforce maxContentLength for data: URLs ([#7011](https://github.com/axios/axios/issues/7011)) ([945435f](https://github.com/axios/axios/commit/945435fc51467303768202250debb8d4ae892593)) - package exports ([#5627](https://github.com/axios/axios/issues/5627)) ([aa78ac2](https://github.com/axios/axios/commit/aa78ac23fc9036163308c0f6bd2bb885e7af3f36)) - **params:** removing '[' and ']' from URL encode exclude characters ([#3316](https://github.com/axios/axios/issues/3316)) ([#5715](https://github.com/axios/axios/issues/5715)) ([6d84189](https://github.com/axios/axios/commit/6d84189349c43b1dcdd977b522610660cc4c7042)) - release pr run ([fd7f404](https://github.com/axios/axios/commit/fd7f404488b2c4f238c2fbe635b58026a634bfd2)) - **types:** change the type guard on isCancel ([#5595](https://github.com/axios/axios/issues/5595)) ([0dbb7fd](https://github.com/axios/axios/commit/0dbb7fd4f61dc568498cd13a681fa7f907d6ec7e)) ### Features - **adapter:** surface low‑level network error details; attach original error via cause ([#6982](https://github.com/axios/axios/issues/6982)) ([78b290c](https://github.com/axios/axios/commit/78b290c57c978ed2ab420b90d97350231c9e5d74)) - **fetch:** add fetch, Request, Response env config variables for the adapter; ([#7003](https://github.com/axios/axios/issues/7003)) ([c959ff2](https://github.com/axios/axios/commit/c959ff29013a3bc90cde3ac7ea2d9a3f9c08974b)) - support reviver on JSON.parse ([#5926](https://github.com/axios/axios/issues/5926)) ([2a97634](https://github.com/axios/axios/commit/2a9763426e43d996fd60d01afe63fa6e1f5b4fca)), closes [#5924](https://github.com/axios/axios/issues/5924) - **types:** extend AxiosResponse interface to include custom headers type ([#6782](https://github.com/axios/axios/issues/6782)) ([7960d34](https://github.com/axios/axios/commit/7960d34eded2de66ffd30b4687f8da0e46c4903e)) ### Contributors to this release - avatar [Willian Agostini](https://github.com/WillianAgostini '+132/-16760 (#7002 #5926 #6782 )') - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+4263/-293 (#7006 #7003 )') - avatar [khani](https://github.com/mkhani01 '+111/-15 (#6982 )') - avatar [Ameer Assadi](https://github.com/AmeerAssadi '+123/-0 (#7011 )') - avatar [Emiedonmokumo Dick-Boro](https://github.com/emiedonmokumo '+55/-35 (#6998 )') - avatar [Zeroday BYTE](https://github.com/opsysdebug '+8/-8 (#6980 )') - avatar [Jason Saayman](https://github.com/jasonsaayman '+7/-7 (#6985 #6985 )') - avatar [최예찬](https://github.com/HealGaren '+5/-7 (#5715 )') - avatar [Gligor Kotushevski](https://github.com/gligorkot '+3/-1 (#5627 )') - avatar [Aleksandar Dimitrov](https://github.com/adimit '+2/-1 (#5595 )') # [1.11.0](https://github.com/axios/axios/compare/v1.10.0...v1.11.0) (2025-07-22) ### Bug Fixes - form-data npm package ([#6970](https://github.com/axios/axios/issues/6970)) ([e72c193](https://github.com/axios/axios/commit/e72c193722530db538b19e5ddaaa4544d226b253)) - prevent RangeError when using large Buffers ([#6961](https://github.com/axios/axios/issues/6961)) ([a2214ca](https://github.com/axios/axios/commit/a2214ca1bc60540baf2c80573cea3a0ff91ba9d1)) - **types:** resolve type discrepancies between ESM and CJS TypeScript declaration files ([#6956](https://github.com/axios/axios/issues/6956)) ([8517aa1](https://github.com/axios/axios/commit/8517aa16f8d082fc1d5309c642220fa736159110)) ### Contributors to this release - avatar [izzy goldman](https://github.com/izzygld '+186/-93 (#6970 )') - avatar [Manish Sahani](https://github.com/manishsahanidev '+70/-0 (#6961 )') - avatar [Noritaka Kobayashi](https://github.com/noritaka1166 '+12/-10 (#6938 #6939 )') - avatar [James Nail](https://github.com/jrnail23 '+13/-2 (#6956 )') - avatar [Tejaswi1305](https://github.com/Tejaswi1305 '+1/-1 (#6894 )') # [1.10.0](https://github.com/axios/axios/compare/v1.9.0...v1.10.0) (2025-06-14) ### Bug Fixes - **adapter:** pass fetchOptions to fetch function ([#6883](https://github.com/axios/axios/issues/6883)) ([0f50af8](https://github.com/axios/axios/commit/0f50af8e076b7fb403844789bd5e812dedcaf4ed)) - **form-data:** convert boolean values to strings in FormData serialization ([#6917](https://github.com/axios/axios/issues/6917)) ([5064b10](https://github.com/axios/axios/commit/5064b108de336ff34862650709761b8a96d26be0)) - **package:** add module entry point for React Native; ([#6933](https://github.com/axios/axios/issues/6933)) ([3d343b8](https://github.com/axios/axios/commit/3d343b86dc4fd0eea0987059c5af04327c7ae304)) ### Features - **types:** improved fetchOptions interface ([#6867](https://github.com/axios/axios/issues/6867)) ([63f1fce](https://github.com/axios/axios/commit/63f1fce233009f5db1abf2586c145825ac98c3d7)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+30/-19 (#6933 #6920 #6893 #6892 )') - avatar [Noritaka Kobayashi](https://github.com/noritaka1166 '+2/-6 (#6922 #6923 )') - avatar [Dimitrios Lazanas](https://github.com/dimitry-lzs '+4/-0 (#6917 )') - avatar [Adrian Knapp](https://github.com/AdrianKnapp '+2/-2 (#6867 )') - avatar [Howie Zhao](https://github.com/howiezhao '+3/-1 (#6872 )') - avatar [Uhyeon Park](https://github.com/warpdev '+1/-1 (#6883 )') - avatar [Sampo Silvennoinen](https://github.com/stscoundrel '+1/-1 (#6913 )') # [1.9.0](https://github.com/axios/axios/compare/v1.8.4...v1.9.0) (2025-04-24) ### Bug Fixes - **core:** fix the Axios constructor implementation to treat the config argument as optional; ([#6881](https://github.com/axios/axios/issues/6881)) ([6c5d4cd](https://github.com/axios/axios/commit/6c5d4cd69286868059c5e52d45085cb9a894a983)) - **fetch:** fixed ERR_NETWORK mapping for Safari browsers; ([#6767](https://github.com/axios/axios/issues/6767)) ([dfe8411](https://github.com/axios/axios/commit/dfe8411c9a082c3d068bdd1f8d6e73054f387f45)) - **headers:** allow iterable objects to be a data source for the set method; ([#6873](https://github.com/axios/axios/issues/6873)) ([1b1f9cc](https://github.com/axios/axios/commit/1b1f9ccdc15f1ea745160ec9a5223de9db4673bc)) - **headers:** fix `getSetCookie` by using 'get' method for caseless access; ([#6874](https://github.com/axios/axios/issues/6874)) ([d4f7df4](https://github.com/axios/axios/commit/d4f7df4b304af8b373488fdf8e830793ff843eb9)) - **headers:** fixed support for setting multiple header values from an iterated source; ([#6885](https://github.com/axios/axios/issues/6885)) ([f7a3b5e](https://github.com/axios/axios/commit/f7a3b5e0f7e5e127b97defa92a132fbf1b55cf15)) - **http:** send minimal end multipart boundary ([#6661](https://github.com/axios/axios/issues/6661)) ([987d2e2](https://github.com/axios/axios/commit/987d2e2dd3b362757550f36eab875e60640b6ddc)) - **types:** fix autocomplete for adapter config ([#6855](https://github.com/axios/axios/issues/6855)) ([e61a893](https://github.com/axios/axios/commit/e61a8934d8f94dd429a2f309b48c67307c700df0)) ### Features - **AxiosHeaders:** add getSetCookie method to retrieve set-cookie headers values ([#5707](https://github.com/axios/axios/issues/5707)) ([80ea756](https://github.com/axios/axios/commit/80ea756e72bcf53110fa792f5d7ab76e8b11c996)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+200/-34 (#6890 #6889 #6888 #6885 #6881 #6767 #6874 #6873 )') - avatar [Jay](https://github.com/jasonsaayman '+26/-1 ()') - avatar [Willian Agostini](https://github.com/WillianAgostini '+21/-0 (#5707 )') - avatar [George Cheng](https://github.com/Gerhut '+3/-3 (#5096 )') - avatar [FatahChan](https://github.com/FatahChan '+2/-2 (#6855 )') - avatar [Ionuț G. Stan](https://github.com/igstan '+1/-1 (#6661 )') ## [1.8.4](https://github.com/axios/axios/compare/v1.8.3...v1.8.4) (2025-03-19) ### Bug Fixes - **buildFullPath:** handle `allowAbsoluteUrls: false` without `baseURL` ([#6833](https://github.com/axios/axios/issues/6833)) ([f10c2e0](https://github.com/axios/axios/commit/f10c2e0de7fde0051f848609a29c2906d0caa1d9)) ### Contributors to this release - avatar [Marc Hassan](https://github.com/mhassan1 '+5/-1 (#6833 )') ## [1.8.3](https://github.com/axios/axios/compare/v1.8.2...v1.8.3) (2025-03-10) ### Bug Fixes - add missing type for allowAbsoluteUrls ([#6818](https://github.com/axios/axios/issues/6818)) ([10fa70e](https://github.com/axios/axios/commit/10fa70ef14fe39558b15a179f0e82f5f5e5d11b2)) - **xhr/fetch:** pass `allowAbsoluteUrls` to `buildFullPath` in `xhr` and `fetch` adapters ([#6814](https://github.com/axios/axios/issues/6814)) ([ec159e5](https://github.com/axios/axios/commit/ec159e507bdf08c04ba1a10fe7710094e9e50ec9)) ### Contributors to this release - avatar [Ashcon Partovi](https://github.com/Electroid '+6/-0 (#6811 )') - avatar [StefanBRas](https://github.com/StefanBRas '+4/-0 (#6818 )') - avatar [Marc Hassan](https://github.com/mhassan1 '+2/-2 (#6814 )') ## [1.8.2](https://github.com/axios/axios/compare/v1.8.1...v1.8.2) (2025-03-07) ### Bug Fixes - **http-adapter:** add allowAbsoluteUrls to path building ([#6810](https://github.com/axios/axios/issues/6810)) ([fb8eec2](https://github.com/axios/axios/commit/fb8eec214ce7744b5ca787f2c3b8339b2f54b00f)) ### Contributors to this release - avatar [Fasoro-Joseph Alexander](https://github.com/lexcorp16 '+1/-1 (#6810 )') ## [1.8.1](https://github.com/axios/axios/compare/v1.8.0...v1.8.1) (2025-02-26) ### Bug Fixes - **utils:** move `generateString` to platform utils to avoid importing crypto module into client builds; ([#6789](https://github.com/axios/axios/issues/6789)) ([36a5a62](https://github.com/axios/axios/commit/36a5a620bec0b181451927f13ac85b9888b86cec)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+51/-47 (#6789 )') # [1.8.0](https://github.com/axios/axios/compare/v1.7.9...v1.8.0) (2025-02-25) ### Bug Fixes - **examples:** application crashed when navigating examples in browser ([#5938](https://github.com/axios/axios/issues/5938)) ([1260ded](https://github.com/axios/axios/commit/1260ded634ec101dd5ed05d3b70f8e8f899dba6c)) - missing word in SUPPORT_QUESTION.yml ([#6757](https://github.com/axios/axios/issues/6757)) ([1f890b1](https://github.com/axios/axios/commit/1f890b13f2c25a016f3c84ae78efb769f244133e)) - **utils:** replace getRandomValues with crypto module ([#6788](https://github.com/axios/axios/issues/6788)) ([23a25af](https://github.com/axios/axios/commit/23a25af0688d1db2c396deb09229d2271cc24f6c)) ### Features - Add config for ignoring absolute URLs ([#5902](https://github.com/axios/axios/issues/5902)) ([#6192](https://github.com/axios/axios/issues/6192)) ([32c7bcc](https://github.com/axios/axios/commit/32c7bcc0f233285ba27dec73a4b1e81fb7a219b3)) ### Reverts - Revert "chore: expose fromDataToStream to be consumable (#6731)" (#6732) ([1317261](https://github.com/axios/axios/commit/1317261125e9c419fe9f126867f64d28f9c1efda)), closes [#6731](https://github.com/axios/axios/issues/6731) [#6732](https://github.com/axios/axios/issues/6732) ### BREAKING CHANGES - code relying on the above will now combine the URLs instead of prefer request URL - feat: add config option for allowing absolute URLs - fix: add default value for allowAbsoluteUrls in buildFullPath - fix: typo in flow control when setting allowAbsoluteUrls ### Contributors to this release - avatar [Michael Toscano](https://github.com/GethosTheWalrus '+42/-8 (#6192 )') - avatar [Willian Agostini](https://github.com/WillianAgostini '+26/-3 (#6788 #6777 )') - avatar [Naron](https://github.com/naronchen '+27/-0 (#5901 )') - avatar [shravan || श्रvan](https://github.com/shravan20 '+7/-3 (#6116 )') - avatar [Justin Dhillon](https://github.com/justindhillon '+0/-7 (#6312 )') - avatar [yionr](https://github.com/yionr '+5/-1 (#6129 )') - avatar [Shin'ya Ueoka](https://github.com/ueokande '+3/-3 (#5935 )') - avatar [Dan Dascalescu](https://github.com/dandv '+3/-3 (#5908 #6757 )') - avatar [Nitin Ramnani](https://github.com/NitinRamnani '+2/-2 (#5938 )') - avatar [Shay Molcho](https://github.com/shaymolcho '+2/-2 (#6770 )') - avatar [Jay](https://github.com/jasonsaayman '+0/-3 (#6732 )') - fancy45daddy - avatar [Habip Akyol](https://github.com/habipakyol '+1/-1 (#6030 )') - avatar [Bailey Lissington](https://github.com/llamington '+1/-1 (#6771 )') - avatar [Bernardo da Eira Duarte](https://github.com/bernardoduarte '+1/-1 (#6480 )') - avatar [Shivam Batham](https://github.com/Shivam-Batham '+1/-1 (#5949 )') - avatar [Lipin Kariappa](https://github.com/lipinnnnn '+1/-1 (#5936 )') ## [1.7.9](https://github.com/axios/axios/compare/v1.7.8...v1.7.9) (2024-12-04) ### Reverts - Revert "fix(types): export CJS types from ESM (#6218)" (#6729) ([c44d2f2](https://github.com/axios/axios/commit/c44d2f2316ad289b38997657248ba10de11deb6c)), closes [#6218](https://github.com/axios/axios/issues/6218) [#6729](https://github.com/axios/axios/issues/6729) ### Contributors to this release - avatar [Jay](https://github.com/jasonsaayman '+596/-108 (#6729 )') ## [1.7.8](https://github.com/axios/axios/compare/v1.7.7...v1.7.8) (2024-11-25) ### Bug Fixes - allow passing a callback as paramsSerializer to buildURL ([#6680](https://github.com/axios/axios/issues/6680)) ([eac4619](https://github.com/axios/axios/commit/eac4619fe2e0926e876cd260ee21e3690381dbb5)) - **core:** fixed config merging bug ([#6668](https://github.com/axios/axios/issues/6668)) ([5d99fe4](https://github.com/axios/axios/commit/5d99fe4491202a6268c71e5dcc09192359d73cea)) - fixed width form to not shrink after 'Send Request' button is clicked ([#6644](https://github.com/axios/axios/issues/6644)) ([7ccd5fd](https://github.com/axios/axios/commit/7ccd5fd42402102d38712c32707bf055be72ab54)) - **http:** add support for File objects as payload in http adapter ([#6588](https://github.com/axios/axios/issues/6588)) ([#6605](https://github.com/axios/axios/issues/6605)) ([6841d8d](https://github.com/axios/axios/commit/6841d8d18ddc71cc1bd202ffcfddb3f95622eef3)) - **http:** fixed proxy-from-env module import ([#5222](https://github.com/axios/axios/issues/5222)) ([12b3295](https://github.com/axios/axios/commit/12b32957f1258aee94ef859809ed39f8f88f9dfa)) - **http:** use `globalThis.TextEncoder` when available ([#6634](https://github.com/axios/axios/issues/6634)) ([df956d1](https://github.com/axios/axios/commit/df956d18febc9100a563298dfdf0f102c3d15410)) - ios11 breaks when build ([#6608](https://github.com/axios/axios/issues/6608)) ([7638952](https://github.com/axios/axios/commit/763895270f7b50c7c780c3c9807ae8635de952cd)) - **types:** add missing types for mergeConfig function ([#6590](https://github.com/axios/axios/issues/6590)) ([00de614](https://github.com/axios/axios/commit/00de614cd07b7149af335e202aef0e076c254f49)) - **types:** export CJS types from ESM ([#6218](https://github.com/axios/axios/issues/6218)) ([c71811b](https://github.com/axios/axios/commit/c71811b00f2fcff558e4382ba913bdac4ad7200e)) - updated stream aborted error message to be more clear ([#6615](https://github.com/axios/axios/issues/6615)) ([cc3217a](https://github.com/axios/axios/commit/cc3217a612024d83a663722a56d7a98d8759c6d5)) - use URL API instead of DOM to fix a potential vulnerability warning; ([#6714](https://github.com/axios/axios/issues/6714)) ([0a8d6e1](https://github.com/axios/axios/commit/0a8d6e19da5b9899a2abafaaa06a75ee548597db)) ### Contributors to this release - avatar [Remco Haszing](https://github.com/remcohaszing '+108/-596 (#6218 )') - avatar [Jay](https://github.com/jasonsaayman '+281/-19 (#6640 #6619 )') - avatar [Aayush Yadav](https://github.com/aayushyadav020 '+124/-111 (#6617 )') - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+12/-65 (#6714 )') - avatar [Ell Bradshaw](https://github.com/cincodenada '+29/-0 (#6489 )') - avatar [Amit Saini](https://github.com/amitsainii '+13/-3 (#5237 )') - avatar [Tommaso Paulon](https://github.com/guuido '+14/-1 (#6680 )') - avatar [Akki](https://github.com/Aakash-Rana '+5/-5 (#6668 )') - avatar [Sampo Silvennoinen](https://github.com/stscoundrel '+3/-3 (#6633 )') - avatar [Kasper Isager Dalsgarð](https://github.com/kasperisager '+2/-2 (#6634 )') - avatar [Christian Clauss](https://github.com/cclauss '+4/-0 (#6683 )') - avatar [Pavan Welihinda](https://github.com/pavan168 '+2/-2 (#5222 )') - avatar [Taylor Flatt](https://github.com/taylorflatt '+2/-2 (#6615 )') - avatar [Kenzo Wada](https://github.com/Kenzo-Wada '+2/-2 (#6608 )') - avatar [Ngole Lawson](https://github.com/echelonnought '+3/-0 (#6644 )') - avatar [Haven](https://github.com/Baoyx007 '+3/-0 (#6590 )') - avatar [Shrivali Dutt](https://github.com/shrivalidutt '+1/-1 (#6637 )') - avatar [Henco Appel](https://github.com/hencoappel '+1/-1 (#6605 )') ## [1.7.7](https://github.com/axios/axios/compare/v1.7.6...v1.7.7) (2024-08-31) ### Bug Fixes - **fetch:** fix stream handling in Safari by fallback to using a stream reader instead of an async iterator; ([#6584](https://github.com/axios/axios/issues/6584)) ([d198085](https://github.com/axios/axios/commit/d1980854fee1765cd02fa0787adf5d6e34dd9dcf)) - **http:** fixed support for IPv6 literal strings in url ([#5731](https://github.com/axios/axios/issues/5731)) ([364993f](https://github.com/axios/axios/commit/364993f0d8bc6e0e06f76b8a35d2d0a35cab054c)) ### Contributors to this release - avatar [Rishi556](https://github.com/Rishi556 '+39/-1 (#5731 )') - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+27/-7 (#6584 )') ## [1.7.6](https://github.com/axios/axios/compare/v1.7.5...v1.7.6) (2024-08-30) ### Bug Fixes - **fetch:** fix content length calculation for FormData payload; ([#6524](https://github.com/axios/axios/issues/6524)) ([085f568](https://github.com/axios/axios/commit/085f56861a83e9ac02c140ad9d68dac540dfeeaa)) - **fetch:** optimize signals composing logic; ([#6582](https://github.com/axios/axios/issues/6582)) ([df9889b](https://github.com/axios/axios/commit/df9889b83c2cc37e9e6189675a73ab70c60f031f)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+98/-46 (#6582 )') - avatar [Jacques Germishuys](https://github.com/jacquesg '+5/-1 (#6524 )') - avatar [kuroino721](https://github.com/kuroino721 '+3/-1 (#6575 )') ## [1.7.5](https://github.com/axios/axios/compare/v1.7.4...v1.7.5) (2024-08-23) ### Bug Fixes - **adapter:** fix undefined reference to hasBrowserEnv ([#6572](https://github.com/axios/axios/issues/6572)) ([7004707](https://github.com/axios/axios/commit/7004707c4180b416341863bd86913fe4fc2f1df1)) - **core:** add the missed implementation of AxiosError#status property; ([#6573](https://github.com/axios/axios/issues/6573)) ([6700a8a](https://github.com/axios/axios/commit/6700a8adac06942205f6a7a21421ecb36c4e0852)) - **core:** fix `ReferenceError: navigator is not defined` for custom environments; ([#6567](https://github.com/axios/axios/issues/6567)) ([fed1a4b](https://github.com/axios/axios/commit/fed1a4b2d78ed4a588c84e09d32749ed01dc2794)) - **fetch:** fix credentials handling in Cloudflare workers ([#6533](https://github.com/axios/axios/issues/6533)) ([550d885](https://github.com/axios/axios/commit/550d885eb90fd156add7b93bbdc54d30d2f9a98d)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+187/-83 (#6573 #6567 #6566 #6564 #6563 #6557 #6556 #6555 #6554 #6552 )') - avatar [Antonin Bas](https://github.com/antoninbas '+6/-6 (#6572 )') - avatar [Hans Otto Wirtz](https://github.com/hansottowirtz '+4/-1 (#6533 )') ## [1.7.4](https://github.com/axios/axios/compare/v1.7.3...v1.7.4) (2024-08-13) ### Bug Fixes - **sec:** CVE-2024-39338 ([#6539](https://github.com/axios/axios/issues/6539)) ([#6543](https://github.com/axios/axios/issues/6543)) ([6b6b605](https://github.com/axios/axios/commit/6b6b605eaf73852fb2dae033f1e786155959de3a)) - **sec:** disregard protocol-relative URL to remediate SSRF ([#6539](https://github.com/axios/axios/issues/6539)) ([07a661a](https://github.com/axios/axios/commit/07a661a2a6b9092c4aa640dcc7f724ec5e65bdda)) ### Contributors to this release - avatar [Lev Pachmanov](https://github.com/levpachmanov '+47/-11 (#6543 )') - avatar [Đỗ Trọng Hải](https://github.com/hainenber '+49/-4 (#6539 )') ## [1.7.3](https://github.com/axios/axios/compare/v1.7.2...v1.7.3) (2024-08-01) ### Bug Fixes - **adapter:** fix progress event emitting; ([#6518](https://github.com/axios/axios/issues/6518)) ([e3c76fc](https://github.com/axios/axios/commit/e3c76fc9bdd03aa4d98afaf211df943e2031453f)) - **fetch:** fix withCredentials request config ([#6505](https://github.com/axios/axios/issues/6505)) ([85d4d0e](https://github.com/axios/axios/commit/85d4d0ea0aae91082f04e303dec46510d1b4e787)) - **xhr:** return original config on errors from XHR adapter ([#6515](https://github.com/axios/axios/issues/6515)) ([8966ee7](https://github.com/axios/axios/commit/8966ee7ea62ecbd6cfb39a905939bcdab5cf6388)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+211/-159 (#6518 #6519 )') - avatar [Valerii Sidorenko](https://github.com/ValeraS '+3/-3 (#6515 )') - avatar [prianYu](https://github.com/prianyu '+2/-2 (#6505 )') ## [1.7.2](https://github.com/axios/axios/compare/v1.7.1...v1.7.2) (2024-05-21) ### Bug Fixes - **fetch:** enhance fetch API detection; ([#6413](https://github.com/axios/axios/issues/6413)) ([4f79aef](https://github.com/axios/axios/commit/4f79aef81b7c4644328365bfc33acf0a9ef595bc)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+3/-3 (#6413 )') ## [1.7.1](https://github.com/axios/axios/compare/v1.7.0...v1.7.1) (2024-05-20) ### Bug Fixes - **fetch:** fixed ReferenceError issue when TextEncoder is not available in the environment; ([#6410](https://github.com/axios/axios/issues/6410)) ([733f15f](https://github.com/axios/axios/commit/733f15fe5bd2d67e1fadaee82e7913b70d45dc5e)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+14/-9 (#6410 )') # [1.7.0](https://github.com/axios/axios/compare/v1.7.0-beta.2...v1.7.0) (2024-05-19) ### Features - **adapter:** add fetch adapter; ([#6371](https://github.com/axios/axios/issues/6371)) ([a3ff99b](https://github.com/axios/axios/commit/a3ff99b59d8ec2ab5dd049e68c043617a4072e42)) ### Bug Fixes - **core/axios:** handle un-writable error stack ([#6362](https://github.com/axios/axios/issues/6362)) ([81e0455](https://github.com/axios/axios/commit/81e0455b7b57fbaf2be16a73ebe0e6591cc6d8f9)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+1015/-127 (#6371 )') - avatar [Jay](https://github.com/jasonsaayman '+30/-14 ()') - avatar [Alexandre ABRIOUX](https://github.com/alexandre-abrioux '+56/-6 (#6362 )') # [1.7.0-beta.2](https://github.com/axios/axios/compare/v1.7.0-beta.1...v1.7.0-beta.2) (2024-05-19) ### Bug Fixes - **fetch:** capitalize HTTP method names; ([#6395](https://github.com/axios/axios/issues/6395)) ([ad3174a](https://github.com/axios/axios/commit/ad3174a3515c3c2573f4bcb94818d582826f3914)) - **fetch:** fix & optimize progress capturing for cases when the request data has a nullish value or zero data length ([#6400](https://github.com/axios/axios/issues/6400)) ([95a3e8e](https://github.com/axios/axios/commit/95a3e8e346cfd6a5548e171f2341df3235d0e26b)) - **fetch:** fix headers getting from a stream response; ([#6401](https://github.com/axios/axios/issues/6401)) ([870e0a7](https://github.com/axios/axios/commit/870e0a76f60d0094774a6a63fa606eec52a381af)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+99/-46 (#6405 #6404 #6401 #6400 #6395 )') # [1.7.0-beta.1](https://github.com/axios/axios/compare/v1.7.0-beta.0...v1.7.0-beta.1) (2024-05-07) ### Bug Fixes - **core/axios:** handle un-writable error stack ([#6362](https://github.com/axios/axios/issues/6362)) ([81e0455](https://github.com/axios/axios/commit/81e0455b7b57fbaf2be16a73ebe0e6591cc6d8f9)) - **fetch:** fix cases when ReadableStream or Response.body are not available; ([#6377](https://github.com/axios/axios/issues/6377)) ([d1d359d](https://github.com/axios/axios/commit/d1d359da347704e8b28d768e61515a3e96c5b072)) - **fetch:** treat fetch-related TypeError as an AxiosError.ERR_NETWORK error; ([#6380](https://github.com/axios/axios/issues/6380)) ([bb5f9a5](https://github.com/axios/axios/commit/bb5f9a5ab768452de9e166dc28d0ffc234245ef1)) ### Contributors to this release - avatar [Alexandre ABRIOUX](https://github.com/alexandre-abrioux '+56/-6 (#6362 )') - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+42/-17 (#6380 #6377 )') # [1.7.0-beta.0](https://github.com/axios/axios/compare/v1.6.8...v1.7.0-beta.0) (2024-04-28) ### Features - **adapter:** add fetch adapter; ([#6371](https://github.com/axios/axios/issues/6371)) ([a3ff99b](https://github.com/axios/axios/commit/a3ff99b59d8ec2ab5dd049e68c043617a4072e42)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+1015/-127 (#6371 )') - avatar [Jay](https://github.com/jasonsaayman '+30/-14 ()') ## [1.6.8](https://github.com/axios/axios/compare/v1.6.7...v1.6.8) (2024-03-15) ### Bug Fixes - **AxiosHeaders:** fix AxiosHeaders conversion to an object during config merging ([#6243](https://github.com/axios/axios/issues/6243)) ([2656612](https://github.com/axios/axios/commit/2656612bc10fe2757e9832b708ed773ab340b5cb)) - **import:** use named export for EventEmitter; ([7320430](https://github.com/axios/axios/commit/7320430aef2e1ba2b89488a0eaf42681165498b1)) - **vulnerability:** update follow-redirects to 1.15.6 ([#6300](https://github.com/axios/axios/issues/6300)) ([8786e0f](https://github.com/axios/axios/commit/8786e0ff55a8c68d4ca989801ad26df924042e27)) ### Contributors to this release - avatar [Jay](https://github.com/jasonsaayman '+4572/-3446 (#6238 )') - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+30/-0 (#6231 )') - avatar [Mitchell](https://github.com/Creaous '+9/-9 (#6300 )') - avatar [Emmanuel](https://github.com/mannoeu '+2/-2 (#6196 )') - avatar [Lucas Keller](https://github.com/ljkeller '+3/-0 (#6194 )') - avatar [Aditya Mogili](https://github.com/ADITYA-176 '+1/-1 ()') - avatar [Miroslav Petrov](https://github.com/petrovmiroslav '+1/-1 (#6243 )') ## [1.6.7](https://github.com/axios/axios/compare/v1.6.6...v1.6.7) (2024-01-25) ### Bug Fixes - capture async stack only for rejections with native error objects; ([#6203](https://github.com/axios/axios/issues/6203)) ([1a08f90](https://github.com/axios/axios/commit/1a08f90f402336e4d00e9ee82f211c6adb1640b0)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+30/-26 (#6203 )') - avatar [zhoulixiang](https://github.com/zh-lx '+0/-3 (#6186 )') ## [1.6.6](https://github.com/axios/axios/compare/v1.6.5...v1.6.6) (2024-01-24) ### Bug Fixes - fixed missed dispatchBeforeRedirect argument ([#5778](https://github.com/axios/axios/issues/5778)) ([a1938ff](https://github.com/axios/axios/commit/a1938ff073fcb0f89011f001dfbc1fa1dc995e39)) - wrap errors to improve async stack trace ([#5987](https://github.com/axios/axios/issues/5987)) ([123f354](https://github.com/axios/axios/commit/123f354b920f154a209ea99f76b7b2ef3d9ebbab)) ### Contributors to this release - avatar [Ilya Priven](https://github.com/ikonst '+91/-8 (#5987 )') - avatar [Zao Soula](https://github.com/zaosoula '+6/-6 (#5778 )') ## [1.6.5](https://github.com/axios/axios/compare/v1.6.4...v1.6.5) (2024-01-05) ### Bug Fixes - **ci:** refactor notify action as a job of publish action; ([#6176](https://github.com/axios/axios/issues/6176)) ([0736f95](https://github.com/axios/axios/commit/0736f95ce8776366dc9ca569f49ba505feb6373c)) - **dns:** fixed lookup error handling; ([#6175](https://github.com/axios/axios/issues/6175)) ([f4f2b03](https://github.com/axios/axios/commit/f4f2b039dd38eb4829e8583caede4ed6d2dd59be)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+41/-6 (#6176 #6175 )') - avatar [Jay](https://github.com/jasonsaayman '+6/-1 ()') ## [1.6.4](https://github.com/axios/axios/compare/v1.6.3...v1.6.4) (2024-01-03) ### Bug Fixes - **security:** fixed formToJSON prototype pollution vulnerability; ([#6167](https://github.com/axios/axios/issues/6167)) ([3c0c11c](https://github.com/axios/axios/commit/3c0c11cade045c4412c242b5727308cff9897a0e)) - **security:** fixed security vulnerability in follow-redirects ([#6163](https://github.com/axios/axios/issues/6163)) ([75af1cd](https://github.com/axios/axios/commit/75af1cdff5b3a6ca3766d3d3afbc3115bb0811b8)) ### Contributors to this release - avatar [Jay](https://github.com/jasonsaayman '+34/-6 ()') - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+34/-3 (#6172 #6167 )') - avatar [Guy Nesher](https://github.com/gnesher '+10/-10 (#6163 )') ## [1.6.3](https://github.com/axios/axios/compare/v1.6.2...v1.6.3) (2023-12-26) ### Bug Fixes - Regular Expression Denial of Service (ReDoS) ([#6132](https://github.com/axios/axios/issues/6132)) ([5e7ad38](https://github.com/axios/axios/commit/5e7ad38fb0f819fceb19fb2ee5d5d38f56aa837d)) ### Contributors to this release - avatar [Jay](https://github.com/jasonsaayman '+15/-6 (#6145 )') - avatar [Willian Agostini](https://github.com/WillianAgostini '+17/-2 (#6132 )') - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+3/-0 (#6084 )') ## [1.6.2](https://github.com/axios/axios/compare/v1.6.1...v1.6.2) (2023-11-14) ### Features - **withXSRFToken:** added withXSRFToken option as a workaround to achieve the old `withCredentials` behavior; ([#6046](https://github.com/axios/axios/issues/6046)) ([cff9967](https://github.com/axios/axios/commit/cff996779b272a5e94c2b52f5503ccf668bc42dc)) ### PRs - feat(withXSRFToken): added withXSRFToken option as a workaround to achieve the old `withCredentials` behavior; ( [#6046](https://api.github.com/repos/axios/axios/pulls/6046) ) ``` 📢 This PR added 'withXSRFToken' option as a replacement for old withCredentials behaviour. You should now use withXSRFToken along with withCredential to get the old behavior. This functionality is considered as a fix. ``` ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+271/-146 (#6081 #6080 #6079 #6078 #6046 #6064 #6063 )') - avatar [Ng Choon Khon (CK)](https://github.com/ckng0221 '+4/-4 (#6073 )') - avatar [Muhammad Noman](https://github.com/mnomanmemon '+2/-2 (#6048 )') ## [1.6.1](https://github.com/axios/axios/compare/v1.6.0...v1.6.1) (2023-11-08) ### Bug Fixes - **formdata:** fixed content-type header normalization for non-standard browser environments; ([#6056](https://github.com/axios/axios/issues/6056)) ([dd465ab](https://github.com/axios/axios/commit/dd465ab22bbfa262c6567be6574bf46a057d5288)) - **platform:** fixed emulated browser detection in node.js environment; ([#6055](https://github.com/axios/axios/issues/6055)) ([3dc8369](https://github.com/axios/axios/commit/3dc8369e505e32a4e12c22f154c55fd63ac67fbb)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+432/-65 (#6059 #6056 #6055 )') - avatar [Fabian Meyer](https://github.com/meyfa '+5/-2 (#5835 )') ### PRs - feat(withXSRFToken): added withXSRFToken option as a workaround to achieve the old `withCredentials` behavior; ( [#6046](https://api.github.com/repos/axios/axios/pulls/6046) ) ``` 📢 This PR added 'withXSRFToken' option as a replacement for old withCredentials behaviour. You should now use withXSRFToken along with withCredential to get the old behavior. This functionality is considered as a fix. ``` # [1.6.0](https://github.com/axios/axios/compare/v1.5.1...v1.6.0) (2023-10-26) ### Bug Fixes - **CSRF:** fixed CSRF vulnerability CVE-2023-45857 ([#6028](https://github.com/axios/axios/issues/6028)) ([96ee232](https://github.com/axios/axios/commit/96ee232bd3ee4de2e657333d4d2191cd389e14d0)) - **dns:** fixed lookup function decorator to work properly in node v20; ([#6011](https://github.com/axios/axios/issues/6011)) ([5aaff53](https://github.com/axios/axios/commit/5aaff532a6b820bb9ab6a8cd0f77131b47e2adb8)) - **types:** fix AxiosHeaders types; ([#5931](https://github.com/axios/axios/issues/5931)) ([a1c8ad0](https://github.com/axios/axios/commit/a1c8ad008b3c13d53e135bbd0862587fb9d3fc09)) ### PRs - CVE 2023 45857 ( [#6028](https://api.github.com/repos/axios/axios/pulls/6028) ) ``` ⚠️ Critical vulnerability fix. See https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459 ``` ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+449/-114 (#6032 #6021 #6011 #5932 #5931 )') - avatar [Valentin Panov](https://github.com/valentin-panov '+4/-4 (#6028 )') - avatar [Rinku Chaudhari](https://github.com/therealrinku '+1/-1 (#5889 )') ## [1.5.1](https://github.com/axios/axios/compare/v1.5.0...v1.5.1) (2023-09-26) ### Bug Fixes - **adapters:** improved adapters loading logic to have clear error messages; ([#5919](https://github.com/axios/axios/issues/5919)) ([e410779](https://github.com/axios/axios/commit/e4107797a7a1376f6209fbecfbbce73d3faa7859)) - **formdata:** fixed automatic addition of the `Content-Type` header for FormData in non-browser environments; ([#5917](https://github.com/axios/axios/issues/5917)) ([bc9af51](https://github.com/axios/axios/commit/bc9af51b1886d1b3529617702f2a21a6c0ed5d92)) - **headers:** allow `content-encoding` header to handle case-insensitive values ([#5890](https://github.com/axios/axios/issues/5890)) ([#5892](https://github.com/axios/axios/issues/5892)) ([4c89f25](https://github.com/axios/axios/commit/4c89f25196525e90a6e75eda9cb31ae0a2e18acd)) - **types:** removed duplicated code ([9e62056](https://github.com/axios/axios/commit/9e6205630e1c9cf863adf141c0edb9e6d8d4b149)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+89/-18 (#5919 #5917 )') - avatar [David Dallas](https://github.com/DavidJDallas '+11/-5 ()') - avatar [Sean Sattler](https://github.com/fb-sean '+2/-8 ()') - avatar [Mustafa Ateş Uzun](https://github.com/0o001 '+4/-4 ()') - avatar [Przemyslaw Motacki](https://github.com/sfc-gh-pmotacki '+2/-1 (#5892 )') - avatar [Michael Di Prisco](https://github.com/Cadienvan '+1/-1 ()') ### PRs - CVE 2023 45857 ( [#6028](https://api.github.com/repos/axios/axios/pulls/6028) ) ``` ⚠️ Critical vulnerability fix. See https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459 ``` # [1.5.0](https://github.com/axios/axios/compare/v1.4.0...v1.5.0) (2023-08-26) ### Bug Fixes - **adapter:** make adapter loading error more clear by using platform-specific adapters explicitly ([#5837](https://github.com/axios/axios/issues/5837)) ([9a414bb](https://github.com/axios/axios/commit/9a414bb6c81796a95c6c7fe668637825458e8b6d)) - **dns:** fixed `cacheable-lookup` integration; ([#5836](https://github.com/axios/axios/issues/5836)) ([b3e327d](https://github.com/axios/axios/commit/b3e327dcc9277bdce34c7ef57beedf644b00d628)) - **headers:** added support for setting header names that overlap with class methods; ([#5831](https://github.com/axios/axios/issues/5831)) ([d8b4ca0](https://github.com/axios/axios/commit/d8b4ca0ea5f2f05efa4edfe1e7684593f9f68273)) - **headers:** fixed common Content-Type header merging; ([#5832](https://github.com/axios/axios/issues/5832)) ([8fda276](https://github.com/axios/axios/commit/8fda2766b1e6bcb72c3fabc146223083ef13ce17)) ### Features - export getAdapter function ([#5324](https://github.com/axios/axios/issues/5324)) ([ca73eb8](https://github.com/axios/axios/commit/ca73eb878df0ae2dace81fe3a7f1fb5986231bf1)) - **export:** export adapters without `unsafe` prefix ([#5839](https://github.com/axios/axios/issues/5839)) ([1601f4a](https://github.com/axios/axios/commit/1601f4a27a81ab47fea228f1e244b2c4e3ce28bf)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+66/-29 (#5839 #5837 #5836 #5832 #5831 )') - avatar [夜葬](https://github.com/geekact '+42/-0 (#5324 )') - avatar [Jonathan Budiman](https://github.com/JBudiman00 '+30/-0 (#5788 )') - avatar [Michael Di Prisco](https://github.com/Cadienvan '+3/-5 (#5791 )') ### PRs - CVE 2023 45857 ( [#6028](https://api.github.com/repos/axios/axios/pulls/6028) ) ``` ⚠️ Critical vulnerability fix. See https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459 ``` # [1.4.0](https://github.com/axios/axios/compare/v1.3.6...v1.4.0) (2023-04-27) ### Bug Fixes - **formdata:** add `multipart/form-data` content type for FormData payload on custom client environments; ([#5678](https://github.com/axios/axios/issues/5678)) ([bbb61e7](https://github.com/axios/axios/commit/bbb61e70cb1185adfb1cbbb86eaf6652c48d89d1)) - **package:** export package internals with unsafe path prefix; ([#5677](https://github.com/axios/axios/issues/5677)) ([df38c94](https://github.com/axios/axios/commit/df38c949f26414d88ba29ec1e353c4d4f97eaf09)) ### Features - **dns:** added support for a custom lookup function; ([#5339](https://github.com/axios/axios/issues/5339)) ([2701911](https://github.com/axios/axios/commit/2701911260a1faa5cc5e1afe437121b330a3b7bb)) - **types:** export `AxiosHeaderValue` type. ([#5525](https://github.com/axios/axios/issues/5525)) ([726f1c8](https://github.com/axios/axios/commit/726f1c8e00cffa0461a8813a9bdcb8f8b9d762cf)) ### Performance Improvements - **merge-config:** optimize mergeConfig performance by avoiding duplicate key visits; ([#5679](https://github.com/axios/axios/issues/5679)) ([e6f7053](https://github.com/axios/axios/commit/e6f7053bf1a3e87cf1f9da8677e12e3fe829d68e)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+151/-16 (#5684 #5339 #5679 #5678 #5677 )') - avatar [Arthur Fiorette](https://github.com/arthurfiorette '+19/-19 (#5525 )') - avatar [PIYUSH NEGI](https://github.com/npiyush97 '+2/-18 (#5670 )') ### PRs - CVE 2023 45857 ( [#6028](https://api.github.com/repos/axios/axios/pulls/6028) ) ``` ⚠️ Critical vulnerability fix. See https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459 ``` ## [1.3.6](https://github.com/axios/axios/compare/v1.3.5...v1.3.6) (2023-04-19) ### Bug Fixes - **types:** added transport to RawAxiosRequestConfig ([#5445](https://github.com/axios/axios/issues/5445)) ([6f360a2](https://github.com/axios/axios/commit/6f360a2531d8d70363fd9becef6a45a323f170e2)) - **utils:** make isFormData detection logic stricter to avoid unnecessary calling of the `toString` method on the target; ([#5661](https://github.com/axios/axios/issues/5661)) ([aa372f7](https://github.com/axios/axios/commit/aa372f7306295dfd1100c1c2c77ce95c95808e76)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+48/-10 (#5665 #5661 #5663 )') - avatar [Michael Di Prisco](https://github.com/Cadienvan '+2/-0 (#5445 )') ### PRs - CVE 2023 45857 ( [#6028](https://api.github.com/repos/axios/axios/pulls/6028) ) ``` ⚠️ Critical vulnerability fix. See https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459 ``` ## [1.3.5](https://github.com/axios/axios/compare/v1.3.4...v1.3.5) (2023-04-05) ### Bug Fixes - **headers:** fixed isValidHeaderName to support full list of allowed characters; ([#5584](https://github.com/axios/axios/issues/5584)) ([e7decef](https://github.com/axios/axios/commit/e7decef6a99f4627e27ed9ea5b00ce8e201c3841)) - **params:** re-added the ability to set the function as `paramsSerializer` config; ([#5633](https://github.com/axios/axios/issues/5633)) ([a56c866](https://github.com/axios/axios/commit/a56c8661209d5ce5a645a05f294a0e08a6c1f6b3)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+28/-10 (#5633 #5584 )') ### PRs - CVE 2023 45857 ( [#6028](https://api.github.com/repos/axios/axios/pulls/6028) ) ``` ⚠️ Critical vulnerability fix. See https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459 ``` ## [1.3.4](https://github.com/axios/axios/compare/v1.3.3...v1.3.4) (2023-02-22) ### Bug Fixes - **blob:** added a check to make sure the Blob class is available in the browser's global scope; ([#5548](https://github.com/axios/axios/issues/5548)) ([3772c8f](https://github.com/axios/axios/commit/3772c8fe74112a56e3e9551f894d899bc3a9443a)) - **http:** fixed regression bug when handling synchronous errors inside the adapter; ([#5564](https://github.com/axios/axios/issues/5564)) ([a3b246c](https://github.com/axios/axios/commit/a3b246c9de5c3bc4b5a742e15add55b375479451)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+38/-26 (#5564 )') - avatar [lcysgsg](https://github.com/lcysgsg '+4/-0 (#5548 )') - avatar [Michael Di Prisco](https://github.com/Cadienvan '+3/-0 (#5444 )') ### PRs - CVE 2023 45857 ( [#6028](https://api.github.com/repos/axios/axios/pulls/6028) ) ``` ⚠️ Critical vulnerability fix. See https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459 ``` ## [1.3.3](https://github.com/axios/axios/compare/v1.3.2...v1.3.3) (2023-02-13) ### Bug Fixes - **formdata:** added a check to make sure the FormData class is available in the browser's global scope; ([#5545](https://github.com/axios/axios/issues/5545)) ([a6dfa72](https://github.com/axios/axios/commit/a6dfa72010db5ad52db8bd13c0f98e537e8fd05d)) - **formdata:** fixed setting NaN as Content-Length for form payload in some cases; ([#5535](https://github.com/axios/axios/issues/5535)) ([c19f7bf](https://github.com/axios/axios/commit/c19f7bf770f90ae8307f4ea3104f227056912da1)) - **headers:** fixed the filtering logic of the clear method; ([#5542](https://github.com/axios/axios/issues/5542)) ([ea87ebf](https://github.com/axios/axios/commit/ea87ebfe6d1699af072b9e7cd40faf8f14b0ab93)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+11/-7 (#5545 #5535 #5542 )') - avatar [陈若枫](https://github.com/ruofee '+2/-2 (#5467 )') ### PRs - CVE 2023 45857 ( [#6028](https://api.github.com/repos/axios/axios/pulls/6028) ) ``` ⚠️ Critical vulnerability fix. See https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459 ``` ## [1.3.2](https://github.com/axios/axios/compare/v1.3.1...v1.3.2) (2023-02-03) ### Bug Fixes - **http:** treat http://localhost as base URL for relative paths to avoid `ERR_INVALID_URL` error; ([#5528](https://github.com/axios/axios/issues/5528)) ([128d56f](https://github.com/axios/axios/commit/128d56f4a0fb8f5f2ed6e0dd80bc9225fee9538c)) - **http:** use explicit import instead of TextEncoder global; ([#5530](https://github.com/axios/axios/issues/5530)) ([6b3c305](https://github.com/axios/axios/commit/6b3c305fc40c56428e0afabedc6f4d29c2830f6f)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+2/-1 (#5530 #5528 )') ### PRs - CVE 2023 45857 ( [#6028](https://api.github.com/repos/axios/axios/pulls/6028) ) ``` ⚠️ Critical vulnerability fix. See https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459 ``` ## [1.3.1](https://github.com/axios/axios/compare/v1.3.0...v1.3.1) (2023-02-01) ### Bug Fixes - **formdata:** add hotfix to use the asynchronous API to compute the content-length header value; ([#5521](https://github.com/axios/axios/issues/5521)) ([96d336f](https://github.com/axios/axios/commit/96d336f527619f21da012fe1f117eeb53e5a2120)) - **serializer:** fixed serialization of array-like objects; ([#5518](https://github.com/axios/axios/issues/5518)) ([08104c0](https://github.com/axios/axios/commit/08104c028c0f9353897b1b6691d74c440fd0c32d)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+27/-8 (#5521 #5518 )') ### PRs - CVE 2023 45857 ( [#6028](https://api.github.com/repos/axios/axios/pulls/6028) ) ``` ⚠️ Critical vulnerability fix. See https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459 ``` # [1.3.0](https://github.com/axios/axios/compare/v1.2.6...v1.3.0) (2023-01-31) ### Bug Fixes - **headers:** fixed & optimized clear method; ([#5507](https://github.com/axios/axios/issues/5507)) ([9915635](https://github.com/axios/axios/commit/9915635c69d0ab70daca5738488421f67ca60959)) - **http:** add zlib headers if missing ([#5497](https://github.com/axios/axios/issues/5497)) ([65e8d1e](https://github.com/axios/axios/commit/65e8d1e28ce829f47a837e45129730e541950d3c)) ### Features - **fomdata:** added support for spec-compliant FormData & Blob types; ([#5316](https://github.com/axios/axios/issues/5316)) ([6ac574e](https://github.com/axios/axios/commit/6ac574e00a06731288347acea1e8246091196953)) ### Contributors to this release - avatar [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+352/-67 (#5514 #5512 #5510 #5509 #5508 #5316 #5507 )') - avatar [ItsNotGoodName](https://github.com/ItsNotGoodName '+43/-2 (#5497 )') ### PRs - CVE 2023 45857 ( [#6028](https://api.github.com/repos/axios/axios/pulls/6028) ) ``` ⚠️ Critical vulnerability fix. See https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459 ``` ## [1.2.6](https://github.com/axios/axios/compare/v1.2.5...v1.2.6) (2023-01-28) ### Bug Fixes - **headers:** added missed Authorization accessor; ([#5502](https://github.com/axios/axios/issues/5502)) ([342c0ba](https://github.com/axios/axios/commit/342c0ba9a16ea50f5ed7d2366c5c1a2c877e3f26)) - **types:** fixed `CommonRequestHeadersList` & `CommonResponseHeadersList` types to be private in commonJS; ([#5503](https://github.com/axios/axios/issues/5503)) ([5a3d0a3](https://github.com/axios/axios/commit/5a3d0a3234d77361a1bc7cedee2da1e11df08e2c)) ### Contributors to this release - ![avatar](https://avatars.githubusercontent.com/u/12586868?v=4&s=16) [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+24/-9 (#5503 #5502 )') ### PRs - CVE 2023 45857 ( [#6028](https://api.github.com/repos/axios/axios/pulls/6028) ) ``` ⚠️ Critical vulnerability fix. See https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459 ``` ## [1.2.5](https://github.com/axios/axios/compare/v1.2.4...v1.2.5) (2023-01-26) ### Bug Fixes - **types:** fixed AxiosHeaders to handle spread syntax by making all methods non-enumerable; ([#5499](https://github.com/axios/axios/issues/5499)) ([580f1e8](https://github.com/axios/axios/commit/580f1e8033a61baa38149d59fd16019de3932c22)) ### Contributors to this release - ![avatar](https://avatars.githubusercontent.com/u/12586868?v=4&s=16) [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+82/-54 (#5499 )') - ![avatar](https://avatars.githubusercontent.com/u/20516159?v=4&s=16) [Elliot Ford](https://github.com/EFord36 '+1/-1 (#5462 )') ### PRs - CVE 2023 45857 ( [#6028](https://api.github.com/repos/axios/axios/pulls/6028) ) ``` ⚠️ Critical vulnerability fix. See https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459 ``` ## [1.2.4](https://github.com/axios/axios/compare/v1.2.3...v1.2.4) (2023-01-22) ### Bug Fixes - **types:** renamed `RawAxiosRequestConfig` back to `AxiosRequestConfig`; ([#5486](https://github.com/axios/axios/issues/5486)) ([2a71f49](https://github.com/axios/axios/commit/2a71f49bc6c68495fa419003a3107ed8bd703ad0)) - **types:** fix `AxiosRequestConfig` generic; ([#5478](https://github.com/axios/axios/issues/5478)) ([9bce81b](https://github.com/axios/axios/commit/186ea062da8b7d578ae78b1a5c220986b9bce81b)) ### Contributors to this release - ![avatar](https://avatars.githubusercontent.com/u/12586868?v=4&s=16) [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+242/-108 (#5486 #5482 )') - ![avatar](https://avatars.githubusercontent.com/u/9430821?v=4&s=16) [Daniel Hillmann](https://github.com/hilleer '+1/-1 (#5478 )') ### PRs - CVE 2023 45857 ( [#6028](https://api.github.com/repos/axios/axios/pulls/6028) ) ``` ⚠️ Critical vulnerability fix. See https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459 ``` ## [1.2.3](https://github.com/axios/axios/compare/1.2.2...1.2.3) (2023-01-10) ### Bug Fixes - **types:** fixed AxiosRequestConfig header interface by refactoring it to RawAxiosRequestConfig; ([#5420](https://github.com/axios/axios/issues/5420)) ([0811963](https://github.com/axios/axios/commit/08119634a22f1d5b19f5c9ea0adccb6d3eebc3bc)) ### Contributors to this release - ![avatar](https://avatars.githubusercontent.com/u/12586868?v=4&s=16) [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS '+938/-442 (#5456 #5455 #5453 #5451 #5449 #5447 #5446 #5443 #5442 #5439 #5420 )') ### PRs - CVE 2023 45857 ( [#6028](https://api.github.com/repos/axios/axios/pulls/6028) ) ``` ⚠️ Critical vulnerability fix. See https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459 ``` ## [1.2.2] - 2022-12-29 ### Fixed - fix(ci): fix release script inputs [#5392](https://github.com/axios/axios/pull/5392) - fix(ci): prerelease scipts [#5377](https://github.com/axios/axios/pull/5377) - fix(ci): release scripts [#5376](https://github.com/axios/axios/pull/5376) - fix(ci): typescript tests [#5375](https://github.com/axios/axios/pull/5375) - fix: Brotli decompression [#5353](https://github.com/axios/axios/pull/5353) - fix: add missing HttpStatusCode [#5345](https://github.com/axios/axios/pull/5345) ### Chores - chore(ci): set conventional-changelog header config [#5406](https://github.com/axios/axios/pull/5406) - chore(ci): fix automatic contributors resolving [#5403](https://github.com/axios/axios/pull/5403) - chore(ci): improved logging for the contributors list generator [#5398](https://github.com/axios/axios/pull/5398) - chore(ci): fix release action [#5397](https://github.com/axios/axios/pull/5397) - chore(ci): fix version bump script by adding bump argument for target version [#5393](https://github.com/axios/axios/pull/5393) - chore(deps): bump decode-uri-component from 0.2.0 to 0.2.2 [#5342](https://github.com/axios/axios/pull/5342) - chore(ci): GitHub Actions Release script [#5384](https://github.com/axios/axios/pull/5384) - chore(ci): release scripts [#5364](https://github.com/axios/axios/pull/5364) ### Contributors to this release - ![avatar](https://avatars.githubusercontent.com/u/12586868?v=4&s=16) [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS) - ![avatar](https://avatars.githubusercontent.com/u/1652293?v=4&s=16) [Winnie](https://github.com/winniehell) ## [1.2.1] - 2022-12-05 ### Changed - feat(exports): export mergeConfig [#5151](https://github.com/axios/axios/pull/5151) ### Fixed - fix(CancelledError): include config [#4922](https://github.com/axios/axios/pull/4922) - fix(general): removing multiple/trailing/leading whitespace [#5022](https://github.com/axios/axios/pull/5022) - fix(headers): decompression for responses without Content-Length header [#5306](https://github.com/axios/axios/pull/5306) - fix(webWorker): exception to sending form data in web worker [#5139](https://github.com/axios/axios/pull/5139) ### Refactors - refactor(types): AxiosProgressEvent.event type to any [#5308](https://github.com/axios/axios/pull/5308) - refactor(types): add missing types for static AxiosError.from method [#4956](https://github.com/axios/axios/pull/4956) ### Chores - chore(docs): remove README link to non-existent upgrade guide [#5307](https://github.com/axios/axios/pull/5307) - chore(docs): typo in issue template name [#5159](https://github.com/axios/axios/pull/5159) ### Contributors to this release - [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS) - [Zachary Lysobey](https://github.com/zachlysobey) - [Kevin Ennis](https://github.com/kevincennis) - [Philipp Loose](https://github.com/phloose) - [secondl1ght](https://github.com/secondl1ght) - [wenzheng](https://github.com/0x30) - [Ivan Barsukov](https://github.com/ovarn) - [Arthur Fiorette](https://github.com/arthurfiorette) ### PRs - CVE 2023 45857 ( [#6028](https://api.github.com/repos/axios/axios/pulls/6028) ) ``` ⚠️ Critical vulnerability fix. See https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459 ``` ## [1.2.0] - 2022-11-10 ### Changed - changed: refactored module exports [#5162](https://github.com/axios/axios/pull/5162) - change: re-added support for loading Axios with require('axios').default [#5225](https://github.com/axios/axios/pull/5225) ### Fixed - fix: improve AxiosHeaders class [#5224](https://github.com/axios/axios/pull/5224) - fix: TypeScript type definitions for commonjs [#5196](https://github.com/axios/axios/pull/5196) - fix: type definition of use method on AxiosInterceptorManager to match the README [#5071](https://github.com/axios/axios/pull/5071) - fix: \_\_dirname is not defined in the sandbox [#5269](https://github.com/axios/axios/pull/5269) - fix: AxiosError.toJSON method to avoid circular references [#5247](https://github.com/axios/axios/pull/5247) - fix: Z_BUF_ERROR when content-encoding is set but the response body is empty [#5250](https://github.com/axios/axios/pull/5250) ### Refactors - refactor: allowing adapters to be loaded by name [#5277](https://github.com/axios/axios/pull/5277) ### Chores - chore: force CI restart [#5243](https://github.com/axios/axios/pull/5243) - chore: update ECOSYSTEM.md [#5077](https://github.com/axios/axios/pull/5077) - chore: update get/index.html [#5116](https://github.com/axios/axios/pull/5116) - chore: update Sandbox UI/UX [#5205](https://github.com/axios/axios/pull/5205) - chore:(actions): remove git credentials after checkout [#5235](https://github.com/axios/axios/pull/5235) - chore(actions): bump actions/dependency-review-action from 2 to 3 [#5266](https://github.com/axios/axios/pull/5266) - chore(packages): bump loader-utils from 1.4.1 to 1.4.2 [#5295](https://github.com/axios/axios/pull/5295) - chore(packages): bump engine.io from 6.2.0 to 6.2.1 [#5294](https://github.com/axios/axios/pull/5294) - chore(packages): bump socket.io-parser from 4.0.4 to 4.0.5 [#5241](https://github.com/axios/axios/pull/5241) - chore(packages): bump loader-utils from 1.4.0 to 1.4.1 [#5245](https://github.com/axios/axios/pull/5245) - chore(docs): update Resources links in README [#5119](https://github.com/axios/axios/pull/5119) - chore(docs): update the link for JSON url [#5265](https://github.com/axios/axios/pull/5265) - chore(docs): fix broken links [#5218](https://github.com/axios/axios/pull/5218) - chore(docs): update and rename UPGRADE_GUIDE.md to MIGRATION_GUIDE.md [#5170](https://github.com/axios/axios/pull/5170) - chore(docs): typo fix line #856 and #920 [#5194](https://github.com/axios/axios/pull/5194) - chore(docs): typo fix #800 [#5193](https://github.com/axios/axios/pull/5193) - chore(docs): fix typos [#5184](https://github.com/axios/axios/pull/5184) - chore(docs): fix punctuation in README.md [#5197](https://github.com/axios/axios/pull/5197) - chore(docs): update readme in the Handling Errors section - issue reference #5260 [#5261](https://github.com/axios/axios/pull/5261) - chore: remove \b from filename [#5207](https://github.com/axios/axios/pull/5207) - chore(docs): update CHANGELOG.md [#5137](https://github.com/axios/axios/pull/5137) - chore: add sideEffects false to package.json [#5025](https://github.com/axios/axios/pull/5025) ### Contributors to this release - [Maddy Miller](https://github.com/me4502) - [Amit Saini](https://github.com/amitsainii) - [ecyrbe](https://github.com/ecyrbe) - [Ikko Ashimine](https://github.com/eltociear) - [Geeth Gunnampalli](https://github.com/thetechie7) - [Shreem Asati](https://github.com/shreem-123) - [Frieder Bluemle](https://github.com/friederbluemle) - [윤세영](https://github.com/yunseyeong) - [Claudio Busatto](https://github.com/cjcbusatto) - [Remco Haszing](https://github.com/remcohaszing) - [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS) - [Csaba Maulis](https://github.com/om4csaba) - [MoPaMo](https://github.com/MoPaMo) - [Daniel Fjeldstad](https://github.com/w3bdesign) - [Adrien Brunet](https://github.com/adrien-may) - [Frazer Smith](https://github.com/Fdawgs) - [HaiTao](https://github.com/836334258) - [AZM](https://github.com/aziyatali) - [relbns](https://github.com/relbns) ### PRs - CVE 2023 45857 ( [#6028](https://api.github.com/repos/axios/axios/pulls/6028) ) ``` ⚠️ Critical vulnerability fix. See https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459 ``` ## [1.1.3] - 2022-10-15 ### Added - Added custom params serializer support [#5113](https://github.com/axios/axios/pull/5113) ### Fixed - Fixed top-level export to keep them in-line with static properties [#5109](https://github.com/axios/axios/pull/5109) - Stopped including null values to query string. [#5108](https://github.com/axios/axios/pull/5108) - Restored proxy config backwards compatibility with 0.x [#5097](https://github.com/axios/axios/pull/5097) - Added back AxiosHeaders in AxiosHeaderValue [#5103](https://github.com/axios/axios/pull/5103) - Pin CDN install instructions to a specific version [#5060](https://github.com/axios/axios/pull/5060) - Handling of array values fixed for AxiosHeaders [#5085](https://github.com/axios/axios/pull/5085) ### Chores - docs: match badge style, add link to them [#5046](https://github.com/axios/axios/pull/5046) - chore: fixing comments typo [#5054](https://github.com/axios/axios/pull/5054) - chore: update issue template [#5061](https://github.com/axios/axios/pull/5061) - chore: added progress capturing section to the docs; [#5084](https://github.com/axios/axios/pull/5084) ### Contributors to this release - [Jason Saayman](https://github.com/jasonsaayman) - [scarf](https://github.com/scarf005) - [Lenz Weber-Tronic](https://github.com/phryneas) - [Arvindh](https://github.com/itsarvindh) - [Félix Legrelle](https://github.com/FelixLgr) - [Patrick Petrovic](https://github.com/ppati000) - [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS) - [littledian](https://github.com/littledian) - [ChronosMasterOfAllTime](https://github.com/ChronosMasterOfAllTime) ### PRs - CVE 2023 45857 ( [#6028](https://api.github.com/repos/axios/axios/pulls/6028) ) ``` ⚠️ Critical vulnerability fix. See https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459 ``` ## [1.1.2] - 2022-10-07 ### Fixed - Fixed broken exports for UMD builds. ### Contributors to this release - [Jason Saayman](https://github.com/jasonsaayman) ### PRs - CVE 2023 45857 ( [#6028](https://api.github.com/repos/axios/axios/pulls/6028) ) ``` ⚠️ Critical vulnerability fix. See https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459 ``` ## [1.1.1] - 2022-10-07 ### Fixed - Fixed broken exports for common js. This fix breaks a prior fix, I will fix both issues ASAP but the commonJS use is more impactful. ### Contributors to this release - [Jason Saayman](https://github.com/jasonsaayman) ### PRs - CVE 2023 45857 ( [#6028](https://api.github.com/repos/axios/axios/pulls/6028) ) ``` ⚠️ Critical vulnerability fix. See https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459 ``` ## [1.1.0] - 2022-10-06 ### Fixed - Fixed missing exports in type definition index.d.ts [#5003](https://github.com/axios/axios/pull/5003) - Fixed query params composing [#5018](https://github.com/axios/axios/pull/5018) - Fixed GenericAbortSignal interface by making it more generic [#5021](https://github.com/axios/axios/pull/5021) - Fixed adding "clear" to AxiosInterceptorManager [#5010](https://github.com/axios/axios/pull/5010) - Fixed commonjs & umd exports [#5030](https://github.com/axios/axios/pull/5030) - Fixed inability to access response headers when using axios 1.x with Jest [#5036](https://github.com/axios/axios/pull/5036) ### Contributors to this release - [Trim21](https://github.com/trim21) - [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS) - [shingo.sasaki](https://github.com/s-sasaki-0529) - [Ivan Pepelko](https://github.com/ivanpepelko) - [Richard Kořínek](https://github.com/risa) ### PRs - CVE 2023 45857 ( [#6028](https://api.github.com/repos/axios/axios/pulls/6028) ) ``` ⚠️ Critical vulnerability fix. See https://security.snyk.io/vuln/SNYK-JS-AXIOS-6032459 ``` ## [1.0.0] - 2022-10-04 ### Added - Added stack trace to AxiosError [#4624](https://github.com/axios/axios/pull/4624) - Add AxiosError to AxiosStatic [#4654](https://github.com/axios/axios/pull/4654) - Replaced Rollup as our build runner [#4596](https://github.com/axios/axios/pull/4596) - Added generic TS types for the exposed toFormData helper [#4668](https://github.com/axios/axios/pull/4668) - Added listen callback function [#4096](https://github.com/axios/axios/pull/4096) - Added instructions for installing using PNPM [#4207](https://github.com/axios/axios/pull/4207) - Added generic AxiosAbortSignal TS interface to avoid importing AbortController polyfill [#4229](https://github.com/axios/axios/pull/4229) - Added axios-url-template in ECOSYSTEM.md [#4238](https://github.com/axios/axios/pull/4238) - Added a clear() function to the request and response interceptors object so a user can ensure that all interceptors have been removed from an axios instance [#4248](https://github.com/axios/axios/pull/4248) - Added react hook plugin [#4319](https://github.com/axios/axios/pull/4319) - Adding HTTP status code for transformResponse [#4580](https://github.com/axios/axios/pull/4580) - Added blob to the list of protocols supported by the browser [#4678](https://github.com/axios/axios/pull/4678) - Resolving proxy from env on redirect [#4436](https://github.com/axios/axios/pull/4436) - Added enhanced toFormData implementation with additional options [4704](https://github.com/axios/axios/pull/4704) - Adding Canceler parameters config and request [#4711](https://github.com/axios/axios/pull/4711) - Added automatic payload serialization to application/x-www-form-urlencoded [#4714](https://github.com/axios/axios/pull/4714) - Added the ability for webpack users to overwrite built-ins [#4715](https://github.com/axios/axios/pull/4715) - Added string[] to AxiosRequestHeaders type [#4322](https://github.com/axios/axios/pull/4322) - Added the ability for the url-encoded-form serializer to respect the formSerializer config [#4721](https://github.com/axios/axios/pull/4721) - Added isCancel type assert [#4293](https://github.com/axios/axios/pull/4293) - Added data URL support for node.js [#4725](https://github.com/axios/axios/pull/4725) - Adding types for progress event callbacks [#4675](https://github.com/axios/axios/pull/4675) - URL params serializer [#4734](https://github.com/axios/axios/pull/4734) - Added axios.formToJSON method [#4735](https://github.com/axios/axios/pull/4735) - Bower platform add data protocol [#4804](https://github.com/axios/axios/pull/4804) - Use WHATWG URL API instead of url.parse() [#4852](https://github.com/axios/axios/pull/4852) - Add ENUM containing Http Status Codes to typings [#4903](https://github.com/axios/axios/pull/4903) - Improve typing of timeout in index.d.ts [#4934](https://github.com/axios/axios/pull/4934) ### Changed - Updated AxiosError.config to be optional in the type definition [#4665](https://github.com/axios/axios/pull/4665) - Updated README emphasizing the URLSearchParam built-in interface over other solutions [#4590](https://github.com/axios/axios/pull/4590) - Include request and config when creating a CanceledError instance [#4659](https://github.com/axios/axios/pull/4659) - Changed func-names eslint rule to as-needed [#4492](https://github.com/axios/axios/pull/4492) - Replacing deprecated substr() with slice() as substr() is deprecated [#4468](https://github.com/axios/axios/pull/4468) - Updating HTTP links in README.md to use HTTPS [#4387](https://github.com/axios/axios/pull/4387) - Updated to a better trim() polyfill [#4072](https://github.com/axios/axios/pull/4072) - Updated types to allow specifying partial default headers on instance create [#4185](https://github.com/axios/axios/pull/4185) - Expanded isAxiosError types [#4344](https://github.com/axios/axios/pull/4344) - Updated type definition for axios instance methods [#4224](https://github.com/axios/axios/pull/4224) - Updated eslint config [#4722](https://github.com/axios/axios/pull/4722) - Updated Docs [#4742](https://github.com/axios/axios/pull/4742) - Refactored Axios to use ES2017 [#4787](https://github.com/axios/axios/pull/4787) ### Deprecated - There are multiple deprecations, refactors and fixes provided in this release. Please read through the full release notes to see how this may impact your project and use case. ### Removed - Removed incorrect argument for NetworkError constructor [#4656](https://github.com/axios/axios/pull/4656) - Removed Webpack [#4596](https://github.com/axios/axios/pull/4596) - Removed function that transform arguments to array [#4544](https://github.com/axios/axios/pull/4544) ### Fixed - Fixed grammar in README [#4649](https://github.com/axios/axios/pull/4649) - Fixed code error in README [#4599](https://github.com/axios/axios/pull/4599) - Optimized the code that checks cancellation [#4587](https://github.com/axios/axios/pull/4587) - Fix url pointing to defaults.js in README [#4532](https://github.com/axios/axios/pull/4532) - Use type alias instead of interface for AxiosPromise [#4505](https://github.com/axios/axios/pull/4505) - Fix some word spelling and lint style in code comments [#4500](https://github.com/axios/axios/pull/4500) - Edited readme with 3 updated browser icons of Chrome, FireFox and Safari [#4414](https://github.com/axios/axios/pull/4414) - Bump follow-redirects from 1.14.9 to 1.15.0 [#4673](https://github.com/axios/axios/pull/4673) - Fixing http tests to avoid hanging when assertions fail [#4435](https://github.com/axios/axios/pull/4435) - Fix TS definition for AxiosRequestTransformer [#4201](https://github.com/axios/axios/pull/4201) - Fix grammatical issues in README [#4232](https://github.com/axios/axios/pull/4232) - Fixing instance.defaults.headers type [#4557](https://github.com/axios/axios/pull/4557) - Fixed race condition on immediate requests cancellation [#4261](https://github.com/axios/axios/pull/4261) - Fixing Z_BUF_ERROR when no content [#4701](https://github.com/axios/axios/pull/4701) - Fixing proxy beforeRedirect regression [#4708](https://github.com/axios/axios/pull/4708) - Fixed AxiosError status code type [#4717](https://github.com/axios/axios/pull/4717) - Fixed AxiosError stack capturing [#4718](https://github.com/axios/axios/pull/4718) - Fixing AxiosRequestHeaders typings [#4334](https://github.com/axios/axios/pull/4334) - Fixed max body length defaults [#4731](https://github.com/axios/axios/pull/4731) - Fixed toFormData Blob issue on node>v17 [#4728](https://github.com/axios/axios/pull/4728) - Bump grunt from 1.5.2 to 1.5.3 [#4743](https://github.com/axios/axios/pull/4743) - Fixing content-type header repeated [#4745](https://github.com/axios/axios/pull/4745) - Fixed timeout error message for http [4738](https://github.com/axios/axios/pull/4738) - Request ignores false, 0 and empty string as body values [#4785](https://github.com/axios/axios/pull/4785) - Added back missing minified builds [#4805](https://github.com/axios/axios/pull/4805) - Fixed a type error [#4815](https://github.com/axios/axios/pull/4815) - Fixed a regression bug with unsubscribing from cancel token; [#4819](https://github.com/axios/axios/pull/4819) - Remove repeated compression algorithm [#4820](https://github.com/axios/axios/pull/4820) - The error of calling extend to pass parameters [#4857](https://github.com/axios/axios/pull/4857) - SerializerOptions.indexes allows boolean | null | undefined [#4862](https://github.com/axios/axios/pull/4862) - Require interceptors to return values [#4874](https://github.com/axios/axios/pull/4874) - Removed unused imports [#4949](https://github.com/axios/axios/pull/4949) - Allow null indexes on formSerializer and paramsSerializer [#4960](https://github.com/axios/axios/pull/4960) ### Chores - Set permissions for GitHub actions [#4765](https://github.com/axios/axios/pull/4765) - Included githubactions in the dependabot config [#4770](https://github.com/axios/axios/pull/4770) - Included dependency review [#4771](https://github.com/axios/axios/pull/4771) - Update security.md [#4784](https://github.com/axios/axios/pull/4784) - Remove unnecessary spaces [#4854](https://github.com/axios/axios/pull/4854) - Simplify the import path of AxiosError [#4875](https://github.com/axios/axios/pull/4875) - Fix Gitpod dead link [#4941](https://github.com/axios/axios/pull/4941) - Enable syntax highlighting for a code block [#4970](https://github.com/axios/axios/pull/4970) - Using Logo Axios in Readme.md [#4993](https://github.com/axios/axios/pull/4993) - Fix markup for note in README [#4825](https://github.com/axios/axios/pull/4825) - Fix typo and formatting, add colons [#4853](https://github.com/axios/axios/pull/4853) - Fix typo in readme [#4942](https://github.com/axios/axios/pull/4942) ### Security - Update SECURITY.md [#4687](https://github.com/axios/axios/pull/4687) ### Contributors to this release - [Bertrand Marron](https://github.com/tusbar) - [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS) - [Dan Mooney](https://github.com/danmooney) - [Michael Li](https://github.com/xiaoyu-tamu) - [aong](https://github.com/yxwzaxns) - [Des Preston](https://github.com/despreston) - [Ted Robertson](https://github.com/tredondo) - [zhoulixiang](https://github.com/zh-lx) - [Arthur Fiorette](https://github.com/arthurfiorette) - [Kumar Shanu](https://github.com/Kr-Shanu) - [JALAL](https://github.com/JLL32) - [Jingyi Lin](https://github.com/MageeLin) - [Philipp Loose](https://github.com/phloose) - [Alexander Shchukin](https://github.com/sashsvamir) - [Dave Cardwell](https://github.com/davecardwell) - [Cat Scarlet](https://github.com/catscarlet) - [Luca Pizzini](https://github.com/lpizzinidev) - [Kai](https://github.com/Schweinepriester) - [Maxime Bargiel](https://github.com/mbargiel) - [Brian Helba](https://github.com/brianhelba) - [reslear](https://github.com/reslear) - [Jamie Slome](https://github.com/JamieSlome) - [Landro3](https://github.com/Landro3) - [rafw87](https://github.com/rafw87) - [Afzal Sayed](https://github.com/afzalsayed96) - [Koki Oyatsu](https://github.com/kaishuu0123) - [Dave](https://github.com/wangcch) - [暴走老七](https://github.com/baozouai) - [Spencer](https://github.com/spalger) - [Adrian Wieprzkowicz](https://github.com/Argeento) - [Jamie Telin](https://github.com/lejahmie) - [毛呆](https://github.com/aweikalee) - [Kirill Shakirov](https://github.com/turisap) - [Rraji Abdelbari](https://github.com/estarossa0) - [Jelle Schutter](https://github.com/jelleschutter) - [Tom Ceuppens](https://github.com/KyorCode) - [Johann Cooper](https://github.com/JohannCooper) - [Dimitris Halatsis](https://github.com/mitsos1os) - [chenjigeng](https://github.com/chenjigeng) - [João Gabriel Quaresma](https://github.com/joaoGabriel55) - [Victor Augusto](https://github.com/VictorAugDB) - [neilnaveen](https://github.com/neilnaveen) - [Pavlos](https://github.com/psmoros) - [Kiryl Valkovich](https://github.com/visortelle) - [Naveen](https://github.com/naveensrinivasan) - [wenzheng](https://github.com/0x30) - [hcwhan](https://github.com/hcwhan) - [Bassel Rachid](https://github.com/basselworkforce) - [Grégoire Pineau](https://github.com/lyrixx) - [felipedamin](https://github.com/felipedamin) - [Karl Horky](https://github.com/karlhorky) - [Yue JIN](https://github.com/kingyue737) - [Usman Ali Siddiqui](https://github.com/usman250994) - [WD](https://github.com/techbirds) - [Günther Foidl](https://github.com/gfoidl) - [Stephen Jennings](https://github.com/jennings) - [C.T.Lin](https://github.com/chentsulin) - [mia-z](https://github.com/mia-z) - [Parth Banathia](https://github.com/Parth0105) - [parth0105pluang](https://github.com/parth0105pluang) - [Marco Weber](https://github.com/mrcwbr) - [Luca Pizzini](https://github.com/lpizzinidev) - [Willian Agostini](https://github.com/WillianAgostini) - [Huyen Nguyen](https://github.com/huyenltnguyen) axios-axios-2d06f96/CLAUDE.md000066400000000000000000000000131521272452000155710ustar00rootroot00000000000000@AGENTS.md axios-axios-2d06f96/CODE_OF_CONDUCT.md000066400000000000000000000031721521272452000171220ustar00rootroot00000000000000# Code of conduct ## Our pledge Contributors and community members commit to a welcoming, safe, and harassment-free environment for everyone. We welcome people regardless of age, body size, disability, ethnicity, gender identity or expression, experience level, education, nationality, race, religion, sexual orientation, or any other personal characteristic. ## Our standards Examples of positive behavior include: - Showing empathy and kindness toward others - Being respectful of different opinions and experiences - Accepting constructive feedback and learning from it - Taking responsibility for mistakes and offering sincere apologies Unacceptable behaviors include: - Sexualized language, imagery, or unwanted advances - Personal attacks, trolling, or insulting comments - Publishing private information (such as email or address) without permission - Any other conduct that would be considered inappropriate in a professional setting ## Enforcement Report unacceptable behavior to the maintainers at [jasonsaayman@gmail.com](mailto:jasonsaayman@gmail.com). Maintainers will review reports promptly and handle them confidentially. ## Enforcement guidelines 1. Correction: a private warning and an explanation of why the behavior was inappropriate. 2. Warning: a clear warning with consequences for continued behavior. 3. Temporary ban: a temporary ban for repeated or severe violations. 4. Permanent ban: permanent removal for repeated harassment or sustained inappropriate conduct. --- _This code of conduct is adapted from the [Contributor Covenant, version 2.1](https://www.contributor-covenant.org/version/2/1/code_of_conduct.html)._ axios-axios-2d06f96/COLLABORATOR_GUIDE.md000066400000000000000000000113751521272452000174510ustar00rootroot00000000000000# Collaborator guide As a collaborator, you help administer axios. This guide covers the responsibilities that come with that access. For architecture, lifecycle, security-sensitive code, and conventions, use [AGENTS.md](./AGENTS.md), the canonical contributor guide. ## Code of conduct Read the [Code of Conduct](./CODE_OF_CONDUCT.md) and help enforce it. Keep the community friendly and welcoming. ## Triage issues - Apply appropriate labels and respond as needed. - For bug reports, ask for a minimal reproduction (axios version, environment, request/response details) before deeper triage. - If an issue is not directly about axios, convert it to a discussion. - Close issues only when they are resolved, a fix is merged, the report lacks enough detail or a reproduction, or the reporter requests closure. Do not close issues for inactivity. We want to keep the history and respond if more information comes in later. ## Answer questions Be helpful and patient. If a question comes from unclear docs, update the docs and consider adding an example instead of only answering in the thread. You are not expected to teach JavaScript or unrelated tooling. Redirect those questions politely. ## Submit PRs When opening a PR, make sure: - The change fits within axios. Decline features early and kindly when they belong in user code or a plugin. - Cover behavior across the XHR, Fetch, and Node HTTP adapters where relevant. Detect by capability, not environment name. - Update both `index.d.ts` (ESM) and `index.d.cts` (CJS) when the public API changes. - Make axios-originated failures throw `AxiosError` with an appropriate code, never raw `Error`. Wrap third-party errors with `AxiosError.from`. - Cover the change with unit tests. Update browser, smoke, or module suites when packaging or runtime surface is affected. - Lint and tests pass before review. Do not merge red PRs. - Do not add runtime dependencies without discussion. `package-lock.json` changes must keep `lockfile-lint` happy (npm HTTPS hosts, integrity hashes). - Package and GitHub Actions update PRs are maintainer/bot-only. Close PRs from outside collaborators that only update npm packages, lockfiles, or GitHub Actions versions. - Keep the 7-day Dependabot delay for these updates. Bypass it only when a critical vulnerability requires a maintainer-led manual update. - Security-sensitive changes get extra scrutiny and focused regression tests. This includes URL construction, redirects, proxy/env handling, XSRF, socket paths, decompression limits, prototype walking, and adapters. Consult [THREATMODEL.md](./THREATMODEL.md). - Warn before removing functionality. - New public API surface is predictable, consistent with existing options, and documented. - PR titles use [Conventional Commits](https://www.conventionalcommits.org/) (`fix:`, `feat:`, `chore:`, `docs:`, etc.). Release tooling depends on this. - Call out whether the change is patch, minor, or breaking, and target the right branch (`v1.x` for the current maintenance line; breaking work goes elsewhere). At least one maintainer must review and approve a PR before merge. If you are unsure about the impact of a change, ask for a second opinion. Call out breaking changes in the PR description and send them to the appropriate branch. Bug fixes need a test that reproduces the issue and verifies the fix. If changes are requested, address them promptly. If you cannot make the changes, say so clearly so someone else can pick them up. > [!IMPORTANT] > We wait up to 28 days for a response to requested changes before closing the PR as stale. After that, we will either address the issue in a maintainer-led PR or open an issue for other contributors. If the author wants to continue the work, they should recreate the PR from the latest version of the correct target branch, address all feedback, and request review from a maintainer. ## Security disclosures If someone reports a suspected vulnerability in a public issue, do not discuss specifics in the thread. Redirect them to the process described in [SECURITY.md](./SECURITY.md) (GitHub security advisories) and close or hide the issue as appropriate. ## What collaborators should not do - Add runtime dependencies without discussion. The dependency surface is intentionally tiny. - Merge package, lockfile, or GitHub Actions version update PRs from outside collaborators. - Disable `ignore-scripts` in `.npmrc` or otherwise weaken install-time safety. - Weaken `beforeRedirect`, proxy, `socketPath`, XSRF, or prototype-pollution safeguards without tests covering the regression cases. --- Thanks for helping keep axios healthy. If you are unsure about a call, ask another collaborator before acting. We would rather move a little slower than ship a regression. If you have questions about your role or responsibilities, contact the maintainers. axios-axios-2d06f96/CONTRIBUTING.md000066400000000000000000000026651521272452000165620ustar00rootroot00000000000000# Contributing We accept community contributions. By contributing to axios, you agree to follow the [code of conduct](https://github.com/axios/axios/blob/master/CODE_OF_CONDUCT.md). ## Code style Follow the [node style guide](https://github.com/felixge/node-style-guide). ## Commit messages Follow [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/). ## Testing Update tests for your changes. Pull requests must pass GitHub Actions. ## Documentation Update the [documentation](https://axios-http.com/docs/intro) when the API changes, so the API and docs stay in sync. ## Dependency and GitHub Actions updates Please do not open pull requests that only update npm packages, lockfiles, or GitHub Actions versions. We close these PRs from outside collaborators. Only maintainers and approved automated bots may create package and GitHub Actions update PRs. We keep the 7-day Dependabot delay for these updates unless a critical vulnerability requires a maintainer-led manual update. ## Developing - `npm run test` runs the Jasmine and Mocha tests - `npm run build` runs Rollup and bundles the source - `npm run version` prepares the code for release ## Running examples Use the examples for manual testing. Run the examples: ```bash > npm run examples # Open 127.0.0.1:3000 ``` Run the browser sandbox: ```bash > npm start # Open 127.0.0.1:3000 ``` Run the terminal sandbox: ```bash > npm start > node ./sandbox/client ``` axios-axios-2d06f96/CONTRIBUTORS.md000066400000000000000000000010651521272452000166010ustar00rootroot00000000000000# Contributors Thanks to everyone who has contributed to axios. ## Core team - [Jay](https://github.com/jasonsaayman) - Lead Maintainer - [Dmitriy Mozgovoy](https://github.com/DigitalBrainJS) - Core Contributor - [Matt Zabriskie](https://github.com/mzabriskie) - Creator ## Notable contributors ## How to contribute To contribute, read the [Contributing Guide](CONTRIBUTING.md). --- _This list is maintained by hand. If you've contributed and want to be listed, open a pull request._ axios-axios-2d06f96/ECOSYSTEM.md000066400000000000000000000072031521272452000162170ustar00rootroot00000000000000# Ecosystem This is a list of axios-related libraries and resources. To add one, open a pull request. ## Libraries ### General - [axios-vcr](https://github.com/nettofarah/axios-vcr) - Records and replays axios requests - [@3846masa/axios-cookiejar-support](https://github.com/3846masa/axios-cookiejar-support) - Adds tough-cookie support to axios - [axios-method-override](https://github.com/jacobbuck/axios-method-override) - Overrides HTTP request methods in axios - [axios-cache-plugin](https://github.com/jin5354/axios-cache-plugin) - Caches GET requests made with axios - [axios-extensions](https://github.com/kuitos/axios-extensions) - Adds axios extensions, including throttling and GET request caching - [axios-fetch](https://github.com/lifeomic/axios-fetch) - Provides a Web API Fetch implementation backed by an axios client - [axios-actions](https://github.com/davestewart/axios-actions) - Bundles endpoints as callable, reusable services - [axios-api-versioning](https://weffe.github.io/axios-api-versioning) - Adds API version management to axios - [axios-data-unpacker](https://github.com/anubhavsrivastava/axios-data-unpacker) - Unpacks HTTP responses through an axios interceptor - [r2curl](https://github.com/uyu423/r2curl) - Extracts cURL command strings from axios objects. (AxiosResponse, AxiosRequestConfig) - [axios-endpoints](https://github.com/renancaraujo/axios-endpoints) - Defines concise endpoint mappings for axios - [axios-multi-api](https://github.com/MattCCC/axios-multi-api) - Handles multiple APIs with declarative axios request definitions - [axios-url-template](https://github.com/rafw87/axios-url-template) - Adds URL template support through an axios interceptor ### API clients - [@hey-api/openapi-ts](https://heyapi.dev/openapi-ts/clients/axios) - Generates TypeScript clients, SDKs, and validators from OpenAPI schemas - [swagger-taxos-codegen](https://github.com/michalzaq12/swagger-taxos-codegen) - Generates TypeScript Swagger clients that use axios - [zodios](https://www.zodios.org) - Type-safe API client based on axios ### Logging and debugging - [axios-response-logger](https://github.com/srph/axios-response-logger) - Logs responses through an axios interceptor - [axios-debug-log](https://github.com/Gerhut/axios-debug-log) - Logs axios requests and responses with debug - [axios-curlirize](https://www.npmjs.com/package/axios-curlirize) - Logs axios requests as cURL commands and attaches the command to the response object ### React and redux - [axios-hooks](https://github.com/simoneb/axios-hooks) - React hooks for axios, with built-in support for server-side rendering - [react-hooks-axios](https://github.com/use-hooks/react-hooks-axios) - Custom React hooks for axios - [redux-saga-requests](https://github.com/klis87/redux-saga-requests) - Redux-Saga addon for AJAX request handling - [redux-axios-middleware](https://github.com/svrcekmichal/redux-axios-middleware) - Redux middleware for fetching data with axios HTTP client - [@react-cmpt/react-request-hook](https://github.com/react-cmpt/react-request-hook) - Lightweight React hook plugin for axios with minimal code changes ### Unit testing - [axiosist](https://github.com/Gerhut/axiosist) - Converts Node.js request handlers into axios adapters for server unit tests - [axios-mock-adapter](https://github.com/ctimmerm/axios-mock-adapter) - Mocks axios requests through a custom adapter - [axios-test-instance](https://github.com/remcohaszing/axios-test-instance) - Tests Node.js backends with axios - [moxios](https://github.com/axios/moxios) - Mocks axios requests for testing - [mocha-axios](https://github.com/jdrydn/mocha-axios) - Streamlines integration testing with Mocha and axios axios-axios-2d06f96/LICENSE000066400000000000000000000020741521272452000153300ustar00rootroot00000000000000# Copyright (c) 2014-present Matt Zabriskie & Collaborators Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. axios-axios-2d06f96/MIGRATION_GUIDE.md000066400000000000000000000523561521272452000171230ustar00rootroot00000000000000# Axios Migration Guide > **Migrating from Axios 0.x to 1.x** > > This guide helps developers upgrade from Axios 0.x to 1.x by documenting breaking changes, providing migration strategies, and offering solutions to common upgrade challenges. ## Table of Contents - [Overview](#overview) - [Breaking Changes](#breaking-changes) - [Error Handling Migration](#error-handling-migration) - [API Changes](#api-changes) - [Configuration Changes](#configuration-changes) - [Migration Strategies](#migration-strategies) - [Common Patterns](#common-patterns) - [Troubleshooting](#troubleshooting) - [Resources](#resources) ## Overview Axios 1.x introduced several breaking changes to improve consistency, security, and developer experience. While these changes provide better error handling and more predictable behavior, they require code updates when migrating from 0.x versions. ### Key Changes Summary | Area | 0.x Behavior | 1.x Behavior | Impact | |------|--------------|--------------|--------| | Error Handling | Selective throwing | Consistent throwing | High | | JSON Parsing | Lenient | Strict | Medium | | Browser Support | IE11+ | Modern browsers | Low-Medium | | TypeScript | Partial | Full support | Low | ### Migration Complexity - **Simple applications**: 1-2 hours - **Medium applications**: 1-2 days - **Large applications with complex error handling**: 3-5 days ## Breaking Changes ### 1. Error Handling Changes **The most significant change in Axios 1.x is how errors are handled.** #### 0.x Behavior ```javascript // Axios 0.x - Some HTTP error codes didn't throw axios.get('/api/data') .then(response => { // Response interceptor could handle all errors console.log('Success:', response.data); }); // Response interceptor handled everything axios.interceptors.response.use( response => response, error => { handleError(error); // Error was "handled" and didn't propagate } ); ``` #### 1.x Behavior ```javascript // Axios 1.x - All HTTP errors throw consistently axios.get('/api/data') .then(response => { console.log('Success:', response.data); }) .catch(error => { // Must handle errors at call site or they propagate console.error('Request failed:', error); }); // Response interceptor must re-throw or return rejected promise axios.interceptors.response.use( response => response, error => { handleError(error); // Must explicitly handle propagation return Promise.reject(error); // or throw error; } ); ``` #### Impact - **Response interceptors** can no longer "swallow" errors silently - **Every API call** must handle errors explicitly or they become unhandled promise rejections - **Centralized error handling** requires new patterns ### 2. JSON Parsing Changes #### 0.x Behavior ```javascript // Axios 0.x - Lenient JSON parsing // Would attempt to parse even invalid JSON response.data; // Might contain partial data or fallbacks ``` #### 1.x Behavior ```javascript // Axios 1.x - Strict JSON parsing // Throws clear errors for invalid JSON try { const data = response.data; } catch (error) { // Handle JSON parsing errors explicitly } ``` ### 3. Request/Response Transform Changes #### 0.x Behavior ```javascript // Implicit transformations with some edge cases transformRequest: [function (data) { // Less predictable behavior return data; }] ``` #### 1.x Behavior ```javascript // More consistent transformation pipeline transformRequest: [function (data, headers) { // Headers parameter always available // More predictable behavior return data; }] ``` ### 4. Browser Support Changes - **0.x**: Supported IE11 and older browsers - **1.x**: Requires modern browsers with Promise support - **Polyfills**: May be needed for older browser support ## Error Handling Migration The error handling changes are the most complex part of migrating to Axios 1.x. Here are proven strategies: ### Strategy 1: Centralized Error Handling with Error Boundary ```javascript // Create a centralized error handler class ApiErrorHandler { constructor() { this.setupInterceptors(); } setupInterceptors() { axios.interceptors.response.use( response => response, error => { // Centralized error processing this.processError(error); // Return a resolved promise with error info for handled errors if (this.isHandledError(error)) { return Promise.resolve({ data: null, error: this.normalizeError(error), handled: true }); } // Re-throw unhandled errors return Promise.reject(error); } ); } processError(error) { // Log errors console.error('API Error:', error); // Show user notifications if (error.response?.status === 401) { this.handleAuthError(); } else if (error.response?.status >= 500) { this.showErrorNotification('Server error occurred'); } } isHandledError(error) { // Define which errors are "handled" centrally const handledStatuses = [401, 403, 404, 422, 500, 502, 503]; return handledStatuses.includes(error.response?.status); } normalizeError(error) { return { status: error.response?.status, message: error.response?.data?.message || error.message, code: error.response?.data?.code || error.code }; } handleAuthError() { // Redirect to login, clear tokens, etc. localStorage.removeItem('token'); window.location.href = '/login'; } showErrorNotification(message) { // Show user-friendly error message console.error(message); // Replace with your notification system } } // Initialize globally const errorHandler = new ApiErrorHandler(); // Usage in components/services async function fetchUserData(userId) { try { const response = await axios.get(`/api/users/${userId}`); // Check if error was handled centrally if (response.handled) { return { data: null, error: response.error }; } return { data: response.data, error: null }; } catch (error) { // Unhandled errors still need local handling return { data: null, error: { message: 'Unexpected error occurred' } }; } } ``` ### Strategy 2: Wrapper Function Pattern ```javascript // Create a wrapper that provides 0.x-like behavior function createApiWrapper() { const api = axios.create(); // Add response interceptor for centralized handling api.interceptors.response.use( response => response, error => { // Handle common errors centrally if (error.response?.status === 401) { // Handle auth errors handleAuthError(); } if (error.response?.status >= 500) { // Handle server errors showServerErrorNotification(); } // Always reject to maintain error propagation return Promise.reject(error); } ); // Wrapper function that mimics 0.x behavior function safeRequest(requestConfig, options = {}) { return api(requestConfig) .then(response => response) .catch(error => { if (options.suppressErrors) { // Return error info instead of throwing return { data: null, error: { status: error.response?.status, message: error.response?.data?.message || error.message } }; } throw error; }); } return { safeRequest, axios: api }; } // Usage const { safeRequest } = createApiWrapper(); // For calls where you want centralized error handling const result = await safeRequest( { method: 'get', url: '/api/data' }, { suppressErrors: true } ); if (result.error) { // Handle error case console.log('Request failed:', result.error.message); } else { // Handle success case console.log('Data:', result.data); } ``` ### Strategy 3: Global Error Handler with Custom Events ```javascript // Set up global error handling with events class GlobalErrorHandler extends EventTarget { constructor() { super(); this.setupInterceptors(); } setupInterceptors() { axios.interceptors.response.use( response => response, error => { // Emit custom event for global handling this.dispatchEvent(new CustomEvent('apiError', { detail: { error, timestamp: new Date() } })); // Always reject to maintain proper error flow return Promise.reject(error); } ); } } const globalErrorHandler = new GlobalErrorHandler(); // Set up global listeners globalErrorHandler.addEventListener('apiError', (event) => { const { error } = event.detail; // Centralized error logic if (error.response?.status === 401) { handleAuthError(); } if (error.response?.status >= 500) { showErrorNotification('Server error occurred'); } }); // Usage remains clean async function apiCall() { try { const response = await axios.get('/api/data'); return response.data; } catch (error) { // Error was already handled globally // Just handle component-specific logic return null; } } ``` ## API Changes ### Request Configuration #### 0.x to 1.x Changes ```javascript // 0.x - Some properties had different defaults const config = { timeout: 0, // No timeout by default maxContentLength: -1, // No limit }; // 1.x - More secure defaults const config = { timeout: 0, // Still no timeout, but easier to configure maxContentLength: 2000, // Default limit for security maxBodyLength: 2000, // New property }; ``` ### Response Object The response object structure remains largely the same, but error responses are more consistent: ```javascript // Both 0.x and 1.x response = { data: {}, // Response body status: 200, // HTTP status statusText: 'OK', // HTTP status message headers: {}, // Response headers config: {}, // Request config request: {} // Request object }; // Error responses are more consistent in 1.x error.response = { data: {}, // Error response body status: 404, // HTTP error status statusText: 'Not Found', headers: {}, config: {}, request: {} }; ``` ## Configuration Changes ### Default Configuration Updates ```javascript // 0.x defaults axios.defaults.timeout = 0; // No timeout axios.defaults.maxContentLength = -1; // No limit // 1.x defaults (more secure) axios.defaults.timeout = 0; // Still no timeout axios.defaults.maxContentLength = 2000; // 2MB limit axios.defaults.maxBodyLength = 2000; // 2MB limit ``` ### Instance Configuration ```javascript // 0.x - Instance creation const api = axios.create({ baseURL: 'https://api.example.com', timeout: 1000, }); // 1.x - Same API, but more options available const api = axios.create({ baseURL: 'https://api.example.com', timeout: 1000, maxBodyLength: Infinity, // Override default if needed maxContentLength: Infinity, }); ``` ## Migration Strategies ### Step-by-Step Migration Process #### Phase 1: Preparation 1. **Audit Current Error Handling** ```bash # Find all axios usage grep -r "axios\." src/ grep -r "\.catch" src/ grep -r "interceptors" src/ ``` 2. **Identify Patterns** - Response interceptors that handle errors - Components that rely on centralized error handling - Authentication and retry logic 3. **Create Test Cases** ```javascript // Test current error handling behavior describe('Error Handling Migration', () => { it('should handle 401 errors consistently', async () => { // Test authentication error flows }); it('should handle 500 errors with user feedback', async () => { // Test server error handling }); }); ``` #### Phase 2: Implementation 1. **Update Dependencies** ```bash npm update axios ``` 2. **Implement New Error Handling** - Choose one of the strategies above - Update response interceptors - Add error handling to API calls 3. **Update Authentication Logic** ```javascript // 0.x pattern axios.interceptors.response.use(null, error => { if (error.response?.status === 401) { logout(); // Error was "handled" } }); // 1.x pattern axios.interceptors.response.use( response => response, error => { if (error.response?.status === 401) { logout(); } return Promise.reject(error); // Always propagate } ); ``` #### Phase 3: Testing and Validation 1. **Test Error Scenarios** - Network failures - HTTP error codes (401, 403, 404, 500, etc.) - Timeout errors - JSON parsing errors 2. **Validate User Experience** - Error messages are shown appropriately - Authentication redirects work - Loading states are handled correctly ### Gradual Migration Approach For large applications, consider gradual migration: ```javascript // Create a compatibility layer const axiosCompat = { // Use new axios instance for new code v1: axios.create({ // 1.x configuration }), // Wrapper for legacy code legacy: createLegacyWrapper(axios.create({ // Configuration that mimics 0.x behavior })) }; function createLegacyWrapper(axiosInstance) { // Add interceptors that provide 0.x-like behavior axiosInstance.interceptors.response.use( response => response, error => { // Handle errors in 0.x style for legacy code handleLegacyError(error); // Don't propagate certain errors if (shouldSuppressError(error)) { return Promise.resolve({ data: null, error: true }); } return Promise.reject(error); } ); return axiosInstance; } ``` ## Common Patterns ### Authentication Interceptors #### Updated Authentication Pattern ```javascript // Token refresh interceptor for 1.x let isRefreshing = false; let refreshSubscribers = []; function subscribeTokenRefresh(cb) { refreshSubscribers.push(cb); } function onTokenRefreshed(token) { refreshSubscribers.forEach(cb => cb(token)); refreshSubscribers = []; } axios.interceptors.response.use( response => response, async error => { const originalRequest = error.config; if (error.response?.status === 401 && !originalRequest._retry) { if (isRefreshing) { // Wait for token refresh return new Promise(resolve => { subscribeTokenRefresh(token => { originalRequest.headers.Authorization = `Bearer ${token}`; resolve(axios(originalRequest)); }); }); } originalRequest._retry = true; isRefreshing = true; try { const newToken = await refreshToken(); onTokenRefreshed(newToken); isRefreshing = false; originalRequest.headers.Authorization = `Bearer ${newToken}`; return axios(originalRequest); } catch (refreshError) { isRefreshing = false; logout(); return Promise.reject(refreshError); } } return Promise.reject(error); } ); ``` ### Retry Logic ```javascript // Retry interceptor for 1.x function createRetryInterceptor(maxRetries = 3, retryDelay = 1000) { return axios.interceptors.response.use( response => response, async error => { const config = error.config; if (!config || !config.retry) { return Promise.reject(error); } config.__retryCount = config.__retryCount || 0; if (config.__retryCount >= maxRetries) { return Promise.reject(error); } config.__retryCount += 1; // Exponential backoff const delay = retryDelay * Math.pow(2, config.__retryCount - 1); await new Promise(resolve => setTimeout(resolve, delay)); return axios(config); } ); } // Usage const api = axios.create(); createRetryInterceptor(3, 1000); // Make request with retry api.get('/api/data', { retry: true }); ``` ### Loading State Management ```javascript // Loading interceptor for 1.x class LoadingManager { constructor() { this.requests = new Set(); this.setupInterceptors(); } setupInterceptors() { axios.interceptors.request.use(config => { this.requests.add(config); this.updateLoadingState(); return config; }); axios.interceptors.response.use( response => { this.requests.delete(response.config); this.updateLoadingState(); return response; }, error => { this.requests.delete(error.config); this.updateLoadingState(); return Promise.reject(error); } ); } updateLoadingState() { const isLoading = this.requests.size > 0; // Update your loading UI document.body.classList.toggle('loading', isLoading); } } const loadingManager = new LoadingManager(); ``` ## Troubleshooting ### Common Migration Issues #### Issue 1: Unhandled Promise Rejections **Problem:** ```javascript // This pattern worked in 0.x but causes unhandled rejections in 1.x axios.get('/api/data'); // No .catch() handler ``` **Solution:** ```javascript // Always handle promises axios.get('/api/data') .catch(error => { // Handle error appropriately console.error('Request failed:', error.message); }); // Or use async/await with try/catch async function fetchData() { try { const response = await axios.get('/api/data'); return response.data; } catch (error) { console.error('Request failed:', error.message); return null; } } ``` #### Issue 2: Response Interceptors Not "Handling" Errors **Problem:** ```javascript // 0.x style - interceptor "handled" errors axios.interceptors.response.use(null, error => { showErrorMessage(error.message); // Error was considered "handled" }); ``` **Solution:** ```javascript // 1.x style - explicitly control error propagation axios.interceptors.response.use( response => response, error => { showErrorMessage(error.message); // Choose whether to propagate the error if (shouldPropagateError(error)) { return Promise.reject(error); } // Return success-like response for "handled" errors return Promise.resolve({ data: null, handled: true, error: normalizeError(error) }); } ); ``` #### Issue 3: JSON Parsing Errors **Problem:** ```javascript // 1.x is stricter about JSON parsing // This might throw where 0.x was lenient const data = response.data; ``` **Solution:** ```javascript // Add response transformer for better error handling axios.defaults.transformResponse = [ function (data) { if (typeof data === 'string') { try { return JSON.parse(data); } catch (e) { // Handle JSON parsing errors gracefully console.warn('Invalid JSON response:', data); return { error: 'Invalid JSON', rawData: data }; } } return data; } ]; ``` #### Issue 4: TypeScript Errors After Upgrade **Problem:** ```typescript // TypeScript errors after upgrade const response = await axios.get('/api/data'); // Property 'someProperty' does not exist on type 'any' ``` **Solution:** ```typescript // Define proper interfaces interface ApiResponse { data: any; message: string; success: boolean; } const response = await axios.get('/api/data'); // Now properly typed console.log(response.data.data); ``` ### Debug Migration Issues #### Enable Debug Logging ```javascript // Add request/response logging axios.interceptors.request.use(config => { console.log('Request:', config); return config; }); axios.interceptors.response.use( response => { console.log('Response:', response); return response; }, error => { console.log('Error:', error); return Promise.reject(error); } ); ``` #### Compare Behavior ```javascript // Create side-by-side comparison during migration const axios0x = require('axios-0x'); // Keep old version for testing const axios1x = require('axios'); async function compareRequests(config) { try { const [result0x, result1x] = await Promise.allSettled([ axios0x(config), axios1x(config) ]); console.log('0.x result:', result0x); console.log('1.x result:', result1x); } catch (error) { console.log('Comparison error:', error); } } ``` ## Resources ### Official Documentation - [Axios 1.x Documentation](https://axios-http.com/) - [Axios GitHub Repository](https://github.com/axios/axios) - [Axios Changelog](https://github.com/axios/axios/blob/main/CHANGELOG.md) ### Migration Tools - [Axios Migration Codemod](https://github.com/axios/axios-migration-codemod) *(if available)* - [ESLint Rules for Axios 1.x](https://github.com/axios/eslint-plugin-axios) *(if available)* ### Community Resources - [Stack Overflow - Axios Migration Questions](https://stackoverflow.com/questions/tagged/axios+migration) - [GitHub Discussions](https://github.com/axios/axios/discussions) - [Axios Discord Community](https://discord.gg/axios) *(if available)* ### Related Issues - [Error Handling Changes Discussion](https://github.com/axios/axios/issues/7208) - [Migration Guide Request](https://github.com/axios/axios/issues/xxxx) *(link to related issues)* --- ## Need Help? If you encounter issues during migration that aren't covered in this guide: 1. **Search existing issues** in the [Axios GitHub repository](https://github.com/axios/axios/issues) 2. **Ask questions** in [GitHub Discussions](https://github.com/axios/axios/discussions) 3. **Contribute improvements** to this migration guide --- *This migration guide is maintained by the community. If you find errors or have suggestions, please [open an issue](https://github.com/axios/axios/issues) or submit a pull request.*axios-axios-2d06f96/PRE_RELEASE_CHANGELOG.md000066400000000000000000000021361521272452000200010ustar00rootroot00000000000000# Pre-Release Changelog ## Unreleased ## Security Fixes - **HTTP Adapter Redirects:** Added a Node.js `sensitiveHeaders` request config option that strips caller-selected custom secret headers from cross-origin redirects. (**#10892**) ## Bug Fixes - **URL Validation:** Reject malformed `http:` and `https:` URLs that omit `//` before adapter URL normalization, returning `ERR_INVALID_URL` instead of silently normalizing invalid input. (**#10900**, closes **#7315**) - **Types:** Add the missing readonly `name: 'CanceledError'` declaration to CommonJS `CanceledError` typings to match the ESM declarations. (**#10922**) - **Config Merge:** Added `transitional.validateStatusUndefinedResolves` (default `true`) so applications can opt into treating explicit `validateStatus: undefined` like an omitted option by setting it to `false`. `validateStatus: null` still accepts every response status. (**#10899**, closes **#6688**) ## Release Tracking - ESM/CJS typings are updated for `transitional.validateStatusUndefinedResolves`; README/docs updates are tracked in `PRE_RELEASE_DOCS.md` for release preparation. axios-axios-2d06f96/PRE_RELEASE_DOCS.md000066400000000000000000000105311521272452000172400ustar00rootroot00000000000000# Pre-Release Documentation Notes ## Purpose Track documentation updates that should be applied during release preparation. Do not treat this file as final documentation. Each entry should give enough context for a maintainer or LLM to update README, docs pages, examples, migration guides, and translated docs when the release is prepared. Do not store raw diffs or line-number-only instructions here; prefer stable section names, target files, required concepts, examples, and release-specific notes. ## Entry Format - **Change:** Short feature/fix name. - **Source:** PR, issue, or changelog reference. - **Status:** Pending | Applied | Skipped. - **Docs targets:** Files or docs sections likely needing updates. - **Required content:** What the docs must explain. - **Examples:** Any code snippets or examples that should be included. - **Notes:** Constraints, release-only wording, translation follow-up, etc. ## Unreleased ### malformed HTTP URL rejection - **Change:** Note that malformed `http:` and `https:` URLs missing `//` are rejected before adapter normalization. - **Source:** `PRE_RELEASE_CHANGELOG.md` Bug Fixes, #10900, closes #7315. - **Status:** Skipped. - **Docs targets:** None beyond release notes. - **Required content:** No API documentation update is needed because this changes handling for invalid URL input without adding or changing request config, types, or public APIs. The release note should mention that axios now throws `AxiosError` with `ERR_INVALID_URL` for malformed HTTP(S) URLs such as `https:example.com` or `http:/example.com` instead of allowing platform URL normalization. - **Examples:** None. - **Notes:** Treat as a bug/security-hardening release note, not a request-config documentation change. ### sensitiveHeaders request config - **Change:** Document the Node.js `sensitiveHeaders` request config option for stripping custom secret headers from cross-origin redirects. - **Source:** `PRE_RELEASE_CHANGELOG.md` Security Fixes, #10892. - **Status:** Pending. - **Docs targets:** `docs/pages/misc/security.md`; `docs/pages/advanced/request-config.md`; README request config section if it lists all config options; translated docs after English docs are finalized. - **Required content:** Explain that `sensitiveHeaders` is an optional array of custom secret-bearing header names. Matching is case-insensitive. The Node.js HTTP adapter removes matching headers only when following a redirect to a different origin. Same-origin redirects keep these headers. If `maxRedirects` is `0`, axios does not follow redirects and `sensitiveHeaders` is not used. Mention common custom authentication headers such as `X-API-Key`. - **Examples:** Include this request example. ```js axios.get('https://api.example.com/users', { headers: { 'X-API-Key': 'secret' }, sensitiveHeaders: ['X-API-Key'] }); ``` - **Notes:** Add a security page row linking to the request-config section and add a `sensitiveHeaders` request-config entry marked Node.js only. ### validateStatus undefined transitional option - **Change:** Document `transitional.validateStatusUndefinedResolves` for the `validateStatus: undefined` merge behavior. - **Source:** `PRE_RELEASE_CHANGELOG.md` Bug Fixes, #10899, closes #6688. - **Status:** Pending. - **Docs targets:** README request config section; `docs/pages/advanced/request-config.md` `validateStatus` section and request config example; translated request-config docs after English docs are finalized. - **Required content:** Explain that `validateStatus: undefined` keeps legacy behavior by default and resolves every response status because `transitional.validateStatusUndefinedResolves` defaults to `true`. Explain that setting `transitional.validateStatusUndefinedResolves` to `false` makes explicit `validateStatus: undefined` behave like the option was omitted, so axios uses the configured/default validator and rejects non-2xx responses by default. Mention that `validateStatus: null` still accepts every response status, and users who disable the transitional behavior should use `null` or `() => true` when they intentionally want all statuses to resolve. - **Examples:** Include a short opt-in example. ```js axios.get('/user/12345', { validateStatus: undefined, transitional: { validateStatusUndefinedResolves: false } }); ``` - **Notes:** This is release-prep documentation only; do not update README or docs pages in the feature/fix PR. axios-axios-2d06f96/README.md000066400000000000000000002625411521272452000156110ustar00rootroot00000000000000

💎 Platinum sponsors

Thanks.dev

We're passionate about making open source sustainable. Scan your dependency tree to better understand which open source projects need funding.

thanks.dev

💜 Become a sponsor
💜 Become a sponsor 💜 Become a sponsor

🥇 Gold sponsors

Principal Financial Group

Free tools to help with your financial planning needs!

principal.com

SAP

BSAP SE, a global software company, is one of the largest vendors of ERP and other enterprise applications.

opensource.sap.com

Descope

Reduce user friction, prevent account takeover, and get a 360° view of your customer and agentic identities with the Descope External IAM platform.

descope.com

Stytch

The identity platform for humans & AI agents

stytch.com

RxDB

RxDB is a NoSQL database for JavaScript that runs directly in your app.

rxdb.info

Poprey

Buy Instagram Likes

poprey.com

Buzzoid - Buy Instagram Followers

At Buzzoid, you can buy Instagram followers through a short checkout flow with safety controls. Rated world's #1 IG service since 2012.

buzzoid.com

Buy Instagram Followers Twicsy

Buy real Instagram followers from Twicsy. Twicsy has been voted the best site to buy followers from the likes of US Magazine.

twicsy.com

Fun 88

Fun88 is a global online gambling and betting brand founded in 2009, offering a wide range of services including sports betting, live casino games, slots, and virtual gaming.

global.fun88.com



Axios

Promise based HTTP client for the browser and node.js

WebsiteDocumentation

[![npm version](https://img.shields.io/npm/v/axios.svg?style=flat-square)](https://www.npmjs.org/package/axios) [![Build status](https://img.shields.io/github/actions/workflow/status/axios/axios/ci.yml?branch=v1.x&label=CI&logo=github&style=flat-square)](https://github.com/axios/axios/actions/workflows/ci.yml) [![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blue?logo=gitpod&style=flat-square)](https://gitpod.io/#https://github.com/axios/axios) [![install size](https://img.shields.io/badge/dynamic/json?url=https://packagephobia.com/v2/api.json?p=axios&query=$.install.pretty&label=install%20size&style=flat-square)](https://packagephobia.now.sh/result?p=axios) [![npm bundle size](https://img.shields.io/bundlephobia/minzip/axios?style=flat-square)](https://bundlephobia.com/package/axios@latest) [![npm downloads](https://img.shields.io/npm/dm/axios.svg?style=flat-square)](https://npm-stat.com/charts.html?package=axios) [![gitter chat](https://img.shields.io/gitter/room/mzabriskie/axios.svg?style=flat-square)](https://gitter.im/mzabriskie/axios) [![code helpers](https://www.codetriage.com/axios/axios/badges/users.svg)](https://www.codetriage.com/axios/axios) [![Contributors](https://img.shields.io/github/contributors/axios/axios.svg?style=flat-square)](CONTRIBUTORS.md) [![Agent Friendly](https://agentfriendlycode.com/api/badge/github/axios/axios.svg)](https://agentfriendlycode.com/repo/32)
## Table of contents - [Features](#features) - [Browser support](#browser-support) - [Installing](#installing) - [Package manager](#package-manager) - [CDN](#cdn) - [Example](#example) - [Axios API](#axios-api) - [Request method aliases](#request-method-aliases) - [Concurrency](#concurrency-deprecated) - [Creating an instance](#creating-an-instance) - [Instance methods](#instance-methods) - [Request config](#request-config) - [Response schema](#response-schema) - [Config defaults](#config-defaults) - [Global axios defaults](#global-axios-defaults) - [Custom instance defaults](#custom-instance-defaults) - [Config order of precedence](#config-order-of-precedence) - [Interceptors](#interceptors) - [Multiple interceptors](#multiple-interceptors) - [Handling errors](#handling-errors) - [Handling timeouts](#handling-timeouts) - [Cancellation](#cancellation) - [AbortController](#abortcontroller) - [CancelToken](#canceltoken-deprecated) - [Using application/x-www-form-urlencoded format](#using-applicationx-www-form-urlencoded-format) - [URLSearchParams](#urlsearchparams) - [Query string](#query-string-older-browsers) - [Automatic serialization](#automatic-serialization-to-urlsearchparams) - [Using multipart/form-data format](#using-multipartform-data-format) - [FormData](#formdata) - [Automatic serialization](#automatic-serialization-to-formdata) - [Posting files](#posting-files) - [HTML form posting](#html-form-posting-browser) - [Progress capturing](#progress-capturing) - [Rate limiting](#rate-limiting) - [AxiosHeaders](#axiosheaders) - [Fetch adapter](#fetch-adapter) - [Custom fetch](#custom-fetch) - [Using with Tauri](#using-with-tauri) - [Using with SvelteKit](#using-with-sveltekit) - [HTTP/2 support](#http2-support) - [Semver](#semver) - [Promises](#promises) - [TypeScript](#typescript) - [Contributing](#contributing) - [Local setup](#local-setup) - [Resources](#resources) - [Credits](#credits) - [License](#license) ## Features - Make [XMLHttpRequests](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) from the browser. - Make [http](https://nodejs.org/api/http.html) requests from Node.js. - Use the [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) API for asynchronous request handling. - Intercept requests and responses to add custom logic or transform data. - Transform request and response data. - Cancel requests with built-in cancellation APIs. - Serialize and parse [JSON](https://www.json.org/json-en.html) data. - Serialize data objects to `multipart/form-data` or `application/x-www-form-urlencoded`. - Add client-side protection against [Cross-Site Request Forgery](https://en.wikipedia.org/wiki/Cross-site_request_forgery). ## Browser support | Chrome | Firefox | Safari | Opera | Edge | | :------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------: | | ![Chrome browser logo](https://raw.githubusercontent.com/alrra/browser-logos/main/src/chrome/chrome_48x48.png) | ![Firefox browser logo](https://raw.githubusercontent.com/alrra/browser-logos/main/src/firefox/firefox_48x48.png) | ![Safari browser logo](https://raw.githubusercontent.com/alrra/browser-logos/main/src/safari/safari_48x48.png) | ![Opera browser logo](https://raw.githubusercontent.com/alrra/browser-logos/main/src/opera/opera_48x48.png) | ![Edge browser logo](https://raw.githubusercontent.com/alrra/browser-logos/main/src/edge/edge_48x48.png) | | Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | Latest ✔ | [![Browser Matrix](https://saucelabs.com/open_sauce/build_matrix/axios.svg)](https://saucelabs.com/u/axios) ## Installing ### Package manager Using npm: ```bash $ npm install axios ``` Using yarn: ```bash $ yarn add axios ``` Using pnpm: ```bash $ pnpm add axios ``` Using bun: ```bash $ bun add axios ``` Once the package is installed, import it with `import` or `require`: ```js import axios, { isCancel, AxiosError } from 'axios'; ``` You can also use the default export, since the named export is just a re-export from the Axios factory: ```js import axios from 'axios'; console.log(axios.isCancel('something')); ``` If you use `require` for importing, **only the default export is available**: ```js const axios = require('axios'); console.log(axios.isCancel('something')); ``` Some bundlers and ES6 linters need this form: ```js import { default as axios } from 'axios'; ``` In custom or legacy environments, you can import the bundle directly: ```js const axios = require('axios/dist/browser/axios.cjs'); // browser commonJS bundle (ES2017) // const axios = require('axios/dist/node/axios.cjs'); // node commonJS bundle (ES2017) ``` ### CDN Using jsDelivr CDN (ES5 UMD browser module): ```html ``` Using unpkg CDN: ```html ``` ## Example ```js import axios from 'axios'; //const axios = require('axios'); // legacy way try { const response = await axios.get('/user?ID=12345'); console.log(response); } catch (error) { console.error(error); } // Optionally the request above could also be done as axios .get('/user', { params: { ID: 12345, }, timeout: 5000, // 5 seconds. See "Handling Timeouts" below for matching error handling }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }) .finally(function () { // always executed }); // Want to use async/await? Add the `async` keyword to your outer function/method. async function getUser() { try { // Example: GET request with query parameters const response = await axios.get('/user', { params: { ID: 12345 } }); // Using the `params` option improves readability and automatically formats query strings console.log(response); } catch (error) { console.error(error); } } ``` > Note: Set a `timeout` in production. Without one, a stalled request can hang > indefinitely. See [Handling Timeouts](#handling-timeouts) for the matching error handling. > Note: `async/await` is part of ECMAScript 2017 and is not supported in Internet > Explorer and older browsers, so use with caution. Performing a `POST` request ```js const response = await axios.post('/user', { firstName: 'Fred', lastName: 'Flintstone', }); console.log(response); ``` Performing multiple concurrent requests ```js function getUserAccount() { return axios.get('/user/12345'); } function getUserPermissions() { return axios.get('/user/12345/permissions'); } Promise.all([getUserAccount(), getUserPermissions()]).then(function (results) { const acct = results[0]; const perm = results[1]; }); ``` ## axios API Requests can be made by passing the relevant config to `axios`. ##### axios(config) ```js // Send a POST request axios({ method: 'post', url: '/user/12345', data: { firstName: 'Fred', lastName: 'Flintstone', }, }); ``` ```js // GET request for remote image in node.js const response = await axios({ method: 'get', url: 'https://bit.ly/2mTM3nY', responseType: 'stream', }); response.data.pipe(fs.createWriteStream('ada_lovelace.jpg')); ``` ##### axios(url[, config]) ```js // Send a GET request (default method) axios('/user/12345'); ``` ### Request method aliases For convenience, aliases have been provided for all common request methods. ##### axios.request(config) ##### axios.get(url[, config]) ##### axios.delete(url[, config]) ##### axios.head(url[, config]) ##### axios.options(url[, config]) ##### axios.post(url[, data[, config]]) ##### axios.put(url[, data[, config]]) ##### axios.patch(url[, data[, config]]) ###### Note When using the alias methods `url`, `method`, and `data` properties don't need to be specified in config. ### Concurrency (deprecated) Use `Promise.all` instead of these helpers. Helper functions for dealing with concurrent requests. axios.all(iterable) axios.spread(callback) ### Creating an instance You can create a new instance of axios with a custom config. ##### axios.create([config]) ```js const instance = axios.create({ baseURL: 'https://some-domain.com/api/', timeout: 1000, headers: { 'X-Custom-Header': 'foobar' }, }); ``` ### Instance methods The following instance methods are available. Axios merges the specified config with the instance config. ##### axios#request(config) ##### axios#get(url[, config]) ##### axios#delete(url[, config]) ##### axios#head(url[, config]) ##### axios#options(url[, config]) ##### axios#post(url[, data[, config]]) ##### axios#put(url[, data[, config]]) ##### axios#patch(url[, data[, config]]) ##### axios#getUri([config]) ## Request config ### Security notice: decompression-bomb protection is opt-in By default `maxContentLength` and `maxBodyLength` are `-1` (unlimited). A malicious or compromised server can return a tiny gzip/deflate/brotli/zstd body that expands to gigabytes and exhaust the Node.js process. If you call servers you do not fully trust, **set a cap**: ```js axios.defaults.maxContentLength = 10 * 1024 * 1024; // 10 MB axios.defaults.maxBodyLength = 10 * 1024 * 1024; ``` See the [security guide](https://axios.rest/pages/misc/security.html) for details. These config options are available for requests. Only `url` is required. Requests default to `GET` when `method` is not set. ```js { // `url` is the server URL for the request url: '/user', // `method` is the request method to be used when making the request method: 'get', // default // Axios prepends `baseURL` to `url` unless `url` is absolute and `allowAbsoluteUrls` is set to true. // It can be convenient to set `baseURL` for an instance of axios to pass relative URLs // to the methods of that instance. baseURL: 'https://some-domain.com/api/', // `allowAbsoluteUrls` determines whether or not absolute URLs will override a configured `baseUrl`. // When set to true (default), absolute values for `url` will override `baseUrl`. // When set to false, absolute values for `url` will always be prepended by `baseUrl`. allowAbsoluteUrls: true, // `transformRequest` allows changes to the request data before it is sent to the server // This is only applicable for request methods 'PUT', 'POST', 'PATCH' and 'DELETE' // The last function in the array must return a string or an instance of Buffer, ArrayBuffer, // FormData or Stream // You may modify the headers object. transformRequest: [function (data, headers) { // Do whatever you want to transform the data return data; }], // `transformResponse` allows changes to the response data to be made before // it is passed to then/catch transformResponse: [function (data) { // Do whatever you want to transform the data return data; }], // `parseReviver` is an optional function passed as the // second argument (reviver) to JSON.parse() parseReviver: function (key, value, context) { // In modern environments, context.source provides the raw JSON string // allowing for precision-safe parsing of BigInt if (typeof value === 'number' && context?.source) { const isInteger = Number.isInteger(value); const isUnsafe = !Number.isSafeInteger(value); const isValidIntegerString = /^-?\d+$/.test(context.source); if (isInteger && isUnsafe && isValidIntegerString) { try { return BigInt(context.source); } catch { // Fallback: return original value if parsing fails } } } return value; }, // `headers` are custom headers to be sent headers: {'X-Requested-With': 'XMLHttpRequest'}, // `params` are the URL parameters to be sent with the request // Must be a plain object or a URLSearchParams object params: { ID: 12345 }, // `paramsSerializer` is an optional config that allows you to customize serializing `params`. paramsSerializer: { // Custom encoder function which sends key/value pairs in an iterative fashion. encode?: (param: string): string => { /* Do custom operations here and return transformed string */ }, // Custom serializer function for the entire parameter. Allows the user to mimic pre 1.x behaviour. serialize?: (params: Record, options?: ParamsSerializerOptions ), // Configuration for formatting array indexes in the params. indexes: false, // Three available options: (1) indexes: null (leads to no brackets), (2) (default) indexes: false (leads to empty brackets), (3) indexes: true (leads to brackets with indexes). // Maximum object nesting depth when serializing params. Payloads deeper than this throw an // AxiosError with code ERR_FORM_DATA_DEPTH_EXCEEDED. Default: 100. Set to Infinity to disable. maxDepth: 100 }, // `data` is the data to be sent as the request body // Only applicable for request methods 'PUT', 'POST', 'DELETE', and 'PATCH' // When no `transformRequest` is set, it must be of one of the following types: // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams // - Browser only: FormData, File, Blob // - React Native: FormData // - Node only: Stream, Buffer, FormData (form-data package) data: { firstName: 'Fred' }, // `formDataHeaderPolicy` controls how node.js FormData#getHeaders() is copied. // 'legacy' (default) copies all returned headers for v1 compatibility. // 'content-only' copies only Content-Type and Content-Length. formDataHeaderPolicy: 'legacy', // syntax alternative to send data into the body // method post // only the value is sent, not the key data: 'Country=Brasil&City=Belo Horizonte', // `timeout` specifies the number of milliseconds before the request times out. // If the request takes longer than `timeout`, Axios aborts it. timeout: 1000, // default is `0` (no timeout) // `withCredentials` indicates whether or not cross-site Access-Control requests // should be made using credentials // This only controls whether the browser sends credentials. // It does not control whether the XSRF header is added. withCredentials: false, // default // `adapter` allows custom handling of requests which makes testing easier. // Return a promise and supply a valid response (see lib/adapters/README.md) adapter: function (config) { /* ... */ }, // Also, you can set the name of the built-in adapter, or provide an array with their names // to choose the first available in the environment adapter: 'xhr', // 'fetch' | 'http' | ['xhr', 'http', 'fetch'] // `auth` indicates that HTTP Basic auth should be used, and supplies credentials. // This will set an `Authorization` header, overwriting any existing // `Authorization` custom headers you have set using `headers`. // If `auth` is omitted, the Node.js HTTP and fetch adapters can read // HTTP Basic auth credentials from the request URL, for example // `https://user:pass@example.com`. Axios decodes percent-encoded URL // credentials, and `auth` takes precedence over URL-embedded credentials. // The Node.js HTTP adapter preserves Basic auth on same-origin redirects // and strips it on cross-origin redirects. // Please note that only HTTP Basic auth is configurable through this parameter. // For Bearer tokens and such, use `Authorization` custom headers instead. auth: { username: 'janedoe', password: 's00pers3cret' }, // `responseType` indicates the type of data that the server will respond with // options are: 'arraybuffer', 'document', 'json', 'text', 'stream' // browser only: 'blob' responseType: 'json', // default // `responseEncoding` indicates encoding to use for decoding responses (Node.js only) // Note: Ignored for `responseType` of 'stream' or client-side requests // options are: 'ascii', 'ASCII', 'ansi', 'ANSI', 'binary', 'BINARY', 'base64', 'BASE64', 'base64url', // 'BASE64URL', 'hex', 'HEX', 'latin1', 'LATIN1', 'ucs-2', 'UCS-2', 'ucs2', 'UCS2', 'utf-8', 'UTF-8', // 'utf8', 'UTF8', 'utf16le', 'UTF16LE' responseEncoding: 'utf8', // default // `xsrfCookieName` is the name of the cookie to use as a value for the xsrf token xsrfCookieName: 'XSRF-TOKEN', // default // `xsrfHeaderName` is the name of the http header that carries the xsrf token value xsrfHeaderName: 'X-XSRF-TOKEN', // default // `withXSRFToken` defines whether to send the XSRF header in browser requests. // `undefined` (default) - set XSRF header only for the same origin requests // `true` - always set XSRF header, including for cross-origin requests // `false` - never set XSRF header // function - resolve with custom logic; receives the internal config object withXSRFToken: boolean | undefined | ((config: InternalAxiosRequestConfig) => boolean | undefined), // `withXSRFToken` controls whether Axios reads the XSRF cookie and sets the XSRF header. // - `undefined` (default): the XSRF header is set only for same-origin requests. // - `true`: attempt to set the XSRF header for all requests (including cross-origin). // - `false`: never set the XSRF header. // - function: a callback that receives the request `config` and returns `true`, // `false`, or `undefined` to decide per-request behavior. // // Note about `withCredentials`: `withCredentials` controls whether cross-site // requests include credentials (cookies and HTTP auth). In older Axios versions, // setting `withCredentials: true` implicitly caused Axios to set the XSRF header // for cross-origin requests. Newer Axios separates these concerns: to allow the // XSRF header to be sent for cross-origin requests you should set both // `withCredentials: true` and `withXSRFToken: true`. // // Example: // axios.get('/user', { withCredentials: true, withXSRFToken: true }); // `onUploadProgress` allows handling of progress events for uploads // browser & node.js onUploadProgress: function ({loaded, total, progress, bytes, estimated, rate, upload = true}) { // Do whatever you want with the Axios progress event }, // `onDownloadProgress` allows handling of progress events for downloads // browser & node.js onDownloadProgress: function ({loaded, total, progress, bytes, estimated, rate, download = true}) { // Do whatever you want with the Axios progress event }, // `maxContentLength` defines the max size of the response content in bytes. // It is enforced by the Node.js HTTP adapter and the fetch adapter. maxContentLength: 2000, // `maxBodyLength` defines the max size of the request content in bytes. // It is enforced by the Node.js HTTP adapter and the fetch adapter when the body length can be determined. maxBodyLength: 2000, // `redact` masks matching config keys when AxiosError#toJSON() is called. // Matching is case-insensitive and recursive. It does not change the request. redact: ['authorization', 'password'], // `validateStatus` defines whether to resolve or reject the promise for a given // HTTP response status code. If `validateStatus` returns `true` (or is set to `null` // or `undefined`), Axios resolves the promise; otherwise, Axios rejects it. validateStatus: function (status) { return status >= 200 && status < 300; // default }, // `maxRedirects` defines the maximum number of redirects to follow in node.js. // If set to 0, Axios follows no redirects. maxRedirects: 21, // default // `sensitiveHeaders` (Node only option) lists custom secret-bearing headers // to remove from cross-origin redirects. Matching is case-insensitive. // Same-origin redirects keep these headers. If `maxRedirects` is 0, this // option is not used. sensitiveHeaders: ['X-API-Key'], // `beforeRedirect` defines a function that Axios calls before redirect. // Use this to adjust the request options upon redirecting, // to inspect the latest response headers, // or to cancel the request by throwing an error // If maxRedirects is set to 0, `beforeRedirect` is not used. beforeRedirect: (options, { headers }) => { if ( options.hostname === "example.com" && options.protocol === "https:" ) { options.auth = "user:password"; } }, // Security note: // The `beforeRedirect` hook runs after sensitive headers are stripped during redirects. // `follow-redirects` removes credentials on protocol downgrades // (HTTPS to HTTP). Because `beforeRedirect` runs after that step, // re-injecting credentials without checking the destination can expose // sensitive data. Only add credentials for trusted HTTPS destinations. // `socketPath` defines a UNIX Socket to be used in node.js. // e.g. '/var/run/docker.sock' to send requests to the docker daemon. // Only either `socketPath` or `proxy` can be specified. // If both are specified, `socketPath` is used. // // Security: when `socketPath` is set, hostname/port of the URL are ignored, // which bypasses hostname-based SSRF protections. Never derive `socketPath` // from untrusted input. Use `allowedSocketPaths` (below) to restrict accepted // socket paths for defense-in-depth. socketPath: null, // default // `allowedSocketPaths` restricts which `socketPath` values are accepted. // Accepts a string or array of strings. Entries and the incoming socketPath // are compared after path.resolve(). A mismatch throws AxiosError with code // `ERR_BAD_OPTION_VALUE`. When null/undefined, no restriction is applied. allowedSocketPaths: null, // default // `transport` determines the transport method for the request. // If defined, Axios uses it. Otherwise, if `maxRedirects` is 0, // Axios uses the default `http` or `https` library, depending on the protocol specified in `protocol`. // Otherwise, Axios uses the `httpFollow` or `httpsFollow` library, again depending on the protocol, // which can handle redirects. transport: undefined, // default // `httpAgent` and `httpsAgent` define a custom agent to be used when performing http // and https requests, respectively, in node.js. This allows options to be added like // `keepAlive` that are not enabled by default before Node.js v19.0.0. After Node.js // v19.0.0, you no longer need to customize the agent to enable `keepAlive` because // `http.globalAgent` has `keepAlive` enabled by default. httpAgent: new http.Agent({ keepAlive: true }), httpsAgent: new https.Agent({ keepAlive: true }), // `proxy` defines the hostname, port, and protocol of the proxy server. // You can also define your proxy using the conventional `http_proxy` and // `https_proxy` environment variables. If you are using environment variables // for your proxy configuration, you can also define a `no_proxy` environment // variable as a comma-separated list of domains that should not be proxied. // Use `false` to disable proxies, ignoring environment variables. // `auth` indicates that HTTP Basic auth should be used to connect to the proxy, and // supplies credentials. // For `http://` targets, axios sends the request to the proxy in // forward-proxy mode and stamps `Proxy-Authorization` onto the request // headers (overwriting any user-supplied `Proxy-Authorization` header). // For `https://` targets, axios establishes a CONNECT tunnel through the // proxy and performs TLS end-to-end with the origin; `Proxy-Authorization` // is sent on the CONNECT request only, never on the wrapped TLS request, // so the proxy never sees the URL, headers, or body. Axios forwards // `httpsAgent` TLS options such as `ca`, `cert`, `key`, and // `rejectUnauthorized` to the generated tunneling agent, so they still apply // to the origin TLS connection. // If you supply an `HttpsProxyAgent`, axios leaves tunneling to that agent. // If the proxy server uses HTTPS, then you must set the protocol to `https`. // A user-supplied `Host` header in `headers` is preserved when forwarding // through a proxy (case-insensitive match on `host`/`Host`/`HOST`); this // lets you target a virtual host that differs from the request URL, for // example, hitting `127.0.0.1:4000` while having the proxy treat the // request as `example.com`. If no `Host` header is supplied, axios // defaults it to the request URL's `hostname:port` as before. The Host // header is only set in forward-proxy mode (HTTP targets); for HTTPS // tunneling the Host header is sent inside the TLS connection, not seen // by the proxy. proxy: { protocol: 'https', host: '127.0.0.1', // hostname: '127.0.0.1' // Takes precedence over 'host' if both are defined port: 9000, auth: { username: 'mikeymike', password: 'rapunz3l' } }, // `cancelToken` specifies a cancel token that can be used to cancel the request // (see Cancellation section below for details) cancelToken: new CancelToken(function (cancel) { }), // an alternative way to cancel Axios requests using AbortController signal: new AbortController().signal, // `decompress` indicates whether or not the response body should be decompressed // automatically. If set to `true` will also remove the 'content-encoding' header // from the responses objects of all decompressed responses // Axios supports gzip, deflate, brotli, and zstd when the current Node.js // runtime provides the corresponding zlib decompressor. // - Node only (XHR cannot turn off decompression) decompress: true, // default // `insecureHTTPParser` boolean. // Indicates where to use an insecure HTTP parser that accepts invalid HTTP headers. // This may allow interoperability with non-conformant HTTP implementations. // Using the insecure parser should be avoided. // see options https://nodejs.org/dist/latest-v12.x/docs/api/http.html#http_http_request_url_options_callback // see also https://nodejs.org/en/blog/vulnerability/february-2020-security-releases/#strict-http-header-parsing-none insecureHTTPParser: undefined, // default // transitional options for backward compatibility that may be removed in the newer versions transitional: { // silent JSON parsing mode // `true` - ignore JSON parsing errors and set response.data to null if parsing failed (old behaviour) // `false` - throw SyntaxError if JSON parsing failed // Important: this option only takes effect when `responseType` is explicitly set to 'json'. // When `responseType` is omitted (defaults to no value), axios uses `forcedJSONParsing` // to attempt JSON parsing, but will silently return the raw string on failure regardless // of this setting. To have invalid JSON throw errors, use: // { responseType: 'json', transitional: { silentJSONParsing: false } } silentJSONParsing: true, // default value for the current Axios version // try to parse the response string as JSON even if `responseType` is not 'json' forcedJSONParsing: true, // throw ETIMEDOUT error instead of generic ECONNABORTED on request timeouts clarifyTimeoutError: false, // advertise `zstd` in the default Accept-Encoding header when the current // Node.js runtime supports zstd decompression. Axios still decompresses // zstd responses when support exists and `decompress` is true. advertiseZstdAcceptEncoding: false, // use the legacy interceptor request/response ordering legacyInterceptorReqResOrdering: true, // default }, env: { // The FormData class to be used to automatically serialize the payload into a FormData object FormData: window?.FormData || global?.FormData }, formSerializer: { visitor: (value, key, path, helpers) => {}; // custom visitor function to serialize form values dots: boolean; // use dots instead of brackets format metaTokens: boolean; // keep special endings like {} in parameter key indexes: boolean; // array indexes format null - no brackets, false - empty brackets, true - brackets with indexes maxDepth: 100; // maximum object nesting depth; throws AxiosError (ERR_FORM_DATA_DEPTH_EXCEEDED) if exceeded. Set to Infinity to disable. }, // http adapter only (node.js) maxRate: [ 100 * 1024, // 100KB/s upload limit, 100 * 1024 // 100KB/s download limit ] } ``` ### Strict RFC 3986 percent-encoding for query params By default, axios decodes `%3A`, `%24`, `%2C` and `%20` back to `:`, `$`, `,` and `+` for readability (the `+` follows the `application/x-www-form-urlencoded` convention for spaces in query strings). These characters are valid in a query component under [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.4), so the default output is correct, but some backends require strict percent-encoding and reject the readable form. Override the default encoder via `paramsSerializer.encode`: ```js // Per-request: emit strict RFC 3986 percent-encoding for query values axios.get('/foo', { params: { filter: JSON.stringify({ startedAt: '2026-01-23' }) }, paramsSerializer: { encode: encodeURIComponent } }); // Or set it on the instance defaults const client = axios.create({ paramsSerializer: { encode: encodeURIComponent } }); ``` ## HTTP/2 support Axios has experimental HTTP/2 support in the Node.js HTTP adapter. Support depends on the runtime environment and Node.js version. Redirects and some adapter behavior may differ from HTTP/1.1. Options like `httpVersion` and `http2Options` are adapter-specific and may not work the same way in every environment. If you need HTTP/2, check runtime support or use a custom adapter. ## Response schema The response to a request contains the following information. ```js { // `data` is the response that was provided by the server data: {}, // `status` is the HTTP status code from the server response status: 200, // `statusText` is the HTTP status message from the server response statusText: 'OK', // `headers` the HTTP headers that the server responded with // All header names are lowercase and can be accessed using the bracket notation. // Example: `response.headers['content-type']` headers: {}, // `config` is the config that was provided to `axios` for the request config: {}, // `request` is the request that generated this response // It is the last ClientRequest instance in node.js (in redirects) // and an XMLHttpRequest instance in the browser request: {} } ``` When using `then`, you receive the response like this: ```js const response = await axios.get('/user/12345'); console.log(response.data); console.log(response.status); console.log(response.statusText); console.log(response.headers); console.log(response.config); ``` When using `catch`, or passing a [rejection callback](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) as the second parameter of `then`, read the response from the `error` object. See [Handling errors](#handling-errors). ## Config defaults Config defaults apply to every request. ### Global axios defaults ```js axios.defaults.baseURL = 'https://api.example.com'; // Important: If you use axios with multiple domains, Axios sends AUTH_TOKEN to all of them. // See below for an example using Custom instance defaults instead. axios.defaults.headers.common['Authorization'] = AUTH_TOKEN; axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; ``` ### Custom instance defaults ```js // Set config defaults when creating the instance const instance = axios.create({ baseURL: 'https://api.example.com', }); // Alter defaults after instance has been created instance.defaults.headers.common['Authorization'] = AUTH_TOKEN; ``` ### Config order of precedence Axios merges config in this order: library defaults from [lib/defaults/index.js](https://github.com/axios/axios/blob/main/lib/defaults/index.js#L49), the instance `defaults` property, and the request `config` argument. Later values take precedence over earlier ones. ```js // Create an instance using the config defaults provided by the library // At this point the timeout config value is `0` as is the default for the library const instance = axios.create(); // Override timeout default for the library // Now all requests using this instance will wait 2.5 seconds before timing out instance.defaults.timeout = 2500; // Override timeout for this request as it's known to take a long time instance.get('/longRequest', { timeout: 5000, }); ``` ## Interceptors You can intercept requests or responses before methods like `.get()` or `.post()` resolve their promises (before code inside `then` or `catch`, or after `await`) ```js const instance = axios.create(); // Add a request interceptor instance.interceptors.request.use( function (config) { // Do something before the request is sent return config; }, function (error) { // Do something with the request error return Promise.reject(error); } ); // Add a response interceptor instance.interceptors.response.use( function (response) { // Any status code that lies within the range of 2xx causes this function to trigger // Do something with response data return response; }, function (error) { // Any status codes that fall outside the range of 2xx cause this function to trigger // Do something with response error return Promise.reject(error); } ); ``` If you need to remove an interceptor later you can. ```js const instance = axios.create(); const myInterceptor = instance.interceptors.request.use(function () { /*...*/ }); instance.interceptors.request.eject(myInterceptor); ``` You can also clear all interceptors for requests or responses. ```js const instance = axios.create(); instance.interceptors.request.use(function () { /*...*/ }); instance.interceptors.request.clear(); // Removes interceptors from requests instance.interceptors.response.use(function () { /*...*/ }); instance.interceptors.response.clear(); // Removes interceptors from responses ``` You can add interceptors to a custom instance of axios. ```js const instance = axios.create(); instance.interceptors.request.use(function () { /*...*/ }); ``` When you add request interceptors, they are presumed to be asynchronous by default. This can cause a delay in the execution of your axios request when the main thread is blocked (a promise is created under the hood for the interceptor and your request gets put at the bottom of the call stack). If your request interceptors are synchronous you can add a flag to the options object that will tell axios to run the code synchronously and avoid any delays in request execution. ```js axios.interceptors.request.use( function (config) { config.headers.test = 'I am only a header!'; return config; }, null, { synchronous: true } ); ``` If you want to execute a particular interceptor based on a runtime check, you can add a `runWhen` function to the options object. The request interceptor will not run **if and only if** the return of `runWhen` is `false`. Axios calls the function with the config object (don't forget that you can bind your own arguments to it as well.) This can be handy when you have an asynchronous request interceptor that only needs to run at certain times. ```js function onGetCall(config) { return config.method === 'get'; } axios.interceptors.request.use( function (config) { config.headers.test = 'special get headers'; return config; }, null, { runWhen: onGetCall } ); ``` > Note: The options parameter (with `synchronous` and `runWhen` properties) is only supported for request interceptors at the moment. ### Interceptor execution order Request and response interceptors use different execution orders. Request interceptors run in reverse order (LIFO: last in, first out). The last interceptor added runs first. Response interceptors run in the order they were added (FIFO: first in, first out). The first interceptor added runs first. Example: ```js const instance = axios.create(); const interceptor = (id) => (base) => { console.log(id); return base; }; instance.interceptors.request.use(interceptor('Request Interceptor 1')); instance.interceptors.request.use(interceptor('Request Interceptor 2')); instance.interceptors.request.use(interceptor('Request Interceptor 3')); instance.interceptors.response.use(interceptor('Response Interceptor 1')); instance.interceptors.response.use(interceptor('Response Interceptor 2')); instance.interceptors.response.use(interceptor('Response Interceptor 3')); // Console output: // Request Interceptor 3 // Request Interceptor 2 // Request Interceptor 1 // [HTTP request is made] // Response Interceptor 1 // Response Interceptor 2 // Response Interceptor 3 ``` ### Multiple interceptors When a response is fulfilled and multiple response interceptors are registered: - Each interceptor runs in registration order. - Each interceptor receives the result from the previous interceptor. - The chain returns the result from the last interceptor. - If a fulfillment interceptor throws, Axios skips the next fulfillment interceptor and calls the next rejection interceptor. - After the error is caught, later fulfillment interceptors run again, just like in a promise chain. Read [the interceptor tests](./test/specs/interceptors.spec.js) to see all this in code. ## Error types Axios error messages include details that can help you debug the request. Axios errors use this structure: | Property | Definition | | -------- | ---------- | | message | A quick summary of the error message and the status it failed with. | | name | This defines where the error originated from. For axios, it will always be an 'AxiosError'. | | stack | Stack trace for the error. | | config | An axios config object with specific instance configurations defined by the user from when the request was made | | code | Axios error code. The table below lists internal Axios error codes. | | status | HTTP response status code. See [here](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) for common HTTP response status code meanings. These are the internal Axios error codes: | Code | Definition | | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ERR_BAD_OPTION_VALUE | Invalid value provided in axios configuration. | | ERR_BAD_OPTION | Invalid option provided in axios configuration. | | ERR_NOT_SUPPORT | Feature or method not supported in the current axios environment. | | ERR_DEPRECATED | Deprecated feature or method used in axios. | | ERR_INVALID_URL | Invalid URL provided for axios request. | | ECONNABORTED | Typically indicates that the request has been timed out (unless `transitional.clarifyTimeoutError` is set) or aborted by the browser or its plugin. | | ERR_CANCELED | The user explicitly canceled the request with an AbortSignal or CancelToken. | | ETIMEDOUT | Request timed out after exceeding the configured Axios timeout. Set `transitional.clarifyTimeoutError` to `true`; otherwise Axios throws a generic `ECONNABORTED` error. | | ERR_NETWORK | Network-related issue. In the browser, this error can also be caused by a [CORS](https://developer.mozilla.org/ru/docs/Web/HTTP/Guides/CORS) or [Mixed Content](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content) policy violation. The browser does not allow the JS code to clarify the real reason for the error caused by security issues, so please check the console. | | ERR_FR_TOO_MANY_REDIRECTS | Request exceeded the configured maximum number of redirects. | | ERR_BAD_RESPONSE | Response cannot be parsed properly or is in an unexpected format. Usually related to a response with `5xx` status code. | | ERR_BAD_REQUEST | The request has an unexpected format or is missing required parameters. Usually related to a response with `4xx` status code. | ## Handling errors By default, Axios rejects responses with status codes outside the 2xx range. ```js axios.get('/user/12345').catch(function (error) { if (error.response) { // The request was made and the server responded with a status code // that falls out of the range of 2xx console.log(error.response.data); console.log(error.response.status); console.log(error.response.headers); } else if (error.request) { // The request was made but no response was received // `error.request` is an instance of XMLHttpRequest in the browser and an instance of // http.ClientRequest in node.js console.log(error.request); } else { // Something happened in setting up the request that triggered an Error console.log('Error', error.message); } console.log(error.config); }); ``` Use `validateStatus` to override the default condition (`status >= 200 && status < 300`) and choose which HTTP status codes should reject. ```js axios.get('/user/12345', { validateStatus: function (status) { return status < 500; // Resolve only if the status code is less than 500 }, }); ``` Use `toJSON` to get more information about the HTTP error. ```js axios.get('/user/12345').catch(function (error) { console.log(error.toJSON()); }); ``` To avoid logging secrets from `error.config`, pass a `redact` array in the request config. Matching config keys are masked case-insensitively at any depth when `AxiosError#toJSON()` is called. ```js axios.get('/user/12345', { headers: { Authorization: 'Bearer token' }, redact: ['authorization'] }).catch(function (error) { console.log(error.toJSON().config.headers.Authorization); // [REDACTED ****] }); ``` ## Handling timeouts ```js async function fetchWithTimeout() { try { const response = await axios.get('https://example.com/data', { timeout: 5000, // 5 seconds transitional: { // set to true if you prefer ETIMEDOUT over ECONNABORTED clarifyTimeoutError: false, }, }); console.log('Response:', response.data); } catch (error) { if (axios.isAxiosError(error)) { if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT') { console.error('Request timed out. Please try again.'); return; } console.error('Axios error:', error.message); return; } console.error('Unexpected error:', error); } } ``` ## Cancellation ### AbortController Since `v0.22.0`, Axios supports AbortController: ```js const controller = new AbortController(); axios .get('/foo/bar', { signal: controller.signal, }) .then(function (response) { //... }); // cancel the request controller.abort(); ``` ### CancelToken (deprecated) You can also cancel a request using a _CancelToken_. > The axios cancel token API is based on the withdrawn [cancellable promises proposal](https://github.com/tc39/proposal-cancelable-promises). > This API is deprecated since v0.22.0 and should not be used in new projects. Create a cancel token with the `CancelToken.source` factory: ```js const CancelToken = axios.CancelToken; const source = CancelToken.source(); axios .get('/user/12345', { cancelToken: source.token, }) .catch(function (thrown) { if (axios.isCancel(thrown)) { console.log('Request canceled', thrown.message); } else { // handle error } }); axios.post( '/user/12345', { name: 'new name', }, { cancelToken: source.token, } ); // cancel the request (the message parameter is optional) source.cancel('Operation canceled by the user.'); ``` You can also pass an executor function to the `CancelToken` constructor: ```js const CancelToken = axios.CancelToken; let cancel; axios.get('/user/12345', { cancelToken: new CancelToken(function executor(c) { // An executor function receives a cancel function as a parameter cancel = c; }), }); // cancel the request cancel(); ``` > Note: You can cancel several requests with the same cancel token or abort controller. > If a cancellation token is already cancelled when an Axios request starts, Axios cancels the request immediately without making a real request. > During the transition period, you can use both cancellation APIs, even for the same request: ## Using `application/x-www-form-urlencoded` format ### URLSearchParams By default, axios serializes JavaScript objects to `JSON`. To send data as [`application/x-www-form-urlencoded`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST), use the [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) API. It works in most browsers and in [Node](https://nodejs.org/api/url.html#url_class_urlsearchparams) v10 and later. ```js const params = new URLSearchParams({ foo: 'bar' }); params.append('extraparam', 'value'); axios.post('/foo', params); ``` ### Query string (older browsers) For very old browsers, use a [polyfill](https://github.com/WebReflection/url-search-params) and make sure it patches the global environment. Alternatively, you can encode data using the [`qs`](https://github.com/ljharb/qs) library: ```js const qs = require('qs'); axios.post('/foo', qs.stringify({ bar: 123 })); ``` With ES modules: ```js import qs from 'qs'; const data = { bar: 123 }; const options = { method: 'POST', headers: { 'content-type': 'application/x-www-form-urlencoded' }, data: qs.stringify(data), url, }; axios(options); ``` ### Older Node.js versions For older Node.js engines, use the [`querystring`](https://nodejs.org/api/querystring.html) module: ```js const querystring = require('querystring'); axios.post('https://something.com/', querystring.stringify({ foo: 'bar' })); ``` You can also use the [`qs`](https://github.com/ljharb/qs) library. > Note: The `qs` library is preferable if you need to stringify nested objects, as the `querystring` method has [known issues](https://github.com/nodejs/node-v0.x-archive/issues/1665) with that use case. ### Automatic serialization to URLSearchParams Axios automatically serializes the data object to urlencoded format if the content-type header is set to "application/x-www-form-urlencoded". ```js const data = { x: 1, arr: [1, 2, 3], arr2: [1, [2], 3], users: [ { name: 'Peter', surname: 'Griffin' }, { name: 'Thomas', surname: 'Anderson' }, ], }; await axios.postForm('https://postman-echo.com/post', data, { headers: { 'content-type': 'application/x-www-form-urlencoded' }, }); ``` The server receives these fields: ```js { x: '1', 'arr[]': [ '1', '2', '3' ], 'arr2[0]': '1', 'arr2[1][0]': '2', 'arr2[2]': '3', 'arr3[]': [ '1', '2', '3' ], 'users[0][name]': 'Peter', 'users[0][surname]': 'griffin', 'users[1][name]': 'Thomas', 'users[1][surname]': 'Anderson' } ``` If your backend body parser, such as `body-parser` for `express.js`, supports nested object decoding, the server receives the same object structure: ```js const app = express(); app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies app.post('/', function (req, res, next) { // echo body as JSON res.send(JSON.stringify(req.body)); }); server = app.listen(3000); ``` ## Using `multipart/form-data` format ### FormData To send data as `multipart/form-data`, pass a FormData instance as the payload. You do not need to set the `Content-Type` header. Axios detects it from the payload type. For browser, web worker, and React Native `FormData`, leave `Content-Type` unset so the runtime can add the multipart boundary. ```js const formData = new FormData(); formData.append('foo', 'bar'); axios.post('https://httpbin.org/post', formData); ``` In node.js, use the [`form-data`](https://github.com/form-data/form-data) library: ```js const FormData = require('form-data'); const form = new FormData(); form.append('my_field', 'my value'); form.append('my_buffer', Buffer.alloc(10)); form.append('my_file', fs.createReadStream('/foo/bar.jpg')); axios.post('https://example.com', form); ``` In node.js, when a `FormData` object provides `getHeaders()`, axios copies all returned headers by default for v1 compatibility. If the `FormData` object is custom or not fully trusted, set `formDataHeaderPolicy: 'content-only'` to copy only `Content-Type` and `Content-Length`, and set any other request headers explicitly with the request `headers` config. ### Automatic serialization to FormData Since `v0.27.0`, Axios can serialize an object to FormData if the request `Content-Type` header is set to `multipart/form-data`. This request submits data as FormData in browsers and Node.js: ```js import axios from 'axios'; axios .post( 'https://httpbin.org/post', { x: 1 }, { headers: { 'Content-Type': 'multipart/form-data', }, } ) .then(({ data }) => console.log(data)); ``` The Node.js build uses the [`form-data`](https://github.com/form-data/form-data) polyfill by default. You can override the FormData class with the `env.FormData` config option, but most applications do not need this: ```js const axios = require('axios'); var FormData = require('form-data'); axios .post( 'https://httpbin.org/post', { x: 1, buf: Buffer.alloc(10) }, { headers: { 'Content-Type': 'multipart/form-data', }, } ) .then(({ data }) => console.log(data)); ``` The Axios FormData serializer supports these special endings: - `{}` - serialize the value with JSON.stringify - `[]` - unwrap the array-like object as separate fields with the same key > Note: Arrays and FileList objects are unwrapped by default. FormData serializer supports additional options via `config.formSerializer: object` property to handle rare cases: - `visitor: Function` - user-defined visitor function that Axios calls recursively to serialize the data object to a `FormData` object by following custom rules. - `dots: boolean = false` - use dot notation instead of brackets to serialize arrays and objects; - `metaTokens: boolean = true` - add the special ending (e.g `user{}: '{"name": "John"}'`) in the FormData key. A backend body parser can use this meta-information to parse the value as JSON. - `indexes: null|false|true = false` - controls how Axios adds indexes to unwrapped keys of `flat` array-like objects. - `null` - don't add brackets (`arr: 1`, `arr: 2`, `arr: 3`) - `false`(default) - add empty brackets (`arr[]: 1`, `arr[]: 2`, `arr[]: 3`) - `true` - add brackets with indexes (`arr[0]: 1`, `arr[1]: 2`, `arr[2]: 3`) - `maxDepth: number = 100` - maximum object nesting depth the serializer will recurse into. If the input object exceeds this depth, an `AxiosError` with `code: 'ERR_FORM_DATA_DEPTH_EXCEEDED'` is thrown instead of overflowing the call stack. This protects server applications from DoS attacks via deeply nested payloads. Set to `Infinity` to disable the limit and restore pre-fix behaviour. ```js // Raise the limit for a schema that genuinely nests deeper than 100 levels: axios.postForm('/api', data, { formSerializer: { maxDepth: 200 } }); // Same protection applies to params serialization: axios.get('/api', { params: data, paramsSerializer: { maxDepth: 200 } }); ``` Given this object: ```js const obj = { x: 1, arr: [1, 2, 3], arr2: [1, [2], 3], users: [ { name: 'Peter', surname: 'Griffin' }, { name: 'Thomas', surname: 'Anderson' }, ], 'obj2{}': [{ x: 1 }], }; ``` The Axios serializer appends these fields: ```js const formData = new FormData(); formData.append('x', '1'); formData.append('arr[]', '1'); formData.append('arr[]', '2'); formData.append('arr[]', '3'); formData.append('arr2[0]', '1'); formData.append('arr2[1][0]', '2'); formData.append('arr2[2]', '3'); formData.append('users[0][name]', 'Peter'); formData.append('users[0][surname]', 'Griffin'); formData.append('users[1][name]', 'Thomas'); formData.append('users[1][surname]', 'Anderson'); formData.append('obj2{}', '[{"x":1}]'); ``` Axios supports `postForm`, `putForm`, and `patchForm` as shortcuts for the matching HTTP methods with the `Content-Type` header preset to `multipart/form-data`. ## Posting files Submit a single file: ```js await axios.postForm('https://httpbin.org/post', { myVar: 'foo', file: document.querySelector('#fileInput').files[0], }); ``` or multiple files as `multipart/form-data`: ```js await axios.postForm('https://httpbin.org/post', { 'files[]': document.querySelector('#fileInput').files, }); ``` `FileList` object can be passed directly: ```js await axios.postForm('https://httpbin.org/post', document.querySelector('#fileInput').files); ``` Axios sends all files with the same field name: `files[]`. ## HTML form posting (browser) Pass an HTML Form element as a payload to submit it as `multipart/form-data` content. ```js await axios.postForm('https://httpbin.org/post', document.querySelector('#htmlForm')); ``` `FormData` and `HTMLForm` objects can also be posted as `JSON` by explicitly setting the `Content-Type` header to `application/json`: ```js await axios.post('https://httpbin.org/post', document.querySelector('#htmlForm'), { headers: { 'Content-Type': 'application/json', }, }); ``` For example, the Form ```html
``` submits this JSON object: ```js { "foo": "1", "deep": { "prop": { "spaced": "3" } }, "baz": [ "4", "5" ], "user": { "age": "value2" } } ``` Sending `Blobs`/`Files` as JSON (`base64`) is not currently supported. ## Progress capturing Axios can capture request upload and download progress in browsers and Node.js. Progress events are limited to `3` times per second. ```js await axios.post(url, data, { onUploadProgress: function (axiosProgressEvent) { /*{ loaded: number; total?: number; progress?: number; // in range [0..1] bytes: number; // how many bytes have been transferred since the last trigger (delta) estimated?: number; // estimated time in seconds rate?: number; // upload speed in bytes upload: true; // upload sign }*/ }, onDownloadProgress: function (axiosProgressEvent) { /*{ loaded: number; total?: number; progress?: number; bytes: number; estimated?: number; rate?: number; // download speed in bytes download: true; // download sign }*/ }, }); ``` You can also track stream upload/download progress in node.js: ```js const { data } = await axios.post(SERVER_URL, readableStream, { onUploadProgress: ({ progress }) => { console.log((progress * 100).toFixed(2)); }, headers: { 'Content-Length': contentLength, }, maxRedirects: 0, // avoid buffering the entire stream }); ``` > Note: > Capturing FormData upload progress is not currently supported in node.js environments. > Warning: > Set `maxRedirects: 0` when uploading streams in node.js. > The follow-redirects package buffers the entire stream in RAM and does not follow the "backpressure" algorithm. ## Rate limiting Download and upload rate limits can only be set for the http adapter (node.js): ```js const { data } = await axios.post(LOCAL_SERVER_URL, myBuffer, { onUploadProgress: ({ progress, rate }) => { console.log(`Upload [${(progress * 100).toFixed(2)}%]: ${(rate / 1024).toFixed(2)}KB/s`); }, maxRate: [100 * 1024], // 100KB/s limit }); ``` ## AxiosHeaders Axios includes an `AxiosHeaders` class for working with headers through a Map-like API. HTTP header names are case-insensitive, but Axios keeps the original header case for style and for servers that incorrectly depend on case. Directly manipulating the headers object still works, but it is deprecated. ### Working with headers An `AxiosHeaders` instance can contain several internal value types that control setting and merging. Axios gets the final headers object with string values by calling `toJSON`. > Note: By JSON here we mean an object consisting only of string values intended to be sent over the network. The header value can be one of the following types: - `string` - normal string value sent to the server - `null` - skip header when rendering to JSON - `false` - skip header when rendering to JSON. Also indicates that the `set` method must be called with `rewrite` set to `true` to overwrite this value (Axios uses this internally to allow users to opt out of installing certain headers like `User-Agent` or `Content-Type`) - `undefined` - value is not set > Note: The header value is considered set if it is not equal to undefined. The headers object is always initialized inside interceptors and transformers: ```ts axios.interceptors.request.use((request: InternalAxiosRequestConfig) => { request.headers.set('My-header', 'value'); request.headers.set({ 'My-set-header1': 'my-set-value1', 'My-set-header2': 'my-set-value2', }); request.headers.set('User-Agent', false); // prevent Axios from setting this header later request.headers.setContentType('text/plain'); request.headers['My-set-header2'] = 'newValue'; // direct access is deprecated return request; }); ``` You can iterate over an `AxiosHeaders` instance using a `for...of` statement: ```js const headers = new AxiosHeaders({ foo: '1', bar: '2', baz: '3', }); for (const [header, value] of headers) { console.log(header, value); } // foo 1 // bar 2 // baz 3 ``` ### Preserving a specific header case Header names are case-insensitive, but `AxiosHeaders` keeps the case of the first matching key it sees. If you need a specific case for non-standard case-sensitive servers, define a case preset with `undefined` and then set the value later: ```js const api = axios.create(); api.defaults.headers.common = { 'content-type': undefined, accept: undefined, }; await api.put(url, data, { headers: { 'Content-Type': 'application/octet-stream', Accept: 'application/json', }, }); ``` You can also compose the same behavior with `AxiosHeaders.concat`: ```js const headers = axios.AxiosHeaders.concat( { 'content-type': undefined }, { 'Content-Type': 'application/octet-stream' } ); await axios.put(url, data, { headers }); ``` ### new AxiosHeaders(headers?) Constructs a new `AxiosHeaders` instance. ``` constructor(headers?: RawAxiosHeaders | AxiosHeaders | string); ``` If the headers object is a string, Axios parses it as raw HTTP headers. ```js const headers = new AxiosHeaders(` Host: www.bing.com User-Agent: curl/7.54.0 Accept: */*`); console.log(headers); // Object [AxiosHeaders] { // host: 'www.bing.com', // 'user-agent': 'curl/7.54.0', // accept: '*/*' // } ``` ### AxiosHeaders#set ```ts set(headerName, value: Axios, rewrite?: boolean); set(headerName, value, rewrite?: (this: AxiosHeaders, value: string, name: string, headers: RawAxiosHeaders) => boolean); set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean); ``` The `rewrite` argument controls the overwriting behavior: - `false` - do not overwrite if the header's value is set (is not `undefined`) - `undefined` (default) - overwrite the header unless its value is set to `false` - `true` - rewrite anyway The option can also accept a user-defined function that determines whether to overwrite the value. Empty or whitespace-only header names are ignored. Returns `this`. ### AxiosHeaders#get(header) ``` get(headerName: string, matcher?: true | AxiosHeaderMatcher): AxiosHeaderValue; get(headerName: string, parser: RegExp): RegExpExecArray | null; ``` Returns the internal value of the header. It can take an extra argument to parse the header's value with `RegExp.exec`, matcher function or internal key-value parser. ```ts const headers = new AxiosHeaders({ 'Content-Type': 'multipart/form-data; boundary=Asrf456BGe4h', }); console.log(headers.get('Content-Type')); // multipart/form-data; boundary=Asrf456BGe4h console.log(headers.get('Content-Type', true)); // parse key-value pairs from a string separated with \s,;= delimiters: // [Object: null prototype] { // 'multipart/form-data': undefined, // boundary: 'Asrf456BGe4h' // } console.log( headers.get('Content-Type', (value, name, headers) => { return String(value).replace(/a/g, 'ZZZ'); }) ); // multipZZZrt/form-dZZZtZZZ; boundZZZry=Asrf456BGe4h console.log(headers.get('Content-Type', /boundary=(\w+)/)?.[0]); // boundary=Asrf456BGe4h ``` Returns the value of the header. ### AxiosHeaders#has(header, matcher?) ``` has(header: string, matcher?: AxiosHeaderMatcher): boolean; ``` Returns `true` if the header is set (has no `undefined` value). ### AxiosHeaders#delete(header, matcher?) ``` delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean; ``` Returns `true` if at least one header has been removed. ### AxiosHeaders#clear(matcher?) ``` clear(matcher?: AxiosHeaderMatcher): boolean; ``` Removes all headers. Unlike the `delete` method matcher, this optional matcher matches the header name rather than the value. ```ts const headers = new AxiosHeaders({ foo: '1', 'x-foo': '2', 'x-bar': '3', }); console.log(headers.clear(/^x-/)); // true console.log(headers.toJSON()); // [Object: null prototype] { foo: '1' } ``` Returns `true` if at least one header has been cleared. ### AxiosHeaders#normalize(format); If the headers object was changed directly, it can have duplicates with the same name but in different cases. This method normalizes the headers object by combining duplicate keys into one. Axios uses this method internally after calling each interceptor. Set `format` to true for converting header names to lowercase and capitalizing the initial letters (`cOntEnt-type` => `Content-Type`) ```js const headers = new AxiosHeaders({ foo: '1', }); headers.Foo = '2'; headers.FOO = '3'; console.log(headers.toJSON()); // [Object: null prototype] { foo: '1', Foo: '2', FOO: '3' } console.log(headers.normalize().toJSON()); // [Object: null prototype] { foo: '3' } console.log(headers.normalize(true).toJSON()); // [Object: null prototype] { Foo: '3' } ``` Returns `this`. ### AxiosHeaders#concat(...targets) ``` concat(...targets: Array): AxiosHeaders; ``` Merges the instance with targets into a new `AxiosHeaders` instance. If the target is a string, Axios parses it as raw HTTP headers. Returns a new `AxiosHeaders` instance. ### AxiosHeaders#toJSON(asStrings?) ``` toJSON(asStrings: true): Record; toJSON(asStrings?: false): Record; ``` Resolves all internal header values into a new null prototype object. Set `asStrings` to true to resolve arrays as a string containing all elements, separated by commas. ### AxiosHeaders.from(thing?) ``` from(thing?: AxiosHeaders | RawAxiosHeaders | string): AxiosHeaders; ``` Returns a new `AxiosHeaders` instance created from the raw headers passed in, or returns the given headers object if it's already an `AxiosHeaders` instance. ### AxiosHeaders.concat(...targets) ``` concat(...targets: Array): AxiosHeaders; ``` Returns a new `AxiosHeaders` instance created by merging the target objects. ### Shortcuts The following shortcuts are available: - `setContentType`, `getContentType`, `hasContentType` - `setContentLength`, `getContentLength`, `hasContentLength` - `setAccept`, `getAccept`, `hasAccept` - `setUserAgent`, `getUserAgent`, `hasUserAgent` - `setContentEncoding`, `getContentEncoding`, `hasContentEncoding` ## Fetch adapter Axios introduced the fetch adapter in `v1.7.0`. By default, Axios uses it when the `xhr` and `http` adapters are not available in the build or not supported by the environment. To use it by default, select it explicitly: ```js const { data } = axios.get(url, { adapter: 'fetch', // by default ['xhr', 'http', 'fetch'] }); ``` You can create a separate instance for this: ```js const fetchAxios = axios.create({ adapter: 'fetch', }); const { data } = fetchAxios.get(url); ``` The adapter supports the same features as the `xhr` adapter, including upload and download progress capturing. It also supports response types such as `stream` and `formdata` when the environment supports them. When `auth` is omitted, the fetch adapter can read HTTP Basic auth credentials from the request URL, for example `https://user:pass@example.com`. Percent-encoded URL credentials are decoded before the `Authorization` header is generated, and `auth` takes precedence over URL-embedded credentials. ### Custom fetch Since `v1.12.0`, you can configure the fetch adapter to use a custom fetch API instead of environment globals. Pass a custom `fetch` function, `Request`, and `Response` constructors through `env` config. This helps in custom environments and app frameworks. When using a custom fetch, you may also need to set custom `Request` and `Response` constructors. If you do not set them, Axios uses the global objects. If your custom fetch API does not provide these objects and the globals are incompatible with it, pass `null` to disable them inside the fetch adapter. > Note: Setting `Request` and `Response` to `null` prevents the fetch adapter from capturing upload and download progress. Basic example: ```js import customFetchFunction from 'customFetchModule'; const instance = axios.create({ adapter: 'fetch', onDownloadProgress(e) { console.log('downloadProgress', e); }, env: { fetch: customFetchFunction, Request: null, // undefined -> use the global constructor Response: null, }, }); ``` #### Using with Tauri A minimal example of setting up Axios for use in a [Tauri](https://tauri.app/plugin/http-client/) app with a platform fetch function that ignores CORS policy for requests. ```js import { fetch } from '@tauri-apps/plugin-http'; import axios from 'axios'; const instance = axios.create({ adapter: 'fetch', onDownloadProgress(e) { console.log('downloadProgress', e); }, env: { fetch, }, }); const { data } = await instance.get('https://google.com'); ``` #### Using with SvelteKit [SvelteKit](https://svelte.dev/docs/kit/web-standards#Fetch-APIs) uses a custom fetch function for server rendering in `load` functions. It also uses relative paths, which are incompatible with the standard URL API. Configure Axios to use SvelteKit's custom fetch API: ```js export async function load({ fetch }) { const { data: post } = await axios.get('https://jsonplaceholder.typicode.com/posts/1', { adapter: 'fetch', env: { fetch, Request: null, Response: null, }, }); return { post }; } ``` #### HTTP/2 support Axios supports HTTP/2 through the Node.js `http` adapter, introduced in v1.13.0. Support depends on the runtime environment. Axios relies on Node.js APIs, so HTTP/2 works in supported Node.js versions but may not work in other environments such as Bun or Deno. Options like `httpVersion` and `http2Options` are adapter-specific and may not behave the same way in every environment. Note: HTTP/2 redirects are currently not supported by the HTTP/2 adapter. ```js const form = new FormData(); form.append('foo', '123'); const { data, headers, status } = await axios.post('https://httpbin.org/post', form, { onUploadProgress(e) { console.log('upload progress', e); }, onDownloadProgress(e) { console.log('download progress', e); }, responseType: 'arraybuffer', }); ``` ## Semver Axios follows [semver](https://semver.org/) since `v1.0.0`. ## Promises axios depends on a native ES6 Promise implementation to be [supported](https://caniuse.com/promises). If your environment doesn't support ES6 Promises, you can [polyfill](https://github.com/jakearchibald/es6-promise). ## TypeScript axios includes [TypeScript](https://typescriptlang.org) definitions and a type guard for axios errors. ```typescript let user: User = null; try { const { data } = await axios.get('/user?ID=12345'); user = data.userDetails; } catch (error) { if (axios.isAxiosError(error)) { handleAxiosError(error); } else { handleUnexpectedError(error); } } ``` Use `axios.isCancel()` to narrow cancellation errors to `CanceledError`: ```typescript const controller = new AbortController(); try { await axios.get('/user?ID=12345', { signal: controller.signal }); } catch (error) { if (axios.isCancel(error)) { handleCancellation(error); } } ``` Because axios publishes an ESM default export and a CJS `module.exports`, TypeScript has a few caveats. The recommended setting is `"moduleResolution": "node16"`, which is implied by `"module": "node16"`. This requires TypeScript 4.7 or greater. If you use ESM, your settings should be fine. If you compile TypeScript to CJS and can't use `"moduleResolution": "node 16"`, enable `esModuleInterop`. If you use TypeScript to type check CJS JavaScript code, your only option is to use `"moduleResolution": "node16"`. You can also create a custom instance with typed interceptors: ```typescript import axios, { AxiosInstance, InternalAxiosRequestConfig } from 'axios'; const apiClient: AxiosInstance = axios.create({ baseURL: 'https://api.example.com', timeout: 10000, }); apiClient.interceptors.request.use((config: InternalAxiosRequestConfig) => { // Add auth token return config; }); ``` ## Online one-click setup You can use Gitpod, a free online IDE for open source projects, to contribute or run the examples online. [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/axios/axios/blob/main/examples/server.js) ## Contributing ### Local setup As a supply-chain hardening measure, this repository ships a project-level `.npmrc` that sets `ignore-scripts=true`. This blocks npm lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency when you run `npm install` or `npm ci` inside the repo. See [THREATMODEL.md](./THREATMODEL.md) (threat T-S2) for the rationale. One consequence: the repository's own `prepare` hook (which installs Husky's git hooks) will **not** run automatically. After your first install, enable the git hooks manually: ```bash npm ci npm rebuild husky && npx husky ``` Run those two commands once per fresh checkout. You do **not** need to re-run them after every subsequent `npm install`. Do not remove `ignore-scripts=true` from `.npmrc` to "fix" this. That reopens the lifecycle-script attack surface for every other package in the tree. All CI workflows already invoke npm with `--ignore-scripts`, so local behaviour matches CI. ## Resources - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Ecosystem](https://github.com/axios/axios/blob/v1.x/ECOSYSTEM.md) - [Contributing Guide](https://github.com/axios/axios/blob/v1.x/CONTRIBUTING.md) - [Code of Conduct](https://github.com/axios/axios/blob/v1.x/CODE_OF_CONDUCT.md) ## Credits axios is heavily inspired by the [$http service](https://docs.angularjs.org/api/ng/service/$http) in [AngularJS](https://angularjs.org/). It provides a standalone `$http`-like service for use outside AngularJS. ## License [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) axios-axios-2d06f96/SECURITY.md000066400000000000000000000112431521272452000161120ustar00rootroot00000000000000# Security policy ## Supported versions The maintainers provide security updates for these versions: | Version | Supported | | ------- | ------------------ | | 0.x.x | :white_check_mark: | | 1.x.x | :white_check_mark: | ## Threat model For details about the runtime attack surface, supply chain security, and development environment security, see [THREATMODEL.md](THREATMODEL.md). Researchers should read it before reporting. It documents what is in scope, what is an explicit non-goal, and where known gaps remain. The maintainer incident-response runbook, including session revocation, key rotation, and notification steps, is in [THREATMODEL.md §3.7](THREATMODEL.md#37-incident-response-runbook). ## Verifying a release Every `axios` tarball on npm is published from GitHub Actions with an [npm provenance attestation](https://docs.npmjs.com/generating-provenance-statements) that cryptographically binds the package to the workflow and commit SHA that produced it. Consumers can verify provenance locally: ```bash # Verify every package in your lockfile, including axios npm audit signatures ``` A successful verification proves the tarball was built in the `axios/axios` GitHub Actions environment on a known commit. It was not tampered with between build and registry. It does not prove the code in that commit is free of bugs. If `npm audit signatures` reports a missing or invalid attestation for a recent `axios` version, treat it as a potential supply-chain incident and report via the private channel below. ## Reporting a vulnerability If you believe you have found a security vulnerability in axios, report it through the private channel below. If the vulnerability is in a third-party library, report it to that library's maintainers. ## Reporting process Do not report security vulnerabilities through public GitHub issues. Use GitHub's private security channel by opening a [security advisory](https://github.com/axios/axios/security). ## Disclosure policy When we receive a security vulnerability report, we assign it a primary handler. The handler confirms the problem, determines affected versions, evaluates severity, develops and ships a fix, and coordinates public disclosure with the reporter. ### 60-day resolution and disclosure commitment We commit to resolving and publicly disclosing every valid security advisory within 60 calendar days of the initial report, measured from the moment a report is received through the [GitHub security advisory channel](https://github.com/axios/axios/security/advisories/new). The 60-day clock is a commitment to reporters and downstream consumers. It is a backstop, not an aspiration. If we cannot ship a fix in time, we still publish the advisory at day 60 with mitigation guidance so consumers can act. We then keep working on the fix and update the advisory with patch details when they are ready. We release the fix separately from the advisory, but we do not delay the advisory beyond day 60. We try to release the fix before publishing the advisory so users can patch before vulnerability details are public. Exceptions and extensions: - If a reporter requests a shorter embargo (e.g. they plan to present findings at a conference), we accommodate where possible. - If a fix requires a breaking change, coordinating with major downstream consumers, or a `follow-redirects` / `form-data` / `proxy-from-env` upstream release, we may extend beyond 60 days. Any extension is disclosed publicly at day 60 via the advisory, with a revised ETA and the reason. - If a report turns out to be out of scope (e.g. falls under an explicit non-goal in [THREATMODEL.md §2.6](THREATMODEL.md)), we close it with an explanation to the reporter within the triage window (≤ 3 days). Out-of-scope reports do not enter the 60-day queue. - Actively exploited vulnerabilities are treated as incidents. The fix and advisory ship as soon as a patch is validated, not on the 60-day schedule. Reporter expectations: While a report is under embargo, we ask reporters not to disclose it publicly until the earlier of the coordinated advisory publication or day 60. If the 60-day deadline passes without action from us, reporters are free to disclose independently. We treat that as a failure on our part, not on theirs. ## Security updates We release security updates after the patch is developed and tested. We notify users through the project's GitHub repository, publish release notes and security advisories on GitHub releases, and deprecate all versions that contain the vulnerability. ## Security partners and acknowledgements Thanks to these security researchers for working with us: - [Socket Dev](https://socket.dev/) - [GitHub Security Lab](https://securitylab.github.com/) axios-axios-2d06f96/THREATMODEL.md000066400000000000000000002706231521272452000164240ustar00rootroot00000000000000# Axios threat model This document describes the threat model for axios: a library used at runtime by millions of applications, and an open-source project with a build pipeline, release infrastructure, and human maintainers. It is for maintainers, security researchers, and downstream consumers doing supply chain due diligence. If you find a gap, open a security advisory rather than a public issue. --- ## 1. Scope and methodology We model two distinct systems: | System | What is being protected | Who attacks it | | ------------------ | ------------------------------------------- | ----------------------------------------------------------------- | | Runtime | Applications that `import axios` | Malicious servers, network attackers, malicious application input | | Project / SDLC | The integrity of what gets published to npm | Supply-chain attackers, phishers, malicious contributors | For each system, we list assets, trust boundaries, threat actors, and threats, rated by likelihood x impact. When mitigations exist in the codebase, we cite the file. When they do not, we say so. The runtime model is general by design. axios is a transport library and cannot know what its callers consider sensitive. The project model is specific and actionable. --- ## 2. Runtime threat model ### 2.1 System overview ``` ┌─────────────────┐ │ Application │ ← trusted: writes the config, owns the secrets │ (caller code) │ └────────┬────────┘ │ axios(config) ┌────────▼────────┐ │ Interceptors │ ← caller-supplied code, runs in-process ├─────────────────┤ │ Config merge │ ← lib/core/mergeConfig.js │ URL build │ ← lib/core/buildFullPath.js, lib/helpers/buildURL.js │ Header build │ ← lib/core/AxiosHeaders.js ├─────────────────┤ │ Adapter │ ← http.js / xhr.js / fetch.js └────────┬────────┘ │ ═════════▼═════════ ← TRUST BOUNDARY (network) │ ┌────────▼────────┐ │ Proxy (opt.) │ ← partially trusted (sees plaintext if HTTP) └────────┬────────┘ ┌────────▼────────┐ │ Origin server │ ← UNTRUSTED in the general case │ + redirects │ └─────────────────┘ ``` ### 2.2 Assets | Asset | Why it matters | | ------------------------------ | ------------------------------------------------------------ | | Credentials in transit | `config.auth`, `Authorization` headers, cookies, XSRF tokens | | Request/response bodies | May contain PII, business secrets | | The caller's process integrity | Prototype pollution can lead to RCE in some downstream gadgets | | The caller's internal network | SSRF can pivot through the host running axios | | Availability | Decompression bombs, redirect loops, slow-loris responses | ### 2.3 Trust boundaries 1. Caller to axios. The caller is fully trusted. Anything the caller passes in `config` is assumed intentional. axios does not defend against a malicious caller; that is a non-goal. 2. axios to network. Everything past the socket is untrusted: response status, headers, body, redirect `Location`, proxy responses. 3. axios to environment variables. `HTTP_PROXY` / `HTTPS_PROXY` / `NO_PROXY` are read by `proxy-from-env`. An attacker who controls the environment can redirect all traffic. This is treated as trusted because it has the same privilege as the process, but it is a relevant pivot in container-escape and CI scenarios. 4. Caller-supplied hooks to axios internals. Interceptors, `transformRequest`, `transformResponse`, `paramsSerializer`, `beforeRedirect`, and custom adapters run with full process privilege. axios does not sandbox them. ### 2.4 Threat actors | Actor | Capability | | ----------------------------- | -------------------------------------------------------------------------------------------------------------------- | | Malicious server | Controls every byte of the response. Most common. | | On-path network attacker | MITM. Mitigated by TLS unless the caller disabled validation. | | Malicious redirect target | A trusted server redirects to an attacker. The attacker sees whatever axios forwards. | | Application user | Controls part of the request (e.g. a URL path segment, a query param, a header value) via the calling application. | ### 2.5 Threats > Severity = Likelihood x Impact, rated for a typical server-side deployment. Browser deployments inherit the browser's same-origin policy and are generally lower risk for SSRF and credential leakage. --- #### T-R1: SSRF via caller-controlled URL | | | | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Description** | Application interpolates user input into `config.url` or `config.baseURL`. Attacker supplies `http://169.254.169.254/`, `http://localhost:6379/`, `file://`, `gopher://`, etc. | | **Likelihood** | **High.** This is the #1 real-world axios misuse pattern. | | **Impact** | **High.** Cloud metadata theft, internal service access. | | **In scope?** | **Partially.** axios cannot know which URLs the caller intends to allow. | | **Mitigations** | • `allowAbsoluteUrls: false` prevents a relative `url` from overriding `baseURL` (`lib/core/buildFullPath.js`). Defaults to `true` for back-compat.
• The HTTP adapter only speaks `http:`/`https:`/`file:`/`data:` (Node) or `http:`/`https:`/`file:`/`blob:`/`url:`/`data:` (browser); exotic schemes like `gopher:` are rejected (`lib/platform/node/index.js`, `lib/platform/browser/index.js`).
• No built-in host allowlist. Callers must validate destinations themselves. | | **Residual risk** | Substantial. This is documented as caller responsibility. | --- #### T-R2: Credential leakage on cross-origin redirect | | | | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Description** | Caller sets `Authorization: Bearer …` and requests `https://api.trusted.com/x`. Server responds `302 Location: https://evil.com/`. Does the bearer token go to evil.com? | | **Likelihood** | Medium | | **Impact** | High (full credential theft) | | **Mitigations** | • Node adapter delegates to `follow-redirects@^1.16.0`, which strips `Authorization`, `Cookie`, and `Proxy-Authorization` on cross-host redirects and on HTTPS→HTTP downgrades.
• `sensitiveHeaders` lets callers list custom secret-bearing headers (for example `X-API-Key`) that axios strips on cross-origin redirects.
• `maxRedirects` defaults to 5; set to `0` to handle redirects manually.
• `beforeRedirect` callback allows custom inspection.
• Browser adapters (XHR/fetch) delegate to the browser, which applies its own cross-origin credential rules. | | **Residual risk** | Low for standard credential headers and configured custom secret headers. We inherit `follow-redirects`' security posture - it is a critical transitive dependency and its CVEs are our CVEs. Callers must list any custom secret headers they want stripped. | --- #### T-R3: Header injection (CRLF) | | | | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Description** | Application puts user input into a header value: `headers: { 'X-User': req.query.name }`. Attacker supplies `foo\r\nX-Injected: bar\r\n\r\n`. A related surface is multipart per-part headers: attacker-controlled `blob.type` or `blob.name` flowing into the multipart body. | | **Likelihood** | Low | | **Impact** | Medium to High (request smuggling, response splitting, multipart parser confusion) | | **Mitigations** | • `lib/core/AxiosHeaders.js` rejects header values containing `\r` or `\n`, and validates header names against an RFC-7230-shaped charset. Node's own `http` module also rejects these.
• `lib/helpers/formDataToStream.js` strips CRLF from `value.type` and percent-encodes CRLF/`"` in `value.name` via `escapeName()` before interpolating them into per-part headers (GHSA-445q-vr5w-6q77). Node's `http` module does not defend here; multipart injection is in body bytes, not request headers. | | **Residual risk** | Very low for HTTP headers (defense in depth: axios + Node). Low for multipart body headers (single layer of defense; regressions here would be silent). | --- #### T-R4: Prototype pollution, write side (polluting response / merge into a target object) | | | | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Description** | Server returns `{"__proto__": {"isAdmin": true}}`. If axios merged this into an object naively, every `{}` in the process would gain `.isAdmin`. | | **Likelihood** | Low (requires a downstream gadget to be exploitable) | | **Impact** | High (process-wide state corruption, sometimes RCE) | | **Mitigations** | • `JSON.parse` itself does not pollute (it creates own-properties named `__proto__`, not prototype links).
• Internal merge paths filter dangerous keys: `lib/utils.js` and `lib/core/mergeConfig.js` filter `__proto__` / `constructor` / `prototype`; `lib/helpers/formDataToJSON.js` filters `__proto__`.
• These were added in response to past advisories. A regression here is a P0. | | **Residual risk** | Low, but this is an area of active attacker interest. New merge helpers must go through the same filtering. | --- #### T-R4b: Prototype pollution, read-side gadgets (polluted `Object.prototype` drives axios behavior) | | | | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Description** | A _different_ library in the caller's dependency tree pollutes `Object.prototype` (e.g. `Object.prototype.validateStatus = () => true`). axios code that reads a config property through the prototype chain then picks up the attacker's value and executes the associated behavior. Each reachable property is a distinct **gadget**: `validateStatus` (bypass HTTP error handling), `parseReviver` (silently tamper JSON response bodies), `transport` / `httpAgent` / `lookup` (MITM / intercept), `withXSRFToken` (leak XSRF token cross-origin), `transformResponse` (response replacement), and so on. | | **Likelihood** | Low to Medium (requires a polluted prototype somewhere in the process, historically common). | | **Impact** | High. Arbitrary behavior change across every axios call (auth bypass, response tampering, credential leakage). Unlike T-R4, this does not require axios itself to pollute; any polluted process is enough. | | **Mitigations** | Config reads that can drive behavior are routed through `hasOwnProp` guards so polluted prototype properties are not seen:
• `lib/core/mergeConfig.js`: per-prop reads from `config1`/`config2` guarded with `hasOwnProp`; `mergeDirectKeys` (used by `validateStatus`) uses `hasOwnProp` rather than the `in` operator which traverses the prototype chain (fix for GHSA-w9j2-pvgh-6h63).
• `lib/defaults/index.js`: `transformResponse` / `transformRequest` read `transitional`, `responseType`, `parseReviver`, `response` via an `own()` wrapper (fix for GHSA-3w6x-2g7m-8v23).
• `lib/adapters/http.js`: `transport`, `httpAgent`, `httpsAgent`, `lookup`, `family`, `http2Options`, etc. read via `hasOwnProp` (fix for GHSA-pf86-5x62-jrwf gadget set).
• `lib/helpers/resolveConfig.js`: `withXSRFToken` requires strict `=== true` to send the header cross-origin; non-boolean truthy values (`1`, `"false"`, `{}`) no longer short-circuit the same-origin check (fix for GHSA-xx6v-rp6x-q39c).
• Regression tests for the gadget class live in `tests/unit/prototypePollution.test.js` (both unit-level and end-to-end against `axios.get`). | | **Residual risk** | Low, but the surface is every config property read. Any new code path that reads `config.foo` / `this.foo` / destructures from a merged config must use a `hasOwnProp` guard. The non-goal that axios does not defend a caller with a polluted prototype is narrower than it sounds. The pollution typically comes from a transitive dependency, not from the caller's own intent, and the above mitigations neutralize the reachable gadgets even when the prototype is polluted. | --- #### T-R5: Decompression bomb | | | | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Description** | Server sends `Content-Encoding: gzip` with a 10 KB body that decompresses to 10 GB. | | **Likelihood** | Low | | **Impact** | Medium (DoS, OOM kill of the calling process) | | **Mitigations** | • `maxContentLength` bounds the decompressed response size in the Node adapter (`lib/adapters/http.js`), enforced chunk-by-chunk on the decompressed stream for both buffered and `responseType: 'stream'` responses (stream path fixed in GHSA-vf2m-468p-8v99).
• `maxBodyLength` bounds the request side, including when `maxRedirects === 0` (previously bypassed).
• Both default to `-1` (unlimited). Callers handling untrusted servers should set these. The README carries a top-level "security notice" call-out and `docs/pages/misc/security.md` documents the exact mitigation snippet in all four locales.
• Decompression uses Node's `zlib`, which streams. Memory is bounded by the limit, not the full expansion. | | **Residual risk** | Medium when limits are not configured. The defaults favor compatibility over safety; the reasoning is that tightening the default would silently break every legitimate download larger than whatever cap were chosen. | --- #### T-R6: TLS validation bypass | | | | ----------------- | --------------------------------------------------------------------------------------------------------------------------------- | | **Description** | Caller passes `httpsAgent: new https.Agent({ rejectUnauthorized: false })` to "fix" a certificate error in dev, ships it to prod. | | **Likelihood** | Medium (very common copy-paste anti-pattern) | | **Impact** | High (silent MITM) | | **In scope?** | **No.** axios delegates TLS entirely to Node's `https` module / the browser. We do not inspect or warn on agent configuration. | | **Mitigations** | None at the axios layer. Documentation responsibility only. | | **Residual risk** | High, but explicitly out of scope. This is caller misconfiguration, not an axios vulnerability. | --- #### T-R7: XSRF token sent cross-origin | | | | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Description** | Browser deployment. `xsrfCookieName` is set; attacker tricks the app into requesting `https://evil.com` and the XSRF token cookie value is attached as a header. | | **Likelihood** | Low | | **Impact** | Medium | | **Mitigations** | `lib/helpers/resolveConfig.js` only attaches the XSRF header when `isURLSameOrigin()` passes (or when `withXSRFToken` is explicitly forced). This was the fix for **CVE-2023-45857**. | | **Residual risk** | Low. The same-origin check uses the WHATWG `URL` parser (`lib/helpers/isURLSameOrigin.js`), which is robust against parser-differential attacks. | --- #### T-R8: Sensitive data in error objects | | | | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Description** | Request fails. `AxiosError` includes `config`, which includes `config.auth`, `config.headers.Authorization`, `config.httpsAgent` (with embedded client cert/key). Caller logs the error, exposing secrets in logs. | | **Likelihood** | **High** | | **Impact** | Medium to High | | **Mitigations** | `AxiosError.toJSON()` (`lib/core/AxiosError.js`) produces a reduced view, but the live error object still carries the full config by reference. | | **Residual risk** | Medium. Callers using structured loggers that walk object graphs (Winston, Pino with serializers, Sentry) will capture credentials unless they configure redaction. This is a documented risk, not a vulnerability, but it is the most common way axios users leak secrets in practice. | --- #### T-R9: Proxy environment variable hijack | | | | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Description** | Attacker controls the process environment (compromised CI step, container escape, `.env` injection) and sets `HTTPS_PROXY=http://evil.com:8080`. All axios traffic is now MITM'd. | | **Likelihood** | Low (requires prior foothold) | | **Impact** | High | | **Mitigations** | • `config.proxy: false` disables environment-based proxy detection entirely.
• `NO_PROXY` is honored (`lib/helpers/shouldBypassProxy.js`), with recent hardening for CIDR ranges, IPv6 literals, and wildcard patterns to close parser-differential edge cases.
• HTTPS through any proxy uses CONNECT tunneling via `https-proxy-agent` so the origin's cert is validated end-to-end and the proxy sees only SNI, never the URL, headers, or body. `Proxy-Authorization` is sent on the CONNECT request only, never on the wrapped TLS-protected request. | | **Residual risk** | Low for HTTPS. High for plain HTTP: the proxy sees and can modify everything. | --- #### T-R10: Malicious interceptor / adapter | | | | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Description** | Caller installs a third-party "axios plugin" from npm that registers an interceptor exfiltrating every `Authorization` header. | | **Likelihood** | Low to Medium | | **Impact** | High | | **In scope?** | **No.** Interceptors are caller-supplied code running in the caller's process. axios provides the hook; vetting what goes into it is the caller's job. | | **Residual risk** | Out of scope, but worth documenting: there is no meaningful difference between `axios.interceptors.request.use(evil)` and `require('evil')`. | --- #### T-R11: Form-data recursion DoS (deeply nested input) | | | | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Description** | Caller passes untrusted object input as request `data` in a context that serializes to `multipart/form-data` or `application/x-www-form-urlencoded`. A pathological input with thousands of nesting levels causes `lib/helpers/toFormData.js` to recurse until stack overflow or the process is killed. | | **Likelihood** | Low (requires the caller to serialize attacker-controlled object input without validation) | | **Impact** | Medium (DoS, stack overflow / process termination) | | **Mitigations** | • `formSerializer.maxDepth` caps recursion depth; default is 100, can be set to `Infinity` to disable.
• Exceeding the cap throws `AxiosError` with code `ERR_FORM_DATA_DEPTH_EXCEEDED` rather than crashing the process.
• Documented per locale in `docs/pages/advanced/multipart-form-data-format.md` and `docs/pages/advanced/x-www-form-urlencoded-format.md`. | | **Residual risk** | Low when callers leave the default in place. Setting `maxDepth: Infinity` reintroduces the risk. | --- ### 2.6 Explicit non-goals (runtime) axios will not: - Sandbox or validate caller-supplied functions (interceptors, transforms, adapters, serializers). - Validate that `config.url` points somewhere "safe." We don't know what safe means for your application. - Warn when TLS validation is disabled via a custom agent. - Redact `config` from thrown errors. The caller may legitimately need it for retry logic. - Defend against a fully compromised caller process (e.g. attacker-controlled code running inside the caller). For the narrower case of a polluted `Object.prototype` arriving via a transitive dependency, axios does defend the reachable config-read gadgets (see T-R4b), but any new config-read path must continue to use `hasOwnProp` guards to stay on this side of the line. - Defend against monkey-patched JavaScript or Node.js runtime APIs (`Object.keys`, `http.request`, `ClientRequest.prototype.setHeader`, `fetch`, etc.). If attacker-controlled code is already running in the same process, it can observe or alter requests below axios and this is outside axios' security boundary. --- ## 3. Project / supply chain threat model This model protects what gets published as `axios` on npm. A successful attack here compromises every downstream consumer at once. Given axios' install base, this is the higher-risk half of the document. ### 3.1 System overview ``` ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │ Maintainer's │ │ Contributor's │ │ GitHub.com │ │ workstation │ │ fork + PR │ │ (source of │ │ │ │ │ │ truth) │ │ ! npm token? │ │ untrusted code │ │ │ │ ! SSH keys │ │ │ │ │ │ ! GPG keys │ │ │ │ │ └────────┬─────────┘ └────────┬─────────┘ └────────▲─────────┘ │ │ │ │ git push │ PR │ └───────────────────────┴───────────────────────┘ │ tag push: v1.x.y │ ┌──────────────▼─────────────┐ │ GitHub Actions │ │ .github/workflows/ │ │ publish.yml │ │ │ │ • npm ci --ignore-scripts │ │ • npm run build │ │ • npm publish │ │ --provenance │ │ │ │ OIDC to npm (no token) │ └──────────────┬─────────────┘ │ ═══════════════▼═══════════════ registry.npmjs.org axios@1.x.y + provenance attestation ``` ### 3.2 Assets | Asset | Compromise means… | | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | **The npm `axios` package name** | Attacker can publish malware as `axios@1.x.y+1`. Game over for the ecosystem. | | **npm publish capability** | Whether via token, OIDC trust, or account takeover. | | **GitHub `axios/axios` write access** | Attacker can push a tag, which triggers publish. Or modify `publish.yml` itself. | | **Maintainer GitHub accounts** | Transitively grants the above. | | **Maintainer workstation secrets** | SSH keys (GitHub push), `~/.npmrc` token if present (direct publish), GPG keys (signed commits), cloud creds (lateral movement). | | **Build determinism** | If `dist/` doesn't match `lib/`, a backdoor can hide in the minified bundle. | | **Runtime dependency integrity** | `follow-redirects`, `form-data`, `proxy-from-env`, `https-proxy-agent` ship inside every axios install. | ### 3.3 Trust boundaries 1. Contributor PRs to main branch. PRs from forks are untrusted. CI runs them, but `pull_request` workflows have no access to secrets and use a read-only `GITHUB_TOKEN`. 2. Main branch to release tag. Pushing to `v1.x` does not publish. Only pushing a `v1.*.*` tag does. Tag push requires write access. 3. GitHub Actions to npm. This boundary is crossed via OIDC (`id-token: write` to npm trusted publisher). The repo has no long-lived `NPM_TOKEN` secret. 4. Maintainer workstation to everything else. This is the softest boundary. A maintainer's laptop is a high-value, low-assurance environment. See §3.5. ### 3.4 Threat actors | Actor | Capability | Motivation | | ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | --------------------------------------- | | Drive-by contributor | Open a PR. No secrets, no write. | Sneak a backdoor past review. | | Compromised dependency | Attempt to run code on `npm install` via lifecycle scripts. Blocked on maintainer workstations (project `.npmrc`) and in CI (`--ignore-scripts` on every job). Residual execution path: plugin code under `npm run build` / `test` / `lint`. | Steal tokens, inject into build. | | Phisher | Send convincing emails/DMs. No technical access. | Maintainer GitHub/npm credential theft. | | Compromised maintainer account | Full write. Can push tags. Can edit workflows. | Direct publish of malware. | | GitHub / npm insider or platform compromise | Out of scope. We trust the platforms. | - | ### 3.5 Threats --- #### T-S1: Malicious code in a contributor PR | | | | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Description** | Attacker opens a PR with a subtle backdoor: an obfuscated payload in a test fixture, a Unicode homoglyph in a comparison, or a malicious `rollup` plugin in the config. | | **Likelihood** | **High** (attempts are constant on high-profile repos) | | **Impact** | Critical, _if_ it lands | | **Mitigations** | • Mandatory review before merge.
• `pull_request` workflows run with no secrets and a read-only token, so a malicious test cannot exfiltrate anything from CI.
• `pull_request_target` is not used because it would grant secrets to fork code.
• `zizmor` lints workflow files for known-dangerous patterns.
• Branch protection on `v1.x`.
• Package, lockfile, and GitHub Actions update PRs are maintainer/bot-only; outside-collaborator PRs for those updates are closed.
• Path-scoped `.github/CODEOWNERS` flags sensitive paths explicitly: runtime source (`/lib/`, `/index.*`), build/release infrastructure (`rollup.config.js`, `package.json`, `package-lock.json`, `.npmrc`), CI automation (`.github/workflows/`, `.github/dependabot.yml`, `CODEOWNERS` itself), and security-critical docs (`THREATMODEL.md`, `SECURITY.md`). Changes to these paths surface the scoped ownership rule in the PR review UI distinct from the catch-all. The audit trail shows that the PR touched a sensitive path. | | **Gaps** | • Review is human and fallible. Obfuscated changes to `dist/` (if checked in) or to large test fixtures are hard to spot.
• No automated diffing of `lib/` to `dist/` to catch build-output tampering.
Single-maintainer constraint: with `@jasonsaayman` as sole owner on every scoped path, CODEOWNERS cannot enforce a second reviewer. Two-person review on sensitive paths remains unavailable until a co-maintainer is added. Path-scoping is pre-staged for that event. | --- #### T-S2: Compromised dev dependency steals maintainer keys > Historically the weakest link. The project-level `.npmrc` and hardware-backed maintainer keys materially improve it, but build-tool plugin execution (Rollup/Babel/Vitest/ESLint) is still the top residual investment area. `ignore-scripts` does not affect those tools, and they run whenever a maintainer builds or tests. | | | | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Description** | One of the ~45 direct dev dependencies, or one of their thousands of transitive dependencies, is compromised (maintainer account takeover, expired domain re-registration, the usual). It ships a `postinstall` script that reads `~/.npmrc`, `~/.ssh/id_*`, `~/.config/gh/hosts.yml`, `~/.aws/credentials`, `~/.gnupg/` and POSTs them to an attacker.

The next time a maintainer runs `npm install` on their workstation, the script runs as the maintainer's user, with full filesystem access. No exploit needed. This is npm working as designed. | | **Likelihood** | Medium and rising. This exact pattern has hit `event-stream`, `ua-parser-js`, `coa`, `rc`, `node-ipc`, `@solana/web3.js`, the Ledger connect-kit, the 2024 polyfill.io incident, and dozens more. axios' dev tree includes Babel, Rollup, Gulp, ESLint, Vitest, and Playwright, each pulling hundreds of transitives. The attack surface is enormous and refreshes on every `npm install`. | | **Impact** | Critical. A stolen npm token with publish rights means direct malware publish. A stolen SSH key with GitHub push rights means tag push, then publish via CI. Either path ends the same way. | | **Current mitigations** | • CI is protected: `publish.yml` runs `npm ci --ignore-scripts`, so a malicious lifecycle script cannot execute during the release build.
• CI uses OIDC, not a stored token. There is no `NPM_TOKEN` secret in GitHub for a malicious workflow step to steal.
• `package-lock.json` pins versions and integrity hashes. A new malicious version won't arrive silently, only on explicit update.
• Project-local `.npmrc` sets `ignore-scripts=true`, so `npm install` / `npm ci` in a contributor or maintainer checkout does not execute lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency.
• `husky` is the only `prepare` hook axios itself declares, and only writes `.git/hooks/`. With `ignore-scripts=true` it must be run manually (`npm rebuild husky && npx husky`), documented in the README "Contributing / Local setup" section. | | **Gaps: workstation** | `ignore-scripts=true` neutralizes the lifecycle-script path, but it does not neutralize build-time code execution. A malicious Rollup / Babel / Terser / ESLint / Vitest plugin still runs when a maintainer executes `npm run build` / `npm test` / `npm run lint`. Those are not lifecycle scripts; they are tools the maintainer explicitly invoked.

The lockfile pins which packages install, but if one of those pinned packages was already malicious when the lock was generated, or the maintainer runs `npm update` / `npm install ` without re-setting `ignore-scripts`, fresh lifecycle scripts can land.

The development environment still has full read access to every credential the maintainer's user can read once a build tool runs. Isolation (devcontainer / VM) remains the strongest control. | Mitigations adopted and recommended. Adopted items are enforced via the repo; others depend on per-maintainer discipline. 1. Don't keep a publish-capable npm token on your workstation. Publishing happens via GitHub Actions OIDC. There is no workflow that requires `npm publish` from a laptop. If `~/.npmrc` has a token, it should be read-only or scoped to unrelated packages. If there is nothing to steal, this attack path is defanged. 2. Run `npm install` / `npm ci` with `--ignore-scripts` locally. Adopted: project ships a `.npmrc` with `ignore-scripts=true`. All `npm install` / `npm ci` runs in a contributor or maintainer checkout skip lifecycle scripts by default. To set up git hooks after install, run the one trusted script manually: ``` npm rebuild husky && npx husky ``` The minor inconvenience of manually running known-good post-install steps is the price of not running thousands of unknown ones. Contributors adding a new dev dependency must not override this flag. 3. Develop in an isolated environment. A devcontainer, VM, or sandbox profile that does not have: - `~/.ssh/` mounted (use a separate deploy key or SSH agent forwarding only when pushing) - `~/.npmrc` with publish tokens - `~/.config/gh/` with a `repo`-scoped GitHub token - `~/.aws/`, `~/.config/gcloud/`, etc. The dev environment should be able to read/write the repo working tree and reach the network for tests. Nothing else. 4. Use hardware-backed keys for GitHub. Adopted project-wide. All maintainers use FIDO2/WebAuthn for GitHub auth and `sk-ssh-ed25519@openssh.com` for git push. A stolen `~/.ssh/id_ed25519_sk` is useless without the physical key. This converts "steal a file" into "steal a file and a physical object." Each maintainer should keep a backup key registered and stored separately. 5. Audit lockfile diffs on dependency-update PRs as carefully as code. A 4000-line `package-lock.json` diff hides a lot. Tooling: `npm diff`, `lockfile-lint`, Socket.dev's PR integration. Pay particular attention to new packages with install scripts (`hasInstallScript: true` in the lockfile). 6. Don't add dev dependencies casually. Each one is a recurring trust decision delegated to a stranger. Prefer tools that can run via `npx` on demand (not in `node_modules`) or that are already in the tree. --- #### T-S3: Phishing to maintainer account takeover | | | | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Description** | Maintainer receives a convincing email:
• "npm security alert: your axios package has been flagged, log in to verify ownership" links to a fake npm login; password + TOTP are captured and replayed in real time.
• "GitHub: @axios has been added to a new organization, review access" links to a fake GitHub OAuth consent screen; the attacker app gets `repo` scope.
• Social: a "recruiter" asks the maintainer to clone and `npm install` a "take-home assignment" repo.

npm and GitHub credentials for axios maintainers have been specifically targeted by these campaigns in the past. This is not theoretical. | | **Likelihood** | High. These campaigns are continuous. | | **Impact** | Critical. GitHub account to push tag to publish. npm account to publish directly. | | **Mitigations** | • npm 2FA is required for publish on the `axios` package.
• OIDC publishing means there is no maintainer npm session involved in a normal release. This narrows the attack to GitHub.
• All maintainers authenticate to GitHub with hardware-backed WebAuthn/passkeys (FIDO2 security keys / platform authenticators). Origin-bound credentials cannot be relayed by a phishing proxy (Evilginx, Modlishka). TOTP alone is not permitted for maintainer accounts.
• Git push uses `sk-ssh-ed25519@openssh.com` hardware-resident SSH keys where supported. A stolen key file is useless without the physical device. | | **Gaps** | • Enforcement is per-account policy, not verifiable from the repo itself. Onboarding/offboarding checklist should confirm hardware-key status.
• Incident-response runbook is documented in §3.7 and needs periodic rehearsal to stay useful.
• Each maintainer should register at least 2 hardware keys (primary + backup stored separately) to avoid lockout-driven fallback to weaker recovery methods. | --- #### T-S4: Compromised runtime dependency | | | | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Description** | `follow-redirects`, `form-data`, `proxy-from-env`, or `https-proxy-agent` ships a malicious version. Unlike T-S2, this code ends up in the published axios bundle / runtime rather than being limited to maintainer machines. Every axios consumer runs it. | | **Likelihood** | Low (only 4 deps; all are mature, narrowly-scoped, and watched) | | **Impact** | Critical | | **Mitigations** | • Three runtime deps total, minimal by design.
• `^` ranges in `package.json` mean consumers may get newer patch versions than the lockfile pins. This is intentional, because consumers get security fixes, but it also means a malicious patch release of `follow-redirects` propagates without an axios release.
• `follow-redirects` is security-conscious and well-maintained; we track its advisories closely (multiple past axios releases were just `follow-redirects` bumps).
• Dependabot is configured (`.github/dependabot.yml`) for both npm and GitHub Actions, running weekly with grouped updates for production and development dependencies. The 7-day cooldown stays in place unless a critical vulnerability requires a maintainer-led manual update. | | **Gaps** | • No vendoring/inlining considered. The deps are small enough that vendoring is plausible, but it would forfeit upstream security fixes. Current judgment: not worth it. | --- #### T-S5: Build-output tampering (`dist/` != `lib/`) | | | | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Description** | The published tarball contains a `dist/axios.min.js` that does not match what `rollup` would produce from `lib/`. Nobody reads minified bundles. A backdoor here is invisible to source review.

Vectors: a malicious dev-dep Rollup/Babel/Terser plugin injects code at build time (T-S2 applied to CI), or a maintainer with a compromised workstation accidentally publishes a tampered local build. | | **Likelihood** | Low | | **Impact** | Critical | | **Mitigations** | • Builds run only in CI as part of `publish.yml`, from a clean `npm ci --ignore-scripts` checkout. There is no "publish from laptop" path.
• `--ignore-scripts` means a malicious dev dependency cannot tamper with `node_modules` before the build, but it can still tamper during the build if it is a Rollup/Babel plugin. Those run as part of `npm run build`, not as lifecycle scripts.
• npm provenance (`--provenance`) cryptographically attests which workflow on which commit produced the tarball. Consumers can verify with `npm audit signatures`. This proves the build ran in GitHub Actions on a known SHA. It does not prove the build is correct, only that it is traceable. | | **Gaps** | • The build is not currently reproducible in the strict sense. A third party cannot independently rebuild and get a byte-identical `dist/`. Timestamps, plugin ordering, and minifier nondeterminism would need to be locked down.
• `.github/workflows/verify-build-reproducibility.yml` performs a two-pass build-and-diff on PRs that touch build-related paths (`lib/**`, `rollup.config.js`, `package.json`, `package-lock.json`, and the workflow itself). It is currently non-blocking (`continue-on-error: true`). It surfaces divergence in the CI summary so reproducibility regressions are visible, without gating merges until the build is deterministic. Once divergence is eliminated, remove `continue-on-error` to promote this to a hard gate. | --- #### T-S6: Workflow file tampering | | | | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Description** | Attacker with write access (or a merged PR that was not reviewed carefully) modifies `.github/workflows/publish.yml` to `curl` the OIDC token somewhere, or to add a step that patches `dist/` after the build. | | **Likelihood** | Low | | **Impact** | Critical | | **Mitigations** | • All actions are pinned to full commit SHAs, not tags: `actions/checkout@de0fac...`, not `@v6`. A compromised action tag can't silently change behavior.
• `permissions:` are minimal (`contents: read`, `id-token: write`).
• `persist-credentials: false` on checkout, so the build steps cannot push back to the repo.
• `zizmor` lints workflows on every PR and push to `v1.x` (`.github/workflows/zizmor.yml`); results surface as GitHub code-scanning alerts via the `security-events: write` permission on that job. This job must remain in the required-checks set on `v1.x` branch protection for the mitigation to be binding.
• The `npm-publish` GitHub Environment can require designated reviewers before the job runs; a tampered workflow still pauses for human approval.
• CODEOWNERS carries a path-scoped rule for `/.github/workflows/` and `/.github/CODEOWNERS` itself, so workflow and ownership changes surface in the review UI as touching a scoped path rather than being folded into the default approval. | | **Gaps** | • Single-maintainer constraint (see T-S1): with one owner, the path-scoped rule cannot enforce a second reviewer on workflow changes. The rule surfaces the sensitivity but does not block single-maintainer approval. Closing this requires adding a co-maintainer. | --- #### T-S7: Tag confusion / replay | | | | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Description** | Attacker with write access force-pushes an existing tag to point at a malicious commit, or pushes `v1.99.99` so that a release is published out of band. | | **Likelihood** | Low (requires write access; assumed compromised at that point) | | **Impact** | High | | **Mitigations** | • npm rejects re-publishing an existing version. Re-tagging cannot overwrite the published `1.15.0`.
• Provenance attestation records the commit SHA the tag pointed to at publish time, which is forensically verifiable. Consumers can confirm with `npm audit signatures axios` (documented in SECURITY.md).
• Tag protection rules: repository setting must forbid tag deletion and force-push for the `v1.*.*` pattern. This is a GitHub UI setting (Settings > Tags > rulesets), not file-based; enforcement is auditable via the Rulesets REST API. | | **Gaps** | A new malicious version (`v1.x.x`) is still publishable by anyone with tag-push rights. This collapses back into T-S3 (account security). | --- #### T-S8: Typosquatting / dependency confusion | | | | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Description** | Attacker publishes `axois`, `axios-http`, `@axios/core`, etc., and waits for typos. Or publishes a package shadowing an internal name used in a consumer's monorepo. | | **Likelihood** | High (these packages already exist) | | **Impact** | Medium. Affects confused consumers, not axios itself | | **In scope?** | Mostly out of scope; the axios project cannot police the npm namespace. | | **Mitigations** | • npm has typosquat detection at publish time (imperfect).
• The `@axios/` npm scope is not owned by the project. `@axios/anything` can be registered by anyone. This is a gap, not a mitigation.
• Provenance gives consumers a way to verify they got the real thing. | --- ### 3.6 Summary: project risk posture | Threat | Likelihood | Impact | Current Posture | Priority Gap | | ---------------------------- | ---------- | ------------ | --------------- | --------------------------------------------------------------------- | | T-S1 Malicious PR | High | Critical | Good | Second maintainer to enable two-person review on scoped paths | | T-S2 Dev-dep steals keys | Medium | Critical | Partial | Isolated dev environment (devcontainer/VM); no publish tokens on workstations. Lifecycle scripts now blocked via project `.npmrc`, but build-tool plugins still execute | | T-S3 Phishing | High | Critical | Good | Document phish-response runbook; require registered backup hardware key | | T-S4 Runtime dep compromise | Low | Critical | Good | - | | T-S5 Build tampering | Low | Critical | Adequate | Eliminate build non-determinism, then promote reproducibility check to blocking | | T-S6 Workflow tampering | Low | Critical | Good | Second maintainer (two-person review) for `/.github/workflows/` | | T-S7 Tag replay | Low | High | Good | - | | T-S8 Typosquat | High | Medium | Out of scope | - | The top remaining investment is T-S2 (dev-dependency compromise of maintainer workstations). Lifecycle-script execution is now blocked by the project-level `.npmrc`, and T-S3 phishing risk dropped materially once all maintainers moved to hardware-backed WebAuthn. Real-time credential relay no longer works. The residual T-S2 gap is build-tool plugin execution (Rollup/Babel/Vitest/ESLint), which `ignore-scripts` does not cover. Closing it requires running builds in an isolated environment without access to long-lived credentials. --- ### 3.7 Incident response runbook If a maintainer suspects credential compromise (phish clicked, lost hardware key, unexpected tag/publish, leaked token in logs), execute the steps below in order. Speed matters more than completeness. A published malicious version affects every downstream consumer. #### 1. Contain, minutes 0 to 15 - GitHub: revoke all active sessions (`https://github.com/settings/sessions`), revoke all OAuth/PAT tokens (`/settings/tokens`, `/settings/applications`), review authorized SSH keys and remove any unrecognised. If a PAT with `repo` or `admin:org` scope existed, assume leak. - npm: run `npm token list` and `npm token revoke ` for any publish-capable token. If no CLI access, revoke via `https://www.npmjs.com/settings//tokens`. Rotate npm password and force sign-out of all sessions. - Workstation: if a build/install ran malicious code, assume full-user compromise of the laptop. Unplug from trusted networks. Do not rely on AV; move to a clean machine for rotation steps. #### 2. Assess, minutes 15 to 60 - Check `https://github.com/axios/axios/settings/security-log` and `https://github.com//security/log` for unrecognised events (key adds, org changes, force-pushes, new tags). - Verify recent tags match intent: `git log --tags --oneline -n 20`. Compare with `https://www.npmjs.com/package/axios?activeTab=versions`. - For each recent publish, verify provenance: `npm audit signatures axios@` and cross-check the `sourceCommit` in the provenance attestation against the tag's SHA. Divergence = investigate. - Review `~/.npmrc`, `~/.ssh/`, `~/.config/gh/hosts.yml`, `~/.gnupg/` for tampering and unexpected files. #### 3. Rotate, hour 1 to 4 - Generate new SSH keys on clean hardware. Remove old keys from GitHub. If using `sk-ssh-ed25519@openssh.com`, register new hardware key first, then deregister the old one. Do not leave the account with zero registered keys. - Re-enrol WebAuthn authenticators (both primary and backup). Deregister lost/compromised authenticators. - Rotate GPG keys if signed commits are used; upload new key to GitHub. - Rotate any cloud credentials (`~/.aws/`, `~/.config/gcloud/`) and any tokens present on the compromised machine. #### 4. Notify, hour 1 onward - npm security: `security@npmjs.com`. Include package name, suspected versions, timeline. - GitHub security: `https://github.com/contact`, Security category. Request an investigation of the account. - Downstream: open a GitHub security advisory (`https://github.com/axios/axios/security/advisories/new`) as soon as a malicious version is confirmed published. Do not wait for a fix. Users need to pin away from the bad version. - Co-maintainers (when present): notify via out-of-band channel (phone/Signal), not through the compromised channel. #### 5. Unpublish / deprecate, hour 1 to 24 - npm allows `npm unpublish @` within 72 hours of publish. After that, use `npm deprecate @ ""` with a message pointing to the advisory. - Publish a patched version that bumps semver above the malicious one, so `^` consumers move forward automatically. #### 6. Post-mortem, within 1 week - Write up timeline: initial vector, dwell time, scope, mitigations applied. - Update this threat model if the incident reveals a gap not captured here. - File a PR if any mitigation can be codified (new CI check, new lint rule, new CODEOWNERS path). Keep this runbook current. A runbook no one has rehearsed is a document, not a control. --- _This document describes intent and current understanding. It does not constitute a security guarantee. To report a gap in the model itself, use the same private advisory channel as for code vulnerabilities._ axios-axios-2d06f96/docs/000077500000000000000000000000001521272452000152505ustar00rootroot00000000000000axios-axios-2d06f96/docs/.vitepress/000077500000000000000000000000001521272452000173525ustar00rootroot00000000000000axios-axios-2d06f96/docs/.vitepress/config.mts000066400000000000000000000356111521272452000213520ustar00rootroot00000000000000import { defineConfig } from 'vitepress'; // https://vitepress.dev/reference/site-config // ─── English ───────────────────────────────────────────────────────────────── const enNav = [ { text: 'Guide', link: '/pages/getting-started/first-steps' }, { text: 'API', link: '/pages/advanced/api-reference' }, { text: 'Sponsors', link: '/pages/misc/sponsors' }, { text: 'v1.x', link: '#' }, ]; const enSidebar = [ { text: 'Getting Started', items: [ { text: 'First steps', link: '/pages/getting-started/first-steps' }, { text: 'Features', link: '/pages/getting-started/features' }, { text: 'Examples', items: [ { text: 'JavaScript', link: '/pages/getting-started/examples/commonjs' }, { text: 'TypeScript', link: '/pages/getting-started/examples/typescript' }, ], }, { text: 'Upgrade guide v0.x -> v1.x', link: '/pages/getting-started/upgrade-guide' }, ], }, { text: 'Advanced', items: [ { text: 'Public API', link: '/pages/advanced/api-reference' }, { text: 'Request method aliases', link: '/pages/advanced/request-method-aliases' }, { text: 'Creating an instance', link: '/pages/advanced/create-an-instance' }, { text: 'Request config', link: '/pages/advanced/request-config' }, { text: 'Adapters', link: '/pages/advanced/adapters' }, { text: 'Response schema', link: '/pages/advanced/response-schema' }, { text: 'Config defaults', link: '/pages/advanced/config-defaults' }, { text: 'Interceptors', link: '/pages/advanced/interceptors' }, { text: 'Error handling', link: '/pages/advanced/error-handling' }, { text: 'Cancellation', link: '/pages/advanced/cancellation' }, { text: 'Authentication', link: '/pages/advanced/authentication' }, { text: 'Retry & error recovery', link: '/pages/advanced/retry' }, { text: 'Testing', link: '/pages/advanced/testing' }, { text: 'x-www-form-urlencoded format', link: '/pages/advanced/x-www-form-urlencoded-format', }, { text: 'Multipart/form-data format', link: '/pages/advanced/multipart-form-data-format' }, { text: 'File posting', link: '/pages/advanced/file-posting' }, { text: 'HTML form processing 🔥', link: '/pages/advanced/html-form-processing' }, { text: 'Progress capturing 🔥', link: '/pages/advanced/progress-capturing' }, { text: 'Rate limiting 🔥', link: '/pages/advanced/rate-limiting' }, { text: 'Headers 🔥', items: [ { text: 'General usage', link: '/pages/advanced/headers' }, { text: 'Methods', link: '/pages/advanced/header-methods' }, ], }, { text: 'Fetch adapter 🔥', link: '/pages/advanced/fetch-adapter' }, { text: 'HTTP2 🔥', link: '/pages/advanced/http2' }, { text: 'Promises', link: '/pages/advanced/promises' }, { text: 'TypeScript', link: '/pages/advanced/type-script' }, ], }, { text: 'Miscellaneous', items: [ { text: 'SemVer', link: '/pages/misc/semver' }, { text: 'Security', link: '/pages/misc/security' }, ], }, ]; // ─── Mandarin Chinese ───────────────────────────────────────────────────────── const zhNav = [ { text: '指南', link: '/zh/pages/getting-started/first-steps' }, { text: 'API', link: '/zh/pages/advanced/api-reference' }, { text: '赞助商', link: '/zh/pages/misc/sponsors' }, { text: 'v1.x', link: '#' }, ]; const zhSidebar = [ { text: '入门指南', items: [ { text: '第一步', link: '/zh/pages/getting-started/first-steps' }, { text: '功能特性', link: '/zh/pages/getting-started/features' }, { text: '示例', items: [ { text: 'JavaScript', link: '/zh/pages/getting-started/examples/commonjs' }, { text: 'TypeScript', link: '/zh/pages/getting-started/examples/typescript' }, ], }, { text: '升级指南 v0.x -> v1.x', link: '/zh/pages/getting-started/upgrade-guide' }, ], }, { text: '进阶', items: [ { text: '公共 API', link: '/zh/pages/advanced/api-reference' }, { text: '请求方法别名', link: '/zh/pages/advanced/request-method-aliases' }, { text: '创建实例', link: '/zh/pages/advanced/create-an-instance' }, { text: '请求配置', link: '/zh/pages/advanced/request-config' }, { text: '适配器', link: '/zh/pages/advanced/adapters' }, { text: '响应结构', link: '/zh/pages/advanced/response-schema' }, { text: '默认配置', link: '/zh/pages/advanced/config-defaults' }, { text: '拦截器', link: '/zh/pages/advanced/interceptors' }, { text: '错误处理', link: '/zh/pages/advanced/error-handling' }, { text: '取消请求', link: '/zh/pages/advanced/cancellation' }, { text: '身份验证', link: '/zh/pages/advanced/authentication' }, { text: '重试与错误恢复', link: '/zh/pages/advanced/retry' }, { text: '测试', link: '/zh/pages/advanced/testing' }, { text: 'x-www-form-urlencoded 格式', link: '/zh/pages/advanced/x-www-form-urlencoded-format', }, { text: 'Multipart/form-data 格式', link: '/zh/pages/advanced/multipart-form-data-format' }, { text: '文件上传', link: '/zh/pages/advanced/file-posting' }, { text: 'HTML 表单处理 🔥', link: '/zh/pages/advanced/html-form-processing' }, { text: '进度捕获 🔥', link: '/zh/pages/advanced/progress-capturing' }, { text: '速率限制 🔥', link: '/zh/pages/advanced/rate-limiting' }, { text: '请求头 🔥', items: [ { text: '基本用法', link: '/zh/pages/advanced/headers' }, { text: '方法', link: '/zh/pages/advanced/header-methods' }, ], }, { text: 'Fetch 适配器 🔥', link: '/zh/pages/advanced/fetch-adapter' }, { text: 'HTTP2 🔥', link: '/zh/pages/advanced/http2' }, { text: 'Promises', link: '/zh/pages/advanced/promises' }, { text: 'TypeScript', link: '/zh/pages/advanced/type-script' }, ], }, { text: '其他', items: [ { text: '语义化版本', link: '/zh/pages/misc/semver' }, { text: '安全', link: '/zh/pages/misc/security' }, ], }, ]; // ─── Spanish ────────────────────────────────────────────────────────────────── const esNav = [ { text: 'Guía', link: '/es/pages/getting-started/first-steps' }, { text: 'API', link: '/es/pages/advanced/api-reference' }, { text: 'Patrocinadores', link: '/es/pages/misc/sponsors' }, { text: 'v1.x', link: '#' }, ]; const esSidebar = [ { text: 'Primeros pasos', items: [ { text: 'Inicio', link: '/es/pages/getting-started/first-steps' }, { text: 'Características', link: '/es/pages/getting-started/features' }, { text: 'Ejemplos', items: [ { text: 'JavaScript', link: '/es/pages/getting-started/examples/commonjs' }, { text: 'TypeScript', link: '/es/pages/getting-started/examples/typescript' }, ], }, { text: 'Guía de actualización v0.x -> v1.x', link: '/es/pages/getting-started/upgrade-guide', }, ], }, { text: 'Avanzado', items: [ { text: 'API pública', link: '/es/pages/advanced/api-reference' }, { text: 'Alias de métodos de solicitud', link: '/es/pages/advanced/request-method-aliases' }, { text: 'Crear una instancia', link: '/es/pages/advanced/create-an-instance' }, { text: 'Configuración de solicitud', link: '/es/pages/advanced/request-config' }, { text: 'Adaptadores', link: '/es/pages/advanced/adapters' }, { text: 'Esquema de respuesta', link: '/es/pages/advanced/response-schema' }, { text: 'Configuración predeterminada', link: '/es/pages/advanced/config-defaults' }, { text: 'Interceptores', link: '/es/pages/advanced/interceptors' }, { text: 'Manejo de errores', link: '/es/pages/advanced/error-handling' }, { text: 'Cancelación', link: '/es/pages/advanced/cancellation' }, { text: 'Autenticación', link: '/es/pages/advanced/authentication' }, { text: 'Reintento y recuperación de errores', link: '/es/pages/advanced/retry' }, { text: 'Pruebas', link: '/es/pages/advanced/testing' }, { text: 'Formato x-www-form-urlencoded', link: '/es/pages/advanced/x-www-form-urlencoded-format', }, { text: 'Formato Multipart/form-data', link: '/es/pages/advanced/multipart-form-data-format', }, { text: 'Publicación de archivos', link: '/es/pages/advanced/file-posting' }, { text: 'Procesamiento de formularios HTML 🔥', link: '/es/pages/advanced/html-form-processing', }, { text: 'Captura de progreso 🔥', link: '/es/pages/advanced/progress-capturing' }, { text: 'Limitación de velocidad 🔥', link: '/es/pages/advanced/rate-limiting' }, { text: 'Cabeceras 🔥', items: [ { text: 'Uso general', link: '/es/pages/advanced/headers' }, { text: 'Métodos', link: '/es/pages/advanced/header-methods' }, ], }, { text: 'Adaptador Fetch 🔥', link: '/es/pages/advanced/fetch-adapter' }, { text: 'HTTP2 🔥', link: '/es/pages/advanced/http2' }, { text: 'Promesas', link: '/es/pages/advanced/promises' }, { text: 'TypeScript', link: '/es/pages/advanced/type-script' }, ], }, { text: 'Miscelánea', items: [ { text: 'SemVer', link: '/es/pages/misc/semver' }, { text: 'Seguridad', link: '/es/pages/misc/security' }, ], }, ]; // ─── French ─────────────────────────────────────────────────────────────────── const frNav = [ { text: 'Guide', link: '/fr/pages/getting-started/first-steps' }, { text: 'API', link: '/fr/pages/advanced/api-reference' }, { text: 'Sponsors', link: '/fr/pages/misc/sponsors' }, { text: 'v1.x', link: '#' }, ]; const frSidebar = [ { text: 'Démarrage', items: [ { text: 'Premiers pas', link: '/fr/pages/getting-started/first-steps' }, { text: 'Fonctionnalités', link: '/fr/pages/getting-started/features' }, { text: 'Exemples', items: [ { text: 'JavaScript', link: '/fr/pages/getting-started/examples/commonjs' }, { text: 'TypeScript', link: '/fr/pages/getting-started/examples/typescript' }, ], }, { text: 'Guide de mise à niveau v0.x -> v1.x', link: '/fr/pages/getting-started/upgrade-guide', }, ], }, { text: 'Avancé', items: [ { text: 'API publique', link: '/fr/pages/advanced/api-reference' }, { text: 'Alias des méthodes de requête', link: '/fr/pages/advanced/request-method-aliases' }, { text: 'Créer une instance', link: '/fr/pages/advanced/create-an-instance' }, { text: 'Configuration des requêtes', link: '/fr/pages/advanced/request-config' }, { text: 'Adaptateurs', link: '/fr/pages/advanced/adapters' }, { text: 'Schéma de réponse', link: '/fr/pages/advanced/response-schema' }, { text: 'Configuration par défaut', link: '/fr/pages/advanced/config-defaults' }, { text: 'Intercepteurs', link: '/fr/pages/advanced/interceptors' }, { text: 'Gestion des erreurs', link: '/fr/pages/advanced/error-handling' }, { text: 'Annulation', link: '/fr/pages/advanced/cancellation' }, { text: 'Authentification', link: '/fr/pages/advanced/authentication' }, { text: "Nouvelles tentatives et récupération d'erreurs", link: '/fr/pages/advanced/retry' }, { text: 'Tests', link: '/fr/pages/advanced/testing' }, { text: 'Format x-www-form-urlencoded', link: '/fr/pages/advanced/x-www-form-urlencoded-format', }, { text: 'Format Multipart/form-data', link: '/fr/pages/advanced/multipart-form-data-format' }, { text: 'Envoi de fichiers', link: '/fr/pages/advanced/file-posting' }, { text: 'Traitement des formulaires HTML 🔥', link: '/fr/pages/advanced/html-form-processing', }, { text: 'Capture de la progression 🔥', link: '/fr/pages/advanced/progress-capturing' }, { text: 'Limitation du débit 🔥', link: '/fr/pages/advanced/rate-limiting' }, { text: 'En-têtes 🔥', items: [ { text: 'Utilisation générale', link: '/fr/pages/advanced/headers' }, { text: 'Méthodes', link: '/fr/pages/advanced/header-methods' }, ], }, { text: 'Adaptateur Fetch 🔥', link: '/fr/pages/advanced/fetch-adapter' }, { text: 'HTTP2 🔥', link: '/fr/pages/advanced/http2' }, { text: 'Promesses', link: '/fr/pages/advanced/promises' }, { text: 'TypeScript', link: '/fr/pages/advanced/type-script' }, ], }, { text: 'Divers', items: [ { text: 'SemVer', link: '/fr/pages/misc/semver' }, { text: 'Sécurité', link: '/fr/pages/misc/security' }, ], }, ]; // ─── Config ─────────────────────────────────────────────────────────────────── export default defineConfig({ title: 'axios | Promise based HTTP client', description: 'Documentation for the axios HTTP project', head: [ ['link', { rel: 'icon', href: '/favicon.ico' }], ['link', { rel: 'apple-touch-icon', sizes: '180x180', href: '/apple-touch-icon.png' }], ['link', { rel: 'icon', type: 'image/png', sizes: '32x32', href: '/favicon-32x32.png' }], ['link', { rel: 'icon', type: 'image/png', sizes: '16x16', href: '/favicon-16x16.png' }], ['link', { rel: 'manifest', href: '/site.webmanifest' }], ], locales: { root: { label: 'English', lang: 'en-US', themeConfig: { nav: enNav, sidebar: enSidebar, }, }, zh: { label: '中文', lang: 'zh-CN', themeConfig: { nav: zhNav, sidebar: zhSidebar, }, }, es: { label: 'Español', lang: 'es-ES', themeConfig: { nav: esNav, sidebar: esSidebar, }, }, fr: { label: 'Français', lang: 'fr-FR', themeConfig: { nav: frNav, sidebar: frSidebar, }, }, }, themeConfig: { logo: { dark: '/words.svg', light: '/words-light.svg', }, siteTitle: false, socialLinks: [{ icon: 'github', link: 'https://github.com/axios/axios' }], footer: { message: 'axios is provided under MIT license', copyright: 'Copyright © 2015-present axios collective', }, }, }); axios-axios-2d06f96/docs/.vitepress/theme/000077500000000000000000000000001521272452000204545ustar00rootroot00000000000000axios-axios-2d06f96/docs/.vitepress/theme/index.ts000066400000000000000000000006631521272452000221400ustar00rootroot00000000000000// https://vitepress.dev/guide/custom-theme import { h } from 'vue' import type { Theme } from 'vitepress' import DefaultTheme from 'vitepress/theme' import './style.css' export default { extends: DefaultTheme, Layout: () => { return h(DefaultTheme.Layout, null, { // https://vitepress.dev/guide/extending-default-theme#layout-slots }) }, enhanceApp({ app, router, siteData }) { // ... } } satisfies Theme axios-axios-2d06f96/docs/.vitepress/theme/style.css000066400000000000000000000102751521272452000223330ustar00rootroot00000000000000/** * Customize default theme styling by overriding CSS variables: * https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css */ /** * Colors * * Each colors have exact same color scale system with 3 levels of solid * colors with different brightness, and 1 soft color. * * - `XXX-1`: The most solid color used mainly for colored text. It must * satisfy the contrast ratio against when used on top of `XXX-soft`. * * - `XXX-2`: The color used mainly for hover state of the button. * * - `XXX-3`: The color for solid background, such as bg color of the button. * It must satisfy the contrast ratio with pure white (#ffffff) text on * top of it. * * - `XXX-soft`: The color used for subtle background such as custom container * or badges. It must satisfy the contrast ratio when putting `XXX-1` colors * on top of it. * * The soft color must be semi transparent alpha channel. This is crucial * because it allows adding multiple "soft" colors on top of each other * to create a accent, such as when having inline code block inside * custom containers. * * - `default`: The color used purely for subtle indication without any * special meanings attached to it such as bg color for menu hover state. * * - `brand`: Used for primary brand colors, such as link text, button with * brand theme, etc. * * - `tip`: Used to indicate useful information. The default theme uses the * brand color for this by default. * * - `warning`: Used to indicate warning to the users. Used in custom * container, badges, etc. * * - `danger`: Used to show error, or dangerous message to the users. Used * in custom container, badges, etc. * -------------------------------------------------------------------------- */ :root { --vp-c-default-1: var(--vp-c-gray-1); --vp-c-default-2: var(--vp-c-gray-2); --vp-c-default-3: var(--vp-c-gray-3); --vp-c-default-soft: var(--vp-c-gray-soft); --vp-c-brand-1: var(--vp-c-indigo-1); --vp-c-brand-2: var(--vp-c-indigo-2); --vp-c-brand-3: var(--vp-c-indigo-3); --vp-c-brand-soft: var(--vp-c-indigo-soft); --vp-c-tip-1: var(--vp-c-brand-1); --vp-c-tip-2: var(--vp-c-brand-2); --vp-c-tip-3: var(--vp-c-brand-3); --vp-c-tip-soft: var(--vp-c-brand-soft); --vp-c-warning-1: var(--vp-c-yellow-1); --vp-c-warning-2: var(--vp-c-yellow-2); --vp-c-warning-3: var(--vp-c-yellow-3); --vp-c-warning-soft: var(--vp-c-yellow-soft); --vp-c-danger-1: var(--vp-c-red-1); --vp-c-danger-2: var(--vp-c-red-2); --vp-c-danger-3: var(--vp-c-red-3); --vp-c-danger-soft: var(--vp-c-red-soft); } /** * Component: Button * -------------------------------------------------------------------------- */ :root { --vp-button-brand-border: transparent; --vp-button-brand-text: var(--vp-c-white); --vp-button-brand-bg: var(--vp-c-brand-3); --vp-button-brand-hover-border: transparent; --vp-button-brand-hover-text: var(--vp-c-white); --vp-button-brand-hover-bg: var(--vp-c-brand-2); --vp-button-brand-active-border: transparent; --vp-button-brand-active-text: var(--vp-c-white); --vp-button-brand-active-bg: var(--vp-c-brand-1); } /** * Component: Home * -------------------------------------------------------------------------- */ :root { --vp-home-hero-name-color: transparent; --vp-home-hero-name-background: -webkit-linear-gradient( 120deg, #bd34fe 30%, #41d1ff ); --vp-home-hero-image-background-image: linear-gradient( -45deg, #bd34fe 50%, #47caff 50% ); --vp-home-hero-image-filter: blur(44px); } @media (min-width: 640px) { :root { --vp-home-hero-image-filter: blur(56px); } } @media (min-width: 960px) { :root { --vp-home-hero-image-filter: blur(68px); } } /** * Component: Custom Block * -------------------------------------------------------------------------- */ :root { --vp-custom-block-tip-border: transparent; --vp-custom-block-tip-text: var(--vp-c-text-1); --vp-custom-block-tip-bg: var(--vp-c-brand-soft); --vp-custom-block-tip-code-bg: var(--vp-c-brand-soft); } /** * Component: Algolia * -------------------------------------------------------------------------- */ .DocSearch { --docsearch-primary-color: var(--vp-c-brand-1) !important; } axios-axios-2d06f96/docs/data/000077500000000000000000000000001521272452000161615ustar00rootroot00000000000000axios-axios-2d06f96/docs/data/sponsors.json000066400000000000000000002500651521272452000207520ustar00rootroot00000000000000{ "backer": [ { "name": "Leonardo Kewitz", "imageUrl": "https://images.opencollective.com/leokewitz/f20630b/avatar.png", "description": "I'm a Software Engineer who advocates for simplicity and readability, I strive for elegant solutions leveraging different languages and paradigms.", "tier": "backer", "slug": "leokewitz", "website": "https://kewitz.js.org/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Benjamin Piouffle", "imageUrl": "https://images.opencollective.com/betree/eb1a3dd/avatar.png", "description": "Full-time @opencollective. Founder/core-contributor @CaptainFact. Usually working with Elixir, React, and NodeJS.", "tier": "backer", "slug": "betree", "website": "https://benjamin.piouffle.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Takeru Ichii", "imageUrl": "https://images.opencollective.com/takeru-ichii/c6be635/avatar.png", "description": null, "tier": "backer", "slug": "takeru-ichii", "website": null, "twitter": null, "active": false }, { "name": "Mesh Payments", "imageUrl": "https://images.opencollective.com/meshpayments/87e9336/logo.png", "description": "Mesh Payments cardless solution allows companies to enjoy full visibility, control, and in-depth payment intelligence", "tier": "backer", "slug": "meshpayments", "website": "https://meshpayments.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/meshpayments?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": true }, { "name": "Orbit", "imageUrl": "https://images.opencollective.com/orbit-love/328bf3b/logo.png", "description": "Mission control for communities", "tier": "backer", "slug": "orbit-love", "website": "https://www.orbit.love/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/orbitmodel?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": false }, { "name": "kohta ito", "imageUrl": "https://images.opencollective.com/kohta-ito/c5cc50b/avatar.png", "description": null, "tier": "backer", "slug": "kohta-ito", "website": null, "twitter": null, "active": false }, { "name": "Orbit", "imageUrl": "https://images.opencollective.com/orbit-love/328bf3b/logo.png", "description": "Mission control for communities", "tier": "backer", "slug": "orbit-love", "website": "https://www.orbit.love/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/orbitmodel?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": false }, { "name": "Yuhei FUJITA", "imageUrl": "https://images.opencollective.com/fjt/3955659/avatar.png", "description": null, "tier": "backer", "slug": "fjt", "website": "https://fujita.dev/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/Yuhei_FUJITA?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": false }, { "name": "DLTx Labs Pty Ltd", "imageUrl": "https://images.opencollective.com/dltxio/d2c191e/logo.png", "description": "DLTx Labs is a blockchain focused software development house and venture studio based in Brisbane, Australia.", "tier": "backer", "slug": "dltxio", "website": "https://dltx.io/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/dltxio?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": false }, { "name": "kzhrk", "imageUrl": "https://images.opencollective.com/kzhrk/e4448b3/avatar.png", "description": null, "tier": "backer", "slug": "kzhrk", "website": null, "twitter": null, "active": false }, { "name": "38elements", "imageUrl": "https://images.opencollective.com/38elements/5dfbefe/avatar.png", "description": null, "tier": "backer", "slug": "38elements", "website": "https://japanese-document.github.io/lit/api-LitElement.html?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/38elements?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": false }, { "name": "Sentry", "imageUrl": "https://images.opencollective.com/sentry/9620d33/logo.png", "description": "We help software teams build better software, faster. From error tracking to performance monitoring, developers can see what actually matters, solve quicker, and learn continuously about their applications - from the frontend to the backend.", "tier": "backer", "slug": "sentry", "website": "https://sentry.io/welcome/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/getsentry?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": false }, { "name": "Corellium", "imageUrl": "https://images.opencollective.com/corellium/09cd5cb/logo.png", "description": "Accelerate your development work on iOS, Android and beyond with the power of ARM-based virtual devices.", "tier": "backer", "slug": "corellium", "website": "https://www.corellium.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/corelliumhq?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": false }, { "name": "Andy Loughran", "imageUrl": "https://images.opencollective.com/andylockran/5d59da6/avatar.png", "description": null, "tier": "backer", "slug": "andylockran", "website": "https://andylockran.dev/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/andylockran?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": true }, { "name": "kei sakamoto", "imageUrl": "https://images.opencollective.com/guest-8c25700c/avatar.png", "description": null, "tier": "backer", "slug": "guest-8c25700c", "website": null, "twitter": null, "active": false }, { "name": "Suhail Doshi", "imageUrl": "https://images.opencollective.com/guest-1ac61aed/avatar.png", "description": null, "tier": "backer", "slug": "guest-1ac61aed", "website": null, "twitter": null, "active": false }, { "name": "Alan Wang", "imageUrl": "https://images.opencollective.com/user-731a6d6b/avatar.png", "description": null, "tier": "backer", "slug": "user-731a6d6b", "website": null, "twitter": null, "active": false }, { "name": "Julio Jordán", "imageUrl": "https://images.opencollective.com/juliojordan/avatar.png", "description": "Sync person, async code. He/him.", "tier": "backer", "slug": "juliojordan", "website": null, "twitter": null, "active": false }, { "name": "neuland - Büro für Informatik", "imageUrl": "https://images.opencollective.com/neuland/2b0d93f/logo.png", "description": null, "tier": "backer", "slug": "neuland", "website": "https://www.neuland-bfi.de/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/neuland?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": false }, { "name": "Jeremy Combs", "imageUrl": "https://images.opencollective.com/jmcombs/22a314a/avatar.png", "description": "Cisco Collaboration Junkie who is enjoying (attempting) software development to further Collaboration.", "tier": "backer", "slug": "jmcombs", "website": "https://wwjcdo.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/dreinidaho?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": false }, { "name": "Guest", "imageUrl": "https://images.opencollective.com/guest-b81fd6d3/avatar.png", "description": null, "tier": "backer", "slug": "guest-b81fd6d3", "website": null, "twitter": null, "active": false }, { "name": "Raider.IO", "imageUrl": "https://images.opencollective.com/raiderio_wow/6935515/logo.png", "description": null, "tier": "backer", "slug": "raiderio_wow", "website": "https://raider.io/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/RaiderIO_WoW?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": true }, { "name": "Midtown Rulers", "imageUrl": "https://images.opencollective.com/midtownrulers/8c856fb/logo.png", "description": null, "tier": "backer", "slug": "midtownrulers", "website": "https://midtownrulers.org/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "SerpApi", "imageUrl": "https://images.opencollective.com/serp_api/19b487e/logo.png", "description": "API to get search engine results with ease.", "tier": "backer", "slug": "serp_api", "website": "https://serpapi.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/serp_api?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": false }, { "name": "GitHub Sponsors", "imageUrl": "https://images.opencollective.com/github-sponsors/dc0ae97/logo.png", "description": "Connect your Collective to GitHub Sponsors: https://docs.opencollective.com/help/collectives/github-sponsors", "tier": "backer", "slug": "github-sponsors", "website": "https://github.com/sponsors/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "intra-mart", "imageUrl": "https://images.opencollective.com/intra-mart/414f3ce/logo.png", "description": null, "tier": "backer", "slug": "intra-mart", "website": "https://dev.intra-mart.jp/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/intramart_dev?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": false }, { "name": "MFB Technologies", "imageUrl": "https://images.opencollective.com/mfbtech/3c62a0c/logo.png", "description": "Develop cutting edge software for litigators.", "tier": "backer", "slug": "mfbtech", "website": "https://mfbtech.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/mfb_tech?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": true }, { "name": "Tomasz", "imageUrl": "https://images.opencollective.com/tomasz-kleszczewski/avatar.png", "description": null, "tier": "backer", "slug": "tomasz-kleszczewski", "website": null, "twitter": null, "active": false }, { "name": "Lay", "imageUrl": "https://images.opencollective.com/brownsugar/c324dd1/avatar.png", "description": null, "tier": "backer", "slug": "brownsugar", "website": "https://brownsugar.tw/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Bervianto Leo Pratama", "imageUrl": "https://images.opencollective.com/berviantoleo/3437bf2/avatar.png", "description": null, "tier": "backer", "slug": "berviantoleo", "website": "https://berviantoleo.my.id/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/berviantoleo?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": false }, { "name": "Quicko", "imageUrl": "https://images.opencollective.com/quicko/91a46e3/logo.png", "description": "On a mission to help India save, pay & file taxes!", "tier": "backer", "slug": "quicko", "website": "https://quicko.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/howtoquicko?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": false }, { "name": "Lowdefy", "imageUrl": "https://images.opencollective.com/lowdefy/aa6698f/logo.png", "description": "Create custom web apps in minutes", "tier": "backer", "slug": "lowdefy", "website": "https://lowdefy.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/lowdefy?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": false }, { "name": "Guest", "imageUrl": "https://images.opencollective.com/guest-73375f18/avatar.png", "description": null, "tier": "backer", "slug": "guest-73375f18", "website": null, "twitter": null, "active": false }, { "name": "Byzic", "imageUrl": "https://images.opencollective.com/byzic/6422f54/logo.png", "description": "All Games, All Fun", "tier": "backer", "slug": "byzic", "website": "https://byzic.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Incognito", "imageUrl": "https://images.opencollective.com/user-5d607d62/avatar.png", "description": null, "tier": "backer", "slug": "user-5d607d62", "website": null, "twitter": null, "active": false }, { "name": "Gama Casino", "imageUrl": "https://images.opencollective.com/gama-casino/a085f51/logo.png", "description": "We offer entertainment for the rich, namely online casinos.", "tier": "backer", "slug": "gama-casino", "website": "https://gamasio.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false } ], "bronze": [ { "name": "WebScraping.AI", "imageUrl": "https://images.opencollective.com/webscraping-ai/9538df4/logo.png", "description": null, "tier": "bronze", "slug": "webscraping-ai", "website": "https://webscraping.ai/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/webscraping_ai?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": false }, { "name": "inkedin", "imageUrl": "https://images.opencollective.com/inkedin/68185e6/logo.png", "description": null, "tier": "bronze", "slug": "inkedin", "website": "https://inkedin.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "nongamstopbets.com", "imageUrl": "https://images.opencollective.com/nongamstopbets-uk/7271d84/logo.png", "description": "Entertainment", "tier": "bronze", "slug": "nongamstopbets-uk", "website": "https://www.nongamstopbets.com/casinos-not-on-gamstop/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "NonStop Casino", "imageUrl": "https://images.opencollective.com/nonstop-casino/5a4c348/logo.png", "description": "Sites Not on GamStop", "tier": "bronze", "slug": "nonstop-casino", "website": "https://nongamstop.nonstopcasino.org/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Proxidize", "imageUrl": "https://images.opencollective.com/proxidize/b14928d/logo.png", "description": "Proxidize is a mobile proxy creation and management platform that provides all needed components from hardware to cloud software and SIM cards.", "tier": "bronze", "slug": "proxidize", "website": "https://proxidize.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/proxidizeHQ?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": false }, { "name": "OnlineCasinoProfy", "imageUrl": "https://images.opencollective.com/onlinecasinoprofy/85c222c/avatar.png", "description": "OnlineCasinoProfy is your guide to the world of gambling.", "tier": "bronze", "slug": "onlinecasinoprofy", "website": "https://polskiekasynaonline24.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Casino Bonussen Nederland", "imageUrl": "https://images.opencollective.com/casino-bonussen-nederland/fa79b5b/logo.png", "description": "HelloBonuses.com bekijkt de beste Nederlandse online casino's en de eerlijke casino bonussen. We lezen de kleine lettertjes hardop voor je.", "tier": "bronze", "slug": "casino-bonussen-nederland", "website": "https://www.hellobonuses.com/nl/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy Youtube Views - Views4You", "imageUrl": "https://images.opencollective.com/buy-youtube-views-views4you/de7d37c/logo.png", "description": "Enhance your online presence and boost your video's performance with Views4You, the trusted source to buy YouTube views and skyrocket your engagement.", "tier": "bronze", "slug": "buy-youtube-views-views4you", "website": "https://views4you.com/buy-youtube-views/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "SidesMedia", "imageUrl": "https://images.opencollective.com/sidesmedia/75de5ff/logo.png", "description": null, "tier": "bronze", "slug": "sidesmedia", "website": "https://sidesmedia.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "EarthWeb", "imageUrl": "https://images.opencollective.com/earthweb1/1752601/logo.png", "description": null, "tier": "bronze", "slug": "earthweb1", "website": "https://earthweb.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Buy YouTube Views by JeffBullas", "imageUrl": "https://images.opencollective.com/buy-youtube-views-by-jeffbullas/60dc577/logo.png", "description": null, "tier": "bronze", "slug": "buy-youtube-views-by-jeffbullas", "website": "https://www.jeffbullas.com/buy-youtube-views/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Proxy Coupons", "imageUrl": "https://images.opencollective.com/proxy-coupons/9dd588f/logo.png", "description": null, "tier": "bronze", "slug": "proxy-coupons", "website": "https://proxy.coupons/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Read more on the best sites to Buy YouTube Subscribers", "imageUrl": "https://images.opencollective.com/read-more-on-the-best-sites-to-buy-youtube-subscribers/f128580/logo.png", "description": null, "tier": "bronze", "slug": "read-more-on-the-best-sites-to-buy-youtube-subscribers", "website": "https://www.santacruzsentinel.com/2024/03/26/buy-youtube-subscribers-2/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Siti Non AAMS", "imageUrl": "https://images.opencollective.com/siti-non-aams/520019c/logo.png", "description": "Scopri i migliori siti non AAMS per un'esperienza di gioco senza limiti e con bonus irresistibili!", "tier": "bronze", "slug": "siti-non-aams", "website": "https://bsc.news/post/siti-scommesse-non-aams?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Buy Instagram Followers Thunderclapit", "imageUrl": "https://images.opencollective.com/buy-instagram-followers-usa/79f7eac/logo.png", "description": "Get real, active Instagram followers delivered straight to your account in minutes. Buy Instagram followers at Thunderclap.it starting just at $2.79", "tier": "bronze", "slug": "buy-instagram-followers-usa", "website": "https://thunderclap.it/buy-instagram-followers?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Buy Google Reviews", "imageUrl": "https://images.opencollective.com/buy-google-reviews-usa/78797fd/logo.png", "description": "Buyreviewz is the best online review service providing - 100% real and non-drop google reviews for local business profiles.", "tier": "bronze", "slug": "buy-google-reviews-usa", "website": "https://buyreviewz.com/buy-google-reviews?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Buy Instagram Reels Views", "imageUrl": "https://images.opencollective.com/buy-instagram-reels-views-instant/72a3dd8/logo.png", "description": null, "tier": "bronze", "slug": "buy-instagram-reels-views-instant", "website": "https://container-news.com/buy-instagram-reel-views/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy TikTok Likes", "imageUrl": "https://images.opencollective.com/buy-tiktok-likes-instant/fd0e180/logo.png", "description": null, "tier": "bronze", "slug": "buy-tiktok-likes-instant", "website": "https://billingsgazette.com/exclusive/article_64390499-5a5a-58f3-990e-7c8f7853b30e.html?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy Instagram Followers", "imageUrl": "https://images.opencollective.com/buy-instagram-followers-cc8dc394/fa7a6e9/avatar.png", "description": "Buy Instagram Followers", "tier": "bronze", "slug": "buy-instagram-followers-cc8dc394", "website": "https://www.reddit.com/r/MarketingHelp/comments/1pi8cvw/anyone_actually_bought_instagram_followers_what/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy Instagram Followers", "imageUrl": "https://images.opencollective.com/buy-instagram-followers-9/d7c422a/logo.png", "description": null, "tier": "bronze", "slug": "buy-instagram-followers-9", "website": "https://www.reddit.com/r/MarketingMentor/comments/1rfzxq0/whats_the_best_site_to_buy_instagram_followers/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy Facebook Likes", "imageUrl": "https://images.opencollective.com/purchase-facebook-page-likes/logo.png", "description": "Forum and Q&A platform", "tier": "bronze", "slug": "purchase-facebook-page-likes", "website": "https://www.reddit.com/r/facebook/comments/1labf0e/legit_site_for_facebook_page_likes_heres_my/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy Telegram Members", "imageUrl": "https://images.opencollective.com/buy-telegram-members-real/8098404/logo.png", "description": null, "tier": "bronze", "slug": "buy-telegram-members-real", "website": "https://aijourn.com/buy-telegram-members/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Fun88", "imageUrl": "https://images.opencollective.com/fun88-official/bf2843c/logo.png", "description": "Best online sports betting and casino company.", "tier": "bronze", "slug": "fun88-official", "website": "https://global.fun88.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy Instagram followers and likes", "imageUrl": "https://images.opencollective.com/buy-instagram-followers-and-likes-2/f9dfe89/avatar.png", "description": "Buy Instagram followers and likes", "tier": "bronze", "slug": "buy-instagram-followers-and-likes-2", "website": "https://www.reddit.com/r/BuildToAttract/comments/1sro5qq/where_can_i_buy_instagram_followers_and_likes_to/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy TikTok likes and views and comments", "imageUrl": "https://images.opencollective.com/buy-tiktok-likes-and-views-and-comments/5680706/avatar.png", "description": "Buy TikTok likes and views and comments", "tier": "bronze", "slug": "buy-tiktok-likes-and-views-and-comments", "website": "https://www.reddit.com/r/SocialBlueprint/comments/1rtiat6/what_is_the_best_site_to_buy_tiktok_likes_views/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy TikTok Followers", "imageUrl": "https://images.opencollective.com/buy-tiktok-followers-6/c1247c2/avatar.png", "description": "Buy TikTok Followers", "tier": "bronze", "slug": "buy-tiktok-followers-6", "website": "https://www.reddit.com/r/TikTokLounge/comments/1rv7lfz/whats_the_best_site_to_buy_tiktok_followers_that/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "TopKasynoOnline PL", "imageUrl": "https://images.opencollective.com/topkasynoonline-pl/714b70a/logo.png", "description": null, "tier": "bronze", "slug": "topkasynoonline-pl", "website": "https://pl.topkasynoonline.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Time Now", "imageUrl": "https://images.opencollective.com/time-now/e7347c5/logo.png", "description": "", "tier": "bronze", "slug": "time-now", "website": "https://time.now/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy Google Reviews", "imageUrl": "https://images.opencollective.com/buy-google-reviews1/be3bf00/avatar.png", "description": "Buy Google Reviews", "tier": "bronze", "slug": "buy-google-reviews1", "website": "https://www.reddit.com/r/growmybusiness/comments/1qh63qr/whats_the_best_site_to_buy_google_reviews/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Fun88 Vietnam EN", "imageUrl": "https://images.opencollective.com/fun88-vietnam-en/2541290/avatar.png", "description": null, "tier": "bronze", "slug": "fun88-vietnam-en", "website": "https://www.fun88vnplay.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "FUN88 Thailand EN", "imageUrl": "https://images.opencollective.com/fun88-thailand-en/cacc530/avatar.png", "description": null, "tier": "bronze", "slug": "fun88-thailand-en", "website": "https://www.fun88asiath.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy Instagram Reels Views", "imageUrl": "https://images.opencollective.com/buy-instagram-reels-views-cheap/ed3335e/logo.png", "description": null, "tier": "bronze", "slug": "buy-instagram-reels-views-cheap", "website": "https://www.techloy.com/buy-instagram-reel-views/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy Real Spotify Plays", "imageUrl": "https://images.opencollective.com/buy-real-spotify-plays/c6658f0/logo.png", "description": "Student News Website", "tier": "bronze", "slug": "buy-real-spotify-plays", "website": "https://www.idsnews.com/article/2026/01/sponsored-where-to-buy-spotify-plays-01212026?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy Real YouTube Likes", "imageUrl": "https://images.opencollective.com/buy-real-youtube-likes/85d3ea7/logo.png", "description": null, "tier": "bronze", "slug": "buy-real-youtube-likes", "website": "https://www.idsnews.com/article/2026/01/sponsored-top-5-sites-to-buy-youtube-likes-fast-01212026?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Fun88", "imageUrl": "https://images.opencollective.com/fun88-vietnam/192b9db/avatar.png", "description": "Nhà cái cá cược thể thao trực tuyến tốt nhất tại Việt Nam", "tier": "bronze", "slug": "fun88-vietnam", "website": "https://www.fun88vnb.com/vn/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy Instagram Followers", "imageUrl": "https://images.opencollective.com/buy-instagram-followers5/acaea89/avatar.png", "description": "Buy Instagram Followers", "tier": "bronze", "slug": "buy-instagram-followers5", "website": "https://www.reddit.com/r/influencermarketing/comments/1qi4wjs/whats_the_best_site_to_buy_instagram_followers/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy Instagram Followers", "imageUrl": "https://images.opencollective.com/buy-instagram-followers10/44e6c85/avatar.png", "description": "Buy Instagram Followers", "tier": "bronze", "slug": "buy-instagram-followers10", "website": "https://www.reddit.com/r/influencermarketing/comments/1r8b8i6/where_do_people_buy_instagram_followers_that/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Fun88", "imageUrl": "https://images.opencollective.com/fun88-thailand/81e1909/avatar.png", "description": "บริษัทรับแทงบอลออนไลน์ที่ดีที่สุดในประเทศไทย", "tier": "bronze", "slug": "fun88-thailand", "website": "https://www.fun88thc.com/th/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy LinkedIn Followers", "imageUrl": "https://images.opencollective.com/buy-linkedin-followers/bb23698/avatar.png", "description": "Buy LinkedIn Followers", "tier": "bronze", "slug": "buy-linkedin-followers", "website": "https://www.reddit.com/r/LinkedinAds/comments/1r8xhat/what_is_the_best_site_to_buy_linkedin_followers/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy YouTube subscribers", "imageUrl": "https://images.opencollective.com/buy-youtube-subscribers3/16536ae/avatar.png", "description": "Buy YouTube subscribers", "tier": "bronze", "slug": "buy-youtube-subscribers3", "website": "https://www.reddit.com/r/YouTubeCamp/comments/1pwtija/whats_the_best_site_to_buy_youtube_subscribers/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy Instagram Followers", "imageUrl": "https://images.opencollective.com/buy-instagram-followers12/fc45f1f/avatar.png", "description": "Buy Instagram Followers", "tier": "bronze", "slug": "buy-instagram-followers12", "website": "https://www.reddit.com/r/growmybusiness/comments/1so2fld/what_is_the_best_site_to_buy_instagram_followers/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "SMM Panel", "imageUrl": "https://images.opencollective.com/smm-panel19/80a629f/avatar.png", "description": "SMM Panel ", "tier": "bronze", "slug": "smm-panel19", "website": "https://www.reddit.com/r/branding/comments/1rar7q0/whats_the_best_smm_panel_right_now/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy Facebook Likes", "imageUrl": "https://images.opencollective.com/buy-facebook-likes-real/9ed49a7/logo.png", "description": null, "tier": "bronze", "slug": "buy-facebook-likes-real", "website": "https://tucson.com/exclusive/article_d407a4ab-a8ef-5129-bca4-02f95328664c.html?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy Instagram Followers from MIXX.com", "imageUrl": "https://images.opencollective.com/buy-instagram-followers-mixx/40c0b65/logo.png", "description": "Buy Instagram Followers with Instant Delivery from MIXX.com. Boost your audience and followers; buy Instagram followers for fast results.", "tier": "bronze", "slug": "buy-instagram-followers-mixx", "website": "https://www.mixx.com/buy-instagram-followers?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "SocialWick", "imageUrl": "https://images.opencollective.com/socialwick/e244614/logo.png", "description": "SocialWick is a leading social media shop, offering a wide range of premium services and exceptional customer support. With SocialWick, you can quickly boost your social media followership and enhance your online presence.", "tier": "bronze", "slug": "socialwick", "website": "https://www.socialwick.com/instagram/followers?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Writing Metier", "imageUrl": "https://images.opencollective.com/writing-metier/762e081/logo.png", "description": "Writing is our job, our passion, our love and of course, our métier. Welcome to the world of Writing Metier OU - professional copywriting services.", "tier": "bronze", "slug": "writing-metier", "website": "https://writingmetier.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/writingmetier?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": true }, { "name": "Teravision Technologies", "imageUrl": "https://images.opencollective.com/teravision-technologies/a0bb15c/avatar.png", "description": null, "tier": "bronze", "slug": "teravision-technologies", "website": "https://www.teravisiontech.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true } ], "silver": [ { "name": "CasinoReviews", "imageUrl": "https://images.opencollective.com/casinoreviews/adca197/logo.png", "description": "Home to unbiased analysis on the biggest and the most aspiring names in iGaming,opinion pieces from experts, and interviews with industry leaders.", "tier": "silver", "slug": "casinoreviews", "website": "https://www.casinoreviews.net/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "BairesDev", "imageUrl": "https://images.opencollective.com/bairesdev/48bb773/logo.png", "description": "We are the leading Nearshore Technology Solutions company. We architect and engineer scalable and high-performing software solutions.", "tier": "silver", "slug": "bairesdev", "website": "https://www.bairesdev.com/sponsoring-open-source-projects/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/bairesdev?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": true }, { "name": "Enric Baltasar", "imageUrl": "https://images.opencollective.com/enric-baltasar/avatar.png", "description": null, "tier": "silver", "slug": "enric-baltasar", "website": null, "twitter": null, "active": false }, { "name": "Ігрові автомати", "imageUrl": "https://images.opencollective.com/igrovye-avtomaty-ua/96bfde3/logo.png", "description": "ігрові автомати беткінг", "tier": "silver", "slug": "igrovye-avtomaty-ua", "website": "https://betking.com.ua/games/all-slots/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Chudovo", "imageUrl": "https://images.opencollective.com/chudovo/3c866f5/logo.png", "description": "Chudovo - international software development company with representative offices in Kyiv, Cologne, New York, Tallinn and London. It has been working on the market since 2006. Company has domain expertise in video security, logistics, medicine, finance and", "tier": "silver", "slug": "chudovo", "website": "https://chudovo.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "OnlineCasinosSpelen", "imageUrl": "https://images.opencollective.com/onlinecasinosspelen/99ac6a2/logo.png", "description": "OnlineCasinosSpelen", "tier": "silver", "slug": "onlinecasinosspelen", "website": "https://onlinecasinosspelen.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "casino-zonder-cruks.eu.com", "imageUrl": "https://images.opencollective.com/czrnet/24e6252/logo.png", "description": "CasinoZonderRegistratie.net - Nederlandse Top Casino's", "tier": "silver", "slug": "czrnet", "website": "https://casinozonderregistratie.net/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Nieuwe-Casinos.net", "imageUrl": "https://images.opencollective.com/nieuwecasinos/c67d423/logo.png", "description": "Beoordelen van nieuwe online casino's 2023", "tier": "silver", "slug": "nieuwecasinos", "website": "https://nieuwe-casinos.net/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "CzC", "imageUrl": "https://images.opencollective.com/user-5b30aec2/f10fca3/avatar.png", "description": null, "tier": "silver", "slug": "user-5b30aec2", "website": "https://casinoszondercruks.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Онлайн казино 777", "imageUrl": "https://images.opencollective.com/casinoinua/c691599/logo.png", "description": "Онлайн казино 777 Україна", "tier": "silver", "slug": "casinoinua", "website": "https://777.ua/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "YTMP3", "imageUrl": "https://images.opencollective.com/ytmp3/4a8db94/logo.png", "description": null, "tier": "silver", "slug": "ytmp3", "website": "https://ytmp3.page/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "https://www.pieria.co.uk/", "imageUrl": "https://images.opencollective.com/https-nongamstopcasinos-net/01aa99b/logo.png", "description": null, "tier": "silver", "slug": "https-nongamstopcasinos-net", "website": "https://www.pieria.co.uk/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "NZ online casinos", "imageUrl": "https://images.opencollective.com/nz-online-casinos/7eb1102/logo.png", "description": null, "tier": "silver", "slug": "nz-online-casinos", "website": "https://onlinecasinoskiwi.co.nz/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "try bookies not on GamStop", "imageUrl": "https://images.opencollective.com/try-bookies-not-on-gamstop/3758aae/logo.png", "description": null, "tier": "silver", "slug": "try-bookies-not-on-gamstop", "website": "https://netto.co.uk/betting-sites-not-on-gamstop/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Best Non Gamstop Casinos", "imageUrl": "https://images.opencollective.com/user-a524d8be/9b18e4a/avatar.png", "description": "https://thelidocafe.co.uk/", "tier": "silver", "slug": "user-a524d8be", "website": "https://thelidocafe.co.uk/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "SSSTwitter", "imageUrl": "https://images.opencollective.com/ssstwitter/9924968/logo.png", "description": "Twitter Video Downloader HD Tool allows you to store tweets on your device (mobile or PC) for free.", "tier": "silver", "slug": "ssstwitter", "website": "https://ssstwitter.online/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Andre Vaughn", "imageUrl": "https://images.opencollective.com/twicsy-followers/avatar.png", "description": null, "tier": "silver", "slug": "twicsy-followers", "website": "https://twicsy.com/buy-instagram-followers/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Buy Instagram Followers Twicsy", "imageUrl": "https://images.opencollective.com/buy-instagram-followers-twicsy/b4c5d7f/logo.png", "description": "Buy real Instagram followers from Twicsy starting at only $2.97. Twicsy has been voted the best site to buy followers from the likes of US Magazine.", "tier": "silver", "slug": "buy-instagram-followers-twicsy", "website": "https://twicsy.com/buy-instagram-followers?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Fortune Tiger", "imageUrl": "https://images.opencollective.com/fortune-tiger2/d821e05/logo.png", "description": null, "tier": "silver", "slug": "fortune-tiger2", "website": "https://fortune-tiger-br.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Parimatch", "imageUrl": "https://images.opencollective.com/parimatch3/c87e839/logo.png", "description": null, "tier": "silver", "slug": "parimatch3", "website": "https://parimattchbr.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Social followers", "imageUrl": "https://images.opencollective.com/socialfollowersuk/e327e52/avatar.png", "description": " Our diverse range of services are designed for popular social media platforms such as Instagram, TikTok, Facebook, Threads, and YouTube.", "tier": "silver", "slug": "socialfollowersuk", "website": "https://www.socialfollowers.uk/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "187990323015587", "imageUrl": "https://images.opencollective.com/adam-smith-1879903/avatar.png", "description": null, "tier": "silver", "slug": "adam-smith-1879903", "website": "https://qbtoolhub.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "EarthWeb", "imageUrl": "https://images.opencollective.com/earthweb1/1752601/logo.png", "description": null, "tier": "silver", "slug": "earthweb1", "website": "https://earthweb.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Top Rating casino", "imageUrl": "https://images.opencollective.com/topratingcasino/bb0b43a/avatar.png", "description": "TopRating.casino ➢ Гід по онлайн-казино в Україні", "tier": "silver", "slug": "topratingcasino", "website": "https://toprating.casino/ua/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy Instagram followers Insfollowpro", "imageUrl": "https://images.opencollective.com/insfollowpro/a070619/logo.png", "description": "Insfollowpro sells Instagram followers, likes, views.", "tier": "silver", "slug": "insfollowpro", "website": "https://insfollowpro.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Bountii", "imageUrl": "https://images.opencollective.com/bountii/7cd628b/logo.png", "description": "At Bountii, we believe that everyone deserves to get the most out of their hard-earned money. That’s why we’ve dedicated ourselves to scouring the internet to bring you the best deals, discounts, and coupons from your favorite stores and brands.", "tier": "silver", "slug": "bountii", "website": "https://bountii.co/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://x.com/bountii?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": false }, { "name": "legjobbmagyarcasino.com", "imageUrl": "https://images.opencollective.com/legjobbmagyarcasinocom/1ede028/logo.png", "description": "Online Casino Reviews", "tier": "silver", "slug": "legjobbmagyarcasinocom", "website": "https://legjobbmagyarcasino.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy X(Twitter) Followers from Bulkoid", "imageUrl": "https://images.opencollective.com/buy-x-twitter-followers/a623928/logo.png", "description": "Find the social proof you need to reach your audience! Boost conversions. Quickly buy Twitter Followers & more with no sign-up. Taking you to the next", "tier": "silver", "slug": "buy-x-twitter-followers", "website": "https://bulkoid.com/buy-twitter-followers?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "HHC Vaper", "imageUrl": "https://images.opencollective.com/hhc-vaper/9f9df9e/logo.png", "description": "HHCVaper.com bietet Premium HHC Vapes, Gummies und Cartridges für Konsum.", "tier": "silver", "slug": "hhc-vaper", "website": "https://hhcvaper.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Buy YouTube Subscribers on YouTube with SidesMedia", "imageUrl": "https://images.opencollective.com/buy-youtube-subscribers-on-youtube-with-sidesmedia/f0e3ec5/logo.png", "description": null, "tier": "silver", "slug": "buy-youtube-subscribers-on-youtube-with-sidesmedia", "website": "https://sidesmedia.com/buy-youtube-subscribers/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Viralyft", "imageUrl": "https://images.opencollective.com/viralyft/b853d22/avatar.png", "description": "Buy Instagram Followers, Likes, Views & Comments", "tier": "silver", "slug": "viralyft", "website": "https://viralyft.com/buy-instagram-followers?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "SocialBoss", "imageUrl": "https://images.opencollective.com/socialboss/a644520/logo.png", "description": "We help improve visibility in social networks. ", "tier": "silver", "slug": "socialboss", "website": "https://socialboss.org/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Airbnb", "imageUrl": "https://images.opencollective.com/airbnb/d327d66/logo.png", "description": "Airbnb was born in 2007 when two Hosts welcomed three guests to their San Francisco home, and has since grown to over 4 million Hosts who have welcomed more than 1 billion guest arrivals in almost every country across the globe.", "tier": "silver", "slug": "airbnb", "website": "https://www.airbnb.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/airbnbeng?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": true }, { "name": "Daily Star UK Casinos", "imageUrl": "https://images.opencollective.com/dailystar-ukcouk/fec3df7/avatar.png", "description": "https://dailystar-uk.co.uk", "tier": "silver", "slug": "dailystar-ukcouk", "website": "https://dailystar-uk.co.uk/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Buy Instagram Likes from BuyTopLikes", "imageUrl": "https://images.opencollective.com/buytoplikes/e2d8fce/logo.png", "description": "We offer various services for Instagram users, including purchasing likes, followers, views, and comments to boost engagement and visibility.", "tier": "silver", "slug": "buytoplikes", "website": "https://buytoplikes.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Anonymous", "imageUrl": "https://images.opencollective.com/account-f1b3f0cf/logo.png", "description": null, "tier": "silver", "slug": "account-f1b3f0cf", "website": null, "twitter": null, "active": false }, { "name": "Free Chip No Deposit", "imageUrl": "https://images.opencollective.com/free-chip-no-deposit/dd08c50/avatar.png", "description": null, "tier": "silver", "slug": "free-chip-no-deposit", "website": "https://free-chip-no-deposit.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "casinochileonline.net", "imageUrl": "https://images.opencollective.com/casinochileonlinenet/52355f7/logo.png", "description": "Online Casino Review", "tier": "silver", "slug": "casinochileonlinenet", "website": "https://casinochileonline.net/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "nejlepsiceskacasina.com", "imageUrl": "https://images.opencollective.com/nejlepsiceskacasinacom/3eb2ad7/logo.png", "description": "Online Casino Review", "tier": "silver", "slug": "nejlepsiceskacasinacom", "website": "https://nejlepsiceskacasina.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "slovenskeonlinecasino.com", "imageUrl": "https://images.opencollective.com/slovenskeonlinecasinocom/524b90a/logo.png", "description": "Online casino reviews", "tier": "silver", "slug": "slovenskeonlinecasinocom", "website": "https://slovenskeonlinecasino.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Viralyft", "imageUrl": "https://images.opencollective.com/viralyft7/90a7ccb/logo.png", "description": "Buy YouTube Views", "tier": "silver", "slug": "viralyft7", "website": "https://viralyft.com/buy-youtube-views?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Buy TikTok Views Poprey", "imageUrl": "https://images.opencollective.com/poprey-likes/3391887/avatar.png", "description": null, "tier": "silver", "slug": "poprey-likes", "website": "https://poprey.com/buy-tiktok-views?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "Slotozilla Deutschland", "imageUrl": "https://images.opencollective.com/slotozilla-deutschland/d137949/logo.png", "description": "SlotoZilla ist eine unabhängige Website mit kostenlosen Spielautomaten und Slotbewertungen. Wir bieten keine Glücksspiele um echtes Geld an.", "tier": "silver", "slug": "slotozilla-deutschland", "website": "https://www.slotozilla.com/de/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "FitclubFinder", "imageUrl": "https://images.opencollective.com/fitclubfinder/b6c5b09/avatar.png", "description": null, "tier": "silver", "slug": "fitclubfinder", "website": "https://fitclubfinder.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "CreditCaptain – Leading AI Credit Repair Service", "imageUrl": "https://images.opencollective.com/creditcaptain/7f7d6f2/logo.png", "description": "CreditCaptain is the leading credit repair service that helps consumers quickly improve their credit scores, using AI for 10x better & faster results.", "tier": "silver", "slug": "creditcaptain", "website": "https://www.creditcaptain.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": false }, { "name": "FBPostLikes", "imageUrl": "https://images.opencollective.com/pankaj-jangir/c5dee33/avatar.png", "description": null, "tier": "silver", "slug": "pankaj-jangir", "website": "https://www.fbpostlikes.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Likescafe", "imageUrl": "https://images.opencollective.com/likescafe/9468493/logo.png", "description": null, "tier": "silver", "slug": "likescafe", "website": "https://likescafe.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "apuesdeportivas.es", "imageUrl": "https://images.opencollective.com/apuesdeportivas-es/6ecf644/avatar.png", "description": null, "tier": "silver", "slug": "apuesdeportivas-es", "website": "https://apuesdeportivas.es/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "iedcdubai", "imageUrl": "https://images.opencollective.com/iedcdubai-ae/62ea64d/avatar.png", "description": null, "tier": "silver", "slug": "iedcdubai-ae", "website": "https://www.iedcdubai.ae/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy.Fans", "imageUrl": "https://images.opencollective.com/buyfans/8122fa8/logo.png", "description": "Create the most suitable order for your target audience from Buy.Fans, the world's most reliable and most preferred social media service platform for 12 years, and strengthen your page!", "tier": "silver", "slug": "buyfans", "website": "https://buy.fans/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/BuyFansOfficial?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": true }, { "name": "Najlepsi Bukmacherzy", "imageUrl": "https://images.opencollective.com/netpositivepl/34f836f/avatar.png", "description": null, "tier": "silver", "slug": "netpositivepl", "website": "https://najlepsibukmacherzy.pl/ranking-legalnych-bukmacherow/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "POLi Pay Casinos", "imageUrl": "https://images.opencollective.com/poli-pay-online-casinos/39bdd37/logo.png", "description": null, "tier": "silver", "slug": "poli-pay-online-casinos", "website": "https://nz.trustpilot.com/review/surfpokies.com?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy Instagram Followers", "imageUrl": "https://images.opencollective.com/bestsitesbuyinstagramfollowers/d6844ba/logo.png", "description": "Adflee is the best place to buy Instagram followers, likes & views. You can buy Real & Non-Drop Instagram followers from Adflee.", "tier": "silver", "slug": "bestsitesbuyinstagramfollowers", "website": "https://www.reddit.com/r/MarketingGeek/comments/1jd6yre/where_to_buy_instagram_followers_any_best_site/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Paras Pikakasino", "imageUrl": "https://images.opencollective.com/paras-pikakasino/eaf9ccb/logo.png", "description": "Paras-pikakasino.com tarjoaa asiantuntevaa tietoa Suomen pikakasinoista ja niiden nopeista palveluista.", "tier": "silver", "slug": "paras-pikakasino", "website": "https://paras-pikakasino.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "iDEAL Casinos", "imageUrl": "https://images.opencollective.com/ideal-casinos/0047cad/logo.png", "description": null, "tier": "silver", "slug": "ideal-casinos", "website": "https://nl.trustpilot.com/review/idealcasinos.co.com?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "SocialDawn", "imageUrl": "https://images.opencollective.com/socialdawn/963a6d4/logo.png", "description": "SocialDawn is a digital marketing brand focused on social media growth and performance campaigns. We help creators and businesses improve visibility and engagement through data-driven strategies and campaign management.", "tier": "silver", "slug": "socialdawn", "website": "https://www.socialdawn.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Casino Zonder Registratie", "imageUrl": "https://images.opencollective.com/casino-zonder-registratie/d7119d9/logo.png", "description": "We testen elke maand tientallen casino’s en kiezen de beste uit voor Nederlandse spelers.", "tier": "silver", "slug": "casino-zonder-registratie", "website": "https://nl.trustpilot.com/review/scandicasinos.com?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Plinko Game", "imageUrl": "https://images.opencollective.com/plinko-game/35bc4b1/logo.png", "description": null, "tier": "silver", "slug": "plinko-game", "website": "https://www.trustpilot.com/review/plinkoplay.top?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Aviator Game Online", "imageUrl": "https://images.opencollective.com/aviator-game-online/31a7922/logo.png", "description": null, "tier": "silver", "slug": "aviator-game-online", "website": "https://www.trustpilot.com/review/aviatorplay.top?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Instant Withdrawal Casinos", "imageUrl": "https://images.opencollective.com/instant-withdrawal-pokies/196c2fa/logo.png", "description": "marketing in australia", "tier": "silver", "slug": "instant-withdrawal-pokies", "website": "https://au.trustpilot.com/review/instantpayoutcasinos.org?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "iDEAL Casinos", "imageUrl": "https://images.opencollective.com/ideal-casinos/0047cad/logo.png", "description": null, "tier": "silver", "slug": "ideal-casinos", "website": "https://nl.trustpilot.com/review/idealcasinos.co.com?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "No Account Casino", "imageUrl": "https://images.opencollective.com/no-account-casino1/784af78/logo.png", "description": "No Account Casino for Swedes ", "tier": "silver", "slug": "no-account-casino1", "website": "https://se.trustpilot.com/review/noaccountcasinos.co.com?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Online Pokies in Australia", "imageUrl": "https://images.opencollective.com/online-pokies-au/7b2ecfc/logo.png", "description": "We collect all reviews about the best online pokies.", "tier": "silver", "slug": "online-pokies-au", "website": "https://au.trustpilot.com/review/aussiepokies.net?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Daman Game", "imageUrl": "https://images.opencollective.com/daman-game-login/86bac66/logo.png", "description": "Colour Prediction Game", "tier": "silver", "slug": "daman-game-login", "website": "https://damanapp.download/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Transparencia en Casinos Online", "imageUrl": "https://images.opencollective.com/educatransparenciacl/88a027e/logo.png", "description": "Mi misión es la educación y transparencia en el mundo de los casinos online", "tier": "silver", "slug": "educatransparenciacl", "website": "https://www.educatransparencia.cl/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "SocialBoosting", "imageUrl": "https://images.opencollective.com/socialboosting/7b6b775/logo.png", "description": "SocialBoosting: Buy Instagram & TikTok Followers, Likes, Views", "tier": "silver", "slug": "socialboosting", "website": "https://www.socialboosting.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "BDG Win", "imageUrl": "https://images.opencollective.com/bdg-win-game/77ea287/logo.png", "description": "BDG Win Game is India's Growing Color prediction Game, Where You Can Play K3, Wingo , 5D And Aviator", "tier": "silver", "slug": "bdg-win-game", "website": "https://win.bdggame.io/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "PayID Pokies Sites", "imageUrl": "https://images.opencollective.com/payid-pokies-sites/c9cd78a/logo.png", "description": "We test dozens of casinos every month and select the coolest ones for Australian players. ", "tier": "silver", "slug": "payid-pokies-sites", "website": "https://au.trustpilot.com/review/payid-casino.net?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Online casino ohne OASIS", "imageUrl": "https://images.opencollective.com/onlinecasinoohneoasisme/a680d7f/logo.png", "description": "Collect reviews", "tier": "silver", "slug": "onlinecasinoohneoasisme", "website": "https://de.trustpilot.com/review/onlinecasinoohneoasis.me?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Online Casino Zonder Registratie", "imageUrl": "https://images.opencollective.com/no-account-casino/121571f/logo.png", "description": null, "tier": "silver", "slug": "no-account-casino", "website": "https://nl.trustpilot.com/review/zonderregistratiecasinos.com?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy Real Instagram Followers", "imageUrl": "https://images.opencollective.com/purchase-real-instagram-followers/logo.png", "description": "Forum and Q&A platform", "tier": "silver", "slug": "purchase-real-instagram-followers", "website": "https://www.reddit.com/r/MarketingHelp/comments/1opxhk1/has_anyone_here_ever_tried_to_buy_instagram/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "PayID Pokies", "imageUrl": "https://images.opencollective.com/bestpayidpokies/07fc9d6/logo.png", "description": "We specialize in the online gambling industry, helping players access reliable and verified information about the best online casinos and pokies in Australia. Our team tests casinos and games, collects user reviews from Trustpilot, and organizes them in o", "tier": "silver", "slug": "bestpayidpokies", "website": "https://au.trustpilot.com/review/bestpayidpokies.net?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "super clone watches", "imageUrl": "https://images.opencollective.com/super-clone-prestige/e681745/logo.png", "description": "Information technology", "tier": "silver", "slug": "super-clone-prestige", "website": "https://finance.yahoo.com/news/best-website-super-clone-watches-073500706.html?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Kasino Kurko: Uudet nettikasinot", "imageUrl": "https://images.opencollective.com/kurko-uudetnettikasinot/a293576/logo.png", "description": "KasinoKurko on Suomen uusien kasinoiden asiantuntija.", "tier": "silver", "slug": "kurko-uudetnettikasinot", "website": "https://kasinokurko.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://x.com/kasinokurko?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": true }, { "name": "Online Pokies in Australia", "imageUrl": "https://images.opencollective.com/betpokies/147f64c/avatar.png", "description": "BetPokies.orgis your Australian guide in the world of online gambling. We attentively select the best brands for Aussie players and write honest reviews, provide useful tips, good bonuses and game demos, all that to assure that our readers get best exper", "tier": "silver", "slug": "betpokies", "website": "https://au.trustpilot.com/review/betpokies.com?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Online Pokies NZ", "imageUrl": "https://images.opencollective.com/betpokiesconz/6433b9d/logo.png", "description": "BetPokies.co.nz is your New Zealand guide in the world of online gambling. Our site was created by gamblers for gamblers.", "tier": "silver", "slug": "betpokiesconz", "website": "https://nz.trustpilot.com/review/betpokies.co.nz?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "PayID Pokies", "imageUrl": "https://images.opencollective.com/bestpayidpokies/07fc9d6/logo.png", "description": "We specialize in the online gambling industry, helping players access reliable and verified information about the best online casinos and pokies in Australia. Our team tests casinos and games, collects user reviews from Trustpilot, and organizes them in o", "tier": "silver", "slug": "bestpayidpokies", "website": "https://au.trustpilot.com/review/bestpayidpokies.net?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "casino seo", "imageUrl": "https://images.opencollective.com/casino-seo/fef9515/avatar.png", "description": null, "tier": "silver", "slug": "casino-seo", "website": "https://seo.casino/en/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "c19.cl - Mejores Casinos Online", "imageUrl": "https://images.opencollective.com/casino-online-chile/91f1057/avatar.png", "description": "", "tier": "silver", "slug": "casino-online-chile", "website": "https://www.c19.cl/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "parhaatuudetkasinot.com", "imageUrl": "https://images.opencollective.com/parhaatuudetkasinotcom/8979792/logo.png", "description": "Uudet Nettikasinot", "tier": "silver", "slug": "parhaatuudetkasinotcom", "website": "https://fi.parhaatuudetkasinot.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "PrestigeWatches", "imageUrl": "https://images.opencollective.com/prestigewatches/5654727/logo.png", "description": null, "tier": "silver", "slug": "prestigewatches", "website": "https://prestigewatches.co/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Famoid", "imageUrl": "https://images.opencollective.com/famoid/b8421b3/logo.png", "description": "Famoid is a digital marketing agency that specializes in social media services and tools.", "tier": "silver", "slug": "famoid", "website": "https://famoid.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Chilecasinoonline", "imageUrl": "https://images.opencollective.com/chilecasinoonline/43c3e6a/avatar.png", "description": "casino online chile", "tier": "silver", "slug": "chilecasinoonline", "website": "https://chilecasinoonline.cl/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Casino Online Chile", "imageUrl": "https://images.opencollective.com/interactive-media-group-ltd/320a3f6/avatar.png", "description": null, "tier": "silver", "slug": "interactive-media-group-ltd", "website": "https://www.acee.cl/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "ViralQR", "imageUrl": "https://images.opencollective.com/viralqr/ff646e9/logo.png", "description": "Create QR codes", "tier": "silver", "slug": "viralqr", "website": "https://viralqr.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buy Instagram Followers & Likes", "imageUrl": "https://images.opencollective.com/leofame/2b658cd/avatar.png", "description": "Boost your social media presence effortlessly with top-quality Instagram and TikTok followers and likes.", "tier": "silver", "slug": "leofame", "website": "https://leofame.com/buy-instagram-followers?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Goread.io", "imageUrl": "https://images.opencollective.com/goread_io/eb6337d/logo.png", "description": null, "tier": "silver", "slug": "goread_io", "website": "https://goread.io/buy-instagram-followers?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/goread_io?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": true }, { "name": "eestionlinekasiinod.org", "imageUrl": "https://images.opencollective.com/eestionlinekasiinod-org/a3c015c/logo.png", "description": "online casino review", "tier": "silver", "slug": "eestionlinekasiinod-org", "website": "https://eestionlinekasiinod.org/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "superluxuryreps", "imageUrl": "https://images.opencollective.com/superluxuryreps/378b62f/avatar.png", "description": "super luxury reps", "tier": "silver", "slug": "superluxuryreps", "website": "https://superluxuryreps.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true } ], "gold": [ { "name": "Stytch", "imageUrl": "https://images.opencollective.com/stytch/f84ce43/logo.png", "description": null, "tier": "gold", "slug": "stytch", "website": "https://stytch.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/stytchauth?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": false }, { "name": "Principal Financial Group", "imageUrl": "https://images.opencollective.com/principal/431e690/logo.png", "description": null, "tier": "gold", "slug": "principal", "website": "https://www.principal.com/about-us?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/Principal?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": true }, { "name": "Descope", "imageUrl": "https://images.opencollective.com/descope/b53243e/logo.png", "description": "Hi, we're Descope! We are building something in the authentication space for app developers and can’t wait to place it in your hands.", "tier": "gold", "slug": "descope", "website": "https://www.descope.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": "https://twitter.com/descopeinc?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": true }, { "name": "RxDB", "imageUrl": "https://images.opencollective.com/rxdbjs/2aec389/logo.png", "description": null, "tier": "gold", "slug": "rxdbjs", "website": "https://rxdb.info/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship&utm_content=logo", "twitter": "https://twitter.com/rxdbjs?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "active": true }, { "name": "Poprey - Buy Instagram Likes", "imageUrl": "https://images.opencollective.com/instagram-likes/2a72a03/avatar.png", "description": "Buy Instagram Likes", "tier": "gold", "slug": "instagram-likes", "website": "https://poprey.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true }, { "name": "Buzzoid - Buy Instagram Followers", "imageUrl": "https://images.opencollective.com/buzzoid-buy-instagram-followers/56a09fe/logo.png", "description": "At Buzzoid, you can buy Instagram followers quickly, safely, and easily with just a few clicks. Rated world's #1 IG service since 2012.", "tier": "gold", "slug": "buzzoid-buy-instagram-followers", "website": "https://buzzoid.com/buy-instagram-followers/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship", "twitter": null, "active": true } ] }axios-axios-2d06f96/docs/es/000077500000000000000000000000001521272452000156575ustar00rootroot00000000000000axios-axios-2d06f96/docs/es/index.md000066400000000000000000000236001521272452000173110ustar00rootroot00000000000000--- # https://vitepress.dev/reference/default-theme-home-page layout: home hero: name: 'axios docs' text: 'axios es un cliente HTTP simple para el navegador y Node.js' image: dark: /logo.svg light: /logo-light.svg alt: axios actions: - theme: brand text: Comenzar link: /es/pages/getting-started/first-steps - theme: alt text: Referencia de API link: /es/pages/advanced/api-reference features: - title: Implementación sencilla details: Comenzar con axios es tan simple como una sola línea de código. Las solicitudes API básicas se pueden realizar en 2 líneas de código. - title: Interceptores potentes details: Nuestro innovador sistema de interceptores le permite controlar el ciclo de vida de solicitudes y respuestas. Puede modificar solicitudes, respuestas y errores. - title: Soporte para TypeScript details: axios declara tipos y tiene soporte completo para TypeScript. Esto significa que puede usar axios con confianza en sus proyectos TypeScript. ---

Patrocinadores

{{ sponsor.name }}

{{ capitalizeFirstLetter(sponsor.tier) }}
axios-axios-2d06f96/docs/es/pages/000077500000000000000000000000001521272452000167565ustar00rootroot00000000000000axios-axios-2d06f96/docs/es/pages/advanced/000077500000000000000000000000001521272452000205235ustar00rootroot00000000000000axios-axios-2d06f96/docs/es/pages/advanced/adapters.md000066400000000000000000000064021521272452000226520ustar00rootroot00000000000000# Adaptadores Los adaptadores te permiten personalizar la forma en que axios maneja los datos de la solicitud. De forma predeterminada, axios usa una lista de prioridad ordenada de `['xhr', 'http', 'fetch']` y selecciona el primer adaptador que sea compatible con el entorno actual. En la práctica, esto significa que `xhr` se usa en los navegadores, `http` en Node.js y `fetch` en entornos donde ninguno de los dos está disponible (como Cloudflare Workers o Deno). Escribir tu propio adaptador te permite controlar completamente cómo axios realiza una solicitud y procesa la respuesta — útil para pruebas, transportes personalizados o entornos no estándar. ## Adaptadores integrados Puedes seleccionar un adaptador integrado por nombre usando la opción de configuración `adapter`: ```js // Use the fetch adapter const instance = axios.create({ adapter: "fetch" }); // Use the XHR adapter (browser default) const instance = axios.create({ adapter: "xhr" }); // Use the HTTP adapter (Node.js default) const instance = axios.create({ adapter: "http" }); ``` También puedes pasar un arreglo de nombres de adaptadores. axios usará el primero que sea compatible con el entorno actual: ```js const instance = axios.create({ adapter: ["fetch", "xhr", "http"] }); ``` Para más detalles sobre el adaptador `fetch`, consulta la página del [Adaptador Fetch](/pages/advanced/fetch-adapter). ## Crear un adaptador personalizado Para crear un adaptador personalizado, escribe una función que acepte un objeto `config` y devuelva una Promise que se resuelva en un objeto de respuesta de axios válido. ```js import axios from "axios"; import { settle } from "axios/unsafe/core/settle.js"; function myAdapter(config) { /** * At this point: * - config has been merged with defaults * - request transformers have run * - request interceptors have run * * The adapter is now responsible for making the request * and returning a valid response object. */ return new Promise((resolve, reject) => { // Perform your custom request logic here. // This example uses the native fetch API as a starting point. fetch(config.url, { method: config.method?.toUpperCase() ?? "GET", headers: config.headers?.toJSON() ?? {}, body: config.data, signal: config.signal, }) .then(async (fetchResponse) => { const responseData = await fetchResponse.text(); const response = { data: responseData, status: fetchResponse.status, statusText: fetchResponse.statusText, headers: Object.fromEntries(fetchResponse.headers.entries()), config, request: null, }; // settle resolves or rejects the promise based on the HTTP status settle(resolve, reject, response); /** * After this point: * - response transformers will run * - response interceptors will run */ }) .catch(reject); }); } const instance = axios.create({ adapter: myAdapter }); ``` ::: tip El helper `settle` resuelve la Promise para códigos de estado 2xx y la rechaza para todo lo demás, siguiendo el comportamiento predeterminado de axios. Si deseas una validación de estado personalizada, usa la opción de configuración `validateStatus`. ::: axios-axios-2d06f96/docs/es/pages/advanced/api-reference.md000066400000000000000000000256571521272452000235710ustar00rootroot00000000000000# Referencia de la API A continuación se presenta una lista de todas las funciones y clases disponibles en el paquete axios. Estas funciones pueden usarse e importarse en tu proyecto. Todas ellas están protegidas por nuestro renovado compromiso de seguir el versionado semántico. Esto significa que puedes confiar en que estas funciones y clases permanecerán estables y sin cambios en futuras versiones, salvo que se realice un cambio de versión mayor. ## Instancia La instancia `axios` es el objeto principal que usarás para realizar solicitudes HTTP. Es una función de fábrica que crea una nueva instancia de la clase `Axios`. La instancia `axios` cuenta con una serie de métodos para hacer solicitudes HTTP, los cuales están documentados en la [sección de alias de solicitud](/pages/advanced/request-method-aliases) de la documentación. ## Clases ### `Axios` La clase `Axios` es la clase principal que usarás para realizar solicitudes HTTP. Es una función de fábrica que crea una nueva instancia de la clase `Axios`. La clase `Axios` cuenta con una serie de métodos para hacer solicitudes HTTP, los cuales están documentados en la [sección de alias de solicitud](/pages/advanced/request-method-aliases) de la documentación. #### `constructor` Crea una nueva instancia de la clase `Axios`. El constructor acepta un objeto de configuración opcional como argumento. ```ts constructor(instanceConfig?: AxiosRequestConfig); ``` #### `request` Gestiona la invocación de la solicitud y la resolución de la respuesta. Este es el método principal que usarás para hacer solicitudes HTTP. Acepta un objeto de configuración como argumento y devuelve una Promise que se resuelve en el objeto de respuesta. ```ts request(configOrUrl: string | AxiosRequestConfig, config: AxiosRequestConfig): Promise>; ``` ### `CancelToken` La clase `CancelToken` estaba basada en la propuesta `tc39/proposal-cancelable-promises`. Se usaba para crear un token que permitiera cancelar una solicitud HTTP. La clase `CancelToken` está ahora obsoleta en favor de la API `AbortController`. A partir de la versión 0.22.0, la clase `CancelToken` está obsoleta y será eliminada en una versión futura. Se recomienda usar la API `AbortController` en su lugar. La clase se exporta principalmente por compatibilidad con versiones anteriores y será eliminada en una versión futura. Desaconsejamos fuertemente su uso en proyectos nuevos, por lo que no documentamos su API. ## Funciones ### `AxiosError` La clase `AxiosError` es una clase de error que se lanza cuando una solicitud HTTP falla. Extiende la clase `Error` y añade propiedades adicionales al objeto de error. #### `constructor` Crea una nueva instancia de la clase `AxiosError`. El constructor acepta opcionalmente un mensaje, un código, una configuración, una solicitud y una respuesta como argumentos. ```ts constructor(message?: string, code?: string, config?: InternalAxiosRequestConfig, request?: any, response?: AxiosResponse); ``` #### `properties` La clase `AxiosError` proporciona las siguientes propiedades: ```ts // Instancia de configuración. config?: InternalAxiosRequestConfig; // Código de error. code?: string; // Instancia de solicitud. request?: any; // Instancia de respuesta. response?: AxiosResponse; // Booleano que indica si el error es un `AxiosError`. isAxiosError: boolean; // Código de estado HTTP del error. status?: number; // Método auxiliar para convertir el error a un objeto JSON. toJSON: () => object; // Causa del error. cause?: Error; ``` ### `AxiosHeaders` La clase `AxiosHeaders` es una clase de utilidad que se usa para gestionar encabezados HTTP. Provee métodos para manipular encabezados, como añadir, eliminar y obtener encabezados. Aquí solo se documentan los métodos principales. Para una lista completa de métodos, consulta el archivo de declaración de tipos. #### `constructor` Crea una nueva instancia de la clase `AxiosHeaders`. El constructor acepta opcionalmente un objeto de encabezados como argumento. ```ts constructor(headers?: RawAxiosHeaders | AxiosHeaders | string); ``` #### `set` Agrega un encabezado al objeto de encabezados. Los nombres de encabezado vacíos o compuestos solo por espacios se ignoran. ```ts set(headerName?: string, value?: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders; set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean): AxiosHeaders; ``` #### `get` Obtiene un encabezado del objeto de encabezados. ```ts get(headerName: string, parser: RegExp): RegExpExecArray | null; get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue; ``` #### `has` Verifica si un encabezado existe en el objeto de encabezados. ```ts has(header: string, matcher?: AxiosHeaderMatcher): boolean; ``` #### `delete` Elimina un encabezado del objeto de encabezados. ```ts delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean; ``` #### `clear` Elimina todos los encabezados del objeto de encabezados. ```ts clear(matcher?: AxiosHeaderMatcher): boolean; ``` #### `normalize` Normaliza el objeto de encabezados. ```ts normalize(format: boolean): AxiosHeaders; ``` #### `concat` Concatena objetos de encabezados. ```ts concat(...targets: Array): AxiosHeaders; ``` #### `toJSON` Convierte el objeto de encabezados a un objeto JSON. ```ts toJSON(asStrings: true): Record; toJSON(asStrings?: false): Record; ``` ### `CanceledError` La clase `CanceledError` es una clase de error que se lanza cuando se cancela una solicitud HTTP. Extiende la clase `AxiosError`. ### `Cancel` La clase `Cancel` es un alias de la clase `CanceledError`. Se exporta por compatibilidad con versiones anteriores y será eliminada en una versión futura. ### `isCancel` Una función que verifica si un error es un `CanceledError`. Es útil para distinguir cancelaciones intencionales de errores inesperados. ```ts isCancel(value: any): value is CanceledError; ``` ```js import axios from "axios"; const controller = new AbortController(); axios.get("/api/data", { signal: controller.signal }).catch((error) => { if (axios.isCancel(error)) { console.log("Request was cancelled:", error.message); } else { console.error("Unexpected error:", error); } }); controller.abort("User navigated away"); ``` ### `isAxiosError` Una función que verifica si un error es un `AxiosError`. Úsala en bloques `catch` para acceder de forma segura a las propiedades específicas de axios como `error.response` y `error.config`. ```ts isAxiosError(value: any): value is AxiosError; ``` ```js import axios from "axios"; try { await axios.get("/api/resource"); } catch (error) { if (axios.isAxiosError(error)) { // error.response, error.config, error.code are all available console.error("HTTP error", error.response?.status, error.message); } else { // A non-axios error (e.g. a programming mistake) throw error; } } ``` ### `all` La función `all` es una función de utilidad que acepta un arreglo de promises y devuelve una única Promise que se resuelve cuando todas las promises del arreglo se han resuelto. La función `all` está ahora obsoleta en favor del método `Promise.all`. Se recomienda usar el método `Promise.all` en su lugar. A partir de la versión 0.22.0, la función `all` está obsoleta y será eliminada en una versión futura. Se recomienda usar el método `Promise.all` en su lugar. ### `spread` La función `spread` es una función de utilidad que puede usarse para distribuir un arreglo de argumentos en una llamada a función. Es útil cuando tienes un arreglo de argumentos que deseas pasar a una función que acepta múltiples argumentos. ```ts spread(callback: (...args: T[]) => R): (array: T[]) => R; ``` ### `toFormData` Convierte un objeto JavaScript plano (o anidado) a una instancia de `FormData`. Es útil cuando deseas construir datos de formulario multipart de forma programática a partir de un objeto. ```ts toFormData(sourceObj: object, formData?: FormData, options?: FormSerializerOptions): FormData; ``` ```js import { toFormData } from "axios"; const data = { name: "Jay", avatar: fileBlob }; const form = toFormData(data); // form is now a FormData instance ready to post await axios.post("/api/users", form); ``` ### `formToJSON` Convierte una instancia de `FormData` de vuelta a un objeto JavaScript plano. Es útil para leer datos de formulario en un formato estructurado. ```ts formToJSON(form: FormData): object; ``` ```js import { formToJSON } from "axios"; const form = new FormData(); form.append("name", "Jay"); form.append("role", "admin"); const obj = formToJSON(form); console.log(obj); // { name: "Jay", role: "admin" } ``` ### `getAdapter` Resuelve y devuelve una función de adaptador por nombre o pasando un arreglo de nombres candidatos. axios usa esto internamente para seleccionar el mejor adaptador disponible para el entorno actual. ```ts getAdapter(adapters: string | string[]): AxiosAdapter; ``` ```js import { getAdapter } from "axios"; // Get the fetch adapter explicitly const fetchAdapter = getAdapter("fetch"); // Get the best available adapter from a priority list const adapter = getAdapter(["fetch", "xhr", "http"]); ``` ### `mergeConfig` Combina dos objetos de configuración de axios, aplicando la misma estrategia de fusión profunda que axios usa internamente al combinar los valores predeterminados con las opciones por solicitud. Los valores posteriores tienen precedencia. ```ts mergeConfig(config1: AxiosRequestConfig, config2: AxiosRequestConfig): AxiosRequestConfig; ``` ```js import { mergeConfig } from "axios"; const base = { baseURL: "https://api.example.com", timeout: 5000 }; const override = { timeout: 10000, headers: { "X-Custom": "value" } }; const merged = mergeConfig(base, override); // { baseURL: "https://api.example.com", timeout: 10000, headers: { "X-Custom": "value" } } ``` ## Constantes ### `HttpStatusCode` Un objeto que contiene una lista de códigos de estado HTTP como constantes con nombre. Úsalo para escribir condicionales legibles en lugar de números directos. ```js import axios, { HttpStatusCode } from "axios"; try { const response = await axios.get("/api/resource"); } catch (error) { if (axios.isAxiosError(error)) { if (error.response?.status === HttpStatusCode.NotFound) { console.error("Resource not found"); } else if (error.response?.status === HttpStatusCode.Unauthorized) { console.error("Authentication required"); } } } ``` ## Miscelánea ### `VERSION` La versión actual del paquete `axios`. Es una cadena que representa el número de versión del paquete. Se actualiza con cada nueva versión del paquete. axios-axios-2d06f96/docs/es/pages/advanced/authentication.md000066400000000000000000000111571521272452000240710ustar00rootroot00000000000000# Autenticación La mayoría de las APIs requieren alguna forma de autenticación. Esta página cubre los patrones más comunes para adjuntar credenciales a las solicitudes de axios. ## Tokens Bearer (JWT) El enfoque más común es adjuntar un JWT en el encabezado `Authorization`. La forma más limpia de hacerlo es a través de un interceptor de solicitud en tu instancia de axios, de manera que el token se lea de nuevo en cada solicitud: ```js import axios from "axios"; const api = axios.create({ baseURL: "https://api.example.com" }); api.interceptors.request.use((config) => { const token = localStorage.getItem("access_token"); if (token) { config.headers.set("Authorization", `Bearer ${token}`); } return config; }); ``` ## Autenticación HTTP Basic Para APIs que usan autenticación HTTP Basic, pasa la opción `auth`. axios codificará las credenciales y establecerá el encabezado `Authorization` automáticamente: ```js const response = await axios.get("https://api.example.com/data", { auth: { username: "myUser", password: "myPassword", }, }); ``` Si no se proporciona `auth`, los adaptadores HTTP de Node.js y fetch también pueden obtener credenciales Basic desde la URL de la solicitud, por ejemplo `https://myUser:myPassword@api.example.com/data`. Las credenciales codificadas con porcentaje en la URL se decodifican antes de generar el encabezado `Authorization`. Para código nuevo, prefiere la opción explícita `auth`; tiene prioridad sobre las credenciales incluidas en la URL. ::: tip Para tokens Bearer y claves de API, usa un encabezado `Authorization` personalizado en lugar de la opción `auth` — `auth` es solo para HTTP Basic. ::: ## Claves de API Las claves de API generalmente se pasan como un encabezado o como un parámetro de consulta, dependiendo de lo que espere la API: ```js // As a header const api = axios.create({ baseURL: "https://api.example.com", headers: { "X-API-Key": "your-api-key-here" }, }); // As a query parameter const response = await axios.get("https://api.example.com/data", { params: { apiKey: "your-api-key-here" }, }); ``` ## Renovación de token Cuando los tokens de acceso expiran, es necesario renovarlos de forma silenciosa y reintentar la solicitud fallida. Un interceptor de respuesta es el lugar adecuado para implementar esto: ```js import axios from "axios"; const api = axios.create({ baseURL: "https://api.example.com" }); // Track whether a refresh is already in progress to avoid parallel refresh calls let isRefreshing = false; let failedQueue = []; const processQueue = (error, token = null) => { failedQueue.forEach((prom) => { if (error) { prom.reject(error); } else { prom.resolve(token); } }); failedQueue = []; }; api.interceptors.response.use( (response) => response, async (error) => { const originalRequest = error.config; if (error.response?.status === 401 && !originalRequest._retry) { if (isRefreshing) { // Queue the request until the refresh completes return new Promise((resolve, reject) => { failedQueue.push({ resolve, reject }); }) .then((token) => { originalRequest.headers["Authorization"] = `Bearer ${token}`; return api(originalRequest); }) .catch((err) => Promise.reject(err)); } originalRequest._retry = true; isRefreshing = true; try { const { data } = await axios.post("/auth/refresh", { refreshToken: localStorage.getItem("refresh_token"), }); const newToken = data.access_token; localStorage.setItem("access_token", newToken); api.defaults.headers.common["Authorization"] = `Bearer ${newToken}`; processQueue(null, newToken); return api(originalRequest); } catch (refreshError) { processQueue(refreshError, null); // Redirect to login or emit an event localStorage.removeItem("access_token"); window.location.href = "/login"; return Promise.reject(refreshError); } finally { isRefreshing = false; } } return Promise.reject(error); } ); ``` ## Autenticación basada en cookies Para APIs basadas en sesiones que dependen de cookies, establece `withCredentials: true` para incluir cookies en solicitudes de origen cruzado: ```js const api = axios.create({ baseURL: "https://api.example.com", withCredentials: true, // send cookies with every request }); ``` ::: warning `withCredentials: true` requiere que el servidor responda con `Access-Control-Allow-Credentials: true` y un valor específico (no comodín) en `Access-Control-Allow-Origin`. ::: axios-axios-2d06f96/docs/es/pages/advanced/cancellation.md000066400000000000000000000041671521272452000235110ustar00rootroot00000000000000# Cancelación A partir de la versión v0.22.0, Axios es compatible con AbortController para cancelar solicitudes de forma limpia. Esta característica está disponible en el navegador y en Node.js cuando se usa una versión de Axios que admite AbortController. Para cancelar una solicitud, debes crear una instancia de `AbortController` y pasar su `signal` a la opción `signal` de la solicitud. ```js const controller = new AbortController(); axios .get("/foo/bar", { signal: controller.signal, }) .then(function (response) { //... }); // cancel the request controller.abort(); ``` ## CancelToken También puedes usar la API `CancelToken` para cancelar solicitudes. Esta API está obsoleta y será eliminada en la próxima versión mayor. Se recomienda usar `AbortController` en su lugar. Puedes crear un token de cancelación usando la fábrica `CancelToken.source` como se muestra a continuación: ```js const CancelToken = axios.CancelToken; const source = CancelToken.source(); axios .get("/user/12345", { cancelToken: source.token, }) .catch(function (thrown) { if (axios.isCancel(thrown)) { console.log("Request canceled", thrown.message); } else { // handle error } }); axios.post( "/user/12345", { name: "new name", }, { cancelToken: source.token, } ); // cancel the request (the message parameter is optional) source.cancel("Operation canceled by the user."); ``` También puedes crear un token de cancelación pasando una función ejecutora al constructor de `CancelToken`: ```js const CancelToken = axios.CancelToken; let cancel; axios.get("/user/12345", { cancelToken: new CancelToken(function executor(c) { // An executor function receives a cancel function as a parameter cancel = c; }), }); // cancel the request cancel(); ``` Puedes cancelar varias solicitudes con el mismo token de cancelación o controlador de cancelación. Si un token de cancelación ya fue cancelado en el momento en que se inicia una solicitud de Axios, la solicitud se cancela inmediatamente, sin intentar realizar ninguna solicitud real. axios-axios-2d06f96/docs/es/pages/advanced/config-defaults.md000066400000000000000000000051411521272452000241200ustar00rootroot00000000000000# Valores predeterminados de configuración axios te permite especificar valores predeterminados de configuración que se aplicarán a cada solicitud. Puedes definir valores predeterminados para `baseURL`, `headers`, `timeout` y otras propiedades. A continuación se muestra un ejemplo de cómo usar los valores predeterminados de configuración: ```js axios.defaults.baseURL = "https://jsonplaceholder.typicode.com/posts"; axios.defaults.headers.common["Authorization"] = AUTH_TOKEN; axios.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded"; ``` ::: warning Los encabezados globales se envían a todos los hosts Si tu aplicación se comunica con más de un dominio, establecer `axios.defaults.headers.common["Authorization"]` enviará el token a **todos** ellos, incluidas APIs de terceros que tal vez no controles. Usa una [instancia personalizada](#valores-predeterminados-personalizados-por-instancia) con un `baseURL` acotado para cualquier cliente que transporte credenciales. ::: ## Valores predeterminados personalizados por instancia Las instancias de axios se declaran con sus propios valores predeterminados al ser creadas. Estos valores pueden sobreescribirse estableciendo la propiedad `defaults` en la instancia. A continuación se muestra un ejemplo de cómo usar valores predeterminados personalizados por instancia: ```js var instance = axios.create({ baseURL: "https://jsonplaceholder.typicode.com/posts", timeout: 1000, headers: { Authorization: "foobar" }, }); instance.defaults.headers.common["Authorization"] = AUTH_TOKEN; ``` ## Orden de precedencia de la configuración La configuración se combinará con un orden de precedencia. El orden es el siguiente: primero se establecen los valores predeterminados de la librería, luego las propiedades predeterminadas de la instancia y, finalmente, el argumento de configuración de la solicitud. A continuación se muestra un ejemplo del orden de precedencia. Primero, vamos a crear una instancia con los valores predeterminados que proporciona la librería. En este punto, el valor de configuración de timeout es `0`, que es el valor predeterminado de la librería. ```js const instance = axios.create(); ``` Ahora sobreescribiremos el timeout predeterminado de la instancia a `2500` milisegundos. A partir de ahora, todas las solicitudes que usen esta instancia esperarán 2.5 segundos antes de expirar. ```js instance.defaults.timeout = 2500; ``` Finalmente, haremos una solicitud con un timeout de `5000` milisegundos. Esta solicitud esperará 5 segundos antes de expirar. ```js instance.get("/longRequest", { timeout: 5000, }); ``` axios-axios-2d06f96/docs/es/pages/advanced/create-an-instance.md000066400000000000000000000056551521272452000245210ustar00rootroot00000000000000# Crear una instancia `axios.create()` te permite crear una instancia de axios preconfigurada. La instancia comparte la misma API de solicitud y respuesta que el objeto `axios` predeterminado, pero utiliza la configuración que proporciones como base para cada solicitud. Esta es la forma recomendada de usar axios en cualquier aplicación que conste de más de un solo archivo. ```ts import axios from "axios"; const instance = axios.create({ baseURL: "https://api.example.com", timeout: 5000, headers: { "X-Custom-Header": "foobar" }, }); ``` El método `create` acepta el objeto completo de [Configuración de solicitud](/pages/advanced/request-config). Luego puedes usar la instancia igual que el objeto axios predeterminado: ```js const response = await instance.get("/users/1"); ``` ## ¿Por qué usar una instancia? ### URL base por servicio En la mayoría de las aplicaciones se interactúa con más de una API. Crear una instancia separada por servicio evita repetir la URL base en cada llamada: ```js const githubApi = axios.create({ baseURL: "https://api.github.com" }); const internalApi = axios.create({ baseURL: "https://api.internal.example.com" }); const { data: repos } = await githubApi.get("/users/axios/repos"); const { data: users } = await internalApi.get("/users"); ``` ### Encabezados de autenticación compartidos Adjunta un token de autenticación a cada solicitud de una instancia sin afectar a las demás: ```js const authApi = axios.create({ baseURL: "https://api.example.com", headers: { Authorization: `Bearer ${getToken()}`, }, }); ``` ### Tiempos de espera y reintentos por servicio Los distintos servicios tienen características de fiabilidad diferentes. Define un tiempo de espera corto para servicios en tiempo real y uno más largo para trabajos por lotes: ```js const realtimeApi = axios.create({ baseURL: "https://realtime.example.com", timeout: 2000 }); const batchApi = axios.create({ baseURL: "https://batch.example.com", timeout: 60000 }); ``` ### Interceptores aislados Los interceptores añadidos a una instancia solo se aplican a esa instancia, manteniendo tus responsabilidades separadas: ```js const loggingApi = axios.create({ baseURL: "https://api.example.com" }); loggingApi.interceptors.request.use((config) => { console.log(`→ ${config.method?.toUpperCase()} ${config.url}`); return config; }); ``` ## Sobreescribir los valores predeterminados por solicitud La configuración pasada en el momento de la solicitud siempre tiene prioridad sobre los valores predeterminados de la instancia: ```js const api = axios.create({ timeout: 5000 }); // This specific request uses a 30-second timeout instead await api.get("/slow-endpoint", { timeout: 30000 }); ``` ::: tip Los valores predeterminados de la instancia también pueden cambiarse después de su creación escribiendo en `instance.defaults`: ```js instance.defaults.headers.common["Authorization"] = `Bearer ${newToken}`; ``` ::: axios-axios-2d06f96/docs/es/pages/advanced/error-handling.md000066400000000000000000000171721521272452000237700ustar00rootroot00000000000000# Manejo de errores axios puede lanzar muchos tipos diferentes de errores. Algunos de estos errores son causados por el propio axios, mientras que otros son causados por el servidor o el cliente. La siguiente tabla lista la estructura general del error lanzado: | Propiedad | Definición | | --------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | message | Un resumen rápido del mensaje de error y el estado con el que falló. | | name | Define el origen del error. Para axios, siempre será un `AxiosError`. | | stack | Proporciona el seguimiento de la pila (stack trace) del error. | | config | Un objeto de configuración de axios con configuraciones específicas de la instancia definidas por el usuario al momento de realizar la solicitud. | | code | Representa un error identificado por axios. La tabla a continuación lista definiciones específicas para errores internos de axios. | | status | Código de estado HTTP de la respuesta. Consulta [aquí](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) para conocer los significados comunes de los códigos de estado HTTP. | A continuación se lista una relación de posibles errores identificados por axios: | Código | Definición | | ------------------------- | --------------------------------------------------------------------------------------------- | | ERR_BAD_OPTION_VALUE | Valor inválido o no compatible proporcionado en la configuración de axios. | | ERR_BAD_OPTION | Opción inválida proporcionada en la configuración de axios. | | ECONNABORTED | Generalmente indica que la solicitud ha expirado (salvo que `transitional.clarifyTimeoutError` esté activado) o fue abortada por el navegador o un complemento del mismo. | | ETIMEDOUT | La solicitud expiró al superar el límite de tiempo predeterminado de axios. Se debe activar `transitional.clarifyTimeoutError` en `true`, de lo contrario se lanzará un error genérico `ECONNABORTED`. | | ERR_NETWORK | Problema relacionado con la red. En el navegador, este error también puede ser causado por una violación de la política [CORS](https://developer.mozilla.org/ru/docs/Web/HTTP/Guides/CORS) o [Mixed Content](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content). El navegador no permite que el código JS aclare la razón real del error por motivos de seguridad; por eso, revisa la consola. | | ERR_FR_TOO_MANY_REDIRECTS | La solicitud fue redirigida demasiadas veces; supera el número máximo de redirecciones especificado en la configuración de axios. | | ERR_DEPRECATED | Se usó una característica o método obsoleto en axios. | | ERR_BAD_RESPONSE | La respuesta no puede ser analizada correctamente o tiene un formato inesperado. Generalmente relacionado con una respuesta con código de estado `5xx`. | | ERR_BAD_REQUEST | La solicitud tiene un formato inesperado o le faltan parámetros requeridos. Generalmente relacionado con una respuesta con código de estado `4xx`. | | ERR_CANCELED | La característica o método fue cancelado explícitamente por el usuario usando un AbortSignal (o un CancelToken). | | ERR_NOT_SUPPORT | Característica o método no compatible en el entorno actual de axios. | | ERR_INVALID_URL | URL inválida proporcionada para la solicitud de axios. | | ERR_FORM_DATA_DEPTH_EXCEEDED | Un objeto excede el `maxDepth` configurado al serializar `params` o datos de formulario. El límite predeterminado es de 100 niveles. Consulta [`paramsSerializer`](/pages/advanced/request-config#paramsserializer) y [`formSerializer`](/pages/advanced/request-config#formserializer). | ## Manejo de errores El comportamiento predeterminado de axios es rechazar la Promise si la solicitud falla. Sin embargo, también puedes capturar el error y manejarlo según lo consideres apropiado. A continuación se muestra un ejemplo de cómo capturar un error: ```js axios.get("/user/12345").catch(function (error) { if (error.response) { // The request was made and the server responded with a status code // that falls out of the range of 2xx console.log(error.response.data); console.log(error.response.status); console.log(error.response.headers); } else if (error.request) { // The request was made but no response was received // `error.request` is an instance of XMLHttpRequest in the browser and an instance of // http.ClientRequest in node.js console.log(error.request); } else { // Something happened in setting up the request that triggered an Error console.log("Error", error.message); } console.log(error.config); }); ``` Usando la opción de configuración `validateStatus`, puedes sobreescribir la condición predeterminada (status >= 200 && status < 300) y definir los códigos HTTP que deben lanzar un error. ```js axios.get("/user/12345", { validateStatus: function (status) { return status < 500; // Resolve only if the status code is less than 500 }, }); ``` Usando el método `toJSON`, puedes obtener un objeto con más información sobre el error. ```js axios.get("/user/12345").catch(function (error) { console.log(error.toJSON()); }); ``` Para evitar registrar secretos desde `error.config`, pasa un arreglo `redact` en la configuración de la solicitud. Las claves de configuración coincidentes se enmascaran de forma insensible a mayúsculas/minúsculas a cualquier profundidad cuando se llama a `AxiosError#toJSON()`. ```js axios.get("/user/12345", { headers: { Authorization: "Bearer token" }, redact: ["authorization"] }).catch(function (error) { console.log(error.toJSON().config.headers.Authorization); // [REDACTED ****] }); ``` ## Manejo de tiempos de espera Cuando una solicitud excede su `timeout` configurado, axios rechaza con `ECONNABORTED` por defecto. Establece `transitional.clarifyTimeoutError: true` para recibir `ETIMEDOUT` en su lugar, lo que facilita distinguir los errores de tiempo de espera de otros abortos. ```js async function fetchWithTimeout() { try { const response = await axios.get("https://example.com/data", { timeout: 5000, // 5 segundos transitional: { // establecer en true si prefieres ETIMEDOUT en lugar de ECONNABORTED clarifyTimeoutError: true, }, }); console.log("Response:", response.data); } catch (error) { if (axios.isAxiosError(error)) { if (error.code === "ECONNABORTED" || error.code === "ETIMEDOUT") { console.error("Request timed out. Please try again."); return; } console.error("Axios error:", error.message); return; } console.error("Unexpected error:", error); } } ``` ::: tip Establece siempre un `timeout` en producción Sin uno, una solicitud detenida puede colgarse indefinidamente. Consulta [`timeout`](/pages/advanced/request-config#timeout) y [`transitional.clarifyTimeoutError`](/pages/advanced/request-config#transitional) para las opciones de configuración correspondientes. ::: axios-axios-2d06f96/docs/es/pages/advanced/fetch-adapter.md000066400000000000000000000074151521272452000235630ustar00rootroot00000000000000# Adaptador Fetch El adaptador `fetch` es un nuevo adaptador que introdujimos a partir de la versión 1.7.0. Proporciona una forma de usar axios con la API `fetch`, dándote lo mejor de ambos mundos. De forma predeterminada, `fetch` se usará si los adaptadores `xhr` y `http` no están disponibles en la compilación o no son compatibles con el entorno. Para usarlo de forma predeterminada, debe seleccionarse explícitamente estableciendo la opción `adapter` en `fetch` al crear una instancia de axios. ```js import axios from 'axios'; const instance = axios.create({ adapter: 'fetch', }); ``` El adaptador admite la misma funcionalidad que el adaptador `xhr`, incluyendo la captura del progreso de carga y descarga. También admite tipos de respuesta adicionales como `stream` y `formdata` (si el entorno lo soporta). Cuando `auth` se omite, el adaptador fetch puede leer credenciales de autenticación HTTP Basic desde la URL de la solicitud, por ejemplo `https://user:pass@example.com`. Las credenciales de URL codificadas con porcentaje se decodifican antes de generar el encabezado `Authorization`, y `auth` tiene prioridad sobre las credenciales incluidas en la URL. ## Fetch personalizado A partir de `v1.12.0`, puedes personalizar el adaptador fetch para que use una función `fetch` personalizada en lugar de la global del entorno. Puedes pasar una función `fetch` personalizada, y los constructores `Request` y `Response` a través de la opción de configuración `env`. Esto es útil cuando trabajas con entornos personalizados o frameworks de aplicación que proporcionan su propia implementación de `fetch`. ::: info Al usar una función `fetch` personalizada, es posible que también necesites proporcionar constructores `Request` y `Response` correspondientes. Si los omites, se usarán los constructores globales. Si tu `fetch` personalizado es incompatible con los globales, pasa `null` para deshabilitarlos. **Nota:** Establecer `Request` y `Response` en `null` hará imposible que el adaptador fetch capture el progreso de carga y descarga. ::: ### Ejemplo básico ```js import customFetchFunction from 'customFetchModule'; const instance = axios.create({ adapter: 'fetch', onDownloadProgress(e) { console.log('downloadProgress', e); }, env: { fetch: customFetchFunction, Request: null, // null -> disable the constructor Response: null, }, }); ``` ### Usando con Tauri [Tauri](https://tauri.app/plugin/http-client/) proporciona una función `fetch` de plataforma que omite las restricciones CORS del navegador para las solicitudes realizadas desde la capa nativa. El ejemplo a continuación muestra una configuración mínima para usar axios dentro de una aplicación Tauri con ese fetch personalizado. ```js import { fetch } from '@tauri-apps/plugin-http'; import axios from 'axios'; const instance = axios.create({ adapter: 'fetch', onDownloadProgress(e) { console.log('downloadProgress', e); }, env: { fetch, }, }); const { data } = await instance.get('https://google.com'); ``` ### Usando con SvelteKit [SvelteKit](https://svelte.dev/docs/kit/web-standards#Fetch-APIs) proporciona una implementación personalizada de `fetch` para las funciones `load` del lado del servidor que gestiona el reenvío de cookies y URLs relativas. Dado que su `fetch` es incompatible con la API estándar de `URL`, axios debe configurarse para usarlo explícitamente, y los constructores globales `Request` y `Response` deben deshabilitarse. ```js export async function load({ fetch }) { const { data: post } = await axios.get('https://jsonplaceholder.typicode.com/posts/1', { adapter: 'fetch', env: { fetch, Request: null, Response: null, }, }); return { post }; } ``` axios-axios-2d06f96/docs/es/pages/advanced/file-posting.md000066400000000000000000000062021521272452000234450ustar00rootroot00000000000000# Publicación de archivos axios facilita la subida de archivos. Usa `postForm` o `FormData` cuando necesites subidas en formato `multipart/form-data`. ## Archivo único (navegador) Pasa un objeto `File` directamente como valor de campo — axios lo detectará y usará automáticamente el tipo de contenido correcto: ```js await axios.postForm("https://httpbin.org/post", { description: "My profile photo", file: document.querySelector("#fileInput").files[0], }); ``` ## Múltiples archivos (navegador) Pasa un `FileList` para subir todos los archivos seleccionados a la vez. Todos se enviarán bajo el mismo nombre de campo (`files[]`): ```js await axios.postForm( "https://httpbin.org/post", document.querySelector("#fileInput").files ); ``` También puedes pasar el `FileList` (o un arreglo de objetos `File`) explícitamente bajo un nombre de campo personalizado añadiendo `[]` a la clave: ```js await axios.postForm("https://httpbin.org/post", { "files[]": document.querySelector("#fileInput").files, }); ``` Para usar nombres de campo distintos para cada archivo, construye un objeto `FormData` manualmente: ```js const formData = new FormData(); formData.append("avatar", avatarFile); formData.append("cover", coverFile); await axios.post("https://httpbin.org/post", formData); ``` ## Seguimiento del progreso de la carga (navegador) Usa el callback `onUploadProgress` para mostrar una barra de progreso o un porcentaje a tus usuarios: ```js await axios.postForm("https://httpbin.org/post", { file: document.querySelector("#fileInput").files[0], }, { onUploadProgress: (progressEvent) => { const percent = Math.round( (progressEvent.loaded * 100) / progressEvent.total ); console.log(`Upload progress: ${percent}%`); }, }); ``` Consulta [Captura de progreso](/pages/advanced/progress-capturing) para ver la lista completa de campos disponibles en el evento de progreso. ## Archivos en Node.js En Node.js, usa `fs.createReadStream` para subir un archivo desde el sistema de archivos sin cargarlo completamente en memoria: ```js import fs from "fs"; import FormData from "form-data"; import axios from "axios"; const form = new FormData(); form.append("file", fs.createReadStream("/path/to/file.jpg")); form.append("description", "My uploaded file"); await axios.post("https://httpbin.org/post", form); ``` ::: tip El paquete npm `form-data` es necesario en entornos Node.js para crear objetos `FormData`. En versiones modernas de Node.js (v18+), el `FormData` global está disponible de forma nativa. ::: ## Subir un Buffer (Node.js) También puedes subir un `Buffer` en memoria directamente: ```js const buffer = Buffer.from("Hello, world!"); const form = new FormData(); form.append("file", buffer, { filename: "hello.txt", contentType: "text/plain", knownLength: buffer.length, }); await axios.post("https://httpbin.org/post", form); ``` ::: warning La captura del progreso de carga de `FormData` no está disponible actualmente en entornos Node.js. ::: ::: danger Al subir un stream legible en Node.js, establece `maxRedirects: 0` para evitar que el paquete `follow-redirects` almacene todo el stream en memoria RAM. ::: axios-axios-2d06f96/docs/es/pages/advanced/header-methods.md000066400000000000000000000172701521272452000237450ustar00rootroot00000000000000# Métodos de encabezados Con la introducción de la nueva clase `AxiosHeaders`, Axios ofrece un conjunto de métodos para manipular encabezados. Estos métodos se usan para establecer, obtener y eliminar encabezados de una forma más conveniente que manipular directamente el objeto de encabezados. ## Constructor `new AxiosHeaders(headers?)` El constructor de la clase `AxiosHeaders` acepta un objeto opcional con encabezados para inicializar la instancia. El objeto de encabezados puede contener cualquier número de encabezados, y las claves son insensibles a mayúsculas y minúsculas. ```js constructor(headers?: RawAxiosHeaders | AxiosHeaders | string); ``` Por conveniencia, puedes pasar una cadena de texto con encabezados separados por un carácter de nueva línea. Los encabezados se analizan y se añaden a la instancia. ```js const headers = new AxiosHeaders(` Host: www.bing.com User-Agent: curl/7.54.0 Accept: */*`); console.log(headers); // Object [AxiosHeaders] { // host: 'www.bing.com', // 'user-agent': 'curl/7.54.0', // accept: '*/*' // } ``` ## Set (Establecer) El método `set` se usa para establecer encabezados en la instancia de `AxiosHeaders`. El método puede ser llamado con un nombre de encabezado y un valor únicos, un objeto con múltiples encabezados, o una cadena de texto con encabezados separados por una nueva línea. El método también acepta un parámetro opcional `rewrite` que controla el comportamiento al establecer el encabezado. ```js set(headerName, value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher); set(headerName, value, rewrite?: (this: AxiosHeaders, value: string, name: string) => boolean); set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean); ``` El argumento `rewrite` controla el comportamiento de sobreescritura: - `false` - no sobreescribir si el valor del encabezado ya está definido (es decir, no es `undefined`) - `undefined` (predeterminado) - sobreescribir el encabezado a menos que su valor esté establecido en `false` - `true` - sobreescribir siempre La opción también puede aceptar una función definida por el usuario que determina si el valor debe ser sobreescrito o no. La función recibe el valor actual, el nombre del encabezado y el objeto de encabezados como argumentos. Los nombres de encabezado vacíos o compuestos solo por espacios se ignoran. `AxiosHeaders` conserva el formato de la primera clave coincidente que encuentra. Puedes usar esto para preservar el formato específico de un encabezado inicializando una clave con `undefined` y luego estableciendo los valores posteriormente. Consulta [Preservar el formato de un encabezado específico](/pages/advanced/headers#preserving-a-specific-header-case). ## Get (Obtener) El método `get` se usa para recuperar el valor de un encabezado. El método puede ser llamado con un nombre de encabezado único, un matcher opcional o un parser. El matcher tiene valor predeterminado `true`. El parser puede ser una expresión regular que se usa para extraer el valor del encabezado. ```js get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue; get(headerName: string, parser: RegExp): RegExpExecArray | null; ``` A continuación se muestra un ejemplo de algunos de los posibles usos del método `get`: ```js const headers = new AxiosHeaders({ 'Content-Type': 'multipart/form-data; boundary=Asrf456BGe4h', }); console.log(headers.get('Content-Type')); // multipart/form-data; boundary=Asrf456BGe4h console.log(headers.get('Content-Type', true)); // parse key-value pairs from a string separated with \s,;= delimiters: // [Object: null prototype] { // 'multipart/form-data': undefined, // boundary: 'Asrf456BGe4h' // } console.log( headers.get('Content-Type', (value, name, headers) => { return String(value).replace(/a/g, 'ZZZ'); }) ); // multipZZZrt/form-dZZZtZZZ; boundZZZry=Asrf456BGe4h console.log(headers.get('Content-Type', /boundary=(\w+)/)?.[0]); // boundary=Asrf456BGe4h ``` ## Has (Verificar existencia) El método `has` se usa para verificar si un encabezado existe en la instancia de `AxiosHeaders`. El método puede ser llamado con un nombre de encabezado único y un matcher opcional. ```js has(header: string, matcher?: AxiosHeaderMatcher): boolean; ``` ::: info Devuelve `true` si el encabezado está definido (tiene un valor que no es `undefined`). ::: ## Delete (Eliminar) El método `delete` se usa para eliminar un encabezado de la instancia de `AxiosHeaders`. El método puede ser llamado con un nombre de encabezado único y un matcher opcional. ```js delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean; ``` ::: info Devuelve `true` si al menos un encabezado fue eliminado. ::: ## Clear (Limpiar) El método `clear` se usa para eliminar todos los encabezados de la instancia de `AxiosHeaders` si no se pasa ningún argumento. Si se pasa un matcher, solo se eliminan los encabezados que coincidan con él; en este caso, el matcher se compara contra el nombre del encabezado en lugar del valor. ```js clear(matcher?: AxiosHeaderMatcher): boolean; ``` ::: info Devuelve `true` si al menos un encabezado fue eliminado. ::: ## Normalize (Normalizar) Si el objeto de encabezados fue modificado directamente, puede generar duplicados con el mismo nombre pero en diferentes formatos. Este método normaliza el objeto de encabezados combinando claves duplicadas en una sola. Axios usa este método internamente después de llamar a cada interceptor. Establece `format` en `true` para convertir los nombres de los encabezados a minúsculas y capitalizar las letras iniciales (`cOntEnt-type` => `Content-Type`) o en `false` para mantener el formato original. ```js const headers = new AxiosHeaders({ foo: '1', }); headers.Foo = '2'; headers.FOO = '3'; console.log(headers.toJSON()); // [Object: null prototype] { foo: '1', Foo: '2', FOO: '3' } console.log(headers.normalize().toJSON()); // [Object: null prototype] { foo: '3' } console.log(headers.normalize(true).toJSON()); // [Object: null prototype] { Foo: '3' } ``` ::: info Devuelve `this` para encadenamiento. ::: ## Concat (Concatenar) Combina la instancia con los objetivos en una nueva instancia de `AxiosHeaders`. Si el objetivo es una cadena de texto, se analizará como encabezados HTTP en formato RAW. Si el objetivo es una instancia de `AxiosHeaders`, se combinará con la instancia actual. Esto es útil para formatos predefinidos de mayúsculas/minúsculas al componer encabezados. Por ejemplo: ```js const headers = AxiosHeaders.concat( { 'content-type': undefined }, { 'Content-Type': 'application/octet-stream' } ); ``` ```js concat(...targets: Array): AxiosHeaders; ``` ::: info Devuelve una nueva instancia de `AxiosHeaders`. ::: ## toJSON Resuelve todos los valores de encabezados internos en un nuevo objeto de prototipo nulo. Establece `asStrings` en `true` para resolver los arreglos como una cadena que contiene todos los elementos, separados por comas. ```js toJSON(asStrings: true): Record; toJSON(asStrings?: false): Record; ``` ## From (Desde) Devuelve una nueva instancia de `AxiosHeaders` creada a partir de los encabezados en bruto pasados, o simplemente devuelve el objeto de encabezados dado si ya es una instancia de `AxiosHeaders`. ```js from(thing?: AxiosHeaders | RawAxiosHeaders | string): AxiosHeaders; ``` ## Atajos Los siguientes atajos están disponibles: - `setContentType`, `getContentType`, `hasContentType` - `setContentLength`, `getContentLength`, `hasContentLength` - `setAccept`, `getAccept`, `hasAccept` - `setUserAgent`, `getUserAgent`, `hasUserAgent` - `setContentEncoding`, `getContentEncoding`, `hasContentEncoding` axios-axios-2d06f96/docs/es/pages/advanced/headers.md000066400000000000000000000126141521272452000224640ustar00rootroot00000000000000# Encabezados Axios expone su propia clase `AxiosHeaders` para manipular encabezados usando una API similar a Map que garantiza claves insensibles a mayúsculas y minúsculas. Esta clase es usada internamente por Axios para gestionar encabezados, pero también está disponible para el usuario por conveniencia. Aunque los encabezados HTTP no son sensibles a mayúsculas y minúsculas, Axios conservará el formato original del encabezado por razones estéticas y como solución alternativa cuando los servidores consideran erróneamente el caso del encabezado. La forma antigua de manipular directamente el objeto de encabezados sigue disponible, pero está obsoleta y no se recomienda para uso futuro. ## Trabajar con encabezados La instancia del objeto `AxiosHeaders` puede contener diferentes tipos de valores internos que controlan la lógica de configuración y combinación. El objeto de encabezados final es obtenido por Axios mediante la llamada al método `toJSON`. El objeto `AxiosHeaders` también es iterable, por lo que puedes usarlo en bucles o convertirlo en un arreglo u objeto. Los valores de los encabezados pueden ser de los siguientes tipos: - `string` - valor de cadena de texto normal que se enviará al servidor - `null` - omitir el encabezado al convertir a JSON - `false` - omitir el encabezado al convertir a JSON; indica además que el método `set` debe ser llamado con la opción `rewrite` en `true` para sobreescribir este valor (Axios usa esto internamente para permitir que los usuarios opten por no instalar ciertos encabezados como `User-Agent` o `Content-Type`) - `undefined` - el valor no está definido ::: warning El valor del encabezado se considera definido si no es `undefined`. ::: El objeto de encabezados siempre se inicializa dentro de los interceptores y transformadores, como se muestra en el siguiente ejemplo: ```js axios.interceptors.request.use((request: InternalAxiosRequestConfig) => { request.headers.set("My-header", "value"); request.headers.set({ "My-set-header1": "my-set-value1", "My-set-header2": "my-set-value2", }); // Disable subsequent setting of this header by Axios request.headers.set("User-Agent", false); request.headers.setContentType("text/plain"); // Direct access like this is deprecated request.headers["My-set-header2"] = "newValue"; return request; }); ``` Puedes iterar sobre un `AxiosHeaders` usando cualquier método iterable, como un bucle for-of, forEach o el operador spread: ```js const headers = new AxiosHeaders({ foo: '1', bar: '2', baz: '3', }); for (const [header, value] of headers) { console.log(header, value); } // foo 1 // bar 2 // baz 3 ``` ## Establecer encabezados en una solicitud El lugar más común para establecer encabezados es la opción `headers` en la configuración de tu solicitud o en la configuración de la instancia: ```js // On a single request await axios.get('/api/data', { headers: { 'Accept-Language': 'en-US', 'X-Request-ID': 'abc123', }, }); // On an instance (applied to every request) const api = axios.create({ headers: { 'X-App-Version': '2.0.0', }, }); ``` ## Preservar el formato de un encabezado específico Los nombres de encabezados de Axios son insensibles a mayúsculas y minúsculas, pero `AxiosHeaders` conserva el formato de la primera clave coincidente que encuentra. Si necesitas un formato específico para un servidor con comportamiento sensible a mayúsculas y minúsculas no estándar, define un formato predeterminado en `defaults` y luego establece los valores normalmente. ```js const api = axios.create(); api.defaults.headers.common = { 'content-type': undefined, accept: undefined, }; await api.put(url, data, { headers: { 'Content-Type': 'application/octet-stream', Accept: 'application/json', }, }); ``` También puedes hacerlo directamente con `AxiosHeaders` al componer encabezados: ```js import axios, { AxiosHeaders } from 'axios'; const headers = AxiosHeaders.concat( { 'content-type': undefined }, { 'Content-Type': 'application/octet-stream' } ); await axios.put(url, data, { headers }); ``` ## Establecer encabezados en un interceptor Los interceptores son el lugar adecuado para adjuntar encabezados dinámicos como tokens de autenticación, ya que el token puede no estar disponible cuando la instancia se crea por primera vez: ```js api.interceptors.request.use((config) => { const token = getAuthToken(); // read at request time config.headers.set('Authorization', `Bearer ${token}`); return config; }); ``` ## Leer encabezados de respuesta Los encabezados de respuesta están disponibles en `response.headers` como una instancia de `AxiosHeaders`. Todos los nombres de encabezados están en minúsculas: ```js const response = await axios.get('/api/data'); console.log(response.headers['content-type']); // application/json; charset=utf-8 console.log(response.headers.get('x-request-id')); // abc123 ``` ## Eliminar un encabezado predeterminado Para optar por no incluir un encabezado que axios establece por defecto (como `Content-Type` o `User-Agent`), establece su valor en `false`: ```js await axios.post('/api/data', payload, { headers: { 'Content-Type': false, // let the browser set it automatically (e.g. for FormData) }, }); ``` Para más detalles sobre la API completa de métodos de `AxiosHeaders`, consulta la página de [Métodos de encabezados](/pages/advanced/header-methods). axios-axios-2d06f96/docs/es/pages/advanced/html-form-processing.md000066400000000000000000000040701521272452000251250ustar00rootroot00000000000000# Envío de formularios HTML (navegador) También puedes enviar un formulario directamente desde un elemento de formulario HTML. Esto es útil cuando tienes un formulario en tu página y deseas enviarlo sin escribir código JavaScript adicional. ```js await axios.postForm('https://httpbin.org/post', document.querySelector('#htmlForm')); ``` Los objetos `FormData` y `HTMLForm` también pueden enviarse como `JSON` estableciendo explícitamente el encabezado `Content-Type` en `application/json`: ```js await axios.post('https://httpbin.org/post', document.querySelector('#htmlForm'), { headers: { 'Content-Type': 'application/json', }, }); ``` Un ejemplo de un formulario válido que puede ser enviado con el código anterior es: ```html
``` El formulario anterior se enviará como: ```json { "foo": "1", "deep": { "prop": { "spaced": "3" } }, "baz": ["4", "5"], "user": { "age": "value2" } } ``` ::: tip Las colisiones de rutas sobrescriben los valores anteriores Los nombres de campo se analizan como rutas de propiedad dividiendo por `.`, corchetes o espacios en blanco. Dos inputs cuyas rutas se solapan colisionarán: en el ejemplo anterior, `deep.prop` se analiza como `["deep", "prop"]` y `deep prop spaced` como `["deep", "prop", "spaced"]`, por lo que la asignación más profunda reemplaza `deep.prop = "2"` por el objeto anidado `{ spaced: "3" }`. Elige nombres de campo no superpuestos si necesitas conservar ambos valores. ::: ::: warning Actualmente no se admite el envío de Blobs/Files como JSON (base64). ::: axios-axios-2d06f96/docs/es/pages/advanced/http2.md000066400000000000000000000052351521272452000221130ustar00rootroot00000000000000# HTTP2 El soporte experimental de HTTP/2 fue añadido al adaptador `http` en la versión `1.13.0`. Solo está disponible en entornos Node.js. ## Uso básico Usa la opción `httpVersion` para seleccionar la versión del protocolo para una solicitud. Establecerla en `2` habilita HTTP/2. ```js const { data, headers, status } = await axios.post( "https://httpbin.org/post", form, { httpVersion: 2, }, ); ``` ## `http2Options` Las opciones nativas adicionales para la llamada interna `session.request()` pueden pasarse a través del objeto de configuración `http2Options`. Esto también incluye el parámetro personalizado `sessionTimeout`, que controla cuánto tiempo (en milisegundos) una sesión HTTP/2 inactiva se mantiene viva antes de cerrarse. Su valor predeterminado es `1000ms`. ```js { httpVersion: 2, http2Options: { rejectUnauthorized: false, // accept self-signed certificates (dev only) sessionTimeout: 5000, // keep idle session alive for 5 seconds }, } ``` ::: warning El soporte de HTTP/2 es actualmente experimental. La API puede cambiar en futuras versiones menores o de parche. ::: ::: warning Las redirecciones no se admiten sobre HTTP/2 El adaptador HTTP/2 actualmente no sigue redirecciones. Si una solicitud emitida con `httpVersion: 2` recibe una respuesta `3xx`, la redirección no se sigue automáticamente. Maneja estas respuestas manualmente o permanece en HTTP/1.x para endpoints que dependen de redirecciones. ::: ## Ejemplo completo El ejemplo a continuación envía una solicitud POST con `multipart/form-data` sobre HTTP/2 y rastrea tanto el progreso de carga como el de descarga. ```js const form = new FormData(); form.append("foo", "123"); const { data, headers, status } = await axios.post( "https://httpbin.org/post", form, { httpVersion: 2, http2Options: { // rejectUnauthorized: false, // sessionTimeout: 1000 }, onUploadProgress(e) { console.log("upload progress", e); }, onDownloadProgress(e) { console.log("download progress", e); }, responseType: "arraybuffer", }, ); ``` ## Referencia de configuración | Opción | Tipo | Predeterminado | Descripción | |---|---|---|---| | `httpVersion` | `number` | `1` | Versión del protocolo HTTP a usar. Establece en `2` para habilitar HTTP/2. | | `http2Options.sessionTimeout` | `number` | `1000` | Tiempo en milisegundos antes de que una sesión HTTP/2 inactiva se cierre. | Todas las demás opciones nativas de `session.request()` compatibles con el módulo `http2` integrado de Node.js también pueden pasarse dentro de `http2Options`. axios-axios-2d06f96/docs/es/pages/advanced/interceptors.md000066400000000000000000000142051521272452000235700ustar00rootroot00000000000000# Interceptores Los interceptores son un mecanismo poderoso que puede usarse para interceptar y modificar solicitudes y respuestas HTTP. Son muy similares al middleware en Express.js. Un interceptor es una función que se ejecuta antes de enviar una solicitud y antes de recibir una respuesta. Los interceptores son útiles para una variedad de tareas como el registro de eventos (logging), la modificación de encabezados de solicitud y la modificación de la respuesta. El uso básico de los interceptores es el siguiente: ```js // Add a request interceptor axios.interceptors.request.use( function (config) { // Do something before request is sent return config; }, function (error) { // Do something with request error return Promise.reject(error); } ); // Add a response interceptor axios.interceptors.response.use( function (response) { // Any status code that lie within the range of 2xx cause this function to trigger // Do something with response data return response; }, function (error) { // Any status codes that falls outside the range of 2xx cause this function to trigger // Do something with response error return Promise.reject(error); } ); ``` ## Eliminar interceptores Puedes eliminar cualquier interceptor usando el método `eject` sobre el interceptor que deseas eliminar. También puedes eliminar todos los interceptores llamando al método `clear` sobre el objeto `axios.interceptors`. A continuación se muestra un ejemplo de cómo eliminar un interceptor: ```js // Eject the request interceptor const myInterceptor = axios.interceptors.request.use(function () { /*...*/ }); axios.interceptors.request.eject(myInterceptor); // Eject the response interceptor const myInterceptor = axios.interceptors.response.use(function () { /*...*/ }); axios.interceptors.response.eject(myInterceptor); ``` A continuación se muestra un ejemplo de cómo eliminar todos los interceptores: ```js const instance = axios.create(); instance.interceptors.request.use(function () { /*...*/ }); instance.interceptors.request.clear(); // Removes interceptors from requests instance.interceptors.response.use(function () { /*...*/ }); instance.interceptors.response.clear(); // Removes interceptors from responses ``` ## Comportamiento predeterminado de los interceptores Cuando añades interceptores de solicitud, se asume que son asíncronos de forma predeterminada. Esto puede causar un retraso en la ejecución de tu solicitud axios cuando el hilo principal está bloqueado (se crea una Promise internamente para el interceptor y tu solicitud queda al final de la pila de llamadas). Si tus interceptores de solicitud son síncronos, puedes añadir un indicador al objeto de opciones que le indicará a axios que ejecute el código de forma síncrona y evite cualquier retraso en la ejecución de la solicitud. ```js axios.interceptors.request.use( function (config) { config.headers.test = "I am only a header!"; return config; }, null, { synchronous: true } ); ``` ## Interceptores usando `runWhen` Si deseas ejecutar un interceptor particular basándote en una verificación en tiempo de ejecución, puedes añadir una función `runWhen` al objeto de opciones. El interceptor no se ejecutará si y solo si el retorno de `runWhen` es `false`. La función se llamará con el objeto de configuración (recuerda que también puedes vincularle tus propios argumentos). Esto puede ser útil cuando tienes un interceptor de solicitud asíncrono que solo necesita ejecutarse en ciertos momentos. ```js function onGetCall(config) { return config.method === "get"; } axios.interceptors.request.use( function (config) { config.headers.test = "special get headers"; return config; }, null, { runWhen: onGetCall } ); ``` ## Orden de ejecución de los interceptores ::: warning Los interceptores de solicitud y respuesta se ejecutan en órdenes **opuestos** Los interceptores de solicitud se ejecutan en **orden inverso** (LIFO — último en entrar, primero en salir). El _último_ interceptor de solicitud añadido se ejecuta _primero_. Los interceptores de respuesta se ejecutan en el **orden en que fueron añadidos** (FIFO — primero en entrar, primero en salir). El _primer_ interceptor de respuesta añadido se ejecuta _primero_. ::: El siguiente ejemplo muestra el orden completo de ejecución para tres interceptores de solicitud y tres interceptores de respuesta: ```js const instance = axios.create(); const interceptor = (id) => (base) => { console.log(id); return base; }; instance.interceptors.request.use(interceptor("Request Interceptor 1")); instance.interceptors.request.use(interceptor("Request Interceptor 2")); instance.interceptors.request.use(interceptor("Request Interceptor 3")); instance.interceptors.response.use(interceptor("Response Interceptor 1")); instance.interceptors.response.use(interceptor("Response Interceptor 2")); instance.interceptors.response.use(interceptor("Response Interceptor 3")); // Salida en consola: // Request Interceptor 3 // Request Interceptor 2 // Request Interceptor 1 // [Se realiza la solicitud HTTP] // Response Interceptor 1 // Response Interceptor 2 // Response Interceptor 3 ``` ## Múltiples interceptores Puedes añadir múltiples interceptores a la misma solicitud o respuesta. Lo siguiente aplica para múltiples interceptores en la misma cadena, en el orden indicado a continuación: - Cada interceptor se ejecuta - Los interceptores de solicitud se ejecutan en orden inverso (LIFO). - Los interceptores de respuesta se ejecutan en el orden en que fueron añadidos (FIFO). - Solo se devuelve el resultado del último interceptor - Cada interceptor recibe el resultado de su predecesor - Cuando el interceptor de cumplimiento lanza una excepción: - El siguiente interceptor de cumplimiento no es llamado - El siguiente interceptor de rechazo es llamado - Una vez capturado, el siguiente interceptor de cumplimiento es llamado nuevamente (igual que en una cadena de promises). ::: tip Para obtener una comprensión profunda de cómo funcionan los interceptores, puedes leer los casos de prueba [aquí](https://github.com/axios/axios/blob/v1.x/test/specs/interceptors.spec.js). ::: axios-axios-2d06f96/docs/es/pages/advanced/multipart-form-data-format.md000066400000000000000000000153401521272452000262270ustar00rootroot00000000000000# Formato multipart-form-data axios puede enviar solicitudes en el formato `multipart/form-data`. Este formato se usa comúnmente al subir archivos. Para enviar una solicitud en este formato, debes crear un objeto `FormData` y agregarle los datos. Luego puedes pasar el objeto `FormData` a la propiedad `data` de la configuración de solicitud de axios. ```js const formData = new FormData(); formData.append('foo', 'bar'); axios.post('https://httpbin.org/post', formData); ``` No establezcas manualmente el encabezado `Content-Type` para `FormData` en navegador, web worker o React Native; esos entornos agregan el boundary multipart por sí mismos. En Node.js, puedes usar la librería `form-data` de la siguiente manera: ```js const FormData = require('form-data'); const form = new FormData(); form.append('my_field', 'my value'); form.append('my_buffer', Buffer.alloc(10)); form.append('my_file', fs.createReadStream('/foo/bar.jpg')); axios.post('https://example.com', form); ``` ## Serialización automática a FormData A partir de la versión v0.27.0, Axios admite la serialización automática de objetos a un objeto FormData si el encabezado `Content-Type` de la solicitud está establecido en `multipart/form-data`. Esto significa que puedes pasar un objeto JavaScript directamente a la propiedad `data` de la configuración de solicitud de axios. Por ejemplo, al pasar datos a una solicitud POST: ```js import axios from 'axios'; axios .post( 'https://httpbin.org/post', { x: 1 }, { headers: { 'Content-Type': 'multipart/form-data', }, } ) .then(({ data }) => console.log(data)); ``` En el entorno de Node.js, el polyfill ([`form-data`](https://github.com/form-data/form-data)) se usa de forma predeterminada. Puedes sobrescribir la clase FormData estableciendo la variable de configuración `env.FormData`, aunque en la mayoría de los casos no lo necesitarás: ```js const axios = require('axios'); var FormData = require('form-data'); axios .post( 'https://httpbin.org/post', { x: 1, buf: Buffer.alloc(10) }, { headers: { 'Content-Type': 'multipart/form-data', }, } ) .then(({ data }) => console.log(data)); ``` ## Política de encabezados para `FormData` de Node.js Cuando pasas un objeto `FormData` de Node.js que expone `getHeaders()` (como el paquete [`form-data`](https://github.com/form-data/form-data)), axios copia por defecto todos los encabezados que devuelve a la solicitud. Esto preserva la compatibilidad con v1, pero puede ser problemático cuando el objeto `FormData` proviene de una fuente no confiable — `getHeaders()` podría sobrescribir encabezados como `Authorization` o inyectar encabezados arbitrarios. Establece `formDataHeaderPolicy: 'content-only'` para copiar **únicamente** `Content-Type` y `Content-Length` desde `getHeaders()`, y luego define cualquier otro encabezado explícitamente a través de la configuración `headers` de la solicitud: ```js await axios.post("https://example.com/upload", form, { formDataHeaderPolicy: "content-only", headers: { Authorization: "Bearer my-token", }, }); ``` El valor predeterminado es `'legacy'`. Consulta [`formDataHeaderPolicy`](/pages/advanced/request-config#formdataheaderpolicy) en la referencia de configuración de solicitud para más detalles. ## Terminaciones admitidas El serializador de FormData de Axios admite algunas terminaciones especiales para realizar las siguientes operaciones: - `{}` - serializa el valor con JSON.stringify - `[]` - desenvuelve el objeto tipo arreglo como campos separados con la misma clave ::: warning Nota: la operación de desenvolvimiento/expansión se usará de forma predeterminada en arreglos y objetos FileList. ::: ## Configurar el serializador de FormData El serializador de FormData admite opciones adicionales a través de la propiedad de objeto `config.formSerializer` para manejar casos especiales: - `visitor: Function` - función de visitante definida por el usuario que se llamará de forma recursiva para serializar el objeto de datos a un objeto FormData siguiendo reglas personalizadas. - `dots: boolean = false` - usa notación de punto en lugar de corchetes para serializar arreglos y objetos; - `metaTokens: boolean = true` - añade la terminación especial (por ejemplo, `user{}: '{"name": "John"}'`) en la clave de FormData. El analizador de cuerpo del backend podría usar esta meta-información para analizar automáticamente el valor como JSON. - `indexes: null|false|true = false` - controla cómo se añadirán los índices a las claves desenvueltas de objetos planos tipo arreglo: - `null` - no añadir corchetes (`arr: 1`, `arr: 2`, `arr: 3`) - `false` (predeterminado) - añadir corchetes vacíos (`arr[]: 1`, `arr[]: 2`, `arr[]: 3`) - `true` - añadir corchetes con índices (`arr[0]: 1`, `arr[1]: 2`, `arr[2]: 3`) - `maxDepth: number = 100` - profundidad máxima de anidación de objetos en la que el serializador recursará. Si la entrada excede esta profundidad, se lanza un `AxiosError` con `code: 'ERR_FORM_DATA_DEPTH_EXCEEDED'`. Esto protege las aplicaciones del lado del servidor contra ataques DoS mediante cargas útiles profundamente anidadas. Establece en `Infinity` para desactivar el límite. ```js // Aumentar el límite para esquemas que legítimamente exceden 100 niveles: axios.postForm('/api', data, { formSerializer: { maxDepth: 200 } }); ``` ::: warning Nota de seguridad El límite predeterminado de 100 es intencional. El código del lado del servidor que reenvía JSON controlado por el cliente a axios como `data` es vulnerable a un desbordamiento de pila de llamadas sin esta protección. Solo aumenta `maxDepth` si tu esquema realmente lo requiere. ::: Por ejemplo, si tenemos un objeto como este: ```js const obj = { x: 1, arr: [1, 2, 3], arr2: [1, [2], 3], users: [ { name: 'Peter', surname: 'Griffin' }, { name: 'Thomas', surname: 'Anderson' }, ], 'obj2{}': [{ x: 1 }], }; ``` El serializador de Axios ejecutará internamente los siguientes pasos: ```js const formData = new FormData(); formData.append('x', '1'); formData.append('arr[]', '1'); formData.append('arr[]', '2'); formData.append('arr[]', '3'); formData.append('arr2[0]', '1'); formData.append('arr2[1][0]', '2'); formData.append('arr2[2]', '3'); formData.append('users[0][name]', 'Peter'); formData.append('users[0][surname]', 'Griffin'); formData.append('users[1][name]', 'Thomas'); formData.append('users[1][surname]', 'Anderson'); formData.append('obj2{}', '[{"x":1}]'); ``` Axios admite los siguientes métodos abreviados: `postForm`, `putForm`, `patchForm`, que son simplemente los métodos HTTP correspondientes con el encabezado `Content-Type` preestablecido en `multipart/form-data`. axios-axios-2d06f96/docs/es/pages/advanced/progress-capturing.md000066400000000000000000000037111521272452000247050ustar00rootroot00000000000000# Captura de progreso Axios admite la captura del progreso de carga y descarga en entornos de navegador y Node.js. La frecuencia de los eventos de progreso está limitada a 3 veces por segundo para evitar saturar el navegador con eventos de progreso. A continuación se muestra un ejemplo de cómo capturar eventos de progreso: ```js await axios.post(url, data, { onUploadProgress: function (axiosProgressEvent) { /*{ loaded: number; total?: number; progress?: number; // in range [0..1] bytes: number; // how many bytes have been transferred since the last trigger (delta) estimated?: number; // estimated time in seconds rate?: number; // upload speed in bytes upload: true; // upload sign }*/ }, onDownloadProgress: function (axiosProgressEvent) { /*{ loaded: number; total?: number; progress?: number; bytes: number; estimated?: number; rate?: number; // download speed in bytes download: true; // download sign }*/ }, }); ``` También puedes transmitir los eventos de progreso de carga y descarga a un stream legible en Node.js. Esto es útil cuando deseas mostrar el progreso de una forma personalizada. A continuación se muestra un ejemplo de cómo transmitir eventos de progreso: ```js const { data } = await axios.post(SERVER_URL, readableStream, { onUploadProgress: ({ progress }) => { console.log((progress * 100).toFixed(2)); }, headers: { "Content-Length": contentLength, }, maxRedirects: 0, // avoid buffering the entire stream }); ``` ::: warning La captura del progreso de carga de FormData no está disponible actualmente en entornos Node.js. ::: ::: danger Se recomienda deshabilitar las redirecciones estableciendo `maxRedirects: 0` para subir el stream en el entorno Node.js, ya que el paquete `follow-redirects` almacenará todo el stream en memoria RAM sin seguir el algoritmo de "backpressure". ::: axios-axios-2d06f96/docs/es/pages/advanced/promises.md000066400000000000000000000043641521272452000227150ustar00rootroot00000000000000# Promises axios está construido sobre la API nativa de Promise de ES6. Cada solicitud de axios devuelve una Promise que se resuelve en un objeto de respuesta o se rechaza con un error. Si tu entorno no admite Promises de ES6, necesitarás añadir un polyfill — por ejemplo con [es6-promise](https://github.com/stefanpenner/es6-promise). ## then / catch / finally Dado que axios devuelve una Promise estándar, puedes usar `.then()`, `.catch()` y `.finally()` para manejar el resultado: ```js axios.get("/api/users") .then((response) => { console.log(response.data); }) .catch((error) => { console.error("Request failed:", error.message); }) .finally(() => { console.log("Request finished"); }); ``` ## async / await El enfoque recomendado para la mayoría de las bases de código es `async/await`, que hace que el código asíncrono se lea como código síncrono: ```js async function fetchUser(id) { try { const response = await axios.get(`/api/users/${id}`); return response.data; } catch (error) { console.error("Failed to fetch user:", error.message); throw error; } } ``` ## Solicitudes en paralelo Dado que axios devuelve una Promise estándar, puedes usar `Promise.all` para hacer múltiples solicitudes al mismo tiempo y esperar a que todas se completen: ```js const [users, posts] = await Promise.all([ axios.get("/api/users"), axios.get("/api/posts"), ]); console.log(users.data, posts.data); ``` ::: tip `Promise.all` se rechazará tan pronto como cualquiera de las solicitudes falle. Si deseas manejar fallos parciales, usa `Promise.allSettled` en su lugar. ::: ```js const results = await Promise.allSettled([ axios.get("/api/users"), axios.get("/api/posts"), ]); results.forEach((result) => { if (result.status === "fulfilled") { console.log(result.value.data); } else { console.error("Request failed:", result.reason.message); } }); ``` ## Encadenar solicitudes Puedes encadenar llamadas `.then()` para ejecutar solicitudes secuencialmente, pasando datos de una a la siguiente: ```js axios.get("/api/user/1") .then(({ data: user }) => axios.get(`/api/posts?userId=${user.id}`)) .then(({ data: posts }) => { console.log("Posts for user:", posts); }) .catch(console.error); ``` axios-axios-2d06f96/docs/es/pages/advanced/rate-limiting.md000066400000000000000000000043031521272452000236120ustar00rootroot00000000000000# Limitación de velocidad axios admite la limitación del ancho de banda en el entorno Node.js a través del adaptador HTTP. Esto te permite controlar la velocidad de carga o descarga de datos, lo que es útil para operaciones masivas, trabajos en segundo plano o scraping educado que no debe saturar una conexión. ## `maxRate` La opción `maxRate` acepta un número (bytes por segundo) o un arreglo donde el primer valor es el límite de carga y el segundo es el límite de descarga. Usa `[uploadRate]` para limitar solo la carga, o `[uploadRate, downloadRate]` para limitar ambas direcciones. Cuando se pasa un número único, el mismo límite se aplica tanto a la carga como a la descarga. ```js // Limit both upload and download to 100 KB/s await axios.get(URL, { maxRate: 100 * 1024 }); // Limit upload to 100 KB/s, download to 500 KB/s await axios.get(URL, { maxRate: [100 * 1024, 500 * 1024] }); ``` ::: warning `maxRate` solo es compatible con el adaptador HTTP de Node.js. No tiene efecto en entornos de navegador. ::: ## Limitación de velocidad de carga Limita la velocidad de carga y registra el progreso al mismo tiempo: ```js const { data } = await axios.post(SERVER_URL, myBuffer, { onUploadProgress: ({ progress, rate }) => { const percent = (progress * 100).toFixed(1); const kbps = (rate / 1024).toFixed(1); console.log(`Upload [${percent}%] at ${kbps} KB/s`); }, maxRate: [100 * 1024], // cap upload at 100 KB/s }); ``` ## Limitación de velocidad de descarga Limita la velocidad de descarga para respuestas de gran tamaño: ```js const { data } = await axios.get(FILE_URL, { onDownloadProgress: ({ progress, rate }) => { const percent = (progress * 100).toFixed(1); const kbps = (rate / 1024).toFixed(1); console.log(`Download [${percent}%] at ${kbps} KB/s`); }, maxRate: [Infinity, 200 * 1024], // no upload limit, 200 KB/s download limit responseType: "arraybuffer", }); ``` ## Limitación combinada de carga y descarga Pasa ambos límites como un arreglo para controlar ambas direcciones simultáneamente: ```js await axios.post(SERVER_URL, largeBuffer, { maxRate: [50 * 1024, 500 * 1024], // 50 KB/s up, 500 KB/s down }); ``` axios-axios-2d06f96/docs/es/pages/advanced/request-config.md000066400000000000000000000701161521272452000240050ustar00rootroot00000000000000# Configuración de solicitud La configuración de solicitud se usa para configurar la solicitud. Existe una amplia gama de opciones disponibles, pero la única opción requerida es `url`. Si el objeto de configuración no contiene un campo `method`, el método predeterminado es `GET`. ::: warning Seguridad: la protección contra bombas de descompresión es opcional Por defecto, `maxContentLength` y `maxBodyLength` están en `-1` (sin límite). Un servidor malicioso o comprometido puede devolver un cuerpo pequeño comprimido con gzip/deflate/brotli/zstd que se expande a gigabytes y agota el proceso de Node.js. Si haces solicitudes a servidores en los que no confías plenamente, **establece un tope**: ```js axios.defaults.maxContentLength = 10 * 1024 * 1024; // 10 MB axios.defaults.maxBodyLength = 10 * 1024 * 1024; ``` Consulta la [guía de seguridad](/pages/misc/security) para más detalles. ::: ### `url` La `url` es la URL a la que se realiza la solicitud. Puede ser una cadena de texto o una instancia de `URL`. ### `method` El `method` es el método HTTP a usar para la solicitud. El método predeterminado es `GET`. ### `baseURL` La `baseURL` es la URL base que se antepondrá a la `url` a menos que la `url` sea una URL absoluta. Es útil para hacer solicitudes al mismo dominio sin tener que repetir el nombre de dominio, ni ningún prefijo de API o versión. ### `allowAbsoluteUrls` `allowAbsoluteUrls` determina si las URLs absolutas sobrescribirán un `baseUrl` configurado. Cuando se establece en `true` (valor predeterminado), los valores absolutos para `url` sobrescribirán `baseUrl`. Cuando se establece en `false`, los valores absolutos para `url` siempre serán antepuestos por `baseUrl`. ### `transformRequest` La función `transformRequest` te permite modificar los datos de la solicitud antes de enviarlos al servidor. Esta función se llama con los datos de la solicitud como único argumento. Solo aplica para los métodos de solicitud `PUT`, `POST`, `PATCH` y `DELETE`. La última función del arreglo debe devolver una cadena de texto o una instancia de Buffer, ArrayBuffer, FormData o Stream. ### `transformResponse` La función `transformResponse` te permite modificar los datos de la respuesta antes de que sean pasados a las funciones `then` o `catch`. Esta función se llama con los datos de la respuesta como único argumento. ### `parseReviver` La función `parseReviver` te permite proporcionar una función "reviver" personalizada directamente a la llamada nativa `JSON.parse()` que utiliza el `transformResponse` predeterminado. Esto resulta especialmente útil para realizar hidratación de tipos de alto rendimiento (por ejemplo, convertir cadenas ISO a objetos `Temporal` o `Date`) o para evitar la pérdida de precisión durante el parseo. En entornos modernos (ES2023+), la función reviver recibe un tercer argumento `context`. Esto proporciona acceso a la fuente JSON cruda (`source`), permitiendo la conversión precisa de enteros grandes (BigInt) que de otro modo perderían precisión al ser parseados como números estándar de JavaScript. > Nota: `Temporal` aún no está disponible en todos los entornos. Considera usar un polyfill si es necesario. ```js const client = axios.create({ parseReviver: (key, value, context) => { // Ejemplo: parseo de BigInt seguro en precisión if (typeof value === 'number' && context?.source) { const isInteger = Number.isInteger(value); const isUnsafe = !Number.isSafeInteger(value); const isValidIntegerString = /^-?\d+$/.test(context.source); if (isInteger && isUnsafe && isValidIntegerString) { try { return BigInt(context.source); } catch { // Alternativa: devolver el valor original si el parseo falla } } } // Ejemplo: hidratar fechas en objetos Temporal if ( typeof value === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(value) && typeof Temporal !== 'undefined' && Temporal?.PlainDate ) { return Temporal.PlainDate.from(value); } return value; }, }); ``` ### `headers` Los `headers` son los encabezados HTTP que se enviarán con la solicitud. El encabezado `Content-Type` se establece en `application/json` de forma predeterminada. ### `params` Los `params` son los parámetros de URL que se enviarán con la solicitud. Debe ser un objeto plano o un objeto URLSearchParams. Si la `url` contiene parámetros de consulta, se combinarán con el objeto `params`. ### `paramsSerializer` La función `paramsSerializer` te permite serializar el objeto `params` antes de enviarlo al servidor. Hay varias opciones disponibles para esta función; consulta el ejemplo completo de configuración de solicitud al final de esta página. #### Codificación porcentual estricta RFC 3986 De forma predeterminada, axios decodifica `%3A`, `%24`, `%2C` y `%20` de vuelta a `:`, `$`, `,` y `+` por legibilidad (el `+` sigue la convención `application/x-www-form-urlencoded` para representar un espacio en una cadena de consulta). Estos caracteres son válidos dentro de un componente de consulta según la [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.4), por lo que la salida predeterminada es correcta. Sin embargo, algunos backends requieren codificación porcentual estricta y rechazan la forma legible. Usa la opción `encode` para sobrescribir el codificador predeterminado: ```js // Por solicitud: emitir codificación porcentual estricta RFC 3986 para los valores de consulta axios.get('/foo', { params: { filter: JSON.stringify({ startedAt: '2026-01-23' }) }, paramsSerializer: { encode: encodeURIComponent } }); // O establecerlo en los valores predeterminados de la instancia const client = axios.create({ paramsSerializer: { encode: encodeURIComponent } }); ``` ### `data` El `data` son los datos que se enviarán como cuerpo de la solicitud. Puede ser una cadena de texto, un objeto plano, un Buffer, ArrayBuffer, FormData, Stream o URLSearchParams. Solo aplica para los métodos de solicitud `PUT`, `POST`, `DELETE` y `PATCH`. Cuando no se establece `transformRequest`, debe ser de uno de los siguientes tipos: - cadena de texto, objeto plano, ArrayBuffer, ArrayBufferView, URLSearchParams - Solo en el navegador: FormData, File, Blob - React Native: FormData - Solo en Node.js: Stream, Buffer, FormData (paquete form-data) Para `FormData` en navegador, web worker y React Native, no establezcas manualmente `Content-Type`; el entorno agrega el boundary multipart. Para los objetos `FormData` de Node.js que proporcionan un método `getHeaders()`, axios copia por defecto todos los encabezados devueltos para mantener la compatibilidad con v1. Si el objeto `FormData` es personalizado o no es de plena confianza, establece `formDataHeaderPolicy: 'content-only'` para copiar únicamente `Content-Type` y `Content-Length`, y define cualquier otro encabezado de la solicitud explícitamente mediante la configuración `headers`. ### `formDataHeaderPolicy` Controla cómo axios copia los encabezados devueltos por `FormData#getHeaders()` de Node.js. El valor por defecto es `'legacy'`, que copia todos los encabezados devueltos para preservar el comportamiento existente de v1. Establece `'content-only'` para copiar únicamente `Content-Type` y `Content-Length` desde `getHeaders()`. ### `timeout` El `timeout` es el número de milisegundos antes de que la solicitud expire. Si la solicitud tarda más que `timeout`, se abortará. ### `withCredentials` La propiedad `withCredentials` indica si las solicitudes de Access-Control entre sitios deben hacerse usando credenciales como cookies, encabezados de autorización o certificados de cliente TLS. Establecer `withCredentials` no tiene efecto en solicitudes del mismo sitio. ### `adapter` `adapter` permite el manejo personalizado de solicitudes, lo que facilita las pruebas. Devuelve una Promise y proporciona una respuesta válida; consulta los [adaptadores](/pages/advanced/adapters) para más información. También proporcionamos una serie de adaptadores integrados. El adaptador predeterminado es `http` para Node.js y `xhr` para navegadores. La lista completa de adaptadores integrados es la siguiente: - fetch - http - xhr También puedes pasar un arreglo de adaptadores. axios usará el primero que sea compatible con el entorno. ### `auth` `auth` indica que se debe usar autenticación HTTP Basic y proporciona las credenciales. Esto establecerá un encabezado `Authorization`, sobrescribiendo cualquier encabezado `Authorization` personalizado que hayas definido usando `headers`. Si `auth` se omite, los adaptadores HTTP de Node.js y fetch pueden obtener credenciales Basic desde la URL de la solicitud, por ejemplo `https://user:pass@example.com`; las credenciales codificadas con porcentaje en la URL se decodifican, y `auth` siempre tiene prioridad sobre las credenciales incluidas en la URL. En el adaptador HTTP de Node.js, la autenticación Basic se conserva en redirecciones del mismo origen y se elimina en redirecciones de origen cruzado. Ten en cuenta que solo la autenticación HTTP Basic es configurable a través de este parámetro. Para tokens Bearer y similares, usa encabezados `Authorization` personalizados. ### `responseType` El `responseType` indica el tipo de datos con el que el servidor responderá. Puede ser uno de los siguientes: - arraybuffer - document - json - text - stream - blob (solo en el navegador) - formdata (solo con el adaptador fetch) ### `responseEncoding` El `responseEncoding` indica la codificación a usar para decodificar las respuestas. Se admiten las siguientes opciones: - ascii - ASCII - ansi - ANSI - binary - BINARY - base64 - BASE64 - base64url - BASE64URL - hex - HEX - latin1 - LATIN1 - ucs-2 - UCS-2 - ucs2 - UCS2 - utf-8 - UTF-8 - utf8 - UTF8 - utf16le - UTF16LE ::: tip Nota: Se ignora para `responseType` de tipo `stream` o solicitudes del lado del cliente. ::: ### `xsrfCookieName` `xsrfCookieName` es el nombre de la cookie que se usará como valor para el token `XSRF`. ### `xsrfHeaderName` `xsrfHeaderName` es el nombre del encabezado que se usará como valor para el token `XSRF`. ### `withXSRFToken` `withXSRFToken` controla si axios lee la cookie XSRF y establece el encabezado XSRF en las solicitudes del navegador. Acepta: - `undefined` _(predeterminado)_ — establece el encabezado XSRF solo para solicitudes del mismo origen. - `true` — siempre establece el encabezado XSRF, incluso para solicitudes de origen cruzado. - `false` — nunca establece el encabezado XSRF. - `(config: InternalAxiosRequestConfig) => boolean | undefined` — un callback que decide por solicitud, recibiendo el objeto de configuración interna. ```ts withXSRFToken: boolean | undefined | ((config: InternalAxiosRequestConfig) => boolean | undefined); ``` ::: warning XSRF de origen cruzado y `withCredentials` `withCredentials` controla si las solicitudes de origen cruzado incluyen credenciales (cookies, autenticación HTTP). En versiones anteriores de axios, establecer `withCredentials: true` provocaba implícitamente que axios estableciera el encabezado XSRF para solicitudes de origen cruzado. Las versiones más recientes de axios separan estas responsabilidades: para permitir que el encabezado XSRF se envíe en solicitudes de origen cruzado debes establecer **ambos** `withCredentials: true` y `withXSRFToken: true`. ```js axios.get('/user', { withCredentials: true, withXSRFToken: true }); ``` ::: ### `onUploadProgress` La función `onUploadProgress` te permite escuchar el progreso de una carga. ### `onDownloadProgress` La función `onDownloadProgress` te permite escuchar el progreso de una descarga. ### `maxContentLength` La propiedad `maxContentLength` define el tamaño máximo de la respuesta en bytes. El adaptador HTTP de Node.js lo aplica en respuestas almacenadas en búfer y en streaming. El adaptador fetch lo aplica cuando la longitud de la respuesta está declarada, se puede rastrear el stream de respuesta o se puede determinar el tamaño de la respuesta. > ⚠️ **Seguridad:** el valor por defecto es `-1` (sin límite). Las respuestas sin límite combinadas con la descompresión gzip/deflate/brotli/zstd permiten ataques de denegación de servicio por bomba de descompresión. > Establece un límite explícito al consumir servidores en los que no confíes plenamente. ### `maxBodyLength` La propiedad `maxBodyLength` define el tamaño máximo del cuerpo de la solicitud en bytes. El adaptador HTTP de Node.js lo aplica, y el adaptador fetch lo aplica cuando se puede determinar la longitud del cuerpo de la solicitud. ### `redact` La propiedad `redact` es un arreglo opcional de nombres de claves de configuración que se enmascararán cuando un `AxiosError` se serialice con `toJSON()`. La coincidencia es insensible a mayúsculas/minúsculas y recursiva a lo largo de la configuración de la solicitud serializada. Los valores coincidentes se reemplazan por `[REDACTED ****]`. `redact` solo afecta a la serialización del error. No modifica los datos de la solicitud, los encabezados ni el objeto de configuración original. ```js axios.get('/user/12345', { headers: { Authorization: 'Bearer token' }, auth: { username: 'me', password: 'secret' }, redact: ['authorization', 'password'] }).catch((error) => { console.log(error.toJSON().config); }); ``` ### `validateStatus` La función `validateStatus` te permite sobreescribir la validación predeterminada del código de estado. Por defecto, axios rechazará la Promise si el código de estado no está en el rango 200-299. Puedes sobreescribir este comportamiento proporcionando una función `validateStatus` personalizada. La función debe devolver `true` si el código de estado está dentro del rango que deseas aceptar. ### `maxRedirects` La propiedad `maxRedirects` define el número máximo de redirecciones a seguir. Si se establece en 0, no se seguirá ninguna redirección. ### `beforeRedirect` La función `beforeRedirect` te permite modificar la solicitud antes de que sea redirigida. Úsala para ajustar las opciones de la solicitud al redirigir, para inspeccionar los últimos encabezados de respuesta, o para cancelar la solicitud lanzando un error. Si `maxRedirects` se establece en 0, `beforeRedirect` no se usa. ```js beforeRedirect: (options, { headers }) => { if ( options.hostname === "example.com" && options.protocol === "https:" ) { options.auth = "user:password"; } } ``` ::: warning Seguridad: reinyección de credenciales en redirecciones El hook `beforeRedirect` se ejecuta **después** de que se eliminan los encabezados sensibles durante las redirecciones. La librería `follow-redirects` elimina las credenciales en una bajada de protocolo (HTTPS → HTTP) por seguridad. Como `beforeRedirect` se ejecuta después, reinyectar credenciales sin verificar el protocolo de destino puede exponer datos sensibles. Reinyecta credenciales únicamente para destinos HTTPS de confianza, y evita reinyectarlas en redirecciones con bajada de protocolo. ::: ### `socketPath` La propiedad `socketPath` define un socket UNIX que se usará en lugar de una conexión TCP. Por ejemplo, `/var/run/docker.sock` para enviar solicitudes al daemon de Docker. Solo se puede especificar `socketPath` o `proxy`. Si ambos se especifican, se usa `socketPath`. :::warning Seguridad Cuando se establece `socketPath`, el hostname y el puerto de la URL se ignoran y axios se comunica directamente con el socket Unix indicado. Si cualquier parte de la configuración de la solicitud proviene de entrada del usuario (por ejemplo, en un proxy o manejador de webhooks que reenvía opciones), un atacante puede inyectar `socketPath` para redirigir el tráfico a sockets locales privilegiados como `/var/run/docker.sock`, `/run/containerd/containerd.sock` o `/run/systemd/private`, eludiendo por completo las protecciones SSRF basadas en hostname (CWE-918). Filtra la configuración recibida desde entradas no confiables y/o restringe las rutas de socket aceptadas con `allowedSocketPaths` (ver más abajo). ::: ### `allowedSocketPaths` Restringe qué rutas de socket pueden usarse a través de `socketPath`. Acepta un string o un array de strings. Cuando está definido, axios resuelve el `socketPath` y lo compara con cada entrada (también resuelta); la solicitud se rechaza con un `AxiosError` de código `ERR_BAD_OPTION_VALUE` si no hay coincidencia. Si no se define (valor por defecto), `socketPath` se comporta igual que antes. ```js const client = axios.create({ allowedSocketPaths: ['/var/run/docker.sock'] }); // permitido await client.get('http://localhost/v1.45/info', { socketPath: '/var/run/docker.sock' }); // rechazado — no está en la lista await client.get('http://localhost/pods', { socketPath: '/var/run/kubelet.sock' }); ``` Un array vacío (`allowedSocketPaths: []`) bloquea todas las rutas de socket. ### `transport` La propiedad `transport` define el transporte a usar para la solicitud. Es útil para hacer solicitudes sobre un protocolo diferente, como `http2`. ### `httpAgent` y `httpsAgent` `httpAgent` y `httpsAgent` definen un agente personalizado para usar al realizar solicitudes http y https respectivamente en Node.js. Esto permite añadir opciones como `keepAlive` que no están habilitadas por defecto. ### `proxy` `proxy` define el nombre de host, puerto y protocolo del servidor proxy que deseas usar. También puedes definir tu proxy usando las variables de entorno convencionales `http_proxy` y `https_proxy`. Si usas variables de entorno para tu configuración de proxy, también puedes definir una variable de entorno `no_proxy` como una lista separada por comas de dominios que no deben ser enviados a través del proxy. Usa `false` para deshabilitar los proxies, ignorando las variables de entorno. `auth` indica que se debe usar autenticación HTTP Basic para conectarse al proxy, y proporciona las credenciales. Esto establecerá un encabezado `Proxy-Authorization`, sobrescribiendo cualquier encabezado `Proxy-Authorization` personalizado que hayas definido usando `headers`. Si el servidor proxy usa HTTPS, debes establecer el protocolo en `https`. Un encabezado `Host` proporcionado por el usuario en `headers` se preserva al reenviar a través de un proxy (coincidencia insensible a mayúsculas en `host` / `Host` / `HOST`). Esto te permite apuntar a un host virtual distinto al de la URL de la solicitud — por ejemplo, llegar a `127.0.0.1:4000` mientras el proxy trata la solicitud como `example.com`. Si no se proporciona ningún encabezado `Host`, axios lo establece por defecto al `hostname:port` de la URL de la solicitud, como antes. Para destinos `https://`, axios establece un túnel CONNECT a través del proxy y realiza TLS de extremo a extremo con el origen. `Proxy-Authorization` se envía solo en la solicitud CONNECT, nunca en la solicitud TLS encapsulada. Las opciones TLS de `httpsAgent`, como `ca`, `cert`, `key` y `rejectUnauthorized`, se reenvían al agente de túnel generado para que sigan aplicándose a la conexión TLS con el origen. Si proporcionas un `HttpsProxyAgent`, axios deja el túnel a cargo de ese agente. ```js proxy: { protocol: "https", host: "127.0.0.1", hostname: "localhost", // Takes precedence over "host" if both are defined port: 9000, auth: { username: "mikeymike", password: "rapunz3l" } }, ``` ### `cancelToken` La propiedad `cancelToken` te permite crear un token de cancelación que puede usarse para cancelar la solicitud. Para más información, consulta la documentación de [cancelación](/pages/advanced/cancellation). ### `signal` La propiedad `signal` te permite pasar una instancia de `AbortSignal` a la solicitud. Esto te permite cancelar la solicitud usando la API `AbortController`. ### `decompress` La propiedad `decompress` indica si los datos de la respuesta deben descomprimirse automáticamente. El valor predeterminado es `true`. El adaptador HTTP de Node.js admite gzip, deflate, brotli y zstd cuando el runtime actual de Node.js proporciona el descompresor zlib correspondiente. ### `insecureHTTPParser` Indica si se debe usar un parser HTTP inseguro que acepta encabezados HTTP inválidos. Esto puede permitir la interoperabilidad con implementaciones HTTP no conformes. Se debe evitar el uso del parser inseguro. Ten en cuenta que la opción `insecureHTTPParser` solo está disponible en Node.js 12.10.0 y versiones posteriores. Consulta la [documentación de Node.js](https://nodejs.org/en/blog/vulnerability/february-2020-security-releases/#strict-http-header-parsing-none) para más información. Consulta el conjunto completo de opciones [aquí](https://nodejs.org/dist/latest-v12.x/docs/api/http.html#http_http_request_url_options_callback). ### `transitional` La propiedad `transitional` te permite habilitar o deshabilitar ciertas características de transición. Las siguientes opciones están disponibles: - `silentJSONParsing`: Si se establece en `true` _(predeterminado)_, axios ignora silenciosamente los errores de parseo de JSON y establece `response.data` en `null` cuando el parseo falla. Establécelo en `false` para que se lance `SyntaxError` en su lugar. ::: tip Importante Esta opción solo tiene efecto cuando `responseType` se establece **explícitamente** en `'json'`. Cuando `responseType` se omite, axios usa `forcedJSONParsing` para intentar el parseo de JSON y devuelve silenciosamente la cadena cruda en caso de fallo, sin importar este ajuste. Para hacer que el JSON inválido lance un error, establece ambos: ```js { responseType: 'json', transitional: { silentJSONParsing: false } } ``` ::: - `forcedJSONParsing`: Fuerza a axios a analizar la cadena de respuesta como JSON incluso si `responseType` no es `'json'`. - `clarifyTimeoutError`: Clarifica el mensaje de error cuando una solicitud expira. Es útil cuando depuras problemas de timeout. - `advertiseZstdAcceptEncoding`: Cuando se establece en `true`, axios añade `zstd` al encabezado `Accept-Encoding` predeterminado cuando el runtime actual de Node.js soporta descompresión zstd. Las respuestas zstd se descomprimen automáticamente cuando son compatibles y `decompress` es `true`. - `legacyInterceptorReqResOrdering`: Cuando se establece en `true`, se usará el orden de solicitud/respuesta de interceptores heredado. ### `env` La propiedad `env` te permite establecer algunas opciones de configuración. Por ejemplo, la clase FormData que se usa para serializar automáticamente el payload en un objeto FormData. - FormData: window?.FormData || global?.FormData ### `formSerializer` La opción `formSerializer` te permite configurar cómo se serializan los objetos planos a `multipart/form-data` cuando se usan como `data` de solicitud. Opciones disponibles: - `visitor` — función visitante personalizada llamada recursivamente para cada valor - `dots` — usar notación de punto en lugar de notación de corchetes - `metaTokens` — preservar terminaciones especiales de clave como `{}` - `indexes` — controlar el formato de corchetes para claves de arreglo (`null` / `false` / `true`) - `maxDepth` _(predeterminado: `100`)_ — profundidad máxima de anidación antes de lanzar un `AxiosError` con código `ERR_FORM_DATA_DEPTH_EXCEEDED`. Establece en `Infinity` para desactivar. Consulta la página [multipart/form-data](/pages/advanced/multipart-form-data-format) para todos los detalles, y el ejemplo completo de configuración de solicitud al final de esta página. ### `maxRate` La propiedad `maxRate` define el **ancho de banda** máximo (en bytes por segundo) para la carga y/o descarga. Acepta un número único (aplicado a ambas direcciones) o un arreglo de dos elementos `[uploadRate, downloadRate]` donde cada elemento es un límite en bytes por segundo. Por ejemplo, `100 * 1024` significa 100 KB/s. Consulta [Limitación de velocidad](/pages/advanced/rate-limiting) para ver ejemplos. ## Ejemplo completo de configuración de solicitud ```js { url: "/posts", method: "get", baseURL: "https://jsonplaceholder.typicode.com", allowAbsoluteUrls: true, transformRequest: [function (data, headers) { return data; }], transformResponse: [function (data) { return data; }], headers: {"X-Requested-With": "XMLHttpRequest"}, params: { postId: 5 }, paramsSerializer: { // Custom encoder function which sends key/value pairs in an iterative fashion. encode?: (param: string): string => { /* Do custom operations here and return transformed string */ }, // Custom serializer function for the entire parameter. Allows user to mimic pre 1.x behaviour. serialize?: (params: Record, options?: ParamsSerializerOptions ), // Configuration for formatting array indexes in the params. // Three available options: // (1) indexes: null (leads to no brackets) // (2) (default) indexes: false (leads to empty brackets) // (3) indexes: true (leads to brackets with indexes). indexes: false, // Profundidad máxima de anidación de objetos al serializar params. Lanza AxiosError // (ERR_FORM_DATA_DEPTH_EXCEEDED) si se excede. Predeterminado: 100. Establecer en Infinity para desactivar. maxDepth: 100 }, data: { firstName: "Fred" }, formDataHeaderPolicy: "legacy", // Syntax alternative to send data into the body method post only the value is sent, not the key data: "Country=Brasil&City=Belo Horizonte", timeout: 1000, withCredentials: false, adapter: function (config) { // Do whatever you want }, adapter: "xhr", auth: { username: "janedoe", password: "s00pers3cret" }, responseType: "json", responseEncoding: "utf8", xsrfCookieName: "XSRF-TOKEN", xsrfHeaderName: "X-XSRF-TOKEN", withXSRFToken: boolean | undefined | ((config: InternalAxiosRequestConfig) => boolean | undefined), onUploadProgress: function ({loaded, total, progress, bytes, estimated, rate, upload = true}) { // Do whatever you want with the Axios progress event }, onDownloadProgress: function ({loaded, total, progress, bytes, estimated, rate, download = true}) { // Do whatever you want with the Axios progress event }, maxContentLength: 2000, maxBodyLength: 2000, redact: ['authorization', 'password'], validateStatus: function (status) { return status >= 200 && status < 300; }, maxRedirects: 21, beforeRedirect: (options, { headers }) => { if (options.hostname === "typicode.com") { options.auth = "user:password"; } }, socketPath: null, allowedSocketPaths: null, transport: undefined, httpAgent: new http.Agent({ keepAlive: true }), httpsAgent: new https.Agent({ keepAlive: true }), proxy: { protocol: "https", host: "127.0.0.1", // hostname: "127.0.0.1" // Takes precedence over "host" if both are defined port: 9000, auth: { username: "mikeymike", password: "rapunz3l" } }, cancelToken: new CancelToken(function (cancel) { cancel("Operation has been canceled."); }), signal: new AbortController().signal, decompress: true, insecureHTTPParser: undefined, transitional: { silentJSONParsing: true, forcedJSONParsing: true, clarifyTimeoutError: false, advertiseZstdAcceptEncoding: false, legacyInterceptorReqResOrdering: true, }, env: { FormData: window?.FormData || global?.FormData }, formSerializer: { // Custom visitor function to serialize form values visitor: (value, key, path, helpers) => {}; // Use dots instead of brackets format dots: boolean; // Keep special endings like {} in parameter key metaTokens: boolean; // Usar formato de índices de arreglo: // null - sin corchetes // false - corchetes vacíos // true - corchetes con índices indexes: boolean; // Profundidad máxima de anidación de objetos. Lanza AxiosError (ERR_FORM_DATA_DEPTH_EXCEEDED) // si se excede. Predeterminado: 100. Establecer en Infinity para desactivar. maxDepth: 100; }, maxRate: [ 100 * 1024, // 100KB/s upload limit, 100 * 1024 // 100KB/s download limit ] } ``` axios-axios-2d06f96/docs/es/pages/advanced/request-method-aliases.md000066400000000000000000000151011521272452000254300ustar00rootroot00000000000000# Alias de solicitud axios proporciona un conjunto de alias para realizar solicitudes HTTP. Estos alias son atajos para hacer solicitudes usando el método `request`. Están diseñados para ser fáciles de usar y ofrecer una forma más conveniente de hacer solicitudes. axios se esfuerza por seguir las RFC 7231 y RFC 5789 de la manera más fiel posible. Los alias están diseñados para ser consistentes con los métodos HTTP definidos en dichas RFC. ### `axios` axios puede usarse para hacer una solicitud HTTP pasando únicamente el objeto de configuración. El objeto de configuración completo está documentado [aquí](/pages/advanced/request-config). ```ts axios(url: string | AxiosRequestConfig, config?: AxiosRequestConfig); ``` ## Alias de método Los siguientes alias están disponibles para hacer solicitudes: ### `request` El método `request` es el método principal que usarás para hacer solicitudes HTTP. Acepta un objeto de configuración como argumento y devuelve una Promise que se resuelve en el objeto de respuesta. Es un método genérico que puede usarse para cualquier tipo de solicitud HTTP. ```ts axios.request(config: AxiosRequestConfig): AxiosResponse; ``` ### `get` El método `get` se usa para hacer una solicitud GET. Acepta una URL y un objeto de configuración opcional como argumentos, y devuelve una Promise que se resuelve en el objeto de respuesta. ```ts axios.get(url: string, config?: AxiosRequestConfig): AxiosResponse; ``` ### `delete` El método `delete` se usa para hacer una solicitud DELETE. Acepta una URL y un objeto de configuración opcional como argumentos, y devuelve una Promise que se resuelve en el objeto de respuesta. ```ts axios.delete(url: string, config?: AxiosRequestConfig): AxiosResponse; ``` ### `head` El método `head` se usa para hacer una solicitud HEAD. Acepta una URL y un objeto de configuración opcional como argumentos, y devuelve una Promise que se resuelve en el objeto de respuesta. ```ts axios.head(url: string, config?: AxiosRequestConfig): AxiosResponse; ``` ### `options` El método `options` se usa para hacer una solicitud OPTIONS. Acepta una URL y un objeto de configuración opcional como argumentos, y devuelve una Promise que se resuelve en el objeto de respuesta. ```ts axios.options(url: string, config?: AxiosRequestConfig): AxiosResponse; ``` ### `post` El método `post` se usa para hacer una solicitud POST. Acepta una URL, un objeto de datos opcional y un objeto de configuración opcional como argumentos, y devuelve una Promise que se resuelve en el objeto de respuesta. ```ts axios.post(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ### `put` El método `put` se usa para hacer una solicitud PUT. Acepta una URL, un objeto de datos opcional y un objeto de configuración opcional como argumentos, y devuelve una Promise que se resuelve en el objeto de respuesta. ```ts axios.put(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ### `patch` El método `patch` se usa para hacer una solicitud PATCH. Acepta una URL, un objeto de datos opcional y un objeto de configuración opcional como argumentos, y devuelve una Promise que se resuelve en el objeto de respuesta. ```ts axios.patch(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ### `query` El método `query` se usa para hacer una solicitud QUERY, un método seguro e idempotente que transporta un cuerpo. Acepta una URL, un objeto de datos opcional y un objeto de configuración opcional como argumentos, y devuelve una Promise que se resuelve en el objeto de respuesta. Úsalo para operaciones de tipo lectura cuyos parámetros sean demasiado complejos o sensibles para ir en la URL. ```ts axios.query(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ```js // Enviar un filtro de búsqueda complejo como cuerpo de la solicitud const { data } = await axios.query("/api/search", { selector: ["name", "email"], filter: { active: true, role: "admin" }, }); ``` ::: warning Especificación en borrador El método QUERY está definido por un [Internet-Draft](https://datatracker.ietf.org/doc/draft-ietf-httpbis-safe-method-w-body/) del IETF y todavía no ha sido estandarizado. La semántica e incluso el propio nombre del método pueden cambiar antes de la publicación final, y el soporte en servidores, proxies y CDN es desigual. Verifica que tu infraestructura acepte `QUERY` de extremo a extremo antes de usarlo en producción. ::: ### `getUri` El método `getUri` devuelve la URL que se enviaría para una configuración dada sin realizar realmente la solicitud. Aplica `baseURL`, `paramsSerializer` y `params`, así que recibes la misma cadena que axios pondría en el cable. Útil para construir enlaces, depurar la serialización o reutilizar la URL resuelta en otra solicitud. ```ts axios.getUri(config?: AxiosRequestConfig): string; ``` ```js const url = axios.getUri({ url: "/users", baseURL: "https://api.example.com", params: { active: true, role: "admin" }, }); // "https://api.example.com/users?active=true&role=admin" ``` ::: tip Usa `getUri` en una instancia (`instance.getUri(config)`) para heredar los valores predeterminados de `baseURL`, `params` y `paramsSerializer` de la instancia. ::: ## Métodos abreviados para datos de formulario Estos métodos son equivalentes a sus contrapartes anteriores, pero predefinen `Content-Type` como `multipart/form-data`. Son la forma recomendada de subir archivos o enviar formularios HTML. ### `postForm` ```ts axios.postForm(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ```js // Upload a file from a browser file input await axios.postForm("/api/upload", { file: document.querySelector("#fileInput").files[0], description: "Profile photo", }); ``` ### `putForm` ```ts axios.putForm(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ```js // Replace a resource with form data await axios.putForm("/api/users/1/avatar", { avatar: document.querySelector("#avatarInput").files[0], }); ``` ### `patchForm` ```ts axios.patchForm(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ```js // Update specific fields using form data await axios.patchForm("/api/users/1", { displayName: "New Name", avatar: document.querySelector("#avatarInput").files[0], }); ``` ::: tip `postForm`, `putForm` y `patchForm` aceptan los mismos tipos de datos que sus métodos base: objetos planos, `FormData`, `FileList` y `HTMLFormElement`. Consulta [Publicación de archivos](/pages/advanced/file-posting) para más ejemplos. ::: axios-axios-2d06f96/docs/es/pages/advanced/response-schema.md000066400000000000000000000044441521272452000241470ustar00rootroot00000000000000# Esquema de respuesta Cada solicitud de axios se resuelve en un objeto de respuesta con la siguiente estructura. El esquema es consistente tanto en el entorno del navegador como en Node.js. ```js { // Los datos de respuesta proporcionados por el servidor. // Al usar `transformResponse`, este será el resultado de la última transformación. data: {}, // El código de estado HTTP de la respuesta del servidor (por ejemplo: 200, 404, 500). status: 200, // El mensaje de estado HTTP correspondiente al código de estado (por ejemplo: "OK", "Not Found"). statusText: "OK", // Los encabezados de respuesta enviados por el servidor. // Los nombres de los encabezados están en minúsculas. Puedes acceder a ellos con notación de corchetes o de punto. headers: {}, // La configuración de axios que se usó para esta solicitud, incluyendo baseURL, // headers, timeout, params y cualquier otra opción que hayas proporcionado. config: {}, // El objeto de solicitud subyacente. // En Node.js: la última instancia de `http.ClientRequest` (después de cualquier redirección). // En el navegador: la instancia de `XMLHttpRequest`. request: {}, } ``` ## Acceder a los campos de la respuesta En la práctica, generalmente desestructurarás solo las partes que necesites: ```js const { data, status, headers } = await axios.get("/api/users/1"); console.log(status); // 200 console.log(headers["content-type"]); // "application/json; charset=utf-8" console.log(data); // { id: 1, name: "Jay", email: "jay@example.com" } ``` ## Verificar el código de estado axios resuelve la Promise para cualquier respuesta 2xx y la rechaza para cualquier cosa fuera de ese rango de forma predeterminada. Puedes personalizar esto con la opción de configuración `validateStatus`: ```js const response = await axios.get("/api/resource", { validateStatus: (status) => status < 500, // resolve for anything below 500 }); ``` ## Acceder a los encabezados de respuesta Todos los nombres de encabezados de respuesta están en minúsculas, independientemente de cómo los haya enviado el servidor: ```js const response = await axios.get("/api/resource"); // These are equivalent const contentType = response.headers["content-type"]; const contentType2 = response.headers.get("content-type"); ``` axios-axios-2d06f96/docs/es/pages/advanced/retry.md000066400000000000000000000074751521272452000222270ustar00rootroot00000000000000# Reintentos y recuperación de errores Las solicitudes de red pueden fallar por razones transitorias — una falla momentánea del servidor, una breve interrupción de la red o una respuesta de límite de tasa. Implementar una estrategia de reintento en un interceptor te permite manejar estos fallos de forma transparente, sin ensuciar el código de tu aplicación. ## Reintento básico con un interceptor de respuesta El enfoque más sencillo es capturar códigos de estado de error específicos y reenviar inmediatamente la solicitud original un número limitado de veces: ```js import axios from "axios"; const api = axios.create({ baseURL: "https://api.example.com" }); const MAX_RETRIES = 3; api.interceptors.response.use( (response) => response, async (error) => { const config = error.config; // Only retry on network errors or 5xx server errors const shouldRetry = !error.response || (error.response.status >= 500 && error.response.status < 600); if (!shouldRetry) { return Promise.reject(error); } config._retryCount = config._retryCount ?? 0; if (config._retryCount >= MAX_RETRIES) { return Promise.reject(error); } config._retryCount += 1; return api(config); } ); ``` ## Retroceso exponencial Reintentar inmediatamente después de un fallo puede sobrecargar a un servidor que ya tiene dificultades. El retroceso exponencial espera progresivamente más tiempo entre cada intento: ```js const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); api.interceptors.response.use( (response) => response, async (error) => { const config = error.config; const shouldRetry = !error.response || (error.response.status >= 500 && error.response.status < 600); if (!shouldRetry) return Promise.reject(error); config._retryCount = config._retryCount ?? 0; if (config._retryCount >= 3) return Promise.reject(error); config._retryCount += 1; // Wait 200ms, 400ms, 800ms, ... before each retry const backoff = 100 * 2 ** config._retryCount; await delay(backoff); return api(config); } ); ``` ## Reintento en 429 (límite de tasa) con Retry-After Cuando el servidor responde con `429 Too Many Requests`, a menudo incluye un encabezado `Retry-After` que indica exactamente cuánto tiempo esperar: ```js api.interceptors.response.use( (response) => response, async (error) => { const config = error.config; if (error.response?.status !== 429) return Promise.reject(error); config._retryCount = config._retryCount ?? 0; if (config._retryCount >= 3) return Promise.reject(error); config._retryCount += 1; const retryAfterHeader = error.response.headers["retry-after"]; const waitMs = retryAfterHeader ? parseFloat(retryAfterHeader) * 1000 // header is in seconds : 1000; // default to 1 second await new Promise((resolve) => setTimeout(resolve, waitMs)); return api(config); } ); ``` ## Desactivar reintentos por solicitud Si algunas solicitudes nunca deben reintentarse (por ejemplo, mutaciones no idempotentes que no deseas duplicar), añade un indicador a la configuración de la solicitud: ```js // Add this to your interceptor before the retry logic: if (config._noRetry) return Promise.reject(error); // Then opt out on specific calls: await api.post("/payments/charge", body, { _noRetry: true }); ``` ## Combinar reintentos con cancelación Usa un `AbortController` para cancelar una solicitud que está esperando un retardo de retroceso: ```js const controller = new AbortController(); try { await api.get("/api/data", { signal: controller.signal }); } catch (error) { if (axios.isCancel(error)) { console.log("Request aborted by user"); } } // Cancel the request (and any pending retry delay) from elsewhere: controller.abort(); ``` axios-axios-2d06f96/docs/es/pages/advanced/testing.md000066400000000000000000000102101521272452000225140ustar00rootroot00000000000000# Pruebas Probar código que realiza solicitudes HTTP con axios es sencillo. El enfoque recomendado es simular (mock) axios directamente, de modo que las pruebas se ejecuten sin acceder a la red real, dándote control total sobre las respuestas que recibe tu código. ## Simulación con Vitest o Jest Tanto Vitest como Jest admiten la simulación de módulos con `vi.mock` / `jest.mock`. Puedes simular todo el módulo de axios y controlar lo que devuelve cada método: ```js // user-service.js import axios from "axios"; export async function getUser(id) { const { data } = await axios.get(`/api/users/${id}`); return data; } ``` ```js // user-service.test.js import { describe, it, expect, vi } from "vitest"; import axios from "axios"; import { getUser } from "./user-service"; vi.mock("axios"); describe("getUser", () => { it("returns user data on success", async () => { const mockUser = { id: 1, name: "Jay" }; // Make axios.get resolve with our fake response axios.get.mockResolvedValueOnce({ data: mockUser }); const result = await getUser(1); expect(result).toEqual(mockUser); expect(axios.get).toHaveBeenCalledWith("/api/users/1"); }); it("throws when the request fails", async () => { axios.get.mockRejectedValueOnce(new Error("Network error")); await expect(getUser(1)).rejects.toThrow("Network error"); }); }); ``` ## Simular un AxiosError Para probar rutas de manejo de errores que inspeccionan `error.response`, crea una instancia de `AxiosError` directamente: ```js import axios, { AxiosError } from "axios"; import { vi } from "vitest"; const mockError = new AxiosError( "Not Found", "ERR_BAD_REQUEST", {}, // config {}, // request { // response status: 404, statusText: "Not Found", data: { message: "User not found" }, headers: {}, config: {}, } ); axios.get.mockRejectedValueOnce(mockError); ``` ## Usando axios-mock-adapter [axios-mock-adapter](https://github.com/ctimmerm/axios-mock-adapter) es una librería que instala un adaptador personalizado en tu instancia de axios, interceptando las solicitudes a nivel del adaptador. Esto significa que tus interceptores siguen ejecutándose, lo que la hace más adecuada para pruebas de integración. ```bash npm install --save-dev axios-mock-adapter ``` ```js import axios from "axios"; import MockAdapter from "axios-mock-adapter"; const mock = new MockAdapter(axios); // Mock a GET request mock.onGet("/api/users/1").reply(200, { id: 1, name: "Jay" }); // Mock a POST request mock.onPost("/api/users").reply(201, { id: 2, name: "New User" }); // Mock a network error mock.onGet("/api/failing").networkError(); // Mock a timeout mock.onGet("/api/slow").timeout(); ``` Reinicia los mocks entre pruebas: ```js afterEach(() => { mock.reset(); // clear all registered handlers }); ``` ## Probar interceptores Para probar interceptores de forma aislada, crea una nueva instancia de axios en tu prueba: ```js import axios from "axios"; import MockAdapter from "axios-mock-adapter"; describe("auth interceptor", () => { it("attaches a Bearer token to every request", async () => { const instance = axios.create(); const mock = new MockAdapter(instance); // Add your interceptor instance.interceptors.request.use((config) => { config.headers.set("Authorization", "Bearer test-token"); return config; }); // Capture the request config by inspecting what mock received let capturedConfig; mock.onGet("/api/data").reply((config) => { capturedConfig = config; return [200, {}]; }); await instance.get("/api/data"); expect(capturedConfig.headers["Authorization"]).toBe("Bearer test-token"); }); }); ``` ## Consejos - Siempre simula a nivel de módulo (o usa `MockAdapter`) — evita simular métodos individuales en una instancia compartida, ya que el estado puede filtrarse entre pruebas. - Usa `mockResolvedValueOnce` / `mockRejectedValueOnce` en lugar de `mockResolvedValue` para que las pruebas estén aisladas y no se afecten entre sí. - Al probar lógica de reintento, usa `MockAdapter` para que el interceptor bajo prueba realmente se ejecute en cada intento. axios-axios-2d06f96/docs/es/pages/advanced/type-script.md000066400000000000000000000053331521272452000233340ustar00rootroot00000000000000# TypeScript `axios` incluye definiciones de TypeScript en el paquete npm a través de `index.d.ts` (ESM) e `index.d.cts` (CJS), por lo que la verificación de tipos y el soporte del editor funcionan de manera nativa para ambos formatos de módulo. ## Consideraciones sobre la resolución de módulos Dado que axios publica de forma dual con una exportación por defecto ESM y un `module.exports` CJS, hay algunas consideraciones de configuración: - La configuración recomendada es `"moduleResolution": "node16"` (implícita en `"module": "node16"`). Esto requiere TypeScript 4.7 o superior. - Si usas ESM, tu configuración debería estar bien. - Si compilas TypeScript a CJS y no puedes usar `"moduleResolution": "node16"`, debes habilitar `esModuleInterop`. - Si usas TypeScript para verificar tipos en código JavaScript CJS, tu única opción es `"moduleResolution": "node16"`. ## Type guards para errores de axios Usa el type guard `axios.isAxiosError` para reducir de forma segura los errores `unknown` en bloques `catch`. Tras la reducción, puedes acceder a propiedades específicas de axios como `error.response`, `error.config` y `error.code` con seguridad de tipos completa. ```ts import axios from "axios"; let user: User | null = null; try { const { data } = await axios.get("/user?ID=12345"); user = data.userDetails; } catch (error) { if (axios.isAxiosError(error)) { handleAxiosError(error); } else { handleUnexpectedError(error); } } ``` Usa `axios.isCancel()` para reducir los errores de cancelación a `CanceledError`: ```ts const controller = new AbortController(); try { await axios.get("/user?ID=12345", { signal: controller.signal }); } catch (error) { if (axios.isCancel(error)) { handleCancellation(error); } } ``` ## Instancias e interceptores tipados Anota el resultado de `axios.create` con `AxiosInstance`, y anota los interceptores de solicitud con `InternalAxiosRequestConfig` para obtener verificación de tipos de extremo a extremo en un cliente personalizado: ```ts import axios, { AxiosInstance, InternalAxiosRequestConfig } from "axios"; const apiClient: AxiosInstance = axios.create({ baseURL: "https://api.example.com", timeout: 10000, }); apiClient.interceptors.request.use((config: InternalAxiosRequestConfig) => { // Añadir token de autenticación, registrar, etc. return config; }); ``` ## Tipado de los datos de respuesta Los métodos de solicitud de Axios son genéricos sobre el tipo de los datos de respuesta. Pasa un parámetro de tipo a `axios.get` (y a los demás alias) para tipar `response.data`: ```ts interface User { id: number; name: string; } const { data } = await apiClient.get("/users/1"); // `data` está tipado como `User` ``` axios-axios-2d06f96/docs/es/pages/advanced/x-www-form-urlencoded-format.md000066400000000000000000000111361521272452000265110ustar00rootroot00000000000000# Formato x-www-form-urlencoded ## URLSearchParams De forma predeterminada, axios serializa los objetos JavaScript a `JSON`. Para enviar datos en el formato [`application/x-www-form-urlencoded`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) en su lugar, puedes usar la API [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams), que es [compatible](http://www.caniuse.com/#feat=urlsearchparams) con la gran mayoría de los navegadores, y con [Node.js](https://nodejs.org/api/url.html#url_class_urlsearchparams) a partir de la versión v10 (lanzada en 2018). ```js const params = new URLSearchParams({ foo: 'bar' }); params.append('extraparam', 'value'); axios.post('/foo', params); ``` ## Cadena de consulta Para navegadores más antiguos o entornos sin `URLSearchParams`, puedes usar la librería [`qs`](https://github.com/ljharb/qs) para serializar objetos al formato `application/x-www-form-urlencoded`. ```js const qs = require('qs'); axios.post('/foo', qs.stringify({ bar: 123 })); ``` Para tener control total sobre los encabezados y el método, pasa la salida de `qs.stringify` como `data` de la solicitud y establece `Content-Type` explícitamente: ```js import qs from 'qs'; const data = { bar: 123 }; const options = { method: 'POST', headers: { 'content-type': 'application/x-www-form-urlencoded' }, data: qs.stringify(data), + url: 'https://example.com/', }; axios(options); ``` En versiones muy antiguas de Node.js, puedes usar el módulo integrado `querystring` que viene con Node.js. Ten en cuenta que este módulo fue marcado como obsoleto en Node.js v16 — prefiere `URLSearchParams` o `qs` para código nuevo. ```js const querystring = require('querystring'); axios.post('https://something.com/', querystring.stringify({ foo: 'bar' })); ``` ::: tip Prefiere `qs` para objetos anidados La librería `qs` es preferible si necesitas serializar objetos anidados, ya que el método `querystring` tiene [problemas conocidos](https://github.com/nodejs/node-v0.x-archive/issues/1665) con ese caso de uso. ::: ## Serialización automática a URLSearchParams A partir de la versión v0.21.0, axios serializa automáticamente los objetos JavaScript a `URLSearchParams` si el encabezado `Content-Type` está establecido en `application/x-www-form-urlencoded`. Esto significa que puedes pasar un objeto JavaScript directamente a la propiedad `data` de la configuración de solicitud de axios. Por ejemplo, al pasar datos a una solicitud `POST`: ```js const data = { x: 1, arr: [1, 2, 3], arr2: [1, [2], 3], users: [ { name: 'Peter', surname: 'Griffin' }, { name: 'Thomas', surname: 'Anderson' }, ], }; await axios.postForm('https://postman-echo.com/post', data, { headers: { 'content-type': 'application/x-www-form-urlencoded' }, }); ``` El objeto `data` será serializado automáticamente a `URLSearchParams` y enviado en el formato `application/x-www-form-urlencoded`. El servidor recibirá los siguientes datos: ```json { "x": "1", "arr[]": ["1", "2", "3"], "arr2[0]": "1", "arr2[1][0]": "2", "arr2[2]": "3", "users[0][name]": "Peter", "users[0][surname]": "Griffin", "users[1][name]": "Thomas", "users[1][surname]": "Anderson" } ``` Si el analizador de cuerpo de tu backend (como `body-parser` de `express.js`) admite la decodificación de objetos anidados, recibirás el mismo objeto en el lado del servidor automáticamente. ## Límite de profundidad para la serialización de parámetros Cuando axios serializa un objeto `params` mediante `AxiosURLSearchParams`, se llama al mismo recorrido recursivo utilizado por el serializador de FormData. Una opción `maxDepth` (predeterminado `100`) limita la profundidad de recursión. Las cargas útiles que exceden el límite lanzan un `AxiosError` con `code: 'ERR_FORM_DATA_DEPTH_EXCEEDED'` en lugar de desbordar la pila de llamadas. ```js // Aumentar el límite si tu objeto params legítimamente anida más de 100 niveles: axios.get('/api', { params: deepObject, paramsSerializer: { maxDepth: 200 } }); ``` ::: warning Nota de seguridad Solo aumenta `maxDepth` si tu esquema realmente lo requiere. El valor predeterminado de 100 protege el código del lado del servidor que reenvía datos controlados por el cliente a axios como `params` contra ataques DoS mediante objetos profundamente anidados. ::: ```js var app = express(); app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies app.post('/', function (req, res, next) { // echo body as JSON res.send(JSON.stringify(req.body)); }); server = app.listen(3000); ``` axios-axios-2d06f96/docs/es/pages/getting-started/000077500000000000000000000000001521272452000220635ustar00rootroot00000000000000axios-axios-2d06f96/docs/es/pages/getting-started/examples/000077500000000000000000000000001521272452000237015ustar00rootroot00000000000000axios-axios-2d06f96/docs/es/pages/getting-started/examples/commonjs.md000066400000000000000000000104451521272452000260540ustar00rootroot00000000000000# Ejemplos en JavaScript ## Importar la librería Para importar la librería en un entorno CommonJS, puedes usar la función `require`, o la declaración `import` si estás usando un empaquetador como Webpack o Rollup. #### Sin empaquetador ```js const axios = require("axios"); ``` #### Con empaquetador (webpack, rollup, vite, etc) ```js import axios from "axios"; ``` ## Usando then/catch/finally Dado que axios devuelve una Promise en su núcleo, puedes optar por usar callbacks con `then`, `catch` y `finally` para manejar los datos de la respuesta, los errores y la finalización. ### Solicitud Get ```js axios .get("https://jsonplaceholder.typicode.com/posts", { params: { postId: 5, }, }) .then((response) => { console.log(response.data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Request completed"); }); ``` ### Solicitud Post ```js axios .post("https://jsonplaceholder.typicode.com/posts", { title: "foo", body: "bar", userId: 1, }) .then((response) => { console.log(response.data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Request completed"); }); ``` ### Solicitud Put ```js axios .put("https://jsonplaceholder.typicode.com/posts/1", { title: "foo", body: "bar", userId: 1, }) .then((response) => { console.log(response.data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Request completed"); }); ``` ### Solicitud Patch ```js axios .patch("https://jsonplaceholder.typicode.com/posts/1", { title: "foo", }) .then((response) => { console.log(response.data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Request completed"); }); ``` ### Solicitud Delete ```js axios .delete("https://jsonplaceholder.typicode.com/posts/1") .then((response) => { console.log(response.data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Request completed"); }); ``` ## Usando async/await Otra forma de manejar promises es mediante `async` y `await`. Esto te permite usar bloques try/catch/finally para manejar errores y la finalización. Esto puede hacer tu código más legible y fácil de entender, y también ayuda a evitar el llamado "callback hell". ::: tip Nota: async/await forma parte de ECMAScript 2017 y no está disponible en Internet Explorer ni en navegadores más antiguos, así que úsalo con precaución. ::: ### Solicitud Get ```js const getPosts = async () => { try { const response = await axios.get( "https://jsonplaceholder.typicode.com/posts", { params: { postId: 5, }, } ); console.log(response.data); } catch (error) { console.error(error); } finally { console.log("Request completed"); } }; ``` ### Solicitud Post ```js const createPost = async () => { try { const response = await axios.post( "https://jsonplaceholder.typicode.com/posts", { title: "foo", body: "bar", userId: 1, } ); console.log(response.data); } catch (error) { console.error(error); } finally { console.log("Request completed"); } }; ``` ### Solicitud Put ```js const updatePost = async () => { try { const response = await axios.put( "https://jsonplaceholder.typicode.com/posts/1", { title: "foo", body: "bar", userId: 1, } ); console.log(response.data); } catch (error) { console.error(error); } finally { console.log("Request completed"); } }; ``` ### Solicitud Patch ```js const updatePost = async () => { try { const response = await axios.patch( "https://jsonplaceholder.typicode.com/posts/1", { title: "foo", } ); console.log(response.data); } catch (error) { console.error(error); } finally { console.log("Request completed"); } }; ``` ### Solicitud Delete ```js const deletePost = async () => { try { const response = await axios.delete( "https://jsonplaceholder.typicode.com/posts/1" ); console.log(response.data); } catch (error) { console.error(error); } finally { console.log("Request completed"); } }; ``` axios-axios-2d06f96/docs/es/pages/getting-started/examples/typescript.md000066400000000000000000000066551521272452000264450ustar00rootroot00000000000000# Ejemplo en TypeScript ## Importar tipos axios incluye definiciones de TypeScript de forma nativa. Puedes importar los tipos que necesites directamente desde `"axios"`: ```ts import axios from "axios"; import type { AxiosRequestConfig, AxiosResponse, AxiosError } from "axios"; ``` ## Tipar una solicitud Usa un parámetro de tipo genérico en la respuesta para indicarle a TypeScript la forma que tendrán tus datos: ```ts import axios from "axios"; type Post = { userId: number; id: number; title: string; body: string; }; const response = await axios.get("https://jsonplaceholder.typicode.com/posts/1"); console.log(response.data.title); // TypeScript knows this is a string ``` ## Tipar una función Envuelve las solicitudes en funciones con tipos de retorno explícitos para maximizar la seguridad de tipos: ```ts import axios, { AxiosResponse } from "axios"; type Post = { userId: number; id: number; title: string; body: string; }; const getPost = async (id: number): Promise => { const response = await axios.get( `https://jsonplaceholder.typicode.com/posts/${id}` ); return response.data; }; ``` ## Tipar una solicitud POST Puedes tipar tanto el cuerpo de la solicitud como la respuesta esperada: ```ts type CreatePostBody = { title: string; body: string; userId: number; }; type CreatePostResponse = CreatePostBody & { id: number }; const createPost = async (data: CreatePostBody): Promise => { const response = await axios.post( "https://jsonplaceholder.typicode.com/posts", data ); return response.data; }; ``` ## Instancia de axios tipada Crea una instancia tipada para que la URL base y los encabezados queden definidos desde el inicio: ```ts import axios from "axios"; import type { AxiosInstance } from "axios"; const api: AxiosInstance = axios.create({ baseURL: "https://api.example.com", timeout: 5000, }); ``` ## Interceptores tipados Usa `InternalAxiosRequestConfig` (no `AxiosRequestConfig`) para los interceptores de solicitud en v1.x: ```ts import axios from "axios"; import type { InternalAxiosRequestConfig, AxiosResponse } from "axios"; api.interceptors.request.use((config: InternalAxiosRequestConfig) => { config.headers.set("Authorization", `Bearer ${getToken()}`); return config; }); api.interceptors.response.use( (response: AxiosResponse) => response, (error) => Promise.reject(error) ); ``` ## Tipar errores Usa `axios.isAxiosError()` para acotar el tipo de un error capturado: ```ts import axios, { AxiosError } from "axios"; type ApiError = { message: string; code: number; }; try { await axios.get("/api/protected-resource"); } catch (error) { if (axios.isAxiosError(error)) { // error.response?.data is typed as ApiError console.error(error.response?.data.message); console.error(error.response?.status); } else { throw error; } } ``` ## Notas sobre la configuración de TypeScript Dado que axios publica tanto en formato ESM como CJS, hay algunas consideraciones según tu configuración: - La configuración recomendada es `"moduleResolution": "node16"` (implícita en `"module": "node16"`). Esto requiere TypeScript 4.7 o superior. - Si compilas TypeScript a CJS y no puedes usar `"moduleResolution": "node16"`, habilita `"esModuleInterop": true`. - Si usas TypeScript para verificar tipos en código JavaScript CJS, tu única opción es `"moduleResolution": "node16"`. axios-axios-2d06f96/docs/es/pages/getting-started/features.md000066400000000000000000000061241521272452000242260ustar00rootroot00000000000000# Características axios es un potente cliente HTTP que proporciona una API simple y fácil de usar para realizar solicitudes HTTP. Es compatible con todos los navegadores modernos y es ampliamente utilizado en la comunidad JavaScript. A continuación se presentan algunas de las características que hacen de axios una excelente opción para tu próximo proyecto. ## Isomórfico axios es un cliente HTTP universal que puede usarse tanto en el navegador como en Node.js. Esto significa que puedes utilizar axios para hacer solicitudes a APIs desde tu código frontend y también desde tu código backend. Esto convierte a axios en una gran opción para construir progressive web apps, aplicaciones de una sola página (SPA) y aplicaciones con renderizado del lado del servidor. axios también es una excelente opción para equipos que trabajan tanto en frontend como en backend. Al usar axios en ambos lados, puedes contar con una API consistente para realizar solicitudes HTTP, lo que ayuda a reducir la complejidad de tu base de código. ## Soporte para Fetch axios ofrece soporte de primera clase para la Fetch API, que es un reemplazo moderno de la API XHR. El adaptador es opcional y puede habilitarse mediante configuración. Se mantiene la misma API tanto para el adaptador XHR como para el adaptador Fetch, lo que facilita adoptar la Fetch API en tu base de código sin necesidad de modificar el código existente. ## Soporte de navegadores axios es compatible con todos los navegadores modernos y algunos más antiguos, incluyendo Chrome, Firefox, Safari y Edge. axios es una excelente opción para construir aplicaciones web que necesiten soportar una amplia variedad de navegadores. ## Soporte de Node.js axios también es compatible con una amplia gama de versiones de Node.js, con compatibilidad probada hasta la versión v12.x, lo que lo convierte en una buena opción en entornos donde actualizar a la última versión de Node.js puede no ser posible o práctico. Además de Node.js, axios cuenta con pruebas de humo para Bun y Deno que validan comportamientos clave en tiempo de ejecución y mejoran la confianza en la compatibilidad entre distintos entornos. ## Características adicionales - Compatible con la API de Promise - Interceptar solicitudes y respuestas - Transformar datos de solicitudes y respuestas - Controlador de cancelación (Abort controller) - Tiempos de espera (timeouts) - Serialización de parámetros de consulta con soporte para entradas anidadas - Serialización automática del cuerpo de la solicitud a: - JSON (application/json) - Multipart / FormData (multipart/form-data) - Formulario codificado en URL (application/x-www-form-urlencoded) - Envío de formularios HTML como JSON - Manejo automático de datos JSON en la respuesta - Captura de progreso para navegadores y Node.js con información adicional (velocidad de transferencia, tiempo restante) - Configuración de límites de ancho de banda para Node.js - Compatible con FormData y Blob conformes a la especificación (incluyendo Node.js) - Soporte del lado del cliente para protección contra XSRF axios-axios-2d06f96/docs/es/pages/getting-started/first-steps.md000066400000000000000000000100711521272452000246670ustar00rootroot00000000000000# Primeros pasos ¡Bienvenido a la documentación de axios! Esta guía te ayudará a comenzar con axios y a realizar tu primera solicitud a una API. Si eres nuevo en axios, te recomendamos empezar aquí. ## Instalación Puedes usar axios en tu proyecto de varias formas. La más común es instalarlo desde npm e incluirlo en tu proyecto. También ofrecemos soporte para jsDelivr, unpkg y más. #### Usando npm ```bash npm install axios ``` #### Usando pnpm ```bash pnpm install axios ``` #### Usando yarn ```bash yarn add axios ``` #### Usando bun ```bash bun add axios ``` #### Usando deno ```bash deno install npm:axios ``` #### Usando jsDelivr Al usar jsDelivr, recomendamos utilizar la versión minificada y fijar el número de versión para evitar cambios inesperados. Si deseas usar la última versión, puedes hacerlo omitiendo el número de versión. Esto está fuertemente desaconsejado para uso en producción, ya que puede ocasionar cambios inesperados en tu aplicación. ```html ``` #### Usando unpkg Al usar unpkg, recomendamos utilizar la versión minificada y fijar el número de versión para evitar cambios inesperados. Si deseas usar la última versión, puedes hacerlo omitiendo el número de versión. Esto está fuertemente desaconsejado para uso en producción, ya que puede ocasionar cambios inesperados en tu aplicación. ```html ``` ## Importación de axios Una vez instalado, puedes importar la librería usando `import` o `require`: ```js import axios, { isCancel, AxiosError } from "axios"; ``` También puedes usar la exportación por defecto, ya que las exportaciones nombradas son simplemente re-exportaciones desde la fábrica de axios: ```js import axios from "axios"; console.log(axios.isCancel("something")); ``` Si usas `require` para importar, **solo está disponible la exportación por defecto**: ```js const axios = require("axios"); console.log(axios.isCancel("something")); ``` Para algunos bundlers y linters de ES6 puede que necesites: ```js import { default as axios } from "axios"; ``` Para entornos personalizados o heredados donde la resolución de módulos no se comporta correctamente, puedes importar el bundle preconstruido directamente: ```js const axios = require("axios/dist/browser/axios.cjs"); // bundle CommonJS para navegador (ES2017) // const axios = require("axios/dist/node/axios.cjs"); // bundle CommonJS para node (ES2017) ``` ## Tu primera solicitud Una solicitud con axios puede realizarse en tan solo dos líneas de código. Hacer tu primera solicitud con axios es muy sencillo. Puedes hacer una solicitud a cualquier API indicando la URL y el método. Por ejemplo, para hacer una solicitud GET a la API de JSONPlaceholder, puedes usar el siguiente código: ```js import axios from "axios"; const response = await axios.get( "https://jsonplaceholder.typicode.com/posts/1" ); console.log(response.data); ``` axios ofrece una API sencilla para realizar solicitudes. Puedes usar el método `axios.get` para hacer una solicitud GET, el método `axios.post` para hacer una solicitud POST, y así sucesivamente. También puedes usar el método `axios.request` para hacer una solicitud con cualquier método. ::: tip Establece un timeout en producción Sin un `timeout`, una solicitud detenida puede colgarse indefinidamente. Pásalo en la configuración de la solicitud: ```js const response = await axios.get("https://example.com/data", { timeout: 5000, // 5 segundos }); ``` Consulta [`timeout` en la configuración de solicitud](/pages/advanced/request-config#timeout) y [Manejo de errores](/pages/advanced/error-handling) para los códigos `ECONNABORTED` / `ETIMEDOUT` correspondientes. ::: ## Próximos pasos Ahora que has realizado tu primera solicitud con axios, estás listo para explorar el resto de la documentación. Puedes aprender más sobre cómo hacer solicitudes, manejar respuestas y usar axios en tus proyectos. Consulta el resto de la documentación para saber más. axios-axios-2d06f96/docs/es/pages/getting-started/upgrade-guide.md000066400000000000000000000110751521272452000251330ustar00rootroot00000000000000# Guía de actualización Esta guía tiene como objetivo ayudarte a actualizar tu proyecto de una versión del framework a otra. Se recomienda leer las notas de la versión de cada versión mayor desde la que estás migrando, ya que pueden contener información importante sobre cambios que rompen la compatibilidad. ## Actualización de v0.x a v1.x ### Cambios en la declaración de importación En v1.x, la declaración de importación fue modificada para usar la exportación `default`. Esto significa que deberás actualizar tus importaciones para usar la exportación `default`. ```diff - import { axios } from "axios"; + import axios from "axios"; ``` ### Cambios en el sistema de interceptores En v1.x debes usar el tipo `InternalAxiosRequestConfig` para tipar el parámetro `config` en el interceptor de `request`. Esto se debe a que el parámetro `config` ahora es del tipo `InternalAxiosRequestConfig` en lugar del tipo público `AxiosRequestConfig`. ```diff - axios.interceptors.request.use((config: AxiosRequestConfig) => { + axios.interceptors.request.use((config: InternalAxiosRequestConfig) => { return config; }); ``` ### Cambios en la estructura de los encabezados de solicitud En v1.x, la estructura de los encabezados de solicitud fue modificada para eliminar la propiedad `common`. Esto significa que deberás actualizar tu código para usar la nueva estructura de encabezados de solicitud de la siguiente manera: ```diff - if (request.headers?.common?.Authorization) { - request.headers.common.Authorization = ... + if (request.headers?.Authorization) { + request.headers.Authorization = ... ``` Los encabezados predeterminados que antes estaban bajo `common`, `get`, `post`, etc., ahora se definen directamente en `axios.defaults.headers`: ```diff - axios.defaults.headers.common["Accept"] = "application/json"; + axios.defaults.headers["Accept"] = "application/json"; ``` ### Datos multipart en formularios Si una solicitud incluye un payload de tipo `FormData`, el encabezado `Content-Type: multipart/form-data` ahora se establece automáticamente. Elimina cualquier encabezado manual para evitar duplicados: ```diff - axios.post("/upload", formData, { - headers: { "Content-Type": "multipart/form-data" }, - }); + axios.post("/upload", formData); ``` Si defines explícitamente `Content-Type: application/json`, axios ahora serializará automáticamente los datos a JSON. ### Serialización de parámetros v1.x introdujo varios cambios que rompen la compatibilidad en la forma en que se serializan los parámetros de URL. Los más importantes son: **Los `params` ahora se codifican por porcentaje (percent-encoded) de forma predeterminada.** Si tu backend esperaba corchetes sin codificar al estilo qs, puede que necesites configurar un serializador personalizado: ```js import qs from 'qs'; axios.create({ paramsSerializer: { serialize: (params) => qs.stringify(params, { arrayFormat: 'brackets' }), }, }); ``` **Los objetos anidados en `params` ahora se serializan con notación de corchetes** (`foo[bar]=1`) en lugar de notación de punto. Si tu backend esperaba notación de punto, usa un serializador personalizado. **Los parámetros con valor `null` o `undefined`** ahora se manejan de forma consistente: los valores `null` se serializan como cadenas vacías, mientras que los valores `undefined` se omiten completamente. Para ver todas las opciones de configuración de serialización de parámetros, consulta la página de [Configuración de solicitud](/pages/advanced/request-config). ### Los internos ya no se exportan Hemos decidido dejar de exportar los internos de axios. Esto significa que deberás actualizar tu código para usar únicamente la API pública de axios. Este cambio se realizó para simplificar la API y reducir la superficie expuesta de axios, permitiéndonos modificar los internos sin declararlos como cambios que rompen la compatibilidad. Consulta la [Referencia de la API](/pages/advanced/api-reference) en este sitio para obtener la información más actualizada sobre la API pública de axios. ### Configuración de solicitud Hemos realizado cambios en el objeto de configuración de solicitud. Consulta la [referencia de configuración](/pages/advanced/request-config) en este sitio para obtener la información más actualizada. ### Cambios que rompen la compatibilidad no cubiertos Esta guía no es exhaustiva y puede no cubrir todos los cambios que rompen la compatibilidad. Si encuentras algún problema, por favor abre un issue en el [repositorio GitHub de la documentación](https://github.com/axios/docs) con la etiqueta `breaking change`. axios-axios-2d06f96/docs/es/pages/misc/000077500000000000000000000000001521272452000177115ustar00rootroot00000000000000axios-axios-2d06f96/docs/es/pages/misc/security.md000066400000000000000000000265171521272452000221150ustar00rootroot00000000000000# Política de seguridad ## ⚠️ Bomba de descompresión / almacenamiento de respuesta sin límites Por defecto, `maxContentLength` y `maxBodyLength` están configurados en `-1` (sin límite). Un servidor malicioso o comprometido puede devolver un cuerpo pequeño comprimido con gzip/deflate/brotli/zstd que se expande a gigabytes, agotando la memoria del proceso Node.js. **Si realizas solicitudes a servidores en los que no confías plenamente, DEBES establecer un `maxContentLength` (y `maxBodyLength`) adecuado para tu carga de trabajo.** El límite se aplica chunk a chunk durante la descompresión en flujo, así que basta con configurarlo para neutralizar ataques de bomba de descompresión. ```js axios.get('https://example.com/data', { maxContentLength: 10 * 1024 * 1024, // 10 MB maxBodyLength: 10 * 1024 * 1024, }); // O globalmente: axios.defaults.maxContentLength = 10 * 1024 * 1024; axios.defaults.maxBodyLength = 10 * 1024 * 1024; ``` El valor por defecto no se ha endurecido porque hacerlo romperá silenciosamente cualquier descarga legítima mayor al límite elegido. La responsabilidad de escoger un tope seguro para fuentes no confiables recae en la aplicación. ## Otras opciones sensibles a la seguridad Las siguientes opciones de configuración de solicitud tienen implicaciones directas de seguridad. Están documentadas en detalle junto al resto de la [configuración de solicitud](/pages/advanced/request-config), y se resumen aquí para que aparezcan en un solo lugar. | Opción | Riesgo | Mitigación | | --- | --- | --- | | [`socketPath`](/pages/advanced/request-config#socketpath) | Si proviene de entrada no confiable, un atacante puede redirigir el tráfico a sockets locales privilegiados como `/var/run/docker.sock`, eludiendo las protecciones SSRF basadas en hostname (CWE-918). | Filtra o restringe con allowlist las claves de configuración provenientes de entradas no confiables. Usa [`allowedSocketPaths`](/pages/advanced/request-config#allowedsocketpaths) para restringir las rutas de socket aceptadas. | | [`beforeRedirect`](/pages/advanced/request-config#beforeredirect) | Se ejecuta después de que `follow-redirects` elimina las credenciales en una bajada de protocolo. Reinyectar credenciales sin verificar el protocolo de destino puede filtrarlas sobre HTTP en texto plano. | Reinyecta credenciales únicamente para destinos HTTPS de confianza. Verifica `options.protocol === "https:"` antes de asignar `auth`. | | [`withXSRFToken`](/pages/advanced/request-config#withxsrftoken) | Establecerlo en `true` fuerza el encabezado XSRF en solicitudes de origen cruzado. Versiones anteriores de axios lo habilitaban implícitamente con `withCredentials: true`; las versiones más recientes requieren ambos indicadores. | Déjalo en `undefined` (solo mismo origen) salvo que tu backend valide explícitamente XSRF en solicitudes de origen cruzado. | | [`redact`](/pages/advanced/request-config#redact) | `AxiosError#toJSON()` incluye la configuración de la solicitud por defecto, lo que puede filtrar encabezados `Authorization` o credenciales `auth` en logs y telemetría de errores. | Pasa un arreglo `redact` con los nombres de claves de configuración sensibles. La coincidencia es insensible a mayúsculas y recursiva. | | [`formDataHeaderPolicy`](/pages/advanced/request-config#formdataheaderpolicy) | Un `FormData` personalizado cuyo `getHeaders()` devuelve valores controlados por un atacante puede sobrescribir encabezados como `Authorization` o inyectar otros arbitrarios en Node.js. | Establece `'content-only'` para copiar únicamente `Content-Type` y `Content-Length`, y luego define los demás encabezados explícitamente a través de la configuración `headers` de la solicitud. | ## Endurecimiento de la cadena de suministro: `ignore-scripts` y scripts de ciclo de vida El repositorio incluye un `.npmrc` a nivel de proyecto que establece `ignore-scripts=true`. Esto bloquea los scripts de ciclo de vida de npm (`preinstall`, `install`, `postinstall`, `prepare`) de cualquier dependencia directa o transitiva al ejecutar `npm install` o `npm ci` dentro del repositorio. Consulta [THREATMODEL.md](https://github.com/axios/axios/blob/v1.x/THREATMODEL.md) (amenaza T-S2) para conocer la justificación. Una consecuencia: el propio hook `prepare` del repositorio (que instala los git hooks de Husky) **no** se ejecuta automáticamente. Tras tu primera instalación, habilita los git hooks manualmente: ```bash npm ci npm rebuild husky && npx husky ``` Ejecuta esos dos comandos una vez por checkout limpio. **No** necesitas volver a ejecutarlos tras cada `npm install` posterior. ::: danger No elimines `ignore-scripts=true` Eliminar `ignore-scripts=true` de `.npmrc` para "arreglar" la configuración de husky reabre la superficie de ataque de los scripts de ciclo de vida para todos los demás paquetes del árbol. Todos los workflows de CI ya invocan npm con `--ignore-scripts`, así que el comportamiento local coincide con CI. ::: Recomendamos el mismo ajuste `ignore-scripts=true` en cualquier proyecto consumidor que incorpore axios (o cualquier otra dependencia) en un entorno de compilación que maneje secretos. ## Verificar una publicación Cada tarball de `axios` publicado en npm proviene de GitHub Actions y lleva una [atestación de provenance de npm](https://docs.npmjs.com/generating-provenance-statements) que vincula criptográficamente el paquete al workflow y al SHA del commit que lo generó. Los consumidores pueden verificar la provenance localmente: ```bash # Verifica todos los paquetes de tu lockfile, incluido axios npm audit signatures ``` Una verificación exitosa demuestra que el tarball fue construido en el entorno de GitHub Actions de `axios/axios` sobre un commit conocido — no fue alterado entre la compilación y el registro. **No** demuestra que el código de ese commit esté libre de bugs. Si `npm audit signatures` reporta una atestación ausente o inválida para una versión reciente de `axios`, trátalo como un posible incidente de cadena de suministro y repórtalo por el canal privado indicado abajo. ## Reportar una vulnerabilidad Si crees haber encontrado una vulnerabilidad de seguridad en el proyecto, por favor repórtanosla como se describe a continuación. Tomamos todas las vulnerabilidades de seguridad con seriedad. Si has encontrado una vulnerabilidad en una librería de terceros, por favor repórtala a los responsables de esa librería. ## Proceso de reporte Por favor, no reportes vulnerabilidades de seguridad a través de los issues públicos de GitHub. Usa el canal oficial de seguridad en GitHub enviando un [aviso de seguridad](https://github.com/axios/axios/security/advisories/new). ## Política de divulgación Cuando recibimos un reporte de vulnerabilidad, asignamos un responsable principal. El responsable confirma el problema, determina las versiones afectadas, evalúa la gravedad, desarrolla y publica una corrección, y coordina la divulgación pública con quien reportó. ### Compromiso de resolución y divulgación en 60 días Nos comprometemos a **resolver y divulgar públicamente cada aviso de seguridad válido dentro de los 60 días naturales posteriores al reporte inicial**, contados desde el momento en que se recibe el reporte a través del [canal de avisos de seguridad de GitHub](https://github.com/axios/axios/security/advisories/new). El plazo de 60 días es un compromiso con quienes reportan y con los consumidores aguas abajo — es un mínimo exigible, no una meta. Si no podemos entregar una corrección a tiempo, publicamos de todos modos el aviso el día 60 con la mejor guía de mitigación disponible para que los consumidores puedan actuar. **Hitos dentro de la ventana de 60 días:** | Día | Hito | | ---- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | 0 | Reporte recibido. Aviso privado abierto en GitHub. | | ≤ 3 | Acuse de recibo enviado a quien reporta. Decisión de triaje: dentro de alcance / fuera de alcance / duplicado / falta información. | | ≤ 10 | Gravedad evaluada (CVSS v4 cuando aplique). Versiones afectadas confirmadas. CVE solicitado vía GitHub si procede un identificador público. | | ≤ 45 | Corrección desarrollada, revisada y probada. Candidata de versión preparada en rama privada. Se ofrece vista previa a quien reporta para validación. | | ≤ 60 | Versión parcheada publicada en npm. Aviso público + CVE publicados. Se acredita a quien reportó salvo solicitud contraria. CHANGELOG actualizado. | **Excepciones y prórrogas.** - Si quien reporta solicita un embargo más corto (por ejemplo, planea presentar los hallazgos en una conferencia), lo acomodamos cuando sea posible. - Si la corrección requiere un cambio disruptivo, coordinación con consumidores aguas abajo importantes, o una publicación upstream de `follow-redirects` / `form-data` / `proxy-from-env`, podemos extender más allá de los 60 días. Cualquier prórroga se divulga públicamente el día 60 vía el aviso, con un ETA revisado y el motivo. - Si un reporte está **fuera de alcance** (por ejemplo, cae bajo un non-goal explícito documentado en el [modelo de amenazas](https://github.com/axios/axios/blob/v1.x/THREATMODEL.md) del proyecto), lo cerramos con una explicación dentro de la ventana de triaje (≤ 3 días). Los reportes fuera de alcance no entran en la cola de 60 días. - Las **vulnerabilidades activamente explotadas** se tratan como incidentes: la corrección y el aviso salen tan pronto como se valide un parche, no según el calendario de 60 días. **Expectativas sobre quien reporta.** Mientras un reporte esté bajo embargo, pedimos que se abstengan de divulgación pública hasta el primero de: (a) la publicación coordinada del aviso, o (b) el día 60. Si la fecha límite de 60 días pasa sin acción de nuestra parte, quien reportó queda libre de divulgar por su cuenta — consideraremos eso un fallo nuestro, no suyo. ## Actualizaciones de seguridad Las actualizaciones de seguridad se publican tan pronto como sea posible después de desarrollar y probar el parche. Notificamos a los usuarios a través del repositorio GitHub del proyecto y publicamos las notas de la versión y los avisos de seguridad en la página de versiones de GitHub. Además, marcamos como obsoletas todas las versiones que contengan la vulnerabilidad. ## Respuesta a incidentes del lado del mantenedor Para escenarios de compromiso que afecten cuentas de mantenedores, estaciones de trabajo o infraestructura de publicación (phishing, pérdida de llave hardware, tag o publicación inesperados), el proyecto mantiene un runbook interno de respuesta a incidentes en [THREATMODEL.md §3.7](https://github.com/axios/axios/blob/v1.x/THREATMODEL.md#37-incident-response-runbook). Cubre revocación de sesiones, rotación de llaves, notificación aguas abajo y procedimientos de unpublish/deprecate. ## Colaboradores y reconocimientos de seguridad Nos gustaría agradecer a los siguientes investigadores de seguridad por trabajar con nosotros para ayudar a que el proyecto sea seguro para todos: - [Socket Dev](https://socket.dev/) - [GitHub Security Lab](https://securitylab.github.com/) axios-axios-2d06f96/docs/es/pages/misc/semver.md000066400000000000000000000051221521272452000215340ustar00rootroot00000000000000# Versionado semántico El versionado semántico es un esquema de versionado que se usa para comunicar la naturaleza de los cambios en un paquete de software. Es un conjunto simple de reglas y requisitos que dictan cómo se asignan e incrementan los números de versión. ## Versionado de axios axios sigue el esquema de versionado semántico. Esto significa que cada versión de axios se asigna con un número de versión compuesto por tres partes: mayor, menor y parche. El número de versión se incrementa según la naturaleza de los cambios en la versión. En el pasado, axios puede que no haya seguido estrictamente el versionado semántico en todo momento; sin embargo, de aquí en adelante se adoptará una adherencia mucho más estricta al esquema de versionado semántico para garantizar que los usuarios puedan confiar en los números de versión para comunicar la naturaleza de los cambios en la librería. A continuación se proporciona un breve resumen del esquema de versionado. ## Formato de versión Un número de versión semántico consta de tres partes: 1. Versión mayor 2. Versión menor 3. Versión de parche El número de versión se escribe como `MAYOR.MENOR.PARCHE`. Cada parte del número de versión tiene un significado específico: - **Versión mayor**: Se incrementa cuando se realizan cambios incompatibles en la API. - **Versión menor**: Se incrementa cuando se añade funcionalidad de manera retrocompatible. - **Versión de parche**: Se incrementa cuando se realizan correcciones de errores retrocompatibles. ## Versiones de prelanzamiento Además de las tres partes del número de versión, puedes añadir una versión de prelanzamiento. Esto se hace añadiendo un guion y una serie de identificadores separados por puntos inmediatamente después de la versión de parche. Por ejemplo, `1.0.0-alpha.1`. Las versiones de prelanzamiento se usan para indicar que una versión es inestable y puede no satisfacer los requisitos de compatibilidad indicados por el número de versión. Las versiones de prelanzamiento se ordenan según el orden de los identificadores. Por ejemplo, `1.0.0-alpha.1` viene antes de `1.0.0-alpha.2`. ## Rangos de versiones Cuando especificas un rango de versiones para un paquete, puedes usar una variedad de operadores para indicar el rango de versiones aceptables. Los siguientes operadores están disponibles: - `>`: Mayor que - `<`: Menor que - `>=`: Mayor o igual que - `<=`: Menor o igual que - `~`: Aproximadamente igual a - `^`: Compatible con Por ejemplo, `^1.0.0` significa que cualquier versión mayor o igual a `1.0.0` y menor que `2.0.0` es aceptable. axios-axios-2d06f96/docs/es/pages/misc/sponsors.md000066400000000000000000000115601521272452000221240ustar00rootroot00000000000000--- layout: page ---

Patrocinadores

Axios cuenta con el apoyo de las siguientes organizaciones. Si deseas patrocinar Axios, visita nuestra página de Open Collective para más información.

{{ capitalizeFirstLetter(sponsor.tier) }}
{{ sponsor.name }}
axios-axios-2d06f96/docs/favicon.ico000066400000000000000000000360561521272452000174030ustar00rootroot00000000000000 h6  (00 h&(  .] *\V+Zq*\V*[+[e&Y*\V*[*[*Z([-*\V*[*[)\+]M*\V*[*[*[I*\V*[*[*[I,Y.)[v*[*[*[I)\K)Z*[*[*[I-Y()Zq*[*[I)Z*[I*U ( @ *[**[*[3f*[)Z*Z0*[)Z*Z0,^.)W,*[)Z*Z0*\H)[*\N*[)Z*Z0*\H)Z)Z*Zz*[)Z*Z0*\H)Z)Z)Z)Z3f *[)Z*Z0*\H)Z)[)[)[*\UU*[)Z*Z0*\H)Z*[*[)Z*Z0*\H)Z*[*[)Z*Z0*\H)Z*[*[)Z*Z0*\H)Z*[*[)Z*Z0*\H)Z*[*[)Z*Z0*\H)Z*[UU*\V*Z`*Z`)Z)Z*Z0*\H)Z*[)\2)[)Z)Z)Z*Z0*\H)Z*[,Y*[)Z)Z*Z0*\H)Z*[*U*Z)Z*Z0*\H)Z*[)[j*Y+*\H)Z*[*\H)Z*[,Y)[*[,^.(0` (` *[I.],*Z)[*U.],*Z)Z*[3M .],*Z)Z*Z0`.],*Z)Z*Z0`3f )W,*U.],*Z)Z*Z0`*`*[)[{.] .],*Z)Z*Z0`*`)[)Z*Z,Y.],*Z)Z*Z0`*`)[)Z)Z)Z&Y(.],*Z)Z*Z0`*`)[)Z)Z)Z*Z*\N@.],*Z)Z*Z0`*`)[)Z)Z)Z)Z)Z)[k3f.],*Z)Z*Z0`*`)[)Z)Z)[)Z)Z)Z,Zc.],*Z)Z*Z0`*`)[)Z)Z*]B,]4,]4,]4.\2@.],*Z)Z*Z0`*`)[)Z)Z*c.],*Z)Z*Z0`*`)[)Z)Z*c.],*Z)Z*Z0`*`)[)Z)Z*c.],*Z)Z*Z0`*`)[)Z)Z*c.],*Z)Z*Z0`*`)[)Z)Z*c.],*Z)Z*Z0`*`)[)Z)Z*c.],*Z)Z*Z0`*`)[)Z)Z*c.],*Z)Z*Z0`*`)[)Z)Z*c.],*Z)Z*Z0`*`)[)Z)Z*c$m*[*[*[*[*Z)Z)Z*Z0`*`)[)Z)Z*c*\$)Z)Z)Z)Z)Z)Z*Z0`*`)[)Z)Z*c,W#)Z*Z)Z)Z)Z*Z0`*`)[)Z)Z*c'b *Zl)Z)Z)Z*Z0`*`)[)Z)Z*cUU*Y\)Z)Z*Z0`*`)[)Z)Z*c+ZA)Z)[0`*`)[)Z)Z*c)Z+ZX'b *`)[)Z)Z*c*`)[)Z)Z*c&Y)[)Z)Z*cU)\2)Z)Z*c*U)]k3Uaxios-axios-2d06f96/docs/fr/000077500000000000000000000000001521272452000156575ustar00rootroot00000000000000axios-axios-2d06f96/docs/fr/index.md000066400000000000000000000236031521272452000173140ustar00rootroot00000000000000--- # https://vitepress.dev/reference/default-theme-home-page layout: home hero: name: 'axios docs' text: 'axios est un client HTTP simple pour le navigateur et Node.js' image: dark: /logo.svg light: /logo-light.svg alt: axios actions: - theme: brand text: Démarrer link: /fr/pages/getting-started/first-steps - theme: alt text: Référence API link: /fr/pages/advanced/api-reference features: - title: Implémentation simple details: Démarrer avec axios est aussi simple qu'une seule ligne de code. Les requêtes API basiques peuvent être effectuées en 2 lignes de code. - title: Intercepteurs puissants details: Notre système d'intercepteurs innovant vous permet de contrôler le cycle de vie des requêtes et des réponses. Vous pouvez modifier les requêtes, les réponses et les erreurs. - title: Support TypeScript details: axios déclare des types et supporte pleinement TypeScript. Vous pouvez utiliser axios en toute confiance dans vos projets TypeScript. ---

Sponsors

{{ sponsor.name }}

{{ capitalizeFirstLetter(sponsor.tier) }}
axios-axios-2d06f96/docs/fr/pages/000077500000000000000000000000001521272452000167565ustar00rootroot00000000000000axios-axios-2d06f96/docs/fr/pages/advanced/000077500000000000000000000000001521272452000205235ustar00rootroot00000000000000axios-axios-2d06f96/docs/fr/pages/advanced/adapters.md000066400000000000000000000070141521272452000226520ustar00rootroot00000000000000# Adaptateurs Les adaptateurs vous permettent de personnaliser la façon dont axios gère les données de la requête. Par défaut, axios utilise une liste de priorité ordonnée `['xhr', 'http', 'fetch']` et sélectionne le premier adaptateur pris en charge par l'environnement actuel. En pratique, cela signifie que `xhr` est utilisé dans les navigateurs, `http` dans Node.js, et `fetch` dans les environnements où ni l'un ni l'autre n'est disponible (comme Cloudflare Workers ou Deno). Écrire votre propre adaptateur vous donne un contrôle total sur la façon dont axios effectue une requête et traite la réponse — utile pour les tests, les transports personnalisés ou les environnements non standard. ## Adaptateurs intégrés Vous pouvez sélectionner un adaptateur intégré par nom en utilisant l'option de configuration `adapter` : ```js // Utiliser l'adaptateur fetch const instance = axios.create({ adapter: "fetch" }); // Utiliser l'adaptateur XHR (par défaut dans les navigateurs) const instance = axios.create({ adapter: "xhr" }); // Utiliser l'adaptateur HTTP (par défaut dans Node.js) const instance = axios.create({ adapter: "http" }); ``` Vous pouvez également passer un tableau de noms d'adaptateurs. axios utilisera le premier pris en charge par l'environnement actuel : ```js const instance = axios.create({ adapter: ["fetch", "xhr", "http"] }); ``` Pour plus de détails sur l'adaptateur `fetch`, consultez la page [Adaptateur Fetch](/pages/advanced/fetch-adapter). ## Créer un adaptateur personnalisé Pour créer un adaptateur personnalisé, écrivez une fonction qui accepte un objet `config` et retourne une Promise qui se résout vers un objet de réponse axios valide. ```js import axios from "axios"; import { settle } from "axios/unsafe/core/settle.js"; function myAdapter(config) { /** * À ce stade : * - la configuration a été fusionnée avec les valeurs par défaut * - les transformateurs de requête ont été exécutés * - les intercepteurs de requête ont été exécutés * * L'adaptateur est maintenant responsable de l'exécution de la requête * et du retour d'un objet de réponse valide. */ return new Promise((resolve, reject) => { // Effectuez votre logique de requête personnalisée ici. // Cet exemple utilise l'API native fetch comme point de départ. fetch(config.url, { method: config.method?.toUpperCase() ?? "GET", headers: config.headers?.toJSON() ?? {}, body: config.data, signal: config.signal, }) .then(async (fetchResponse) => { const responseData = await fetchResponse.text(); const response = { data: responseData, status: fetchResponse.status, statusText: fetchResponse.statusText, headers: Object.fromEntries(fetchResponse.headers.entries()), config, request: null, }; // settle résout ou rejette la promise selon le statut HTTP settle(resolve, reject, response); /** * Après ce point : * - les transformateurs de réponse seront exécutés * - les intercepteurs de réponse seront exécutés */ }) .catch(reject); }); } const instance = axios.create({ adapter: myAdapter }); ``` ::: tip Le helper `settle` résout la promise pour les codes de statut 2xx et la rejette pour tout le reste, conformément au comportement par défaut d'axios. Si vous souhaitez une validation de statut personnalisée, utilisez plutôt l'option de configuration `validateStatus`. ::: axios-axios-2d06f96/docs/fr/pages/advanced/api-reference.md000066400000000000000000000260311521272452000235540ustar00rootroot00000000000000# Référence API Vous trouverez ci-dessous la liste de toutes les fonctions et classes disponibles dans le package axios. Ces fonctions peuvent être utilisées et importées dans votre projet. Elles sont toutes protégées par notre engagement renouvelé à respecter le versionnage sémantique. Vous pouvez donc compter sur leur stabilité dans les versions futures, sauf en cas de changement de version majeure. ## Instance L'instance `axios` est l'objet principal que vous utiliserez pour effectuer des requêtes HTTP. C'est une fonction fabrique qui crée une nouvelle instance de la classe `Axios`. L'instance `axios` dispose d'un certain nombre de méthodes pour effectuer des requêtes HTTP. Ces méthodes sont documentées dans la [section Alias de requête](/pages/advanced/request-method-aliases) de la documentation. ## Classes ### `Axios` La classe `Axios` est la classe principale que vous utiliserez pour effectuer des requêtes HTTP. C'est une fonction fabrique qui crée une nouvelle instance de la classe `Axios`. La classe `Axios` dispose d'un certain nombre de méthodes pour effectuer des requêtes HTTP. Ces méthodes sont documentées dans la [section Alias de requête](/pages/advanced/request-method-aliases) de la documentation. #### `constructor` Crée une nouvelle instance de la classe `Axios`. Le constructeur accepte un objet de configuration optionnel en argument. ```ts constructor(instanceConfig?: AxiosRequestConfig); ``` #### `request` Gère l'invocation de la requête et la résolution de la réponse. C'est la méthode principale pour effectuer des requêtes HTTP. Elle accepte un objet de configuration en argument et retourne une promise qui se résout vers l'objet de réponse. ```ts request(configOrUrl: string | AxiosRequestConfig, config: AxiosRequestConfig): Promise>; ``` ### `CancelToken` La classe `CancelToken` était basée sur la proposition `tc39/proposal-cancelable-promises`. Elle était utilisée pour créer un token permettant d'annuler une requête HTTP. La classe `CancelToken` est désormais dépréciée en faveur de l'API `AbortController`. Depuis la version 0.22.0, la classe `CancelToken` est dépréciée et sera supprimée dans une prochaine version. Il est recommandé d'utiliser l'API `AbortController` à la place. La classe est exportée principalement pour des raisons de rétrocompatibilité et sera supprimée dans une prochaine version. Nous déconseillons fortement son utilisation dans de nouveaux projets et ne documentons donc pas cette API. ## Fonctions ### `AxiosError` La classe `AxiosError` est une classe d'erreur levée lorsqu'une requête HTTP échoue. Elle étend la classe `Error` et ajoute des propriétés supplémentaires à l'objet d'erreur. #### `constructor` Crée une nouvelle instance de la classe `AxiosError`. Le constructeur accepte en argument un message, un code, une configuration, une requête et une réponse optionnels. ```ts constructor(message?: string, code?: string, config?: InternalAxiosRequestConfig, request?: any, response?: AxiosResponse); ``` #### `properties` La classe `AxiosError` fournit les propriétés suivantes : ```ts // Instance de config. config?: InternalAxiosRequestConfig; // Code d'erreur. code?: string; // Instance de requête. request?: any; // Instance de réponse. response?: AxiosResponse; // Booléen indiquant si l'erreur est une `AxiosError`. isAxiosError: boolean; // Code de statut HTTP de l'erreur. status?: number; // Méthode utilitaire pour convertir l'erreur en objet JSON. toJSON: () => object; // Cause de l'erreur. cause?: Error; ``` ### `AxiosHeaders` La classe `AxiosHeaders` est une classe utilitaire permettant de gérer les en-têtes HTTP. Elle fournit des méthodes pour manipuler les en-têtes, comme l'ajout, la suppression et la récupération d'en-têtes. Seules les méthodes principales sont documentées ici. Pour la liste complète des méthodes, référez-vous au fichier de déclaration de types. #### `constructor` Crée une nouvelle instance de la classe `AxiosHeaders`. Le constructeur accepte un objet d'en-têtes optionnel en argument. ```ts constructor(headers?: RawAxiosHeaders | AxiosHeaders | string); ``` #### `set` Ajoute un en-tête à l'objet d'en-têtes. Les noms d'en-têtes vides ou composés uniquement d'espaces sont ignorés. ```ts set(headerName?: string, value?: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders; set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean): AxiosHeaders; ``` #### `get` Récupère un en-tête depuis l'objet d'en-têtes. ```ts get(headerName: string, parser: RegExp): RegExpExecArray | null; get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue; ``` #### `has` Vérifie si un en-tête existe dans l'objet d'en-têtes. ```ts has(header: string, matcher?: AxiosHeaderMatcher): boolean; ``` #### `delete` Supprime un en-tête de l'objet d'en-têtes. ```ts delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean; ``` #### `clear` Supprime tous les en-têtes de l'objet d'en-têtes. ```ts clear(matcher?: AxiosHeaderMatcher): boolean; ``` #### `normalize` Normalise l'objet d'en-têtes. ```ts normalize(format: boolean): AxiosHeaders; ``` #### `concat` Concatène des objets d'en-têtes. ```ts concat(...targets: Array): AxiosHeaders; ``` #### `toJSON` Convertit l'objet d'en-têtes en objet JSON. ```ts toJSON(asStrings: true): Record; toJSON(asStrings?: false): Record; ``` ### `CanceledError` La classe `CanceledError` est une classe d'erreur levée lorsqu'une requête HTTP est annulée. Elle étend la classe `AxiosError`. ### `Cancel` La classe `Cancel` est un alias de la classe `CanceledError`. Elle est exportée pour des raisons de rétrocompatibilité et sera supprimée dans une prochaine version. ### `isCancel` Une fonction qui vérifie si une erreur est une `CanceledError`. Utile pour distinguer les annulations intentionnelles des erreurs inattendues. ```ts isCancel(value: any): value is CanceledError; ``` ```js import axios from "axios"; const controller = new AbortController(); axios.get("/api/data", { signal: controller.signal }).catch((error) => { if (axios.isCancel(error)) { console.log("Request was cancelled:", error.message); } else { console.error("Unexpected error:", error); } }); controller.abort("User navigated away"); ``` ### `isAxiosError` Une fonction qui vérifie si une erreur est une `AxiosError`. Utilisez-la dans les blocs `catch` pour accéder en toute sécurité aux propriétés spécifiques d'axios comme `error.response` et `error.config`. ```ts isAxiosError(value: any): value is AxiosError; ``` ```js import axios from "axios"; try { await axios.get("/api/resource"); } catch (error) { if (axios.isAxiosError(error)) { // error.response, error.config, error.code sont tous disponibles console.error("HTTP error", error.response?.status, error.message); } else { // Une erreur non-axios (ex. une erreur de programmation) throw error; } } ``` ### `all` La fonction `all` est une fonction utilitaire qui prend un tableau de promises et retourne une promise unique qui se résout lorsque toutes les promises du tableau sont résolues. La fonction `all` est désormais dépréciée en faveur de la méthode `Promise.all`. Il est recommandé d'utiliser `Promise.all` à la place. Depuis la version 0.22.0, la fonction `all` est dépréciée et sera supprimée dans une prochaine version. ### `spread` La fonction `spread` est une fonction utilitaire qui peut être utilisée pour décomposer un tableau d'arguments dans un appel de fonction. Utile lorsque vous avez un tableau d'arguments à passer à une fonction qui en accepte plusieurs. ```ts spread(callback: (...args: T[]) => R): (array: T[]) => R; ``` ### `toFormData` Convertit un objet JavaScript simple (ou imbriqué) en instance `FormData`. Utile pour construire programmatiquement des données de formulaire multipart à partir d'un objet. ```ts toFormData(sourceObj: object, formData?: FormData, options?: FormSerializerOptions): FormData; ``` ```js import { toFormData } from "axios"; const data = { name: "Jay", avatar: fileBlob }; const form = toFormData(data); // form est maintenant une instance FormData prête à être envoyée await axios.post("/api/users", form); ``` ### `formToJSON` Convertit une instance `FormData` en objet JavaScript simple. Utile pour lire les données d'un formulaire dans un format structuré. ```ts formToJSON(form: FormData): object; ``` ```js import { formToJSON } from "axios"; const form = new FormData(); form.append("name", "Jay"); form.append("role", "admin"); const obj = formToJSON(form); console.log(obj); // { name: "Jay", role: "admin" } ``` ### `getAdapter` Résout et retourne une fonction d'adaptateur par nom ou en passant un tableau de noms candidats. axios utilise ceci en interne pour sélectionner le meilleur adaptateur disponible pour l'environnement actuel. ```ts getAdapter(adapters: string | string[]): AxiosAdapter; ``` ```js import { getAdapter } from "axios"; // Obtenir explicitement l'adaptateur fetch const fetchAdapter = getAdapter("fetch"); // Obtenir le meilleur adaptateur disponible depuis une liste de priorité const adapter = getAdapter(["fetch", "xhr", "http"]); ``` ### `mergeConfig` Fusionne deux objets de configuration axios, en appliquant la même stratégie de fusion profonde qu'axios utilise en interne lors de la combinaison des valeurs par défaut avec les options par requête. Les valeurs ultérieures ont la priorité. ```ts mergeConfig(config1: AxiosRequestConfig, config2: AxiosRequestConfig): AxiosRequestConfig; ``` ```js import { mergeConfig } from "axios"; const base = { baseURL: "https://api.example.com", timeout: 5000 }; const override = { timeout: 10000, headers: { "X-Custom": "value" } }; const merged = mergeConfig(base, override); // { baseURL: "https://api.example.com", timeout: 10000, headers: { "X-Custom": "value" } } ``` ## Constantes ### `HttpStatusCode` Un objet contenant une liste de codes de statut HTTP sous forme de constantes nommées. Utilisez-le pour écrire des conditions lisibles plutôt que des nombres bruts. ```js import axios, { HttpStatusCode } from "axios"; try { const response = await axios.get("/api/resource"); } catch (error) { if (axios.isAxiosError(error)) { if (error.response?.status === HttpStatusCode.NotFound) { console.error("Resource not found"); } else if (error.response?.status === HttpStatusCode.Unauthorized) { console.error("Authentication required"); } } } ``` ## Divers ### `VERSION` La version actuelle du package `axios`. Il s'agit d'une chaîne représentant le numéro de version du package, mise à jour à chaque nouvelle version. axios-axios-2d06f96/docs/fr/pages/advanced/authentication.md000066400000000000000000000113541521272452000240700ustar00rootroot00000000000000# Authentification La plupart des APIs requièrent une forme d'authentification. Cette page couvre les schémas les plus courants pour attacher des identifiants aux requêtes axios. ## Tokens Bearer (JWT) L'approche la plus courante consiste à attacher un JWT dans l'en-tête `Authorization`. La façon la plus propre de procéder est via un intercepteur de requête sur votre instance axios, afin que le token soit lu à jour à chaque requête : ```js import axios from "axios"; const api = axios.create({ baseURL: "https://api.example.com" }); api.interceptors.request.use((config) => { const token = localStorage.getItem("access_token"); if (token) { config.headers.set("Authorization", `Bearer ${token}`); } return config; }); ``` ## Authentification HTTP Basic Pour les APIs utilisant l'authentification HTTP Basic, passez l'option `auth`. axios encodera les identifiants et définira automatiquement l'en-tête `Authorization` : ```js const response = await axios.get("https://api.example.com/data", { auth: { username: "myUser", password: "myPassword", }, }); ``` Si `auth` n'est pas fourni, les adaptateurs HTTP Node.js et fetch peuvent aussi déduire les identifiants Basic depuis l'URL de requête, par exemple `https://myUser:myPassword@api.example.com/data`. Les identifiants encodés en pourcentage dans l'URL sont décodés avant la génération de l'en-tête `Authorization`. Pour le nouveau code, préférez l'option explicite `auth` ; elle prend le dessus sur les identifiants intégrés à l'URL. ::: tip Pour les tokens Bearer et les clés API, utilisez un en-tête `Authorization` personnalisé plutôt que l'option `auth` — `auth` est réservé à l'authentification HTTP Basic. ::: ## Clés API Les clés API sont généralement passées sous forme d'en-tête ou de paramètre de requête, selon ce qu'attend l'API : ```js // En tant qu'en-tête const api = axios.create({ baseURL: "https://api.example.com", headers: { "X-API-Key": "your-api-key-here" }, }); // En tant que paramètre de requête const response = await axios.get("https://api.example.com/data", { params: { apiKey: "your-api-key-here" }, }); ``` ## Renouvellement de token Lorsque les tokens d'accès expirent, vous devez les renouveler silencieusement et réessayer la requête échouée. Un intercepteur de réponse est l'endroit idéal pour implémenter cela : ```js import axios from "axios"; const api = axios.create({ baseURL: "https://api.example.com" }); // Suivre si un renouvellement est déjà en cours pour éviter des appels parallèles let isRefreshing = false; let failedQueue = []; const processQueue = (error, token = null) => { failedQueue.forEach((prom) => { if (error) { prom.reject(error); } else { prom.resolve(token); } }); failedQueue = []; }; api.interceptors.response.use( (response) => response, async (error) => { const originalRequest = error.config; if (error.response?.status === 401 && !originalRequest._retry) { if (isRefreshing) { // Mettre la requête en file d'attente jusqu'à la fin du renouvellement return new Promise((resolve, reject) => { failedQueue.push({ resolve, reject }); }) .then((token) => { originalRequest.headers["Authorization"] = `Bearer ${token}`; return api(originalRequest); }) .catch((err) => Promise.reject(err)); } originalRequest._retry = true; isRefreshing = true; try { const { data } = await axios.post("/auth/refresh", { refreshToken: localStorage.getItem("refresh_token"), }); const newToken = data.access_token; localStorage.setItem("access_token", newToken); api.defaults.headers.common["Authorization"] = `Bearer ${newToken}`; processQueue(null, newToken); return api(originalRequest); } catch (refreshError) { processQueue(refreshError, null); // Rediriger vers la connexion ou émettre un événement localStorage.removeItem("access_token"); window.location.href = "/login"; return Promise.reject(refreshError); } finally { isRefreshing = false; } } return Promise.reject(error); } ); ``` ## Authentification par cookie Pour les APIs basées sur les sessions qui s'appuient sur les cookies, définissez `withCredentials: true` pour inclure les cookies dans les requêtes cross-origin : ```js const api = axios.create({ baseURL: "https://api.example.com", withCredentials: true, // envoyer les cookies avec chaque requête }); ``` ::: warning `withCredentials: true` exige que le serveur réponde avec `Access-Control-Allow-Credentials: true` et un `Access-Control-Allow-Origin` spécifique (pas de joker). ::: axios-axios-2d06f96/docs/fr/pages/advanced/cancellation.md000066400000000000000000000043261521272452000235060ustar00rootroot00000000000000# Annulation À partir de la version v0.22.0, Axios prend en charge AbortController pour annuler les requêtes de manière propre. Cette fonctionnalité est disponible dans le navigateur et dans Node.js lorsque vous utilisez une version d'Axios qui prend en charge AbortController. Pour annuler une requête, vous devez créer une instance d'`AbortController` et passer son `signal` à l'option `signal` de la requête. ```js const controller = new AbortController(); axios .get("/foo/bar", { signal: controller.signal, }) .then(function (response) { //... }); // annuler la requête controller.abort(); ``` ## CancelToken Vous pouvez également utiliser l'API `CancelToken` pour annuler les requêtes. Cette API est dépréciée et sera supprimée dans la prochaine version majeure. Il est recommandé d'utiliser `AbortController` à la place. Vous pouvez créer un token d'annulation en utilisant la factory `CancelToken.source` comme indiqué ci-dessous : ```js const CancelToken = axios.CancelToken; const source = CancelToken.source(); axios .get("/user/12345", { cancelToken: source.token, }) .catch(function (thrown) { if (axios.isCancel(thrown)) { console.log("Request canceled", thrown.message); } else { // gérer l'erreur } }); axios.post( "/user/12345", { name: "new name", }, { cancelToken: source.token, } ); // annuler la requête (le paramètre message est optionnel) source.cancel("Operation canceled by the user."); ``` Vous pouvez également créer un token d'annulation en passant une fonction d'exécution au constructeur `CancelToken` : ```js const CancelToken = axios.CancelToken; let cancel; axios.get("/user/12345", { cancelToken: new CancelToken(function executor(c) { // Une fonction d'exécution reçoit une fonction d'annulation comme paramètre cancel = c; }), }); // annuler la requête cancel(); ``` Vous pouvez annuler plusieurs requêtes avec le même token d'annulation ou le même abort controller. Si un token d'annulation est déjà annulé au moment où une requête Axios démarre, alors la requête est annulée immédiatement, sans aucune tentative d'effectuer une vraie requête. axios-axios-2d06f96/docs/fr/pages/advanced/config-defaults.md000066400000000000000000000051001521272452000241130ustar00rootroot00000000000000# Valeurs par défaut de configuration axios vous permet de spécifier des valeurs par défaut de configuration qui seront appliquées à toutes les requêtes. Vous pouvez définir des valeurs par défaut pour `baseURL`, `headers`, `timeout` et d'autres propriétés. Voici un exemple d'utilisation des valeurs par défaut de configuration : ```js axios.defaults.baseURL = "https://jsonplaceholder.typicode.com/posts"; axios.defaults.headers.common["Authorization"] = AUTH_TOKEN; axios.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded"; ``` ::: warning Les en-têtes globaux sont envoyés à chaque hôte Si votre application communique avec plus d'un domaine, définir `axios.defaults.headers.common["Authorization"]` enverra le token à **tous** ces domaines, y compris à des APIs tierces que vous ne contrôlez peut-être pas. Utilisez une [instance personnalisée](#valeurs-par-défaut-d-une-instance-personnalisée) avec une `baseURL` limitée pour tout client qui transporte des identifiants. ::: ## Valeurs par défaut d'une instance personnalisée Les instances axios sont déclarées avec leurs propres valeurs par défaut lors de leur création. Ces valeurs par défaut peuvent être remplacées en définissant la propriété `defaults` de l'instance. Voici un exemple d'utilisation des valeurs par défaut d'une instance personnalisée : ```js var instance = axios.create({ baseURL: "https://jsonplaceholder.typicode.com/posts", timeout: 1000, headers: { Authorization: "foobar" }, }); instance.defaults.headers.common["Authorization"] = AUTH_TOKEN; ``` ## Ordre de priorité de la configuration La configuration est fusionnée selon un ordre de priorité. L'ordre est le suivant : d'abord les valeurs par défaut de la bibliothèque, puis les propriétés par défaut de l'instance, et enfin l'argument de configuration de la requête. Voici un exemple de cet ordre de priorité : Créons d'abord une instance avec les valeurs par défaut fournies par la bibliothèque. À ce stade, la valeur de configuration du timeout est `0`, valeur par défaut de la bibliothèque. ```js const instance = axios.create(); ``` Nous allons maintenant remplacer la valeur par défaut du timeout pour l'instance par `2500` millisecondes. Désormais, toutes les requêtes utilisant cette instance attendront 2,5 secondes avant d'expirer. ```js instance.defaults.timeout = 2500; ``` Enfin, nous allons effectuer une requête avec un timeout de `5000` millisecondes. Cette requête attendra 5 secondes avant d'expirer. ```js instance.get("/longRequest", { timeout: 5000, }); ``` axios-axios-2d06f96/docs/fr/pages/advanced/create-an-instance.md000066400000000000000000000057101521272452000245110ustar00rootroot00000000000000# Créer une instance `axios.create()` vous permet de créer une instance axios préconfigurée. L'instance partage la même API de requête et de réponse que l'objet `axios` par défaut, mais utilise la configuration que vous fournissez comme base pour chaque requête. C'est la façon recommandée d'utiliser axios dans toute application dépassant un seul fichier. ```ts import axios from "axios"; const instance = axios.create({ baseURL: "https://api.example.com", timeout: 5000, headers: { "X-Custom-Header": "foobar" }, }); ``` La méthode `create` accepte l'objet complet de [Configuration de requête](/pages/advanced/request-config). Vous pouvez ensuite utiliser l'instance exactement comme l'objet axios par défaut : ```js const response = await instance.get("/users/1"); ``` ## Pourquoi utiliser une instance ? ### URL de base par service Dans la plupart des applications, vous communiquez avec plusieurs API. Créer une instance distincte par service évite de répéter l'URL de base à chaque appel : ```js const githubApi = axios.create({ baseURL: "https://api.github.com" }); const internalApi = axios.create({ baseURL: "https://api.internal.example.com" }); const { data: repos } = await githubApi.get("/users/axios/repos"); const { data: users } = await internalApi.get("/users"); ``` ### En-têtes d'authentification partagés Attachez un token d'authentification à chaque requête d'une instance sans toucher aux autres : ```js const authApi = axios.create({ baseURL: "https://api.example.com", headers: { Authorization: `Bearer ${getToken()}`, }, }); ``` ### Délais d'attente et nouvelles tentatives par service Différents services ont des caractéristiques de fiabilité différentes. Définissez un délai court pour les services temps réel et un délai long pour les traitements par lots : ```js const realtimeApi = axios.create({ baseURL: "https://realtime.example.com", timeout: 2000 }); const batchApi = axios.create({ baseURL: "https://batch.example.com", timeout: 60000 }); ``` ### Intercepteurs isolés Les intercepteurs ajoutés à une instance ne s'appliquent qu'à cette instance, ce qui permet de bien séparer les responsabilités : ```js const loggingApi = axios.create({ baseURL: "https://api.example.com" }); loggingApi.interceptors.request.use((config) => { console.log(`→ ${config.method?.toUpperCase()} ${config.url}`); return config; }); ``` ## Surcharger les valeurs par défaut par requête La configuration passée au moment de la requête remplace toujours les valeurs par défaut de l'instance : ```js const api = axios.create({ timeout: 5000 }); // Cette requête spécifique utilise un délai de 30 secondes à la place await api.get("/slow-endpoint", { timeout: 30000 }); ``` ::: tip Les valeurs par défaut de l'instance peuvent également être modifiées après sa création en écrivant dans `instance.defaults` : ```js instance.defaults.headers.common["Authorization"] = `Bearer ${newToken}`; ``` ::: axios-axios-2d06f96/docs/fr/pages/advanced/error-handling.md000066400000000000000000000173321521272452000237660ustar00rootroot00000000000000# Gestion des erreurs axios peut lever de nombreux types d'erreurs différents. Certaines de ces erreurs sont causées par axios lui-même, tandis que d'autres sont causées par le serveur ou le client. Le tableau suivant liste la structure générale de l'erreur levée : | Propriété | Définition | | --------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | message | Un résumé rapide du message d'erreur et du statut avec lequel elle a échoué. | | name | Définit l'origine de l'erreur. Pour axios, ce sera toujours une `AxiosError`. | | stack | Fournit la trace de pile de l'erreur. | | config | Un objet de configuration axios avec les configurations d'instance spécifiques définies par l'utilisateur au moment de la requête. | | code | Représente une erreur identifiée par axios. Le tableau ci-dessous liste les définitions spécifiques des erreurs internes d'axios. | | status | Code de statut de la réponse HTTP. Consultez [ici](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) pour la signification des codes de statut HTTP courants. | Voici une liste des erreurs potentielles identifiées par axios : | Code | Définition | | ------------------------- | --------------------------------------------------------------------------------------------- | | ERR_BAD_OPTION_VALUE | Valeur invalide ou non supportée fournie dans la configuration axios. | | ERR_BAD_OPTION | Option invalide fournie dans la configuration axios. | | ECONNABORTED | Indique généralement que la requête a expiré (sauf si `transitional.clarifyTimeoutError` est défini) ou a été abandonnée par le navigateur ou son plugin. | | ETIMEDOUT | La requête a expiré en dépassant la limite de temps par défaut d'axios. `transitional.clarifyTimeoutError` doit être défini à `true`, sinon une erreur générique `ECONNABORTED` sera levée à la place. | | ERR_NETWORK | Problème lié au réseau. Dans le navigateur, cette erreur peut également être causée par une violation de politique [CORS](https://developer.mozilla.org/ru/docs/Web/HTTP/Guides/CORS) ou de [contenu mixte](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content). Le navigateur ne permet pas au code JS de clarifier la raison réelle de l'erreur pour des raisons de sécurité ; veuillez vérifier la console. | | ERR_FR_TOO_MANY_REDIRECTS | La requête est redirigée trop de fois ; dépasse le nombre maximum de redirections spécifié dans la configuration axios. | | ERR_DEPRECATED | Fonctionnalité ou méthode dépréciée utilisée dans axios. | | ERR_BAD_RESPONSE | La réponse ne peut pas être analysée correctement ou est dans un format inattendu. Généralement lié à une réponse avec un code de statut `5xx`. | | ERR_BAD_REQUEST | La requête a un format inattendu ou des paramètres requis manquants. Généralement lié à une réponse avec un code de statut `4xx`. | | ERR_CANCELED | Fonctionnalité ou méthode annulée explicitement par l'utilisateur via un AbortSignal (ou un CancelToken). | | ERR_NOT_SUPPORT | Fonctionnalité ou méthode non supportée dans l'environnement axios actuel. | | ERR_INVALID_URL | URL invalide fournie pour la requête axios. | | ERR_FORM_DATA_DEPTH_EXCEEDED | Un objet dépasse la `maxDepth` configurée lors de la sérialisation de `params` ou des données de formulaire. La limite par défaut est de 100 niveaux. Voir [`paramsSerializer`](/pages/advanced/request-config#paramsserializer) et [`formSerializer`](/pages/advanced/request-config#formserializer). | ## Gérer les erreurs Le comportement par défaut d'axios est de rejeter la promise si la requête échoue. Cependant, vous pouvez également capturer l'erreur et la gérer comme bon vous semble. Voici un exemple de capture d'une erreur : ```js axios.get("/user/12345").catch(function (error) { if (error.response) { // La requête a été effectuée et le serveur a répondu avec un code de statut // qui n'est pas dans la plage 2xx console.log(error.response.data); console.log(error.response.status); console.log(error.response.headers); } else if (error.request) { // La requête a été effectuée mais aucune réponse n'a été reçue // `error.request` est une instance de XMLHttpRequest dans le navigateur et une instance de // http.ClientRequest dans Node.js console.log(error.request); } else { // Quelque chose s'est produit lors de la configuration de la requête qui a déclenché une erreur console.log("Error", error.message); } console.log(error.config); }); ``` En utilisant l'option de configuration `validateStatus`, vous pouvez remplacer la condition par défaut (status >= 200 && status < 300) et définir le ou les codes HTTP qui doivent lever une erreur. ```js axios.get("/user/12345", { validateStatus: function (status) { return status < 500; // Résoudre uniquement si le code de statut est inférieur à 500 }, }); ``` En utilisant la méthode `toJSON`, vous pouvez obtenir un objet avec plus d'informations sur l'erreur. ```js axios.get("/user/12345").catch(function (error) { console.log(error.toJSON()); }); ``` Pour éviter de journaliser des secrets depuis `error.config`, passez un tableau `redact` dans la configuration de la requête. Les clés de configuration correspondantes sont masquées de manière insensible à la casse à n'importe quelle profondeur lorsque `AxiosError#toJSON()` est appelée. ```js axios.get("/user/12345", { headers: { Authorization: "Bearer token" }, redact: ["authorization"] }).catch(function (error) { console.log(error.toJSON().config.headers.Authorization); // [REDACTED ****] }); ``` ## Gestion des délais d'attente Lorsqu'une requête dépasse son `timeout` configuré, axios rejette avec `ECONNABORTED` par défaut. Définissez `transitional.clarifyTimeoutError: true` pour recevoir `ETIMEDOUT` à la place, ce qui rend les erreurs de délai d'attente plus faciles à distinguer des autres abandons. ```js async function fetchWithTimeout() { try { const response = await axios.get("https://example.com/data", { timeout: 5000, // 5 secondes transitional: { // définir à true si vous préférez ETIMEDOUT à ECONNABORTED clarifyTimeoutError: true, }, }); console.log("Response:", response.data); } catch (error) { if (axios.isAxiosError(error)) { if (error.code === "ECONNABORTED" || error.code === "ETIMEDOUT") { console.error("Request timed out. Please try again."); return; } console.error("Axios error:", error.message); return; } console.error("Unexpected error:", error); } } ``` ::: tip Définissez toujours un `timeout` en production Sans cela, une requête bloquée peut rester en attente indéfiniment. Consultez [`timeout`](/pages/advanced/request-config#timeout) et [`transitional.clarifyTimeoutError`](/pages/advanced/request-config#transitional) pour les options de configuration correspondantes. ::: axios-axios-2d06f96/docs/fr/pages/advanced/fetch-adapter.md000066400000000000000000000076711521272452000235670ustar00rootroot00000000000000# Adaptateur Fetch L'adaptateur `fetch` est un nouvel adaptateur introduit à partir de la version 1.7.0. Il permet d'utiliser axios avec l'API `fetch`, vous offrant ainsi le meilleur des deux mondes. Par défaut, `fetch` sera utilisé si les adaptateurs `xhr` et `http` ne sont pas disponibles dans le build, ou non supportés par l'environnement. Pour l'utiliser par défaut, il doit être sélectionné explicitement en définissant l'option `adapter` à `fetch` lors de la création d'une instance axios. ```js import axios from 'axios'; const instance = axios.create({ adapter: 'fetch', }); ``` L'adaptateur supporte les mêmes fonctionnalités que l'adaptateur `xhr`, notamment la capture de la progression des envois et téléchargements. Il supporte également des types de réponse supplémentaires tels que `stream` et `formdata` (si l'environnement les prend en charge). Lorsque `auth` est omis, l'adaptateur fetch peut lire les identifiants HTTP Basic depuis l'URL de requête, par exemple `https://user:pass@example.com`. Les identifiants d'URL encodés en pourcentage sont décodés avant la génération de l'en-tête `Authorization`, et `auth` prend le dessus sur les identifiants intégrés à l'URL. ## Fetch personnalisé À partir de `v1.12.0`, vous pouvez personnaliser l'adaptateur fetch pour utiliser une fonction `fetch` personnalisée au lieu de celle de l'environnement global. Vous pouvez passer une fonction `fetch`, ainsi que des constructeurs `Request` et `Response` personnalisés via l'option de configuration `env`. Cela est utile lorsque vous travaillez avec des environnements personnalisés ou des frameworks d'application qui fournissent leur propre implémentation de `fetch`. ::: info Lorsque vous utilisez une fonction `fetch` personnalisée, vous devrez peut-être également fournir des constructeurs `Request` et `Response` correspondants. Si vous les omettez, les constructeurs globaux seront utilisés. Si votre `fetch` personnalisé est incompatible avec les constructeurs globaux, passez `null` pour les désactiver. **Remarque :** Définir `Request` et `Response` à `null` rendra impossible pour l'adaptateur fetch de capturer la progression des envois et téléchargements. ::: ### Exemple de base ```js import customFetchFunction from 'customFetchModule'; const instance = axios.create({ adapter: 'fetch', onDownloadProgress(e) { console.log('downloadProgress', e); }, env: { fetch: customFetchFunction, Request: null, // null -> désactiver le constructeur Response: null, }, }); ``` ### Utilisation avec Tauri [Tauri](https://tauri.app/plugin/http-client/) fournit une fonction `fetch` de plateforme qui contourne les restrictions CORS du navigateur pour les requêtes effectuées depuis la couche native. L'exemple ci-dessous montre une configuration minimale pour utiliser axios dans une application Tauri avec ce fetch personnalisé. ```js import { fetch } from '@tauri-apps/plugin-http'; import axios from 'axios'; const instance = axios.create({ adapter: 'fetch', onDownloadProgress(e) { console.log('downloadProgress', e); }, env: { fetch, }, }); const { data } = await instance.get('https://google.com'); ``` ### Utilisation avec SvelteKit [SvelteKit](https://svelte.dev/docs/kit/web-standards#Fetch-APIs) fournit une implémentation `fetch` personnalisée pour les fonctions `load` côté serveur qui gère la transmission des cookies et les URLs relatives. Comme son `fetch` est incompatible avec l'API `URL` standard, axios doit être configuré pour l'utiliser explicitement, et les constructeurs `Request` et `Response` globaux doivent être désactivés. ```js export async function load({ fetch }) { const { data: post } = await axios.get('https://jsonplaceholder.typicode.com/posts/1', { adapter: 'fetch', env: { fetch, Request: null, Response: null, }, }); return { post }; } ``` axios-axios-2d06f96/docs/fr/pages/advanced/file-posting.md000066400000000000000000000064011521272452000234460ustar00rootroot00000000000000# Envoi de fichiers axios simplifie l'envoi de fichiers. Utilisez `postForm` ou `FormData` lorsque vous avez besoin d'envois `multipart/form-data`. ## Fichier unique (navigateur) Passez un objet `File` directement comme valeur de champ — axios le détectera et utilisera automatiquement le type de contenu correct : ```js await axios.postForm("https://httpbin.org/post", { description: "My profile photo", file: document.querySelector("#fileInput").files[0], }); ``` ## Plusieurs fichiers (navigateur) Passez une `FileList` pour envoyer tous les fichiers sélectionnés en une seule fois. Ils seront tous envoyés sous le même nom de champ (`files[]`) : ```js await axios.postForm( "https://httpbin.org/post", document.querySelector("#fileInput").files ); ``` Vous pouvez également passer la `FileList` (ou un tableau d'objets `File`) explicitement sous un nom de champ personnalisé en ajoutant `[]` à la clé : ```js await axios.postForm("https://httpbin.org/post", { "files[]": document.querySelector("#fileInput").files, }); ``` Pour utiliser des noms de champs distincts pour chaque fichier, construisez un objet `FormData` manuellement : ```js const formData = new FormData(); formData.append("avatar", avatarFile); formData.append("cover", coverFile); await axios.post("https://httpbin.org/post", formData); ``` ## Suivi de la progression de l'envoi (navigateur) Utilisez le callback `onUploadProgress` pour afficher une barre de progression ou un pourcentage à vos utilisateurs : ```js await axios.postForm("https://httpbin.org/post", { file: document.querySelector("#fileInput").files[0], }, { onUploadProgress: (progressEvent) => { const percent = Math.round( (progressEvent.loaded * 100) / progressEvent.total ); console.log(`Upload progress: ${percent}%`); }, }); ``` Consultez [Capture de progression](/pages/advanced/progress-capturing) pour la liste complète des champs disponibles sur l'événement de progression. ## Fichiers dans Node.js Dans Node.js, utilisez `fs.createReadStream` pour envoyer un fichier depuis le système de fichiers sans le charger entièrement en mémoire : ```js import fs from "fs"; import FormData from "form-data"; import axios from "axios"; const form = new FormData(); form.append("file", fs.createReadStream("/path/to/file.jpg")); form.append("description", "My uploaded file"); await axios.post("https://httpbin.org/post", form); ``` ::: tip Le package npm `form-data` est nécessaire dans les environnements Node.js pour créer des objets `FormData`. Dans Node.js moderne (v18+), le `FormData` global est disponible nativement. ::: ## Envoi d'un Buffer (Node.js) Vous pouvez également envoyer directement un `Buffer` en mémoire : ```js const buffer = Buffer.from("Hello, world!"); const form = new FormData(); form.append("file", buffer, { filename: "hello.txt", contentType: "text/plain", knownLength: buffer.length, }); await axios.post("https://httpbin.org/post", form); ``` ::: warning La capture de la progression d'envoi de `FormData` n'est actuellement pas supportée dans les environnements Node.js. ::: ::: danger Lors de l'envoi d'un stream lisible dans Node.js, définissez `maxRedirects: 0` pour empêcher le package `follow-redirects` de buffériser l'intégralité du stream en RAM. ::: axios-axios-2d06f96/docs/fr/pages/advanced/header-methods.md000066400000000000000000000171071521272452000237440ustar00rootroot00000000000000# Méthodes d'en-têtes Avec l'introduction de la nouvelle classe `AxiosHeaders`, Axios fournit un ensemble de méthodes pour manipuler les en-têtes. Ces méthodes sont utilisées pour définir, récupérer et supprimer des en-têtes de manière plus pratique que la manipulation directe de l'objet d'en-têtes. ## Constructeur `new AxiosHeaders(headers?)` Le constructeur de la classe `AxiosHeaders` accepte un objet optionnel avec des en-têtes pour initialiser l'instance. L'objet d'en-têtes peut contenir un nombre quelconque d'en-têtes, et les clés sont insensibles à la casse. ```js constructor(headers?: RawAxiosHeaders | AxiosHeaders | string); ``` Pour plus de commodité, vous pouvez passer une chaîne avec des en-têtes séparés par un caractère de nouvelle ligne. Les en-têtes sont alors analysés et ajoutés à l'instance. ```js const headers = new AxiosHeaders(` Host: www.bing.com User-Agent: curl/7.54.0 Accept: */*`); console.log(headers); // Object [AxiosHeaders] { // host: 'www.bing.com', // 'user-agent': 'curl/7.54.0', // accept: '*/*' // } ``` ## Set La méthode `set` est utilisée pour définir des en-têtes sur l'instance d'`AxiosHeaders`. La méthode peut être appelée avec un seul nom d'en-tête et une valeur, un objet avec plusieurs en-têtes, ou une chaîne avec des en-têtes séparés par un caractère de nouvelle ligne. La méthode accepte également un paramètre optionnel `rewrite` qui contrôle le comportement de définition de l'en-tête. ```js set(headerName, value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher); set(headerName, value, rewrite?: (this: AxiosHeaders, value: string, name: string) => boolean); set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean); ``` L'argument `rewrite` contrôle le comportement d'écrasement : - `false` - ne pas écraser si la valeur de l'en-tête est définie (n'est pas undefined) - `undefined` (défaut) - écraser l'en-tête sauf si sa valeur est définie à false - `true` - écraser dans tous les cas L'option peut également accepter une fonction définie par l'utilisateur qui détermine si la valeur doit être écrasée ou non. La fonction reçoit la valeur actuelle, le nom de l'en-tête et l'objet d'en-têtes comme arguments. Les noms d'en-têtes vides ou composés uniquement d'espaces sont ignorés. `AxiosHeaders` conserve la casse de la première clé correspondante qu'il voit. Vous pouvez utiliser cela pour préserver la casse spécifique d'un en-tête en initialisant une clé avec `undefined` puis en définissant les valeurs ultérieurement. Voir [Préserver la casse d'un en-tête spécifique](/pages/advanced/headers#preserving-a-specific-header-case). ## Get La méthode `get` est utilisée pour récupérer la valeur d'un en-tête. La méthode peut être appelée avec un seul nom d'en-tête, un matcher optionnel ou un analyseur. Le matcher est par défaut `true`. L'analyseur peut être une expression régulière utilisée pour extraire la valeur de l'en-tête. ```js get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue; get(headerName: string, parser: RegExp): RegExpExecArray | null; ``` Voici un exemple de quelques-unes des utilisations possibles de la méthode `get` : ```js const headers = new AxiosHeaders({ 'Content-Type': 'multipart/form-data; boundary=Asrf456BGe4h', }); console.log(headers.get('Content-Type')); // multipart/form-data; boundary=Asrf456BGe4h console.log(headers.get('Content-Type', true)); // analyser les paires clé-valeur depuis une chaîne séparée par des délimiteurs \s,;= : // [Object: null prototype] { // 'multipart/form-data': undefined, // boundary: 'Asrf456BGe4h' // } console.log( headers.get('Content-Type', (value, name, headers) => { return String(value).replace(/a/g, 'ZZZ'); }) ); // multipZZZrt/form-dZZZtZZZ; boundZZZry=Asrf456BGe4h console.log(headers.get('Content-Type', /boundary=(\w+)/)?.[0]); // boundary=Asrf456BGe4h ``` ## Has La méthode `has` est utilisée pour vérifier si un en-tête existe dans l'instance d'`AxiosHeaders`. La méthode peut être appelée avec un seul nom d'en-tête et un matcher optionnel. ```js has(header: string, matcher?: AxiosHeaderMatcher): boolean; ``` ::: info Retourne true si l'en-tête est défini (n'a pas de valeur undefined). ::: ## Delete La méthode `delete` est utilisée pour supprimer un en-tête de l'instance d'`AxiosHeaders`. La méthode peut être appelée avec un seul nom d'en-tête et un matcher optionnel. ```js delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean; ``` ::: info Retourne true si au moins un en-tête a été supprimé. ::: ## Clear La méthode `clear` est utilisée pour supprimer tous les en-têtes de l'instance d'`AxiosHeaders` si rien n'est passé. Si un matcher est passé, seuls les en-têtes correspondant au matcher sont supprimés ; dans ce cas, le matcher est utilisé pour correspondre au nom de l'en-tête plutôt qu'à sa valeur. ```js clear(matcher?: AxiosHeaderMatcher): boolean; ``` ::: info Retourne true si au moins un en-tête a été effacé. ::: ## Normalize Si l'objet d'en-têtes a été modifié directement, cela peut créer des doublons avec le même nom mais dans des casses différentes. Cette méthode normalise l'objet d'en-têtes en combinant les clés dupliquées en une seule. Axios utilise cette méthode en interne après l'appel de chaque intercepteur. Définissez `format` à `true` pour convertir les noms d'en-têtes en minuscules et capitaliser les premières lettres (cOntEnt-type => Content-Type) ou `false` pour conserver le format original. ```js const headers = new AxiosHeaders({ foo: '1', }); headers.Foo = '2'; headers.FOO = '3'; console.log(headers.toJSON()); // [Object: null prototype] { foo: '1', Foo: '2', FOO: '3' } console.log(headers.normalize().toJSON()); // [Object: null prototype] { foo: '3' } console.log(headers.normalize(true).toJSON()); // [Object: null prototype] { Foo: '3' } ``` ::: info Retourne `this` pour le chaînage. ::: ## Concat Fusionne l'instance avec des cibles dans une nouvelle instance AxiosHeaders. Si la cible est une chaîne, elle sera analysée comme des en-têtes HTTP bruts. Si la cible est une instance AxiosHeaders, elle sera fusionnée avec l'instance actuelle. Utile pour les préréglages de casse lors de la composition d'en-têtes. Par exemple : ```js const headers = AxiosHeaders.concat( { 'content-type': undefined }, { 'Content-Type': 'application/octet-stream' } ); ``` ```js concat(...targets: Array): AxiosHeaders; ``` ::: info Retourne une nouvelle instance AxiosHeaders. ::: ## toJSON Résout toutes les valeurs d'en-têtes internes dans un nouvel objet à prototype null. Définissez `asStrings` à true pour résoudre les tableaux en une chaîne contenant tous les éléments, séparés par des virgules. ```js toJSON(asStrings: true): Record; toJSON(asStrings?: false): Record; ``` ## From Retourne une nouvelle instance d'`AxiosHeaders` créée à partir des en-têtes bruts passés, ou retourne simplement l'objet d'en-têtes donné s'il s'agit déjà d'une instance d'`AxiosHeaders`. ```js from(thing?: AxiosHeaders | RawAxiosHeaders | string): AxiosHeaders; ``` ## Raccourcis Les raccourcis suivants sont disponibles : - `setContentType`, `getContentType`, `hasContentType` - `setContentLength`, `getContentLength`, `hasContentLength` - `setAccept`, `getAccept`, `hasAccept` - `setUserAgent`, `getUserAgent`, `hasUserAgent` - `setContentEncoding`, `getContentEncoding`, `hasContentEncoding` axios-axios-2d06f96/docs/fr/pages/advanced/headers.md000066400000000000000000000127731521272452000224720ustar00rootroot00000000000000# En-têtes Axios expose sa propre classe AxiosHeaders pour manipuler les en-têtes en utilisant une API de type Map qui garantit des clés insensibles à la casse. Cette classe est utilisée en interne par Axios pour gérer les en-têtes, mais elle est également exposée à l'utilisateur pour plus de commodité. Bien que les en-têtes HTTP soient insensibles à la casse, Axios conservera la casse de l'en-tête original pour des raisons stylistiques et comme solution de contournement lorsque des serveurs tiennent incorrectement compte de la casse des en-têtes. L'ancienne méthode de manipulation directe de l'objet d'en-têtes est toujours disponible, mais dépréciée et non recommandée pour un usage futur. ## Travailler avec les en-têtes L'instance d'objet AxiosHeaders peut contenir différents types de valeurs internes qui contrôlent la logique de définition et de fusion. L'objet d'en-têtes final est obtenu par Axios en appelant la méthode toJSON. L'objet AxiosHeaders est également itérable, vous pouvez donc l'utiliser dans des boucles ou le convertir en tableau ou en objet. Les valeurs d'en-tête peuvent être de l'un des types suivants : - `string` - valeur de chaîne normale qui sera envoyée au serveur - `null` - ignorer l'en-tête lors de la conversion en JSON - `false` - ignorer l'en-tête lors de la conversion en JSON, indique également que la méthode set doit être appelée avec l'option rewrite définie à true pour écraser cette valeur (Axios l'utilise en interne pour permettre aux utilisateurs de refuser l'installation de certains en-têtes comme User-Agent ou Content-Type) - `undefined` - la valeur n'est pas définie ::: warning La valeur de l'en-tête est considérée comme définie si elle n'est pas undefined. ::: L'objet d'en-têtes est toujours initialisé à l'intérieur des intercepteurs et des transformateurs, comme illustré dans l'exemple suivant : ```js axios.interceptors.request.use((request: InternalAxiosRequestConfig) => { request.headers.set("My-header", "value"); request.headers.set({ "My-set-header1": "my-set-value1", "My-set-header2": "my-set-value2", }); // Désactiver la définition ultérieure de cet en-tête par Axios request.headers.set("User-Agent", false); request.headers.setContentType("text/plain"); // L'accès direct comme celui-ci est déprécié request.headers["My-set-header2"] = "newValue"; return request; }); ``` Vous pouvez itérer sur un AxiosHeaders en utilisant n'importe quelle méthode itérable, comme une boucle for-of, forEach, ou l'opérateur spread : ```js const headers = new AxiosHeaders({ foo: '1', bar: '2', baz: '3', }); for (const [header, value] of headers) { console.log(header, value); } // foo 1 // bar 2 // baz 3 ``` ## Définir des en-têtes sur une requête L'endroit le plus courant pour définir des en-têtes est l'option `headers` dans votre configuration de requête ou de configuration d'instance : ```js // Sur une seule requête await axios.get('/api/data', { headers: { 'Accept-Language': 'en-US', 'X-Request-ID': 'abc123', }, }); // Sur une instance (appliqué à chaque requête) const api = axios.create({ headers: { 'X-App-Version': '2.0.0', }, }); ``` ## Préserver la casse d'un en-tête spécifique Les noms d'en-têtes Axios sont insensibles à la casse, mais `AxiosHeaders` conserve la casse de la première clé correspondante qu'il voit. Si vous avez besoin d'une casse spécifique pour un serveur avec un comportement non standard sensible à la casse, définissez un préréglage de casse dans les valeurs par défaut puis définissez les valeurs normalement. ```js const api = axios.create(); api.defaults.headers.common = { 'content-type': undefined, accept: undefined, }; await api.put(url, data, { headers: { 'Content-Type': 'application/octet-stream', Accept: 'application/json', }, }); ``` Vous pouvez également le faire avec `AxiosHeaders` directement lors de la composition d'en-têtes : ```js import axios, { AxiosHeaders } from 'axios'; const headers = AxiosHeaders.concat( { 'content-type': undefined }, { 'Content-Type': 'application/octet-stream' } ); await axios.put(url, data, { headers }); ``` ## Définir des en-têtes dans un intercepteur Les intercepteurs sont l'endroit approprié pour attacher des en-têtes dynamiques comme les tokens d'authentification, car le token peut ne pas être disponible au moment où l'instance est créée : ```js api.interceptors.request.use((config) => { const token = getAuthToken(); // lire au moment de la requête config.headers.set('Authorization', `Bearer ${token}`); return config; }); ``` ## Lire les en-têtes de réponse Les en-têtes de réponse sont disponibles sur `response.headers` en tant qu'instance d'`AxiosHeaders`. Tous les noms d'en-têtes sont en minuscules : ```js const response = await axios.get('/api/data'); console.log(response.headers['content-type']); // application/json; charset=utf-8 console.log(response.headers.get('x-request-id')); // abc123 ``` ## Supprimer un en-tête par défaut Pour refuser un en-tête qu'axios définit par défaut (comme `Content-Type` ou `User-Agent`), définissez sa valeur à `false` : ```js await axios.post('/api/data', payload, { headers: { 'Content-Type': false, // laisser le navigateur le définir automatiquement (ex. pour FormData) }, }); ``` Pour plus de détails sur l'API complète des méthodes `AxiosHeaders`, consultez la page [Méthodes d'en-têtes](/pages/advanced/header-methods). axios-axios-2d06f96/docs/fr/pages/advanced/html-form-processing.md000066400000000000000000000042061521272452000251260ustar00rootroot00000000000000# Traitement de formulaires HTML (navigateur) Vous pouvez également envoyer un formulaire directement depuis un élément de formulaire HTML. Cela est utile lorsque vous avez un formulaire dans votre page et que vous souhaitez le soumettre sans aucun code JavaScript. ```js await axios.postForm('https://httpbin.org/post', document.querySelector('#htmlForm')); ``` Les objets `FormData` et `HTMLForm` peuvent également être envoyés en `JSON` en définissant explicitement l'en-tête `Content-Type` à `application/json` : ```js await axios.post('https://httpbin.org/post', document.querySelector('#htmlForm'), { headers: { 'Content-Type': 'application/json', }, }); ``` Voici un exemple de formulaire valide pouvant être soumis par le code ci-dessus : ```html
``` Le formulaire ci-dessus sera soumis sous la forme : ```json { "foo": "1", "deep": { "prop": { "spaced": "3" } }, "baz": ["4", "5"], "user": { "age": "value2" } } ``` ::: tip Les collisions de chemins écrasent les valeurs précédentes Les noms de champs sont convertis en chemins de propriétés en les divisant sur `.`, les crochets ou les espaces. Deux entrées dont les chemins se chevauchent entreront en collision : dans l'exemple ci-dessus, `deep.prop` est analysé en `["deep", "prop"]` et `deep prop spaced` en `["deep", "prop", "spaced"]`, donc l'affectation plus profonde remplace `deep.prop = "2"` par l'objet imbriqué `{ spaced: "3" }`. Choisissez des noms de champs sans chevauchement si vous avez besoin des deux valeurs. ::: ::: warning L'envoi de Blobs/Fichiers en JSON (base64) n'est actuellement pas supporté. ::: axios-axios-2d06f96/docs/fr/pages/advanced/http2.md000066400000000000000000000054341521272452000221140ustar00rootroot00000000000000# HTTP2 Le support expérimental de HTTP/2 a été ajouté à l'adaptateur `http` dans la version `1.13.0`. Il est disponible uniquement dans les environnements Node.js. ## Utilisation de base Utilisez l'option `httpVersion` pour sélectionner la version du protocole pour une requête. En la définissant à `2`, vous activez HTTP/2. ```js const { data, headers, status } = await axios.post( "https://httpbin.org/post", form, { httpVersion: 2, }, ); ``` ## `http2Options` Des options natives supplémentaires pour l'appel interne `session.request()` peuvent être passées via l'objet de configuration `http2Options`. Cela inclut également le paramètre personnalisé `sessionTimeout`, qui contrôle la durée (en millisecondes) pendant laquelle une session HTTP/2 inactive est maintenue avant d'être fermée. La valeur par défaut est `1000ms`. ```js { httpVersion: 2, http2Options: { rejectUnauthorized: false, // accepter les certificats auto-signés (développement uniquement) sessionTimeout: 5000, // maintenir la session inactive pendant 5 secondes }, } ``` ::: warning Le support HTTP/2 est actuellement expérimental. L'API peut changer dans les prochaines versions mineures ou de correctifs. ::: ::: warning Les redirections ne sont pas supportées via HTTP/2 L'adaptateur HTTP/2 ne suit actuellement pas les redirections. Si une requête émise avec `httpVersion: 2` reçoit une réponse `3xx`, la redirection n'est pas suivie automatiquement. Gérez ces réponses manuellement ou restez sur HTTP/1.x pour les endpoints qui s'appuient sur les redirections. ::: ## Exemple complet L'exemple ci-dessous envoie une requête POST `multipart/form-data` via HTTP/2 et suit à la fois la progression de l'envoi et du téléchargement. ```js const form = new FormData(); form.append("foo", "123"); const { data, headers, status } = await axios.post( "https://httpbin.org/post", form, { httpVersion: 2, http2Options: { // rejectUnauthorized: false, // sessionTimeout: 1000 }, onUploadProgress(e) { console.log("upload progress", e); }, onDownloadProgress(e) { console.log("download progress", e); }, responseType: "arraybuffer", }, ); ``` ## Référence de configuration | Option | Type | Défaut | Description | |---|---|---|---| | `httpVersion` | `number` | `1` | Version du protocole HTTP à utiliser. Définissez à `2` pour activer HTTP/2. | | `http2Options.sessionTimeout` | `number` | `1000` | Durée en millisecondes avant qu'une session HTTP/2 inactive soit fermée. | Toutes les autres options natives de `session.request()` supportées par le module `http2` intégré de Node.js peuvent également être passées dans `http2Options`. axios-axios-2d06f96/docs/fr/pages/advanced/interceptors.md000066400000000000000000000144031521272452000235700ustar00rootroot00000000000000# Intercepteurs Les intercepteurs sont un mécanisme puissant permettant d'intercepter et de modifier les requêtes et réponses HTTP. Ils sont très similaires aux middlewares dans Express.js. Un intercepteur est une fonction exécutée avant l'envoi d'une requête et avant la réception d'une réponse. Les intercepteurs sont utiles pour de nombreuses tâches telles que la journalisation, la modification des en-têtes de requête et la modification de la réponse. L'utilisation de base des intercepteurs est la suivante : ```js // Ajouter un intercepteur de requête axios.interceptors.request.use( function (config) { // Effectuez une action avant l'envoi de la requête return config; }, function (error) { // Traitez l'erreur de requête return Promise.reject(error); } ); // Ajouter un intercepteur de réponse axios.interceptors.response.use( function (response) { // Tout code de statut dans la plage 2xx déclenchera cette fonction // Traitez les données de réponse return response; }, function (error) { // Tout code de statut en dehors de la plage 2xx déclenchera cette fonction // Traitez l'erreur de réponse return Promise.reject(error); } ); ``` ## Supprimer des intercepteurs Vous pouvez supprimer n'importe quel intercepteur en utilisant la méthode `eject` sur l'intercepteur que vous souhaitez supprimer. Vous pouvez également supprimer tous les intercepteurs en appelant la méthode `clear` sur l'objet `axios.interceptors`. Voici un exemple de suppression d'un intercepteur : ```js // Éjecter l'intercepteur de requête const myInterceptor = axios.interceptors.request.use(function () { /*...*/ }); axios.interceptors.request.eject(myInterceptor); // Éjecter l'intercepteur de réponse const myInterceptor = axios.interceptors.response.use(function () { /*...*/ }); axios.interceptors.response.eject(myInterceptor); ``` Voici un exemple de suppression de tous les intercepteurs : ```js const instance = axios.create(); instance.interceptors.request.use(function () { /*...*/ }); instance.interceptors.request.clear(); // Supprime les intercepteurs des requêtes instance.interceptors.response.use(function () { /*...*/ }); instance.interceptors.response.clear(); // Supprime les intercepteurs des réponses ``` ## Comportement par défaut des intercepteurs Lorsque vous ajoutez des intercepteurs de requête, ils sont considérés comme asynchrones par défaut. Cela peut provoquer un délai dans l'exécution de votre requête axios lorsque le thread principal est bloqué (une promise est créée en coulisses pour l'intercepteur et votre requête est placée en bas de la pile d'appels). Si vos intercepteurs de requête sont synchrones, vous pouvez ajouter un indicateur à l'objet d'options qui indiquera à axios d'exécuter le code de manière synchrone et d'éviter tout délai dans l'exécution des requêtes. ```js axios.interceptors.request.use( function (config) { config.headers.test = "I am only a header!"; return config; }, null, { synchronous: true } ); ``` ## Intercepteurs avec `runWhen` Si vous souhaitez exécuter un intercepteur particulier en fonction d'une vérification au moment de l'exécution, vous pouvez ajouter une fonction `runWhen` à l'objet d'options. L'intercepteur ne sera pas exécuté si et seulement si le résultat de `runWhen` est `false`. La fonction sera appelée avec l'objet de configuration (n'oubliez pas que vous pouvez également y lier vos propres arguments). Cela peut être utile lorsque vous avez un intercepteur de requête asynchrone qui ne doit s'exécuter que dans certaines conditions. ```js function onGetCall(config) { return config.method === "get"; } axios.interceptors.request.use( function (config) { config.headers.test = "special get headers"; return config; }, null, { runWhen: onGetCall } ); ``` ## Ordre d'exécution des intercepteurs ::: warning Les intercepteurs de requête et de réponse s'exécutent dans des ordres **opposés** Les intercepteurs de requête sont exécutés dans l'**ordre inverse** (LIFO — last in, first out). Le _dernier_ intercepteur de requête ajouté est exécuté en _premier_. Les intercepteurs de réponse sont exécutés dans l'**ordre où ils ont été ajoutés** (FIFO — first in, first out). Le _premier_ intercepteur de réponse ajouté est exécuté en _premier_. ::: L'exemple suivant montre l'ordre d'exécution complet pour trois intercepteurs de requête et trois intercepteurs de réponse : ```js const instance = axios.create(); const interceptor = (id) => (base) => { console.log(id); return base; }; instance.interceptors.request.use(interceptor("Request Interceptor 1")); instance.interceptors.request.use(interceptor("Request Interceptor 2")); instance.interceptors.request.use(interceptor("Request Interceptor 3")); instance.interceptors.response.use(interceptor("Response Interceptor 1")); instance.interceptors.response.use(interceptor("Response Interceptor 2")); instance.interceptors.response.use(interceptor("Response Interceptor 3")); // Sortie console : // Request Interceptor 3 // Request Interceptor 2 // Request Interceptor 1 // [La requête HTTP est effectuée] // Response Interceptor 1 // Response Interceptor 2 // Response Interceptor 3 ``` ## Intercepteurs multiples Vous pouvez ajouter plusieurs intercepteurs à la même requête ou réponse. Les règles suivantes s'appliquent pour plusieurs intercepteurs dans la même chaîne, dans l'ordre indiqué ci-dessous : - Chaque intercepteur est exécuté - Les intercepteurs de requête sont exécutés dans l'ordre inverse (LIFO). - Les intercepteurs de réponse sont exécutés dans l'ordre où ils ont été ajoutés (FIFO). - Seul le résultat du dernier intercepteur est retourné - Chaque intercepteur reçoit le résultat de son prédécesseur - Lorsqu'un intercepteur de réussite lève une exception : - L'intercepteur de réussite suivant n'est pas appelé - L'intercepteur d'échec suivant est appelé - Une fois capturée, un autre intercepteur de réussite suivant est à nouveau appelé (comme dans une chaîne de promises). ::: tip Pour une compréhension approfondie du fonctionnement des intercepteurs, vous pouvez lire les cas de test disponibles [ici](https://github.com/axios/axios/blob/v1.x/test/specs/interceptors.spec.js). ::: axios-axios-2d06f96/docs/fr/pages/advanced/multipart-form-data-format.md000066400000000000000000000155351521272452000262350ustar00rootroot00000000000000# Format multipart/form-data axios peut envoyer des requêtes au format `multipart/form-data`. Ce format est couramment utilisé lors de l'envoi de fichiers. Pour envoyer une requête dans ce format, vous devez créer un objet `FormData` et y ajouter les données. Vous pouvez ensuite passer l'objet `FormData` à la propriété `data` de la configuration de requête axios. ```js const formData = new FormData(); formData.append('foo', 'bar'); axios.post('https://httpbin.org/post', formData); ``` Ne définissez pas manuellement l'en-tête `Content-Type` pour les objets `FormData` de navigateur, web worker ou React Native ; ces environnements ajoutent eux-mêmes la boundary multipart. Dans Node.js, vous pouvez utiliser la bibliothèque `form-data` comme suit : ```js const FormData = require('form-data'); const form = new FormData(); form.append('my_field', 'my value'); form.append('my_buffer', Buffer.alloc(10)); form.append('my_file', fs.createReadStream('/foo/bar.jpg')); axios.post('https://example.com', form); ``` ## Sérialisation automatique vers FormData À partir de la version v0.27.0, Axios prend en charge la sérialisation automatique d'objets en objet FormData si l'en-tête Content-Type de la requête est défini à multipart/form-data. Cela signifie que vous pouvez passer directement un objet JavaScript à la propriété data de la configuration de requête axios. Par exemple lors de l'envoi de données vers une requête POST : ```js import axios from 'axios'; axios .post( 'https://httpbin.org/post', { x: 1 }, { headers: { 'Content-Type': 'multipart/form-data', }, } ) .then(({ data }) => console.log(data)); ``` Dans la version Node.js, le polyfill ([`form-data`](https://github.com/form-data/form-data)) est utilisé par défaut. Vous pouvez remplacer la classe FormData en définissant la variable de configuration env.FormData, mais vous n'en aurez probablement pas besoin dans la plupart des cas : ```js const axios = require('axios'); var FormData = require('form-data'); axios .post( 'https://httpbin.org/post', { x: 1, buf: Buffer.alloc(10) }, { headers: { 'Content-Type': 'multipart/form-data', }, } ) .then(({ data }) => console.log(data)); ``` ## Politique d'en-têtes pour `FormData` Node.js Lorsque vous passez un objet `FormData` Node.js qui expose `getHeaders()` (comme le package [`form-data`](https://github.com/form-data/form-data)), axios copie par défaut tous les en-têtes qu'il retourne sur la requête. Cela préserve la compatibilité v1 mais peut être problématique lorsque l'objet `FormData` provient d'une source non fiable — `getHeaders()` pourrait écraser des en-têtes comme `Authorization` ou en injecter des arbitraires. Définissez `formDataHeaderPolicy: 'content-only'` pour copier **uniquement** `Content-Type` et `Content-Length` depuis `getHeaders()`, puis définissez tout autre en-tête explicitement via la configuration `headers` de la requête : ```js await axios.post("https://example.com/upload", form, { formDataHeaderPolicy: "content-only", headers: { Authorization: "Bearer my-token", }, }); ``` La valeur par défaut est `'legacy'`. Voir [`formDataHeaderPolicy`](/pages/advanced/request-config#formdataheaderpolicy) dans la référence de configuration de requête pour plus de détails. ## Terminaisons supportées Le sérialiseur FormData d'Axios supporte quelques terminaisons spéciales pour effectuer les opérations suivantes : - `{}` - sérialiser la valeur avec JSON.stringify - `[]` - décomposer l'objet de type tableau en champs séparés avec la même clé ::: warning Remarque : l'opération de décomposition/expansion sera utilisée par défaut sur les tableaux et les objets FileList ::: ## Configurer le sérialiseur FormData Le sérialiseur FormData supporte des options supplémentaires via la propriété d'objet config.formSerializer pour gérer les cas particuliers : - `visitor: Function` - fonction visiteur définie par l'utilisateur qui sera appelée récursivement pour sérialiser l'objet de données en objet FormData en suivant des règles personnalisées. - `dots: boolean = false` - utiliser la notation pointée au lieu de crochets pour sérialiser les tableaux et les objets ; - `metaTokens: boolean = true` - ajouter la terminaison spéciale (ex. `user{}: '{"name": "John"}'`) dans la clé FormData. Le body-parser du backend pourrait potentiellement utiliser ces méta-informations pour analyser automatiquement la valeur en JSON. - `indexes: null|false|true = false` - contrôle comment les index seront ajoutés aux clés décomposées d'objets de type tableau plat - `null` - ne pas ajouter de crochets (`arr: 1`, `arr: 2`, `arr: 3`) - `false` (défaut) - ajouter des crochets vides (`arr[]: 1`, `arr[]: 2`, `arr[]: 3`) - `true` - ajouter des crochets avec index (`arr[0]: 1`, `arr[1]: 2`, `arr[2]: 3`) - `maxDepth: number = 100` - profondeur maximale d'imbrication des objets dans laquelle le sérialiseur va récurser. Si l'entrée dépasse cette profondeur, une `AxiosError` avec `code: 'ERR_FORM_DATA_DEPTH_EXCEEDED'` est levée. Cela protège les applications côté serveur contre les attaques DoS via des charges utiles profondément imbriquées. Définir à `Infinity` pour désactiver la limite. ```js // Autoriser une imbrication plus profonde pour les schémas qui dépassent légitimement 100 niveaux : axios.postForm('/api', data, { formSerializer: { maxDepth: 200 } }); ``` ::: warning Note de sécurité La limite par défaut de 100 est intentionnelle. Le code côté serveur qui transfère du JSON contrôlé par le client vers axios en tant que `data` est vulnérable à un débordement de pile d'appels sans cette protection. N'augmentez `maxDepth` que si votre schéma le nécessite réellement. ::: Par exemple, si nous avons un objet comme celui-ci : ```js const obj = { x: 1, arr: [1, 2, 3], arr2: [1, [2], 3], users: [ { name: 'Peter', surname: 'Griffin' }, { name: 'Thomas', surname: 'Anderson' }, ], 'obj2{}': [{ x: 1 }], }; ``` Les étapes suivantes seront exécutées en interne par le sérialiseur Axios : ```js const formData = new FormData(); formData.append('x', '1'); formData.append('arr[]', '1'); formData.append('arr[]', '2'); formData.append('arr[]', '3'); formData.append('arr2[0]', '1'); formData.append('arr2[1][0]', '2'); formData.append('arr2[2]', '3'); formData.append('users[0][name]', 'Peter'); formData.append('users[0][surname]', 'Griffin'); formData.append('users[1][name]', 'Thomas'); formData.append('users[1][surname]', 'Anderson'); formData.append('obj2{}', '[{"x":1}]'); ``` Axios supporte les méthodes raccourcies suivantes : `postForm`, `putForm`, `patchForm` qui sont simplement les méthodes HTTP correspondantes avec l'en-tête `Content-Type` prédéfini à `multipart/form-data`. axios-axios-2d06f96/docs/fr/pages/advanced/progress-capturing.md000066400000000000000000000042111521272452000247010ustar00rootroot00000000000000# Capture de progression Axios prend en charge la capture de la progression des envois et téléchargements dans les environnements navigateur et Node.js. La fréquence des événements de progression est limitée à 3 fois par seconde. Cela permet d'éviter de surcharger le navigateur avec des événements de progression. Voici un exemple de capture d'événements de progression : ```js await axios.post(url, data, { onUploadProgress: function (axiosProgressEvent) { /*{ loaded: number; total?: number; progress?: number; // dans la plage [0..1] bytes: number; // nombre d'octets transférés depuis le dernier déclenchement (delta) estimated?: number; // temps estimé en secondes rate?: number; // vitesse d'envoi en octets upload: true; // indicateur d'envoi }*/ }, onDownloadProgress: function (axiosProgressEvent) { /*{ loaded: number; total?: number; progress?: number; bytes: number; estimated?: number; rate?: number; // vitesse de téléchargement en octets download: true; // indicateur de téléchargement }*/ }, }); ``` Vous pouvez également transmettre les événements de progression d'envoi et de téléchargement vers un stream lisible dans Node.js. Cela est utile lorsque vous souhaitez afficher la progression de manière personnalisée. Voici un exemple de transmission des événements de progression : ```js const { data } = await axios.post(SERVER_URL, readableStream, { onUploadProgress: ({ progress }) => { console.log((progress * 100).toFixed(2)); }, headers: { "Content-Length": contentLength, }, maxRedirects: 0, // éviter de buffériser l'intégralité du stream }); ``` ::: warning La capture de la progression d'envoi de FormData n'est actuellement pas supportée dans les environnements Node.js ::: ::: danger Il est recommandé de désactiver les redirections en définissant maxRedirects: 0 pour envoyer le stream dans l'environnement Node.js, car le package follow-redirects bufférisera l'intégralité du stream en RAM sans suivre l'algorithme de « backpressure » ::: axios-axios-2d06f96/docs/fr/pages/advanced/promises.md000066400000000000000000000044251521272452000227130ustar00rootroot00000000000000# Promises axios est construit sur l'API Promise native d'ES6. Chaque requête axios retourne une Promise qui se résout vers un objet de réponse ou se rejette avec une erreur. Si votre environnement ne supporte pas les Promises ES6, vous devrez les polyfiller — par exemple avec [es6-promise](https://github.com/stefanpenner/es6-promise). ## then / catch / finally Comme axios retourne une Promise standard, vous pouvez utiliser `.then()`, `.catch()` et `.finally()` pour gérer le résultat : ```js axios.get("/api/users") .then((response) => { console.log(response.data); }) .catch((error) => { console.error("Request failed:", error.message); }) .finally(() => { console.log("Request finished"); }); ``` ## async / await L'approche recommandée pour la plupart des bases de code est `async/await`, qui rend le code asynchrone lisible comme du code synchrone : ```js async function fetchUser(id) { try { const response = await axios.get(`/api/users/${id}`); return response.data; } catch (error) { console.error("Failed to fetch user:", error.message); throw error; } } ``` ## Requêtes parallèles Comme axios retourne une Promise standard, vous pouvez utiliser `Promise.all` pour effectuer plusieurs requêtes simultanément et attendre qu'elles se terminent toutes : ```js const [users, posts] = await Promise.all([ axios.get("/api/users"), axios.get("/api/posts"), ]); console.log(users.data, posts.data); ``` ::: tip `Promise.all` rejettera dès que l'une des requêtes échoue. Si vous souhaitez gérer les échecs partiels, utilisez plutôt `Promise.allSettled`. ::: ```js const results = await Promise.allSettled([ axios.get("/api/users"), axios.get("/api/posts"), ]); results.forEach((result) => { if (result.status === "fulfilled") { console.log(result.value.data); } else { console.error("Request failed:", result.reason.message); } }); ``` ## Chaînage de requêtes Vous pouvez chaîner des appels `.then()` pour exécuter des requêtes séquentiellement, en passant les données d'une requête à la suivante : ```js axios.get("/api/user/1") .then(({ data: user }) => axios.get(`/api/posts?userId=${user.id}`)) .then(({ data: posts }) => { console.log("Posts for user:", posts); }) .catch(console.error); ``` axios-axios-2d06f96/docs/fr/pages/advanced/rate-limiting.md000066400000000000000000000045701521272452000236200ustar00rootroot00000000000000# Limitation de débit axios prend en charge la limitation de bande passante dans l'environnement Node.js via l'adaptateur HTTP. Cela vous permet de plafonner la vitesse d'envoi ou de téléchargement des données, ce qui est utile pour les opérations en masse, les tâches en arrière-plan ou le scraping respectueux qui ne doit pas saturer une connexion. ## `maxRate` L'option `maxRate` accepte soit un nombre (octets par seconde) soit un tableau où la première valeur est la limite d'envoi et la deuxième valeur est la limite de téléchargement. Utilisez `[uploadRate]` pour limiter uniquement l'envoi, ou `[uploadRate, downloadRate]` pour limiter les deux sens. Lorsqu'un nombre unique est passé, la même limite s'applique à l'envoi et au téléchargement. ```js // Limiter l'envoi et le téléchargement à 100 Ko/s await axios.get(URL, { maxRate: 100 * 1024 }); // Limiter l'envoi à 100 Ko/s, le téléchargement à 500 Ko/s await axios.get(URL, { maxRate: [100 * 1024, 500 * 1024] }); ``` ::: warning `maxRate` n'est supporté que par l'adaptateur HTTP Node.js. Il n'a aucun effet dans les environnements navigateur. ::: ## Limitation du débit d'envoi Plafonnez la vitesse d'envoi tout en journalisant la progression en même temps : ```js const { data } = await axios.post(SERVER_URL, myBuffer, { onUploadProgress: ({ progress, rate }) => { const percent = (progress * 100).toFixed(1); const kbps = (rate / 1024).toFixed(1); console.log(`Upload [${percent}%] at ${kbps} KB/s`); }, maxRate: [100 * 1024], // plafonner l'envoi à 100 Ko/s }); ``` ## Limitation du débit de téléchargement Plafonnez la vitesse de téléchargement pour les réponses volumineuses : ```js const { data } = await axios.get(FILE_URL, { onDownloadProgress: ({ progress, rate }) => { const percent = (progress * 100).toFixed(1); const kbps = (rate / 1024).toFixed(1); console.log(`Download [${percent}%] at ${kbps} KB/s`); }, maxRate: [Infinity, 200 * 1024], // pas de limite d'envoi, 200 Ko/s en téléchargement responseType: "arraybuffer", }); ``` ## Limitation combinée envoi et téléchargement Passez les deux limites sous forme de tableau pour contrôler les deux sens simultanément : ```js await axios.post(SERVER_URL, largeBuffer, { maxRate: [50 * 1024, 500 * 1024], // 50 Ko/s en envoi, 500 Ko/s en téléchargement }); ``` axios-axios-2d06f96/docs/fr/pages/advanced/request-config.md000066400000000000000000000722261521272452000240110ustar00rootroot00000000000000# Configuration de requête La configuration de requête est utilisée pour paramétrer la requête. Un large éventail d'options est disponible, mais la seule option obligatoire est `url`. Si l'objet de configuration ne contient pas de champ `method`, la méthode par défaut est `GET`. ::: warning Sécurité : la protection contre les bombes de décompression est optionnelle Par défaut, `maxContentLength` et `maxBodyLength` valent `-1` (illimité). Un serveur malveillant ou compromis peut renvoyer un petit corps compressé en gzip/deflate/brotli/zstd qui s'étend à plusieurs gigaoctets et épuise le processus Node.js. Si vous appelez des serveurs auxquels vous ne faites pas pleinement confiance, **définissez un plafond** : ```js axios.defaults.maxContentLength = 10 * 1024 * 1024; // 10 Mo axios.defaults.maxBodyLength = 10 * 1024 * 1024; ``` Consultez le [guide de sécurité](/pages/misc/security) pour plus de détails. ::: ### `url` L'`url` est l'URL vers laquelle la requête est envoyée. Il peut s'agir d'une chaîne de caractères ou d'une instance de `URL`. ### `method` La `method` est la méthode HTTP à utiliser pour la requête. La méthode par défaut est `GET`. ### `baseURL` La `baseURL` est l'URL de base à ajouter en préfixe à l'`url`, sauf si celle-ci est une URL absolue. Utile pour effectuer des requêtes vers le même domaine sans avoir à répéter le nom de domaine et tout préfixe d'API ou de version. ### `allowAbsoluteUrls` `allowAbsoluteUrls` détermine si les URLs absolues peuvent remplacer une `baseUrl` configurée. Lorsqu'elle est définie à `true` (valeur par défaut), les valeurs absolues de `url` remplacent `baseUrl`. Lorsqu'elle est définie à `false`, les valeurs absolues de `url` sont toujours précédées de `baseUrl`. ### `transformRequest` La fonction `transformRequest` vous permet de modifier les données de la requête avant leur envoi au serveur. Cette fonction est appelée avec les données de la requête comme seul argument. Elle ne s'applique que pour les méthodes de requête `PUT`, `POST`, `PATCH` et `DELETE`. La dernière fonction du tableau doit retourner une chaîne ou une instance de Buffer, ArrayBuffer, FormData ou Stream. ### `transformResponse` La fonction `transformResponse` vous permet de modifier les données de la réponse avant qu'elles ne soient transmises aux fonctions `then` ou `catch`. Cette fonction est appelée avec les données de la réponse comme seul argument. ### `parseReviver` La fonction `parseReviver` vous permet de fournir une fonction « reviver » personnalisée directement à l'appel natif `JSON.parse()` utilisé par le `transformResponse` par défaut. C'est particulièrement utile pour effectuer une hydratation de types haute performance (par exemple, convertir des chaînes ISO en objets `Temporal` ou `Date`) ou pour éviter une perte de précision lors de l'analyse. Dans les environnements modernes (ES2023+), la fonction reviver reçoit un troisième argument `context`. Celui-ci donne accès au `source` JSON brut, permettant la conversion précise de grands entiers (BigInt) qui perdraient autrement en précision s'ils étaient analysés comme des nombres JavaScript standards. > Remarque : `Temporal` n'est pas encore disponible dans tous les environnements. Envisagez l'utilisation d'un polyfill si nécessaire. ```js const client = axios.create({ parseReviver: (key, value, context) => { // Exemple : analyse BigInt sans perte de précision if (typeof value === 'number' && context?.source) { const isInteger = Number.isInteger(value); const isUnsafe = !Number.isSafeInteger(value); const isValidIntegerString = /^-?\d+$/.test(context.source); if (isInteger && isUnsafe && isValidIntegerString) { try { return BigInt(context.source); } catch { // Solution de repli : retourne la valeur d'origine si l'analyse échoue } } } // Exemple : hydratation des dates en objets Temporal if ( typeof value === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(value) && typeof Temporal !== 'undefined' && Temporal?.PlainDate ) { return Temporal.PlainDate.from(value); } return value; }, }); ``` ### `headers` Les `headers` sont les en-têtes HTTP à envoyer avec la requête. L'en-tête `Content-Type` est défini à `application/json` par défaut. ### `params` Les `params` sont les paramètres d'URL à envoyer avec la requête. Il doit s'agir d'un objet simple ou d'un objet URLSearchParams. Si l'`url` contient des paramètres de requête, ils seront fusionnés avec l'objet `params`. ### `paramsSerializer` La fonction `paramsSerializer` vous permet de sérialiser l'objet `params` avant son envoi au serveur. Plusieurs options sont disponibles pour cette fonction ; veuillez vous référer à l'exemple de configuration complète en bas de cette page. #### Encodage pour-cent strict RFC 3986 Par défaut, axios redécode `%3A`, `%24`, `%2C` et `%20` vers `:`, `$`, `,` et `+` pour la lisibilité (le `+` suit la convention `application/x-www-form-urlencoded` pour représenter une espace dans une chaîne de requête). Ces caractères sont valides dans un composant de requête selon la [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.4), donc la sortie par défaut est correcte. Cependant, certains backends exigent un encodage pour-cent strict et rejettent la forme lisible. Utilisez l'option `encode` pour remplacer l'encodeur par défaut : ```js // Par requête : émettre un encodage pour-cent strict RFC 3986 pour les valeurs de requête axios.get('/foo', { params: { filter: JSON.stringify({ startedAt: '2026-01-23' }) }, paramsSerializer: { encode: encodeURIComponent } }); // Ou définir cela sur les valeurs par défaut de l'instance const client = axios.create({ paramsSerializer: { encode: encodeURIComponent } }); ``` ### `data` Les `data` sont les données à envoyer comme corps de la requête. Il peut s'agir d'une chaîne, d'un objet simple, d'un Buffer, d'un ArrayBuffer, d'un FormData, d'un Stream ou d'un URLSearchParams. Ne s'applique que pour les méthodes de requête `PUT`, `POST`, `DELETE` et `PATCH`. Sans `transformRequest`, doit être de l'un des types suivants : - chaîne, objet simple, ArrayBuffer, ArrayBufferView, URLSearchParams - Navigateur uniquement : FormData, File, Blob - React Native : FormData - Node uniquement : Stream, Buffer, FormData (package form-data) Pour les objets `FormData` de navigateur, web worker et React Native, ne définissez pas manuellement `Content-Type` ; l'environnement ajoute lui-même la boundary multipart. Pour les objets `FormData` Node.js qui fournissent une méthode `getHeaders()`, axios copie tous les en-têtes retournés par défaut pour assurer la compatibilité avec la v1. Si l'objet `FormData` est personnalisé ou n'est pas pleinement de confiance, définissez `formDataHeaderPolicy: 'content-only'` pour ne copier que `Content-Type` et `Content-Length`, et définissez explicitement tout autre en-tête de requête via la configuration `headers` de la requête. ### `formDataHeaderPolicy` Contrôle la manière dont axios copie les en-têtes retournés par `FormData#getHeaders()` de Node.js. La valeur par défaut est `'legacy'`, qui copie tous les en-têtes retournés afin de préserver le comportement existant de la v1. Définissez `'content-only'` pour ne copier que `Content-Type` et `Content-Length` depuis `getHeaders()`. ### `timeout` Le `timeout` est le nombre de millisecondes avant l'expiration de la requête. Si la requête dure plus longtemps que `timeout`, elle sera annulée. ### `withCredentials` La propriété `withCredentials` indique si les requêtes Cross-site Access-Control doivent être effectuées avec des informations d'identification telles que des cookies, des en-têtes d'autorisation ou des certificats client TLS. La définition de `withCredentials` n'a aucun effet sur les requêtes du même site. ### `adapter` `adapter` permet une gestion personnalisée des requêtes, ce qui facilite les tests. Retournez une promise et fournissez une réponse valide ; consultez [les adaptateurs](/pages/advanced/adapters) pour plus d'informations. Nous fournissons également un certain nombre d'adaptateurs intégrés. L'adaptateur par défaut est `http` pour Node et `xhr` pour les navigateurs. La liste complète des adaptateurs intégrés est la suivante : - fetch - http - xhr Vous pouvez également passer un tableau d'adaptateurs ; axios utilisera le premier pris en charge par l'environnement. ### `auth` `auth` indique que l'authentification HTTP Basic doit être utilisée, et fournit les identifiants. Cela définira un en-tête `Authorization`, en écrasant tout en-tête `Authorization` personnalisé que vous auriez défini via `headers`. Si `auth` est omis, les adaptateurs HTTP Node.js et fetch peuvent déduire les identifiants Basic depuis l'URL de requête, par exemple `https://user:pass@example.com` ; les identifiants encodés en pourcentage dans l'URL sont décodés, et `auth` prend toujours le dessus sur les identifiants intégrés à l'URL. Dans l'adaptateur HTTP Node.js, l'authentification Basic est conservée lors des redirections de même origine et supprimée lors des redirections cross-origin. Notez que seule l'authentification HTTP Basic est configurable via ce paramètre. Pour les tokens Bearer et similaires, utilisez plutôt des en-têtes `Authorization` personnalisés. ### `responseType` Le `responseType` indique le type de données que le serveur retournera. Il peut s'agir de l'un des types suivants : - arraybuffer - document - json - text - stream - blob (navigateur uniquement) - formdata (adaptateur fetch uniquement) ### `responseEncoding` Le `responseEncoding` indique l'encodage à utiliser pour décoder les réponses. Les options suivantes sont prises en charge : - ascii - ASCII - ansi - ANSI - binary - BINARY - base64 - BASE64 - base64url - BASE64URL - hex - HEX - latin1 - LATIN1 - ucs-2 - UCS-2 - ucs2 - UCS2 - utf-8 - UTF-8 - utf8 - UTF8 - utf16le - UTF16LE ::: tip Remarque : ignoré pour un `responseType` de `stream` ou pour les requêtes côté client ::: ### `xsrfCookieName` Le `xsrfCookieName` est le nom du cookie à utiliser comme valeur pour le token `XSRF`. ### `xsrfHeaderName` Le `xsrfHeaderName` est le nom de l'en-tête à utiliser comme valeur pour le token `XSRF`. ### `withXSRFToken` `withXSRFToken` contrôle si axios lit le cookie XSRF et définit l'en-tête XSRF sur les requêtes du navigateur. Accepte : - `undefined` _(par défaut)_ — définit l'en-tête XSRF uniquement pour les requêtes du même site (same-origin). - `true` — définit toujours l'en-tête XSRF, y compris pour les requêtes cross-origin. - `false` — ne définit jamais l'en-tête XSRF. - `(config: InternalAxiosRequestConfig) => boolean | undefined` — un callback qui décide par requête, en recevant l'objet de configuration interne. ```ts withXSRFToken: boolean | undefined | ((config: InternalAxiosRequestConfig) => boolean | undefined); ``` ::: warning XSRF cross-origin et `withCredentials` `withCredentials` contrôle si les requêtes cross-site incluent des informations d'identification (cookies, authentification HTTP). Dans les anciennes versions d'axios, définir `withCredentials: true` provoquait implicitement l'envoi de l'en-tête XSRF pour les requêtes cross-origin. Les versions plus récentes d'axios séparent ces préoccupations : pour autoriser l'envoi de l'en-tête XSRF sur des requêtes cross-origin, vous devez définir **à la fois** `withCredentials: true` et `withXSRFToken: true`. ```js axios.get('/user', { withCredentials: true, withXSRFToken: true }); ``` ::: ### `onUploadProgress` La fonction `onUploadProgress` vous permet d'écouter la progression d'un envoi. ### `onDownloadProgress` La fonction `onDownloadProgress` vous permet d'écouter la progression d'un téléchargement. ### `maxContentLength` La propriété `maxContentLength` définit la taille maximale de la réponse en octets. L'adaptateur HTTP Node.js l'applique aux réponses mises en mémoire tampon et aux réponses streamées. L'adaptateur fetch l'applique lorsque la longueur de la réponse est déclarée, lorsque le stream de réponse peut être suivi ou lorsque la taille de la réponse peut être déterminée. > ⚠️ **Sécurité :** la valeur par défaut est `-1` (illimitée). Des réponses non bornées combinées à la décompression gzip/deflate/brotli/zstd rendent possible un déni de service par bombe de décompression. > Définissez une limite explicite lorsque vous consommez des serveurs auxquels vous ne faites pas pleinement confiance. ### `maxBodyLength` La propriété `maxBodyLength` définit la taille maximale du corps de requête en octets. L'adaptateur HTTP Node.js l'applique, et l'adaptateur fetch l'applique lorsque la longueur du corps de requête peut être déterminée. ### `redact` La propriété `redact` est un tableau optionnel de noms de clés de configuration à masquer lorsqu'une `AxiosError` est sérialisée avec `toJSON()`. La correspondance est insensible à la casse et récursive sur l'ensemble de la configuration de requête sérialisée. Les valeurs correspondantes sont remplacées par `[REDACTED ****]`. `redact` n'affecte que la sérialisation des erreurs. Elle ne modifie ni les données de la requête, ni les en-têtes, ni l'objet de configuration original. ```js axios.get('/user/12345', { headers: { Authorization: 'Bearer token' }, auth: { username: 'me', password: 'secret' }, redact: ['authorization', 'password'] }).catch((error) => { console.log(error.toJSON().config); }); ``` ### `validateStatus` La fonction `validateStatus` vous permet de remplacer la validation du code de statut par défaut. Par défaut, axios rejette la promise si le code de statut n'est pas dans la plage 200-299. Vous pouvez remplacer ce comportement en fournissant une fonction `validateStatus` personnalisée. La fonction doit retourner `true` si le code de statut est dans la plage que vous souhaitez accepter. ### `maxRedirects` La propriété `maxRedirects` définit le nombre maximum de redirections à suivre. Si défini à 0, aucune redirection ne sera suivie. ### `beforeRedirect` La fonction `beforeRedirect` vous permet de modifier la requête avant qu'elle ne soit redirigée. Utilisez-la pour ajuster les options de requête lors d'une redirection, inspecter les derniers en-têtes de réponse, ou annuler la requête en levant une erreur. Si `maxRedirects` est défini à 0, `beforeRedirect` n'est pas utilisé. ```js beforeRedirect: (options, { headers }) => { if ( options.hostname === "example.com" && options.protocol === "https:" ) { options.auth = "user:password"; } } ``` ::: warning Sécurité : réinjection d'identifiants lors d'une redirection Le hook `beforeRedirect` s'exécute **après** que les en-têtes sensibles aient été retirés pendant les redirections. La bibliothèque `follow-redirects` supprime les identifiants en cas de rétrogradation de protocole (HTTPS → HTTP) pour des raisons de sécurité. Comme `beforeRedirect` s'exécute après cela, réinjecter des identifiants sans vérifier le protocole de destination peut exposer des données sensibles. Ne réinjectez les identifiants que pour des destinations HTTPS de confiance, et évitez de les réinjecter sur des redirections rétrogradées. ::: ### `socketPath` La propriété `socketPath` définit un socket UNIX à utiliser à la place d'une connexion TCP. Par exemple `/var/run/docker.sock` pour envoyer des requêtes au daemon Docker. Seul `socketPath` ou `proxy` peut être spécifié. Si les deux sont spécifiés, `socketPath` est utilisé. :::warning Sécurité Lorsque `socketPath` est défini, le hostname et le port de l'URL de la requête sont ignorés et axios communique directement avec le socket Unix indiqué. Si une partie de la configuration de la requête provient d'une entrée utilisateur (par exemple dans un proxy ou un gestionnaire de webhooks qui transfère des options), un attaquant peut injecter `socketPath` pour rediriger le trafic vers des sockets locaux privilégiés tels que `/var/run/docker.sock`, `/run/containerd/containerd.sock` ou `/run/systemd/private`, contournant entièrement les protections SSRF basées sur le hostname (CWE-918). Filtrez la configuration provenant d'entrées non fiables et/ou restreignez les chemins de socket acceptés avec `allowedSocketPaths` (voir ci-dessous). ::: ### `allowedSocketPaths` Restreint les chemins de socket pouvant être utilisés via `socketPath`. Accepte une chaîne ou un tableau de chaînes. Lorsqu'elle est définie, axios résout le `socketPath` et le compare à chaque entrée (également résolue) ; la requête est rejetée avec une `AxiosError` de code `ERR_BAD_OPTION_VALUE` s'il n'y a aucune correspondance. Lorsque non définie (par défaut), `socketPath` se comporte comme avant. ```js const client = axios.create({ allowedSocketPaths: ['/var/run/docker.sock'] }); // autorisé await client.get('http://localhost/v1.45/info', { socketPath: '/var/run/docker.sock' }); // rejeté — pas dans la liste await client.get('http://localhost/pods', { socketPath: '/var/run/kubelet.sock' }); ``` Un tableau vide (`allowedSocketPaths: []`) bloque tous les chemins de socket. ### `transport` La propriété `transport` définit le transport à utiliser pour la requête. Utile pour effectuer des requêtes via un protocole différent, comme `http2`. ### `httpAgent` et `httpsAgent` Les `httpAgent` et `httpsAgent` définissent un agent personnalisé à utiliser pour les requêtes http et https respectivement dans Node.js. Cela permet d'ajouter des options comme `keepAlive` qui ne sont pas activées par défaut. ### `proxy` Le `proxy` définit le nom d'hôte, le port et le protocole d'un serveur proxy que vous souhaitez utiliser. Vous pouvez également définir votre proxy en utilisant les variables d'environnement conventionnelles `http_proxy` et `https_proxy`. Si vous utilisez des variables d'environnement pour la configuration de votre proxy, vous pouvez également définir une variable d'environnement `no_proxy` sous la forme d'une liste de domaines séparés par des virgules qui ne doivent pas être mandatés. Utilisez `false` pour désactiver les proxies, en ignorant les variables d'environnement. `auth` indique que l'authentification HTTP Basic doit être utilisée pour se connecter au proxy, et fournit les identifiants. Cela définira un en-tête `Proxy-Authorization`, en écrasant tout en-tête `Proxy-Authorization` personnalisé que vous auriez défini via `headers`. Si le serveur proxy utilise HTTPS, vous devez définir le protocole à `https`. Un en-tête `Host` fourni par l'utilisateur dans `headers` est préservé lorsqu'il est transféré via un proxy (correspondance insensible à la casse sur `host` / `Host` / `HOST`). Cela vous permet de cibler un hôte virtuel différent de l'URL de la requête — par exemple, atteindre `127.0.0.1:4000` tout en faisant traiter la requête par le proxy comme provenant de `example.com`. Si aucun en-tête `Host` n'est fourni, axios utilise par défaut le `hostname:port` de l'URL de la requête comme auparavant. Pour les cibles `https://`, axios établit un tunnel CONNECT via le proxy et effectue TLS de bout en bout avec l'origine. `Proxy-Authorization` est envoyé uniquement sur la requête CONNECT, jamais sur la requête TLS encapsulée. Les options TLS de `httpsAgent`, comme `ca`, `cert`, `key` et `rejectUnauthorized`, sont transmises à l'agent de tunnel généré afin qu'elles continuent de s'appliquer à la connexion TLS avec l'origine. Si vous fournissez un `HttpsProxyAgent`, axios laisse cet agent gérer le tunnel. ```js proxy: { protocol: "https", host: "127.0.0.1", hostname: "localhost", // Prend le dessus sur "host" si les deux sont définis port: 9000, auth: { username: "mikeymike", password: "rapunz3l" } }, ``` ### `cancelToken` La propriété `cancelToken` vous permet de créer un token d'annulation pouvant être utilisé pour annuler la requête. Pour plus d'informations, consultez la documentation sur l'[annulation](/pages/advanced/cancellation). ### `signal` La propriété `signal` vous permet de passer une instance d'`AbortSignal` à la requête. Cela vous permet d'annuler la requête en utilisant l'API `AbortController`. ### `decompress` La propriété `decompress` indique si les données de la réponse doivent être automatiquement décompressées. La valeur par défaut est `true`. L'adaptateur HTTP Node.js prend en charge gzip, deflate, brotli et zstd lorsque le runtime Node.js actuel fournit le décompresseur zlib correspondant. ### `insecureHTTPParser` Indique s'il faut utiliser un analyseur HTTP non sécurisé qui accepte des en-têtes HTTP invalides. Cela peut permettre l'interopérabilité avec des implémentations HTTP non conformes. L'utilisation de l'analyseur non sécurisé doit être évitée. Notez que l'option `insecureHTTPParser` n'est disponible que dans Node.js 12.10.0 et ultérieur. Consultez la [documentation Node.js](https://nodejs.org/en/blog/vulnerability/february-2020-security-releases/#strict-http-header-parsing-none) pour plus d'informations. Voir l'ensemble complet des options [ici](https://nodejs.org/dist/latest-v12.x/docs/api/http.html#http_http_request_url_options_callback) ### `transitional` La propriété `transitional` vous permet d'activer ou de désactiver certaines fonctionnalités de transition. Les options suivantes sont disponibles : - `silentJSONParsing` : Si défini à `true` _(par défaut)_, axios ignore silencieusement les erreurs d'analyse JSON et définit `response.data` à `null` lorsque l'analyse échoue. Définissez à `false` pour lever une `SyntaxError` à la place. ::: tip Important Cette option ne prend effet que lorsque `responseType` est **explicitement** défini à `'json'`. Lorsque `responseType` est omis, axios utilise `forcedJSONParsing` pour tenter l'analyse JSON et retourne silencieusement la chaîne brute en cas d'échec, indépendamment de ce paramètre. Pour qu'un JSON invalide lève une erreur, définissez les deux : ```js { responseType: 'json', transitional: { silentJSONParsing: false } } ``` ::: - `forcedJSONParsing` : Force axios à analyser la chaîne de réponse comme du JSON même si `responseType` n'est pas `'json'`. - `clarifyTimeoutError` : Clarifie le message d'erreur lorsqu'une requête expire. Utile lors du débogage de problèmes de délai d'attente. - `advertiseZstdAcceptEncoding` : Lorsqu'elle vaut `true`, axios ajoute `zstd` à l'en-tête `Accept-Encoding` par défaut lorsque le runtime Node.js actuel prend en charge la décompression zstd. Les réponses zstd sont tout de même décompressées automatiquement lorsqu'elles sont prises en charge et que `decompress` vaut `true`. - `legacyInterceptorReqResOrdering` : Lorsque défini à true, l'ordre hérité de traitement requête/réponse des intercepteurs sera utilisé. ### `env` La propriété `env` vous permet de définir certaines options de configuration. Par exemple, la classe FormData qui est utilisée pour sérialiser automatiquement le payload en objet FormData. - FormData: window?.FormData || global?.FormData ### `formSerializer` L'option `formSerializer` vous permet de configurer comment les objets simples sont sérialisés en `multipart/form-data` lorsqu'ils sont utilisés comme `data` de requête. Options disponibles : - `visitor` — fonction visiteur personnalisée appelée récursivement pour chaque valeur - `dots` — utiliser la notation pointée au lieu de la notation entre crochets - `metaTokens` — conserver les terminaisons spéciales de clé telles que `{}` - `indexes` — contrôler le format des crochets pour les clés de tableau (`null` / `false` / `true`) - `maxDepth` _(par défaut : `100`)_ — profondeur maximale d'imbrication avant de lever une `AxiosError` avec le code `ERR_FORM_DATA_DEPTH_EXCEEDED`. Définir à `Infinity` pour désactiver. Consultez la page [multipart/form-data](/pages/advanced/multipart-form-data-format) pour tous les détails, et l'exemple de configuration complète en bas de cette page. ### `maxRate` La propriété `maxRate` définit la **bande passante** maximale (en octets par seconde) pour l'envoi et/ou le téléchargement. Elle accepte soit un nombre unique (appliqué dans les deux sens) soit un tableau de deux éléments `[uploadRate, downloadRate]` où chaque élément est une limite en octets par seconde. Par exemple, `100 * 1024` signifie 100 Ko/s. Consultez [Limitation de débit](/pages/advanced/rate-limiting) pour des exemples. ## Exemple de configuration complète ```js { url: "/posts", method: "get", baseURL: "https://jsonplaceholder.typicode.com", allowAbsoluteUrls: true, transformRequest: [function (data, headers) { return data; }], transformResponse: [function (data) { return data; }], headers: {"X-Requested-With": "XMLHttpRequest"}, params: { postId: 5 }, paramsSerializer: { // Fonction d'encodage personnalisée qui envoie les paires clé/valeur de façon itérative. encode?: (param: string): string => { /* Effectuez des opérations personnalisées ici et retournez la chaîne transformée */ }, // Fonction de sérialisation personnalisée pour l'ensemble du paramètre. Permet à l'utilisateur de reproduire le comportement antérieur à la v1.x. serialize?: (params: Record, options?: ParamsSerializerOptions ), // Configuration du format des index de tableaux dans les params. // Trois options disponibles : // (1) indexes: null (pas de crochets) // (2) (défaut) indexes: false (crochets vides) // (3) indexes: true (crochets avec index). indexes: false, // Profondeur maximale d'imbrication des objets lors de la sérialisation des params. Lève une AxiosError // (ERR_FORM_DATA_DEPTH_EXCEEDED) si dépassée. Par défaut : 100. Définir à Infinity pour désactiver. maxDepth: 100 }, data: { firstName: "Fred" }, formDataHeaderPolicy: "legacy", // Syntaxe alternative pour envoyer des données dans le corps de la méthode post : seule la valeur est envoyée, pas la clé data: "Country=Brasil&City=Belo Horizonte", timeout: 1000, withCredentials: false, adapter: function (config) { // Faites ce que vous voulez }, adapter: "xhr", auth: { username: "janedoe", password: "s00pers3cret" }, responseType: "json", responseEncoding: "utf8", xsrfCookieName: "XSRF-TOKEN", xsrfHeaderName: "X-XSRF-TOKEN", withXSRFToken: boolean | undefined | ((config: InternalAxiosRequestConfig) => boolean | undefined), onUploadProgress: function ({loaded, total, progress, bytes, estimated, rate, upload = true}) { // Faites ce que vous voulez avec l'événement de progression Axios }, onDownloadProgress: function ({loaded, total, progress, bytes, estimated, rate, download = true}) { // Faites ce que vous voulez avec l'événement de progression Axios }, maxContentLength: 2000, maxBodyLength: 2000, redact: ['authorization', 'password'], validateStatus: function (status) { return status >= 200 && status < 300; }, maxRedirects: 21, beforeRedirect: (options, { headers }) => { if (options.hostname === "typicode.com") { options.auth = "user:password"; } }, socketPath: null, allowedSocketPaths: null, transport: undefined, httpAgent: new http.Agent({ keepAlive: true }), httpsAgent: new https.Agent({ keepAlive: true }), proxy: { protocol: "https", host: "127.0.0.1", // hostname: "127.0.0.1" // Prend le dessus sur "host" si les deux sont définis port: 9000, auth: { username: "mikeymike", password: "rapunz3l" } }, cancelToken: new CancelToken(function (cancel) { cancel("Operation has been canceled."); }), signal: new AbortController().signal, decompress: true, insecureHTTPParser: undefined, transitional: { silentJSONParsing: true, forcedJSONParsing: true, clarifyTimeoutError: false, advertiseZstdAcceptEncoding: false, legacyInterceptorReqResOrdering: true, }, env: { FormData: window?.FormData || global?.FormData }, formSerializer: { // Fonction visiteur personnalisée pour sérialiser les valeurs du formulaire visitor: (value, key, path, helpers) => {}; // Utiliser des points au lieu de crochets dots: boolean; // Conserver les terminaisons spéciales comme {} dans la clé de paramètre metaTokens: boolean; // Utiliser le format des index de tableau : // null - pas de crochets // false - crochets vides // true - crochets avec index indexes: boolean; // Profondeur maximale d'imbrication des objets. Lève une AxiosError (ERR_FORM_DATA_DEPTH_EXCEEDED) // si dépassée. Par défaut : 100. Définir à Infinity pour désactiver. maxDepth: 100; }, maxRate: [ 100 * 1024, // Limite d'envoi de 100Ko/s, 100 * 1024 // Limite de téléchargement de 100Ko/s ] } ``` axios-axios-2d06f96/docs/fr/pages/advanced/request-method-aliases.md000066400000000000000000000156071521272452000254430ustar00rootroot00000000000000# Alias de requête axios fournit un ensemble d'alias pour effectuer des requêtes HTTP. Ces alias sont des raccourcis pour effectuer des requêtes via la méthode `request`. Ils sont conçus pour être faciles à utiliser et offrir une façon plus pratique d'effectuer des requêtes. axios s'efforce de suivre les RFC 7231 et RFC 5789 aussi fidèlement que possible. Les alias sont conçus pour être cohérents avec les méthodes HTTP définies dans ces RFC. ### `axios` axios peut être utilisé pour effectuer une requête HTTP en passant uniquement l'objet de configuration. L'objet de configuration complet est documenté [ici](/pages/advanced/request-config) ```ts axios(url: string | AxiosRequestConfig, config?: AxiosRequestConfig); ``` ## Alias de méthode Les alias suivants sont disponibles pour effectuer des requêtes : ### `request` La méthode `request` est la méthode principale pour effectuer des requêtes HTTP. Elle accepte un objet de configuration en argument et retourne une promise qui se résout vers l'objet de réponse. C'est une méthode générique pouvant être utilisée pour tout type de requête HTTP. ```ts axios.request(config: AxiosRequestConfig): AxiosResponse; ``` ### `get` La méthode `get` est utilisée pour effectuer une requête GET. Elle accepte une URL et un objet de configuration optionnel en arguments et retourne une promise qui se résout vers l'objet de réponse. ```ts axios.get(url: string, config?: AxiosRequestConfig): AxiosResponse; ``` ### `delete` La méthode `delete` est utilisée pour effectuer une requête DELETE. Elle accepte une URL et un objet de configuration optionnel en arguments et retourne une promise qui se résout vers l'objet de réponse. ```ts axios.delete(url: string, config?: AxiosRequestConfig): AxiosResponse; ``` ### `head` La méthode `head` est utilisée pour effectuer une requête HEAD. Elle accepte une URL et un objet de configuration optionnel en arguments et retourne une promise qui se résout vers l'objet de réponse. ```ts axios.head(url: string, config?: AxiosRequestConfig): AxiosResponse; ``` ### `options` La méthode `options` est utilisée pour effectuer une requête OPTIONS. Elle accepte une URL et un objet de configuration optionnel en arguments et retourne une promise qui se résout vers l'objet de réponse. ```ts axios.options(url: string, config?: AxiosRequestConfig): AxiosResponse; ``` ### `post` La méthode `post` est utilisée pour effectuer une requête POST. Elle accepte une URL, un objet de données optionnel et un objet de configuration optionnel en arguments et retourne une promise qui se résout vers l'objet de réponse. ```ts axios.post(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ### `put` La méthode `put` est utilisée pour effectuer une requête PUT. Elle accepte une URL, un objet de données optionnel et un objet de configuration optionnel en arguments et retourne une promise qui se résout vers l'objet de réponse. ```ts axios.put(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ### `patch` La méthode `patch` est utilisée pour effectuer une requête PATCH. Elle accepte une URL, un objet de données optionnel et un objet de configuration optionnel en arguments et retourne une promise qui se résout vers l'objet de réponse. ```ts axios.patch(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ### `query` La méthode `query` est utilisée pour effectuer une requête QUERY, une méthode sûre et idempotente qui transporte un corps. Elle accepte une URL, un objet de données optionnel et un objet de configuration optionnel en arguments et retourne une promise qui se résout vers l'objet de réponse. Utilisez-la pour des opérations de type lecture dont les paramètres sont trop complexes ou trop sensibles pour figurer dans l'URL. ```ts axios.query(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ```js // Envoyer un filtre de recherche complexe dans le corps de la requête const { data } = await axios.query("/api/search", { selector: ["name", "email"], filter: { active: true, role: "admin" }, }); ``` ::: warning Spécification en cours d'élaboration La méthode QUERY est définie par un [Internet-Draft](https://datatracker.ietf.org/doc/draft-ietf-httpbis-safe-method-w-body/) de l'IETF et n'a pas encore été standardisée. La sémantique et le nom même de la méthode peuvent évoluer avant la publication finale, et la prise en charge par les serveurs, proxys et CDN est inégale. Vérifiez que votre pile accepte `QUERY` de bout en bout avant de vous en servir en production. ::: ### `getUri` La méthode `getUri` retourne l'URL qui serait envoyée pour une configuration donnée sans réellement effectuer la requête. Elle applique `baseURL`, `paramsSerializer` et `params`, vous obtenez donc la même chaîne qu'axios mettrait sur le réseau. Utile pour construire des liens, déboguer la sérialisation ou réutiliser l'URL résolue dans une autre requête. ```ts axios.getUri(config?: AxiosRequestConfig): string; ``` ```js const url = axios.getUri({ url: "/users", baseURL: "https://api.example.com", params: { active: true, role: "admin" }, }); // "https://api.example.com/users?active=true&role=admin" ``` ::: tip Utilisez `getUri` sur une instance (`instance.getUri(config)`) pour hériter des valeurs par défaut de l'instance pour `baseURL`, `params` et `paramsSerializer`. ::: ## Méthodes raccourcies pour les données de formulaire Ces méthodes sont équivalentes à leurs homologues ci-dessus, mais prédéfinissent le `Content-Type` à `multipart/form-data`. Elles constituent la façon recommandée d'envoyer des fichiers ou de soumettre des formulaires HTML. ### `postForm` ```ts axios.postForm(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ```js // Envoyer un fichier depuis un input file du navigateur await axios.postForm("/api/upload", { file: document.querySelector("#fileInput").files[0], description: "Profile photo", }); ``` ### `putForm` ```ts axios.putForm(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ```js // Remplacer une ressource avec des données de formulaire await axios.putForm("/api/users/1/avatar", { avatar: document.querySelector("#avatarInput").files[0], }); ``` ### `patchForm` ```ts axios.patchForm(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ```js // Mettre à jour des champs spécifiques avec des données de formulaire await axios.patchForm("/api/users/1", { displayName: "New Name", avatar: document.querySelector("#avatarInput").files[0], }); ``` ::: tip `postForm`, `putForm` et `patchForm` acceptent les mêmes types de données que leurs méthodes de base — objets simples, `FormData`, `FileList` et `HTMLFormElement`. Consultez [Envoi de fichiers](/pages/advanced/file-posting) pour plus d'exemples. ::: axios-axios-2d06f96/docs/fr/pages/advanced/response-schema.md000066400000000000000000000044121521272452000241420ustar00rootroot00000000000000# Schéma de réponse Chaque requête axios se résout vers un objet de réponse ayant la structure suivante. Le schéma est cohérent aussi bien dans les environnements navigateur que Node.js. ```js { // Les données de réponse fournies par le serveur. // Lors de l'utilisation de `transformResponse`, ce sera le résultat de la dernière transformation. data: {}, // Le code de statut HTTP de la réponse du serveur (ex. 200, 404, 500). status: 200, // Le message de statut HTTP correspondant au code de statut (ex. "OK", "Not Found"). statusText: "OK", // Les en-têtes de réponse envoyés par le serveur. // Les noms d'en-têtes sont en minuscules. Vous pouvez y accéder par notation crochet ou point. headers: {}, // La configuration axios utilisée pour cette requête, incluant baseURL, // headers, timeout, params, et toutes autres options que vous avez fournies. config: {}, // L'objet de requête sous-jacent. // Dans Node.js : la dernière instance de `http.ClientRequest` (après toute redirection). // Dans le navigateur : l'instance de `XMLHttpRequest`. request: {}, } ``` ## Accéder aux champs de la réponse En pratique, vous déstructurerez généralement uniquement les parties dont vous avez besoin : ```js const { data, status, headers } = await axios.get("/api/users/1"); console.log(status); // 200 console.log(headers["content-type"]); // "application/json; charset=utf-8" console.log(data); // { id: 1, name: "Jay", email: "jay@example.com" } ``` ## Vérifier le code de statut axios résout la promise pour toute réponse 2xx et rejette pour tout ce qui est en dehors de cette plage par défaut. Vous pouvez personnaliser ce comportement avec l'option de configuration `validateStatus` : ```js const response = await axios.get("/api/resource", { validateStatus: (status) => status < 500, // résoudre pour tout statut inférieur à 500 }); ``` ## Accéder aux en-têtes de réponse Tous les noms d'en-têtes de réponse sont en minuscules, quelle que soit la façon dont le serveur les a envoyés : ```js const response = await axios.get("/api/resource"); // Ces deux lignes sont équivalentes const contentType = response.headers["content-type"]; const contentType2 = response.headers.get("content-type"); ``` axios-axios-2d06f96/docs/fr/pages/advanced/retry.md000066400000000000000000000101031521272452000222050ustar00rootroot00000000000000# Nouvelles tentatives et récupération sur erreur Les requêtes réseau peuvent échouer pour des raisons transitoires — une défaillance momentanée du serveur, une brève interruption du réseau, ou une réponse de limitation de débit. Implémenter une stratégie de nouvelle tentative dans un intercepteur vous permet de gérer ces échecs de manière transparente, sans polluer votre code applicatif. ## Nouvelle tentative de base avec un intercepteur de réponse L'approche la plus simple consiste à intercepter des codes de statut d'erreur spécifiques et à renvoyer immédiatement la requête originale un nombre limité de fois : ```js import axios from "axios"; const api = axios.create({ baseURL: "https://api.example.com" }); const MAX_RETRIES = 3; api.interceptors.response.use( (response) => response, async (error) => { const config = error.config; // Ne réessayer que pour les erreurs réseau ou les erreurs serveur 5xx const shouldRetry = !error.response || (error.response.status >= 500 && error.response.status < 600); if (!shouldRetry) { return Promise.reject(error); } config._retryCount = config._retryCount ?? 0; if (config._retryCount >= MAX_RETRIES) { return Promise.reject(error); } config._retryCount += 1; return api(config); } ); ``` ## Délai exponentiel Réessayer immédiatement après un échec peut surcharger un serveur déjà en difficulté. Le délai exponentiel attend progressivement plus longtemps entre chaque tentative : ```js const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); api.interceptors.response.use( (response) => response, async (error) => { const config = error.config; const shouldRetry = !error.response || (error.response.status >= 500 && error.response.status < 600); if (!shouldRetry) return Promise.reject(error); config._retryCount = config._retryCount ?? 0; if (config._retryCount >= 3) return Promise.reject(error); config._retryCount += 1; // Attendre 200ms, 400ms, 800ms, ... avant chaque nouvelle tentative const backoff = 100 * 2 ** config._retryCount; await delay(backoff); return api(config); } ); ``` ## Nouvelle tentative sur 429 (limite de débit) avec Retry-After Lorsque le serveur répond avec `429 Too Many Requests`, il inclut souvent un en-tête `Retry-After` indiquant exactement combien de temps attendre : ```js api.interceptors.response.use( (response) => response, async (error) => { const config = error.config; if (error.response?.status !== 429) return Promise.reject(error); config._retryCount = config._retryCount ?? 0; if (config._retryCount >= 3) return Promise.reject(error); config._retryCount += 1; const retryAfterHeader = error.response.headers["retry-after"]; const waitMs = retryAfterHeader ? parseFloat(retryAfterHeader) * 1000 // l'en-tête est en secondes : 1000; // par défaut 1 seconde await new Promise((resolve) => setTimeout(resolve, waitMs)); return api(config); } ); ``` ## Désactiver les nouvelles tentatives pour une requête spécifique Si certaines requêtes ne doivent jamais être réessayées (ex. des mutations non idempotentes que vous ne voulez pas dupliquer), ajoutez un indicateur à la configuration de la requête : ```js // Ajoutez ceci dans votre intercepteur avant la logique de nouvelle tentative : if (config._noRetry) return Promise.reject(error); // Puis désactivez les nouvelles tentatives pour des appels spécifiques : await api.post("/payments/charge", body, { _noRetry: true }); ``` ## Combiner nouvelles tentatives et annulation Utilisez un `AbortController` pour annuler une requête qui attend un délai de backoff : ```js const controller = new AbortController(); try { await api.get("/api/data", { signal: controller.signal }); } catch (error) { if (axios.isCancel(error)) { console.log("Request aborted by user"); } } // Annuler la requête (et tout délai de nouvelle tentative en attente) depuis un autre endroit : controller.abort(); ``` axios-axios-2d06f96/docs/fr/pages/advanced/testing.md000066400000000000000000000105351521272452000225260ustar00rootroot00000000000000# Tests Tester du code qui effectue des requêtes HTTP avec axios est simple. L'approche recommandée consiste à simuler (mocker) axios lui-même afin que vos tests s'exécutent sans toucher un vrai réseau, vous donnant un contrôle total sur les réponses que reçoit votre code. ## Simulation avec Vitest ou Jest Vitest et Jest supportent tous deux la simulation de modules avec `vi.mock` / `jest.mock`. Vous pouvez simuler l'ensemble du module axios et contrôler ce que chaque méthode retourne : ```js // user-service.js import axios from "axios"; export async function getUser(id) { const { data } = await axios.get(`/api/users/${id}`); return data; } ``` ```js // user-service.test.js import { describe, it, expect, vi } from "vitest"; import axios from "axios"; import { getUser } from "./user-service"; vi.mock("axios"); describe("getUser", () => { it("returns user data on success", async () => { const mockUser = { id: 1, name: "Jay" }; // Faire en sorte que axios.get se résolve avec notre fausse réponse axios.get.mockResolvedValueOnce({ data: mockUser }); const result = await getUser(1); expect(result).toEqual(mockUser); expect(axios.get).toHaveBeenCalledWith("/api/users/1"); }); it("throws when the request fails", async () => { axios.get.mockRejectedValueOnce(new Error("Network error")); await expect(getUser(1)).rejects.toThrow("Network error"); }); }); ``` ## Simuler une AxiosError Pour tester les chemins de gestion d'erreurs qui inspectent `error.response`, créez directement une instance d'`AxiosError` : ```js import axios, { AxiosError } from "axios"; import { vi } from "vitest"; const mockError = new AxiosError( "Not Found", "ERR_BAD_REQUEST", {}, // config {}, // request { // response status: 404, statusText: "Not Found", data: { message: "User not found" }, headers: {}, config: {}, } ); axios.get.mockRejectedValueOnce(mockError); ``` ## Utiliser axios-mock-adapter [axios-mock-adapter](https://github.com/ctimmerm/axios-mock-adapter) est une bibliothèque qui installe un adaptateur personnalisé sur votre instance axios, interceptant les requêtes au niveau de l'adaptateur. Cela signifie que vos intercepteurs continuent de s'exécuter, ce qui la rend plus adaptée aux tests d'intégration. ```bash npm install --save-dev axios-mock-adapter ``` ```js import axios from "axios"; import MockAdapter from "axios-mock-adapter"; const mock = new MockAdapter(axios); // Simuler une requête GET mock.onGet("/api/users/1").reply(200, { id: 1, name: "Jay" }); // Simuler une requête POST mock.onPost("/api/users").reply(201, { id: 2, name: "New User" }); // Simuler une erreur réseau mock.onGet("/api/failing").networkError(); // Simuler un délai d'attente dépassé mock.onGet("/api/slow").timeout(); ``` Réinitialisez les simulations entre les tests : ```js afterEach(() => { mock.reset(); // effacer tous les gestionnaires enregistrés }); ``` ## Tester les intercepteurs Pour tester les intercepteurs de manière isolée, créez une nouvelle instance axios dans votre test : ```js import axios from "axios"; import MockAdapter from "axios-mock-adapter"; describe("auth interceptor", () => { it("attaches a Bearer token to every request", async () => { const instance = axios.create(); const mock = new MockAdapter(instance); // Ajoutez votre intercepteur instance.interceptors.request.use((config) => { config.headers.set("Authorization", "Bearer test-token"); return config; }); // Capturez la configuration de la requête en inspectant ce que mock a reçu let capturedConfig; mock.onGet("/api/data").reply((config) => { capturedConfig = config; return [200, {}]; }); await instance.get("/api/data"); expect(capturedConfig.headers["Authorization"]).toBe("Bearer test-token"); }); }); ``` ## Conseils - Simulez toujours au niveau du module (ou utilisez `MockAdapter`) — évitez de simuler des méthodes individuelles sur une instance partagée, car l'état peut fuiter entre les tests. - Préférez `mockResolvedValueOnce` / `mockRejectedValueOnce` à `mockResolvedValue` pour que les tests soient isolés et ne s'affectent pas mutuellement. - Pour tester la logique de nouvelle tentative, utilisez `MockAdapter` afin que l'intercepteur testé s'exécute réellement à chaque tentative. axios-axios-2d06f96/docs/fr/pages/advanced/type-script.md000066400000000000000000000054771521272452000233450ustar00rootroot00000000000000# TypeScript `axios` fournit des définitions de types TypeScript dans le package npm via `index.d.ts` (ESM) et `index.d.cts` (CJS), de sorte que la vérification de types et le support de l'éditeur fonctionnent immédiatement pour les deux formats de modules. ## Nuances de résolution de modules Comme axios publie à la fois avec un export par défaut ESM et un `module.exports` CJS, il existe quelques nuances de configuration à prendre en compte : - Le paramètre recommandé est `"moduleResolution": "node16"` (impliqué par `"module": "node16"`). Cela nécessite TypeScript 4.7 ou supérieur. - Si vous utilisez ESM, vos paramètres devraient convenir. - Si vous compilez TypeScript en CJS et ne pouvez pas utiliser `"moduleResolution": "node16"`, vous devez activer `esModuleInterop`. - Si vous utilisez TypeScript pour vérifier les types de code JavaScript CJS, votre seule option est `"moduleResolution": "node16"`. ## Type guards pour les erreurs axios Utilisez le type guard `axios.isAxiosError` pour affiner en toute sécurité les erreurs `unknown` dans les blocs `catch`. Après l'affinement, vous pouvez accéder aux propriétés spécifiques à axios telles que `error.response`, `error.config` et `error.code` avec une sécurité de type complète. ```ts import axios from "axios"; let user: User | null = null; try { const { data } = await axios.get("/user?ID=12345"); user = data.userDetails; } catch (error) { if (axios.isAxiosError(error)) { handleAxiosError(error); } else { handleUnexpectedError(error); } } ``` Utilisez `axios.isCancel()` pour affiner les erreurs d'annulation en `CanceledError` : ```ts const controller = new AbortController(); try { await axios.get("/user?ID=12345", { signal: controller.signal }); } catch (error) { if (axios.isCancel(error)) { handleCancellation(error); } } ``` ## Instances et intercepteurs typés Annotez le résultat de `axios.create` avec `AxiosInstance`, et annotez les intercepteurs de requête avec `InternalAxiosRequestConfig` pour obtenir une vérification de types de bout en bout sur un client personnalisé : ```ts import axios, { AxiosInstance, InternalAxiosRequestConfig } from "axios"; const apiClient: AxiosInstance = axios.create({ baseURL: "https://api.example.com", timeout: 10000, }); apiClient.interceptors.request.use((config: InternalAxiosRequestConfig) => { // Ajouter un token d'authentification, journaliser, etc. return config; }); ``` ## Typage des données de réponse Les méthodes de requête axios sont génériques par rapport au type de données de réponse. Passez un paramètre de type à `axios.get` (et aux autres alias) pour typer `response.data` : ```ts interface User { id: number; name: string; } const { data } = await apiClient.get("/users/1"); // `data` est typé comme `User` ``` axios-axios-2d06f96/docs/fr/pages/advanced/x-www-form-urlencoded-format.md000066400000000000000000000112601521272452000265070ustar00rootroot00000000000000# Format x-www-form-urlencoded ## URLSearchParams Par défaut, axios sérialise les objets JavaScript en `JSON`. Pour envoyer des données au format [`application/x-www-form-urlencoded`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) à la place, vous pouvez utiliser l'API [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams), [supportée](http://www.caniuse.com/#feat=urlsearchparams) par la grande majorité des navigateurs, et [Node.js](https://nodejs.org/api/url.html#url_class_urlsearchparams) depuis la version v10 (publiée en 2018). ```js const params = new URLSearchParams({ foo: 'bar' }); params.append('extraparam', 'value'); axios.post('/foo', params); ``` ## Chaîne de requête Pour les navigateurs plus anciens ou les environnements sans `URLSearchParams`, vous pouvez utiliser la bibliothèque [`qs`](https://github.com/ljharb/qs) pour sérialiser des objets au format `application/x-www-form-urlencoded`. ```js const qs = require('qs'); axios.post('/foo', qs.stringify({ bar: 123 })); ``` Pour un contrôle complet sur les en-têtes et la méthode, passez la sortie de `qs.stringify` comme `data` de la requête et définissez `Content-Type` explicitement : ```js import qs from 'qs'; const data = { bar: 123 }; const options = { method: 'POST', headers: { 'content-type': 'application/x-www-form-urlencoded' }, data: qs.stringify(data), url: '/foo', }; axios(options); ``` Dans les très anciennes versions de Node.js, vous pouvez utiliser le module natif `querystring` fourni avec Node.js. Notez que ce module a été déprécié dans Node.js v16 — préférez `URLSearchParams` ou `qs` pour le nouveau code. ```js const querystring = require('querystring'); axios.post('https://something.com/', querystring.stringify({ foo: 'bar' })); ``` ::: tip Préférez `qs` pour les objets imbriqués La bibliothèque `qs` est préférable si vous devez sérialiser des objets imbriqués, car la méthode `querystring` présente des [problèmes connus](https://github.com/nodejs/node-v0.x-archive/issues/1665) avec ce cas d'usage. ::: ## Sérialisation automatique vers URLSearchParams À partir de la version v0.21.0, axios sérialise automatiquement les objets JavaScript en `URLSearchParams` si l'en-tête `Content-Type` est défini à `application/x-www-form-urlencoded`. Cela signifie que vous pouvez passer directement un objet JavaScript à la propriété `data` de la configuration de requête axios. Par exemple lors de l'envoi de données vers une requête `POST` : ```js const data = { x: 1, arr: [1, 2, 3], arr2: [1, [2], 3], users: [ { name: 'Peter', surname: 'Griffin' }, { name: 'Thomas', surname: 'Anderson' }, ], }; await axios.postForm('https://postman-echo.com/post', data, { headers: { 'content-type': 'application/x-www-form-urlencoded' }, }); ``` L'objet `data` sera automatiquement sérialisé en `URLSearchParams` et envoyé au format `application/x-www-form-urlencoded`. Le serveur recevra les données suivantes : ```json { "x": "1", "arr[]": ["1", "2", "3"], "arr2[0]": "1", "arr2[1][0]": "2", "arr2[2]": "3", "users[0][name]": "Peter", "users[0][surname]": "Griffin", "users[1][name]": "Thomas", "users[1][surname]": "Anderson" } ``` Si le body-parser de votre backend (comme `body-parser` d'`express.js`) prend en charge le décodage des objets imbriqués, vous obtiendrez automatiquement le même objet côté serveur. ## Limite de profondeur pour la sérialisation des paramètres Lorsqu'axios sérialise un objet `params` via `AxiosURLSearchParams`, le même parcours récursif utilisé par le sérialiseur FormData est appelé. Une option `maxDepth` (par défaut `100`) limite la profondeur de récursion. Les charges utiles dépassant la limite lèvent une `AxiosError` avec `code: 'ERR_FORM_DATA_DEPTH_EXCEEDED'` au lieu de provoquer un débordement de pile d'appels. ```js // Augmenter la limite si votre objet params nécessite légitimement plus de 100 niveaux d'imbrication : axios.get('/api', { params: deepObject, paramsSerializer: { maxDepth: 200 } }); ``` ::: warning Note de sécurité N'augmentez `maxDepth` que si votre schéma le nécessite réellement. La valeur par défaut de 100 protège le code côté serveur qui transfère des données contrôlées par le client vers axios en tant que `params` contre les attaques DoS via des objets profondément imbriqués. ::: ```js var app = express(); app.use(bodyParser.urlencoded({ extended: true })); // support des corps encodés app.post('/', function (req, res, next) { // écho du corps en JSON res.send(JSON.stringify(req.body)); }); server = app.listen(3000); ``` axios-axios-2d06f96/docs/fr/pages/getting-started/000077500000000000000000000000001521272452000220635ustar00rootroot00000000000000axios-axios-2d06f96/docs/fr/pages/getting-started/examples/000077500000000000000000000000001521272452000237015ustar00rootroot00000000000000axios-axios-2d06f96/docs/fr/pages/getting-started/examples/commonjs.md000066400000000000000000000105701521272452000260530ustar00rootroot00000000000000# Exemples JavaScript ## Importer la bibliothèque Pour importer la bibliothèque dans un environnement CommonJS, vous pouvez utiliser la fonction `require`, ou l'instruction `import` si vous utilisez un bundler comme Webpack ou Rollup. #### Sans bundler ```js const axios = require("axios"); ``` #### Avec bundler (webpack, rollup, vite, etc.) ```js import axios from "axios"; ``` ## Utiliser then/catch/finally Comme axios retourne une Promise en son coeur, vous pouvez choisir d'utiliser des callbacks avec `then`, `catch` et `finally` pour gérer vos données de réponse, les erreurs et la fin de la requête. ### Requête GET ```js axios .get("https://jsonplaceholder.typicode.com/posts", { params: { postId: 5, }, }) .then((response) => { console.log(response.data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Request completed"); }); ``` ### Requête POST ```js axios .post("https://jsonplaceholder.typicode.com/posts", { title: "foo", body: "bar", userId: 1, }) .then((response) => { console.log(response.data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Request completed"); }); ``` ### Requête PUT ```js axios .put("https://jsonplaceholder.typicode.com/posts/1", { title: "foo", body: "bar", userId: 1, }) .then((response) => { console.log(response.data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Request completed"); }); ``` ### Requête PATCH ```js axios .patch("https://jsonplaceholder.typicode.com/posts/1", { title: "foo", }) .then((response) => { console.log(response.data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Request completed"); }); ``` ### Requête DELETE ```js axios .delete("https://jsonplaceholder.typicode.com/posts/1") .then((response) => { console.log(response.data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Request completed"); }); ``` ## Utiliser async/await Une autre façon de gérer les promises est d'utiliser `async` et `await`. Cela vous permet d'utiliser des blocs try/catch/finally pour gérer les erreurs et la fin de la requête. Cette approche rend votre code plus lisible et plus facile à comprendre, et permet également d'éviter ce qu'on appelle le « callback hell ». ::: tip Remarque : async/await fait partie d'ECMAScript 2017 et n'est pas supporté par Internet Explorer et les navigateurs plus anciens. À utiliser avec précaution. ::: ### Requête GET ```js const getPosts = async () => { try { const response = await axios.get( "https://jsonplaceholder.typicode.com/posts", { params: { postId: 5, }, } ); console.log(response.data); } catch (error) { console.error(error); } finally { console.log("Request completed"); } }; ``` ### Requête POST ```js const createPost = async () => { try { const response = await axios.post( "https://jsonplaceholder.typicode.com/posts", { title: "foo", body: "bar", userId: 1, } ); console.log(response.data); } catch (error) { console.error(error); } finally { console.log("Request completed"); } }; ``` ### Requête PUT ```js const updatePost = async () => { try { const response = await axios.put( "https://jsonplaceholder.typicode.com/posts/1", { title: "foo", body: "bar", userId: 1, } ); console.log(response.data); } catch (error) { console.error(error); } finally { console.log("Request completed"); } }; ``` ### Requête PATCH ```js const updatePost = async () => { try { const response = await axios.patch( "https://jsonplaceholder.typicode.com/posts/1", { title: "foo", } ); console.log(response.data); } catch (error) { console.error(error); } finally { console.log("Request completed"); } }; ``` ### Requête DELETE ```js const deletePost = async () => { try { const response = await axios.delete( "https://jsonplaceholder.typicode.com/posts/1" ); console.log(response.data); } catch (error) { console.error(error); } finally { console.log("Request completed"); } }; ``` axios-axios-2d06f96/docs/fr/pages/getting-started/examples/typescript.md000066400000000000000000000067751521272452000264500ustar00rootroot00000000000000# Exemple TypeScript ## Importer les types axios inclut des définitions TypeScript prêtes à l'emploi. Vous pouvez importer les types dont vous avez besoin directement depuis `"axios"` : ```ts import axios from "axios"; import type { AxiosRequestConfig, AxiosResponse, AxiosError } from "axios"; ``` ## Typer une requête Utilisez un paramètre de type générique sur la réponse pour indiquer à TypeScript la forme que prendront vos données : ```ts import axios from "axios"; type Post = { userId: number; id: number; title: string; body: string; }; const response = await axios.get("https://jsonplaceholder.typicode.com/posts/1"); console.log(response.data.title); // TypeScript sait que c'est une string ``` ## Typer une fonction Encapsulez les requêtes dans des fonctions avec des types de retour explicites pour une sécurité de type maximale : ```ts import axios, { AxiosResponse } from "axios"; type Post = { userId: number; id: number; title: string; body: string; }; const getPost = async (id: number): Promise => { const response = await axios.get( `https://jsonplaceholder.typicode.com/posts/${id}` ); return response.data; }; ``` ## Typer une requête POST Vous pouvez typer à la fois le corps de la requête et la réponse attendue : ```ts type CreatePostBody = { title: string; body: string; userId: number; }; type CreatePostResponse = CreatePostBody & { id: number }; const createPost = async (data: CreatePostBody): Promise => { const response = await axios.post( "https://jsonplaceholder.typicode.com/posts", data ); return response.data; }; ``` ## Instance axios typée Créez une instance typée afin d'y intégrer votre URL de base et vos en-têtes : ```ts import axios from "axios"; import type { AxiosInstance } from "axios"; const api: AxiosInstance = axios.create({ baseURL: "https://api.example.com", timeout: 5000, }); ``` ## Intercepteurs typés Utilisez `InternalAxiosRequestConfig` (et non `AxiosRequestConfig`) pour les intercepteurs de requête dans v1.x : ```ts import axios from "axios"; import type { InternalAxiosRequestConfig, AxiosResponse } from "axios"; api.interceptors.request.use((config: InternalAxiosRequestConfig) => { config.headers.set("Authorization", `Bearer ${getToken()}`); return config; }); api.interceptors.response.use( (response: AxiosResponse) => response, (error) => Promise.reject(error) ); ``` ## Typer les erreurs Utilisez `axios.isAxiosError()` pour affiner le type d'une erreur capturée : ```ts import axios, { AxiosError } from "axios"; type ApiError = { message: string; code: number; }; try { await axios.get("/api/protected-resource"); } catch (error) { if (axios.isAxiosError(error)) { // error.response?.data est typé comme ApiError console.error(error.response?.data.message); console.error(error.response?.status); } else { throw error; } } ``` ## Notes sur la configuration TypeScript Comme axios publie à la fois des versions ESM et CJS, il existe quelques nuances selon votre configuration : - Le paramètre recommandé est `"moduleResolution": "node16"` (impliqué par `"module": "node16"`). Cela nécessite TypeScript 4.7 ou supérieur. - Si vous compilez TypeScript vers CJS et ne pouvez pas utiliser `"moduleResolution": "node16"`, activez `"esModuleInterop": true`. - Si vous utilisez TypeScript pour vérifier les types de code JavaScript CJS, votre seule option est `"moduleResolution": "node16"`. axios-axios-2d06f96/docs/fr/pages/getting-started/features.md000066400000000000000000000061311521272452000242240ustar00rootroot00000000000000# Fonctionnalités axios est un client HTTP puissant qui propose une API simple et facile à utiliser pour effectuer des requêtes HTTP. Il prend en charge tous les navigateurs modernes et est largement utilisé dans la communauté JavaScript. Voici quelques-unes des fonctionnalités qui font d'axios un excellent choix pour votre prochain projet. ## Isomorphique axios est un client HTTP universel qui peut être utilisé aussi bien dans le navigateur que dans Node.js. Cela signifie que vous pouvez utiliser axios pour effectuer des requêtes API depuis votre code frontend aussi bien que depuis votre code backend. Cela fait d'axios un excellent choix pour développer des applications web progressives, des applications monopages et des applications avec rendu côté serveur. axios est également un excellent choix pour les équipes qui travaillent à la fois sur le frontend et le backend. En utilisant axios pour les deux, vous disposez d'une API cohérente pour effectuer des requêtes HTTP, ce qui peut contribuer à réduire la complexité de votre code. ## Support Fetch axios offre une prise en charge de premier plan de l'API Fetch, qui est un remplacement moderne de l'API XHR. L'adaptateur est optionnel et peut être activé via la configuration. La même API est maintenue pour les adaptateurs XHR et Fetch, ce qui facilite l'adoption de l'API Fetch dans votre code sans modifier votre code existant. ## Support des navigateurs axios prend en charge tous les navigateurs modernes et certains navigateurs plus anciens, notamment Chrome, Firefox, Safari et Edge. axios est un excellent choix pour développer des applications web devant prendre en charge un large éventail de navigateurs. ## Support de Node.js axios supporte également un large éventail de versions de Node.js, avec une compatibilité testée jusqu'à la version v12.x, ce qui en fait un bon choix dans les environnements où la mise à jour vers la dernière version de Node.js n'est pas possible ou pratique. En plus de Node.js, axios dispose de tests de fumée pour Bun et Deno qui valident les comportements clés de l'exécution et renforcent la confiance dans la compatibilité multi-environnements. ## Fonctionnalités supplémentaires - Support de l'API Promise - Interception des requêtes et des réponses - Transformation des données de requête et de réponse - Abort controller - Délais d'attente (timeouts) - Sérialisation des paramètres de requête avec support des entrées imbriquées - Sérialisation automatique du corps de la requête vers : - JSON (application/json) - Multipart / FormData (multipart/form-data) - Formulaire encodé en URL (application/x-www-form-urlencoded) - Envoi de formulaires HTML en JSON - Gestion automatique des données JSON dans la réponse - Capture de la progression pour les navigateurs et Node.js avec des informations supplémentaires (vitesse de transfert, temps restant) - Limitation de la bande passante pour Node.js - Compatible avec les implémentations conformes de FormData et Blob (y compris Node.js) - Protection côté client contre les attaques XSRF axios-axios-2d06f96/docs/fr/pages/getting-started/first-steps.md000066400000000000000000000105621521272452000246740ustar00rootroot00000000000000# Premiers pas Bienvenue dans la documentation d'axios ! Ce guide vous aidera à démarrer avec axios et à effectuer votre première requête API. Si vous débutez avec axios, nous vous recommandons de commencer ici. ## Installation Vous pouvez utiliser axios dans votre projet de plusieurs façons. La méthode la plus courante consiste à l'installer depuis npm et à l'inclure dans votre projet. Nous supportons également jsDelivr, unpkg, et d'autres options. #### Avec npm ```bash npm install axios ``` #### Avec pnpm ```bash pnpm install axios ``` #### Avec yarn ```bash yarn add axios ``` #### Avec bun ```bash bun add axios ``` #### Avec deno ```bash deno install npm:axios ``` #### Avec jsDelivr Lors de l'utilisation de jsDelivr, nous recommandons d'utiliser la version minifiée ainsi que d'épingler le numéro de version afin d'éviter des changements inattendus. Si vous souhaitez utiliser la dernière version, vous pouvez le faire en omettant le numéro de version. Ceci est fortement déconseillé en production car cela peut entraîner des modifications inattendues dans votre application. ```html ``` #### Avec unpkg Lors de l'utilisation d'unpkg, nous recommandons d'utiliser la version minifiée ainsi que d'épingler le numéro de version afin d'éviter des changements inattendus. Si vous souhaitez utiliser la dernière version, vous pouvez le faire en omettant le numéro de version. Ceci est fortement déconseillé en production car cela peut entraîner des modifications inattendues dans votre application. ```html ``` ## Importer axios Une fois installé, vous pouvez importer la bibliothèque en utilisant `import` ou `require` : ```js import axios, { isCancel, AxiosError } from "axios"; ``` Vous pouvez également utiliser l'export par défaut, puisque l'export nommé est juste une réexportation depuis la fabrique axios : ```js import axios from "axios"; console.log(axios.isCancel("something")); ``` Si vous utilisez `require` pour l'importation, **seul l'export par défaut est disponible** : ```js const axios = require("axios"); console.log(axios.isCancel("something")); ``` Pour certains bundlers et linters ES6, vous pourriez avoir besoin de : ```js import { default as axios } from "axios"; ``` Pour les environnements personnalisés ou hérités où la résolution de modules ne se comporte pas correctement, vous pouvez importer le bundle préconstruit directement : ```js const axios = require("axios/dist/browser/axios.cjs"); // bundle CommonJS navigateur (ES2017) // const axios = require("axios/dist/node/axios.cjs"); // bundle CommonJS Node (ES2017) ``` ## Votre première requête Une requête axios peut être effectuée en seulement deux lignes de code. Envoyer votre première requête avec axios est très simple. Vous pouvez interroger n'importe quelle API en fournissant l'URL et la méthode. Par exemple, pour effectuer une requête GET vers l'API JSONPlaceholder, vous pouvez utiliser le code suivant : ```js import axios from "axios"; const response = await axios.get( "https://jsonplaceholder.typicode.com/posts/1" ); console.log(response.data); ``` axios propose une API simple pour effectuer des requêtes. Vous pouvez utiliser la méthode `axios.get` pour une requête GET, la méthode `axios.post` pour une requête POST, et ainsi de suite. Vous pouvez également utiliser la méthode `axios.request` pour effectuer une requête avec n'importe quelle méthode HTTP. ::: tip Définissez un timeout en production Sans `timeout`, une requête bloquée peut rester en attente indéfiniment. Passez-en un via la configuration de requête : ```js const response = await axios.get("https://example.com/data", { timeout: 5000, // 5 secondes }); ``` Voir [`timeout` dans la configuration de requête](/pages/advanced/request-config#timeout) et [Gestion des erreurs](/pages/advanced/error-handling) pour les codes `ECONNABORTED` / `ETIMEDOUT` correspondants. ::: ## Prochaines étapes Maintenant que vous avez effectué votre première requête avec axios, vous êtes prêt à explorer le reste de la documentation. Vous pouvez en apprendre davantage sur l'envoi de requêtes, la gestion des réponses et l'utilisation d'axios dans vos projets. Consultez le reste de la documentation pour en savoir plus. axios-axios-2d06f96/docs/fr/pages/getting-started/upgrade-guide.md000066400000000000000000000111631521272452000251310ustar00rootroot00000000000000# Guide de migration Ce guide a pour but de vous aider à migrer votre projet d'une version du framework à une autre. Il est recommandé de lire les notes de version de chaque version majeure que vous migrez, car elles peuvent contenir des informations importantes sur les changements incompatibles. ## Migration de v0.x vers v1.x ### Modification de l'instruction d'importation Dans v1.x, l'instruction d'importation a été modifiée pour utiliser l'export `default`. Vous devrez donc mettre à jour vos instructions d'importation en conséquence. ```diff - import { axios } from "axios"; + import axios from "axios"; ``` ### Modifications du système d'intercepteurs Dans v1.x, vous devez utiliser le type `InternalAxiosRequestConfig` pour typer le paramètre `config` dans l'intercepteur de `request`. En effet, le paramètre `config` est désormais typé comme `InternalAxiosRequestConfig` au lieu du type public `AxiosRequestConfig`. ```diff - axios.interceptors.request.use((config: AxiosRequestConfig) => { + axios.interceptors.request.use((config: InternalAxiosRequestConfig) => { return config; }); ``` ### Modifications de la structure des en-têtes de requête Dans v1.x, la structure des en-têtes de requête a été modifiée pour supprimer la propriété `common`. Vous devrez donc mettre à jour votre code pour utiliser la nouvelle structure des en-têtes de requête comme suit : ```diff - if (request.headers?.common?.Authorization) { - request.headers.common.Authorization = ... + if (request.headers?.Authorization) { + request.headers.Authorization = ... ``` Les en-têtes par défaut qui se trouvaient précédemment sous `common`, `get`, `post`, etc. sont désormais définis directement sur `axios.defaults.headers` : ```diff - axios.defaults.headers.common["Accept"] = "application/json"; + axios.defaults.headers["Accept"] = "application/json"; ``` ### Données multipart/form-data Si une requête inclut un payload `FormData`, l'en-tête `Content-Type: multipart/form-data` est désormais défini automatiquement. Supprimez tout en-tête manuel pour éviter les doublons : ```diff - axios.post("/upload", formData, { - headers: { "Content-Type": "multipart/form-data" }, - }); + axios.post("/upload", formData); ``` Si vous définissez explicitement `Content-Type: application/json`, axios sérialisera désormais automatiquement les données en JSON. ### Sérialisation des paramètres v1.x a introduit plusieurs changements incompatibles dans la façon dont les paramètres d'URL sont sérialisés. Les plus importants : **Les `params` sont désormais encodés en pourcentage par défaut.** Si votre backend attendait des crochets bruts issus de l'encodage de style qs, vous devrez peut-être configurer un sérialiseur personnalisé : ```js import qs from 'qs'; axios.create({ paramsSerializer: { serialize: (params) => qs.stringify(params, { arrayFormat: 'brackets' }), }, }); ``` **Les objets imbriqués dans `params` sont désormais sérialisés avec la notation entre crochets** (`foo[bar]=1`) plutôt que la notation pointée. Si votre backend attendait la notation pointée, utilisez un sérialiseur personnalisé. **Les paramètres `null` et `undefined`** sont désormais gérés de manière cohérente : les valeurs `null` sont sérialisées comme des chaînes vides, tandis que les valeurs `undefined` sont entièrement omises. Pour les options complètes de configuration de la sérialisation des paramètres, consultez la page [Configuration de requête](/pages/advanced/request-config). ### Les éléments internes ne sont plus exportés Nous avons décidé de ne plus exporter les éléments internes d'axios. Vous devrez donc mettre à jour votre code pour n'utiliser que l'API publique d'axios. Cette modification a été apportée pour simplifier l'API et réduire la surface exposée d'axios, nous permettant ainsi d'effectuer des modifications internes sans les déclarer comme des changements incompatibles. Veuillez consulter la [référence API](/pages/advanced/api-reference) sur ce site pour obtenir les dernières informations sur l'API publique d'axios. ### Configuration de requête Nous avons apporté des modifications à l'objet de configuration de requête. Veuillez consulter la [référence de configuration](/pages/advanced/request-config) sur ce site pour obtenir les dernières informations. ### Changements incompatibles non répertoriés Ce guide n'est pas exhaustif et peut ne pas couvrir tous les changements incompatibles. Si vous rencontrez un problème, veuillez ouvrir un ticket sur le [dépôt GitHub de la documentation](https://github.com/axios/docs) avec le label `breaking change`. axios-axios-2d06f96/docs/fr/pages/misc/000077500000000000000000000000001521272452000177115ustar00rootroot00000000000000axios-axios-2d06f96/docs/fr/pages/misc/security.md000066400000000000000000000270551521272452000221130ustar00rootroot00000000000000# Politique de sécurité ## ⚠️ Bombe de décompression / mise en tampon de réponse sans limite Par défaut, `maxContentLength` et `maxBodyLength` valent `-1` (illimité). Un serveur malveillant ou compromis peut renvoyer un petit corps compressé en gzip/deflate/brotli/zstd qui s'étend à plusieurs gigaoctets, épuisant la mémoire du processus Node.js. **Si vous effectuez des requêtes vers des serveurs que vous ne contrôlez pas totalement, vous DEVEZ définir `maxContentLength` en fonction de votre charge.** La limite est appliquée chunk par chunk pendant la décompression en flux, il suffit donc de la définir pour neutraliser les attaques de bombe de décompression. ```js axios.get('https://example.com/data', { maxContentLength: 10 * 1024 * 1024, // 10 Mo maxBodyLength: 10 * 1024 * 1024, }); // Ou globalement : axios.defaults.maxContentLength = 10 * 1024 * 1024; axios.defaults.maxBodyLength = 10 * 1024 * 1024; ``` La valeur par défaut n'a pas été durcie car cela casserait silencieusement tout téléchargement légitime dépassant le plafond choisi. Le choix d'un plafond sûr pour des sources non fiables incombe à l'application. ## Autres options sensibles à la sécurité Les options de configuration de requête suivantes ont des implications directes en matière de sécurité. Elles sont documentées intégralement avec le reste de la [configuration de requête](/pages/advanced/request-config), et résumées ici pour qu'elles apparaissent en un seul endroit. | Option | Risque | Atténuation | | --- | --- | --- | | [`socketPath`](/pages/advanced/request-config#socketpath) | Si dérivée d'une entrée non fiable, un attaquant peut rediriger le trafic vers des sockets locaux privilégiés tels que `/var/run/docker.sock`, contournant les protections SSRF basées sur le hostname (CWE-918). | Filtrez ou créez une liste blanche des clés de configuration provenant d'entrées non fiables. Utilisez [`allowedSocketPaths`](/pages/advanced/request-config#allowedsocketpaths) pour restreindre les chemins de socket acceptés. | | [`beforeRedirect`](/pages/advanced/request-config#beforeredirect) | S'exécute après que `follow-redirects` ait retiré les identifiants en cas de rétrogradation de protocole. Réinjecter des identifiants sans vérifier le protocole de destination peut les exposer en HTTP en clair. | Ne réinjectez les identifiants que pour des destinations HTTPS de confiance. Vérifiez `options.protocol === "https:"` avant d'assigner `auth`. | | [`withXSRFToken`](/pages/advanced/request-config#withxsrftoken) | La définir à `true` force l'en-tête XSRF sur les requêtes cross-origin. Les anciennes versions d'axios l'activaient implicitement avec `withCredentials: true` ; les versions plus récentes nécessitent les deux indicateurs. | Laissez à `undefined` (same-origin uniquement) sauf si votre backend valide explicitement XSRF sur les requêtes cross-origin. | | [`redact`](/pages/advanced/request-config#redact) | `AxiosError#toJSON()` inclut la configuration de requête par défaut, ce qui peut faire fuiter des en-têtes `Authorization` ou des identifiants `auth` dans les logs d'erreurs et la télémétrie. | Passez un tableau `redact` avec les noms de clés de configuration sensibles. La correspondance est insensible à la casse et récursive. | | [`formDataHeaderPolicy`](/pages/advanced/request-config#formdataheaderpolicy) | Un `FormData` personnalisé dont `getHeaders()` retourne des valeurs contrôlées par un attaquant peut écraser des en-têtes comme `Authorization` ou en injecter des arbitraires dans Node.js. | Définissez `'content-only'` pour ne copier que `Content-Type` et `Content-Length`, puis définissez les autres en-têtes explicitement via la configuration `headers` de la requête. | ## Durcissement de la chaîne d'approvisionnement : `ignore-scripts` et scripts de cycle de vie Le dépôt fournit un `.npmrc` au niveau du projet qui définit `ignore-scripts=true`. Cela bloque les scripts de cycle de vie npm (`preinstall`, `install`, `postinstall`, `prepare`) de toute dépendance directe ou transitive lors de l'exécution de `npm install` ou `npm ci` à l'intérieur du dépôt. Voir [THREATMODEL.md](https://github.com/axios/axios/blob/v1.x/THREATMODEL.md) (menace T-S2) pour la justification. Une conséquence : le hook `prepare` du dépôt lui-même (qui installe les git hooks de Husky) ne s'exécute **pas** automatiquement. Après votre première installation, activez les git hooks manuellement : ```bash npm ci npm rebuild husky && npx husky ``` Exécutez ces deux commandes une fois par checkout fraîchement effectué. Vous n'avez **pas** besoin de les ré-exécuter après chaque `npm install` suivant. ::: danger Ne supprimez pas `ignore-scripts=true` Supprimer `ignore-scripts=true` de `.npmrc` pour « réparer » l'installation de husky rouvre la surface d'attaque des scripts de cycle de vie pour tout autre paquet de l'arborescence. Tous les workflows CI invoquent déjà npm avec `--ignore-scripts`, donc le comportement local correspond au CI. ::: Nous recommandons le même paramètre `ignore-scripts=true` dans tout projet consommateur qui intègre axios (ou toute autre dépendance) dans un environnement de build manipulant des secrets. ## Vérifier une version publiée Chaque tarball `axios` publié sur npm provient de GitHub Actions et comporte une [attestation de provenance npm](https://docs.npmjs.com/generating-provenance-statements) qui lie cryptographiquement le paquet au workflow et au SHA de commit qui l'a produit. Les consommateurs peuvent vérifier la provenance localement : ```bash # Vérifier chaque paquet de votre lockfile, y compris axios npm audit signatures ``` Une vérification réussie prouve que le tarball a été construit dans l'environnement GitHub Actions de `axios/axios` à partir d'un commit connu — il n'a pas été altéré entre la construction et le registre. Elle ne prouve **pas** que le code de ce commit est exempt de bugs. Si `npm audit signatures` signale une attestation manquante ou invalide pour une version récente d'`axios`, traitez-le comme un incident potentiel de chaîne d'approvisionnement et signalez-le via le canal privé ci-dessous. ## Signaler une vulnérabilité Si vous pensez avoir trouvé une vulnérabilité de sécurité dans le projet, veuillez nous la signaler comme décrit ci-dessous. Nous prenons toutes les vulnérabilités de sécurité au sérieux. Si vous avez trouvé une vulnérabilité dans une bibliothèque tierce, veuillez la signaler aux mainteneurs de cette bibliothèque. ## Processus de signalement Veuillez ne pas signaler les vulnérabilités de sécurité via des issues GitHub publiques. Veuillez utiliser le canal de sécurité officiel sur GitHub en créant un [avis de sécurité](https://github.com/axios/axios/security/advisories/new). ## Politique de divulgation Lorsque nous recevons un rapport de vulnérabilité, nous lui assignons un responsable principal. Le responsable confirme le problème, détermine les versions affectées, évalue la gravité, développe et publie un correctif, et coordonne la divulgation publique avec le rapporteur. ### Engagement de résolution et de divulgation sous 60 jours Nous nous engageons à **résoudre et divulguer publiquement chaque avis de sécurité valide dans les 60 jours calendaires suivant le rapport initial**, à compter du moment où un rapport est reçu via le [canal des avis de sécurité GitHub](https://github.com/axios/axios/security/advisories/new). L'horloge des 60 jours est un engagement envers les rapporteurs et les consommateurs en aval — un filet de sécurité, pas un objectif. Si nous ne pouvons pas livrer un correctif à temps, nous publions tout de même l'avis au jour 60 avec les meilleures recommandations d'atténuation disponibles, afin que les consommateurs puissent agir. **Jalons dans la fenêtre de 60 jours :** | Jour | Jalon | | ---- | ----------------------------------------------------------------------------------------------------------------------------------------- | | 0 | Rapport reçu. Avis privé ouvert sur GitHub. | | ≤ 3 | Accusé de réception envoyé au rapporteur. Décision de triage : dans le périmètre / hors du périmètre / doublon / informations manquantes. | | ≤ 10 | Gravité évaluée (CVSS v4 le cas échéant). Versions affectées confirmées. CVE demandé via GitHub si un identifiant public est justifié. | | ≤ 45 | Correctif développé, revu, testé. Release candidate préparée sur une branche privée. Aperçu proposé au rapporteur pour validation. | | ≤ 60 | Version corrigée publiée sur npm. Avis public + CVE publiés. Rapporteur crédité sauf demande contraire. CHANGELOG mis à jour. | **Exceptions et prolongations.** - Si un rapporteur demande un embargo plus court (par exemple pour présenter ses résultats à une conférence), nous nous adaptons dans la mesure du possible. - Si un correctif nécessite un changement cassant, la coordination avec des consommateurs en aval majeurs, ou une publication en amont de `follow-redirects` / `form-data` / `proxy-from-env`, nous pouvons prolonger au-delà de 60 jours. Toute prolongation est divulguée publiquement au jour 60 via l'avis, avec une ETA révisée et la raison. - Si un rapport est **hors du périmètre** (par exemple, il relève d'un non-objectif explicite documenté dans le [modèle de menaces](https://github.com/axios/axios/blob/v1.x/THREATMODEL.md) du projet), nous le clôturons avec une explication au rapporteur dans la fenêtre de triage (≤ 3 jours). Les rapports hors périmètre n'entrent pas dans la file des 60 jours. - Les **vulnérabilités activement exploitées** sont traitées comme des incidents : le correctif et l'avis sont publiés dès qu'un patch est validé, hors du calendrier des 60 jours. **Attentes vis-à-vis du rapporteur.** Pendant qu'un rapport est sous embargo, nous demandons aux rapporteurs de s'abstenir de toute divulgation publique jusqu'à la plus proche de : (a) la publication coordonnée de l'avis, ou (b) le jour 60. Si l'échéance des 60 jours passe sans action de notre part, les rapporteurs sont libres de divulguer indépendamment — nous considérerons cela comme un échec de notre part, pas du leur. ## Mises à jour de sécurité Les mises à jour de sécurité sont publiées dès que possible après que le correctif a été développé et testé. Nous informons les utilisateurs via le dépôt GitHub du projet et publions les notes de version et les avis de sécurité sur la page des versions GitHub. Nous déprécions également toutes les versions contenant la vulnérabilité. ## Réponse à incident côté mainteneur Pour les scénarios de compromission affectant les comptes mainteneurs, les postes de travail ou l'infrastructure de publication (phishing, clé matérielle volée, tag ou publication inattendus), le projet maintient un runbook interne de réponse à incident dans [THREATMODEL.md §3.7](https://github.com/axios/axios/blob/v1.x/THREATMODEL.md#37-incident-response-runbook). Il couvre la révocation des sessions, la rotation des clés, la notification en aval et les procédures de dépublication/dépréciation. ## Partenaires de sécurité et remerciements Nous tenons à remercier les chercheurs en sécurité suivants pour leur collaboration afin de contribuer à la sécurité du projet pour tous : - [Socket Dev](https://socket.dev/) - [GitHub Security Lab](https://securitylab.github.com/) axios-axios-2d06f96/docs/fr/pages/misc/semver.md000066400000000000000000000053721521272452000215430ustar00rootroot00000000000000# Versionnage sémantique Le versionnage sémantique est un schéma de versionnage utilisé pour communiquer la nature des changements dans un package logiciel. C'est un ensemble simple de règles et d'exigences qui dictent comment les numéros de version sont attribués et incrémentés. ## Versionnage d'axios axios suit le schéma de versionnage sémantique. Cela signifie que chaque version d'axios se voit attribuer un numéro de version composé de trois parties : majeure, mineure et correctif. Le numéro de version est incrémenté en fonction de la nature des changements apportés dans la version. Dans le passé, axios n'a pas toujours strictement suivi le versionnage sémantique, mais à l'avenir, une adhérence beaucoup plus stricte au schéma de versionnage sémantique sera maintenue pour garantir que les utilisateurs peuvent se fier aux numéros de version pour communiquer la nature des changements dans la bibliothèque. Un bref aperçu du schéma de versionnage est fourni ci-dessous. ## Format de version Un numéro de version sémantique est composé de trois parties : 1. Version majeure 2. Version mineure 3. Version de correctif Le numéro de version est écrit sous la forme `MAJEURE.MINEURE.CORRECTIF`. Chaque partie du numéro de version a une signification spécifique : - **Version majeure** : Incrémentée lorsque vous effectuez des changements d'API incompatibles. - **Version mineure** : Incrémentée lorsque vous ajoutez des fonctionnalités de manière rétrocompatible. - **Version de correctif** : Incrémentée lorsque vous effectuez des corrections de bugs rétrocompatibles. ## Versions de pré-publication En plus des trois parties du numéro de version, vous pouvez ajouter une version de pré-publication. Cela se fait en ajoutant un tiret et une série d'identifiants séparés par des points immédiatement après la version de correctif. Par exemple, `1.0.0-alpha.1`. Les versions de pré-publication sont utilisées pour indiquer qu'une version est instable et peut ne pas satisfaire les exigences de compatibilité prévues telles qu'indiquées par le numéro de version. Les versions de pré-publication sont ordonnées en fonction de l'ordre des identifiants. Par exemple, `1.0.0-alpha.1` vient avant `1.0.0-alpha.2`. ## Plages de versions Lorsque vous spécifiez une plage de versions pour un package, vous pouvez utiliser une variété d'opérateurs pour spécifier la plage de versions acceptables. Les opérateurs suivants sont disponibles : - `>` : Supérieur à - `<` : Inférieur à - `>=` : Supérieur ou égal à - `<=` : Inférieur ou égal à - `~` : Approximativement égal à - `^` : Compatible avec Par exemple, `^1.0.0` signifie que toute version supérieure ou égale à `1.0.0` et inférieure à `2.0.0` est acceptable. axios-axios-2d06f96/docs/fr/pages/misc/sponsors.md000066400000000000000000000115471521272452000221310ustar00rootroot00000000000000--- layout: page ---

Sponsors

Axios est soutenu par les organisations suivantes. Si vous souhaitez sponsoriser Axios, consultez notre page Open Collective pour plus d'informations.

{{ capitalizeFirstLetter(sponsor.tier) }}
{{ sponsor.name }}
axios-axios-2d06f96/docs/index.md000066400000000000000000000234731521272452000167120ustar00rootroot00000000000000--- # https://vitepress.dev/reference/default-theme-home-page layout: home hero: name: 'axios docs' text: 'axios is a simple HTTP client for the browser and Node.js' image: dark: /logo.svg light: /logo-light.svg alt: axios actions: - theme: brand text: Get started link: /pages/getting-started/first-steps - theme: alt text: API reference link: /pages/advanced/api-reference features: - title: Simple implementation details: Getting started with axios is as simple as a single line of code. Making simple API requests can be done in 2 lines of code. - title: Powerful interceptors details: Our innovative interceptor system allows you to control the request and response lifecycle. You can modify requests, responses, and errors. - title: TypeScript support details: axios declares types and has full support for TypeScript. This means you can use axios with confidence in your TypeScript projects. ---

Sponsors

{{ sponsor.name }}

{{ capitalizeFirstLetter(sponsor.tier) }}
axios-axios-2d06f96/docs/package-lock.json000066400000000000000000003500651521272452000204750ustar00rootroot00000000000000{ "name": "axios", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "axios", "version": "1.0.0", "hasInstallScript": true, "license": "MIT", "dependencies": { "@splidejs/splide": "^4.1.4", "axios": "^1.15.2", "vitepress": "^1.6.4" }, "devDependencies": { "chalk": "^5.3.0", "dayjs": "^1.11.13", "patch-package": "^8.0.1", "vue": "^3.5.32" } }, "node_modules/@algolia/abtesting": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.16.1.tgz", "integrity": "sha512-Xxk4l00pYI+jE0PNw8y0MvsQWh5278WRtZQav8/BMMi3HKi2xmeuqe11WJ3y8/6nuBHdv39w76OpJb09TMfAVQ==", "license": "MIT", "dependencies": { "@algolia/client-common": "5.50.1", "@algolia/requester-browser-xhr": "5.50.1", "@algolia/requester-fetch": "5.50.1", "@algolia/requester-node-http": "5.50.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/autocomplete-core": { "version": "1.17.7", "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.17.7.tgz", "integrity": "sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==", "license": "MIT", "dependencies": { "@algolia/autocomplete-plugin-algolia-insights": "1.17.7", "@algolia/autocomplete-shared": "1.17.7" } }, "node_modules/@algolia/autocomplete-plugin-algolia-insights": { "version": "1.17.7", "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.7.tgz", "integrity": "sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==", "license": "MIT", "dependencies": { "@algolia/autocomplete-shared": "1.17.7" }, "peerDependencies": { "search-insights": ">= 1 < 3" } }, "node_modules/@algolia/autocomplete-preset-algolia": { "version": "1.17.7", "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.7.tgz", "integrity": "sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==", "license": "MIT", "dependencies": { "@algolia/autocomplete-shared": "1.17.7" }, "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", "algoliasearch": ">= 4.9.1 < 6" } }, "node_modules/@algolia/autocomplete-shared": { "version": "1.17.7", "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.7.tgz", "integrity": "sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==", "license": "MIT", "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", "algoliasearch": ">= 4.9.1 < 6" } }, "node_modules/@algolia/client-abtesting": { "version": "5.50.1", "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.50.1.tgz", "integrity": "sha512-4peZlPXMwTOey9q1rQKMdCnwZb/E95/1e+7KujXpLLSh0FawJzg//U2NM+r4AiJy4+naT2MTBhj0K30yshnVTA==", "license": "MIT", "dependencies": { "@algolia/client-common": "5.50.1", "@algolia/requester-browser-xhr": "5.50.1", "@algolia/requester-fetch": "5.50.1", "@algolia/requester-node-http": "5.50.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-analytics": { "version": "5.50.1", "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.50.1.tgz", "integrity": "sha512-i+aWHHG8NZvGFHtPeMZkxL2Loc6Fm7iaRo15lYSMx8gFL+at9vgdWxhka7mD1fqxkrxXsQstUBCIsSY8FvkEOw==", "license": "MIT", "dependencies": { "@algolia/client-common": "5.50.1", "@algolia/requester-browser-xhr": "5.50.1", "@algolia/requester-fetch": "5.50.1", "@algolia/requester-node-http": "5.50.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-common": { "version": "5.50.1", "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.50.1.tgz", "integrity": "sha512-Hw52Fwapyk/7hMSV/fI4+s3H9MGZEUcRh4VphyXLAk2oLYdndVUkc6KBi0zwHSzwPAr+ZBwFPe2x6naUt9mZGw==", "license": "MIT", "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-insights": { "version": "5.50.1", "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.50.1.tgz", "integrity": "sha512-Bn/wtwhJ7p1OD/6pY+Zzn+zlu2N/SJnH46md/PAbvqIzmjVuwjNwD4y0vV5Ov8naeukXdd7UU9v550+v8+mtlg==", "license": "MIT", "dependencies": { "@algolia/client-common": "5.50.1", "@algolia/requester-browser-xhr": "5.50.1", "@algolia/requester-fetch": "5.50.1", "@algolia/requester-node-http": "5.50.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-personalization": { "version": "5.50.1", "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.50.1.tgz", "integrity": "sha512-0V4Tu0RWR8YxkgI9EPVOZHGE4K5pEIhkLNN0CTkP/rnPsqaaSQpNMYW3/mGWdiKOWbX0iVmwLB9QESk3H0jS5g==", "license": "MIT", "dependencies": { "@algolia/client-common": "5.50.1", "@algolia/requester-browser-xhr": "5.50.1", "@algolia/requester-fetch": "5.50.1", "@algolia/requester-node-http": "5.50.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-query-suggestions": { "version": "5.50.1", "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.50.1.tgz", "integrity": "sha512-jofcWNYMXJDDr87Z2eivlWY6o71Zn7F7aOvQCXSDAo9QTlyf7BhXEsZymLUvF0O1yU9Q9wvrjAWn8uVHYnAvgw==", "license": "MIT", "dependencies": { "@algolia/client-common": "5.50.1", "@algolia/requester-browser-xhr": "5.50.1", "@algolia/requester-fetch": "5.50.1", "@algolia/requester-node-http": "5.50.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/client-search": { "version": "5.50.1", "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.50.1.tgz", "integrity": "sha512-OteRb8WubcmEvU0YlMJwCXs3Q6xrdkb0v50/qZBJP1TF0CvujFZQM++9BjEkTER/Jr9wbPHvjSFKnbMta0b4dQ==", "license": "MIT", "dependencies": { "@algolia/client-common": "5.50.1", "@algolia/requester-browser-xhr": "5.50.1", "@algolia/requester-fetch": "5.50.1", "@algolia/requester-node-http": "5.50.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/ingestion": { "version": "1.50.1", "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.50.1.tgz", "integrity": "sha512-0GmfSgDQK6oiIVXnJvGxtNFOfosBspRTR7csCOYCTL1P8QtxX2vDCIKwTM7xdSAEbJaZ43QlWg25q0Qdsndz8Q==", "license": "MIT", "dependencies": { "@algolia/client-common": "5.50.1", "@algolia/requester-browser-xhr": "5.50.1", "@algolia/requester-fetch": "5.50.1", "@algolia/requester-node-http": "5.50.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/monitoring": { "version": "1.50.1", "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.50.1.tgz", "integrity": "sha512-ySuigKEe4YjYV3si8NVk9BHQpFj/1B+ON7DhhvTvbrZJseHQQloxzq0yHwKmznSdlO6C956fx4pcfOKkZClsyg==", "license": "MIT", "dependencies": { "@algolia/client-common": "5.50.1", "@algolia/requester-browser-xhr": "5.50.1", "@algolia/requester-fetch": "5.50.1", "@algolia/requester-node-http": "5.50.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/recommend": { "version": "5.50.1", "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.50.1.tgz", "integrity": "sha512-Cp8T/B0gVmjFlzzp6eP47hwKh5FGyeqQp1N48/ANDdvdiQkPqLyFHQVDwLBH0LddfIPQE+yqmZIgmKc82haF4A==", "license": "MIT", "dependencies": { "@algolia/client-common": "5.50.1", "@algolia/requester-browser-xhr": "5.50.1", "@algolia/requester-fetch": "5.50.1", "@algolia/requester-node-http": "5.50.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-browser-xhr": { "version": "5.50.1", "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.50.1.tgz", "integrity": "sha512-XKdGGLikfrlK66ZSXh/vWcXZZ8Vg3byDFbJD8pwEvN1FoBRGxhxya476IY2ohoTymLa4qB5LBRlIa+2TLHx3Uw==", "license": "MIT", "dependencies": { "@algolia/client-common": "5.50.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-fetch": { "version": "5.50.1", "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.50.1.tgz", "integrity": "sha512-mBAU6WyVsDwhHyGM+nodt1/oebHxgvuLlOAoMGbj/1i6LygDHZWDgL1t5JEs37x9Aywv7ZGhqbM1GsfZ54sU6g==", "license": "MIT", "dependencies": { "@algolia/client-common": "5.50.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@algolia/requester-node-http": { "version": "5.50.1", "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.50.1.tgz", "integrity": "sha512-qmo1LXrNKLHvJE6mdQbLnsZAoZvj7VyF2ft4xmbSGWI2WWm87fx/CjUX4kEExt4y0a6T6nEts6ofpUfH5TEE1A==", "license": "MIT", "dependencies": { "@algolia/client-common": "5.50.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@babel/helper-string-parser": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { "version": "7.28.5", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { "version": "7.29.2", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", "license": "MIT", "dependencies": { "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/types": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@docsearch/css": { "version": "3.8.2", "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.8.2.tgz", "integrity": "sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ==", "license": "MIT" }, "node_modules/@docsearch/js": { "version": "3.8.2", "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.8.2.tgz", "integrity": "sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ==", "license": "MIT", "dependencies": { "@docsearch/react": "3.8.2", "preact": "^10.0.0" } }, "node_modules/@docsearch/react": { "version": "3.8.2", "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.8.2.tgz", "integrity": "sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg==", "license": "MIT", "dependencies": { "@algolia/autocomplete-core": "1.17.7", "@algolia/autocomplete-preset-algolia": "1.17.7", "@docsearch/css": "3.8.2", "algoliasearch": "^5.14.2" }, "peerDependencies": { "@types/react": ">= 16.8.0 < 19.0.0", "react": ">= 16.8.0 < 19.0.0", "react-dom": ">= 16.8.0 < 19.0.0", "search-insights": ">= 1 < 3" }, "peerDependenciesMeta": { "@types/react": { "optional": true }, "react": { "optional": true }, "react-dom": { "optional": true }, "search-insights": { "optional": true } } }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", "cpu": [ "ppc64" ], "license": "MIT", "optional": true, "os": [ "aix" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/android-arm": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", "cpu": [ "arm" ], "license": "MIT", "optional": true, "os": [ "android" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/android-arm64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ "android" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/android-x64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ "android" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/darwin-arm64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/darwin-x64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/freebsd-arm64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ "freebsd" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/freebsd-x64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ "freebsd" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/linux-arm": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", "cpu": [ "arm" ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/linux-arm64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/linux-ia32": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", "cpu": [ "ia32" ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/linux-loong64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", "cpu": [ "loong64" ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/linux-mips64el": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", "cpu": [ "mips64el" ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/linux-ppc64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", "cpu": [ "ppc64" ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/linux-riscv64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", "cpu": [ "riscv64" ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/linux-s390x": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", "cpu": [ "s390x" ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/linux-x64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/netbsd-arm64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ "netbsd" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/netbsd-x64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ "netbsd" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/openbsd-arm64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ "openbsd" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/openbsd-x64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ "openbsd" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/openharmony-arm64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ "openharmony" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/sunos-x64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ "sunos" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/win32-arm64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/win32-ia32": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", "cpu": [ "ia32" ], "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { "node": ">=18" } }, "node_modules/@esbuild/win32-x64": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { "node": ">=18" } }, "node_modules/@iconify-json/simple-icons": { "version": "1.2.76", "resolved": "https://registry.npmjs.org/@iconify-json/simple-icons/-/simple-icons-1.2.76.tgz", "integrity": "sha512-lLRlA8yaf+1L5VCPRvR9lynoSklsddKHEylchmZJKdj/q2xVQ1ZAEJ8SCQlv9cbgtMefnlyM98U+8Si2aoFZPA==", "license": "CC0-1.0", "dependencies": { "@iconify/types": "*" } }, "node_modules/@iconify/types": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", "license": "MIT" }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz", "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==", "cpu": [ "arm" ], "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-android-arm64": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz", "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-darwin-arm64": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz", "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-darwin-x64": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz", "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-freebsd-arm64": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz", "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ "freebsd" ] }, "node_modules/@rollup/rollup-freebsd-x64": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz", "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ "freebsd" ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz", "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==", "cpu": [ "arm" ], "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz", "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==", "cpu": [ "arm" ], "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz", "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz", "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz", "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==", "cpu": [ "loong64" ], "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz", "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==", "cpu": [ "loong64" ], "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz", "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==", "cpu": [ "ppc64" ], "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz", "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==", "cpu": [ "ppc64" ], "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz", "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==", "cpu": [ "riscv64" ], "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz", "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==", "cpu": [ "riscv64" ], "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz", "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==", "cpu": [ "s390x" ], "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.1.tgz", "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-musl": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz", "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-openbsd-x64": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz", "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ "openbsd" ] }, "node_modules/@rollup/rollup-openharmony-arm64": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz", "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ "openharmony" ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz", "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==", "cpu": [ "arm64" ], "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz", "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==", "cpu": [ "ia32" ], "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz", "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz", "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==", "cpu": [ "x64" ], "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@shikijs/core": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-2.5.0.tgz", "integrity": "sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg==", "license": "MIT", "dependencies": { "@shikijs/engine-javascript": "2.5.0", "@shikijs/engine-oniguruma": "2.5.0", "@shikijs/types": "2.5.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.4" } }, "node_modules/@shikijs/engine-javascript": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-2.5.0.tgz", "integrity": "sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w==", "license": "MIT", "dependencies": { "@shikijs/types": "2.5.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^3.1.0" } }, "node_modules/@shikijs/engine-oniguruma": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-2.5.0.tgz", "integrity": "sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw==", "license": "MIT", "dependencies": { "@shikijs/types": "2.5.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "node_modules/@shikijs/langs": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-2.5.0.tgz", "integrity": "sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w==", "license": "MIT", "dependencies": { "@shikijs/types": "2.5.0" } }, "node_modules/@shikijs/themes": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-2.5.0.tgz", "integrity": "sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw==", "license": "MIT", "dependencies": { "@shikijs/types": "2.5.0" } }, "node_modules/@shikijs/transformers": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-2.5.0.tgz", "integrity": "sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg==", "license": "MIT", "dependencies": { "@shikijs/core": "2.5.0", "@shikijs/types": "2.5.0" } }, "node_modules/@shikijs/types": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-2.5.0.tgz", "integrity": "sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw==", "license": "MIT", "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "node_modules/@shikijs/vscode-textmate": { "version": "10.0.2", "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", "license": "MIT" }, "node_modules/@splidejs/splide": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/@splidejs/splide/-/splide-4.1.4.tgz", "integrity": "sha512-5I30evTJcAJQXt6vJ26g2xEkG+l1nXcpEw4xpKh0/FWQ8ozmAeTbtniVtVmz2sH1Es3vgfC4SS8B2X4o5JMptA==", "license": "MIT" }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "license": "MIT" }, "node_modules/@types/hast": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", "license": "MIT", "dependencies": { "@types/unist": "*" } }, "node_modules/@types/linkify-it": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", "license": "MIT" }, "node_modules/@types/markdown-it": { "version": "14.1.2", "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", "license": "MIT", "dependencies": { "@types/linkify-it": "^5", "@types/mdurl": "^2" } }, "node_modules/@types/mdast": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", "license": "MIT", "dependencies": { "@types/unist": "*" } }, "node_modules/@types/mdurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", "license": "MIT" }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "license": "MIT" }, "node_modules/@types/web-bluetooth": { "version": "0.0.21", "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", "license": "MIT" }, "node_modules/@ungap/structured-clone": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", "license": "ISC" }, "node_modules/@vitejs/plugin-vue": { "version": "5.2.4", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", "license": "MIT", "engines": { "node": "^18.0.0 || >=20.0.0" }, "peerDependencies": { "vite": "^5.0.0 || ^6.0.0", "vue": "^3.2.25" } }, "node_modules/@vue/compiler-core": { "version": "3.5.32", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.32.tgz", "integrity": "sha512-4x74Tbtqnda8s/NSD6e1Dr5p1c8HdMU5RWSjMSUzb8RTcUQqevDCxVAitcLBKT+ie3o0Dl9crc/S/opJM7qBGQ==", "license": "MIT", "dependencies": { "@babel/parser": "^7.29.2", "@vue/shared": "3.5.32", "entities": "^7.0.1", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-dom": { "version": "3.5.32", "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.32.tgz", "integrity": "sha512-ybHAu70NtiEI1fvAUz3oXZqkUYEe5J98GjMDpTGl5iHb0T15wQYLR4wE3h9xfuTNA+Cm2f4czfe8B4s+CCH57Q==", "license": "MIT", "dependencies": { "@vue/compiler-core": "3.5.32", "@vue/shared": "3.5.32" } }, "node_modules/@vue/compiler-sfc": { "version": "3.5.32", "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.32.tgz", "integrity": "sha512-8UYUYo71cP/0YHMO814TRZlPuUUw3oifHuMR7Wp9SNoRSrxRQnhMLNlCeaODNn6kNTJsjFoQ/kqIj4qGvya4Xg==", "license": "MIT", "dependencies": { "@babel/parser": "^7.29.2", "@vue/compiler-core": "3.5.32", "@vue/compiler-dom": "3.5.32", "@vue/compiler-ssr": "3.5.32", "@vue/shared": "3.5.32", "estree-walker": "^2.0.2", "magic-string": "^0.30.21", "postcss": "^8.5.8", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-ssr": { "version": "3.5.32", "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.32.tgz", "integrity": "sha512-Gp4gTs22T3DgRotZ8aA/6m2jMR+GMztvBXUBEUOYOcST+giyGWJ4WvFd7QLHBkzTxkfOt8IELKNdpzITLbA2rw==", "license": "MIT", "dependencies": { "@vue/compiler-dom": "3.5.32", "@vue/shared": "3.5.32" } }, "node_modules/@vue/devtools-api": { "version": "7.7.9", "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.9.tgz", "integrity": "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==", "license": "MIT", "dependencies": { "@vue/devtools-kit": "^7.7.9" } }, "node_modules/@vue/devtools-kit": { "version": "7.7.9", "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz", "integrity": "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==", "license": "MIT", "dependencies": { "@vue/devtools-shared": "^7.7.9", "birpc": "^2.3.0", "hookable": "^5.5.3", "mitt": "^3.0.1", "perfect-debounce": "^1.0.0", "speakingurl": "^14.0.1", "superjson": "^2.2.2" } }, "node_modules/@vue/devtools-shared": { "version": "7.7.9", "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz", "integrity": "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==", "license": "MIT", "dependencies": { "rfdc": "^1.4.1" } }, "node_modules/@vue/reactivity": { "version": "3.5.32", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.32.tgz", "integrity": "sha512-/ORasxSGvZ6MN5gc+uE364SxFdJ0+WqVG0CENXaGW58TOCdrAW76WWaplDtECeS1qphvtBZtR+3/o1g1zL4xPQ==", "license": "MIT", "dependencies": { "@vue/shared": "3.5.32" } }, "node_modules/@vue/runtime-core": { "version": "3.5.32", "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.32.tgz", "integrity": "sha512-pDrXCejn4UpFDFmMd27AcJEbHaLemaE5o4pbb7sLk79SRIhc6/t34BQA7SGNgYtbMnvbF/HHOftYBgFJtUoJUQ==", "license": "MIT", "dependencies": { "@vue/reactivity": "3.5.32", "@vue/shared": "3.5.32" } }, "node_modules/@vue/runtime-dom": { "version": "3.5.32", "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.32.tgz", "integrity": "sha512-1CDVv7tv/IV13V8Nip1k/aaObVbWqRlVCVezTwx3K07p7Vxossp5JU1dcPNhJk3w347gonIUT9jQOGutyJrSVQ==", "license": "MIT", "dependencies": { "@vue/reactivity": "3.5.32", "@vue/runtime-core": "3.5.32", "@vue/shared": "3.5.32", "csstype": "^3.2.3" } }, "node_modules/@vue/server-renderer": { "version": "3.5.32", "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.32.tgz", "integrity": "sha512-IOjm2+JQwRFS7W28HNuJeXQle9KdZbODFY7hFGVtnnghF51ta20EWAZJHX+zLGtsHhaU6uC9BGPV52KVpYryMQ==", "license": "MIT", "dependencies": { "@vue/compiler-ssr": "3.5.32", "@vue/shared": "3.5.32" }, "peerDependencies": { "vue": "3.5.32" } }, "node_modules/@vue/shared": { "version": "3.5.32", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.32.tgz", "integrity": "sha512-ksNyrmRQzWJJ8n3cRDuSF7zNNontuJg1YHnmWRJd2AMu8Ij2bqwiiri2lH5rHtYPZjj4STkNcgcmiQqlOjiYGg==", "license": "MIT" }, "node_modules/@vueuse/core": { "version": "12.8.2", "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-12.8.2.tgz", "integrity": "sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==", "license": "MIT", "dependencies": { "@types/web-bluetooth": "^0.0.21", "@vueuse/metadata": "12.8.2", "@vueuse/shared": "12.8.2", "vue": "^3.5.13" }, "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/@vueuse/integrations": { "version": "12.8.2", "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-12.8.2.tgz", "integrity": "sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g==", "license": "MIT", "dependencies": { "@vueuse/core": "12.8.2", "@vueuse/shared": "12.8.2", "vue": "^3.5.13" }, "funding": { "url": "https://github.com/sponsors/antfu" }, "peerDependencies": { "async-validator": "^4", "axios": "^1", "change-case": "^5", "drauu": "^0.4", "focus-trap": "^7", "fuse.js": "^7", "idb-keyval": "^6", "jwt-decode": "^4", "nprogress": "^0.2", "qrcode": "^1.5", "sortablejs": "^1", "universal-cookie": "^7" }, "peerDependenciesMeta": { "async-validator": { "optional": true }, "axios": { "optional": true }, "change-case": { "optional": true }, "drauu": { "optional": true }, "focus-trap": { "optional": true }, "fuse.js": { "optional": true }, "idb-keyval": { "optional": true }, "jwt-decode": { "optional": true }, "nprogress": { "optional": true }, "qrcode": { "optional": true }, "sortablejs": { "optional": true }, "universal-cookie": { "optional": true } } }, "node_modules/@vueuse/metadata": { "version": "12.8.2", "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-12.8.2.tgz", "integrity": "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/@vueuse/shared": { "version": "12.8.2", "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-12.8.2.tgz", "integrity": "sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==", "license": "MIT", "dependencies": { "vue": "^3.5.13" }, "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", "dev": true, "license": "BSD-2-Clause" }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "license": "MIT", "dependencies": { "debug": "4" }, "engines": { "node": ">= 6.0.0" } }, "node_modules/algoliasearch": { "version": "5.50.1", "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.50.1.tgz", "integrity": "sha512-/bwdue1/8LWELn/DBalGRfuLsXBLXULJo/yOeavJtDu8rBwxIzC6/Rz9Jg19S21VkJvRuZO1k8CZXBMS73mYbA==", "license": "MIT", "dependencies": { "@algolia/abtesting": "1.16.1", "@algolia/client-abtesting": "5.50.1", "@algolia/client-analytics": "5.50.1", "@algolia/client-common": "5.50.1", "@algolia/client-insights": "5.50.1", "@algolia/client-personalization": "5.50.1", "@algolia/client-query-suggestions": "5.50.1", "@algolia/client-search": "5.50.1", "@algolia/ingestion": "1.50.1", "@algolia/monitoring": "1.50.1", "@algolia/recommend": "5.50.1", "@algolia/requester-browser-xhr": "5.50.1", "@algolia/requester-fetch": "5.50.1", "@algolia/requester-node-http": "5.50.1" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, "node_modules/axios": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/axios/-/axios-1.16.1.tgz", "integrity": "sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==", "license": "MIT", "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.5", "https-proxy-agent": "^5.0.1", "proxy-from-env": "^2.1.0" } }, "node_modules/birpc": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/call-bound": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/ccount": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, "node_modules/chalk": { "version": "5.6.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/character-entities-html4": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, "node_modules/character-entities-legacy": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, "node_modules/ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/sibiraj-s" } ], "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, "engines": { "node": ">=7.0.0" } }, "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, "engines": { "node": ">= 0.8" } }, "node_modules/comma-separated-tokens": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, "node_modules/copy-anything": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz", "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==", "license": "MIT", "dependencies": { "is-what": "^5.2.0" }, "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/mesqueeb" } }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" }, "engines": { "node": ">= 8" } }, "node_modules/csstype": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "license": "MIT" }, "node_modules/dayjs": { "version": "1.11.20", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.20.tgz", "integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==", "dev": true, "license": "MIT" }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" }, "engines": { "node": ">=6.0" }, "peerDependenciesMeta": { "supports-color": { "optional": true } } }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "license": "MIT", "engines": { "node": ">=0.4.0" } }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/devlop": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", "license": "MIT", "dependencies": { "dequal": "^2.0.0" }, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/emoji-regex-xs": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz", "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==", "license": "MIT" }, "node_modules/entities": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", "license": "BSD-2-Clause", "engines": { "node": ">=0.12" }, "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/es-errors": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/es-object-atoms": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-set-tostringtag": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/esbuild": { "version": "0.25.12", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", "hasInstallScript": true, "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, "engines": { "node": ">=18" }, "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" } }, "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "license": "MIT" }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/find-yarn-workspace-root": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "micromatch": "^4.0.2" } }, "node_modules/focus-trap": { "version": "7.8.0", "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.8.0.tgz", "integrity": "sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA==", "license": "MIT", "dependencies": { "tabbable": "^6.4.0" } }, "node_modules/follow-redirects": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", "funding": [ { "type": "individual", "url": "https://github.com/sponsors/RubenVerborgh" } ], "license": "MIT", "engines": { "node": ">=4.0" }, "peerDependenciesMeta": { "debug": { "optional": true } } }, "node_modules/form-data": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { "node": ">= 6" } }, "node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" }, "engines": { "node": ">=12" } }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "hasInstallScript": true, "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true, "license": "ISC" }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/has-property-descriptors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-tostringtag": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/hast-util-to-html": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, "node_modules/hast-util-whitespace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, "node_modules/hookable": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", "license": "MIT" }, "node_modules/html-void-elements": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "license": "MIT", "dependencies": { "agent-base": "6", "debug": "4" }, "engines": { "node": ">= 6" } }, "node_modules/is-docker": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "dev": true, "license": "MIT", "bin": { "is-docker": "cli.js" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" } }, "node_modules/is-what": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz", "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", "license": "MIT", "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/mesqueeb" } }, "node_modules/is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "dev": true, "license": "MIT", "dependencies": { "is-docker": "^2.0.0" }, "engines": { "node": ">=8" } }, "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true, "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, "license": "ISC" }, "node_modules/json-stable-stringify": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz", "integrity": "sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==", "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "isarray": "^2.0.5", "jsonify": "^0.0.1", "object-keys": "^1.1.1" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/jsonfile": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "node_modules/jsonify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", "dev": true, "license": "Public Domain", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/klaw-sync": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.1.11" } }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/mark.js": { "version": "8.11.1", "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==", "license": "MIT" }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/mdast-util-to-hast": { "version": "13.2.1", "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, "node_modules/micromark-util-character": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", "funding": [ { "type": "GitHub Sponsors", "url": "https://github.com/sponsors/unifiedjs" }, { "type": "OpenCollective", "url": "https://opencollective.com/unified" } ], "license": "MIT", "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "node_modules/micromark-util-encode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", "funding": [ { "type": "GitHub Sponsors", "url": "https://github.com/sponsors/unifiedjs" }, { "type": "OpenCollective", "url": "https://opencollective.com/unified" } ], "license": "MIT" }, "node_modules/micromark-util-sanitize-uri": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", "funding": [ { "type": "GitHub Sponsors", "url": "https://github.com/sponsors/unifiedjs" }, { "type": "OpenCollective", "url": "https://opencollective.com/unified" } ], "license": "MIT", "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "node_modules/micromark-util-symbol": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", "funding": [ { "type": "GitHub Sponsors", "url": "https://github.com/sponsors/unifiedjs" }, { "type": "OpenCollective", "url": "https://opencollective.com/unified" } ], "license": "MIT" }, "node_modules/micromark-util-types": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", "funding": [ { "type": "GitHub Sponsors", "url": "https://github.com/sponsors/unifiedjs" }, { "type": "OpenCollective", "url": "https://opencollective.com/unified" } ], "license": "MIT" }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { "node": ">=8.6" } }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" } }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/minisearch": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.2.0.tgz", "integrity": "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==", "license": "MIT" }, "node_modules/mitt": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", "license": "MIT" }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/ai" } ], "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, "engines": { "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/oniguruma-to-es": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-3.1.1.tgz", "integrity": "sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ==", "license": "MIT", "dependencies": { "emoji-regex-xs": "^1.0.0", "regex": "^6.0.1", "regex-recursion": "^6.0.2" } }, "node_modules/open": { "version": "7.4.2", "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", "dev": true, "license": "MIT", "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/patch-package": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.1.tgz", "integrity": "sha512-VsKRIA8f5uqHQ7NGhwIna6Bx6D9s/1iXlA1hthBVBEbkq+t4kXD0HHt+rJhf/Z+Ci0F/HCB2hvn0qLdLG+Qxlw==", "dev": true, "license": "MIT", "dependencies": { "@yarnpkg/lockfile": "^1.1.0", "chalk": "^4.1.2", "ci-info": "^3.7.0", "cross-spawn": "^7.0.3", "find-yarn-workspace-root": "^2.0.0", "fs-extra": "^10.0.0", "json-stable-stringify": "^1.0.2", "klaw-sync": "^6.0.0", "minimist": "^1.2.6", "open": "^7.4.2", "semver": "^7.5.3", "slash": "^2.0.0", "tmp": "^0.2.4", "yaml": "^2.2.2" }, "bin": { "patch-package": "index.js" }, "engines": { "node": ">=14", "npm": ">5" } }, "node_modules/patch-package/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/perfect-debounce": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", "license": "MIT" }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { "node": ">=8.6" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/postcss": { "version": "8.5.12", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.12.tgz", "integrity": "sha512-W62t/Se6rA0Az3DfCL0AqJwXuKwBeYg6nOaIgzP+xZ7N5BFCI7DYi1qs6ygUYT6rvfi6t9k65UMLJC+PHZpDAA==", "funding": [ { "type": "opencollective", "url": "https://opencollective.com/postcss/" }, { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" }, { "type": "github", "url": "https://github.com/sponsors/ai" } ], "license": "MIT", "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" } }, "node_modules/preact": { "version": "10.29.1", "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.1.tgz", "integrity": "sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==", "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" } }, "node_modules/property-information": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, "node_modules/proxy-from-env": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", "license": "MIT", "engines": { "node": ">=10" } }, "node_modules/regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", "license": "MIT", "dependencies": { "regex-utilities": "^2.3.0" } }, "node_modules/regex-recursion": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", "license": "MIT", "dependencies": { "regex-utilities": "^2.3.0" } }, "node_modules/regex-utilities": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", "license": "MIT" }, "node_modules/rfdc": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "license": "MIT" }, "node_modules/rollup": { "version": "4.60.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz", "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==", "license": "MIT", "dependencies": { "@types/estree": "1.0.8" }, "bin": { "rollup": "dist/bin/rollup" }, "engines": { "node": ">=18.0.0", "npm": ">=8.0.0" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.60.1", "@rollup/rollup-android-arm64": "4.60.1", "@rollup/rollup-darwin-arm64": "4.60.1", "@rollup/rollup-darwin-x64": "4.60.1", "@rollup/rollup-freebsd-arm64": "4.60.1", "@rollup/rollup-freebsd-x64": "4.60.1", "@rollup/rollup-linux-arm-gnueabihf": "4.60.1", "@rollup/rollup-linux-arm-musleabihf": "4.60.1", "@rollup/rollup-linux-arm64-gnu": "4.60.1", "@rollup/rollup-linux-arm64-musl": "4.60.1", "@rollup/rollup-linux-loong64-gnu": "4.60.1", "@rollup/rollup-linux-loong64-musl": "4.60.1", "@rollup/rollup-linux-ppc64-gnu": "4.60.1", "@rollup/rollup-linux-ppc64-musl": "4.60.1", "@rollup/rollup-linux-riscv64-gnu": "4.60.1", "@rollup/rollup-linux-riscv64-musl": "4.60.1", "@rollup/rollup-linux-s390x-gnu": "4.60.1", "@rollup/rollup-linux-x64-gnu": "4.60.1", "@rollup/rollup-linux-x64-musl": "4.60.1", "@rollup/rollup-openbsd-x64": "4.60.1", "@rollup/rollup-openharmony-arm64": "4.60.1", "@rollup/rollup-win32-arm64-msvc": "4.60.1", "@rollup/rollup-win32-ia32-msvc": "4.60.1", "@rollup/rollup-win32-x64-gnu": "4.60.1", "@rollup/rollup-win32-x64-msvc": "4.60.1", "fsevents": "~2.3.2" } }, "node_modules/search-insights": { "version": "2.17.3", "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz", "integrity": "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==", "license": "MIT", "peer": true }, "node_modules/semver": { "version": "7.7.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" }, "engines": { "node": ">=10" } }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/shiki": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/shiki/-/shiki-2.5.0.tgz", "integrity": "sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ==", "license": "MIT", "dependencies": { "@shikijs/core": "2.5.0", "@shikijs/engine-javascript": "2.5.0", "@shikijs/engine-oniguruma": "2.5.0", "@shikijs/langs": "2.5.0", "@shikijs/themes": "2.5.0", "@shikijs/types": "2.5.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "node_modules/slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/space-separated-tokens": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, "node_modules/speakingurl": { "version": "14.0.1", "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/stringify-entities": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", "license": "MIT", "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" }, "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, "node_modules/superjson": { "version": "2.2.6", "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz", "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", "license": "MIT", "dependencies": { "copy-anything": "^4" }, "engines": { "node": ">=16" } }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/tabbable": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", "license": "MIT" }, "node_modules/tmp": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", "dev": true, "license": "MIT", "engines": { "node": ">=14.14" } }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, "engines": { "node": ">=8.0" } }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, "node_modules/unist-util-is": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, "node_modules/unist-util-position": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, "node_modules/unist-util-stringify-position": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, "node_modules/unist-util-visit": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, "node_modules/unist-util-visit-parents": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", "engines": { "node": ">= 10.0.0" } }, "node_modules/vfile": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, "node_modules/vfile-message": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, "node_modules/vite": { "version": "5.4.21", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", "license": "MIT", "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "bin": { "vite": "bin/vite.js" }, "engines": { "node": "^18.0.0 || >=20.0.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "peerDependenciesMeta": { "@types/node": { "optional": true }, "less": { "optional": true }, "lightningcss": { "optional": true }, "sass": { "optional": true }, "sass-embedded": { "optional": true }, "stylus": { "optional": true }, "sugarss": { "optional": true }, "terser": { "optional": true } } }, "node_modules/vitepress": { "version": "1.6.4", "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.6.4.tgz", "integrity": "sha512-+2ym1/+0VVrbhNyRoFFesVvBvHAVMZMK0rw60E3X/5349M1GuVdKeazuksqopEdvkKwKGs21Q729jX81/bkBJg==", "license": "MIT", "dependencies": { "@docsearch/css": "3.8.2", "@docsearch/js": "3.8.2", "@iconify-json/simple-icons": "^1.2.21", "@shikijs/core": "^2.1.0", "@shikijs/transformers": "^2.1.0", "@shikijs/types": "^2.1.0", "@types/markdown-it": "^14.1.2", "@vitejs/plugin-vue": "^5.2.1", "@vue/devtools-api": "^7.7.0", "@vue/shared": "^3.5.13", "@vueuse/core": "^12.4.0", "@vueuse/integrations": "^12.4.0", "focus-trap": "^7.6.4", "mark.js": "8.11.1", "minisearch": "^7.1.1", "shiki": "^2.1.0", "vite": "^5.4.14", "vue": "^3.5.13" }, "bin": { "vitepress": "bin/vitepress.js" }, "peerDependencies": { "markdown-it-mathjax3": "^4", "postcss": "^8" }, "peerDependenciesMeta": { "markdown-it-mathjax3": { "optional": true }, "postcss": { "optional": true } } }, "node_modules/vue": { "version": "3.5.32", "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.32.tgz", "integrity": "sha512-vM4z4Q9tTafVfMAK7IVzmxg34rSzTFMyIe0UUEijUCkn9+23lj0WRfA83dg7eQZIUlgOSGrkViIaCfqSAUXsMw==", "license": "MIT", "dependencies": { "@vue/compiler-dom": "3.5.32", "@vue/compiler-sfc": "3.5.32", "@vue/runtime-dom": "3.5.32", "@vue/server-renderer": "3.5.32", "@vue/shared": "3.5.32" }, "peerDependencies": { "typescript": "*" }, "peerDependenciesMeta": { "typescript": { "optional": true } } }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" }, "engines": { "node": ">= 8" } }, "node_modules/yaml": { "version": "2.8.3", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", "dev": true, "license": "ISC", "bin": { "yaml": "bin.mjs" }, "engines": { "node": ">= 14.6" }, "funding": { "url": "https://github.com/sponsors/eemeli" } }, "node_modules/zwitch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } } } } axios-axios-2d06f96/docs/package.json000066400000000000000000000014021521272452000175330ustar00rootroot00000000000000{ "name": "axios", "version": "1.0.0", "description": "Documentation for the Axios HTTP client", "license": "MIT", "type": "module", "private": true, "scripts": { "docs:dev": "vitepress dev", "docs:build": "vitepress build", "docs:preview": "vitepress preview", "docs:update:sponsors": "node ./scripts/process-sponsors.js", "prod:build": "npm run docs:update:sponsors && npm run docs:build", "postinstall": "patch-package --exclude nothing" }, "dependencies": { "@splidejs/splide": "^4.1.4", "axios": "^1.15.2", "vitepress": "^1.6.4" }, "devDependencies": { "chalk": "^5.3.0", "dayjs": "^1.11.13", "patch-package": "^8.0.1", "vue": "^3.5.32" }, "overrides": { "esbuild": "^0.25.12" } } axios-axios-2d06f96/docs/pages/000077500000000000000000000000001521272452000163475ustar00rootroot00000000000000axios-axios-2d06f96/docs/pages/advanced/000077500000000000000000000000001521272452000201145ustar00rootroot00000000000000axios-axios-2d06f96/docs/pages/advanced/adapters.md000066400000000000000000000060431521272452000222440ustar00rootroot00000000000000# Adapters Adapters allow you to customize the way axios handles the request data. By default, axios uses an ordered priority list of `['xhr', 'http', 'fetch']` and selects the first adapter that is supported by the current environment. In practice this means `xhr` is used in browsers, `http` in Node.js, and `fetch` in environments where neither is available (such as Cloudflare Workers or Deno). Writing your own adapter lets you fully control how axios makes a request and processes the response — useful for testing, custom transports, or non-standard environments. ## Built-in adapters You can select a built-in adapter by name using the `adapter` config option: ```js // Use the fetch adapter const instance = axios.create({ adapter: "fetch" }); // Use the XHR adapter (browser default) const instance = axios.create({ adapter: "xhr" }); // Use the HTTP adapter (Node.js default) const instance = axios.create({ adapter: "http" }); ``` You can also pass an array of adapter names. axios will use the first one supported by the current environment: ```js const instance = axios.create({ adapter: ["fetch", "xhr", "http"] }); ``` For more details on the `fetch` adapter, see the [Fetch adapter](/pages/advanced/fetch-adapter) page. ## Creating a custom adapter To create a custom adapter, write a function that accepts a `config` object and returns a Promise that resolves to a valid axios response object. ```js import axios from "axios"; import { settle } from "axios/unsafe/core/settle.js"; function myAdapter(config) { /** * At this point: * - config has been merged with defaults * - request transformers have run * - request interceptors have run * * The adapter is now responsible for making the request * and returning a valid response object. */ return new Promise((resolve, reject) => { // Perform your custom request logic here. // This example uses the native fetch API as a starting point. fetch(config.url, { method: config.method?.toUpperCase() ?? "GET", headers: config.headers?.toJSON() ?? {}, body: config.data, signal: config.signal, }) .then(async (fetchResponse) => { const responseData = await fetchResponse.text(); const response = { data: responseData, status: fetchResponse.status, statusText: fetchResponse.statusText, headers: Object.fromEntries(fetchResponse.headers.entries()), config, request: null, }; // settle resolves or rejects the promise based on the HTTP status settle(resolve, reject, response); /** * After this point: * - response transformers will run * - response interceptors will run */ }) .catch(reject); }); } const instance = axios.create({ adapter: myAdapter }); ``` ::: tip The `settle` helper resolves the promise for 2xx status codes and rejects it for everything else, matching axios's default behaviour. If you want custom status validation, use the `validateStatus` config option instead. ::: axios-axios-2d06f96/docs/pages/advanced/api-reference.md000066400000000000000000000246151521272452000231530ustar00rootroot00000000000000# API reference Below is a list of all the available functions and classes in the axios package. These functions may be used and imported in your project. All of these functions and classes are protected by our renewed promise to follow semantic versioning. This means that you can rely on these functions and classes to remain stable and unchanged in future releases unless a major version change is made. ## Instance The `axios` instance is the main object that you will use to make HTTP requests. It is a factory function that creates a new instance of the `Axios` class. The `axios` instance has a number of methods that you can use to make HTTP requests. These methods are documented in the [Request aliases section](/pages/advanced/request-method-aliases) of the documentation. ## Classes ### `Axios` The `Axios` class is the main class that you will use to make HTTP requests. It is a factory function that creates a new instance of the `Axios` class. The `Axios` class has a number of methods that you can use to make HTTP requests. These methods are documented in the [Request aliases section](/pages/advanced/request-method-aliases) of the documentation. #### `constructor` Creates a new instance of the `Axios` class. The constructor takes an optional configuration object as an argument. ```ts constructor(instanceConfig?: AxiosRequestConfig); ``` #### `request` Handles request invocation and response resolution. This is the main method that you will use to make HTTP requests. It takes a configuration object as an argument and returns a promise that resolves to the response object. ```ts request(configOrUrl: string | AxiosRequestConfig, config: AxiosRequestConfig): Promise>; ``` ### `CancelToken` The `CancelToken` class was based on the `tc39/proposal-cancelable-promises` proposal. It was used to create a token that could be used to cancel an HTTP request. The `CancelToken` class is now deprecated in favour of the `AbortController` API. As of version 0.22.0, the `CancelToken` class is deprecated and will be removed in a future release. It is recommended that you use the `AbortController` API instead. The class is exported mainly for backwards compatibility and will be removed in a future release. We also strongly discourage its use in new projects, we therefore are not documenting the API as use is discouraged. ## Functions ### `AxiosError` The `AxiosError` class is an error class that is thrown when an HTTP request fails. It extends the `Error` class and adds additional properties to the error object. #### `constructor` Creates a new instance of the `AxiosError` class. The constructor takes an optional message, code, config, request, and response as arguments. ```ts constructor(message?: string, code?: string, config?: InternalAxiosRequestConfig, request?: any, response?: AxiosResponse); ``` #### `properties` The `AxiosError` class provides the following properties: ```ts // Config instance. config?: InternalAxiosRequestConfig; // Error code. code?: string; // Request instance. request?: any; // Response instance. response?: AxiosResponse; // Boolean indicating if the error is an `AxiosError`. isAxiosError: boolean; // Error status code. status?: number; // Helper method to convert the error to a JSON object. toJSON: () => object; // Error cause. cause?: Error; ``` ### `AxiosHeaders` The `AxiosHeaders` class is a utility class that is used to manage HTTP headers. It provides methods for manipulating headers, such as adding, removing, and getting headers. Only the main methods are documented here. For a full list of methods, please refer to the type declaration file. #### `constructor` Creates a new instance of the `AxiosHeaders` class. The constructor takes an optional headers object as an argument. ```ts constructor(headers?: RawAxiosHeaders | AxiosHeaders | string); ``` #### `set` Adds a header to the headers object. Empty or whitespace-only header names are ignored. ```ts set(headerName?: string, value?: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders; set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean): AxiosHeaders; ``` #### `get` Gets a header from the headers object. ```ts get(headerName: string, parser: RegExp): RegExpExecArray | null; get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue; ``` #### `has` Checks if a header exists in the headers object. ```ts has(header: string, matcher?: AxiosHeaderMatcher): boolean; ``` #### `delete` Removes a header from the headers object. ```ts delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean; ``` #### `clear` Removes all headers from the headers object. ```ts clear(matcher?: AxiosHeaderMatcher): boolean; ``` #### `normalize` Normalizes the headers object. ```ts normalize(format: boolean): AxiosHeaders; ``` #### `concat` Concatenates headers objects. ```ts concat(...targets: Array): AxiosHeaders; ``` #### `toJSON` Converts the headers object to a JSON object. ```ts toJSON(asStrings: true): Record; toJSON(asStrings?: false): Record; ``` ### `CanceledError` The `CanceledError` class is an error class that is thrown when an HTTP request is canceled. It extends the `AxiosError` class. ### `Cancel` The `Cancel` class is an alias for the `CanceledError` class. It is exported for backwards compatibility and will be removed in a future release. ### `isCancel` A function that checks if an error is a `CanceledError`. Useful for distinguishing intentional cancellations from unexpected errors. ```ts isCancel(value: any): value is CanceledError; ``` ```js import axios from "axios"; const controller = new AbortController(); axios.get("/api/data", { signal: controller.signal }).catch((error) => { if (axios.isCancel(error)) { console.log("Request was cancelled:", error.message); } else { console.error("Unexpected error:", error); } }); controller.abort("User navigated away"); ``` ### `isAxiosError` A function that checks if an error is an `AxiosError`. Use this in `catch` blocks to safely access axios-specific error properties like `error.response` and `error.config`. ```ts isAxiosError(value: any): value is AxiosError; ``` ```js import axios from "axios"; try { await axios.get("/api/resource"); } catch (error) { if (axios.isAxiosError(error)) { // error.response, error.config, error.code are all available console.error("HTTP error", error.response?.status, error.message); } else { // A non-axios error (e.g. a programming mistake) throw error; } } ``` ### `all` The `all` function is a utility function that takes an array of promises and returns a single promise that resolves when all of the promises in the array have resolved. The `all` function is now deprecated in favour of the `Promise.all` method. It is recommended that you use the `Promise.all` method instead. As of version 0.22.0, the `all` function is deprecated and will be removed in a future release. It is recommended that you use the `Promise.all` method instead. ### `spread` The `spread` function is a utility function that can be used to spread an array of arguments into a function call. This is useful when you have an array of arguments that you want to pass to a function that takes multiple arguments. ```ts spread(callback: (...args: T[]) => R): (array: T[]) => R; ``` ### `toFormData` Converts a plain JavaScript object (or a nested one) to a `FormData` instance. Useful when you want to programmatically build multipart form data from an object. ```ts toFormData(sourceObj: object, formData?: FormData, options?: FormSerializerOptions): FormData; ``` ```js import { toFormData } from "axios"; const data = { name: "Jay", avatar: fileBlob }; const form = toFormData(data); // form is now a FormData instance ready to post await axios.post("/api/users", form); ``` ### `formToJSON` Converts a `FormData` instance back to a plain JavaScript object. Useful for reading form data in a structured format. ```ts formToJSON(form: FormData): object; ``` ```js import { formToJSON } from "axios"; const form = new FormData(); form.append("name", "Jay"); form.append("role", "admin"); const obj = formToJSON(form); console.log(obj); // { name: "Jay", role: "admin" } ``` ### `getAdapter` Resolves and returns an adapter function by name or by passing an array of candidate names. axios uses this internally to select the best available adapter for the current environment. ```ts getAdapter(adapters: string | string[]): AxiosAdapter; ``` ```js import { getAdapter } from "axios"; // Get the fetch adapter explicitly const fetchAdapter = getAdapter("fetch"); // Get the best available adapter from a priority list const adapter = getAdapter(["fetch", "xhr", "http"]); ``` ### `mergeConfig` Merges two axios config objects together, applying the same deep-merge strategy that axios uses internally when combining defaults with per-request options. Later values take precedence. ```ts mergeConfig(config1: AxiosRequestConfig, config2: AxiosRequestConfig): AxiosRequestConfig; ``` ```js import { mergeConfig } from "axios"; const base = { baseURL: "https://api.example.com", timeout: 5000 }; const override = { timeout: 10000, headers: { "X-Custom": "value" } }; const merged = mergeConfig(base, override); // { baseURL: "https://api.example.com", timeout: 10000, headers: { "X-Custom": "value" } } ``` ## Constants ### `HttpStatusCode` An object that contains a list of HTTP status codes as named constants. Use this to write readable conditionals instead of bare numbers. ```js import axios, { HttpStatusCode } from "axios"; try { const response = await axios.get("/api/resource"); } catch (error) { if (axios.isAxiosError(error)) { if (error.response?.status === HttpStatusCode.NotFound) { console.error("Resource not found"); } else if (error.response?.status === HttpStatusCode.Unauthorized) { console.error("Authentication required"); } } } ``` ## Miscellaneous ### `VERSION` The current version of the `axios` package. This is a string that represents the version number of the package. It is updated with each release of the package. axios-axios-2d06f96/docs/pages/advanced/authentication.md000066400000000000000000000105111521272452000234530ustar00rootroot00000000000000# Authentication Most APIs require some form of authentication. This page covers the most common patterns for attaching credentials to axios requests. ## Bearer tokens (JWT) The most common approach is to attach a JWT in the `Authorization` header. The cleanest way to do this is via a request interceptor on your axios instance, so the token is read fresh on every request: ```js import axios from "axios"; const api = axios.create({ baseURL: "https://api.example.com" }); api.interceptors.request.use((config) => { const token = localStorage.getItem("access_token"); if (token) { config.headers.set("Authorization", `Bearer ${token}`); } return config; }); ``` ## HTTP Basic auth For APIs that use HTTP Basic authentication, pass the `auth` option. axios will encode the credentials and set the `Authorization` header automatically: ```js const response = await axios.get("https://api.example.com/data", { auth: { username: "myUser", password: "myPassword", }, }); ``` If `auth` is not supplied, the Node.js HTTP and fetch adapters can also derive Basic auth credentials from the request URL, for example `https://myUser:myPassword@api.example.com/data`. Percent-encoded URL credentials are decoded before the `Authorization` header is generated. Prefer the explicit `auth` option for new code; it takes precedence over URL-embedded credentials. ::: tip For Bearer tokens and API keys, use a custom `Authorization` header rather than the `auth` option — `auth` is only for HTTP Basic. ::: ## API keys API keys are typically passed as a header or a query parameter, depending on what the API expects: ```js // As a header const api = axios.create({ baseURL: "https://api.example.com", headers: { "X-API-Key": "your-api-key-here" }, }); // As a query parameter const response = await axios.get("https://api.example.com/data", { params: { apiKey: "your-api-key-here" }, }); ``` ## Token refresh When access tokens expire, you need to silently refresh them and retry the failed request. A response interceptor is the right place to implement this: ```js import axios from "axios"; const api = axios.create({ baseURL: "https://api.example.com" }); // Track whether a refresh is already in progress to avoid parallel refresh calls let isRefreshing = false; let failedQueue = []; const processQueue = (error, token = null) => { failedQueue.forEach((prom) => { if (error) { prom.reject(error); } else { prom.resolve(token); } }); failedQueue = []; }; api.interceptors.response.use( (response) => response, async (error) => { const originalRequest = error.config; if (error.response?.status === 401 && !originalRequest._retry) { if (isRefreshing) { // Queue the request until the refresh completes return new Promise((resolve, reject) => { failedQueue.push({ resolve, reject }); }) .then((token) => { originalRequest.headers["Authorization"] = `Bearer ${token}`; return api(originalRequest); }) .catch((err) => Promise.reject(err)); } originalRequest._retry = true; isRefreshing = true; try { const { data } = await axios.post("/auth/refresh", { refreshToken: localStorage.getItem("refresh_token"), }); const newToken = data.access_token; localStorage.setItem("access_token", newToken); api.defaults.headers.common["Authorization"] = `Bearer ${newToken}`; processQueue(null, newToken); return api(originalRequest); } catch (refreshError) { processQueue(refreshError, null); // Redirect to login or emit an event localStorage.removeItem("access_token"); window.location.href = "/login"; return Promise.reject(refreshError); } finally { isRefreshing = false; } } return Promise.reject(error); } ); ``` ## Cookie-based authentication For session-based APIs that rely on cookies, set `withCredentials: true` to include cookies in cross-origin requests: ```js const api = axios.create({ baseURL: "https://api.example.com", withCredentials: true, // send cookies with every request }); ``` ::: warning `withCredentials: true` requires the server to respond with `Access-Control-Allow-Credentials: true` and a specific (non-wildcard) `Access-Control-Allow-Origin`. ::: axios-axios-2d06f96/docs/pages/advanced/cancellation.md000066400000000000000000000037711521272452000231020ustar00rootroot00000000000000# Cancellation Starting from v0.22.0 Axios supports AbortController to cancel requests in a clean way. This feature is available in the browser and in Node.js when using a version of Axios that supports AbortController. To cancel a request, you need to create an instance of `AbortController` and pass its `signal` to the request's `signal` option. ```js const controller = new AbortController(); axios .get("/foo/bar", { signal: controller.signal, }) .then(function (response) { //... }); // cancel the request controller.abort(); ``` ## CancelToken You can also use the `CancelToken` API to cancel requests. This API is deprecated and will be removed in the next major release. It is recommended to use `AbortController` instead. You can create a cancel token using the `CancelToken.source` factory as shown below: ```js const CancelToken = axios.CancelToken; const source = CancelToken.source(); axios .get("/user/12345", { cancelToken: source.token, }) .catch(function (thrown) { if (axios.isCancel(thrown)) { console.log("Request canceled", thrown.message); } else { // handle error } }); axios.post( "/user/12345", { name: "new name", }, { cancelToken: source.token, } ); // cancel the request (the message parameter is optional) source.cancel("Operation canceled by the user."); ``` You can also create a cancel token by passing an executor function to the `CancelToken` constructor: ```js const CancelToken = axios.CancelToken; let cancel; axios.get("/user/12345", { cancelToken: new CancelToken(function executor(c) { // An executor function receives a cancel function as a parameter cancel = c; }), }); // cancel the request cancel(); ``` You can cancel several requests with the same cancel token/abort controller. If a cancellation token is already cancelled at the moment of starting an Axios request, then the request is cancelled immediately, without any attempts to make a real request. axios-axios-2d06f96/docs/pages/advanced/config-defaults.md000066400000000000000000000041771521272452000235210ustar00rootroot00000000000000# Config defaults axios allows you to specify config defaults that will be applied to ever request. You can specify defaults for the `baseURL`, `headers`, `timeout`, and other properties. An example of using config defaults is shown below: ```js axios.defaults.baseURL = "https://jsonplaceholder.typicode.com/posts"; axios.defaults.headers.common["Authorization"] = AUTH_TOKEN; axios.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded"; ``` ::: warning Global headers are sent to every host If your application talks to more than one domain, setting `axios.defaults.headers.common["Authorization"]` will send the token to **all** of them, including third-party APIs you may not control. Use a [custom instance](#custom-instance-defaults) with a scoped `baseURL` for any client that carries credentials. ::: ## Custom instance defaults axios instances are declared with their own defaults when created. These defaults may be overridden setting the `defaults` property to the instance. An example of using custom instance defaults is shown below: ```js var instance = axios.create({ baseURL: "https://jsonplaceholder.typicode.com/posts", timeout: 1000, headers: { Authorization: "foobar" }, }); instance.defaults.headers.common["Authorization"] = AUTH_TOKEN; ``` ## Config order of precedence Config will be merged with an order of precedence. The order is as follows, first the library defaults are set, then default properties of the instance, and finally config argument for the request. An example of the order of precedence is shown below: First lets create an instance with the defaults provided by the library. At this point the timeout config value is `0` as is the default for the library. ```js const instance = axios.create(); ``` Now we will override the timeout default for the instance to `2500` milliseconds. Now all requests using this instance will wait 2.5 seconds before timing out. ```js instance.defaults.timeout = 2500; ``` Finally we will make a request with a timeout of `5000` milliseconds. This request will wait 5 seconds before timing out. ```js instance.get("/longRequest", { timeout: 5000, }); ``` axios-axios-2d06f96/docs/pages/advanced/create-an-instance.md000066400000000000000000000051251521272452000241020ustar00rootroot00000000000000# Creating an instance `axios.create()` lets you create a pre-configured axios instance. The instance shares the same request and response API as the default `axios` object, but uses the config you provide as its baseline for every request. This is the recommended way to use axios in any application larger than a single file. ```ts import axios from "axios"; const instance = axios.create({ baseURL: "https://api.example.com", timeout: 5000, headers: { "X-Custom-Header": "foobar" }, }); ``` The `create` method accepts the full [Request Config](/pages/advanced/request-config) object. You can then use the instance just like the default axios object: ```js const response = await instance.get("/users/1"); ``` ## Why use an instance? ### Per-service base URL In most apps you talk to more than one API. Creating a separate instance per service avoids repeating the base URL on every call: ```js const githubApi = axios.create({ baseURL: "https://api.github.com" }); const internalApi = axios.create({ baseURL: "https://api.internal.example.com" }); const { data: repos } = await githubApi.get("/users/axios/repos"); const { data: users } = await internalApi.get("/users"); ``` ### Shared authentication headers Attach an auth token to every request from one instance without touching others: ```js const authApi = axios.create({ baseURL: "https://api.example.com", headers: { Authorization: `Bearer ${getToken()}`, }, }); ``` ### Per-service timeouts and retries Different services have different reliability characteristics. Set a tight timeout for real-time services and a relaxed one for batch jobs: ```js const realtimeApi = axios.create({ baseURL: "https://realtime.example.com", timeout: 2000 }); const batchApi = axios.create({ baseURL: "https://batch.example.com", timeout: 60000 }); ``` ### Isolated interceptors Interceptors added to an instance only apply to that instance, keeping your concerns separate: ```js const loggingApi = axios.create({ baseURL: "https://api.example.com" }); loggingApi.interceptors.request.use((config) => { console.log(`→ ${config.method?.toUpperCase()} ${config.url}`); return config; }); ``` ## Overriding defaults per request Config passed at request time always overrides the instance defaults: ```js const api = axios.create({ timeout: 5000 }); // This specific request uses a 30-second timeout instead await api.get("/slow-endpoint", { timeout: 30000 }); ``` ::: tip Instance defaults can also be changed after creation by writing to `instance.defaults`: ```js instance.defaults.headers.common["Authorization"] = `Bearer ${newToken}`; ``` ::: axios-axios-2d06f96/docs/pages/advanced/error-handling.md000066400000000000000000000160361521272452000233570ustar00rootroot00000000000000# Error handling axios may throw many different types of errors. Some of these errors are caused by axios itself, while others are caused by the server or the client. The following table lists the general structure of the thrown error: | Property | Definition | | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | message | A quick summary of the error message and the status it failed with. | | name | This defines where the error originated from. For axios, it will always be an `AxiosError`. | | stack | Provides the stack trace of the error. | | config | An axios config object with specific instance configurations defined by the user from when the request was made. | | code | Represents an axios identified error. The table below lists out specific definitions for internal axios error. | | status | HTTP response status code. See [here](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) for common HTTP response status code meanings. | Below is a list of potential axios identified error | Code | Definition | | ------------------------- | --------------------------------------------------------------------------------------------- | | ERR_BAD_OPTION_VALUE | Invalid or unsupported value provided in axios configuration. | | ERR_BAD_OPTION | Invalid option provided in axios configuration. | | ECONNABORTED | Typically indicates that the request has been timed out (unless `transitional.clarifyTimeoutError` is set) or aborted by the browser or its plugin. | | ETIMEDOUT | Request timed out due to exceeding the default axios timelimit. `transitional.clarifyTimeoutError` must be set to `true`, otherwise a generic `ECONNABORTED` error will be thrown instead | | ERR_NETWORK | Network-related issue. In the browser, this error can also be caused by a [CORS](https://developer.mozilla.org/ru/docs/Web/HTTP/Guides/CORS) or [Mixed Content](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content) policy violation. The browser does not allow the JS code to clarify the real reason for the error caused by security issues, so please check the console. | | ERR_FR_TOO_MANY_REDIRECTS | Request is redirected too many times; exceeds max redirects specified in axios configuration. | | ERR_DEPRECATED | Deprecated feature or method used in axios. | | ERR_BAD_RESPONSE | Response cannot be parsed properly or is in an unexpected format. Usually related to a response with `5xx` status code. | | ERR_BAD_REQUEST | The request has an unexpected format or is missing required parameters. Usually related to a response with `4xx` status code. | | ERR_CANCELED | Feature or method is canceled explicitly by the user using an AbortSignal (or a CancelToken). | | ERR_NOT_SUPPORT | Feature or method not supported in the current axios environment. | | ERR_INVALID_URL | Invalid URL provided for axios request. | | ERR_FORM_DATA_DEPTH_EXCEEDED | An object exceeds the configured `maxDepth` while serializing `params` or form data. Default limit is 100 levels. See [`paramsSerializer`](/pages/advanced/request-config#paramsserializer) and [`formSerializer`](/pages/advanced/request-config#formserializer). | ## Handling errors The default behaviour of axios is to reject the promise if the request fails. However, you can also catch the error and handle it as you see fit. Below is an example of how to catch an error: ```js axios.get("/user/12345").catch(function (error) { if (error.response) { // The request was made and the server responded with a status code // that falls out of the range of 2xx console.log(error.response.data); console.log(error.response.status); console.log(error.response.headers); } else if (error.request) { // The request was made but no response was received // `error.request` is an instance of XMLHttpRequest in the browser and an instance of // http.ClientRequest in node.js console.log(error.request); } else { // Something happened in setting up the request that triggered an Error console.log("Error", error.message); } console.log(error.config); }); ``` Using the `validateStatus` config option, you can override the default condition (status >= 200 && status < 300) and define HTTP code(s) that should throw an error. ```js axios.get("/user/12345", { validateStatus: function (status) { return status < 500; // Resolve only if the status code is less than 500 }, }); ``` Using the `toJSON` method, you can get an object with more information about the error. ```js axios.get("/user/12345").catch(function (error) { console.log(error.toJSON()); }); ``` To avoid logging secrets from `error.config`, pass a `redact` array in the request config. Matching config keys are masked case-insensitively at any depth when `AxiosError#toJSON()` is called. ```js axios.get("/user/12345", { headers: { Authorization: "Bearer token" }, redact: ["authorization"] }).catch(function (error) { console.log(error.toJSON().config.headers.Authorization); // [REDACTED ****] }); ``` ## Handling timeouts When a request exceeds its configured `timeout`, axios rejects with `ECONNABORTED` by default. Set `transitional.clarifyTimeoutError: true` to receive `ETIMEDOUT` instead, which makes timeout errors easier to distinguish from other aborts. ```js async function fetchWithTimeout() { try { const response = await axios.get("https://example.com/data", { timeout: 5000, // 5 seconds transitional: { // set to true if you prefer ETIMEDOUT over ECONNABORTED clarifyTimeoutError: true, }, }); console.log("Response:", response.data); } catch (error) { if (axios.isAxiosError(error)) { if (error.code === "ECONNABORTED" || error.code === "ETIMEDOUT") { console.error("Request timed out. Please try again."); return; } console.error("Axios error:", error.message); return; } console.error("Unexpected error:", error); } } ``` ::: tip Always set a `timeout` in production Without one, a stalled request can hang indefinitely. See [`timeout`](/pages/advanced/request-config#timeout) and [`transitional.clarifyTimeoutError`](/pages/advanced/request-config#transitional) for the matching config options. ::: axios-axios-2d06f96/docs/pages/advanced/fetch-adapter.md000066400000000000000000000066721521272452000231600ustar00rootroot00000000000000# Fetch adapter The `fetch` adapter is a new adapter that we have introduced as of version 1.7.0. This provides a way to use axios with the `fetch` API thus giving you the best of both worlds. By default, `fetch` will be used if `xhr` and `http` adapters are not available in the build, or not supported by the environment. To use it by default, it must be selected explicitly by setting the `adapter` option to `fetch` when creating an instance of axios. ```js import axios from 'axios'; const instance = axios.create({ adapter: 'fetch', }); ``` The adapter supports the same functionality as the `xhr` adapter, including upload and download progress capturing. It also supports additional response types such as `stream` and `formdata` (if supported by the environment). When `auth` is omitted, the fetch adapter can read HTTP Basic auth credentials from the request URL, for example `https://user:pass@example.com`. Percent-encoded URL credentials are decoded before the `Authorization` header is generated, and `auth` takes precedence over URL-embedded credentials. ## Custom fetch Starting from `v1.12.0`, you can customise the fetch adapter to use a custom `fetch` function instead of the environment global. You can pass a custom `fetch` function, `Request`, and `Response` constructors via the `env` config option. This is useful when working with custom environments or app frameworks that provide their own `fetch` implementation. ::: info When using a custom `fetch` function, you may also need to supply matching `Request` and `Response` constructors. If you omit them, the global constructors will be used. If your custom `fetch` is incompatible with the globals, pass `null` to disable them. **Note:** Setting `Request` and `Response` to `null` will make it impossible for the fetch adapter to capture upload and download progress. ::: ### Basic example ```js import customFetchFunction from 'customFetchModule'; const instance = axios.create({ adapter: 'fetch', onDownloadProgress(e) { console.log('downloadProgress', e); }, env: { fetch: customFetchFunction, Request: null, // null -> disable the constructor Response: null, }, }); ``` ### Using with Tauri [Tauri](https://tauri.app/plugin/http-client/) provides a platform `fetch` function that bypasses browser CORS restrictions for requests made from the native layer. The example below shows a minimal setup for using axios inside a Tauri app with that custom fetch. ```js import { fetch } from '@tauri-apps/plugin-http'; import axios from 'axios'; const instance = axios.create({ adapter: 'fetch', onDownloadProgress(e) { console.log('downloadProgress', e); }, env: { fetch, }, }); const { data } = await instance.get('https://google.com'); ``` ### Using with SvelteKit [SvelteKit](https://svelte.dev/docs/kit/web-standards#Fetch-APIs) provides a custom `fetch` implementation for server-side `load` functions that handles cookie forwarding and relative URLs. Because its `fetch` is incompatible with the standard `URL` API, axios must be configured to use it explicitly, and the global `Request` and `Response` constructors must be disabled. ```js export async function load({ fetch }) { const { data: post } = await axios.get('https://jsonplaceholder.typicode.com/posts/1', { adapter: 'fetch', env: { fetch, Request: null, Response: null, }, }); return { post }; } ``` axios-axios-2d06f96/docs/pages/advanced/file-posting.md000066400000000000000000000056551521272452000230510ustar00rootroot00000000000000# File posting axios makes file uploads straightforward. Use `postForm` or `FormData` when you need `multipart/form-data` uploads. ## Single file (browser) Pass a `File` object directly as a field value — axios will detect it and use the correct content type automatically: ```js await axios.postForm("https://httpbin.org/post", { description: "My profile photo", file: document.querySelector("#fileInput").files[0], }); ``` ## Multiple files (browser) Pass a `FileList` to upload all selected files at once. They will all be sent under the same field name (`files[]`): ```js await axios.postForm( "https://httpbin.org/post", document.querySelector("#fileInput").files ); ``` You can also pass the `FileList` (or array of `File` objects) explicitly under a custom field name by appending `[]` to the key: ```js await axios.postForm("https://httpbin.org/post", { "files[]": document.querySelector("#fileInput").files, }); ``` To use distinct field names for each file, build a `FormData` object manually: ```js const formData = new FormData(); formData.append("avatar", avatarFile); formData.append("cover", coverFile); await axios.post("https://httpbin.org/post", formData); ``` ## Tracking upload progress (browser) Use the `onUploadProgress` callback to show a progress bar or percentage to your users: ```js await axios.postForm("https://httpbin.org/post", { file: document.querySelector("#fileInput").files[0], }, { onUploadProgress: (progressEvent) => { const percent = Math.round( (progressEvent.loaded * 100) / progressEvent.total ); console.log(`Upload progress: ${percent}%`); }, }); ``` See [Progress capturing](/pages/advanced/progress-capturing) for the full list of fields available on the progress event. ## Files in Node.js In Node.js, use `fs.createReadStream` to upload a file from the filesystem without loading it entirely into memory: ```js import fs from "fs"; import FormData from "form-data"; import axios from "axios"; const form = new FormData(); form.append("file", fs.createReadStream("/path/to/file.jpg")); form.append("description", "My uploaded file"); await axios.post("https://httpbin.org/post", form); ``` ::: tip The `form-data` npm package is required in Node.js environments to create `FormData` objects. In modern Node.js (v18+), the global `FormData` is available natively. ::: ## Uploading a Buffer (Node.js) You can also upload an in-memory `Buffer` directly: ```js const buffer = Buffer.from("Hello, world!"); const form = new FormData(); form.append("file", buffer, { filename: "hello.txt", contentType: "text/plain", knownLength: buffer.length, }); await axios.post("https://httpbin.org/post", form); ``` ::: warning Capturing `FormData` upload progress is not currently supported in Node.js environments. ::: ::: danger When uploading a readable stream in Node.js, set `maxRedirects: 0` to prevent the `follow-redirects` package from buffering the entire stream in RAM. ::: axios-axios-2d06f96/docs/pages/advanced/header-methods.md000066400000000000000000000154641521272452000233410ustar00rootroot00000000000000# Header methods With the introduction of the new `AxiosHeaders` class, Axios provides a set of methods to manipulate headers. These methods are used to set, get, and delete headers in a more convenient way than directly manipulating the headers object. ## Constructor `new AxiosHeaders(headers?)` The `AxiosHeaders` class constructor accepts an optional object with headers to initialize the instance. The headers object can contain any number of headers, and the keys are case-insensitive. ```js constructor(headers?: RawAxiosHeaders | AxiosHeaders | string); ``` For convenience, you can pass a string with headers separated by a newline character. The headers are then parsed and added to the instance. ```js const headers = new AxiosHeaders(` Host: www.bing.com User-Agent: curl/7.54.0 Accept: */*`); console.log(headers); // Object [AxiosHeaders] { // host: 'www.bing.com', // 'user-agent': 'curl/7.54.0', // accept: '*/*' // } ``` ## Set The `set` method is used to set headers on the instance of `AxiosHeaders`. The method can be called with a single header name and value, an object with multiple headers, or a string with headers separated by a newline character. The method also accepts an optional `rewrite` parameter that controls the behaviour of setting the header. ```js set(headerName, value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher); set(headerName, value, rewrite?: (this: AxiosHeaders, value: string, name: string) => boolean); set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean); ``` The rewrite argument controls the overwriting behaviour: - `false` - do not overwrite if header's value is set (is not undefined) - `undefined` (default) - overwrite the header unless its value is set to false - `true` - rewrite anyway The option can also accept a user-defined function that determines whether the value should be overwritten or not. The function receives the current value, header name, and the headers object as arguments. Empty or whitespace-only header names are ignored. `AxiosHeaders` keeps the case of the first matching key it sees. You can use this to preserve specific header casing by seeding a key with `undefined` and then setting values later. See [Preserving a specific header case](/pages/advanced/headers#preserving-a-specific-header-case). ## Get The `get` method is used to retrieve the value of a header. The method can be called with a single header name, an optional matcher, or a parser. The matcher is defaulted to `true`. The parser can be a regular expression that is used to extract the value from the header. ```js get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue; get(headerName: string, parser: RegExp): RegExpExecArray | null; ``` An example of some of the possible usages of the `get` method is shown below: ```js const headers = new AxiosHeaders({ 'Content-Type': 'multipart/form-data; boundary=Asrf456BGe4h', }); console.log(headers.get('Content-Type')); // multipart/form-data; boundary=Asrf456BGe4h console.log(headers.get('Content-Type', true)); // parse key-value pairs from a string separated with \s,;= delimiters: // [Object: null prototype] { // 'multipart/form-data': undefined, // boundary: 'Asrf456BGe4h' // } console.log( headers.get('Content-Type', (value, name, headers) => { return String(value).replace(/a/g, 'ZZZ'); }) ); // multipZZZrt/form-dZZZtZZZ; boundZZZry=Asrf456BGe4h console.log(headers.get('Content-Type', /boundary=(\w+)/)?.[0]); // boundary=Asrf456BGe4h ``` ## Has The `has` method is used to check if a header exists in the instance of `AxiosHeaders`. The method can be called with a single header name and an optional matcher. ```js has(header: string, matcher?: AxiosHeaderMatcher): boolean; ``` ::: info Returns true if the header is set (has no undefined value). ::: ## Delete The `delete` method is used to delete a header from the instance of `AxiosHeaders`. The method can be called with a single header name and an optional matcher. ```js delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean; ``` ::: info Returns true if at least one header has been removed. ::: ## Clear The `clear` method is used to delete all headers from the instance of `AxiosHeaders` if nothing is passed. If a matcher is passed, only the headers that match the matcher are removed, in this case, the matcher is used to match against the header name rather than the value. ```js clear(matcher?: AxiosHeaderMatcher): boolean; ``` ::: info Returns true if at least one header has been cleared. ::: ## Normalize If the headers object was changed directly, it can cause duplicates with the same name but in different cases. This method normalizes the headers object by combining duplicate keys into one. Axios uses this method internally after calling each interceptor. Set format to true for converting headers name to lowercase and capitalize the initial letters (cOntEnt-type => Content-Type) or false to keep the original format. ```js const headers = new AxiosHeaders({ foo: '1', }); headers.Foo = '2'; headers.FOO = '3'; console.log(headers.toJSON()); // [Object: null prototype] { foo: '1', Foo: '2', FOO: '3' } console.log(headers.normalize().toJSON()); // [Object: null prototype] { foo: '3' } console.log(headers.normalize(true).toJSON()); // [Object: null prototype] { Foo: '3' } ``` ::: info Returns `this` for chaining. ::: ## Concat Merges the instance with targets into a new AxiosHeaders instance. If the target is a string, it will be parsed as RAW HTTP headers. If the target is an AxiosHeaders instance, it will be merged with the current instance. This is useful for case presets when composing headers. For example: ```js const headers = AxiosHeaders.concat( { 'content-type': undefined }, { 'Content-Type': 'application/octet-stream' } ); ``` ```js concat(...targets: Array): AxiosHeaders; ``` ::: info Returns a new AxiosHeaders instance. ::: ## toJSON Resolve all internal headers values into a new null prototype object. Set `asStrings` to true to resolve arrays as a string containing all elements, separated by commas. ```js toJSON(asStrings: true): Record; toJSON(asStrings?: false): Record; ``` ## From Returns a new `AxiosHeaders` instance created from the raw headers passed in, or simply returns the given headers object if it's an `AxiosHeaders` instance. ```js from(thing?: AxiosHeaders | RawAxiosHeaders | string): AxiosHeaders; ``` ## Shortcuts The following shortcuts are available: - `setContentType`, `getContentType`, `hasContentType` - `setContentLength`, `getContentLength`, `hasContentLength` - `setAccept`, `getAccept`, `hasAccept` - `setUserAgent`, `getUserAgent`, `hasUserAgent` - `setContentEncoding`, `getContentEncoding`, `hasContentEncoding` axios-axios-2d06f96/docs/pages/advanced/headers.md000066400000000000000000000134411521272452000220540ustar00rootroot00000000000000# Headers Axios exposes its own AxiosHeaders class to manipulate headers using a Map-like API that guarantees case-insensitive keys. This class is used internally by Axios to manage headers, but it's also exposed to the user for convenience. Although HTTP headers are case-insensitive, Axios will retain the case of the original header for stylistic reasons and for a workaround when servers mistakenly consider the header's case. The old method of directly manipulating the headers object is still available, but deprecated and not recommended for future usage. ## Working with headers The AxiosHeaders object instance can contain different types of internal values that control the setting and merging logic. The final headers object is obtained by Axios by calling the toJSON method. The AxiosHeaders object is also iterable, so you can use it in loops or convert it to an array or object. The header values can be one of the following types: - `string` - normal string value that will be sent to the server - `null` - skip header when converting to JSON - `false` - skip header when converting to JSON, additionally indicates that set method must be called with rewrite option set to true to overwrite this value (Axios uses this internally to allow users to opt out of installing certain headers like User-Agent or Content-Type) - `undefined` - value is not set ::: warning The header value is considered set if it is not undefined. ::: The headers object is always initialized inside interceptors and transformers as seen in the following example: ```js axios.interceptors.request.use((request: InternalAxiosRequestConfig) => { request.headers.set("My-header", "value"); request.headers.set({ "My-set-header1": "my-set-value1", "My-set-header2": "my-set-value2", }); // Disable subsequent setting of this header by Axios request.headers.set("User-Agent", false); request.headers.setContentType("text/plain"); // Direct access like this is deprecated request.headers["My-set-header2"] = "newValue"; return request; }); ``` You can iterate over an AxiosHeaders using any iterable method, like for-of loop, forEach, or spread operator: ```js const headers = new AxiosHeaders({ foo: '1', bar: '2', baz: '3', }); for (const [header, value] of headers) { console.log(header, value); } // foo 1 // bar 2 // baz 3 ``` ## Setting headers on a request The most common place to set headers is the `headers` option in your request config or instance config: ```js // On a single request await axios.get('/api/data', { headers: { 'Accept-Language': 'en-US', 'X-Request-ID': 'abc123', }, }); // On an instance (applied to every request) const api = axios.create({ headers: { 'X-App-Version': '2.0.0', }, }); ``` ## Preserving a specific header case Axios header names are case-insensitive, but `AxiosHeaders` keeps the case of the first matching key it sees. If you need a specific case for a server with non-standard case-sensitive behavior, define a case preset in defaults and then set values as usual. ```js const api = axios.create(); api.defaults.headers.common = { 'content-type': undefined, accept: undefined, }; await api.put(url, data, { headers: { 'Content-Type': 'application/octet-stream', Accept: 'application/json', }, }); ``` You can also do this with `AxiosHeaders` directly when composing headers: ```js import axios, { AxiosHeaders } from 'axios'; const headers = AxiosHeaders.concat( { 'content-type': undefined }, { 'Content-Type': 'application/octet-stream' } ); await axios.put(url, data, { headers }); ``` ## Setting headers in an interceptor Interceptors are the right place to attach dynamic headers like auth tokens, because the token may not be available when the instance is first created: ```js api.interceptors.request.use((config) => { const token = getAuthToken(); // read at request time config.headers.set('Authorization', `Bearer ${token}`); return config; }); ``` ## Unicode header values `AxiosHeaders` preserves non-control Unicode characters in header values so request interceptors can transform them before the request is sent. CR/LF and other C0 control bytes are still stripped at set time to prevent header injection. Adapters sanitize header values to byte-safe (HT, printable ASCII, and Latin-1 supplement) right before handing them to the platform — Node's `http.request`, the browser's `XMLHttpRequest.setRequestHeader`, and `fetch`'s `Headers`. If a header value contains characters outside that range and you have not encoded it, those characters are stripped, which can produce an empty value on the wire. If you need to send non-ASCII data in a header, encode it in a request interceptor: ```js api.interceptors.request.use((config) => { if (config.headers.has('X-Name')) { config.headers.set('X-Name', encodeURIComponent(config.headers.get('X-Name'))); } return config; }); await api.get('/api/data', { headers: { 'X-Name': '请求用户', }, }); // → request is sent with X-Name: %E8%AF%B7%E6%B1%82%E7%94%A8%E6%88%B7 ``` ## Reading response headers Response headers are available on `response.headers` as an `AxiosHeaders` instance. All header names are lower-cased: ```js const response = await axios.get('/api/data'); console.log(response.headers['content-type']); // application/json; charset=utf-8 console.log(response.headers.get('x-request-id')); // abc123 ``` ## Removing a default header To opt out of a header that axios sets by default (such as `Content-Type` or `User-Agent`), set its value to `false`: ```js await axios.post('/api/data', payload, { headers: { 'Content-Type': false, // let the browser set it automatically (e.g. for FormData) }, }); ``` For more detail on the full `AxiosHeaders` method API, see the [Header methods](/pages/advanced/header-methods) page. axios-axios-2d06f96/docs/pages/advanced/html-form-processing.md000066400000000000000000000036161521272452000245230ustar00rootroot00000000000000# HTML form posting (browser) You can also post a form directly from a HTML form element. This is useful when you have a form in your page and you want to submit it without any JavaScript code. ```js await axios.postForm('https://httpbin.org/post', document.querySelector('#htmlForm')); ``` `FormData` and `HTMLForm` objects can also be posted as `JSON` by explicitly setting the `Content-Type` header to `application/json`: ```js await axios.post('https://httpbin.org/post', document.querySelector('#htmlForm'), { headers: { 'Content-Type': 'application/json', }, }); ``` An example of a form that is valid and can be submitted by the above code is: ```html
``` The above form will be submitted as: ```json { "foo": "1", "deep": { "prop": { "spaced": "3" } }, "baz": ["4", "5"], "user": { "age": "value2" } } ``` ::: tip Path collisions overwrite earlier values Field names are parsed into property paths by splitting on `.`, brackets, or whitespace. Two inputs whose paths overlap will collide: in the example above, `deep.prop` parses to `["deep", "prop"]` and `deep prop spaced` parses to `["deep", "prop", "spaced"]`, so the deeper assignment replaces `deep.prop = "2"` with the nested object `{ spaced: "3" }`. Pick non-overlapping field names if you need both values. ::: ::: warning Sending Blobs/Files as JSON (base64) is not currently supported. ::: axios-axios-2d06f96/docs/pages/advanced/http2.md000066400000000000000000000046461521272452000215110ustar00rootroot00000000000000# HTTP2 Experimental HTTP/2 support was added to the `http` adapter in version `1.13.0`. It is available in Node.js environments only. ## Basic usage Use the `httpVersion` option to select the protocol version for a request. Setting it to `2` enables HTTP/2. ```js const { data, headers, status } = await axios.post( "https://httpbin.org/post", form, { httpVersion: 2, }, ); ``` ## `http2Options` Additional native options for the internal `session.request()` call can be passed via the `http2Options` config object. This also includes the custom `sessionTimeout` parameter, which controls how long (in milliseconds) an idle HTTP/2 session is kept alive before being closed. It defaults to `1000ms`. ```js { httpVersion: 2, http2Options: { rejectUnauthorized: false, // accept self-signed certificates (dev only) sessionTimeout: 5000, // keep idle session alive for 5 seconds }, } ``` ::: warning HTTP/2 support is currently experimental. The API may change in future minor or patch releases. ::: ::: warning Redirects are not supported over HTTP/2 The HTTP/2 adapter does not currently follow redirects. If a request issued with `httpVersion: 2` receives a `3xx` response, the redirect is not followed automatically. Handle these responses manually or stay on HTTP/1.x for endpoints that rely on redirects. ::: ## Full example The example below sends a `multipart/form-data` POST request over HTTP/2 and tracks both upload and download progress. ```js const form = new FormData(); form.append("foo", "123"); const { data, headers, status } = await axios.post( "https://httpbin.org/post", form, { httpVersion: 2, http2Options: { // rejectUnauthorized: false, // sessionTimeout: 1000 }, onUploadProgress(e) { console.log("upload progress", e); }, onDownloadProgress(e) { console.log("download progress", e); }, responseType: "arraybuffer", }, ); ``` ## Config reference | Option | Type | Default | Description | |---|---|---|---| | `httpVersion` | `number` | `1` | HTTP protocol version to use. Set to `2` to enable HTTP/2. | | `http2Options.sessionTimeout` | `number` | `1000` | Time in milliseconds before an idle HTTP/2 session is closed. | All other native `session.request()` options supported by Node.js's built-in `http2` module can also be passed inside `http2Options`. axios-axios-2d06f96/docs/pages/advanced/interceptors.md000066400000000000000000000131501521272452000231570ustar00rootroot00000000000000# Interceptors Interceptors are a powerful mechanism that can be used to intercept and modify HTTP requests and responses. They are very similar to middleware in Express.js. The interceptor is a function that gets executed before a request is sent and before a response is received. Interceptors are useful for a variety of tasks such as logging, modifying request headers, and modifying the response. Basic usage of interceptors is as follows: ```js // Add a request interceptor axios.interceptors.request.use( function (config) { // Do something before request is sent return config; }, function (error) { // Do something with request error return Promise.reject(error); } ); // Add a response interceptor axios.interceptors.response.use( function (response) { // Any status code that lie within the range of 2xx cause this function to trigger // Do something with response data return response; }, function (error) { // Any status codes that falls outside the range of 2xx cause this function to trigger // Do something with response error return Promise.reject(error); } ); ``` ## Removing Interceptors You can remove any interceptor by using the `eject` method on the interceptor you want to remove. You can also remove all interceptors by calling the `clear` method on the `axios.interceptors` object. Here is an example of how to remove an interceptor: ```js // Eject the request interceptor const myInterceptor = axios.interceptors.request.use(function () { /*...*/ }); axios.interceptors.request.eject(myInterceptor); // Eject the response interceptor const myInterceptor = axios.interceptors.response.use(function () { /*...*/ }); axios.interceptors.response.eject(myInterceptor); ``` Here is an example of how to remove all interceptors: ```js const instance = axios.create(); instance.interceptors.request.use(function () { /*...*/ }); instance.interceptors.request.clear(); // Removes interceptors from requests instance.interceptors.response.use(function () { /*...*/ }); instance.interceptors.response.clear(); // Removes interceptors from responses ``` ## Interceptors default behaviour When you add request interceptors, they are presumed to be asynchronous by default. This can cause a delay in the execution of your axios request when the main thread is blocked (a promise is created under the hood for the interceptor and your request gets put on the bottom of the call stack). If your request interceptors are synchronous you can add a flag to the options object that will tell axios to run the code synchronously and avoid any delays in request execution. ```js axios.interceptors.request.use( function (config) { config.headers.test = "I am only a header!"; return config; }, null, { synchronous: true } ); ``` ## Interceptors using `runWhen` If you want to execute a particular interceptor based on a runtime check, you can add a runWhen function to the options object. The interceptor will not be executed if and only if the return of runWhen is false. The function will be called with the config object (don't forget that you can bind your own arguments to it as well.) This can be handy when you have an asynchronous request interceptor that only needs to run at certain times. ```js function onGetCall(config) { return config.method === "get"; } axios.interceptors.request.use( function (config) { config.headers.test = "special get headers"; return config; }, null, { runWhen: onGetCall } ); ``` ## Interceptor execution order ::: warning Request and response interceptors run in **opposite** orders Request interceptors are executed in **reverse order** (LIFO — last in, first out). The _last_ request interceptor added is executed _first_. Response interceptors are executed in the **order they were added** (FIFO — first in, first out). The _first_ response interceptor added is executed _first_. ::: The following example shows the full execution order for three request interceptors and three response interceptors: ```js const instance = axios.create(); const interceptor = (id) => (base) => { console.log(id); return base; }; instance.interceptors.request.use(interceptor("Request Interceptor 1")); instance.interceptors.request.use(interceptor("Request Interceptor 2")); instance.interceptors.request.use(interceptor("Request Interceptor 3")); instance.interceptors.response.use(interceptor("Response Interceptor 1")); instance.interceptors.response.use(interceptor("Response Interceptor 2")); instance.interceptors.response.use(interceptor("Response Interceptor 3")); // Console output: // Request Interceptor 3 // Request Interceptor 2 // Request Interceptor 1 // [HTTP request is made] // Response Interceptor 1 // Response Interceptor 2 // Response Interceptor 3 ``` ## Multiple interceptors You may add multiple interceptors to the same request or response. The following will hold true for multiple interceptors in the same chain in the order below: - Each interceptor is executed - Request interceptors are executed in reverse order (LIFO). - Response interceptors are executed in the order they were added (FIFO). - only the last interceptor's result is returned - every interceptor receives the result of its predecessor - when the fulfilment-interceptor throws - the following fulfilment-interceptor is not called - the following rejection-interceptor is called - once caught, another following fulfil-interceptor is called again (just like in a promise chain). ::: tip To gain an in-depth understanding of how interceptors work, you can read the test cases over [here](https://github.com/axios/axios/blob/v1.x/test/specs/interceptors.spec.js). ::: axios-axios-2d06f96/docs/pages/advanced/multipart-form-data-format.md000066400000000000000000000140441521272452000256200ustar00rootroot00000000000000# multipart-form-data format axios can send requests in the `multipart/form-data` format. This format is commonly used when uploading files. To send a request in this format, you need to create a `FormData` object and append the data to it. Then you can pass the `FormData` object to the `data` property of the axios request config. ```js const formData = new FormData(); formData.append('foo', 'bar'); axios.post('https://httpbin.org/post', formData); ``` Do not manually set the `Content-Type` header for browser, web worker, or React Native `FormData`; those runtimes add the multipart boundary themselves. In node.js, you can use the `form-data` library as follows: ```js const FormData = require('form-data'); const form = new FormData(); form.append('my_field', 'my value'); form.append('my_buffer', Buffer.alloc(10)); form.append('my_file', fs.createReadStream('/foo/bar.jpg')); axios.post('https://example.com', form); ``` ## Automatic serialization to FormData Starting from v0.27.0, Axios supports automatic object serialization to a FormData object if the request Content-Type header is set to multipart/form-data. This means that you can pass a JavaScript object directly to the data property of the axios request config. For example when passing data to a POST request: ```js import axios from 'axios'; axios .post( 'https://httpbin.org/post', { x: 1 }, { headers: { 'Content-Type': 'multipart/form-data', }, } ) .then(({ data }) => console.log(data)); ``` In the node.js build, the ([`form-data`](https://github.com/form-data/form-data)) polyfill is used by default. You can overload the FormData class by setting the env.FormData config variable, but you probably won't need it in most cases: ```js const axios = require('axios'); var FormData = require('form-data'); axios .post( 'https://httpbin.org/post', { x: 1, buf: Buffer.alloc(10) }, { headers: { 'Content-Type': 'multipart/form-data', }, } ) .then(({ data }) => console.log(data)); ``` ## Header policy for Node.js `FormData` When you pass a Node.js `FormData` object that exposes `getHeaders()` (such as the [`form-data`](https://github.com/form-data/form-data) package), axios copies all headers it returns onto the request by default. This preserves v1 compatibility but can be problematic when the `FormData` object comes from an untrusted source — `getHeaders()` could overwrite headers like `Authorization` or inject arbitrary ones. Set `formDataHeaderPolicy: 'content-only'` to copy **only** `Content-Type` and `Content-Length` from `getHeaders()`, then set any other headers explicitly via the request `headers` config: ```js await axios.post("https://example.com/upload", form, { formDataHeaderPolicy: "content-only", headers: { Authorization: "Bearer my-token", }, }); ``` The default value is `'legacy'`. See [`formDataHeaderPolicy`](/pages/advanced/request-config#formdataheaderpolicy) in the request config reference for details. ## Supported endings Axios FormData serializer supports some special endings to perform the following operations: - `{}` - serialize the value with JSON.stringify - `[]` - unwrap the array-like object as separate fields with the same key ::: warning Note: unwrap/expand operation will be used by default on arrays and FileList objects ::: ## Configuring the FormData serializer FormData serializer supports additional options via config.formSerializer: object property to handle rare cases: - `visitor: Function` - user-defined visitor function that will be called recursively to serialize the data object to a FormData object by following custom rules. - `dots: boolean = false` - use dot notation instead of brackets to serialize arrays and objects; - `metaTokens: boolean = true` - add the special ending (e.g `user{}: '{"name": "John"}'`) in the FormData key. The back-end body-parser could potentially use this meta-information to automatically parse the value as JSON. - `indexes: null|false|true = false` - controls how indexes will be added to unwrapped keys of flat array-like objects - `null` - don't add brackets (`arr: 1`, `arr: 2`, `arr: 3`) - `false` (default) - add empty brackets (`arr[]: 1`, `arr[]: 2`, `arr[]: 3`) - `true` - add brackets with indexes (`arr[0]: 1`, `arr[1]: 2`, `arr[2]: 3`) - `maxDepth: number = 100` - maximum object nesting depth the serializer will recurse into. If the input exceeds this depth, an `AxiosError` with `code: 'ERR_FORM_DATA_DEPTH_EXCEEDED'` is thrown. This protects server-side applications from DoS attacks via deeply nested payloads. Set to `Infinity` to disable the limit. ```js // Allow deeper nesting for schemas that legitimately exceed 100 levels: axios.postForm('/api', data, { formSerializer: { maxDepth: 200 } }); ``` ::: warning Security note The default limit of 100 is intentional. Server-side code that forwards client-controlled JSON to axios as `data` is vulnerable to a call-stack overflow without this guard. Only raise `maxDepth` if your schema genuinely requires it. ::: For example, if we have an object like this: ```js const obj = { x: 1, arr: [1, 2, 3], arr2: [1, [2], 3], users: [ { name: 'Peter', surname: 'Griffin' }, { name: 'Thomas', surname: 'Anderson' }, ], 'obj2{}': [{ x: 1 }], }; ``` The following steps will be executed by the Axios serializer internally: ```js const formData = new FormData(); formData.append('x', '1'); formData.append('arr[]', '1'); formData.append('arr[]', '2'); formData.append('arr[]', '3'); formData.append('arr2[0]', '1'); formData.append('arr2[1][0]', '2'); formData.append('arr2[2]', '3'); formData.append('users[0][name]', 'Peter'); formData.append('users[0][surname]', 'Griffin'); formData.append('users[1][name]', 'Thomas'); formData.append('users[1][surname]', 'Anderson'); formData.append('obj2{}', '[{"x":1}]'); ``` Axios supports the following shortcut methods: `postForm`, `putForm`, `patchForm` which are just the corresponding http methods with the `Content-Type` header preset to `multipart/form-data`. axios-axios-2d06f96/docs/pages/advanced/progress-capturing.md000066400000000000000000000036101521272452000242740ustar00rootroot00000000000000# Progress capturing Axios supports both browser and node environments to capture request upload/download progress. The frequency of progress events is forced to be limited to 3 times per second. This is to prevent the browser from being overwhelmed with progress events. An example of capturing progress events is shown below: ```js await axios.post(url, data, { onUploadProgress: function (axiosProgressEvent) { /*{ loaded: number; total?: number; progress?: number; // in range [0..1] bytes: number; // how many bytes have been transferred since the last trigger (delta) estimated?: number; // estimated time in seconds rate?: number; // upload speed in bytes upload: true; // upload sign }*/ }, onDownloadProgress: function (axiosProgressEvent) { /*{ loaded: number; total?: number; progress?: number; bytes: number; estimated?: number; rate?: number; // download speed in bytes download: true; // download sign }*/ }, }); ``` You can also stream the upload and download progress events to a readable stream in Node.js. This is useful when you want to display the progress in a custom way. An example of streaming progress events is shown below: ```js const { data } = await axios.post(SERVER_URL, readableStream, { onUploadProgress: ({ progress }) => { console.log((progress * 100).toFixed(2)); }, headers: { "Content-Length": contentLength, }, maxRedirects: 0, // avoid buffering the entire stream }); ``` ::: warning Capturing FormData upload progress is not currently supported in node.js environments ::: ::: danger It is recommended to disable redirects by setting maxRedirects: 0 to upload the stream in the node.js environment, as the follow-redirects package will buffer the entire stream in RAM without following the "backpressure" algorithm ::: axios-axios-2d06f96/docs/pages/advanced/promises.md000066400000000000000000000042131521272452000222770ustar00rootroot00000000000000# Promises axios is built on top of the native ES6 Promise API. Every axios request returns a Promise that resolves to a response object or rejects with an error. If your environment doesn't support ES6 Promises, you will need to polyfill them — for example with [es6-promise](https://github.com/stefanpenner/es6-promise). ## then / catch / finally Because axios returns a standard Promise, you can use `.then()`, `.catch()`, and `.finally()` to handle the result: ```js axios.get("/api/users") .then((response) => { console.log(response.data); }) .catch((error) => { console.error("Request failed:", error.message); }) .finally(() => { console.log("Request finished"); }); ``` ## async / await The recommended approach for most codebases is `async/await`, which makes asynchronous code read like synchronous code: ```js async function fetchUser(id) { try { const response = await axios.get(`/api/users/${id}`); return response.data; } catch (error) { console.error("Failed to fetch user:", error.message); throw error; } } ``` ## Parallel requests Because axios returns a standard Promise, you can use `Promise.all` to make multiple requests at the same time and wait for all of them to complete: ```js const [users, posts] = await Promise.all([ axios.get("/api/users"), axios.get("/api/posts"), ]); console.log(users.data, posts.data); ``` ::: tip `Promise.all` will reject as soon as any one of the requests fails. If you want to handle partial failures, use `Promise.allSettled` instead. ::: ```js const results = await Promise.allSettled([ axios.get("/api/users"), axios.get("/api/posts"), ]); results.forEach((result) => { if (result.status === "fulfilled") { console.log(result.value.data); } else { console.error("Request failed:", result.reason.message); } }); ``` ## Chaining requests You can chain `.then()` calls to run requests sequentially, passing data from one to the next: ```js axios.get("/api/user/1") .then(({ data: user }) => axios.get(`/api/posts?userId=${user.id}`)) .then(({ data: posts }) => { console.log("Posts for user:", posts); }) .catch(console.error); ``` axios-axios-2d06f96/docs/pages/advanced/rate-limiting.md000066400000000000000000000040471521272452000232100ustar00rootroot00000000000000# Rate limiting axios supports bandwidth limiting in the Node.js environment via the HTTP adapter. This lets you cap how fast data is uploaded or downloaded, which is useful for bulk operations, background jobs, or polite scraping that shouldn't saturate a connection. ## `maxRate` The `maxRate` option accepts either a number (bytes per second) or an array where the first value is the upload limit and the second value is the download limit. Use `[uploadRate]` to limit upload only, or `[uploadRate, downloadRate]` to limit both directions. When a single number is passed, the same limit applies to both upload and download. ```js // Limit both upload and download to 100 KB/s await axios.get(URL, { maxRate: 100 * 1024 }); // Limit upload to 100 KB/s, download to 500 KB/s await axios.get(URL, { maxRate: [100 * 1024, 500 * 1024] }); ``` ::: warning `maxRate` is only supported by the Node.js HTTP adapter. It has no effect in browser environments. ::: ## Upload rate limiting Cap the upload speed and log progress at the same time: ```js const { data } = await axios.post(SERVER_URL, myBuffer, { onUploadProgress: ({ progress, rate }) => { const percent = (progress * 100).toFixed(1); const kbps = (rate / 1024).toFixed(1); console.log(`Upload [${percent}%] at ${kbps} KB/s`); }, maxRate: [100 * 1024], // cap upload at 100 KB/s }); ``` ## Download rate limiting Cap the download speed for large responses: ```js const { data } = await axios.get(FILE_URL, { onDownloadProgress: ({ progress, rate }) => { const percent = (progress * 100).toFixed(1); const kbps = (rate / 1024).toFixed(1); console.log(`Download [${percent}%] at ${kbps} KB/s`); }, maxRate: [Infinity, 200 * 1024], // no upload limit, 200 KB/s download limit responseType: "arraybuffer", }); ``` ## Combined upload and download limiting Pass both limits as an array to control both directions simultaneously: ```js await axios.post(SERVER_URL, largeBuffer, { maxRate: [50 * 1024, 500 * 1024], // 50 KB/s up, 500 KB/s down }); ``` axios-axios-2d06f96/docs/pages/advanced/request-config.md000066400000000000000000000626661521272452000234110ustar00rootroot00000000000000# Request config The request config is used to configure the request. There is a wide range of options available, but the only required option is `url`. If the configuration object does not contain a `method` field, the default method is `GET`. ::: warning Security: decompression-bomb protection is opt-in By default `maxContentLength` and `maxBodyLength` are `-1` (unlimited). A malicious or compromised server can return a tiny gzip/deflate/brotli/zstd body that expands to gigabytes and exhaust the Node.js process. If you call servers you do not fully trust, **set a cap**: ```js axios.defaults.maxContentLength = 10 * 1024 * 1024; // 10 MB axios.defaults.maxBodyLength = 10 * 1024 * 1024; ``` See the [security guide](/pages/misc/security) for details. ::: ### `url` The `url` is the URL to which the request is made. It can be a string or an instance of `URL`. ### `method` The `method` is the HTTP method to use for the request. The default method is `GET`. ### `baseURL` The `baseURL` is the base URL to be prepended to the `url` unless the `url` is an absolute URL. This is useful for making requests to the same domain without having to repeat the domain name and any api or version prefix. ### `allowAbsoluteUrls` The `allowAbsoluteUrls` determines whether or not absolute URLs will override a configured `baseUrl`. When set to true (default), absolute values for `url` will override `baseUrl`. When set to false, absolute values for `url` will always be prepended by `baseUrl`. ### `transformRequest` The `transformRequest` function allows you to modify the request data before it is sent to the server. This function is called with the request data as its only argument. This is only applicable for request methods `PUT`, `POST`, `PATCH` and `DELETE`. The last function in the array must return a string or an instance of Buffer, ArrayBuffer, FormData or Stream. ### `transformResponse` The `transformResponse` function allows you to modify the response data before it is passed to the `then` or `catch` functions. This function is called with the response data as its only argument. ### `parseReviver` The `parseReviver` function allows you to provide a custom "reviver" function directly to the native `JSON.parse()` call used by the default `transformResponse`. This is particularly useful for performing high-performance type hydration (e.g., converting ISO strings to `Temporal` or `Date` objects) or preventing precision loss during parsing. In modern environments (ES2023+), the reviver function receives a third `context` argument. This provides access to the raw JSON `source`, allowing for precise conversion of large integers (BigInt) that would otherwise lose precision if parsed as standard JavaScript numbers. > Note: `Temporal` is not yet available in all environments. Consider using a polyfill if needed. ```js const client = axios.create({ parseReviver: (key, value, context) => { // Example: Precision-safe BigInt parsing if (typeof value === 'number' && context?.source) { const isInteger = Number.isInteger(value); const isUnsafe = !Number.isSafeInteger(value); const isValidIntegerString = /^-?\d+$/.test(context.source); if (isInteger && isUnsafe && isValidIntegerString) { try { return BigInt(context.source); } catch { // Fallback: return original value if parsing fails } } } // Example: Hydrating dates into Temporal objects if ( typeof value === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(value) && typeof Temporal !== 'undefined' && Temporal?.PlainDate ) { return Temporal.PlainDate.from(value); } return value; }, }); ``` ### `headers` The `headers` are the HTTP headers to be sent with the request. The `Content-Type` header is set to `application/json` by default. ### `params` The `params` are the URL parameters to be sent with the request. This must be a plain object or a URLSearchParams object. If the `url` contains query parameters, they will be merged with the `params` object. ### `paramsSerializer` The `paramsSerializer` function allows you to serialize the `params` object before it is sent to the server. There are a few options available for this function, so please refer to the full request config example at the end of this page. #### Strict RFC 3986 percent-encoding By default, axios decodes `%3A`, `%24`, `%2C` and `%20` back to `:`, `$`, `,` and `+` for readability (the `+` follows the `application/x-www-form-urlencoded` convention for spaces in query strings). These characters are valid in a query component under [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.4), so the default output is correct. However, some backends require strict percent-encoding and reject the readable form. Use the `encode` option to override the default encoder: ```js // Per-request: emit strict RFC 3986 percent-encoding for query values axios.get('/foo', { params: { filter: JSON.stringify({ startedAt: '2026-01-23' }) }, paramsSerializer: { encode: encodeURIComponent } }); // Or set it on the instance defaults const client = axios.create({ paramsSerializer: { encode: encodeURIComponent } }); ``` ### `data` The `data` is the data to be sent as the request body. This can be a string, a plain object, a Buffer, ArrayBuffer, FormData, Stream, or URLSearchParams. Only applicable for request methods `PUT`, `POST`, `DELETE` , and `PATCH`. When no `transformRequest` is set, must be of one of the following types: - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams - Browser only: FormData, File, Blob - React Native: FormData - Node only: Stream, Buffer, FormData (form-data package) For browser, web worker, and React Native `FormData`, do not manually set `Content-Type`; the runtime adds the multipart boundary. For Node.js `FormData` objects that provide a `getHeaders()` method, axios copies all returned headers by default for v1 compatibility. If the `FormData` object is custom or not fully trusted, set `formDataHeaderPolicy: 'content-only'` to copy only `Content-Type` and `Content-Length`, and set any other request headers explicitly via the request `headers` config. ### `formDataHeaderPolicy` Controls how axios copies headers returned by Node.js `FormData#getHeaders()`. The default is `'legacy'`, which copies all returned headers to preserve existing v1 behavior. Set `'content-only'` to copy only `Content-Type` and `Content-Length` from `getHeaders()`. ### `timeout` The `timeout` is the number of milliseconds before the request times out. If the request takes longer than `timeout`, the request will be aborted. ### `withCredentials` The `withCredentials` property indicates whether or not cross-site Access-Control requests should be made using credentials such as cookies, authorization headers, or TLS client certificates. Setting withCredentials has no effect on same-site requests. ### `adapter` `adapter` allows custom handling of requests which makes testing easier. Return a promise and supply a valid response see [adapters](/pages/advanced/adapters) for more information. We also provide a number of built-in adapters. The default adapter is `http` for node and `xhr` for browsers. The full list of built-in adapters as follows: - fetch - http - xhr You may also pass an array of adapters to be used, axios will use the first adapter that is supported by the environment. ### `auth` `auth` indicates that HTTP Basic auth should be used, and supplies credentials. This will set an `Authorization` header, overwriting any existing `Authorization` custom headers you have set using `headers`. If `auth` is omitted, the Node.js HTTP and fetch adapters can derive Basic auth credentials from the request URL, for example `https://user:pass@example.com`; percent-encoded URL credentials are decoded, and `auth` always takes precedence over URL-embedded credentials. In the Node.js HTTP adapter, Basic auth is preserved on same-origin redirects and stripped on cross-origin redirects. Please note that only HTTP Basic auth is configurable through this parameter. For Bearer tokens and such, use `Authorization` custom headers instead. ### `responseType` The `responseType` indicates the type of data that the server will respond with. This can be one of the following: - arraybuffer - document - json - text - stream - blob (browser only) - formdata (fetch adapter only) ### `responseEncoding` The `responseEncoding` indicates encoding to use for decoding responses. The following options are supported: - ascii - ASCII - ansi - ANSI - binary - BINARY - base64 - BASE64 - base64url - BASE64URL - hex - HEX - latin1 - LATIN1 - ucs-2 - UCS-2 - ucs2 - UCS2 - utf-8 - UTF-8 - utf8 - UTF8 - utf16le - UTF16LE ::: tip Note: Ignored for `responseType` of `stream` or client-side requests ::: ### `xsrfCookieName` The `xsrfCookieName` is the name of the cookie to use as a value for `XSRF` token. ### `xsrfHeaderName` The `xsrfHeaderName` is the name of the header to use as a value for `XSRF` token. ### `withXSRFToken` `withXSRFToken` controls whether axios reads the XSRF cookie and sets the XSRF header on browser requests. It accepts: - `undefined` _(default)_ — set the XSRF header only for same-origin requests. - `true` — always set the XSRF header, including for cross-origin requests. - `false` — never set the XSRF header. - `(config: InternalAxiosRequestConfig) => boolean | undefined` — a callback that decides per-request, receiving the internal config object. ```ts withXSRFToken: boolean | undefined | ((config: InternalAxiosRequestConfig) => boolean | undefined); ``` ::: warning Cross-origin XSRF and `withCredentials` `withCredentials` controls whether cross-site requests include credentials (cookies, HTTP auth). `withXSRFToken` controls whether axios sets the XSRF header. For cross-origin requests, set `withXSRFToken: true` to force the header; additionally set `withCredentials: true` only when the request also needs credentials/cookies. ```js axios.get('/user', { withCredentials: true, withXSRFToken: true }); ``` ::: ### `onUploadProgress` The `onUploadProgress` function allows you to listen to the progress of an upload. ### `onDownloadProgress` The `onDownloadProgress` function allows you to listen to the progress of a download. ### `maxContentLength` The `maxContentLength` property defines the maximum response size in bytes. The Node.js HTTP adapter enforces it for buffered and streamed responses. The fetch adapter enforces it when the response length is declared, the response stream can be tracked, or the response size can otherwise be determined. > ⚠️ **Security:** defaults to `-1` (unlimited). Unbounded responses combined with gzip/deflate/brotli/zstd decompression allow decompression-bomb DoS. > Set an explicit limit when requesting servers you do not fully trust. ### `maxBodyLength` The `maxBodyLength` property defines the maximum request body size in bytes. The Node.js HTTP adapter enforces it, and the fetch adapter enforces it when the request body length can be determined. ### `redact` The `redact` property is an optional array of config key names to mask when an `AxiosError` is serialized with `toJSON()`. Matching is case-insensitive and recursive across the serialized request config. Matching values are replaced with `[REDACTED ****]`. `redact` only affects error serialization. It does not change request data, headers, or the original config object. ```js axios.get('/user/12345', { headers: { Authorization: 'Bearer token' }, auth: { username: 'me', password: 'secret' }, redact: ['authorization', 'password'] }).catch((error) => { console.log(error.toJSON().config); }); ``` ### `validateStatus` The `validateStatus` function allows you to override the default status code validation. By default, axios will reject the promise if the status code is not in the range of 200-299. You can override this behavior by providing a custom `validateStatus` function. The function should return `true` if the status code is within the range you want to accept. ### `maxRedirects` The `maxRedirects` property defines the maximum number of redirects to follow. If set to 0, no redirects will be followed. ### `beforeRedirect` The `beforeRedirect` function allows you to modify the request before it is redirected. Use this to adjust the request options upon redirecting, to inspect the latest response headers, or to cancel the request by throwing an error. If maxRedirects is set to 0, `beforeRedirect` is not used. ```js beforeRedirect: (options, { headers }) => { if ( options.hostname === "example.com" && options.protocol === "https:" ) { options.auth = "user:password"; } } ``` ::: warning Security: re-injecting credentials on redirect The `beforeRedirect` hook runs **after** sensitive headers are stripped during redirects. The `follow-redirects` library removes credentials on protocol downgrade (HTTPS → HTTP) for security. Since `beforeRedirect` runs after this, re-injecting credentials without checking the destination protocol can expose sensitive data. Only re-add credentials for trusted HTTPS destinations, and avoid re-adding them on downgraded redirects. ::: ### `socketPath` The `socketPath` property defines a UNIX socket to use instead of a TCP connection. e.g. `/var/run/docker.sock` to send requests to the docker daemon. Only `socketPath` or `proxy` can be specified. If both are specified, `socketPath` is used. :::warning Security When `socketPath` is set, the hostname and port of the request URL are ignored and axios communicates directly with the specified Unix domain socket. If any part of the request config is derived from user input (for example, when forwarding or merging request options in a proxy/webhook handler), an attacker can inject `socketPath` to redirect traffic to privileged local sockets such as `/var/run/docker.sock`, `/run/containerd/containerd.sock`, or `/run/systemd/private` — bypassing hostname-based SSRF protections entirely (CWE-918). Strip or allowlist config keys from untrusted input, and/or restrict accepted socket paths with `allowedSocketPaths` (see below). ::: ### `allowedSocketPaths` Restricts which socket paths may be used via `socketPath`. Accepts a string or an array of strings. When set, axios resolves the `socketPath` and compares it against each entry (also resolved); the request is rejected with `AxiosError` code `ERR_BAD_OPTION_VALUE` when there is no match. When unset (default), `socketPath` behaves as before. ```js const client = axios.create({ allowedSocketPaths: ['/var/run/docker.sock'], }); // allowed await client.get('http://localhost/v1.45/info', { socketPath: '/var/run/docker.sock' }); // rejected — not in allowlist await client.get('http://localhost/pods', { socketPath: '/var/run/kubelet.sock' }); ``` An empty array (`allowedSocketPaths: []`) blocks all socket paths. ### `transport` The `transport` property defines the transport to use for the request. This is useful for making requests over a different protocol, such as `http2`. ### `httpAgent` and `httpsAgent` The `httpAgent` and `httpsAgent` define a custom agent to be used when performing http and https requests, respectively, in node.js. This allows options to be added like `keepAlive` that are not enabled by default. ### `proxy` The `proxy` defines the hostname, port, and protocol of a proxy server you would like to use. You can also define your proxy using the conventional `http_proxy` and `https_proxy` environment variables. If you are using environment variables for your proxy configuration, you can also define a `no_proxy` environment variable as a comma-separated list of domains that should not be proxied. Use `false` to disable proxies, ignoring environment variables. `auth` indicates that HTTP Basic auth should be used to connect to the proxy, and supplies credentials. This will set an `Proxy-Authorization` header, overwriting any existing `Proxy-Authorization` custom headers you have set using `headers`. If the proxy server uses HTTPS, then you must set the protocol to `https`. A user-supplied `Host` header in `headers` is preserved when forwarding through a proxy (case-insensitive match on `host` / `Host` / `HOST`). This lets you target a virtual host that differs from the request URL — for example, hitting `127.0.0.1:4000` while having the proxy treat the request as `example.com`. If no `Host` header is supplied, axios defaults it to the request URL's `hostname:port` as before. For `https://` targets, axios establishes a CONNECT tunnel through the proxy and performs TLS end-to-end with the origin. `Proxy-Authorization` is sent only on the CONNECT request, never on the wrapped TLS request. `httpsAgent` TLS options such as `ca`, `cert`, `key`, and `rejectUnauthorized` are forwarded to the generated tunneling agent so they still apply to the origin TLS connection. If you supply an `HttpsProxyAgent`, axios leaves tunneling to that agent. ```js proxy: { protocol: "https", host: "127.0.0.1", hostname: "localhost", // Takes precedence over "host" if both are defined port: 9000, auth: { username: "mikeymike", password: "rapunz3l" } }, ``` ### `cancelToken` The `cancelToken` property allows you to create a cancel token that can be used to cancel the request. For more information, see the [cancellation](/pages/advanced/cancellation) documentation. ### `signal` The `signal` property allows you to pass an instance of `AbortSignal` to the request. This allows you to cancel the request using the `AbortController` API. ### `decompress` The `decompress` property indicates whether or not to automatically decompress the response data. The default value is `true`. The Node.js HTTP adapter supports gzip, deflate, brotli, and zstd when the current Node.js runtime provides the corresponding zlib decompressor. ### `insecureHTTPParser` Indicates where to use an insecure HTTP parser that accepts invalid HTTP headers. This may allow interoperability with non-conformant HTTP implementations. Using the insecure parser should be avoided. Please note that the `insecureHTTPParser` option is only available in Node.js 12.10.0 and later. Please read the [Node.js documentation](https://nodejs.org/en/blog/vulnerability/february-2020-security-releases/#strict-http-header-parsing-none) for more information. See the full set of options [here](https://nodejs.org/dist/latest-v12.x/docs/api/http.html#http_http_request_url_options_callback) ### `transitional` The `transitional` property allows you to enable or disable certain transitional features. The following options are available: - `silentJSONParsing`: If set to `true` _(default)_, axios silently ignores JSON parsing errors and sets `response.data` to `null` when parsing fails. Set to `false` to throw `SyntaxError` instead. ::: tip Important This option only takes effect when `responseType` is **explicitly** set to `'json'`. When `responseType` is omitted, axios uses `forcedJSONParsing` to attempt JSON parsing and silently returns the raw string on failure regardless of this setting. To make invalid JSON throw, set both: ```js { responseType: 'json', transitional: { silentJSONParsing: false } } ``` ::: - `forcedJSONParsing`: Forces axios to parse the response string as JSON even if `responseType` is not `'json'`. - `clarifyTimeoutError`: Clarifies the error message when a request times out. This is useful when you are debugging timeout issues. - `advertiseZstdAcceptEncoding`: When set to `true`, axios adds `zstd` to the default `Accept-Encoding` request header when the current Node.js runtime supports zstd decompression. zstd responses are still decompressed automatically when supported and `decompress` is `true`. - `legacyInterceptorReqResOrdering`: When set to true we will use the legacy interceptor request/response ordering. ### `env` The `env` property allows you to set some configuration options. For example the FormData class which is used to automatically serialize the payload into a FormData object. - FormData: window?.FormData || global?.FormData ### `formSerializer` The `formSerializer` option allows you to configure how plain objects are serialized to `multipart/form-data` when used as request `data`. Available options: - `visitor` — custom visitor function called recursively for each value - `dots` — use dot notation instead of bracket notation - `metaTokens` — preserve special key endings such as `{}` - `indexes` — control bracket format for array keys (`null` / `false` / `true`) - `maxDepth` _(default: `100`)_ — maximum nesting depth before throwing `AxiosError` with code `ERR_FORM_DATA_DEPTH_EXCEEDED`. Set to `Infinity` to disable. See the [multipart/form-data](/pages/advanced/multipart-form-data-format) page for full details, and the full request config example at the end of this page. ### `maxRate` The `maxRate` property defines the maximum **bandwidth** (in bytes per second) for upload and/or download. It accepts either a single number (applied to both directions) or a two-element array `[uploadRate, downloadRate]` where each element is a byte-per-second limit. For example, `100 * 1024` means 100 KB/s. See [Rate limiting](/pages/advanced/rate-limiting) for examples. ## Full request config example ```js { url: "/posts", method: "get", baseURL: "https://jsonplaceholder.typicode.com", allowAbsoluteUrls: true, transformRequest: [function (data, headers) { return data; }], transformResponse: [function (data) { return data; }], headers: {"X-Requested-With": "XMLHttpRequest"}, params: { postId: 5 }, paramsSerializer: { // Custom encoder function which sends key/value pairs in an iterative fashion. encode?: (param: string): string => { /* Do custom operations here and return transformed string */ }, // Custom serializer function for the entire parameter. Allows user to mimic pre 1.x behaviour. serialize?: (params: Record, options?: ParamsSerializerOptions ), // Configuration for formatting array indexes in the params. // Three available options: // (1) indexes: null (leads to no brackets) // (2) (default) indexes: false (leads to empty brackets) // (3) indexes: true (leads to brackets with indexes). indexes: false, // Maximum object nesting depth when serializing params. Throws AxiosError // (ERR_FORM_DATA_DEPTH_EXCEEDED) if exceeded. Default: 100. Set to Infinity to disable. maxDepth: 100 }, data: { firstName: "Fred" }, formDataHeaderPolicy: "legacy", // Syntax alternative to send data into the body method post only the value is sent, not the key data: "Country=Brasil&City=Belo Horizonte", timeout: 1000, withCredentials: false, adapter: function (config) { // Do whatever you want }, adapter: "xhr", auth: { username: "janedoe", password: "s00pers3cret" }, responseType: "json", responseEncoding: "utf8", xsrfCookieName: "XSRF-TOKEN", xsrfHeaderName: "X-XSRF-TOKEN", withXSRFToken: boolean | undefined | ((config: InternalAxiosRequestConfig) => boolean | undefined), onUploadProgress: function ({loaded, total, progress, bytes, estimated, rate, upload = true}) { // Do whatever you want with the Axios progress event }, onDownloadProgress: function ({loaded, total, progress, bytes, estimated, rate, download = true}) { // Do whatever you want with the Axios progress event }, maxContentLength: 2000, maxBodyLength: 2000, redact: ['authorization', 'password'], validateStatus: function (status) { return status >= 200 && status < 300; }, maxRedirects: 21, beforeRedirect: (options, { headers }) => { if (options.hostname === "typicode.com") { options.auth = "user:password"; } }, socketPath: null, allowedSocketPaths: null, transport: undefined, httpAgent: new http.Agent({ keepAlive: true }), httpsAgent: new https.Agent({ keepAlive: true }), proxy: { protocol: "https", host: "127.0.0.1", // hostname: "127.0.0.1" // Takes precedence over "host" if both are defined port: 9000, auth: { username: "mikeymike", password: "rapunz3l" } }, cancelToken: new CancelToken(function (cancel) { cancel("Operation has been canceled."); }), signal: new AbortController().signal, decompress: true, insecureHTTPParser: undefined, transitional: { silentJSONParsing: true, forcedJSONParsing: true, clarifyTimeoutError: false, advertiseZstdAcceptEncoding: false, legacyInterceptorReqResOrdering: true, }, env: { FormData: window?.FormData || global?.FormData }, formSerializer: { // Custom visitor function to serialize form values visitor: (value, key, path, helpers) => {}; // Use dots instead of brackets format dots: boolean; // Keep special endings like {} in parameter key metaTokens: boolean; // Use array indexes format: // null - no brackets // false - empty brackets // true - brackets with indexes indexes: boolean; // Maximum object nesting depth. Throws AxiosError (ERR_FORM_DATA_DEPTH_EXCEEDED) // if exceeded. Default: 100. Set to Infinity to disable. maxDepth: 100; }, maxRate: [ 100 * 1024, // 100KB/s upload limit, 100 * 1024 // 100KB/s download limit ] } ``` axios-axios-2d06f96/docs/pages/advanced/request-method-aliases.md000066400000000000000000000142031521272452000250230ustar00rootroot00000000000000# Request aliases axios provides a set of aliases for making HTTP requests. These aliases are shortcuts for making requests using the `request` method. The aliases are designed to be easy to use and to provide a more convenient way to make requests. axios endeavours to follow RFC 7231 and RFC 5789, as closely as possible. The aliases are designed to be consistent with the HTTP methods defined in these RFCs. ### `axios` axios can be used to make HTTP request by passing only the config object. The full config object is documented [here](/pages/advanced/request-config) ```ts axios(url: string | AxiosRequestConfig, config?: AxiosRequestConfig); ``` ## Method aliases The following aliases are available for making requests: ### `request` The `request` method is the main method that you will use to make HTTP requests. It takes a configuration object as an argument and returns a promise that resolves to the response object. The `request` method is a generic method that can be used to make any type of HTTP request. ```ts axios.request(config: AxiosRequestConfig): AxiosResponse; ``` ### `get` The `get` method is used to make a GET request. It takes a URL and an optional configuration object as arguments and returns a promise that resolves to the response object. ```ts axios.get(url: string, config?: AxiosRequestConfig): AxiosResponse; ``` ### `delete` The `delete` method is used to make a DELETE request. It takes a URL and an optional configuration object as arguments and returns a promise that resolves to the response object. ```ts axios.delete(url: string, config?: AxiosRequestConfig): AxiosResponse; ``` ### `head` The `head` method is used to make a HEAD request. It takes a URL and an optional configuration object as arguments and returns a promise that resolves to the response object. ```ts axios.head(url: string, config?: AxiosRequestConfig): AxiosResponse; ``` ### `options` The `options` method is used to make an OPTIONS request. It takes a URL and an optional configuration object as arguments and returns a promise that resolves to the response object. ```ts axios.options(url: string, config?: AxiosRequestConfig): AxiosResponse; ``` ### `post` The `post` method is used to make a POST request. It takes a URL, an optional data object, and an optional configuration object as arguments and returns a promise that resolves to the response object. ```ts axios.post(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ### `put` The `put` method is used to make a PUT request. It takes a URL, an optional data object, and an optional configuration object as arguments and returns a promise that resolves to the response object. ```ts axios.put(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ### `patch` The `patch` method is used to make a PATCH request. It takes a URL, an optional data object, and an optional configuration object as arguments and returns a promise that resolves to the response object. ```ts axios.patch(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ### `query` The `query` method is used to make a QUERY request, a safe and idempotent method that carries a body. It takes a URL, an optional data object, and an optional configuration object as arguments and returns a promise that resolves to the response object. Use it for read-style operations whose parameters are too complex or sensitive to fit in the URL. ```ts axios.query(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ```js // Send a complex search filter as a request body const { data } = await axios.query("/api/search", { selector: ["name", "email"], filter: { active: true, role: "admin" }, }); ``` ::: warning Draft specification The QUERY method is defined by an IETF [Internet-Draft](https://datatracker.ietf.org/doc/draft-ietf-httpbis-safe-method-w-body/) and has not yet been standardized. Semantics and the method name itself may change before final publication, and server, proxy, and CDN support is uneven. Verify your stack accepts `QUERY` end to end before relying on it in production. ::: ### `getUri` The `getUri` method returns the URL that would be sent for a given config without actually making the request. It applies `baseURL`, `paramsSerializer`, and `params`, so you get back the same string axios would put on the wire. Useful for building links, debugging serialization, or reusing the resolved URL in another request. ```ts axios.getUri(config?: AxiosRequestConfig): string; ``` ```js const url = axios.getUri({ url: "/users", baseURL: "https://api.example.com", params: { active: true, role: "admin" }, }); // "https://api.example.com/users?active=true&role=admin" ``` ::: tip Use `getUri` on an instance (`instance.getUri(config)`) to inherit the instance's `baseURL`, `params`, and `paramsSerializer` defaults. ::: ## Form data shorthand methods These methods are equivalent to their counterparts above, but preset `Content-Type` to `multipart/form-data`. They are the recommended way to upload files or submit HTML forms. ### `postForm` ```ts axios.postForm(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ```js // Upload a file from a browser file input await axios.postForm("/api/upload", { file: document.querySelector("#fileInput").files[0], description: "Profile photo", }); ``` ### `putForm` ```ts axios.putForm(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ```js // Replace a resource with form data await axios.putForm("/api/users/1/avatar", { avatar: document.querySelector("#avatarInput").files[0], }); ``` ### `patchForm` ```ts axios.patchForm(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ```js // Update specific fields using form data await axios.patchForm("/api/users/1", { displayName: "New Name", avatar: document.querySelector("#avatarInput").files[0], }); ``` ::: tip `postForm`, `putForm`, and `patchForm` accept all the same data types as their base methods — plain objects, `FormData`, `FileList`, and `HTMLFormElement`. See [File posting](/pages/advanced/file-posting) for more examples. ::: axios-axios-2d06f96/docs/pages/advanced/response-schema.md000066400000000000000000000037541521272452000235430ustar00rootroot00000000000000# Response schema Every axios request resolves to a response object with the following shape. The schema is consistent across both browser and Node.js environments. ```js { // The response data provided by the server. // When using `transformResponse`, this will be the result of the last transform. data: {}, // The HTTP status code from the server response (e.g. 200, 404, 500). status: 200, // The HTTP status message matching the status code (e.g. "OK", "Not Found"). statusText: "OK", // The response headers sent by the server. // Header names are lower-cased. You can access them using bracket or dot notation. headers: {}, // The axios config that was used for this request, including baseURL, // headers, timeout, params, and any other options you provided. config: {}, // The underlying request object. // In Node.js: the last `http.ClientRequest` instance (after any redirects). // In the browser: the `XMLHttpRequest` instance. request: {}, } ``` ## Accessing response fields In practice you will usually destructure just the parts you need: ```js const { data, status, headers } = await axios.get("/api/users/1"); console.log(status); // 200 console.log(headers["content-type"]); // "application/json; charset=utf-8" console.log(data); // { id: 1, name: "Jay", email: "jay@example.com" } ``` ## Checking the status code axios resolves the promise for any 2xx response and rejects for anything outside that range by default. You can customise this with the `validateStatus` config option: ```js const response = await axios.get("/api/resource", { validateStatus: (status) => status < 500, // resolve for anything below 500 }); ``` ## Accessing response headers All response header names are lower-cased, regardless of how the server sent them: ```js const response = await axios.get("/api/resource"); // These are equivalent const contentType = response.headers["content-type"]; const contentType2 = response.headers.get("content-type"); ``` axios-axios-2d06f96/docs/pages/advanced/retry.md000066400000000000000000000071201521272452000216030ustar00rootroot00000000000000# Retry and error recovery Network requests can fail for transient reasons — a server blip, a brief network drop, or a rate-limit response. Implementing a retry strategy in an interceptor lets you handle these failures transparently, without cluttering your application code. ## Basic retry with a response interceptor The simplest approach is to catch specific error status codes and immediately re-send the original request a limited number of times: ```js import axios from "axios"; const api = axios.create({ baseURL: "https://api.example.com" }); const MAX_RETRIES = 3; api.interceptors.response.use( (response) => response, async (error) => { const config = error.config; // Only retry on network errors or 5xx server errors const shouldRetry = !error.response || (error.response.status >= 500 && error.response.status < 600); if (!shouldRetry) { return Promise.reject(error); } config._retryCount = config._retryCount ?? 0; if (config._retryCount >= MAX_RETRIES) { return Promise.reject(error); } config._retryCount += 1; return api(config); } ); ``` ## Exponential backoff Retrying immediately after a failure can overload an already-struggling server. Exponential backoff waits progressively longer between each attempt: ```js const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); api.interceptors.response.use( (response) => response, async (error) => { const config = error.config; const shouldRetry = !error.response || (error.response.status >= 500 && error.response.status < 600); if (!shouldRetry) return Promise.reject(error); config._retryCount = config._retryCount ?? 0; if (config._retryCount >= 3) return Promise.reject(error); config._retryCount += 1; // Wait 200ms, 400ms, 800ms, ... before each retry const backoff = 100 * 2 ** config._retryCount; await delay(backoff); return api(config); } ); ``` ## Retrying on 429 (rate limit) with Retry-After When the server responds with `429 Too Many Requests`, it often includes a `Retry-After` header telling you exactly how long to wait: ```js api.interceptors.response.use( (response) => response, async (error) => { const config = error.config; if (error.response?.status !== 429) return Promise.reject(error); config._retryCount = config._retryCount ?? 0; if (config._retryCount >= 3) return Promise.reject(error); config._retryCount += 1; const retryAfterHeader = error.response.headers["retry-after"]; const waitMs = retryAfterHeader ? parseFloat(retryAfterHeader) * 1000 // header is in seconds : 1000; // default to 1 second await new Promise((resolve) => setTimeout(resolve, waitMs)); return api(config); } ); ``` ## Opting out of retries per request If some requests should never be retried (e.g. non-idempotent mutations you don't want to duplicate), add a flag to the request config: ```js // Add this to your interceptor before the retry logic: if (config._noRetry) return Promise.reject(error); // Then opt out on specific calls: await api.post("/payments/charge", body, { _noRetry: true }); ``` ## Combining retry with cancellation Use an `AbortController` to cancel a request that is waiting for a backoff delay: ```js const controller = new AbortController(); try { await api.get("/api/data", { signal: controller.signal }); } catch (error) { if (axios.isCancel(error)) { console.log("Request aborted by user"); } } // Cancel the request (and any pending retry delay) from elsewhere: controller.abort(); ``` axios-axios-2d06f96/docs/pages/advanced/testing.md000066400000000000000000000077101521272452000221200ustar00rootroot00000000000000# Testing Testing code that makes HTTP requests with axios is straightforward. The recommended approach is to mock axios itself so that your tests run without hitting a real network, giving you full control over what responses your code receives. ## Mocking with Vitest or Jest Both Vitest and Jest support module mocking with `vi.mock` / `jest.mock`. You can mock the entire axios module and control what each method returns: ```js // user-service.js import axios from "axios"; export async function getUser(id) { const { data } = await axios.get(`/api/users/${id}`); return data; } ``` ```js // user-service.test.js import { describe, it, expect, vi } from "vitest"; import axios from "axios"; import { getUser } from "./user-service"; vi.mock("axios"); describe("getUser", () => { it("returns user data on success", async () => { const mockUser = { id: 1, name: "Jay" }; // Make axios.get resolve with our fake response axios.get.mockResolvedValueOnce({ data: mockUser }); const result = await getUser(1); expect(result).toEqual(mockUser); expect(axios.get).toHaveBeenCalledWith("/api/users/1"); }); it("throws when the request fails", async () => { axios.get.mockRejectedValueOnce(new Error("Network error")); await expect(getUser(1)).rejects.toThrow("Network error"); }); }); ``` ## Mocking an AxiosError To test error-handling paths that inspect `error.response`, create an `AxiosError` instance directly: ```js import axios, { AxiosError } from "axios"; import { vi } from "vitest"; const mockError = new AxiosError( "Not Found", "ERR_BAD_REQUEST", {}, // config {}, // request { // response status: 404, statusText: "Not Found", data: { message: "User not found" }, headers: {}, config: {}, } ); axios.get.mockRejectedValueOnce(mockError); ``` ## Using axios-mock-adapter [axios-mock-adapter](https://github.com/ctimmerm/axios-mock-adapter) is a library that installs a custom adapter on your axios instance, intercepting requests at the adapter level. This means your interceptors still run, making it better for integration tests. ```bash npm install --save-dev axios-mock-adapter ``` ```js import axios from "axios"; import MockAdapter from "axios-mock-adapter"; const mock = new MockAdapter(axios); // Mock a GET request mock.onGet("/api/users/1").reply(200, { id: 1, name: "Jay" }); // Mock a POST request mock.onPost("/api/users").reply(201, { id: 2, name: "New User" }); // Mock a network error mock.onGet("/api/failing").networkError(); // Mock a timeout mock.onGet("/api/slow").timeout(); ``` Reset mocks between tests: ```js afterEach(() => { mock.reset(); // clear all registered handlers }); ``` ## Testing interceptors To test interceptors in isolation, create a fresh axios instance in your test: ```js import axios from "axios"; import MockAdapter from "axios-mock-adapter"; describe("auth interceptor", () => { it("attaches a Bearer token to every request", async () => { const instance = axios.create(); const mock = new MockAdapter(instance); // Add your interceptor instance.interceptors.request.use((config) => { config.headers.set("Authorization", "Bearer test-token"); return config; }); // Capture the request config by inspecting what mock received let capturedConfig; mock.onGet("/api/data").reply((config) => { capturedConfig = config; return [200, {}]; }); await instance.get("/api/data"); expect(capturedConfig.headers["Authorization"]).toBe("Bearer test-token"); }); }); ``` ## Tips - Always mock at the module level (or use `MockAdapter`) — avoid mocking individual methods on a shared instance, as state can leak between tests. - Use `mockResolvedValueOnce` / `mockRejectedValueOnce` in preference to `mockResolvedValue` so that tests are isolated and don't affect one another. - When testing retry logic, use `MockAdapter` so that the interceptor under test actually runs on each attempt. axios-axios-2d06f96/docs/pages/advanced/type-script.md000066400000000000000000000046761521272452000227360ustar00rootroot00000000000000# TypeScript `axios` ships TypeScript definitions in the npm package via `index.d.ts` (ESM) and `index.d.cts` (CJS), so type checking and editor support work out of the box for both module formats. ## Module resolution caveats Because axios dual-publishes with an ESM default export and a CJS `module.exports`, there are a few configuration caveats: - The recommended setting is `"moduleResolution": "node16"` (implied by `"module": "node16"`). This requires TypeScript 4.7 or greater. - If you use ESM, your settings should be fine. - If you compile TypeScript to CJS and you can't use `"moduleResolution": "node16"`, you must enable `esModuleInterop`. - If you use TypeScript to type-check CJS JavaScript code, your only option is `"moduleResolution": "node16"`. ## Type guards for axios errors Use the `axios.isAxiosError` type guard to safely narrow `unknown` errors in `catch` blocks. After narrowing, you can access axios-specific properties like `error.response`, `error.config`, and `error.code` with full type safety. ```ts import axios from "axios"; let user: User | null = null; try { const { data } = await axios.get("/user?ID=12345"); user = data.userDetails; } catch (error) { if (axios.isAxiosError(error)) { handleAxiosError(error); } else { handleUnexpectedError(error); } } ``` Use `axios.isCancel()` to narrow cancellation errors to `CanceledError`: ```ts const controller = new AbortController(); try { await axios.get("/user?ID=12345", { signal: controller.signal }); } catch (error) { if (axios.isCancel(error)) { handleCancellation(error); } } ``` ## Typed instances and interceptors Annotate the result of `axios.create` with `AxiosInstance`, and annotate request interceptors with `InternalAxiosRequestConfig` to get end-to-end type checking on a custom client: ```ts import axios, { AxiosInstance, InternalAxiosRequestConfig } from "axios"; const apiClient: AxiosInstance = axios.create({ baseURL: "https://api.example.com", timeout: 10000, }); apiClient.interceptors.request.use((config: InternalAxiosRequestConfig) => { // Add auth token, log, etc. return config; }); ``` ## Typing response data Axios request methods are generic over the response data type. Pass a type parameter to `axios.get` (and the other aliases) to type `response.data`: ```ts interface User { id: number; name: string; } const { data } = await apiClient.get("/users/1"); // `data` is typed as `User` ``` axios-axios-2d06f96/docs/pages/advanced/x-www-form-urlencoded-format.md000066400000000000000000000103401521272452000260760ustar00rootroot00000000000000# x-www-form-urlencoded format ## URLSearchParams By default, axios serializes JavaScript objects to `JSON`. To send data in the [`application/x-www-form-urlencoded` format](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) instead, you can use the [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) API, which is [supported](http://www.caniuse.com/#feat=urlsearchparams) in the vast majority of browsers, and [Node](https://nodejs.org/api/url.html#url_class_urlsearchparams) starting with v10 (released in 2018). ```js const params = new URLSearchParams({ foo: 'bar' }); params.append('extraparam', 'value'); axios.post('/foo', params); ``` ## Query string For older browsers or environments without `URLSearchParams`, you can use the [`qs`](https://github.com/ljharb/qs) library to serialize objects to the `application/x-www-form-urlencoded` format. ```js const qs = require('qs'); axios.post('/foo', qs.stringify({ bar: 123 })); ``` For full control over headers and method, pass `qs.stringify` output as the request `data` and set `Content-Type` explicitly: ```js import qs from 'qs'; const data = { bar: 123 }; const options = { method: 'POST', headers: { 'content-type': 'application/x-www-form-urlencoded' }, data: qs.stringify(data), url: '/foo', }; axios(options); ``` In very old versions of Node.js, you can use the built-in `querystring` module that ships with Node.js. Note that this module has been deprecated in Node.js v16 — prefer `URLSearchParams` or `qs` for new code. ```js const querystring = require('querystring'); axios.post('https://something.com/', querystring.stringify({ foo: 'bar' })); ``` ::: tip Prefer `qs` for nested objects The `qs` library is preferable if you need to stringify nested objects, as the `querystring` method has [known issues](https://github.com/nodejs/node-v0.x-archive/issues/1665) with that use case. ::: ## Automatic serialization to URLSearchParams Starting from v0.21.0, axios automatically serializes JavaScript objects to `URLSearchParams` if the `Content-Type` header is set to `application/x-www-form-urlencoded`. This means that you can pass a JavaScript object directly to the `data` property of the axios request config. For example when passing data to a `POST` request: ```js const data = { x: 1, arr: [1, 2, 3], arr2: [1, [2], 3], users: [ { name: 'Peter', surname: 'Griffin' }, { name: 'Thomas', surname: 'Anderson' }, ], }; await axios.postForm('https://postman-echo.com/post', data, { headers: { 'content-type': 'application/x-www-form-urlencoded' }, }); ``` The `data` object will be automatically serialized to `URLSearchParams` and sent in the `application/x-www-form-urlencoded` format. The server will receive the following data: ```json { "x": "1", "arr[]": ["1", "2", "3"], "arr2[0]": "1", "arr2[1][0]": "2", "arr2[2]": "3", "users[0][name]": "Peter", "users[0][surname]": "Griffin", "users[1][name]": "Thomas", "users[1][surname]": "Anderson" } ``` If your backend body-parser (like `body-parser` of `express.js`) supports nested objects decoding, you will get the same object on the server-side automatically ## Depth limit for params serialization When axios serializes a `params` object via `AxiosURLSearchParams`, the same recursive walker used by the FormData serializer is called. A `maxDepth` option (default `100`) limits how deeply it will recurse. Payloads exceeding the limit throw an `AxiosError` with `code: 'ERR_FORM_DATA_DEPTH_EXCEEDED'` instead of overflowing the call stack. ```js // Raise the limit if your params object legitimately nests deeper than 100 levels: axios.get('/api', { params: deepObject, paramsSerializer: { maxDepth: 200 } }); ``` ::: warning Security note Only raise `maxDepth` if your schema genuinely requires it. The default of 100 protects server-side code that forwards client-controlled data to axios as `params` from DoS attacks via deeply nested objects. ::: ```js var app = express(); app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies app.post('/', function (req, res, next) { // echo body as JSON res.send(JSON.stringify(req.body)); }); server = app.listen(3000); ``` axios-axios-2d06f96/docs/pages/getting-started/000077500000000000000000000000001521272452000214545ustar00rootroot00000000000000axios-axios-2d06f96/docs/pages/getting-started/examples/000077500000000000000000000000001521272452000232725ustar00rootroot00000000000000axios-axios-2d06f96/docs/pages/getting-started/examples/commonjs.md000066400000000000000000000102771521272452000254500ustar00rootroot00000000000000# JavaScript examples ## Importing the library To import the library in a CommonJS environment, you can use the `require` function, or the `import` statement if you are using a bundler like Webpack or Rollup. #### No bundler ```js const axios = require("axios"); ``` #### With bundler (webpack, rollup, vite, etc) ```js import axios from "axios"; ``` ## Using then/catch/finally Since axios returns a promise at it's core you can choose to use callbacks with `then`, `catch`, and `finally` to handle your response data, errors, and completion. ### Get request ```js axios .get("https://jsonplaceholder.typicode.com/posts", { params: { postId: 5, }, }) .then((response) => { console.log(response.data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Request completed"); }); ``` ### Post request ```js axios .post("https://jsonplaceholder.typicode.com/posts", { title: "foo", body: "bar", userId: 1, }) .then((response) => { console.log(response.data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Request completed"); }); ``` ### Put request ```js axios .put("https://jsonplaceholder.typicode.com/posts/1", { title: "foo", body: "bar", userId: 1, }) .then((response) => { console.log(response.data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Request completed"); }); ``` ### Patch request ```js axios .patch("https://jsonplaceholder.typicode.com/posts/1", { title: "foo", }) .then((response) => { console.log(response.data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Request completed"); }); ``` ### Delete request ```js axios .delete("https://jsonplaceholder.typicode.com/posts/1") .then((response) => { console.log(response.data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Request completed"); }); ``` ## Using async/await Another way to handle promises is by using `async` and `await`. This allows you to use try/catch/finally blocks to handle errors and completion. This can make your code more readable and easier to understand, this also helps prevents so called callback hell. ::: tip Note: async/await is part of ECMAScript 2017 and is not supported in Internet Explorer and older browsers, so use with caution. ::: ### Get request ```js const getPosts = async () => { try { const response = await axios.get( "https://jsonplaceholder.typicode.com/posts", { params: { postId: 5, }, } ); console.log(response.data); } catch (error) { console.error(error); } finally { console.log("Request completed"); } }; ``` ### Post request ```js const createPost = async () => { try { const response = await axios.post( "https://jsonplaceholder.typicode.com/posts", { title: "foo", body: "bar", userId: 1, } ); console.log(response.data); } catch (error) { console.error(error); } finally { console.log("Request completed"); } }; ``` ### Put request ```js const updatePost = async () => { try { const response = await axios.put( "https://jsonplaceholder.typicode.com/posts/1", { title: "foo", body: "bar", userId: 1, } ); console.log(response.data); } catch (error) { console.error(error); } finally { console.log("Request completed"); } }; ``` ### Patch request ```js const updatePost = async () => { try { const response = await axios.patch( "https://jsonplaceholder.typicode.com/posts/1", { title: "foo", } ); console.log(response.data); } catch (error) { console.error(error); } finally { console.log("Request completed"); } }; ``` ### Delete request ```js const deletePost = async () => { try { const response = await axios.delete( "https://jsonplaceholder.typicode.com/posts/1" ); console.log(response.data); } catch (error) { console.error(error); } finally { console.log("Request completed"); } }; ``` axios-axios-2d06f96/docs/pages/getting-started/examples/typescript.md000066400000000000000000000063641521272452000260330ustar00rootroot00000000000000# TypeScript example ## Importing types axios ships with TypeScript definitions out of the box. You can import the types you need directly from `"axios"`: ```ts import axios from "axios"; import type { AxiosRequestConfig, AxiosResponse, AxiosError } from "axios"; ``` ## Typing a request Use a generic type parameter on the response to tell TypeScript what shape your data will have: ```ts import axios from "axios"; type Post = { userId: number; id: number; title: string; body: string; }; const response = await axios.get("https://jsonplaceholder.typicode.com/posts/1"); console.log(response.data.title); // TypeScript knows this is a string ``` ## Typing a function Wrap requests in functions with explicit return types for maximum type safety: ```ts import axios, { AxiosResponse } from "axios"; type Post = { userId: number; id: number; title: string; body: string; }; const getPost = async (id: number): Promise => { const response = await axios.get( `https://jsonplaceholder.typicode.com/posts/${id}` ); return response.data; }; ``` ## Typing a POST request You can type both the request body and the expected response: ```ts type CreatePostBody = { title: string; body: string; userId: number; }; type CreatePostResponse = CreatePostBody & { id: number }; const createPost = async (data: CreatePostBody): Promise => { const response = await axios.post( "https://jsonplaceholder.typicode.com/posts", data ); return response.data; }; ``` ## Typed axios instance Create a typed instance so your base URL and headers are baked in: ```ts import axios from "axios"; import type { AxiosInstance } from "axios"; const api: AxiosInstance = axios.create({ baseURL: "https://api.example.com", timeout: 5000, }); ``` ## Typed interceptors Use `InternalAxiosRequestConfig` (not `AxiosRequestConfig`) for request interceptors in v1.x: ```ts import axios from "axios"; import type { InternalAxiosRequestConfig, AxiosResponse } from "axios"; api.interceptors.request.use((config: InternalAxiosRequestConfig) => { config.headers.set("Authorization", `Bearer ${getToken()}`); return config; }); api.interceptors.response.use( (response: AxiosResponse) => response, (error) => Promise.reject(error) ); ``` ## Typing errors Use `axios.isAxiosError()` to narrow the type of a caught error: ```ts import axios, { AxiosError } from "axios"; type ApiError = { message: string; code: number; }; try { await axios.get("/api/protected-resource"); } catch (error) { if (axios.isAxiosError(error)) { // error.response?.data is typed as ApiError console.error(error.response?.data.message); console.error(error.response?.status); } else { throw error; } } ``` ## TypeScript configuration notes Because axios dual-publishes ESM and CJS, there are a few caveats depending on your setup: - The recommended setting is `"moduleResolution": "node16"` (implied by `"module": "node16"`). This requires TypeScript 4.7 or greater. - If you compile TypeScript to CJS and cannot use `"moduleResolution": "node16"`, enable `"esModuleInterop": true`. - If you use TypeScript to type-check CJS JavaScript code, your only option is `"moduleResolution": "node16"`. axios-axios-2d06f96/docs/pages/getting-started/features.md000066400000000000000000000050021521272452000236110ustar00rootroot00000000000000# Features axios is a powerful HTTP client that provides a simple and easy-to-use API for making HTTP requests. It supports all modern browsers and is widely used in the JavaScript community. Here are some of the features that make axios a great choice for your next project. ## Isomorphic axios is a universal HTTP client that can be used in both the browser and Node.js. This means you can use axios to make API requests from your frontend code as well as your backend code. This makes axios a great choice for building progressive web apps, single-page applications, and server-side rendered applications. axios is also a great choice for teams that work on both frontend and backend code. By using axios for both frontend and backend code, you can have a consistent API for making HTTP requests, which can help reduce the complexity of your codebase. ## Fetch support axios provides first class support for the Fetch API, which is a modern replacement for the XHR API. The adapter is optional and can be used through configuration. The same API is maintained for both the XHR and Fetch adapters, which makes it easy to adopt the Fetch API in your codebase without changing your existing code. ## Browser support axios supports all modern and select older browsers, including Chrome, Firefox, Safari, and Edge. axios is a great choice for building web applications that need to support a wide range of browsers. ## Node.js support axios also supports a wide range Node.js versions with tested compatibility as far back as v12.x, making it a good choice in environments where upgrading to the latest Node.js version might not be possible or practical. In addition to Node.js, axios has Bun and Deno smoke tests that validate key runtime behavior and improve confidence in cross-runtime compatibility. ## Additional features - Supports the Promise API - Intercept request and response - Transform request and response data - Abort controller - Timeouts - Query parameters serialization with support for nested entries - Automatic request body serialization to: - JSON (application/json) - Multipart / FormData (multipart/form-data) - URL encoded form (application/x-www-form-urlencoded) - Posting HTML forms as JSON - Automatic JSON data handling in response - Progress capturing for browsers and node.js with extra info (speed rate, remaining time) - Setting bandwidth limits for node.js - Compatible with spec-compliant FormData and Blob (including node.js) - Client side support for protecting against XSRF axios-axios-2d06f96/docs/pages/getting-started/first-steps.md000066400000000000000000000073751521272452000242750ustar00rootroot00000000000000# First steps Welcome to the axios documentation! This guide will help you get started with axios and make your first API request. If you're new to axios, we recommend starting here. ## Installing You can use axios in your project in a few different ways. The most common way is to install it from npm and include it in your project. But we also support jsDelivr, unpkg, and more. #### Using npm ```bash npm install axios ``` #### Using pnpm ```bash pnpm install axios ``` #### Using yarn ```bash yarn add axios ``` #### Using bun ```bash bun add axios ``` #### Using deno ```bash deno install npm:axios ``` #### Using jsDelivr When using jsDelivr we recommend using the minified version as well as pinning the version number to avoid unexpected changes. If you would like to use the latest version you can do so by dropping the version number. This is strongly discouraged for production use as it can lead to unexpected changes in your application. ```html ``` #### Using unpkg When using unpkg we recommend using the minified version as well as pinning the version number to avoid unexpected changes. If you would like to use the latest version you can do so by dropping the version number. This is strongly discouraged for production use as it can lead to unexpected changes in your application. ```html ``` ## Importing axios Once installed, you can import the library using either `import` or `require`: ```js import axios, { isCancel, AxiosError } from "axios"; ``` You can also use the default export, since the named export is just a re-export from the axios factory: ```js import axios from "axios"; console.log(axios.isCancel("something")); ``` If you use `require` for importing, **only the default export is available**: ```js const axios = require("axios"); console.log(axios.isCancel("something")); ``` For some bundlers and ES6 linters you may need: ```js import { default as axios } from "axios"; ``` For custom or legacy environments where module resolution misbehaves, you can import the prebuilt bundle directly: ```js const axios = require("axios/dist/browser/axios.cjs"); // browser CommonJS bundle (ES2017) // const axios = require("axios/dist/node/axios.cjs"); // node CommonJS bundle (ES2017) ``` ## Making your first request An axios request can be made in as few as two lines of code. Making your first request with axios is very simple. You can make a request to any API by providing the URL and method. For example, to make a GET request to the JSONPlaceholder API, you can use the following code: ```js import axios from "axios"; const response = await axios.get( "https://jsonplaceholder.typicode.com/posts/1" ); console.log(response.data); ``` axios provides a simple API for making requests. You can use the `axios.get` method to make a GET request, the `axios.post` method to make a POST request, and so on. You can also use the `axios.request` method to make a request with any method. ::: tip Set a timeout in production Without a `timeout`, a stalled request can hang indefinitely. Pass one via the request config: ```js const response = await axios.get("https://example.com/data", { timeout: 5000, // 5 seconds }); ``` See [`timeout` in the request config](/pages/advanced/request-config#timeout) and [Error handling](/pages/advanced/error-handling) for the matching `ECONNABORTED` / `ETIMEDOUT` codes. ::: ## Next steps Now that you've made your first request with axios, you're ready to start exploring the rest of the axios documentation. You can learn more about making requests, handling responses, and using axios in your projects. Check out the rest of the documentation to learn more. axios-axios-2d06f96/docs/pages/getting-started/upgrade-guide.md000066400000000000000000000076761521272452000245400ustar00rootroot00000000000000# Upgrade guide This guide is intended to help you upgrade your project from one version of the framework to another. It is recommended to read the release notes for each major version you are upgrading from/to, as they may contain important information about breaking changes. ## Upgrading from v0.x to v1.x ### Changes to the import statement In v1.x, the import statement has been changed to use the `default` export. This means that you will need to update your import statements to use the `default` export. ```diff - import { axios } from "axios"; + import axios from "axios"; ``` ### Changes to the interceptor system In v1.x you need to leverage the type `InternalAxiosRequestConfig` to type the `config` parameter in the `request` interceptor. This is because the `config` parameter is now typed as `InternalAxiosRequestConfig` instead of the public `AxiosRequestConfig` type. ```diff - axios.interceptors.request.use((config: AxiosRequestConfig) => { + axios.interceptors.request.use((config: InternalAxiosRequestConfig) => { return config; }); ``` ### Changes to request headers shape In v1.x, the shape of the request headers has been changed to drop the `common` property. This means that you will need to update your code to use the new shape of the request headers as follows: ```diff - if (request.headers?.common?.Authorization) { - request.headers.common.Authorization = ... + if (request.headers?.Authorization) { + request.headers.Authorization = ... ``` Default headers that were previously under `common`, `get`, `post`, etc. are now set directly on `axios.defaults.headers`: ```diff - axios.defaults.headers.common["Accept"] = "application/json"; + axios.defaults.headers["Accept"] = "application/json"; ``` ### Multipart form data If a request includes a `FormData` payload, the `Content-Type: multipart/form-data` header is now set automatically. Remove any manual header to avoid duplicates: ```diff - axios.post("/upload", formData, { - headers: { "Content-Type": "multipart/form-data" }, - }); + axios.post("/upload", formData); ``` If you explicitly set `Content-Type: application/json`, axios will now automatically serialize the data to JSON. ### Parameter serialization v1.x introduced several breaking changes to how URL parameters are serialized. The most important ones: **`params` are now percent-encoded by default.** If your backend expected raw brackets from qs-style encoding, you may need to configure a custom serializer: ```js import qs from 'qs'; axios.create({ paramsSerializer: { serialize: (params) => qs.stringify(params, { arrayFormat: 'brackets' }), }, }); ``` **Nested objects in `params` are now serialized with bracket notation** (`foo[bar]=1`) rather than dot notation. If your backend expected dot notation, use a custom serializer. **`null` and `undefined` params** are now handled consistently: `null` values are serialized as empty strings, while `undefined` values are omitted entirely. For the full parameter serialization config options, see the [Request config](/pages/advanced/request-config) page. ### Internals no longer exported We have elected to no longer export the internals of axios. This means that you will need to update your code to only use the public API of axios. This change was made to simplify the API and reduce the surface area of axios, allowing us to make changes to the internals without declaring them as breaking changes. Please review the [API reference](/pages/advanced/api-reference) on this site for the latest information on the public API of axios. ### Request config We have made changes to the request config object. Please review the [config reference](/pages/advanced/request-config) on this site for the latest information. ### Missed breaking changes This guide is not exhaustive and may not cover all breaking changes. Should you encounter any issue, please open an issue on the [docs GitHub repository](https://github.com/axios/docs) with the label `breaking change`. axios-axios-2d06f96/docs/pages/misc/000077500000000000000000000000001521272452000173025ustar00rootroot00000000000000axios-axios-2d06f96/docs/pages/misc/security.md000066400000000000000000000235571521272452000215070ustar00rootroot00000000000000# Security policy ## ⚠️ Decompression bomb / unbounded response buffering By default, `maxContentLength` and `maxBodyLength` are set to `-1` (unlimited). A malicious or compromised server can return a small gzip/deflate/brotli/zstd-compressed body that expands to gigabytes, exhausting memory in the Node.js process. **If you make requests to servers you do not fully trust, you MUST set a `maxContentLength` (and `maxBodyLength`) suitable for your workload.** The limit is enforced chunk-by-chunk during streaming decompression, so setting it is sufficient to neutralize decompression-bomb attacks. ```js axios.get('https://example.com/data', { maxContentLength: 10 * 1024 * 1024, // 10 MB maxBodyLength: 10 * 1024 * 1024, }); // Or globally: axios.defaults.maxContentLength = 10 * 1024 * 1024; axios.defaults.maxBodyLength = 10 * 1024 * 1024; ``` The default was not tightened because doing so would silently break every legitimate download larger than the chosen cap. The responsibility to pick a safe ceiling for untrusted sources rests with the application. ## Other security-sensitive options The following request-config options have direct security implications. They are documented in full alongside the rest of the [request config](/pages/advanced/request-config), and summarised here so they show up in one place. | Option | Risk | Mitigation | | --- | --- | --- | | [`socketPath`](/pages/advanced/request-config#socketpath) | If derived from untrusted input, an attacker can redirect traffic to privileged local sockets like `/var/run/docker.sock`, bypassing hostname-based SSRF protections (CWE-918). | Strip or allowlist config keys from untrusted input. Use [`allowedSocketPaths`](/pages/advanced/request-config#allowedsocketpaths) to restrict accepted socket paths. | | [`beforeRedirect`](/pages/advanced/request-config#beforeredirect) | Runs after `follow-redirects` strips credentials on protocol downgrade. Re-injecting credentials without checking the destination protocol can leak them over plain HTTP. | Only re-add credentials for trusted HTTPS destinations. Check `options.protocol === "https:"` before assigning `auth`. | | [`withXSRFToken`](/pages/advanced/request-config#withxsrftoken) | Setting `true` forces the XSRF header on cross-origin requests. Older axios versions implicitly enabled this with `withCredentials: true`; newer versions require both flags. | Leave at `undefined` (same-origin only) unless your backend explicitly validates XSRF on cross-origin requests. | | [`redact`](/pages/advanced/request-config#redact) | `AxiosError#toJSON()` includes the request config by default, which can leak `Authorization` headers or `auth` credentials into error logs and telemetry. | Pass a `redact` array with sensitive config key names. Matching is case-insensitive and recursive. | | [`formDataHeaderPolicy`](/pages/advanced/request-config#formdataheaderpolicy) | A custom `FormData` whose `getHeaders()` returns attacker-controlled values can overwrite headers like `Authorization` or inject arbitrary ones in Node.js. | Set `'content-only'` to copy only `Content-Type` and `Content-Length`, then set other headers explicitly via the request `headers` config. | ## Supply-chain hardening: `ignore-scripts` and lifecycle scripts The repository ships a project-level `.npmrc` that sets `ignore-scripts=true`. This blocks npm lifecycle scripts (`preinstall`, `install`, `postinstall`, `prepare`) from any direct or transitive dependency when running `npm install` or `npm ci` inside the repo. See [THREATMODEL.md](https://github.com/axios/axios/blob/v1.x/THREATMODEL.md) (threat T-S2) for the rationale. One consequence: the repository's own `prepare` hook (which installs Husky's git hooks) does **not** run automatically. After your first install, enable the git hooks manually: ```bash npm ci npm rebuild husky && npx husky ``` Run those two commands once per fresh checkout. You do **not** need to re-run them after every subsequent `npm install`. ::: danger Do not remove `ignore-scripts=true` Removing `ignore-scripts=true` from `.npmrc` to "fix" the husky setup re-opens the lifecycle-script attack surface for every other package in the tree. All CI workflows already invoke npm with `--ignore-scripts`, so local behaviour matches CI. ::: We recommend the same `ignore-scripts=true` setting in any consumer project that pulls axios (or any other dependency) into a build environment that handles secrets. ## Verifying a Release Every `axios` tarball on npm is published from GitHub Actions with an [npm provenance attestation](https://docs.npmjs.com/generating-provenance-statements) that cryptographically binds the package to the workflow and commit SHA that produced it. Consumers can verify provenance locally: ```bash # Verify every package in your lockfile, including axios npm audit signatures ``` A successful verification proves the tarball was built in `axios/axios`' GitHub Actions environment on a known commit — it was not tampered with between build and registry. It does **not** prove the code in that commit is free of bugs. If `npm audit signatures` reports a missing or invalid attestation for a recent `axios` version, treat it as a potential supply-chain incident and report via the private channel below. ## Reporting a Vulnerability If you believe you have found a security vulnerability in the project, please report it to us as described below. We take all security vulnerabilities seriously. If you have found a vulnerability in a third-party library, please report it to the maintainers of that library. ## Reporting Process Please do not report security vulnerabilities through public GitHub issues. Please use the official security channel on GitHub by logging a [security advisory](https://github.com/axios/axios/security/advisories/new). ## Disclosure Policy When we receive a security vulnerability report, we assign it a primary handler. The handler confirms the problem, determines affected versions, evaluates severity, develops and ships a fix, and coordinates public disclosure with the reporter. ### 60-day resolution and disclosure commitment We commit to **resolving and publicly disclosing every valid security advisory within 60 calendar days of the initial report**, measured from the moment a report is received via the [GitHub security advisory channel](https://github.com/axios/axios/security/advisories/new). The 60-day clock is a commitment to reporters and downstream consumers — a backstop, not an aspiration. If we cannot ship a fix in time, we still publish the advisory at day 60 with the best available mitigation guidance so consumers can act. **Milestones inside the 60-day window:** | Day | Milestone | | ---- | ---------------------------------------------------------------------------------------------------------------------------------------- | | 0 | Report received. Private advisory opened on GitHub. | | ≤ 3 | Acknowledgement sent to reporter. Triage decision: in scope / out of scope / duplicate / needs-info. | | ≤ 10 | Severity assessed (CVSS v4 where applicable). Affected versions confirmed. CVE requested via GitHub if a public identifier is warranted. | | ≤ 45 | Fix developed, reviewed, tested. Release candidate prepared on a private branch. Reporter offered a preview for validation. | | ≤ 60 | Patched release published to npm. Public advisory + CVE published. Reporter credited unless they request otherwise. CHANGELOG updated. | **Exceptions and extensions.** - If a reporter requests a shorter embargo (e.g. they plan to present findings at a conference), we accommodate where possible. - If a fix requires a breaking change, coordinating with major downstream consumers, or a `follow-redirects` / `form-data` / `proxy-from-env` upstream release, we may extend beyond 60 days. Any extension is disclosed publicly at day 60 via the advisory, with a revised ETA and the reason. - If a report is **out of scope** (e.g. falls under an explicit non-goal documented in the project's [threat model](https://github.com/axios/axios/blob/v1.x/THREATMODEL.md)), we close it with an explanation to the reporter within the triage window (≤ 3 days). Out-of-scope reports do not enter the 60-day queue. - **Actively exploited vulnerabilities** are treated as incidents: fix and advisory ship as soon as a patch is validated, not on the 60-day schedule. **Reporter expectations.** While a report is under embargo, we ask reporters to refrain from public disclosure until the earlier of: (a) the coordinated advisory publication, or (b) day 60. If the 60-day deadline passes without action from us, reporters are free to disclose independently — we will treat that as a failure on our part, not on theirs. ## Security Updates Security updates are released as soon as possible after the patch has been developed and tested. We notify users of the release via the project's GitHub repository and publish release notes and security advisories on the GitHub releases page. We also deprecate all versions that contain the vulnerability. ## Maintainer-side incident response For compromise scenarios affecting maintainer accounts, workstations, or release infrastructure (phishing, stolen hardware key, unexpected tag/publish), the project maintains an internal incident-response runbook in [THREATMODEL.md §3.7](https://github.com/axios/axios/blob/v1.x/THREATMODEL.md#37-incident-response-runbook). It covers session revocation, key rotation, downstream notification, and unpublish/deprecate procedures. ## Security Partners and Acknowledgements We would like to thank the following security researchers for working with us to help make the project safe for everyone: - [Socket Dev](https://socket.dev/) - [GitHub Security Lab](https://securitylab.github.com/) axios-axios-2d06f96/docs/pages/misc/semver.md000066400000000000000000000045051521272452000211310ustar00rootroot00000000000000# Semantic versioning Semantic versioning is a versioning scheme that is used to communicate the nature of changes in a software package. It is a simple set of rules and requirements that dictate how version numbers are assigned and incremented. ## axios versioning axios follows the semantic versioning scheme. This means that each version of axios is assigned a version number that consists of three parts: major, minor, and patch. The version number is incremented based on the nature of the changes in the release. In the past axios may have at times not strictly followed semantic versioning, however going forward there will be a much stricter adherence to the semantic versioning scheme to ensure that users can rely on the version numbers to communicate the nature of changes in the library. A brief overview of the versioning scheme is provided below. ## Version format A semantic version number consists of three parts: 1. Major version 2. Minor version 3. Patch version The version number is written as `MAJOR.MINOR.PATCH`. Each part of the version number has a specific meaning: - **Major version**: Incremented when you make incompatible API changes. - **Minor version**: Incremented when you add functionality in a backwards-compatible manner. - **Patch version**: Incremented when you make backwards-compatible bug fixes. ## Pre-release versions In addition to the three parts of the version number, you can append a pre-release version. This is done by adding a hyphen and a series of dot-separated identifiers immediately following the patch version. For example, `1.0.0-alpha.1`. Pre-release versions are used to indicate that a version is unstable and might not satisfy the intended compatibility requirements as denoted by the version number. Pre-release versions are ordered based on the order of the identifiers. For example, `1.0.0-alpha.1` comes before `1.0.0-alpha.2`. ## Version ranges When you specify a version range for a package, you can use a variety of operators to specify the range of versions that are acceptable. The following operators are available: - `>`: Greater than - `<`: Less than - `>=`: Greater than or equal to - `<=`: Less than or equal to - `~`: Approximately equal to - `^`: Compatible with For example, `^1.0.0` means that any version greater than or equal to `1.0.0` and less than `2.0.0` is acceptable. axios-axios-2d06f96/docs/pages/misc/sponsors.md000066400000000000000000000115321521272452000215140ustar00rootroot00000000000000--- layout: page ---

Sponsors

Axios is supported by the following organizations. If you'd like to sponsor Axios, please see our open collective page for more information.

{{ capitalizeFirstLetter(sponsor.tier) }}
{{ sponsor.name }}
axios-axios-2d06f96/docs/patches/000077500000000000000000000000001521272452000166775ustar00rootroot00000000000000axios-axios-2d06f96/docs/patches/@splidejs+splide+4.1.4.patch000066400000000000000000000010631521272452000235510ustar00rootroot00000000000000diff --git a/node_modules/@splidejs/splide/package.json b/node_modules/@splidejs/splide/package.json index 677e6d0..d274e39 100644 --- a/node_modules/@splidejs/splide/package.json +++ b/node_modules/@splidejs/splide/package.json @@ -4,6 +4,7 @@ "description": "Splide is a lightweight, flexible and accessible slider/carousel. No dependencies, no Lighthouse errors.", "author": "Naotoshi Fujita", "license": "MIT", + "type": "module", "main": "dist/js/splide.cjs.js", "module": "dist/js/splide.esm.js", "types": "dist/types/index.d.ts", axios-axios-2d06f96/docs/public/000077500000000000000000000000001521272452000165265ustar00rootroot00000000000000axios-axios-2d06f96/docs/public/android-chrome-192x192.png000066400000000000000000000057721521272452000230770ustar00rootroot00000000000000PNG  IHDRRlsRGB IDATx^mlgsN{`LJ\[&Q5?%m",9Pcd,脘9&/H|ٲ PHKW%̭sK 鹞s~mO & G'P^ P)@(@w h yx ;4 t<<~M]?Ox&@AASށ P)@(@w h yx ;4 t<<~M]?Ox&@AMX\:zfU mۿMx7[nHޥ{?,QP&\kVC 6~ H ŧ*MIR$ gtc  Aq.7EU̶!L85zTpܺlhqTzX!+!5 8h驭 5D_WCi7HJ{KscsSC,Q`VuN T' JT(? ,*^mn PP6IxNP0s"((0A D) `$J EP<'Q `(9RCIxNP0s"((0A D) `$J EP<'Q `(9RCIxNP0s"((0A D) `$J EP<'Q `(9RCIxNP0s"((0A D) `$J EP<'Q `(9RCIxNP0s"((0A D) `$J EP<'Q `("{!EE DӜ\ЌF!8g8¥Qcy5G19OD 9KEBtc Ӛ:.$ho߂Mڦ/O<8ĀiP] pM؀P_ CJio_oȫ=LB@Qq>ѧMl [ ?:ñUl"N GvQ `9bc޿#Eqeju.G!V Tq`G!<~t>J ;o3R&L7O ݇Q"Q `șF_>w_-|'a !J dw~p?ٝj`.@ضKj8JQ `>K8}sFe٭D P;;d&4мEݿ_-C/b<{ްuF_#@ W*dWԢ>cF)@UDh#"R(}Ca(5.ݷ-CMF)l(? $=}mO$(zWyK.C߄M>k'Q$TyP=(?0.ܾec1Hi!i p m5+1lф(@BP-a+HxNP0s"((0A D) `$J EP<'Q `("G54,h(h"P|u'NYrց0@*`=c{ܰu"@ `'@˗x}}`( dG!.6*J +0F~FE)EA"$?3Lh P8<3,J t ]E>koypiZB̌ #\ "# #\ "# #\ "# #\ "# #\ "# #\ "# #\ "# #\ "# #\ "# #\ "# #\ "# #\ "# #\ "# #\ "# #\ "# #\ "# #\ Hj6IENDB`axios-axios-2d06f96/docs/public/android-chrome-512x512.png000066400000000000000000000225421521272452000230610ustar00rootroot00000000000000PNG  IHDRxsRGB IDATx^TǙ+XxcA6#8oKǖ OO`בAd&fNQxDpt]Uo>]]*} @tt'v` @`.H( ݑ  @p @@BpL;@ Cwd  P@$# @ @ w$  @@ @ H8tG&@ @ @¡;2H( ݑ  @p @@BpL;@ Cwd  P@$# @ @ w$  @@ @ H8tG&@ @ @¡;2H( ݑ  @p @@BpL;@ Cwd  P@$# @ @ w$  @@ @ H8tG&@ @ @¡;2H( ݑ  @p @@BpL;@ Cwd  P@$# @ @ w$  @@ @ H8tG&@ @ @¡;2H( ݑ  @p @@BpL;@ Cwd  P@$# @ @ w$  @@ @ H8tG&@ @ @¡;2H( ݑ  @p @@BpL;@ Cwd qOVͯu&m@:Q>h3ӛ;`I;!!}7&po>4~%!PG@q* >֫4MXqc[O}2Oӭ}nU @`7~7Oދl$8H4lG%ВWsڞӄs |-~}izd Pr3 @`KͿϫ_+]BJy2l!~OΟWoG$ G{K_lJ@X$p_+](e` (xK} >m|t#O @?{K}, m|t#O P MgV_<^( E` x6TRJy2<'> m|t#O ٣mz_)(e` x.lP@Ʃ;3-"z_@,˼!#ЈhdA H@AZ` ;_6mK`K%hT@4:"Кhm"C`7OH# ҌA$vL ]}@[y f@1[ |@>oN<{NG L@QZ@1@3CK-H, чCա |oj[Ե6 F^_ km7>ynmŪ{ac&?&Nhq7?wo5Mr<0@EPjܸ姫s $0wN6pVW)"E`|0spyn(A>= =:K6?2Z~}iB9 @^{?G̶t& :ؼg=,9D˳w@cϿg- K&hy8>O/q<󵨯Q!C@䘳S6$_>O 5o=>ޮ?1 t& :+}V,, PY/9yn*PSԉX|vݶU {xϒ %Z%@@*l~?ַkaWmWT% , F`_n>O 5o(~OΟ/uk`WA'K@䚷Vr%KO 5o-ÏΡ_Sg %Z%@@^h>K#hy>O/q<Q@Sg |v <\ ׼%G{=e7K-'} %Z%@@)Ze>B*r \viZe>G*r \N^d``g @~ 4WA F./P*r \Nw{rܽ~Ϯ <\ ׼Sv,XY;0pq/Y2D˳w`8^Ϯ <\ ׼>/Y20D˳w`Q_d8`g @2]!vy@yw_d``g @^d8`g @w~  88(/_*0/Yj`WA'K@wקÏN,XY;Ѕ@֗,XY;д>O/q<7@C m~Ϯ <\ ׼9,Xn2 o~޿`vn>E :ϝ:% rͻzZ@&iڍ}b#bB 2F FYZ@aʍ/n|?{izu%lAA}_}CčV9xoj 3|୓UFp XPi5w@V# @,$ ba@w@% +b=F@* XXi5 PI@ XOJ VzZpT j;@V# @,$ ba@w@% +b=F@* XXi5 PI@ XOJ VzZpT j;@V# @,$ ba@w@% +b=F@* XXi5 PI@ XOJ VzZpT j;@V# @,$ ba@w@% +b=F@* XXi5 PI@ XOJ VzZpT j;@V# @,$ ba@w@% +b=F@* XXi5 PI@ XOJ VzZpT j;@V# @,$ ba@w@% +b=F@* XXi5 PI@ XOJ VzZpT j;@V# @,$ ba@w@% +b=F@* XXi5 PI@ XOJ VzZpT j;@V# @,$ ba@w@% +b=F@* XXi5 PI@ XOJ VzZpT j;@V# @,$ ba@w@% +b=F@* XXi5 PI@ XOJ VzZpT j;@V# @,$ ba@w@% +b=F@* XXi5 PI@ XOJ VzZpT j;@V# @,$ ba@w@% +b=F@* XXi5 PI@ XOJ VzZpT j;@V# @,$ ba@w@% +b=F@* XXi5 PI@ XOJ VzZpT j;@V# @,$ ba@w@% +b=F@* XXi5 PI@ XOJ VzZpT j;@V# @,$ ba@w@% {4OQmvw>c[vXa @ V@z]595D{vy>wsu , A\n/\z9R'Af?Yh'ozɁx& \ tV[Q@F@9Vwt~` rwyG`u ϠLo/~Оl3".7k_Lm`Ȏ__6}ڜ]=/  ܧ%ޮH<|G# 긶>!{Q@@0hyOs@ X@6|W:isvE``޾-hq^T}@PܧyM;Y Anj=_ؑ]hK@5@@41Dد1D[c[ӛOyt~- co] }{M~7/ 4& >op0)qM~M fDK) ƜSP@rƾa|0pԳr>oN\Y@Trj( 2Nݙ xo{^okż 일EG`#  t<}wĬh`>!!jvzn~>MT@Jy@(zciǿ?-o{C$P* J%J!PS@ԵvJM~)g bK} Who~}O ! ƘS4$ s^`^|,G H@AZ/๻>AYhlW0Mwyso '|{[ ,|k2>|W:qMh[@=P oxOՖ w:}%) jZ;@az>)Cw. :'(&(T$P&#V|wx@k/:p \}xk׏'X}s29@ι;uEP 0J pA@0%{J@t5.%V@dK@Դ?pD@t2(GgVvJ <}g" Z` j9 @Ô+ոl@Zv^K@Ԓ. RZ-wN@'~~fe2 w* E # z=L]f iG@-Y ) "5EpD@t2(GgVvJ <}g" Z` j9մ㟾{} R)({O~{v~#ЍfT6ڋ@^?{qOm:~=e 'd Dy.މ߉  j , ?r r+O(( M̧CTP-[7 ! ژ] $c?hIDAT؎BclMW9."V@x1yy:{k[m6j>C5~|mǕ!@5D{_Z@ =^;W̼>N% @`u P" JԤlcQ覫DdS쐩>lbJ,āۚMy$ Dy[RM!Sh$ rKdՙ(tm)tmf?Nȇ/܀B׆B+m&iELHR)tm)tm2K]奖 F%/2 @?C 9P `?ЊEȣ"r_QR(t[%"=VY ?ZM롖 }DZSI^dVO)4/K (Ϙ\(f (׷cs7R)"W׏o:kkW]|t>!"]8*}Gk|BЪ?u侻5'+F`-$qddբQhΖd.MΒx~0^-l_(́W+E`+MɎtqǮẀ׉6FjSh[T =ۦ^%mB_SMko8^#+n&Ul2xQhE/Iͧ_qb<=0UXcm`VԶN /W/BWg~"*/i7=c1>FA< m*2]{wk jQOW8|;;MB*xJ:~#"x4!@A<&ya,e9:\W~#q[p$*}20Vp!Ϣ~/jQϔ-*j R/R=)&D9DR#iLc=V2^ ykDs Ŀ*0Ca{}K|PZiM6,flAgm}"S'9v @W[,=c?$%G;]dܥ ,0%X,QlAY\׹QP/j%쩀@ (+ 2!hIENDB`axios-axios-2d06f96/docs/public/favicon.ico000066400000000000000000000360561521272452000206610ustar00rootroot00000000000000 h6  (00 h&(  .] *\V+Zq*\V*[+[e&Y*\V*[*[*Z([-*\V*[*[)\+]M*\V*[*[*[I*\V*[*[*[I,Y.)[v*[*[*[I)\K)Z*[*[*[I-Y()Zq*[*[I)Z*[I*U ( @ *[**[*[3f*[)Z*Z0*[)Z*Z0,^.)W,*[)Z*Z0*\H)[*\N*[)Z*Z0*\H)Z)Z*Zz*[)Z*Z0*\H)Z)Z)Z)Z3f *[)Z*Z0*\H)Z)[)[)[*\UU*[)Z*Z0*\H)Z*[*[)Z*Z0*\H)Z*[*[)Z*Z0*\H)Z*[*[)Z*Z0*\H)Z*[*[)Z*Z0*\H)Z*[*[)Z*Z0*\H)Z*[UU*\V*Z`*Z`)Z)Z*Z0*\H)Z*[)\2)[)Z)Z)Z*Z0*\H)Z*[,Y*[)Z)Z*Z0*\H)Z*[*U*Z)Z*Z0*\H)Z*[)[j*Y+*\H)Z*[*\H)Z*[,Y)[*[,^.(0` (` *[I.],*Z)[*U.],*Z)Z*[3M .],*Z)Z*Z0`.],*Z)Z*Z0`3f )W,*U.],*Z)Z*Z0`*`*[)[{.] .],*Z)Z*Z0`*`)[)Z*Z,Y.],*Z)Z*Z0`*`)[)Z)Z)Z&Y(.],*Z)Z*Z0`*`)[)Z)Z)Z*Z*\N@.],*Z)Z*Z0`*`)[)Z)Z)Z)Z)Z)[k3f.],*Z)Z*Z0`*`)[)Z)Z)[)Z)Z)Z,Zc.],*Z)Z*Z0`*`)[)Z)Z*]B,]4,]4,]4.\2@.],*Z)Z*Z0`*`)[)Z)Z*c.],*Z)Z*Z0`*`)[)Z)Z*c.],*Z)Z*Z0`*`)[)Z)Z*c.],*Z)Z*Z0`*`)[)Z)Z*c.],*Z)Z*Z0`*`)[)Z)Z*c.],*Z)Z*Z0`*`)[)Z)Z*c.],*Z)Z*Z0`*`)[)Z)Z*c.],*Z)Z*Z0`*`)[)Z)Z*c.],*Z)Z*Z0`*`)[)Z)Z*c$m*[*[*[*[*Z)Z)Z*Z0`*`)[)Z)Z*c*\$)Z)Z)Z)Z)Z)Z*Z0`*`)[)Z)Z*c,W#)Z*Z)Z)Z)Z*Z0`*`)[)Z)Z*c'b *Zl)Z)Z)Z*Z0`*`)[)Z)Z*cUU*Y\)Z)Z*Z0`*`)[)Z)Z*c+ZA)Z)[0`*`)[)Z)Z*c)Z+ZX'b *`)[)Z)Z*c*`)[)Z)Z*c&Y)[)Z)Z*cU)\2)Z)Z*c*U)]k3Uaxios-axios-2d06f96/docs/public/logo-light.svg000066400000000000000000000305441521272452000213220ustar00rootroot00000000000000 axios-axios-2d06f96/docs/public/logo.svg000066400000000000000000000305441521272452000202150ustar00rootroot00000000000000 axios-axios-2d06f96/docs/public/site.webmanifest000066400000000000000000000006151521272452000217220ustar00rootroot00000000000000{ "name": "axios | promise based HTTP client", "short_name": "axios", "icons": [ { "src": "/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png" }, { "src": "/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png" } ], "theme_color": "#552cdb", "background_color": "#552cdb", "display": "standalone" }axios-axios-2d06f96/docs/public/words-light.svg000066400000000000000000000126161521272452000215200ustar00rootroot00000000000000axios-axios-2d06f96/docs/public/words.svg000066400000000000000000000126161521272452000204130ustar00rootroot00000000000000axios-axios-2d06f96/docs/scripts/000077500000000000000000000000001521272452000167375ustar00rootroot00000000000000axios-axios-2d06f96/docs/scripts/process-sponsors.js000066400000000000000000000174241521272452000226470ustar00rootroot00000000000000import fs from 'node:fs'; import axios from 'axios'; import { printSuccessMessage, printErrorMessage, printInfoMessage } from './utils.js'; /** * Special configuration for processing sponsor data. */ const config = { legacyAgreements: { Stytch: 'gold', Airbnb: 'silver', Descope: 'gold', 'Principal Financial Group': 'gold', }, sponsorsToIgnore: ['axios'], additionalSponsors: [ { name: 'superluxuryreps', imageUrl: 'https://images.opencollective.com/superluxuryreps/378b62f/avatar.png', description: 'super luxury reps', tier: 'silver', slug: 'superluxuryreps', website: 'https://superluxuryreps.com/?utm_source=axios_docs_website&utm_medium=website&utm_campaign=axios_open_collective_sponsorship', twitter: null, active: true, }, ], }; /** * The GraphQL query to get all sponsors. * * @type {string} */ const getAllSponsorsQuery = ` query Account { account(githubHandle: "https://github.com/axios") { name slug members(role: BACKER) { totalCount nodes { account { name slug socialLinks { type url createdAt updatedAt } website imageUrl legalName description } tier { name } totalDonations { value currency } since } } } } `; /** * The GraphQL query to get all active sponsors. * * @type {string} */ const getActiveSponsorsQuery = ` query Account { account(githubHandle: "https://github.com/axios") { orders(onlyActiveSubscriptions: true, onlySubscriptions: true, frequency: MONTHLY, status: ACTIVE) { totalCount nodes { tier { name } fromAccount { id name socialLinks { type url } imageUrl legalName description website slug } amount { currency value } totalDonations { value currency } } } } } `; /** * Gets all sponsors. * * @returns {Promise} The sponsors. */ const getAllSponsors = async () => { printInfoMessage('getting all sponsors...'); const response = await axios.post('https://api.opencollective.com/graphql/v2', { query: getAllSponsorsQuery, }); return response.data.data; }; /** * Gets all active sponsors. * * @returns {Promise} The active sponsors. */ const getActiveSponsors = async () => { printInfoMessage('getting active sponsors...'); const response = await axios.post('https://api.opencollective.com/graphql/v2', { query: getActiveSponsorsQuery, }); return response.data.data; }; /** * Builds a URL with UTM parameters. * * @param {string} url - The URL to build. * @param {boolean} bypass - Whether to bypass UTM parameters. * @returns {string} The URL with UTM parameters. */ const buildLinks = (url, bypass = false) => { if (bypass) { return url; } try { const urlObject = new URL(url); const { searchParams } = urlObject; searchParams.set('utm_source', 'axios_docs_website'); searchParams.set('utm_medium', 'website'); searchParams.set('utm_campaign', 'axios_open_collective_sponsorship'); return urlObject.toString(); } catch { return url; } }; /** * Formats all active sponsors. * * @param {any} sponsorsData - The sponsors data. * @returns {any} The formatted sponsor data. */ const formatActiveSponsorData = (sponsorsData) => { const getSponsorTier = (sponsor) => { if (config.legacyAgreements[sponsor.fromAccount.name]) { return config.legacyAgreements[sponsor.fromAccount.name]; } if (sponsor.tier?.name.toLowerCase() === 'silver sponsor') { return 'silver'; } return sponsor.tier?.name.toLowerCase() || 'backer'; }; const processedData = sponsorsData .map((sponsor) => ({ name: sponsor.fromAccount.name ?? 'Backer', imageUrl: sponsor.fromAccount.imageUrl ?? null, description: sponsor.fromAccount.description ?? null, tier: getSponsorTier(sponsor), slug: sponsor.fromAccount.slug, website: sponsor.fromAccount.website ? buildLinks(sponsor.fromAccount.website) : (buildLinks( sponsor.fromAccount.socialLinks.find((link) => link.type === 'WEBSITE')?.url ) ?? null), twitter: buildLinks(sponsor.fromAccount.socialLinks.find((link) => link.type === 'TWITTER')?.url) ?? null, })) .filter((sponsor) => !config.sponsorsToIgnore.includes(sponsor.name)); return processedData; }; /** * Formats all sponsors irrespective state. * * @param {any} sponsorsData - The sponsors data. * @returns {any} The formatted sponsor data. */ const formatAllSponsorData = (sponsorsData) => { const getSponsorTier = (sponsor) => { if (config.legacyAgreements[sponsor.account.name]) { return config.legacyAgreements[sponsor.account.name]; } if (sponsor.tier?.name.toLowerCase() === 'silver sponsor') { return 'silver'; } return sponsor.tier?.name.toLowerCase() || 'backer'; }; const processedData = sponsorsData .map((sponsor) => ({ name: sponsor.account.name ?? 'Backer', imageUrl: sponsor.account.imageUrl ?? null, description: sponsor.account.description ?? null, tier: getSponsorTier(sponsor), slug: sponsor.account.slug, website: sponsor.account.website ? buildLinks(sponsor.account.website) : (buildLinks(sponsor.account.socialLinks.find((link) => link.type === 'WEBSITE')?.url) ?? null), twitter: buildLinks(sponsor.account.socialLinks.find((link) => link.type === 'TWITTER')?.url) ?? null, })) .filter((sponsor) => !config.sponsorsToIgnore.includes(sponsor.name)); return processedData; }; /** * The main process. */ const mainProcess = async () => { try { const allSponsors = await getAllSponsors(); const activeSponsors = await getActiveSponsors(); const allSponsorsProcessedData = formatAllSponsorData(allSponsors.account.members.nodes); const activeSponsorsProcessedData = formatActiveSponsorData( activeSponsors.account.orders.nodes ); const sponsorsByTier = {}; for (const sponsor of allSponsorsProcessedData) { sponsorsByTier[sponsor.tier] ||= []; const isActiveSponsor = activeSponsorsProcessedData.find( (activeSponsor) => activeSponsor.slug === sponsor.slug ); if (isActiveSponsor) { sponsorsByTier[sponsor.tier].push({ ...sponsor, active: true, }); } else { sponsorsByTier[sponsor.tier].push({ ...sponsor, active: false, }); } } for (const sponsor of activeSponsorsProcessedData) { const isSponsorInAllSponsors = allSponsorsProcessedData.find( (allSponsor) => allSponsor.slug === sponsor.slug ); if (!isSponsorInAllSponsors) { if (!sponsorsByTier[sponsor.tier]) { sponsorsByTier[sponsor.tier] ||= []; } sponsorsByTier[sponsor.tier].push({ ...sponsor, active: true, }); } } for (const additionalSponsor of config.additionalSponsors) { if (!sponsorsByTier[additionalSponsor.tier]) { sponsorsByTier[additionalSponsor.tier] ||= []; } sponsorsByTier[additionalSponsor.tier].push({ ...additionalSponsor, active: true, }); } fs.writeFileSync('./data/sponsors.json', JSON.stringify(sponsorsByTier, null, 2)); printSuccessMessage('processed sponsors successfully!'); } catch (_) { printErrorMessage('failed to process sponsors!'); console.error(_); } }; await mainProcess(); axios-axios-2d06f96/docs/scripts/utils.js000066400000000000000000000005221521272452000204340ustar00rootroot00000000000000import chalk from 'chalk'; export const printSuccessMessage = (message) => { console.log(chalk.green('Success:'), `${message}`); }; export const printInfoMessage = (message) => { console.log(chalk.blue('Info:'), `${message}`); }; export const printErrorMessage = (message) => { console.log(chalk.red('Error:'), `${message}`); }; axios-axios-2d06f96/docs/site.webmanifest000066400000000000000000000005621521272452000204450ustar00rootroot00000000000000{ "name": "axios", "short_name": "axios", "icons": [ { "src": "/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png" }, { "src": "/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png" } ], "theme_color": "#ffffff", "background_color": "#ffffff", "display": "standalone" } axios-axios-2d06f96/docs/zh/000077500000000000000000000000001521272452000156715ustar00rootroot00000000000000axios-axios-2d06f96/docs/zh/index.md000066400000000000000000000234351521272452000173310ustar00rootroot00000000000000--- # https://vitepress.dev/reference/default-theme-home-page layout: home hero: name: 'axios 文档' text: 'axios 是一个基于 Promise 的简单 HTTP 客户端,适用于浏览器和 Node.js' image: dark: /logo.svg light: /logo-light.svg alt: axios actions: - theme: brand text: 快速开始 link: /zh/pages/getting-started/first-steps - theme: alt text: API 参考 link: /zh/pages/advanced/api-reference features: - title: 简单易用 details: axios 上手极为简单,一行代码即可完成初始化。最基本的 API 请求仅需 2 行代码。 - title: 强大的拦截器 details: 创新的拦截器系统让您可以完全掌控请求和响应的生命周期,支持修改请求、响应及错误。 - title: TypeScript 支持 details: axios 提供完整的类型声明,全面支持 TypeScript,让您可以在 TypeScript 项目中放心使用。 ---

赞助商

{{ sponsor.name }}

{{ capitalizeFirstLetter(sponsor.tier) }}
axios-axios-2d06f96/docs/zh/pages/000077500000000000000000000000001521272452000167705ustar00rootroot00000000000000axios-axios-2d06f96/docs/zh/pages/advanced/000077500000000000000000000000001521272452000205355ustar00rootroot00000000000000axios-axios-2d06f96/docs/zh/pages/advanced/adapters.md000066400000000000000000000056431521272452000226720ustar00rootroot00000000000000# 适配器 适配器允许你自定义 axios 处理请求数据的方式。默认情况下,axios 使用 `['xhr', 'http', 'fetch']` 的有序优先级列表,并选择当前环境支持的第一个适配器。实际上,这意味着在浏览器中使用 `xhr`,在 Node.js 中使用 `http`,在两者均不可用的环境(如 Cloudflare Workers 或 Deno)中使用 `fetch`。 编写自定义适配器可以让你完全掌控 axios 如何发起请求和处理响应,适用于测试、自定义传输或非标准环境等场景。 ## 内置适配器 可以通过 `adapter` 配置选项按名称选择内置适配器: ```js // 使用 fetch 适配器 const instance = axios.create({ adapter: "fetch" }); // 使用 XHR 适配器(浏览器默认) const instance = axios.create({ adapter: "xhr" }); // 使用 HTTP 适配器(Node.js 默认) const instance = axios.create({ adapter: "http" }); ``` 你也可以传入一个适配器名称数组,axios 将使用当前环境支持的第一个: ```js const instance = axios.create({ adapter: ["fetch", "xhr", "http"] }); ``` 关于 `fetch` 适配器的更多详情,请参阅 [Fetch 适配器](/pages/advanced/fetch-adapter)页面。 ## 创建自定义适配器 要创建自定义适配器,需要编写一个接受 `config` 对象并返回 Promise 的函数,该 Promise 需解析为有效的 axios 响应对象。 ```js import axios from "axios"; import { settle } from "axios/unsafe/core/settle.js"; function myAdapter(config) { /** * 到此时: * - config 已与默认配置合并 * - 请求转换器已执行 * - 请求拦截器已执行 * * 适配器现在负责发起请求 * 并返回有效的响应对象。 */ return new Promise((resolve, reject) => { // 在此执行自定义请求逻辑。 // 本示例以原生 fetch API 为起点。 fetch(config.url, { method: config.method?.toUpperCase() ?? "GET", headers: config.headers?.toJSON() ?? {}, body: config.data, signal: config.signal, }) .then(async (fetchResponse) => { const responseData = await fetchResponse.text(); const response = { data: responseData, status: fetchResponse.status, statusText: fetchResponse.statusText, headers: Object.fromEntries(fetchResponse.headers.entries()), config, request: null, }; // settle 根据 HTTP 状态码决定是 resolve 还是 reject settle(resolve, reject, response); /** * 到此后: * - 响应转换器将执行 * - 响应拦截器将执行 */ }) .catch(reject); }); } const instance = axios.create({ adapter: myAdapter }); ``` ::: tip `settle` 辅助函数对 2xx 状态码 resolve Promise,对其他状态码 reject Promise,与 axios 的默认行为一致。如果需要自定义状态码验证,请改用 `validateStatus` 配置选项。 ::: axios-axios-2d06f96/docs/zh/pages/advanced/api-reference.md000066400000000000000000000220521521272452000235650ustar00rootroot00000000000000# API 参考 以下是 axios 包中所有可用函数和类的列表。这些函数可在你的项目中使用和导入。所有函数和类均受我们遵循语义化版本的承诺保护,即在未发布主版本变更的情况下,这些 API 将保持稳定不变。 ## 实例 `axios` 实例是你用于发起 HTTP 请求的主要对象,它是一个创建 `Axios` 类新实例的工厂函数。`axios` 实例提供了多个请求方法,详见文档的[请求别名](/pages/advanced/request-method-aliases)章节。 ## 类 ### `Axios` `Axios` 类是发起 HTTP 请求的核心类,是一个创建 `Axios` 类新实例的工厂函数。该类提供多个 HTTP 请求方法,详见文档的[请求别名](/pages/advanced/request-method-aliases)章节。 #### `constructor` 创建一个新的 `Axios` 实例,构造函数接受一个可选的配置对象作为参数。 ```ts constructor(instanceConfig?: AxiosRequestConfig); ``` #### `request` 处理请求调用和响应解析,是发起 HTTP 请求的核心方法。接受一个配置对象作为参数,返回一个解析为响应对象的 Promise。 ```ts request(configOrUrl: string | AxiosRequestConfig, config: AxiosRequestConfig): Promise>; ``` ### `CancelToken` `CancelToken` 类基于 `tc39/proposal-cancelable-promises` 提案,用于创建可取消 HTTP 请求的令牌。该类现已废弃,推荐使用 `AbortController` API。 从 0.22.0 版本起,`CancelToken` 类已废弃,将在未来版本中移除。建议改用 `AbortController` API。 该类主要为了向后兼容而保留导出,未来将被移除。我们强烈不建议在新项目中使用,因此不再对其 API 进行文档说明。 ## 函数 ### `AxiosError` `AxiosError` 类是 HTTP 请求失败时抛出的错误类,继承自 `Error` 类并添加了额外属性。 #### `constructor` 创建一个新的 `AxiosError` 实例,构造函数接受可选的 message、code、config、request 和 response 作为参数。 ```ts constructor(message?: string, code?: string, config?: InternalAxiosRequestConfig, request?: any, response?: AxiosResponse); ``` #### `properties` `AxiosError` 类提供以下属性: ```ts // 配置实例。 config?: InternalAxiosRequestConfig; // 错误代码。 code?: string; // 请求实例。 request?: any; // 响应实例。 response?: AxiosResponse; // 表示该错误是否为 AxiosError 的布尔值。 isAxiosError: boolean; // 错误状态码。 status?: number; // 将错误转换为 JSON 对象的辅助方法。 toJSON: () => object; // 错误原因。 cause?: Error; ``` ### `AxiosHeaders` `AxiosHeaders` 类是用于管理 HTTP 请求头的工具类,提供添加、删除和获取请求头等操作方法。 此处仅列出主要方法,完整方法列表请参阅类型声明文件。 #### `constructor` 创建一个新的 `AxiosHeaders` 实例,构造函数接受一个可选的请求头对象作为参数。 ```ts constructor(headers?: RawAxiosHeaders | AxiosHeaders | string); ``` #### `set` 向请求头对象添加一个请求头。 空字符串或仅包含空白字符的请求头名称会被忽略。 ```ts set(headerName?: string, value?: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders; set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean): AxiosHeaders; ``` #### `get` 从请求头对象获取一个请求头。 ```ts get(headerName: string, parser: RegExp): RegExpExecArray | null; get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue; ``` #### `has` 检查请求头对象中是否存在某个请求头。 ```ts has(header: string, matcher?: AxiosHeaderMatcher): boolean; ``` #### `delete` 从请求头对象移除一个请求头。 ```ts delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean; ``` #### `clear` 从请求头对象移除所有请求头。 ```ts clear(matcher?: AxiosHeaderMatcher): boolean; ``` #### `normalize` 规范化请求头对象。 ```ts normalize(format: boolean): AxiosHeaders; ``` #### `concat` 合并多个请求头对象。 ```ts concat(...targets: Array): AxiosHeaders; ``` #### `toJSON` 将请求头对象转换为 JSON 对象。 ```ts toJSON(asStrings: true): Record; toJSON(asStrings?: false): Record; ``` ### `CanceledError` `CanceledError` 类是 HTTP 请求被取消时抛出的错误类,继承自 `AxiosError` 类。 ### `Cancel` `Cancel` 类是 `CanceledError` 类的别名,为向后兼容而保留导出,将在未来版本中移除。 ### `isCancel` 检查某个错误是否为 `CanceledError` 的函数,可用于区分主动取消和意外错误。 ```ts isCancel(value: any): value is CanceledError; ``` ```js import axios from "axios"; const controller = new AbortController(); axios.get("/api/data", { signal: controller.signal }).catch((error) => { if (axios.isCancel(error)) { console.log("Request was cancelled:", error.message); } else { console.error("Unexpected error:", error); } }); controller.abort("User navigated away"); ``` ### `isAxiosError` 检查某个错误是否为 `AxiosError` 的函数。在 `catch` 块中使用此函数,可安全访问 axios 特有的错误属性,如 `error.response` 和 `error.config`。 ```ts isAxiosError(value: any): value is AxiosError; ``` ```js import axios from "axios"; try { await axios.get("/api/resource"); } catch (error) { if (axios.isAxiosError(error)) { // error.response、error.config、error.code 均可使用 console.error("HTTP error", error.response?.status, error.message); } else { // 非 axios 错误(例如编程错误) throw error; } } ``` ### `all` `all` 函数接受一组 Promise 并返回一个在所有 Promise 都完成后才完成的单一 Promise,现已废弃,推荐使用 `Promise.all` 方法。 从 0.22.0 版本起,`all` 函数已废弃,将在未来版本中移除。建议改用 `Promise.all` 方法。 ### `spread` `spread` 函数可将一个参数数组展开为函数调用的多个参数,在你需要将数组参数传递给接收多个参数的函数时非常实用。 ```ts spread(callback: (...args: T[]) => R): (array: T[]) => R; ``` ### `toFormData` 将普通 JavaScript 对象(包括嵌套对象)转换为 `FormData` 实例,在需要从对象中以编程方式构建 multipart 表单数据时非常实用。 ```ts toFormData(sourceObj: object, formData?: FormData, options?: FormSerializerOptions): FormData; ``` ```js import { toFormData } from "axios"; const data = { name: "Jay", avatar: fileBlob }; const form = toFormData(data); // form 现在是一个可直接发送的 FormData 实例 await axios.post("/api/users", form); ``` ### `formToJSON` 将 `FormData` 实例转换回普通 JavaScript 对象,在需要以结构化格式读取表单数据时非常实用。 ```ts formToJSON(form: FormData): object; ``` ```js import { formToJSON } from "axios"; const form = new FormData(); form.append("name", "Jay"); form.append("role", "admin"); const obj = formToJSON(form); console.log(obj); // { name: "Jay", role: "admin" } ``` ### `getAdapter` 通过名称或名称数组解析并返回一个适配器函数。axios 在内部使用此函数为当前环境选择最合适的适配器。 ```ts getAdapter(adapters: string | string[]): AxiosAdapter; ``` ```js import { getAdapter } from "axios"; // 显式获取 fetch 适配器 const fetchAdapter = getAdapter("fetch"); // 按优先级列表获取最合适的适配器 const adapter = getAdapter(["fetch", "xhr", "http"]); ``` ### `mergeConfig` 合并两个 axios 配置对象,使用与 axios 内部合并默认配置和请求级选项相同的深度合并策略。后者的值优先级更高。 ```ts mergeConfig(config1: AxiosRequestConfig, config2: AxiosRequestConfig): AxiosRequestConfig; ``` ```js import { mergeConfig } from "axios"; const base = { baseURL: "https://api.example.com", timeout: 5000 }; const override = { timeout: 10000, headers: { "X-Custom": "value" } }; const merged = mergeConfig(base, override); // { baseURL: "https://api.example.com", timeout: 10000, headers: { "X-Custom": "value" } } ``` ## 常量 ### `HttpStatusCode` 包含 HTTP 状态码命名常量的对象,可用于编写更具可读性的条件判断,避免直接使用数字字面量。 ```js import axios, { HttpStatusCode } from "axios"; try { const response = await axios.get("/api/resource"); } catch (error) { if (axios.isAxiosError(error)) { if (error.response?.status === HttpStatusCode.NotFound) { console.error("Resource not found"); } else if (error.response?.status === HttpStatusCode.Unauthorized) { console.error("Authentication required"); } } } ``` ## 其他 ### `VERSION` `axios` 包的当前版本号字符串,随每次发布更新。 axios-axios-2d06f96/docs/zh/pages/advanced/authentication.md000066400000000000000000000103541521272452000241010ustar00rootroot00000000000000# 认证 大多数 API 都需要某种形式的认证。本页介绍在 axios 请求中附加凭据的最常见模式。 ## Bearer 令牌(JWT) 最常见的方式是在 `Authorization` 请求头中附加 JWT。最简洁的做法是通过 axios 实例上的请求拦截器实现,这样令牌会在每次请求时实时读取: ```js import axios from "axios"; const api = axios.create({ baseURL: "https://api.example.com" }); api.interceptors.request.use((config) => { const token = localStorage.getItem("access_token"); if (token) { config.headers.set("Authorization", `Bearer ${token}`); } return config; }); ``` ## HTTP Basic 认证 对于使用 HTTP Basic 认证的 API,传入 `auth` 选项即可。axios 会自动对凭据进行编码并设置 `Authorization` 请求头: ```js const response = await axios.get("https://api.example.com/data", { auth: { username: "myUser", password: "myPassword", }, }); ``` 如果未提供 `auth`,Node.js HTTP 和 fetch 适配器也可以从请求 URL 中提取 Basic 认证凭据,例如 `https://myUser:myPassword@api.example.com/data`。URL 中经过百分号编码的凭据会在生成 `Authorization` 请求头前解码。新代码建议优先使用显式的 `auth` 选项;它会优先于 URL 中的凭据。 ::: tip 对于 Bearer 令牌和 API 密钥,请使用自定义 `Authorization` 请求头,而非 `auth` 选项——`auth` 仅适用于 HTTP Basic 认证。 ::: ## API 密钥 API 密钥通常作为请求头或查询参数传递,具体取决于 API 的要求: ```js // 作为请求头 const api = axios.create({ baseURL: "https://api.example.com", headers: { "X-API-Key": "your-api-key-here" }, }); // 作为查询参数 const response = await axios.get("https://api.example.com/data", { params: { apiKey: "your-api-key-here" }, }); ``` ## 令牌刷新 当访问令牌过期时,你需要静默刷新它并重新发送失败的请求。响应拦截器是实现此逻辑的合适位置: ```js import axios from "axios"; const api = axios.create({ baseURL: "https://api.example.com" }); // 跟踪是否已有刷新正在进行,以避免并行发起多个刷新请求 let isRefreshing = false; let failedQueue = []; const processQueue = (error, token = null) => { failedQueue.forEach((prom) => { if (error) { prom.reject(error); } else { prom.resolve(token); } }); failedQueue = []; }; api.interceptors.response.use( (response) => response, async (error) => { const originalRequest = error.config; if (error.response?.status === 401 && !originalRequest._retry) { if (isRefreshing) { // 将请求加入队列,等待刷新完成 return new Promise((resolve, reject) => { failedQueue.push({ resolve, reject }); }) .then((token) => { originalRequest.headers["Authorization"] = `Bearer ${token}`; return api(originalRequest); }) .catch((err) => Promise.reject(err)); } originalRequest._retry = true; isRefreshing = true; try { const { data } = await axios.post("/auth/refresh", { refreshToken: localStorage.getItem("refresh_token"), }); const newToken = data.access_token; localStorage.setItem("access_token", newToken); api.defaults.headers.common["Authorization"] = `Bearer ${newToken}`; processQueue(null, newToken); return api(originalRequest); } catch (refreshError) { processQueue(refreshError, null); // 跳转到登录页或触发事件 localStorage.removeItem("access_token"); window.location.href = "/login"; return Promise.reject(refreshError); } finally { isRefreshing = false; } } return Promise.reject(error); } ); ``` ## 基于 Cookie 的认证 对于依赖 Cookie 的会话 API,设置 `withCredentials: true` 以在跨域请求中携带 Cookie: ```js const api = axios.create({ baseURL: "https://api.example.com", withCredentials: true, // 每次请求均携带 Cookie }); ``` ::: warning `withCredentials: true` 要求服务器响应时携带 `Access-Control-Allow-Credentials: true`,且 `Access-Control-Allow-Origin` 必须为具体域名(不能是通配符)。 ::: axios-axios-2d06f96/docs/zh/pages/advanced/cancellation.md000066400000000000000000000035351521272452000235210ustar00rootroot00000000000000# 取消请求 从 v0.22.0 起,axios 支持使用 AbortController 以简洁的方式取消请求。该功能在浏览器和 Node.js(使用支持 AbortController 的 axios 版本)中均可使用。要取消请求,需要创建一个 `AbortController` 实例,并将其 `signal` 传入请求的 `signal` 选项。 ```js const controller = new AbortController(); axios .get("/foo/bar", { signal: controller.signal, }) .then(function (response) { //... }); // 取消请求 controller.abort(); ``` ## CancelToken 你也可以使用 `CancelToken` API 来取消请求。该 API 已废弃,将在下一个主版本中移除,建议改用 `AbortController`。可以使用 `CancelToken.source` 工厂方法创建取消令牌,如下所示: ```js const CancelToken = axios.CancelToken; const source = CancelToken.source(); axios .get("/user/12345", { cancelToken: source.token, }) .catch(function (thrown) { if (axios.isCancel(thrown)) { console.log("Request canceled", thrown.message); } else { // 处理错误 } }); axios.post( "/user/12345", { name: "new name", }, { cancelToken: source.token, } ); // 取消请求(message 参数可选) source.cancel("Operation canceled by the user."); ``` 也可以通过向 `CancelToken` 构造函数传入执行函数来创建取消令牌: ```js const CancelToken = axios.CancelToken; let cancel; axios.get("/user/12345", { cancelToken: new CancelToken(function executor(c) { // 执行函数接收一个 cancel 函数作为参数 cancel = c; }), }); // 取消请求 cancel(); ``` 你可以使用同一个取消令牌或 AbortController 取消多个请求。如果在 axios 请求开始时取消令牌已处于已取消状态,则请求会立即被取消,不会尝试发起实际的网络请求。 axios-axios-2d06f96/docs/zh/pages/advanced/config-defaults.md000066400000000000000000000035661521272452000241430ustar00rootroot00000000000000# 配置默认值 axios 允许你指定应用于每个请求的配置默认值,包括 `baseURL`、`headers`、`timeout` 等属性。下面是使用配置默认值的示例: ```js axios.defaults.baseURL = "https://jsonplaceholder.typicode.com/posts"; axios.defaults.headers.common["Authorization"] = AUTH_TOKEN; axios.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded"; ``` ::: warning 全局请求头会被发送到所有主机 如果你的应用会与多个域名通信,设置 `axios.defaults.headers.common["Authorization"]` 会将令牌发送到**所有**域名,包括你可能无法控制的第三方 API。对任何携带凭据的客户端,请使用带有限定 `baseURL` 的[自定义实例](#自定义实例默认值)。 ::: ## 自定义实例默认值 axios 实例在创建时会有自己的默认配置,这些默认配置可以通过修改实例的 `defaults` 属性来覆盖。下面是使用自定义实例默认值的示例: ```js var instance = axios.create({ baseURL: "https://jsonplaceholder.typicode.com/posts", timeout: 1000, headers: { Authorization: "foobar" }, }); instance.defaults.headers.common["Authorization"] = AUTH_TOKEN; ``` ## 配置优先级 配置将按照优先级顺序合并,依次为:库的默认值、实例的默认属性,最后是请求时传入的配置参数。下面通过示例说明优先级顺序。 首先,创建一个使用库提供的默认值的实例。此时 timeout 配置值为 `0`,这是库的默认值。 ```js const instance = axios.create(); ``` 接下来,将实例的 timeout 默认值覆盖为 `2500` 毫秒。此后,使用该实例的所有请求都将在 2.5 秒后超时。 ```js instance.defaults.timeout = 2500; ``` 最后,发起一个 timeout 为 `5000` 毫秒的请求,该请求将在 5 秒后超时。 ```js instance.get("/longRequest", { timeout: 5000, }); ``` axios-axios-2d06f96/docs/zh/pages/advanced/create-an-instance.md000066400000000000000000000050511521272452000245210ustar00rootroot00000000000000# 创建实例 `axios.create()` 允许你创建一个预配置的 axios 实例。该实例与默认 `axios` 对象拥有相同的请求和响应 API,但会将你提供的配置作为每次请求的基础配置。对于任何超过单文件规模的应用,这是使用 axios 的推荐方式。 ```ts import axios from "axios"; const instance = axios.create({ baseURL: "https://api.example.com", timeout: 5000, headers: { "X-Custom-Header": "foobar" }, }); ``` `create` 方法接受完整的[请求配置](/pages/advanced/request-config)对象。之后可以像使用默认 axios 对象一样使用该实例: ```js const response = await instance.get("/users/1"); ``` ## 为什么要使用实例? ### 按服务设置 baseURL 在大多数应用中,你需要与多个 API 通信。为每个服务创建独立的实例,可以避免在每次调用时重复指定 baseURL: ```js const githubApi = axios.create({ baseURL: "https://api.github.com" }); const internalApi = axios.create({ baseURL: "https://api.internal.example.com" }); const { data: repos } = await githubApi.get("/users/axios/repos"); const { data: users } = await internalApi.get("/users"); ``` ### 共享认证请求头 在一个实例上附加认证令牌,让该实例的所有请求自动携带,而不影响其他实例: ```js const authApi = axios.create({ baseURL: "https://api.example.com", headers: { Authorization: `Bearer ${getToken()}`, }, }); ``` ### 按服务设置超时与重试 不同服务有不同的可靠性特征。可以为实时服务设置较短的超时,为批处理任务设置较长的超时: ```js const realtimeApi = axios.create({ baseURL: "https://realtime.example.com", timeout: 2000 }); const batchApi = axios.create({ baseURL: "https://batch.example.com", timeout: 60000 }); ``` ### 隔离的拦截器 添加到实例上的拦截器只对该实例生效,有助于保持关注点分离: ```js const loggingApi = axios.create({ baseURL: "https://api.example.com" }); loggingApi.interceptors.request.use((config) => { console.log(`→ ${config.method?.toUpperCase()} ${config.url}`); return config; }); ``` ## 按请求覆盖默认配置 在请求时传入的配置始终会覆盖实例默认配置: ```js const api = axios.create({ timeout: 5000 }); // 这个特定请求使用 30 秒超时 await api.get("/slow-endpoint", { timeout: 30000 }); ``` ::: tip 实例默认配置也可以在创建后通过修改 `instance.defaults` 来更改: ```js instance.defaults.headers.common["Authorization"] = `Bearer ${newToken}`; ``` ::: axios-axios-2d06f96/docs/zh/pages/advanced/error-handling.md000066400000000000000000000155601521272452000240010ustar00rootroot00000000000000# 错误处理 axios 可能会抛出多种不同类型的错误,有些来自 axios 本身,有些来自服务器或客户端。下表列出了所抛出错误的基本结构: | 属性 | 说明 | | ------- | --------------------------------------------------------------------------------------------------------------------------------------------- | | message | 错误信息的简要摘要,以及失败时的状态码。 | | name | 定义错误的来源,对于 axios 来说始终是 `AxiosError`。 | | stack | 提供错误的堆栈跟踪。 | | config | 包含用户在发起请求时定义的特定实例配置的 axios 配置对象。 | | code | 表示 axios 内部识别的错误,下表列出了 axios 内部错误的具体说明。 | | status | HTTP 响应状态码。常见 HTTP 响应状态码的含义请参阅[此处](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes)。 | 以下是 axios 内部可能出现的错误列表: | 错误代码 | 说明 | | ------------------------- | --------------------------------------------------------------------------------------- | | ERR_BAD_OPTION_VALUE | axios 配置中提供了无效或不支持的值。 | | ERR_BAD_OPTION | axios 配置中提供了无效选项。 | | ECONNABORTED | 通常表示请求已超时(除非设置了 `transitional.clarifyTimeoutError`)或被浏览器或其插件中止。 | | ETIMEDOUT | 请求因超过 axios 默认时限而超时。必须将 `transitional.clarifyTimeoutError` 设置为 `true`,否则会抛出通用的 `ECONNABORTED` 错误。 | | ERR_NETWORK | 网络相关问题。在浏览器中,此错误也可能由 [CORS](https://developer.mozilla.org/ru/docs/Web/HTTP/Guides/CORS) 或[混合内容](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content)策略违规引起。出于安全考虑,浏览器不允许 JS 代码获知错误的真实原因,请检查控制台。 | | ERR_FR_TOO_MANY_REDIRECTS | 请求重定向次数过多,超过了 axios 配置中指定的最大重定向次数。 | | ERR_DEPRECATED | 使用了 axios 中已废弃的功能或方法。 | | ERR_BAD_RESPONSE | 响应无法正确解析或格式异常,通常与 `5xx` 状态码的响应有关。 | | ERR_BAD_REQUEST | 请求格式异常或缺少必要参数,通常与 `4xx` 状态码的响应有关。 | | ERR_CANCELED | 功能或方法被用户通过 AbortSignal(或 CancelToken)显式取消。 | | ERR_NOT_SUPPORT | 当前 axios 环境不支持该功能或方法。 | | ERR_INVALID_URL | axios 请求提供了无效的 URL。 | | ERR_FORM_DATA_DEPTH_EXCEEDED | 在序列化 `params` 或表单数据时,对象超过了配置的 `maxDepth`,默认上限为 100 层。详见 [`paramsSerializer`](/pages/advanced/request-config#paramsserializer) 和 [`formSerializer`](/pages/advanced/request-config#formserializer)。 | ## 处理错误 axios 的默认行为是在请求失败时 reject Promise。不过,你也可以捕获错误并按需处理。以下是捕获错误的示例: ```js axios.get("/user/12345").catch(function (error) { if (error.response) { // 请求已发出,服务器返回了不在 2xx 范围内的状态码 console.log(error.response.data); console.log(error.response.status); console.log(error.response.headers); } else if (error.request) { // 请求已发出,但未收到响应 // `error.request` 在浏览器中是 XMLHttpRequest 实例,在 node.js 中是 http.ClientRequest 实例 console.log(error.request); } else { // 在设置请求时触发了错误 console.log("Error", error.message); } console.log(error.config); }); ``` 使用 `validateStatus` 配置选项,可以覆盖默认条件(`status >= 200 && status < 300`),自定义应当抛出错误的 HTTP 状态码。 ```js axios.get("/user/12345", { validateStatus: function (status) { return status < 500; // 仅在状态码小于 500 时 resolve }, }); ``` 使用 `toJSON` 方法,可以获取包含更多错误信息的对象。 ```js axios.get("/user/12345").catch(function (error) { console.log(error.toJSON()); }); ``` 为避免从 `error.config` 中泄露敏感信息,可在请求配置中传入 `redact` 数组。当调用 `AxiosError#toJSON()` 时,匹配的配置键会在任意深度上以不区分大小写的方式被脱敏。 ```js axios.get("/user/12345", { headers: { Authorization: "Bearer token" }, redact: ["authorization"] }).catch(function (error) { console.log(error.toJSON().config.headers.Authorization); // [REDACTED ****] }); ``` ## 处理超时 当请求超过其配置的 `timeout` 时,axios 默认会以 `ECONNABORTED` 拒绝。设置 `transitional.clarifyTimeoutError: true` 可改为收到 `ETIMEDOUT`,便于将超时错误与其他中止情况区分开。 ```js async function fetchWithTimeout() { try { const response = await axios.get("https://example.com/data", { timeout: 5000, // 5 秒 transitional: { // 如果你更倾向于使用 ETIMEDOUT 而非 ECONNABORTED,请设置为 true clarifyTimeoutError: true, }, }); console.log("Response:", response.data); } catch (error) { if (axios.isAxiosError(error)) { if (error.code === "ECONNABORTED" || error.code === "ETIMEDOUT") { console.error("请求超时,请重试。"); return; } console.error("Axios 错误:", error.message); return; } console.error("意外错误:", error); } } ``` ::: tip 在生产环境中始终设置 `timeout` 若不设置超时,停滞的请求可能会无限挂起。匹配的配置选项请参阅 [`timeout`](/pages/advanced/request-config#timeout) 与 [`transitional.clarifyTimeoutError`](/pages/advanced/request-config#transitional)。 ::: axios-axios-2d06f96/docs/zh/pages/advanced/fetch-adapter.md000066400000000000000000000062441521272452000235740ustar00rootroot00000000000000# Fetch 适配器 `fetch` 适配器是我们在 1.7.0 版本中引入的新适配器,使 axios 能够使用 `fetch` API,兼顾两者的优势。默认情况下,当构建中 `xhr` 和 `http` 适配器不可用,或当前环境不支持时,会使用 `fetch`。若要将其作为默认适配器,必须在创建 axios 实例时通过 `adapter` 选项显式指定。 ```js import axios from 'axios'; const instance = axios.create({ adapter: 'fetch', }); ``` 该适配器支持与 `xhr` 适配器相同的功能,包括上传和下载进度捕获,还支持额外的响应类型,如 `stream` 和 `formdata`(如果环境支持)。 当省略 `auth` 时,fetch 适配器可以从请求 URL 中读取 HTTP Basic 认证凭据,例如 `https://user:pass@example.com`。生成 `Authorization` 请求头前会先解码 URL 中经过百分号编码的凭据,并且 `auth` 优先于 URL 中的凭据。 ## 自定义 fetch 从 `v1.12.0` 起,你可以自定义 fetch 适配器,使用自定义的 `fetch` 函数代替环境全局的 `fetch`。可以通过 `env` 配置选项传入自定义的 `fetch` 函数、`Request` 和 `Response` 构造函数。这在使用提供了自己 `fetch` 实现的自定义环境或应用框架时非常实用。 ::: info 使用自定义 `fetch` 函数时,可能还需要提供匹配的 `Request` 和 `Response` 构造函数。如果省略,将使用全局构造函数。如果你的自定义 `fetch` 与全局构造函数不兼容,可以传入 `null` 来禁用它们。 **注意:** 将 `Request` 和 `Response` 设置为 `null` 后,fetch 适配器将无法捕获上传和下载进度。 ::: ### 基本示例 ```js import customFetchFunction from 'customFetchModule'; const instance = axios.create({ adapter: 'fetch', onDownloadProgress(e) { console.log('downloadProgress', e); }, env: { fetch: customFetchFunction, Request: null, // null -> 禁用该构造函数 Response: null, }, }); ``` ### 与 Tauri 一起使用 [Tauri](https://tauri.app/plugin/http-client/) 提供了一个平台 `fetch` 函数,可绕过浏览器对原生层请求的 CORS 限制。以下示例展示了在 Tauri 应用中使用该自定义 fetch 配置 axios 的最简设置。 ```js import { fetch } from '@tauri-apps/plugin-http'; import axios from 'axios'; const instance = axios.create({ adapter: 'fetch', onDownloadProgress(e) { console.log('downloadProgress', e); }, env: { fetch, }, }); const { data } = await instance.get('https://google.com'); ``` ### 与 SvelteKit 一起使用 [SvelteKit](https://svelte.dev/docs/kit/web-standards#Fetch-APIs) 为服务端 `load` 函数提供了自定义的 `fetch` 实现,用于处理 Cookie 转发和相对 URL。由于其 `fetch` 与标准 `URL` API 不兼容,必须明确配置 axios 使用它,并禁用全局 `Request` 和 `Response` 构造函数。 ```js export async function load({ fetch }) { const { data: post } = await axios.get('https://jsonplaceholder.typicode.com/posts/1', { adapter: 'fetch', env: { fetch, Request: null, Response: null, }, }); return { post }; } ``` axios-axios-2d06f96/docs/zh/pages/advanced/file-posting.md000066400000000000000000000055571521272452000234730ustar00rootroot00000000000000# 文件上传 axios 让文件上传变得简单。需要 `multipart/form-data` 上传时,使用 `postForm` 或 `FormData` 即可。 ## 单文件上传(浏览器) 直接将 `File` 对象作为字段值传入——axios 会自动检测并使用正确的内容类型: ```js await axios.postForm("https://httpbin.org/post", { description: "My profile photo", file: document.querySelector("#fileInput").files[0], }); ``` ## 多文件上传(浏览器) 传入 `FileList` 可一次性上传所有选中的文件,所有文件将使用相同的字段名(`files[]`)发送: ```js await axios.postForm( "https://httpbin.org/post", document.querySelector("#fileInput").files ); ``` 也可以通过在键名末尾追加 `[]` 来显式指定一个自定义字段名,传入 `FileList`(或 `File` 对象数组): ```js await axios.postForm("https://httpbin.org/post", { "files[]": document.querySelector("#fileInput").files, }); ``` 如需为每个文件使用不同的字段名,请手动构建 `FormData` 对象: ```js const formData = new FormData(); formData.append("avatar", avatarFile); formData.append("cover", coverFile); await axios.post("https://httpbin.org/post", formData); ``` ## 跟踪上传进度(浏览器) 使用 `onUploadProgress` 回调向用户显示进度条或百分比: ```js await axios.postForm("https://httpbin.org/post", { file: document.querySelector("#fileInput").files[0], }, { onUploadProgress: (progressEvent) => { const percent = Math.round( (progressEvent.loaded * 100) / progressEvent.total ); console.log(`Upload progress: ${percent}%`); }, }); ``` 进度事件对象上可用的完整字段列表,请参阅[进度捕获](/pages/advanced/progress-capturing)。 ## Node.js 中的文件上传 在 Node.js 中,使用 `fs.createReadStream` 上传文件系统中的文件,无需将整个文件加载到内存: ```js import fs from "fs"; import FormData from "form-data"; import axios from "axios"; const form = new FormData(); form.append("file", fs.createReadStream("/path/to/file.jpg")); form.append("description", "My uploaded file"); await axios.post("https://httpbin.org/post", form); ``` ::: tip 在 Node.js 环境中创建 `FormData` 对象需要 `form-data` npm 包。在现代 Node.js(v18+)中,全局 `FormData` 已原生可用。 ::: ## 上传 Buffer(Node.js) 也可以直接上传内存中的 `Buffer`: ```js const buffer = Buffer.from("Hello, world!"); const form = new FormData(); form.append("file", buffer, { filename: "hello.txt", contentType: "text/plain", knownLength: buffer.length, }); await axios.post("https://httpbin.org/post", form); ``` ::: warning Node.js 环境目前不支持捕获 `FormData` 上传进度。 ::: ::: danger 在 Node.js 中上传可读流时,请设置 `maxRedirects: 0`,以防止 `follow-redirects` 包将整个流缓冲到内存中。 ::: axios-axios-2d06f96/docs/zh/pages/advanced/header-methods.md000066400000000000000000000145611521272452000237570ustar00rootroot00000000000000# 请求头方法 随着新 `AxiosHeaders` 类的引入,axios 提供了一组操作请求头的方法,比直接操作请求头对象更加方便。 ## 构造函数 `new AxiosHeaders(headers?)` `AxiosHeaders` 类的构造函数接受一个可选的请求头对象来初始化实例,对象可以包含任意数量的请求头,且键名不区分大小写。 ```js constructor(headers?: RawAxiosHeaders | AxiosHeaders | string); ``` 为方便起见,你可以传入一个以换行符分隔的请求头字符串,它们会被解析并添加到实例中。 ```js const headers = new AxiosHeaders(` Host: www.bing.com User-Agent: curl/7.54.0 Accept: */*`); console.log(headers); // Object [AxiosHeaders] { // host: 'www.bing.com', // 'user-agent': 'curl/7.54.0', // accept: '*/*' // } ``` ## Set `set` 方法用于在 `AxiosHeaders` 实例上设置请求头,可以传入单个请求头名称和值、包含多个请求头的对象,或以换行符分隔的请求头字符串。该方法还接受一个可选的 `rewrite` 参数,用于控制设置请求头时的覆盖行为。 ```js set(headerName, value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher); set(headerName, value, rewrite?: (this: AxiosHeaders, value: string, name: string) => boolean); set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean); ``` `rewrite` 参数控制覆盖行为: - `false` - 如果请求头的值已设置(不为 undefined),则不覆盖 - `undefined`(默认)- 覆盖请求头,除非其值被设置为 false - `true` - 始终覆盖 该参数也可以接受一个用户自定义函数,用于决定是否应覆盖该值,函数接收当前值、请求头名称和请求头对象作为参数。 空字符串或仅包含空白字符的请求头名称会被忽略。 `AxiosHeaders` 会保留第一个匹配键的大小写形式。你可以利用这一特性,先以 `undefined` 值预设一个键名,之后再设置值,从而保留特定的请求头大小写。详见[保留特定请求头大小写](/pages/advanced/headers#preserving-a-specific-header-case)。 ## Get `get` 方法用于获取请求头的值,可以传入单个请求头名称、可选的匹配器或解析器。匹配器默认为 `true`,解析器可以是用于从请求头中提取值的正则表达式。 ```js get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue; get(headerName: string, parser: RegExp): RegExpExecArray | null; ``` 以下是 `get` 方法的一些使用示例: ```js const headers = new AxiosHeaders({ 'Content-Type': 'multipart/form-data; boundary=Asrf456BGe4h', }); console.log(headers.get('Content-Type')); // multipart/form-data; boundary=Asrf456BGe4h console.log(headers.get('Content-Type', true)); // 解析以 \s,;= 为分隔符的键值对字符串: // [Object: null prototype] { // 'multipart/form-data': undefined, // boundary: 'Asrf456BGe4h' // } console.log( headers.get('Content-Type', (value, name, headers) => { return String(value).replace(/a/g, 'ZZZ'); }) ); // multipZZZrt/form-dZZZtZZZ; boundZZZry=Asrf456BGe4h console.log(headers.get('Content-Type', /boundary=(\w+)/)?.[0]); // boundary=Asrf456BGe4h ``` ## Has `has` 方法用于检查 `AxiosHeaders` 实例中是否存在某个请求头,可以传入单个请求头名称和可选的匹配器。 ```js has(header: string, matcher?: AxiosHeaderMatcher): boolean; ``` ::: info 如果请求头已设置(值不为 undefined),则返回 true。 ::: ## Delete `delete` 方法用于从 `AxiosHeaders` 实例中删除某个请求头,可以传入单个请求头名称和可选的匹配器。 ```js delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean; ``` ::: info 如果至少有一个请求头被移除,则返回 true。 ::: ## Clear `clear` 方法用于在不传入任何参数时删除 `AxiosHeaders` 实例中的所有请求头。如果传入匹配器,则只移除与匹配器匹配的请求头,此时匹配器用于匹配请求头名称而非值。 ```js clear(matcher?: AxiosHeaderMatcher): boolean; ``` ::: info 如果至少有一个请求头被清除,则返回 true。 ::: ## Normalize 如果直接修改了请求头对象,可能导致相同名称但大小写不同的重复项。此方法通过将重复键合并为一个来规范化请求头对象。axios 在每个拦截器调用后内部使用此方法。将 format 设置为 true 可将请求头名称转换为首字母大写的格式(cOntEnt-type => Content-Type),设置为 false 则保留原始格式。 ```js const headers = new AxiosHeaders({ foo: '1', }); headers.Foo = '2'; headers.FOO = '3'; console.log(headers.toJSON()); // [Object: null prototype] { foo: '1', Foo: '2', FOO: '3' } console.log(headers.normalize().toJSON()); // [Object: null prototype] { foo: '3' } console.log(headers.normalize(true).toJSON()); // [Object: null prototype] { Foo: '3' } ``` ::: info 返回 `this` 以支持链式调用。 ::: ## Concat 将实例与目标对象合并到一个新的 AxiosHeaders 实例中。如果目标是字符串,它将被解析为原始 HTTP 请求头;如果目标是 AxiosHeaders 实例,它将与当前实例合并。 这对于组合请求头时的大小写预设非常有用,例如: ```js const headers = AxiosHeaders.concat( { 'content-type': undefined }, { 'Content-Type': 'application/octet-stream' } ); ``` ```js concat(...targets: Array): AxiosHeaders; ``` ::: info 返回一个新的 AxiosHeaders 实例。 ::: ## toJSON 将所有内部请求头值解析到一个新的 null 原型对象中。将 `asStrings` 设置为 true 可将数组解析为以逗号分隔的字符串。 ```js toJSON(asStrings: true): Record; toJSON(asStrings?: false): Record; ``` ## From 从传入的原始请求头创建并返回一个新的 `AxiosHeaders` 实例;如果传入的已经是 `AxiosHeaders` 实例,则直接返回该实例。 ```js from(thing?: AxiosHeaders | RawAxiosHeaders | string): AxiosHeaders; ``` ## 快捷方法 以下快捷方法可供使用: - `setContentType`、`getContentType`、`hasContentType` - `setContentLength`、`getContentLength`、`hasContentLength` - `setAccept`、`getAccept`、`hasAccept` - `setUserAgent`、`getUserAgent`、`hasUserAgent` - `setContentEncoding`、`getContentEncoding`、`hasContentEncoding` axios-axios-2d06f96/docs/zh/pages/advanced/headers.md000066400000000000000000000110001521272452000224620ustar00rootroot00000000000000# 请求头 axios 暴露了自己的 AxiosHeaders 类,通过类 Map 的 API 来操作请求头,保证键名不区分大小写。axios 内部使用该类管理请求头,同时也将其暴露给用户以提供便利。尽管 HTTP 请求头本身不区分大小写,axios 仍会保留原始请求头的大小写形式,以满足风格需求,并在服务器错误地将请求头大小写视为有效区分时提供兼容。直接操作请求头对象的旧方式仍然可用,但已废弃,不建议在新代码中使用。 ## 使用请求头 AxiosHeaders 对象实例可以包含不同类型的内部值,用于控制设置和合并逻辑。axios 在将最终请求头对象发送前会调用 `toJSON` 方法。AxiosHeaders 对象也是可迭代的,可以在循环中使用,或转换为数组或对象。 请求头值可以是以下类型之一: - `string` - 正常的字符串值,将被发送到服务器 - `null` - 转换为 JSON 时跳过该请求头 - `false` - 转换为 JSON 时跳过该请求头,并额外表示调用 `set` 方法时必须将 `rewrite` 选项设置为 true 才能覆盖此值(axios 内部使用此机制允许用户选择不安装某些请求头,如 User-Agent 或 Content-Type) - `undefined` - 值未设置 ::: warning 如果请求头值不是 undefined,则视为已设置。 ::: 请求头对象始终在拦截器和转换器中初始化,如以下示例所示: ```js axios.interceptors.request.use((request: InternalAxiosRequestConfig) => { request.headers.set("My-header", "value"); request.headers.set({ "My-set-header1": "my-set-value1", "My-set-header2": "my-set-value2", }); // 禁止 axios 后续设置此请求头 request.headers.set("User-Agent", false); request.headers.setContentType("text/plain"); // 直接访问的方式已废弃 request.headers["My-set-header2"] = "newValue"; return request; }); ``` 你可以使用任何可迭代方法遍历 AxiosHeaders,如 for-of 循环、forEach 或展开运算符: ```js const headers = new AxiosHeaders({ foo: '1', bar: '2', baz: '3', }); for (const [header, value] of headers) { console.log(header, value); } // foo 1 // bar 2 // baz 3 ``` ## 在请求中设置请求头 最常见的设置请求头的方式是在请求配置或实例配置的 `headers` 选项中设置: ```js // 针对单个请求 await axios.get('/api/data', { headers: { 'Accept-Language': 'en-US', 'X-Request-ID': 'abc123', }, }); // 针对实例(应用于每个请求) const api = axios.create({ headers: { 'X-App-Version': '2.0.0', }, }); ``` ## 保留特定请求头大小写 axios 请求头名称不区分大小写,但 `AxiosHeaders` 会保留第一个匹配键的大小写形式。如果你需要为大小写敏感的非标准服务器保留特定大小写,可以在 `defaults` 中预设键名,之后再按常规方式设置值。 ```js const api = axios.create(); api.defaults.headers.common = { 'content-type': undefined, accept: undefined, }; await api.put(url, data, { headers: { 'Content-Type': 'application/octet-stream', Accept: 'application/json', }, }); ``` 也可以在组合请求头时直接使用 `AxiosHeaders` 实现: ```js import axios, { AxiosHeaders } from 'axios'; const headers = AxiosHeaders.concat( { 'content-type': undefined }, { 'Content-Type': 'application/octet-stream' } ); await axios.put(url, data, { headers }); ``` ## 在拦截器中设置请求头 拦截器是附加动态请求头(如认证令牌)的合适位置,因为令牌可能在实例首次创建时还不可用: ```js api.interceptors.request.use((config) => { const token = getAuthToken(); // 在请求时读取 config.headers.set('Authorization', `Bearer ${token}`); return config; }); ``` ## 读取响应头 响应头以 `AxiosHeaders` 实例的形式在 `response.headers` 上可用,所有头名称均为小写: ```js const response = await axios.get('/api/data'); console.log(response.headers['content-type']); // application/json; charset=utf-8 console.log(response.headers.get('x-request-id')); // abc123 ``` ## 移除默认请求头 如需取消 axios 默认设置的请求头(如 `Content-Type` 或 `User-Agent`),将其值设置为 `false`: ```js await axios.post('/api/data', payload, { headers: { 'Content-Type': false, // 让浏览器自动设置(例如针对 FormData) }, }); ``` 关于完整 `AxiosHeaders` 方法 API 的详细说明,请参阅[请求头方法](/pages/advanced/header-methods)页面。 axios-axios-2d06f96/docs/zh/pages/advanced/html-form-processing.md000066400000000000000000000035461521272452000251460ustar00rootroot00000000000000# HTML 表单提交(浏览器) 你也可以直接从 HTML 表单元素提交数据,无需任何额外的 JavaScript 代码即可提交页面中的表单。 ```js await axios.postForm('https://httpbin.org/post', document.querySelector('#htmlForm')); ``` `FormData` 和 `HTMLForm` 对象也可以通过显式将 `Content-Type` 请求头设置为 `application/json` 来以 `JSON` 格式发送: ```js await axios.post('https://httpbin.org/post', document.querySelector('#htmlForm'), { headers: { 'Content-Type': 'application/json', }, }); ``` 以下是一个有效的、可被上述代码提交的表单示例: ```html
``` 上述表单将以如下格式提交: ```json { "foo": "1", "deep": { "prop": { "spaced": "3" } }, "baz": ["4", "5"], "user": { "age": "value2" } } ``` ::: tip 路径冲突会覆盖先前的值 字段名会按 `.`、方括号或空白拆分为属性路径。两个路径重叠的输入会发生冲突:在上面的示例中,`deep.prop` 解析为 `["deep", "prop"]`,而 `deep prop spaced` 解析为 `["deep", "prop", "spaced"]`,因此更深的赋值会将 `deep.prop = "2"` 替换为嵌套对象 `{ spaced: "3" }`。如果你需要同时保留两个值,请使用互不重叠的字段名。 ::: ::: warning 目前不支持将 Blob/File 以 JSON(base64)格式发送。 ::: axios-axios-2d06f96/docs/zh/pages/advanced/http2.md000066400000000000000000000044621521272452000221260ustar00rootroot00000000000000# HTTP2 在 `1.13.0` 版本中,`http` 适配器新增了实验性的 HTTP/2 支持,仅在 Node.js 环境中可用。 ## 基本用法 使用 `httpVersion` 选项来选择请求使用的协议版本,将其设置为 `2` 可启用 HTTP/2。 ```js const { data, headers, status } = await axios.post( "https://httpbin.org/post", form, { httpVersion: 2, }, ); ``` ## `http2Options` 可以通过 `http2Options` 配置对象传入内部 `session.request()` 调用的原生额外选项,其中还包括自定义的 `sessionTimeout` 参数,用于控制空闲 HTTP/2 会话在关闭前保持存活的时间(毫秒),默认值为 `1000ms`。 ```js { httpVersion: 2, http2Options: { rejectUnauthorized: false, // 接受自签名证书(仅用于开发环境) sessionTimeout: 5000, // 空闲会话保持 5 秒 }, } ``` ::: warning HTTP/2 支持目前仍为实验性功能,API 可能在未来的次要版本或补丁版本中发生变化。 ::: ::: warning HTTP/2 不支持重定向 HTTP/2 适配器目前不会自动跟随重定向。如果使用 `httpVersion: 2` 发起的请求收到 `3xx` 响应,重定向不会被自动跟随。请手动处理这类响应,或对依赖重定向的端点继续使用 HTTP/1.x。 ::: ## 完整示例 以下示例通过 HTTP/2 发送 `multipart/form-data` POST 请求,并同时跟踪上传和下载进度。 ```js const form = new FormData(); form.append("foo", "123"); const { data, headers, status } = await axios.post( "https://httpbin.org/post", form, { httpVersion: 2, http2Options: { // rejectUnauthorized: false, // sessionTimeout: 1000 }, onUploadProgress(e) { console.log("upload progress", e); }, onDownloadProgress(e) { console.log("download progress", e); }, responseType: "arraybuffer", }, ); ``` ## 配置参考 | 选项 | 类型 | 默认值 | 说明 | |---|---|---|---| | `httpVersion` | `number` | `1` | 使用的 HTTP 协议版本,设置为 `2` 可启用 HTTP/2。 | | `http2Options.sessionTimeout` | `number` | `1000` | 空闲 HTTP/2 会话关闭前等待的时间(毫秒)。 | Node.js 内置 `http2` 模块支持的其他原生 `session.request()` 选项也可以通过 `http2Options` 传入。 axios-axios-2d06f96/docs/zh/pages/advanced/interceptors.md000066400000000000000000000117001521272452000235770ustar00rootroot00000000000000# 拦截器 拦截器是一种强大的机制,可用于拦截和修改 HTTP 请求与响应,与 Express.js 中的中间件非常相似。拦截器是在请求发送前和响应接收前执行的函数,适用于日志记录、修改请求头、修改响应等多种场景。 拦截器的基本用法如下: ```js // 添加请求拦截器 axios.interceptors.request.use( function (config) { // 在请求发送之前执行某些操作 return config; }, function (error) { // 处理请求错误 return Promise.reject(error); } ); // 添加响应拦截器 axios.interceptors.response.use( function (response) { // 状态码在 2xx 范围内的响应会触发此函数 // 处理响应数据 return response; }, function (error) { // 状态码不在 2xx 范围内的响应会触发此函数 // 处理响应错误 return Promise.reject(error); } ); ``` ## 移除拦截器 可以通过对要移除的拦截器调用 `eject` 方法来移除特定拦截器。也可以通过在 `axios.interceptors` 对象上调用 `clear` 方法来移除所有拦截器。以下是移除拦截器的示例: ```js // 移除请求拦截器 const myInterceptor = axios.interceptors.request.use(function () { /*...*/ }); axios.interceptors.request.eject(myInterceptor); // 移除响应拦截器 const myInterceptor = axios.interceptors.response.use(function () { /*...*/ }); axios.interceptors.response.eject(myInterceptor); ``` 以下是移除所有拦截器的示例: ```js const instance = axios.create(); instance.interceptors.request.use(function () { /*...*/ }); instance.interceptors.request.clear(); // 移除所有请求拦截器 instance.interceptors.response.use(function () { /*...*/ }); instance.interceptors.response.clear(); // 移除所有响应拦截器 ``` ## 拦截器的默认行为 添加请求拦截器时,默认被视为异步执行。当主线程被阻塞时(拦截器底层会创建一个 Promise,你的请求会被放到调用栈底部),这可能导致 axios 请求的执行出现延迟。如果你的请求拦截器是同步的,可以在选项对象中添加一个标志,告知 axios 同步运行该代码,从而避免请求执行的延迟。 ```js axios.interceptors.request.use( function (config) { config.headers.test = "I am only a header!"; return config; }, null, { synchronous: true } ); ``` ## 使用 `runWhen` 的拦截器 如果你希望根据运行时条件决定是否执行某个拦截器,可以在选项对象中添加 `runWhen` 函数。仅当 `runWhen` 返回 `false` 时,拦截器不会执行。该函数会以 config 对象作为参数调用(你也可以为其绑定自定义参数)。这对于只需在特定时机运行的异步请求拦截器非常实用。 ```js function onGetCall(config) { return config.method === "get"; } axios.interceptors.request.use( function (config) { config.headers.test = "special get headers"; return config; }, null, { runWhen: onGetCall } ); ``` ## 拦截器执行顺序 ::: warning 请求拦截器与响应拦截器的执行顺序**相反** 请求拦截器按**逆序**执行(LIFO——后进先出)。**最后**添加的请求拦截器**最先**执行。 响应拦截器按**添加顺序**执行(FIFO——先进先出)。**最先**添加的响应拦截器**最先**执行。 ::: 下面的示例展示了三个请求拦截器和三个响应拦截器的完整执行顺序: ```js const instance = axios.create(); const interceptor = (id) => (base) => { console.log(id); return base; }; instance.interceptors.request.use(interceptor("Request Interceptor 1")); instance.interceptors.request.use(interceptor("Request Interceptor 2")); instance.interceptors.request.use(interceptor("Request Interceptor 3")); instance.interceptors.response.use(interceptor("Response Interceptor 1")); instance.interceptors.response.use(interceptor("Response Interceptor 2")); instance.interceptors.response.use(interceptor("Response Interceptor 3")); // 控制台输出: // Request Interceptor 3 // Request Interceptor 2 // Request Interceptor 1 // [发起 HTTP 请求] // Response Interceptor 1 // Response Interceptor 2 // Response Interceptor 3 ``` ## 多个拦截器 你可以在同一个请求或响应上添加多个拦截器,同一拦截器链中的多个拦截器遵循以下规则: - 每个拦截器都会执行 - 请求拦截器按照后进先出(LIFO)的顺序执行 - 响应拦截器按照添加顺序(FIFO)执行 - 只返回最后一个拦截器的结果 - 每个拦截器接收其前驱拦截器的结果 - 当成功回调中的拦截器抛出错误时 - 后续的成功回调拦截器不会被调用 - 后续的错误回调拦截器会被调用 - 一旦被捕获,后续的成功回调拦截器将再次被调用(与 Promise 链的行为一致) ::: tip 要深入了解拦截器的工作原理,可以查阅[这里](https://github.com/axios/axios/blob/v1.x/test/specs/interceptors.spec.js)的测试用例。 ::: axios-axios-2d06f96/docs/zh/pages/advanced/multipart-form-data-format.md000066400000000000000000000134031521272452000262370ustar00rootroot00000000000000# multipart/form-data 格式 axios 支持以 `multipart/form-data` 格式发送请求,这种格式常用于文件上传。要以该格式发送请求,需要创建一个 `FormData` 对象并向其追加数据,然后将 `FormData` 对象传入 axios 请求配置的 `data` 属性。 ```js const formData = new FormData(); formData.append('foo', 'bar'); axios.post('https://httpbin.org/post', formData); ``` 对于浏览器、Web Worker 或 React Native 的 `FormData`,不要手动设置 `Content-Type` 请求头;这些运行时会自行添加 multipart boundary。 在 Node.js 中,可以使用 `form-data` 库,如下所示: ```js const FormData = require('form-data'); const form = new FormData(); form.append('my_field', 'my value'); form.append('my_buffer', Buffer.alloc(10)); form.append('my_file', fs.createReadStream('/foo/bar.jpg')); axios.post('https://example.com', form); ``` ## 自动序列化为 FormData 从 v0.27.0 起,如果请求的 Content-Type 请求头设置为 `multipart/form-data`,axios 支持自动将对象序列化为 FormData 对象。这意味着你可以直接将 JavaScript 对象传入 axios 请求配置的 `data` 属性。例如,向 POST 请求传递数据时: ```js import axios from 'axios'; axios .post( 'https://httpbin.org/post', { x: 1 }, { headers: { 'Content-Type': 'multipart/form-data', }, } ) .then(({ data }) => console.log(data)); ``` 在 Node.js 构建中,默认使用 ([`form-data`](https://github.com/form-data/form-data)) 作为 polyfill。你可以通过设置 `env.FormData` 配置变量来覆盖 FormData 类,但大多数情况下不需要这样做: ```js const axios = require('axios'); var FormData = require('form-data'); axios .post( 'https://httpbin.org/post', { x: 1, buf: Buffer.alloc(10) }, { headers: { 'Content-Type': 'multipart/form-data', }, } ) .then(({ data }) => console.log(data)); ``` ## Node.js `FormData` 的请求头策略 当你传入一个暴露 `getHeaders()` 的 Node.js `FormData` 对象(例如 [`form-data`](https://github.com/form-data/form-data) 包)时,axios 默认会将它返回的所有请求头复制到请求上。这保留了 v1 的兼容性,但如果 `FormData` 对象来自不可信来源,可能会出问题——`getHeaders()` 可能覆盖 `Authorization` 等请求头或注入任意请求头。 设置 `formDataHeaderPolicy: 'content-only'` 可**只**从 `getHeaders()` 复制 `Content-Type` 和 `Content-Length`,再通过请求的 `headers` 配置显式设置其他请求头: ```js await axios.post("https://example.com/upload", form, { formDataHeaderPolicy: "content-only", headers: { Authorization: "Bearer my-token", }, }); ``` 默认值为 `'legacy'`。详见请求配置参考中的 [`formDataHeaderPolicy`](/pages/advanced/request-config#formdataheaderpolicy)。 ## 支持的特殊结尾 axios FormData 序列化器支持以下特殊结尾,用于执行对应操作: - `{}` - 使用 JSON.stringify 序列化该值 - `[]` - 将类数组对象展开为具有相同键的独立字段 ::: warning 注意:展开/扩展操作默认应用于数组和 FileList 对象 ::: ## 配置 FormData 序列化器 FormData 序列化器通过 `config.formSerializer` 对象属性支持以下额外选项,用于处理特殊情况: - `visitor: Function` - 用户自定义的访问者函数,将递归调用以按照自定义规则将数据对象序列化为 FormData 对象。 - `dots: boolean = false` - 使用点号表示法代替方括号来序列化数组和对象; - `metaTokens: boolean = true` - 在 FormData 键中添加特殊结尾(如 `user{}: '{"name": "John"}'`)。后端 body 解析器可以利用此元信息自动将值解析为 JSON。 - `indexes: null|false|true = false` - 控制如何为扁平类数组对象的展开键添加索引 - `null` - 不添加方括号(`arr: 1`,`arr: 2`,`arr: 3`) - `false`(默认)- 添加空方括号(`arr[]: 1`,`arr[]: 2`,`arr[]: 3`) - `true` - 添加带索引的方括号(`arr[0]: 1`,`arr[1]: 2`,`arr[2]: 3`) - `maxDepth: number = 100` - 序列化器递归的最大对象嵌套深度。如果输入超过此深度,将抛出 `code: 'ERR_FORM_DATA_DEPTH_EXCEEDED'` 的 `AxiosError`。这可以保护服务端应用免受深层嵌套载荷的 DoS 攻击。设置为 `Infinity` 可禁用此限制。 ```js // 当 schema 确实需要超过 100 层嵌套时,可提高限制: axios.postForm('/api', data, { formSerializer: { maxDepth: 200 } }); ``` ::: warning 安全提示 默认限制 100 是有意为之。将客户端控制的 JSON 作为 `data` 转发给 axios 的服务端代码,如果没有此保护,容易发生调用栈溢出。除非你的 schema 确实需要,否则不要提高 `maxDepth`。 ::: 例如,对于以下对象: ```js const obj = { x: 1, arr: [1, 2, 3], arr2: [1, [2], 3], users: [ { name: 'Peter', surname: 'Griffin' }, { name: 'Thomas', surname: 'Anderson' }, ], 'obj2{}': [{ x: 1 }], }; ``` axios 序列化器内部将执行以下步骤: ```js const formData = new FormData(); formData.append('x', '1'); formData.append('arr[]', '1'); formData.append('arr[]', '2'); formData.append('arr[]', '3'); formData.append('arr2[0]', '1'); formData.append('arr2[1][0]', '2'); formData.append('arr2[2]', '3'); formData.append('users[0][name]', 'Peter'); formData.append('users[0][surname]', 'Griffin'); formData.append('users[1][name]', 'Thomas'); formData.append('users[1][surname]', 'Anderson'); formData.append('obj2{}', '[{"x":1}]'); ``` axios 支持以下快捷方法:`postForm`、`putForm`、`patchForm`,它们分别对应相应的 HTTP 方法,并预设 `Content-Type` 请求头为 `multipart/form-data`。 axios-axios-2d06f96/docs/zh/pages/advanced/progress-capturing.md000066400000000000000000000032711521272452000247200ustar00rootroot00000000000000# 进度捕获 axios 同时支持在浏览器和 Node.js 环境中捕获请求的上传/下载进度。进度事件的触发频率被限制为每秒最多 3 次,以避免浏览器被过多的进度事件压垮。以下是捕获进度事件的示例: ```js await axios.post(url, data, { onUploadProgress: function (axiosProgressEvent) { /*{ loaded: number; total?: number; progress?: number; // 范围 [0..1] bytes: number; // 自上次触发以来传输的字节数(增量) estimated?: number; // 预计剩余时间(秒) rate?: number; // 上传速度(字节/秒) upload: true; // 上传标识 }*/ }, onDownloadProgress: function (axiosProgressEvent) { /*{ loaded: number; total?: number; progress?: number; bytes: number; estimated?: number; rate?: number; // 下载速度(字节/秒) download: true; // 下载标识 }*/ }, }); ``` 你也可以在 Node.js 中将上传和下载进度事件流式传输到可读流,以便以自定义方式显示进度。以下是流式传输进度事件的示例: ```js const { data } = await axios.post(SERVER_URL, readableStream, { onUploadProgress: ({ progress }) => { console.log((progress * 100).toFixed(2)); }, headers: { "Content-Length": contentLength, }, maxRedirects: 0, // 避免缓冲整个流 }); ``` ::: warning Node.js 环境目前不支持捕获 FormData 上传进度 ::: ::: danger 建议通过设置 `maxRedirects: 0` 来禁用重定向,以便在 Node.js 环境中上传流,因为 `follow-redirects` 包会不遵循"背压"算法而将整个流缓冲到内存中 ::: axios-axios-2d06f96/docs/zh/pages/advanced/promises.md000066400000000000000000000040601521272452000227200ustar00rootroot00000000000000# Promise axios 基于原生 ES6 Promise API 构建。每个 axios 请求都返回一个 Promise,该 Promise 解析为响应对象或以错误拒绝。如果你的环境不支持 ES6 Promise,需要使用 polyfill,例如 [es6-promise](https://github.com/stefanpenner/es6-promise)。 ## then / catch / finally 由于 axios 返回的是标准 Promise,你可以使用 `.then()`、`.catch()` 和 `.finally()` 来处理结果: ```js axios.get("/api/users") .then((response) => { console.log(response.data); }) .catch((error) => { console.error("Request failed:", error.message); }) .finally(() => { console.log("Request finished"); }); ``` ## async / await 大多数代码库推荐使用 `async/await`,它使异步代码读起来像同步代码: ```js async function fetchUser(id) { try { const response = await axios.get(`/api/users/${id}`); return response.data; } catch (error) { console.error("Failed to fetch user:", error.message); throw error; } } ``` ## 并行请求 由于 axios 返回标准 Promise,你可以使用 `Promise.all` 同时发起多个请求,并等待所有请求完成: ```js const [users, posts] = await Promise.all([ axios.get("/api/users"), axios.get("/api/posts"), ]); console.log(users.data, posts.data); ``` ::: tip `Promise.all` 会在任何一个请求失败时立即 reject。如果你希望处理部分失败的情况,请改用 `Promise.allSettled`。 ::: ```js const results = await Promise.allSettled([ axios.get("/api/users"), axios.get("/api/posts"), ]); results.forEach((result) => { if (result.status === "fulfilled") { console.log(result.value.data); } else { console.error("Request failed:", result.reason.message); } }); ``` ## 链式请求 可以链式调用 `.then()` 来顺序执行请求,将上一个请求的数据传递给下一个: ```js axios.get("/api/user/1") .then(({ data: user }) => axios.get(`/api/posts?userId=${user.id}`)) .then(({ data: posts }) => { console.log("Posts for user:", posts); }) .catch(console.error); ``` axios-axios-2d06f96/docs/zh/pages/advanced/rate-limiting.md000066400000000000000000000036321521272452000236300ustar00rootroot00000000000000# 速率限制 axios 通过 HTTP 适配器在 Node.js 环境中支持带宽限制。你可以限制数据的上传或下载速度,适用于批量操作、后台任务或不希望占满带宽的礼貌抓取等场景。 ## `maxRate` `maxRate` 选项接受一个数字(字节/秒)或一个数组,数组第一个值为上传限制,第二个值为下载限制。使用 `[uploadRate]` 仅限制上传,使用 `[uploadRate, downloadRate]` 同时限制两个方向。传入单个数字时,该限制同时应用于上传和下载。 ```js // 将上传和下载速度均限制为 100 KB/s await axios.get(URL, { maxRate: 100 * 1024 }); // 上传限制 100 KB/s,下载限制 500 KB/s await axios.get(URL, { maxRate: [100 * 1024, 500 * 1024] }); ``` ::: warning `maxRate` 仅支持 Node.js HTTP 适配器,在浏览器环境中无效。 ::: ## 上传速率限制 限制上传速度的同时记录进度: ```js const { data } = await axios.post(SERVER_URL, myBuffer, { onUploadProgress: ({ progress, rate }) => { const percent = (progress * 100).toFixed(1); const kbps = (rate / 1024).toFixed(1); console.log(`Upload [${percent}%] at ${kbps} KB/s`); }, maxRate: [100 * 1024], // 上传限制 100 KB/s }); ``` ## 下载速率限制 限制大响应体的下载速度: ```js const { data } = await axios.get(FILE_URL, { onDownloadProgress: ({ progress, rate }) => { const percent = (progress * 100).toFixed(1); const kbps = (rate / 1024).toFixed(1); console.log(`Download [${percent}%] at ${kbps} KB/s`); }, maxRate: [Infinity, 200 * 1024], // 不限制上传,下载限制 200 KB/s responseType: "arraybuffer", }); ``` ## 同时限制上传和下载 将两个限制作为数组传入,可同时控制两个方向: ```js await axios.post(SERVER_URL, largeBuffer, { maxRate: [50 * 1024, 500 * 1024], // 上传 50 KB/s,下载 500 KB/s }); ``` axios-axios-2d06f96/docs/zh/pages/advanced/request-config.md000066400000000000000000000573721521272452000240300ustar00rootroot00000000000000# 请求配置 请求配置用于配置 HTTP 请求的各项参数。虽然有大量可用选项,但唯一必填的选项是 `url`。如果配置对象中没有 `method` 字段,默认使用 `GET` 方法。 ::: warning 安全提示:解压炸弹防护是可选的 默认情况下 `maxContentLength` 和 `maxBodyLength` 均为 `-1`(不限制)。恶意或被攻陷的服务器可能返回一个很小的 gzip/deflate/brotli/zstd 响应,解压后可达数 GB,从而耗尽 Node.js 进程的内存。 如果你向不完全可信的服务器发起请求,**请设置上限**: ```js axios.defaults.maxContentLength = 10 * 1024 * 1024; // 10 MB axios.defaults.maxBodyLength = 10 * 1024 * 1024; ``` 详见[安全指南](/pages/misc/security)。 ::: ### `url` `url` 是请求的目标 URL,可以是字符串或 `URL` 实例。 ### `method` `method` 是请求使用的 HTTP 方法,默认为 `GET`。 ### `baseURL` `baseURL` 是拼接在 `url` 前面的基础 URL,除非 `url` 是绝对 URL。这对于向同一域名发起请求非常实用,无需在每次请求时重复写域名和 API 版本前缀。 ### `allowAbsoluteUrls` `allowAbsoluteUrls` 决定绝对 URL 是否可以覆盖已配置的 `baseUrl`。设置为 `true`(默认值)时,绝对 `url` 会覆盖 `baseUrl`;设置为 `false` 时,绝对 `url` 始终会拼接在 `baseUrl` 之后。 ### `transformRequest` `transformRequest` 函数允许你在数据发送到服务器之前对其进行修改,仅适用于 `PUT`、`POST`、`PATCH` 和 `DELETE` 请求方法。数组中的最后一个函数必须返回字符串、Buffer、ArrayBuffer、FormData 或 Stream 实例。 ### `transformResponse` `transformResponse` 函数允许你在数据传递给 `then` 或 `catch` 函数之前对响应数据进行修改,函数以响应数据为唯一参数。 ### `parseReviver` `parseReviver` 函数允许你向默认 `transformResponse` 所使用的原生 `JSON.parse()` 调用直接提供一个自定义的 "reviver" 函数。 这对于执行高性能的类型水合(例如将 ISO 字符串转换为 `Temporal` 或 `Date` 对象)或防止解析过程中的精度丢失尤为有用。 在支持 `JSON.parse` reviver `context` 参数的环境中,reviver 函数会接收第三个 `context` 参数,用于访问原始 JSON `source`,从而能够精确转换那些以标准 JavaScript 数字解析时会丢失精度的大整数(BigInt)。 > 注意:`Temporal` 尚未在所有环境中可用,必要时请考虑使用 polyfill。 ```js const client = axios.create({ parseReviver: (key, value, context) => { // 示例:精度安全的 BigInt 解析 if (typeof value === 'number' && context?.source) { const isInteger = Number.isInteger(value); const isUnsafe = !Number.isSafeInteger(value); const isValidIntegerString = /^-?\d+$/.test(context.source); if (isInteger && isUnsafe && isValidIntegerString) { try { return BigInt(context.source); } catch { // 兜底:如果解析失败则返回原始值 } } } // 示例:将日期水合为 Temporal 对象 if ( typeof value === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(value) && typeof Temporal !== 'undefined' && Temporal?.PlainDate ) { return Temporal.PlainDate.from(value); } return value; }, }); ``` ### `headers` `headers` 是随请求发送的 HTTP 请求头,默认将 `Content-Type` 设置为 `application/json`。 ### `params` `params` 是随请求发送的 URL 查询参数,必须是普通对象或 URLSearchParams 对象。如果 `url` 中已包含查询参数,它们将与 `params` 对象合并。 ### `paramsSerializer` `paramsSerializer` 函数允许你在参数发送到服务器之前自定义 `params` 对象的序列化方式,有多个可用选项,详见本页末尾的完整请求配置示例。 #### 严格的 RFC 3986 百分号编码 axios 默认会将 `%3A`、`%24`、`%2C` 和 `%20` 解码回 `:`、`$`、`,` 和 `+`,以提升可读性(其中 `+` 遵循查询字符串中表示空格的 `application/x-www-form-urlencoded` 约定)。这些字符在 [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.4) 中对查询组件而言都是合法的,因此默认输出是正确的。但部分后端要求严格的百分号编码,会拒绝这种可读形式。 可通过 `encode` 选项覆盖默认编码器: ```js // 单次请求:对查询值使用严格的 RFC 3986 百分号编码 axios.get('/foo', { params: { filter: JSON.stringify({ startedAt: '2026-01-23' }) }, paramsSerializer: { encode: encodeURIComponent } }); // 也可在实例默认值中设置 const client = axios.create({ paramsSerializer: { encode: encodeURIComponent } }); ``` ### `data` `data` 是作为请求体发送的数据,可以是字符串、普通对象、Buffer、ArrayBuffer、FormData、Stream 或 URLSearchParams,仅适用于 `PUT`、`POST`、`DELETE` 和 `PATCH` 请求方法。在未设置 `transformRequest` 的情况下,必须是以下类型之一: - string、普通对象、ArrayBuffer、ArrayBufferView、URLSearchParams - 仅浏览器:FormData、File、Blob - React Native:FormData - 仅 Node.js:Stream、Buffer、FormData(form-data 包) 对于浏览器、Web Worker 和 React Native 的 `FormData`,不要手动设置 `Content-Type`;运行时会自行添加 multipart boundary。 对于提供了 `getHeaders()` 方法的 Node.js `FormData` 对象,axios 默认会复制其返回的所有请求头,以保持 v1 兼容性。如果 `FormData` 对象是自定义的或不完全可信,可设置 `formDataHeaderPolicy: 'content-only'`,仅复制 `Content-Type` 和 `Content-Length`,其他请求头则通过请求 `headers` 配置显式设置。 ### `formDataHeaderPolicy` 控制 axios 如何复制 Node.js `FormData#getHeaders()` 返回的请求头。默认值为 `'legacy'`,即复制所有返回的请求头以保留现有的 v1 行为。设置为 `'content-only'` 时,仅从 `getHeaders()` 复制 `Content-Type` 和 `Content-Length`。 ### `timeout` `timeout` 是请求超时前等待的毫秒数。如果请求耗时超过 `timeout`,请求将被中止。 ### `withCredentials` `withCredentials` 属性指示跨域 Access-Control 请求是否应携带 cookie、授权请求头或 TLS 客户端证书等凭据。该设置对同源请求无效。 ### `adapter` `adapter` 允许自定义请求处理方式,便于测试。返回一个 Promise 并提供有效的响应,详见[适配器](/pages/advanced/adapters)文档。我们还提供了多个内置适配器,Node.js 默认使用 `http`,浏览器默认使用 `xhr`。内置适配器列表如下: - fetch - http - xhr 你也可以传入一个适配器数组,axios 将使用当前环境支持的第一个适配器。 ### `auth` `auth` 表示使用 HTTP Basic 认证,并提供凭据。这将设置 `Authorization` 请求头,覆盖任何通过 `headers` 自定义的 `Authorization` 请求头。如果省略 `auth`,Node.js HTTP 和 fetch 适配器可以从请求 URL 中提取 Basic 认证凭据,例如 `https://user:pass@example.com`;URL 中经过百分号编码的凭据会先解码,且 `auth` 始终优先于 URL 中的凭据。在 Node.js HTTP 适配器中,Basic 认证会在同源重定向时保留,并在跨源重定向时剥离。请注意,仅 HTTP Basic 认证可通过此参数配置,Bearer 令牌等请改用自定义 `Authorization` 请求头。 ### `responseType` `responseType` 指示服务器响应的数据类型,可以是以下之一: - arraybuffer - document - json - text - stream - blob(仅浏览器) - formdata(仅 fetch 适配器) ### `responseEncoding` `responseEncoding` 指示解码响应时使用的编码,支持以下选项: - ascii - ASCII - ansi - ANSI - binary - BINARY - base64 - BASE64 - base64url - BASE64URL - hex - HEX - latin1 - LATIN1 - ucs-2 - UCS-2 - ucs2 - UCS2 - utf-8 - UTF-8 - utf8 - UTF8 - utf16le - UTF16LE ::: tip 注意:当 `responseType` 为 `stream` 或客户端请求时,此选项将被忽略 ::: ### `xsrfCookieName` `xsrfCookieName` 是用作 `XSRF` 令牌值的 cookie 名称。 ### `xsrfHeaderName` `xsrfHeaderName` 是用作 `XSRF` 令牌值的请求头名称。 ### `withXSRFToken` `withXSRFToken` 控制 axios 在浏览器请求中是否读取 XSRF cookie 并设置 XSRF 请求头。可选值如下: - `undefined` _(默认)_ — 仅在同源请求时设置 XSRF 请求头。 - `true` — 始终设置 XSRF 请求头,包括跨域请求。 - `false` — 永不设置 XSRF 请求头。 - `(config: InternalAxiosRequestConfig) => boolean | undefined` — 回调函数,按请求决定是否设置,会接收内部 config 对象。 ```ts withXSRFToken: boolean | undefined | ((config: InternalAxiosRequestConfig) => boolean | undefined); ``` ::: warning 跨域 XSRF 与 `withCredentials` `withCredentials` 控制跨站请求是否携带凭据(cookie、HTTP 认证)。在较旧版本的 axios 中,设置 `withCredentials: true` 会隐式地让 axios 在跨域请求中设置 XSRF 请求头。新版本 axios 将这两个关注点分开:要在跨域请求中发送 XSRF 请求头,必须**同时**设置 `withCredentials: true` 和 `withXSRFToken: true`。 ```js axios.get('/user', { withCredentials: true, withXSRFToken: true }); ``` ::: ### `onUploadProgress` `onUploadProgress` 函数允许你监听上传进度。 ### `onDownloadProgress` `onDownloadProgress` 函数允许你监听下载进度。 ### `maxContentLength` `maxContentLength` 属性定义响应内容允许的最大字节数。Node.js HTTP 适配器会对缓冲响应和流式响应执行该限制。fetch 适配器会在响应声明了长度、响应流可跟踪,或响应大小可确定时执行该限制。 > ⚠️ **安全提示:** 默认值为 `-1`(不限制)。响应不加限制再加上 gzip/deflate/brotli/zstd 解压,会带来解压炸弹导致的拒绝服务风险。 > 在访问不完全可信的服务器时,请显式设置该限制。 ### `maxBodyLength` `maxBodyLength` 属性定义请求体允许的最大字节数。Node.js HTTP 适配器会执行该限制;fetch 适配器会在请求体长度可确定时执行该限制。 ### `redact` `redact` 属性是一个可选的配置键名数组,用于在 `AxiosError` 通过 `toJSON()` 序列化时对匹配的键进行脱敏。匹配不区分大小写,并会在序列化后的请求配置中递归进行,命中的值会被替换为 `[REDACTED ****]`。 `redact` 仅影响错误序列化,不会修改请求数据、请求头或原始配置对象。 ```js axios.get('/user/12345', { headers: { Authorization: 'Bearer token' }, auth: { username: 'me', password: 'secret' }, redact: ['authorization', 'password'] }).catch((error) => { console.log(error.toJSON().config); }); ``` ### `validateStatus` `validateStatus` 函数允许你覆盖默认的状态码验证逻辑。默认情况下,axios 会在状态码不在 200-299 范围内时拒绝 Promise。你可以提供自定义的 `validateStatus` 函数来覆盖此行为,该函数应在状态码在你希望接受的范围内时返回 `true`。 ### `maxRedirects` `maxRedirects` 属性定义最大重定向次数,设置为 0 时不跟随任何重定向。 ### `beforeRedirect` `beforeRedirect` 函数允许你在请求重定向前对其进行修改,可用于调整重定向时的请求选项、检查最新的响应头或通过抛出错误来取消请求。当 `maxRedirects` 设置为 0 时,不会使用 `beforeRedirect`。 ```js beforeRedirect: (options, { headers }) => { if ( options.hostname === "example.com" && options.protocol === "https:" ) { options.auth = "user:password"; } } ``` ::: warning 安全提示:在重定向时重新注入凭据 `beforeRedirect` 钩子在重定向过程中**敏感请求头被剥离之后**运行。出于安全考虑,`follow-redirects` 库会在协议降级(HTTPS → HTTP)时移除凭据。由于 `beforeRedirect` 在此之后运行,如果不检查目标协议就重新注入凭据,可能会泄露敏感数据。仅对可信的 HTTPS 目标重新添加凭据,避免在被降级的重定向上重新添加凭据。 ::: ### `socketPath` `socketPath` 属性定义用于替代 TCP 连接的 UNIX 套接字路径,例如 `/var/run/docker.sock`,用于向 Docker 守护进程发送请求。`socketPath` 和 `proxy` 只能指定其中一个,如果两者都指定,则使用 `socketPath`。 :::warning 安全提示 设置 `socketPath` 后,请求 URL 中的主机名和端口将被忽略,axios 会直接与指定的 Unix 域套接字通信。如果请求配置中有任何部分来自用户输入(例如在转发或合并请求选项的代理/Webhook 处理程序中),攻击者可以注入 `socketPath` 将流量重定向到特权本地套接字,如 `/var/run/docker.sock`、`/run/containerd/containerd.sock` 或 `/run/systemd/private`,从而完全绕过基于主机名的 SSRF 防护(CWE-918)。应对来自不可信输入的配置进行过滤或仅允许特定键,并/或使用 `allowedSocketPaths`(见下文)限制接受的套接字路径。 ::: ### `allowedSocketPaths` 限制可通过 `socketPath` 使用的套接字路径。接受一个字符串或字符串数组。设置后,axios 会解析 `socketPath` 并与每个条目(同样解析后)比较;若无匹配,请求将以 `ERR_BAD_OPTION_VALUE` 错误码的 `AxiosError` 被拒绝。未设置(默认)时,`socketPath` 行为与以往一致。 ```js const client = axios.create({ allowedSocketPaths: ['/var/run/docker.sock'] }); // 允许 await client.get('http://localhost/v1.45/info', { socketPath: '/var/run/docker.sock' }); // 拒绝 — 不在白名单中 await client.get('http://localhost/pods', { socketPath: '/var/run/kubelet.sock' }); ``` 空数组 (`allowedSocketPaths: []`) 会阻止所有套接字路径。 ### `transport` `transport` 属性定义请求使用的传输方式,适用于通过不同协议(如 `http2`)发起请求的场景。 ### `httpAgent` 和 `httpsAgent` `httpAgent` 和 `httpsAgent` 分别定义在 Node.js 中执行 HTTP 和 HTTPS 请求时使用的自定义代理,可用于添加 `keepAlive` 等默认未启用的选项。 ### `proxy` `proxy` 定义代理服务器的主机名、端口和协议,也可以通过常规的 `http_proxy` 和 `https_proxy` 环境变量来定义代理。 如果你使用环境变量配置代理,还可以定义 `no_proxy` 环境变量,以逗号分隔的方式列出不需要代理的域名。 设置为 `false` 可禁用代理,忽略环境变量。`auth` 表示使用 HTTP Basic 认证连接代理并提供凭据,这将设置 `Proxy-Authorization` 请求头,覆盖任何通过 `headers` 自定义的 `Proxy-Authorization` 请求头。如果代理服务器使用 HTTPS,则必须将协议设置为 `https`。 通过代理转发时,如果用户在 `headers` 中提供了 `Host` 请求头,axios 会保留它(不区分大小写匹配 `host` / `Host` / `HOST`)。这样你就可以指向一个与请求 URL 不同的虚拟主机——例如,访问 `127.0.0.1:4000`,但让代理将请求当作 `example.com` 处理。如果未提供 `Host` 请求头,axios 仍会像以前一样将其默认设为请求 URL 的 `hostname:port`。 对于 `https://` 目标,axios 会通过代理建立 CONNECT 隧道,并与源站执行端到端 TLS。`Proxy-Authorization` 只会发送在 CONNECT 请求上,不会发送到被 TLS 包裹的源站请求中。`httpsAgent` 的 TLS 选项(如 `ca`、`cert`、`key` 和 `rejectUnauthorized`)会转发给生成的隧道代理,因此仍会应用到源站 TLS 连接。如果你提供的是 `HttpsProxyAgent`,axios 会让该代理自行处理隧道。 ```js proxy: { protocol: "https", host: "127.0.0.1", hostname: "localhost", // 如果同时定义了 "host" 和 "hostname",则优先使用 "hostname" port: 9000, auth: { username: "mikeymike", password: "rapunz3l" } }, ``` ### `cancelToken` `cancelToken` 属性允许你创建一个取消令牌,用于取消请求。详见[取消请求](/pages/advanced/cancellation)文档。 ### `signal` `signal` 属性允许你向请求传入一个 `AbortSignal` 实例,从而通过 `AbortController` API 取消请求。 ### `decompress` `decompress` 属性指示是否自动解压响应数据,默认值为 `true`。当当前 Node.js 运行时提供对应的 zlib 解压器时,Node.js HTTP 适配器支持 gzip、deflate、brotli 和 zstd。 ### `insecureHTTPParser` 指示是否使用接受无效 HTTP 请求头的不安全 HTTP 解析器,可用于与不符合规范的 HTTP 实现互通。不建议使用不安全解析器。 请注意,`insecureHTTPParser` 选项仅在 Node.js 12.10.0 及更高版本中可用。请阅读 [Node.js 文档](https://nodejs.org/en/blog/vulnerability/february-2020-security-releases/#strict-http-header-parsing-none)以获取更多信息。完整选项列表见[此处](https://nodejs.org/dist/latest-v12.x/docs/api/http.html#http_http_request_url_options_callback)。 ### `transitional` `transitional` 属性允许你启用或禁用某些过渡性功能,可用选项如下: - `silentJSONParsing`:若设置为 `true` _(默认)_,axios 会在 JSON 解析失败时静默忽略错误,并保留原始响应字符串。设置为 `false` 则会抛出 `SyntaxError`。 ::: tip 重要说明 此选项仅在 `responseType` **显式**设置为 `'json'` 时生效。当未指定 `responseType` 时,axios 会通过 `forcedJSONParsing` 尝试解析为 JSON,若失败则不论此设置如何,都会静默返回原始字符串。如果希望无效 JSON 抛出错误,请同时设置: ```js { responseType: 'json', transitional: { silentJSONParsing: false } } ``` ::: - `forcedJSONParsing`:强制 axios 将响应解析为 JSON,即使响应不是有效的 JSON。适用于返回无效 JSON 的 API。 - `clarifyTimeoutError`:在请求超时时提供更清晰的错误信息,适用于调试超时问题。 - `advertiseZstdAcceptEncoding`:设为 `true` 时,如果当前 Node.js 运行时支持 zstd 解压,axios 会在默认 `Accept-Encoding` 请求头中加入 `zstd`。在受支持且 `decompress` 为 `true` 时,zstd 响应仍会自动解压。 - `legacyInterceptorReqResOrdering`:设置为 true 时使用旧版拦截器请求/响应排序。 ### `env` `env` 属性允许你设置一些配置选项,例如用于自动将数据序列化为 FormData 对象的 FormData 类。 - FormData: window?.FormData || global?.FormData ### `formSerializer` `formSerializer` 选项允许你配置普通对象作为请求 `data` 时如何序列化为 `multipart/form-data`。可用选项: - `visitor` — 对每个值递归调用的自定义访问者函数 - `dots` — 使用点号表示法代替方括号表示法 - `metaTokens` — 保留特殊的键后缀(如 `{}`) - `indexes` — 控制数组键的方括号格式(`null` / `false` / `true`) - `maxDepth` _(默认:`100`)_ — 抛出 `AxiosError`(错误码 `ERR_FORM_DATA_DEPTH_EXCEEDED`)前的最大嵌套深度。设置为 `Infinity` 可禁用。 详见 [multipart/form-data](/pages/advanced/multipart-form-data-format) 页面以及本页末尾的完整请求配置示例。 ### `maxRate` `maxRate` 属性定义上传和/或下载的最大**带宽**(字节/秒)。接受单个数字(同时适用于两个方向)或两元素数组 `[uploadRate, downloadRate]`,每个元素为字节/秒限制。例如,`100 * 1024` 表示 100 KB/s。详见[速率限制](/pages/advanced/rate-limiting)中的示例。 ## 完整请求配置示例 ```js { url: "/posts", method: "get", baseURL: "https://jsonplaceholder.typicode.com", allowAbsoluteUrls: true, transformRequest: [function (data, headers) { return data; }], transformResponse: [function (data) { return data; }], headers: {"X-Requested-With": "XMLHttpRequest"}, params: { postId: 5 }, paramsSerializer: { // 自定义编码函数,以迭代方式逐个序列化键值对。 encode?: (param: string): string => { /* 在此执行自定义操作并返回转换后的字符串 */ }, // 对整个参数进行自定义序列化的函数,允许用户模拟 1.x 之前的行为。 serialize?: (params: Record, options?: ParamsSerializerOptions ), // 配置数组索引在参数中的格式。 // 三种可用选项: // (1) indexes: null(不添加方括号) // (2)(默认)indexes: false(添加空方括号) // (3) indexes: true(添加带索引的方括号) indexes: false, // 序列化参数时的最大对象嵌套深度。超过时抛出 AxiosError // (ERR_FORM_DATA_DEPTH_EXCEEDED)。默认:100。设置为 Infinity 可禁用。 maxDepth: 100 }, data: { firstName: "Fred" }, formDataHeaderPolicy: "legacy", // 另一种将数据发送到请求体的语法,仅适用于 POST 方法,只发送值,不发送键 data: "Country=Brasil&City=Belo Horizonte", timeout: 1000, withCredentials: false, adapter: function (config) { // 在此执行自定义逻辑 }, adapter: "xhr", auth: { username: "janedoe", password: "s00pers3cret" }, responseType: "json", responseEncoding: "utf8", xsrfCookieName: "XSRF-TOKEN", xsrfHeaderName: "X-XSRF-TOKEN", withXSRFToken: boolean | undefined | ((config: InternalAxiosRequestConfig) => boolean | undefined), onUploadProgress: function ({loaded, total, progress, bytes, estimated, rate, upload = true}) { // 在此处理 axios 进度事件 }, onDownloadProgress: function ({loaded, total, progress, bytes, estimated, rate, download = true}) { // 在此处理 axios 进度事件 }, maxContentLength: 2000, maxBodyLength: 2000, redact: ['authorization', 'password'], validateStatus: function (status) { return status >= 200 && status < 300; }, maxRedirects: 21, beforeRedirect: (options, { headers }) => { if (options.hostname === "typicode.com") { options.auth = "user:password"; } }, socketPath: null, allowedSocketPaths: null, transport: undefined, httpAgent: new http.Agent({ keepAlive: true }), httpsAgent: new https.Agent({ keepAlive: true }), proxy: { protocol: "https", host: "127.0.0.1", // hostname: "127.0.0.1" // 如果同时定义了 "host" 和 "hostname",则优先使用 "hostname" port: 9000, auth: { username: "mikeymike", password: "rapunz3l" } }, cancelToken: new CancelToken(function (cancel) { cancel("Operation has been canceled."); }), signal: new AbortController().signal, decompress: true, insecureHTTPParser: undefined, transitional: { silentJSONParsing: true, forcedJSONParsing: true, clarifyTimeoutError: false, advertiseZstdAcceptEncoding: false, legacyInterceptorReqResOrdering: true, }, env: { FormData: window?.FormData || global?.FormData }, formSerializer: { // 自定义访问者函数,用于序列化表单值 visitor: (value, key, path, helpers) => {}; // 使用点号表示法代替方括号格式 dots: boolean; // 在参数键中保留特殊结尾(如 {}) metaTokens: boolean; // 使用数组索引格式: // null - 不添加方括号 // false - 添加空方括号 // true - 添加带索引的方括号 indexes: boolean; // 最大对象嵌套深度。超过时抛出 AxiosError (ERR_FORM_DATA_DEPTH_EXCEEDED)。 // 默认:100。设置为 Infinity 可禁用。 maxDepth: 100; }, maxRate: [ 100 * 1024, // 上传限制 100KB/s 100 * 1024 // 下载限制 100KB/s ] } ``` axios-axios-2d06f96/docs/zh/pages/advanced/request-method-aliases.md000066400000000000000000000125571521272452000254560ustar00rootroot00000000000000# 请求别名 axios 提供了一组发起 HTTP 请求的别名方法,这些别名是 `request` 方法的快捷方式,设计简洁、使用方便。 axios 尽量遵循 RFC 7231 和 RFC 5789 规范,别名方法与这些规范中定义的 HTTP 方法保持一致。 ### `axios` axios 可以通过仅传入配置对象来发起 HTTP 请求,完整的配置对象文档见[此处](/pages/advanced/request-config)。 ```ts axios(url: string | AxiosRequestConfig, config?: AxiosRequestConfig); ``` ## 方法别名 以下是可用的请求别名方法: ### `request` `request` 方法是发起 HTTP 请求的主方法,接受一个配置对象并返回解析为响应对象的 Promise,可用于发起任意类型的 HTTP 请求。 ```ts axios.request(config: AxiosRequestConfig): AxiosResponse; ``` ### `get` `get` 方法用于发起 GET 请求,接受 URL 和可选配置对象,返回解析为响应对象的 Promise。 ```ts axios.get(url: string, config?: AxiosRequestConfig): AxiosResponse; ``` ### `delete` `delete` 方法用于发起 DELETE 请求,接受 URL 和可选配置对象,返回解析为响应对象的 Promise。 ```ts axios.delete(url: string, config?: AxiosRequestConfig): AxiosResponse; ``` ### `head` `head` 方法用于发起 HEAD 请求,接受 URL 和可选配置对象,返回解析为响应对象的 Promise。 ```ts axios.head(url: string, config?: AxiosRequestConfig): AxiosResponse; ``` ### `options` `options` 方法用于发起 OPTIONS 请求,接受 URL 和可选配置对象,返回解析为响应对象的 Promise。 ```ts axios.options(url: string, config?: AxiosRequestConfig): AxiosResponse; ``` ### `post` `post` 方法用于发起 POST 请求,接受 URL、可选数据对象和可选配置对象,返回解析为响应对象的 Promise。 ```ts axios.post(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ### `put` `put` 方法用于发起 PUT 请求,接受 URL、可选数据对象和可选配置对象,返回解析为响应对象的 Promise。 ```ts axios.put(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ### `patch` `patch` 方法用于发起 PATCH 请求,接受 URL、可选数据对象和可选配置对象,返回解析为响应对象的 Promise。 ```ts axios.patch(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ### `query` `query` 方法用于发起 QUERY 请求,这是一种安全且幂等的、可以携带请求体的方法。它接受 URL、可选数据对象和可选配置对象,返回解析为响应对象的 Promise。当读取类操作的参数过于复杂或敏感、不适合放在 URL 中时,可以使用该方法。 ```ts axios.query(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ```js // 将复杂的搜索条件作为请求体发送 const { data } = await axios.query("/api/search", { selector: ["name", "email"], filter: { active: true, role: "admin" }, }); ``` ::: warning 草案规范 QUERY 方法目前由 IETF 的 [Internet-Draft](https://datatracker.ietf.org/doc/draft-ietf-httpbis-safe-method-w-body/) 定义,尚未成为正式标准。其语义乃至方法名称都可能在最终发布前发生变化,并且服务器、代理和 CDN 的支持情况参差不齐。在用于生产环境之前,请确认你的整个链路都能够正确处理 `QUERY` 请求。 ::: ### `getUri` `getUri` 方法返回给定配置在不实际发起请求的情况下会发送的 URL。它会应用 `baseURL`、`paramsSerializer` 和 `params`,因此你拿到的字符串与 axios 实际发出的 URL 相同。可用于构建链接、调试序列化逻辑,或在另一个请求中复用解析后的 URL。 ```ts axios.getUri(config?: AxiosRequestConfig): string; ``` ```js const url = axios.getUri({ url: "/users", baseURL: "https://api.example.com", params: { active: true, role: "admin" }, }); // "https://api.example.com/users?active=true&role=admin" ``` ::: tip 在实例上调用 `getUri`(`instance.getUri(config)`)会继承该实例的 `baseURL`、`params` 和 `paramsSerializer` 默认值。 ::: ## 表单数据快捷方法 这些方法与上述对应方法等价,但会预设 `Content-Type` 为 `multipart/form-data`,是上传文件或提交 HTML 表单的推荐方式。 ### `postForm` ```ts axios.postForm(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ```js // 从浏览器文件输入框上传文件 await axios.postForm("/api/upload", { file: document.querySelector("#fileInput").files[0], description: "Profile photo", }); ``` ### `putForm` ```ts axios.putForm(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ```js // 用表单数据替换资源 await axios.putForm("/api/users/1/avatar", { avatar: document.querySelector("#avatarInput").files[0], }); ``` ### `patchForm` ```ts axios.patchForm(url: string, data?: D, config?: AxiosRequestConfig): AxiosResponse; ``` ```js // 使用表单数据更新特定字段 await axios.patchForm("/api/users/1", { displayName: "New Name", avatar: document.querySelector("#avatarInput").files[0], }); ``` ::: tip `postForm`、`putForm` 和 `patchForm` 接受与基础方法相同的所有数据类型——普通对象、`FormData`、`FileList` 以及 `HTMLFormElement`。更多示例请参阅[文件上传](/pages/advanced/file-posting)。 ::: axios-axios-2d06f96/docs/zh/pages/advanced/response-schema.md000066400000000000000000000035421521272452000241570ustar00rootroot00000000000000# 响应结构 每个 axios 请求都会解析为具有以下结构的响应对象,在浏览器和 Node.js 环境中保持一致。 ```js { // 服务器提供的响应数据。 // 使用 `transformResponse` 时,这将是最后一次转换的结果。 data: {}, // 服务器响应的 HTTP 状态码(如 200、404、500)。 status: 200, // 与状态码对应的 HTTP 状态消息(如 "OK"、"Not Found")。 statusText: "OK", // 服务器发送的响应头。 // 响应头名称均为小写,可通过方括号或点号表示法访问。 headers: {}, // 本次请求使用的 axios 配置,包括 baseURL、headers、timeout、params 及其他选项。 config: {}, // 底层请求对象。 // 在 Node.js 中:最后一个 `http.ClientRequest` 实例(经过任何重定向后)。 // 在浏览器中:`XMLHttpRequest` 实例。 request: {}, } ``` ## 访问响应字段 实际使用中,你通常只需要解构出所需的部分: ```js const { data, status, headers } = await axios.get("/api/users/1"); console.log(status); // 200 console.log(headers["content-type"]); // "application/json; charset=utf-8" console.log(data); // { id: 1, name: "Jay", email: "jay@example.com" } ``` ## 检查状态码 axios 默认对任何 2xx 响应 resolve Promise,对超出该范围的响应 reject Promise。可以通过 `validateStatus` 配置选项自定义此行为: ```js const response = await axios.get("/api/resource", { validateStatus: (status) => status < 500, // 500 以下的所有状态码均 resolve }); ``` ## 访问响应头 无论服务器如何发送,所有响应头名称均为小写: ```js const response = await axios.get("/api/resource"); // 以下两种写法等价 const contentType = response.headers["content-type"]; const contentType2 = response.headers.get("content-type"); ``` axios-axios-2d06f96/docs/zh/pages/advanced/retry.md000066400000000000000000000070711521272452000222310ustar00rootroot00000000000000# 重试与错误恢复 网络请求可能因瞬时原因而失败——服务器抖动、短暂的网络中断或限流响应。在拦截器中实现重试策略,可以让你透明地处理这些失败,无需在业务代码中添加繁琐的重试逻辑。 ## 基本重试(使用响应拦截器) 最简单的方式是捕获特定错误状态码,并在有限次数内立即重新发送原始请求: ```js import axios from "axios"; const api = axios.create({ baseURL: "https://api.example.com" }); const MAX_RETRIES = 3; api.interceptors.response.use( (response) => response, async (error) => { const config = error.config; // 仅在网络错误或 5xx 服务器错误时重试 const shouldRetry = !error.response || (error.response.status >= 500 && error.response.status < 600); if (!shouldRetry) { return Promise.reject(error); } config._retryCount = config._retryCount ?? 0; if (config._retryCount >= MAX_RETRIES) { return Promise.reject(error); } config._retryCount += 1; return api(config); } ); ``` ## 指数退避 失败后立即重试可能会使本已压力过大的服务器雪上加霜。指数退避策略会在每次重试之间等待逐渐增长的时间: ```js const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); api.interceptors.response.use( (response) => response, async (error) => { const config = error.config; const shouldRetry = !error.response || (error.response.status >= 500 && error.response.status < 600); if (!shouldRetry) return Promise.reject(error); config._retryCount = config._retryCount ?? 0; if (config._retryCount >= 3) return Promise.reject(error); config._retryCount += 1; // 每次重试前分别等待 200ms、400ms、800ms…… const backoff = 100 * 2 ** config._retryCount; await delay(backoff); return api(config); } ); ``` ## 响应 429(限流)时使用 Retry-After 当服务器返回 `429 Too Many Requests` 时,通常会在响应头中包含 `Retry-After` 字段,明确告知你需要等待多长时间: ```js api.interceptors.response.use( (response) => response, async (error) => { const config = error.config; if (error.response?.status !== 429) return Promise.reject(error); config._retryCount = config._retryCount ?? 0; if (config._retryCount >= 3) return Promise.reject(error); config._retryCount += 1; const retryAfterHeader = error.response.headers["retry-after"]; const waitMs = retryAfterHeader ? parseFloat(retryAfterHeader) * 1000 // 请求头单位为秒 : 1000; // 默认等待 1 秒 await new Promise((resolve) => setTimeout(resolve, waitMs)); return api(config); } ); ``` ## 针对特定请求禁用重试 如果某些请求不应被重试(例如不幂等的变更操作,不希望重复执行),可以在请求配置中添加一个标志: ```js // 在重试逻辑之前,在拦截器中添加以下判断: if (config._noRetry) return Promise.reject(error); // 然后在特定调用中禁用重试: await api.post("/payments/charge", body, { _noRetry: true }); ``` ## 结合重试与取消 使用 `AbortController` 可以取消正在等待退避延迟的请求: ```js const controller = new AbortController(); try { await api.get("/api/data", { signal: controller.signal }); } catch (error) { if (axios.isCancel(error)) { console.log("Request aborted by user"); } } // 从其他地方取消请求(以及任何待处理的重试延迟): controller.abort(); ``` axios-axios-2d06f96/docs/zh/pages/advanced/testing.md000066400000000000000000000076411521272452000225440ustar00rootroot00000000000000# 测试 测试使用 axios 发起 HTTP 请求的代码非常简单。推荐的方式是对 axios 本身进行 mock,让测试在不触及真实网络的情况下运行,从而完全控制代码收到的响应内容。 ## 使用 Vitest 或 Jest 进行 Mock Vitest 和 Jest 都支持通过 `vi.mock` / `jest.mock` 进行模块级 mock。你可以 mock 整个 axios 模块,并控制每个方法的返回值: ```js // user-service.js import axios from "axios"; export async function getUser(id) { const { data } = await axios.get(`/api/users/${id}`); return data; } ``` ```js // user-service.test.js import { describe, it, expect, vi } from "vitest"; import axios from "axios"; import { getUser } from "./user-service"; vi.mock("axios"); describe("getUser", () => { it("returns user data on success", async () => { const mockUser = { id: 1, name: "Jay" }; // 让 axios.get 返回我们的假响应 axios.get.mockResolvedValueOnce({ data: mockUser }); const result = await getUser(1); expect(result).toEqual(mockUser); expect(axios.get).toHaveBeenCalledWith("/api/users/1"); }); it("throws when the request fails", async () => { axios.get.mockRejectedValueOnce(new Error("Network error")); await expect(getUser(1)).rejects.toThrow("Network error"); }); }); ``` ## Mock AxiosError 要测试检查 `error.response` 的错误处理路径,可以直接创建一个 `AxiosError` 实例: ```js import axios, { AxiosError } from "axios"; import { vi } from "vitest"; const mockError = new AxiosError( "Not Found", "ERR_BAD_REQUEST", {}, // config {}, // request { // response status: 404, statusText: "Not Found", data: { message: "User not found" }, headers: {}, config: {}, } ); axios.get.mockRejectedValueOnce(mockError); ``` ## 使用 axios-mock-adapter [axios-mock-adapter](https://github.com/ctimmerm/axios-mock-adapter) 是一个在 axios 实例上安装自定义适配器的库,在适配器层面拦截请求。这意味着你的拦截器仍然会执行,因此更适合集成测试。 ```bash npm install --save-dev axios-mock-adapter ``` ```js import axios from "axios"; import MockAdapter from "axios-mock-adapter"; const mock = new MockAdapter(axios); // Mock GET 请求 mock.onGet("/api/users/1").reply(200, { id: 1, name: "Jay" }); // Mock POST 请求 mock.onPost("/api/users").reply(201, { id: 2, name: "New User" }); // Mock 网络错误 mock.onGet("/api/failing").networkError(); // Mock 超时 mock.onGet("/api/slow").timeout(); ``` 在每个测试之间重置 mock: ```js afterEach(() => { mock.reset(); // 清除所有已注册的处理器 }); ``` ## 测试拦截器 要单独测试拦截器,在测试中创建一个全新的 axios 实例: ```js import axios from "axios"; import MockAdapter from "axios-mock-adapter"; describe("auth interceptor", () => { it("attaches a Bearer token to every request", async () => { const instance = axios.create(); const mock = new MockAdapter(instance); // 添加你的拦截器 instance.interceptors.request.use((config) => { config.headers.set("Authorization", "Bearer test-token"); return config; }); // 通过检查 mock 收到的内容来捕获请求配置 let capturedConfig; mock.onGet("/api/data").reply((config) => { capturedConfig = config; return [200, {}]; }); await instance.get("/api/data"); expect(capturedConfig.headers["Authorization"]).toBe("Bearer test-token"); }); }); ``` ## 最佳实践 - 始终在模块级别进行 mock(或使用 `MockAdapter`)——避免在共享实例的单个方法上进行 mock,因为状态可能在测试之间泄漏。 - 优先使用 `mockResolvedValueOnce` / `mockRejectedValueOnce`,而不是 `mockResolvedValue`,以确保测试相互隔离,互不影响。 - 测试重试逻辑时,使用 `MockAdapter`,以便被测拦截器在每次重试时都能真正执行。 axios-axios-2d06f96/docs/zh/pages/advanced/type-script.md000066400000000000000000000047741521272452000233560ustar00rootroot00000000000000# TypeScript `axios` 在 npm 包中通过 `index.d.ts`(ESM)和 `index.d.cts`(CJS)随包提供 TypeScript 类型定义,因此两种模块格式下的类型检查与编辑器支持都开箱即用。 ## 模块解析注意事项 由于 axios 同时以 ESM 默认导出和 CJS `module.exports` 两种方式发布,存在以下配置注意事项: - 推荐使用 `"moduleResolution": "node16"`(由 `"module": "node16"` 隐式指定),需要 TypeScript 4.7 或更高版本。 - 如果你使用 ESM,现有配置应该没有问题。 - 如果你将 TypeScript 编译为 CJS 且无法使用 `"moduleResolution": "node16"`,则必须启用 `esModuleInterop`。 - 如果你使用 TypeScript 对 CJS JavaScript 代码进行类型检查,则只能使用 `"moduleResolution": "node16"`。 ## axios 错误的类型守卫 使用 `axios.isAxiosError` 类型守卫可以在 `catch` 块中安全地收窄 `unknown` 错误。收窄之后,你便可以在完整的类型支持下访问 `error.response`、`error.config` 和 `error.code` 等 axios 专有属性。 ```ts import axios from "axios"; let user: User | null = null; try { const { data } = await axios.get("/user?ID=12345"); user = data.userDetails; } catch (error) { if (axios.isAxiosError(error)) { handleAxiosError(error); } else { handleUnexpectedError(error); } } ``` 使用 `axios.isCancel()` 可以将取消错误收窄为 `CanceledError`: ```ts const controller = new AbortController(); try { await axios.get("/user?ID=12345", { signal: controller.signal }); } catch (error) { if (axios.isCancel(error)) { handleCancellation(error); } } ``` ## 带类型的实例与拦截器 将 `axios.create` 的结果标注为 `AxiosInstance`,并将请求拦截器标注为 `InternalAxiosRequestConfig`,即可对自定义客户端实现端到端的类型检查: ```ts import axios, { AxiosInstance, InternalAxiosRequestConfig } from "axios"; const apiClient: AxiosInstance = axios.create({ baseURL: "https://api.example.com", timeout: 10000, }); apiClient.interceptors.request.use((config: InternalAxiosRequestConfig) => { // 添加认证令牌、记录日志等 return config; }); ``` ## 为响应数据添加类型 axios 的请求方法对响应数据类型是泛型的。向 `axios.get`(以及其他别名)传入类型参数即可为 `response.data` 添加类型: ```ts interface User { id: number; name: string; } const { data } = await apiClient.get("/users/1"); // `data` 的类型为 `User` ``` axios-axios-2d06f96/docs/zh/pages/advanced/x-www-form-urlencoded-format.md000066400000000000000000000102051521272452000265170ustar00rootroot00000000000000# x-www-form-urlencoded 格式 ## URLSearchParams 默认情况下,axios 会将 JavaScript 对象序列化为 `JSON`。如果需要以 [`application/x-www-form-urlencoded` 格式](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST)发送数据,可以使用 [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) API,绝大多数浏览器[已支持](http://www.caniuse.com/#feat=urlsearchparams)该 API,Node.js 从 v10(2018 年发布)开始也[支持](https://nodejs.org/api/url.html#url_class_urlsearchparams)。 ```js const params = new URLSearchParams({ foo: 'bar' }); params.append('extraparam', 'value'); axios.post('/foo', params); ``` ## 查询字符串 对于不支持 `URLSearchParams` 的旧版浏览器或环境,可以使用 [`qs`](https://github.com/ljharb/qs) 库将对象序列化为 `application/x-www-form-urlencoded` 格式。 ```js const qs = require('qs'); axios.post('/foo', qs.stringify({ bar: 123 })); ``` 如需完全控制请求头和方法,可将 `qs.stringify` 的输出作为请求 `data` 传入,并显式设置 `Content-Type`: ```js import qs from 'qs'; const data = { bar: 123 }; const options = { method: 'POST', headers: { 'content-type': 'application/x-www-form-urlencoded' }, data: qs.stringify(data), url: '/foo', }; axios(options); ``` 在非常旧的 Node.js 版本中,可以使用 Node.js 内置的 `querystring` 模块。注意该模块在 Node.js v16 中已废弃——新代码请优先使用 `URLSearchParams` 或 `qs`。 ```js const querystring = require('querystring'); axios.post('https://something.com/', querystring.stringify({ foo: 'bar' })); ``` ::: tip 嵌套对象优先使用 `qs` 如果你需要序列化嵌套对象,建议使用 `qs` 库,因为 `querystring` 方法在该场景下存在[已知问题](https://github.com/nodejs/node-v0.x-archive/issues/1665)。 ::: ## 自动序列化为 URLSearchParams 从 v0.21.0 起,如果将 `Content-Type` 请求头设置为 `application/x-www-form-urlencoded`,axios 会自动将 JavaScript 对象序列化为 `URLSearchParams`。这意味着你可以直接将 JavaScript 对象传入 axios 请求配置的 `data` 属性。例如,向 `POST` 请求传递数据时: ```js const data = { x: 1, arr: [1, 2, 3], arr2: [1, [2], 3], users: [ { name: 'Peter', surname: 'Griffin' }, { name: 'Thomas', surname: 'Anderson' }, ], }; await axios.postForm('https://postman-echo.com/post', data, { headers: { 'content-type': 'application/x-www-form-urlencoded' }, }); ``` `data` 对象将被自动序列化为 `URLSearchParams` 并以 `application/x-www-form-urlencoded` 格式发送。服务器将收到以下数据: ```json { "x": "1", "arr[]": ["1", "2", "3"], "arr2[0]": "1", "arr2[1][0]": "2", "arr2[2]": "3", "users[0][name]": "Peter", "users[0][surname]": "Griffin", "users[1][name]": "Thomas", "users[1][surname]": "Anderson" } ``` 如果你的后端 body 解析器(如 `express.js` 的 `body-parser`)支持嵌套对象解码,服务器端将自动还原为相同的对象结构: ## 参数序列化的深度限制 当 axios 通过 `AxiosURLSearchParams` 序列化 `params` 对象时,会调用与 FormData 序列化器相同的递归遍历器。`maxDepth` 选项(默认 `100`)限制递归的最大深度。超过限制的载荷会抛出 `code: 'ERR_FORM_DATA_DEPTH_EXCEEDED'` 的 `AxiosError`,而不是导致调用栈溢出。 ```js // 如果你的 params 对象确实需要超过 100 层嵌套,可提高限制: axios.get('/api', { params: deepObject, paramsSerializer: { maxDepth: 200 } }); ``` ::: warning 安全提示 除非你的 schema 确实需要,否则不要提高 `maxDepth`。默认值 100 可保护将客户端控制的数据作为 `params` 转发给 axios 的服务端代码免受深层嵌套对象的 DoS 攻击。 ::: ```js var app = express(); app.use(bodyParser.urlencoded({ extended: true })); // 支持编码后的请求体 app.post('/', function (req, res, next) { // 将请求体以 JSON 格式回传 res.send(JSON.stringify(req.body)); }); server = app.listen(3000); ``` axios-axios-2d06f96/docs/zh/pages/getting-started/000077500000000000000000000000001521272452000220755ustar00rootroot00000000000000axios-axios-2d06f96/docs/zh/pages/getting-started/examples/000077500000000000000000000000001521272452000237135ustar00rootroot00000000000000axios-axios-2d06f96/docs/zh/pages/getting-started/examples/commonjs.md000066400000000000000000000102161521272452000260620ustar00rootroot00000000000000# JavaScript 示例 ## 导入库 在 CommonJS 环境中,可以使用 `require` 函数导入库;如果使用 Webpack 或 Rollup 等打包工具,则可以使用 `import` 语句。 #### 不使用打包工具 ```js const axios = require("axios"); ``` #### 使用打包工具(webpack、rollup、vite 等) ```js import axios from "axios"; ``` ## 使用 then/catch/finally axios 的核心返回的是一个 Promise,你可以使用 `then`、`catch` 和 `finally` 回调来处理响应数据、错误以及请求完成的逻辑。 ### GET 请求 ```js axios .get("https://jsonplaceholder.typicode.com/posts", { params: { postId: 5, }, }) .then((response) => { console.log(response.data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Request completed"); }); ``` ### POST 请求 ```js axios .post("https://jsonplaceholder.typicode.com/posts", { title: "foo", body: "bar", userId: 1, }) .then((response) => { console.log(response.data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Request completed"); }); ``` ### PUT 请求 ```js axios .put("https://jsonplaceholder.typicode.com/posts/1", { title: "foo", body: "bar", userId: 1, }) .then((response) => { console.log(response.data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Request completed"); }); ``` ### PATCH 请求 ```js axios .patch("https://jsonplaceholder.typicode.com/posts/1", { title: "foo", }) .then((response) => { console.log(response.data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Request completed"); }); ``` ### DELETE 请求 ```js axios .delete("https://jsonplaceholder.typicode.com/posts/1") .then((response) => { console.log(response.data); }) .catch((error) => { console.error(error); }) .finally(() => { console.log("Request completed"); }); ``` ## 使用 async/await 处理 Promise 的另一种方式是使用 `async` 和 `await`,配合 try/catch/finally 块来处理错误和完成逻辑。这种写法可以让代码更加清晰易读,同时有效避免所谓的"回调地狱"。 ::: tip 注意:async/await 属于 ECMAScript 2017 规范,Internet Explorer 及部分旧版浏览器不支持,使用时请注意兼容性。 ::: ### GET 请求 ```js const getPosts = async () => { try { const response = await axios.get( "https://jsonplaceholder.typicode.com/posts", { params: { postId: 5, }, } ); console.log(response.data); } catch (error) { console.error(error); } finally { console.log("Request completed"); } }; ``` ### POST 请求 ```js const createPost = async () => { try { const response = await axios.post( "https://jsonplaceholder.typicode.com/posts", { title: "foo", body: "bar", userId: 1, } ); console.log(response.data); } catch (error) { console.error(error); } finally { console.log("Request completed"); } }; ``` ### PUT 请求 ```js const updatePost = async () => { try { const response = await axios.put( "https://jsonplaceholder.typicode.com/posts/1", { title: "foo", body: "bar", userId: 1, } ); console.log(response.data); } catch (error) { console.error(error); } finally { console.log("Request completed"); } }; ``` ### PATCH 请求 ```js const updatePost = async () => { try { const response = await axios.patch( "https://jsonplaceholder.typicode.com/posts/1", { title: "foo", } ); console.log(response.data); } catch (error) { console.error(error); } finally { console.log("Request completed"); } }; ``` ### DELETE 请求 ```js const deletePost = async () => { try { const response = await axios.delete( "https://jsonplaceholder.typicode.com/posts/1" ); console.log(response.data); } catch (error) { console.error(error); } finally { console.log("Request completed"); } }; ``` axios-axios-2d06f96/docs/zh/pages/getting-started/examples/typescript.md000066400000000000000000000064701521272452000264520ustar00rootroot00000000000000# TypeScript 示例 ## 导入类型 axios 内置了 TypeScript 类型定义,你可以直接从 `"axios"` 导入所需的类型: ```ts import axios from "axios"; import type { AxiosRequestConfig, AxiosResponse, AxiosError } from "axios"; ``` ## 为请求标注类型 在响应上使用泛型参数,告知 TypeScript 数据的具体结构: ```ts import axios from "axios"; type Post = { userId: number; id: number; title: string; body: string; }; const response = await axios.get("https://jsonplaceholder.typicode.com/posts/1"); console.log(response.data.title); // TypeScript 知道这是一个字符串 ``` ## 为函数标注类型 将请求封装在函数中,并明确声明返回类型,以获得最佳的类型安全性: ```ts import axios, { AxiosResponse } from "axios"; type Post = { userId: number; id: number; title: string; body: string; }; const getPost = async (id: number): Promise => { const response = await axios.get( `https://jsonplaceholder.typicode.com/posts/${id}` ); return response.data; }; ``` ## 为 POST 请求标注类型 你可以同时为请求体和预期响应标注类型: ```ts type CreatePostBody = { title: string; body: string; userId: number; }; type CreatePostResponse = CreatePostBody & { id: number }; const createPost = async (data: CreatePostBody): Promise => { const response = await axios.post( "https://jsonplaceholder.typicode.com/posts", data ); return response.data; }; ``` ## 带类型的 axios 实例 创建一个带类型的实例,将 baseURL 和请求头内置其中: ```ts import axios from "axios"; import type { AxiosInstance } from "axios"; const api: AxiosInstance = axios.create({ baseURL: "https://api.example.com", timeout: 5000, }); ``` ## 带类型的拦截器 在 v1.x 中,请求拦截器应使用 `InternalAxiosRequestConfig`(而非 `AxiosRequestConfig`): ```ts import axios from "axios"; import type { InternalAxiosRequestConfig, AxiosResponse } from "axios"; api.interceptors.request.use((config: InternalAxiosRequestConfig) => { config.headers.set("Authorization", `Bearer ${getToken()}`); return config; }); api.interceptors.response.use( (response: AxiosResponse) => response, (error) => Promise.reject(error) ); ``` ## 为错误标注类型 使用 `axios.isAxiosError()` 对捕获的错误进行类型收窄: ```ts import axios, { AxiosError } from "axios"; type ApiError = { message: string; code: number; }; try { await axios.get("/api/protected-resource"); } catch (error) { if (axios.isAxiosError(error)) { // error.response?.data 的类型为 ApiError console.error(error.response?.data.message); console.error(error.response?.status); } else { throw error; } } ``` ## TypeScript 配置说明 由于 axios 同时发布了 ESM 和 CJS 版本,根据你的配置不同,可能存在以下注意事项: - 推荐设置为 `"moduleResolution": "node16"`(由 `"module": "node16"` 隐式指定),需要 TypeScript 4.7 或更高版本。 - 如果你将 TypeScript 编译为 CJS 且无法使用 `"moduleResolution": "node16"`,请启用 `"esModuleInterop": true`。 - 如果你使用 TypeScript 对 CJS JavaScript 代码进行类型检查,则只能使用 `"moduleResolution": "node16"`。 axios-axios-2d06f96/docs/zh/pages/getting-started/features.md000066400000000000000000000044001521272452000242330ustar00rootroot00000000000000# 功能特性 axios 是一个功能强大的 HTTP 客户端,提供简单易用的 API 来发起 HTTP 请求。它支持所有主流浏览器,在 JavaScript 社区中被广泛使用。以下是 axios 的核心特性,这些特性使其成为你下一个项目的优选方案。 ## 同构(Isomorphic) axios 是一个通用 HTTP 客户端,可在浏览器和 Node.js 中同时使用。这意味着你既可以在前端代码中发起 API 请求,也可以在后端代码中使用 axios,非常适合构建渐进式 Web 应用、单页应用以及服务端渲染应用。 对于同时负责前后端开发的团队,axios 也是绝佳选择。统一使用 axios 发起 HTTP 请求,可以降低代码库的复杂度,保持前后端 API 的一致性。 ## Fetch 支持 axios 对 Fetch API 提供了一流的支持。Fetch API 是 XHR API 的现代替代方案,可通过配置选项启用该适配器。XHR 适配器和 Fetch 适配器使用完全相同的 API,因此无需修改现有代码即可平滑迁移到 Fetch API。 ## 浏览器支持 axios 支持所有主流浏览器及部分较旧的浏览器,包括 Chrome、Firefox、Safari 和 Edge,是构建需要兼容多种浏览器的 Web 应用的理想选择。 ## Node.js 支持 axios 同样支持多个 Node.js 版本,兼容性经过测试,最早可追溯至 v12.x,在无法或不便升级到最新 Node.js 版本的环境中同样可以放心使用。 此外,axios 还有针对 Bun 和 Deno 的冒烟测试,用于验证关键的运行时行为,增强跨运行时兼容性的可信度。 ## 其他特性 - 支持 Promise API - 拦截请求和响应 - 转换请求和响应数据 - AbortController 支持 - 超时设置 - 支持嵌套参数的查询字符串序列化 - 自动将请求体序列化为: - JSON(application/json) - Multipart / FormData(multipart/form-data) - URL 编码表单(application/x-www-form-urlencoded) - 将 HTML 表单数据以 JSON 格式发送 - 自动处理响应中的 JSON 数据 - 支持浏览器和 Node.js 的进度捕获,并提供额外信息(传输速率、剩余时间) - 支持在 Node.js 中设置带宽限制 - 兼容规范的 FormData 和 Blob(包括 Node.js 环境) - 客户端 XSRF 防护支持 axios-axios-2d06f96/docs/zh/pages/getting-started/first-steps.md000066400000000000000000000064551521272452000247140ustar00rootroot00000000000000# 入门指南 欢迎阅读 axios 文档!本指南将帮助你快速上手 axios,并发起第一个 API 请求。如果你是 axios 新手,建议从这里开始。 ## 安装 你可以通过多种方式在项目中使用 axios。最常见的方式是通过 npm 安装,也支持 jsDelivr、unpkg 等 CDN。 #### 使用 npm ```bash npm install axios ``` #### 使用 pnpm ```bash pnpm install axios ``` #### 使用 yarn ```bash yarn add axios ``` #### 使用 bun ```bash bun add axios ``` #### 使用 deno ```bash deno install npm:axios ``` #### 使用 jsDelivr 使用 jsDelivr 时,建议使用压缩版本并固定版本号,以避免意外更新。如需使用最新版本,可以去掉版本号,但强烈不建议在生产环境这样做,因为可能导致应用出现意外变化。 ```html ``` #### 使用 unpkg 使用 unpkg 时,建议使用压缩版本并固定版本号,以避免意外更新。如需使用最新版本,可以去掉版本号,但强烈不建议在生产环境这样做,因为可能导致应用出现意外变化。 ```html ``` ## 导入 axios 安装完成后,你可以使用 `import` 或 `require` 来导入此库: ```js import axios, { isCancel, AxiosError } from "axios"; ``` 也可以使用默认导出,因为命名导出只是从 axios 工厂的再导出: ```js import axios from "axios"; console.log(axios.isCancel("something")); ``` 如果使用 `require` 导入,**只有默认导出可用**: ```js const axios = require("axios"); console.log(axios.isCancel("something")); ``` 某些打包器和 ES6 lint 规则可能需要: ```js import { default as axios } from "axios"; ``` 对于自定义或较旧的环境,如果模块解析行为不正常,可以直接导入预构建包: ```js const axios = require("axios/dist/browser/axios.cjs"); // 浏览器 CommonJS 包(ES2017) // const axios = require("axios/dist/node/axios.cjs"); // node CommonJS 包(ES2017) ``` ## 发起第一个请求 使用 axios 发起请求最少只需要两行代码。你可以通过提供 URL 和请求方法向任意 API 发送请求。例如,向 JSONPlaceholder API 发起一个 GET 请求: ```js import axios from "axios"; const response = await axios.get( "https://jsonplaceholder.typicode.com/posts/1" ); console.log(response.data); ``` axios 提供了简洁的请求 API。你可以使用 `axios.get` 发起 GET 请求,使用 `axios.post` 发起 POST 请求,依此类推。也可以使用 `axios.request` 方法发起任意类型的请求。 ::: tip 在生产环境中设置 `timeout` 如果不设置 `timeout`,停滞的请求可能会无限挂起。可通过请求配置传入: ```js const response = await axios.get("https://example.com/data", { timeout: 5000, // 5 秒 }); ``` 匹配的 `ECONNABORTED` / `ETIMEDOUT` 错误码请参阅[请求配置中的 `timeout`](/pages/advanced/request-config#timeout) 与[错误处理](/pages/advanced/error-handling)。 ::: ## 下一步 现在你已经用 axios 完成了第一个请求,可以继续探索 axios 文档的其余内容。了解更多关于发起请求、处理响应以及在项目中使用 axios 的知识,请查阅文档其他章节。 axios-axios-2d06f96/docs/zh/pages/getting-started/upgrade-guide.md000066400000000000000000000067411521272452000251510ustar00rootroot00000000000000# 升级指南 本指南旨在帮助你将项目从旧版本升级到新版本。建议阅读每个主要版本的发布说明,其中可能包含关于破坏性变更的重要信息。 ## 从 v0.x 升级到 v1.x ### import 语句变更 在 v1.x 中,import 语句改为使用 `default` 导出,你需要将 import 语句更新为如下形式: ```diff - import { axios } from "axios"; + import axios from "axios"; ``` ### 拦截器系统变更 在 v1.x 中,你需要使用 `InternalAxiosRequestConfig` 类型来为 `request` 拦截器的 `config` 参数标注类型。这是因为该参数现在的类型是 `InternalAxiosRequestConfig`,而不再是公开的 `AxiosRequestConfig`。 ```diff - axios.interceptors.request.use((config: AxiosRequestConfig) => { + axios.interceptors.request.use((config: InternalAxiosRequestConfig) => { return config; }); ``` ### 请求头结构变更 在 v1.x 中,请求头的结构已去除 `common` 属性,你需要按如下方式更新相关代码: ```diff - if (request.headers?.common?.Authorization) { - request.headers.common.Authorization = ... + if (request.headers?.Authorization) { + request.headers.Authorization = ... ``` 原本位于 `common`、`get`、`post` 等属性下的默认请求头,现在直接设置在 `axios.defaults.headers` 上: ```diff - axios.defaults.headers.common["Accept"] = "application/json"; + axios.defaults.headers["Accept"] = "application/json"; ``` ### Multipart 表单数据 如果请求包含 `FormData` 数据,`Content-Type: multipart/form-data` 请求头现在会被自动设置,请移除手动设置以避免重复: ```diff - axios.post("/upload", formData, { - headers: { "Content-Type": "multipart/form-data" }, - }); + axios.post("/upload", formData); ``` 如果你明确设置了 `Content-Type: application/json`,axios 现在会自动将数据序列化为 JSON。 ### 参数序列化 v1.x 对 URL 参数的序列化方式进行了若干破坏性变更,主要包括: **`params` 默认会进行百分号编码。** 如果你的后端期望接收 qs 风格的原始方括号编码,可能需要配置自定义序列化器: ```js import qs from 'qs'; axios.create({ paramsSerializer: { serialize: (params) => qs.stringify(params, { arrayFormat: 'brackets' }), }, }); ``` **`params` 中的嵌套对象现在使用方括号表示法**(`foo[bar]=1`)序列化,而不再使用点号表示法。如果你的后端期望点号表示法,请使用自定义序列化器。 **`null` 和 `undefined` 参数**的处理方式现在已统一:`null` 值序列化为空字符串,而 `undefined` 值则被完全忽略。 关于参数序列化配置的完整选项,请参阅[请求配置](/pages/advanced/request-config)页面。 ### 内部模块不再导出 我们决定不再导出 axios 的内部模块,你需要将代码更新为仅使用 axios 的公开 API。此变更旨在简化 API,缩小 axios 的接口范围,使我们能够在不声明破坏性变更的情况下修改内部实现。 请查阅本站的 [API 参考](/pages/advanced/api-reference),获取最新的公开 API 信息。 ### 请求配置 我们对请求配置对象进行了调整,请查阅本站的[配置参考](/pages/advanced/request-config)获取最新信息。 ### 遗漏的破坏性变更 本指南并不详尽,可能未涵盖所有破坏性变更。如果你遇到任何问题,欢迎在 [docs GitHub 仓库](https://github.com/axios/docs)提交 issue,并添加 `breaking change` 标签。 axios-axios-2d06f96/docs/zh/pages/misc/000077500000000000000000000000001521272452000177235ustar00rootroot00000000000000axios-axios-2d06f96/docs/zh/pages/misc/security.md000066400000000000000000000223311521272452000221150ustar00rootroot00000000000000# 安全政策 ## ⚠️ 解压炸弹 / 响应无限缓冲 默认情况下,`maxContentLength` 与 `maxBodyLength` 均为 `-1`(不限制)。恶意或被攻陷的服务器可以返回一个很小的 gzip/deflate/brotli/zstd 压缩响应,解压后体积可达数 GB,耗尽 Node.js 进程的内存。 **如果你向不完全可信的服务器发起请求,必须根据你的业务场景设置合适的 `maxContentLength`(以及 `maxBodyLength`)。** 在流式解压过程中会按分块强制执行该限制,因此只需设置该值即可抵御解压炸弹攻击。 ```js axios.get('https://example.com/data', { maxContentLength: 10 * 1024 * 1024, // 10 MB maxBodyLength: 10 * 1024 * 1024, }); // 或全局设置: axios.defaults.maxContentLength = 10 * 1024 * 1024; axios.defaults.maxBodyLength = 10 * 1024 * 1024; ``` 默认值未被调低是因为调低会静默地影响所有合法的大文件下载。为不可信来源选择合理的上限,应由应用自行负责。 ## 其他安全敏感的选项 以下请求配置选项具有直接的安全影响。它们在[请求配置](/pages/advanced/request-config)中均有完整说明,这里集中列出以便统一查阅。 | 选项 | 风险 | 缓解措施 | | --- | --- | --- | | [`socketPath`](/pages/advanced/request-config#socketpath) | 如果取自不可信输入,攻击者可将流量重定向到 `/var/run/docker.sock` 等特权本地套接字,绕过基于主机名的 SSRF 防护(CWE-918)。 | 对来自不可信输入的配置进行过滤或仅允许特定键。使用 [`allowedSocketPaths`](/pages/advanced/request-config#allowedsocketpaths) 限制可接受的套接字路径。 | | [`beforeRedirect`](/pages/advanced/request-config#beforeredirect) | 在 `follow-redirects` 因协议降级剥离凭据**之后**运行。如果不检查目标协议就重新注入凭据,可能在明文 HTTP 上泄露凭据。 | 仅对可信的 HTTPS 目标重新添加凭据。在为 `auth` 赋值前检查 `options.protocol === "https:"`。 | | [`withXSRFToken`](/pages/advanced/request-config#withxsrftoken) | 设置为 `true` 会在跨域请求中强制设置 XSRF 请求头。较旧的 axios 版本会在 `withCredentials: true` 时隐式启用此行为;新版本要求两个标志同时设置。 | 保持为 `undefined`(仅同源),除非你的后端确实在跨域请求中校验 XSRF。 | | [`redact`](/pages/advanced/request-config#redact) | `AxiosError#toJSON()` 默认会包含请求配置,可能将 `Authorization` 请求头或 `auth` 凭据泄露到错误日志和遥测中。 | 通过 `redact` 数组传入需要遮蔽的配置键名。匹配不区分大小写,且会递归处理。 | | [`formDataHeaderPolicy`](/pages/advanced/request-config#formdataheaderpolicy) | 自定义 `FormData` 的 `getHeaders()` 若返回攻击者可控的值,可能在 Node.js 中覆盖 `Authorization` 等请求头或注入任意请求头。 | 设置为 `'content-only'` 仅复制 `Content-Type` 与 `Content-Length`,再通过请求 `headers` 配置显式设置其他请求头。 | ## 供应链加固:`ignore-scripts` 与生命周期脚本 仓库附带项目级的 `.npmrc`,其中设置了 `ignore-scripts=true`。这会在仓库内运行 `npm install` 或 `npm ci` 时阻止任何直接或传递依赖的 npm 生命周期脚本(`preinstall`、`install`、`postinstall`、`prepare`)执行。详见 [THREATMODEL.md](https://github.com/axios/axios/blob/v1.x/THREATMODEL.md)(威胁 T-S2)了解原因。 由此带来的一个影响:仓库自身的 `prepare` 钩子(用于安装 Husky 的 git 钩子)**不会**自动运行。在你首次安装后,请手动启用 git 钩子: ```bash npm ci npm rebuild husky && npx husky ``` 每次全新检出仓库后只需运行一次这两条命令。后续每次 `npm install` 后**不**需要重新执行。 ::: danger 不要移除 `ignore-scripts=true` 为了"修复"husky 设置而从 `.npmrc` 中移除 `ignore-scripts=true`,会重新打开依赖树中所有其他包的生命周期脚本攻击面。所有 CI 工作流都已使用 `--ignore-scripts` 调用 npm,因此本地行为与 CI 保持一致。 ::: 我们建议在任何将 axios(或其他依赖)引入到处理机密的构建环境的下游项目中,也使用相同的 `ignore-scripts=true` 设置。 ## 验证发布版本 自 `axios` 在 npm 上发布的每一个 tarball 均通过 GitHub Actions 发布,并附带 [npm provenance 证明](https://docs.npmjs.com/generating-provenance-statements),以密码学方式将软件包与生成它的工作流及提交 SHA 绑定。 使用者可在本地验证该证明: ```bash # 验证你 lockfile 中的所有包(包括 axios) npm audit signatures ``` 验证通过仅证明该 tarball 是在 `axios/axios` 的 GitHub Actions 环境中、基于已知 commit 构建的,且在构建至 registry 之间未被篡改。它**不**证明该 commit 中的代码没有 bug。 如果 `npm audit signatures` 针对较新版本的 `axios` 报告缺失或无效的证明,请视为潜在的供应链事件,并通过下方的私密渠道上报。 ## 报告漏洞 如果你认为在本项目中发现了安全漏洞,请按照以下说明向我们报告。我们对所有安全漏洞报告都认真对待。如果你发现的是第三方库中的漏洞,请向该库的维护者报告。 ## 报告流程 请勿通过公开的 GitHub issue 报告安全漏洞。请使用 GitHub 官方安全渠道,提交 [security advisory(安全公告)](https://github.com/axios/axios/security/advisories/new)。 ## 披露政策 收到安全漏洞报告后,我们将指定一名主要负责人。该负责人负责确认问题、确定受影响版本、评估严重程度、开发并发布修复,并与报告人协调公开披露。 ### 60 天解决与披露承诺 我们承诺 **在收到初次报告后 60 个自然日内解决并公开披露每一个有效的安全公告**,计时从通过 [GitHub 安全公告渠道](https://github.com/axios/axios/security/advisories/new) 接到报告的那一刻起算。 这 60 天是对报告人和下游使用者的硬性承诺,是底线而非目标。如果我们无法在期限内发布修复,也会在第 60 天公开发布公告,提供当前可行的最佳缓解指引,让使用者能够采取行动。 **60 天窗口内的各里程碑:** | 天 | 里程碑 | | ----- | ---------------------------------------------------------------------------------------------------- | | 0 | 收到报告。在 GitHub 上开启私密公告。 | | ≤ 3 | 向报告人发送确认收到。分流决定:在范围内 / 不在范围内 / 重复 / 需补充信息。 | | ≤ 10 | 评估严重程度(在适用时使用 CVSS v4)。确认受影响版本。如有必要,经由 GitHub 申请 CVE。 | | ≤ 45 | 修复已开发、评审、测试完毕。在私有分支上准备候选版本。向报告人提供预览以便验证。 | | ≤ 60 | 已修复版本发布至 npm。公开公告 + CVE 发布。除非报告人另有要求,否则给予署名。更新 CHANGELOG。 | **例外与延期。** - 如果报告人要求缩短禁运期(例如计划在会议上披露研究成果),我们会尽量配合。 - 如果修复需要引入破坏性变更、需与主要下游使用者协调、或依赖 `follow-redirects` / `form-data` / `proxy-from-env` 的上游发布,我们可能将期限延长至 60 天以上。任何延期都会在第 60 天通过公告公开披露,并说明修订后的预期时间与原因。 - 如果报告**不在范围内**(例如属于项目 [威胁模型](https://github.com/axios/axios/blob/v1.x/THREATMODEL.md) 中明确列出的 non-goal),我们会在分流窗口内(≤ 3 天)向报告人说明并关闭。不在范围内的报告不会进入 60 天队列。 - **正在被实际利用的漏洞** 按事件处理:修复与公告在补丁验证通过后立即发布,而非按 60 天时间表。 **对报告人的期望。** 在报告处于禁运期时,我们请报告人在以下较早发生的时间点之前不要公开披露:(a) 协调披露的公告发布,或 (b) 第 60 天。如果我们未在 60 天内行动,报告人即可自行披露——我们会将其视为我们的失败,而非报告人的失败。 ## 安全更新 安全更新将在补丁开发和测试完成后尽快发布。我们将通过项目的 GitHub 仓库通知用户,并在项目的 GitHub Releases 页面发布发版说明和安全公告。我们还将弃用所有包含该安全漏洞的版本。 ## 维护者侧事件响应 对于影响维护者账号、工作站或发布基础设施的入侵场景(钓鱼、硬件密钥丢失、异常 tag/发布),项目在 [THREATMODEL.md §3.7](https://github.com/axios/axios/blob/v1.x/THREATMODEL.md#37-incident-response-runbook) 中维护了一份内部事件响应手册。内容涵盖会话吊销、密钥轮换、下游通知、以及取消发布/弃用流程。 ## 安全合作伙伴与致谢 感谢以下安全研究人员与我们合作,共同保障项目的安全: - [Socket Dev](https://socket.dev/) - [GitHub Security Lab](https://securitylab.github.com/) axios-axios-2d06f96/docs/zh/pages/misc/semver.md000066400000000000000000000034241521272452000215510ustar00rootroot00000000000000# 语义化版本 语义化版本是一种版本控制方案,用于传达软件包中变更的性质。它是一套简单的规则和要求,规定了版本号的分配和递增方式。 ## axios 的版本控制 axios 遵循语义化版本方案。这意味着每个 axios 版本都由三个部分组成:主版本号、次版本号和补丁版本号,版本号根据发版中变更的性质递增。 过去,axios 有时可能未严格遵循语义化版本,但未来将更严格地遵循语义化版本方案,以确保用户可以依赖版本号来了解库中变更的性质。 以下是版本方案的简要概述。 ## 版本格式 语义化版本号由三个部分组成: 1. 主版本号(Major) 2. 次版本号(Minor) 3. 补丁版本号(Patch) 版本号写作 `MAJOR.MINOR.PATCH`,每个部分有其特定含义: - **主版本号**:进行不兼容的 API 变更时递增。 - **次版本号**:以向后兼容的方式添加新功能时递增。 - **补丁版本号**:进行向后兼容的缺陷修复时递增。 ## 预发布版本 除版本号的三个部分外,还可以附加预发布版本标识。方式是在补丁版本号后紧跟一个连字符和一系列点号分隔的标识符,例如 `1.0.0-alpha.1`。 预发布版本表示该版本不稳定,可能不满足版本号所指示的预期兼容性要求。预发布版本按标识符的顺序排列,例如 `1.0.0-alpha.1` 早于 `1.0.0-alpha.2`。 ## 版本范围 指定包的版本范围时,可以使用多种运算符来表示可接受的版本范围,可用运算符如下: - `>`:大于 - `<`:小于 - `>=`:大于或等于 - `<=`:小于或等于 - `~`:近似等于 - `^`:兼容 例如,`^1.0.0` 表示接受任何大于或等于 `1.0.0` 且小于 `2.0.0` 的版本。 axios-axios-2d06f96/docs/zh/pages/misc/sponsors.md000066400000000000000000000115141521272452000221350ustar00rootroot00000000000000--- layout: page ---

赞助商

axios 由以下组织提供支持。如果你希望赞助 axios,请访问我们的 open collective 页面了解详情。

{{ capitalizeFirstLetter(sponsor.tier) }}
{{ sponsor.name }}
axios-axios-2d06f96/eslint.config.js000066400000000000000000000023421521272452000174210ustar00rootroot00000000000000import js from '@eslint/js'; import globals from 'globals'; export default [ { ...js.configs.recommended, files: ['lib/**/*.js'], linterOptions: { reportUnusedDisableDirectives: 'off' }, languageOptions: { ecmaVersion: 2018, sourceType: 'module' }, rules: { ...js.configs.recommended.rules, 'no-cond-assign': 0, 'no-useless-assignment': 'off', 'no-unused-vars': [ 'error', { args: 'none', caughtErrors: 'none', varsIgnorePattern: '^_' } ] } }, { files: ['lib/**/*.js'], ignores: [ 'lib/adapters/http.js', 'lib/adapters/xhr.js', 'lib/platform/node/**/*.js', 'lib/platform/browser/**/*.js' ], languageOptions: { globals: { ...globals.browser, ...globals.node, globalThis: 'readonly' } } }, { files: ['lib/adapters/http.js', 'lib/platform/node/**/*.js'], languageOptions: { globals: { ...globals.node, globalThis: 'readonly' } } }, { files: ['lib/adapters/xhr.js', 'lib/platform/browser/**/*.js'], languageOptions: { globals: { ...globals.browser, globalThis: 'readonly' } } } ]; axios-axios-2d06f96/examples/000077500000000000000000000000001521272452000161365ustar00rootroot00000000000000axios-axios-2d06f96/examples/README.md000066400000000000000000000003241521272452000174140ustar00rootroot00000000000000# axios examples To run the examples: 1. `git clone https://github.com/axios/axios.git` 2. `cd axios` 3. `npm install` 4. `npm run build` 5. `npm run examples` 6. [http://localhost:3000](http://localhost:3000) axios-axios-2d06f96/examples/abort-controller/000077500000000000000000000000001521272452000214265ustar00rootroot00000000000000axios-axios-2d06f96/examples/abort-controller/index.html000066400000000000000000000110711521272452000234230ustar00rootroot00000000000000 axios - abort controller example

axios.AbortController

1. Single Request Cancellation

Click "Start Request" to begin a 3-second request. Click "Cancel Request" to abort it.


2. Search-as-you-type (Race Condition Handling)

Type quickly. Previous pending requests will be cancelled automatically.

    axios-axios-2d06f96/examples/abort-controller/server.js000066400000000000000000000010331521272452000232670ustar00rootroot00000000000000export default function (req, res) { let parsedUrl; try { parsedUrl = new URL(req.url, 'http://localhost'); } catch { res.writeHead(400, { 'Content-Type': 'text/plain' }); res.end('Invalid URL'); return; } const delay = parsedUrl.searchParams.get('delay') || 3000; setTimeout(() => { res.writeHead(200, { 'Content-Type': 'text/json', }); res.write( JSON.stringify({ message: 'Response completed successfully after ' + delay + 'ms', }) ); res.end(); }, delay); } axios-axios-2d06f96/examples/all/000077500000000000000000000000001521272452000167065ustar00rootroot00000000000000axios-axios-2d06f96/examples/all/index.html000066400000000000000000000024111521272452000207010ustar00rootroot00000000000000 axios - all example

    axios.all

    User


    Orgs

      axios-axios-2d06f96/examples/amd/000077500000000000000000000000001521272452000166775ustar00rootroot00000000000000axios-axios-2d06f96/examples/amd/index.html000066400000000000000000000016631521272452000207020ustar00rootroot00000000000000 AMD

      AMD

      User

      axios-axios-2d06f96/examples/get/000077500000000000000000000000001521272452000167155ustar00rootroot00000000000000axios-axios-2d06f96/examples/get/index.html000066400000000000000000000024551521272452000207200ustar00rootroot00000000000000 axios - get example

      axios.get

        axios-axios-2d06f96/examples/get/server.js000066400000000000000000000011651521272452000205640ustar00rootroot00000000000000const people = [ { name: 'Matt Zabriskie', github: 'mzabriskie', twitter: 'mzabriskie', avatar: '199035', }, { name: 'Ryan Florence', github: 'rpflorence', twitter: 'ryanflorence', avatar: '100200', }, { name: 'Kent C. Dodds', github: 'kentcdodds', twitter: 'kentcdodds', avatar: '1500684', }, { name: 'Chris Esplin', github: 'deltaepsilon', twitter: 'chrisesplin', avatar: '878947', }, ]; export default function (req, res) { res.writeHead(200, { 'Content-Type': 'application/json', }); res.write(JSON.stringify(people)); res.end(); } axios-axios-2d06f96/examples/improved-network-errors.md000066400000000000000000000037741521272452000233210ustar00rootroot00000000000000# Overview of this document: This document explains a simple approach to make Axios network errors more helpful and human-readable. By default, Axios shows a generic `"Network Error"` message for many failures. This can be confusing because it doesn't explain "what actually went wrong" (e.g., no internet, a timeout, a CORS issue, etc.). Our approach adds clear, categorised error messages for different network issues. --- ==> Problem Axios currently throws the same `Network Error` message for many different cases: - The Internet is disconnected - DNS lookup fails - Server is down or refusing connections - CORS blocked requests - Request timed out These cases all look the same to developers and users, making debugging harder. --> Our Approach — Wrapper / Middleware We created a small wrapper function called `enhanceNetworkError()` that: - Detects Common network problems using `error.code`, `error.message`, and response status. - Adds a new field `error.detailedMessage` with a short, clear explanation. - Assigns a new `error.code` (like `ERR_TIMEOUT`, `ERR_DNS_FAILURE`, etc.). - Works for both browser and Node.js environments. The wrapper is used inside an Axios instance via a Response interceptor. -> How It Works 1. When Axios throws an error, the interceptor catches it. 2. The `enhanceNetworkError()` function checks what type of error it is: - Offline → `ERR_NO_INTERNET` - DNS failure → `ERR_DNS_FAILURE` - Timeout → `ERR_TIMEOUT` - CORS blocked → `ERR_CORS_BLOCKED` - Server-side → `ERR_SERVER` - Client-side → `ERR_CLIENT` - Other → `ERR_NETWORK_GENERIC` 3. It returns a more descriptive error with both `code` and `detailedMessage`. -> Example Usage ```javascript const api = createEnhancedClient({ baseURL: 'https://example.com' }); api .get('/data') .then((res) => console.log(res.data)) .catch((err) => { console.error(err.code); // e.g., ERR_TIMEOUT console.error(err.detailedMessage); // e.g., "The request took too long to respond." }); ``` axios-axios-2d06f96/examples/network_enhanced.js000066400000000000000000000043511521272452000220150ustar00rootroot00000000000000import axios from 'axios'; function enhanceNetworkError(error) { // when Offline (no internet) if (typeof navigator !== 'undefined' && !navigator.onLine) { error.code = 'ERR_NO_INTERNET'; error.detailedMessage = 'No internet connection detected. Please check your connection and try again.'; } // when DNS failure occurs (invalid domain) else if (error.code === 'ENOTFOUND' || /dns/i.test(error.message)) { error.code = 'ERR_DNS_FAILURE'; error.detailedMessage = 'Unable to reach the requested domain. Please verify the URL or your network settings.'; } // when Connection refused by server else if (error.code === 'ECONNREFUSED' || /refused/i.test(error.message)) { error.code = 'ERR_CONNECTION_REFUSED'; error.detailedMessage = 'Connection was refused by the server. It may be temporarily unavailable.'; } // when Request timeout happens else if (error.code === 'ETIMEDOUT' || /timeout/i.test(error.message)) { error.code = 'ERR_TIMEOUT'; error.detailedMessage = 'The request took too long to respond. Please try again later.'; } // when CORS restriction happens (for browser only) else if (/CORS/i.test(error.message)) { error.code = 'ERR_CORS_BLOCKED'; error.detailedMessage = 'The request was blocked due to cross-origin restrictions.'; } // when Server-side error occurs else if (error.response && error.response.status >= 500) { error.code = 'ERR_SERVER'; error.detailedMessage = 'A server-side issue occurred. Please try again later.'; } // when Client-side error occurs else if (error.response && error.response.status >= 400) { error.code = 'ERR_CLIENT'; error.detailedMessage = 'A client-side error occurred. Please check your request.'; } // when unknown network issue occurs else { error.code = 'ERR_NETWORK_GENERIC'; error.detailedMessage = 'A network issue occurred. Please check your connection or try again later.'; } return error; } export function createEnhancedClient(config = {}) { const client = axios.create(config); client.interceptors.response.use( (response) => response, (error) => { throw enhanceNetworkError(error); } ); return client; } export default enhanceNetworkError; axios-axios-2d06f96/examples/post/000077500000000000000000000000001521272452000171235ustar00rootroot00000000000000axios-axios-2d06f96/examples/post/index.html000066400000000000000000000022571521272452000211260ustar00rootroot00000000000000 axios - post example

        axios.post

        axios-axios-2d06f96/examples/post/server.js000066400000000000000000000005011521272452000207630ustar00rootroot00000000000000export default function (req, res) { let data = ''; req.on('data', function (chunk) { data += chunk; }); req.on('end', function () { console.log('POST data received'); res.writeHead(200, { 'Content-Type': 'application/json', }); res.write(JSON.stringify(data)); res.end(); }); } axios-axios-2d06f96/examples/postMultipartFormData/000077500000000000000000000000001521272452000224435ustar00rootroot00000000000000axios-axios-2d06f96/examples/postMultipartFormData/index.html000066400000000000000000000344231521272452000244460ustar00rootroot00000000000000 Axios - Multipart Form Example

        Multipart Form Data

        Response Data
        Submit the form to see the response data here
        This form demonstrates how to submit multipart/form-data with both text fields and files.
        axios-axios-2d06f96/examples/postMultipartFormData/server.js000066400000000000000000000003601521272452000243060ustar00rootroot00000000000000export default function (req, res) { req.on('data', function (chunk) {}); req.on('end', function () { console.log('POST received'); res.writeHead(200, { 'Content-Type': 'application/json', }); res.end(); }); } axios-axios-2d06f96/examples/server.js000066400000000000000000000110501521272452000177770ustar00rootroot00000000000000import fs from 'fs'; import path from 'path'; import http from 'http'; import minimist from 'minimist'; import url from 'url'; const argv = minimist(process.argv.slice(2)); let server; let dirs; const __filename = url.fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); function listDirs(root) { const files = fs.readdirSync(root); const dirs = []; for (let i = 0, l = files.length; i < l; i++) { const file = files[i]; if (file[0] !== '.') { const stat = fs.statSync(path.join(root, file)); if (stat.isDirectory()) { dirs.push(file); } } } return dirs; } function getIndexTemplate() { const links = dirs.map(function (dir) { const url = '/' + dir; return ( '
      • ' + url + '
      • ' ); }); return ( '' + '' + '' + 'axios examples' + '' + '' + '
          ' + links.join('') + '
        ' ); } function sendResponse(res, statusCode, body) { res.writeHead(statusCode); res.write(body); res.end(); } function send200(res, body) { sendResponse(res, 200, body || '

        OK

        '); } function send404(res, body) { sendResponse(res, 404, body || '

        Not Found

        '); } function pipeFileToResponse(res, file, type) { try { // Validate file path - prevent directory traversal const safeBasePath = path.join(__dirname, 'examples'); const resolvedPath = path.resolve(path.join(safeBasePath, file)); // Ensure the resolved path is within intended directory if (!resolvedPath.startsWith(safeBasePath)) { res.writeHead(400); res.end('Invalid file path'); return; } // Check if file exists if (!fs.existsSync(resolvedPath)) { res.writeHead(404); res.end('File not found'); return; } if (type) { res.writeHead(200, { 'Content-Type': type, }); } else { res.writeHead(200); } const stream = fs.createReadStream(resolvedPath); stream.on('error', (err) => { console.error('Error while reading file:', err.message); if (!res.headersSent) { res.writeHead(500, { 'Content-Type': 'text/plain' }); } res.end('File read error'); }); stream.pipe(res); } catch (err) { console.error('Unexpected error:', err.message); if (!res.headersSent) { res.writeHead(500, { 'Content-Type': 'text/plain' }); } res.end('Internal server error'); } } dirs = listDirs(__dirname); server = http.createServer(function (req, res) { let url = req.url; // Process axios itself if (/axios\.min\.js$/.test(url)) { pipeFileToResponse(res, '../dist/axios.min.js', 'text/javascript'); return; } if (/axios\.min\.map$/.test(url)) { pipeFileToResponse(res, '../dist/axios.min.map', 'text/javascript'); return; } if (/axios\.amd\.min\.js$/.test(url)) { pipeFileToResponse(res, '../dist/axios.amd.min.js', 'text/javascript'); return; } if (/axios\.amd\.min\.map$/.test(url)) { pipeFileToResponse(res, '../dist/axios.amd.min.map', 'text/javascript'); return; } // Process / if (url === '/' || url === '/index.html') { send200(res, getIndexTemplate()); return; } // Format request */ -> */index.html if (/\/$/.test(url)) { url += 'index.html'; } // Format request /get -> /get/index.html const parts = url.split('/'); if (dirs.indexOf(parts[parts.length - 1]) > -1) { url += '/index.html'; } // Process index.html request if (/index\.html$/.test(url)) { if (fs.existsSync(path.join(__dirname, url))) { pipeFileToResponse(res, url, 'text/html'); } else { send404(res); } return; } // Process server request else if (new RegExp('(' + dirs.join('|') + ')\/server').test(url)) { if (fs.existsSync(path.join(__dirname, url + '.js'))) { import('file://' + path.join(__dirname, url + '.js')) .then((server) => { server.default(req, res); }) .catch((err) => { console.error('Error importing server:', err); send404(res); }); } else { send404(res); } return; } else { send404(res); } }); const PORT = argv.p || 3000; server.listen(PORT, () => { console.log(`Examples running on ${PORT}`); }); axios-axios-2d06f96/examples/transform-response/000077500000000000000000000000001521272452000220055ustar00rootroot00000000000000axios-axios-2d06f96/examples/transform-response/index.html000066400000000000000000000027141521272452000240060ustar00rootroot00000000000000 axios - transform response example

        transformResponse


        Created:
        Updated:
        axios-axios-2d06f96/examples/upload/000077500000000000000000000000001521272452000174225ustar00rootroot00000000000000axios-axios-2d06f96/examples/upload/index.html000066400000000000000000000031141521272452000214160ustar00rootroot00000000000000 axios - file upload example

        file upload

        axios-axios-2d06f96/examples/upload/server.js000066400000000000000000000003461521272452000212710ustar00rootroot00000000000000export default function (req, res) { let _data = ''; req.on('data', function (chunk) { _data += chunk; }); req.on('end', function () { console.log('File uploaded'); res.writeHead(200); res.end(); }); } axios-axios-2d06f96/gulpfile.js000066400000000000000000000042051521272452000164660ustar00rootroot00000000000000import gulp from 'gulp'; import fs from 'fs-extra'; import axios from './scripts/axios-build-instance.js'; import minimist from 'minimist'; const argv = minimist(process.argv.slice(2)); gulp.task('default', async function () { console.log('hello!'); }); const clear = gulp.task('clear', async function () { await fs.emptyDir('./dist/'); }); async function getContributors(user, repo, maxCount = 1) { const contributors = ( await axios.get( `https://api.github.com/repos/${encodeURIComponent(user)}/${encodeURIComponent(repo)}/contributors`, { params: { per_page: maxCount } } ) ).data; return Promise.all( contributors.map(async (contributor) => { return { ...contributor, ...( await axios.get(`https://api.github.com/users/${encodeURIComponent(contributor.login)}`) ).data, }; }) ); } const packageJSON = gulp.task('package', async function () { const CONTRIBUTION_THRESHOLD = 3; const npm = JSON.parse(await fs.readFile('package.json')); try { const contributors = await getContributors('axios', 'axios', 15); npm.contributors = contributors .filter( ({ type, contributions }) => type.toLowerCase() === 'user' && contributions >= CONTRIBUTION_THRESHOLD ) .map(({ login, name, _ }) => `${name || login} (https://github.com/${login})`); await fs.writeFile('package.json', JSON.stringify(npm, null, 2)); } catch (err) { if (axios.isAxiosError(err) && err.response && err.response.status === 403) { throw Error(`GitHub API Error: ${err.response.data && err.response.data.message}`); } throw err; } }); const env = gulp.task('env', async function () { var npm = JSON.parse(await fs.readFile('package.json')); const envFilePath = './lib/env/data.js'; await fs.writeFile( envFilePath, Object.entries({ VERSION: (argv.bump || npm.version).replace(/^v/, ''), }) .map(([key, value]) => { return `export const ${key} = ${JSON.stringify(value)};`; }) .join('\n') ); }); const version = gulp.series('env', 'package'); export { env, clear, version, packageJSON }; axios-axios-2d06f96/index.d.cts000066400000000000000000000516501521272452000163730ustar00rootroot00000000000000type MethodsHeaders = Partial< { [Key in axios.Method as Lowercase]: AxiosHeaders; } & { common: AxiosHeaders } >; type AxiosHeaderMatcher = | string | RegExp | ((this: AxiosHeaders, value: string, name: string) => boolean); type AxiosHeaderParser = (this: AxiosHeaders, value: axios.AxiosHeaderValue, header: string) => any; type CommonRequestHeadersList = | 'Accept' | 'Content-Length' | 'User-Agent' | 'Content-Encoding' | 'Authorization' | 'Location'; type ContentType = | axios.AxiosHeaderValue | 'text/html' | 'text/plain' | 'multipart/form-data' | 'application/json' | 'application/x-www-form-urlencoded' | 'application/octet-stream'; type CommonResponseHeadersList = | 'Server' | 'Content-Type' | 'Content-Length' | 'Cache-Control' | 'Content-Encoding'; type CommonResponseHeaderKey = CommonResponseHeadersList | Lowercase; type BrowserProgressEvent = any; declare class AxiosHeaders { constructor(headers?: axios.RawAxiosHeaders | AxiosHeaders | string); [key: string]: any; set( headerName?: string, value?: axios.AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher ): AxiosHeaders; set(headers?: axios.RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean): AxiosHeaders; get(headerName: string, parser: RegExp): RegExpExecArray | null; get(headerName: string, matcher?: true | AxiosHeaderParser): axios.AxiosHeaderValue; has(header: string, matcher?: AxiosHeaderMatcher): boolean; delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean; clear(matcher?: AxiosHeaderMatcher): boolean; normalize(format: boolean): AxiosHeaders; concat( ...targets: Array ): AxiosHeaders; toJSON(asStrings: true): Record; toJSON(asStrings?: false): Record; toJSON(asStrings?: boolean): Record; static from(thing?: AxiosHeaders | axios.RawAxiosHeaders | string): AxiosHeaders; static accessor(header: string | string[]): AxiosHeaders; static concat( ...targets: Array ): AxiosHeaders; setContentType(value: ContentType, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders; getContentType(parser?: RegExp): RegExpExecArray | null; getContentType(matcher?: AxiosHeaderMatcher): axios.AxiosHeaderValue; hasContentType(matcher?: AxiosHeaderMatcher): boolean; setContentLength( value: axios.AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher ): AxiosHeaders; getContentLength(parser?: RegExp): RegExpExecArray | null; getContentLength(matcher?: AxiosHeaderMatcher): axios.AxiosHeaderValue; hasContentLength(matcher?: AxiosHeaderMatcher): boolean; setAccept(value: axios.AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders; getAccept(parser?: RegExp): RegExpExecArray | null; getAccept(matcher?: AxiosHeaderMatcher): axios.AxiosHeaderValue; hasAccept(matcher?: AxiosHeaderMatcher): boolean; setUserAgent(value: axios.AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders; getUserAgent(parser?: RegExp): RegExpExecArray | null; getUserAgent(matcher?: AxiosHeaderMatcher): axios.AxiosHeaderValue; hasUserAgent(matcher?: AxiosHeaderMatcher): boolean; setContentEncoding( value: axios.AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher ): AxiosHeaders; getContentEncoding(parser?: RegExp): RegExpExecArray | null; getContentEncoding(matcher?: AxiosHeaderMatcher): axios.AxiosHeaderValue; hasContentEncoding(matcher?: AxiosHeaderMatcher): boolean; setAuthorization( value: axios.AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher ): AxiosHeaders; getAuthorization(parser?: RegExp): RegExpExecArray | null; getAuthorization(matcher?: AxiosHeaderMatcher): axios.AxiosHeaderValue; hasAuthorization(matcher?: AxiosHeaderMatcher): boolean; getSetCookie(): string[]; [Symbol.iterator](): IterableIterator<[string, axios.AxiosHeaderValue]>; } declare class AxiosError extends Error { constructor( message?: string, code?: string, config?: axios.InternalAxiosRequestConfig, request?: any, response?: axios.AxiosResponse ); config?: axios.InternalAxiosRequestConfig; code?: string; request?: any; response?: axios.AxiosResponse; isAxiosError: boolean; status?: number; toJSON: () => object; cause?: Error; event?: BrowserProgressEvent; static from( error: Error | unknown, code?: string, config?: axios.InternalAxiosRequestConfig, request?: any, response?: axios.AxiosResponse, customProps?: object ): AxiosError; static readonly ERR_FR_TOO_MANY_REDIRECTS = 'ERR_FR_TOO_MANY_REDIRECTS'; static readonly ERR_BAD_OPTION_VALUE = 'ERR_BAD_OPTION_VALUE'; static readonly ERR_BAD_OPTION = 'ERR_BAD_OPTION'; static readonly ERR_NETWORK = 'ERR_NETWORK'; static readonly ERR_DEPRECATED = 'ERR_DEPRECATED'; static readonly ERR_BAD_RESPONSE = 'ERR_BAD_RESPONSE'; static readonly ERR_BAD_REQUEST = 'ERR_BAD_REQUEST'; static readonly ERR_NOT_SUPPORT = 'ERR_NOT_SUPPORT'; static readonly ERR_INVALID_URL = 'ERR_INVALID_URL'; static readonly ERR_CANCELED = 'ERR_CANCELED'; static readonly ERR_FORM_DATA_DEPTH_EXCEEDED = 'ERR_FORM_DATA_DEPTH_EXCEEDED'; static readonly ECONNABORTED = 'ECONNABORTED'; static readonly ECONNREFUSED = 'ECONNREFUSED'; static readonly ETIMEDOUT = 'ETIMEDOUT'; } declare class CanceledError extends AxiosError { readonly name: 'CanceledError'; } declare class Axios { constructor(config?: axios.AxiosRequestConfig); defaults: axios.AxiosDefaults; interceptors: { request: axios.AxiosInterceptorManager; response: axios.AxiosInterceptorManager; }; getUri(config?: axios.AxiosRequestConfig): string; request, D = any>( config: axios.AxiosRequestConfig ): Promise; get, D = any>( url: string, config?: axios.AxiosRequestConfig ): Promise; delete, D = any>( url: string, config?: axios.AxiosRequestConfig ): Promise; head, D = any>( url: string, config?: axios.AxiosRequestConfig ): Promise; options, D = any>( url: string, config?: axios.AxiosRequestConfig ): Promise; post, D = any>( url: string, data?: D, config?: axios.AxiosRequestConfig ): Promise; put, D = any>( url: string, data?: D, config?: axios.AxiosRequestConfig ): Promise; patch, D = any>( url: string, data?: D, config?: axios.AxiosRequestConfig ): Promise; postForm, D = any>( url: string, data?: D, config?: axios.AxiosRequestConfig ): Promise; putForm, D = any>( url: string, data?: D, config?: axios.AxiosRequestConfig ): Promise; patchForm, D = any>( url: string, data?: D, config?: axios.AxiosRequestConfig ): Promise; query, D = any>( url: string, data?: D, config?: axios.AxiosRequestConfig ): Promise; } declare enum HttpStatusCode { Continue = 100, SwitchingProtocols = 101, Processing = 102, EarlyHints = 103, Ok = 200, Created = 201, Accepted = 202, NonAuthoritativeInformation = 203, NoContent = 204, ResetContent = 205, PartialContent = 206, MultiStatus = 207, AlreadyReported = 208, ImUsed = 226, MultipleChoices = 300, MovedPermanently = 301, Found = 302, SeeOther = 303, NotModified = 304, UseProxy = 305, Unused = 306, TemporaryRedirect = 307, PermanentRedirect = 308, BadRequest = 400, Unauthorized = 401, PaymentRequired = 402, Forbidden = 403, NotFound = 404, MethodNotAllowed = 405, NotAcceptable = 406, ProxyAuthenticationRequired = 407, RequestTimeout = 408, Conflict = 409, Gone = 410, LengthRequired = 411, PreconditionFailed = 412, PayloadTooLarge = 413, UriTooLong = 414, UnsupportedMediaType = 415, RangeNotSatisfiable = 416, ExpectationFailed = 417, ImATeapot = 418, MisdirectedRequest = 421, UnprocessableEntity = 422, Locked = 423, FailedDependency = 424, TooEarly = 425, UpgradeRequired = 426, PreconditionRequired = 428, TooManyRequests = 429, RequestHeaderFieldsTooLarge = 431, UnavailableForLegalReasons = 451, InternalServerError = 500, NotImplemented = 501, BadGateway = 502, ServiceUnavailable = 503, GatewayTimeout = 504, HttpVersionNotSupported = 505, VariantAlsoNegotiates = 506, InsufficientStorage = 507, LoopDetected = 508, NotExtended = 510, NetworkAuthenticationRequired = 511, } type InternalAxiosError = AxiosError; declare namespace axios { type AxiosError = InternalAxiosError; interface RawAxiosHeaders { [key: string]: AxiosHeaderValue; } type RawAxiosRequestHeaders = Partial< RawAxiosHeaders & { [Key in CommonRequestHeadersList]: AxiosHeaderValue; } & { 'Content-Type': ContentType; } >; type AxiosRequestHeaders = RawAxiosRequestHeaders & AxiosHeaders; type AxiosHeaderValue = AxiosHeaders | string | string[] | number | boolean | null; type RawCommonResponseHeaders = { [Key in CommonResponseHeaderKey]: AxiosHeaderValue; } & { 'set-cookie': string[]; }; type RawAxiosResponseHeaders = Partial; type AxiosResponseHeaders = RawAxiosResponseHeaders & AxiosHeaders; interface AxiosRequestTransformer { (this: InternalAxiosRequestConfig, data: any, headers: AxiosRequestHeaders): any; } interface AxiosResponseTransformer { ( this: InternalAxiosRequestConfig, data: any, headers: AxiosResponseHeaders, status?: number ): any; } interface AxiosAdapter { (config: InternalAxiosRequestConfig): AxiosPromise; } interface AxiosBasicCredentials { username: string; password: string; } interface AxiosProxyConfig { host: string; port: number; auth?: AxiosBasicCredentials; protocol?: string; } type UppercaseMethod = | 'GET' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'POST' | 'PUT' | 'PATCH' | 'PURGE' | 'LINK' | 'UNLINK' | 'QUERY'; type Method = (UppercaseMethod | Lowercase) & {}; type ResponseType = 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream' | 'formdata'; type UppercaseResponseEncoding = | 'ASCII' | 'ANSI' | 'BINARY' | 'BASE64' | 'BASE64URL' | 'HEX' | 'LATIN1' | 'UCS-2' | 'UCS2' | 'UTF-8' | 'UTF8' | 'UTF16LE'; type responseEncoding = (UppercaseResponseEncoding | Lowercase) & {}; interface TransitionalOptions { silentJSONParsing?: boolean; forcedJSONParsing?: boolean; clarifyTimeoutError?: boolean; legacyInterceptorReqResOrdering?: boolean; advertiseZstdAcceptEncoding?: boolean; validateStatusUndefinedResolves?: boolean; } interface GenericAbortSignal { readonly aborted: boolean; onabort?: ((...args: any) => any) | null; addEventListener?: (...args: any) => any; removeEventListener?: (...args: any) => any; } interface FormDataVisitorHelpers { defaultVisitor: SerializerVisitor; convertValue: (value: any) => any; isVisitable: (value: any) => boolean; } interface SerializerVisitor { ( this: GenericFormData, value: any, key: string | number, path: null | Array, helpers: FormDataVisitorHelpers ): boolean; } interface SerializerOptions { visitor?: SerializerVisitor; dots?: boolean; metaTokens?: boolean; indexes?: boolean | null; } // tslint:disable-next-line interface FormSerializerOptions extends SerializerOptions {} interface ParamEncoder { (value: any, defaultEncoder: (value: any) => any): any; } interface CustomParamsSerializer { (params: Record, options?: ParamsSerializerOptions): string; } interface ParamsSerializerOptions extends SerializerOptions { encode?: ParamEncoder; serialize?: CustomParamsSerializer; } type MaxUploadRate = number; type MaxDownloadRate = number; interface AxiosProgressEvent { loaded: number; total?: number; progress?: number; bytes: number; rate?: number; estimated?: number; upload?: boolean; download?: boolean; event?: BrowserProgressEvent; lengthComputable: boolean; } type Milliseconds = number; type AxiosAdapterName = 'fetch' | 'xhr' | 'http' | (string & {}); type AxiosAdapterConfig = AxiosAdapter | AxiosAdapterName; type AddressFamily = 4 | 6 | undefined; interface LookupAddressEntry { address: string; family?: AddressFamily; } type LookupAddress = string | LookupAddressEntry; interface AxiosRequestConfig { url?: string; method?: Method | string; baseURL?: string; allowAbsoluteUrls?: boolean; transformRequest?: AxiosRequestTransformer | AxiosRequestTransformer[]; transformResponse?: AxiosResponseTransformer | AxiosResponseTransformer[]; headers?: (RawAxiosRequestHeaders & MethodsHeaders) | AxiosHeaders; params?: any; paramsSerializer?: ParamsSerializerOptions | CustomParamsSerializer; data?: D; timeout?: Milliseconds; timeoutErrorMessage?: string; withCredentials?: boolean; adapter?: AxiosAdapterConfig | AxiosAdapterConfig[]; auth?: AxiosBasicCredentials; responseType?: ResponseType; responseEncoding?: responseEncoding | string; xsrfCookieName?: string; xsrfHeaderName?: string; onUploadProgress?: (progressEvent: AxiosProgressEvent) => void; onDownloadProgress?: (progressEvent: AxiosProgressEvent) => void; maxContentLength?: number; validateStatus?: ((status: number) => boolean) | null; maxBodyLength?: number; maxRedirects?: number; maxRate?: number | [MaxUploadRate, MaxDownloadRate]; beforeRedirect?: ( options: Record, responseDetails: { headers: Record; statusCode: HttpStatusCode }, requestDetails: { headers: Record; url: string; method: string }, ) => void; socketPath?: string | null; allowedSocketPaths?: string | string[] | null; transport?: any; httpAgent?: any; httpsAgent?: any; proxy?: AxiosProxyConfig | false; cancelToken?: CancelToken | undefined; decompress?: boolean; transitional?: TransitionalOptions; signal?: GenericAbortSignal; insecureHTTPParser?: boolean; env?: { FormData?: new (...args: any[]) => object; fetch?: (input: URL | Request | string, init?: RequestInit) => Promise; Request?: new (input: URL | Request | string, init?: RequestInit) => Request; Response?: new ( body?: ArrayBuffer | ArrayBufferView | Blob | FormData | URLSearchParams | string | null, init?: ResponseInit ) => Response; }; formSerializer?: FormSerializerOptions; family?: AddressFamily; lookup?: | (( hostname: string, options: object, cb: ( err: Error | null, address: LookupAddress | LookupAddress[], family?: AddressFamily ) => void ) => void) | (( hostname: string, options: object ) => Promise< | [address: LookupAddressEntry | LookupAddressEntry[], family?: AddressFamily] | LookupAddress >); withXSRFToken?: boolean | ((config: InternalAxiosRequestConfig) => boolean | undefined); parseReviver?: (this: any, key: string, value: any, context?: { source?: string }) => any; fetchOptions?: | Omit | Record; httpVersion?: 1 | 2; http2Options?: Record & { sessionTimeout?: number; }; formDataHeaderPolicy?: 'legacy' | 'content-only'; redact?: string[]; sensitiveHeaders?: string[]; } // Alias type RawAxiosRequestConfig = AxiosRequestConfig; interface InternalAxiosRequestConfig extends AxiosRequestConfig { headers: AxiosRequestHeaders; } interface HeadersDefaults { common: RawAxiosRequestHeaders; delete: RawAxiosRequestHeaders; get: RawAxiosRequestHeaders; head: RawAxiosRequestHeaders; post: RawAxiosRequestHeaders; put: RawAxiosRequestHeaders; patch: RawAxiosRequestHeaders; options?: RawAxiosRequestHeaders; purge?: RawAxiosRequestHeaders; link?: RawAxiosRequestHeaders; unlink?: RawAxiosRequestHeaders; query?: RawAxiosRequestHeaders; } interface AxiosDefaults extends Omit, 'headers'> { headers: HeadersDefaults; } interface CreateAxiosDefaults extends Omit, 'headers'> { headers?: RawAxiosRequestHeaders | AxiosHeaders | Partial; } interface AxiosResponse { data: T; status: number; statusText: string; headers: (H & RawAxiosResponseHeaders) | AxiosResponseHeaders; config: InternalAxiosRequestConfig; request?: any; } type AxiosPromise = Promise>; interface CancelStatic { new (message?: string): Cancel; } interface Cancel { message: string | undefined; } interface Canceler { (message?: string, config?: AxiosRequestConfig, request?: any): void; } interface CancelTokenStatic { new (executor: (cancel: Canceler) => void): CancelToken; source(): CancelTokenSource; } interface CancelToken { promise: Promise; reason?: Cancel; throwIfRequested(): void; } interface CancelTokenSource { token: CancelToken; cancel: Canceler; } interface AxiosInterceptorOptions { synchronous?: boolean; runWhen?: ((config: InternalAxiosRequestConfig) => boolean) | null; } type AxiosInterceptorFulfilled = (value: T) => T | Promise; type AxiosInterceptorRejected = (error: any) => any; type AxiosRequestInterceptorUse = ( onFulfilled?: AxiosInterceptorFulfilled | null, onRejected?: AxiosInterceptorRejected | null, options?: AxiosInterceptorOptions ) => number; type AxiosResponseInterceptorUse = ( onFulfilled?: AxiosInterceptorFulfilled | null, onRejected?: AxiosInterceptorRejected | null ) => number; interface AxiosInterceptorHandler { fulfilled: AxiosInterceptorFulfilled; rejected?: AxiosInterceptorRejected; synchronous: boolean; runWhen?: ((config: InternalAxiosRequestConfig) => boolean) | null; } interface AxiosInterceptorManager { use: V extends AxiosResponse ? AxiosResponseInterceptorUse : AxiosRequestInterceptorUse; eject(id: number): void; clear(): void; handlers?: Array>; } interface AxiosInstance extends Axios { , D = any>(config: AxiosRequestConfig): Promise; , D = any>( url: string, config?: AxiosRequestConfig ): Promise; create(config?: CreateAxiosDefaults): AxiosInstance; defaults: Omit & { headers: HeadersDefaults & { [key: string]: AxiosHeaderValue; }; }; } interface GenericFormData { append(name: string, value: any, options?: any): any; } interface GenericHTMLFormElement { name: string; method: string; submit(): void; } interface AxiosStatic extends AxiosInstance { Cancel: CancelStatic; CancelToken: CancelTokenStatic; Axios: typeof Axios; AxiosError: typeof AxiosError; CanceledError: typeof CanceledError; HttpStatusCode: typeof HttpStatusCode; readonly VERSION: string; isCancel(value: any): value is CanceledError; all(values: Array>): Promise; spread(callback: (...args: T[]) => R): (array: T[]) => R; isAxiosError(payload: any): payload is AxiosError; toFormData( sourceObj: object, targetFormData?: GenericFormData, options?: FormSerializerOptions ): GenericFormData; formToJSON(form: GenericFormData | GenericHTMLFormElement): object; getAdapter(adapters: AxiosAdapterConfig | AxiosAdapterConfig[] | undefined): AxiosAdapter; AxiosHeaders: typeof AxiosHeaders; mergeConfig( config1: AxiosRequestConfig, config2: AxiosRequestConfig ): AxiosRequestConfig; } } declare const axios: axios.AxiosStatic; export = axios; axios-axios-2d06f96/index.d.ts000066400000000000000000000511231521272452000162230ustar00rootroot00000000000000// TypeScript Version: 4.7 type StringLiteralsOrString = Literals | (string & {}); export type AxiosHeaderValue = AxiosHeaders | string | string[] | number | boolean | null; export interface RawAxiosHeaders { [key: string]: AxiosHeaderValue; } type MethodsHeaders = Partial< { [Key in Method as Lowercase]: AxiosHeaders; } & { common: AxiosHeaders } >; type AxiosHeaderMatcher = | string | RegExp | ((this: AxiosHeaders, value: string, name: string) => boolean); type AxiosHeaderParser = (this: AxiosHeaders, value: AxiosHeaderValue, header: string) => any; export class AxiosHeaders { constructor(headers?: RawAxiosHeaders | AxiosHeaders | string); [key: string]: any; set( headerName?: string, value?: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher ): AxiosHeaders; set(headers?: RawAxiosHeaders | AxiosHeaders | string, rewrite?: boolean): AxiosHeaders; get(headerName: string, parser: RegExp): RegExpExecArray | null; get(headerName: string, matcher?: true | AxiosHeaderParser): AxiosHeaderValue; has(header: string, matcher?: AxiosHeaderMatcher): boolean; delete(header: string | string[], matcher?: AxiosHeaderMatcher): boolean; clear(matcher?: AxiosHeaderMatcher): boolean; normalize(format: boolean): AxiosHeaders; concat( ...targets: Array ): AxiosHeaders; toJSON(asStrings: true): Record; toJSON(asStrings?: false): Record; toJSON(asStrings?: boolean): Record; static from(thing?: AxiosHeaders | RawAxiosHeaders | string): AxiosHeaders; static accessor(header: string | string[]): AxiosHeaders; static concat( ...targets: Array ): AxiosHeaders; setContentType(value: ContentType, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders; getContentType(parser?: RegExp): RegExpExecArray | null; getContentType(matcher?: AxiosHeaderMatcher): AxiosHeaderValue; hasContentType(matcher?: AxiosHeaderMatcher): boolean; setContentLength(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders; getContentLength(parser?: RegExp): RegExpExecArray | null; getContentLength(matcher?: AxiosHeaderMatcher): AxiosHeaderValue; hasContentLength(matcher?: AxiosHeaderMatcher): boolean; setAccept(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders; getAccept(parser?: RegExp): RegExpExecArray | null; getAccept(matcher?: AxiosHeaderMatcher): AxiosHeaderValue; hasAccept(matcher?: AxiosHeaderMatcher): boolean; setUserAgent(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders; getUserAgent(parser?: RegExp): RegExpExecArray | null; getUserAgent(matcher?: AxiosHeaderMatcher): AxiosHeaderValue; hasUserAgent(matcher?: AxiosHeaderMatcher): boolean; setContentEncoding(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders; getContentEncoding(parser?: RegExp): RegExpExecArray | null; getContentEncoding(matcher?: AxiosHeaderMatcher): AxiosHeaderValue; hasContentEncoding(matcher?: AxiosHeaderMatcher): boolean; setAuthorization(value: AxiosHeaderValue, rewrite?: boolean | AxiosHeaderMatcher): AxiosHeaders; getAuthorization(parser?: RegExp): RegExpExecArray | null; getAuthorization(matcher?: AxiosHeaderMatcher): AxiosHeaderValue; hasAuthorization(matcher?: AxiosHeaderMatcher): boolean; getSetCookie(): string[]; [Symbol.iterator](): IterableIterator<[string, AxiosHeaderValue]>; } type CommonRequestHeadersList = | 'Accept' | 'Content-Length' | 'User-Agent' | 'Content-Encoding' | 'Authorization' | 'Location'; type ContentType = | AxiosHeaderValue | 'text/html' | 'text/plain' | 'multipart/form-data' | 'application/json' | 'application/x-www-form-urlencoded' | 'application/octet-stream'; export type RawAxiosRequestHeaders = Partial< RawAxiosHeaders & { [Key in CommonRequestHeadersList]: AxiosHeaderValue; } & { 'Content-Type': ContentType; } >; export type AxiosRequestHeaders = RawAxiosRequestHeaders & AxiosHeaders; type CommonResponseHeadersList = | 'Server' | 'Content-Type' | 'Content-Length' | 'Cache-Control' | 'Content-Encoding'; type CommonResponseHeaderKey = CommonResponseHeadersList | Lowercase; type RawCommonResponseHeaders = { [Key in CommonResponseHeaderKey]: AxiosHeaderValue; } & { 'set-cookie': string[]; }; export type RawAxiosResponseHeaders = Partial; export type AxiosResponseHeaders = RawAxiosResponseHeaders & AxiosHeaders; export interface AxiosRequestTransformer { (this: InternalAxiosRequestConfig, data: any, headers: AxiosRequestHeaders): any; } export interface AxiosResponseTransformer { ( this: InternalAxiosRequestConfig, data: any, headers: AxiosResponseHeaders, status?: number ): any; } export interface AxiosAdapter { (config: InternalAxiosRequestConfig): AxiosPromise; } export interface AxiosBasicCredentials { username: string; password: string; } export interface AxiosProxyConfig { host: string; port: number; auth?: AxiosBasicCredentials; protocol?: string; } export enum HttpStatusCode { Continue = 100, SwitchingProtocols = 101, Processing = 102, EarlyHints = 103, Ok = 200, Created = 201, Accepted = 202, NonAuthoritativeInformation = 203, NoContent = 204, ResetContent = 205, PartialContent = 206, MultiStatus = 207, AlreadyReported = 208, ImUsed = 226, MultipleChoices = 300, MovedPermanently = 301, Found = 302, SeeOther = 303, NotModified = 304, UseProxy = 305, Unused = 306, TemporaryRedirect = 307, PermanentRedirect = 308, BadRequest = 400, Unauthorized = 401, PaymentRequired = 402, Forbidden = 403, NotFound = 404, MethodNotAllowed = 405, NotAcceptable = 406, ProxyAuthenticationRequired = 407, RequestTimeout = 408, Conflict = 409, Gone = 410, LengthRequired = 411, PreconditionFailed = 412, PayloadTooLarge = 413, UriTooLong = 414, UnsupportedMediaType = 415, RangeNotSatisfiable = 416, ExpectationFailed = 417, ImATeapot = 418, MisdirectedRequest = 421, UnprocessableEntity = 422, Locked = 423, FailedDependency = 424, TooEarly = 425, UpgradeRequired = 426, PreconditionRequired = 428, TooManyRequests = 429, RequestHeaderFieldsTooLarge = 431, UnavailableForLegalReasons = 451, InternalServerError = 500, NotImplemented = 501, BadGateway = 502, ServiceUnavailable = 503, GatewayTimeout = 504, HttpVersionNotSupported = 505, VariantAlsoNegotiates = 506, InsufficientStorage = 507, LoopDetected = 508, NotExtended = 510, NetworkAuthenticationRequired = 511, } type UppercaseMethod = | 'GET' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'POST' | 'PUT' | 'PATCH' | 'PURGE' | 'LINK' | 'UNLINK' | 'QUERY'; export type Method = (UppercaseMethod | Lowercase) & {}; export type ResponseType = | 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream' | 'formdata'; type UppercaseResponseEncoding = | 'ASCII' | 'ANSI' | 'BINARY' | 'BASE64' | 'BASE64URL' | 'HEX' | 'LATIN1' | 'UCS-2' | 'UCS2' | 'UTF-8' | 'UTF8' | 'UTF16LE'; export type responseEncoding = ( | UppercaseResponseEncoding | Lowercase ) & {}; export interface TransitionalOptions { silentJSONParsing?: boolean; forcedJSONParsing?: boolean; clarifyTimeoutError?: boolean; legacyInterceptorReqResOrdering?: boolean; advertiseZstdAcceptEncoding?: boolean; validateStatusUndefinedResolves?: boolean; } export interface GenericAbortSignal { readonly aborted: boolean; onabort?: ((...args: any) => any) | null; addEventListener?: (...args: any) => any; removeEventListener?: (...args: any) => any; } export interface FormDataVisitorHelpers { defaultVisitor: SerializerVisitor; convertValue: (value: any) => any; isVisitable: (value: any) => boolean; } export interface SerializerVisitor { ( this: GenericFormData, value: any, key: string | number, path: null | Array, helpers: FormDataVisitorHelpers ): boolean; } export interface SerializerOptions { visitor?: SerializerVisitor; dots?: boolean; metaTokens?: boolean; indexes?: boolean | null; } // tslint:disable-next-line export interface FormSerializerOptions extends SerializerOptions {} export interface ParamEncoder { (value: any, defaultEncoder: (value: any) => any): any; } export interface CustomParamsSerializer { (params: Record, options?: ParamsSerializerOptions): string; } export interface ParamsSerializerOptions extends SerializerOptions { encode?: ParamEncoder; serialize?: CustomParamsSerializer; } type MaxUploadRate = number; type MaxDownloadRate = number; type BrowserProgressEvent = any; export interface AxiosProgressEvent { loaded: number; total?: number; progress?: number; bytes: number; rate?: number; estimated?: number; upload?: boolean; download?: boolean; event?: BrowserProgressEvent; lengthComputable: boolean; } type Milliseconds = number; type AxiosAdapterName = StringLiteralsOrString<'xhr' | 'http' | 'fetch'>; type AxiosAdapterConfig = AxiosAdapter | AxiosAdapterName; export type AddressFamily = 4 | 6 | undefined; export interface LookupAddressEntry { address: string; family?: AddressFamily; } export type LookupAddress = string | LookupAddressEntry; export interface AxiosRequestConfig { url?: string; method?: StringLiteralsOrString; baseURL?: string; allowAbsoluteUrls?: boolean; transformRequest?: AxiosRequestTransformer | AxiosRequestTransformer[]; transformResponse?: AxiosResponseTransformer | AxiosResponseTransformer[]; headers?: (RawAxiosRequestHeaders & MethodsHeaders) | AxiosHeaders; params?: any; paramsSerializer?: ParamsSerializerOptions | CustomParamsSerializer; data?: D; timeout?: Milliseconds; timeoutErrorMessage?: string; withCredentials?: boolean; adapter?: AxiosAdapterConfig | AxiosAdapterConfig[]; auth?: AxiosBasicCredentials; responseType?: ResponseType; responseEncoding?: StringLiteralsOrString; xsrfCookieName?: string; xsrfHeaderName?: string; onUploadProgress?: (progressEvent: AxiosProgressEvent) => void; onDownloadProgress?: (progressEvent: AxiosProgressEvent) => void; maxContentLength?: number; validateStatus?: ((status: number) => boolean) | null; maxBodyLength?: number; maxRedirects?: number; maxRate?: number | [MaxUploadRate, MaxDownloadRate]; beforeRedirect?: ( options: Record, responseDetails: { headers: Record; statusCode: HttpStatusCode; }, requestDetails: { headers: Record; url: string; method: string; }, ) => void; socketPath?: string | null; allowedSocketPaths?: string | string[] | null; transport?: any; httpAgent?: any; httpsAgent?: any; proxy?: AxiosProxyConfig | false; cancelToken?: CancelToken | undefined; decompress?: boolean; transitional?: TransitionalOptions; signal?: GenericAbortSignal; insecureHTTPParser?: boolean; env?: { FormData?: new (...args: any[]) => object; fetch?: (input: URL | Request | string, init?: RequestInit) => Promise; Request?: new (input: URL | Request | string, init?: RequestInit) => Request; Response?: new ( body?: ArrayBuffer | ArrayBufferView | Blob | FormData | URLSearchParams | string | null, init?: ResponseInit ) => Response; }; formSerializer?: FormSerializerOptions; family?: AddressFamily; lookup?: | (( hostname: string, options: object, cb: ( err: Error | null, address: LookupAddress | LookupAddress[], family?: AddressFamily ) => void ) => void) | (( hostname: string, options: object ) => Promise< [address: LookupAddressEntry | LookupAddressEntry[], family?: AddressFamily] | LookupAddress >); withXSRFToken?: boolean | ((config: InternalAxiosRequestConfig) => boolean | undefined); parseReviver?: (this: any, key: string, value: any, context?: { source?: string }) => any; fetchOptions?: Omit | Record; httpVersion?: 1 | 2; http2Options?: Record & { sessionTimeout?: number; }; formDataHeaderPolicy?: 'legacy' | 'content-only'; redact?: string[]; sensitiveHeaders?: string[]; } // Alias export type RawAxiosRequestConfig = AxiosRequestConfig; export interface InternalAxiosRequestConfig extends AxiosRequestConfig { headers: AxiosRequestHeaders; } export interface HeadersDefaults { common: RawAxiosRequestHeaders; delete: RawAxiosRequestHeaders; get: RawAxiosRequestHeaders; head: RawAxiosRequestHeaders; post: RawAxiosRequestHeaders; put: RawAxiosRequestHeaders; patch: RawAxiosRequestHeaders; options?: RawAxiosRequestHeaders; purge?: RawAxiosRequestHeaders; link?: RawAxiosRequestHeaders; unlink?: RawAxiosRequestHeaders; query?: RawAxiosRequestHeaders; } export interface AxiosDefaults extends Omit, 'headers'> { headers: HeadersDefaults; } export interface CreateAxiosDefaults extends Omit, 'headers'> { headers?: RawAxiosRequestHeaders | AxiosHeaders | Partial; } export interface AxiosResponse { data: T; status: number; statusText: string; headers: (H & RawAxiosResponseHeaders) | AxiosResponseHeaders; config: InternalAxiosRequestConfig; request?: any; } export class AxiosError extends Error { constructor( message?: string, code?: string, config?: InternalAxiosRequestConfig, request?: any, response?: AxiosResponse ); config?: InternalAxiosRequestConfig; code?: string; request?: any; response?: AxiosResponse; isAxiosError: boolean; status?: number; toJSON: () => object; cause?: Error; event?: BrowserProgressEvent; static from( error: Error | unknown, code?: string, config?: InternalAxiosRequestConfig, request?: any, response?: AxiosResponse, customProps?: object ): AxiosError; static readonly ERR_FR_TOO_MANY_REDIRECTS = 'ERR_FR_TOO_MANY_REDIRECTS'; static readonly ERR_BAD_OPTION_VALUE = 'ERR_BAD_OPTION_VALUE'; static readonly ERR_BAD_OPTION = 'ERR_BAD_OPTION'; static readonly ERR_NETWORK = 'ERR_NETWORK'; static readonly ERR_DEPRECATED = 'ERR_DEPRECATED'; static readonly ERR_BAD_RESPONSE = 'ERR_BAD_RESPONSE'; static readonly ERR_BAD_REQUEST = 'ERR_BAD_REQUEST'; static readonly ERR_NOT_SUPPORT = 'ERR_NOT_SUPPORT'; static readonly ERR_INVALID_URL = 'ERR_INVALID_URL'; static readonly ERR_CANCELED = 'ERR_CANCELED'; static readonly ERR_FORM_DATA_DEPTH_EXCEEDED = 'ERR_FORM_DATA_DEPTH_EXCEEDED'; static readonly ECONNABORTED = 'ECONNABORTED'; static readonly ECONNREFUSED = 'ECONNREFUSED'; static readonly ETIMEDOUT = 'ETIMEDOUT'; } export class CanceledError extends AxiosError { readonly name: 'CanceledError'; } export type AxiosPromise = Promise>; export interface CancelStatic { new (message?: string): Cancel; } export interface Cancel { message: string | undefined; } export interface Canceler { (message?: string, config?: AxiosRequestConfig, request?: any): void; } export interface CancelTokenStatic { new (executor: (cancel: Canceler) => void): CancelToken; source(): CancelTokenSource; } export interface CancelToken { promise: Promise; reason?: Cancel; throwIfRequested(): void; } export interface CancelTokenSource { token: CancelToken; cancel: Canceler; } export interface AxiosInterceptorOptions { synchronous?: boolean; runWhen?: ((config: InternalAxiosRequestConfig) => boolean) | null; } type AxiosInterceptorFulfilled = (value: T) => T | Promise; type AxiosInterceptorRejected = (error: any) => any; type AxiosRequestInterceptorUse = ( onFulfilled?: AxiosInterceptorFulfilled | null, onRejected?: AxiosInterceptorRejected | null, options?: AxiosInterceptorOptions ) => number; type AxiosResponseInterceptorUse = ( onFulfilled?: AxiosInterceptorFulfilled | null, onRejected?: AxiosInterceptorRejected | null ) => number; interface AxiosInterceptorHandler { fulfilled: AxiosInterceptorFulfilled; rejected?: AxiosInterceptorRejected; synchronous: boolean; runWhen?: ((config: InternalAxiosRequestConfig) => boolean) | null; } export interface AxiosInterceptorManager { use: V extends AxiosResponse ? AxiosResponseInterceptorUse : AxiosRequestInterceptorUse; eject(id: number): void; clear(): void; handlers?: Array>; } export class Axios { constructor(config?: AxiosRequestConfig); defaults: AxiosDefaults; interceptors: { request: AxiosInterceptorManager; response: AxiosInterceptorManager; }; getUri(config?: AxiosRequestConfig): string; request, D = any>(config: AxiosRequestConfig): Promise; get, D = any>( url: string, config?: AxiosRequestConfig ): Promise; delete, D = any>( url: string, config?: AxiosRequestConfig ): Promise; head, D = any>( url: string, config?: AxiosRequestConfig ): Promise; options, D = any>( url: string, config?: AxiosRequestConfig ): Promise; post, D = any>( url: string, data?: D, config?: AxiosRequestConfig ): Promise; put, D = any>( url: string, data?: D, config?: AxiosRequestConfig ): Promise; patch, D = any>( url: string, data?: D, config?: AxiosRequestConfig ): Promise; postForm, D = any>( url: string, data?: D, config?: AxiosRequestConfig ): Promise; putForm, D = any>( url: string, data?: D, config?: AxiosRequestConfig ): Promise; patchForm, D = any>( url: string, data?: D, config?: AxiosRequestConfig ): Promise; query, D = any>( url: string, data?: D, config?: AxiosRequestConfig ): Promise; } export interface AxiosInstance extends Axios { , D = any>(config: AxiosRequestConfig): Promise; , D = any>(url: string, config?: AxiosRequestConfig): Promise; create(config?: CreateAxiosDefaults): AxiosInstance; defaults: Omit & { headers: HeadersDefaults & { [key: string]: AxiosHeaderValue; }; }; } export interface GenericFormData { append(name: string, value: any, options?: any): any; } export interface GenericHTMLFormElement { name: string; method: string; submit(): void; } export function getAdapter( adapters: AxiosAdapterConfig | AxiosAdapterConfig[] | undefined ): AxiosAdapter; export function toFormData( sourceObj: object, targetFormData?: GenericFormData, options?: FormSerializerOptions ): GenericFormData; export function formToJSON(form: GenericFormData | GenericHTMLFormElement): object; export function isAxiosError(payload: any): payload is AxiosError; export function spread(callback: (...args: T[]) => R): (array: T[]) => R; export function isCancel(value: any): value is CanceledError; export function all(values: Array>): Promise; export function mergeConfig( config1: AxiosRequestConfig, config2: AxiosRequestConfig ): AxiosRequestConfig; export function create(config?: CreateAxiosDefaults): AxiosInstance; export interface AxiosStatic extends AxiosInstance { Cancel: CancelStatic; CancelToken: CancelTokenStatic; Axios: typeof Axios; AxiosError: typeof AxiosError; HttpStatusCode: typeof HttpStatusCode; readonly VERSION: string; isCancel: typeof isCancel; all: typeof all; spread: typeof spread; isAxiosError: typeof isAxiosError; toFormData: typeof toFormData; formToJSON: typeof formToJSON; getAdapter: typeof getAdapter; CanceledError: typeof CanceledError; AxiosHeaders: typeof AxiosHeaders; mergeConfig: typeof mergeConfig; } declare const axios: AxiosStatic; export default axios; axios-axios-2d06f96/index.js000066400000000000000000000013001521272452000157570ustar00rootroot00000000000000import axios from './lib/axios.js'; // This module is intended to unwrap Axios default export as named. // Keep top-level export same with static properties // so that it can keep same with es module or cjs const { Axios, AxiosError, CanceledError, isCancel, CancelToken, VERSION, all, Cancel, isAxiosError, spread, toFormData, AxiosHeaders, HttpStatusCode, formToJSON, getAdapter, mergeConfig, create, } = axios; export { axios as default, create, Axios, AxiosError, CanceledError, isCancel, CancelToken, VERSION, all, Cancel, isAxiosError, spread, toFormData, AxiosHeaders, HttpStatusCode, formToJSON, getAdapter, mergeConfig, }; axios-axios-2d06f96/lib/000077500000000000000000000000001521272452000150665ustar00rootroot00000000000000axios-axios-2d06f96/lib/adapters/000077500000000000000000000000001521272452000166715ustar00rootroot00000000000000axios-axios-2d06f96/lib/adapters/README.md000066400000000000000000000016171521272452000201550ustar00rootroot00000000000000# axios // adapters The modules under `adapters/` are modules that handle dispatching a request and settling a returned `Promise` once a response is received. ## Example ```js var settle = require('../core/settle'); module.exports = function myAdapter(config) { // At this point: // - config has been merged with defaults // - request transformers have already run // - request interceptors have already run // Make the request using config provided // Upon response settle the Promise return new Promise(function (resolve, reject) { var response = { data: responseData, status: request.status, statusText: request.statusText, headers: responseHeaders, config: config, request: request, }; settle(resolve, reject, response); // From here: // - response transformers will run // - response interceptors will run }); }; ``` axios-axios-2d06f96/lib/adapters/adapters.js000066400000000000000000000066501521272452000210410ustar00rootroot00000000000000import utils from '../utils.js'; import httpAdapter from './http.js'; import xhrAdapter from './xhr.js'; import * as fetchAdapter from './fetch.js'; import AxiosError from '../core/AxiosError.js'; /** * Known adapters mapping. * Provides environment-specific adapters for Axios: * - `http` for Node.js * - `xhr` for browsers * - `fetch` for fetch API-based requests * * @type {Object} */ const knownAdapters = { http: httpAdapter, xhr: xhrAdapter, fetch: { get: fetchAdapter.getFetch, }, }; // Assign adapter names for easier debugging and identification utils.forEach(knownAdapters, (fn, value) => { if (fn) { try { // Null-proto descriptors so a polluted Object.prototype.get cannot turn // these data descriptors into accessor descriptors on the way in. Object.defineProperty(fn, 'name', { __proto__: null, value }); } catch (e) { // eslint-disable-next-line no-empty } Object.defineProperty(fn, 'adapterName', { __proto__: null, value }); } }); /** * Render a rejection reason string for unknown or unsupported adapters * * @param {string} reason * @returns {string} */ const renderReason = (reason) => `- ${reason}`; /** * Check if the adapter is resolved (function, null, or false) * * @param {Function|null|false} adapter * @returns {boolean} */ const isResolvedHandle = (adapter) => utils.isFunction(adapter) || adapter === null || adapter === false; /** * Get the first suitable adapter from the provided list. * Tries each adapter in order until a supported one is found. * Throws an AxiosError if no adapter is suitable. * * @param {Array|string|Function} adapters - Adapter(s) by name or function. * @param {Object} config - Axios request configuration * @throws {AxiosError} If no suitable adapter is available * @returns {Function} The resolved adapter function */ function getAdapter(adapters, config) { adapters = utils.isArray(adapters) ? adapters : [adapters]; const { length } = adapters; let nameOrAdapter; let adapter; const rejectedReasons = {}; for (let i = 0; i < length; i++) { nameOrAdapter = adapters[i]; let id; adapter = nameOrAdapter; if (!isResolvedHandle(nameOrAdapter)) { adapter = knownAdapters[(id = String(nameOrAdapter)).toLowerCase()]; if (adapter === undefined) { throw new AxiosError(`Unknown adapter '${id}'`); } } if (adapter && (utils.isFunction(adapter) || (adapter = adapter.get(config)))) { break; } rejectedReasons[id || '#' + i] = adapter; } if (!adapter) { const reasons = Object.entries(rejectedReasons).map( ([id, state]) => `adapter ${id} ` + (state === false ? 'is not supported by the environment' : 'is not available in the build') ); let s = length ? reasons.length > 1 ? 'since :\n' + reasons.map(renderReason).join('\n') : ' ' + renderReason(reasons[0]) : 'as no adapter specified'; throw new AxiosError( `There is no suitable adapter to dispatch the request ` + s, 'ERR_NOT_SUPPORT' ); } return adapter; } /** * Exports Axios adapters and utility to resolve an adapter */ export default { /** * Resolve an adapter from a list of adapter names or functions. * @type {Function} */ getAdapter, /** * Exposes all known adapters * @type {Object} */ adapters: knownAdapters, }; axios-axios-2d06f96/lib/adapters/fetch.js000066400000000000000000000464141521272452000203310ustar00rootroot00000000000000import platform from '../platform/index.js'; import utils from '../utils.js'; import AxiosError from '../core/AxiosError.js'; import composeSignals from '../helpers/composeSignals.js'; import { trackStream } from '../helpers/trackStream.js'; import AxiosHeaders from '../core/AxiosHeaders.js'; import { progressEventReducer, progressEventDecorator, asyncDecorator, } from '../helpers/progressEventReducer.js'; import resolveConfig from '../helpers/resolveConfig.js'; import settle from '../core/settle.js'; import estimateDataURLDecodedBytes from '../helpers/estimateDataURLDecodedBytes.js'; import { VERSION } from '../env/data.js'; import { toByteStringHeaderObject } from '../helpers/sanitizeHeaderValue.js'; const DEFAULT_CHUNK_SIZE = 64 * 1024; const { isFunction } = utils; /** * Encode a UTF-8 string to a Latin-1 byte string for use with btoa(). * This is a modern replacement for the deprecated unescape(encodeURIComponent(str)) pattern. * * @param {string} str The string to encode * * @returns {string} UTF-8 bytes as a Latin-1 string */ const encodeUTF8 = (str) => encodeURIComponent(str).replace(/%([0-9A-F]{2})/gi, (_, hex) => String.fromCharCode(parseInt(hex, 16)) ); // Node's WHATWG URL parser returns `username` and `password` percent-encoded. // Decode before composing the `auth` option so credentials such as // `my%40email.com:pass` are sent as `my@email.com:pass`. Falls back to the // original value for malformed input so a bad encoding never throws. const decodeURIComponentSafe = (value) => { if (!utils.isString(value)) { return value; } try { return decodeURIComponent(value); } catch (error) { return value; } }; const test = (fn, ...args) => { try { return !!fn(...args); } catch (e) { return false; } }; const maybeWithAuthCredentials = (url) => { const protocolIndex = url.indexOf('://'); let urlToCheck = url; if (protocolIndex !== -1) { urlToCheck = urlToCheck.slice(protocolIndex + 3); } return urlToCheck.includes('@') || urlToCheck.includes(':'); }; const factory = (env) => { const globalObject = utils.global !== undefined && utils.global !== null ? utils.global : globalThis; const { ReadableStream, TextEncoder } = globalObject; env = utils.merge.call( { skipUndefined: true, }, { Request: globalObject.Request, Response: globalObject.Response, }, env ); const { fetch: envFetch, Request, Response } = env; const isFetchSupported = envFetch ? isFunction(envFetch) : typeof fetch === 'function'; const isRequestSupported = isFunction(Request); const isResponseSupported = isFunction(Response); if (!isFetchSupported) { return false; } const isReadableStreamSupported = isFetchSupported && isFunction(ReadableStream); const encodeText = isFetchSupported && (typeof TextEncoder === 'function' ? ( (encoder) => (str) => encoder.encode(str) )(new TextEncoder()) : async (str) => new Uint8Array(await new Request(str).arrayBuffer())); const supportsRequestStream = isRequestSupported && isReadableStreamSupported && test(() => { let duplexAccessed = false; const request = new Request(platform.origin, { body: new ReadableStream(), method: 'POST', get duplex() { duplexAccessed = true; return 'half'; }, }); const hasContentType = request.headers.has('Content-Type'); if (request.body != null) { request.body.cancel(); } return duplexAccessed && !hasContentType; }); const supportsResponseStream = isResponseSupported && isReadableStreamSupported && test(() => utils.isReadableStream(new Response('').body)); const resolvers = { stream: supportsResponseStream && ((res) => res.body), }; isFetchSupported && (() => { ['text', 'arrayBuffer', 'blob', 'formData', 'stream'].forEach((type) => { !resolvers[type] && (resolvers[type] = (res, config) => { let method = res && res[type]; if (method) { return method.call(res); } throw new AxiosError( `Response type '${type}' is not supported`, AxiosError.ERR_NOT_SUPPORT, config ); }); }); })(); const getBodyLength = async (body) => { if (body == null) { return 0; } if (utils.isBlob(body)) { return body.size; } if (utils.isSpecCompliantForm(body)) { const _request = new Request(platform.origin, { method: 'POST', body, }); return (await _request.arrayBuffer()).byteLength; } if (utils.isArrayBufferView(body) || utils.isArrayBuffer(body)) { return body.byteLength; } if (utils.isURLSearchParams(body)) { body = body + ''; } if (utils.isString(body)) { return (await encodeText(body)).byteLength; } }; const resolveBodyLength = async (headers, body) => { const length = utils.toFiniteNumber(headers.getContentLength()); return length == null ? getBodyLength(body) : length; }; return async (config) => { let { url, method, data, signal, cancelToken, timeout, onDownloadProgress, onUploadProgress, responseType, headers, withCredentials = 'same-origin', fetchOptions, maxContentLength, maxBodyLength, } = resolveConfig(config); const hasMaxContentLength = utils.isNumber(maxContentLength) && maxContentLength > -1; const hasMaxBodyLength = utils.isNumber(maxBodyLength) && maxBodyLength > -1; const own = (key) => (utils.hasOwnProp(config, key) ? config[key] : undefined); let _fetch = envFetch || fetch; responseType = responseType ? (responseType + '').toLowerCase() : 'text'; let composedSignal = composeSignals( [signal, cancelToken && cancelToken.toAbortSignal()], timeout ); let request = null; const unsubscribe = composedSignal && composedSignal.unsubscribe && (() => { composedSignal.unsubscribe(); }); let requestContentLength; // AxiosError we raise while the request body is being streamed. Captured // by identity so the catch block can surface it directly, regardless of // how the runtime wraps the resulting fetch rejection (undici exposes it // as `err.cause`; some browsers drop the original error entirely). let pendingBodyError = null; const maxBodyLengthError = () => new AxiosError( 'Request body larger than maxBodyLength limit', AxiosError.ERR_BAD_REQUEST, config, request ); try { // HTTP basic authentication let auth = undefined; const configAuth = own('auth'); if (configAuth) { const username = utils.getSafeProp(configAuth, 'username') || ''; const password = utils.getSafeProp(configAuth, 'password') || ''; auth = { username, password }; } if (maybeWithAuthCredentials(url)) { const parsedURL = new URL(url, platform.origin); if (!auth && (parsedURL.username || parsedURL.password)) { const urlUsername = decodeURIComponentSafe(parsedURL.username); const urlPassword = decodeURIComponentSafe(parsedURL.password); auth = { username: urlUsername, password: urlPassword }; } if (parsedURL.username || parsedURL.password) { parsedURL.username = ''; parsedURL.password = ''; url = parsedURL.href; } } if (auth) { headers.delete('authorization'); headers.set( 'Authorization', 'Basic ' + btoa(encodeUTF8((auth.username || '') + ':' + (auth.password || ''))) ); } // Enforce maxContentLength for data: URLs up-front so we never materialize // an oversized payload. The HTTP adapter applies the same check (see http.js // "if (protocol === 'data:')" branch). if (hasMaxContentLength && typeof url === 'string' && url.startsWith('data:')) { const estimated = estimateDataURLDecodedBytes(url); if (estimated > maxContentLength) { throw new AxiosError( 'maxContentLength size of ' + maxContentLength + ' exceeded', AxiosError.ERR_BAD_RESPONSE, config, request ); } } // Enforce maxBodyLength against known-size bodies before dispatch using // the body's *actual* size — never a caller-declared Content-Length, // which could under-report to slip an oversized body past the check. // Unknown-size streams return undefined here and are counted per-chunk // below as fetch consumes them. if (hasMaxBodyLength && method !== 'get' && method !== 'head') { const outboundLength = await getBodyLength(data); if (typeof outboundLength === 'number' && isFinite(outboundLength)) { requestContentLength = outboundLength; if (outboundLength > maxBodyLength) { throw maxBodyLengthError(); } } } // A streamed body under maxBodyLength must be counted as fetch consumes // it; its size is never trusted from a caller-declared Content-Length. const mustEnforceStreamBody = hasMaxBodyLength && (utils.isReadableStream(data) || utils.isStream(data)); const trackRequestStream = (stream, onProgress, flush) => trackStream( stream, DEFAULT_CHUNK_SIZE, (loadedBytes) => { if (hasMaxBodyLength && loadedBytes > maxBodyLength) { throw (pendingBodyError = maxBodyLengthError()); } onProgress && onProgress(loadedBytes); }, flush ); if ( supportsRequestStream && method !== 'get' && method !== 'head' && (onUploadProgress || mustEnforceStreamBody) ) { requestContentLength = requestContentLength == null ? await resolveBodyLength(headers, data) : requestContentLength; // A declared length of 0 is only trusted to skip the wrap when we are // not enforcing a stream limit (which must not rely on that header). if (requestContentLength !== 0 || mustEnforceStreamBody) { let _request = new Request(url, { method: 'POST', body: data, duplex: 'half', }); let contentTypeHeader; if (utils.isFormData(data) && (contentTypeHeader = _request.headers.get('content-type'))) { headers.setContentType(contentTypeHeader); } if (_request.body) { const [onProgress, flush] = (onUploadProgress && progressEventDecorator( requestContentLength, progressEventReducer(asyncDecorator(onUploadProgress)) )) || []; data = trackRequestStream(_request.body, onProgress, flush); } } } else if ( mustEnforceStreamBody && !isRequestSupported && isReadableStreamSupported && method !== 'get' && method !== 'head' ) { data = trackRequestStream(data); } else if ( mustEnforceStreamBody && isRequestSupported && !supportsRequestStream && method !== 'get' && method !== 'head' ) { throw new AxiosError( 'Stream request bodies are not supported by the current fetch implementation', AxiosError.ERR_NOT_SUPPORT, config, request ); } if (!utils.isString(withCredentials)) { withCredentials = withCredentials ? 'include' : 'omit'; } // Cloudflare Workers throws when credentials are defined // see https://github.com/cloudflare/workerd/issues/902 const isCredentialsSupported = isRequestSupported && 'credentials' in Request.prototype; // If data is FormData and Content-Type is multipart/form-data without boundary, // delete it so fetch can set it correctly with the boundary if (utils.isFormData(data)) { const contentType = headers.getContentType(); if ( contentType && /^multipart\/form-data/i.test(contentType) && !/boundary=/i.test(contentType) ) { headers.delete('content-type'); } } // Set User-Agent header if not already set (fetch defaults to 'node' in Node.js) headers.set('User-Agent', 'axios/' + VERSION, false); const resolvedOptions = { ...fetchOptions, signal: composedSignal, method: method.toUpperCase(), headers: toByteStringHeaderObject(headers.normalize()), body: data, duplex: 'half', credentials: isCredentialsSupported ? withCredentials : undefined, }; request = isRequestSupported && new Request(url, resolvedOptions); let response = await (isRequestSupported ? _fetch(request, fetchOptions) : _fetch(url, resolvedOptions)); const responseHeaders = AxiosHeaders.from(response.headers); // Cheap pre-check: if the server honestly declares a content-length that // already exceeds the cap, reject before we start streaming. if (hasMaxContentLength) { const declaredLength = utils.toFiniteNumber(responseHeaders.getContentLength()); if (declaredLength != null && declaredLength > maxContentLength) { throw new AxiosError( 'maxContentLength size of ' + maxContentLength + ' exceeded', AxiosError.ERR_BAD_RESPONSE, config, request ); } } const isStreamResponse = supportsResponseStream && (responseType === 'stream' || responseType === 'response'); if ( supportsResponseStream && response.body && (onDownloadProgress || hasMaxContentLength || (isStreamResponse && unsubscribe)) ) { const options = {}; ['status', 'statusText', 'headers'].forEach((prop) => { options[prop] = response[prop]; }); const responseContentLength = utils.toFiniteNumber(responseHeaders.getContentLength()); const [onProgress, flush] = (onDownloadProgress && progressEventDecorator( responseContentLength, progressEventReducer(asyncDecorator(onDownloadProgress), true) )) || []; let bytesRead = 0; const onChunkProgress = (loadedBytes) => { if (hasMaxContentLength) { bytesRead = loadedBytes; if (bytesRead > maxContentLength) { throw new AxiosError( 'maxContentLength size of ' + maxContentLength + ' exceeded', AxiosError.ERR_BAD_RESPONSE, config, request ); } } onProgress && onProgress(loadedBytes); }; response = new Response( trackStream(response.body, DEFAULT_CHUNK_SIZE, onChunkProgress, () => { flush && flush(); unsubscribe && unsubscribe(); }), options ); } responseType = responseType || 'text'; let responseData = await resolvers[utils.findKey(resolvers, responseType) || 'text']( response, config ); // Fallback enforcement for environments without ReadableStream support // (legacy runtimes). Detect materialized size from typed output; skip // streams/Response passthrough since the user will read those themselves. if (hasMaxContentLength && !supportsResponseStream && !isStreamResponse) { let materializedSize; if (responseData != null) { if (typeof responseData.byteLength === 'number') { materializedSize = responseData.byteLength; } else if (typeof responseData.size === 'number') { materializedSize = responseData.size; } else if (typeof responseData === 'string') { materializedSize = typeof TextEncoder === 'function' ? new TextEncoder().encode(responseData).byteLength : responseData.length; } } if (typeof materializedSize === 'number' && materializedSize > maxContentLength) { throw new AxiosError( 'maxContentLength size of ' + maxContentLength + ' exceeded', AxiosError.ERR_BAD_RESPONSE, config, request ); } } !isStreamResponse && unsubscribe && unsubscribe(); return await new Promise((resolve, reject) => { settle(resolve, reject, { data: responseData, headers: AxiosHeaders.from(response.headers), status: response.status, statusText: response.statusText, config, request, }); }); } catch (err) { unsubscribe && unsubscribe(); // Safari can surface fetch aborts as a DOMException-like object whose // branded getters throw. Prefer our composed signal reason before reading // the caught error, preserving timeout vs cancellation semantics. if (composedSignal && composedSignal.aborted && composedSignal.reason instanceof AxiosError) { const canceledError = composedSignal.reason; canceledError.config = config; request && (canceledError.request = request); err !== canceledError && (canceledError.cause = err); throw canceledError; } // Surface a maxBodyLength violation we raised while the request body was // being streamed. Matching by identity (rather than reading // `err.cause.isAxiosError`) keeps the error deterministic across runtimes // and avoids both prototype-pollution reads and mis-attributing a foreign // AxiosError that merely happened to land in `err.cause`. if (pendingBodyError) { request && !pendingBodyError.request && (pendingBodyError.request = request); throw pendingBodyError; } // Re-throw AxiosErrors we raised synchronously (data: URL / content-length // pre-checks, response size enforcement) without re-wrapping them. if (err instanceof AxiosError) { request && !err.request && (err.request = request); throw err; } if (err && err.name === 'TypeError' && /Load failed|fetch/i.test(err.message)) { throw Object.assign( new AxiosError( 'Network Error', AxiosError.ERR_NETWORK, config, request, err && err.response ), { cause: err.cause || err, } ); } throw AxiosError.from(err, err && err.code, config, request, err && err.response); } }; }; const seedCache = new Map(); export const getFetch = (config) => { let env = (config && config.env) || {}; const { fetch, Request, Response } = env; const seeds = [Request, Response, fetch]; let len = seeds.length, i = len, seed, target, map = seedCache; while (i--) { seed = seeds[i]; target = map.get(seed); target === undefined && map.set(seed, (target = i ? new Map() : factory(env))); map = target; } return target; }; const adapter = getFetch(); export default adapter; axios-axios-2d06f96/lib/adapters/http.js000077500000000000000000001362421521272452000202210ustar00rootroot00000000000000import utils from '../utils.js'; import settle from '../core/settle.js'; import buildFullPath from '../core/buildFullPath.js'; import buildURL from '../helpers/buildURL.js'; import { getProxyForUrl } from 'proxy-from-env'; import HttpsProxyAgent from 'https-proxy-agent'; import http from 'http'; import https from 'https'; import http2 from 'http2'; import util from 'util'; import { resolve as resolvePath } from 'path'; import followRedirects from 'follow-redirects'; import zlib from 'zlib'; import { VERSION } from '../env/data.js'; import transitionalDefaults from '../defaults/transitional.js'; import AxiosError from '../core/AxiosError.js'; import CanceledError from '../cancel/CanceledError.js'; import platform from '../platform/index.js'; import fromDataURI from '../helpers/fromDataURI.js'; import stream from 'stream'; import AxiosHeaders from '../core/AxiosHeaders.js'; import AxiosTransformStream from '../helpers/AxiosTransformStream.js'; import { EventEmitter } from 'events'; import formDataToStream from '../helpers/formDataToStream.js'; import readBlob from '../helpers/readBlob.js'; import ZlibHeaderTransformStream from '../helpers/ZlibHeaderTransformStream.js'; import Http2Sessions from '../helpers/Http2Sessions.js'; import callbackify from '../helpers/callbackify.js'; import shouldBypassProxy from '../helpers/shouldBypassProxy.js'; import { toByteStringHeaderObject } from '../helpers/sanitizeHeaderValue.js'; import { progressEventReducer, progressEventDecorator, asyncDecorator, } from '../helpers/progressEventReducer.js'; import estimateDataURLDecodedBytes from '../helpers/estimateDataURLDecodedBytes.js'; const zlibOptions = { flush: zlib.constants.Z_SYNC_FLUSH, finishFlush: zlib.constants.Z_SYNC_FLUSH, }; const brotliOptions = { flush: zlib.constants.BROTLI_OPERATION_FLUSH, finishFlush: zlib.constants.BROTLI_OPERATION_FLUSH, }; const zstdOptions = { flush: zlib.constants.ZSTD_e_flush, finishFlush: zlib.constants.ZSTD_e_flush, }; const isBrotliSupported = utils.isFunction(zlib.createBrotliDecompress); const isZstdSupported = utils.isFunction(zlib.createZstdDecompress); const ACCEPT_ENCODING = 'gzip, compress, deflate' + (isBrotliSupported ? ', br' : ''); const ACCEPT_ENCODING_WITH_ZSTD = ACCEPT_ENCODING + (isZstdSupported ? ', zstd' : ''); const { http: httpFollow, https: httpsFollow } = followRedirects; const isHttps = /https:?/; const FORM_DATA_CONTENT_HEADERS = ['content-type', 'content-length']; function setFormDataHeaders(headers, formHeaders, policy) { if (policy !== 'content-only') { headers.set(formHeaders); return; } Object.entries(formHeaders).forEach(([key, val]) => { if (FORM_DATA_CONTENT_HEADERS.includes(key.toLowerCase())) { headers.set(key, val); } }); } // Symbols used to bind a single 'error' listener to a pooled socket and track // the request currently owning that socket across keep-alive reuse (issue #10780). const kAxiosSocketListener = Symbol('axios.http.socketListener'); const kAxiosCurrentReq = Symbol('axios.http.currentReq'); // Tags HttpsProxyAgent instances installed by setProxy() so the redirect path // can strip them without clobbering a user-supplied agent that happens to be // an HttpsProxyAgent. const kAxiosInstalledTunnel = Symbol('axios.http.installedTunnel'); // Cache of CONNECT-tunneling agents keyed by proxy config so repeat requests // through the same proxy reuse a single agent (and its socket pool). The // keyspace is bounded by the set of distinct proxy configs the process uses, // so unbounded growth is not a concern in practice. const tunnelingAgentCache = new Map(); const tunnelingAgentCacheUser = new WeakMap(); function getTunnelingAgent(agentOptions, userHttpsAgent) { const key = agentOptions.protocol + '//' + agentOptions.hostname + ':' + (agentOptions.port || '') + '#' + (agentOptions.auth || ''); const cache = userHttpsAgent ? (tunnelingAgentCacheUser.get(userHttpsAgent) || tunnelingAgentCacheUser.set(userHttpsAgent, new Map()).get(userHttpsAgent)) : tunnelingAgentCache; let agent = cache.get(key); if (agent) return agent; // Forward the user's TLS options (custom CA, rejectUnauthorized, client cert, // etc.) into the tunneling agent so they apply to the origin TLS upgrade // performed after CONNECT. Our proxy fields take precedence on conflict. const merged = userHttpsAgent && userHttpsAgent.options ? { ...userHttpsAgent.options, ...agentOptions } : agentOptions; agent = new HttpsProxyAgent(merged); if (userHttpsAgent && userHttpsAgent.options) { const originTLSOptions = { ...userHttpsAgent.options }; const callback = agent.callback; agent.callback = function axiosTunnelingAgentCallback(req, opts) { // HttpsProxyAgent v5 reads callback opts for the post-CONNECT origin TLS upgrade. return callback.call(this, req, { ...originTLSOptions, ...opts }); }; } agent[kAxiosInstalledTunnel] = true; cache.set(key, agent); return agent; } const supportedProtocols = platform.protocols.map((protocol) => { return protocol + ':'; }); // Node's WHATWG URL parser returns `username` and `password` percent-encoded. // Decode before composing the `auth` option so credentials such as // `my%40email.com:pass` are sent as `my@email.com:pass`. Falls back to the // original value for malformed input so a bad encoding never throws. const decodeURIComponentSafe = (value) => { if (!utils.isString(value)) { return value; } try { return decodeURIComponent(value); } catch (error) { return value; } }; const flushOnFinish = (stream, [throttled, flush]) => { stream.on('end', flush).on('error', flush); return throttled; }; const http2Sessions = new Http2Sessions(); /** * If the proxy, auth, sensitive header, or config beforeRedirects functions are defined, * call them with the options object. * * @param {Object} options - The options object that was passed to the request. * * @returns {Object} */ function dispatchBeforeRedirect(options, responseDetails, requestDetails) { if (options.beforeRedirects.proxy) { options.beforeRedirects.proxy(options); } if (options.beforeRedirects.auth) { options.beforeRedirects.auth(options); } if (options.beforeRedirects.sensitiveHeaders) { options.beforeRedirects.sensitiveHeaders(options, requestDetails); } if (options.beforeRedirects.config) { options.beforeRedirects.config(options, responseDetails, requestDetails); } } function stripMatchingHeaders(headers, sensitiveSet) { if (!headers) { return; } Object.keys(headers).forEach((header) => { if (sensitiveSet.has(header.toLowerCase())) { delete headers[header]; } }); } function isSameOriginRedirect(redirectOptions, requestDetails) { if (!requestDetails) { return false; } try { return new URL(requestDetails.url).origin === new URL(redirectOptions.href).origin; } catch (e) { // If origin comparison fails, treat the redirect as unsafe. return false; } } /** * If the proxy or config afterRedirects functions are defined, call them with the options * * @param {http.ClientRequestArgs} options * @param {AxiosProxyConfig} configProxy configuration from Axios options object * @param {string} location * * @returns {http.ClientRequestArgs} */ function setProxy(options, configProxy, location, isRedirect, configHttpsAgent) { let proxy = configProxy; if (!proxy && proxy !== false) { const proxyUrl = getProxyForUrl(location); if (proxyUrl) { if (!shouldBypassProxy(location)) { proxy = new URL(proxyUrl); } } } // On redirect re-invocation, strip any stale Proxy-Authorization header carried // over from the prior request (e.g. new target no longer uses a proxy, or uses // a different proxy). Skip on the initial request so user-supplied headers are // preserved. Header names are case-insensitive, so remove every case variant. if (isRedirect && options.headers) { for (const name of Object.keys(options.headers)) { if (name.toLowerCase() === 'proxy-authorization') { delete options.headers[name]; } } } // Strip any tunneling agent we installed for the previous hop so a redirect // that drops the proxy or crosses an HTTPS↔HTTP boundary doesn't reuse a // stale one. Match on our Symbol marker so a user-supplied HttpsProxyAgent // (which won't carry the marker) is left alone. if (isRedirect && options.agent && options.agent[kAxiosInstalledTunnel]) { options.agent = undefined; } if (proxy) { // Read proxy fields without traversing the prototype chain. URL instances expose // username/password/hostname/host/port/protocol via getters on URL.prototype (so // direct reads are shielded), but plain object proxies — and the `auth` field // (which URL does not expose) — must be guarded so a polluted Object.prototype // (e.g. Object.prototype.auth = { username, password }) cannot inject // attacker-controlled credentials into the Proxy-Authorization header or // redirect proxying to an attacker-controlled host. const isProxyURL = proxy instanceof URL; const readProxyField = (key) => isProxyURL || utils.hasOwnProp(proxy, key) ? proxy[key] : undefined; const proxyUsername = readProxyField('username'); const proxyPassword = readProxyField('password'); let proxyAuth = utils.hasOwnProp(proxy, 'auth') ? proxy.auth : undefined; // Basic proxy authorization if (proxyUsername) { proxyAuth = (proxyUsername || '') + ':' + (proxyPassword || ''); } if (proxyAuth) { // Support proxy auth object form. Read sub-fields via own-prop checks so a // plain object inheriting from polluted Object.prototype cannot leak creds. const authIsObject = typeof proxyAuth === 'object'; const authUsername = authIsObject && utils.hasOwnProp(proxyAuth, 'username') ? proxyAuth.username : undefined; const authPassword = authIsObject && utils.hasOwnProp(proxyAuth, 'password') ? proxyAuth.password : undefined; const validProxyAuth = Boolean(authUsername || authPassword); if (validProxyAuth) { proxyAuth = (authUsername || '') + ':' + (authPassword || ''); } else if (authIsObject) { throw new AxiosError('Invalid proxy authorization', AxiosError.ERR_BAD_OPTION, { proxy }); } } const targetIsHttps = isHttps.test(options.protocol); if (targetIsHttps) { // CONNECT-tunneling path for HTTPS targets. Preserves end-to-end TLS to // the origin so the proxy cannot inspect the URL, headers, or body — the // behavior already promised by THREATMODEL.md (T-R9). HttpsProxyAgent // sends Proxy-Authorization on the CONNECT request only, never on the // wrapped TLS request, which is why we don't stamp it onto // options.headers here. If the user already supplied an HttpsProxyAgent, // they own tunneling end-to-end and we leave them alone; otherwise we // install our own tunneling agent and forward their TLS options (if any) // so a custom httpsAgent for cert pinning / rejectUnauthorized still // applies to the origin TLS upgrade. if (!(configHttpsAgent instanceof HttpsProxyAgent)) { const proxyHost = readProxyField('hostname') || readProxyField('host'); const proxyPort = readProxyField('port'); const rawProxyProtocol = readProxyField('protocol'); const normalizedProtocol = rawProxyProtocol ? rawProxyProtocol.includes(':') ? rawProxyProtocol : `${rawProxyProtocol}:` : 'http:'; // Bracket IPv6 literals for URL parsing; URL.hostname strips the // brackets again on read so the agent receives the raw form. const proxyHostForURL = proxyHost && proxyHost.includes(':') && !proxyHost.startsWith('[') ? `[${proxyHost}]` : proxyHost; const proxyURL = new URL( `${normalizedProtocol}//${proxyHostForURL}${proxyPort ? ':' + proxyPort : ''}` ); const agentOptions = { protocol: proxyURL.protocol, hostname: proxyURL.hostname.replace(/^\[|\]$/g, ''), port: proxyURL.port, auth: proxyAuth && typeof proxyAuth === 'string' ? proxyAuth : undefined, }; if (proxyURL.protocol === 'https:') { agentOptions.ALPNProtocols = ['http/1.1']; } const tunnelingAgent = getTunnelingAgent(agentOptions, configHttpsAgent); // Set both: `options.agent` is consumed by the native https.request path // (maxRedirects === 0); `options.agents.https` is consumed by // follow-redirects, which ignores `options.agent` when `options.agents` // is present. options.agent = tunnelingAgent; if (options.agents) { options.agents.https = tunnelingAgent; } } } else { // Forward-proxy mode for plaintext HTTP targets. The request line carries // the absolute URL and the proxy sees everything — acceptable for plain // HTTP since the wire was already plaintext. if (proxyAuth) { const base64 = Buffer.from(proxyAuth, 'utf8').toString('base64'); options.headers['Proxy-Authorization'] = 'Basic ' + base64; } // Preserve a user-supplied Host header (case-insensitive) so callers can override // the value forwarded to the proxy; otherwise default to the request URL's host. let hasUserHostHeader = false; for (const name of Object.keys(options.headers)) { if (name.toLowerCase() === 'host') { hasUserHostHeader = true; break; } } if (!hasUserHostHeader) { options.headers.host = options.hostname + (options.port ? ':' + options.port : ''); } const proxyHost = readProxyField('hostname') || readProxyField('host'); options.hostname = proxyHost; // Replace 'host' since options is not a URL object options.host = proxyHost; options.port = readProxyField('port'); options.path = location; const proxyProtocol = readProxyField('protocol'); if (proxyProtocol) { options.protocol = proxyProtocol.includes(':') ? proxyProtocol : `${proxyProtocol}:`; } } } options.beforeRedirects.proxy = function beforeRedirect(redirectOptions) { // Configure proxy for redirected request, passing the original config proxy to apply // the exact same logic as if the redirected request was performed by axios directly. setProxy(redirectOptions, configProxy, redirectOptions.href, true, configHttpsAgent); }; } const isHttpAdapterSupported = typeof process !== 'undefined' && utils.kindOf(process) === 'process'; // temporary hotfix const wrapAsync = (asyncExecutor) => { return new Promise((resolve, reject) => { let onDone; let isDone; const done = (value, isRejected) => { if (isDone) return; isDone = true; onDone && onDone(value, isRejected); }; const _resolve = (value) => { done(value); resolve(value); }; const _reject = (reason) => { done(reason, true); reject(reason); }; asyncExecutor(_resolve, _reject, (onDoneHandler) => (onDone = onDoneHandler)).catch(_reject); }); }; const resolveFamily = ({ address, family }) => { if (!utils.isString(address)) { throw TypeError('address must be a string'); } return { address, family: family || (address.indexOf('.') < 0 ? 6 : 4), }; }; const buildAddressEntry = (address, family) => resolveFamily(utils.isObject(address) ? address : { address, family }); const http2Transport = { request(options, cb) { const authority = options.protocol + '//' + options.hostname + ':' + (options.port || (options.protocol === 'https:' ? 443 : 80)); const { http2Options, headers } = options; const session = http2Sessions.getSession(authority, http2Options); const { HTTP2_HEADER_SCHEME, HTTP2_HEADER_METHOD, HTTP2_HEADER_PATH, HTTP2_HEADER_STATUS } = http2.constants; const http2Headers = { [HTTP2_HEADER_SCHEME]: options.protocol.replace(':', ''), [HTTP2_HEADER_METHOD]: options.method, [HTTP2_HEADER_PATH]: options.path, }; utils.forEach(headers, (header, name) => { name.charAt(0) !== ':' && (http2Headers[name] = header); }); const req = session.request(http2Headers); req.once('response', (responseHeaders) => { const response = req; //duplex responseHeaders = Object.assign({}, responseHeaders); const status = responseHeaders[HTTP2_HEADER_STATUS]; delete responseHeaders[HTTP2_HEADER_STATUS]; response.headers = responseHeaders; response.statusCode = +status; cb(response); }); return req; }, }; /*eslint consistent-return:0*/ export default isHttpAdapterSupported && function httpAdapter(config) { return wrapAsync(async function dispatchHttpRequest(resolve, reject, onDone) { // Read config pollution-safely: own properties and members inherited from // a non-Object.prototype source (e.g. an Object.create(defaults) template) // are honored, but values injected onto a polluted Object.prototype are // ignored. All behavior-affecting reads in this adapter go through own() // so the protection boundary stays consistent. const own = (key) => utils.getSafeProp(config, key); const transitional = own('transitional') || transitionalDefaults; let data = own('data'); let lookup = own('lookup'); let family = own('family'); let httpVersion = own('httpVersion'); if (httpVersion === undefined) httpVersion = 1; let http2Options = own('http2Options'); const responseType = own('responseType'); const responseEncoding = own('responseEncoding'); const httpAgent = own('httpAgent'); const httpsAgent = own('httpsAgent'); const method = own('method').toUpperCase(); const maxRedirects = own('maxRedirects'); const maxBodyLength = own('maxBodyLength'); const maxContentLength = own('maxContentLength'); const decompress = own('decompress'); let isDone; let rejected = false; let req; let connectPhaseTimer; httpVersion = +httpVersion; if (Number.isNaN(httpVersion)) { throw TypeError(`Invalid protocol version: '${config.httpVersion}' is not a number`); } if (httpVersion !== 1 && httpVersion !== 2) { throw TypeError(`Unsupported protocol version '${httpVersion}'`); } const isHttp2 = httpVersion === 2; if (lookup) { const _lookup = callbackify(lookup, (value) => (utils.isArray(value) ? value : [value])); // hotfix to support opt.all option which is required for node 20.x lookup = (hostname, opt, cb) => { _lookup(hostname, opt, (err, arg0, arg1) => { if (err) { return cb(err); } const addresses = utils.isArray(arg0) ? arg0.map((addr) => buildAddressEntry(addr)) : [buildAddressEntry(arg0, arg1)]; opt.all ? cb(err, addresses) : cb(err, addresses[0].address, addresses[0].family); }); }; } const abortEmitter = new EventEmitter(); function abort(reason) { try { abortEmitter.emit( 'abort', !reason || reason.type ? new CanceledError(null, config, req) : reason ); } catch (err) { // ignore emit errors } } function clearConnectPhaseTimer() { if (connectPhaseTimer) { clearTimeout(connectPhaseTimer); connectPhaseTimer = null; } } function createTimeoutError() { const configTimeout = own('timeout'); let timeoutErrorMessage = configTimeout ? 'timeout of ' + configTimeout + 'ms exceeded' : 'timeout exceeded'; const configTimeoutErrorMessage = own('timeoutErrorMessage'); if (configTimeoutErrorMessage) { timeoutErrorMessage = configTimeoutErrorMessage; } return new AxiosError( timeoutErrorMessage, transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED, config, req ); } abortEmitter.once('abort', reject); const onFinished = () => { clearConnectPhaseTimer(); if (config.cancelToken) { config.cancelToken.unsubscribe(abort); } if (config.signal) { config.signal.removeEventListener('abort', abort); } abortEmitter.removeAllListeners(); }; if (config.cancelToken || config.signal) { config.cancelToken && config.cancelToken.subscribe(abort); if (config.signal) { config.signal.aborted ? abort() : config.signal.addEventListener('abort', abort); } } onDone((response, isRejected) => { isDone = true; clearConnectPhaseTimer(); if (isRejected) { rejected = true; onFinished(); return; } const { data } = response; if (data instanceof stream.Readable || data instanceof stream.Duplex) { const offListeners = stream.finished(data, () => { offListeners(); onFinished(); }); } else { onFinished(); } }); // Parse url const fullPath = buildFullPath(own('baseURL'), own('url'), own('allowAbsoluteUrls'), config); const parsed = new URL(fullPath, platform.hasBrowserEnv ? platform.origin : undefined); const protocol = parsed.protocol || supportedProtocols[0]; if (protocol === 'data:') { // Apply the same semantics as HTTP: only enforce if a finite, non-negative cap is set. if (maxContentLength > -1) { // Use the exact string passed to fromDataURI (the configured url); fall back to fullPath if needed. const dataUrl = String(own('url') || fullPath || ''); const estimated = estimateDataURLDecodedBytes(dataUrl); if (estimated > maxContentLength) { return reject( new AxiosError( 'maxContentLength size of ' + maxContentLength + ' exceeded', AxiosError.ERR_BAD_RESPONSE, config ) ); } } let convertedData; if (method !== 'GET') { return settle(resolve, reject, { status: 405, statusText: 'method not allowed', headers: {}, config, }); } try { convertedData = fromDataURI(own('url'), responseType === 'blob', { Blob: config.env && config.env.Blob, }); } catch (err) { throw AxiosError.from(err, AxiosError.ERR_BAD_REQUEST, config); } if (responseType === 'text') { convertedData = convertedData.toString(responseEncoding); if (!responseEncoding || responseEncoding === 'utf8') { convertedData = utils.stripBOM(convertedData); } } else if (responseType === 'stream') { convertedData = stream.Readable.from(convertedData); } return settle(resolve, reject, { data: convertedData, status: 200, statusText: 'OK', headers: new AxiosHeaders(), config, }); } if (supportedProtocols.indexOf(protocol) === -1) { return reject( new AxiosError('Unsupported protocol ' + protocol, AxiosError.ERR_BAD_REQUEST, config) ); } const headers = AxiosHeaders.from(config.headers).normalize(); // Set User-Agent (required by some servers) // See https://github.com/axios/axios/issues/69 // User-Agent is specified; handle case where no UA header is desired // Only set header if it hasn't been set in config headers.set('User-Agent', 'axios/' + VERSION, false); const { onUploadProgress, onDownloadProgress } = config; const maxRate = config.maxRate; let maxUploadRate = undefined; let maxDownloadRate = undefined; // support for spec compliant FormData objects if (utils.isSpecCompliantForm(data)) { const userBoundary = headers.getContentType(/boundary=([-_\w\d]{10,70})/i); data = formDataToStream( data, (formHeaders) => { headers.set(formHeaders); }, { tag: `axios-${VERSION}-boundary`, boundary: (userBoundary && userBoundary[1]) || undefined, } ); // support for https://www.npmjs.com/package/form-data api } else if ( utils.isFormData(data) && utils.isFunction(data.getHeaders) && data.getHeaders !== Object.prototype.getHeaders ) { setFormDataHeaders(headers, data.getHeaders(), own('formDataHeaderPolicy')); if (!headers.hasContentLength()) { try { const knownLength = await util.promisify(data.getLength).call(data); Number.isFinite(knownLength) && knownLength >= 0 && headers.setContentLength(knownLength); /*eslint no-empty:0*/ } catch (e) {} } } else if (utils.isBlob(data) || utils.isFile(data)) { data.size && headers.setContentType(data.type || 'application/octet-stream'); headers.setContentLength(data.size || 0); data = stream.Readable.from(readBlob(data)); } else if (data && !utils.isStream(data)) { if (Buffer.isBuffer(data)) { // Nothing to do... } else if (utils.isArrayBuffer(data)) { data = Buffer.from(new Uint8Array(data)); } else if (utils.isString(data)) { data = Buffer.from(data, 'utf-8'); } else { return reject( new AxiosError( 'Data after transformation must be a string, an ArrayBuffer, a Buffer, or a Stream', AxiosError.ERR_BAD_REQUEST, config ) ); } // Add Content-Length header if data exists headers.setContentLength(data.length, false); if (maxBodyLength > -1 && data.length > maxBodyLength) { return reject( new AxiosError( 'Request body larger than maxBodyLength limit', AxiosError.ERR_BAD_REQUEST, config ) ); } } const contentLength = utils.toFiniteNumber(headers.getContentLength()); if (utils.isArray(maxRate)) { maxUploadRate = maxRate[0]; maxDownloadRate = maxRate[1]; } else { maxUploadRate = maxDownloadRate = maxRate; } if (data && (onUploadProgress || maxUploadRate)) { if (!utils.isStream(data)) { data = stream.Readable.from(data, { objectMode: false }); } data = stream.pipeline( [ data, new AxiosTransformStream({ maxRate: utils.toFiniteNumber(maxUploadRate), }), ], utils.noop ); onUploadProgress && data.on( 'progress', flushOnFinish( data, progressEventDecorator( contentLength, progressEventReducer(asyncDecorator(onUploadProgress), false, 3) ) ) ); } // HTTP basic authentication let auth = undefined; const configAuth = own('auth'); if (configAuth) { const username = utils.getSafeProp(configAuth, 'username') || ''; const password = utils.getSafeProp(configAuth, 'password') || ''; auth = username + ':' + password; } if (!auth && (parsed.username || parsed.password)) { const urlUsername = decodeURIComponentSafe(parsed.username); const urlPassword = decodeURIComponentSafe(parsed.password); auth = urlUsername + ':' + urlPassword; } auth && headers.delete('authorization'); let path; try { path = buildURL( parsed.pathname + parsed.search, own('params'), own('paramsSerializer') ).replace(/^\?/, ''); } catch (err) { const customErr = new Error(err.message); customErr.config = config; customErr.url = own('url'); customErr.exists = true; return reject(customErr); } headers.set( 'Accept-Encoding', utils.hasOwnProp(transitional, 'advertiseZstdAcceptEncoding') && transitional.advertiseZstdAcceptEncoding === true ? ACCEPT_ENCODING_WITH_ZSTD : ACCEPT_ENCODING, false ); // Null-prototype to block prototype pollution gadgets on properties read // directly by Node's http.request (e.g. insecureHTTPParser, lookup). const options = Object.assign(Object.create(null), { path, method: method, headers: toByteStringHeaderObject(headers), agents: { http: httpAgent, https: httpsAgent }, auth, protocol, family, beforeRedirect: dispatchBeforeRedirect, beforeRedirects: Object.create(null), http2Options, }); // cacheable-lookup integration hotfix !utils.isUndefined(lookup) && (options.lookup = lookup); const socketPath = own('socketPath'); if (socketPath) { if (typeof socketPath !== 'string') { return reject( new AxiosError('socketPath must be a string', AxiosError.ERR_BAD_OPTION_VALUE, config) ); } const allowedSocketPaths = own('allowedSocketPaths'); if (allowedSocketPaths != null) { const allowed = Array.isArray(allowedSocketPaths) ? allowedSocketPaths : [allowedSocketPaths]; const resolvedSocket = resolvePath(socketPath); const isAllowed = allowed.some( (entry) => typeof entry === 'string' && resolvePath(entry) === resolvedSocket ); if (!isAllowed) { return reject( new AxiosError( `socketPath "${socketPath}" is not permitted by allowedSocketPaths`, AxiosError.ERR_BAD_OPTION_VALUE, config ) ); } } options.socketPath = socketPath; } else { options.hostname = parsed.hostname.startsWith('[') ? parsed.hostname.slice(1, -1) : parsed.hostname; options.port = parsed.port; setProxy( options, own('proxy'), protocol + '//' + parsed.hostname + (parsed.port ? ':' + parsed.port : '') + options.path, false, httpsAgent ); } let transport; let isNativeTransport = false; // True only for the follow-redirects transport, which applies // options.maxBodyLength itself. Every other transport (http2, native // http/https, a user-supplied custom transport) needs the explicit // byte-counting pipeline below to enforce maxBodyLength on streamed uploads. let transportEnforcesMaxBodyLength = false; const isHttpsRequest = isHttps.test(options.protocol); // Don't clobber a CONNECT-tunneling agent installed by setProxy() for an // HTTPS target. if (options.agent == null) { options.agent = isHttpsRequest ? httpsAgent : httpAgent; } if (isHttp2) { transport = http2Transport; } else { const configTransport = own('transport'); if (configTransport) { transport = configTransport; } else if (maxRedirects === 0) { transport = isHttpsRequest ? https : http; isNativeTransport = true; } else { transportEnforcesMaxBodyLength = true; options.sensitiveHeaders = []; if (maxRedirects) { options.maxRedirects = maxRedirects; } const configBeforeRedirect = own('beforeRedirect'); if (configBeforeRedirect) { options.beforeRedirects.config = configBeforeRedirect; } if (auth) { // Restore HTTP Basic credentials on same-origin redirects only. // follow-redirects >= 1.15.8 strips Authorization on every redirect (see #6929); // cross-origin stripping is the documented mitigation for T-R2 in THREATMODEL.md // and is preserved by deliberately not restoring on origin change. const requestOrigin = parsed.origin; const authToRestore = auth; options.beforeRedirects.auth = function beforeRedirectAuth(redirectOptions) { try { if (new URL(redirectOptions.href).origin === requestOrigin) { redirectOptions.auth = authToRestore; } } catch (e) { // ignore malformed URL: leaving auth stripped is fail-safe } }; } const sensitiveHeaders = own('sensitiveHeaders'); if (sensitiveHeaders != null) { if (!utils.isArray(sensitiveHeaders)) { return reject( new AxiosError( 'sensitiveHeaders must be an array of strings', AxiosError.ERR_BAD_OPTION_VALUE, config ) ); } const sensitiveSet = new Set(); for (const header of sensitiveHeaders) { if (!utils.isString(header)) { return reject( new AxiosError( 'sensitiveHeaders must be an array of strings', AxiosError.ERR_BAD_OPTION_VALUE, config ) ); } sensitiveSet.add(header.toLowerCase()); } if (sensitiveSet.size) { options.sensitiveHeaders = Array.from(sensitiveSet); options.beforeRedirects.sensitiveHeaders = function beforeRedirectSensitiveHeaders( redirectOptions, requestDetails ) { if (!isSameOriginRedirect(redirectOptions, requestDetails)) { stripMatchingHeaders(redirectOptions.headers, sensitiveSet); } }; } } transport = isHttpsRequest ? httpsFollow : httpFollow; } } if (maxBodyLength > -1) { options.maxBodyLength = maxBodyLength; } else { // follow-redirects does not skip comparison, so it should always succeed for axios -1 unlimited options.maxBodyLength = Infinity; } // Always set an explicit own value so a polluted // Object.prototype.insecureHTTPParser cannot enable the lenient parser // through Node's internal options copy options.insecureHTTPParser = Boolean(own('insecureHTTPParser')); // Create the request req = transport.request(options, function handleResponse(res) { clearConnectPhaseTimer(); if (req.destroyed) return; const streams = [res]; const responseLength = utils.toFiniteNumber(res.headers['content-length']); if (onDownloadProgress || maxDownloadRate) { const transformStream = new AxiosTransformStream({ maxRate: utils.toFiniteNumber(maxDownloadRate), }); onDownloadProgress && transformStream.on( 'progress', flushOnFinish( transformStream, progressEventDecorator( responseLength, progressEventReducer(asyncDecorator(onDownloadProgress), true, 3) ) ) ); streams.push(transformStream); } // decompress the response body transparently if required let responseStream = res; // return the last request in case of redirects const lastRequest = res.req || req; // if decompress disabled we should not decompress if (decompress !== false && res.headers['content-encoding']) { // if no content, but headers still say that it is encoded, // remove the header not confuse downstream operations if (method === 'HEAD' || res.statusCode === 204) { delete res.headers['content-encoding']; } switch ((res.headers['content-encoding'] || '').toLowerCase()) { /*eslint default-case:0*/ case 'gzip': case 'x-gzip': case 'compress': case 'x-compress': // add the unzipper to the body stream processing pipeline streams.push(zlib.createUnzip(zlibOptions)); // remove the content-encoding in order to not confuse downstream operations delete res.headers['content-encoding']; break; case 'deflate': streams.push(new ZlibHeaderTransformStream()); // add the unzipper to the body stream processing pipeline streams.push(zlib.createUnzip(zlibOptions)); // remove the content-encoding in order to not confuse downstream operations delete res.headers['content-encoding']; break; case 'br': if (isBrotliSupported) { streams.push(zlib.createBrotliDecompress(brotliOptions)); delete res.headers['content-encoding']; } break; case 'zstd': if (isZstdSupported) { streams.push(zlib.createZstdDecompress(zstdOptions)); delete res.headers['content-encoding']; } break; } } responseStream = streams.length > 1 ? stream.pipeline(streams, utils.noop) : streams[0]; const response = { status: res.statusCode, statusText: res.statusMessage, headers: new AxiosHeaders(res.headers), config, request: lastRequest, }; if (responseType === 'stream') { // Enforce maxContentLength on streamed responses; previously this // was applied only to buffered responses. if (maxContentLength > -1) { const limit = maxContentLength; const source = responseStream; async function* enforceMaxContentLength() { let totalResponseBytes = 0; for await (const chunk of source) { totalResponseBytes += chunk.length; if (totalResponseBytes > limit) { throw new AxiosError( 'maxContentLength size of ' + limit + ' exceeded', AxiosError.ERR_BAD_RESPONSE, config, lastRequest ); } yield chunk; } } responseStream = stream.Readable.from(enforceMaxContentLength(), { objectMode: false, }); } response.data = responseStream; settle(resolve, reject, response); } else { const responseBuffer = []; let totalResponseBytes = 0; responseStream.on('data', function handleStreamData(chunk) { responseBuffer.push(chunk); totalResponseBytes += chunk.length; // make sure the content length is not over the maxContentLength if specified if (maxContentLength > -1 && totalResponseBytes > maxContentLength) { // stream.destroy() emit aborted event before calling reject() on Node.js v16 rejected = true; responseStream.destroy(); abort( new AxiosError( 'maxContentLength size of ' + maxContentLength + ' exceeded', AxiosError.ERR_BAD_RESPONSE, config, lastRequest ) ); } }); responseStream.on('aborted', function handlerStreamAborted() { if (rejected) { return; } const err = new AxiosError( 'stream has been aborted', AxiosError.ERR_BAD_RESPONSE, config, lastRequest, response ); responseStream.destroy(err); reject(err); }); responseStream.on('error', function handleStreamError(err) { if (rejected) return; reject(AxiosError.from(err, null, config, lastRequest, response)); }); responseStream.on('end', function handleStreamEnd() { try { let responseData = responseBuffer.length === 1 ? responseBuffer[0] : Buffer.concat(responseBuffer); if (responseType !== 'arraybuffer') { responseData = responseData.toString(responseEncoding); if (!responseEncoding || responseEncoding === 'utf8') { responseData = utils.stripBOM(responseData); } } response.data = responseData; } catch (err) { return reject(AxiosError.from(err, null, config, response.request, response)); } settle(resolve, reject, response); }); } abortEmitter.once('abort', (err) => { if (!responseStream.destroyed) { responseStream.emit('error', err); responseStream.destroy(); } }); }); abortEmitter.once('abort', (err) => { if (req.close) { req.close(); } else { req.destroy(err); } }); // Handle errors req.on('error', function handleRequestError(err) { reject(AxiosError.from(err, null, config, req)); }); // set tcp keep alive to prevent drop connection by peer // Track every socket bound to this outer RedirectableRequest so a single // 'close' listener can release ownership on all of them. follow-redirects // re-emits the 'socket' event for each hop's native request onto the same // outer request, so attaching per-request listeners inside this handler // would accumulate across hops and trigger MaxListenersExceededWarning at // >= 11 redirects. Clearing only the last-bound socket would leave stale // kAxiosCurrentReq refs on earlier hop sockets returned to the keep-alive // pool, causing an idle-pool 'error' to be attributed to a closed req. const boundSockets = new Set(); req.on('socket', function handleRequestSocket(socket) { // default interval of sending ack packet is 1 minute socket.setKeepAlive(true, 1000 * 60); // Install a single 'error' listener per socket (not per request) to avoid // accumulating listeners on pooled keep-alive sockets that get reassigned // to new requests before the previous request's 'close' fires (issue #10780). // The listener is bound to the socket's currently-active request via a // symbol, which is swapped as the socket is reassigned. if (!socket[kAxiosSocketListener]) { socket.on('error', function handleSocketError(err) { const current = socket[kAxiosCurrentReq]; if (current && !current.destroyed) { current.destroy(err); } }); socket[kAxiosSocketListener] = true; } socket[kAxiosCurrentReq] = req; boundSockets.add(socket); }); req.once('close', function clearCurrentReq() { clearConnectPhaseTimer(); for (const socket of boundSockets) { if (socket[kAxiosCurrentReq] === req) { socket[kAxiosCurrentReq] = null; } } boundSockets.clear(); }); // Handle request timeout if (own('timeout')) { // This is forcing a int timeout to avoid problems if the `req` interface doesn't handle other types. const timeout = parseInt(own('timeout'), 10); if (Number.isNaN(timeout)) { abort( new AxiosError( 'error trying to parse `config.timeout` to int', AxiosError.ERR_BAD_OPTION_VALUE, config, req ) ); return; } const handleTimeout = function handleTimeout() { if (isDone) return; abort(createTimeoutError()); }; if (isNativeTransport && timeout > 0) { // Native ClientRequest#setTimeout starts from the socket lifecycle and // may not fire while TCP connect is still pending. Mirror the // follow-redirects wall-clock timer for the maxRedirects === 0 path. connectPhaseTimer = setTimeout(handleTimeout, timeout); } // Sometime, the response will be very slow, and does not respond, the connect event will be block by event loop system. // And timer callback will be fired, and abort() will be invoked before connection, then get "socket hang up" and code ECONNRESET. // At this time, if we have a large number of request, nodejs will hang up some socket on background. and the number will up and up. // And then these socket which be hang up will devouring CPU little by little. // ClientRequest.setTimeout will be fired on the specify milliseconds, and can make sure that abort() will be fired after connect. req.setTimeout(timeout, handleTimeout); } else { // explicitly reset the socket timeout value for a possible `keep-alive` request req.setTimeout(0); } // Send the request if (utils.isStream(data)) { let ended = false; let errored = false; data.on('end', () => { ended = true; }); data.once('error', (err) => { errored = true; req.destroy(err); }); data.on('close', () => { if (!ended && !errored) { abort(new CanceledError('Request stream has been aborted', config, req)); } }); // Enforce maxBodyLength for streamed uploads on every transport that // does not apply options.maxBodyLength itself (native http/https, http2, // and user-supplied custom transports). The follow-redirects transport // enforces it on the redirected HTTP/1 path. let uploadStream = data; if (maxBodyLength > -1 && !transportEnforcesMaxBodyLength) { const limit = maxBodyLength; let bytesSent = 0; uploadStream = stream.pipeline( [ data, new stream.Transform({ transform(chunk, _enc, cb) { bytesSent += chunk.length; if (bytesSent > limit) { return cb( new AxiosError( 'Request body larger than maxBodyLength limit', AxiosError.ERR_BAD_REQUEST, config, req ) ); } cb(null, chunk); }, }), ], utils.noop ); uploadStream.on('error', (err) => { if (!req.destroyed) req.destroy(err); }); } uploadStream.pipe(req); } else { data && req.write(data); req.end(); } }); }; export const __setProxy = setProxy; export const __isSameOriginRedirect = isSameOriginRedirect; axios-axios-2d06f96/lib/adapters/xhr.js000066400000000000000000000166611521272452000200420ustar00rootroot00000000000000import utils from '../utils.js'; import settle from '../core/settle.js'; import transitionalDefaults from '../defaults/transitional.js'; import AxiosError from '../core/AxiosError.js'; import CanceledError from '../cancel/CanceledError.js'; import parseProtocol from '../helpers/parseProtocol.js'; import platform from '../platform/index.js'; import AxiosHeaders from '../core/AxiosHeaders.js'; import { progressEventReducer } from '../helpers/progressEventReducer.js'; import resolveConfig from '../helpers/resolveConfig.js'; import { toByteStringHeaderObject } from '../helpers/sanitizeHeaderValue.js'; const isXHRAdapterSupported = typeof XMLHttpRequest !== 'undefined'; export default isXHRAdapterSupported && function (config) { return new Promise(function dispatchXhrRequest(resolve, reject) { const _config = resolveConfig(config); let requestData = _config.data; const requestHeaders = AxiosHeaders.from(_config.headers).normalize(); let { responseType, onUploadProgress, onDownloadProgress } = _config; let onCanceled; let uploadThrottled, downloadThrottled; let flushUpload, flushDownload; function done() { flushUpload && flushUpload(); // flush events flushDownload && flushDownload(); // flush events _config.cancelToken && _config.cancelToken.unsubscribe(onCanceled); _config.signal && _config.signal.removeEventListener('abort', onCanceled); } let request = new XMLHttpRequest(); request.open(_config.method.toUpperCase(), _config.url, true); // Set the request timeout in MS request.timeout = _config.timeout; function onloadend() { if (!request) { return; } // Prepare the response const responseHeaders = AxiosHeaders.from( 'getAllResponseHeaders' in request && request.getAllResponseHeaders() ); const responseData = !responseType || responseType === 'text' || responseType === 'json' ? request.responseText : request.response; const response = { data: responseData, status: request.status, statusText: request.statusText, headers: responseHeaders, config, request, }; settle( function _resolve(value) { resolve(value); done(); }, function _reject(err) { reject(err); done(); }, response ); // Clean up request request = null; } if ('onloadend' in request) { // Use onloadend if available request.onloadend = onloadend; } else { // Listen for ready state to emulate onloadend request.onreadystatechange = function handleLoad() { if (!request || request.readyState !== 4) { return; } // The request errored out and we didn't get a response, this will be // handled by onerror instead // With one exception: request that using file: protocol, most browsers // will return status as 0 even though it's a successful request if ( request.status === 0 && !(request.responseURL && request.responseURL.startsWith('file:')) ) { return; } // readystate handler is calling before onerror or ontimeout handlers, // so we should call onloadend on the next 'tick' setTimeout(onloadend); }; } // Handle browser request cancellation (as opposed to a manual cancellation) request.onabort = function handleAbort() { if (!request) { return; } reject(new AxiosError('Request aborted', AxiosError.ECONNABORTED, config, request)); done(); // Clean up request request = null; }; // Handle low level network errors request.onerror = function handleError(event) { // Browsers deliver a ProgressEvent in XHR onerror // (message may be empty; when present, surface it) // See https://developer.mozilla.org/docs/Web/API/XMLHttpRequest/error_event const msg = event && event.message ? event.message : 'Network Error'; const err = new AxiosError(msg, AxiosError.ERR_NETWORK, config, request); // attach the underlying event for consumers who want details err.event = event || null; reject(err); done(); request = null; }; // Handle timeout request.ontimeout = function handleTimeout() { let timeoutErrorMessage = _config.timeout ? 'timeout of ' + _config.timeout + 'ms exceeded' : 'timeout exceeded'; const transitional = _config.transitional || transitionalDefaults; if (_config.timeoutErrorMessage) { timeoutErrorMessage = _config.timeoutErrorMessage; } reject( new AxiosError( timeoutErrorMessage, transitional.clarifyTimeoutError ? AxiosError.ETIMEDOUT : AxiosError.ECONNABORTED, config, request ) ); done(); // Clean up request request = null; }; // Remove Content-Type if data is undefined requestData === undefined && requestHeaders.setContentType(null); // Add headers to the request if ('setRequestHeader' in request) { utils.forEach(toByteStringHeaderObject(requestHeaders), function setRequestHeader(val, key) { request.setRequestHeader(key, val); }); } // Add withCredentials to request if needed if (!utils.isUndefined(_config.withCredentials)) { request.withCredentials = !!_config.withCredentials; } // Add responseType to request if needed if (responseType && responseType !== 'json') { request.responseType = _config.responseType; } // Handle progress if needed if (onDownloadProgress) { [downloadThrottled, flushDownload] = progressEventReducer(onDownloadProgress, true); request.addEventListener('progress', downloadThrottled); } // Not all browsers support upload events if (onUploadProgress && request.upload) { [uploadThrottled, flushUpload] = progressEventReducer(onUploadProgress); request.upload.addEventListener('progress', uploadThrottled); request.upload.addEventListener('loadend', flushUpload); } if (_config.cancelToken || _config.signal) { // Handle cancellation // eslint-disable-next-line func-names onCanceled = (cancel) => { if (!request) { return; } reject(!cancel || cancel.type ? new CanceledError(null, config, request) : cancel); request.abort(); done(); request = null; }; _config.cancelToken && _config.cancelToken.subscribe(onCanceled); if (_config.signal) { _config.signal.aborted ? onCanceled() : _config.signal.addEventListener('abort', onCanceled); } } const protocol = parseProtocol(_config.url); if (protocol && !platform.protocols.includes(protocol)) { reject( new AxiosError( 'Unsupported protocol ' + protocol + ':', AxiosError.ERR_BAD_REQUEST, config ) ); return; } // Send the request request.send(requestData || null); }); }; axios-axios-2d06f96/lib/axios.js000066400000000000000000000047761521272452000165650ustar00rootroot00000000000000'use strict'; import utils from './utils.js'; import bind from './helpers/bind.js'; import Axios from './core/Axios.js'; import mergeConfig from './core/mergeConfig.js'; import defaults from './defaults/index.js'; import formDataToJSON from './helpers/formDataToJSON.js'; import CanceledError from './cancel/CanceledError.js'; import CancelToken from './cancel/CancelToken.js'; import isCancel from './cancel/isCancel.js'; import { VERSION } from './env/data.js'; import toFormData from './helpers/toFormData.js'; import AxiosError from './core/AxiosError.js'; import spread from './helpers/spread.js'; import isAxiosError from './helpers/isAxiosError.js'; import AxiosHeaders from './core/AxiosHeaders.js'; import adapters from './adapters/adapters.js'; import HttpStatusCode from './helpers/HttpStatusCode.js'; /** * Create an instance of Axios * * @param {Object} defaultConfig The default config for the instance * * @returns {Axios} A new instance of Axios */ function createInstance(defaultConfig) { const context = new Axios(defaultConfig); const instance = bind(Axios.prototype.request, context); // Copy axios.prototype to instance utils.extend(instance, Axios.prototype, context, { allOwnKeys: true }); // Copy context to instance utils.extend(instance, context, null, { allOwnKeys: true }); // Factory for creating new instances instance.create = function create(instanceConfig) { return createInstance(mergeConfig(defaultConfig, instanceConfig)); }; return instance; } // Create the default instance to be exported const axios = createInstance(defaults); // Expose Axios class to allow class inheritance axios.Axios = Axios; // Expose Cancel & CancelToken axios.CanceledError = CanceledError; axios.CancelToken = CancelToken; axios.isCancel = isCancel; axios.VERSION = VERSION; axios.toFormData = toFormData; // Expose AxiosError class axios.AxiosError = AxiosError; // alias for CanceledError for backward compatibility axios.Cancel = axios.CanceledError; // Expose all/spread axios.all = function all(promises) { return Promise.all(promises); }; axios.spread = spread; // Expose isAxiosError axios.isAxiosError = isAxiosError; // Expose mergeConfig axios.mergeConfig = mergeConfig; axios.AxiosHeaders = AxiosHeaders; axios.formToJSON = (thing) => formDataToJSON(utils.isHTMLForm(thing) ? new FormData(thing) : thing); axios.getAdapter = adapters.getAdapter; axios.HttpStatusCode = HttpStatusCode; axios.default = axios; // this module should only have a default export export default axios; axios-axios-2d06f96/lib/cancel/000077500000000000000000000000001521272452000163135ustar00rootroot00000000000000axios-axios-2d06f96/lib/cancel/CancelToken.js000066400000000000000000000053541521272452000210460ustar00rootroot00000000000000'use strict'; import CanceledError from './CanceledError.js'; /** * A `CancelToken` is an object that can be used to request cancellation of an operation. * * @param {Function} executor The executor function. * * @returns {CancelToken} */ class CancelToken { constructor(executor) { if (typeof executor !== 'function') { throw new TypeError('executor must be a function.'); } let resolvePromise; this.promise = new Promise(function promiseExecutor(resolve) { resolvePromise = resolve; }); const token = this; // eslint-disable-next-line func-names this.promise.then((cancel) => { if (!token._listeners) return; let i = token._listeners.length; while (i-- > 0) { token._listeners[i](cancel); } token._listeners = null; }); // eslint-disable-next-line func-names this.promise.then = (onfulfilled) => { let _resolve; // eslint-disable-next-line func-names const promise = new Promise((resolve) => { token.subscribe(resolve); _resolve = resolve; }).then(onfulfilled); promise.cancel = function reject() { token.unsubscribe(_resolve); }; return promise; }; executor(function cancel(message, config, request) { if (token.reason) { // Cancellation has already been requested return; } token.reason = new CanceledError(message, config, request); resolvePromise(token.reason); }); } /** * Throws a `CanceledError` if cancellation has been requested. */ throwIfRequested() { if (this.reason) { throw this.reason; } } /** * Subscribe to the cancel signal */ subscribe(listener) { if (this.reason) { listener(this.reason); return; } if (this._listeners) { this._listeners.push(listener); } else { this._listeners = [listener]; } } /** * Unsubscribe from the cancel signal */ unsubscribe(listener) { if (!this._listeners) { return; } const index = this._listeners.indexOf(listener); if (index !== -1) { this._listeners.splice(index, 1); } } toAbortSignal() { const controller = new AbortController(); const abort = (err) => { controller.abort(err); }; this.subscribe(abort); controller.signal.unsubscribe = () => this.unsubscribe(abort); return controller.signal; } /** * Returns an object that contains a new `CancelToken` and a function that, when called, * cancels the `CancelToken`. */ static source() { let cancel; const token = new CancelToken(function executor(c) { cancel = c; }); return { token, cancel, }; } } export default CancelToken; axios-axios-2d06f96/lib/cancel/CanceledError.js000066400000000000000000000011521521272452000213600ustar00rootroot00000000000000'use strict'; import AxiosError from '../core/AxiosError.js'; class CanceledError extends AxiosError { /** * A `CanceledError` is an object that is thrown when an operation is canceled. * * @param {string=} message The message. * @param {Object=} config The config. * @param {Object=} request The request. * * @returns {CanceledError} The created error. */ constructor(message, config, request) { super(message == null ? 'canceled' : message, AxiosError.ERR_CANCELED, config, request); this.name = 'CanceledError'; this.__CANCEL__ = true; } } export default CanceledError; axios-axios-2d06f96/lib/cancel/isCancel.js000066400000000000000000000001431521272452000203700ustar00rootroot00000000000000'use strict'; export default function isCancel(value) { return !!(value && value.__CANCEL__); } axios-axios-2d06f96/lib/core/000077500000000000000000000000001521272452000160165ustar00rootroot00000000000000axios-axios-2d06f96/lib/core/Axios.js000066400000000000000000000203611521272452000174410ustar00rootroot00000000000000'use strict'; import utils from '../utils.js'; import buildURL from '../helpers/buildURL.js'; import InterceptorManager from './InterceptorManager.js'; import dispatchRequest from './dispatchRequest.js'; import mergeConfig from './mergeConfig.js'; import buildFullPath from './buildFullPath.js'; import validator from '../helpers/validator.js'; import AxiosHeaders from './AxiosHeaders.js'; import transitionalDefaults from '../defaults/transitional.js'; const validators = validator.validators; /** * Create a new instance of Axios * * @param {Object} instanceConfig The default config for the instance * * @return {Axios} A new instance of Axios */ class Axios { constructor(instanceConfig) { this.defaults = instanceConfig || {}; this.interceptors = { request: new InterceptorManager(), response: new InterceptorManager(), }; } /** * Dispatch a request * * @param {String|Object} configOrUrl The config specific for this request (merged with this.defaults) * @param {?Object} config * * @returns {Promise} The Promise to be fulfilled */ async request(configOrUrl, config) { try { return await this._request(configOrUrl, config); } catch (err) { if (err instanceof Error) { let dummy = {}; Error.captureStackTrace ? Error.captureStackTrace(dummy) : (dummy = new Error()); // slice off the Error: ... line const stack = (() => { if (!dummy.stack) { return ''; } const firstNewlineIndex = dummy.stack.indexOf('\n'); return firstNewlineIndex === -1 ? '' : dummy.stack.slice(firstNewlineIndex + 1); })(); try { if (!err.stack) { err.stack = stack; // match without the 2 top stack lines } else if (stack) { const firstNewlineIndex = stack.indexOf('\n'); const secondNewlineIndex = firstNewlineIndex === -1 ? -1 : stack.indexOf('\n', firstNewlineIndex + 1); const stackWithoutTwoTopLines = secondNewlineIndex === -1 ? '' : stack.slice(secondNewlineIndex + 1); if (!String(err.stack).endsWith(stackWithoutTwoTopLines)) { err.stack += '\n' + stack; } } } catch (e) { // ignore the case where "stack" is an un-writable property } } throw err; } } _request(configOrUrl, config) { /*eslint no-param-reassign:0*/ // Allow for axios('example/url'[, config]) a la fetch API if (typeof configOrUrl === 'string') { config = config || {}; config.url = configOrUrl; } else { config = configOrUrl || {}; } config = mergeConfig(this.defaults, config); const { transitional, paramsSerializer, headers } = config; if (transitional !== undefined) { validator.assertOptions( transitional, { silentJSONParsing: validators.transitional(validators.boolean), forcedJSONParsing: validators.transitional(validators.boolean), clarifyTimeoutError: validators.transitional(validators.boolean), legacyInterceptorReqResOrdering: validators.transitional(validators.boolean), advertiseZstdAcceptEncoding: validators.transitional(validators.boolean), validateStatusUndefinedResolves: validators.transitional(validators.boolean), }, false ); } if (paramsSerializer != null) { if (utils.isFunction(paramsSerializer)) { config.paramsSerializer = { serialize: paramsSerializer, }; } else { validator.assertOptions( paramsSerializer, { encode: validators.function, serialize: validators.function, }, true ); } } // Set config.allowAbsoluteUrls if (config.allowAbsoluteUrls !== undefined) { // do nothing } else if (this.defaults.allowAbsoluteUrls !== undefined) { config.allowAbsoluteUrls = this.defaults.allowAbsoluteUrls; } else { config.allowAbsoluteUrls = true; } validator.assertOptions( config, { baseUrl: validators.spelling('baseURL'), withXsrfToken: validators.spelling('withXSRFToken'), }, true ); // Set config.method config.method = (config.method || this.defaults.method || 'get').toLowerCase(); // Flatten headers let contextHeaders = headers && utils.merge(headers.common, headers[config.method]); headers && utils.forEach(['delete', 'get', 'head', 'post', 'put', 'patch', 'query', 'common'], (method) => { delete headers[method]; }); config.headers = AxiosHeaders.concat(contextHeaders, headers); // filter out skipped interceptors const requestInterceptorChain = []; let synchronousRequestInterceptors = true; this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) { if (typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) { return; } synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous; const transitional = config.transitional || transitionalDefaults; const legacyInterceptorReqResOrdering = transitional && transitional.legacyInterceptorReqResOrdering; if (legacyInterceptorReqResOrdering) { requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected); } else { requestInterceptorChain.push(interceptor.fulfilled, interceptor.rejected); } }); const responseInterceptorChain = []; this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) { responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected); }); let promise; let i = 0; let len; if (!synchronousRequestInterceptors) { const chain = [dispatchRequest.bind(this), undefined]; chain.unshift(...requestInterceptorChain); chain.push(...responseInterceptorChain); len = chain.length; promise = Promise.resolve(config); while (i < len) { promise = promise.then(chain[i++], chain[i++]); } return promise; } len = requestInterceptorChain.length; let newConfig = config; while (i < len) { const onFulfilled = requestInterceptorChain[i++]; const onRejected = requestInterceptorChain[i++]; try { newConfig = onFulfilled(newConfig); } catch (error) { onRejected.call(this, error); break; } } try { promise = dispatchRequest.call(this, newConfig); } catch (error) { return Promise.reject(error); } i = 0; len = responseInterceptorChain.length; while (i < len) { promise = promise.then(responseInterceptorChain[i++], responseInterceptorChain[i++]); } return promise; } getUri(config) { config = mergeConfig(this.defaults, config); const fullPath = buildFullPath(config.baseURL, config.url, config.allowAbsoluteUrls, config); return buildURL(fullPath, config.params, config.paramsSerializer); } } // Provide aliases for supported request methods utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) { /*eslint func-names:0*/ Axios.prototype[method] = function (url, config) { return this.request( mergeConfig(config || {}, { method, url, data: config && utils.hasOwnProp(config, 'data') ? config.data : undefined, }) ); }; }); utils.forEach(['post', 'put', 'patch', 'query'], function forEachMethodWithData(method) { function generateHTTPMethod(isForm) { return function httpMethod(url, data, config) { return this.request( mergeConfig(config || {}, { method, headers: isForm ? { 'Content-Type': 'multipart/form-data', } : {}, url, data, }) ); }; } Axios.prototype[method] = generateHTTPMethod(); // QUERY is a safe/idempotent read method; multipart form bodies don't fit // its semantics, so no queryForm shorthand is generated. if (method !== 'query') { Axios.prototype[method + 'Form'] = generateHTTPMethod(true); } }); export default Axios; axios-axios-2d06f96/lib/core/AxiosError.js000066400000000000000000000126701521272452000204570ustar00rootroot00000000000000'use strict'; import utils from '../utils.js'; import AxiosHeaders from './AxiosHeaders.js'; const REDACTED = '[REDACTED ****]'; function hasOwnOrPrototypeToJSON(source) { if (utils.hasOwnProp(source, 'toJSON')) { return true; } let prototype = Object.getPrototypeOf(source); while (prototype && prototype !== Object.prototype) { if (utils.hasOwnProp(prototype, 'toJSON')) { return true; } prototype = Object.getPrototypeOf(prototype); } return false; } // Build a plain-object snapshot of `config` and replace the value of any key // (case-insensitive) listed in `redactKeys` with REDACTED. Walks through arrays // and AxiosHeaders, and short-circuits on circular references. function redactConfig(config, redactKeys) { const lowerKeys = new Set(redactKeys.map((k) => String(k).toLowerCase())); const seen = []; const visit = (source) => { if (source === null || typeof source !== 'object') return source; if (utils.isBuffer(source)) return source; if (seen.indexOf(source) !== -1) return undefined; if (source instanceof AxiosHeaders) { source = source.toJSON(); } seen.push(source); let result; if (utils.isArray(source)) { result = []; source.forEach((v, i) => { const reducedValue = visit(v); if (!utils.isUndefined(reducedValue)) { result[i] = reducedValue; } }); } else { if (!utils.isPlainObject(source) && hasOwnOrPrototypeToJSON(source)) { seen.pop(); return source; } result = Object.create(null); for (const [key, value] of Object.entries(source)) { const reducedValue = lowerKeys.has(key.toLowerCase()) ? REDACTED : visit(value); if (!utils.isUndefined(reducedValue)) { result[key] = reducedValue; } } } seen.pop(); return result; }; return visit(config); } class AxiosError extends Error { static from(error, code, config, request, response, customProps) { const axiosError = new AxiosError(error.message, code || error.code, config, request, response); axiosError.cause = error; axiosError.name = error.name; // Preserve status from the original error if not already set from response if (error.status != null && axiosError.status == null) { axiosError.status = error.status; } customProps && Object.assign(axiosError, customProps); return axiosError; } /** * Create an Error with the specified message, config, error code, request and response. * * @param {string} message The error message. * @param {string} [code] The error code (for example, 'ECONNABORTED'). * @param {Object} [config] The config. * @param {Object} [request] The request. * @param {Object} [response] The response. * * @returns {Error} The created error. */ constructor(message, code, config, request, response) { super(message); // Make message enumerable to maintain backward compatibility // The native Error constructor sets message as non-enumerable, // but axios < v1.13.3 had it as enumerable Object.defineProperty(this, 'message', { // Null-proto descriptor so a polluted Object.prototype.get cannot turn // this data descriptor into an accessor descriptor on the way in. __proto__: null, value: message, enumerable: true, writable: true, configurable: true, }); this.name = 'AxiosError'; this.isAxiosError = true; code && (this.code = code); config && (this.config = config); request && (this.request = request); if (response) { this.response = response; this.status = response.status; } } toJSON() { // Opt-in redaction: when the request config carries a `redact` array, the // value of any matching key (case-insensitive, at any depth) is replaced // with REDACTED in the serialized snapshot. Undefined or empty leaves the // existing serialization behavior unchanged. const config = this.config; const redactKeys = config && utils.hasOwnProp(config, 'redact') ? config.redact : undefined; const serializedConfig = utils.isArray(redactKeys) && redactKeys.length > 0 ? redactConfig(config, redactKeys) : utils.toJSONObject(config); return { // Standard message: this.message, name: this.name, // Microsoft description: this.description, number: this.number, // Mozilla fileName: this.fileName, lineNumber: this.lineNumber, columnNumber: this.columnNumber, stack: this.stack, // Axios config: serializedConfig, code: this.code, status: this.status, }; } } // This can be changed to static properties as soon as the parser options in .eslint.cjs are updated. AxiosError.ERR_BAD_OPTION_VALUE = 'ERR_BAD_OPTION_VALUE'; AxiosError.ERR_BAD_OPTION = 'ERR_BAD_OPTION'; AxiosError.ECONNABORTED = 'ECONNABORTED'; AxiosError.ETIMEDOUT = 'ETIMEDOUT'; AxiosError.ECONNREFUSED = 'ECONNREFUSED'; AxiosError.ERR_NETWORK = 'ERR_NETWORK'; AxiosError.ERR_FR_TOO_MANY_REDIRECTS = 'ERR_FR_TOO_MANY_REDIRECTS'; AxiosError.ERR_DEPRECATED = 'ERR_DEPRECATED'; AxiosError.ERR_BAD_RESPONSE = 'ERR_BAD_RESPONSE'; AxiosError.ERR_BAD_REQUEST = 'ERR_BAD_REQUEST'; AxiosError.ERR_CANCELED = 'ERR_CANCELED'; AxiosError.ERR_NOT_SUPPORT = 'ERR_NOT_SUPPORT'; AxiosError.ERR_INVALID_URL = 'ERR_INVALID_URL'; AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED = 'ERR_FORM_DATA_DEPTH_EXCEEDED'; export default AxiosError; axios-axios-2d06f96/lib/core/AxiosHeaders.js000066400000000000000000000173621521272452000207440ustar00rootroot00000000000000'use strict'; import utils from '../utils.js'; import parseHeaders from '../helpers/parseHeaders.js'; import { sanitizeHeaderValue } from '../helpers/sanitizeHeaderValue.js'; const $internals = Symbol('internals'); function normalizeHeader(header) { return header && String(header).trim().toLowerCase(); } function normalizeValue(value) { if (value === false || value == null) { return value; } return utils.isArray(value) ? value.map(normalizeValue) : sanitizeHeaderValue(String(value)); } function parseTokens(str) { const tokens = Object.create(null); const tokensRE = /([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g; let match; while ((match = tokensRE.exec(str))) { tokens[match[1]] = match[2]; } return tokens; } const isValidHeaderName = (str) => /^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(str.trim()); function matchHeaderValue(context, value, header, filter, isHeaderNameFilter) { if (utils.isFunction(filter)) { return filter.call(this, value, header); } if (isHeaderNameFilter) { value = header; } if (!utils.isString(value)) return; if (utils.isString(filter)) { return value.indexOf(filter) !== -1; } if (utils.isRegExp(filter)) { return filter.test(value); } } function formatHeader(header) { return header .trim() .toLowerCase() .replace(/([a-z\d])(\w*)/g, (w, char, str) => { return char.toUpperCase() + str; }); } function buildAccessors(obj, header) { const accessorName = utils.toCamelCase(' ' + header); ['get', 'set', 'has'].forEach((methodName) => { Object.defineProperty(obj, methodName + accessorName, { // Null-proto descriptor so a polluted Object.prototype.get cannot turn // this data descriptor into an accessor descriptor on the way in. __proto__: null, value: function (arg1, arg2, arg3) { return this[methodName].call(this, header, arg1, arg2, arg3); }, configurable: true, }); }); } class AxiosHeaders { constructor(headers) { headers && this.set(headers); } set(header, valueOrRewrite, rewrite) { const self = this; function setHeader(_value, _header, _rewrite) { const lHeader = normalizeHeader(_header); if (!lHeader) { return; } const key = utils.findKey(self, lHeader); if ( !key || self[key] === undefined || _rewrite === true || (_rewrite === undefined && self[key] !== false) ) { self[key || _header] = normalizeValue(_value); } } const setHeaders = (headers, _rewrite) => utils.forEach(headers, (_value, _header) => setHeader(_value, _header, _rewrite)); if (utils.isPlainObject(header) || header instanceof this.constructor) { setHeaders(header, valueOrRewrite); } else if (utils.isString(header) && (header = header.trim()) && !isValidHeaderName(header)) { setHeaders(parseHeaders(header), valueOrRewrite); } else if (utils.isObject(header) && utils.isSafeIterable(header)) { let obj = Object.create(null), dest, key; for (const entry of header) { if (!utils.isArray(entry)) { throw new TypeError('Object iterator must return a key-value pair'); } key = entry[0]; if (utils.hasOwnProp(obj, key)) { dest = obj[key]; obj[key] = utils.isArray(dest) ? [...dest, entry[1]] : [dest, entry[1]]; } else { obj[key] = entry[1]; } } setHeaders(obj, valueOrRewrite); } else { header != null && setHeader(valueOrRewrite, header, rewrite); } return this; } get(header, parser) { header = normalizeHeader(header); if (header) { const key = utils.findKey(this, header); if (key) { const value = this[key]; if (!parser) { return value; } if (parser === true) { return parseTokens(value); } if (utils.isFunction(parser)) { return parser.call(this, value, key); } if (utils.isRegExp(parser)) { return parser.exec(value); } throw new TypeError('parser must be boolean|regexp|function'); } } } has(header, matcher) { header = normalizeHeader(header); if (header) { const key = utils.findKey(this, header); return !!( key && this[key] !== undefined && (!matcher || matchHeaderValue(this, this[key], key, matcher)) ); } return false; } delete(header, matcher) { const self = this; let deleted = false; function deleteHeader(_header) { _header = normalizeHeader(_header); if (_header) { const key = utils.findKey(self, _header); if (key && (!matcher || matchHeaderValue(self, self[key], key, matcher))) { delete self[key]; deleted = true; } } } if (utils.isArray(header)) { header.forEach(deleteHeader); } else { deleteHeader(header); } return deleted; } clear(matcher) { const keys = Object.keys(this); let i = keys.length; let deleted = false; while (i--) { const key = keys[i]; if (!matcher || matchHeaderValue(this, this[key], key, matcher, true)) { delete this[key]; deleted = true; } } return deleted; } normalize(format) { const self = this; const headers = {}; utils.forEach(this, (value, header) => { const key = utils.findKey(headers, header); if (key) { self[key] = normalizeValue(value); delete self[header]; return; } const normalized = format ? formatHeader(header) : String(header).trim(); if (normalized !== header) { delete self[header]; } self[normalized] = normalizeValue(value); headers[normalized] = true; }); return this; } concat(...targets) { return this.constructor.concat(this, ...targets); } toJSON(asStrings) { const obj = Object.create(null); utils.forEach(this, (value, header) => { value != null && value !== false && (obj[header] = asStrings && utils.isArray(value) ? value.join(', ') : value); }); return obj; } [Symbol.iterator]() { return Object.entries(this.toJSON())[Symbol.iterator](); } toString() { return Object.entries(this.toJSON()) .map(([header, value]) => header + ': ' + value) .join('\n'); } getSetCookie() { return this.get('set-cookie') || []; } get [Symbol.toStringTag]() { return 'AxiosHeaders'; } static from(thing) { return thing instanceof this ? thing : new this(thing); } static concat(first, ...targets) { const computed = new this(first); targets.forEach((target) => computed.set(target)); return computed; } static accessor(header) { const internals = (this[$internals] = this[$internals] = { accessors: {}, }); const accessors = internals.accessors; const prototype = this.prototype; function defineAccessor(_header) { const lHeader = normalizeHeader(_header); if (!accessors[lHeader]) { buildAccessors(prototype, _header); accessors[lHeader] = true; } } utils.isArray(header) ? header.forEach(defineAccessor) : defineAccessor(header); return this; } } AxiosHeaders.accessor([ 'Content-Type', 'Content-Length', 'Accept', 'Accept-Encoding', 'User-Agent', 'Authorization', ]); // reserved names hotfix utils.reduceDescriptors(AxiosHeaders.prototype, ({ value }, key) => { let mapped = key[0].toUpperCase() + key.slice(1); // map `set` => `Set` return { get: () => value, set(headerValue) { this[mapped] = headerValue; }, }; }); utils.freezeMethods(AxiosHeaders); export default AxiosHeaders; axios-axios-2d06f96/lib/core/InterceptorManager.js000066400000000000000000000030721521272452000221470ustar00rootroot00000000000000'use strict'; import utils from '../utils.js'; class InterceptorManager { constructor() { this.handlers = []; } /** * Add a new interceptor to the stack * * @param {Function} fulfilled The function to handle `then` for a `Promise` * @param {Function} rejected The function to handle `reject` for a `Promise` * @param {Object} options The options for the interceptor, synchronous and runWhen * * @return {Number} An ID used to remove interceptor later */ use(fulfilled, rejected, options) { this.handlers.push({ fulfilled, rejected, synchronous: options ? options.synchronous : false, runWhen: options ? options.runWhen : null, }); return this.handlers.length - 1; } /** * Remove an interceptor from the stack * * @param {Number} id The ID that was returned by `use` * * @returns {void} */ eject(id) { if (this.handlers[id]) { this.handlers[id] = null; } } /** * Clear all interceptors from the stack * * @returns {void} */ clear() { if (this.handlers) { this.handlers = []; } } /** * Iterate over all the registered interceptors * * This method is particularly useful for skipping over any * interceptors that may have become `null` calling `eject`. * * @param {Function} fn The function to call for each interceptor * * @returns {void} */ forEach(fn) { utils.forEach(this.handlers, function forEachHandler(h) { if (h !== null) { fn(h); } }); } } export default InterceptorManager; axios-axios-2d06f96/lib/core/README.md000066400000000000000000000006171521272452000173010ustar00rootroot00000000000000# axios // core The modules found in `core/` should be modules that are specific to the domain logic of axios. These modules would most likely not make sense to be consumed outside of the axios module, as their logic is too specific. Some examples of core modules are: - Dispatching requests - Requests sent via `adapters/` (see lib/adapters/README.md) - Managing interceptors - Handling config axios-axios-2d06f96/lib/core/buildFullPath.js000066400000000000000000000031141521272452000211120ustar00rootroot00000000000000'use strict'; import AxiosError from './AxiosError.js'; import isAbsoluteURL from '../helpers/isAbsoluteURL.js'; import combineURLs from '../helpers/combineURLs.js'; const malformedHttpProtocol = /^https?:(?!\/\/)/i; const httpProtocolControlCharacters = /[\t\n\r]/g; function stripLeadingC0ControlOrSpace(url) { let i = 0; while (i < url.length && url.charCodeAt(i) <= 0x20) { i++; } return url.slice(i); } function normalizeURLForProtocolCheck(url) { return stripLeadingC0ControlOrSpace(url).replace(httpProtocolControlCharacters, ''); } function assertValidHttpProtocolURL(url, config) { if (typeof url === 'string' && malformedHttpProtocol.test(normalizeURLForProtocolCheck(url))) { throw new AxiosError( 'Invalid URL: missing "//" after protocol', AxiosError.ERR_INVALID_URL, config ); } } /** * Creates a new URL by combining the baseURL with the requestedURL, * only when the requestedURL is not already an absolute URL. * If the requestURL is absolute, this function returns the requestedURL untouched. * * @param {string} baseURL The base URL * @param {string} requestedURL Absolute or relative URL to combine * * @returns {string} The combined full path */ export default function buildFullPath(baseURL, requestedURL, allowAbsoluteUrls, config) { assertValidHttpProtocolURL(requestedURL, config); let isRelativeUrl = !isAbsoluteURL(requestedURL); if (baseURL && (isRelativeUrl || allowAbsoluteUrls === false)) { assertValidHttpProtocolURL(baseURL, config); return combineURLs(baseURL, requestedURL); } return requestedURL; } axios-axios-2d06f96/lib/core/dispatchRequest.js000066400000000000000000000051341521272452000215270ustar00rootroot00000000000000'use strict'; import transformData from './transformData.js'; import isCancel from '../cancel/isCancel.js'; import defaults from '../defaults/index.js'; import CanceledError from '../cancel/CanceledError.js'; import AxiosHeaders from '../core/AxiosHeaders.js'; import adapters from '../adapters/adapters.js'; /** * Throws a `CanceledError` if cancellation has been requested. * * @param {Object} config The config that is to be used for the request * * @returns {void} */ function throwIfCancellationRequested(config) { if (config.cancelToken) { config.cancelToken.throwIfRequested(); } if (config.signal && config.signal.aborted) { throw new CanceledError(null, config); } } /** * Dispatch a request to the server using the configured adapter. * * @param {object} config The config that is to be used for the request * * @returns {Promise} The Promise to be fulfilled */ export default function dispatchRequest(config) { throwIfCancellationRequested(config); config.headers = AxiosHeaders.from(config.headers); // Transform request data config.data = transformData.call(config, config.transformRequest); if (['post', 'put', 'patch'].indexOf(config.method) !== -1) { config.headers.setContentType('application/x-www-form-urlencoded', false); } const adapter = adapters.getAdapter(config.adapter || defaults.adapter, config); return adapter(config).then( function onAdapterResolution(response) { throwIfCancellationRequested(config); // Expose the current response on config so that transformResponse can // attach it to any AxiosError it throws (e.g. on JSON parse failure). // We clean it up afterwards to avoid polluting the config object. config.response = response; try { response.data = transformData.call(config, config.transformResponse, response); } finally { delete config.response; } response.headers = AxiosHeaders.from(response.headers); return response; }, function onAdapterRejection(reason) { if (!isCancel(reason)) { throwIfCancellationRequested(config); // Transform response data if (reason && reason.response) { config.response = reason.response; try { reason.response.data = transformData.call( config, config.transformResponse, reason.response ); } finally { delete config.response; } reason.response.headers = AxiosHeaders.from(reason.response.headers); } } return Promise.reject(reason); } ); } axios-axios-2d06f96/lib/core/mergeConfig.js000066400000000000000000000123761521272452000206120ustar00rootroot00000000000000'use strict'; import utils from '../utils.js'; import AxiosHeaders from './AxiosHeaders.js'; const headersToObject = (thing) => (thing instanceof AxiosHeaders ? { ...thing } : thing); /** * Config-specific merge-function which creates a new config-object * by merging two configuration objects together. * * @param {Object} config1 * @param {Object} config2 * * @returns {Object} New object resulting from merging config2 to config1 */ export default function mergeConfig(config1, config2) { // eslint-disable-next-line no-param-reassign config2 = config2 || {}; // Use a null-prototype object so that downstream reads such as `config.auth` // or `config.baseURL` cannot inherit polluted values from Object.prototype. // `hasOwnProperty` is restored as a non-enumerable own slot to preserve // ergonomics for user code that relies on it. const config = Object.create(null); Object.defineProperty(config, 'hasOwnProperty', { // Null-proto descriptor so a polluted Object.prototype.get cannot turn // this data descriptor into an accessor descriptor on the way in. __proto__: null, value: Object.prototype.hasOwnProperty, enumerable: false, writable: true, configurable: true, }); function getMergedValue(target, source, prop, caseless) { if (utils.isPlainObject(target) && utils.isPlainObject(source)) { return utils.merge.call({ caseless }, target, source); } else if (utils.isPlainObject(source)) { return utils.merge({}, source); } else if (utils.isArray(source)) { return source.slice(); } return source; } function mergeDeepProperties(a, b, prop, caseless) { if (!utils.isUndefined(b)) { return getMergedValue(a, b, prop, caseless); } else if (!utils.isUndefined(a)) { return getMergedValue(undefined, a, prop, caseless); } } // eslint-disable-next-line consistent-return function valueFromConfig2(a, b) { if (!utils.isUndefined(b)) { return getMergedValue(undefined, b); } } // eslint-disable-next-line consistent-return function defaultToConfig2(a, b) { if (!utils.isUndefined(b)) { return getMergedValue(undefined, b); } else if (!utils.isUndefined(a)) { return getMergedValue(undefined, a); } } function getMergedTransitionalOption(prop) { const transitional2 = utils.hasOwnProp(config2, 'transitional') ? config2.transitional : undefined; if (!utils.isUndefined(transitional2)) { if (utils.isPlainObject(transitional2)) { if (utils.hasOwnProp(transitional2, prop)) { return transitional2[prop]; } } else { return undefined; } } const transitional1 = utils.hasOwnProp(config1, 'transitional') ? config1.transitional : undefined; if (utils.isPlainObject(transitional1) && utils.hasOwnProp(transitional1, prop)) { return transitional1[prop]; } return undefined; } // eslint-disable-next-line consistent-return function mergeDirectKeys(a, b, prop) { if (utils.hasOwnProp(config2, prop)) { return getMergedValue(a, b); } else if (utils.hasOwnProp(config1, prop)) { return getMergedValue(undefined, a); } } const mergeMap = { url: valueFromConfig2, method: valueFromConfig2, data: valueFromConfig2, baseURL: defaultToConfig2, transformRequest: defaultToConfig2, transformResponse: defaultToConfig2, paramsSerializer: defaultToConfig2, timeout: defaultToConfig2, timeoutMessage: defaultToConfig2, withCredentials: defaultToConfig2, withXSRFToken: defaultToConfig2, adapter: defaultToConfig2, responseType: defaultToConfig2, xsrfCookieName: defaultToConfig2, xsrfHeaderName: defaultToConfig2, onUploadProgress: defaultToConfig2, onDownloadProgress: defaultToConfig2, decompress: defaultToConfig2, maxContentLength: defaultToConfig2, maxBodyLength: defaultToConfig2, beforeRedirect: defaultToConfig2, transport: defaultToConfig2, httpAgent: defaultToConfig2, httpsAgent: defaultToConfig2, cancelToken: defaultToConfig2, socketPath: defaultToConfig2, allowedSocketPaths: defaultToConfig2, responseEncoding: defaultToConfig2, validateStatus: mergeDirectKeys, headers: (a, b, prop) => mergeDeepProperties(headersToObject(a), headersToObject(b), prop, true), }; utils.forEach(Object.keys({ ...config1, ...config2 }), function computeConfigValue(prop) { if (prop === '__proto__' || prop === 'constructor' || prop === 'prototype') return; const merge = utils.hasOwnProp(mergeMap, prop) ? mergeMap[prop] : mergeDeepProperties; const a = utils.hasOwnProp(config1, prop) ? config1[prop] : undefined; const b = utils.hasOwnProp(config2, prop) ? config2[prop] : undefined; const configValue = merge(a, b, prop); (utils.isUndefined(configValue) && merge !== mergeDirectKeys) || (config[prop] = configValue); }); if ( utils.hasOwnProp(config2, 'validateStatus') && utils.isUndefined(config2.validateStatus) && getMergedTransitionalOption('validateStatusUndefinedResolves') === false ) { if (utils.hasOwnProp(config1, 'validateStatus')) { config.validateStatus = getMergedValue(undefined, config1.validateStatus); } else { delete config.validateStatus; } } return config; } axios-axios-2d06f96/lib/core/settle.js000066400000000000000000000015161521272452000176570ustar00rootroot00000000000000'use strict'; import AxiosError from './AxiosError.js'; /** * Resolve or reject a Promise based on response status. * * @param {Function} resolve A function that resolves the promise. * @param {Function} reject A function that rejects the promise. * @param {object} response The response. * * @returns {object} The response. */ export default function settle(resolve, reject, response) { const validateStatus = response.config.validateStatus; if (!response.status || !validateStatus || validateStatus(response.status)) { resolve(response); } else { reject(new AxiosError( 'Request failed with status code ' + response.status, response.status >= 400 && response.status < 500 ? AxiosError.ERR_BAD_REQUEST : AxiosError.ERR_BAD_RESPONSE, response.config, response.request, response )); } } axios-axios-2d06f96/lib/core/transformData.js000066400000000000000000000014101521272452000211550ustar00rootroot00000000000000'use strict'; import utils from '../utils.js'; import defaults from '../defaults/index.js'; import AxiosHeaders from '../core/AxiosHeaders.js'; /** * Transform the data for a request or a response * * @param {Array|Function} fns A single function or Array of functions * @param {?Object} response The response object * * @returns {*} The resulting transformed data */ export default function transformData(fns, response) { const config = this || defaults; const context = response || config; const headers = AxiosHeaders.from(context.headers); let data = context.data; utils.forEach(fns, function transform(fn) { data = fn.call(config, data, headers.normalize(), response ? response.status : undefined); }); headers.normalize(); return data; } axios-axios-2d06f96/lib/defaults/000077500000000000000000000000001521272452000166755ustar00rootroot00000000000000axios-axios-2d06f96/lib/defaults/index.js000066400000000000000000000115611521272452000203460ustar00rootroot00000000000000'use strict'; import utils from '../utils.js'; import AxiosError from '../core/AxiosError.js'; import transitionalDefaults from './transitional.js'; import toFormData from '../helpers/toFormData.js'; import toURLEncodedForm from '../helpers/toURLEncodedForm.js'; import platform from '../platform/index.js'; import formDataToJSON from '../helpers/formDataToJSON.js'; const own = (obj, key) => (obj != null && utils.hasOwnProp(obj, key) ? obj[key] : undefined); /** * It takes a string, tries to parse it, and if it fails, it returns the stringified version * of the input * * @param {any} rawValue - The value to be stringified. * @param {Function} parser - A function that parses a string into a JavaScript object. * @param {Function} encoder - A function that takes a value and returns a string. * * @returns {string} A stringified version of the rawValue. */ function stringifySafely(rawValue, parser, encoder) { if (utils.isString(rawValue)) { try { (parser || JSON.parse)(rawValue); return utils.trim(rawValue); } catch (e) { if (e.name !== 'SyntaxError') { throw e; } } } return (encoder || JSON.stringify)(rawValue); } const defaults = { transitional: transitionalDefaults, adapter: ['xhr', 'http', 'fetch'], transformRequest: [ function transformRequest(data, headers) { const contentType = headers.getContentType() || ''; const hasJSONContentType = contentType.indexOf('application/json') > -1; const isObjectPayload = utils.isObject(data); if (isObjectPayload && utils.isHTMLForm(data)) { data = new FormData(data); } const isFormData = utils.isFormData(data); if (isFormData) { return hasJSONContentType ? JSON.stringify(formDataToJSON(data)) : data; } if ( utils.isArrayBuffer(data) || utils.isBuffer(data) || utils.isStream(data) || utils.isFile(data) || utils.isBlob(data) || utils.isReadableStream(data) ) { return data; } if (utils.isArrayBufferView(data)) { return data.buffer; } if (utils.isURLSearchParams(data)) { headers.setContentType('application/x-www-form-urlencoded;charset=utf-8', false); return data.toString(); } let isFileList; if (isObjectPayload) { const formSerializer = own(this, 'formSerializer'); if (contentType.indexOf('application/x-www-form-urlencoded') > -1) { return toURLEncodedForm(data, formSerializer).toString(); } if ( (isFileList = utils.isFileList(data)) || contentType.indexOf('multipart/form-data') > -1 ) { const env = own(this, 'env'); const _FormData = env && env.FormData; return toFormData( isFileList ? { 'files[]': data } : data, _FormData && new _FormData(), formSerializer ); } } if (isObjectPayload || hasJSONContentType) { headers.setContentType('application/json', false); return stringifySafely(data); } return data; }, ], transformResponse: [ function transformResponse(data) { const transitional = own(this, 'transitional') || defaults.transitional; const forcedJSONParsing = transitional && transitional.forcedJSONParsing; const responseType = own(this, 'responseType'); const JSONRequested = responseType === 'json'; if (utils.isResponse(data) || utils.isReadableStream(data)) { return data; } if ( data && utils.isString(data) && ((forcedJSONParsing && !responseType) || JSONRequested) ) { const silentJSONParsing = transitional && transitional.silentJSONParsing; const strictJSONParsing = !silentJSONParsing && JSONRequested; try { return JSON.parse(data, own(this, 'parseReviver')); } catch (e) { if (strictJSONParsing) { if (e.name === 'SyntaxError') { throw AxiosError.from(e, AxiosError.ERR_BAD_RESPONSE, this, null, own(this, 'response')); } throw e; } } } return data; }, ], /** * A timeout in milliseconds to abort a request. If set to 0 (default) a * timeout is not created. */ timeout: 0, xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', maxContentLength: -1, maxBodyLength: -1, env: { FormData: platform.classes.FormData, Blob: platform.classes.Blob, }, validateStatus: function validateStatus(status) { return status >= 200 && status < 300; }, headers: { common: { Accept: 'application/json, text/plain, */*', 'Content-Type': undefined, }, }, }; utils.forEach(['delete', 'get', 'head', 'post', 'put', 'patch', 'query'], (method) => { defaults.headers[method] = {}; }); export default defaults; axios-axios-2d06f96/lib/defaults/transitional.js000066400000000000000000000003571521272452000217470ustar00rootroot00000000000000'use strict'; export default { silentJSONParsing: true, forcedJSONParsing: true, clarifyTimeoutError: false, legacyInterceptorReqResOrdering: true, advertiseZstdAcceptEncoding: false, validateStatusUndefinedResolves: true, }; axios-axios-2d06f96/lib/env/000077500000000000000000000000001521272452000156565ustar00rootroot00000000000000axios-axios-2d06f96/lib/env/README.md000066400000000000000000000002031521272452000171300ustar00rootroot00000000000000# axios // env The `data.js` file is updated automatically when the package version is upgrading. Please do not edit it manually. axios-axios-2d06f96/lib/env/classes/000077500000000000000000000000001521272452000173135ustar00rootroot00000000000000axios-axios-2d06f96/lib/env/classes/FormData.js000066400000000000000000000001521521272452000213440ustar00rootroot00000000000000import _FormData from 'form-data'; export default typeof FormData !== 'undefined' ? FormData : _FormData; axios-axios-2d06f96/lib/env/data.js000066400000000000000000000000401521272452000171170ustar00rootroot00000000000000export const VERSION = "1.18.0";axios-axios-2d06f96/lib/helpers/000077500000000000000000000000001521272452000165305ustar00rootroot00000000000000axios-axios-2d06f96/lib/helpers/AxiosTransformStream.js000066400000000000000000000073411521272452000232260ustar00rootroot00000000000000'use strict'; import stream from 'stream'; import utils from '../utils.js'; const kInternals = Symbol('internals'); class AxiosTransformStream extends stream.Transform { constructor(options) { options = utils.toFlatObject( options, { maxRate: 0, chunkSize: 64 * 1024, minChunkSize: 100, timeWindow: 500, ticksRate: 2, samplesCount: 15, }, null, (prop, source) => { return !utils.isUndefined(source[prop]); } ); super({ readableHighWaterMark: options.chunkSize, }); const internals = (this[kInternals] = { timeWindow: options.timeWindow, chunkSize: options.chunkSize, maxRate: options.maxRate, minChunkSize: options.minChunkSize, bytesSeen: 0, isCaptured: false, notifiedBytesLoaded: 0, ts: Date.now(), bytes: 0, onReadCallback: null, }); this.on('newListener', (event) => { if (event === 'progress') { if (!internals.isCaptured) { internals.isCaptured = true; } } }); } _read(size) { const internals = this[kInternals]; if (internals.onReadCallback) { internals.onReadCallback(); } return super._read(size); } _transform(chunk, encoding, callback) { const internals = this[kInternals]; const maxRate = internals.maxRate; const readableHighWaterMark = this.readableHighWaterMark; const timeWindow = internals.timeWindow; const divider = 1000 / timeWindow; const bytesThreshold = maxRate / divider; const minChunkSize = internals.minChunkSize !== false ? Math.max(internals.minChunkSize, bytesThreshold * 0.01) : 0; const pushChunk = (_chunk, _callback) => { const bytes = Buffer.byteLength(_chunk); internals.bytesSeen += bytes; internals.bytes += bytes; internals.isCaptured && this.emit('progress', internals.bytesSeen); if (this.push(_chunk)) { process.nextTick(_callback); } else { internals.onReadCallback = () => { internals.onReadCallback = null; process.nextTick(_callback); }; } }; const transformChunk = (_chunk, _callback) => { const chunkSize = Buffer.byteLength(_chunk); let chunkRemainder = null; let maxChunkSize = readableHighWaterMark; let bytesLeft; let passed = 0; if (maxRate) { const now = Date.now(); if (!internals.ts || (passed = now - internals.ts) >= timeWindow) { internals.ts = now; bytesLeft = bytesThreshold - internals.bytes; internals.bytes = bytesLeft < 0 ? -bytesLeft : 0; passed = 0; } bytesLeft = bytesThreshold - internals.bytes; } if (maxRate) { if (bytesLeft <= 0) { // next time window return setTimeout(() => { _callback(null, _chunk); }, timeWindow - passed); } if (bytesLeft < maxChunkSize) { maxChunkSize = bytesLeft; } } if (maxChunkSize && chunkSize > maxChunkSize && chunkSize - maxChunkSize > minChunkSize) { chunkRemainder = _chunk.subarray(maxChunkSize); _chunk = _chunk.subarray(0, maxChunkSize); } pushChunk( _chunk, chunkRemainder ? () => { process.nextTick(_callback, null, chunkRemainder); } : _callback ); }; transformChunk(chunk, function transformNextChunk(err, _chunk) { if (err) { return callback(err); } if (_chunk) { transformChunk(_chunk, transformNextChunk); } else { callback(null); } }); } } export default AxiosTransformStream; axios-axios-2d06f96/lib/helpers/AxiosURLSearchParams.js000066400000000000000000000026501521272452000230310ustar00rootroot00000000000000'use strict'; import toFormData from './toFormData.js'; /** * It encodes a string by replacing all characters that are not in the unreserved set with * their percent-encoded equivalents * * @param {string} str - The string to encode. * * @returns {string} The encoded string. */ function encode(str) { const charMap = { '!': '%21', "'": '%27', '(': '%28', ')': '%29', '~': '%7E', '%20': '+', }; return encodeURIComponent(str).replace(/[!'()~]|%20/g, function replacer(match) { return charMap[match]; }); } /** * It takes a params object and converts it to a FormData object * * @param {Object} params - The parameters to be converted to a FormData object. * @param {Object} options - The options object passed to the Axios constructor. * * @returns {void} */ function AxiosURLSearchParams(params, options) { this._pairs = []; params && toFormData(params, this, options); } const prototype = AxiosURLSearchParams.prototype; prototype.append = function append(name, value) { this._pairs.push([name, value]); }; prototype.toString = function toString(encoder) { const _encode = encoder ? function (value) { return encoder.call(this, value, encode); } : encode; return this._pairs .map(function each(pair) { return _encode(pair[0]) + '=' + _encode(pair[1]); }, '') .join('&'); }; export default AxiosURLSearchParams; axios-axios-2d06f96/lib/helpers/Http2Sessions.js000066400000000000000000000050761521272452000216260ustar00rootroot00000000000000'use strict'; // Node-only: relies on the built-in `http2` module. Browser/react-native // builds replace `lib/adapters/http.js` (the sole importer) with `lib/helpers/null.js` // via the `browser` package.json field, so this module is never reached in // those environments. Do not import it from any browser-reachable code path. import http2 from 'http2'; import util from 'util'; class Http2Sessions { constructor() { this.sessions = Object.create(null); } getSession(authority, options) { options = Object.assign( { sessionTimeout: 1000, }, options ); let authoritySessions = this.sessions[authority]; if (authoritySessions) { let len = authoritySessions.length; for (let i = 0; i < len; i++) { const [sessionHandle, sessionOptions] = authoritySessions[i]; if ( !sessionHandle.destroyed && !sessionHandle.closed && util.isDeepStrictEqual(sessionOptions, options) ) { return sessionHandle; } } } const session = http2.connect(authority, options); let removed; let timer; const removeSession = () => { if (removed) { return; } removed = true; if (timer) { clearTimeout(timer); timer = null; } let entries = authoritySessions, len = entries.length, i = len; while (i--) { if (entries[i][0] === session) { if (len === 1) { delete this.sessions[authority]; } else { entries.splice(i, 1); } if (!session.closed) { session.close(); } return; } } }; const originalRequestFn = session.request; const { sessionTimeout } = options; if (sessionTimeout != null) { let streamsCount = 0; session.request = function () { const stream = originalRequestFn.apply(this, arguments); streamsCount++; if (timer) { clearTimeout(timer); timer = null; } stream.once('close', () => { if (!--streamsCount) { timer = setTimeout(() => { timer = null; removeSession(); }, sessionTimeout); } }); return stream; }; } session.once('close', removeSession); let entry = [session, options]; authoritySessions ? authoritySessions.push(entry) : (authoritySessions = this.sessions[authority] = [entry]); return session; } } export default Http2Sessions; axios-axios-2d06f96/lib/helpers/HttpStatusCode.js000066400000000000000000000033401521272452000220040ustar00rootroot00000000000000const HttpStatusCode = { Continue: 100, SwitchingProtocols: 101, Processing: 102, EarlyHints: 103, Ok: 200, Created: 201, Accepted: 202, NonAuthoritativeInformation: 203, NoContent: 204, ResetContent: 205, PartialContent: 206, MultiStatus: 207, AlreadyReported: 208, ImUsed: 226, MultipleChoices: 300, MovedPermanently: 301, Found: 302, SeeOther: 303, NotModified: 304, UseProxy: 305, Unused: 306, TemporaryRedirect: 307, PermanentRedirect: 308, BadRequest: 400, Unauthorized: 401, PaymentRequired: 402, Forbidden: 403, NotFound: 404, MethodNotAllowed: 405, NotAcceptable: 406, ProxyAuthenticationRequired: 407, RequestTimeout: 408, Conflict: 409, Gone: 410, LengthRequired: 411, PreconditionFailed: 412, PayloadTooLarge: 413, UriTooLong: 414, UnsupportedMediaType: 415, RangeNotSatisfiable: 416, ExpectationFailed: 417, ImATeapot: 418, MisdirectedRequest: 421, UnprocessableEntity: 422, Locked: 423, FailedDependency: 424, TooEarly: 425, UpgradeRequired: 426, PreconditionRequired: 428, TooManyRequests: 429, RequestHeaderFieldsTooLarge: 431, UnavailableForLegalReasons: 451, InternalServerError: 500, NotImplemented: 501, BadGateway: 502, ServiceUnavailable: 503, GatewayTimeout: 504, HttpVersionNotSupported: 505, VariantAlsoNegotiates: 506, InsufficientStorage: 507, LoopDetected: 508, NotExtended: 510, NetworkAuthenticationRequired: 511, WebServerIsDown: 521, ConnectionTimedOut: 522, OriginIsUnreachable: 523, TimeoutOccurred: 524, SslHandshakeFailed: 525, InvalidSslCertificate: 526, }; Object.entries(HttpStatusCode).forEach(([key, value]) => { HttpStatusCode[value] = key; }); export default HttpStatusCode; axios-axios-2d06f96/lib/helpers/README.md000066400000000000000000000005371521272452000200140ustar00rootroot00000000000000# axios // helpers The modules found in `helpers/` should be generic modules that are _not_ specific to the domain logic of axios. These modules could theoretically be published to npm on their own and consumed by other modules or apps. Some examples of generic modules are things like: - Browser polyfills - Managing cookies - Parsing HTTP headers axios-axios-2d06f96/lib/helpers/ZlibHeaderTransformStream.js000066400000000000000000000012601521272452000241460ustar00rootroot00000000000000'use strict'; import stream from 'stream'; class ZlibHeaderTransformStream extends stream.Transform { __transform(chunk, encoding, callback) { this.push(chunk); callback(); } _transform(chunk, encoding, callback) { if (chunk.length !== 0) { this._transform = this.__transform; // Add Default Compression headers if no zlib headers are present if (chunk[0] !== 120) { // Hex: 78 const header = Buffer.alloc(2); header[0] = 120; // Hex: 78 header[1] = 156; // Hex: 9C this.push(header, encoding); } } this.__transform(chunk, encoding, callback); } } export default ZlibHeaderTransformStream; axios-axios-2d06f96/lib/helpers/bind.js000066400000000000000000000006741521272452000200110ustar00rootroot00000000000000'use strict'; /** * Create a bound version of a function with a specified `this` context * * @param {Function} fn - The function to bind * @param {*} thisArg - The value to be passed as the `this` parameter * @returns {Function} A new function that will call the original function with the specified `this` context */ export default function bind(fn, thisArg) { return function wrap() { return fn.apply(thisArg, arguments); }; } axios-axios-2d06f96/lib/helpers/buildURL.js000066400000000000000000000034101521272452000205460ustar00rootroot00000000000000'use strict'; import utils from '../utils.js'; import AxiosURLSearchParams from './AxiosURLSearchParams.js'; /** * It replaces URL-encoded forms of `:`, `$`, `,`, and spaces with * their plain counterparts (`:`, `$`, `,`, `+`). * * @param {string} val The value to be encoded. * * @returns {string} The encoded value. */ export function encode(val) { return encodeURIComponent(val) .replace(/%3A/gi, ':') .replace(/%24/g, '$') .replace(/%2C/gi, ',') .replace(/%20/g, '+'); } /** * Build a URL by appending params to the end * * @param {string} url The base of the url (e.g., http://www.google.com) * @param {object} [params] The params to be appended * @param {?(object|Function)} options * * @returns {string} The formatted url */ export default function buildURL(url, params, options) { if (!params) { return url; } const _options = utils.isFunction(options) ? { serialize: options, } : options; // Read serializer options pollution-safely: own properties and methods on a // class/template prototype are honored, but values injected onto a polluted // Object.prototype are ignored. const _encode = utils.getSafeProp(_options, 'encode') || encode; const serializeFn = utils.getSafeProp(_options, 'serialize'); let serializedParams; if (serializeFn) { serializedParams = serializeFn(params, _options); } else { serializedParams = utils.isURLSearchParams(params) ? params.toString() : new AxiosURLSearchParams(params, _options).toString(_encode); } if (serializedParams) { const hashmarkIndex = url.indexOf('#'); if (hashmarkIndex !== -1) { url = url.slice(0, hashmarkIndex); } url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams; } return url; } axios-axios-2d06f96/lib/helpers/callbackify.js000066400000000000000000000006411521272452000213330ustar00rootroot00000000000000import utils from '../utils.js'; const callbackify = (fn, reducer) => { return utils.isAsyncFn(fn) ? function (...args) { const cb = args.pop(); fn.apply(this, args).then((value) => { try { reducer ? cb(null, ...reducer(value)) : cb(null, value); } catch (err) { cb(err); } }, cb); } : fn; }; export default callbackify; axios-axios-2d06f96/lib/helpers/combineURLs.js000066400000000000000000000005761521272452000212600ustar00rootroot00000000000000'use strict'; /** * Creates a new URL by combining the specified URLs * * @param {string} baseURL The base URL * @param {string} relativeURL The relative URL * * @returns {string} The combined URL */ export default function combineURLs(baseURL, relativeURL) { return relativeURL ? baseURL.replace(/\/?\/$/, '') + '/' + relativeURL.replace(/^\/+/, '') : baseURL; } axios-axios-2d06f96/lib/helpers/composeSignals.js000066400000000000000000000025551521272452000220630ustar00rootroot00000000000000import CanceledError from '../cancel/CanceledError.js'; import AxiosError from '../core/AxiosError.js'; import utils from '../utils.js'; const composeSignals = (signals, timeout) => { signals = signals ? signals.filter(Boolean) : []; if (!timeout && !signals.length) { return; } const controller = new AbortController(); let aborted = false; const onabort = function (reason) { if (!aborted) { aborted = true; unsubscribe(); const err = reason instanceof Error ? reason : this.reason; controller.abort( err instanceof AxiosError ? err : new CanceledError(err instanceof Error ? err.message : err) ); } }; let timer = timeout && setTimeout(() => { timer = null; onabort(new AxiosError(`timeout of ${timeout}ms exceeded`, AxiosError.ETIMEDOUT)); }, timeout); const unsubscribe = () => { if (!signals) { return; } timer && clearTimeout(timer); timer = null; signals.forEach((signal) => { signal.unsubscribe ? signal.unsubscribe(onabort) : signal.removeEventListener('abort', onabort); }); signals = null; }; signals.forEach((signal) => signal.addEventListener('abort', onabort)); const { signal } = controller; signal.unsubscribe = () => utils.asap(unsubscribe); return signal; }; export default composeSignals; axios-axios-2d06f96/lib/helpers/cookies.js000066400000000000000000000040011521272452000205150ustar00rootroot00000000000000import utils from '../utils.js'; import platform from '../platform/index.js'; export default platform.hasStandardBrowserEnv ? // Standard browser envs support document.cookie { write(name, value, expires, path, domain, secure, sameSite) { if (typeof document === 'undefined') return; const cookie = [`${name}=${encodeURIComponent(value)}`]; if (utils.isNumber(expires)) { cookie.push(`expires=${new Date(expires).toUTCString()}`); } if (utils.isString(path)) { cookie.push(`path=${path}`); } if (utils.isString(domain)) { cookie.push(`domain=${domain}`); } if (secure === true) { cookie.push('secure'); } if (utils.isString(sameSite)) { cookie.push(`SameSite=${sameSite}`); } document.cookie = cookie.join('; '); }, read(name) { if (typeof document === 'undefined') return null; // Match name=value by splitting on the semicolon separator instead of building a // RegExp from `name` — interpolating an unescaped string into a RegExp would let // metacharacters (e.g. `.+?` in an attacker-influenced cookie name) cause ReDoS or // match the wrong cookie. Browsers may serialize cookie pairs as either ";" or // "; ", so ignore optional whitespace before each cookie name. const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].replace(/^\s+/, ''); const eq = cookie.indexOf('='); if (eq !== -1 && cookie.slice(0, eq) === name) { return decodeURIComponent(cookie.slice(eq + 1)); } } return null; }, remove(name) { this.write(name, '', Date.now() - 86400000, '/'); }, } : // Non-standard browser env (web workers, react-native) lack needed support. { write() {}, read() { return null; }, remove() {}, }; axios-axios-2d06f96/lib/helpers/deprecatedMethod.js000066400000000000000000000014111521272452000223240ustar00rootroot00000000000000'use strict'; /*eslint no-console:0*/ /** * Supply a warning to the developer that a method they are using * has been deprecated. * * @param {string} method The name of the deprecated method * @param {string} [instead] The alternate method to use if applicable * @param {string} [docs] The documentation URL to get further details * * @returns {void} */ export default function deprecatedMethod(method, instead, docs) { try { console.warn( 'DEPRECATED method `' + method + '`.' + (instead ? ' Use `' + instead + '` instead.' : '') + ' This method will be removed in a future release.' ); if (docs) { console.warn('For more information about usage see ' + docs); } } catch (e) { /* Ignore */ } } axios-axios-2d06f96/lib/helpers/estimateDataURLDecodedBytes.js000066400000000000000000000057671521272452000243540ustar00rootroot00000000000000/** * Estimate decoded byte length of a data:// URL *without* allocating large buffers. * - For base64: compute exact decoded size using length and padding; * handle %XX at the character-count level (no string allocation). * - For non-base64: compute the exact percent-decoded UTF-8 byte length. * * @param {string} url * @returns {number} */ const isHexDigit = (charCode) => (charCode >= 48 && charCode <= 57) || (charCode >= 65 && charCode <= 70) || (charCode >= 97 && charCode <= 102); const isPercentEncodedByte = (str, i, len) => i + 2 < len && isHexDigit(str.charCodeAt(i + 1)) && isHexDigit(str.charCodeAt(i + 2)); export default function estimateDataURLDecodedBytes(url) { if (!url || typeof url !== 'string') return 0; if (!url.startsWith('data:')) return 0; const comma = url.indexOf(','); if (comma < 0) return 0; const meta = url.slice(5, comma); const body = url.slice(comma + 1); const isBase64 = /;base64/i.test(meta); if (isBase64) { let effectiveLen = body.length; const len = body.length; // cache length for (let i = 0; i < len; i++) { if (body.charCodeAt(i) === 37 /* '%' */ && i + 2 < len) { const a = body.charCodeAt(i + 1); const b = body.charCodeAt(i + 2); const isHex = isHexDigit(a) && isHexDigit(b); if (isHex) { effectiveLen -= 2; i += 2; } } } let pad = 0; let idx = len - 1; const tailIsPct3D = (j) => j >= 2 && body.charCodeAt(j - 2) === 37 && // '%' body.charCodeAt(j - 1) === 51 && // '3' (body.charCodeAt(j) === 68 || body.charCodeAt(j) === 100); // 'D' or 'd' if (idx >= 0) { if (body.charCodeAt(idx) === 61 /* '=' */) { pad++; idx--; } else if (tailIsPct3D(idx)) { pad++; idx -= 3; } } if (pad === 1 && idx >= 0) { if (body.charCodeAt(idx) === 61 /* '=' */) { pad++; } else if (tailIsPct3D(idx)) { pad++; } } const groups = Math.floor(effectiveLen / 4); const bytes = groups * 3 - (pad || 0); return bytes > 0 ? bytes : 0; } // Compute UTF-8 byte length directly from UTF-16 code units without allocating // a byte buffer (TextEncoder.encode would defeat the DoS guard on large bodies). // Valid %XX triplets count as one decoded byte; this matches the bytes that // decodeURIComponent(body) would produce before Buffer re-encodes the string. let bytes = 0; for (let i = 0, len = body.length; i < len; i++) { const c = body.charCodeAt(i); if (c === 37 /* '%' */ && isPercentEncodedByte(body, i, len)) { bytes += 1; i += 2; } else if (c < 0x80) { bytes += 1; } else if (c < 0x800) { bytes += 2; } else if (c >= 0xd800 && c <= 0xdbff && i + 1 < len) { const next = body.charCodeAt(i + 1); if (next >= 0xdc00 && next <= 0xdfff) { bytes += 4; i++; } else { bytes += 3; } } else { bytes += 3; } } return bytes; } axios-axios-2d06f96/lib/helpers/formDataToJSON.js000066400000000000000000000053741521272452000216310ustar00rootroot00000000000000'use strict'; import utils from '../utils.js'; import AxiosError from '../core/AxiosError.js'; import { DEFAULT_FORM_DATA_MAX_DEPTH } from './toFormData.js'; const MAX_DEPTH = DEFAULT_FORM_DATA_MAX_DEPTH; function throwIfDepthExceeded(index) { if (index > MAX_DEPTH) { throw new AxiosError( 'FormData field is too deeply nested (' + index + ' levels). Max depth: ' + MAX_DEPTH, AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED ); } } /** * It takes a string like `foo[x][y][z]` and returns an array like `['foo', 'x', 'y', 'z'] * * @param {string} name - The name of the property to get. * * @returns An array of strings. */ function parsePropPath(name) { // foo[x][y][z] // foo.x.y.z // foo-x-y-z // foo x y z const path = []; const pattern = /\w+|\[(\w*)]/g; let match; while ((match = pattern.exec(name)) !== null) { throwIfDepthExceeded(path.length); path.push(match[0] === '[]' ? '' : match[1] || match[0]); } return path; } /** * Convert an array to an object. * * @param {Array} arr - The array to convert to an object. * * @returns An object with the same keys and values as the array. */ function arrayToObject(arr) { const obj = {}; const keys = Object.keys(arr); let i; const len = keys.length; let key; for (i = 0; i < len; i++) { key = keys[i]; obj[key] = arr[key]; } return obj; } /** * It takes a FormData object and returns a JavaScript object * * @param {string} formData The FormData object to convert to JSON. * * @returns {Object | null} The converted object. */ function formDataToJSON(formData) { function buildPath(path, value, target, index) { throwIfDepthExceeded(index); let name = path[index++]; if (name === '__proto__') return true; const isNumericKey = Number.isFinite(+name); const isLast = index >= path.length; name = !name && utils.isArray(target) ? target.length : name; if (isLast) { if (utils.hasOwnProp(target, name)) { target[name] = utils.isArray(target[name]) ? target[name].concat(value) : [target[name], value]; } else { target[name] = value; } return !isNumericKey; } if (!utils.hasOwnProp(target, name) || !utils.isObject(target[name])) { target[name] = []; } const result = buildPath(path, value, target[name], index); if (result && utils.isArray(target[name])) { target[name] = arrayToObject(target[name]); } return !isNumericKey; } if (utils.isFormData(formData) && utils.isFunction(formData.entries)) { const obj = {}; utils.forEachEntry(formData, (name, value) => { buildPath(parsePropPath(name), value, obj, 0); }); return obj; } return null; } export default formDataToJSON; axios-axios-2d06f96/lib/helpers/formDataToStream.js000066400000000000000000000060341521272452000223050ustar00rootroot00000000000000import util from 'util'; import { Readable } from 'stream'; import utils from '../utils.js'; import readBlob from './readBlob.js'; import platform from '../platform/index.js'; const BOUNDARY_ALPHABET = platform.ALPHABET.ALPHA_DIGIT + '-_'; const textEncoder = typeof TextEncoder === 'function' ? new TextEncoder() : new util.TextEncoder(); const CRLF = '\r\n'; const CRLF_BYTES = textEncoder.encode(CRLF); const CRLF_BYTES_COUNT = 2; class FormDataPart { constructor(name, value) { const { escapeName } = this.constructor; const isStringValue = utils.isString(value); let headers = `Content-Disposition: form-data; name="${escapeName(name)}"${ !isStringValue && value.name ? `; filename="${escapeName(value.name)}"` : '' }${CRLF}`; if (isStringValue) { value = textEncoder.encode(String(value).replace(/\r?\n|\r\n?/g, CRLF)); } else { const safeType = String(value.type || 'application/octet-stream').replace(/[\r\n]/g, ''); headers += `Content-Type: ${safeType}${CRLF}`; } this.headers = textEncoder.encode(headers + CRLF); this.contentLength = isStringValue ? value.byteLength : value.size; this.size = this.headers.byteLength + this.contentLength + CRLF_BYTES_COUNT; this.name = name; this.value = value; } async *encode() { yield this.headers; const { value } = this; if (utils.isTypedArray(value)) { yield value; } else { yield* readBlob(value); } yield CRLF_BYTES; } static escapeName(name) { return String(name).replace( /[\r\n"]/g, (match) => ({ '\r': '%0D', '\n': '%0A', '"': '%22', })[match] ); } } const formDataToStream = (form, headersHandler, options) => { const { tag = 'form-data-boundary', size = 25, boundary = tag + '-' + platform.generateString(size, BOUNDARY_ALPHABET), } = options || {}; if (!utils.isFormData(form)) { throw new TypeError('FormData instance required'); } if (boundary.length < 1 || boundary.length > 70) { throw new Error('boundary must be 1-70 characters long'); } const boundaryBytes = textEncoder.encode('--' + boundary + CRLF); const footerBytes = textEncoder.encode('--' + boundary + '--' + CRLF); let contentLength = footerBytes.byteLength; const parts = Array.from(form.entries()).map(([name, value]) => { const part = new FormDataPart(name, value); contentLength += part.size; return part; }); contentLength += boundaryBytes.byteLength * parts.length; contentLength = utils.toFiniteNumber(contentLength); const computedHeaders = { 'Content-Type': `multipart/form-data; boundary=${boundary}`, }; if (Number.isFinite(contentLength)) { computedHeaders['Content-Length'] = contentLength; } headersHandler && headersHandler(computedHeaders); return Readable.from( (async function* () { for (const part of parts) { yield boundaryBytes; yield* part.encode(); } yield footerBytes; })() ); }; export default formDataToStream; axios-axios-2d06f96/lib/helpers/fromDataURI.js000066400000000000000000000034521521272452000212070ustar00rootroot00000000000000'use strict'; import AxiosError from '../core/AxiosError.js'; import parseProtocol from './parseProtocol.js'; import platform from '../platform/index.js'; // RFC 2397: data:[][;base64], // mediatype = type/subtype followed by optional ;name=value parameters const DATA_URL_PATTERN = /^([^,;]+\/[^,;]+)?((?:;[^,;=]+=[^,;]+)*)(;base64)?,([\s\S]*)$/; /** * Parse data uri to a Buffer or Blob * * @param {String} uri * @param {?Boolean} asBlob * @param {?Object} options * @param {?Function} options.Blob * * @returns {Buffer|Blob} */ export default function fromDataURI(uri, asBlob, options) { const _Blob = (options && options.Blob) || platform.classes.Blob; const protocol = parseProtocol(uri); if (asBlob === undefined && _Blob) { asBlob = true; } if (protocol === 'data') { uri = protocol.length ? uri.slice(protocol.length + 1) : uri; const match = DATA_URL_PATTERN.exec(uri); if (!match) { throw new AxiosError('Invalid URL', AxiosError.ERR_INVALID_URL); } const type = match[1]; const params = match[2]; const encoding = match[3] ? 'base64' : 'utf8'; const body = match[4]; // RFC 2397 section 3: default mediatype is text/plain;charset=US-ASCII // Bare `data:,` leaves mime undefined; Blob normalises that to "" per spec. let mime; if (type) { mime = params ? type + params : type; } else if (params) { mime = 'text/plain' + params; } const buffer = Buffer.from(decodeURIComponent(body), encoding); if (asBlob) { if (!_Blob) { throw new AxiosError('Blob is not supported', AxiosError.ERR_NOT_SUPPORT); } return new _Blob([buffer], { type: mime }); } return buffer; } throw new AxiosError('Unsupported protocol ' + protocol, AxiosError.ERR_NOT_SUPPORT); } axios-axios-2d06f96/lib/helpers/isAbsoluteURL.js000066400000000000000000000011511521272452000215610ustar00rootroot00000000000000'use strict'; /** * Determines whether the specified URL is absolute * * @param {string} url The URL to test * * @returns {boolean} True if the specified URL is absolute, otherwise false */ export default function isAbsoluteURL(url) { // A URL is considered absolute if it begins with "://" or "//" (protocol-relative URL). // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed // by any combination of letters, digits, plus, period, or hyphen. if (typeof url !== 'string') { return false; } return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url); } axios-axios-2d06f96/lib/helpers/isAxiosError.js000066400000000000000000000005611521272452000215210ustar00rootroot00000000000000'use strict'; import utils from '../utils.js'; /** * Determines whether the payload is an error thrown by Axios * * @param {*} payload The value to test * * @returns {boolean} True if the payload is an error thrown by Axios, otherwise false */ export default function isAxiosError(payload) { return utils.isObject(payload) && payload.isAxiosError === true; } axios-axios-2d06f96/lib/helpers/isURLSameOrigin.js000066400000000000000000000007201521272452000220410ustar00rootroot00000000000000import platform from '../platform/index.js'; export default platform.hasStandardBrowserEnv ? ((origin, isMSIE) => (url) => { url = new URL(url, platform.origin); return ( origin.protocol === url.protocol && origin.host === url.host && (isMSIE || origin.port === url.port) ); })( new URL(platform.origin), platform.navigator && /(msie|trident)/i.test(platform.navigator.userAgent) ) : () => true; axios-axios-2d06f96/lib/helpers/null.js000066400000000000000000000000701521272452000200350ustar00rootroot00000000000000// eslint-disable-next-line strict export default null; axios-axios-2d06f96/lib/helpers/parseHeaders.js000066400000000000000000000026451521272452000215030ustar00rootroot00000000000000'use strict'; import utils from '../utils.js'; // RawAxiosHeaders whose duplicates are ignored by node // c.f. https://nodejs.org/api/http.html#http_message_headers const ignoreDuplicateOf = utils.toObjectSet([ 'age', 'authorization', 'content-length', 'content-type', 'etag', 'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since', 'last-modified', 'location', 'max-forwards', 'proxy-authorization', 'referer', 'retry-after', 'user-agent', ]); /** * Parse headers into an object * * ``` * Date: Wed, 27 Aug 2014 08:58:49 GMT * Content-Type: application/json * Connection: keep-alive * Transfer-Encoding: chunked * ``` * * @param {String} rawHeaders Headers needing to be parsed * * @returns {Object} Headers parsed into an object */ export default (rawHeaders) => { const parsed = {}; let key; let val; let i; rawHeaders && rawHeaders.split('\n').forEach(function parser(line) { i = line.indexOf(':'); key = line.substring(0, i).trim().toLowerCase(); val = line.substring(i + 1).trim(); if (!key || (parsed[key] && ignoreDuplicateOf[key])) { return; } if (key === 'set-cookie') { if (parsed[key]) { parsed[key].push(val); } else { parsed[key] = [val]; } } else { parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; } }); return parsed; }; axios-axios-2d06f96/lib/helpers/parseProtocol.js000066400000000000000000000002311521272452000217160ustar00rootroot00000000000000'use strict'; export default function parseProtocol(url) { const match = /^([-+\w]{1,25}):(?:\/\/)?/.exec(url); return (match && match[1]) || ''; } axios-axios-2d06f96/lib/helpers/progressEventReducer.js000066400000000000000000000026101521272452000232450ustar00rootroot00000000000000import speedometer from './speedometer.js'; import throttle from './throttle.js'; import utils from '../utils.js'; export const progressEventReducer = (listener, isDownloadStream, freq = 3) => { let bytesNotified = 0; const _speedometer = speedometer(50, 250); return throttle((e) => { if (!e || typeof e.loaded !== 'number') { return; } const rawLoaded = e.loaded; const total = e.lengthComputable ? e.total : undefined; const loaded = total != null ? Math.min(rawLoaded, total) : rawLoaded; const progressBytes = Math.max(0, loaded - bytesNotified); const rate = _speedometer(progressBytes); bytesNotified = Math.max(bytesNotified, loaded); const data = { loaded, total, progress: total ? loaded / total : undefined, bytes: progressBytes, rate: rate ? rate : undefined, estimated: rate && total ? (total - loaded) / rate : undefined, event: e, lengthComputable: total != null, [isDownloadStream ? 'download' : 'upload']: true, }; listener(data); }, freq); }; export const progressEventDecorator = (total, throttled) => { const lengthComputable = total != null; return [ (loaded) => throttled[0]({ lengthComputable, total, loaded, }), throttled[1], ]; }; export const asyncDecorator = (fn) => (...args) => utils.asap(() => fn(...args)); axios-axios-2d06f96/lib/helpers/readBlob.js000066400000000000000000000005031521272452000205760ustar00rootroot00000000000000const { asyncIterator } = Symbol; const readBlob = async function* (blob) { if (blob.stream) { yield* blob.stream(); } else if (blob.arrayBuffer) { yield await blob.arrayBuffer(); } else if (blob[asyncIterator]) { yield* blob[asyncIterator](); } else { yield blob; } }; export default readBlob; axios-axios-2d06f96/lib/helpers/resolveConfig.js000066400000000000000000000071231521272452000216760ustar00rootroot00000000000000import platform from '../platform/index.js'; import utils from '../utils.js'; import isURLSameOrigin from './isURLSameOrigin.js'; import cookies from './cookies.js'; import buildFullPath from '../core/buildFullPath.js'; import mergeConfig from '../core/mergeConfig.js'; import AxiosHeaders from '../core/AxiosHeaders.js'; import buildURL from './buildURL.js'; const FORM_DATA_CONTENT_HEADERS = ['content-type', 'content-length']; function setFormDataHeaders(headers, formHeaders, policy) { if (policy !== 'content-only') { headers.set(formHeaders); return; } Object.entries(formHeaders).forEach(([key, val]) => { if (FORM_DATA_CONTENT_HEADERS.includes(key.toLowerCase())) { headers.set(key, val); } }); } /** * Encode a UTF-8 string to a Latin-1 byte string for use with btoa(). * This is a modern replacement for the deprecated unescape(encodeURIComponent(str)) pattern. * * @param {string} str The string to encode * * @returns {string} UTF-8 bytes as a Latin-1 string */ const encodeUTF8 = (str) => encodeURIComponent(str).replace(/%([0-9A-F]{2})/gi, (_, hex) => String.fromCharCode(parseInt(hex, 16)) ); function resolveConfig(config) { const newConfig = mergeConfig({}, config); // Read only own properties to prevent prototype pollution gadgets // (e.g. Object.prototype.baseURL = 'https://evil.com'). const own = (key) => (utils.hasOwnProp(newConfig, key) ? newConfig[key] : undefined); const data = own('data'); let withXSRFToken = own('withXSRFToken'); const xsrfHeaderName = own('xsrfHeaderName'); const xsrfCookieName = own('xsrfCookieName'); let headers = own('headers'); const auth = own('auth'); const baseURL = own('baseURL'); const allowAbsoluteUrls = own('allowAbsoluteUrls'); const url = own('url'); newConfig.headers = headers = AxiosHeaders.from(headers); newConfig.url = buildURL( buildFullPath(baseURL, url, allowAbsoluteUrls, newConfig), own('params'), own('paramsSerializer') ); // HTTP basic authentication if (auth) { const username = utils.getSafeProp(auth, 'username') || ''; const password = utils.getSafeProp(auth, 'password') || ''; headers.set( 'Authorization', 'Basic ' + btoa(username + ':' + (password ? encodeUTF8(password) : '')) ); } if (utils.isFormData(data)) { if ( platform.hasStandardBrowserEnv || platform.hasStandardBrowserWebWorkerEnv || utils.isReactNative(data) ) { headers.setContentType(undefined); // browser/web worker/RN handles it } else if (utils.isFunction(data.getHeaders)) { // Node.js FormData (like form-data package) setFormDataHeaders(headers, data.getHeaders(), own('formDataHeaderPolicy')); } } // Add xsrf header // This is only done if running in a standard browser environment. // Specifically not if we're in a web worker, or react-native. if (platform.hasStandardBrowserEnv) { if (utils.isFunction(withXSRFToken)) { withXSRFToken = withXSRFToken(newConfig); } // Strict boolean check — prevents proto-pollution gadgets (e.g. Object.prototype.withXSRFToken = 1) // and misconfigurations (e.g. "false") from short-circuiting the same-origin check and leaking // the XSRF token cross-origin. const shouldSendXSRF = withXSRFToken === true || (withXSRFToken == null && isURLSameOrigin(newConfig.url)); if (shouldSendXSRF) { const xsrfValue = xsrfHeaderName && xsrfCookieName && cookies.read(xsrfCookieName); if (xsrfValue) { headers.set(xsrfHeaderName, xsrfValue); } } } return newConfig; } export default resolveConfig; axios-axios-2d06f96/lib/helpers/sanitizeHeaderValue.js000066400000000000000000000030651521272452000230260ustar00rootroot00000000000000'use strict'; import utils from '../utils.js'; function trimSPorHTAB(str) { let start = 0; let end = str.length; while (start < end) { const code = str.charCodeAt(start); if (code !== 0x09 && code !== 0x20) { break; } start += 1; } while (end > start) { const code = str.charCodeAt(end - 1); if (code !== 0x09 && code !== 0x20) { break; } end -= 1; } return start === 0 && end === str.length ? str : str.slice(start, end); } // The control-code ranges are intentional: header sanitization strips C0/DEL bytes. // eslint-disable-next-line no-control-regex const INVALID_UNICODE_HEADER_VALUE_CHARS = new RegExp('[\\u0000-\\u0008\\u000a-\\u001f\\u007f]+', 'g'); // eslint-disable-next-line no-control-regex const INVALID_BYTE_STRING_HEADER_VALUE_CHARS = new RegExp('[^\\u0009\\u0020-\\u007e\\u0080-\\u00ff]+', 'g'); function sanitizeValue(value, invalidChars) { if (utils.isArray(value)) { return value.map((item) => sanitizeValue(item, invalidChars)); } return trimSPorHTAB(String(value).replace(invalidChars, '')); } export const sanitizeHeaderValue = (value) => sanitizeValue(value, INVALID_UNICODE_HEADER_VALUE_CHARS); export const sanitizeByteStringHeaderValue = (value) => sanitizeValue(value, INVALID_BYTE_STRING_HEADER_VALUE_CHARS); export function toByteStringHeaderObject(headers) { const byteStringHeaders = Object.create(null); utils.forEach(headers.toJSON(), (value, header) => { byteStringHeaders[header] = sanitizeByteStringHeaderValue(value); }); return byteStringHeaders; } axios-axios-2d06f96/lib/helpers/shouldBypassProxy.js000066400000000000000000000141051521272452000226110ustar00rootroot00000000000000const LOOPBACK_HOSTNAMES = new Set(['localhost', '0.0.0.0']); const isIPv4Loopback = (host) => { const parts = host.split('.'); if (parts.length !== 4) return false; if (parts[0] !== '127') return false; return parts.every((p) => /^\d+$/.test(p) && Number(p) >= 0 && Number(p) <= 255); }; const isIPv6ZeroGroup = (group) => /^0{1,4}$/.test(group); // The unspecified address (IPv4 0.0.0.0 / IPv6 ::) resolves to the local host // for outbound connections, so treat it as loopback-equivalent for NO_PROXY // matching. 0.0.0.0 is covered by LOOPBACK_HOSTNAMES; this handles compressed // and full IPv6 all-zero forms so both families bypass symmetrically. const isIPv6Unspecified = (host) => { if (host === '::') return true; const compressionIndex = host.indexOf('::'); if (compressionIndex !== -1) { if (compressionIndex !== host.lastIndexOf('::')) return false; const left = host.slice(0, compressionIndex); const right = host.slice(compressionIndex + 2); const leftGroups = left ? left.split(':') : []; const rightGroups = right ? right.split(':') : []; const explicitGroups = leftGroups.length + rightGroups.length; return ( explicitGroups < 8 && leftGroups.every(isIPv6ZeroGroup) && rightGroups.every(isIPv6ZeroGroup) ); } const groups = host.split(':'); return groups.length === 8 && groups.every(isIPv6ZeroGroup); }; const isIPv6Loopback = (host) => { // Collapse all-zero groups: any form of ::1 / 0:0:...:0:1 // First, strip any leading "::" by normalising with Set lookup of common forms, // then fall back to structural check. if (host === '::1') return true; // Check IPv4-mapped IPv6 loopback: ::ffff: or ::ffff: // Node's URL parser normalises ::ffff:127.0.0.1 → ::ffff:7f00:1 const v4MappedDotted = host.match(/^::ffff:(\d+\.\d+\.\d+\.\d+)$/i); if (v4MappedDotted) return isIPv4Loopback(v4MappedDotted[1]); const v4MappedHex = host.match(/^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i); if (v4MappedHex) { const high = parseInt(v4MappedHex[1], 16); // High 16 bits must start with 127 (0x7f) — i.e. 0x7f00..0x7fff return high >= 0x7f00 && high <= 0x7fff; } // Full-form ::1 variants: any number of zero groups followed by trailing 1 // e.g. 0:0:0:0:0:0:0:1, 0000:...:0001 const groups = host.split(':'); if (groups.length === 8) { for (let i = 0; i < 7; i++) { if (!/^0+$/.test(groups[i])) return false; } return /^0*1$/.test(groups[7]); } return false; }; const isLoopback = (host) => { if (!host) return false; if (LOOPBACK_HOSTNAMES.has(host)) return true; if (isIPv4Loopback(host)) return true; if (isIPv6Unspecified(host)) return true; return isIPv6Loopback(host); }; const DEFAULT_PORTS = { http: 80, https: 443, ws: 80, wss: 443, ftp: 21, }; const parseNoProxyEntry = (entry) => { let entryHost = entry; let entryPort = 0; if (entryHost.charAt(0) === '[') { const bracketIndex = entryHost.indexOf(']'); if (bracketIndex !== -1) { const host = entryHost.slice(1, bracketIndex); const rest = entryHost.slice(bracketIndex + 1); if (rest.charAt(0) === ':' && /^\d+$/.test(rest.slice(1))) { entryPort = Number.parseInt(rest.slice(1), 10); } return [host, entryPort]; } } const firstColon = entryHost.indexOf(':'); const lastColon = entryHost.lastIndexOf(':'); if ( firstColon !== -1 && firstColon === lastColon && /^\d+$/.test(entryHost.slice(lastColon + 1)) ) { entryPort = Number.parseInt(entryHost.slice(lastColon + 1), 10); entryHost = entryHost.slice(0, lastColon); } return [entryHost, entryPort]; }; // Convert IPv4-mapped IPv6 (::ffff:0:0/96 prefix) to IPv4 dotted form so both // sides of a NO_PROXY comparison see the same canonical address. Without this, // `NO_PROXY=192.168.1.5` would not match a request to `http://[::ffff:192.168.1.5]/` // (Node's URL parser normalises that to `[::ffff:c0a8:105]`), and vice-versa, // allowing the proxy-bypass policy to be circumvented by using the alternate // representation. Returns the input unchanged when not IPv4-mapped. const IPV4_MAPPED_DOTTED_RE = /^(?:::|(?:0{1,4}:){1,4}:|(?:0{1,4}:){5})ffff:(\d+\.\d+\.\d+\.\d+)$/i; const IPV4_MAPPED_HEX_RE = /^(?:::|(?:0{1,4}:){1,4}:|(?:0{1,4}:){5})ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i; const unmapIPv4MappedIPv6 = (host) => { if (typeof host !== 'string' || host.indexOf(':') === -1) return host; const dotted = host.match(IPV4_MAPPED_DOTTED_RE); if (dotted) return dotted[1]; const hex = host.match(IPV4_MAPPED_HEX_RE); if (hex) { const high = parseInt(hex[1], 16); const low = parseInt(hex[2], 16); return `${high >> 8}.${high & 0xff}.${low >> 8}.${low & 0xff}`; } return host; }; const normalizeNoProxyHost = (hostname) => { if (!hostname) { return hostname; } if (hostname.charAt(0) === '[' && hostname.charAt(hostname.length - 1) === ']') { hostname = hostname.slice(1, -1); } return unmapIPv4MappedIPv6(hostname.replace(/\.+$/, '')); }; export default function shouldBypassProxy(location) { let parsed; try { parsed = new URL(location); } catch (_err) { return false; } const noProxy = (process.env.no_proxy || process.env.NO_PROXY || '').toLowerCase(); if (!noProxy) { return false; } if (noProxy === '*') { return true; } const port = Number.parseInt(parsed.port, 10) || DEFAULT_PORTS[parsed.protocol.split(':', 1)[0]] || 0; const hostname = normalizeNoProxyHost(parsed.hostname.toLowerCase()); return noProxy.split(/[\s,]+/).some((entry) => { if (!entry) { return false; } let [entryHost, entryPort] = parseNoProxyEntry(entry); entryHost = normalizeNoProxyHost(entryHost); if (!entryHost) { return false; } if (entryPort && entryPort !== port) { return false; } if (entryHost.charAt(0) === '*') { entryHost = entryHost.slice(1); } if (entryHost.charAt(0) === '.') { return hostname.endsWith(entryHost); } return hostname === entryHost || (isLoopback(hostname) && isLoopback(entryHost)); }); } axios-axios-2d06f96/lib/helpers/speedometer.js000066400000000000000000000021061521272452000214010ustar00rootroot00000000000000'use strict'; /** * Calculate data maxRate * @param {Number} [samplesCount= 10] * @param {Number} [min= 1000] * @returns {Function} */ function speedometer(samplesCount, min) { samplesCount = samplesCount || 10; const bytes = new Array(samplesCount); const timestamps = new Array(samplesCount); let head = 0; let tail = 0; let firstSampleTS; min = min !== undefined ? min : 1000; return function push(chunkLength) { const now = Date.now(); const startedAt = timestamps[tail]; if (!firstSampleTS) { firstSampleTS = now; } bytes[head] = chunkLength; timestamps[head] = now; let i = tail; let bytesCount = 0; while (i !== head) { bytesCount += bytes[i++]; i = i % samplesCount; } head = (head + 1) % samplesCount; if (head === tail) { tail = (tail + 1) % samplesCount; } if (now - firstSampleTS < min) { return; } const passed = startedAt && now - startedAt; return passed ? Math.round((bytesCount * 1000) / passed) : undefined; }; } export default speedometer; axios-axios-2d06f96/lib/helpers/spread.js000066400000000000000000000010661521272452000203470ustar00rootroot00000000000000'use strict'; /** * Syntactic sugar for invoking a function and expanding an array for arguments. * * Common use case would be to use `Function.prototype.apply`. * * ```js * function f(x, y, z) {} * const args = [1, 2, 3]; * f.apply(null, args); * ``` * * With `spread` this example can be re-written. * * ```js * spread(function(x, y, z) {})([1, 2, 3]); * ``` * * @param {Function} callback * * @returns {Function} */ export default function spread(callback) { return function wrap(arr) { return callback.apply(null, arr); }; } axios-axios-2d06f96/lib/helpers/throttle.js000066400000000000000000000015261521272452000207370ustar00rootroot00000000000000/** * Throttle decorator * @param {Function} fn * @param {Number} freq * @return {Function} */ function throttle(fn, freq) { let timestamp = 0; let threshold = 1000 / freq; let lastArgs; let timer; const invoke = (args, now = Date.now()) => { timestamp = now; lastArgs = null; if (timer) { clearTimeout(timer); timer = null; } fn(...args); }; const throttled = (...args) => { const now = Date.now(); const passed = now - timestamp; if (passed >= threshold) { invoke(args, now); } else { lastArgs = args; if (!timer) { timer = setTimeout(() => { timer = null; invoke(lastArgs); }, threshold - passed); } } }; const flush = () => lastArgs && invoke(lastArgs); return [throttled, flush]; } export default throttle; axios-axios-2d06f96/lib/helpers/toFormData.js000066400000000000000000000166631521272452000211420ustar00rootroot00000000000000'use strict'; import utils from '../utils.js'; import AxiosError from '../core/AxiosError.js'; // temporary hotfix to avoid circular references until AxiosURLSearchParams is refactored import PlatformFormData from '../platform/node/classes/FormData.js'; // Default nesting limit shared with the inverse transform (formDataToJSON) so // the FormData <-> JSON round-trip stays symmetric. export const DEFAULT_FORM_DATA_MAX_DEPTH = 100; /** * Determines if the given thing is a array or js object. * * @param {string} thing - The object or array to be visited. * * @returns {boolean} */ function isVisitable(thing) { return utils.isPlainObject(thing) || utils.isArray(thing); } /** * It removes the brackets from the end of a string * * @param {string} key - The key of the parameter. * * @returns {string} the key without the brackets. */ function removeBrackets(key) { return utils.endsWith(key, '[]') ? key.slice(0, -2) : key; } /** * It takes a path, a key, and a boolean, and returns a string * * @param {string} path - The path to the current key. * @param {string} key - The key of the current object being iterated over. * @param {string} dots - If true, the key will be rendered with dots instead of brackets. * * @returns {string} The path to the current key. */ function renderKey(path, key, dots) { if (!path) return key; return path .concat(key) .map(function each(token, i) { // eslint-disable-next-line no-param-reassign token = removeBrackets(token); return !dots && i ? '[' + token + ']' : token; }) .join(dots ? '.' : ''); } /** * If the array is an array and none of its elements are visitable, then it's a flat array. * * @param {Array} arr - The array to check * * @returns {boolean} */ function isFlatArray(arr) { return utils.isArray(arr) && !arr.some(isVisitable); } const predicates = utils.toFlatObject(utils, {}, null, function filter(prop) { return /^is[A-Z]/.test(prop); }); /** * Convert a data object to FormData * * @param {Object} obj * @param {?Object} [formData] * @param {?Object} [options] * @param {Function} [options.visitor] * @param {Boolean} [options.metaTokens = true] * @param {Boolean} [options.dots = false] * @param {?Boolean} [options.indexes = false] * * @returns {Object} **/ /** * It converts an object into a FormData object * * @param {Object} obj - The object to convert to form data. * @param {string} formData - The FormData object to append to. * @param {Object} options * * @returns */ function toFormData(obj, formData, options) { if (!utils.isObject(obj)) { throw new TypeError('target must be an object'); } // eslint-disable-next-line no-param-reassign formData = formData || new (PlatformFormData || FormData)(); // eslint-disable-next-line no-param-reassign options = utils.toFlatObject( options, { metaTokens: true, dots: false, indexes: false, }, false, function defined(option, source) { // eslint-disable-next-line no-eq-null,eqeqeq return !utils.isUndefined(source[option]); } ); const metaTokens = options.metaTokens; // eslint-disable-next-line no-use-before-define const visitor = options.visitor || defaultVisitor; const dots = options.dots; const indexes = options.indexes; const _Blob = options.Blob || (typeof Blob !== 'undefined' && Blob); const maxDepth = options.maxDepth === undefined ? DEFAULT_FORM_DATA_MAX_DEPTH : options.maxDepth; const useBlob = _Blob && utils.isSpecCompliantForm(formData); const stack = []; if (!utils.isFunction(visitor)) { throw new TypeError('visitor must be a function'); } function convertValue(value) { if (value === null) return ''; if (utils.isDate(value)) { return value.toISOString(); } if (utils.isBoolean(value)) { return value.toString(); } if (!useBlob && utils.isBlob(value)) { throw new AxiosError('Blob is not supported. Use a Buffer instead.'); } if (utils.isArrayBuffer(value) || utils.isTypedArray(value)) { return useBlob && typeof Blob === 'function' ? new Blob([value]) : Buffer.from(value); } return value; } function throwIfMaxDepthExceeded(depth) { if (depth > maxDepth) { throw new AxiosError( 'Object is too deeply nested (' + depth + ' levels). Max depth: ' + maxDepth, AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED ); } } function stringifyWithDepthLimit(value, depth) { if (maxDepth === Infinity) { return JSON.stringify(value); } const ancestors = []; return JSON.stringify(value, function limitDepth(_key, currentValue) { if (!utils.isObject(currentValue)) { return currentValue; } while (ancestors.length && ancestors[ancestors.length - 1] !== this) { ancestors.pop(); } ancestors.push(currentValue); throwIfMaxDepthExceeded(depth + ancestors.length - 1); return currentValue; }); } /** * Default visitor. * * @param {*} value * @param {String|Number} key * @param {Array} path * @this {FormData} * * @returns {boolean} return true to visit the each prop of the value recursively */ function defaultVisitor(value, key, path) { let arr = value; if (utils.isReactNative(formData) && utils.isReactNativeBlob(value)) { formData.append(renderKey(path, key, dots), convertValue(value)); return false; } if (value && !path && typeof value === 'object') { if (utils.endsWith(key, '{}')) { // eslint-disable-next-line no-param-reassign key = metaTokens ? key : key.slice(0, -2); // eslint-disable-next-line no-param-reassign value = stringifyWithDepthLimit(value, 1); } else if ( (utils.isArray(value) && isFlatArray(value)) || ((utils.isFileList(value) || utils.endsWith(key, '[]')) && (arr = utils.toArray(value))) ) { // eslint-disable-next-line no-param-reassign key = removeBrackets(key); arr.forEach(function each(el, index) { !(utils.isUndefined(el) || el === null) && formData.append( // eslint-disable-next-line no-nested-ternary indexes === true ? renderKey([key], index, dots) : indexes === null ? key : key + '[]', convertValue(el) ); }); return false; } } if (isVisitable(value)) { return true; } formData.append(renderKey(path, key, dots), convertValue(value)); return false; } const exposedHelpers = Object.assign(predicates, { defaultVisitor, convertValue, isVisitable, }); function build(value, path, depth = 0) { if (utils.isUndefined(value)) return; throwIfMaxDepthExceeded(depth); if (stack.indexOf(value) !== -1) { throw new Error('Circular reference detected in ' + path.join('.')); } stack.push(value); utils.forEach(value, function each(el, key) { const result = !(utils.isUndefined(el) || el === null) && visitor.call(formData, el, utils.isString(key) ? key.trim() : key, path, exposedHelpers); if (result === true) { build(el, path ? path.concat(key) : [key], depth + 1); } }); stack.pop(); } if (!utils.isObject(obj)) { throw new TypeError('data must be an object'); } build(obj); return formData; } export default toFormData; axios-axios-2d06f96/lib/helpers/toURLEncodedForm.js000066400000000000000000000010361521272452000222010ustar00rootroot00000000000000'use strict'; import utils from '../utils.js'; import toFormData from './toFormData.js'; import platform from '../platform/index.js'; export default function toURLEncodedForm(data, options) { return toFormData(data, new platform.classes.URLSearchParams(), { visitor: function (value, key, path, helpers) { if (platform.isNode && utils.isBuffer(value)) { this.append(key, value.toString('base64')); return false; } return helpers.defaultVisitor.apply(this, arguments); }, ...options, }); } axios-axios-2d06f96/lib/helpers/trackStream.js000066400000000000000000000033441521272452000213520ustar00rootroot00000000000000export const streamChunk = function* (chunk, chunkSize) { let len = chunk.byteLength; if (!chunkSize || len < chunkSize) { yield chunk; return; } let pos = 0; let end; while (pos < len) { end = pos + chunkSize; yield chunk.slice(pos, end); pos = end; } }; export const readBytes = async function* (iterable, chunkSize) { for await (const chunk of readStream(iterable)) { yield* streamChunk(chunk, chunkSize); } }; const readStream = async function* (stream) { if (stream[Symbol.asyncIterator]) { yield* stream; return; } const reader = stream.getReader(); try { for (;;) { const { done, value } = await reader.read(); if (done) { break; } yield value; } } finally { await reader.cancel(); } }; export const trackStream = (stream, chunkSize, onProgress, onFinish) => { const iterator = readBytes(stream, chunkSize); let bytes = 0; let done; let _onFinish = (e) => { if (!done) { done = true; onFinish && onFinish(e); } }; return new ReadableStream( { async pull(controller) { try { const { done, value } = await iterator.next(); if (done) { _onFinish(); controller.close(); return; } let len = value.byteLength; if (onProgress) { let loadedBytes = (bytes += len); onProgress(loadedBytes); } controller.enqueue(new Uint8Array(value)); } catch (err) { _onFinish(err); throw err; } }, cancel(reason) { _onFinish(reason); return iterator.return(); }, }, { highWaterMark: 2, } ); }; axios-axios-2d06f96/lib/helpers/validator.js000066400000000000000000000057671521272452000210720ustar00rootroot00000000000000'use strict'; import { VERSION } from '../env/data.js'; import AxiosError from '../core/AxiosError.js'; const validators = {}; // eslint-disable-next-line func-names ['object', 'boolean', 'number', 'function', 'string', 'symbol'].forEach((type, i) => { validators[type] = function validator(thing) { return typeof thing === type || 'a' + (i < 1 ? 'n ' : ' ') + type; }; }); const deprecatedWarnings = {}; /** * Transitional option validator * * @param {function|boolean?} validator - set to false if the transitional option has been removed * @param {string?} version - deprecated version / removed since version * @param {string?} message - some message with additional info * * @returns {function} */ validators.transitional = function transitional(validator, version, message) { function formatMessage(opt, desc) { return ( '[Axios v' + VERSION + "] Transitional option '" + opt + "'" + desc + (message ? '. ' + message : '') ); } // eslint-disable-next-line func-names return (value, opt, opts) => { if (validator === false) { throw new AxiosError( formatMessage(opt, ' has been removed' + (version ? ' in ' + version : '')), AxiosError.ERR_DEPRECATED ); } if (version && !deprecatedWarnings[opt]) { deprecatedWarnings[opt] = true; // eslint-disable-next-line no-console console.warn( formatMessage( opt, ' has been deprecated since v' + version + ' and will be removed in the near future' ) ); } return validator ? validator(value, opt, opts) : true; }; }; validators.spelling = function spelling(correctSpelling) { return (value, opt) => { // eslint-disable-next-line no-console console.warn(`${opt} is likely a misspelling of ${correctSpelling}`); return true; }; }; /** * Assert object's properties type * * @param {object} options * @param {object} schema * @param {boolean?} allowUnknown * * @returns {object} */ function assertOptions(options, schema, allowUnknown) { if (typeof options !== 'object') { throw new AxiosError('options must be an object', AxiosError.ERR_BAD_OPTION_VALUE); } const keys = Object.keys(options); let i = keys.length; while (i-- > 0) { const opt = keys[i]; // Use hasOwnProperty so a polluted Object.prototype. cannot supply // a non-function validator and cause a TypeError. const validator = Object.prototype.hasOwnProperty.call(schema, opt) ? schema[opt] : undefined; if (validator) { const value = options[opt]; const result = value === undefined || validator(value, opt, options); if (result !== true) { throw new AxiosError( 'option ' + opt + ' must be ' + result, AxiosError.ERR_BAD_OPTION_VALUE ); } continue; } if (allowUnknown !== true) { throw new AxiosError('Unknown option ' + opt, AxiosError.ERR_BAD_OPTION); } } } export default { assertOptions, validators, }; axios-axios-2d06f96/lib/platform/000077500000000000000000000000001521272452000167125ustar00rootroot00000000000000axios-axios-2d06f96/lib/platform/browser/000077500000000000000000000000001521272452000203755ustar00rootroot00000000000000axios-axios-2d06f96/lib/platform/browser/classes/000077500000000000000000000000001521272452000220325ustar00rootroot00000000000000axios-axios-2d06f96/lib/platform/browser/classes/Blob.js000066400000000000000000000001111521272452000232370ustar00rootroot00000000000000'use strict'; export default typeof Blob !== 'undefined' ? Blob : null; axios-axios-2d06f96/lib/platform/browser/classes/FormData.js000066400000000000000000000001211521272452000240570ustar00rootroot00000000000000'use strict'; export default typeof FormData !== 'undefined' ? FormData : null; axios-axios-2d06f96/lib/platform/browser/classes/URLSearchParams.js000066400000000000000000000002741521272452000253270ustar00rootroot00000000000000'use strict'; import AxiosURLSearchParams from '../../../helpers/AxiosURLSearchParams.js'; export default typeof URLSearchParams !== 'undefined' ? URLSearchParams : AxiosURLSearchParams; axios-axios-2d06f96/lib/platform/browser/index.js000066400000000000000000000004661521272452000220500ustar00rootroot00000000000000import URLSearchParams from './classes/URLSearchParams.js'; import FormData from './classes/FormData.js'; import Blob from './classes/Blob.js'; export default { isBrowser: true, classes: { URLSearchParams, FormData, Blob, }, protocols: ['http', 'https', 'file', 'blob', 'url', 'data'], }; axios-axios-2d06f96/lib/platform/common/000077500000000000000000000000001521272452000202025ustar00rootroot00000000000000axios-axios-2d06f96/lib/platform/common/utils.js000066400000000000000000000031031521272452000216750ustar00rootroot00000000000000const hasBrowserEnv = typeof window !== 'undefined' && typeof document !== 'undefined'; const _navigator = (typeof navigator === 'object' && navigator) || undefined; /** * Determine if we're running in a standard browser environment * * This allows axios to run in a web worker, and react-native. * Both environments support XMLHttpRequest, but not fully standard globals. * * web workers: * typeof window -> undefined * typeof document -> undefined * * react-native: * navigator.product -> 'ReactNative' * nativescript * navigator.product -> 'NativeScript' or 'NS' * * @returns {boolean} */ const hasStandardBrowserEnv = hasBrowserEnv && (!_navigator || ['ReactNative', 'NativeScript', 'NS'].indexOf(_navigator.product) < 0); /** * Determine if we're running in a standard browser webWorker environment * * Although the `isStandardBrowserEnv` method indicates that * `allows axios to run in a web worker`, the WebWorker will still be * filtered out due to its judgment standard * `typeof window !== 'undefined' && typeof document !== 'undefined'`. * This leads to a problem when axios post `FormData` in webWorker */ const hasStandardBrowserWebWorkerEnv = (() => { return ( typeof WorkerGlobalScope !== 'undefined' && // eslint-disable-next-line no-undef self instanceof WorkerGlobalScope && typeof self.importScripts === 'function' ); })(); const origin = (hasBrowserEnv && window.location.href) || 'http://localhost'; export { hasBrowserEnv, hasStandardBrowserWebWorkerEnv, hasStandardBrowserEnv, _navigator as navigator, origin, }; axios-axios-2d06f96/lib/platform/index.js000066400000000000000000000002041521272452000203530ustar00rootroot00000000000000import platform from './node/index.js'; import * as utils from './common/utils.js'; export default { ...utils, ...platform, }; axios-axios-2d06f96/lib/platform/node/000077500000000000000000000000001521272452000176375ustar00rootroot00000000000000axios-axios-2d06f96/lib/platform/node/classes/000077500000000000000000000000001521272452000212745ustar00rootroot00000000000000axios-axios-2d06f96/lib/platform/node/classes/FormData.js000066400000000000000000000000741521272452000233300ustar00rootroot00000000000000import FormData from 'form-data'; export default FormData; axios-axios-2d06f96/lib/platform/node/classes/URLSearchParams.js000066400000000000000000000001121521272452000245600ustar00rootroot00000000000000'use strict'; import url from 'url'; export default url.URLSearchParams; axios-axios-2d06f96/lib/platform/node/index.js000066400000000000000000000015051521272452000213050ustar00rootroot00000000000000import crypto from 'crypto'; import URLSearchParams from './classes/URLSearchParams.js'; import FormData from './classes/FormData.js'; const ALPHA = 'abcdefghijklmnopqrstuvwxyz'; const DIGIT = '0123456789'; const ALPHABET = { DIGIT, ALPHA, ALPHA_DIGIT: ALPHA + ALPHA.toUpperCase() + DIGIT, }; const generateString = (size = 16, alphabet = ALPHABET.ALPHA_DIGIT) => { let str = ''; const { length } = alphabet; const randomValues = new Uint32Array(size); crypto.randomFillSync(randomValues); for (let i = 0; i < size; i++) { str += alphabet[randomValues[i] % length]; } return str; }; export default { isNode: true, classes: { URLSearchParams, FormData, Blob: (typeof Blob !== 'undefined' && Blob) || null, }, ALPHABET, generateString, protocols: ['http', 'https', 'file', 'data'], }; axios-axios-2d06f96/lib/utils.js000066400000000000000000000650151521272452000165730ustar00rootroot00000000000000'use strict'; import bind from './helpers/bind.js'; // utils is a library of generic helper functions non-specific to axios const { toString } = Object.prototype; const { getPrototypeOf } = Object; const { iterator, toStringTag } = Symbol; /* Creating a function that will check if an object has a property. */ const hasOwnProperty = ( ({ hasOwnProperty }) => (obj, prop) => hasOwnProperty.call(obj, prop) )(Object.prototype); /** * Walk the prototype chain (excluding the shared Object.prototype) looking for * an own `prop`. This distinguishes genuine own/inherited members — including * class accessors and template prototypes — from members injected via * Object.prototype pollution (e.g. `Object.prototype.username = '...'`), which * live on Object.prototype itself and are therefore never matched. * * @param {*} thing The value whose chain to inspect * @param {string|symbol} prop The property key to look for * * @returns {boolean} True when `prop` is owned below Object.prototype */ const hasOwnInPrototypeChain = (thing, prop) => { let obj = thing; const seen = []; while (obj != null && obj !== Object.prototype) { if (seen.indexOf(obj) !== -1) { return false; } seen.push(obj); if (hasOwnProperty(obj, prop)) { return true; } obj = getPrototypeOf(obj); } return false; }; /** * Read `obj[prop]` only when it is safe from Object.prototype pollution. Own * properties and members inherited from a non-Object.prototype source (a class * instance or template object) are honored; a value reachable only through a * polluted Object.prototype is ignored and `undefined` is returned. * * @param {*} obj The source object * @param {string|symbol} prop The property key to read * * @returns {*} The resolved value, or undefined when unsafe/absent */ const getSafeProp = (obj, prop) => obj != null && hasOwnInPrototypeChain(obj, prop) ? obj[prop] : undefined; const kindOf = ((cache) => (thing) => { const str = toString.call(thing); return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase()); })(Object.create(null)); const kindOfTest = (type) => { type = type.toLowerCase(); return (thing) => kindOf(thing) === type; }; const typeOfTest = (type) => (thing) => typeof thing === type; /** * Determine if a value is a non-null object * * @param {Object} val The value to test * * @returns {boolean} True if value is an Array, otherwise false */ const { isArray } = Array; /** * Determine if a value is undefined * * @param {*} val The value to test * * @returns {boolean} True if the value is undefined, otherwise false */ const isUndefined = typeOfTest('undefined'); /** * Determine if a value is a Buffer * * @param {*} val The value to test * * @returns {boolean} True if value is a Buffer, otherwise false */ function isBuffer(val) { return ( val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor) && isFunction(val.constructor.isBuffer) && val.constructor.isBuffer(val) ); } /** * Determine if a value is an ArrayBuffer * * @param {*} val The value to test * * @returns {boolean} True if value is an ArrayBuffer, otherwise false */ const isArrayBuffer = kindOfTest('ArrayBuffer'); /** * Determine if a value is a view on an ArrayBuffer * * @param {*} val The value to test * * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false */ function isArrayBufferView(val) { let result; if (typeof ArrayBuffer !== 'undefined' && ArrayBuffer.isView) { result = ArrayBuffer.isView(val); } else { result = val && val.buffer && isArrayBuffer(val.buffer); } return result; } /** * Determine if a value is a String * * @param {*} val The value to test * * @returns {boolean} True if value is a String, otherwise false */ const isString = typeOfTest('string'); /** * Determine if a value is a Function * * @param {*} val The value to test * @returns {boolean} True if value is a Function, otherwise false */ const isFunction = typeOfTest('function'); /** * Determine if a value is a Number * * @param {*} val The value to test * * @returns {boolean} True if value is a Number, otherwise false */ const isNumber = typeOfTest('number'); /** * Determine if a value is an Object * * @param {*} thing The value to test * * @returns {boolean} True if value is an Object, otherwise false */ const isObject = (thing) => thing !== null && typeof thing === 'object'; /** * Determine if a value is a Boolean * * @param {*} thing The value to test * @returns {boolean} True if value is a Boolean, otherwise false */ const isBoolean = (thing) => thing === true || thing === false; /** * Determine if a value is a plain Object * * @param {*} val The value to test * * @returns {boolean} True if value is a plain Object, otherwise false */ const isPlainObject = (val) => { if (!isObject(val)) { return false; } const prototype = getPrototypeOf(val); return ( (prototype === null || prototype === Object.prototype || getPrototypeOf(prototype) === null) && // Treat any genuine (non-Object.prototype-polluted) Symbol.toStringTag or // Symbol.iterator as evidence the value is a tagged/iterable type rather // than a plain object, while ignoring keys injected onto Object.prototype. !hasOwnInPrototypeChain(val, toStringTag) && !hasOwnInPrototypeChain(val, iterator) ); }; /** * Determine if a value is an empty object (safely handles Buffers) * * @param {*} val The value to test * * @returns {boolean} True if value is an empty object, otherwise false */ const isEmptyObject = (val) => { // Early return for non-objects or Buffers to prevent RangeError if (!isObject(val) || isBuffer(val)) { return false; } try { return Object.keys(val).length === 0 && Object.getPrototypeOf(val) === Object.prototype; } catch (e) { // Fallback for any other objects that might cause RangeError with Object.keys() return false; } }; /** * Determine if a value is a Date * * @param {*} val The value to test * * @returns {boolean} True if value is a Date, otherwise false */ const isDate = kindOfTest('Date'); /** * Determine if a value is a File * * @param {*} val The value to test * * @returns {boolean} True if value is a File, otherwise false */ const isFile = kindOfTest('File'); /** * Determine if a value is a React Native Blob * React Native "blob": an object with a `uri` attribute. Optionally, it can * also have a `name` and `type` attribute to specify filename and content type * * @see https://github.com/facebook/react-native/blob/26684cf3adf4094eb6c405d345a75bf8c7c0bf88/Libraries/Network/FormData.js#L68-L71 * * @param {*} value The value to test * * @returns {boolean} True if value is a React Native Blob, otherwise false */ const isReactNativeBlob = (value) => { return !!(value && typeof value.uri !== 'undefined'); }; /** * Determine if environment is React Native * ReactNative `FormData` has a non-standard `getParts()` method * * @param {*} formData The formData to test * * @returns {boolean} True if environment is React Native, otherwise false */ const isReactNative = (formData) => formData && typeof formData.getParts !== 'undefined'; /** * Determine if a value is a Blob * * @param {*} val The value to test * * @returns {boolean} True if value is a Blob, otherwise false */ const isBlob = kindOfTest('Blob'); /** * Determine if a value is a FileList * * @param {*} val The value to test * * @returns {boolean} True if value is a FileList, otherwise false */ const isFileList = kindOfTest('FileList'); /** * Determine if a value is a Stream * * @param {*} val The value to test * * @returns {boolean} True if value is a Stream, otherwise false */ const isStream = (val) => isObject(val) && isFunction(val.pipe); /** * Determine if a value is a FormData * * @param {*} thing The value to test * * @returns {boolean} True if value is an FormData, otherwise false */ function getGlobal() { if (typeof globalThis !== 'undefined') return globalThis; if (typeof self !== 'undefined') return self; if (typeof window !== 'undefined') return window; if (typeof global !== 'undefined') return global; return {}; } const G = getGlobal(); const FormDataCtor = typeof G.FormData !== 'undefined' ? G.FormData : undefined; const isFormData = (thing) => { if (!thing) return false; if (FormDataCtor && thing instanceof FormDataCtor) return true; // Reject plain objects inheriting directly from Object.prototype so prototype-pollution gadgets can't spoof FormData. const proto = getPrototypeOf(thing); if (!proto || proto === Object.prototype) return false; if (!isFunction(thing.append)) return false; const kind = kindOf(thing); return ( kind === 'formdata' || // detect form-data instance (kind === 'object' && isFunction(thing.toString) && thing.toString() === '[object FormData]') ); }; /** * Determine if a value is a URLSearchParams object * * @param {*} val The value to test * * @returns {boolean} True if value is a URLSearchParams object, otherwise false */ const isURLSearchParams = kindOfTest('URLSearchParams'); const [isReadableStream, isRequest, isResponse, isHeaders] = [ 'ReadableStream', 'Request', 'Response', 'Headers', ].map(kindOfTest); /** * Trim excess whitespace off the beginning and end of a string * * @param {String} str The String to trim * * @returns {String} The String freed of excess whitespace */ const trim = (str) => { return str.trim ? str.trim() : str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); }; /** * Iterate over an Array or an Object invoking a function for each item. * * If `obj` is an Array callback will be called passing * the value, index, and complete array for each item. * * If 'obj' is an Object callback will be called passing * the value, key, and complete object for each property. * * @param {Object|Array} obj The object to iterate * @param {Function} fn The callback to invoke for each item * * @param {Object} [options] * @param {Boolean} [options.allOwnKeys = false] * @returns {any} */ function forEach(obj, fn, { allOwnKeys = false } = {}) { // Don't bother if no value provided if (obj === null || typeof obj === 'undefined') { return; } let i; let l; // Force an array if not already something iterable if (typeof obj !== 'object') { /*eslint no-param-reassign:0*/ obj = [obj]; } if (isArray(obj)) { // Iterate over array values for (i = 0, l = obj.length; i < l; i++) { fn.call(null, obj[i], i, obj); } } else { // Buffer check if (isBuffer(obj)) { return; } // Iterate over object keys const keys = allOwnKeys ? Object.getOwnPropertyNames(obj) : Object.keys(obj); const len = keys.length; let key; for (i = 0; i < len; i++) { key = keys[i]; fn.call(null, obj[key], key, obj); } } } /** * Finds a key in an object, case-insensitive, returning the actual key name. * Returns null if the object is a Buffer or if no match is found. * * @param {Object} obj - The object to search. * @param {string} key - The key to find (case-insensitive). * @returns {?string} The actual key name if found, otherwise null. */ function findKey(obj, key) { if (isBuffer(obj)) { return null; } key = key.toLowerCase(); const keys = Object.keys(obj); let i = keys.length; let _key; while (i-- > 0) { _key = keys[i]; if (key === _key.toLowerCase()) { return _key; } } return null; } const _global = (() => { /*eslint no-undef:0*/ if (typeof globalThis !== 'undefined') return globalThis; return typeof self !== 'undefined' ? self : typeof window !== 'undefined' ? window : global; })(); const isContextDefined = (context) => !isUndefined(context) && context !== _global; /** * Accepts varargs expecting each argument to be an object, then * immutably merges the properties of each object and returns result. * * When multiple objects contain the same key the later object in * the arguments list will take precedence. * * Example: * * ```js * const result = merge({foo: 123}, {foo: 456}); * console.log(result.foo); // outputs 456 * ``` * * @param {Object} obj1 Object to merge * * @returns {Object} Result of all merge properties */ function merge(...objs) { const { caseless, skipUndefined } = (isContextDefined(this) && this) || {}; const result = {}; const assignValue = (val, key) => { // Skip dangerous property names to prevent prototype pollution if (key === '__proto__' || key === 'constructor' || key === 'prototype') { return; } // findKey lowercases the key, so caseless lookup only applies to strings — // symbol keys are identity-matched. const targetKey = (caseless && typeof key === 'string' && findKey(result, key)) || key; // Read via own-prop only — a bare `result[targetKey]` walks the prototype // chain, so a polluted Object.prototype value could surface here and get // copied into the merged result. const existing = hasOwnProperty(result, targetKey) ? result[targetKey] : undefined; if (isPlainObject(existing) && isPlainObject(val)) { result[targetKey] = merge(existing, val); } else if (isPlainObject(val)) { result[targetKey] = merge({}, val); } else if (isArray(val)) { result[targetKey] = val.slice(); } else if (!skipUndefined || !isUndefined(val)) { result[targetKey] = val; } }; for (let i = 0, l = objs.length; i < l; i++) { const source = objs[i]; if (!source || isBuffer(source)) { continue; } forEach(source, assignValue); if (typeof source !== 'object' || isArray(source)) { continue; } const symbols = Object.getOwnPropertySymbols(source); for (let j = 0; j < symbols.length; j++) { const symbol = symbols[j]; if (propertyIsEnumerable.call(source, symbol)) { assignValue(source[symbol], symbol); } } } return result; } /** * Extends object a by mutably adding to it the properties of object b. * * @param {Object} a The object to be extended * @param {Object} b The object to copy properties from * @param {Object} thisArg The object to bind function to * * @param {Object} [options] * @param {Boolean} [options.allOwnKeys] * @returns {Object} The resulting value of object a */ const extend = (a, b, thisArg, { allOwnKeys } = {}) => { forEach( b, (val, key) => { if (thisArg && isFunction(val)) { Object.defineProperty(a, key, { // Null-proto descriptor so a polluted Object.prototype.get cannot // hijack defineProperty's accessor-vs-data resolution. __proto__: null, value: bind(val, thisArg), writable: true, enumerable: true, configurable: true, }); } else { Object.defineProperty(a, key, { __proto__: null, value: val, writable: true, enumerable: true, configurable: true, }); } }, { allOwnKeys } ); return a; }; /** * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM) * * @param {string} content with BOM * * @returns {string} content value without BOM */ const stripBOM = (content) => { if (content.charCodeAt(0) === 0xfeff) { content = content.slice(1); } return content; }; /** * Inherit the prototype methods from one constructor into another * @param {function} constructor * @param {function} superConstructor * @param {object} [props] * @param {object} [descriptors] * * @returns {void} */ const inherits = (constructor, superConstructor, props, descriptors) => { constructor.prototype = Object.create(superConstructor.prototype, descriptors); Object.defineProperty(constructor.prototype, 'constructor', { __proto__: null, value: constructor, writable: true, enumerable: false, configurable: true, }); Object.defineProperty(constructor, 'super', { __proto__: null, value: superConstructor.prototype, }); props && Object.assign(constructor.prototype, props); }; /** * Resolve object with deep prototype chain to a flat object * @param {Object} sourceObj source object * @param {Object} [destObj] * @param {Function|Boolean} [filter] * @param {Function} [propFilter] * * @returns {Object} */ const toFlatObject = (sourceObj, destObj, filter, propFilter) => { let props; let i; let prop; const merged = {}; destObj = destObj || {}; // eslint-disable-next-line no-eq-null,eqeqeq if (sourceObj == null) return destObj; do { props = Object.getOwnPropertyNames(sourceObj); i = props.length; while (i-- > 0) { prop = props[i]; if ((!propFilter || propFilter(prop, sourceObj, destObj)) && !merged[prop]) { destObj[prop] = sourceObj[prop]; merged[prop] = true; } } sourceObj = filter !== false && getPrototypeOf(sourceObj); } while (sourceObj && (!filter || filter(sourceObj, destObj)) && sourceObj !== Object.prototype); return destObj; }; /** * Determines whether a string ends with the characters of a specified string * * @param {String} str * @param {String} searchString * @param {Number} [position= 0] * * @returns {boolean} */ const endsWith = (str, searchString, position) => { str = String(str); if (position === undefined || position > str.length) { position = str.length; } position -= searchString.length; const lastIndex = str.indexOf(searchString, position); return lastIndex !== -1 && lastIndex === position; }; /** * Returns new array from array like object or null if failed * * @param {*} [thing] * * @returns {?Array} */ const toArray = (thing) => { if (!thing) return null; if (isArray(thing)) return thing; let i = thing.length; if (!isNumber(i)) return null; const arr = new Array(i); while (i-- > 0) { arr[i] = thing[i]; } return arr; }; /** * Checking if the Uint8Array exists and if it does, it returns a function that checks if the * thing passed in is an instance of Uint8Array * * @param {TypedArray} * * @returns {Array} */ // eslint-disable-next-line func-names const isTypedArray = ((TypedArray) => { // eslint-disable-next-line func-names return (thing) => { return TypedArray && thing instanceof TypedArray; }; })(typeof Uint8Array !== 'undefined' && getPrototypeOf(Uint8Array)); /** * For each entry in the object, call the function with the key and value. * * @param {Object} obj - The object to iterate over. * @param {Function} fn - The function to call for each entry. * * @returns {void} */ const forEachEntry = (obj, fn) => { const generator = obj && obj[iterator]; const _iterator = generator.call(obj); let result; while ((result = _iterator.next()) && !result.done) { const pair = result.value; fn.call(obj, pair[0], pair[1]); } }; /** * It takes a regular expression and a string, and returns an array of all the matches * * @param {string} regExp - The regular expression to match against. * @param {string} str - The string to search. * * @returns {Array} */ const matchAll = (regExp, str) => { let matches; const arr = []; while ((matches = regExp.exec(str)) !== null) { arr.push(matches); } return arr; }; /* Checking if the kindOfTest function returns true when passed an HTMLFormElement. */ const isHTMLForm = kindOfTest('HTMLFormElement'); const toCamelCase = (str) => { return str.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g, function replacer(m, p1, p2) { return p1.toUpperCase() + p2; }); }; const { propertyIsEnumerable } = Object.prototype; /** * Determine if a value is a RegExp object * * @param {*} val The value to test * * @returns {boolean} True if value is a RegExp object, otherwise false */ const isRegExp = kindOfTest('RegExp'); const reduceDescriptors = (obj, reducer) => { const descriptors = Object.getOwnPropertyDescriptors(obj); const reducedDescriptors = {}; forEach(descriptors, (descriptor, name) => { let ret; if ((ret = reducer(descriptor, name, obj)) !== false) { reducedDescriptors[name] = ret || descriptor; } }); Object.defineProperties(obj, reducedDescriptors); }; /** * Makes all methods read-only * @param {Object} obj */ const freezeMethods = (obj) => { reduceDescriptors(obj, (descriptor, name) => { // skip restricted props in strict mode if (isFunction(obj) && ['arguments', 'caller', 'callee'].includes(name)) { return false; } const value = obj[name]; if (!isFunction(value)) return; descriptor.enumerable = false; if ('writable' in descriptor) { descriptor.writable = false; return; } if (!descriptor.set) { descriptor.set = () => { throw Error("Can not rewrite read-only method '" + name + "'"); }; } }); }; /** * Converts an array or a delimited string into an object set with values as keys and true as values. * Useful for fast membership checks. * * @param {Array|string} arrayOrString - The array or string to convert. * @param {string} delimiter - The delimiter to use if input is a string. * @returns {Object} An object with keys from the array or string, values set to true. */ const toObjectSet = (arrayOrString, delimiter) => { const obj = {}; const define = (arr) => { arr.forEach((value) => { obj[value] = true; }); }; isArray(arrayOrString) ? define(arrayOrString) : define(String(arrayOrString).split(delimiter)); return obj; }; const noop = () => {}; const toFiniteNumber = (value, defaultValue) => { return value != null && Number.isFinite((value = +value)) ? value : defaultValue; }; /** * If the thing is a FormData object, return true, otherwise return false. * * @param {unknown} thing - The thing to check. * * @returns {boolean} */ function isSpecCompliantForm(thing) { return !!( thing && isFunction(thing.append) && thing[toStringTag] === 'FormData' && thing[iterator] ); } /** * Recursively converts an object to a JSON-compatible object, handling circular references and Buffers. * * @param {Object} obj - The object to convert. * @returns {Object} The JSON-compatible object. */ const toJSONObject = (obj) => { const visited = new WeakSet(); const visit = (source) => { if (isObject(source)) { if (visited.has(source)) { return; } //Buffer check if (isBuffer(source)) { return source; } if (!('toJSON' in source)) { // add-on descent / delete-on-ascent: preserves path semantics, so DAG nodes serialise at every occurrence (see #7230). visited.add(source); const target = isArray(source) ? [] : {}; forEach(source, (value, key) => { const reducedValue = visit(value); !isUndefined(reducedValue) && (target[key] = reducedValue); }); visited.delete(source); return target; } } return source; }; return visit(obj); }; /** * Determines if a value is an async function. * * @param {*} thing - The value to test. * @returns {boolean} True if value is an async function, otherwise false. */ const isAsyncFn = kindOfTest('AsyncFunction'); /** * Determines if a value is thenable (has then and catch methods). * * @param {*} thing - The value to test. * @returns {boolean} True if value is thenable, otherwise false. */ const isThenable = (thing) => thing && (isObject(thing) || isFunction(thing)) && isFunction(thing.then) && isFunction(thing.catch); // original code // https://github.com/DigitalBrainJS/AxiosPromise/blob/16deab13710ec09779922131f3fa5954320f83ab/lib/utils.js#L11-L34 /** * Provides a cross-platform setImmediate implementation. * Uses native setImmediate if available, otherwise falls back to postMessage or setTimeout. * * @param {boolean} setImmediateSupported - Whether setImmediate is supported. * @param {boolean} postMessageSupported - Whether postMessage is supported. * @returns {Function} A function to schedule a callback asynchronously. */ const _setImmediate = ((setImmediateSupported, postMessageSupported) => { if (setImmediateSupported) { return setImmediate; } return postMessageSupported ? ((token, callbacks) => { _global.addEventListener( 'message', ({ source, data }) => { if (source === _global && data === token) { callbacks.length && callbacks.shift()(); } }, false ); return (cb) => { callbacks.push(cb); _global.postMessage(token, '*'); }; })(`axios@${Math.random()}`, []) : (cb) => setTimeout(cb); })(typeof setImmediate === 'function', isFunction(_global.postMessage)); /** * Schedules a microtask or asynchronous callback as soon as possible. * Uses queueMicrotask if available, otherwise falls back to process.nextTick or _setImmediate. * * @type {Function} */ const asap = typeof queueMicrotask !== 'undefined' ? queueMicrotask.bind(_global) : (typeof process !== 'undefined' && process.nextTick) || _setImmediate; // ********************* const isIterable = (thing) => thing != null && isFunction(thing[iterator]); /** * Determine if a value is iterable via an iterator that is NOT sourced solely * from a polluted Object.prototype. Use this instead of `isIterable` whenever * the iterable comes from untrusted input (e.g. user-supplied header sources), * so `Object.prototype[Symbol.iterator] = ...` cannot turn an ordinary object * into an attacker-controlled entries iterator. * * @param {*} thing The value to test * * @returns {boolean} True if value has a non-polluted iterator */ const isSafeIterable = (thing) => thing != null && hasOwnInPrototypeChain(thing, iterator) && isIterable(thing); export default { isArray, isArrayBuffer, isBuffer, isFormData, isArrayBufferView, isString, isNumber, isBoolean, isObject, isPlainObject, isEmptyObject, isReadableStream, isRequest, isResponse, isHeaders, isUndefined, isDate, isFile, isReactNativeBlob, isReactNative, isBlob, isRegExp, isFunction, isStream, isURLSearchParams, isTypedArray, isFileList, forEach, merge, extend, trim, stripBOM, inherits, toFlatObject, kindOf, kindOfTest, endsWith, toArray, forEachEntry, matchAll, isHTMLForm, hasOwnProperty, hasOwnProp: hasOwnProperty, // an alias to avoid ESLint no-prototype-builtins detection hasOwnInPrototypeChain, getSafeProp, reduceDescriptors, freezeMethods, toObjectSet, toCamelCase, noop, toFiniteNumber, findKey, global: _global, isContextDefined, isSpecCompliantForm, toJSONObject, isAsyncFn, isThenable, setImmediate: _setImmediate, asap, isIterable, isSafeIterable, }; axios-axios-2d06f96/package-lock.json000066400000000000000000012714071521272452000175500ustar00rootroot00000000000000{ "name": "axios", "version": "1.18.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "axios", "version": "1.18.0", "license": "MIT", "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.5", "https-proxy-agent": "^5.0.1", "proxy-from-env": "^2.1.0" }, "devDependencies": { "@babel/core": "^7.29.0", "@babel/preset-env": "^7.29.5", "@commitlint/cli": "^21.0.1", "@commitlint/config-conventional": "^21.0.1", "@eslint/js": "^10.0.1", "@rollup/plugin-alias": "^6.0.0", "@rollup/plugin-babel": "^7.0.0", "@rollup/plugin-commonjs": "^29.0.2", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.3", "@rollup/plugin-terser": "^1.0.0", "@vitest/browser": "^4.1.7", "@vitest/browser-playwright": "^4.1.7", "abortcontroller-polyfill": "^1.7.8", "acorn": "^8.16.0", "body-parser": "^2.2.2", "chalk": "^5.6.2", "cross-env": "^10.1.0", "dev-null": "^0.1.1", "eslint": "^10.4.0", "express": "^5.2.1", "formdata-node": "^6.0.3", "formidable": "^3.5.4", "fs-extra": "^11.3.4", "get-stream": "^9.0.1", "globals": "^17.6.0", "gulp": "^5.0.1", "husky": "^9.1.7", "lint-staged": "^17.0.5", "minimist": "^1.2.8", "multer": "^2.1.1", "playwright": "^1.60.0", "prettier": "^3.8.3", "rollup": "^4.60.4", "rollup-plugin-bundle-size": "^1.0.3", "selfsigned": "^5.5.0", "stream-throttle": "^0.1.3", "typescript": "^5.9.3", "vitest": "^4.1.7" } }, "node_modules/@babel/code-frame": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.7", "@babel/helper-compilation-targets": "^7.29.7", "@babel/helper-module-transforms": "^7.29.7", "@babel/helpers": "^7.29.7", "@babel/parser": "^7.29.7", "@babel/template": "^7.29.7", "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/babel" } }, "node_modules/@babel/generator": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.29.7", "@babel/types": "^7.29.7", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-annotate-as-pure": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.29.7.tgz", "integrity": "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==", "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", "dev": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.29.7", "@babel/helper-validator-option": "^7.29.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-create-class-features-plugin": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.7.tgz", "integrity": "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-member-expression-to-functions": "^7.29.7", "@babel/helper-optimise-call-expression": "^7.29.7", "@babel/helper-replace-supers": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", "@babel/traverse": "^7.29.7", "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-create-regexp-features-plugin": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.29.7.tgz", "integrity": "sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "regexpu-core": "^6.3.1", "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-define-polyfill-provider": { "version": "0.6.7", "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.7.tgz", "integrity": "sha512-6Fqi8MtQ/PweQ9xvux65emkLQ83uB+qAVtfHkC9UodyHMIZdxNI01HjLCLUtybElp2KY2XNE0nOgyP1E1vXw9w==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "debug": "^4.4.3", "lodash.debounce": "^4.0.8", "resolve": "^1.22.11" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/@babel/helper-globals": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.29.7.tgz", "integrity": "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==", "dev": true, "license": "MIT", "dependencies": { "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", "dev": true, "license": "MIT", "dependencies": { "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7", "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-optimise-call-expression": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.29.7.tgz", "integrity": "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==", "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-remap-async-to-generator": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.29.7.tgz", "integrity": "sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-wrap-function": "^7.29.7", "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-replace-supers": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.29.7.tgz", "integrity": "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-member-expression-to-functions": "^7.29.7", "@babel/helper-optimise-call-expression": "^7.29.7", "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.29.7.tgz", "integrity": "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-wrap-function": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.29.7.tgz", "integrity": "sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==", "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.29.7", "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.29.7", "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.29.7" }, "bin": { "parser": "bin/babel-parser.js" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.29.7.tgz", "integrity": "sha512-j8SrR0zLZrRsC09DlszEx8FpMiwukKffYXMK0d5LmOglO7vGG6sz/BR/20yHqWH+Lnn31JTt2PE3hIWNgM2J6w==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.29.7.tgz", "integrity": "sha512-r8j8escF+U2FUHo0KOhPUdMzUO+jp9fInva6+ACVAF3Y97Ev+5iNZwiqTghmzNeWwDkOPlYuTcfb1vDaoZKmAQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.29.7.tgz", "integrity": "sha512-GE1TFSiuFeGsCxmYXZl8HwoPrVlwe4rHPFE8weieGKZqnDORK+Ar3vgWMgW+AOxQ6/2TgLSKx9p6W7O4rC6qgQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.7.tgz", "integrity": "sha512-oBNVCvnO5tND+xSopWvV8WNGfpTfgP4Zr/YXXSj8zfmcPktp5Ku/aZlsIowgSD4fjmgHn6sGmB9APVsU5zOdhA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.29.7.tgz", "integrity": "sha512-QQt9qKHZ2sg/kivaLr7lnQr8HVrQDdBNSfCsTjiDxRuX/K5ORyKq+Bu8Xr0cDE3Dfkv0cw28Ve0EKyKMvulkOw==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", "@babel/plugin-transform-optional-chaining": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.13.0" } }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.29.7.tgz", "integrity": "sha512-pn6QacGLgvCcwc+syUhKE/qSjV2D1IHDB84RNxWYSt1mW3K/SCtjinZ2p0cETJxAWBjPy3K/1lHwG5BjjPxNlw==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/plugin-proposal-private-property-in-object": { "version": "7.21.0-placeholder-for-preset-env.2", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-import-assertions": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.29.7.tgz", "integrity": "sha512-/An1OCBN93thpBAGyfsK2pcf0jvju1SAtKkL2Ny++B5Sy6sqgzXDQH1cZxWbF96Wuk+bn41MDA9bLd4VVAw6rw==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-import-attributes": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz", "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-syntax-unicode-sets-regex": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/plugin-transform-arrow-functions": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.29.7.tgz", "integrity": "sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-async-generator-functions": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.7.tgz", "integrity": "sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-remap-async-to-generator": "^7.29.7", "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-async-to-generator": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.29.7.tgz", "integrity": "sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-remap-async-to-generator": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.29.7.tgz", "integrity": "sha512-cUSmjh72N+rN4PrkFlN1dJwNCwjVp5d38/CQrEsFggkD10UiFlBFgdH3tv5dNsLuHY+3S8db2xCHjhZcv5WgvA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-block-scoping": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.29.7.tgz", "integrity": "sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-class-properties": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.29.7.tgz", "integrity": "sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-class-static-block": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.29.7.tgz", "integrity": "sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.12.0" } }, "node_modules/@babel/plugin-transform-classes": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.29.7.tgz", "integrity": "sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-compilation-targets": "^7.29.7", "@babel/helper-globals": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-replace-supers": "^7.29.7", "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-computed-properties": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.29.7.tgz", "integrity": "sha512-RK7/IyU5phpuCdBAuig5VkzG/EnbDaui5SQGdU9BFrHdV+mV4cUjLMQ9lJDjLNtWHsqtiefpGZUXQP2BiTYMsA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/template": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-destructuring": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.29.7.tgz", "integrity": "sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-dotall-regex": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.29.7.tgz", "integrity": "sha512-3qc18hsD2RdZiyJNDNc7HQpv6xbncwh8FYtxNFFzclSyh/trPD9KkVR9BDECUjDLvb7yJVF15GfYUuC+LMkkiQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-duplicate-keys": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.29.7.tgz", "integrity": "sha512-6IvRRriEMqnBwD6chtxdLpMYCHWEzN+oL5cyQtjykya19UgzbmKhxmhZgKC/LHxS2nYr9Q/qYPZ5Lr6jOL9+yQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.7.tgz", "integrity": "sha512-2wiIyo2BjtgU7HufSeDnL9L2O7zr8jmhFKuSr65VpRkUiRKRNpb0mdlk56+XPPKoIrfHqzbMuglDvZun0RISsA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/plugin-transform-dynamic-import": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.29.7.tgz", "integrity": "sha512-giOlEm/EFjfjr+te9NsdjkUo2v4f8rS/SXPumRVHAtbNcyNlvtREkU1dZzaIDclNpnaVhlCqRdFKhJBjBikzLg==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-explicit-resource-management": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.29.7.tgz", "integrity": "sha512-Rstj7coNz8sE+7Ju7ihpHLI564lsK5pUpNNlvptCIC/16E/S5hbl6n3kESPKdNRmqEWlpn5xpS5Q2dvXBsySLw==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/plugin-transform-destructuring": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-exponentiation-operator": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.29.7.tgz", "integrity": "sha512-zFpMOTLZBdW5LfObqcSbL6kefg4R4eLdmvS0wbN9M6D5Mym/sKm9toOoWyVOa+xDjvCnuWcHls2YonXwHvH3CQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-export-namespace-from": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.29.7.tgz", "integrity": "sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-for-of": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.29.7.tgz", "integrity": "sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-function-name": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.29.7.tgz", "integrity": "sha512-otRWaHXE6fbAGkePvaj/kvs3HsqXfPhlnzwSOlnFgbqCPMd975dW+4wZ00WFBt+/YlBGcJwNrARQTOJOb4ZrIg==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-json-strings": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.29.7.tgz", "integrity": "sha512-RRnE2+eon1rJAq8MnoF1b5kTpY1vU88twHcvcKMrsqP/jxIRqDVs9iJB5fqPuqyeFAW0wJo4MlUIPpQCq/aRsg==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-literals": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.29.7.tgz", "integrity": "sha512-DZ/oLP21ZuWx1vKqnoNv6/tvEK48AQOBRai40CX9dTjGluvT/YZCyY3rryDtyUqCEoyNroy5KKPwX2iQCiRvyw==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.29.7.tgz", "integrity": "sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-member-expression-literals": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.29.7.tgz", "integrity": "sha512-hl1kwFZCCiDyfH25Xmco9jTrkPgnS9pmOzSG7W5I4SaGbLeqKv417hcU2RKmaxoPEgsoJh7ZPOrnPGq99bHoUg==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-modules-amd": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.29.7.tgz", "integrity": "sha512-fxtQoH3m5ywUSIfaH0FGCzWu4McsYon5bD3K4XnskC7f+OyQMj7rsOMi4NvvmJ83WwBAg4UCe+ov4VZlqEvyew==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-modules-commonjs": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.29.7.tgz", "integrity": "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-modules-systemjs": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.7.tgz", "integrity": "sha512-TM2ZcQLoG2/y4HODiStCo10DibYhWhGWAwVv+EQKmG/7GFl0N+AAmUiXOMKM+aiJ9XBJ9AHVZBvTzMnJ2sM3cQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7", "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-modules-umd": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.29.7.tgz", "integrity": "sha512-B4UkaTK3QpgCwJnrxKfMPKdo92CN7OKXAlpAAnM3UPu0Q0lCCk57ylA9AJbRy2v8dDKOPAAWcoR6CMyeoHwRCA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.7.tgz", "integrity": "sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/plugin-transform-new-target": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.29.7.tgz", "integrity": "sha512-fEo41GmsOUhOBlw8ioo6zvjX5Xc2Lqkzlyfqbpsk3eB6TReV18uhxZ0esfEokVbY2+PVJAQHNKxER6lGrzNd3A==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.29.7.tgz", "integrity": "sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-numeric-separator": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.29.7.tgz", "integrity": "sha512-zR7fv/z14OjgHl4AgRtkDBvBMhIzCxqV/qN/2BCRC7LjFwvuzjYe7gDWxC4Wl/SNsLM6SE1IWvRPYMgSJaUvNw==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-object-rest-spread": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.29.7.tgz", "integrity": "sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/plugin-transform-destructuring": "^7.29.7", "@babel/plugin-transform-parameters": "^7.29.7", "@babel/traverse": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-object-super": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.29.7.tgz", "integrity": "sha512-Ea/diGcw0twB5IlZPO5sgET6fJsLJqPABqTuFWIR+iMPGPZJkATEIWx0wa+aEQ5UY1CBQyP/gkAiLEqn1vBiQA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-replace-supers": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-optional-catch-binding": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.29.7.tgz", "integrity": "sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-optional-chaining": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.29.7.tgz", "integrity": "sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-parameters": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.29.7.tgz", "integrity": "sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-private-methods": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.29.7.tgz", "integrity": "sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-private-property-in-object": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.29.7.tgz", "integrity": "sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-property-literals": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.29.7.tgz", "integrity": "sha512-bOMRLQuI0A5ZqHq3OWJ89/rXpJ/NJrbVhXiP4zwPGMs6kpcVsuTUNjwoE30K0Qm3mf48a/TnRYYD6vPNqcg6jA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-regenerator": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.7.tgz", "integrity": "sha512-rNNFV0DBAJp988xW2DOntfDoYn1eR8GGF5AT5vYc+rjyfaQkM242c9tZUHHPe7KYaiJizXPWhQTzzdbXySyhBw==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-regexp-modifiers": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.29.7.tgz", "integrity": "sha512-mB5Fs0VWrJ42ZCmc8114v60qetdaUVNkj9PmSZRmanCZM3S9hm0CFRLjRmYIsuXav14l2jvZ+4T8iiCGnhj3nQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/plugin-transform-reserved-words": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.29.7.tgz", "integrity": "sha512-5+YhdpVgmfSmwZyLMftfaiffLRMHjzIRHFHHLdibcSyJm2pasMrKHrO3Ptrt2DRshjvpgjEJJ1zVW14WPq/6QA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-shorthand-properties": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.29.7.tgz", "integrity": "sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-spread": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.29.7.tgz", "integrity": "sha512-/u5K1QWada7tbYNqTjMh96718g9NTwh9tfPJMsSmVsQwGT447FskV+KcfeXkXq2GWki4EM/MuTdmBec+hOuVTQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-sticky-regex": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.29.7.tgz", "integrity": "sha512-BCHzNYJGe9l7EpwwDBN/ztlL2NYFFq8hp9ddjtUEM9f2O7S7kKV/lL6Fwo7IF7NSkYhPK2vO+86nIGltA90MsA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-template-literals": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.29.7.tgz", "integrity": "sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-typeof-symbol": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.29.7.tgz", "integrity": "sha512-223mNGoTkBiTEWFoK+Q6Go3tueMRclO8vxxxxquNCYuNI4jWOofFKJRRDu6SDrB8Sgo1UEGW9T4GAQ8ZyRso1A==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-unicode-escapes": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.29.7.tgz", "integrity": "sha512-jCfXxSjf94lf4E0hKE0AByxF6F3/pVFqRdUUNkDJhsY0m1ZKjnN6ZYyMeHNpzflxb/0q5b7t3p+BE+SLF1WOtA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-unicode-property-regex": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.29.7.tgz", "integrity": "sha512-OgZ+zoAJgZLUCunsTRQ5LAjOywDv5zzZ2/hQ5aMw1pGXyY2rtE8/chXYUmu3AlVHKpm10KEdG9aMwbI/K76ZGw==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-unicode-regex": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.29.7.tgz", "integrity": "sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.29.7.tgz", "integrity": "sha512-BLOhLht9DOJwIxlmp91wHvkXv1lguuHS3/FwUO8HL1H0u8s4hR1gASVFyilu9iGtcTRYqjTZmlsFFeQletntEg==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "node_modules/@babel/preset-env": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.7.tgz", "integrity": "sha512-GYzX36n1nsciIb0uyH0GHwxwtNwPQIcpxSeiVLDtG/B7jB5xXgchnmL1f/jCX5o+pwnaDBtO60ONSJhEBJfxYA==", "dev": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.29.7", "@babel/helper-compilation-targets": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-validator-option": "^7.29.7", "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.29.7", "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.29.7", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.29.7", "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.7", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.29.7", "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.29.7", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-import-assertions": "^7.29.7", "@babel/plugin-syntax-import-attributes": "^7.29.7", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", "@babel/plugin-transform-arrow-functions": "^7.29.7", "@babel/plugin-transform-async-generator-functions": "^7.29.7", "@babel/plugin-transform-async-to-generator": "^7.29.7", "@babel/plugin-transform-block-scoped-functions": "^7.29.7", "@babel/plugin-transform-block-scoping": "^7.29.7", "@babel/plugin-transform-class-properties": "^7.29.7", "@babel/plugin-transform-class-static-block": "^7.29.7", "@babel/plugin-transform-classes": "^7.29.7", "@babel/plugin-transform-computed-properties": "^7.29.7", "@babel/plugin-transform-destructuring": "^7.29.7", "@babel/plugin-transform-dotall-regex": "^7.29.7", "@babel/plugin-transform-duplicate-keys": "^7.29.7", "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.7", "@babel/plugin-transform-dynamic-import": "^7.29.7", "@babel/plugin-transform-explicit-resource-management": "^7.29.7", "@babel/plugin-transform-exponentiation-operator": "^7.29.7", "@babel/plugin-transform-export-namespace-from": "^7.29.7", "@babel/plugin-transform-for-of": "^7.29.7", "@babel/plugin-transform-function-name": "^7.29.7", "@babel/plugin-transform-json-strings": "^7.29.7", "@babel/plugin-transform-literals": "^7.29.7", "@babel/plugin-transform-logical-assignment-operators": "^7.29.7", "@babel/plugin-transform-member-expression-literals": "^7.29.7", "@babel/plugin-transform-modules-amd": "^7.29.7", "@babel/plugin-transform-modules-commonjs": "^7.29.7", "@babel/plugin-transform-modules-systemjs": "^7.29.7", "@babel/plugin-transform-modules-umd": "^7.29.7", "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.7", "@babel/plugin-transform-new-target": "^7.29.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.29.7", "@babel/plugin-transform-numeric-separator": "^7.29.7", "@babel/plugin-transform-object-rest-spread": "^7.29.7", "@babel/plugin-transform-object-super": "^7.29.7", "@babel/plugin-transform-optional-catch-binding": "^7.29.7", "@babel/plugin-transform-optional-chaining": "^7.29.7", "@babel/plugin-transform-parameters": "^7.29.7", "@babel/plugin-transform-private-methods": "^7.29.7", "@babel/plugin-transform-private-property-in-object": "^7.29.7", "@babel/plugin-transform-property-literals": "^7.29.7", "@babel/plugin-transform-regenerator": "^7.29.7", "@babel/plugin-transform-regexp-modifiers": "^7.29.7", "@babel/plugin-transform-reserved-words": "^7.29.7", "@babel/plugin-transform-shorthand-properties": "^7.29.7", "@babel/plugin-transform-spread": "^7.29.7", "@babel/plugin-transform-sticky-regex": "^7.29.7", "@babel/plugin-transform-template-literals": "^7.29.7", "@babel/plugin-transform-typeof-symbol": "^7.29.7", "@babel/plugin-transform-unicode-escapes": "^7.29.7", "@babel/plugin-transform-unicode-property-regex": "^7.29.7", "@babel/plugin-transform-unicode-regex": "^7.29.7", "@babel/plugin-transform-unicode-sets-regex": "^7.29.7", "@babel/preset-modules": "0.1.6-no-external-plugins", "babel-plugin-polyfill-corejs2": "^0.4.15", "babel-plugin-polyfill-corejs3": "^0.14.0", "babel-plugin-polyfill-regenerator": "^0.6.6", "core-js-compat": "^3.48.0", "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "node_modules/@babel/preset-modules": { "version": "0.1.6-no-external-plugins", "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", "esutils": "^2.0.2" }, "peerDependencies": { "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, "node_modules/@babel/template": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/parser": "^7.29.7", "@babel/types": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/generator": "^7.29.7", "@babel/helper-globals": "^7.29.7", "@babel/parser": "^7.29.7", "@babel/template": "^7.29.7", "@babel/types": "^7.29.7", "debug": "^4.3.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/types": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@blazediff/core": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/@blazediff/core/-/core-1.9.1.tgz", "integrity": "sha512-ehg3jIkYKulZh+8om/O25vkvSsXXwC+skXmyA87FFx6A/45eqOkZsBltMw/TVteb0mloiGT8oGRTcjRAz66zaA==", "dev": true, "license": "MIT" }, "node_modules/@commitlint/cli": { "version": "21.0.2", "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-21.0.2.tgz", "integrity": "sha512-YMmfLbqBg+ZRvvmPhc+cilSQFrh/AgzVgCT1U/OifmUZEwPbvCtA8rN//YNaF9d5eoZphxVMGYtmwA2QgQORgg==", "dev": true, "license": "MIT", "dependencies": { "@commitlint/format": "^21.0.1", "@commitlint/lint": "^21.0.2", "@commitlint/load": "^21.0.2", "@commitlint/read": "^21.0.2", "@commitlint/types": "^21.0.1", "tinyexec": "^1.0.0", "yargs": "^18.0.0" }, "bin": { "commitlint": "cli.js" }, "engines": { "node": ">=22.12.0" } }, "node_modules/@commitlint/config-conventional": { "version": "21.0.2", "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-21.0.2.tgz", "integrity": "sha512-P/ZRhryQmkj0Z0dY9FOoRwe3xkwJyyAdtXwt01NT2kuZttcG2CNYp1q5Ci3u+nDT2jcbJRw2kt13Czl1qKNPfg==", "dev": true, "license": "MIT", "dependencies": { "@commitlint/types": "^21.0.1", "conventional-changelog-conventionalcommits": "^9.2.0" }, "engines": { "node": ">=22.12.0" } }, "node_modules/@commitlint/config-validator": { "version": "21.0.1", "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-21.0.1.tgz", "integrity": "sha512-Zd2UFdndeMMaW2O96HK0tdfT4gOImUvidMpAd/pws2zZ4m1nrAZ/9b/v2JYuE8fs86GpXv9F7LNaIuCIWhY+pA==", "dev": true, "license": "MIT", "dependencies": { "@commitlint/types": "^21.0.1", "ajv": "^8.11.0" }, "engines": { "node": ">=22.12.0" } }, "node_modules/@commitlint/ensure": { "version": "21.0.1", "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-21.0.1.tgz", "integrity": "sha512-jJ1037967wU7YN/xkv+iRlOBlmaOXPhPO5KQSqya6GyXzBlwuLzELBFao16DVg9dZyqmNrhewzwZ3SAibetHBQ==", "dev": true, "license": "MIT", "dependencies": { "@commitlint/types": "^21.0.1", "es-toolkit": "^1.46.0" }, "engines": { "node": ">=22.12.0" } }, "node_modules/@commitlint/execute-rule": { "version": "21.0.1", "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-21.0.1.tgz", "integrity": "sha512-RifH+FmImozKBE6mozhF4K3r2RRKP7SMi/Q/zLCmExtp5e05lhHOUYqGBlFBAGNHaZxU/WYw1XuugYK9jQzqnA==", "dev": true, "license": "MIT", "engines": { "node": ">=22.12.0" } }, "node_modules/@commitlint/format": { "version": "21.0.1", "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-21.0.1.tgz", "integrity": "sha512-ksmG2+cHGtuDPQQbhBbC4unwm444+6TiPw0d1bKf67hntgZqZ8E0g1MuYKUuyT5IH4IMmXZhKq22/Z3jBvtQIw==", "dev": true, "license": "MIT", "dependencies": { "@commitlint/types": "^21.0.1", "picocolors": "^1.1.1" }, "engines": { "node": ">=22.12.0" } }, "node_modules/@commitlint/is-ignored": { "version": "21.0.2", "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-21.0.2.tgz", "integrity": "sha512-H5z4t8PC9tUsmZ/o+EptM3Nq8sTFtskAShdcqxCoyzklW5eaVT5xbrDAET2uypzir9Vsj4ZZmBtyKjYe2XqgeQ==", "dev": true, "license": "MIT", "dependencies": { "@commitlint/types": "^21.0.1", "semver": "^7.6.0" }, "engines": { "node": ">=22.12.0" } }, "node_modules/@commitlint/is-ignored/node_modules/semver": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.3.tgz", "integrity": "sha512-wnilbGyMxzbY7dNOl7jpKbLSjcfeweJWU5j4+u5qW+6/wuGD9KzIGOyZnQVSBM9E7DtWaaH3CyHkppYrKYoxwg==", "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" }, "engines": { "node": ">=10" } }, "node_modules/@commitlint/lint": { "version": "21.0.2", "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-21.0.2.tgz", "integrity": "sha512-PnUmLYGeGLfW8oVatR9KpNxSHYAnJOEWlMZzfdeFOUq6WUrFx1fGQaWCWJqMoIll/xPM+GdfJV+tKHZVHhl0Fg==", "dev": true, "license": "MIT", "dependencies": { "@commitlint/is-ignored": "^21.0.2", "@commitlint/parse": "^21.0.2", "@commitlint/rules": "^21.0.2", "@commitlint/types": "^21.0.1" }, "engines": { "node": ">=22.12.0" } }, "node_modules/@commitlint/load": { "version": "21.0.2", "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-21.0.2.tgz", "integrity": "sha512-lwUE70hN0/qE/ZRROhbaX65ly/FF12DrqfReLCESo37M0OQCFAf2jRS+2tSCSORq+bm4Kdju7qNDj46uc1QzTA==", "dev": true, "license": "MIT", "dependencies": { "@commitlint/config-validator": "^21.0.1", "@commitlint/execute-rule": "^21.0.1", "@commitlint/resolve-extends": "^21.0.1", "@commitlint/types": "^21.0.1", "cosmiconfig": "^9.0.1", "cosmiconfig-typescript-loader": "^6.1.0", "es-toolkit": "^1.46.0", "is-plain-obj": "^4.1.0", "picocolors": "^1.1.1" }, "engines": { "node": ">=22.12.0" } }, "node_modules/@commitlint/message": { "version": "21.0.2", "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-21.0.2.tgz", "integrity": "sha512-5n4aqHGD/FNnom/D5L8i7cYtV+xjuXcBL832C3w9VglEsZzIsoHpJsvxzJ7cgiOsOdc/2jU4t5+7qMHh7GBX3g==", "dev": true, "license": "MIT", "engines": { "node": ">=22.12.0" } }, "node_modules/@commitlint/parse": { "version": "21.0.2", "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-21.0.2.tgz", "integrity": "sha512-QVZJhGHTm+oiuWyEKOCTQ0ZM3mfJ0eGWFeHuj7WzSKEth+UukcCHac9GD8pgdFlg/qGkFWOtyaNd1T8REgagaw==", "dev": true, "license": "MIT", "dependencies": { "@commitlint/types": "^21.0.1", "conventional-changelog-angular": "^8.2.0", "conventional-commits-parser": "^6.3.0" }, "engines": { "node": ">=22.12.0" } }, "node_modules/@commitlint/read": { "version": "21.0.2", "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-21.0.2.tgz", "integrity": "sha512-BtsrnLVycSSKf4Q0gMch4giCj5NNlmcbhc8ra5vONgGtP2IjRDo33bEFtr5Pm+2N+5fXGWb2MksWPrspPfdhdw==", "dev": true, "license": "MIT", "dependencies": { "@commitlint/top-level": "^21.0.2", "@commitlint/types": "^21.0.1", "git-raw-commits": "^5.0.0", "tinyexec": "^1.0.0" }, "engines": { "node": ">=22.12.0" } }, "node_modules/@commitlint/resolve-extends": { "version": "21.0.1", "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-21.0.1.tgz", "integrity": "sha512-0DhjYWL6uYrY16Efa032fYk3woGJDU4AGWiG1XXltT9AMUNYKyb5cIZU2ivbaMZ3+kKFqUjikD2cjh66Sbh/Sg==", "dev": true, "license": "MIT", "dependencies": { "@commitlint/config-validator": "^21.0.1", "@commitlint/types": "^21.0.1", "es-toolkit": "^1.46.0", "global-directory": "^5.0.0", "resolve-from": "^5.0.0" }, "engines": { "node": ">=22.12.0" } }, "node_modules/@commitlint/rules": { "version": "21.0.2", "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-21.0.2.tgz", "integrity": "sha512-k6tQ69Td7t2qUSIbik8D3TL1q3ZJpkEbV+yLogDzCRAdOxJm4ndhtBNREsLA1/puRfWvzS9eioF2w43WT+hHgQ==", "dev": true, "license": "MIT", "dependencies": { "@commitlint/ensure": "^21.0.1", "@commitlint/message": "^21.0.2", "@commitlint/to-lines": "^21.0.1", "@commitlint/types": "^21.0.1" }, "engines": { "node": ">=22.12.0" } }, "node_modules/@commitlint/to-lines": { "version": "21.0.1", "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-21.0.1.tgz", "integrity": "sha512-bd1BFII7p1EQZre9Kaj+kKaMFP3cFCdt21K7DItVux9XP5WjLgJ0/Uy1pJJh9aPwVJ6SKg62PxqlZaHI8hQAXw==", "dev": true, "license": "MIT", "engines": { "node": ">=22.12.0" } }, "node_modules/@commitlint/top-level": { "version": "21.0.2", "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-21.0.2.tgz", "integrity": "sha512-s9KKM+e+mXgFeIh4n7KmOGAVT3mkJ3Fp1bBYHIK5pjeUwlEMzp/tZfb5u0Poa680AsQTXMEMRxZi1vQ9m2X5ug==", "dev": true, "license": "MIT", "dependencies": { "escalade": "^3.2.0" }, "engines": { "node": ">=22.12.0" } }, "node_modules/@commitlint/types": { "version": "21.0.1", "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-21.0.1.tgz", "integrity": "sha512-4u7w8jcoCUFWhjWnASYzZHAP34OqOtuFBN87nQmFvqda03YU0T6z+yB4w0gSAMpekiRqqGk5rt+qSlW+a2vSEg==", "dev": true, "license": "MIT", "dependencies": { "conventional-commits-parser": "^6.3.0", "picocolors": "^1.1.1" }, "engines": { "node": ">=22.12.0" } }, "node_modules/@conventional-changelog/git-client": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/@conventional-changelog/git-client/-/git-client-2.7.0.tgz", "integrity": "sha512-j7A8/LBEQ+3rugMzPXoKYzyUPpw/0CBQCyvtTR7Lmu4olG4yRC/Tfkq79Mr3yuPs0SUitlO2HwGP3gitMJnRFw==", "dev": true, "license": "MIT", "dependencies": { "@simple-libs/child-process-utils": "^1.0.0", "@simple-libs/stream-utils": "^1.2.0", "semver": "^7.5.2" }, "engines": { "node": ">=18" }, "peerDependencies": { "conventional-commits-filter": "^5.0.0", "conventional-commits-parser": "^6.4.0" }, "peerDependenciesMeta": { "conventional-commits-filter": { "optional": true }, "conventional-commits-parser": { "optional": true } } }, "node_modules/@conventional-changelog/git-client/node_modules/semver": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.3.tgz", "integrity": "sha512-wnilbGyMxzbY7dNOl7jpKbLSjcfeweJWU5j4+u5qW+6/wuGD9KzIGOyZnQVSBM9E7DtWaaH3CyHkppYrKYoxwg==", "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" }, "engines": { "node": ">=10" } }, "node_modules/@emnapi/core": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", "dev": true, "license": "MIT", "optional": true, "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "node_modules/@emnapi/runtime": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", "dev": true, "license": "MIT", "optional": true, "dependencies": { "tslib": "^2.4.0" } }, "node_modules/@emnapi/wasi-threads": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", "dev": true, "license": "MIT", "optional": true, "dependencies": { "tslib": "^2.4.0" } }, "node_modules/@epic-web/invariant": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz", "integrity": "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==", "dev": true, "license": "MIT" }, "node_modules/@eslint-community/eslint-utils": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/eslint" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/@eslint-community/regexpp": { "version": "4.12.2", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/config-array": { "version": "0.23.5", "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", "dev": true, "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^3.0.5", "debug": "^4.3.1", "minimatch": "^10.2.4" }, "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/config-helpers": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.6.0.tgz", "integrity": "sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA==", "dev": true, "license": "Apache-2.0", "dependencies": { "@eslint/core": "^1.2.1" }, "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/core": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" }, "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/js": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz", "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==", "dev": true, "license": "MIT", "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://eslint.org/donate" }, "peerDependencies": { "eslint": "^10.0.0" }, "peerDependenciesMeta": { "eslint": { "optional": true } } }, "node_modules/@eslint/object-schema": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", "dev": true, "license": "Apache-2.0", "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@eslint/plugin-kit": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz", "integrity": "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==", "dev": true, "license": "Apache-2.0", "dependencies": { "@eslint/core": "^1.2.1", "levn": "^0.4.1" }, "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" } }, "node_modules/@gulpjs/messages": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@gulpjs/messages/-/messages-1.1.0.tgz", "integrity": "sha512-Ys9sazDatyTgZVb4xPlDufLweJ/Os2uHWOv+Caxvy2O85JcnT4M3vc73bi8pdLWlv3fdWQz3pdI9tVwo8rQQSg==", "dev": true, "license": "MIT", "engines": { "node": ">=10.13.0" } }, "node_modules/@gulpjs/to-absolute-glob": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@gulpjs/to-absolute-glob/-/to-absolute-glob-4.0.0.tgz", "integrity": "sha512-kjotm7XJrJ6v+7knhPaRgaT6q8F8K2jiafwYdNHLzmV0uGLuZY43FK6smNSHUPrhq5kX2slCUy+RGG/xGqmIKA==", "dev": true, "license": "MIT", "dependencies": { "is-negated-glob": "^1.0.0" }, "engines": { "node": ">=10.13.0" } }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, "license": "Apache-2.0", "engines": { "node": ">=18.18.0" } }, "node_modules/@humanfs/node": { "version": "0.16.7", "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" }, "engines": { "node": ">=18.18.0" } }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, "license": "Apache-2.0", "engines": { "node": ">=12.22" }, "funding": { "type": "github", "url": "https://github.com/sponsors/nzakas" } }, "node_modules/@humanwhocodes/retry": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, "license": "Apache-2.0", "engines": { "node": ">=18.18" }, "funding": { "type": "github", "url": "https://github.com/sponsors/nzakas" } }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "node_modules/@jridgewell/remapping": { "version": "2.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/source-map": { "version": "0.3.11", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.31", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@napi-rs/wasm-runtime": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", "dev": true, "license": "MIT", "optional": true, "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "funding": { "type": "github", "url": "https://github.com/sponsors/Brooooooklyn" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "node_modules/@noble/hashes": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", "dev": true, "license": "MIT", "engines": { "node": "^14.21.3 || >=16" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@oxc-project/types": { "version": "0.130.0", "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.130.0.tgz", "integrity": "sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==", "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/Boshen" } }, "node_modules/@paralleldrive/cuid2": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz", "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==", "dev": true, "license": "MIT", "dependencies": { "@noble/hashes": "^1.1.5" } }, "node_modules/@peculiar/asn1-cms": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.6.1.tgz", "integrity": "sha512-vdG4fBF6Lkirkcl53q6eOdn3XYKt+kJTG59edgRZORlg/3atWWEReRCx5rYE1ZzTTX6vLK5zDMjHh7vbrcXGtw==", "dev": true, "license": "MIT", "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.1", "@peculiar/asn1-x509-attr": "^2.6.1", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "node_modules/@peculiar/asn1-csr": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.6.1.tgz", "integrity": "sha512-WRWnKfIocHyzFYQTka8O/tXCiBquAPSrRjXbOkHbO4qdmS6loffCEGs+rby6WxxGdJCuunnhS2duHURhjyio6w==", "dev": true, "license": "MIT", "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.1", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "node_modules/@peculiar/asn1-ecc": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.6.1.tgz", "integrity": "sha512-+Vqw8WFxrtDIN5ehUdvlN2m73exS2JVG0UAyfVB31gIfor3zWEAQPD+K9ydCxaj3MLen9k0JhKpu9LqviuCE1g==", "dev": true, "license": "MIT", "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.1", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "node_modules/@peculiar/asn1-pfx": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.6.1.tgz", "integrity": "sha512-nB5jVQy3MAAWvq0KY0R2JUZG8bO/bTLpnwyOzXyEh/e54ynGTatAR+csOnXkkVD9AFZ2uL8Z7EV918+qB1qDvw==", "dev": true, "license": "MIT", "dependencies": { "@peculiar/asn1-cms": "^2.6.1", "@peculiar/asn1-pkcs8": "^2.6.1", "@peculiar/asn1-rsa": "^2.6.1", "@peculiar/asn1-schema": "^2.6.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "node_modules/@peculiar/asn1-pkcs8": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.6.1.tgz", "integrity": "sha512-JB5iQ9Izn5yGMw3ZG4Nw3Xn/hb/G38GYF3lf7WmJb8JZUydhVGEjK/ZlFSWhnlB7K/4oqEs8HnfFIKklhR58Tw==", "dev": true, "license": "MIT", "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.1", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "node_modules/@peculiar/asn1-pkcs9": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.6.1.tgz", "integrity": "sha512-5EV8nZoMSxeWmcxWmmcolg22ojZRgJg+Y9MX2fnE2bGRo5KQLqV5IL9kdSQDZxlHz95tHvIq9F//bvL1OeNILw==", "dev": true, "license": "MIT", "dependencies": { "@peculiar/asn1-cms": "^2.6.1", "@peculiar/asn1-pfx": "^2.6.1", "@peculiar/asn1-pkcs8": "^2.6.1", "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.1", "@peculiar/asn1-x509-attr": "^2.6.1", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "node_modules/@peculiar/asn1-rsa": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.6.1.tgz", "integrity": "sha512-1nVMEh46SElUt5CB3RUTV4EG/z7iYc7EoaDY5ECwganibQPkZ/Y2eMsTKB/LeyrUJ+W/tKoD9WUqIy8vB+CEdA==", "dev": true, "license": "MIT", "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.1", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "node_modules/@peculiar/asn1-schema": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.6.0.tgz", "integrity": "sha512-xNLYLBFTBKkCzEZIw842BxytQQATQv+lDTCEMZ8C196iJcJJMBUZxrhSTxLaohMyKK8QlzRNTRkUmanucnDSqg==", "dev": true, "license": "MIT", "dependencies": { "asn1js": "^3.0.6", "pvtsutils": "^1.3.6", "tslib": "^2.8.1" } }, "node_modules/@peculiar/asn1-x509": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.6.1.tgz", "integrity": "sha512-O9jT5F1A2+t3r7C4VT7LYGXqkGLK7Kj1xFpz7U0isPrubwU5PbDoyYtx6MiGst29yq7pXN5vZbQFKRCP+lLZlA==", "dev": true, "license": "MIT", "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "asn1js": "^3.0.6", "pvtsutils": "^1.3.6", "tslib": "^2.8.1" } }, "node_modules/@peculiar/asn1-x509-attr": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.6.1.tgz", "integrity": "sha512-tlW6cxoHwgcQghnJwv3YS+9OO1737zgPogZ+CgWRUK4roEwIPzRH4JEiG770xe5HX2ATfCpmX60gurfWIF9dcQ==", "dev": true, "license": "MIT", "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.1", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "node_modules/@peculiar/x509": { "version": "1.14.3", "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.14.3.tgz", "integrity": "sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA==", "dev": true, "license": "MIT", "dependencies": { "@peculiar/asn1-cms": "^2.6.0", "@peculiar/asn1-csr": "^2.6.0", "@peculiar/asn1-ecc": "^2.6.0", "@peculiar/asn1-pkcs9": "^2.6.0", "@peculiar/asn1-rsa": "^2.6.0", "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "pvtsutils": "^1.3.6", "reflect-metadata": "^0.2.2", "tslib": "^2.8.1", "tsyringe": "^4.10.0" }, "engines": { "node": ">=20.0.0" } }, "node_modules/@polka/url": { "version": "1.0.0-next.29", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", "dev": true, "license": "MIT" }, "node_modules/@rolldown/binding-android-arm64": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.1.tgz", "integrity": "sha512-fJI3I0r3C3Oj/zdBCpaCmBRZYf07xpaq4yCfDDoSFm+beWNzbIl26puW8RraUdugoJw/95zerNOn6jasAhzSmg==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "android" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-darwin-arm64": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.1.tgz", "integrity": "sha512-cKnAhWEsV7TPcA/5EAteDp6KcJZBQ2G+BqE7zayMMi7kMvwRsbv7WT9aOnn0WNl4SKEIf43vjS31iUPu80nzXg==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-darwin-x64": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.1.tgz", "integrity": "sha512-YKrVwQjIRBPo+5G/u03wGjbdy4q7pyzCe93DK9VJ7zkVmeg8LJ7GbgsiHWdR4xSoe4CAXRD7Bcjgbtr64bkXNg==", "cpu": [ "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-freebsd-x64": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.1.tgz", "integrity": "sha512-z/oBsREo46SsFqBwYtFe0kpJeBijAT48O/WXLI4suiCLBkr03RTtTJMCzSdDd2znlh8VJizL09XVkQgk8IZonw==", "cpu": [ "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "freebsd" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.1.tgz", "integrity": "sha512-ik8q7GM11zxvYxFc2PeDcT6TBvhCQMaUxfph/M5l9sKuTs/Sjg3L+Byw0F7w0ZVLBZmx30P+gG0ECzzN+MFcmQ==", "cpu": [ "arm" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.1.tgz", "integrity": "sha512-QoSx2EkyrrdZ6kcyE8stqZ62t0Yra8Fs5ia9lOxJrh6TMQJK7gQKmscdTHf7pOXKREKrVwOtJcQG3qVSfc866A==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-arm64-musl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.1.tgz", "integrity": "sha512-uwNwFpwKeNiZawfAWBgg0VIztPTV3ihhh1vV334h9ivnNLorxnQMU6Fz8wG1Zb4Qh9LC1/MkcyT3YlDXG3Rsgg==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.1.tgz", "integrity": "sha512-zY1bul7OWr7DFBiJ++wofXvnr8B45ce3QsQUhKrIhXsygAh7bTkwyeM1bi1a2g5C/yC/N8TZyGDEoMfm/l9mpg==", "cpu": [ "ppc64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.1.tgz", "integrity": "sha512-0frlsT/f4Ft6I7SMESTKnF3cZsdicQn1dCMkF/jT9wDLE+gGoiQfv1nmT9e+s7s/fekvvy6tZM2jHvI2tkbJDQ==", "cpu": [ "s390x" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-x64-gnu": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.1.tgz", "integrity": "sha512-XABVmGp9Tg0WspTVvwduTc4fpqy6JnAUrSQe6OuyqD/03nI7r0O9OWUkMIwFrjKAIqolvqoA4ZrJppgwE0Gxmw==", "cpu": [ "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-x64-musl": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.1.tgz", "integrity": "sha512-bV4fzswuzVcKD90o/VM6QqKxnxlDq0g2BISDLNVmxrnhpv1DDbyPhCIjYfvzYLV+MvkKKnQt2Q6AO86SEBULUQ==", "cpu": [ "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-openharmony-arm64": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.1.tgz", "integrity": "sha512-/Mh0Zhq3OP7fVs0kcQHZP6lZEthMGTaSf8UBQYSFEZDWGXXlEC+nJ6EqenaK2t4LBXMe3A+K/G2BVXXdtOr4PQ==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "openharmony" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-wasm32-wasi": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.1.tgz", "integrity": "sha512-+1xc9X45l8ufsBAm6Gjvx2qDRIY9lTVt0cgWNcJ+1gdhXvkbxePA60yRTwSTuXL09CMhyJmjpV7E3NoyxbqFQQ==", "cpu": [ "wasm32" ], "dev": true, "license": "MIT", "optional": true, "dependencies": { "@emnapi/core": "1.10.0", "@emnapi/runtime": "1.10.0", "@napi-rs/wasm-runtime": "^1.1.4" }, "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.1.tgz", "integrity": "sha512-1D+UqZdfnuR+Jy1GgMJwi85bD40H21uNmOPRWQhw4oRSuolZ/B5rixZ45DK2KXOTCvmVCecauWgEhbw8bI7tOw==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-win32-x64-msvc": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.1.tgz", "integrity": "sha512-INAycaWuhlOK3wk4mRHGsdgwYWmd9cChdPdE9bwWmy6rn9VqVNYNFGhOdXrofXUxwHIncSiPNb8tNm8knDVIeQ==", "cpu": [ "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/pluginutils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", "dev": true, "license": "MIT" }, "node_modules/@rollup/plugin-alias": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@rollup/plugin-alias/-/plugin-alias-6.0.0.tgz", "integrity": "sha512-tPCzJOtS7uuVZd+xPhoy5W4vThe6KWXNmsFCNktaAh5RTqcLiSfT4huPQIXkgJ6YCOjJHvecOAzQxLFhPxKr+g==", "dev": true, "license": "MIT", "engines": { "node": ">=20.19.0" }, "peerDependencies": { "rollup": ">=4.0.0" }, "peerDependenciesMeta": { "rollup": { "optional": true } } }, "node_modules/@rollup/plugin-babel": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-7.1.0.tgz", "integrity": "sha512-h9Y+xYha6p4wKO+FwdiPIkE+eIYCm8MzZPpX1iARIoFBnmKP9CnpT1p9dDf/DTFm6fyN8PmuLyRI5qZgchnitw==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.18.6", "@rollup/pluginutils": "^5.0.1", "workerpool": "^9.0.0" }, "engines": { "node": ">=14.0.0" }, "peerDependencies": { "@babel/core": "^7.0.0", "@types/babel__core": "^7.1.9", "rollup": "^2.0.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "@types/babel__core": { "optional": true }, "rollup": { "optional": true } } }, "node_modules/@rollup/plugin-commonjs": { "version": "29.0.3", "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-29.0.3.tgz", "integrity": "sha512-ZaOxZceP7SOUW7Lqw5IRVweSQYWaeIPnXIGLiB690EBA3FGJTO40EEr2L5yZplJWsgTCogILRSpcAe7+U0Otdg==", "dev": true, "license": "MIT", "dependencies": { "@rollup/pluginutils": "^5.0.1", "commondir": "^1.0.1", "estree-walker": "^2.0.2", "fdir": "^6.2.0", "is-reference": "1.2.1", "magic-string": "^0.30.3", "picomatch": "^4.0.2" }, "engines": { "node": ">=16.0.0 || 14 >= 14.17" }, "peerDependencies": { "rollup": "^2.68.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { "optional": true } } }, "node_modules/@rollup/plugin-json": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", "integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==", "dev": true, "license": "MIT", "dependencies": { "@rollup/pluginutils": "^5.1.0" }, "engines": { "node": ">=14.0.0" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { "optional": true } } }, "node_modules/@rollup/plugin-node-resolve": { "version": "16.0.3", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.3.tgz", "integrity": "sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg==", "dev": true, "license": "MIT", "dependencies": { "@rollup/pluginutils": "^5.0.1", "@types/resolve": "1.20.2", "deepmerge": "^4.2.2", "is-module": "^1.0.0", "resolve": "^1.22.1" }, "engines": { "node": ">=14.0.0" }, "peerDependencies": { "rollup": "^2.78.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { "optional": true } } }, "node_modules/@rollup/plugin-terser": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-1.0.0.tgz", "integrity": "sha512-FnCxhTBx6bMOYQrar6C8h3scPt8/JwIzw3+AJ2K++6guogH5fYaIFia+zZuhqv0eo1RN7W1Pz630SyvLbDjhtQ==", "dev": true, "license": "MIT", "dependencies": { "serialize-javascript": "^7.0.3", "smob": "^1.0.0", "terser": "^5.17.4" }, "engines": { "node": ">=20.0.0" }, "peerDependencies": { "rollup": "^2.0.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { "optional": true } } }, "node_modules/@rollup/pluginutils": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", "dev": true, "license": "MIT", "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "engines": { "node": ">=14.0.0" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "peerDependenciesMeta": { "rollup": { "optional": true } } }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.61.0.tgz", "integrity": "sha512-dnxczajOqt0gesZlN5pGQ1s1imQVrsmCw5G2Ci4oM+0WvNz3pyRnlWrT7McoZIb8VlFwCawdmbWRmxRn7HI+VQ==", "cpu": [ "arm" ], "dev": true, "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-android-arm64": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.61.0.tgz", "integrity": "sha512-Bp3JpGP00Vu3f238ivRrjf7z3xSzVPXqCmaJYA9t2c+c8vKYvOzmXF7LkkeUalTEGd6cZcSWe+PFIP3Vy48fRg==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "android" ] }, "node_modules/@rollup/rollup-darwin-arm64": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.61.0.tgz", "integrity": "sha512-zaYIpr670mUmmZ1tVzUFplbQbG7h3Gugx3L5FoqhsC2m/YnLlR1a7zVLmXNPy+iY1tFPEbNG+HHBXZGyId0G5w==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-darwin-x64": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.61.0.tgz", "integrity": "sha512-+P49fvkv2dSoeevUW+lgZ/I2JHSsJCK1Lyjj7Cu6E4UHG4tS9XIefzIjo5qhgELjAclnen1rLzK2PMKJdo+Dyg==", "cpu": [ "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" ] }, "node_modules/@rollup/rollup-freebsd-arm64": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.61.0.tgz", "integrity": "sha512-l3FAAOyKJXH2ea6KNFN+MMgC/rnE94YGLXs2ehYqDcCoHt1DpvgWX75BhUJxN38XojP7Ul+4H8PRn7EdyqSDrw==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "freebsd" ] }, "node_modules/@rollup/rollup-freebsd-x64": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.61.0.tgz", "integrity": "sha512-VokPN3TSctKj65cyCNPaUh4vMFA8awxOot/0sp+4J7ZlNRKQEhXhawqPwajoi8H5ZFt61i0ugZJuTKXBjGJ17Q==", "cpu": [ "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "freebsd" ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.61.0.tgz", "integrity": "sha512-DxH0P3wxm+Yzs/p3zrk9dw1rURu8p0Nv5+MRK/L7OtnLNg5rLZraSBFZ8iUXOd9f2BlhJyEpIZUH/emjq4UJ4g==", "cpu": [ "arm" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.61.0.tgz", "integrity": "sha512-T6ZvMNe84kAz6TBWHC7hGAoEtzP1LWYw/AqayGWEF6uISt3Abk/st06LqRD9THd7Xz3NxzurUpzAuEAUbZf+nw==", "cpu": [ "arm" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.61.0.tgz", "integrity": "sha512-q/4hzvQkDs8b4jIBab1pnLiiM0ayTZsN2amBFPDzuyZxjEd4wDwx0UJFYM3cOZzSf5Kw8fnWSprJzIBMkcR44Q==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.61.0.tgz", "integrity": "sha512-vvYWX3akdEAY6km+9wAqFDnk6pQsbJKVnj7xawcvs/+fdlYBGp+U+Qq/lLfpIxYIZvZLHMAKD9HLdacSx/r3dw==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.61.0.tgz", "integrity": "sha512-DePa5cqOxDP/Zp0VOXpeWaGew5iIv5DXp9NYbzkX5PFQyWVX9184WCTh3hvr/7lhXo8ZVlbFLkz8+o/q1dU6gA==", "cpu": [ "loong64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.61.0.tgz", "integrity": "sha512-LV8aWMB8UChglMCEzs7RkN0GsH29RJaLLqwm9fCIjlqwxQTiWAqNcc7wjBkH31hV0PU/yVxGYvrYsgfea2qw6g==", "cpu": [ "loong64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.61.0.tgz", "integrity": "sha512-QoNSnwQtaeNu5grdBbsL0tt1uyl5EnS8DA8Mr3nluMXbhdQNyhN+G4tBax7VCdxLKj8YJ0/4OO9Ho84jMnJtKA==", "cpu": [ "ppc64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.61.0.tgz", "integrity": "sha512-/zZp5MKapIIApE8trN8qLGNSiRN9TUoaUZ1cmVu4XnVdd5LQLOXTtyi+vtfUbNnT3iyjzpPqYeKXmvJ+gJGYWw==", "cpu": [ "ppc64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.61.0.tgz", "integrity": "sha512-RbrzcD3aJ1k3UbtMRRBNwojdVVyXjuVAFTfn/xPa6EEl6GE9Sm/akPgFTb9aAC9pMKGJ6CtWxaGrqWcabH+ySg==", "cpu": [ "riscv64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.61.0.tgz", "integrity": "sha512-ZF+onDsBso8PJf1XaG9lB+O9RnBpKGnY6OrzC4CSHrtC1jb6jWLTKK4bRqdoCXHd22gyr2hiYmEAm8Wns/BOCw==", "cpu": [ "riscv64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.61.0.tgz", "integrity": "sha512-Atk0aSIk5Zx2Wuh9dgRQgLP0Koc8hOeYpbWryMXyk8G8/HmPkwPPkMqIIDhrXHHYqfUzSJA/I7IWSBv8xSmRBA==", "cpu": [ "s390x" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.61.0.tgz", "integrity": "sha512-0uMOcf3eZ5K+K4cYHkdxShFMPlPXCOdfDFEFn9dNYAEEd2cVvmOfH7zFgRVoDgmtQ1m9k5q7qfrHzyMAubKYUA==", "cpu": [ "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-linux-x64-musl": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.61.0.tgz", "integrity": "sha512-mvFtE4A/t/7hRJ7X8Ozmu8FsIkAUat2nzl12pgU337BRmq87AQUJztwHz2Zv5/tjo9/C95E66CK03SI/ToEDJw==", "cpu": [ "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ] }, "node_modules/@rollup/rollup-openbsd-x64": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.61.0.tgz", "integrity": "sha512-z9b9+aTxvt8n2rNltMPvyaUfB8NJ+CVyOrGK/MdIKHx7B+lXmZpm/XbRsU7Rpf3fRqJ2uS6mBJiJveCtq8LHDg==", "cpu": [ "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "openbsd" ] }, "node_modules/@rollup/rollup-openharmony-arm64": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.61.0.tgz", "integrity": "sha512-jXaXFqKMehsOc+g8R6oo33RRC6w07G9jDBxAE5eAKX7mOcCbZloYIPNhfG9Wl+P9O9IWHFO4OJgPi1Ml2qkt7w==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "openharmony" ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.61.0.tgz", "integrity": "sha512-OXNWVFocS2IA4+QplhTZZ2a+8hPZR7T8KuozsNmJKK8y7cp83StHvGksfHzPG3wczWTczyWHVQuqeiTUbjiyBg==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.61.0.tgz", "integrity": "sha512-AlAbNtBO637LxSldqV43z0FfXoGfl2TW1DgAg/bs7aQswFbDewz2SJm3BUhiGfbOVtW571xbc9p+REdxhyN/Eg==", "cpu": [ "ia32" ], "dev": true, "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.61.0.tgz", "integrity": "sha512-QRSrQXyJ1M4tjNXdR0/G/IgV6lzfQQJYBjlWIEYkY2Xs86DRl/iEpQ4blMDjJxSl7n19eDKKXMg0AmuBVYy8pQ==", "cpu": [ "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.61.0.tgz", "integrity": "sha512-tkuFxhvKO/HlGd0VsINF6vHSYH8AF8W0TcNxKDK6JZmrehngFj78pToc8iemtnvwilDjs2G/qSzYFhe9U8q+fw==", "cpu": [ "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "win32" ] }, "node_modules/@sec-ant/readable-stream": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", "dev": true, "license": "MIT" }, "node_modules/@simple-libs/child-process-utils": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@simple-libs/child-process-utils/-/child-process-utils-1.0.2.tgz", "integrity": "sha512-/4R8QKnd/8agJynkNdJmNw2MBxuFTRcNFnE5Sg/G+jkSsV8/UBgULMzhizWWW42p8L5H7flImV2ATi79Ove2Tw==", "dev": true, "license": "MIT", "dependencies": { "@simple-libs/stream-utils": "^1.2.0" }, "engines": { "node": ">=18" }, "funding": { "url": "https://ko-fi.com/dangreen" } }, "node_modules/@simple-libs/stream-utils": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@simple-libs/stream-utils/-/stream-utils-1.2.0.tgz", "integrity": "sha512-KxXvfapcixpz6rVEB6HPjOUZT22yN6v0vI0urQSk1L8MlEWPDFCZkhw2xmkyoTGYeFw7tWTZd7e3lVzRZRN/EA==", "dev": true, "license": "MIT", "engines": { "node": ">=18" }, "funding": { "url": "https://ko-fi.com/dangreen" } }, "node_modules/@standard-schema/spec": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", "dev": true, "license": "MIT" }, "node_modules/@tybys/wasm-util": { "version": "0.10.2", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", "dev": true, "license": "MIT", "optional": true, "dependencies": { "tslib": "^2.4.0" } }, "node_modules/@types/chai": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", "dev": true, "license": "MIT", "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "node_modules/@types/deep-eql": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", "dev": true, "license": "MIT" }, "node_modules/@types/esrecurse": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", "dev": true, "license": "MIT" }, "node_modules/@types/estree": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "dev": true, "license": "MIT" }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true, "license": "MIT" }, "node_modules/@types/node": { "version": "25.9.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz", "integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "node_modules/@types/resolve": { "version": "1.20.2", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", "dev": true, "license": "MIT" }, "node_modules/@vitest/browser": { "version": "4.1.8", "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-4.1.8.tgz", "integrity": "sha512-u21VzX07HzlJYpFgkxmjEXar/tG2UqWGgyGG/46SrrPc7rSdCTPw5vuowopO9CIqF8UCUQzDFdbVnNpw6N0BfQ==", "dev": true, "license": "MIT", "dependencies": { "@blazediff/core": "1.9.1", "@vitest/mocker": "4.1.8", "@vitest/utils": "4.1.8", "magic-string": "^0.30.21", "pngjs": "^7.0.0", "sirv": "^3.0.2", "tinyrainbow": "^3.1.0", "ws": "^8.19.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "vitest": "4.1.8" } }, "node_modules/@vitest/browser-playwright": { "version": "4.1.8", "resolved": "https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-4.1.8.tgz", "integrity": "sha512-SR7FqgegaexEg73xvf3ArtygXegagMdXnL0EZMpxrWvvhQxvicD/E8p0ib0J91riPRtQUViyh67Xjw3NqvyhVg==", "dev": true, "license": "MIT", "dependencies": { "@vitest/browser": "4.1.8", "@vitest/mocker": "4.1.8", "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "playwright": "*", "vitest": "4.1.8" }, "peerDependenciesMeta": { "playwright": { "optional": false } } }, "node_modules/@vitest/expect": { "version": "4.1.8", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.8.tgz", "integrity": "sha512-h3nDO677RDLEGlBxyQ5CW8RlMThSKSRLUePLOx09gNIWRL40edgA1GCZSZgf1W55MFAG6/Sw14KeaAnqv0NKdQ==", "dev": true, "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.8", "@vitest/utils": "4.1.8", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/mocker": { "version": "4.1.8", "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.8.tgz", "integrity": "sha512-LEiN/xe4OSIbKe9HQIp5OC24agGD9J5CnmMgsLohVVoOPWL9a2sBoR6VBx43jQZb7Kr1l4RCuyCJzcAa0+dojw==", "dev": true, "license": "MIT", "dependencies": { "@vitest/spy": "4.1.8", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "msw": { "optional": true }, "vite": { "optional": true } } }, "node_modules/@vitest/mocker/node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dev": true, "license": "MIT", "dependencies": { "@types/estree": "^1.0.0" } }, "node_modules/@vitest/pretty-format": { "version": "4.1.8", "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.8.tgz", "integrity": "sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA==", "dev": true, "license": "MIT", "dependencies": { "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/runner": { "version": "4.1.8", "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.8.tgz", "integrity": "sha512-EmVxeBAfMJvycdjd6Hm+RbFBbA9fKvo0Kx37hNpBYoYeavH3RNsBXWDooR1mgD52dCrxIIuP7UotpfiwOikvcg==", "dev": true, "license": "MIT", "dependencies": { "@vitest/utils": "4.1.8", "pathe": "^2.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot": { "version": "4.1.8", "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.8.tgz", "integrity": "sha512-acfZboRmAIf05DEKcBQy33VXojFJjtUdLyo7oOmV9kebb2xdU01UknNiPuPZoJZQyO7DF0gZdTGTpeAzET9QPQ==", "dev": true, "license": "MIT", "dependencies": { "@vitest/pretty-format": "4.1.8", "@vitest/utils": "4.1.8", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/spy": { "version": "4.1.8", "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.8.tgz", "integrity": "sha512-6EevtBp6OZOPF7bmz36HrGMeP3txgVSrgebWxHOafDXGkhIzfXK14f8KF6MuFfgXXUeHxmpD3BQxkV00/3s5mA==", "dev": true, "license": "MIT", "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/utils": { "version": "4.1.8", "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.8.tgz", "integrity": "sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg==", "dev": true, "license": "MIT", "dependencies": { "@vitest/pretty-format": "4.1.8", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/abortcontroller-polyfill": { "version": "1.7.8", "resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.8.tgz", "integrity": "sha512-9f1iZ2uWh92VcrU9Y8x+LdM4DLj75VE0MJB8zuF1iUnroEptStw+DQ8EQPMUdfe5k+PkB1uUfDQfWbhstH8LrQ==", "dev": true, "license": "MIT" }, "node_modules/accepts": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", "dev": true, "license": "MIT", "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" }, "engines": { "node": ">= 0.6" } }, "node_modules/accepts/node_modules/mime-db": { "version": "1.54.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/accepts/node_modules/mime-types": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "dev": true, "license": "MIT", "dependencies": { "mime-db": "^1.54.0" }, "engines": { "node": ">=18" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/express" } }, "node_modules/acorn": { "version": "8.16.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" }, "engines": { "node": ">=0.4.0" } }, "node_modules/acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "license": "MIT", "dependencies": { "debug": "4" }, "engines": { "node": ">= 6.0.0" } }, "node_modules/ajv": { "version": "8.20.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" }, "funding": { "type": "github", "url": "https://github.com/sponsors/epoberezkin" } }, "node_modules/ansi-escapes": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", "dev": true, "license": "MIT", "dependencies": { "environment": "^1.0.0" }, "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/ansi-styles": { "version": "6.2.3", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", "dev": true, "license": "MIT", "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" }, "engines": { "node": ">= 8" } }, "node_modules/anymatch/node_modules/picomatch": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { "node": ">=8.6" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/append-field": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", "dev": true, "license": "MIT" }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, "license": "Python-2.0" }, "node_modules/array-each": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", "integrity": "sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", "dev": true, "license": "MIT" }, "node_modules/array-slice": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", "dev": true, "license": "MIT" }, "node_modules/asn1js": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.7.tgz", "integrity": "sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { "pvtsutils": "^1.3.6", "pvutils": "^1.1.3", "tslib": "^2.8.1" }, "engines": { "node": ">=12.0.0" } }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "license": "MIT", "engines": { "node": ">=12" } }, "node_modules/async-done": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/async-done/-/async-done-2.0.0.tgz", "integrity": "sha512-j0s3bzYq9yKIVLKGE/tWlCpa3PfFLcrDZLTSVdnnCTGagXuXBJO4SsY9Xdk/fQBirCkH4evW5xOeJXqlAQFdsw==", "dev": true, "license": "MIT", "dependencies": { "end-of-stream": "^1.4.4", "once": "^1.4.0", "stream-exhaust": "^1.0.2" }, "engines": { "node": ">= 10.13.0" } }, "node_modules/async-settle": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-2.0.0.tgz", "integrity": "sha512-Obu/KE8FurfQRN6ODdHN9LuXqwC+JFIM9NRyZqJJ4ZfLJmIYN9Rg0/kb+wF70VV5+fJusTMQlJ1t5rF7J/ETdg==", "dev": true, "license": "MIT", "dependencies": { "async-done": "^2.0.0" }, "engines": { "node": ">= 10.13.0" } }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, "node_modules/b4a": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.0.tgz", "integrity": "sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==", "dev": true, "license": "Apache-2.0", "peerDependencies": { "react-native-b4a": "*" }, "peerDependenciesMeta": { "react-native-b4a": { "optional": true } } }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.16", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.16.tgz", "integrity": "sha512-xaVwwSfebXf0ooE11BJovZYKhFjIvQo7TsyVpETuIeH2JHv0k/T6Y5j22pPTvqYqmpkxdlPAJlyJ0tfOJAoMxw==", "dev": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-define-polyfill-provider": "^0.6.7", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-corejs3": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.1.tgz", "integrity": "sha512-ENp89vM9Pw4kv/koBb5N2f9bDZsR0hpf3BdPMOg/pkS3pwO4dzNnQZVXtBbeyAadgm865DmQG2jMMLqmZXvuCw==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.7", "core-js-compat": "^3.48.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/babel-plugin-polyfill-regenerator": { "version": "0.6.7", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.7.tgz", "integrity": "sha512-OTYbUlSwXhNgr4g6efMZgsO8//jA61P7ZbRX3iTT53VON8l+WQS8IAUEVo4a4cWknrg2W8Cj4gQhRYNCJ8GkAA==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.7" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "node_modules/bach": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/bach/-/bach-2.0.1.tgz", "integrity": "sha512-A7bvGMGiTOxGMpNupYl9HQTf0FFDNF4VCmks4PJpFyN1AX2pdKuxuwdvUz2Hu388wcgp+OvGFNsumBfFNkR7eg==", "dev": true, "license": "MIT", "dependencies": { "async-done": "^2.0.0", "async-settle": "^2.0.0", "now-and-later": "^3.0.0" }, "engines": { "node": ">=10.13.0" } }, "node_modules/balanced-match": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, "license": "MIT", "engines": { "node": "18 || 20 || >=22" } }, "node_modules/bare-events": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", "dev": true, "license": "Apache-2.0", "peerDependencies": { "bare-abort-controller": "*" }, "peerDependenciesMeta": { "bare-abort-controller": { "optional": true } } }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ], "license": "MIT" }, "node_modules/baseline-browser-mapping": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", "dev": true, "license": "Apache-2.0", "bin": { "baseline-browser-mapping": "dist/cli.cjs" }, "engines": { "node": ">=6.0.0" } }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "license": "MIT", "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/bl": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", "dev": true, "license": "MIT", "dependencies": { "buffer": "^6.0.3", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "node_modules/body-parser": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", "dev": true, "license": "MIT", "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" }, "engines": { "node": ">=18" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/express" } }, "node_modules/body-parser/node_modules/media-typer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/body-parser/node_modules/mime-db": { "version": "1.54.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/body-parser/node_modules/mime-types": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "dev": true, "license": "MIT", "dependencies": { "mime-db": "^1.54.0" }, "engines": { "node": ">=18" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/express" } }, "node_modules/body-parser/node_modules/type-is": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", "dev": true, "license": "MIT", "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" }, "engines": { "node": ">= 0.6" } }, "node_modules/brace-expansion": { "version": "5.0.6", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" }, "engines": { "node": "18 || 20 || >=22" } }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, "node_modules/browserslist": { "version": "4.28.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/browserslist" }, { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" }, { "type": "github", "url": "https://github.com/sponsors/ai" } ], "license": "MIT", "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" }, "engines": { "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, "node_modules/buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ], "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true, "license": "MIT" }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", "dev": true, "dependencies": { "streamsearch": "^1.1.0" }, "engines": { "node": ">=10.16.0" } }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/bytestreamjs": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/bytestreamjs/-/bytestreamjs-2.0.1.tgz", "integrity": "sha512-U1Z/ob71V/bXfVABvNr/Kumf5VyeQRBEm6Txb0PQ6S7V5GpBM3w4Cbqz/xPDicR5tN0uvDifng8C+5qECeGwyQ==", "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=6.0.0" } }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/call-bound": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/caniuse-lite": { "version": "1.0.30001777", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001777.tgz", "integrity": "sha512-tmN+fJxroPndC74efCdp12j+0rk0RHwV5Jwa1zWaFVyw2ZxAuPeG8ZgWC3Wz7uSjT3qMRQ5XHZ4COgQmsCMJAQ==", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/browserslist" }, { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" }, { "type": "github", "url": "https://github.com/sponsors/ai" } ], "license": "CC-BY-4.0" }, "node_modules/chai": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", "dev": true, "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/chalk": { "version": "5.6.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", "dev": true, "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "engines": { "node": ">= 8.10.0" }, "funding": { "url": "https://paulmillr.com/funding/" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "node_modules/chokidar/node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, "engines": { "node": ">= 6" } }, "node_modules/cli-cursor": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", "dev": true, "license": "MIT", "dependencies": { "restore-cursor": "^5.0.0" }, "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/cli-truncate": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-5.2.0.tgz", "integrity": "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw==", "dev": true, "license": "MIT", "dependencies": { "slice-ansi": "^8.0.0", "string-width": "^8.2.0" }, "engines": { "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/cliui": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", "dev": true, "license": "ISC", "dependencies": { "string-width": "^7.2.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" }, "engines": { "node": ">=20" } }, "node_modules/cliui/node_modules/ansi-regex": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/cliui/node_modules/string-width": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" }, "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/cliui/node_modules/strip-ansi": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^6.2.2" }, "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/cliui/node_modules/wrap-ansi": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" }, "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", "dev": true, "license": "MIT", "engines": { "node": ">=0.8" } }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, "engines": { "node": ">=7.0.0" } }, "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, "engines": { "node": ">= 0.8" } }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "dev": true, "license": "MIT" }, "node_modules/compare-func": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", "dev": true, "license": "MIT", "dependencies": { "array-ify": "^1.0.0", "dot-prop": "^5.1.0" } }, "node_modules/content-disposition": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", "dev": true, "license": "MIT", "engines": { "node": ">=18" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/express" } }, "node_modules/content-type": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/conventional-changelog-angular": { "version": "8.3.1", "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-8.3.1.tgz", "integrity": "sha512-6gfI3otXK5Ph5DfCOI1dblr+kN3FAm5a97hYoQkqNZxOaYa5WKfXH+AnpsmS+iUH2mgVC2Cg2Qw9m5OKcmNrIg==", "dev": true, "license": "ISC", "dependencies": { "compare-func": "^2.0.0" }, "engines": { "node": ">=18" } }, "node_modules/conventional-changelog-conventionalcommits": { "version": "9.3.0", "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-9.3.0.tgz", "integrity": "sha512-kYFx6gAyjSIMwNtASkI3ZE99U1fuVDJr0yTYgVy+I2QG46zNZfl2her+0+eoviG82c5WQvW1jMt1eOQTeJLodA==", "dev": true, "license": "ISC", "dependencies": { "compare-func": "^2.0.0" }, "engines": { "node": ">=18" } }, "node_modules/conventional-commits-parser": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-6.4.0.tgz", "integrity": "sha512-tvRg7FIBNlyPzjdG8wWRlPHQJJHI7DylhtRGeU9Lq+JuoPh5BKpPRX83ZdLrvXuOSu5Eo/e7SzOQhU4Hd2Miuw==", "dev": true, "license": "MIT", "dependencies": { "@simple-libs/stream-utils": "^1.2.0", "meow": "^13.0.0" }, "bin": { "conventional-commits-parser": "dist/cli/index.js" }, "engines": { "node": ">=18" } }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, "license": "MIT" }, "node_modules/cookie": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/cookie-signature": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", "dev": true, "license": "MIT", "engines": { "node": ">=6.6.0" } }, "node_modules/copy-props": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-4.0.0.tgz", "integrity": "sha512-bVWtw1wQLzzKiYROtvNlbJgxgBYt2bMJpkCbKmXM3xyijvcjjWXEk5nyrrT3bgJ7ODb19ZohE2T0Y3FgNPyoTw==", "dev": true, "license": "MIT", "dependencies": { "each-props": "^3.0.0", "is-plain-object": "^5.0.0" }, "engines": { "node": ">= 10.13.0" } }, "node_modules/core-js-compat": { "version": "3.48.0", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.48.0.tgz", "integrity": "sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==", "dev": true, "license": "MIT", "dependencies": { "browserslist": "^4.28.1" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/core-js" } }, "node_modules/cosmiconfig": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.2.tgz", "integrity": "sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg==", "dev": true, "license": "MIT", "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0" }, "engines": { "node": ">=14" }, "funding": { "url": "https://github.com/sponsors/d-fischer" }, "peerDependencies": { "typescript": ">=4.9.5" }, "peerDependenciesMeta": { "typescript": { "optional": true } } }, "node_modules/cosmiconfig-typescript-loader": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-6.3.0.tgz", "integrity": "sha512-Akr82WH1Wfqatyiqpj8HDkO2o2KmJRu1FhKfSNJP3K4IdXwHfEyL7MOb62i1AGQVLtIQM+iCE9CGOtrfhR+mmA==", "dev": true, "license": "MIT", "dependencies": { "jiti": "2.6.1" }, "engines": { "node": ">=v18" }, "peerDependencies": { "@types/node": "*", "cosmiconfig": ">=9", "typescript": ">=5" } }, "node_modules/cross-env": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.1.0.tgz", "integrity": "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==", "dev": true, "license": "MIT", "dependencies": { "@epic-web/invariant": "^1.0.0", "cross-spawn": "^7.0.6" }, "bin": { "cross-env": "dist/bin/cross-env.js", "cross-env-shell": "dist/bin/cross-env-shell.js" }, "engines": { "node": ">=20" } }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" }, "engines": { "node": ">= 8" } }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "license": "MIT", "dependencies": { "ms": "^2.1.3" }, "engines": { "node": ">=6.0" }, "peerDependenciesMeta": { "supports-color": { "optional": true } } }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true, "license": "MIT" }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "license": "MIT", "engines": { "node": ">=0.4.0" } }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/detect-file": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, "license": "Apache-2.0", "engines": { "node": ">=8" } }, "node_modules/dev-null": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/dev-null/-/dev-null-0.1.1.tgz", "integrity": "sha512-nMNZG0zfMgmdv8S5O0TM5cpwNbGKRGPCxVsr0SmA3NZZy9CYBbuNLL0PD3Acx9e5LIUgwONXtM9kM6RlawPxEQ==", "dev": true, "license": "MIT" }, "node_modules/dezalgo": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", "dev": true, "license": "ISC", "dependencies": { "asap": "^2.0.0", "wrappy": "1" } }, "node_modules/dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", "dev": true, "license": "MIT", "dependencies": { "is-obj": "^2.0.0" }, "engines": { "node": ">=8" } }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/duplexer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", "dev": true, "license": "MIT" }, "node_modules/each-props": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/each-props/-/each-props-3.0.0.tgz", "integrity": "sha512-IYf1hpuWrdzse/s/YJOrFmU15lyhSzxelNVAHTEG3DtP4QsLTWZUzcUL3HMXmKQxXpa4EIrBPpwRgj0aehdvAw==", "dev": true, "license": "MIT", "dependencies": { "is-plain-object": "^5.0.0", "object.defaults": "^1.1.0" }, "engines": { "node": ">= 10.13.0" } }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "dev": true, "license": "MIT" }, "node_modules/electron-to-chromium": { "version": "1.5.307", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.307.tgz", "integrity": "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==", "dev": true, "license": "ISC" }, "node_modules/emoji-regex": { "version": "10.6.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", "dev": true, "license": "MIT" }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/end-of-stream": { "version": "1.4.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", "dev": true, "license": "MIT", "dependencies": { "once": "^1.4.0" } }, "node_modules/env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/environment": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", "dev": true, "license": "MIT", "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/error-ex": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", "dev": true, "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" } }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/es-errors": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/es-module-lexer": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", "dev": true, "license": "MIT" }, "node_modules/es-object-atoms": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-set-tostringtag": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-toolkit": { "version": "1.47.0", "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.47.0.tgz", "integrity": "sha512-n1GuoD0WEQZMBk5tttoZSqwgyLx01oqa5XsBmCHwPyNe1S9jPBEmtR2pSgp2kJuWE3ciFZ6yRHmY4pM4C3OOkw==", "dev": true, "license": "MIT", "workspaces": [ "docs", "benchmarks" ] }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "dev": true, "license": "MIT" }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint": { "version": "10.4.1", "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.4.1.tgz", "integrity": "sha512-AyIKhnOBuOAdueD7RB3xB+YeAWScb9jHsJBgH2Hcde8InP5JYhqrRR6iTMHyTEwgENK54Cp44e4v8BwNhsuHuw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.5", "@eslint/config-helpers": "^0.6.0", "@eslint/core": "^1.2.1", "@eslint/plugin-kit": "^0.7.2", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.2.0", "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "minimatch": "^10.2.4", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://eslint.org/donate" }, "peerDependencies": { "jiti": "*" }, "peerDependenciesMeta": { "jiti": { "optional": true } } }, "node_modules/eslint-scope": { "version": "9.1.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "@types/esrecurse": "^4.3.1", "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-visitor-keys": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/ajv": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" }, "funding": { "type": "github", "url": "https://github.com/sponsors/epoberezkin" } }, "node_modules/eslint/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, "license": "MIT" }, "node_modules/espree": { "version": "11.2.0", "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^5.0.1" }, "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/esquery": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, "engines": { "node": ">=0.10" } }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, "engines": { "node": ">=4.0" } }, "node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true, "license": "MIT" }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/eventemitter3": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", "dev": true, "license": "MIT" }, "node_modules/events-universal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", "dev": true, "license": "Apache-2.0", "dependencies": { "bare-events": "^2.7.0" } }, "node_modules/expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", "dev": true, "license": "MIT", "dependencies": { "homedir-polyfill": "^1.0.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/expect-type": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", "dev": true, "license": "Apache-2.0", "engines": { "node": ">=12.0.0" } }, "node_modules/express": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", "dev": true, "license": "MIT", "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" }, "engines": { "node": ">= 18" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/express" } }, "node_modules/express/node_modules/media-typer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/express/node_modules/mime-db": { "version": "1.54.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/express/node_modules/mime-types": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "dev": true, "license": "MIT", "dependencies": { "mime-db": "^1.54.0" }, "engines": { "node": ">=18" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/express" } }, "node_modules/express/node_modules/type-is": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", "dev": true, "license": "MIT", "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" }, "engines": { "node": ">= 0.6" } }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true, "license": "MIT" }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, "license": "MIT" }, "node_modules/fast-fifo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", "dev": true, "license": "MIT" }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true, "license": "MIT" }, "node_modules/fast-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/fastify" }, { "type": "opencollective", "url": "https://opencollective.com/fastify" } ], "license": "BSD-3-Clause" }, "node_modules/fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "dev": true, "license": "MIT", "engines": { "node": ">= 4.9.1" } }, "node_modules/fastq": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", "dev": true, "license": "ISC", "dependencies": { "reusify": "^1.0.4" } }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", "engines": { "node": ">=12.0.0" }, "peerDependencies": { "picomatch": "^3 || ^4" }, "peerDependenciesMeta": { "picomatch": { "optional": true } } }, "node_modules/figures": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", "integrity": "sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==", "dev": true, "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.5", "object-assign": "^4.1.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/figures/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", "dependencies": { "flat-cache": "^4.0.0" }, "engines": { "node": ">=16.0.0" } }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/finalhandler": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", "dev": true, "license": "MIT", "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" }, "engines": { "node": ">= 18.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/express" } }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/findup-sync": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-5.0.0.tgz", "integrity": "sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==", "dev": true, "license": "MIT", "dependencies": { "detect-file": "^1.0.0", "is-glob": "^4.0.3", "micromatch": "^4.0.4", "resolve-dir": "^1.0.1" }, "engines": { "node": ">= 10.13.0" } }, "node_modules/fined": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fined/-/fined-2.0.0.tgz", "integrity": "sha512-OFRzsL6ZMHz5s0JrsEr+TpdGNCtrVtnuG3x1yzGNiQHT0yaDnXAj8V/lWcpJVrnoDpcwXcASxAZYbuXda2Y82A==", "dev": true, "license": "MIT", "dependencies": { "expand-tilde": "^2.0.2", "is-plain-object": "^5.0.0", "object.defaults": "^1.1.0", "object.pick": "^1.3.0", "parse-filepath": "^1.0.2" }, "engines": { "node": ">= 10.13.0" } }, "node_modules/flagged-respawn": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-2.0.0.tgz", "integrity": "sha512-Gq/a6YCi8zexmGHMuJwahTGzXlAZAOsbCVKduWXC6TlLCjjFRlExMJc4GC2NYPYZ0r/brw9P7CpRgQmlPVeOoA==", "dev": true, "license": "MIT", "engines": { "node": ">= 10.13.0" } }, "node_modules/flat-cache": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" }, "engines": { "node": ">=16" } }, "node_modules/flatted": { "version": "3.4.2", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true, "license": "ISC" }, "node_modules/follow-redirects": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", "funding": [ { "type": "individual", "url": "https://github.com/sponsors/RubenVerborgh" } ], "license": "MIT", "engines": { "node": ">=4.0" }, "peerDependenciesMeta": { "debug": { "optional": true } } }, "node_modules/for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/for-own": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", "integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==", "dev": true, "license": "MIT", "dependencies": { "for-in": "^1.0.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/form-data": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { "node": ">= 6" } }, "node_modules/formdata-node": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-6.0.3.tgz", "integrity": "sha512-8e1++BCiTzUno9v5IZ2J6bv4RU+3UKDmqWUQD0MIMVCd9AdhWkO1gw57oo1mNEX1dMq2EGI+FbWz4B92pscSQg==", "dev": true, "license": "MIT", "engines": { "node": ">= 18" } }, "node_modules/formidable": { "version": "3.5.4", "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz", "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==", "dev": true, "license": "MIT", "dependencies": { "@paralleldrive/cuid2": "^2.2.2", "dezalgo": "^1.0.4", "once": "^1.4.0" }, "engines": { "node": ">=14.0.0" }, "funding": { "url": "https://ko-fi.com/tunnckoCore/commissions" } }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/fresh": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/fs-extra": { "version": "11.3.5", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.5.tgz", "integrity": "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==", "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" }, "engines": { "node": ">=14.14" } }, "node_modules/fs-mkdirp-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-2.0.1.tgz", "integrity": "sha512-UTOY+59K6IA94tec8Wjqm0FSh5OVudGNB0NL/P6fB3HiE3bYOY3VYBGijsnOHNkQSwC1FKkU77pmq7xp9CskLw==", "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.8", "streamx": "^2.12.0" }, "engines": { "node": ">=10.13.0" } }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-east-asian-width": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz", "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==", "dev": true, "license": "MIT", "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/get-intrinsic": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/get-stream": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", "dev": true, "license": "MIT", "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" }, "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/get-stream/node_modules/is-stream": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", "dev": true, "license": "MIT", "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/git-raw-commits": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-5.0.1.tgz", "integrity": "sha512-Y+csSm2GD/PCSh6Isd/WiMjNAydu0VBiG9J7EdQsNA5P9uXvLayqjmTsNlK5Gs9IhblFZqOU0yid5Il5JPoLiQ==", "dev": true, "license": "MIT", "dependencies": { "@conventional-changelog/git-client": "^2.6.0", "meow": "^13.0.0" }, "bin": { "git-raw-commits": "src/cli.js" }, "engines": { "node": ">=18" } }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, "engines": { "node": ">=10.13.0" } }, "node_modules/glob-stream": { "version": "8.0.3", "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-8.0.3.tgz", "integrity": "sha512-fqZVj22LtFJkHODT+M4N1RJQ3TjnnQhfE9GwZI8qXscYarnhpip70poMldRnP8ipQ/w0B621kOhfc53/J9bd/A==", "dev": true, "license": "MIT", "dependencies": { "@gulpjs/to-absolute-glob": "^4.0.0", "anymatch": "^3.1.3", "fastq": "^1.13.0", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "is-negated-glob": "^1.0.0", "normalize-path": "^3.0.0", "streamx": "^2.12.5" }, "engines": { "node": ">=10.13.0" } }, "node_modules/glob-watcher": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-6.0.0.tgz", "integrity": "sha512-wGM28Ehmcnk2NqRORXFOTOR064L4imSw3EeOqU5bIwUf62eXGwg89WivH6VMahL8zlQHeodzvHpXplrqzrz3Nw==", "dev": true, "license": "MIT", "dependencies": { "async-done": "^2.0.0", "chokidar": "^3.5.3" }, "engines": { "node": ">= 10.13.0" } }, "node_modules/global-directory": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-5.0.0.tgz", "integrity": "sha512-1pgFdhK3J2LeM+dVf2Pd424yHx2ou338lC0ErNP2hPx4j8eW1Sp0XqSjNxtk6Tc4Kr5wlWtSvz8cn2yb7/SG/w==", "dev": true, "license": "MIT", "dependencies": { "ini": "6.0.0" }, "engines": { "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", "dev": true, "license": "MIT", "dependencies": { "global-prefix": "^1.0.1", "is-windows": "^1.0.1", "resolve-dir": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/global-prefix": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", "dev": true, "license": "MIT", "dependencies": { "expand-tilde": "^2.0.2", "homedir-polyfill": "^1.0.1", "ini": "^1.3.4", "is-windows": "^1.0.1", "which": "^1.2.14" }, "engines": { "node": ">=0.10.0" } }, "node_modules/global-prefix/node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true, "license": "ISC" }, "node_modules/global-prefix/node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "bin/which" } }, "node_modules/globals": { "version": "17.6.0", "resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz", "integrity": "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==", "dev": true, "license": "MIT", "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/glogg": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/glogg/-/glogg-2.2.0.tgz", "integrity": "sha512-eWv1ds/zAlz+M1ioHsyKJomfY7jbDDPpwSkv14KQj89bycx1nvK5/2Cj/T9g7kzJcX5Bc7Yv22FjfBZS/jl94A==", "dev": true, "license": "MIT", "dependencies": { "sparkles": "^2.1.0" }, "engines": { "node": ">= 10.13.0" } }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true, "license": "ISC" }, "node_modules/gulp": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/gulp/-/gulp-5.0.1.tgz", "integrity": "sha512-PErok3DZSA5WGMd6XXV3IRNO0mlB+wW3OzhFJLEec1jSERg2j1bxJ6e5Fh6N6fn3FH2T9AP4UYNb/pYlADB9sA==", "dev": true, "license": "MIT", "dependencies": { "glob-watcher": "^6.0.0", "gulp-cli": "^3.1.0", "undertaker": "^2.0.0", "vinyl-fs": "^4.0.2" }, "bin": { "gulp": "bin/gulp.js" }, "engines": { "node": ">=10.13.0" } }, "node_modules/gulp-cli": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-3.1.0.tgz", "integrity": "sha512-zZzwlmEsTfXcxRKiCHsdyjZZnFvXWM4v1NqBJSYbuApkvVKivjcmOS2qruAJ+PkEHLFavcDKH40DPc1+t12a9Q==", "dev": true, "license": "MIT", "dependencies": { "@gulpjs/messages": "^1.1.0", "chalk": "^4.1.2", "copy-props": "^4.0.0", "gulplog": "^2.2.0", "interpret": "^3.1.1", "liftoff": "^5.0.1", "mute-stdout": "^2.0.0", "replace-homedir": "^2.0.0", "semver-greatest-satisfied-range": "^2.0.0", "string-width": "^4.2.3", "v8flags": "^4.0.0", "yargs": "^16.2.0" }, "bin": { "gulp": "bin/gulp.js" }, "engines": { "node": ">=10.13.0" } }, "node_modules/gulp-cli/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/gulp-cli/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/gulp-cli/node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "node_modules/gulp-cli/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, "license": "MIT" }, "node_modules/gulp-cli/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/gulp-cli/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" } }, "node_modules/gulp-cli/node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/gulp-cli/node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" }, "engines": { "node": ">=10" } }, "node_modules/gulp-cli/node_modules/yargs-parser": { "version": "20.2.9", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true, "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/gulplog": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-2.2.0.tgz", "integrity": "sha512-V2FaKiOhpR3DRXZuYdRLn/qiY0yI5XmqbTKrYbdemJ+xOh2d2MOweI/XFgMzd/9+1twdvMwllnZbWZNJ+BOm4A==", "dev": true, "license": "MIT", "dependencies": { "glogg": "^2.2.0" }, "engines": { "node": ">= 10.13.0" } }, "node_modules/gzip-size": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-3.0.0.tgz", "integrity": "sha512-6s8trQiK+OMzSaCSVXX+iqIcLV9tC+E73jrJrJTyS4h/AJhlxHvzFKqM1YLDJWRGgHX8uLkBeXkA0njNj39L4w==", "dev": true, "license": "MIT", "dependencies": { "duplexer": "^0.1.1" }, "engines": { "node": ">=0.12.0" } }, "node_modules/has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/has-ansi/node_modules/ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-tostringtag": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/homedir-polyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", "dev": true, "license": "MIT", "dependencies": { "parse-passwd": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", "dev": true, "license": "MIT", "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" }, "engines": { "node": ">= 0.8" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/express" } }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "license": "MIT", "dependencies": { "agent-base": "6", "debug": "4" }, "engines": { "node": ">= 6" } }, "node_modules/husky": { "version": "9.1.7", "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", "dev": true, "license": "MIT", "bin": { "husky": "bin.js" }, "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/typicode" } }, "node_modules/iconv-lite": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", "dev": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/express" } }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ], "license": "BSD-3-Clause" }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/import-fresh": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" }, "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/import-fresh/node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "license": "MIT", "engines": { "node": ">=0.8.19" } }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true, "license": "ISC" }, "node_modules/ini": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/ini/-/ini-6.0.0.tgz", "integrity": "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==", "dev": true, "license": "ISC", "engines": { "node": "^20.17.0 || >=22.9.0" } }, "node_modules/interpret": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", "dev": true, "license": "MIT", "engines": { "node": ">=10.13.0" } }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.10" } }, "node_modules/is-absolute": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", "dev": true, "license": "MIT", "dependencies": { "is-relative": "^1.0.0", "is-windows": "^1.0.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true, "license": "MIT" }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, "engines": { "node": ">=8" } }, "node_modules/is-core-module": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, "license": "MIT", "dependencies": { "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/is-fullwidth-code-point": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", "dev": true, "license": "MIT", "dependencies": { "get-east-asian-width": "^1.3.1" }, "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", "dev": true, "license": "MIT" }, "node_modules/is-negated-glob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", "integrity": "sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" } }, "node_modules/is-obj": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-plain-obj": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", "dev": true, "license": "MIT", "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-plain-object": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/is-reference": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", "dev": true, "license": "MIT", "dependencies": { "@types/estree": "*" } }, "node_modules/is-relative": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", "dev": true, "license": "MIT", "dependencies": { "is-unc-path": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", "dev": true, "license": "MIT", "dependencies": { "unc-path-regex": "^0.1.2" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-valid-glob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", "integrity": "sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, "license": "ISC" }, "node_modules/isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/jiti": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", "dev": true, "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" } }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true, "license": "MIT" }, "node_modules/js-yaml": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/puzrin" }, { "type": "github", "url": "https://github.com/sponsors/nodeca" } ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { "node": ">=6" } }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true, "license": "MIT" }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true, "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true, "license": "MIT" }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "license": "MIT", "bin": { "json5": "lib/cli.js" }, "engines": { "node": ">=6" } }, "node_modules/jsonfile": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } }, "node_modules/last-run": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/last-run/-/last-run-2.0.0.tgz", "integrity": "sha512-j+y6WhTLN4Itnf9j5ZQos1BGPCS8DAwmgMroR3OzfxAsBxam0hMw7J8M3KqZl0pLQJ1jNnwIexg5DYpC/ctwEQ==", "dev": true, "license": "MIT", "engines": { "node": ">= 10.13.0" } }, "node_modules/lead": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/lead/-/lead-4.0.0.tgz", "integrity": "sha512-DpMa59o5uGUWWjruMp71e6knmwKU3jRBBn1kjuLWN9EeIOxNeSAwvHf03WIl8g/ZMR2oSQC9ej3yeLBwdDc/pg==", "dev": true, "license": "MIT", "engines": { "node": ">=10.13.0" } }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/liftoff": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-5.0.1.tgz", "integrity": "sha512-wwLXMbuxSF8gMvubFcFRp56lkFV69twvbU5vDPbaw+Q+/rF8j0HKjGbIdlSi+LuJm9jf7k9PB+nTxnsLMPcv2Q==", "dev": true, "license": "MIT", "dependencies": { "extend": "^3.0.2", "findup-sync": "^5.0.0", "fined": "^2.0.0", "flagged-respawn": "^2.0.0", "is-plain-object": "^5.0.0", "rechoir": "^0.8.0", "resolve": "^1.20.0" }, "engines": { "node": ">=10.13.0" } }, "node_modules/lightningcss": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", "dev": true, "license": "MPL-2.0", "dependencies": { "detect-libc": "^2.0.3" }, "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "node_modules/lightningcss-android-arm64": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", "cpu": [ "arm64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "android" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-darwin-arm64": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", "cpu": [ "arm64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "darwin" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-darwin-x64": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", "cpu": [ "x64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "darwin" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-freebsd-x64": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", "cpu": [ "x64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "freebsd" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-linux-arm-gnueabihf": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", "cpu": [ "arm" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "linux" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-linux-arm64-gnu": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", "cpu": [ "arm64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "linux" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-linux-arm64-musl": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", "cpu": [ "arm64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "linux" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-linux-x64-gnu": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", "cpu": [ "x64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "linux" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-linux-x64-musl": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", "cpu": [ "x64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "linux" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-win32-arm64-msvc": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", "cpu": [ "arm64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "win32" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-win32-x64-msvc": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", "cpu": [ "x64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "win32" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/limiter": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==", "dev": true }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true, "license": "MIT" }, "node_modules/lint-staged": { "version": "17.0.7", "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-17.0.7.tgz", "integrity": "sha512-JrSobt+tW3rH8IOMi8tDZd3foorM5yPEkLD/V2NxobgHrFfHWGee4MOLVuZeScgxftEwbHrPHIFA/ZL+nUJeuA==", "dev": true, "license": "MIT", "dependencies": { "listr2": "^10.2.1", "picomatch": "^4.0.4", "string-argv": "^0.3.2", "tinyexec": "^1.2.4" }, "bin": { "lint-staged": "bin/lint-staged.js" }, "engines": { "node": ">=22.22.1" }, "funding": { "url": "https://opencollective.com/lint-staged" }, "optionalDependencies": { "yaml": "^2.9.0" } }, "node_modules/listr2": { "version": "10.2.1", "resolved": "https://registry.npmjs.org/listr2/-/listr2-10.2.1.tgz", "integrity": "sha512-7I5knELsJKTUjXG+A6BkKAiGkW1i25fNa/xlUl9hFtk15WbE9jndA89xu5FzQKrY5llajE1hfZZFMILXkDHk/Q==", "dev": true, "license": "MIT", "dependencies": { "cli-truncate": "^5.2.0", "eventemitter3": "^5.0.4", "log-update": "^6.1.0", "rfdc": "^1.4.1", "wrap-ansi": "^10.0.0" }, "engines": { "node": ">=22.13.0" } }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "dev": true, "license": "MIT" }, "node_modules/log-update": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", "dev": true, "license": "MIT", "dependencies": { "ansi-escapes": "^7.0.0", "cli-cursor": "^5.0.0", "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" }, "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/log-update/node_modules/ansi-regex": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/log-update/node_modules/slice-ansi": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" }, "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, "node_modules/log-update/node_modules/string-width": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" }, "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/log-update/node_modules/strip-ansi": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^6.2.2" }, "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/log-update/node_modules/wrap-ansi": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" }, "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "license": "ISC", "dependencies": { "yallist": "^3.0.2" } }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/maxmin": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-2.1.0.tgz", "integrity": "sha512-NWlApBjW9az9qRPaeg7CX4sQBWwytqz32bIEo1PW9pRW+kBP9KLRfJO3UC+TV31EcQZEUq7eMzikC7zt3zPJcw==", "dev": true, "license": "MIT", "dependencies": { "chalk": "^1.0.0", "figures": "^1.0.1", "gzip-size": "^3.0.0", "pretty-bytes": "^3.0.0" }, "engines": { "node": ">=0.12" } }, "node_modules/maxmin/node_modules/ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/maxmin/node_modules/ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/maxmin/node_modules/chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", "has-ansi": "^2.0.0", "strip-ansi": "^3.0.0", "supports-color": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/maxmin/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/maxmin/node_modules/pretty-bytes": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-3.0.1.tgz", "integrity": "sha512-eb7ZAeUTgfh294cElcu51w+OTRp/6ItW758LjwJSK72LDevcuJn0P4eD71PLMDGPwwatXmAmYHTkzvpKlJE3ow==", "dev": true, "license": "MIT", "dependencies": { "number-is-nan": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/maxmin/node_modules/strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/maxmin/node_modules/supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", "dev": true, "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/meow": { "version": "13.2.0", "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", "dev": true, "license": "MIT", "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/merge-descriptors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", "dev": true, "license": "MIT", "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { "node": ">=8.6" } }, "node_modules/micromatch/node_modules/picomatch": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { "node": ">=8.6" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" } }, "node_modules/mimic-function": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", "dev": true, "license": "MIT", "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/minimatch": { "version": "10.2.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "brace-expansion": "^5.0.5" }, "engines": { "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/mrmime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", "dev": true, "license": "MIT", "engines": { "node": ">=10" } }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, "node_modules/multer": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/multer/-/multer-2.1.1.tgz", "integrity": "sha512-mo+QTzKlx8R7E5ylSXxWzGoXoZbOsRMpyitcht8By2KHvMbf3tjwosZ/Mu/XYU6UuJ3VZnODIrak5ZrPiPyB6A==", "dev": true, "license": "MIT", "dependencies": { "append-field": "^1.0.0", "busboy": "^1.6.0", "concat-stream": "^2.0.0", "type-is": "^1.6.18" }, "engines": { "node": ">= 10.16.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/express" } }, "node_modules/multer/node_modules/concat-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", "dev": true, "engines": [ "node >= 6.0" ], "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.0.2", "typedarray": "^0.0.6" } }, "node_modules/mute-stdout": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-2.0.0.tgz", "integrity": "sha512-32GSKM3Wyc8dg/p39lWPKYu8zci9mJFzV1Np9Of0ZEpe6Fhssn/FbI7ywAMd40uX+p3ZKh3T5EeCFv81qS3HmQ==", "dev": true, "license": "MIT", "engines": { "node": ">= 10.13.0" } }, "node_modules/nanoid": { "version": "3.3.12", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/ai" } ], "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, "engines": { "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, "license": "MIT" }, "node_modules/negotiator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/node-releases": { "version": "2.0.36", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", "dev": true, "license": "MIT" }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/now-and-later": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-3.0.0.tgz", "integrity": "sha512-pGO4pzSdaxhWTGkfSfHx3hVzJVslFPwBp2Myq9MYN/ChfJZF87ochMAXnvz6/58RJSf5ik2q9tXprBBrk2cpcg==", "dev": true, "license": "MIT", "dependencies": { "once": "^1.4.0" }, "engines": { "node": ">= 10.13.0" } }, "node_modules/number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/object-inspect": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/object.defaults": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", "integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==", "dev": true, "license": "MIT", "dependencies": { "array-each": "^1.0.1", "array-slice": "^1.0.0", "for-own": "^1.0.0", "isobject": "^3.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", "dev": true, "license": "MIT", "dependencies": { "isobject": "^3.0.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/obug": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", "dev": true, "funding": [ "https://github.com/sponsors/sxzz", "https://opencollective.com/debug" ], "license": "MIT" }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dev": true, "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, "engines": { "node": ">= 0.8" } }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" } }, "node_modules/onetime": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", "dev": true, "license": "MIT", "dependencies": { "mimic-function": "^5.0.0" }, "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, "license": "MIT", "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, "engines": { "node": ">=6" } }, "node_modules/parse-filepath": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", "dev": true, "license": "MIT", "dependencies": { "is-absolute": "^1.0.0", "map-cache": "^0.2.0", "path-root": "^0.1.1" }, "engines": { "node": ">=0.8" } }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true, "license": "MIT" }, "node_modules/path-root": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", "dev": true, "license": "MIT", "dependencies": { "path-root-regex": "^0.1.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/path-root-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/path-to-regexp": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz", "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==", "dev": true, "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/express" } }, "node_modules/pathe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, "license": "MIT" }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, "license": "ISC" }, "node_modules/picomatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/pkijs": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/pkijs/-/pkijs-3.4.0.tgz", "integrity": "sha512-emEcLuomt2j03vxD54giVB4SxTjnsqkU692xZOZXHDVoYyypEm+b3jpiTcc+Cf+myooc+/Ly0z01jqeNHVgJGw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { "@noble/hashes": "1.4.0", "asn1js": "^3.0.6", "bytestreamjs": "^2.0.1", "pvtsutils": "^1.3.6", "pvutils": "^1.1.3", "tslib": "^2.8.1" }, "engines": { "node": ">=16.0.0" } }, "node_modules/pkijs/node_modules/@noble/hashes": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", "dev": true, "license": "MIT", "engines": { "node": ">= 16" }, "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/playwright": { "version": "1.60.0", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.60.0.tgz", "integrity": "sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==", "dev": true, "license": "Apache-2.0", "dependencies": { "playwright-core": "1.60.0" }, "bin": { "playwright": "cli.js" }, "engines": { "node": ">=18" }, "optionalDependencies": { "fsevents": "2.3.2" } }, "node_modules/playwright-core": { "version": "1.60.0", "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.60.0.tgz", "integrity": "sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==", "dev": true, "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, "engines": { "node": ">=18" } }, "node_modules/playwright/node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, "node_modules/pngjs": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==", "dev": true, "license": "MIT", "engines": { "node": ">=14.19.0" } }, "node_modules/postcss": { "version": "8.5.15", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/postcss/" }, { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" }, { "type": "github", "url": "https://github.com/sponsors/ai" } ], "license": "MIT", "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" } }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.8.0" } }, "node_modules/prettier": { "version": "3.8.3", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz", "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", "dev": true, "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, "engines": { "node": ">=14" }, "funding": { "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", "dev": true, "license": "MIT", "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" }, "engines": { "node": ">= 0.10" } }, "node_modules/proxy-from-env": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", "license": "MIT", "engines": { "node": ">=10" } }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/pvtsutils": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz", "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==", "dev": true, "license": "MIT", "dependencies": { "tslib": "^2.8.1" } }, "node_modules/pvutils": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.5.tgz", "integrity": "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==", "dev": true, "license": "MIT", "engines": { "node": ">=16.0.0" } }, "node_modules/qs": { "version": "6.15.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", "dev": true, "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/raw-body": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", "dev": true, "license": "MIT", "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.10" } }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" }, "engines": { "node": ">= 6" } }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, "engines": { "node": ">=8.10.0" } }, "node_modules/readdirp/node_modules/picomatch": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { "node": ">=8.6" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/rechoir": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", "dev": true, "license": "MIT", "dependencies": { "resolve": "^1.20.0" }, "engines": { "node": ">= 10.13.0" } }, "node_modules/reflect-metadata": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", "dev": true, "license": "Apache-2.0" }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", "dev": true, "license": "MIT" }, "node_modules/regenerate-unicode-properties": { "version": "10.2.2", "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz", "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", "dev": true, "license": "MIT", "dependencies": { "regenerate": "^1.4.2" }, "engines": { "node": ">=4" } }, "node_modules/regexpu-core": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz", "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==", "dev": true, "license": "MIT", "dependencies": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.2.2", "regjsgen": "^0.8.0", "regjsparser": "^0.13.0", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.2.1" }, "engines": { "node": ">=4" } }, "node_modules/regjsgen": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", "dev": true, "license": "MIT" }, "node_modules/regjsparser": { "version": "0.13.0", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.0.tgz", "integrity": "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "jsesc": "~3.1.0" }, "bin": { "regjsparser": "bin/parser" } }, "node_modules/remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", "dev": true, "license": "ISC" }, "node_modules/replace-ext": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", "dev": true, "license": "MIT", "engines": { "node": ">= 10" } }, "node_modules/replace-homedir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-2.0.0.tgz", "integrity": "sha512-bgEuQQ/BHW0XkkJtawzrfzHFSN70f/3cNOiHa2QsYxqrjaC30X1k74FJ6xswVBP0sr0SpGIdVFuPwfrYziVeyw==", "dev": true, "license": "MIT", "engines": { "node": ">= 10.13.0" } }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/resolve": { "version": "1.22.11", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", "dev": true, "license": "MIT", "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/resolve-dir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", "dev": true, "license": "MIT", "dependencies": { "expand-tilde": "^2.0.0", "global-modules": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/resolve-options": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-2.0.0.tgz", "integrity": "sha512-/FopbmmFOQCfsCx77BRFdKOniglTiHumLgwvd6IDPihy1GKkadZbgQJBcTb2lMzSR1pndzd96b1nZrreZ7+9/A==", "dev": true, "license": "MIT", "dependencies": { "value-or-function": "^4.0.0" }, "engines": { "node": ">= 10.13.0" } }, "node_modules/restore-cursor": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", "dev": true, "license": "MIT", "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" }, "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" } }, "node_modules/rfdc": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "dev": true, "license": "MIT" }, "node_modules/rolldown": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.1.tgz", "integrity": "sha512-X0KQHljNnEkWNqqiz9zJrGunh1B0HgOxLXvnFpCOcadzcy5qohZ3tqMEUg00vncoRovXuK3ZqCT9KnnKzoInFQ==", "dev": true, "license": "MIT", "dependencies": { "@oxc-project/types": "=0.130.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { "rolldown": "bin/cli.mjs" }, "engines": { "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.1", "@rolldown/binding-darwin-arm64": "1.0.1", "@rolldown/binding-darwin-x64": "1.0.1", "@rolldown/binding-freebsd-x64": "1.0.1", "@rolldown/binding-linux-arm-gnueabihf": "1.0.1", "@rolldown/binding-linux-arm64-gnu": "1.0.1", "@rolldown/binding-linux-arm64-musl": "1.0.1", "@rolldown/binding-linux-ppc64-gnu": "1.0.1", "@rolldown/binding-linux-s390x-gnu": "1.0.1", "@rolldown/binding-linux-x64-gnu": "1.0.1", "@rolldown/binding-linux-x64-musl": "1.0.1", "@rolldown/binding-openharmony-arm64": "1.0.1", "@rolldown/binding-wasm32-wasi": "1.0.1", "@rolldown/binding-win32-arm64-msvc": "1.0.1", "@rolldown/binding-win32-x64-msvc": "1.0.1" } }, "node_modules/rollup": { "version": "4.61.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.61.0.tgz", "integrity": "sha512-T9mWdbWfQtp0B5lv/HX+wrhYsmXRlcWnXXmJbXqKJhlRaoS6KMhq0gpyzW4UJfclcxrEdLnTgjT2NjruLONu0g==", "dev": true, "license": "MIT", "dependencies": { "@types/estree": "1.0.9" }, "bin": { "rollup": "dist/bin/rollup" }, "engines": { "node": ">=18.0.0", "npm": ">=8.0.0" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.61.0", "@rollup/rollup-android-arm64": "4.61.0", "@rollup/rollup-darwin-arm64": "4.61.0", "@rollup/rollup-darwin-x64": "4.61.0", "@rollup/rollup-freebsd-arm64": "4.61.0", "@rollup/rollup-freebsd-x64": "4.61.0", "@rollup/rollup-linux-arm-gnueabihf": "4.61.0", "@rollup/rollup-linux-arm-musleabihf": "4.61.0", "@rollup/rollup-linux-arm64-gnu": "4.61.0", "@rollup/rollup-linux-arm64-musl": "4.61.0", "@rollup/rollup-linux-loong64-gnu": "4.61.0", "@rollup/rollup-linux-loong64-musl": "4.61.0", "@rollup/rollup-linux-ppc64-gnu": "4.61.0", "@rollup/rollup-linux-ppc64-musl": "4.61.0", "@rollup/rollup-linux-riscv64-gnu": "4.61.0", "@rollup/rollup-linux-riscv64-musl": "4.61.0", "@rollup/rollup-linux-s390x-gnu": "4.61.0", "@rollup/rollup-linux-x64-gnu": "4.61.0", "@rollup/rollup-linux-x64-musl": "4.61.0", "@rollup/rollup-openbsd-x64": "4.61.0", "@rollup/rollup-openharmony-arm64": "4.61.0", "@rollup/rollup-win32-arm64-msvc": "4.61.0", "@rollup/rollup-win32-ia32-msvc": "4.61.0", "@rollup/rollup-win32-x64-gnu": "4.61.0", "@rollup/rollup-win32-x64-msvc": "4.61.0", "fsevents": "~2.3.2" } }, "node_modules/rollup-plugin-bundle-size": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/rollup-plugin-bundle-size/-/rollup-plugin-bundle-size-1.0.3.tgz", "integrity": "sha512-aWj0Pvzq90fqbI5vN1IvUrlf4utOqy+AERYxwWjegH1G8PzheMnrRIgQ5tkwKVtQMDP0bHZEACW/zLDF+XgfXQ==", "dev": true, "license": "MIT", "dependencies": { "chalk": "^1.1.3", "maxmin": "^2.1.0" } }, "node_modules/rollup-plugin-bundle-size/node_modules/ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/rollup-plugin-bundle-size/node_modules/ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/rollup-plugin-bundle-size/node_modules/chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", "has-ansi": "^2.0.0", "strip-ansi": "^3.0.0", "supports-color": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/rollup-plugin-bundle-size/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/rollup-plugin-bundle-size/node_modules/strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/rollup-plugin-bundle-size/node_modules/supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", "dev": true, "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/router": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", "dev": true, "license": "MIT", "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" }, "engines": { "node": ">= 18" } }, "node_modules/router/node_modules/is-promise": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", "dev": true, "license": "MIT" }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "license": "MIT" }, "node_modules/selfsigned": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-5.5.0.tgz", "integrity": "sha512-ftnu3TW4+3eBfLRFnDEkzGxSF/10BJBkaLJuBHZX0kiPS7bRdlpZGu6YGt4KngMkdTwJE6MbjavFpqHvqVt+Ew==", "dev": true, "license": "MIT", "dependencies": { "@peculiar/x509": "^1.14.2", "pkijs": "^3.3.3" }, "engines": { "node": ">=18" } }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/semver-greatest-satisfied-range": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-2.0.0.tgz", "integrity": "sha512-lH3f6kMbwyANB7HuOWRMlLCa2itaCrZJ+SAqqkSZrZKO/cAsk2EOyaKHUtNkVLFyFW9pct22SFesFp3Z7zpA0g==", "dev": true, "license": "MIT", "dependencies": { "sver": "^1.8.3" }, "engines": { "node": ">= 10.13.0" } }, "node_modules/send": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", "dev": true, "license": "MIT", "dependencies": { "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.1", "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.2" }, "engines": { "node": ">= 18" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/express" } }, "node_modules/send/node_modules/mime-db": { "version": "1.54.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/send/node_modules/mime-types": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", "dev": true, "license": "MIT", "dependencies": { "mime-db": "^1.54.0" }, "engines": { "node": ">=18" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/express" } }, "node_modules/serialize-javascript": { "version": "7.0.5", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.0.5.tgz", "integrity": "sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==", "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=20.0.0" } }, "node_modules/serve-static": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", "dev": true, "license": "MIT", "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" }, "engines": { "node": ">= 18" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/express" } }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", "dev": true, "license": "ISC" }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/side-channel-list": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/side-channel-map": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/side-channel-weakmap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/siginfo": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true, "license": "ISC" }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, "license": "ISC", "engines": { "node": ">=14" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/sirv": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", "dev": true, "license": "MIT", "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" }, "engines": { "node": ">=18" } }, "node_modules/slice-ansi": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-8.0.0.tgz", "integrity": "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg==", "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^6.2.3", "is-fullwidth-code-point": "^5.1.0" }, "engines": { "node": ">=20" }, "funding": { "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, "node_modules/smob": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/smob/-/smob-1.6.1.tgz", "integrity": "sha512-KAkBqZl3c2GvNgNhcoyJae1aKldDW0LO279wF9bk1PnluRTETKBq0WyzRXxEhoQLk56yHaOY4JCBEKDuJIET5g==", "dev": true, "license": "MIT", "engines": { "node": ">=20.0.0" } }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "node_modules/sparkles": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-2.1.0.tgz", "integrity": "sha512-r7iW1bDw8R/cFifrD3JnQJX0K1jqT0kprL48BiBpLZLJPmAm34zsVBsK5lc7HirZYZqMW65dOXZgbAGt/I6frg==", "dev": true, "license": "MIT", "engines": { "node": ">= 10.13.0" } }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true, "license": "MIT" }, "node_modules/statuses": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/std-env": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.1.0.tgz", "integrity": "sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==", "dev": true, "license": "MIT" }, "node_modules/stream-composer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stream-composer/-/stream-composer-1.0.2.tgz", "integrity": "sha512-bnBselmwfX5K10AH6L4c8+S5lgZMWI7ZYrz2rvYjCPB2DIMC4Ig8OpxGpNJSxRZ58oti7y1IcNvjBAz9vW5m4w==", "dev": true, "license": "MIT", "dependencies": { "streamx": "^2.13.2" } }, "node_modules/stream-exhaust": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", "dev": true, "license": "MIT" }, "node_modules/stream-throttle": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/stream-throttle/-/stream-throttle-0.1.3.tgz", "integrity": "sha512-889+B9vN9dq7/vLbGyuHeZ6/ctf5sNuGWsDy89uNxkFTAgzy0eK7+w5fL3KLNRTkLle7EgZGvHUphZW0Q26MnQ==", "dev": true, "license": "BSD-3-Clause", "dependencies": { "commander": "^2.2.0", "limiter": "^1.0.5" }, "bin": { "throttleproxy": "bin/throttleproxy.js" }, "engines": { "node": ">= 0.10.0" } }, "node_modules/stream-throttle/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, "license": "MIT" }, "node_modules/streamsearch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", "dev": true, "engines": { "node": ">=10.0.0" } }, "node_modules/streamx": { "version": "2.23.0", "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.23.0.tgz", "integrity": "sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==", "dev": true, "license": "MIT", "dependencies": { "events-universal": "^1.0.0", "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" } }, "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "~5.1.0" } }, "node_modules/string_decoder/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, "license": "MIT" }, "node_modules/string-argv": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", "dev": true, "license": "MIT", "engines": { "node": ">=0.6.19" } }, "node_modules/string-width": { "version": "8.2.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.1.tgz", "integrity": "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==", "dev": true, "license": "MIT", "dependencies": { "get-east-asian-width": "^1.5.0", "strip-ansi": "^7.1.2" }, "engines": { "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/string-width/node_modules/ansi-regex": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/string-width/node_modules/strip-ansi": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^6.2.2" }, "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/sver": { "version": "1.8.4", "resolved": "https://registry.npmjs.org/sver/-/sver-1.8.4.tgz", "integrity": "sha512-71o1zfzyawLfIWBOmw8brleKyvnbn73oVHNCsu51uPMz/HWiKkkXsI31JjHW5zqXEqnPYkIiHd8ZmL7FCimLEA==", "dev": true, "license": "MIT", "optionalDependencies": { "semver": "^6.3.0" } }, "node_modules/teex": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", "dev": true, "license": "MIT", "dependencies": { "streamx": "^2.12.5" } }, "node_modules/terser": { "version": "5.46.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" }, "engines": { "node": ">=10" } }, "node_modules/terser/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, "license": "MIT" }, "node_modules/text-decoder": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz", "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "b4a": "^1.6.4" } }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", "dev": true, "license": "MIT" }, "node_modules/tinyexec": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", "dev": true, "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/tinyglobby": { "version": "0.2.16", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" }, "engines": { "node": ">=12.0.0" }, "funding": { "url": "https://github.com/sponsors/SuperchupuDev" } }, "node_modules/tinyrainbow": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", "dev": true, "license": "MIT", "engines": { "node": ">=14.0.0" } }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, "engines": { "node": ">=8.0" } }, "node_modules/to-through": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/to-through/-/to-through-3.0.0.tgz", "integrity": "sha512-y8MN937s/HVhEoBU1SxfHC+wxCHkV1a9gW8eAdTadYh/bGyesZIVcbjI+mSpFbSVwQici/XjBjuUyri1dnXwBw==", "dev": true, "license": "MIT", "dependencies": { "streamx": "^2.12.5" }, "engines": { "node": ">=10.13.0" } }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true, "license": "MIT", "engines": { "node": ">=0.6" } }, "node_modules/totalist": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, "license": "0BSD" }, "node_modules/tsyringe": { "version": "4.10.0", "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.10.0.tgz", "integrity": "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==", "dev": true, "license": "MIT", "dependencies": { "tslib": "^1.9.3" }, "engines": { "node": ">= 6.0.0" } }, "node_modules/tsyringe/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true, "license": "0BSD" }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, "engines": { "node": ">= 0.8.0" } }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" }, "engines": { "node": ">= 0.6" } }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", "dev": true, "license": "MIT" }, "node_modules/typescript": { "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { "node": ">=14.17" } }, "node_modules/unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/undertaker": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-2.0.0.tgz", "integrity": "sha512-tO/bf30wBbTsJ7go80j0RzA2rcwX6o7XPBpeFcb+jzoeb4pfMM2zUeSDIkY1AWqeZabWxaQZ/h8N9t35QKDLPQ==", "dev": true, "license": "MIT", "dependencies": { "bach": "^2.0.1", "fast-levenshtein": "^3.0.0", "last-run": "^2.0.0", "undertaker-registry": "^2.0.0" }, "engines": { "node": ">=10.13.0" } }, "node_modules/undertaker-registry": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-2.0.0.tgz", "integrity": "sha512-+hhVICbnp+rlzZMgxXenpvTxpuvA67Bfgtt+O9WOE5jo7w/dyiF1VmoZVIHvP2EkUjsyKyTwYKlLhA+j47m1Ew==", "dev": true, "license": "MIT", "engines": { "node": ">= 10.13.0" } }, "node_modules/undertaker/node_modules/fast-levenshtein": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-3.0.0.tgz", "integrity": "sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ==", "dev": true, "license": "MIT", "dependencies": { "fastest-levenshtein": "^1.0.7" } }, "node_modules/undici-types": { "version": "7.24.6", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", "dev": true, "license": "MIT", "peer": true }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", "dev": true, "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/unicode-match-property-ecmascript": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", "dev": true, "license": "MIT", "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" }, "engines": { "node": ">=4" } }, "node_modules/unicode-match-property-value-ecmascript": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz", "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", "dev": true, "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/unicode-property-aliases-ecmascript": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", "dev": true, "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "license": "MIT", "engines": { "node": ">= 10.0.0" } }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/update-browserslist-db": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/browserslist" }, { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" }, { "type": "github", "url": "https://github.com/sponsors/ai" } ], "license": "MIT", "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" }, "peerDependencies": { "browserslist": ">= 4.21.0" } }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true, "license": "MIT" }, "node_modules/v8flags": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-4.0.1.tgz", "integrity": "sha512-fcRLaS4H/hrZk9hYwbdRM35D0U8IYMfEClhXxCivOojl+yTRAZH3Zy2sSy6qVCiGbV9YAtPssP6jaChqC9vPCg==", "dev": true, "license": "MIT", "engines": { "node": ">= 10.13.0" } }, "node_modules/value-or-function": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-4.0.0.tgz", "integrity": "sha512-aeVK81SIuT6aMJfNo9Vte8Dw0/FZINGBV8BfCraGtqVxIeLAEhJyoWs8SmvRVmXfGss2PmmOwZCuBPbZR+IYWg==", "dev": true, "license": "MIT", "engines": { "node": ">= 10.13.0" } }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/vinyl": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.1.tgz", "integrity": "sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==", "dev": true, "license": "MIT", "dependencies": { "clone": "^2.1.2", "remove-trailing-separator": "^1.1.0", "replace-ext": "^2.0.0", "teex": "^1.0.1" }, "engines": { "node": ">=10.13.0" } }, "node_modules/vinyl-contents": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/vinyl-contents/-/vinyl-contents-2.0.0.tgz", "integrity": "sha512-cHq6NnGyi2pZ7xwdHSW1v4Jfnho4TEGtxZHw01cmnc8+i7jgR6bRnED/LbrKan/Q7CvVLbnvA5OepnhbpjBZ5Q==", "dev": true, "license": "MIT", "dependencies": { "bl": "^5.0.0", "vinyl": "^3.0.0" }, "engines": { "node": ">=10.13.0" } }, "node_modules/vinyl-fs": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-4.0.2.tgz", "integrity": "sha512-XRFwBLLTl8lRAOYiBqxY279wY46tVxLaRhSwo3GzKEuLz1giffsOquWWboD/haGf5lx+JyTigCFfe7DWHoARIA==", "dev": true, "license": "MIT", "dependencies": { "fs-mkdirp-stream": "^2.0.1", "glob-stream": "^8.0.3", "graceful-fs": "^4.2.11", "iconv-lite": "^0.6.3", "is-valid-glob": "^1.0.0", "lead": "^4.0.0", "normalize-path": "3.0.0", "resolve-options": "^2.0.0", "stream-composer": "^1.0.2", "streamx": "^2.14.0", "to-through": "^3.0.0", "value-or-function": "^4.0.0", "vinyl": "^3.0.1", "vinyl-sourcemap": "^2.0.0" }, "engines": { "node": ">=10.13.0" } }, "node_modules/vinyl-fs/node_modules/iconv-lite": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/vinyl-sourcemap": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-2.0.0.tgz", "integrity": "sha512-BAEvWxbBUXvlNoFQVFVHpybBbjW1r03WhohJzJDSfgrrK5xVYIDTan6xN14DlyImShgDRv2gl9qhM6irVMsV0Q==", "dev": true, "license": "MIT", "dependencies": { "convert-source-map": "^2.0.0", "graceful-fs": "^4.2.10", "now-and-later": "^3.0.0", "streamx": "^2.12.5", "vinyl": "^3.0.0", "vinyl-contents": "^2.0.0" }, "engines": { "node": ">=10.13.0" } }, "node_modules/vite": { "version": "8.0.13", "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.13.tgz", "integrity": "sha512-MFtjBYgzmSxmgA4RAfjIyXWpGe1oALnjgUTzzV7QLx/TKxCzjtMH6Fd9/eVK+5Fg1qNoz5VAwsmMs/NofrmJvw==", "dev": true, "license": "MIT", "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.14", "rolldown": "1.0.1", "tinyglobby": "^0.2.16" }, "bin": { "vite": "bin/vite.js" }, "engines": { "node": "^20.19.0 || >=22.12.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.18", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "peerDependenciesMeta": { "@types/node": { "optional": true }, "@vitejs/devtools": { "optional": true }, "esbuild": { "optional": true }, "jiti": { "optional": true }, "less": { "optional": true }, "sass": { "optional": true }, "sass-embedded": { "optional": true }, "stylus": { "optional": true }, "sugarss": { "optional": true }, "terser": { "optional": true }, "tsx": { "optional": true }, "yaml": { "optional": true } } }, "node_modules/vitest": { "version": "4.1.8", "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.8.tgz", "integrity": "sha512-flY6ScbCIt9HThs+C5HS7jvGOB560DJtk/Z15IQROTA6zEy49Nh8T/dofWTQL+n3vswqn87sbJNiuqw1SDp5Ig==", "dev": true, "license": "MIT", "dependencies": { "@vitest/expect": "4.1.8", "@vitest/mocker": "4.1.8", "@vitest/pretty-format": "4.1.8", "@vitest/runner": "4.1.8", "@vitest/snapshot": "4.1.8", "@vitest/spy": "4.1.8", "@vitest/utils": "4.1.8", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "bin": { "vitest": "vitest.mjs" }, "engines": { "node": "^20.0.0 || ^22.0.0 || >=24.0.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.8", "@vitest/browser-preview": "4.1.8", "@vitest/browser-webdriverio": "4.1.8", "@vitest/coverage-istanbul": "4.1.8", "@vitest/coverage-v8": "4.1.8", "@vitest/ui": "4.1.8", "happy-dom": "*", "jsdom": "*", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "@edge-runtime/vm": { "optional": true }, "@opentelemetry/api": { "optional": true }, "@types/node": { "optional": true }, "@vitest/browser-playwright": { "optional": true }, "@vitest/browser-preview": { "optional": true }, "@vitest/browser-webdriverio": { "optional": true }, "@vitest/coverage-istanbul": { "optional": true }, "@vitest/coverage-v8": { "optional": true }, "@vitest/ui": { "optional": true }, "happy-dom": { "optional": true }, "jsdom": { "optional": true }, "vite": { "optional": false } } }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" }, "engines": { "node": ">= 8" } }, "node_modules/why-is-node-running": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", "dev": true, "license": "MIT", "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" }, "engines": { "node": ">=8" } }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/workerpool": { "version": "9.3.4", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", "dev": true, "license": "Apache-2.0" }, "node_modules/wrap-ansi": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-10.0.0.tgz", "integrity": "sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==", "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^6.2.3", "string-width": "^8.2.0", "strip-ansi": "^7.1.2" }, "engines": { "node": ">=20" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/wrap-ansi/node_modules/ansi-regex": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/wrap-ansi/node_modules/strip-ansi": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^6.2.2" }, "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true, "license": "ISC" }, "node_modules/ws": { "version": "8.20.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { "optional": true }, "utf-8-validate": { "optional": true } } }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, "license": "ISC" }, "node_modules/yaml": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", "dev": true, "license": "ISC", "optional": true, "bin": { "yaml": "bin.mjs" }, "engines": { "node": ">= 14.6" }, "funding": { "url": "https://github.com/sponsors/eemeli" } }, "node_modules/yargs": { "version": "18.0.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", "dev": true, "license": "MIT", "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "string-width": "^7.2.0", "y18n": "^5.0.5", "yargs-parser": "^22.0.0" }, "engines": { "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/yargs-parser": { "version": "22.0.0", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", "dev": true, "license": "ISC", "engines": { "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/yargs/node_modules/ansi-regex": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/yargs/node_modules/string-width": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" }, "engines": { "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/yargs/node_modules/strip-ansi": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^6.2.2" }, "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "license": "MIT", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } } } } axios-axios-2d06f96/package.json000066400000000000000000000146201521272452000166110ustar00rootroot00000000000000{ "name": "axios", "version": "1.18.0", "description": "Promise based HTTP client for the browser and node.js", "main": "./dist/node/axios.cjs", "module": "./index.js", "type": "module", "types": "index.d.ts", "jsdelivr": "dist/axios.min.js", "unpkg": "dist/axios.min.js", "typings": "./index.d.ts", "exports": { ".": { "types": { "require": "./index.d.cts", "default": "./index.d.ts" }, "bun": { "require": "./dist/node/axios.cjs", "default": "./index.js" }, "react-native": { "require": "./dist/browser/axios.cjs", "default": "./dist/esm/axios.js" }, "browser": { "require": "./dist/browser/axios.cjs", "default": "./index.js" }, "default": { "require": "./dist/node/axios.cjs", "default": "./index.js" } }, "./lib/adapters/http.js": "./lib/adapters/http.js", "./lib/adapters/xhr.js": "./lib/adapters/xhr.js", "./unsafe/*": "./lib/*", "./unsafe/core/settle.js": "./lib/core/settle.js", "./unsafe/core/buildFullPath.js": "./lib/core/buildFullPath.js", "./unsafe/helpers/isAbsoluteURL.js": "./lib/helpers/isAbsoluteURL.js", "./unsafe/helpers/buildURL.js": "./lib/helpers/buildURL.js", "./unsafe/helpers/combineURLs.js": "./lib/helpers/combineURLs.js", "./unsafe/adapters/http.js": "./lib/adapters/http.js", "./unsafe/adapters/xhr.js": "./lib/adapters/xhr.js", "./unsafe/utils.js": "./lib/utils.js", "./package.json": "./package.json", "./dist/browser/axios.cjs": "./dist/browser/axios.cjs", "./dist/node/axios.cjs": "./dist/node/axios.cjs" }, "browser": { "./dist/node/axios.cjs": "./dist/browser/axios.cjs", "./lib/adapters/http.js": "./lib/helpers/null.js", "./lib/platform/node/index.js": "./lib/platform/browser/index.js", "./lib/platform/node/classes/FormData.js": "./lib/helpers/null.js" }, "react-native": { "./dist/node/axios.cjs": "./dist/browser/axios.cjs", "./lib/adapters/http.js": "./lib/helpers/null.js", "./lib/platform/node/index.js": "./lib/platform/browser/index.js", "./lib/platform/node/classes/FormData.js": "./lib/helpers/null.js" }, "repository": { "type": "git", "url": "https://github.com/axios/axios.git" }, "keywords": [ "xhr", "http", "ajax", "promise", "node", "browser", "fetch", "rest", "api", "client" ], "author": "Matt Zabriskie", "contributors": [ "Matt Zabriskie (https://github.com/mzabriskie)", "Jay (https://github.com/jasonsaayman)", "Dmitriy Mozgovoy (https://github.com/DigitalBrainJS)", "Nick Uraltsev (https://github.com/nickuraltsev)", "Emily Morehouse (https://github.com/emilyemorehouse)", "Rubén Norte (https://github.com/rubennorte)", "Justin Beckwith (https://github.com/JustinBeckwith)", "Martti Laine (https://github.com/codeclown)", "Xianming Zhong (https://github.com/chinesedfan)", "Shaan Majid (https://github.com/shaanmajid)", "Willian Agostini (https://github.com/WillianAgostini)", "Remco Haszing (https://github.com/remcohaszing)", "Rikki Gibson (https://github.com/RikkiGibson)" ], "sideEffects": false, "license": "MIT", "bugs": { "url": "https://github.com/axios/axios/issues" }, "homepage": "https://axios-http.com", "files": [ "index.js", "index.d.ts", "index.d.cts", "CHANGELOG.md", "MIGRATION_GUIDE.md", "lib/", "dist/axios.js", "dist/axios.min.js", "dist/axios.min.js.map", "dist/esm/axios.js", "dist/esm/axios.min.js", "dist/esm/axios.min.js.map", "dist/browser/axios.cjs", "dist/node/axios.cjs" ], "scripts": { "build": "gulp clear && cross-env NODE_ENV=production rollup -c -m", "version": "npm run build && git add package.json", "preversion": "gulp version", "test": "npm run test:vitest", "test:vitest": "vitest run", "test:vitest:unit": "vitest run --project unit", "test:vitest:browser": "vitest run --project browser", "test:vitest:browser:headless": "vitest run --project browser-headless", "test:vitest:watch": "vitest", "test:smoke:cjs:vitest": "npm --prefix tests/smoke/cjs run test:smoke:cjs:mocha", "test:smoke:esm:vitest": "npm --prefix tests/smoke/esm run test:smoke:esm:vitest", "test:smoke:deno": "deno task --cwd tests/smoke/deno test", "test:smoke:bun": "bun test --cwd tests/smoke/bun", "test:module:cjs": "npm --prefix tests/module/cjs run test:module:cjs", "test:module:esm": "npm --prefix tests/module/esm run test:module:esm", "docs:dev": "cd docs && npm run docs:dev", "start": "node ./sandbox/server.js", "examples": "node ./examples/server.js", "lint": "eslint lib/**/*.js", "fix": "eslint --fix lib/**/*.js", "prepare": "husky" }, "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.5", "https-proxy-agent": "^5.0.1", "proxy-from-env": "^2.1.0" }, "devDependencies": { "@babel/core": "^7.29.0", "@babel/preset-env": "^7.29.5", "@commitlint/cli": "^21.0.1", "@commitlint/config-conventional": "^21.0.1", "@eslint/js": "^10.0.1", "@rollup/plugin-alias": "^6.0.0", "@rollup/plugin-babel": "^7.0.0", "@rollup/plugin-commonjs": "^29.0.2", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.3", "@rollup/plugin-terser": "^1.0.0", "@vitest/browser": "^4.1.7", "@vitest/browser-playwright": "^4.1.7", "abortcontroller-polyfill": "^1.7.8", "acorn": "^8.16.0", "body-parser": "^2.2.2", "chalk": "^5.6.2", "cross-env": "^10.1.0", "dev-null": "^0.1.1", "eslint": "^10.4.0", "express": "^5.2.1", "formdata-node": "^6.0.3", "formidable": "^3.5.4", "fs-extra": "^11.3.4", "get-stream": "^9.0.1", "globals": "^17.6.0", "gulp": "^5.0.1", "husky": "^9.1.7", "lint-staged": "^17.0.5", "minimist": "^1.2.8", "multer": "^2.1.1", "playwright": "^1.60.0", "prettier": "^3.8.3", "rollup": "^4.60.4", "rollup-plugin-bundle-size": "^1.0.3", "selfsigned": "^5.5.0", "stream-throttle": "^0.1.3", "typescript": "^5.9.3", "vitest": "^4.1.7" }, "commitlint": { "rules": { "header-max-length": [ 2, "always", 130 ] }, "extends": [ "@commitlint/config-conventional" ] }, "lint-staged": { "*.{js,cjs,mjs,ts,json,md,yml,yaml}": "prettier --write" } }axios-axios-2d06f96/rollup.config.js000066400000000000000000000063661521272452000174520ustar00rootroot00000000000000import resolve from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; import terser from '@rollup/plugin-terser'; import json from '@rollup/plugin-json'; import { babel } from '@rollup/plugin-babel'; import bundleSize from 'rollup-plugin-bundle-size'; import aliasPlugin from '@rollup/plugin-alias'; import path from 'path'; import { createRequire } from 'module'; const require = createRequire(import.meta.url); const lib = require('./package.json'); const outputFileName = 'axios'; const name = 'axios'; const namedInput = './index.js'; const defaultInput = './lib/axios.js'; const buildConfig = ({ es5, browser = true, minifiedVersion = true, alias, ...config }) => { const { file } = config.output; const ext = path.extname(file); const basename = path.basename(file, ext); const extArr = ext.split('.'); extArr.shift(); const build = ({ minified }) => ({ input: namedInput, ...config, output: { ...config.output, file: `${path.dirname(file)}/${basename}.${(minified ? ['min', ...extArr] : extArr).join('.')}`, }, plugins: [ aliasPlugin({ entries: alias || [], }), json(), resolve({ browser }), commonjs(), minified && terser({ maxWorkers: 1, }), minified && bundleSize(), ...(es5 ? [ babel({ babelHelpers: 'bundled', presets: ['@babel/preset-env'], }), ] : []), ...(config.plugins || []), ], }); const configs = [build({ minified: false })]; if (minifiedVersion) { configs.push(build({ minified: true })); } return configs; }; const nodeCjsExternal = (id) => { if (id === 'proxy-from-env') { return false; } if (id.startsWith('.') || path.isAbsolute(id) || id.startsWith('\0')) { return false; } return true; }; export default async () => { const year = new Date().getFullYear(); const banner = `/*! Axios v${lib.version} Copyright (c) ${year} ${lib.author} and contributors */`; return [ // browser ESM bundle for CDN ...buildConfig({ input: namedInput, output: { file: `dist/esm/${outputFileName}.js`, format: 'esm', exports: 'named', banner, }, }), // Browser UMD bundle for CDN ...buildConfig({ input: defaultInput, es5: true, output: { file: `dist/${outputFileName}.js`, name, format: 'umd', exports: 'default', banner, }, }), // Browser CJS bundle ...buildConfig({ input: defaultInput, es5: false, minifiedVersion: false, output: { file: `dist/browser/${name}.cjs`, name, format: 'cjs', exports: 'default', banner, }, }), // Node.js commonjs bundle (transpiled for Node 12) { input: defaultInput, external: nodeCjsExternal, output: { file: `dist/node/${name}.cjs`, format: 'cjs', exports: 'default', banner, }, plugins: [ resolve(), commonjs(), babel({ babelHelpers: 'bundled', presets: [['@babel/preset-env', { targets: { node: '12' } }]], }), ], }, ]; }; axios-axios-2d06f96/sandbox/000077500000000000000000000000001521272452000157565ustar00rootroot00000000000000axios-axios-2d06f96/sandbox/client.html000066400000000000000000000334561521272452000201350ustar00rootroot00000000000000 AXIOS | Sandbox
        axios

         | Sandbox

        Input

        Request

        No Data

        Response

        No Data

        Error

        None
        axios-axios-2d06f96/sandbox/client.js000066400000000000000000000006121521272452000175710ustar00rootroot00000000000000import axios from '../index.js'; const URL = 'http://127.0.0.1:3000/api'; const BODY = { foo: 'bar', baz: 1234, }; function handleSuccess(data) { console.log(data); } function handleFailure(data) { console.log('error', data); } // GET axios.get(URL, { params: BODY }).then(handleSuccess).catch(handleFailure); // POST axios.post(URL, BODY).then(handleSuccess).catch(handleFailure); axios-axios-2d06f96/sandbox/server.js000066400000000000000000000060101521272452000176170ustar00rootroot00000000000000import fs from 'fs'; import path from 'path'; import http from 'http'; let server; /** * Pipes a file to the HTTP response. * * @param {http.ServerResponse} res - The HTTP response object. * @param {string} file - The relative path to the file to be served. * @param {string} [type] - Optional MIME type for the response. */ function pipeFileToResponse(res, file, type) { if (type) { res.writeHead(200, { 'Content-Type': type, }); } fs.createReadStream(path.join(path.resolve(), 'sandbox', file)).pipe(res); } /** * Handles API requests to /api. * * Collects request data, parses it as JSON, and returns a JSON response * containing the request URL, method, headers, and parsed data. * * @param {http.IncomingMessage} req - The HTTP request object. * @param {http.ServerResponse} res - The HTTP response object. */ function handleApiRequest(req, res) { let status; let result; let data = ''; req.on('data', (chunk) => { data += chunk; }); req.on('end', () => { try { status = 200; result = { url: req.url, data: data ? JSON.parse(data) : undefined, method: req.method, headers: req.headers, }; } catch (e) { console.error('Error:', e.message); status = 400; result = { error: e.message, }; } res.writeHead(status, { 'Content-Type': 'application/json', }); res.end(JSON.stringify(result)); }); } /** * Handles incoming HTTP requests. * * Serves static files like index.html and axios.js, or routes API requests to * handleApiRequest. Responds with 404 for unrecognized paths. * * @param {http.IncomingMessage} req - The HTTP request object. * @param {http.ServerResponse} res - The HTTP response object. */ function requestHandler(req, res) { req.setEncoding('utf8'); const parsed = new URL(req.url, 'http://localhost'); const pathname = parsed.pathname; console.log('[' + new Date() + ']', req.method, pathname); if (pathname === '/') { pathname = '/index.html'; } switch (pathname) { case '/index.html': pipeFileToResponse(res, './client.html', 'text/html'); break; case '/axios.js': pipeFileToResponse(res, '../dist/axios.js', 'text/javascript'); break; case '/axios.js.map': pipeFileToResponse(res, '../dist/axios.js.map', 'text/javascript'); break; case '/api': handleApiRequest(req, res); break; default: res.writeHead(404); res.end('

        404 Not Found

        '); break; } } const PORT = 3000; // Create and start the HTTP server server = http.createServer(requestHandler); server.listen(PORT, () => { console.log(`Listening on localhost:${PORT}...`); }); /** * Handles server errors, e.g., port already in use. * * @param {NodeJS.ErrnoException} error - The server error object. */ server.on('error', (error) => { if (error.code === 'EADDRINUSE') { console.log(`Address localhost:${PORT} in use. Please retry when the port is available!`); server.close(); } }); axios-axios-2d06f96/scripts/000077500000000000000000000000001521272452000160075ustar00rootroot00000000000000axios-axios-2d06f96/scripts/axios-build-instance.js000066400000000000000000000011711521272452000223670ustar00rootroot00000000000000import axios from '../index.js'; const { GITHUB_TOKEN } = process.env; if (GITHUB_TOKEN) { console.log(`[GITHUB_TOKEN OK]`); } else { console.warn(`[GITHUB_TOKEN is not defined]`); } const defaultTransform = axios.defaults.transformRequest; export default axios.create({ transformRequest: [ defaultTransform[0], function (data) { console.log( `[${this.method.toUpperCase()}] Request [${new URL(axios.getUri(this)).pathname}]` ); return data; }, ], baseURL: 'https://api.github.com/', headers: { ...(GITHUB_TOKEN ? { Authorization: `token ${GITHUB_TOKEN}` } : {}), }, }); axios-axios-2d06f96/tests/000077500000000000000000000000001521272452000154625ustar00rootroot00000000000000axios-axios-2d06f96/tests/README.md000066400000000000000000000077071521272452000167540ustar00rootroot00000000000000# Test Contribution Guide This guide explains how to contribute tests inside the `tests` directory. It is intentionally scoped to this directory only. ## Tests Directory Layout ```text tests/ browser/ # browser runtime tests setup/ # shared test setup utilities smoke/ # package-compat smoke suites (esm + cjs) unit/ # focused unit/behavior tests ``` Use the runtime-first layout already present in this directory: - Put browser-runtime behavior in `tests/browser`. - Put non-browser focused tests in `tests/unit`. - Put packaging/compatibility smoke checks in `tests/smoke/esm/tests` and `tests/smoke/cjs/tests`. - Reuse helpers from `tests/setup` instead of duplicating setup logic. ## File Naming Conventions Follow the existing file patterns: - Unit tests: `*.test.js` - Browser tests: `*.browser.test.js` - ESM smoke tests: `*.smoke.test.js` - CJS smoke tests: `*.smoke.test.cjs` When adding a new test, match the nearest existing file name pattern in the same subdirectory. ## Suite-Specific Authoring Patterns ### Unit (`tests/unit`) - Keep tests focused on one behavior or API surface. - For adapter/network behavior, prefer local test servers using utilities from `tests/setup/server.js`. - Ensure server cleanup with `try/finally` so tests do not leak resources. - Keep fixtures close to the tests that use them (see `tests/unit/adapters` for examples). Representative files: - `tests/unit/adapters/http.test.js` - `tests/unit/adapters/fetch.test.js` - `tests/unit/regression.test.js` ### Browser (`tests/browser`) - Use local in-file `MockXMLHttpRequest` style mocks when testing request behavior. - Replace global XHR in `beforeEach` and restore it in `afterEach`. - Reset spies/mocks in cleanup hooks to keep tests isolated. - Keep assertions centered on observable request/response behavior. Representative files: - `tests/browser/requests.browser.test.js` - `tests/browser/adapter.browser.test.js` - `tests/browser/defaults.browser.test.js` ### Smoke (`tests/smoke`) - Keep ESM and CJS smoke coverage aligned for compatibility-sensitive behavior. - If you add a new smoke scenario in one format, add the equivalent in the other format. - Keep smoke tests small and focused on import/runtime behavior and critical request flows. Representative files: - `tests/smoke/esm/tests/fetch.smoke.test.js` - `tests/smoke/cjs/tests/fetch.smoke.test.cjs` - `tests/smoke/esm/tests/basic.smoke.test.js` - `tests/smoke/cjs/tests/basic.smoke.test.cjs` ## Shared Setup Utilities (`tests/setup`) Use shared helpers before introducing new setup code: - `tests/setup/server.js` - Server lifecycle helpers: `startHTTPServer`, `stopHTTPServer`, `stopAllTrackedHTTPServers` - Timing helpers: `setTimeoutAsync` - Data/stream helpers used by adapter tests - `tests/setup/browser.setup.js` - Browser cleanup hook (`afterEach`) for clearing test DOM state General expectation: if a helper can be reused by multiple tests in this directory, add or extend it in `tests/setup` instead of copying setup code between test files. ## Fixtures and Test Data - Prefer colocated fixtures near the test files that need them. - Keep fixture names explicit and stable. - For matrix-like scenarios, prefer concise table-driven cases inside the test file when practical. Examples of colocated fixtures: - `tests/unit/adapters/cert.pem` - `tests/unit/adapters/key.pem` - `tests/unit/adapters/axios.png` ## Contributor Checklist Before opening a PR for tests in this directory: - File is placed in the correct suite directory (`unit`, `browser`, or `smoke`). - File name matches the local pattern (`*.test.js`, `*.browser.test.js`, `*.smoke.test.js`, `*.smoke.test.cjs`). - Test setup/teardown is explicit and leaves no global/server state behind. - Shared setup logic uses `tests/setup` helpers where possible. - Smoke tests remain ESM/CJS consistent when behavior is format-sensitive. - Fixtures are colocated and minimal. - Assertions are deterministic and avoid unnecessary timing/network flakiness. axios-axios-2d06f96/tests/browser/000077500000000000000000000000001521272452000171455ustar00rootroot00000000000000axios-axios-2d06f96/tests/browser/adapter.browser.test.js000066400000000000000000000107321521272452000235660ustar00rootroot00000000000000import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import axios from '../../index.js'; class MockXMLHttpRequest { constructor() { this.readyState = 0; this.status = 0; this.statusText = ''; this.responseText = ''; this.response = null; this.onreadystatechange = null; this.onloadend = null; this.upload = { addEventListener() {}, }; this.requestHeaders = {}; } open(method, url, async = true) { this.method = method; this.url = url; this.async = async; } setRequestHeader(key, value) { this.requestHeaders[key] = value; } addEventListener() {} getAllResponseHeaders() { return ''; } send(data) { this.params = data; requests.push(this); } respondWith({ status = 200, statusText = 'OK', responseText = '' } = {}) { this.status = status; this.statusText = statusText; this.responseText = responseText; this.response = responseText; this.readyState = 4; queueMicrotask(() => { if (this.onloadend) { this.onloadend(); } else if (this.onreadystatechange) { this.onreadystatechange(); } }); } abort() {} } let requests = []; let OriginalXMLHttpRequest; const sleep = (ms = 0) => new Promise((resolve) => setTimeout(resolve, ms)); const waitForRequest = async (timeoutMs = 1000) => { const start = Date.now(); while (Date.now() - start < timeoutMs) { const request = requests.at(-1); if (request) { return request; } await sleep(0); } throw new Error('Expected an XHR request to be sent'); }; describe('adapter (vitest browser)', () => { beforeEach(() => { requests = []; OriginalXMLHttpRequest = window.XMLHttpRequest; window.XMLHttpRequest = MockXMLHttpRequest; }); afterEach(() => { window.XMLHttpRequest = OriginalXMLHttpRequest; axios.interceptors.request.handlers = []; axios.interceptors.response.handlers = []; }); it('should support custom adapter', async () => { const responsePromise = axios('/foo', { adapter(config) { return new Promise((resolve) => { const request = new XMLHttpRequest(); request.open('GET', '/bar'); request.onreadystatechange = function onReadyStateChange() { resolve({ config, request, }); }; request.send(null); }); }, }); const request = await waitForRequest(); expect(request.url).toBe('/bar'); request.respondWith(); await responsePromise; }); it('should execute adapter code synchronously', async () => { let asyncFlag = false; const responsePromise = axios('/foo', { adapter(config) { return new Promise((resolve) => { const request = new XMLHttpRequest(); request.open('GET', '/bar'); request.onreadystatechange = function onReadyStateChange() { resolve({ config, request, }); }; expect(asyncFlag).toBe(false); request.send(null); }); }, }); asyncFlag = true; const request = await waitForRequest(); request.respondWith(); await responsePromise; }); it('should execute adapter code asynchronously when interceptor is present', async () => { let asyncFlag = false; axios.interceptors.request.use((config) => { config.headers.async = 'async it!'; return config; }); const responsePromise = axios('/foo', { adapter(config) { return new Promise((resolve) => { const request = new XMLHttpRequest(); request.open('GET', '/bar'); request.onreadystatechange = function onReadyStateChange() { resolve({ config, request, }); }; expect(asyncFlag).toBe(true); request.send(null); }); }, }); asyncFlag = true; const request = await waitForRequest(); request.respondWith(); await responsePromise; }); it('should sanitize request headers containing CRLF characters', async () => { const responsePromise = axios('/foo', { headers: { 'x-test': '\tok\r\nInjected: yes ', }, }); const request = await waitForRequest(); expect(request.requestHeaders['x-test']).toBe('okInjected: yes'); expect(request.requestHeaders.Injected).toBeUndefined(); request.respondWith(); await responsePromise; }); }); axios-axios-2d06f96/tests/browser/basicAuth.browser.test.js000066400000000000000000000075721521272452000240610ustar00rootroot00000000000000import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import axios from '../../index.js'; class MockXMLHttpRequest { constructor() { this.requestHeaders = {}; this.responseHeaders = ''; this.readyState = 0; this.status = 0; this.statusText = ''; this.responseText = ''; this.response = null; this.onreadystatechange = null; this.onloadend = null; this.upload = { addEventListener() {}, }; } open(method, url, async = true) { this.method = method; this.url = url; this.async = async; } setRequestHeader(key, value) { this.requestHeaders[key] = value; } addEventListener() {} getAllResponseHeaders() { return this.responseHeaders; } send(data) { this.params = data; requests.push(this); } respondWith({ status = 200, statusText = 'OK', responseText = '', responseHeaders = '' } = {}) { this.status = status; this.statusText = statusText; this.responseText = responseText; this.response = responseText; this.responseHeaders = responseHeaders; this.readyState = 4; queueMicrotask(() => { if (this.onloadend) { this.onloadend(); } else if (this.onreadystatechange) { this.onreadystatechange(); } }); } abort() {} } let requests = []; let OriginalXMLHttpRequest; const startRequest = (...args) => { const promise = axios(...args); const request = requests.at(-1); expect(request).toBeDefined(); return { request, promise }; }; const flushSuccess = async (request, promise) => { request.respondWith({ status: 200 }); await promise; }; describe('basicAuth (vitest browser)', () => { beforeEach(() => { requests = []; OriginalXMLHttpRequest = window.XMLHttpRequest; window.XMLHttpRequest = MockXMLHttpRequest; }); afterEach(() => { window.XMLHttpRequest = OriginalXMLHttpRequest; }); it('should accept HTTP Basic auth with username/password', async () => { const { request, promise } = startRequest('/foo', { auth: { username: 'Aladdin', password: 'open sesame', }, }); expect(request.requestHeaders.Authorization).toBe('Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=='); await flushSuccess(request, promise); }); it('should accept HTTP Basic auth credentials without the password parameter', async () => { const { request, promise } = startRequest('/foo', { auth: { username: 'Aladdin', }, }); expect(request.requestHeaders.Authorization).toBe('Basic QWxhZGRpbjo='); await flushSuccess(request, promise); }); it('should accept HTTP Basic auth credentials with non-Latin1 characters in password', async () => { const { request, promise } = startRequest('/foo', { auth: { username: 'Aladdin', password: 'open ßç£☃sesame', }, }); expect(request.requestHeaders.Authorization).toBe('Basic QWxhZGRpbjpvcGVuIMOfw6fCo+KYg3Nlc2FtZQ=='); await flushSuccess(request, promise); }); it('should ignore inherited nested auth fields', async () => { Object.defineProperty(Object.prototype, 'username', { value: 'inherited-user', configurable: true, }); Object.defineProperty(Object.prototype, 'password', { value: 'inherited-pass', configurable: true, }); try { const { request, promise } = startRequest('/foo', { auth: {}, }); expect(request.requestHeaders.Authorization).toBe('Basic Og=='); await flushSuccess(request, promise); } finally { delete Object.prototype.username; delete Object.prototype.password; } }); it('should fail to encode HTTP Basic auth credentials with non-Latin1 characters in username', async () => { await expect(axios('/foo', { auth: { username: 'Aladßç£☃din', password: 'open sesame', }, })).rejects.toThrow(/character/i); }); }); axios-axios-2d06f96/tests/browser/cancel.browser.test.js000066400000000000000000000136721521272452000234010ustar00rootroot00000000000000import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import axios from '../../index.js'; class MockXMLHttpRequest { constructor() { this.requestHeaders = {}; this.responseHeaders = ''; this.readyState = 0; this.status = 0; this.statusText = ''; this.responseText = ''; this.response = null; this.onreadystatechange = null; this.onloadend = null; this.onabort = null; this.upload = { addEventListener() {}, }; } open(method, url, async = true) { this.method = method; this.url = url; this.async = async; } setRequestHeader(key, value) { this.requestHeaders[key] = value; } addEventListener() {} getAllResponseHeaders() { return this.responseHeaders; } send(data) { this.params = data; requests.push(this); } respondWith({ status = 200, statusText = 'OK', responseText = '', responseHeaders = '' } = {}) { this.status = status; this.statusText = statusText; this.responseText = responseText; this.response = responseText; this.responseHeaders = responseHeaders; this.readyState = 4; queueMicrotask(() => { if (this.onloadend) { this.onloadend(); } else if (this.onreadystatechange) { this.onreadystatechange(); } }); } abort() { this.statusText = 'abort'; if (this.onabort) { this.onabort(); } } } let requests = []; let OriginalXMLHttpRequest; const waitForRequest = async (timeoutMs = 1000) => { const start = Date.now(); while (Date.now() - start < timeoutMs) { const request = requests.at(-1); if (request) { return request; } await Promise.resolve(); } throw new Error('Expected an XHR request to be sent'); }; describe('cancel (vitest browser)', () => { beforeEach(() => { requests = []; OriginalXMLHttpRequest = window.XMLHttpRequest; window.XMLHttpRequest = MockXMLHttpRequest; }); afterEach(() => { window.XMLHttpRequest = OriginalXMLHttpRequest; }); describe('when called before sending request', () => { it('rejects Promise with a CanceledError object', async () => { const source = axios.CancelToken.source(); source.cancel('Operation has been canceled.'); const error = await axios .get('/foo', { cancelToken: source.token, }) .catch((thrown) => thrown); expect(axios.isCancel(error)).toBe(true); expect(error.message).toBe('Operation has been canceled.'); expect(requests).toHaveLength(0); }); }); describe('when called after request has been sent', () => { it('rejects Promise with a CanceledError object', async () => { const source = axios.CancelToken.source(); const promise = axios.get('/foo/bar', { cancelToken: source.token, }); const request = await waitForRequest(); // Call cancel() after the request has been sent, but before response is received. source.cancel('Operation has been canceled.'); request.respondWith({ status: 200, responseText: 'OK', }); const error = await promise.catch((thrown) => thrown); expect(axios.isCancel(error)).toBe(true); expect(error.message).toBe('Operation has been canceled.'); }); it('calls abort on request object', async () => { const source = axios.CancelToken.source(); const promise = axios.get('/foo/bar', { cancelToken: source.token, }); const request = await waitForRequest(); // Call cancel() after the request has been sent, but before response is received. source.cancel(); await promise.catch(() => undefined); expect(request.statusText).toBe('abort'); }); }); it('supports cancellation using AbortController signal', async () => { const controller = new AbortController(); const promise = axios.get('/foo/bar', { signal: controller.signal, }); const request = await waitForRequest(); // Call abort() after the request has been sent, but before response is received. controller.abort(); setTimeout(() => { request.respondWith({ status: 200, responseText: 'OK', }); }, 0); const error = await promise.catch((thrown) => thrown); expect(axios.isCancel(error)).toBe(true); }); describe('listener cleanup on error paths', () => { for (const { label, trigger } of [ { label: 'network error', trigger: (r) => r.onerror(new Error('Network Error')) }, { label: 'timeout', trigger: (r) => r.ontimeout() }, { label: 'browser abort', trigger: (r) => r.onabort() }, ]) { it(`unsubscribes cancelToken listener after ${label}`, async () => { const source = axios.CancelToken.source(); const promise = axios .get('/foo/bar', { cancelToken: source.token }) .catch((thrown) => thrown); const request = await waitForRequest(); trigger(request); await promise; expect(source.token._listeners || []).toEqual([]); }); } it('removes AbortSignal listener after network error', async () => { const controller = new AbortController(); let listenerCount = 0; const nativeAdd = controller.signal.addEventListener.bind(controller.signal); const nativeRemove = controller.signal.removeEventListener.bind(controller.signal); controller.signal.addEventListener = (type, fn, options) => { if (type === 'abort') listenerCount++; return nativeAdd(type, fn, options); }; controller.signal.removeEventListener = (type, fn, options) => { if (type === 'abort') listenerCount--; return nativeRemove(type, fn, options); }; const promise = axios .get('/foo/bar', { signal: controller.signal }) .catch((thrown) => thrown); const request = await waitForRequest(); request.onerror(new Error('Network Error')); await promise; expect(listenerCount).toBe(0); }); }); }); axios-axios-2d06f96/tests/browser/cancelToken.browser.test.js000066400000000000000000000052501521272452000243730ustar00rootroot00000000000000import { describe, expect, it } from 'vitest'; import CancelToken from '../../lib/cancel/CancelToken.js'; import CanceledError from '../../lib/cancel/CanceledError.js'; describe('CancelToken (vitest browser)', () => { describe('constructor', () => { it('throws when executor is not specified', () => { expect(() => new CancelToken()).toThrowError( new TypeError('executor must be a function.') ); }); it('throws when executor is not a function', () => { expect(() => new CancelToken(123)).toThrowError( new TypeError('executor must be a function.') ); }); }); describe('reason', () => { it('returns a CanceledError if cancellation has been requested', () => { let cancel; const token = new CancelToken((c) => { cancel = c; }); cancel('Operation has been canceled.'); expect(token.reason).toBeInstanceOf(CanceledError); expect(token.reason?.message).toBe('Operation has been canceled.'); }); it('returns undefined if cancellation has not been requested', () => { const token = new CancelToken(() => {}); expect(token.reason).toBeUndefined(); }); }); describe('promise', () => { it('resolves when cancellation is requested', async () => { let cancel; const token = new CancelToken((c) => { cancel = c; }); cancel('Operation has been canceled.'); const reason = await token.promise; expect(reason).toBeInstanceOf(CanceledError); expect(reason.message).toBe('Operation has been canceled.'); }); }); describe('throwIfRequested', () => { it('throws if cancellation has been requested', () => { let cancel; const token = new CancelToken((c) => { cancel = c; }); cancel('Operation has been canceled.'); expect(() => token.throwIfRequested()).toThrow(CanceledError); expect(() => token.throwIfRequested()).toThrow('Operation has been canceled.'); }); it('does not throw if cancellation has not been requested', () => { const token = new CancelToken(() => {}); expect(() => token.throwIfRequested()).not.toThrow(); }); }); describe('source', () => { it('returns an object containing token and cancel function', () => { const source = CancelToken.source(); expect(source.token).toBeInstanceOf(CancelToken); expect(source.cancel).toBeTypeOf('function'); expect(source.token.reason).toBeUndefined(); source.cancel('Operation has been canceled.'); expect(source.token.reason).toBeInstanceOf(CanceledError); expect(source.token.reason?.message).toBe('Operation has been canceled.'); }); }); }); axios-axios-2d06f96/tests/browser/cookies.browser.test.js000066400000000000000000000046541521272452000236100ustar00rootroot00000000000000import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import cookies from '../../lib/helpers/cookies.js'; const clearAllCookies = () => { const expiry = new Date(Date.now() - 86400000).toUTCString(); for (const cookie of document.cookie.split(';')) { const name = cookie.split('=')[0].trim(); if (!name) { continue; } // Clear both default-path and root-path cookies for the same key. document.cookie = `${name}=; expires=${expiry}`; document.cookie = `${name}=; expires=${expiry}; path=/`; } }; describe('helpers::cookies (vitest browser)', () => { beforeEach(() => { clearAllCookies(); }); afterEach(() => { clearAllCookies(); }); it('writes cookies', () => { cookies.write('foo', 'baz'); expect(document.cookie).toBe('foo=baz'); }); it('reads cookies', () => { cookies.write('foo', 'abc'); cookies.write('bar', 'def'); expect(cookies.read('foo')).toBe('abc'); expect(cookies.read('bar')).toBe('def'); }); it('reads cookies when the cookie separator has no following space', () => { const descriptor = Object.getOwnPropertyDescriptor(document, 'cookie'); Object.defineProperty(document, 'cookie', { configurable: true, get() { return 'foo=abc;bar=def'; }, }); try { expect(cookies.read('bar')).toBe('def'); } finally { if (descriptor) { Object.defineProperty(document, 'cookie', descriptor); } else { delete document.cookie; } } }); it('removes cookies', () => { cookies.write('foo', 'bar'); cookies.remove('foo'); expect(cookies.read('foo')).toBeNull(); }); it('uri encodes values', () => { cookies.write('foo', 'bar baz%'); expect(document.cookie).toBe('foo=bar%20baz%25'); }); it('matches cookie names exactly even when the name contains regex metacharacters', () => { // previously cookies.read built a RegExp by interpolating // the requested name. Metacharacters could match a different cookie or trigger // catastrophic backtracking. A name such as "X.Y" must not match a cookie called // "XAY" set by the same site. cookies.write('XAY', 'wrong'); expect(cookies.read('X.Y')).toBeNull(); }); it('does not return a partial match for a name that is a prefix of another cookie', () => { cookies.write('xsrf-token-extra', 'wrong'); expect(cookies.read('xsrf-token')).toBeNull(); }); }); axios-axios-2d06f96/tests/browser/defaults.browser.test.js000066400000000000000000000175141521272452000237620ustar00rootroot00000000000000import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import axios from '../../index.js'; import defaults from '../../lib/defaults/index.js'; import AxiosHeaders from '../../lib/core/AxiosHeaders.js'; class MockXMLHttpRequest { constructor() { this.requestHeaders = {}; this.responseHeaders = ''; this.readyState = 0; this.status = 0; this.statusText = ''; this.responseText = ''; this.response = null; this.onreadystatechange = null; this.onloadend = null; this.upload = { addEventListener() {}, }; } open(method, url, async = true) { this.method = method; this.url = url; this.async = async; } setRequestHeader(key, value) { this.requestHeaders[key] = value; } addEventListener() {} getAllResponseHeaders() { return this.responseHeaders; } send(data) { this.params = data; requests.push(this); } respondWith({ status = 200, statusText = 'OK', responseText = '', responseHeaders = '' } = {}) { this.status = status; this.statusText = statusText; this.responseText = responseText; this.response = responseText; this.responseHeaders = responseHeaders; this.readyState = 4; queueMicrotask(() => { if (this.onloadend) { this.onloadend(); } else if (this.onreadystatechange) { this.onreadystatechange(); } }); } abort() {} } const XSRF_COOKIE_NAME = 'CUSTOM-XSRF-TOKEN'; let requests = []; let OriginalXMLHttpRequest; const getLastRequest = () => { const request = requests.at(-1); expect(request).toBeDefined(); return request; }; const finishRequest = async (request, promise) => { request.respondWith({ status: 200 }); await promise; }; describe('defaults (vitest browser)', () => { beforeEach(() => { requests = []; OriginalXMLHttpRequest = window.XMLHttpRequest; window.XMLHttpRequest = MockXMLHttpRequest; }); afterEach(() => { window.XMLHttpRequest = OriginalXMLHttpRequest; delete axios.defaults.baseURL; delete axios.defaults.headers.get['X-CUSTOM-HEADER']; delete axios.defaults.headers.post['X-CUSTOM-HEADER']; document.cookie = `${XSRF_COOKIE_NAME}=;expires=${new Date(Date.now() - 86400000).toUTCString()}`; }); it('should transform request json', () => { expect(defaults.transformRequest[0]({ foo: 'bar' }, new AxiosHeaders())).toBe('{"foo":"bar"}'); }); it("should also transform request json when 'Content-Type' is 'application/json'", () => { const headers = new AxiosHeaders({ 'Content-Type': 'application/json', }); expect(defaults.transformRequest[0](JSON.stringify({ foo: 'bar' }), headers)).toBe('{"foo":"bar"}'); expect(defaults.transformRequest[0]([42, 43], headers)).toBe('[42,43]'); expect(defaults.transformRequest[0]('foo', headers)).toBe('"foo"'); expect(defaults.transformRequest[0](42, headers)).toBe('42'); expect(defaults.transformRequest[0](true, headers)).toBe('true'); expect(defaults.transformRequest[0](false, headers)).toBe('false'); expect(defaults.transformRequest[0](null, headers)).toBe('null'); }); it("should transform the plain data object to a FormData instance when header is 'multipart/form-data'", () => { const headers = new AxiosHeaders({ 'Content-Type': 'multipart/form-data', }); const transformed = defaults.transformRequest[0]({ x: 1 }, headers); expect(transformed).toBeInstanceOf(FormData); }); it('should do nothing to request string', () => { expect(defaults.transformRequest[0]('foo=bar', new AxiosHeaders())).toBe('foo=bar'); }); it('should transform response json', () => { const data = defaults.transformResponse[0].call(defaults, '{"foo":"bar"}'); expect(typeof data).toBe('object'); expect(data.foo).toBe('bar'); }); it('should do nothing to response string', () => { expect(defaults.transformResponse[0]('foo=bar')).toBe('foo=bar'); }); it('should use global defaults config', async () => { const promise = axios('/foo'); const request = getLastRequest(); expect(request.url).toBe('/foo'); await finishRequest(request, promise); }); it('should use modified defaults config', async () => { axios.defaults.baseURL = 'http://example.com/'; const promise = axios('/foo'); const request = getLastRequest(); expect(request.url).toBe('http://example.com/foo'); await finishRequest(request, promise); }); it('should use request config', async () => { const promise = axios('/foo', { baseURL: 'http://www.example.com', }); const request = getLastRequest(); expect(request.url).toBe('http://www.example.com/foo'); await finishRequest(request, promise); }); it('should use default config for custom instance', async () => { const instance = axios.create({ xsrfCookieName: XSRF_COOKIE_NAME, xsrfHeaderName: 'X-CUSTOM-XSRF-TOKEN', }); document.cookie = `${instance.defaults.xsrfCookieName}=foobarbaz`; const promise = instance.get('/foo'); const request = getLastRequest(); expect(request.requestHeaders[instance.defaults.xsrfHeaderName]).toBe('foobarbaz'); await finishRequest(request, promise); }); it('should use GET headers', async () => { axios.defaults.headers.get['X-CUSTOM-HEADER'] = 'foo'; const promise = axios.get('/foo'); const request = getLastRequest(); expect(request.requestHeaders['X-CUSTOM-HEADER']).toBe('foo'); await finishRequest(request, promise); }); it('should use POST headers', async () => { axios.defaults.headers.post['X-CUSTOM-HEADER'] = 'foo'; const promise = axios.post('/foo', {}); const request = getLastRequest(); expect(request.requestHeaders['X-CUSTOM-HEADER']).toBe('foo'); await finishRequest(request, promise); }); it('should use header config', async () => { const instance = axios.create({ headers: { common: { 'X-COMMON-HEADER': 'commonHeaderValue', }, get: { 'X-GET-HEADER': 'getHeaderValue', }, post: { 'X-POST-HEADER': 'postHeaderValue', }, }, }); const promise = instance.get('/foo', { headers: { 'X-FOO-HEADER': 'fooHeaderValue', 'X-BAR-HEADER': 'barHeaderValue', }, }); const request = getLastRequest(); expect(request.requestHeaders).toEqual( AxiosHeaders.concat(defaults.headers.common, defaults.headers.get, { 'X-COMMON-HEADER': 'commonHeaderValue', 'X-GET-HEADER': 'getHeaderValue', 'X-FOO-HEADER': 'fooHeaderValue', 'X-BAR-HEADER': 'barHeaderValue', }).toJSON() ); await finishRequest(request, promise); }); it('should be used by custom instance if set before instance created', async () => { axios.defaults.baseURL = 'http://example.org/'; const instance = axios.create(); const promise = instance.get('/foo'); const request = getLastRequest(); expect(request.url).toBe('http://example.org/foo'); await finishRequest(request, promise); }); it('should not be used by custom instance if set after instance created', async () => { const instance = axios.create(); axios.defaults.baseURL = 'http://example.org/'; const promise = instance.get('/foo/users'); const request = getLastRequest(); expect(request.url).toBe('/foo/users'); await finishRequest(request, promise); }); it('should resistant to ReDoS attack', async () => { const instance = axios.create(); const start = performance.now(); const slashes = '/'.repeat(100000); instance.defaults.baseURL = `/${slashes}bar/`; const promise = instance.get('/foo'); const request = getLastRequest(); const elapsedTimeMs = performance.now() - start; expect(elapsedTimeMs).toBeLessThan(20); expect(request.url).toBe(`/${slashes}bar/foo`); await finishRequest(request, promise); }); }); axios-axios-2d06f96/tests/browser/formdata.browser.test.js000066400000000000000000000043361521272452000237460ustar00rootroot00000000000000import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import axios from '../../index.js'; class MockXMLHttpRequest { constructor() { this.requestHeaders = {}; this.responseHeaders = ''; this.readyState = 0; this.status = 0; this.statusText = ''; this.responseText = ''; this.response = null; this.onreadystatechange = null; this.onloadend = null; this.upload = { addEventListener() {}, }; } open(method, url, async = true) { this.method = method; this.url = url; this.async = async; } setRequestHeader(key, value) { this.requestHeaders[key] = value; } addEventListener() {} getAllResponseHeaders() { return this.responseHeaders; } send(data) { this.params = data; requests.push(this); } respondWith({ status = 200, statusText = 'OK', responseText = '', responseHeaders = '' } = {}) { this.status = status; this.statusText = statusText; this.responseText = responseText; this.response = responseText; this.responseHeaders = responseHeaders; this.readyState = 4; queueMicrotask(() => { if (this.onloadend) { this.onloadend(); } else if (this.onreadystatechange) { this.onreadystatechange(); } }); } abort() {} } let requests = []; let OriginalXMLHttpRequest; const getLastRequest = () => { const request = requests.at(-1); expect(request).toBeDefined(); return request; }; describe('formdata (vitest browser)', () => { beforeEach(() => { requests = []; OriginalXMLHttpRequest = window.XMLHttpRequest; window.XMLHttpRequest = MockXMLHttpRequest; }); afterEach(() => { window.XMLHttpRequest = OriginalXMLHttpRequest; }); it('should allow FormData posting', async () => { const responsePromise = axios.postForm('/foo', { a: 'foo', b: 'bar', }); const request = getLastRequest(); expect(request.params).toBeInstanceOf(FormData); expect(Object.fromEntries(request.params.entries())).toEqual({ a: 'foo', b: 'bar', }); request.respondWith({ status: 200, responseText: '{}', responseHeaders: 'Content-Type: application/json', }); await responsePromise; }); }); axios-axios-2d06f96/tests/browser/headers.browser.test.js000066400000000000000000000152441521272452000235640ustar00rootroot00000000000000import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import axios, { AxiosHeaders } from '../../index.js'; class MockXMLHttpRequest { constructor() { this.requestHeaders = {}; this.readyState = 0; this.status = 0; this.statusText = ''; this.responseText = ''; this.response = null; this.onreadystatechange = null; this.onloadend = null; this.upload = { addEventListener() {}, }; } open(method, url, async = true) { this.method = method; this.url = url; this.async = async; } setRequestHeader(key, value) { this.requestHeaders[key] = value; } addEventListener() {} getAllResponseHeaders() { return ''; } send(data) { this.params = data; requests.push(this); } respondWith({ status = 200, statusText = 'OK', responseText = '' } = {}) { this.status = status; this.statusText = statusText; this.responseText = responseText; this.response = responseText; this.readyState = 4; queueMicrotask(() => { if (this.onloadend) { this.onloadend(); } else if (this.onreadystatechange) { this.onreadystatechange(); } }); } abort() {} } let requests = []; let OriginalXMLHttpRequest; const getLastRequest = () => { const request = requests.at(-1); expect(request).toBeDefined(); return request; }; const finishRequest = async (request, promise) => { request.respondWith({ status: 200 }); await promise; }; function testHeaderValue(headers, key, val) { let found = false; for (const k in headers) { if (k.toLowerCase() === key.toLowerCase()) { found = true; expect(headers[k]).toBe(val); break; } } if (!found) { if (typeof val === 'undefined') { expect(Object.prototype.hasOwnProperty.call(headers, key)).toBe(false); } else { throw new Error(`${key} was not found in headers`); } } } describe('headers (vitest browser)', () => { beforeEach(() => { requests = []; OriginalXMLHttpRequest = window.XMLHttpRequest; window.XMLHttpRequest = MockXMLHttpRequest; }); afterEach(() => { window.XMLHttpRequest = OriginalXMLHttpRequest; }); it('should default common headers', async () => { const headers = axios.defaults.headers.common; const promise = axios('/foo'); const request = getLastRequest(); for (const key in headers) { if (Object.prototype.hasOwnProperty.call(headers, key)) { expect(request.requestHeaders[key]).toBe(headers[key]); } } await finishRequest(request, promise); }); it('should allow request interceptors to encode Unicode header values before XHR sends them', async () => { const instance = axios.create({ adapter: 'xhr' }); instance.interceptors.request.use((config) => { config.headers.oprtName = encodeURIComponent(config.headers.oprtName); return config; }); const promise = instance.get('/foo', { headers: { oprtName: '请求用户', }, }); await new Promise((resolve) => setTimeout(resolve)); const request = getLastRequest(); expect(request.requestHeaders.oprtName).toBe(encodeURIComponent('请求用户')); await finishRequest(request, promise); }); it('should sanitize unencoded Unicode headers before passing them to XHR', async () => { const promise = axios.get('/foo', { adapter: 'xhr', headers: { oprtName: '请求用户', }, }); const request = getLastRequest(); expect(request.requestHeaders.oprtName).toBe(''); await finishRequest(request, promise); }); it('should respect common Content-Type header', async () => { const instance = axios.create(); instance.defaults.headers.common['Content-Type'] = 'application/custom'; const promise = instance.patch('/foo', ''); const request = getLastRequest(); expect(request.requestHeaders['Content-Type']).toBe('application/custom'); await finishRequest(request, promise); }); it('should add extra headers for post', async () => { const headers = AxiosHeaders.from(axios.defaults.headers.common).toJSON(); const promise = axios.post('/foo', 'fizz=buzz'); const request = getLastRequest(); for (const key in headers) { expect(request.requestHeaders[key]).toBe(headers[key]); } await finishRequest(request, promise); }); it('should reset headers by null or explicit undefined', async () => { const promise = axios.create({ headers: { common: { 'x-header-a': 'a', 'x-header-b': 'b', 'x-header-c': 'c', }, }, }).post( '/foo', { fizz: 'buzz' }, { headers: { 'Content-Type': null, 'x-header-a': null, 'x-header-b': undefined, }, } ); const request = getLastRequest(); testHeaderValue(request.requestHeaders, 'Content-Type', undefined); testHeaderValue(request.requestHeaders, 'x-header-a', undefined); testHeaderValue(request.requestHeaders, 'x-header-b', undefined); testHeaderValue(request.requestHeaders, 'x-header-c', 'c'); await finishRequest(request, promise); }); it('should use application/json when posting an object', async () => { const promise = axios.post('/foo/bar', { firstName: 'foo', lastName: 'bar', }); const request = getLastRequest(); testHeaderValue(request.requestHeaders, 'Content-Type', 'application/json'); await finishRequest(request, promise); }); it('should remove content-type if data is empty', async () => { const promise = axios.post('/foo'); const request = getLastRequest(); testHeaderValue(request.requestHeaders, 'Content-Type', undefined); await finishRequest(request, promise); }); it('should preserve content-type if data is false', async () => { const promise = axios.post('/foo', false); const request = getLastRequest(); testHeaderValue(request.requestHeaders, 'Content-Type', 'application/x-www-form-urlencoded'); await finishRequest(request, promise); }); it('should allow an AxiosHeaders instance to be used as the value of the headers option', async () => { const instance = axios.create({ headers: new AxiosHeaders({ xFoo: 'foo', xBar: 'bar', }), }); const promise = instance.get('/foo', { headers: { XFOO: 'foo2', xBaz: 'baz', }, }); const request = getLastRequest(); expect(request.requestHeaders.xFoo).toBe('foo2'); expect(request.requestHeaders.xBar).toBe('bar'); expect(request.requestHeaders.xBaz).toBe('baz'); expect(request.requestHeaders.XFOO).toBeUndefined(); await finishRequest(request, promise); }); }); axios-axios-2d06f96/tests/browser/instance.browser.test.js000066400000000000000000000137101521272452000237510ustar00rootroot00000000000000import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import axios from '../../index.js'; class MockXMLHttpRequest { constructor() { this.requestHeaders = {}; this.responseHeaders = ''; this.readyState = 0; this.status = 0; this.statusText = ''; this.responseText = ''; this.response = null; this.onreadystatechange = null; this.onloadend = null; this.upload = { addEventListener() {}, }; } open(method, url, async = true) { this.method = method; this.url = url; this.async = async; } setRequestHeader(key, value) { this.requestHeaders[key] = value; } addEventListener() {} getAllResponseHeaders() { return this.responseHeaders; } send(data) { this.params = data; requests.push(this); } respondWith({ status = 200, statusText = 'OK', responseText = '', responseHeaders = '' } = {}) { this.status = status; this.statusText = statusText; this.responseText = responseText; this.response = responseText; this.responseHeaders = responseHeaders; this.readyState = 4; queueMicrotask(() => { if (this.onloadend) { this.onloadend(); } else if (this.onreadystatechange) { this.onreadystatechange(); } }); } } let requests = []; let OriginalXMLHttpRequest; const getLastRequest = () => { const request = requests.at(-1); expect(request).toBeDefined(); return request; }; const flushSuccess = async (request, promise) => { request.respondWith({ status: 200 }); await promise; }; const waitForRequest = async (timeoutMs = 1000) => { const start = Date.now(); while (Date.now() - start < timeoutMs) { const request = requests.at(-1); if (request) { return request; } await Promise.resolve(); } throw new Error('Expected an XHR request to be sent'); }; describe('instance (vitest browser)', () => { beforeEach(() => { requests = []; OriginalXMLHttpRequest = window.XMLHttpRequest; window.XMLHttpRequest = MockXMLHttpRequest; }); afterEach(() => { window.XMLHttpRequest = OriginalXMLHttpRequest; }); it('should have the same methods as default instance', () => { const instance = axios.create(); for (const prop in axios) { if ( [ 'Axios', 'AxiosError', 'create', 'Cancel', 'CanceledError', 'CancelToken', 'isCancel', 'all', 'spread', 'getUri', 'isAxiosError', 'mergeConfig', 'getAdapter', 'VERSION', 'default', 'toFormData', 'formToJSON', 'AxiosHeaders', 'HttpStatusCode', ].includes(prop) ) { continue; } expect(typeof instance[prop]).toBe(typeof axios[prop]); } }); it('should make an http request without verb helper', async () => { const instance = axios.create(); const promise = instance('/foo'); const request = getLastRequest(); expect(request.url).toBe('/foo'); await flushSuccess(request, promise); }); it('should make an http request with url instead of baseURL', async () => { const instance = axios.create({ url: 'https://api.example.com', }); const promise = instance('/foo'); const request = getLastRequest(); expect(request.url).toBe('/foo'); await flushSuccess(request, promise); }); it('should make an http request', async () => { const instance = axios.create(); const promise = instance.get('/foo'); const request = getLastRequest(); expect(request.url).toBe('/foo'); await flushSuccess(request, promise); }); it('should use instance options', async () => { const instance = axios.create({ timeout: 1000 }); const promise = instance.get('/foo'); const request = getLastRequest(); expect(request.timeout).toBe(1000); await flushSuccess(request, promise); }); it('should have defaults.headers', () => { const instance = axios.create({ baseURL: 'https://api.example.com', }); expect(typeof instance.defaults.headers).toBe('object'); expect(typeof instance.defaults.headers.common).toBe('object'); }); it('should have interceptors on the instance', async () => { const requestInterceptorId = axios.interceptors.request.use((config) => { config.foo = true; return config; }); const instance = axios.create(); const instanceInterceptorId = instance.interceptors.request.use((config) => { config.bar = true; return config; }); try { const responsePromise = instance.get('/foo'); const request = await waitForRequest(); request.respondWith({ status: 200, }); const response = await responsePromise; expect(response.config.foo).toBeUndefined(); expect(response.config.bar).toBe(true); } finally { axios.interceptors.request.eject(requestInterceptorId); instance.interceptors.request.eject(instanceInterceptorId); } }); it('should have getUri on the instance', () => { const instance = axios.create({ baseURL: 'https://api.example.com', }); const options = { url: 'foo/bar', params: { name: 'axios', }, }; expect(instance.getUri(options)).toBe('https://api.example.com/foo/bar?name=axios'); }); it('should correctly build url without baseURL', () => { const instance = axios.create(); const options = { url: 'foo/bar?foo=bar', params: { name: 'axios', }, }; expect(instance.getUri(options)).toBe('foo/bar?foo=bar&name=axios'); }); it('should correctly discard url hash mark', () => { const instance = axios.create(); const options = { baseURL: 'https://api.example.com', url: 'foo/bar?foo=bar#hash', params: { name: 'axios', }, }; expect(instance.getUri(options)).toBe('https://api.example.com/foo/bar?foo=bar&name=axios'); }); }); axios-axios-2d06f96/tests/browser/interceptors.browser.test.js000066400000000000000000000467061521272452000247010ustar00rootroot00000000000000import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import axios from '../../index.js'; class MockXMLHttpRequest { constructor() { this.requestHeaders = {}; this.responseHeaders = {}; this.readyState = 0; this.status = 0; this.statusText = ''; this.responseText = ''; this.response = null; this.responseURL = ''; this.timeout = 0; this.withCredentials = false; this.onreadystatechange = null; this.onloadend = null; this.onabort = null; this.onerror = null; this.ontimeout = null; this.upload = { addEventListener() {}, }; } open(method, url, async = true) { this.method = method; this.url = url; this.async = async; } setRequestHeader(key, value) { this.requestHeaders[key] = value; } addEventListener() {} getAllResponseHeaders() { if (typeof this.responseHeaders === 'string') { return this.responseHeaders; } return Object.entries(this.responseHeaders) .map(([key, value]) => `${key}: ${value}`) .join('\n'); } send(data) { this.params = data; requests.push(this); this.readyState = 1; } respondWith({ status = 200, statusText = 'OK', responseText = '', response = null, responseHeaders = {}, headers = {}, responseURL = '', } = {}) { this.status = status; this.statusText = statusText; this.responseText = responseText; this.response = response === null ? responseText : response; this.responseHeaders = Object.keys(headers).length ? headers : responseHeaders; this.responseURL = responseURL; this.readyState = 4; this.finish(); } responseTimeout() { if (this.ontimeout) { this.ontimeout(); } } failNetworkError(message = 'Network Error') { if (this.onerror) { this.onerror({ message }); } } abort() { if (this.onabort) { this.onabort(); } } finish() { queueMicrotask(() => { if (this.onloadend) { this.onloadend(); } else if (this.onreadystatechange) { this.onreadystatechange(); } }); } } let requests = []; let OriginalXMLHttpRequest; const sleep = (ms = 0) => new Promise((resolve) => setTimeout(resolve, ms)); const waitForRequest = async (timeoutMs = 1000) => { const start = Date.now(); while (Date.now() - start < timeoutMs) { const request = requests.at(-1); if (request) { return request; } await sleep(0); } throw new Error('Expected an XHR request to be sent'); }; describe('interceptors (vitest browser)', () => { beforeEach(() => { requests = []; OriginalXMLHttpRequest = window.XMLHttpRequest; window.XMLHttpRequest = MockXMLHttpRequest; }); afterEach(() => { window.XMLHttpRequest = OriginalXMLHttpRequest; axios.interceptors.request.handlers = []; axios.interceptors.response.handlers = []; vi.restoreAllMocks(); }); it('should add a request interceptor (asynchronous by default)', async () => { let asyncFlag = false; axios.interceptors.request.use((config) => { config.headers.test = 'added by interceptor'; expect(asyncFlag).toBe(true); return config; }); const responsePromise = axios('/foo'); asyncFlag = true; const request = await waitForRequest(); expect(request.requestHeaders.test).toBe('added by interceptor'); request.respondWith(); await responsePromise; }); it('should add a request interceptor (explicitly flagged as asynchronous)', async () => { let asyncFlag = false; axios.interceptors.request.use( (config) => { config.headers.test = 'added by interceptor'; expect(asyncFlag).toBe(true); return config; }, null, { synchronous: false } ); const responsePromise = axios('/foo'); asyncFlag = true; const request = await waitForRequest(); expect(request.requestHeaders.test).toBe('added by interceptor'); request.respondWith(); await responsePromise; }); it('should add a request interceptor that is executed synchronously when flag is provided', async () => { let asyncFlag = false; axios.interceptors.request.use( (config) => { config.headers.test = 'added by synchronous interceptor'; expect(asyncFlag).toBe(false); return config; }, null, { synchronous: true } ); const responsePromise = axios('/foo'); asyncFlag = true; const request = await waitForRequest(); expect(request.requestHeaders.test).toBe('added by synchronous interceptor'); request.respondWith(); await responsePromise; }); it('should execute asynchronously when not all interceptors are explicitly flagged as synchronous', async () => { let asyncFlag = false; axios.interceptors.request.use((config) => { config.headers.foo = 'uh oh, async'; expect(asyncFlag).toBe(true); return config; }); axios.interceptors.request.use( (config) => { config.headers.test = 'added by synchronous interceptor'; expect(asyncFlag).toBe(true); return config; }, null, { synchronous: true } ); axios.interceptors.request.use((config) => { config.headers.test = 'added by the async interceptor'; expect(asyncFlag).toBe(true); return config; }); const responsePromise = axios('/foo'); asyncFlag = true; const request = await waitForRequest(); expect(request.requestHeaders.foo).toBe('uh oh, async'); expect(request.requestHeaders.test).toBe('added by synchronous interceptor'); request.respondWith(); await responsePromise; }); it('should execute request interceptor in legacy order', async () => { let sequence = ''; axios.interceptors.request.use((config) => { sequence += '1'; return config; }); axios.interceptors.request.use((config) => { sequence += '2'; return config; }); axios.interceptors.request.use((config) => { sequence += '3'; return config; }); const responsePromise = axios({ url: '/foo' }); const request = await waitForRequest(); expect(sequence).toBe('321'); request.respondWith(); await responsePromise; }); it('should execute request interceptor in order', async () => { let sequence = ''; axios.interceptors.request.use((config) => { sequence += '1'; return config; }); axios.interceptors.request.use((config) => { sequence += '2'; return config; }); axios.interceptors.request.use((config) => { sequence += '3'; return config; }); const responsePromise = axios({ url: '/foo', transitional: { legacyInterceptorReqResOrdering: false, }, }); const request = await waitForRequest(); expect(sequence).toBe('123'); request.respondWith(); await responsePromise; }); it('runs the interceptor if runWhen function is provided and resolves to true', async () => { const onGetCall = (config) => config.method === 'get'; axios.interceptors.request.use( (config) => { config.headers.test = 'special get headers'; return config; }, null, { runWhen: onGetCall } ); const responsePromise = axios('/foo'); const request = await waitForRequest(); expect(request.requestHeaders.test).toBe('special get headers'); request.respondWith(); await responsePromise; }); it('does not run the interceptor if runWhen function is provided and resolves to false', async () => { const onPostCall = (config) => config.method === 'post'; axios.interceptors.request.use( (config) => { config.headers.test = 'special get headers'; return config; }, null, { runWhen: onPostCall } ); const responsePromise = axios('/foo'); const request = await waitForRequest(); expect(request.requestHeaders.test).toBeUndefined(); request.respondWith(); await responsePromise; }); it('does not run async interceptor if runWhen resolves to false (and runs synchronously)', async () => { let asyncFlag = false; const onPostCall = (config) => config.method === 'post'; axios.interceptors.request.use( (config) => { config.headers.test = 'special get headers'; return config; }, null, { synchronous: false, runWhen: onPostCall } ); axios.interceptors.request.use( (config) => { config.headers.sync = 'hello world'; expect(asyncFlag).toBe(false); return config; }, null, { synchronous: true } ); const responsePromise = axios('/foo'); asyncFlag = true; const request = await waitForRequest(); expect(request.requestHeaders.test).toBeUndefined(); expect(request.requestHeaders.sync).toBe('hello world'); request.respondWith(); await responsePromise; }); it('should call request onRejected when interceptor throws', async () => { const rejectedSpy = vi.fn(); const error = new Error('deadly error'); axios.interceptors.request.use( () => { throw error; }, rejectedSpy, { synchronous: true } ); const responsePromise = axios('/foo').catch(() => {}); const request = await waitForRequest(); request.respondWith(); await responsePromise; expect(rejectedSpy).toHaveBeenCalledWith(error); }); it('should add a request interceptor that returns a new config object', async () => { axios.interceptors.request.use(() => ({ url: '/bar', method: 'post', })); const responsePromise = axios('/foo'); const request = await waitForRequest(); expect(request.method).toBe('POST'); expect(request.url).toBe('/bar'); request.respondWith(); await responsePromise; }); it('should add a request interceptor that returns a promise', async () => { axios.interceptors.request.use((config) => new Promise((resolve) => { setTimeout(() => { config.headers.async = 'promise'; resolve(config); }, 100); }) ); const responsePromise = axios('/foo'); const request = await waitForRequest(1500); expect(request.requestHeaders.async).toBe('promise'); request.respondWith(); await responsePromise; }); it('should add multiple request interceptors', async () => { axios.interceptors.request.use((config) => { config.headers.test1 = '1'; return config; }); axios.interceptors.request.use((config) => { config.headers.test2 = '2'; return config; }); axios.interceptors.request.use((config) => { config.headers.test3 = '3'; return config; }); const responsePromise = axios('/foo'); const request = await waitForRequest(); expect(request.requestHeaders.test1).toBe('1'); expect(request.requestHeaders.test2).toBe('2'); expect(request.requestHeaders.test3).toBe('3'); request.respondWith(); await responsePromise; }); it('should add a response interceptor', async () => { axios.interceptors.response.use((data) => { data.data = `${data.data} - modified by interceptor`; return data; }); const responsePromise = axios('/foo'); const request = await waitForRequest(); request.respondWith({ status: 200, responseText: 'OK', }); const response = await responsePromise; expect(response.data).toBe('OK - modified by interceptor'); }); it('should add a response interceptor when request interceptor is defined', async () => { axios.interceptors.request.use((data) => data); axios.interceptors.response.use((data) => { data.data = `${data.data} - modified by interceptor`; return data; }); const responsePromise = axios('/foo'); const request = await waitForRequest(); request.respondWith({ status: 200, responseText: 'OK', }); const response = await responsePromise; expect(response.data).toBe('OK - modified by interceptor'); }); it('should add a response interceptor that returns a new data object', async () => { axios.interceptors.response.use(() => ({ data: 'stuff', })); const responsePromise = axios('/foo'); const request = await waitForRequest(); request.respondWith({ status: 200, responseText: 'OK', }); const response = await responsePromise; expect(response.data).toBe('stuff'); }); it('should add a response interceptor that returns a promise', async () => { axios.interceptors.response.use((data) => new Promise((resolve) => { setTimeout(() => { data.data = 'you have been promised!'; resolve(data); }, 10); }) ); const responsePromise = axios('/foo'); const request = await waitForRequest(); request.respondWith({ status: 200, responseText: 'OK', }); const response = await responsePromise; expect(response.data).toBe('you have been promised!'); }); describe('given multiple response interceptors', () => { const fireRequest = async () => { const responsePromise = axios('/foo'); const request = await waitForRequest(); request.respondWith({ status: 200, responseText: 'OK', }); return responsePromise; }; it('then each interceptor is executed', async () => { const interceptor1 = vi.fn((response) => response); const interceptor2 = vi.fn((response) => response); axios.interceptors.response.use(interceptor1); axios.interceptors.response.use(interceptor2); await fireRequest(); expect(interceptor1).toHaveBeenCalled(); expect(interceptor2).toHaveBeenCalled(); }); it('then they are executed in the order they were added', async () => { const interceptor1 = vi.fn((response) => response); const interceptor2 = vi.fn((response) => response); axios.interceptors.response.use(interceptor1); axios.interceptors.response.use(interceptor2); await fireRequest(); expect(interceptor1.mock.invocationCallOrder[0]).toBeLessThan(interceptor2.mock.invocationCallOrder[0]); }); it("then only the last interceptor's result is returned", async () => { axios.interceptors.response.use(() => 'response 1'); axios.interceptors.response.use(() => 'response 2'); const response = await fireRequest(); expect(response).toBe('response 2'); }); it("then every interceptor receives the result of its predecessor", async () => { axios.interceptors.response.use(() => 'response 1'); axios.interceptors.response.use((response) => [response, 'response 2']); const response = await fireRequest(); expect(response).toEqual(['response 1', 'response 2']); }); describe('and when the fulfillment interceptor throws', () => { const fireRequestCatch = async () => { const responsePromise = axios('/foo').catch(() => {}); const request = await waitForRequest(); request.respondWith({ status: 200, responseText: 'OK', }); await responsePromise; }; it('then the following fulfillment interceptor is not called', async () => { axios.interceptors.response.use(() => { throw new Error('throwing interceptor'); }); const interceptor2 = vi.fn((response) => response); axios.interceptors.response.use(interceptor2); await fireRequestCatch(); expect(interceptor2).not.toHaveBeenCalled(); }); it('then the following rejection interceptor is called', async () => { axios.interceptors.response.use(() => { throw new Error('throwing interceptor'); }); const rejectIntercept = vi.fn((error) => Promise.reject(error)); axios.interceptors.response.use(() => {}, rejectIntercept); await fireRequestCatch(); expect(rejectIntercept).toHaveBeenCalled(); }); it('once caught, another following fulfillment interceptor is called again', async () => { axios.interceptors.response.use(() => { throw new Error('throwing interceptor'); }); axios.interceptors.response.use( () => {}, () => 'recovered' ); const interceptor3 = vi.fn((response) => response); axios.interceptors.response.use(interceptor3); await fireRequestCatch(); expect(interceptor3).toHaveBeenCalled(); }); }); }); it('should allow removing interceptors', async () => { axios.interceptors.response.use((data) => { data.data = `${data.data}1`; return data; }); const intercept = axios.interceptors.response.use((data) => { data.data = `${data.data}2`; return data; }); axios.interceptors.response.use((data) => { data.data = `${data.data}3`; return data; }); axios.interceptors.response.eject(intercept); const responsePromise = axios('/foo'); const request = await waitForRequest(); request.respondWith({ status: 200, responseText: 'OK', }); const response = await responsePromise; expect(response.data).toBe('OK13'); }); it('should remove async interceptor before making request and execute synchronously', async () => { let asyncFlag = false; const asyncIntercept = axios.interceptors.request.use( (config) => { config.headers.async = 'async it!'; return config; }, null, { synchronous: false } ); axios.interceptors.request.use( (config) => { config.headers.sync = 'hello world'; expect(asyncFlag).toBe(false); return config; }, null, { synchronous: true } ); axios.interceptors.request.eject(asyncIntercept); const responsePromise = axios('/foo'); asyncFlag = true; const request = await waitForRequest(); expect(request.requestHeaders.async).toBeUndefined(); expect(request.requestHeaders.sync).toBe('hello world'); request.respondWith(); await responsePromise; }); it('should execute interceptors before transformers', async () => { axios.interceptors.request.use((config) => { config.data.baz = 'qux'; return config; }); const responsePromise = axios.post('/foo', { foo: 'bar', }); const request = await waitForRequest(); expect(request.params).toEqual('{"foo":"bar","baz":"qux"}'); request.respondWith(); await responsePromise; }); it('should modify base URL in request interceptor', async () => { const instance = axios.create({ baseURL: 'http://test.com/', }); instance.interceptors.request.use((config) => { config.baseURL = 'http://rebase.com/'; return config; }); const responsePromise = instance.get('/foo'); const request = await waitForRequest(); expect(request.url).toBe('http://rebase.com/foo'); request.respondWith(); await responsePromise; }); it('should clear all request interceptors', () => { const instance = axios.create({ baseURL: 'http://test.com/', }); instance.interceptors.request.use((config) => config); instance.interceptors.request.clear(); expect(instance.interceptors.request.handlers.length).toBe(0); }); it('should clear all response interceptors', () => { const instance = axios.create({ baseURL: 'http://test.com/', }); instance.interceptors.response.use((config) => config); instance.interceptors.response.clear(); expect(instance.interceptors.response.handlers.length).toBe(0); }); }); axios-axios-2d06f96/tests/browser/isURLSameOrigin.browser.test.js000066400000000000000000000006321521272452000251200ustar00rootroot00000000000000import { describe, expect, it } from 'vitest'; import isURLSameOrigin from '../../lib/helpers/isURLSameOrigin.js'; describe('helpers::isURLSameOrigin (vitest browser)', () => { it('detects same origin', () => { expect(isURLSameOrigin(window.location.href)).toBe(true); }); it('detects different origin', () => { expect(isURLSameOrigin('https://github.com/axios/axios')).toBe(false); }); }); axios-axios-2d06f96/tests/browser/options.browser.test.js000066400000000000000000000135761521272452000236520ustar00rootroot00000000000000import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import axios from '../../index.js'; class MockXMLHttpRequest { constructor() { this.requestHeaders = {}; this.responseHeaders = ''; this.readyState = 0; this.status = 0; this.statusText = ''; this.responseText = ''; this.response = null; this.onreadystatechange = null; this.onloadend = null; this.upload = { addEventListener() {}, }; } open(method, url, async = true) { this.method = method; this.url = url; this.async = async; } setRequestHeader(key, value) { this.requestHeaders[key] = value; } addEventListener() {} getAllResponseHeaders() { return this.responseHeaders; } send(data) { this.params = data; requests.push(this); } respondWith({ status = 200, statusText = 'OK', responseText = '', responseHeaders = '' } = {}) { this.status = status; this.statusText = statusText; this.responseText = responseText; this.response = responseText; this.responseHeaders = responseHeaders; this.readyState = 4; queueMicrotask(() => { if (this.onloadend) { this.onloadend(); } else if (this.onreadystatechange) { this.onreadystatechange(); } }); } } let requests = []; let OriginalXMLHttpRequest; const startRequest = (...args) => { const promise = axios(...args); const request = requests.at(-1); expect(request).toBeDefined(); return { request, promise }; }; const flushSuccess = async (request, promise) => { request.respondWith({ status: 200 }); await promise; }; describe('options (vitest browser)', () => { beforeEach(() => { requests = []; OriginalXMLHttpRequest = window.XMLHttpRequest; window.XMLHttpRequest = MockXMLHttpRequest; }); afterEach(() => { window.XMLHttpRequest = OriginalXMLHttpRequest; vi.restoreAllMocks(); }); it('should default method to get', async () => { const { request, promise } = startRequest('/foo'); expect(request.method).toBe('GET'); await flushSuccess(request, promise); }); it('should accept headers', async () => { const { request, promise } = startRequest('/foo', { headers: { 'X-Requested-With': 'XMLHttpRequest', }, }); expect(request.requestHeaders['X-Requested-With']).toBe('XMLHttpRequest'); await flushSuccess(request, promise); }); it('should accept params', async () => { const { request, promise } = startRequest('/foo', { params: { foo: 123, bar: 456, }, }); expect(request.url).toBe('/foo?foo=123&bar=456'); await flushSuccess(request, promise); }); it('should allow overriding default headers', async () => { const { request, promise } = startRequest('/foo', { headers: { Accept: 'foo/bar', }, }); expect(request.requestHeaders.Accept).toBe('foo/bar'); await flushSuccess(request, promise); }); it('should accept base URL', async () => { const instance = axios.create({ baseURL: 'http://test.com/', }); const promise = instance.get('/foo'); const request = requests.at(-1); expect(request).toBeDefined(); expect(request.url).toBe('http://test.com/foo'); await flushSuccess(request, promise); }); it('should warn about baseUrl', async () => { const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); const instance = axios.create({ baseUrl: 'http://example.com/', }); const promise = instance.get('/foo'); const request = requests.at(-1); expect(request).toBeDefined(); expect(warnSpy).toHaveBeenCalledWith('baseUrl is likely a misspelling of baseURL'); expect(request.url).toBe('/foo'); await flushSuccess(request, promise); }); it('should ignore base URL if request URL is absolute', async () => { const instance = axios.create({ baseURL: 'http://someurl.com/', }); const promise = instance.get('http://someotherurl.com/'); const request = requests.at(-1); expect(request).toBeDefined(); expect(request.url).toBe('http://someotherurl.com/'); await flushSuccess(request, promise); }); it('should combine the URLs if base url and request url exist and allowAbsoluteUrls is false', async () => { const instance = axios.create({ baseURL: 'http://someurl.com/', allowAbsoluteUrls: false, }); const promise = instance.get('http://someotherurl.com/'); const request = requests.at(-1); expect(request).toBeDefined(); expect(request.url).toBe('http://someurl.com/http://someotherurl.com/'); await flushSuccess(request, promise); }); it('should change only the baseURL of the specified instance', () => { const instance1 = axios.create(); const instance2 = axios.create(); instance1.defaults.baseURL = 'http://instance1.example.com/'; expect(instance2.defaults.baseURL).not.toBe('http://instance1.example.com/'); }); it('should change only the headers of the specified instance', () => { const instance1 = axios.create(); const instance2 = axios.create(); instance1.defaults.headers.common.Authorization = 'faketoken'; instance2.defaults.headers.common.Authorization = 'differentfaketoken'; instance1.defaults.headers.common['Content-Type'] = 'application/xml'; instance2.defaults.headers.common['Content-Type'] = 'application/x-www-form-urlencoded'; expect(axios.defaults.headers.common.Authorization).toBeUndefined(); expect(instance1.defaults.headers.common.Authorization).toBe('faketoken'); expect(instance2.defaults.headers.common.Authorization).toBe('differentfaketoken'); expect(axios.defaults.headers.common['Content-Type']).toBeUndefined(); expect(instance1.defaults.headers.common['Content-Type']).toBe('application/xml'); expect(instance2.defaults.headers.common['Content-Type']).toBe('application/x-www-form-urlencoded'); }); }); axios-axios-2d06f96/tests/browser/progress.browser.test.js000066400000000000000000000136241521272452000240150ustar00rootroot00000000000000import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import axios from '../../index.js'; class MockXMLHttpRequest { constructor() { this.requestHeaders = {}; this.responseHeaders = {}; this.readyState = 0; this.status = 0; this.statusText = ''; this.responseText = ''; this.response = null; this.timeout = 0; this.withCredentials = false; this.onreadystatechange = null; this.onloadend = null; this.onabort = null; this.onerror = null; this.ontimeout = null; this._listeners = {}; this._uploadListeners = {}; this.upload = { addEventListener: (type, listener) => { this._uploadListeners[type] ||= []; this._uploadListeners[type].push(listener); }, }; } open(method, url, async = true) { this.method = method; this.url = url; this.async = async; } setRequestHeader(key, value) { this.requestHeaders[key] = value; } addEventListener(type, listener) { this._listeners[type] ||= []; this._listeners[type].push(listener); } getAllResponseHeaders() { return Object.entries(this.responseHeaders) .map(([key, value]) => `${key}: ${value}`) .join('\n'); } send(data) { this.params = data; this.readyState = 1; requests.push(this); } getListenerCount(type, target = 'request') { const listeners = target === 'upload' ? this._uploadListeners : this._listeners; return listeners[type]?.length || 0; } emit(type, target = 'request', event = {}) { const listeners = target === 'upload' ? this._uploadListeners : this._listeners; (listeners[type] || []).forEach((listener) => listener(event)); } respondWith({ status = 200, statusText = 'OK', responseText = '', response = null, headers = {}, } = {}) { this.status = status; this.statusText = statusText; this.responseText = responseText; this.response = response; this.responseHeaders = headers; this.readyState = 4; this.emit('progress', 'request', { loaded: responseText.length, total: responseText.length, lengthComputable: true, }); queueMicrotask(() => { if (this.onloadend) { this.onloadend(); } else if (this.onreadystatechange) { this.onreadystatechange(); } }); } } let requests = []; let OriginalXMLHttpRequest; const getLastRequest = () => { const request = requests.at(-1); expect(request).toBeDefined(); return request; }; describe('progress (vitest browser)', () => { beforeEach(() => { requests = []; OriginalXMLHttpRequest = window.XMLHttpRequest; window.XMLHttpRequest = MockXMLHttpRequest; }); afterEach(() => { window.XMLHttpRequest = OriginalXMLHttpRequest; vi.restoreAllMocks(); }); it('should add a download progress handler', async () => { const progressSpy = vi.fn(); const responsePromise = axios('/foo', { onDownloadProgress: progressSpy }); const request = getLastRequest(); request.respondWith({ status: 200, responseText: '{"foo": "bar"}', }); await responsePromise; expect(progressSpy).toHaveBeenCalled(); }); it('should add an upload progress handler', async () => { const progressSpy = vi.fn(); const responsePromise = axios('/foo', { onUploadProgress: progressSpy }); const request = getLastRequest(); expect(request.getListenerCount('progress', 'upload')).toBe(1); request.respondWith({ status: 200, responseText: '{"foo": "bar"}', }); await responsePromise; }); it('should add both upload and download progress handlers', async () => { const downloadProgressSpy = vi.fn(); const uploadProgressSpy = vi.fn(); const responsePromise = axios('/foo', { onDownloadProgress: downloadProgressSpy, onUploadProgress: uploadProgressSpy, }); const request = getLastRequest(); expect(downloadProgressSpy).not.toHaveBeenCalled(); expect(request.getListenerCount('progress', 'request')).toBe(1); expect(request.getListenerCount('progress', 'upload')).toBe(1); request.respondWith({ status: 200, responseText: '{"foo": "bar"}', }); await responsePromise; expect(downloadProgressSpy).toHaveBeenCalled(); }); it('should add a download progress handler from instance config', async () => { const progressSpy = vi.fn(); const instance = axios.create({ onDownloadProgress: progressSpy, }); const responsePromise = instance.get('/foo'); const request = getLastRequest(); request.respondWith({ status: 200, responseText: '{"foo": "bar"}', }); await responsePromise; expect(progressSpy).toHaveBeenCalled(); }); it('should add an upload progress handler from instance config', async () => { const progressSpy = vi.fn(); const instance = axios.create({ onUploadProgress: progressSpy, }); const responsePromise = instance.get('/foo'); const request = getLastRequest(); expect(request.getListenerCount('progress', 'upload')).toBe(1); request.respondWith({ status: 200, responseText: '{"foo": "bar"}', }); await responsePromise; }); it('should add upload and download progress handlers from instance config', async () => { const downloadProgressSpy = vi.fn(); const uploadProgressSpy = vi.fn(); const instance = axios.create({ onDownloadProgress: downloadProgressSpy, onUploadProgress: uploadProgressSpy, }); const responsePromise = instance.get('/foo'); const request = getLastRequest(); expect(downloadProgressSpy).not.toHaveBeenCalled(); expect(request.getListenerCount('progress', 'request')).toBe(1); expect(request.getListenerCount('progress', 'upload')).toBe(1); request.respondWith({ status: 200, responseText: '{"foo": "bar"}', }); await responsePromise; expect(downloadProgressSpy).toHaveBeenCalled(); }); }); axios-axios-2d06f96/tests/browser/promise.browser.test.js000066400000000000000000000054231521272452000236250ustar00rootroot00000000000000import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import axios from '../../index.js'; class MockXMLHttpRequest { constructor() { this.requestHeaders = {}; this.responseHeaders = ''; this.readyState = 0; this.status = 0; this.statusText = ''; this.responseText = ''; this.response = null; this.onreadystatechange = null; this.onloadend = null; this.upload = { addEventListener() {}, }; } open(method, url, async = true) { this.method = method; this.url = url; this.async = async; } setRequestHeader(key, value) { this.requestHeaders[key] = value; } addEventListener() {} getAllResponseHeaders() { return this.responseHeaders; } send(data) { this.params = data; requests.push(this); } respondWith({ status = 200, statusText = 'OK', responseText = '', responseHeaders = '' } = {}) { this.status = status; this.statusText = statusText; this.responseText = responseText; this.response = responseText; this.responseHeaders = responseHeaders; this.readyState = 4; queueMicrotask(() => { if (this.onloadend) { this.onloadend(); } else if (this.onreadystatechange) { this.onreadystatechange(); } }); } abort() {} } let requests = []; let OriginalXMLHttpRequest; const getLastRequest = () => { const request = requests.at(-1); expect(request).toBeDefined(); return request; }; describe('promise (vitest browser)', () => { beforeEach(() => { requests = []; OriginalXMLHttpRequest = window.XMLHttpRequest; window.XMLHttpRequest = MockXMLHttpRequest; }); afterEach(() => { window.XMLHttpRequest = OriginalXMLHttpRequest; }); it('should provide succinct object to then', async () => { const responsePromise = axios('/foo'); const request = getLastRequest(); request.respondWith({ status: 200, responseText: '{"hello":"world"}', responseHeaders: 'Content-Type: application/json', }); const response = await responsePromise; expect(typeof response).toBe('object'); expect(response.data.hello).toBe('world'); expect(response.status).toBe(200); expect(response.headers['content-type']).toBe('application/json'); expect(response.config.url).toBe('/foo'); }); it('should support all', async () => { const result = await axios.all([true, 123]); expect(result).toEqual([true, 123]); }); it('should support spread', async () => { let fulfilled = false; const result = await axios.all([123, 456]).then( axios.spread((a, b) => { expect(a + b).toBe(123 + 456); fulfilled = true; return 'hello world'; }) ); expect(fulfilled).toBe(true); expect(result).toBe('hello world'); }); }); axios-axios-2d06f96/tests/browser/requests.browser.test.js000066400000000000000000000336101521272452000240210ustar00rootroot00000000000000import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import axios from '../../index.js'; import AxiosError from '../../lib/core/AxiosError.js'; class MockXMLHttpRequest { constructor() { this.requestHeaders = {}; this.responseHeaders = {}; this.readyState = 0; this.status = 0; this.statusText = ''; this.responseText = ''; this.response = null; this.responseURL = ''; this.timeout = 0; this.withCredentials = false; this.onreadystatechange = null; this.onloadend = null; this.onabort = null; this.onerror = null; this.ontimeout = null; this.upload = { addEventListener() {}, }; } open(method, url, async = true) { this.method = method; this.url = url; this.async = async; } setRequestHeader(key, value) { this.requestHeaders[key] = value; } addEventListener() {} getAllResponseHeaders() { return Object.entries(this.responseHeaders) .map(([key, value]) => `${key}: ${value}`) .join('\n'); } send(data) { this.params = data; this.readyState = 1; requests.push(this); } respondWith({ status = 200, statusText = 'OK', responseText = '', response = null, headers = {}, responseURL = '', } = {}) { this.status = status; this.statusText = statusText; this.responseText = responseText; this.response = response; this.responseHeaders = headers; this.responseURL = responseURL; this.readyState = 4; this.finish(); } responseTimeout() { if (this.ontimeout) { this.ontimeout(); } } failNetworkError(message = 'Network Error') { if (this.onerror) { this.onerror({ message }); } } abort() { if (this.onabort) { this.onabort(); } } finish() { queueMicrotask(() => { if (this.onloadend) { this.onloadend(); } else if (this.onreadystatechange) { this.onreadystatechange(); } }); } } let requests = []; let OriginalXMLHttpRequest; const startRequest = (...args) => { const promise = axios(...args); const request = requests.at(-1); expect(request).toBeDefined(); return { request, promise }; }; const flushSuccess = async (request, promise) => { request.respondWith({ status: 200 }); await promise; }; describe('requests (vitest browser)', () => { beforeEach(() => { requests = []; OriginalXMLHttpRequest = window.XMLHttpRequest; window.XMLHttpRequest = MockXMLHttpRequest; }); afterEach(() => { window.XMLHttpRequest = OriginalXMLHttpRequest; vi.restoreAllMocks(); }); it('should treat single string arg as url', async () => { const { request, promise } = startRequest('/foo'); expect(request.url).toBe('/foo'); expect(request.method).toBe('GET'); await flushSuccess(request, promise); }); it('should treat method value as lowercase string', async () => { const { request, promise } = startRequest({ url: '/foo', method: 'POST', }); request.respondWith({ status: 200 }); const response = await promise; expect(response.config.method).toBe('post'); }); it('should allow string arg as url, and config arg', async () => { const { request, promise } = startRequest('/foo', { method: 'post', }); expect(request.url).toBe('/foo'); expect(request.method).toBe('POST'); await flushSuccess(request, promise); }); it('should allow data', async () => { const { request, promise } = startRequest('/foo', { method: 'delete', data: { foo: 'bar' }, }); expect(request.params).toBe(JSON.stringify({ foo: 'bar' })); await flushSuccess(request, promise); }); it('should make an http request', async () => { const { request, promise } = startRequest('/foo'); expect(request.url).toBe('/foo'); await flushSuccess(request, promise); }); describe('timeouts', () => { it('should handle timeouts', async () => { const { request, promise } = startRequest({ url: '/foo', timeout: 100, }); request.responseTimeout(); const err = await promise.catch((error) => error); expect(err).toBeInstanceOf(Error); expect(err.code).toBe('ECONNABORTED'); }); describe('transitional.clarifyTimeoutError', () => { it('should throw ETIMEDOUT instead of ECONNABORTED on request timeouts', async () => { const { request, promise } = startRequest({ url: '/foo', timeout: 100, transitional: { clarifyTimeoutError: true, }, }); request.responseTimeout(); const err = await promise.catch((error) => error); expect(err).toBeInstanceOf(Error); expect(err.code).toBe('ETIMEDOUT'); }); }); }); it('should reject on network errors', async () => { const { request, promise } = startRequest('http://thisisnotaserver/foo'); request.failNetworkError(); const reason = await promise.catch((error) => error); expect(reason).toBeInstanceOf(Error); expect(reason.config.method).toBe('get'); expect(reason.config.url).toBe('http://thisisnotaserver/foo'); expect(reason.request).toBeInstanceOf(MockXMLHttpRequest); }); it('rejects malformed HTTP URLs before opening an XHR request', async () => { const openSpy = vi.spyOn(MockXMLHttpRequest.prototype, 'open'); const reason = await axios .get('\u0000https:example.com/users', { adapter: 'xhr', headers: { 'X-Test': 'yes', }, }) .catch((error) => error); expect(reason).toBeInstanceOf(AxiosError); expect(reason.code).toBe(AxiosError.ERR_INVALID_URL); expect(reason.message).toBe('Invalid URL: missing "//" after protocol'); expect(reason.config.url).toBe('\u0000https:example.com/users'); expect(reason.config.headers.get('X-Test')).toBe('yes'); expect(openSpy).not.toHaveBeenCalled(); expect(requests).toHaveLength(0); }); it('should reject on abort', async () => { const { request, promise } = startRequest('/foo'); request.abort(); const reason = await promise.catch((error) => error); expect(reason).toBeInstanceOf(Error); expect(reason.config.method).toBe('get'); expect(reason.config.url).toBe('/foo'); expect(reason.request).toBeInstanceOf(MockXMLHttpRequest); }); it('should reject when validateStatus returns false', async () => { const { request, promise } = startRequest('/foo', { validateStatus(status) { return status !== 500; }, }); request.respondWith({ status: 500 }); const reason = await promise.catch((error) => error); expect(reason).toBeInstanceOf(Error); expect(reason.message).toBe('Request failed with status code 500'); expect(reason.config.method).toBe('get'); expect(reason.config.url).toBe('/foo'); expect(reason.response.status).toBe(500); }); it('should resolve when validateStatus returns true', async () => { const { request, promise } = startRequest('/foo', { validateStatus(status) { return status === 500; }, }); request.respondWith({ status: 500 }); await expect(promise).resolves.toBeDefined(); }); it('should resolve when the response status is 0 (file protocol)', async () => { const { request, promise } = startRequest('file:///xxx'); request.respondWith({ status: 0, responseURL: 'file:///xxx', }); await expect(promise).resolves.toBeDefined(); }); it('should resolve when validateStatus is null', async () => { const { request, promise } = startRequest('/foo', { validateStatus: null, }); request.respondWith({ status: 500 }); await expect(promise).resolves.toBeDefined(); }); it('should resolve when validateStatus is undefined by default', async () => { const { request, promise } = startRequest('/foo', { validateStatus: undefined, }); request.respondWith({ status: 500 }); await expect(promise).resolves.toBeDefined(); }); // https://github.com/axios/axios/issues/6688 it('should reject when validateStatus is undefined and the transitional option is disabled', async () => { const { request, promise } = startRequest('/foo', { validateStatus: undefined, transitional: { validateStatusUndefinedResolves: false }, }); request.respondWith({ status: 500 }); const reason = await promise.catch((error) => error); expect(reason).toBeInstanceOf(Error); expect(reason.message).toBe('Request failed with status code 500'); expect(reason.config.method).toBe('get'); expect(reason.config.url).toBe('/foo'); expect(reason.response.status).toBe(500); }); // https://github.com/axios/axios/issues/378 it('should return JSON when rejecting', async () => { const { request, promise } = startRequest( '/api/account/signup', { username: null, password: null, }, { method: 'post', headers: { Accept: 'application/json', }, } ); request.respondWith({ status: 400, statusText: 'Bad Request', responseText: '{"error": "BAD USERNAME", "code": 1}', }); const error = await promise.catch((err) => err); const response = error.response; expect(typeof response.data).toBe('object'); expect(response.data.error).toBe('BAD USERNAME'); expect(response.data.code).toBe(1); }); it('should make cross domain http request', async () => { const { request, promise } = startRequest('www.someurl.com/foo', { method: 'post', }); request.respondWith({ status: 200, statusText: 'OK', responseText: '{"foo": "bar"}', headers: { 'Content-Type': 'application/json', }, }); const response = await promise; expect(response.data.foo).toBe('bar'); expect(response.status).toBe(200); expect(response.statusText).toBe('OK'); expect(response.headers['content-type']).toBe('application/json'); }); it('should supply correct response', async () => { const { request, promise } = startRequest('/foo', { method: 'post', }); request.respondWith({ status: 200, statusText: 'OK', responseText: '{"foo": "bar"}', headers: { 'Content-Type': 'application/json', }, }); const response = await promise; expect(response.data.foo).toBe('bar'); expect(response.status).toBe(200); expect(response.statusText).toBe('OK'); expect(response.headers['content-type']).toBe('application/json'); }); it('should not modify the config url with relative baseURL', async () => { const { request, promise } = startRequest('/foo', { baseURL: '/api', }); request.respondWith({ status: 404, statusText: 'NOT FOUND', responseText: 'Resource not found', }); const error = await promise.catch((err) => err); const config = error.config; expect(config.baseURL).toBe('/api'); expect(config.url).toBe('/foo'); }); it('should allow overriding Content-Type header case-insensitive', async () => { const contentType = 'application/vnd.myapp.type+json'; const { request, promise } = startRequest('/foo', { method: 'post', data: { prop: 'value' }, headers: { 'Content-Type': contentType, }, }); expect(request.requestHeaders['Content-Type']).toBe(contentType); await flushSuccess(request, promise); }); it('should support binary data as array buffer', async () => { const input = new Int8Array([1, 2]); const { request, promise } = startRequest('/foo', { method: 'post', data: input.buffer, }); const output = new Int8Array(request.params); expect(output.length).toBe(2); expect(output[0]).toBe(1); expect(output[1]).toBe(2); await flushSuccess(request, promise); }); it('should support binary data as array buffer view', async () => { const input = new Int8Array([1, 2]); const { request, promise } = startRequest('/foo', { method: 'post', data: input, }); const output = new Int8Array(request.params); expect(output.length).toBe(2); expect(output[0]).toBe(1); expect(output[1]).toBe(2); await flushSuccess(request, promise); }); it('should support array buffer response', async () => { const str2ab = (str) => { const buff = new ArrayBuffer(str.length * 2); const view = new Uint16Array(buff); for (let i = 0; i < str.length; i++) { view[i] = str.charCodeAt(i); } return buff; }; const { request, promise } = startRequest('/foo', { responseType: 'arraybuffer', }); request.respondWith({ status: 200, response: str2ab('Hello world'), }); const response = await promise; expect(response.data.byteLength).toBe(22); }); it('should support URLSearchParams', async () => { const params = new URLSearchParams(); params.append('param1', 'value1'); params.append('param2', 'value2'); const { request, promise } = startRequest('/foo', { method: 'post', data: params, }); expect(request.requestHeaders['Content-Type']).toBe( 'application/x-www-form-urlencoded;charset=utf-8' ); expect(request.params).toBe('param1=value1¶m2=value2'); await flushSuccess(request, promise); }); it('should support HTTP protocol', async () => { const { request, promise } = startRequest('/foo', { method: 'get', }); expect(request.method).toBe('GET'); await flushSuccess(request, promise); }); it('should support HTTPS protocol', async () => { const { request, promise } = startRequest('https://www.google.com', { method: 'get', }); expect(request.method).toBe('GET'); await flushSuccess(request, promise); }); it('should return unsupported protocol error message', async () => { await expect(axios.get('ftp:localhost')).rejects.toMatchObject({ message: 'Unsupported protocol ftp:', }); }); }); axios-axios-2d06f96/tests/browser/settle.browser.test.js000066400000000000000000000050351521272452000234460ustar00rootroot00000000000000import { describe, expect, it, vi } from 'vitest'; import settle from '../../lib/core/settle.js'; import AxiosError from '../../lib/core/AxiosError.js'; describe('core::settle (vitest browser)', () => { it('resolves when response status is missing', () => { const resolve = vi.fn(); const reject = vi.fn(); const response = { config: { validateStatus: () => true, }, }; settle(resolve, reject, response); expect(resolve).toHaveBeenCalledOnce(); expect(resolve).toHaveBeenCalledWith(response); expect(reject).not.toHaveBeenCalled(); }); it('resolves when validateStatus is not configured', () => { const resolve = vi.fn(); const reject = vi.fn(); const response = { status: 500, config: {}, }; settle(resolve, reject, response); expect(resolve).toHaveBeenCalledOnce(); expect(resolve).toHaveBeenCalledWith(response); expect(reject).not.toHaveBeenCalled(); }); it('resolves when validateStatus returns true', () => { const resolve = vi.fn(); const reject = vi.fn(); const response = { status: 500, config: { validateStatus: () => true, }, }; settle(resolve, reject, response); expect(resolve).toHaveBeenCalledOnce(); expect(resolve).toHaveBeenCalledWith(response); expect(reject).not.toHaveBeenCalled(); }); it('rejects with an AxiosError when validateStatus returns false', () => { const resolve = vi.fn(); const reject = vi.fn(); const request = { path: '/foo', }; const response = { status: 500, config: { validateStatus: () => false, }, request, }; settle(resolve, reject, response); expect(resolve).not.toHaveBeenCalled(); expect(reject).toHaveBeenCalledOnce(); const reason = reject.mock.calls[0][0]; expect(reason).toBeInstanceOf(AxiosError); expect(reason.message).toBe('Request failed with status code 500'); expect(reason.code).toBe(AxiosError.ERR_BAD_RESPONSE); expect(reason.config).toBe(response.config); expect(reason.request).toBe(request); expect(reason.response).toBe(response); }); it('passes response status to validateStatus', () => { const resolve = vi.fn(); const reject = vi.fn(); const validateStatus = vi.fn(); const response = { status: 500, config: { validateStatus, }, }; settle(resolve, reject, response); expect(validateStatus).toHaveBeenCalledOnce(); expect(validateStatus).toHaveBeenCalledWith(500); }); }); axios-axios-2d06f96/tests/browser/toFormData.browser.test.js000066400000000000000000000066631521272452000242160ustar00rootroot00000000000000import { describe, expect, it } from 'vitest'; import toFormData from '../../lib/helpers/toFormData.js'; describe('helpers::toFormData (vitest browser)', () => { it('converts nested data object to FormData with dots option enabled', () => { const data = { val: 123, nested: { arr: ['hello', 'world'], }, }; const form = toFormData(data, null, { dots: true }); expect(form).toBeInstanceOf(FormData); expect(Array.from(form.keys())).toHaveLength(3); expect(form.get('val')).toBe('123'); expect(form.get('nested.arr.0')).toBe('hello'); }); it('respects metaTokens option', () => { const data = { 'obj{}': { x: 1, y: 2 }, }; const serialized = JSON.stringify(data['obj{}']); const form = toFormData(data, null, { metaTokens: false }); expect(Array.from(form.keys())).toHaveLength(1); expect(form.getAll('obj')).toEqual([serialized]); }); describe('flat arrays serialization', () => { it('includes full indexes when indexes option is true', () => { const data = { arr: [1, 2, 3], arr2: [1, [2], 3], }; const form = toFormData(data, null, { indexes: true }); expect(Array.from(form.keys())).toHaveLength(6); expect(form.get('arr[0]')).toBe('1'); expect(form.get('arr[1]')).toBe('2'); expect(form.get('arr[2]')).toBe('3'); expect(form.get('arr2[0]')).toBe('1'); expect(form.get('arr2[1][0]')).toBe('2'); expect(form.get('arr2[2]')).toBe('3'); }); it('includes brackets only when indexes option is false', () => { const data = { arr: [1, 2, 3], arr2: [1, [2], 3], }; const form = toFormData(data, null, { indexes: false }); expect(Array.from(form.keys())).toHaveLength(6); expect(form.getAll('arr[]')).toEqual(['1', '2', '3']); expect(form.get('arr2[0]')).toBe('1'); expect(form.get('arr2[1][0]')).toBe('2'); expect(form.get('arr2[2]')).toBe('3'); }); it('omits brackets when indexes option is null', () => { const data = { arr: [1, 2, 3], arr2: [1, [2], 3], }; const form = toFormData(data, null, { indexes: null }); expect(Array.from(form.keys())).toHaveLength(6); expect(form.getAll('arr')).toEqual(['1', '2', '3']); expect(form.get('arr2[0]')).toBe('1'); expect(form.get('arr2[1][0]')).toBe('2'); expect(form.get('arr2[2]')).toBe('3'); }); }); it('converts nested data object to FormData', () => { const data = { val: 123, nested: { arr: ['hello', 'world'], }, }; const form = toFormData(data); expect(form).toBeInstanceOf(FormData); expect(Array.from(form.keys())).toHaveLength(3); expect(form.get('val')).toBe('123'); expect(form.get('nested[arr][0]')).toBe('hello'); }); it('appends value whose key ends with [] as separate values with the same key', () => { const data = { 'arr[]': [1, 2, 3], }; const form = toFormData(data); expect(Array.from(form.keys())).toHaveLength(3); expect(form.getAll('arr[]')).toEqual(['1', '2', '3']); }); it('appends value whose key ends with {} as a JSON string', () => { const data = { 'obj{}': { x: 1, y: 2 }, }; const serialized = JSON.stringify(data['obj{}']); const form = toFormData(data); expect(Array.from(form.keys())).toHaveLength(1); expect(form.getAll('obj{}')).toEqual([serialized]); }); }); axios-axios-2d06f96/tests/browser/transform.browser.test.js000066400000000000000000000150271521272452000241630ustar00rootroot00000000000000import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import axios from '../../index.js'; import AxiosError from '../../lib/core/AxiosError.js'; class MockXMLHttpRequest { constructor() { this.requestHeaders = {}; this.responseHeaders = ''; this.readyState = 0; this.status = 0; this.statusText = ''; this.responseText = ''; this.response = null; this.timeout = 0; this.onreadystatechange = null; this.onloadend = null; this.onabort = null; this.onerror = null; this.ontimeout = null; this.upload = { addEventListener() {}, }; } open(method, url, async = true) { this.method = method; this.url = url; this.async = async; } setRequestHeader(key, value) { this.requestHeaders[key] = value; } addEventListener() {} getAllResponseHeaders() { return this.responseHeaders; } send(data) { this.params = data; requests.push(this); } respondWith({ status = 200, statusText = 'OK', responseText = '', responseHeaders = '' } = {}) { this.status = status; this.statusText = statusText; this.responseText = responseText; this.response = responseText; this.responseHeaders = responseHeaders; this.readyState = 4; queueMicrotask(() => { if (this.onloadend) { this.onloadend(); } else if (this.onreadystatechange) { this.onreadystatechange(); } }); } abort() {} } let requests = []; let OriginalXMLHttpRequest; const getLastRequest = () => { const request = requests.at(-1); expect(request).toBeDefined(); return request; }; describe('transform (vitest browser)', () => { beforeEach(() => { requests = []; OriginalXMLHttpRequest = window.XMLHttpRequest; window.XMLHttpRequest = MockXMLHttpRequest; }); afterEach(() => { window.XMLHttpRequest = OriginalXMLHttpRequest; }); it('should transform JSON to string', async () => { const responsePromise = axios.post('/foo', { foo: 'bar' }); const request = getLastRequest(); expect(request.params).toBe('{"foo":"bar"}'); request.respondWith(); await responsePromise; }); it('should transform string to JSON', async () => { const responsePromise = axios('/foo'); const request = getLastRequest(); request.respondWith({ status: 200, responseText: '{"foo": "bar"}', }); const response = await responsePromise; expect(typeof response.data).toBe('object'); expect(response.data.foo).toBe('bar'); }); it('should throw a SyntaxError if JSON parsing failed and responseType is "json" if silentJSONParsing is false', async () => { const responsePromise = axios({ url: '/foo', responseType: 'json', transitional: { silentJSONParsing: false }, }); const request = getLastRequest(); request.respondWith({ status: 200, responseText: '{foo": "bar"}', }); const thrown = await responsePromise.catch((error) => error); expect(thrown).toBeTruthy(); expect(thrown.name).toContain('SyntaxError'); expect(thrown.code).toBe(AxiosError.ERR_BAD_RESPONSE); }); it('should send data as JSON if request content-type is application/json', async () => { const responsePromise = axios.post('/foo', 123, { headers: { 'Content-Type': 'application/json' }, }); const request = getLastRequest(); request.respondWith({ status: 200, responseText: '', }); const response = await responsePromise; expect(response).toBeTruthy(); expect(request.requestHeaders['Content-Type']).toBe('application/json'); expect(JSON.parse(request.params)).toBe(123); }); it('should not assume JSON if responseType is not `json`', async () => { const responsePromise = axios.get('/foo', { responseType: 'text', transitional: { forcedJSONParsing: false, }, }); const request = getLastRequest(); const rawData = '{"x":1}'; request.respondWith({ status: 200, responseText: rawData, }); const response = await responsePromise; expect(response).toBeTruthy(); expect(response.data).toBe(rawData); }); it('should override default transform', async () => { const responsePromise = axios.post( '/foo', { foo: 'bar' }, { transformRequest(data) { return data; }, } ); const request = getLastRequest(); expect(typeof request.params).toBe('object'); request.respondWith(); await responsePromise; }); it('should allow an Array of transformers', async () => { const responsePromise = axios.post( '/foo', { foo: 'bar' }, { transformRequest: axios.defaults.transformRequest.concat(function (data) { return data.replace('bar', 'baz'); }), } ); const request = getLastRequest(); expect(request.params).toBe('{"foo":"baz"}'); request.respondWith(); await responsePromise; }); it('should allowing mutating headers', async () => { const token = Math.floor(Math.random() * Math.pow(2, 64)).toString(36); const responsePromise = axios('/foo', { transformRequest(data, headers) { headers['X-Authorization'] = token; return data; }, }); const request = getLastRequest(); expect(request.requestHeaders['X-Authorization']).toBe(token); request.respondWith(); await responsePromise; }); it("should normalize 'content-type' header when using a custom transformRequest", async () => { const responsePromise = axios.post( '/foo', { foo: 'bar' }, { headers: { 'content-type': 'application/x-www-form-urlencoded' }, transformRequest: [ function () { return 'aa=44'; }, ], } ); const request = getLastRequest(); expect(request.requestHeaders['Content-Type']).toBe('application/x-www-form-urlencoded'); request.respondWith(); await responsePromise; }); it('should return response.data as parsed JSON object when responseType is json', async () => { const instance = axios.create({ baseURL: '/api', responseType: 'json', }); const responsePromise = instance.get('my/endpoint', { responseType: 'json' }); const request = getLastRequest(); request.respondWith({ status: 200, responseText: '{"key1": "value1"}', responseHeaders: 'content-type: application/json', }); const response = await responsePromise; expect(response).toBeTruthy(); expect(response.data).toEqual({ key1: 'value1' }); }); }); axios-axios-2d06f96/tests/browser/xsrf.browser.test.js000066400000000000000000000143031521272452000231260ustar00rootroot00000000000000import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import axios from '../../index.js'; import cookies from '../../lib/helpers/cookies.js'; class MockXMLHttpRequest { constructor() { this.requestHeaders = {}; this.readyState = 0; this.status = 200; this.statusText = 'OK'; this.responseText = ''; this.timeout = 0; this.onreadystatechange = null; this.onloadend = null; this.onabort = null; this.onerror = null; this.ontimeout = null; this.upload = { addEventListener() {}, }; } open(method, url, async = true) { this.method = method; this.url = url; this.async = async; } setRequestHeader(key, value) { this.requestHeaders[key] = value; } addEventListener() {} getAllResponseHeaders() { return ''; } send() { requests.push(this); this.readyState = 4; queueMicrotask(() => { if (this.onloadend) { this.onloadend(); } else if (this.onreadystatechange) { this.onreadystatechange(); } }); } abort() {} } let requests = []; let OriginalXMLHttpRequest; const setXsrfCookie = (value) => { document.cookie = `${axios.defaults.xsrfCookieName}=${value}; path=/`; }; const clearXsrfCookie = () => { document.cookie = `${axios.defaults.xsrfCookieName}=; expires=${new Date( Date.now() - 86400000 ).toUTCString()}; path=/`; }; const sendRequest = async (url, config) => { const responsePromise = axios(url, config); const request = requests.at(-1); expect(request).toBeDefined(); await responsePromise; return request; }; describe('xsrf (vitest browser)', () => { beforeEach(() => { requests = []; OriginalXMLHttpRequest = window.XMLHttpRequest; window.XMLHttpRequest = MockXMLHttpRequest; }); afterEach(() => { clearXsrfCookie(); window.XMLHttpRequest = OriginalXMLHttpRequest; vi.restoreAllMocks(); }); it('should not set xsrf header if cookie is null', async () => { const request = await sendRequest('/foo'); expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toBeUndefined(); }); it('should set xsrf header if cookie is set', async () => { setXsrfCookie('12345'); const request = await sendRequest('/foo'); expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toBe('12345'); }); it('should not set xsrf header if xsrfCookieName is null', async () => { setXsrfCookie('12345'); const request = await sendRequest('/foo', { xsrfCookieName: null, }); expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toBeUndefined(); }); it('should not read cookies at all if xsrfCookieName is null', async () => { const readSpy = vi.spyOn(cookies, 'read'); await sendRequest('/foo', { xsrfCookieName: null, }); expect(readSpy).not.toHaveBeenCalled(); }); it('should not set xsrf header for cross origin', async () => { setXsrfCookie('12345'); const request = await sendRequest('http://example.com/'); expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toBeUndefined(); }); it('should not set xsrf header for cross origin when using withCredentials', async () => { setXsrfCookie('12345'); const request = await sendRequest('http://example.com/', { withCredentials: true, }); expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toBeUndefined(); }); describe('withXSRFToken option', () => { it('should set xsrf header for cross origin when withXSRFToken = true', async () => { const token = '12345'; setXsrfCookie(token); const request = await sendRequest('http://example.com/', { withXSRFToken: true, }); expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toBe(token); }); it('should not set xsrf header for the same origin when withXSRFToken = false', async () => { const token = '12345'; setXsrfCookie(token); const request = await sendRequest('/foo', { withXSRFToken: false, }); expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toBeUndefined(); }); it('should support function resolver', async () => { const token = '12345'; setXsrfCookie(token); const request = await sendRequest('/foo', { withXSRFToken: (config) => config.userFlag === 'yes', userFlag: 'yes', }); expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toBe(token); }); }); // Non-boolean truthy withXSRFToken must not short-circuit // the same-origin check and leak the XSRF token cross-origin. describe('non-boolean withXSRFToken', () => { afterEach(() => { delete Object.prototype.withXSRFToken; }); const leakCases = [ ['number 1', 1], ['string "false"', 'false'], ['empty object', {}], ['empty array', []], ]; leakCases.forEach(([label, value]) => { it(`should not send xsrf header cross-origin when withXSRFToken = ${label}`, async () => { setXsrfCookie('12345'); const request = await sendRequest('http://example.com/', { withXSRFToken: value, }); expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toBeUndefined(); }); }); it('should not send xsrf header cross-origin when Object.prototype.withXSRFToken is polluted', async () => { Object.prototype.withXSRFToken = 1; setXsrfCookie('12345'); const request = await sendRequest('http://example.com/'); expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toBeUndefined(); }); it('should still send xsrf header cross-origin when withXSRFToken === true (strict)', async () => { const token = '12345'; setXsrfCookie(token); const request = await sendRequest('http://example.com/', { withXSRFToken: true, }); expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toBe(token); }); it('should still send xsrf header same-origin when withXSRFToken is undefined', async () => { const token = '12345'; setXsrfCookie(token); const request = await sendRequest('/foo'); expect(request.requestHeaders[axios.defaults.xsrfHeaderName]).toBe(token); }); }); }); axios-axios-2d06f96/tests/module/000077500000000000000000000000001521272452000167475ustar00rootroot00000000000000axios-axios-2d06f96/tests/module/cjs/000077500000000000000000000000001521272452000175265ustar00rootroot00000000000000axios-axios-2d06f96/tests/module/cjs/package-lock.json000066400000000000000000001156351521272452000227550ustar00rootroot00000000000000{ "name": "@axios/cjs-module-tests", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@axios/cjs-module-tests", "version": "1.0.0", "license": "MIT", "devDependencies": { "@types/node": "12.20.55", "chai": "4.5.0", "mocha": "9.2.2", "typescript": "4.9.5" } }, "node_modules/@types/node": { "version": "12.20.55", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", "dev": true, "license": "MIT" }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", "dev": true, "license": "ISC" }, "node_modules/ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" }, "engines": { "node": ">= 8" } }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, "license": "Python-2.0" }, "node_modules/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true, "license": "MIT", "engines": { "node": "*" } }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, "license": "MIT" }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "license": "MIT", "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true, "license": "ISC" }, "node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "license": "MIT", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/chai": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", "dev": true, "license": "MIT", "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.3", "deep-eql": "^4.1.3", "get-func-name": "^2.0.2", "loupe": "^2.3.6", "pathval": "^1.1.1", "type-detect": "^4.1.0" }, "engines": { "node": ">=4" } }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/chalk/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/check-error": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", "dev": true, "license": "MIT", "dependencies": { "get-func-name": "^2.0.2" }, "engines": { "node": "*" } }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "dev": true, "funding": [ { "type": "individual", "url": "https://paulmillr.com/funding/" } ], "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "engines": { "node": ">= 8.10.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, "engines": { "node": ">=7.0.0" } }, "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, "license": "MIT" }, "node_modules/debug": { "version": "4.3.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "dev": true, "license": "MIT", "dependencies": { "ms": "2.1.2" }, "engines": { "node": ">=6.0" }, "peerDependenciesMeta": { "supports-color": { "optional": true } } }, "node_modules/debug/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true, "license": "MIT" }, "node_modules/decamelize": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", "dev": true, "license": "MIT", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/deep-eql": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", "dev": true, "license": "MIT", "dependencies": { "type-detect": "^4.0.0" }, "engines": { "node": ">=6" } }, "node_modules/diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, "license": "MIT" }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, "license": "BSD-3-Clause", "bin": { "flat": "cli.js" } }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true, "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-func-name": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true, "license": "MIT", "engines": { "node": "*" } }, "node_modules/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, "engines": { "node": ">= 6" } }, "node_modules/glob/node_modules/minimatch": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { "node": "*" } }, "node_modules/growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true, "license": "MIT", "engines": { "node": ">=4.x" } }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true, "license": "MIT", "bin": { "he": "bin/he" } }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true, "license": "ISC" }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, "engines": { "node": ">=8" } }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" } }, "node_modules/is-plain-obj": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, "license": "MIT", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, "license": "ISC" }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/loupe": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", "dev": true, "license": "MIT", "dependencies": { "get-func-name": "^2.0.1" } }, "node_modules/minimatch": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { "node": ">=10" } }, "node_modules/mocha": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", "dev": true, "license": "MIT", "dependencies": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", "chokidar": "3.5.3", "debug": "4.3.3", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", "glob": "7.2.0", "growl": "1.10.5", "he": "1.2.0", "js-yaml": "4.1.0", "log-symbols": "4.1.0", "minimatch": "4.2.1", "ms": "2.1.3", "nanoid": "3.3.1", "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", "workerpool": "6.2.0", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" }, "bin": { "_mocha": "bin/_mocha", "mocha": "bin/mocha" }, "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/mochajs" } }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "license": "MIT" }, "node_modules/nanoid": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "dev": true, "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, "engines": { "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" } }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true, "license": "MIT", "engines": { "node": "*" } }, "node_modules/picomatch": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { "node": ">=8.6" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, "engines": { "node": ">=8.10.0" } }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ], "license": "MIT" }, "node_modules/serialize-javascript": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" } }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, "license": "MIT", "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, "engines": { "node": ">=8.0" } }, "node_modules/type-detect": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", "dev": true, "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { "node": ">=4.2.0" } }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" }, "engines": { "node": ">= 8" } }, "node_modules/workerpool": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", "dev": true, "license": "Apache-2.0" }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true, "license": "ISC" }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", "dev": true, "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" }, "engines": { "node": ">=10" } }, "node_modules/yargs-parser": { "version": "20.2.4", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", "dev": true, "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yargs-unparser": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", "dev": true, "license": "MIT", "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", "flat": "^5.0.2", "is-plain-obj": "^2.1.0" }, "engines": { "node": ">=10" } }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "license": "MIT", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } } } } axios-axios-2d06f96/tests/module/cjs/package.json000066400000000000000000000006571521272452000220240ustar00rootroot00000000000000{ "name": "@axios/cjs-module-tests", "version": "1.0.0", "description": "CJS module compatibility tests for axios", "private": true, "scripts": { "test:module:cjs": "mocha --timeout 10000 \"tests/**/*.module.test.cjs\"" }, "keywords": [], "author": "axios team", "license": "MIT", "devDependencies": { "@types/node": "12.20.55", "chai": "4.5.0", "mocha": "9.2.2", "typescript": "4.9.5" } }axios-axios-2d06f96/tests/module/cjs/tests/000077500000000000000000000000001521272452000206705ustar00rootroot00000000000000axios-axios-2d06f96/tests/module/cjs/tests/fixture-cleanup.module.test.cjs000066400000000000000000000026101521272452000267450ustar00rootroot00000000000000const assert = require('assert'); const fs = require('fs'); const os = require('os'); const path = require('path'); const { describe, it } = require('mocha'); const { cleanupTempFixture } = require('./helpers/fixture.cjs'); describe('module fixture cleanup helper', () => { it('removes fixture directories without shelling out to rm', () => { const fixturePath = fs.mkdtempSync(path.join(os.tmpdir(), 'axios-module-fixture-')); const nestedPath = path.join(fixturePath, 'nested'); const originalPath = process.env.PATH; fs.mkdirSync(nestedPath); fs.writeFileSync(path.join(nestedPath, 'index.ts'), 'export {};\n'); process.env.PATH = ''; try { cleanupTempFixture(fixturePath); } finally { process.env.PATH = originalPath; } assert.strictEqual(fs.existsSync(fixturePath), false); }); it('removes fixture directories when fs.rmSync is unavailable', () => { const fixturePath = fs.mkdtempSync(path.join(os.tmpdir(), 'axios-module-fixture-legacy-')); const nestedPath = path.join(fixturePath, 'nested'); const originalRmSync = fs.rmSync; fs.mkdirSync(nestedPath); fs.writeFileSync(path.join(nestedPath, 'index.ts'), 'export {};\n'); fs.rmSync = undefined; try { cleanupTempFixture(fixturePath); } finally { fs.rmSync = originalRmSync; } assert.strictEqual(fs.existsSync(fixturePath), false); }); }); axios-axios-2d06f96/tests/module/cjs/tests/helpers/000077500000000000000000000000001521272452000223325ustar00rootroot00000000000000axios-axios-2d06f96/tests/module/cjs/tests/helpers/cjs-is-cancel-typing.ts000066400000000000000000000006751521272452000266350ustar00rootroot00000000000000import axios = require('axios'); declare const thrown: unknown; if (axios.isCancel<{ ok: true }>(thrown)) { const canceled: InstanceType = thrown; const data: { ok: true } | undefined = thrown.response?.data; // @ts-expect-error -- The generic response data must not be widened to any. const wrongData: { ok: false } | undefined = thrown.response?.data; console.log(canceled.message, data, wrongData); } axios-axios-2d06f96/tests/module/cjs/tests/helpers/cjs-typing.ts000066400000000000000000000337621521272452000250040ustar00rootroot00000000000000// @ts-nocheck import axios = require('axios'); const config: axios.AxiosRequestConfig = { url: '/user', method: 'get', allowAbsoluteUrls: false, baseURL: 'https://api.example.com/', transformRequest: (data: any) => '{"foo":"bar"}', transformResponse: [(data: any) => ({ baz: 'qux' })], headers: { 'X-FOO': 'bar' }, params: { id: 12345 }, paramsSerializer: { indexes: true, encode: (value: any) => value, serialize: (value: Record, options?: axios.ParamsSerializerOptions) => String(value), }, data: { foo: 'bar' }, timeout: 10000, withCredentials: true, auth: { username: 'janedoe', password: 's00pers3cret', }, responseType: 'json', xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', onUploadProgress: (progressEvent: axios.AxiosProgressEvent) => {}, onDownloadProgress: (progressEvent: axios.AxiosProgressEvent) => {}, maxContentLength: 2000, maxBodyLength: 2000, validateStatus: (status: number) => status >= 200 && status < 300, maxRedirects: 5, proxy: { host: '127.0.0.1', port: 9000, }, cancelToken: new axios.CancelToken((cancel: axios.Canceler) => {}), }; const nullValidateStatusConfig: axios.AxiosRequestConfig = { validateStatus: null, }; const undefinedValidateStatusConfig: axios.AxiosRequestConfig = { validateStatus: undefined, }; const handleResponse = (response: axios.AxiosResponse) => { console.log(response.data); console.log(response.status); console.log(response.statusText); console.log(response.headers); console.log(response.config); }; const handleError = (error: axios.AxiosError) => { if (error.response) { console.log(error.response.data); console.log(error.response.status); console.log(error.response.headers); } else { console.log(error.message); } }; axios(config).then(handleResponse).catch(handleError); axios.get('/user?id=12345').then(handleResponse).catch(handleError); axios .get('/user', { params: { id: 12345 } }) .then(handleResponse) .catch(handleError); axios.head('/user').then(handleResponse).catch(handleError); axios.options('/user').then(handleResponse).catch(handleError); axios.delete('/user').then(handleResponse).catch(handleError); axios.post('/user', { foo: 'bar' }).then(handleResponse).catch(handleError); axios .post('/user', { foo: 'bar' }, { headers: { 'X-FOO': 'bar' } }) .then(handleResponse) .catch(handleError); axios.put('/user', { foo: 'bar' }).then(handleResponse).catch(handleError); axios.patch('/user', { foo: 'bar' }).then(handleResponse).catch(handleError); axios.query('/user', { foo: 'bar' }).then(handleResponse).catch(handleError); // Typed methods interface UserCreationDef { name: string; } interface User { id: number; name: string; } interface ResponseHeaders { 'x-header': string; } // with default axios.AxiosResponse result const handleUserResponse = (response: axios.AxiosResponse) => { console.log(response.data.id); console.log(response.data.name); console.log(response.status); console.log(response.statusText); console.log(response.headers); console.log(response.config); }; axios.get('/user?id=12345').then(handleUserResponse).catch(handleError); axios .get('/user', { params: { id: 12345 } }) .then(handleUserResponse) .catch(handleError); axios.head('/user').then(handleUserResponse).catch(handleError); axios.options('/user').then(handleUserResponse).catch(handleError); axios.delete('/user').then(handleUserResponse).catch(handleError); axios.post('/user', { name: 'foo', id: 1 }).then(handleUserResponse).catch(handleError); axios .post('/user', { name: 'foo', id: 1 }, { headers: { 'X-FOO': 'bar' } }) .then(handleUserResponse) .catch(handleError); axios.put('/user', { name: 'foo', id: 1 }).then(handleUserResponse).catch(handleError); axios.patch('/user', { name: 'foo', id: 1 }).then(handleUserResponse).catch(handleError); // with custom response headers axios.AxiosResponse result const handleUserResponseWithCustomHeaders = ( response: axios.AxiosResponse ) => { console.log(response.data.id); console.log(response.data.name); console.log(response.status); console.log(response.statusText); console.log(response.headers); console.log(response.config); }; axios .get>('/user?id=12345') .then(handleUserResponseWithCustomHeaders) .catch(handleError); axios .get>('/user', { params: { id: 12345 } }) .then(handleUserResponseWithCustomHeaders) .catch(handleError); axios .head>('/user') .then(handleUserResponseWithCustomHeaders) .catch(handleError); axios .options>('/user') .then(handleUserResponseWithCustomHeaders) .catch(handleError); axios .delete>('/user') .then(handleUserResponseWithCustomHeaders) .catch(handleError); axios .post>('/user', { name: 'foo', id: 1 }) .then(handleUserResponseWithCustomHeaders) .catch(handleError); axios .post>( '/user', { name: 'foo', id: 1 }, { headers: { 'X-FOO': 'bar' } } ) .then(handleUserResponseWithCustomHeaders) .catch(handleError); axios .put>('/user', { name: 'foo', id: 1 }) .then(handleUserResponseWithCustomHeaders) .catch(handleError); axios .patch>('/user', { name: 'foo', id: 1 }) .then(handleUserResponseWithCustomHeaders) .catch(handleError); // (Typed methods) with custom response type const handleStringResponse = (response: string) => { console.log(response); }; axios.get('/user?id=12345').then(handleStringResponse).catch(handleError); axios .get('/user', { params: { id: 12345 } }) .then(handleStringResponse) .catch(handleError); axios.head('/user').then(handleStringResponse).catch(handleError); axios.options('/user').then(handleStringResponse).catch(handleError); axios.delete('/user').then(handleStringResponse).catch(handleError); axios .post, string>('/user', { name: 'foo' }) .then(handleStringResponse) .catch(handleError); axios .post, string>('/user', { name: 'foo' }, { headers: { 'X-FOO': 'bar' } }) .then(handleStringResponse) .catch(handleError); axios .put, string>('/user', { name: 'foo' }) .then(handleStringResponse) .catch(handleError); axios .patch, string>('/user', { name: 'foo' }) .then(handleStringResponse) .catch(handleError); axios .request({ method: 'get', url: '/user?id=12345', }) .then(handleStringResponse) .catch(handleError); // Instances const instance1: axios.AxiosInstance = axios.create(); const instance2: axios.AxiosInstance = axios.create(config); instance1(config).then(handleResponse).catch(handleError); instance1.request(config).then(handleResponse).catch(handleError); instance1.get('/user?id=12345').then(handleResponse).catch(handleError); instance1.options('/user').then(handleResponse).catch(handleError); instance1 .get('/user', { params: { id: 12345 } }) .then(handleResponse) .catch(handleError); instance1.post('/user', { foo: 'bar' }).then(handleResponse).catch(handleError); instance1 .post('/user', { foo: 'bar' }, { headers: { 'X-FOO': 'bar' } }) .then(handleResponse) .catch(handleError); // Defaults axios.defaults.headers['X-FOO']; axios.defaults.baseURL = 'https://api.example.com/'; axios.defaults.headers.common['Accept'] = 'application/json'; axios.defaults.headers.post['X-FOO'] = 'bar'; axios.defaults.timeout = 2500; instance1.defaults.baseURL = 'https://api.example.com/'; instance1.defaults.headers.common['Accept'] = 'application/json'; instance1.defaults.headers.post['X-FOO'] = 'bar'; instance1.defaults.timeout = 2500; // axios create defaults axios.create({ headers: { foo: 'bar' } }); axios.create({ headers: { common: { foo: 'bar' } } }); axios.create({ headers: { 'Content-Type': 'application/json', }, formSerializer: { indexes: null, }, paramsSerializer: { indexes: null, }, }); // Interceptors const requestInterceptorId: number = axios.interceptors.request.use( (config: axios.InternalAxiosRequestConfig) => config, (error: any) => Promise.reject(error) ); axios.interceptors.request.eject(requestInterceptorId); axios.interceptors.request.use( (config: axios.InternalAxiosRequestConfig) => Promise.resolve(config), (error: any) => Promise.reject(error) ); axios.interceptors.request.use((config: axios.InternalAxiosRequestConfig) => config); axios.interceptors.request.use((config: axios.InternalAxiosRequestConfig) => Promise.resolve(config) ); const responseInterceptorId: number = axios.interceptors.response.use( (response: axios.AxiosResponse) => response, (error: any) => Promise.reject(error) ); axios.interceptors.response.eject(responseInterceptorId); axios.interceptors.response.use( (response: axios.AxiosResponse) => Promise.resolve(response), (error: any) => Promise.reject(error) ); axios.interceptors.request.use((req) => { // https://github.com/axios/axios/issues/5415 req.headers.set('foo', 'bar'); req.headers['Content-Type'] = 123; return req; }); const voidRequestInterceptorId = axios.interceptors.request.use( // @ts-expect-error -- Must return an axios.AxiosRequestConfig (or throw) (_response) => {}, (error: any) => Promise.reject(error) ); const voidResponseInterceptorId = axios.interceptors.response.use( // @ts-expect-error -- Must return an axios.AxiosResponse (or throw) (_response) => {}, (error: any) => Promise.reject(error) ); axios.interceptors.request.eject(voidRequestInterceptorId); axios.interceptors.response.eject(voidResponseInterceptorId); axios.interceptors.response.use((response: axios.AxiosResponse) => response); axios.interceptors.response.use((response: axios.AxiosResponse) => Promise.resolve(response)); axios.interceptors.request.clear(); axios.interceptors.response.clear(); // Adapters const adapter: axios.AxiosAdapter = (config: axios.InternalAxiosRequestConfig) => { const response: axios.AxiosResponse = { data: { foo: 'bar' }, status: 200, statusText: 'OK', headers: { 'X-FOO': 'bar' }, config, }; return Promise.resolve(response); }; axios.defaults.adapter = adapter; // axios.all const promises = [Promise.resolve(1), Promise.resolve(2)]; const promise: Promise = axios.all(promises); // axios.spread const fn1 = (a: number, b: number, c: number) => `${a}-${b}-${c}`; const fn2: (arr: number[]) => string = axios.spread(fn1); // Promises axios .get('/user') .then((response: axios.AxiosResponse) => 'foo') .then((value: string) => {}); axios .get('/user') .then((response: axios.AxiosResponse) => Promise.resolve('foo')) .then((value: string) => {}); axios .get('/user') .then( (response: axios.AxiosResponse) => 'foo', (error: any) => 'bar' ) .then((value: string) => {}); axios .get('/user') .then( (response: axios.AxiosResponse) => 'foo', (error: any) => 123 ) .then((value: string | number) => {}); axios .get('/user') .catch((error: any) => 'foo') .then((value) => {}); axios .get('/user') .catch((error: any) => Promise.resolve('foo')) .then((value) => {}); // axios.Cancellation const source: axios.CancelTokenSource = axios.CancelToken.source(); axios .get('/user', { cancelToken: source.token, }) .catch((thrown: axios.AxiosError | axios.Cancel) => { if (axios.isCancel(thrown)) { const cancel: axios.Cancel = thrown; console.log(cancel.message); } }); source.cancel('Operation has been axios.Canceled.'); // axios.AxiosError axios.get('/user').catch((error) => { if (axios.isAxiosError(error)) { const axiosError: axios.AxiosError = error; console.log(axiosError.message); } }); // FormData axios.toFormData({ x: 1 }, new FormData()); // AbortSignal axios.get('/user', { signal: new AbortController().signal }); // AxiosHeaders methods axios.get('/user', { transformRequest: (data, headers) => { headers.setContentType('text/plain'); headers['Foo'] = 'bar'; }, transformResponse: (data, headers) => { headers.has('foo'); }, }); // Max Rate axios.get('/user', { maxRate: 1000, }); axios.get('/user', { maxRate: [1000, 1000], }); // Node progress axios.get('/user', { onUploadProgress: (e: axios.AxiosProgressEvent) => { console.log(e.loaded); console.log(e.total); console.log(e.progress); console.log(e.rate); }, }); // AxiosHeaders // iterator const headers = new axios.AxiosHeaders({ foo: 'bar' }); for (const [header, value] of headers) { console.log(header, value); } // index signature (() => { const headers = new axios.AxiosHeaders({ x: 1 }); headers.y = 2; })(); // AxiosRequestHeaders (() => { const headers: axios.AxiosRequestHeaders = new axios.AxiosHeaders({ x: 1 }); headers.y = 2; headers.get('x'); })(); // AxiosHeaders instance assignment { const requestInterceptorId: number = axios.interceptors.request.use( async (config) => { config.headers.Accept = 'foo'; config.headers.setAccept('foo'); config.headers = new axios.AxiosHeaders({ x: 1 }); config.headers.foo = '1'; config.headers.set('bar', '2'); config.headers.set({ myHeader: 'myValue' }); config.headers = new axios.AxiosHeaders({ myHeader: 'myValue' }); config.headers = { ...config.headers } as axios.AxiosRequestHeaders; return config; }, (error: any) => Promise.reject(error) ); } { const config: axios.AxiosRequestConfig = { headers: new axios.AxiosHeaders({ foo: 1 }) }; axios.get('', { headers: { bar: 2, ...config.headers, }, }); } axios-axios-2d06f96/tests/module/cjs/tests/helpers/fixture.cjs000066400000000000000000000015711521272452000245250ustar00rootroot00000000000000const fs = require('fs'); const path = require('path'); const createTempFixture = (suiteRoot, name, sourcePath, tsconfig, packageJson) => { const tempRoot = fs.mkdtempSync(path.join(suiteRoot, `.tmp-module-${name}-`)); const source = fs.readFileSync(sourcePath, 'utf8'); fs.writeFileSync(path.join(tempRoot, 'index.ts'), source); fs.writeFileSync(path.join(tempRoot, 'tsconfig.json'), JSON.stringify(tsconfig, null, 2)); if (packageJson) { fs.writeFileSync(path.join(tempRoot, 'package.json'), JSON.stringify(packageJson, null, 2)); } return tempRoot; }; const cleanupTempFixture = (dirPath) => { if (typeof fs.rmSync === 'function') { fs.rmSync(dirPath, { recursive: true, force: true }); return; } if (fs.existsSync(dirPath)) { fs.rmdirSync(dirPath, { recursive: true }); } }; module.exports = { createTempFixture, cleanupTempFixture, }; axios-axios-2d06f96/tests/module/cjs/tests/helpers/run-command.cjs000066400000000000000000000017471521272452000252640ustar00rootroot00000000000000const { spawnSync } = require('child_process'); const formatCommand = (command, args) => [command].concat(args || []).join(' '); const runCommand = (command, args, options) => { const spawnOptions = Object.assign({ encoding: 'utf8' }, options || {}); const result = spawnSync(command, args || [], spawnOptions); const output = { code: result.status, stdout: result.stdout || '', stderr: result.stderr || '', command: formatCommand(command, args), cwd: spawnOptions.cwd || process.cwd(), }; if (result.error) { throw result.error; } if (output.code !== 0) { const error = new Error( [ 'Command failed:', ` command: ${output.command}`, ` cwd: ${output.cwd}`, ` exitCode: ${String(output.code)}`, ` stdout:\n${output.stdout}`, ` stderr:\n${output.stderr}`, ].join('\n') ); error.commandResult = output; throw error; } return output; }; module.exports = { runCommand, }; axios-axios-2d06f96/tests/module/cjs/tests/helpers/ts-require-default.ts000066400000000000000000000023251521272452000264260ustar00rootroot00000000000000// @ts-nocheck const assert = require('assert'); const axios = require('axios').default; const { CanceledError, AxiosError, AxiosHeaders, formToJSON, spread, isAxiosError, isCancel, all, toFormData, } = axios; assert.strictEqual(typeof axios, 'function'); assert.strictEqual(typeof CanceledError, 'function'); assert.strictEqual(typeof AxiosError, 'function'); assert.strictEqual(typeof AxiosHeaders, 'function'); assert.strictEqual(typeof formToJSON, 'function'); assert.strictEqual(typeof spread, 'function'); assert.strictEqual(typeof isAxiosError, 'function'); assert.strictEqual(typeof isCancel, 'function'); assert.strictEqual(typeof all, 'function'); assert.strictEqual(typeof toFormData, 'function'); assert.strictEqual(typeof axios.CanceledError, 'function'); assert.strictEqual(typeof axios.AxiosError, 'function'); assert.strictEqual(typeof axios.AxiosHeaders, 'function'); assert.strictEqual(typeof axios.formToJSON, 'function'); assert.strictEqual(typeof axios.spread, 'function'); assert.strictEqual(typeof axios.isAxiosError, 'function'); assert.strictEqual(typeof axios.isCancel, 'function'); assert.strictEqual(typeof axios.all, 'function'); assert.strictEqual(typeof axios.toFormData, 'function'); axios-axios-2d06f96/tests/module/cjs/tests/helpers/ts-require.ts000066400000000000000000000023151521272452000250030ustar00rootroot00000000000000// @ts-nocheck const assert = require('assert'); const axios = require('axios'); const { CanceledError, AxiosError, AxiosHeaders, formToJSON, spread, isAxiosError, isCancel, all, toFormData, } = axios; assert.strictEqual(typeof axios, 'function'); assert.strictEqual(typeof CanceledError, 'function'); assert.strictEqual(typeof AxiosError, 'function'); assert.strictEqual(typeof AxiosHeaders, 'function'); assert.strictEqual(typeof formToJSON, 'function'); assert.strictEqual(typeof spread, 'function'); assert.strictEqual(typeof isAxiosError, 'function'); assert.strictEqual(typeof isCancel, 'function'); assert.strictEqual(typeof all, 'function'); assert.strictEqual(typeof toFormData, 'function'); assert.strictEqual(typeof axios.CanceledError, 'function'); assert.strictEqual(typeof axios.AxiosError, 'function'); assert.strictEqual(typeof axios.AxiosHeaders, 'function'); assert.strictEqual(typeof axios.formToJSON, 'function'); assert.strictEqual(typeof axios.spread, 'function'); assert.strictEqual(typeof axios.isAxiosError, 'function'); assert.strictEqual(typeof axios.isCancel, 'function'); assert.strictEqual(typeof axios.all, 'function'); assert.strictEqual(typeof axios.toFormData, 'function'); axios-axios-2d06f96/tests/module/cjs/tests/ts-require-default.module.test.cjs000066400000000000000000000022001521272452000273470ustar00rootroot00000000000000const path = require('path'); const { describe, it } = require('mocha'); const { createTempFixture, cleanupTempFixture } = require('./helpers/fixture.cjs'); const { runCommand } = require('./helpers/run-command.cjs'); const suiteRoot = path.resolve(__dirname, '..'); const repoRoot = path.resolve(suiteRoot, '../../..'); const tscBin = path.join(suiteRoot, 'node_modules', 'typescript', 'bin', 'tsc'); const tsconfig = { compilerOptions: { target: 'es2016', module: 'commonjs', moduleResolution: 'node', esModuleInterop: true, strict: true, skipLibCheck: true, }, }; describe('module ts-require-default compatibility', () => { it('compiles and executes require("axios").default imports', () => { const sourcePath = path.join(repoRoot, 'tests/module/cjs/tests/helpers/ts-require-default.ts'); const fixturePath = createTempFixture(suiteRoot, 'ts-require-default', sourcePath, tsconfig); try { runCommand('node', [tscBin, '-p', 'tsconfig.json'], { cwd: fixturePath }); runCommand('node', ['index.js'], { cwd: fixturePath }); } finally { cleanupTempFixture(fixturePath); } }); }); axios-axios-2d06f96/tests/module/cjs/tests/ts-require.module.test.cjs000066400000000000000000000021401521272452000257300ustar00rootroot00000000000000const path = require('path'); const { describe, it } = require('mocha'); const { createTempFixture, cleanupTempFixture } = require('./helpers/fixture.cjs'); const { runCommand } = require('./helpers/run-command.cjs'); const suiteRoot = path.resolve(__dirname, '..'); const repoRoot = path.resolve(suiteRoot, '../../..'); const tscBin = path.join(suiteRoot, 'node_modules', 'typescript', 'bin', 'tsc'); const tsconfig = { compilerOptions: { target: 'es2016', module: 'commonjs', moduleResolution: 'node', esModuleInterop: true, strict: true, skipLibCheck: true, }, }; describe('module ts-require compatibility', () => { it('compiles and executes require("axios") imports', () => { const sourcePath = path.join(repoRoot, 'tests/module/cjs/tests/helpers/ts-require.ts'); const fixturePath = createTempFixture(suiteRoot, 'ts-require', sourcePath, tsconfig); try { runCommand('node', [tscBin, '-p', 'tsconfig.json'], { cwd: fixturePath }); runCommand('node', ['index.js'], { cwd: fixturePath }); } finally { cleanupTempFixture(fixturePath); } }); }); axios-axios-2d06f96/tests/module/cjs/tests/typings.module.test.cjs000066400000000000000000000025711521272452000253350ustar00rootroot00000000000000const path = require('path'); const { describe, it } = require('mocha'); const { createTempFixture, cleanupTempFixture } = require('./helpers/fixture.cjs'); const { runCommand } = require('./helpers/run-command.cjs'); const suiteRoot = path.resolve(__dirname, '..'); const repoRoot = path.resolve(suiteRoot, '../../..'); const tscBin = path.join(suiteRoot, 'node_modules', 'typescript', 'bin', 'tsc'); const tsconfig = { compilerOptions: { checkJs: true, module: 'node16', }, }; describe('module cjs typings compatibility', () => { it('type-checks commonjs axios typings', () => { const sourcePath = path.join(repoRoot, 'tests/module/cjs/tests/helpers/cjs-typing.ts'); const fixturePath = createTempFixture(suiteRoot, 'typings-cjs', sourcePath, tsconfig); try { runCommand('node', [tscBin, '--noEmit', '-p', 'tsconfig.json'], { cwd: fixturePath }); } finally { cleanupTempFixture(fixturePath); } }); it('narrows isCancel to CanceledError in commonjs typings', () => { const sourcePath = path.join(repoRoot, 'tests/module/cjs/tests/helpers/cjs-is-cancel-typing.ts'); const fixturePath = createTempFixture(suiteRoot, 'typings-cjs-is-cancel', sourcePath, tsconfig); try { runCommand('node', [tscBin, '--noEmit', '-p', 'tsconfig.json'], { cwd: fixturePath }); } finally { cleanupTempFixture(fixturePath); } }); }); axios-axios-2d06f96/tests/module/esm/000077500000000000000000000000001521272452000175335ustar00rootroot00000000000000axios-axios-2d06f96/tests/module/esm/package-lock.json000066400000000000000000001246501521272452000227570ustar00rootroot00000000000000{ "name": "@axios/esm-module-tests", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@axios/esm-module-tests", "version": "1.0.0", "license": "MIT", "devDependencies": { "@types/node": "^20.19.39", "typescript": "^5.9.3", "vitest": "4.1.5" } }, "node_modules/@emnapi/core": { "version": "1.9.2", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", "dev": true, "license": "MIT", "optional": true, "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "node_modules/@emnapi/runtime": { "version": "1.9.2", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", "dev": true, "license": "MIT", "optional": true, "dependencies": { "tslib": "^2.4.0" } }, "node_modules/@emnapi/wasi-threads": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", "dev": true, "license": "MIT", "optional": true, "dependencies": { "tslib": "^2.4.0" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, "license": "MIT" }, "node_modules/@napi-rs/wasm-runtime": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", "dev": true, "license": "MIT", "optional": true, "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "funding": { "type": "github", "url": "https://github.com/sponsors/Brooooooklyn" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "node_modules/@oxc-project/types": { "version": "0.126.0", "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.126.0.tgz", "integrity": "sha512-oGfVtjAgwQVVpfBrbtk4e1XDyWHRFta6BS3GWVzrF8xYBT2VGQAk39yJS/wFSMrZqoiCU4oghT3Ch0HaHGIHcQ==", "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/Boshen" } }, "node_modules/@rolldown/binding-android-arm64": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.16.tgz", "integrity": "sha512-rhY3k7Bsae9qQfOtph2Pm2jZEA+s8Gmjoz4hhmx70K9iMQ/ddeae+xhRQcM5IuVx5ry1+bGfkvMn7D6MJggVSA==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "android" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-darwin-arm64": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.16.tgz", "integrity": "sha512-rNz0yK078yrNn3DrdgN+PKiMOW8HfQ92jQiXxwX8yW899ayV00MLVdaCNeVBhG/TbH3ouYVObo8/yrkiectkcQ==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-darwin-x64": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.16.tgz", "integrity": "sha512-r/OmdR00HmD4i79Z//xO06uEPOq5hRXdhw7nzkxQxwSavs3PSHa1ijntdpOiZ2mzOQ3fVVu8C1M19FoNM+dMUQ==", "cpu": [ "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-freebsd-x64": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.16.tgz", "integrity": "sha512-KcRE5w8h0OnjUatG8pldyD14/CQ5Phs1oxfR+3pKDjboHRo9+MkqQaiIZlZRpsxC15paeXme/I127tUa9TXJ6g==", "cpu": [ "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "freebsd" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.16.tgz", "integrity": "sha512-bT0guA1bpxEJ/ZhTRniQf7rNF8ybvXOuWbNIeLABaV5NGjx4EtOWBTSRGWFU9ZWVkPOZ+HNFP8RMcBokBiZ0Kg==", "cpu": [ "arm" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.16.tgz", "integrity": "sha512-+tHktCHWV8BDQSjemUqm/Jl/TPk3QObCTIjmdDy/nlupcujZghmKK2962LYrqFpWu+ai01AN/REOH3NEpqvYQg==", "cpu": [ "arm64" ], "dev": true, "libc": [ "glibc" ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-arm64-musl": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.16.tgz", "integrity": "sha512-3fPzdREH806oRLxpTWW1Gt4tQHs0TitZFOECB2xzCFLPKnSOy90gwA7P29cksYilFO6XVRY1kzga0cL2nRjKPg==", "cpu": [ "arm64" ], "dev": true, "libc": [ "musl" ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.16.tgz", "integrity": "sha512-EKwI1tSrLs7YVw+JPJT/G2dJQ1jl9qlTTTEG0V2Ok/RdOenRfBw2PQdLPyjhIu58ocdBfP7vIRN/pvMsPxs/AQ==", "cpu": [ "ppc64" ], "dev": true, "libc": [ "glibc" ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.16.tgz", "integrity": "sha512-Uknladnb3Sxqu6SEcqBldQyJUpk8NleooZEc0MbRBJ4inEhRYWZX0NJu12vNf2mqAq7gsofAxHrGghiUYjhaLQ==", "cpu": [ "s390x" ], "dev": true, "libc": [ "glibc" ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-x64-gnu": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.16.tgz", "integrity": "sha512-FIb8+uG49sZBtLTn+zt1AJ20TqVcqWeSIyoVt0or7uAWesgKaHbiBh6OpA/k9v0LTt+PTrb1Lao133kP4uVxkg==", "cpu": [ "x64" ], "dev": true, "libc": [ "glibc" ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-x64-musl": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.16.tgz", "integrity": "sha512-RuERhF9/EgWxZEXYWCOaViUWHIboceK4/ivdtQ3R0T44NjLkIIlGIAVAuCddFxsZ7vnRHtNQUrt2vR2n2slB2w==", "cpu": [ "x64" ], "dev": true, "libc": [ "musl" ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-openharmony-arm64": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.16.tgz", "integrity": "sha512-mXcXnvd9GpazCxeUCCnZ2+YF7nut+ZOEbE4GtaiPtyY6AkhZWbK70y1KK3j+RDhjVq5+U8FySkKRb/+w0EeUwA==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "openharmony" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-wasm32-wasi": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.16.tgz", "integrity": "sha512-3Q2KQxnC8IJOLqXmUMoYwyIPZU9hzRbnHaoV3Euz+VVnjZKcY8ktnNP8T9R4/GGQtb27C/UYKABxesKWb8lsvQ==", "cpu": [ "wasm32" ], "dev": true, "license": "MIT", "optional": true, "dependencies": { "@emnapi/core": "1.9.2", "@emnapi/runtime": "1.9.2", "@napi-rs/wasm-runtime": "^1.1.4" }, "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.16.tgz", "integrity": "sha512-tj7XRemQcOcFwv7qhpUxMTBbI5mWMlE4c1Omhg5+h8GuLXzyj8HviYgR+bB2DMDgRqUE+jiDleqSCRjx4aYk/Q==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-win32-x64-msvc": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.16.tgz", "integrity": "sha512-PH5DRZT+F4f2PTXRXR8uJxnBq2po/xFtddyabTJVJs/ZYVHqXPEgNIr35IHTEa6bpa0Q8Awg+ymkTaGnKITw4g==", "cpu": [ "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.16.tgz", "integrity": "sha512-45+YtqxLYKDWQouLKCrpIZhke+nXxhsw+qAHVzHDVwttyBlHNBVs2K25rDXrZzhpTp9w1FlAlvweV1H++fdZoA==", "dev": true, "license": "MIT" }, "node_modules/@standard-schema/spec": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", "dev": true, "license": "MIT" }, "node_modules/@tybys/wasm-util": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", "dev": true, "license": "MIT", "optional": true, "dependencies": { "tslib": "^2.4.0" } }, "node_modules/@types/chai": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", "dev": true, "license": "MIT", "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "node_modules/@types/deep-eql": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", "dev": true, "license": "MIT" }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, "license": "MIT" }, "node_modules/@types/node": { "version": "20.19.39", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.39.tgz", "integrity": "sha512-orrrD74MBUyK8jOAD/r0+lfa1I2MO6I+vAkmAWzMYbCcgrN4lCrmK52gRFQq/JRxfYPfonkr4b0jcY7Olqdqbw==", "dev": true, "license": "MIT", "dependencies": { "undici-types": "~6.21.0" } }, "node_modules/@vitest/expect": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.5.tgz", "integrity": "sha512-PWBaRY5JoKuRnHlUHfpV/KohFylaDZTupcXN1H9vYryNLOnitSw60Mw9IAE2r67NbwwzBw/Cc/8q9BK3kIX8Kw==", "dev": true, "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.5", "@vitest/utils": "4.1.5", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/mocker": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.5.tgz", "integrity": "sha512-/x2EmFC4mT4NNzqvC3fmesuV97w5FC903KPmey4gsnJiMQ3Be1IlDKVaDaG8iqaLFHqJ2FVEkxZk5VmeLjIItw==", "dev": true, "license": "MIT", "dependencies": { "@vitest/spy": "4.1.5", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "msw": { "optional": true }, "vite": { "optional": true } } }, "node_modules/@vitest/pretty-format": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.5.tgz", "integrity": "sha512-7I3q6l5qr03dVfMX2wCo9FxwSJbPdwKjy2uu/YPpU3wfHvIL4QHwVRp57OfGrDFeUJ8/8QdfBKIV12FTtLn00g==", "dev": true, "license": "MIT", "dependencies": { "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/runner": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.5.tgz", "integrity": "sha512-2D+o7Pr82IEO46YPpoA/YU0neeyr6FTerQb5Ro7BUnBuv6NQtT/kmVnczngiMEBhzgqz2UZYl5gArejsyERDSQ==", "dev": true, "license": "MIT", "dependencies": { "@vitest/utils": "4.1.5", "pathe": "^2.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.5.tgz", "integrity": "sha512-zypXEt4KH/XgKGPUz4eC2AvErYx0My5hfL8oDb1HzGFpEk1P62bxSohdyOmvz+d9UJwanI68MKwr2EquOaOgMQ==", "dev": true, "license": "MIT", "dependencies": { "@vitest/pretty-format": "4.1.5", "@vitest/utils": "4.1.5", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/spy": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.5.tgz", "integrity": "sha512-2lNOsh6+R2Idnf1TCZqSwYlKN2E/iDlD8sgU59kYVl+OMDmvldO1VDk39smRfpUNwYpNRVn3w4YfuC7KfbBnkQ==", "dev": true, "license": "MIT", "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/utils": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.5.tgz", "integrity": "sha512-76wdkrmfXfqGjueGgnb45ITPyUi1ycZ4IHgC2bhPDUfWHklY/q3MdLOAB+TF1e6xfl8NxNY0ZYaPCFNWSsw3Ug==", "dev": true, "license": "MIT", "dependencies": { "@vitest/pretty-format": "4.1.5", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "license": "MIT", "engines": { "node": ">=12" } }, "node_modules/chai": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", "dev": true, "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, "license": "MIT" }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, "license": "Apache-2.0", "engines": { "node": ">=8" } }, "node_modules/es-module-lexer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", "dev": true, "license": "MIT" }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dev": true, "license": "MIT", "dependencies": { "@types/estree": "^1.0.0" } }, "node_modules/expect-type": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", "dev": true, "license": "Apache-2.0", "engines": { "node": ">=12.0.0" } }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", "engines": { "node": ">=12.0.0" }, "peerDependencies": { "picomatch": "^3 || ^4" }, "peerDependenciesMeta": { "picomatch": { "optional": true } } }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, "node_modules/lightningcss": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", "dev": true, "license": "MPL-2.0", "dependencies": { "detect-libc": "^2.0.3" }, "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "node_modules/lightningcss-android-arm64": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", "cpu": [ "arm64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "android" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-darwin-arm64": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", "cpu": [ "arm64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "darwin" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-darwin-x64": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", "cpu": [ "x64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "darwin" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-freebsd-x64": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", "cpu": [ "x64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "freebsd" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-linux-arm-gnueabihf": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", "cpu": [ "arm" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "linux" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-linux-arm64-gnu": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", "cpu": [ "arm64" ], "dev": true, "libc": [ "glibc" ], "license": "MPL-2.0", "optional": true, "os": [ "linux" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-linux-arm64-musl": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", "cpu": [ "arm64" ], "dev": true, "libc": [ "musl" ], "license": "MPL-2.0", "optional": true, "os": [ "linux" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-linux-x64-gnu": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", "cpu": [ "x64" ], "dev": true, "libc": [ "glibc" ], "license": "MPL-2.0", "optional": true, "os": [ "linux" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-linux-x64-musl": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", "cpu": [ "x64" ], "dev": true, "libc": [ "musl" ], "license": "MPL-2.0", "optional": true, "os": [ "linux" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-win32-arm64-msvc": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", "cpu": [ "arm64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "win32" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-win32-x64-msvc": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", "cpu": [ "x64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "win32" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/ai" } ], "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, "engines": { "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, "node_modules/obug": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", "dev": true, "funding": [ "https://github.com/sponsors/sxzz", "https://opencollective.com/debug" ], "license": "MIT" }, "node_modules/pathe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, "license": "MIT" }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, "license": "ISC" }, "node_modules/picomatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/postcss": { "version": "8.5.10", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz", "integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/postcss/" }, { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" }, { "type": "github", "url": "https://github.com/sponsors/ai" } ], "license": "MIT", "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" } }, "node_modules/rolldown": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.16.tgz", "integrity": "sha512-rzi5WqKzEZw3SooTt7cgm4eqIoujPIyGcJNGFL7iPEuajQw7vxMHUkXylu4/vhCkJGXsgRmxqMKXUpT6FEgl0g==", "dev": true, "license": "MIT", "dependencies": { "@oxc-project/types": "=0.126.0", "@rolldown/pluginutils": "1.0.0-rc.16" }, "bin": { "rolldown": "bin/cli.mjs" }, "engines": { "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.16", "@rolldown/binding-darwin-arm64": "1.0.0-rc.16", "@rolldown/binding-darwin-x64": "1.0.0-rc.16", "@rolldown/binding-freebsd-x64": "1.0.0-rc.16", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.16", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.16", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.16", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.16", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.16", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.16", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.16", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.16", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.16", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.16", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.16" } }, "node_modules/siginfo": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true, "license": "ISC" }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true, "license": "MIT" }, "node_modules/std-env": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz", "integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==", "dev": true, "license": "MIT" }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", "dev": true, "license": "MIT" }, "node_modules/tinyexec": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz", "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==", "dev": true, "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/tinyglobby": { "version": "0.2.16", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" }, "engines": { "node": ">=12.0.0" }, "funding": { "url": "https://github.com/sponsors/SuperchupuDev" } }, "node_modules/tinyrainbow": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", "dev": true, "license": "MIT", "engines": { "node": ">=14.0.0" } }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, "license": "0BSD", "optional": true }, "node_modules/typescript": { "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { "node": ">=14.17" } }, "node_modules/undici-types": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "dev": true, "license": "MIT" }, "node_modules/vite": { "version": "8.0.9", "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.9.tgz", "integrity": "sha512-t7g7GVRpMXjNpa67HaVWI/8BWtdVIQPCL2WoozXXA7LBGEFK4AkkKkHx2hAQf5x1GZSlcmEDPkVLSGahxnEEZw==", "dev": true, "license": "MIT", "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.10", "rolldown": "1.0.0-rc.16", "tinyglobby": "^0.2.16" }, "bin": { "vite": "bin/vite.js" }, "engines": { "node": "^20.19.0 || >=22.12.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "peerDependenciesMeta": { "@types/node": { "optional": true }, "@vitejs/devtools": { "optional": true }, "esbuild": { "optional": true }, "jiti": { "optional": true }, "less": { "optional": true }, "sass": { "optional": true }, "sass-embedded": { "optional": true }, "stylus": { "optional": true }, "sugarss": { "optional": true }, "terser": { "optional": true }, "tsx": { "optional": true }, "yaml": { "optional": true } } }, "node_modules/vitest": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.5.tgz", "integrity": "sha512-9Xx1v3/ih3m9hN+SbfkUyy0JAs72ap3r7joc87XL6jwF0jGg6mFBvQ1SrwaX+h8BlkX6Hz9shdd1uo6AF+ZGpg==", "dev": true, "license": "MIT", "dependencies": { "@vitest/expect": "4.1.5", "@vitest/mocker": "4.1.5", "@vitest/pretty-format": "4.1.5", "@vitest/runner": "4.1.5", "@vitest/snapshot": "4.1.5", "@vitest/spy": "4.1.5", "@vitest/utils": "4.1.5", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "bin": { "vitest": "vitest.mjs" }, "engines": { "node": "^20.0.0 || ^22.0.0 || >=24.0.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.5", "@vitest/browser-preview": "4.1.5", "@vitest/browser-webdriverio": "4.1.5", "@vitest/coverage-istanbul": "4.1.5", "@vitest/coverage-v8": "4.1.5", "@vitest/ui": "4.1.5", "happy-dom": "*", "jsdom": "*", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "@edge-runtime/vm": { "optional": true }, "@opentelemetry/api": { "optional": true }, "@types/node": { "optional": true }, "@vitest/browser-playwright": { "optional": true }, "@vitest/browser-preview": { "optional": true }, "@vitest/browser-webdriverio": { "optional": true }, "@vitest/coverage-istanbul": { "optional": true }, "@vitest/coverage-v8": { "optional": true }, "@vitest/ui": { "optional": true }, "happy-dom": { "optional": true }, "jsdom": { "optional": true }, "vite": { "optional": false } } }, "node_modules/why-is-node-running": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", "dev": true, "license": "MIT", "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" }, "engines": { "node": ">=8" } } } } axios-axios-2d06f96/tests/module/esm/package.json000066400000000000000000000006611521272452000220240ustar00rootroot00000000000000{ "name": "@axios/esm-module-tests", "version": "1.0.0", "description": "ESM module compatibility tests for axios", "private": true, "type": "module", "scripts": { "test:module:esm": "vitest run --config vitest.config.js --project module" }, "keywords": [], "author": "axios team", "license": "MIT", "devDependencies": { "@types/node": "20.19.39", "typescript": "5.9.3", "vitest": "4.1.5" } } axios-axios-2d06f96/tests/module/esm/tests/000077500000000000000000000000001521272452000206755ustar00rootroot00000000000000axios-axios-2d06f96/tests/module/esm/tests/fixture-cleanup.module.test.js000066400000000000000000000014501521272452000266100ustar00rootroot00000000000000import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; import { describe, expect, it } from 'vitest'; import { cleanupTempFixture } from './helpers/fixture.js'; describe('module fixture cleanup helper', () => { it('removes fixture directories without shelling out to rm', () => { const fixturePath = fs.mkdtempSync(path.join(os.tmpdir(), 'axios-esm-module-fixture-')); const nestedPath = path.join(fixturePath, 'nested'); const originalPath = process.env.PATH; fs.mkdirSync(nestedPath); fs.writeFileSync(path.join(nestedPath, 'index.ts'), 'export {};\n'); process.env.PATH = ''; try { cleanupTempFixture(fixturePath); } finally { process.env.PATH = originalPath; } expect(fs.existsSync(fixturePath)).toBe(false); }); }); axios-axios-2d06f96/tests/module/esm/tests/helpers/000077500000000000000000000000001521272452000223375ustar00rootroot00000000000000axios-axios-2d06f96/tests/module/esm/tests/helpers/esm-functions.ts000066400000000000000000000022651521272452000255060ustar00rootroot00000000000000// @ts-nocheck import assert from 'assert'; import axios, { CanceledError, AxiosError, AxiosHeaders, formToJSON, spread, isAxiosError, isCancel, all, toFormData, } from 'axios'; assert.strictEqual(typeof axios, 'function'); assert.strictEqual(typeof CanceledError, 'function'); assert.strictEqual(typeof AxiosError, 'function'); assert.strictEqual(typeof AxiosHeaders, 'function'); assert.strictEqual(typeof formToJSON, 'function'); assert.strictEqual(typeof spread, 'function'); assert.strictEqual(typeof isAxiosError, 'function'); assert.strictEqual(typeof isCancel, 'function'); assert.strictEqual(typeof all, 'function'); assert.strictEqual(typeof toFormData, 'function'); assert.strictEqual(typeof axios.CanceledError, 'function'); assert.strictEqual(typeof axios.AxiosError, 'function'); assert.strictEqual(typeof axios.AxiosHeaders, 'function'); assert.strictEqual(typeof axios.formToJSON, 'function'); assert.strictEqual(typeof axios.spread, 'function'); assert.strictEqual(typeof axios.isAxiosError, 'function'); assert.strictEqual(typeof axios.isCancel, 'function'); assert.strictEqual(typeof axios.all, 'function'); assert.strictEqual(typeof axios.toFormData, 'function'); axios-axios-2d06f96/tests/module/esm/tests/helpers/esm-index.ts000066400000000000000000000414421521272452000246050ustar00rootroot00000000000000// @ts-nocheck import axios, { AxiosRequestConfig, AxiosHeaders, AxiosRequestHeaders, AxiosResponseHeaders, RawAxiosRequestHeaders, AxiosResponse, AxiosError, AxiosInstance, AxiosAdapter, Cancel, CancelTokenSource, Canceler, AxiosProgressEvent, ParamsSerializerOptions, toFormData, formToJSON, getAdapter, all, isCancel, isAxiosError, spread, AddressFamily, } from 'axios'; const config: AxiosRequestConfig = { url: '/user', method: 'get', baseURL: 'https://api.example.com/', allowAbsoluteUrls: false, transformRequest: (data: any) => '{"foo":"bar"}', transformResponse: [(data: any) => ({ baz: 'qux' })], headers: { 'X-FOO': 'bar' }, params: { id: 12345 }, paramsSerializer: { indexes: true, encode: (value: any) => value, serialize: (value: Record, options?: ParamsSerializerOptions) => String(value), }, data: { foo: 'bar' }, timeout: 10000, withCredentials: true, auth: { username: 'janedoe', password: 's00pers3cret', }, responseType: 'json', xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', onUploadProgress: (progressEvent: AxiosProgressEvent) => {}, onDownloadProgress: (progressEvent: AxiosProgressEvent) => {}, maxContentLength: 2000, maxBodyLength: 2000, validateStatus: (status: number) => status >= 200 && status < 300, maxRedirects: 5, proxy: { host: '127.0.0.1', port: 9000, }, cancelToken: new axios.CancelToken((cancel: Canceler) => {}), }; const nullValidateStatusConfig: AxiosRequestConfig = { validateStatus: null, }; const undefinedValidateStatusConfig: AxiosRequestConfig = { validateStatus: undefined, }; const handleResponse = (response: AxiosResponse) => { console.log(response.data); console.log(response.status); console.log(response.statusText); console.log(response.headers); console.log(response.config); }; const handleError = (error: AxiosError) => { if (error.response) { console.log(error.response.data); console.log(error.response.status); console.log(error.response.headers); } else { console.log(error.message); } }; axios(config).then(handleResponse).catch(handleError); axios.get('/user?id=12345').then(handleResponse).catch(handleError); axios .get('/user', { params: { id: 12345 } }) .then(handleResponse) .catch(handleError); axios.head('/user').then(handleResponse).catch(handleError); axios.options('/user').then(handleResponse).catch(handleError); axios.delete('/user').then(handleResponse).catch(handleError); axios.post('/user', { foo: 'bar' }).then(handleResponse).catch(handleError); axios .post('/user', { foo: 'bar' }, { headers: { 'X-FOO': 'bar' } }) .then(handleResponse) .catch(handleError); axios.put('/user', { foo: 'bar' }).then(handleResponse).catch(handleError); axios.patch('/user', { foo: 'bar' }).then(handleResponse).catch(handleError); axios.query('/user', { foo: 'bar' }).then(handleResponse).catch(handleError); // Typed methods interface UserCreationDef { name: string; } interface User { id: number; name: string; } interface ResponseHeaders { 'x-header': string; } // with default AxiosResponse result const handleUserResponse = (response: AxiosResponse) => { console.log(response.data.id); console.log(response.data.name); console.log(response.status); console.log(response.statusText); console.log(response.headers); console.log(response.config); }; axios.get('/user?id=12345').then(handleUserResponse).catch(handleError); axios .get('/user', { params: { id: 12345 } }) .then(handleUserResponse) .catch(handleError); axios.head('/user').then(handleUserResponse).catch(handleError); axios.options('/user').then(handleUserResponse).catch(handleError); axios.delete('/user').then(handleUserResponse).catch(handleError); axios.post('/user', { name: 'foo', id: 1 }).then(handleUserResponse).catch(handleError); axios .post('/user', { name: 'foo', id: 1 }, { headers: { 'X-FOO': 'bar' } }) .then(handleUserResponse) .catch(handleError); axios.put('/user', { name: 'foo', id: 1 }).then(handleUserResponse).catch(handleError); axios.patch('/user', { name: 'foo', id: 1 }).then(handleUserResponse).catch(handleError); // with custom response headers AxiosResponse result const handleUserResponseWithCustomHeaders = ( response: AxiosResponse ) => { console.log(response.data.id); console.log(response.data.name); console.log(response.status); console.log(response.statusText); console.log(response.headers); console.log(response.config); }; axios .get>('/user?id=12345') .then(handleUserResponseWithCustomHeaders) .catch(handleError); axios .get>('/user', { params: { id: 12345 } }) .then(handleUserResponseWithCustomHeaders) .catch(handleError); axios .head>('/user') .then(handleUserResponseWithCustomHeaders) .catch(handleError); axios .options>('/user') .then(handleUserResponseWithCustomHeaders) .catch(handleError); axios .delete>('/user') .then(handleUserResponseWithCustomHeaders) .catch(handleError); axios .post>('/user', { name: 'foo', id: 1 }) .then(handleUserResponseWithCustomHeaders) .catch(handleError); axios .post>( '/user', { name: 'foo', id: 1 }, { headers: { 'X-FOO': 'bar' } } ) .then(handleUserResponseWithCustomHeaders) .catch(handleError); axios .put>('/user', { name: 'foo', id: 1 }) .then(handleUserResponseWithCustomHeaders) .catch(handleError); axios .patch>('/user', { name: 'foo', id: 1 }) .then(handleUserResponseWithCustomHeaders) .catch(handleError); // (Typed methods) with custom response type const handleStringResponse = (response: string) => { console.log(response); }; axios.get('/user?id=12345').then(handleStringResponse).catch(handleError); axios .get('/user', { params: { id: 12345 } }) .then(handleStringResponse) .catch(handleError); axios.head('/user').then(handleStringResponse).catch(handleError); axios.options('/user').then(handleStringResponse).catch(handleError); axios.delete('/user').then(handleStringResponse).catch(handleError); axios .post, string>('/user', { name: 'foo' }) .then(handleStringResponse) .catch(handleError); axios .post, string>('/user', { name: 'foo' }, { headers: { 'X-FOO': 'bar' } }) .then(handleStringResponse) .catch(handleError); axios .put, string>('/user', { name: 'foo' }) .then(handleStringResponse) .catch(handleError); axios .patch, string>('/user', { name: 'foo' }) .then(handleStringResponse) .catch(handleError); axios .request({ method: 'get', url: '/user?id=12345', }) .then(handleStringResponse) .catch(handleError); // Instances const instance1: AxiosInstance = axios.create(); const instance2: AxiosInstance = instance1.create(config); instance1(config).then(handleResponse).catch(handleError); instance1.request(config).then(handleResponse).catch(handleError); instance1.get('/user?id=12345').then(handleResponse).catch(handleError); instance1.options('/user').then(handleResponse).catch(handleError); instance1 .get('/user', { params: { id: 12345 } }) .then(handleResponse) .catch(handleError); instance1.post('/user', { foo: 'bar' }).then(handleResponse).catch(handleError); instance1 .post('/user', { foo: 'bar' }, { headers: { 'X-FOO': 'bar' } }) .then(handleResponse) .catch(handleError); // Defaults axios.defaults.headers['X-FOO']; axios.defaults.baseURL = 'https://api.example.com/'; axios.defaults.headers.common['Accept'] = 'application/json'; axios.defaults.headers.post['X-FOO'] = 'bar'; axios.defaults.timeout = 2500; instance1.defaults.baseURL = 'https://api.example.com/'; instance1.defaults.headers.common['Accept'] = 'application/json'; instance1.defaults.headers.post['X-FOO'] = 'bar'; instance1.defaults.timeout = 2500; // axios create defaults axios.create({ headers: { foo: 'bar' } }); axios.create({ headers: { common: { foo: 'bar' } } }); axios.create({ headers: { 'Content-Type': 'application/json', }, formSerializer: { indexes: null, }, paramsSerializer: { indexes: null, }, }); // Interceptors const requestInterceptorId: number = axios.interceptors.request.use( async (config) => { await axios.get('/foo', { headers: config.headers, }); return config; }, (error: any) => Promise.reject(error), { synchronous: false } ); axios.interceptors.request.eject(requestInterceptorId); axios.interceptors.request.use( (config) => Promise.resolve(config), (error: any) => Promise.reject(error) ); axios.interceptors.request.use((config) => config); axios.interceptors.request.use((config) => Promise.resolve(config)); const responseInterceptorId: number = axios.interceptors.response.use( (response: AxiosResponse) => response, (error: any) => Promise.reject(error) ); axios.interceptors.response.eject(responseInterceptorId); axios.interceptors.response.use( (response: AxiosResponse) => Promise.resolve(response), (error: any) => Promise.reject(error) ); axios.interceptors.request.use((req) => { // https://github.com/axios/axios/issues/5415 req.headers.set('foo', 'bar'); req.headers['Content-Type'] = 123; return req; }); const voidRequestInterceptorId = axios.interceptors.request.use( // @ts-expect-error -- Must return an AxiosRequestConfig (or throw) (_response) => {}, (error: any) => Promise.reject(error) ); const voidResponseInterceptorId = axios.interceptors.response.use( // @ts-expect-error -- Must return an AxiosResponse (or throw) (_response) => {}, (error: any) => Promise.reject(error) ); axios.interceptors.request.eject(voidRequestInterceptorId); axios.interceptors.response.eject(voidResponseInterceptorId); axios.interceptors.response.use((response: AxiosResponse) => response); axios.interceptors.response.use((response: AxiosResponse) => Promise.resolve(response)); axios.interceptors.request.clear(); axios.interceptors.response.clear(); // Adapters const adapter: AxiosAdapter = (config) => { const response: AxiosResponse = { data: { foo: 'bar' }, status: 200, statusText: 'OK', headers: { 'X-FOO': 'bar' }, config, }; return Promise.resolve(response); }; axios.defaults.adapter = adapter; // axios.all const promises = [Promise.resolve(1), Promise.resolve(2)]; const promise: Promise = axios.all(promises); // axios.all named export (() => { const promises = [Promise.resolve(1), Promise.resolve(2)]; const promise: Promise = all(promises); })(); // axios.spread const fn1 = (a: number, b: number, c: number) => `${a}-${b}-${c}`; const fn2: (arr: number[]) => string = axios.spread(fn1); // axios.spread named export (() => { const fn1 = (a: number, b: number, c: number) => `${a}-${b}-${c}`; const fn2: (arr: number[]) => string = spread(fn1); })(); // Promises axios .get('/user') .then((response: AxiosResponse) => 'foo') .then((value: string) => {}); axios .get('/user') .then((response: AxiosResponse) => Promise.resolve('foo')) .then((value: string) => {}); axios .get('/user') .then( (response: AxiosResponse) => 'foo', (error: any) => 'bar' ) .then((value: string) => {}); axios .get('/user') .then( (response: AxiosResponse) => 'foo', (error: any) => 123 ) .then((value: string | number) => {}); axios .get('/user') .catch((error: any) => 'foo') .then((value: any) => {}); axios .get('/user') .catch((error: any) => Promise.resolve('foo')) .then((value: any) => {}); // Cancellation const source: CancelTokenSource = axios.CancelToken.source(); axios .get('/user', { cancelToken: source.token, }) .catch((thrown: AxiosError | Cancel) => { if (axios.isCancel(thrown)) { const cancel: Cancel = thrown; console.log(cancel.message); } // named export if (isCancel(thrown)) { const cancel: Cancel = thrown; console.log(cancel.message); } }); source.cancel('Operation has been canceled.'); // AxiosError axios.get('/user').catch((error: AxiosError) => { if (axios.isAxiosError(error)) { const axiosError: AxiosError = error; console.log(axiosError.message); } // named export if (isAxiosError(error)) { const axiosError: AxiosError = error; console.log(axiosError.message); } }); // FormData axios.toFormData({ x: 1 }, new FormData()); // named export toFormData({ x: 1 }, new FormData()); // formToJSON axios.toFormData(new FormData()); // named export formToJSON(new FormData()); // AbortSignal axios.get('/user', { signal: new AbortController().signal }); // AxiosHeaders methods axios.get('/user', { transformRequest: [ (data: any, headers) => { headers.setContentType('text/plain'); return 'baz'; }, (data: any, headers) => { headers['foo'] = 'bar'; return 'baz'; }, ], transformResponse: [ (data: any, headers: AxiosResponseHeaders) => { headers.has('foo'); }, ], }); // config headers axios.get('/user', { headers: new AxiosHeaders({ x: 1 }), }); axios.get('/user', { headers: { foo: 1, }, }); // issue #5034 function getRequestConfig1(options: AxiosRequestConfig): AxiosRequestConfig { return { ...options, headers: { ...(options.headers as RawAxiosRequestHeaders), Authorization: `Bearer ...`, }, }; } function getRequestConfig2(options: AxiosRequestConfig): AxiosRequestConfig { return { ...options, headers: { ...(options.headers as AxiosHeaders).toJSON(), Authorization: `Bearer ...`, }, }; } // Max Rate axios.get('/user', { maxRate: 1000, }); axios.get('/user', { maxRate: [1000, 1000], }); // Node progress axios.get('/user', { onUploadProgress: (e: AxiosProgressEvent) => { console.log(e.loaded); console.log(e.total); console.log(e.progress); console.log(e.rate); }, }); // adapters axios.get('/user', { adapter: 'xhr', }); axios.get('/user', { adapter: 'http', }); axios.get('/user', { adapter: ['xhr', 'http'], }); { // getAdapter getAdapter(axios.create().defaults.adapter); getAdapter(undefined); getAdapter([]); getAdapter(['xhr']); getAdapter([adapter]); getAdapter(['xhr', 'http']); getAdapter([adapter, 'xhr']); getAdapter([adapter, adapter]); getAdapter('xhr'); getAdapter(adapter); const _: AxiosAdapter = getAdapter('xhr'); const __: AxiosAdapter = getAdapter(['xhr']); // @ts-expect-error getAdapter(); // @ts-expect-error getAdapter(123); // @ts-expect-error getAdapter([123]); // @ts-expect-error getAdapter('xhr', 'http'); } // AxiosHeaders // iterator const headers = new AxiosHeaders({ foo: 'bar' }); for (const [header, value] of headers) { console.log(header, value); } // index signature (() => { const headers = new AxiosHeaders({ x: 1 }); headers.y = 2; })(); // AxiosRequestHeaders (() => { const headers: AxiosRequestHeaders = new AxiosHeaders({ x: 1 }); headers.y = 2; headers.get('x'); })(); // AxiosHeaders instance assignment { const requestInterceptorId: number = axios.interceptors.request.use( async (config) => { config.headers.Accept = 'foo'; config.headers.setAccept('foo'); config.headers = new AxiosHeaders({ x: 1 }); config.headers.foo = '1'; config.headers.set('bar', '2'); config.headers.set({ myHeader: 'myValue' }); config.headers = new AxiosHeaders({ myHeader: 'myValue' }); config.headers = { ...config.headers } as AxiosRequestHeaders; return config; }, (error: any) => Promise.reject(error) ); } { const config: AxiosRequestConfig = { headers: new AxiosHeaders({ foo: 1 }) }; axios.get('', { headers: { bar: 2, ...config.headers, }, }); } // lookup axios.get('/user', { lookup: ( hostname: string, opt: object, cb: (err: Error | null, address: string, family: AddressFamily) => void ) => { cb(null, '127.0.0.1', 4); }, }); // lookup async axios.get('/user', { lookup: (hostname: string, opt: object) => { return ['127.0.0.1', 4]; }, }); // AxiosError.cause should be typed as Error to allow accessing .message axios.get('/user').catch((error: AxiosError) => { if (error.cause) { // This should not produce a type error - cause is typed as Error const causeMessage: string | undefined = error.cause.message; console.log(causeMessage); } }); axios-axios-2d06f96/tests/module/esm/tests/helpers/fixture.js000066400000000000000000000012651521272452000243670ustar00rootroot00000000000000import fs from 'node:fs'; import path from 'node:path'; export const createTempFixture = (suiteRoot, name, sourcePath, tsconfig, packageJson) => { const tempRoot = fs.mkdtempSync(path.join(suiteRoot, `.tmp-module-${name}-`)); const source = fs.readFileSync(sourcePath, 'utf8'); fs.writeFileSync(path.join(tempRoot, 'index.ts'), source); fs.writeFileSync(path.join(tempRoot, 'tsconfig.json'), JSON.stringify(tsconfig, null, 2)); if (packageJson) { fs.writeFileSync(path.join(tempRoot, 'package.json'), JSON.stringify(packageJson, null, 2)); } return tempRoot; }; export const cleanupTempFixture = (dirPath) => { fs.rmSync(dirPath, { recursive: true, force: true }); }; axios-axios-2d06f96/tests/module/esm/tests/helpers/run-command.js000066400000000000000000000015761521272452000251260ustar00rootroot00000000000000import { spawnSync } from 'node:child_process'; const formatCommand = (command, args) => [command, ...(args || [])].join(' '); export const runCommand = (command, args = [], options = {}) => { const spawnOptions = { encoding: 'utf8', ...options }; const result = spawnSync(command, args, spawnOptions); const output = { code: result.status, stdout: result.stdout || '', stderr: result.stderr || '', command: formatCommand(command, args), cwd: spawnOptions.cwd || process.cwd(), }; if (result.error) { throw result.error; } if (output.code !== 0) { throw new Error( [ 'Command failed:', ` command: ${output.command}`, ` cwd: ${output.cwd}`, ` exitCode: ${String(output.code)}`, ` stdout:\n${output.stdout}`, ` stderr:\n${output.stderr}`, ].join('\n') ); } return output; }; axios-axios-2d06f96/tests/module/esm/tests/ts.module.test.js000066400000000000000000000022541521272452000241260ustar00rootroot00000000000000import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { describe, it } from 'vitest'; import { createTempFixture, cleanupTempFixture } from './helpers/fixture.js'; import { runCommand } from './helpers/run-command.js'; const suiteRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); const repoRoot = path.resolve(suiteRoot, '../../..'); const tscBin = path.join(suiteRoot, 'node_modules', 'typescript', 'bin', 'tsc'); const tsconfig = { compilerOptions: { target: 'es2016', module: 'commonjs', moduleResolution: 'node', esModuleInterop: true, strict: true, skipLibCheck: true, }, }; describe('module ts compatibility', () => { it('compiles and executes import axios syntax', () => { const sourcePath = path.join(repoRoot, 'tests/module/esm/tests/helpers/esm-functions.ts'); const fixturePath = createTempFixture(suiteRoot, 'ts', sourcePath, tsconfig, { type: 'commonjs', }); try { runCommand('node', [tscBin, '-p', 'tsconfig.json'], { cwd: fixturePath }); runCommand('node', ['index.js'], { cwd: fixturePath }); } finally { cleanupTempFixture(fixturePath); } }); }); axios-axios-2d06f96/tests/module/esm/tests/typings.module.test.js000066400000000000000000000020221521272452000251660ustar00rootroot00000000000000import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { describe, it } from 'vitest'; import { createTempFixture, cleanupTempFixture } from './helpers/fixture.js'; import { runCommand } from './helpers/run-command.js'; const suiteRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); const repoRoot = path.resolve(suiteRoot, '../../..'); const tscBin = path.join(suiteRoot, 'node_modules', 'typescript', 'bin', 'tsc'); const tsconfig = { compilerOptions: { checkJs: true, module: 'node16', }, }; describe('module esm typings compatibility', () => { it('type-checks esm axios typings', () => { const sourcePath = path.join(repoRoot, 'tests/module/esm/tests/helpers/esm-index.ts'); const fixturePath = createTempFixture(suiteRoot, 'typings-esm', sourcePath, tsconfig, { type: 'module', }); try { runCommand('node', [tscBin, '--noEmit', '-p', 'tsconfig.json'], { cwd: fixturePath }); } finally { cleanupTempFixture(fixturePath); } }); }); axios-axios-2d06f96/tests/module/esm/vitest.config.js000066400000000000000000000005001521272452000226460ustar00rootroot00000000000000import { defineConfig } from 'vitest/config'; export default defineConfig({ test: { testTimeout: 60000, projects: [ { test: { name: 'module', environment: 'node', include: ['tests/**/*.module.test.js'], setupFiles: [], }, }, ], }, }); axios-axios-2d06f96/tests/setup/000077500000000000000000000000001521272452000166225ustar00rootroot00000000000000axios-axios-2d06f96/tests/setup/browser.setup.js000066400000000000000000000001331521272452000217770ustar00rootroot00000000000000import { afterEach } from 'vitest'; afterEach(() => { document.body.innerHTML = ''; }); axios-axios-2d06f96/tests/setup/server.js000066400000000000000000000164501521272452000204740ustar00rootroot00000000000000import http from 'http'; import http2 from 'http2'; import stream from 'stream'; import getStream, { getStreamAsBuffer } from 'get-stream'; import { Throttle } from 'stream-throttle'; import { IncomingForm } from 'formidable'; import selfsigned from 'selfsigned'; export const SERVER_HANDLER_STREAM_ECHO = (req, res) => req.pipe(res); export const setTimeoutAsync = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); const certificatePromise = selfsigned.generate(null, { keySize: 2048 }); const trackedServers = new Set(); const untrackServer = (server) => { trackedServers.delete(server); }; export const startHTTPServer = async (handlerOrOptions, options) => { const certificate = await certificatePromise; const { handler, useBuffering = false, rate = undefined, // Default to 0 so the OS assigns a free ephemeral port. Tests that need // a deterministic port can still pass one explicitly. Sharing a fixed // port across many tests creates TIME_WAIT / pool-reuse races that // surface as EPIPE on the client under CI runner load. port = 0, keepAlive = 1000, useHTTP2, key = certificate.private, cert = certificate.cert, } = Object.assign( typeof handlerOrOptions === 'function' ? { handler: handlerOrOptions, } : handlerOrOptions || {}, options ); return new Promise((resolve, reject) => { const serverHandler = handler || async function (req, res) { try { req.headers['content-length'] && res.setHeader('content-length', req.headers['content-length']); let dataStream = req; if (useBuffering) { dataStream = stream.Readable.from(await getStream(req)); } const streams = [dataStream]; if (rate) { streams.push(new Throttle({ rate })); } streams.push(res); stream.pipeline(streams, (err) => { err && console.log('Server warning: ' + err.message); }); } catch (err) { console.warn('HTTP server error:', err); } }; const server = useHTTP2 ? http2.createSecureServer({ key, cert }, serverHandler) : http.createServer(serverHandler); const sessions = new Set(); if (useHTTP2) { server.on('session', (session) => { sessions.add(session); session.once('close', () => { sessions.delete(session); }); }); server.closeAllSessions = () => { for (const session of sessions) { session.destroy(); } }; } else { server.keepAliveTimeout = keepAlive; } server.listen(port, function (err) { if (err) { reject(err); return; } trackedServers.add(this); resolve(this); }); }); }; export const stopHTTPServer = async (server, timeout = 10000) => { if (!server) return; // Try a graceful close first so in-flight requests can finish writing and // clients see clean FINs instead of RSTs. Forcefully tearing down sockets // up-front (closeAllConnections) is what produces dangling RSTs that the // next test on the same port can observe as EPIPE on its client write. // Force-close only after a short grace period. const closed = new Promise((resolve) => server.close(resolve)); const grace = Math.min(2000, Math.max(0, timeout / 2)); const winner = await Promise.race([ closed.then(() => 'graceful'), setTimeoutAsync(grace).then(() => 'grace_elapsed'), ]); if (winner === 'grace_elapsed') { if (typeof server.closeAllConnections === 'function') { server.closeAllConnections(); } if (typeof server.closeAllSessions === 'function') { server.closeAllSessions(); } await Promise.race([closed, setTimeoutAsync(timeout - grace)]); } untrackServer(server); }; export const stopAllTrackedHTTPServers = async (timeout = 10000) => { const servers = Array.from(trackedServers); await Promise.all(servers.map((server) => stopHTTPServer(server, timeout))); }; export const handleFormData = (req) => { return new Promise((resolve, reject) => { const form = new IncomingForm(); form.parse(req, (err, fields, files) => { if (err) { // Drain any unread bytes so the kernel doesn't send an RST when the // server closes the response. An unread request buffer is what causes // the client write side to surface EPIPE on a subsequent test. if (typeof req.resume === 'function') req.resume(); return reject(err); } resolve({ fields, files }); }); }); }; export const nodeVersion = process.versions.node.split('.').map((v) => parseInt(v, 10)); export const generateReadable = (length = 1024 * 1024, chunkSize = 10 * 1024, sleep = 50) => { return stream.Readable.from( (async function* () { let dataLength = 0; while (dataLength < length) { const leftBytes = length - dataLength; const chunk = Buffer.alloc(leftBytes > chunkSize ? chunkSize : leftBytes); dataLength += chunk.length; yield chunk; if (sleep) { await setTimeoutAsync(sleep); } } })() ); }; export const makeReadableStream = (chunk = 'chunk', n = 10, timeout = 100) => { return new ReadableStream( { async pull(controller) { await setTimeoutAsync(timeout); n-- ? controller.enqueue(chunk) : controller.close(); }, }, { highWaterMark: 1, } ); }; export const makeEchoStream = (echo) => new WritableStream({ write(chunk) { echo && console.log('Echo chunk', chunk); }, }); export const startTestServer = async (port) => { const handler = async (req) => { const parsed = new URL(req.url, `http://localhost:${port}`); const params = Object.fromEntries(parsed.searchParams); const response = { url: req.url, pathname: parsed.pathname, params, method: req.method, headers: req.headers, }; const contentType = req.headers['content-type'] || ''; const { delay = 0 } = params; if (+delay) { await setTimeoutAsync(+delay); } switch (parsed.pathname.replace(/\/$/, '')) { case '/echo/json': default: if (contentType.startsWith('multipart/')) { const { fields, files } = await handleFormData(req); response.form = fields; response.files = files; } else { response.body = (await getStreamAsBuffer(req)).toString('hex'); } return { body: response, }; } }; return await startHTTPServer( (req, res) => { res.setHeader('Access-Control-Allow-Origin', `*`); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', '*'); res.setHeader('Access-Control-Max-Age', '86400'); if (req.method === 'OPTIONS') { res.writeHead(204); res.end(); return; } Promise.resolve(handler(req, res)).then((result) => { const { status = 200, headers = {}, body } = result || {}; res.statusCode = status; Object.entries(headers).forEach(([header, value]) => { res.setHeader(header, value); }); res.end(JSON.stringify(body, null, 2)); }); }, { port } ); }; axios-axios-2d06f96/tests/smoke/000077500000000000000000000000001521272452000166005ustar00rootroot00000000000000axios-axios-2d06f96/tests/smoke/bun/000077500000000000000000000000001521272452000173645ustar00rootroot00000000000000axios-axios-2d06f96/tests/smoke/bun/bun.lock000066400000000000000000006024521521272452000210330ustar00rootroot00000000000000{ "lockfileVersion": 1, "configVersion": 1, "workspaces": { "": { "name": "@axios/bun-smoke-tests", "devDependencies": { "@types/bun": "latest", "axios": "file:../../../", }, "peerDependencies": { "typescript": "^5", }, }, }, "packages": { "@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="], "@babel/compat-data": ["@babel/compat-data@7.29.0", "", {}, "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg=="], "@babel/core": ["@babel/core@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA=="], "@babel/generator": ["@babel/generator@7.29.1", "", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw=="], "@babel/helper-annotate-as-pure": ["@babel/helper-annotate-as-pure@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" } }, "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg=="], "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.28.6", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA=="], "@babel/helper-create-class-features-plugin": ["@babel/helper-create-class-features-plugin@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/helper-replace-supers": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/traverse": "^7.28.6", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow=="], "@babel/helper-create-regexp-features-plugin": ["@babel/helper-create-regexp-features-plugin@7.28.5", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "regexpu-core": "^6.3.1", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw=="], "@babel/helper-define-polyfill-provider": ["@babel/helper-define-polyfill-provider@0.6.8", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "debug": "^4.4.3", "lodash.debounce": "^4.0.8", "resolve": "^1.22.11" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA=="], "@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="], "@babel/helper-member-expression-to-functions": ["@babel/helper-member-expression-to-functions@7.28.5", "", { "dependencies": { "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5" } }, "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg=="], "@babel/helper-module-imports": ["@babel/helper-module-imports@7.28.6", "", { "dependencies": { "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw=="], "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.6", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-validator-identifier": "^7.28.5", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA=="], "@babel/helper-optimise-call-expression": ["@babel/helper-optimise-call-expression@7.27.1", "", { "dependencies": { "@babel/types": "^7.27.1" } }, "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw=="], "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.28.6", "", {}, "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug=="], "@babel/helper-remap-async-to-generator": ["@babel/helper-remap-async-to-generator@7.27.1", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.1", "@babel/helper-wrap-function": "^7.27.1", "@babel/traverse": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA=="], "@babel/helper-replace-supers": ["@babel/helper-replace-supers@7.28.6", "", { "dependencies": { "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg=="], "@babel/helper-skip-transparent-expression-wrappers": ["@babel/helper-skip-transparent-expression-wrappers@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg=="], "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="], "@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="], "@babel/helper-wrap-function": ["@babel/helper-wrap-function@7.28.6", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ=="], "@babel/helpers": ["@babel/helpers@7.29.2", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.29.0" } }, "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw=="], "@babel/parser": ["@babel/parser@7.29.2", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA=="], "@babel/plugin-bugfix-firefox-class-in-computed-class-key": ["@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/traverse": "^7.28.5" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q=="], "@babel/plugin-bugfix-safari-class-field-initializer-scope": ["@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA=="], "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": ["@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA=="], "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": ["@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/plugin-transform-optional-chaining": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.13.0" } }, "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw=="], "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": ["@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g=="], "@babel/plugin-proposal-private-property-in-object": ["@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2", "", { "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w=="], "@babel/plugin-syntax-import-assertions": ["@babel/plugin-syntax-import-assertions@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw=="], "@babel/plugin-syntax-import-attributes": ["@babel/plugin-syntax-import-attributes@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw=="], "@babel/plugin-syntax-unicode-sets-regex": ["@babel/plugin-syntax-unicode-sets-regex@7.18.6", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg=="], "@babel/plugin-transform-arrow-functions": ["@babel/plugin-transform-arrow-functions@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA=="], "@babel/plugin-transform-async-generator-functions": ["@babel/plugin-transform-async-generator-functions@7.29.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-remap-async-to-generator": "^7.27.1", "@babel/traverse": "^7.29.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w=="], "@babel/plugin-transform-async-to-generator": ["@babel/plugin-transform-async-to-generator@7.28.6", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-remap-async-to-generator": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g=="], "@babel/plugin-transform-block-scoped-functions": ["@babel/plugin-transform-block-scoped-functions@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg=="], "@babel/plugin-transform-block-scoping": ["@babel/plugin-transform-block-scoping@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw=="], "@babel/plugin-transform-class-properties": ["@babel/plugin-transform-class-properties@7.28.6", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw=="], "@babel/plugin-transform-class-static-block": ["@babel/plugin-transform-class-static-block@7.28.6", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.12.0" } }, "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ=="], "@babel/plugin-transform-classes": ["@babel/plugin-transform-classes@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-globals": "^7.28.0", "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-replace-supers": "^7.28.6", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q=="], "@babel/plugin-transform-computed-properties": ["@babel/plugin-transform-computed-properties@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/template": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ=="], "@babel/plugin-transform-destructuring": ["@babel/plugin-transform-destructuring@7.28.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/traverse": "^7.28.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw=="], "@babel/plugin-transform-dotall-regex": ["@babel/plugin-transform-dotall-regex@7.28.6", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg=="], "@babel/plugin-transform-duplicate-keys": ["@babel/plugin-transform-duplicate-keys@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q=="], "@babel/plugin-transform-duplicate-named-capturing-groups-regex": ["@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw=="], "@babel/plugin-transform-dynamic-import": ["@babel/plugin-transform-dynamic-import@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A=="], "@babel/plugin-transform-explicit-resource-management": ["@babel/plugin-transform-explicit-resource-management@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/plugin-transform-destructuring": "^7.28.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg=="], "@babel/plugin-transform-exponentiation-operator": ["@babel/plugin-transform-exponentiation-operator@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw=="], "@babel/plugin-transform-export-namespace-from": ["@babel/plugin-transform-export-namespace-from@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ=="], "@babel/plugin-transform-for-of": ["@babel/plugin-transform-for-of@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw=="], "@babel/plugin-transform-function-name": ["@babel/plugin-transform-function-name@7.27.1", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1", "@babel/traverse": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ=="], "@babel/plugin-transform-json-strings": ["@babel/plugin-transform-json-strings@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw=="], "@babel/plugin-transform-literals": ["@babel/plugin-transform-literals@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA=="], "@babel/plugin-transform-logical-assignment-operators": ["@babel/plugin-transform-logical-assignment-operators@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A=="], "@babel/plugin-transform-member-expression-literals": ["@babel/plugin-transform-member-expression-literals@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ=="], "@babel/plugin-transform-modules-amd": ["@babel/plugin-transform-modules-amd@7.27.1", "", { "dependencies": { "@babel/helper-module-transforms": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA=="], "@babel/plugin-transform-modules-commonjs": ["@babel/plugin-transform-modules-commonjs@7.28.6", "", { "dependencies": { "@babel/helper-module-transforms": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA=="], "@babel/plugin-transform-modules-systemjs": ["@babel/plugin-transform-modules-systemjs@7.29.0", "", { "dependencies": { "@babel/helper-module-transforms": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-validator-identifier": "^7.28.5", "@babel/traverse": "^7.29.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ=="], "@babel/plugin-transform-modules-umd": ["@babel/plugin-transform-modules-umd@7.27.1", "", { "dependencies": { "@babel/helper-module-transforms": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w=="], "@babel/plugin-transform-named-capturing-groups-regex": ["@babel/plugin-transform-named-capturing-groups-regex@7.29.0", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ=="], "@babel/plugin-transform-new-target": ["@babel/plugin-transform-new-target@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ=="], "@babel/plugin-transform-nullish-coalescing-operator": ["@babel/plugin-transform-nullish-coalescing-operator@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg=="], "@babel/plugin-transform-numeric-separator": ["@babel/plugin-transform-numeric-separator@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w=="], "@babel/plugin-transform-object-rest-spread": ["@babel/plugin-transform-object-rest-spread@7.28.6", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/plugin-transform-destructuring": "^7.28.5", "@babel/plugin-transform-parameters": "^7.27.7", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA=="], "@babel/plugin-transform-object-super": ["@babel/plugin-transform-object-super@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng=="], "@babel/plugin-transform-optional-catch-binding": ["@babel/plugin-transform-optional-catch-binding@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ=="], "@babel/plugin-transform-optional-chaining": ["@babel/plugin-transform-optional-chaining@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w=="], "@babel/plugin-transform-parameters": ["@babel/plugin-transform-parameters@7.27.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg=="], "@babel/plugin-transform-private-methods": ["@babel/plugin-transform-private-methods@7.28.6", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg=="], "@babel/plugin-transform-private-property-in-object": ["@babel/plugin-transform-private-property-in-object@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA=="], "@babel/plugin-transform-property-literals": ["@babel/plugin-transform-property-literals@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ=="], "@babel/plugin-transform-regenerator": ["@babel/plugin-transform-regenerator@7.29.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog=="], "@babel/plugin-transform-regexp-modifiers": ["@babel/plugin-transform-regexp-modifiers@7.28.6", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg=="], "@babel/plugin-transform-reserved-words": ["@babel/plugin-transform-reserved-words@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw=="], "@babel/plugin-transform-shorthand-properties": ["@babel/plugin-transform-shorthand-properties@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ=="], "@babel/plugin-transform-spread": ["@babel/plugin-transform-spread@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA=="], "@babel/plugin-transform-sticky-regex": ["@babel/plugin-transform-sticky-regex@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g=="], "@babel/plugin-transform-template-literals": ["@babel/plugin-transform-template-literals@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg=="], "@babel/plugin-transform-typeof-symbol": ["@babel/plugin-transform-typeof-symbol@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw=="], "@babel/plugin-transform-unicode-escapes": ["@babel/plugin-transform-unicode-escapes@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg=="], "@babel/plugin-transform-unicode-property-regex": ["@babel/plugin-transform-unicode-property-regex@7.28.6", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A=="], "@babel/plugin-transform-unicode-regex": ["@babel/plugin-transform-unicode-regex@7.27.1", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw=="], "@babel/plugin-transform-unicode-sets-regex": ["@babel/plugin-transform-unicode-sets-regex@7.28.6", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.28.5", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q=="], "@babel/preset-env": ["@babel/preset-env@7.29.2", "", { "dependencies": { "@babel/compat-data": "^7.29.0", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-import-assertions": "^7.28.6", "@babel/plugin-syntax-import-attributes": "^7.28.6", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", "@babel/plugin-transform-arrow-functions": "^7.27.1", "@babel/plugin-transform-async-generator-functions": "^7.29.0", "@babel/plugin-transform-async-to-generator": "^7.28.6", "@babel/plugin-transform-block-scoped-functions": "^7.27.1", "@babel/plugin-transform-block-scoping": "^7.28.6", "@babel/plugin-transform-class-properties": "^7.28.6", "@babel/plugin-transform-class-static-block": "^7.28.6", "@babel/plugin-transform-classes": "^7.28.6", "@babel/plugin-transform-computed-properties": "^7.28.6", "@babel/plugin-transform-destructuring": "^7.28.5", "@babel/plugin-transform-dotall-regex": "^7.28.6", "@babel/plugin-transform-duplicate-keys": "^7.27.1", "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.0", "@babel/plugin-transform-dynamic-import": "^7.27.1", "@babel/plugin-transform-explicit-resource-management": "^7.28.6", "@babel/plugin-transform-exponentiation-operator": "^7.28.6", "@babel/plugin-transform-export-namespace-from": "^7.27.1", "@babel/plugin-transform-for-of": "^7.27.1", "@babel/plugin-transform-function-name": "^7.27.1", "@babel/plugin-transform-json-strings": "^7.28.6", "@babel/plugin-transform-literals": "^7.27.1", "@babel/plugin-transform-logical-assignment-operators": "^7.28.6", "@babel/plugin-transform-member-expression-literals": "^7.27.1", "@babel/plugin-transform-modules-amd": "^7.27.1", "@babel/plugin-transform-modules-commonjs": "^7.28.6", "@babel/plugin-transform-modules-systemjs": "^7.29.0", "@babel/plugin-transform-modules-umd": "^7.27.1", "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.0", "@babel/plugin-transform-new-target": "^7.27.1", "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6", "@babel/plugin-transform-numeric-separator": "^7.28.6", "@babel/plugin-transform-object-rest-spread": "^7.28.6", "@babel/plugin-transform-object-super": "^7.27.1", "@babel/plugin-transform-optional-catch-binding": "^7.28.6", "@babel/plugin-transform-optional-chaining": "^7.28.6", "@babel/plugin-transform-parameters": "^7.27.7", "@babel/plugin-transform-private-methods": "^7.28.6", "@babel/plugin-transform-private-property-in-object": "^7.28.6", "@babel/plugin-transform-property-literals": "^7.27.1", "@babel/plugin-transform-regenerator": "^7.29.0", "@babel/plugin-transform-regexp-modifiers": "^7.28.6", "@babel/plugin-transform-reserved-words": "^7.27.1", "@babel/plugin-transform-shorthand-properties": "^7.27.1", "@babel/plugin-transform-spread": "^7.28.6", "@babel/plugin-transform-sticky-regex": "^7.27.1", "@babel/plugin-transform-template-literals": "^7.27.1", "@babel/plugin-transform-typeof-symbol": "^7.27.1", "@babel/plugin-transform-unicode-escapes": "^7.27.1", "@babel/plugin-transform-unicode-property-regex": "^7.28.6", "@babel/plugin-transform-unicode-regex": "^7.27.1", "@babel/plugin-transform-unicode-sets-regex": "^7.28.6", "@babel/preset-modules": "0.1.6-no-external-plugins", "babel-plugin-polyfill-corejs2": "^0.4.15", "babel-plugin-polyfill-corejs3": "^0.14.0", "babel-plugin-polyfill-regenerator": "^0.6.6", "core-js-compat": "^3.48.0", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-DYD23veRYGvBFhcTY1iUvJnDNpuqNd/BzBwCvzOTKUnJjKg5kpUBh3/u9585Agdkgj+QuygG7jLfOPWMa2KVNw=="], "@babel/preset-modules": ["@babel/preset-modules@0.1.6-no-external-plugins", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", "esutils": "^2.0.2" }, "peerDependencies": { "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA=="], "@babel/template": ["@babel/template@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ=="], "@babel/traverse": ["@babel/traverse@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="], "@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="], "@blazediff/core": ["@blazediff/core@1.9.1", "", {}, "sha512-ehg3jIkYKulZh+8om/O25vkvSsXXwC+skXmyA87FFx6A/45eqOkZsBltMw/TVteb0mloiGT8oGRTcjRAz66zaA=="], "@commitlint/cli": ["@commitlint/cli@20.5.0", "", { "dependencies": { "@commitlint/format": "^20.5.0", "@commitlint/lint": "^20.5.0", "@commitlint/load": "^20.5.0", "@commitlint/read": "^20.5.0", "@commitlint/types": "^20.5.0", "tinyexec": "^1.0.0", "yargs": "^17.0.0" }, "bin": { "commitlint": "./cli.js" } }, "sha512-yNkyN/tuKTJS3wdVfsZ2tXDM4G4Gi7z+jW54Cki8N8tZqwKBltbIvUUrSbT4hz1bhW/h0CdR+5sCSpXD+wMKaQ=="], "@commitlint/config-conventional": ["@commitlint/config-conventional@20.5.0", "", { "dependencies": { "@commitlint/types": "^20.5.0", "conventional-changelog-conventionalcommits": "^9.2.0" } }, "sha512-t3Ni88rFw1XMa4nZHgOKJ8fIAT9M2j5TnKyTqJzsxea7FUetlNdYFus9dz+MhIRZmc16P0PPyEfh6X2d/qw8SA=="], "@commitlint/config-validator": ["@commitlint/config-validator@20.5.0", "", { "dependencies": { "@commitlint/types": "^20.5.0", "ajv": "^8.11.0" } }, "sha512-T/Uh6iJUzyx7j35GmHWdIiGRQB+ouZDk0pwAaYq4SXgB54KZhFdJ0vYmxiW6AMYICTIWuyMxDBl1jK74oFp/Gw=="], "@commitlint/ensure": ["@commitlint/ensure@20.5.0", "", { "dependencies": { "@commitlint/types": "^20.5.0", "lodash.camelcase": "^4.3.0", "lodash.kebabcase": "^4.1.1", "lodash.snakecase": "^4.1.1", "lodash.startcase": "^4.4.0", "lodash.upperfirst": "^4.3.1" } }, "sha512-IpHqAUesBeW1EDDdjzJeaOxU9tnogLAyXLRBn03SHlj1SGENn2JGZqSWGkFvBJkJzfXAuCNtsoYzax+ZPS+puw=="], "@commitlint/execute-rule": ["@commitlint/execute-rule@20.0.0", "", {}, "sha512-xyCoOShoPuPL44gVa+5EdZsBVao/pNzpQhkzq3RdtlFdKZtjWcLlUFQHSWBuhk5utKYykeJPSz2i8ABHQA+ZZw=="], "@commitlint/format": ["@commitlint/format@20.5.0", "", { "dependencies": { "@commitlint/types": "^20.5.0", "picocolors": "^1.1.1" } }, "sha512-TI9EwFU/qZWSK7a5qyXMpKPPv3qta7FO4tKW+Wt2al7sgMbLWTsAcDpX1cU8k16TRdsiiet9aOw0zpvRXNJu7Q=="], "@commitlint/is-ignored": ["@commitlint/is-ignored@20.5.0", "", { "dependencies": { "@commitlint/types": "^20.5.0", "semver": "^7.6.0" } }, "sha512-JWLarAsurHJhPozbuAH6GbP4p/hdOCoqS9zJMfqwswne+/GPs5V0+rrsfOkP68Y8PSLphwtFXV0EzJ+GTXTTGg=="], "@commitlint/lint": ["@commitlint/lint@20.5.0", "", { "dependencies": { "@commitlint/is-ignored": "^20.5.0", "@commitlint/parse": "^20.5.0", "@commitlint/rules": "^20.5.0", "@commitlint/types": "^20.5.0" } }, "sha512-jiM3hNUdu04jFBf1VgPdjtIPvbuVfDTBAc6L98AWcoLjF5sYqkulBHBzlVWll4rMF1T5zeQFB6r//a+s+BBKlA=="], "@commitlint/load": ["@commitlint/load@20.5.0", "", { "dependencies": { "@commitlint/config-validator": "^20.5.0", "@commitlint/execute-rule": "^20.0.0", "@commitlint/resolve-extends": "^20.5.0", "@commitlint/types": "^20.5.0", "cosmiconfig": "^9.0.1", "cosmiconfig-typescript-loader": "^6.1.0", "is-plain-obj": "^4.1.0", "lodash.mergewith": "^4.6.2", "picocolors": "^1.1.1" } }, "sha512-sLhhYTL/KxeOTZjjabKDhwidGZan84XKK1+XFkwDYL/4883kIajcz/dZFAhBJmZPtL8+nBx6bnkzA95YxPeDPw=="], "@commitlint/message": ["@commitlint/message@20.4.3", "", {}, "sha512-6akwCYrzcrFcTYz9GyUaWlhisY4lmQ3KvrnabmhoeAV8nRH4dXJAh4+EUQ3uArtxxKQkvxJS78hNX2EU3USgxQ=="], "@commitlint/parse": ["@commitlint/parse@20.5.0", "", { "dependencies": { "@commitlint/types": "^20.5.0", "conventional-changelog-angular": "^8.2.0", "conventional-commits-parser": "^6.3.0" } }, "sha512-SeKWHBMk7YOTnnEWUhx+d1a9vHsjjuo6Uo1xRfPNfeY4bdYFasCH1dDpAv13Lyn+dDPOels+jP6D2GRZqzc5fA=="], "@commitlint/read": ["@commitlint/read@20.5.0", "", { "dependencies": { "@commitlint/top-level": "^20.4.3", "@commitlint/types": "^20.5.0", "git-raw-commits": "^5.0.0", "minimist": "^1.2.8", "tinyexec": "^1.0.0" } }, "sha512-JDEIJ2+GnWpK8QqwfmW7O42h0aycJEWNqcdkJnyzLD11nf9dW2dWLTVEa8Wtlo4IZFGLPATjR5neA5QlOvIH1w=="], "@commitlint/resolve-extends": ["@commitlint/resolve-extends@20.5.0", "", { "dependencies": { "@commitlint/config-validator": "^20.5.0", "@commitlint/types": "^20.5.0", "global-directory": "^4.0.1", "import-meta-resolve": "^4.0.0", "lodash.mergewith": "^4.6.2", "resolve-from": "^5.0.0" } }, "sha512-3SHPWUW2v0tyspCTcfSsYml0gses92l6TlogwzvM2cbxDgmhSRc+fldDjvGkCXJrjSM87BBaWYTPWwwyASZRrg=="], "@commitlint/rules": ["@commitlint/rules@20.5.0", "", { "dependencies": { "@commitlint/ensure": "^20.5.0", "@commitlint/message": "^20.4.3", "@commitlint/to-lines": "^20.0.0", "@commitlint/types": "^20.5.0" } }, "sha512-5NdQXQEdnDPT5pK8O39ZA7HohzPRHEsDGU23cyVCNPQy4WegAbAwrQk3nIu7p2sl3dutPk8RZd91yKTrMTnRkQ=="], "@commitlint/to-lines": ["@commitlint/to-lines@20.0.0", "", {}, "sha512-2l9gmwiCRqZNWgV+pX1X7z4yP0b3ex/86UmUFgoRt672Ez6cAM2lOQeHFRUTuE6sPpi8XBCGnd8Kh3bMoyHwJw=="], "@commitlint/top-level": ["@commitlint/top-level@20.4.3", "", { "dependencies": { "escalade": "^3.2.0" } }, "sha512-qD9xfP6dFg5jQ3NMrOhG0/w5y3bBUsVGyJvXxdWEwBm8hyx4WOk3kKXw28T5czBYvyeCVJgJJ6aoJZUWDpaacQ=="], "@commitlint/types": ["@commitlint/types@20.5.0", "", { "dependencies": { "conventional-commits-parser": "^6.3.0", "picocolors": "^1.1.1" } }, "sha512-ZJoS8oSq2CAZEpc/YI9SulLrdiIyXeHb/OGqGrkUP6Q7YV+0ouNAa7GjqRdXeQPncHQIDz/jbCTlHScvYvO/gA=="], "@conventional-changelog/git-client": ["@conventional-changelog/git-client@2.6.0", "", { "dependencies": { "@simple-libs/child-process-utils": "^1.0.0", "@simple-libs/stream-utils": "^1.2.0", "semver": "^7.5.2" }, "peerDependencies": { "conventional-commits-filter": "^5.0.0", "conventional-commits-parser": "^6.3.0" }, "optionalPeers": ["conventional-commits-filter", "conventional-commits-parser"] }, "sha512-T+uPDciKf0/ioNNDpMGc8FDsehJClZP0yR3Q5MN6wE/Y/1QZ7F+80OgznnTCOlMEG4AV0LvH2UJi3C/nBnaBUg=="], "@emnapi/core": ["@emnapi/core@1.9.2", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA=="], "@emnapi/runtime": ["@emnapi/runtime@1.9.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw=="], "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="], "@epic-web/invariant": ["@epic-web/invariant@1.0.0", "", {}, "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA=="], "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="], "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="], "@eslint/config-array": ["@eslint/config-array@0.23.4", "", { "dependencies": { "@eslint/object-schema": "^3.0.4", "debug": "^4.3.1", "minimatch": "^10.2.4" } }, "sha512-lf19F24LSMfF8weXvW5QEtnLqW70u7kgit5e9PSx0MsHAFclGd1T9ynvWEMDT1w5J4Qt54tomGeAhdoAku1Xow=="], "@eslint/config-helpers": ["@eslint/config-helpers@0.5.4", "", { "dependencies": { "@eslint/core": "^1.2.0" } }, "sha512-jJhqiY3wPMlWWO3370M86CPJ7pt8GmEwSLglMfQhjXal07RCvhmU0as4IuUEW5SJeunfItiEetHmSxCCe9lDBg=="], "@eslint/core": ["@eslint/core@1.2.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-8FTGbNzTvmSlc4cZBaShkC6YvFMG0riksYWRFKXztqVdXaQbcZLXlFbSpC05s70sGEsXAw0qwhx69JiW7hQS7A=="], "@eslint/js": ["@eslint/js@10.0.1", "", { "peerDependencies": { "eslint": "^10.0.0" }, "optionalPeers": ["eslint"] }, "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA=="], "@eslint/object-schema": ["@eslint/object-schema@3.0.4", "", {}, "sha512-55lO/7+Yp0ISKRP0PsPtNTeNGapXaO085aELZmWCVc5SH3jfrqpuU6YgOdIxMS99ZHkQN1cXKE+cdIqwww9ptw=="], "@eslint/plugin-kit": ["@eslint/plugin-kit@0.7.0", "", { "dependencies": { "@eslint/core": "^1.2.0", "levn": "^0.4.1" } }, "sha512-ejvBr8MQCbVsWNZnCwDXjUKq40MDmHalq7cJ6e9s/qzTUFIIo/afzt1Vui9T97FM/V/pN4YsFVoed5NIa96RDg=="], "@gar/promise-retry": ["@gar/promise-retry@1.0.3", "", {}, "sha512-GmzA9ckNokPypTg10pgpeHNQe7ph+iIKKmhKu3Ob9ANkswreCx7R3cKmY781K8QK3AqVL3xVh9A42JvIAbkkSA=="], "@gulpjs/messages": ["@gulpjs/messages@1.1.0", "", {}, "sha512-Ys9sazDatyTgZVb4xPlDufLweJ/Os2uHWOv+Caxvy2O85JcnT4M3vc73bi8pdLWlv3fdWQz3pdI9tVwo8rQQSg=="], "@gulpjs/to-absolute-glob": ["@gulpjs/to-absolute-glob@4.0.0", "", { "dependencies": { "is-negated-glob": "^1.0.0" } }, "sha512-kjotm7XJrJ6v+7knhPaRgaT6q8F8K2jiafwYdNHLzmV0uGLuZY43FK6smNSHUPrhq5kX2slCUy+RGG/xGqmIKA=="], "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], "@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="], "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], "@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="], "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="], "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], "@jridgewell/source-map": ["@jridgewell/source-map@0.3.11", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" } }, "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA=="], "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.2", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw=="], "@noble/hashes": ["@noble/hashes@1.4.0", "", {}, "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg=="], "@npmcli/agent": ["@npmcli/agent@4.0.0", "", { "dependencies": { "agent-base": "^7.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.1", "lru-cache": "^11.2.1", "socks-proxy-agent": "^8.0.3" } }, "sha512-kAQTcEN9E8ERLVg5AsGwLNoFb+oEG6engbqAU2P43gD4JEIkNGMHdVQ096FsOAAYpZPB0RSt0zgInKIAS1l5QA=="], "@npmcli/fs": ["@npmcli/fs@5.0.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og=="], "@npmcli/git": ["@npmcli/git@7.0.2", "", { "dependencies": { "@gar/promise-retry": "^1.0.0", "@npmcli/promise-spawn": "^9.0.0", "ini": "^6.0.0", "lru-cache": "^11.2.1", "npm-pick-manifest": "^11.0.1", "proc-log": "^6.0.0", "semver": "^7.3.5", "which": "^6.0.0" } }, "sha512-oeolHDjExNAJAnlYP2qzNjMX/Xi9bmu78C9dIGr4xjobrSKbuMYCph8lTzn4vnW3NjIqVmw/f8BCfouqyJXlRg=="], "@npmcli/installed-package-contents": ["@npmcli/installed-package-contents@4.0.0", "", { "dependencies": { "npm-bundled": "^5.0.0", "npm-normalize-package-bin": "^5.0.0" }, "bin": { "installed-package-contents": "bin/index.js" } }, "sha512-yNyAdkBxB72gtZ4GrwXCM0ZUedo9nIbOMKfGjt6Cu6DXf0p8y1PViZAKDC8q8kv/fufx0WTjRBdSlyrvnP7hmA=="], "@npmcli/node-gyp": ["@npmcli/node-gyp@5.0.0", "", {}, "sha512-uuG5HZFXLfyFKqg8QypsmgLQW7smiRjVc45bqD/ofZZcR/uxEjgQU8qDPv0s9TEeMUiAAU/GC5bR6++UdTirIQ=="], "@npmcli/package-json": ["@npmcli/package-json@7.0.5", "", { "dependencies": { "@npmcli/git": "^7.0.0", "glob": "^13.0.0", "hosted-git-info": "^9.0.0", "json-parse-even-better-errors": "^5.0.0", "proc-log": "^6.0.0", "semver": "^7.5.3", "spdx-expression-parse": "^4.0.0" } }, "sha512-iVuTlG3ORq2iaVa1IWUxAO/jIp77tUKBhoMjuzYW2kL4MLN1bi/ofqkZ7D7OOwh8coAx1/S2ge0rMdGv8sLSOQ=="], "@npmcli/promise-spawn": ["@npmcli/promise-spawn@9.0.1", "", { "dependencies": { "which": "^6.0.0" } }, "sha512-OLUaoqBuyxeTqUvjA3FZFiXUfYC1alp3Sa99gW3EUDz3tZ3CbXDdcZ7qWKBzicrJleIgucoWamWH1saAmH/l2Q=="], "@npmcli/redact": ["@npmcli/redact@4.0.0", "", {}, "sha512-gOBg5YHMfZy+TfHArfVogwgfBeQnKbbGo3pSUyK/gSI0AVu+pEiDVcKlQb0D8Mg1LNRZILZ6XG8I5dJ4KuAd9Q=="], "@npmcli/run-script": ["@npmcli/run-script@10.0.4", "", { "dependencies": { "@npmcli/node-gyp": "^5.0.0", "@npmcli/package-json": "^7.0.0", "@npmcli/promise-spawn": "^9.0.0", "node-gyp": "^12.1.0", "proc-log": "^6.0.0" } }, "sha512-mGUWr1uMnf0le2TwfOZY4SFxZGXGfm4Jtay/nwAa2FLNAKXUoUwaGwBMNH36UHPtinWfTSJ3nqFQr0091CxVGg=="], "@oxc-project/types": ["@oxc-project/types@0.122.0", "", {}, "sha512-oLAl5kBpV4w69UtFZ9xqcmTi+GENWOcPF7FCrczTiBbmC0ibXxCwyvZGbO39rCVEuLGAZM84DH0pUIyyv/YJzA=="], "@paralleldrive/cuid2": ["@paralleldrive/cuid2@2.3.1", "", { "dependencies": { "@noble/hashes": "^1.1.5" } }, "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw=="], "@peculiar/asn1-cms": ["@peculiar/asn1-cms@2.6.1", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.1", "@peculiar/asn1-x509-attr": "^2.6.1", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-vdG4fBF6Lkirkcl53q6eOdn3XYKt+kJTG59edgRZORlg/3atWWEReRCx5rYE1ZzTTX6vLK5zDMjHh7vbrcXGtw=="], "@peculiar/asn1-csr": ["@peculiar/asn1-csr@2.6.1", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.1", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-WRWnKfIocHyzFYQTka8O/tXCiBquAPSrRjXbOkHbO4qdmS6loffCEGs+rby6WxxGdJCuunnhS2duHURhjyio6w=="], "@peculiar/asn1-ecc": ["@peculiar/asn1-ecc@2.6.1", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.1", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-+Vqw8WFxrtDIN5ehUdvlN2m73exS2JVG0UAyfVB31gIfor3zWEAQPD+K9ydCxaj3MLen9k0JhKpu9LqviuCE1g=="], "@peculiar/asn1-pfx": ["@peculiar/asn1-pfx@2.6.1", "", { "dependencies": { "@peculiar/asn1-cms": "^2.6.1", "@peculiar/asn1-pkcs8": "^2.6.1", "@peculiar/asn1-rsa": "^2.6.1", "@peculiar/asn1-schema": "^2.6.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-nB5jVQy3MAAWvq0KY0R2JUZG8bO/bTLpnwyOzXyEh/e54ynGTatAR+csOnXkkVD9AFZ2uL8Z7EV918+qB1qDvw=="], "@peculiar/asn1-pkcs8": ["@peculiar/asn1-pkcs8@2.6.1", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.1", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-JB5iQ9Izn5yGMw3ZG4Nw3Xn/hb/G38GYF3lf7WmJb8JZUydhVGEjK/ZlFSWhnlB7K/4oqEs8HnfFIKklhR58Tw=="], "@peculiar/asn1-pkcs9": ["@peculiar/asn1-pkcs9@2.6.1", "", { "dependencies": { "@peculiar/asn1-cms": "^2.6.1", "@peculiar/asn1-pfx": "^2.6.1", "@peculiar/asn1-pkcs8": "^2.6.1", "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.1", "@peculiar/asn1-x509-attr": "^2.6.1", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-5EV8nZoMSxeWmcxWmmcolg22ojZRgJg+Y9MX2fnE2bGRo5KQLqV5IL9kdSQDZxlHz95tHvIq9F//bvL1OeNILw=="], "@peculiar/asn1-rsa": ["@peculiar/asn1-rsa@2.6.1", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.1", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-1nVMEh46SElUt5CB3RUTV4EG/z7iYc7EoaDY5ECwganibQPkZ/Y2eMsTKB/LeyrUJ+W/tKoD9WUqIy8vB+CEdA=="], "@peculiar/asn1-schema": ["@peculiar/asn1-schema@2.6.0", "", { "dependencies": { "asn1js": "^3.0.6", "pvtsutils": "^1.3.6", "tslib": "^2.8.1" } }, "sha512-xNLYLBFTBKkCzEZIw842BxytQQATQv+lDTCEMZ8C196iJcJJMBUZxrhSTxLaohMyKK8QlzRNTRkUmanucnDSqg=="], "@peculiar/asn1-x509": ["@peculiar/asn1-x509@2.6.1", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "asn1js": "^3.0.6", "pvtsutils": "^1.3.6", "tslib": "^2.8.1" } }, "sha512-O9jT5F1A2+t3r7C4VT7LYGXqkGLK7Kj1xFpz7U0isPrubwU5PbDoyYtx6MiGst29yq7pXN5vZbQFKRCP+lLZlA=="], "@peculiar/asn1-x509-attr": ["@peculiar/asn1-x509-attr@2.6.1", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.1", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-tlW6cxoHwgcQghnJwv3YS+9OO1737zgPogZ+CgWRUK4roEwIPzRH4JEiG770xe5HX2ATfCpmX60gurfWIF9dcQ=="], "@peculiar/x509": ["@peculiar/x509@1.14.3", "", { "dependencies": { "@peculiar/asn1-cms": "^2.6.0", "@peculiar/asn1-csr": "^2.6.0", "@peculiar/asn1-ecc": "^2.6.0", "@peculiar/asn1-pkcs9": "^2.6.0", "@peculiar/asn1-rsa": "^2.6.0", "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "pvtsutils": "^1.3.6", "reflect-metadata": "^0.2.2", "tslib": "^2.8.1", "tsyringe": "^4.10.0" } }, "sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA=="], "@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="], "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.12", "", { "os": "android", "cpu": "arm64" }, "sha512-pv1y2Fv0JybcykuiiD3qBOBdz6RteYojRFY1d+b95WVuzx211CRh+ytI/+9iVyWQ6koTh5dawe4S/yRfOFjgaA=="], "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-cFYr6zTG/3PXXF3pUO+umXxt1wkRK/0AYT8lDwuqvRC+LuKYWSAQAQZjCWDQpAH172ZV6ieYrNnFzVVcnSflAg=="], "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-ZCsYknnHzeXYps0lGBz8JrF37GpE9bFVefrlmDrAQhOEi4IOIlcoU1+FwHEtyXGx2VkYAvhu7dyBf75EJQffBw=="], "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dMLeprcVsyJsKolRXyoTH3NL6qtsT0Y2xeuEA8WQJquWFXkEC4bcu1rLZZSnZRMtAqwtrF/Ib9Ddtpa/Gkge9Q=="], "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.12", "", { "os": "linux", "cpu": "arm" }, "sha512-YqWjAgGC/9M1lz3GR1r1rP79nMgo3mQiiA+Hfo+pvKFK1fAJ1bCi0ZQVh8noOqNacuY1qIcfyVfP6HoyBRZ85Q=="], "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-/I5AS4cIroLpslsmzXfwbe5OmWvSsrFuEw3mwvbQ1kDxJ822hFHIx+vsN/TAzNVyepI/j/GSzrtCIwQPeKCLIg=="], "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw=="], "@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g=="], "@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.0-rc.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-nWwpvUSPkoFmZo0kQazZYOrT7J5DGOJ/+QHHzjvNlooDZED8oH82Yg67HvehPPLAg5fUff7TfWFHQS8IV1n3og=="], "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.12", "", { "os": "linux", "cpu": "x64" }, "sha512-RNrafz5bcwRy+O9e6P8Z/OCAJW/A+qtBczIqVYwTs14pf4iV1/+eKEjdOUta93q2TsT/FI0XYDP3TCky38LMAg=="], "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.12", "", { "os": "linux", "cpu": "x64" }, "sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig=="], "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.12", "", { "os": "none", "cpu": "arm64" }, "sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA=="], "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.12", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.1" }, "cpu": "none" }, "sha512-ykGiLr/6kkiHc0XnBfmFJuCjr5ZYKKofkx+chJWDjitX+KsJuAmrzWhwyOMSHzPhzOHOy7u9HlFoa5MoAOJ/Zg=="], "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-5eOND4duWkwx1AzCxadcOrNeighiLwMInEADT0YM7xeEOOFcovWZCq8dadXgcRHSf3Ulh1kFo/qvzoFiCLOL1Q=="], "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.12", "", { "os": "win32", "cpu": "x64" }, "sha512-PyqoipaswDLAZtot351MLhrlrh6lcZPo2LSYE+VDxbVk24LVKAGOuE4hb8xZQmrPAuEtTZW8E6D2zc5EUZX4Lw=="], "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.12", "", {}, "sha512-HHMwmarRKvoFsJorqYlFeFRzXZqCt2ETQlEDOb9aqssrnVBB1/+xgTGtuTrIk5vzLNX1MjMtTf7W9z3tsSbrxw=="], "@rollup/plugin-alias": ["@rollup/plugin-alias@6.0.0", "", { "peerDependencies": { "rollup": ">=4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-tPCzJOtS7uuVZd+xPhoy5W4vThe6KWXNmsFCNktaAh5RTqcLiSfT4huPQIXkgJ6YCOjJHvecOAzQxLFhPxKr+g=="], "@rollup/plugin-babel": ["@rollup/plugin-babel@7.0.0", "", { "dependencies": { "@babel/helper-module-imports": "^7.18.6", "@rollup/pluginutils": "^5.0.1" }, "peerDependencies": { "@babel/core": "^7.0.0", "@types/babel__core": "^7.1.9", "rollup": "^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["@types/babel__core", "rollup"] }, "sha512-NS2+P7v80N3MQqehZEjgpaFb9UyX3URNMW/zvoECKGo4PY4DvJfQusTI7BX/Ks+CPvtTfk3TqcR6S9VYBi/C+A=="], "@rollup/plugin-commonjs": ["@rollup/plugin-commonjs@29.0.2", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "commondir": "^1.0.1", "estree-walker": "^2.0.2", "fdir": "^6.2.0", "is-reference": "1.2.1", "magic-string": "^0.30.3", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^2.68.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-S/ggWH1LU7jTyi9DxZOKyxpVd4hF/OZ0JrEbeLjXk/DFXwRny0tjD2c992zOUYQobLrVkRVMDdmHP16HKP7GRg=="], "@rollup/plugin-json": ["@rollup/plugin-json@6.1.0", "", { "dependencies": { "@rollup/pluginutils": "^5.1.0" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA=="], "@rollup/plugin-node-resolve": ["@rollup/plugin-node-resolve@16.0.3", "", { "dependencies": { "@rollup/pluginutils": "^5.0.1", "@types/resolve": "1.20.2", "deepmerge": "^4.2.2", "is-module": "^1.0.0", "resolve": "^1.22.1" }, "peerDependencies": { "rollup": "^2.78.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg=="], "@rollup/plugin-terser": ["@rollup/plugin-terser@1.0.0", "", { "dependencies": { "serialize-javascript": "^7.0.3", "smob": "^1.0.0", "terser": "^5.17.4" }, "peerDependencies": { "rollup": "^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-FnCxhTBx6bMOYQrar6C8h3scPt8/JwIzw3+AJ2K++6guogH5fYaIFia+zZuhqv0eo1RN7W1Pz630SyvLbDjhtQ=="], "@rollup/pluginutils": ["@rollup/pluginutils@5.3.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q=="], "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.60.1", "", { "os": "android", "cpu": "arm" }, "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA=="], "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.60.1", "", { "os": "android", "cpu": "arm64" }, "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA=="], "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.60.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw=="], "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.60.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew=="], "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.60.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w=="], "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.60.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g=="], "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.60.1", "", { "os": "linux", "cpu": "arm" }, "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g=="], "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.60.1", "", { "os": "linux", "cpu": "arm" }, "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg=="], "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.60.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ=="], "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.60.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA=="], "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.60.1", "", { "os": "linux", "cpu": "none" }, "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ=="], "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.60.1", "", { "os": "linux", "cpu": "none" }, "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw=="], "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.60.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw=="], "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.60.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg=="], "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.60.1", "", { "os": "linux", "cpu": "none" }, "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg=="], "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.60.1", "", { "os": "linux", "cpu": "none" }, "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg=="], "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.60.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ=="], "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.60.1", "", { "os": "linux", "cpu": "x64" }, "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg=="], "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.60.1", "", { "os": "linux", "cpu": "x64" }, "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w=="], "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.60.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw=="], "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.60.1", "", { "os": "none", "cpu": "arm64" }, "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA=="], "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.60.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g=="], "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.60.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg=="], "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.60.1", "", { "os": "win32", "cpu": "x64" }, "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg=="], "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.60.1", "", { "os": "win32", "cpu": "x64" }, "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ=="], "@sec-ant/readable-stream": ["@sec-ant/readable-stream@0.4.1", "", {}, "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg=="], "@sigstore/bundle": ["@sigstore/bundle@4.0.0", "", { "dependencies": { "@sigstore/protobuf-specs": "^0.5.0" } }, "sha512-NwCl5Y0V6Di0NexvkTqdoVfmjTaQwoLM236r89KEojGmq/jMls8S+zb7yOwAPdXvbwfKDlP+lmXgAL4vKSQT+A=="], "@sigstore/core": ["@sigstore/core@3.2.0", "", {}, "sha512-kxHrDQ9YgfrWUSXU0cjsQGv8JykOFZQ9ErNKbFPWzk3Hgpwu8x2hHrQ9IdA8yl+j9RTLTC3sAF3Tdq1IQCP4oA=="], "@sigstore/protobuf-specs": ["@sigstore/protobuf-specs@0.5.0", "", {}, "sha512-MM8XIwUjN2bwvCg1QvrMtbBmpcSHrkhFSCu1D11NyPvDQ25HEc4oG5/OcQfd/Tlf/OxmKWERDj0zGE23jQaMwA=="], "@sigstore/sign": ["@sigstore/sign@4.1.1", "", { "dependencies": { "@gar/promise-retry": "^1.0.2", "@sigstore/bundle": "^4.0.0", "@sigstore/core": "^3.2.0", "@sigstore/protobuf-specs": "^0.5.0", "make-fetch-happen": "^15.0.4", "proc-log": "^6.1.0" } }, "sha512-Hf4xglukg0XXQ2RiD5vSoLjdPe8OBUPA8XeVjUObheuDcWdYWrnH/BNmxZCzkAy68MzmNCxXLeurJvs6hcP2OQ=="], "@sigstore/tuf": ["@sigstore/tuf@4.0.2", "", { "dependencies": { "@sigstore/protobuf-specs": "^0.5.0", "tuf-js": "^4.1.0" } }, "sha512-TCAzTy0xzdP79EnxSjq9KQ3eaR7+FmudLC6eRKknVKZbV7ZNlGLClAAQb/HMNJ5n2OBNk2GT1tEmU0xuPr+SLQ=="], "@sigstore/verify": ["@sigstore/verify@3.1.0", "", { "dependencies": { "@sigstore/bundle": "^4.0.0", "@sigstore/core": "^3.1.0", "@sigstore/protobuf-specs": "^0.5.0" } }, "sha512-mNe0Iigql08YupSOGv197YdHpPPr+EzDZmfCgMc7RPNaZTw5aLN01nBl6CHJOh3BGtnMIj83EeN4butBchc8Ag=="], "@simple-libs/child-process-utils": ["@simple-libs/child-process-utils@1.0.2", "", { "dependencies": { "@simple-libs/stream-utils": "^1.2.0" } }, "sha512-/4R8QKnd/8agJynkNdJmNw2MBxuFTRcNFnE5Sg/G+jkSsV8/UBgULMzhizWWW42p8L5H7flImV2ATi79Ove2Tw=="], "@simple-libs/stream-utils": ["@simple-libs/stream-utils@1.2.0", "", {}, "sha512-KxXvfapcixpz6rVEB6HPjOUZT22yN6v0vI0urQSk1L8MlEWPDFCZkhw2xmkyoTGYeFw7tWTZd7e3lVzRZRN/EA=="], "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], "@tufjs/canonical-json": ["@tufjs/canonical-json@2.0.0", "", {}, "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA=="], "@tufjs/models": ["@tufjs/models@4.1.0", "", { "dependencies": { "@tufjs/canonical-json": "2.0.0", "minimatch": "^10.1.1" } }, "sha512-Y8cK9aggNRsqJVaKUlEYs4s7CvQ1b1ta2DVPyAimb0I2qhzjNk+A+mxvll/klL0RlfuIUei8BF7YWiua4kQqww=="], "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], "@types/bun": ["@types/bun@1.3.11", "", { "dependencies": { "bun-types": "1.3.11" } }, "sha512-5vPne5QvtpjGpsGYXiFyycfpDF2ECyPcTSsFBMa0fraoxiQyMJ3SmuQIGhzPg2WJuWxVBoxWJ2kClYTcw/4fAg=="], "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="], "@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="], "@types/esrecurse": ["@types/esrecurse@4.3.1", "", {}, "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw=="], "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], "@types/node": ["@types/node@25.5.2", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg=="], "@types/resolve": ["@types/resolve@1.20.2", "", {}, "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q=="], "@vitest/browser": ["@vitest/browser@4.1.2", "", { "dependencies": { "@blazediff/core": "1.9.1", "@vitest/mocker": "4.1.2", "@vitest/utils": "4.1.2", "magic-string": "^0.30.21", "pngjs": "^7.0.0", "sirv": "^3.0.2", "tinyrainbow": "^3.1.0", "ws": "^8.19.0" }, "peerDependencies": { "vitest": "4.1.2" } }, "sha512-CwdIf90LNf1Zitgqy63ciMAzmyb4oIGs8WZ40VGYrWkssQKeEKr32EzO8MKUrDPPcPVHFI9oQ5ni2Hp24NaNRQ=="], "@vitest/browser-playwright": ["@vitest/browser-playwright@4.1.2", "", { "dependencies": { "@vitest/browser": "4.1.2", "@vitest/mocker": "4.1.2", "tinyrainbow": "^3.1.0" }, "peerDependencies": { "playwright": "*", "vitest": "4.1.2" } }, "sha512-N0Z2HzMLvMR6k/tWPTS6Q/DaRscrkax/f2f9DIbNQr+Cd1l4W4wTf/I6S983PAMr0tNqqoTL+xNkLh9M5vbkLg=="], "@vitest/expect": ["@vitest/expect@4.1.2", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.2", "@vitest/utils": "4.1.2", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" } }, "sha512-gbu+7B0YgUJ2nkdsRJrFFW6X7NTP44WlhiclHniUhxADQJH5Szt9mZ9hWnJPJ8YwOK5zUOSSlSvyzRf0u1DSBQ=="], "@vitest/mocker": ["@vitest/mocker@4.1.2", "", { "dependencies": { "@vitest/spy": "4.1.2", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-Ize4iQtEALHDttPRCmN+FKqOl2vxTiNUhzobQFFt/BM1lRUTG7zRCLOykG/6Vo4E4hnUdfVLo5/eqKPukcWW7Q=="], "@vitest/pretty-format": ["@vitest/pretty-format@4.1.2", "", { "dependencies": { "tinyrainbow": "^3.1.0" } }, "sha512-dwQga8aejqeuB+TvXCMzSQemvV9hNEtDDpgUKDzOmNQayl2OG241PSWeJwKRH3CiC+sESrmoFd49rfnq7T4RnA=="], "@vitest/runner": ["@vitest/runner@4.1.2", "", { "dependencies": { "@vitest/utils": "4.1.2", "pathe": "^2.0.3" } }, "sha512-Gr+FQan34CdiYAwpGJmQG8PgkyFVmARK8/xSijia3eTFgVfpcpztWLuP6FttGNfPLJhaZVP/euvujeNYar36OQ=="], "@vitest/snapshot": ["@vitest/snapshot@4.1.2", "", { "dependencies": { "@vitest/pretty-format": "4.1.2", "@vitest/utils": "4.1.2", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-g7yfUmxYS4mNxk31qbOYsSt2F4m1E02LFqO53Xpzg3zKMhLAPZAjjfyl9e6z7HrW6LvUdTwAQR3HHfLjpko16A=="], "@vitest/spy": ["@vitest/spy@4.1.2", "", {}, "sha512-DU4fBnbVCJGNBwVA6xSToNXrkZNSiw59H8tcuUspVMsBDBST4nfvsPsEHDHGtWRRnqBERBQu7TrTKskmjqTXKA=="], "@vitest/utils": ["@vitest/utils@4.1.2", "", { "dependencies": { "@vitest/pretty-format": "4.1.2", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-xw2/TiX82lQHA06cgbqRKFb5lCAy3axQ4H4SoUFhUsg+wztiet+co86IAMDtF6Vm1hc7J6j09oh/rgDn+JdKIQ=="], "abbrev": ["abbrev@4.0.0", "", {}, "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA=="], "abortcontroller-polyfill": ["abortcontroller-polyfill@1.7.8", "", {}, "sha512-9f1iZ2uWh92VcrU9Y8x+LdM4DLj75VE0MJB8zuF1iUnroEptStw+DQ8EQPMUdfe5k+PkB1uUfDQfWbhstH8LrQ=="], "accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="], "acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], "ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="], "ansi-escapes": ["ansi-escapes@7.3.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg=="], "ansi-regex": ["ansi-regex@2.1.1", "", {}, "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA=="], "ansi-styles": ["ansi-styles@2.2.1", "", {}, "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA=="], "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], "append-field": ["append-field@1.0.0", "", {}, "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw=="], "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], "array-each": ["array-each@1.0.1", "", {}, "sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA=="], "array-ify": ["array-ify@1.0.0", "", {}, "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng=="], "array-slice": ["array-slice@1.1.0", "", {}, "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w=="], "asap": ["asap@2.0.6", "", {}, "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA=="], "asn1js": ["asn1js@3.0.7", "", { "dependencies": { "pvtsutils": "^1.3.6", "pvutils": "^1.1.3", "tslib": "^2.8.1" } }, "sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ=="], "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], "async-done": ["async-done@2.0.0", "", { "dependencies": { "end-of-stream": "^1.4.4", "once": "^1.4.0", "stream-exhaust": "^1.0.2" } }, "sha512-j0s3bzYq9yKIVLKGE/tWlCpa3PfFLcrDZLTSVdnnCTGagXuXBJO4SsY9Xdk/fQBirCkH4evW5xOeJXqlAQFdsw=="], "async-settle": ["async-settle@2.0.0", "", { "dependencies": { "async-done": "^2.0.0" } }, "sha512-Obu/KE8FurfQRN6ODdHN9LuXqwC+JFIM9NRyZqJJ4ZfLJmIYN9Rg0/kb+wF70VV5+fJusTMQlJ1t5rF7J/ETdg=="], "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], "auto-changelog": ["auto-changelog@2.5.0", "", { "dependencies": { "commander": "^7.2.0", "handlebars": "^4.7.7", "import-cwd": "^3.0.0", "node-fetch": "^2.6.1", "parse-github-url": "^1.0.3", "semver": "^7.3.5" }, "bin": { "auto-changelog": "src/index.js" } }, "sha512-UTnLjT7I9U2U/xkCUH5buDlp8C7g0SGChfib+iDrJkamcj5kaMqNKHNfbKJw1kthJUq8sUo3i3q2S6FzO/l/wA=="], "axios": ["axios@file:../../..", { "dependencies": { "follow-redirects": "^1.15.11", "form-data": "^4.0.5", "proxy-from-env": "^2.1.0" }, "devDependencies": { "@babel/core": "^7.29.0", "@babel/preset-env": "^7.29.0", "@commitlint/cli": "^20.4.4", "@commitlint/config-conventional": "^20.4.4", "@eslint/js": "^10.0.1", "@rollup/plugin-alias": "^6.0.0", "@rollup/plugin-babel": "^7.0.0", "@rollup/plugin-commonjs": "^29.0.2", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^16.0.3", "@rollup/plugin-terser": "^1.0.0", "@vitest/browser": "^4.1.1", "@vitest/browser-playwright": "^4.1.1", "abortcontroller-polyfill": "^1.7.8", "auto-changelog": "^2.5.0", "body-parser": "^2.2.2", "chalk": "^5.6.2", "cross-env": "^10.1.0", "dev-null": "^0.1.1", "eslint": "^10.1.0", "express": "^5.2.1", "formdata-node": "^6.0.3", "formidable": "^3.2.4", "fs-extra": "^11.3.4", "get-stream": "^9.0.1", "globals": "^17.4.0", "gulp": "^5.0.1", "handlebars": "^4.7.8", "husky": "^9.1.7", "lint-staged": "^16.4.0", "memoizee": "^0.4.17", "minimist": "^1.2.8", "multer": "^2.1.1", "pacote": "^21.5.0", "playwright": "^1.58.2", "prettier": "^3.8.1", "pretty-bytes": "^7.1.0", "rollup": "^4.60.0", "rollup-plugin-bundle-size": "^1.0.3", "selfsigned": "^5.5.0", "stream-throttle": "^0.1.3", "string-replace-async": "^3.0.2", "tar-stream": "^3.1.8", "typescript": "^5.9.3", "vitest": "^4.1.1" } }], "b4a": ["b4a@1.8.0", "", { "peerDependencies": { "react-native-b4a": "*" }, "optionalPeers": ["react-native-b4a"] }, "sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg=="], "babel-plugin-polyfill-corejs2": ["babel-plugin-polyfill-corejs2@0.4.17", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-define-polyfill-provider": "^0.6.8", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w=="], "babel-plugin-polyfill-corejs3": ["babel-plugin-polyfill-corejs3@0.14.2", "", { "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.8", "core-js-compat": "^3.48.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g=="], "babel-plugin-polyfill-regenerator": ["babel-plugin-polyfill-regenerator@0.6.8", "", { "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.8" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg=="], "bach": ["bach@2.0.1", "", { "dependencies": { "async-done": "^2.0.0", "async-settle": "^2.0.0", "now-and-later": "^3.0.0" } }, "sha512-A7bvGMGiTOxGMpNupYl9HQTf0FFDNF4VCmks4PJpFyN1AX2pdKuxuwdvUz2Hu388wcgp+OvGFNsumBfFNkR7eg=="], "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], "bare-events": ["bare-events@2.8.2", "", { "peerDependencies": { "bare-abort-controller": "*" }, "optionalPeers": ["bare-abort-controller"] }, "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ=="], "bare-fs": ["bare-fs@4.6.0", "", { "dependencies": { "bare-events": "^2.5.4", "bare-path": "^3.0.0", "bare-stream": "^2.6.4", "bare-url": "^2.2.2", "fast-fifo": "^1.3.2" }, "peerDependencies": { "bare-buffer": "*" }, "optionalPeers": ["bare-buffer"] }, "sha512-2YkS7NuiJceSEbyEOdSNLE9tsGd+f4+f7C+Nik/MCk27SYdwIMPT/yRKvg++FZhQXgk0KWJKJyXX9RhVV0RGqA=="], "bare-os": ["bare-os@3.8.7", "", {}, "sha512-G4Gr1UsGeEy2qtDTZwL7JFLo2wapUarz7iTMcYcMFdS89AIQuBoyjgXZz0Utv7uHs3xA9LckhVbeBi8lEQrC+w=="], "bare-path": ["bare-path@3.0.0", "", { "dependencies": { "bare-os": "^3.0.1" } }, "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw=="], "bare-stream": ["bare-stream@2.12.0", "", { "dependencies": { "streamx": "^2.25.0", "teex": "^1.0.1" }, "peerDependencies": { "bare-abort-controller": "*", "bare-buffer": "*", "bare-events": "*" }, "optionalPeers": ["bare-abort-controller", "bare-buffer", "bare-events"] }, "sha512-w28i8lkBgREV3rPXGbgK+BO66q+ZpKqRWrZLiCdmmUlLPrQ45CzkvRhN+7lnv00Gpi2zy5naRxnUFAxCECDm9g=="], "bare-url": ["bare-url@2.4.0", "", { "dependencies": { "bare-path": "^3.0.0" } }, "sha512-NSTU5WN+fy/L0DDenfE8SXQna4voXuW0FHM7wH8i3/q9khUSchfPbPezO4zSFMnDGIf9YE+mt/RWhZgNRKRIXA=="], "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], "baseline-browser-mapping": ["baseline-browser-mapping@2.10.14", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-fOVLPAsFTsQfuCkvahZkzq6nf8KvGWanlYoTh0SVA0A/PIUxQGU2AOZAoD95n2gFLVDW/jP6sbGLny95nmEuHA=="], "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], "bl": ["bl@5.1.0", "", { "dependencies": { "buffer": "^6.0.3", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ=="], "body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="], "brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="], "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], "browserslist": ["browserslist@4.28.2", "", { "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", "electron-to-chromium": "^1.5.328", "node-releases": "^2.0.36", "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg=="], "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], "bun-types": ["bun-types@1.3.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-1KGPpoxQWl9f6wcZh57LvrPIInQMn2TQ7jsgxqpRzg+l0QPOFvJVH7HmvHo/AiPgwXy+/Thf6Ov3EdVn1vOabg=="], "busboy": ["busboy@1.6.0", "", { "dependencies": { "streamsearch": "^1.1.0" } }, "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA=="], "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], "bytestreamjs": ["bytestreamjs@2.0.1", "", {}, "sha512-U1Z/ob71V/bXfVABvNr/Kumf5VyeQRBEm6Txb0PQ6S7V5GpBM3w4Cbqz/xPDicR5tN0uvDifng8C+5qECeGwyQ=="], "cacache": ["cacache@20.0.4", "", { "dependencies": { "@npmcli/fs": "^5.0.0", "fs-minipass": "^3.0.0", "glob": "^13.0.0", "lru-cache": "^11.1.0", "minipass": "^7.0.3", "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "p-map": "^7.0.2", "ssri": "^13.0.0" } }, "sha512-M3Lab8NPYlZU2exsL3bMVvMrMqgwCnMWfdZbK28bn3pK6APT/Te/I8hjRPNu1uwORY9a1eEQoifXbKPQMfMTOA=="], "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], "caniuse-lite": ["caniuse-lite@1.0.30001785", "", {}, "sha512-blhOL/WNR+Km1RI/LCVAvA73xplXA7ZbjzI4YkMK9pa6T/P3F2GxjNpEkyw5repTw9IvkyrjyHpwjnhZ5FOvYQ=="], "chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="], "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], "chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], "chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="], "cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="], "cli-truncate": ["cli-truncate@5.2.0", "", { "dependencies": { "slice-ansi": "^8.0.0", "string-width": "^8.2.0" } }, "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw=="], "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], "clone": ["clone@2.1.2", "", {}, "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w=="], "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], "colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="], "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], "commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="], "commondir": ["commondir@1.0.1", "", {}, "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg=="], "compare-func": ["compare-func@2.0.0", "", { "dependencies": { "array-ify": "^1.0.0", "dot-prop": "^5.1.0" } }, "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA=="], "concat-stream": ["concat-stream@2.0.0", "", { "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.0.2", "typedarray": "^0.0.6" } }, "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A=="], "content-disposition": ["content-disposition@1.0.1", "", {}, "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q=="], "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], "conventional-changelog-angular": ["conventional-changelog-angular@8.3.1", "", { "dependencies": { "compare-func": "^2.0.0" } }, "sha512-6gfI3otXK5Ph5DfCOI1dblr+kN3FAm5a97hYoQkqNZxOaYa5WKfXH+AnpsmS+iUH2mgVC2Cg2Qw9m5OKcmNrIg=="], "conventional-changelog-conventionalcommits": ["conventional-changelog-conventionalcommits@9.3.1", "", { "dependencies": { "compare-func": "^2.0.0" } }, "sha512-dTYtpIacRpcZgrvBYvBfArMmK2xvIpv2TaxM0/ZI5CBtNUzvF2x0t15HsbRABWprS6UPmvj+PzHVjSx4qAVKyw=="], "conventional-commits-parser": ["conventional-commits-parser@6.4.0", "", { "dependencies": { "@simple-libs/stream-utils": "^1.2.0", "meow": "^13.0.0" }, "bin": { "conventional-commits-parser": "dist/cli/index.js" } }, "sha512-tvRg7FIBNlyPzjdG8wWRlPHQJJHI7DylhtRGeU9Lq+JuoPh5BKpPRX83ZdLrvXuOSu5Eo/e7SzOQhU4Hd2Miuw=="], "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], "cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], "cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="], "copy-props": ["copy-props@4.0.0", "", { "dependencies": { "each-props": "^3.0.0", "is-plain-object": "^5.0.0" } }, "sha512-bVWtw1wQLzzKiYROtvNlbJgxgBYt2bMJpkCbKmXM3xyijvcjjWXEk5nyrrT3bgJ7ODb19ZohE2T0Y3FgNPyoTw=="], "core-js-compat": ["core-js-compat@3.49.0", "", { "dependencies": { "browserslist": "^4.28.1" } }, "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA=="], "cosmiconfig": ["cosmiconfig@9.0.1", "", { "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0" }, "peerDependencies": { "typescript": ">=4.9.5" }, "optionalPeers": ["typescript"] }, "sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ=="], "cosmiconfig-typescript-loader": ["cosmiconfig-typescript-loader@6.2.0", "", { "dependencies": { "jiti": "^2.6.1" }, "peerDependencies": { "@types/node": "*", "cosmiconfig": ">=9", "typescript": ">=5" } }, "sha512-GEN39v7TgdxgIoNcdkRE3uiAzQt3UXLyHbRHD6YoL048XAeOomyxaP+Hh/+2C6C2wYjxJ2onhJcsQp+L4YEkVQ=="], "cross-env": ["cross-env@10.1.0", "", { "dependencies": { "@epic-web/invariant": "^1.0.0", "cross-spawn": "^7.0.6" }, "bin": { "cross-env": "dist/bin/cross-env.js", "cross-env-shell": "dist/bin/cross-env-shell.js" } }, "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw=="], "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], "d": ["d@1.0.2", "", { "dependencies": { "es5-ext": "^0.10.64", "type": "^2.7.2" } }, "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw=="], "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="], "detect-file": ["detect-file@1.0.0", "", {}, "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q=="], "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], "dev-null": ["dev-null@0.1.1", "", {}, "sha512-nMNZG0zfMgmdv8S5O0TM5cpwNbGKRGPCxVsr0SmA3NZZy9CYBbuNLL0PD3Acx9e5LIUgwONXtM9kM6RlawPxEQ=="], "dezalgo": ["dezalgo@1.0.4", "", { "dependencies": { "asap": "^2.0.0", "wrappy": "1" } }, "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig=="], "dot-prop": ["dot-prop@5.3.0", "", { "dependencies": { "is-obj": "^2.0.0" } }, "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q=="], "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], "duplexer": ["duplexer@0.1.2", "", {}, "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg=="], "each-props": ["each-props@3.0.0", "", { "dependencies": { "is-plain-object": "^5.0.0", "object.defaults": "^1.1.0" } }, "sha512-IYf1hpuWrdzse/s/YJOrFmU15lyhSzxelNVAHTEG3DtP4QsLTWZUzcUL3HMXmKQxXpa4EIrBPpwRgj0aehdvAw=="], "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], "electron-to-chromium": ["electron-to-chromium@1.5.331", "", {}, "sha512-IbxXrsTlD3hRodkLnbxAPP4OuJYdWCeM3IOdT+CpcMoIwIoDfCmRpEtSPfwBXxVkg9xmBeY7Lz2Eo2TDn/HC3Q=="], "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="], "env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="], "environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="], "error-ex": ["error-ex@1.3.4", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ=="], "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], "es-module-lexer": ["es-module-lexer@2.0.0", "", {}, "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw=="], "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], "es5-ext": ["es5-ext@0.10.64", "", { "dependencies": { "es6-iterator": "^2.0.3", "es6-symbol": "^3.1.3", "esniff": "^2.0.1", "next-tick": "^1.1.0" } }, "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg=="], "es6-iterator": ["es6-iterator@2.0.3", "", { "dependencies": { "d": "1", "es5-ext": "^0.10.35", "es6-symbol": "^3.1.1" } }, "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g=="], "es6-symbol": ["es6-symbol@3.1.4", "", { "dependencies": { "d": "^1.0.2", "ext": "^1.7.0" } }, "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg=="], "es6-weak-map": ["es6-weak-map@2.0.3", "", { "dependencies": { "d": "1", "es5-ext": "^0.10.46", "es6-iterator": "^2.0.3", "es6-symbol": "^3.1.1" } }, "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA=="], "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], "eslint": ["eslint@10.2.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.4", "@eslint/config-helpers": "^0.5.4", "@eslint/core": "^1.2.0", "@eslint/plugin-kit": "^0.7.0", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.2.0", "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "minimatch": "^10.2.4", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-+L0vBFYGIpSNIt/KWTpFonPrqYvgKw1eUI5Vn7mEogrQcWtWYtNQ7dNqC+px/J0idT3BAkiWrhfS7k+Tum8TUA=="], "eslint-scope": ["eslint-scope@9.1.2", "", { "dependencies": { "@types/esrecurse": "^4.3.1", "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ=="], "eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="], "esniff": ["esniff@2.0.1", "", { "dependencies": { "d": "^1.0.1", "es5-ext": "^0.10.62", "event-emitter": "^0.3.5", "type": "^2.7.2" } }, "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg=="], "espree": ["espree@11.2.0", "", { "dependencies": { "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^5.0.1" } }, "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw=="], "esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="], "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], "estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="], "event-emitter": ["event-emitter@0.3.5", "", { "dependencies": { "d": "1", "es5-ext": "~0.10.14" } }, "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA=="], "eventemitter3": ["eventemitter3@5.0.4", "", {}, "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw=="], "events-universal": ["events-universal@1.0.1", "", { "dependencies": { "bare-events": "^2.7.0" } }, "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw=="], "expand-tilde": ["expand-tilde@2.0.2", "", { "dependencies": { "homedir-polyfill": "^1.0.1" } }, "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw=="], "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="], "exponential-backoff": ["exponential-backoff@3.1.3", "", {}, "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA=="], "express": ["express@5.2.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="], "ext": ["ext@1.7.0", "", { "dependencies": { "type": "^2.7.2" } }, "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw=="], "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], "fast-fifo": ["fast-fifo@1.3.2", "", {}, "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ=="], "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], "fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="], "fastest-levenshtein": ["fastest-levenshtein@1.0.16", "", {}, "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg=="], "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], "figures": ["figures@1.7.0", "", { "dependencies": { "escape-string-regexp": "^1.0.5", "object-assign": "^4.1.0" } }, "sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ=="], "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], "finalhandler": ["finalhandler@2.1.1", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA=="], "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], "findup-sync": ["findup-sync@5.0.0", "", { "dependencies": { "detect-file": "^1.0.0", "is-glob": "^4.0.3", "micromatch": "^4.0.4", "resolve-dir": "^1.0.1" } }, "sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ=="], "fined": ["fined@2.0.0", "", { "dependencies": { "expand-tilde": "^2.0.2", "is-plain-object": "^5.0.0", "object.defaults": "^1.1.0", "object.pick": "^1.3.0", "parse-filepath": "^1.0.2" } }, "sha512-OFRzsL6ZMHz5s0JrsEr+TpdGNCtrVtnuG3x1yzGNiQHT0yaDnXAj8V/lWcpJVrnoDpcwXcASxAZYbuXda2Y82A=="], "flagged-respawn": ["flagged-respawn@2.0.0", "", {}, "sha512-Gq/a6YCi8zexmGHMuJwahTGzXlAZAOsbCVKduWXC6TlLCjjFRlExMJc4GC2NYPYZ0r/brw9P7CpRgQmlPVeOoA=="], "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], "flatted": ["flatted@3.4.2", "", {}, "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA=="], "follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="], "for-in": ["for-in@1.0.2", "", {}, "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ=="], "for-own": ["for-own@1.0.0", "", { "dependencies": { "for-in": "^1.0.1" } }, "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg=="], "form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="], "formdata-node": ["formdata-node@6.0.3", "", {}, "sha512-8e1++BCiTzUno9v5IZ2J6bv4RU+3UKDmqWUQD0MIMVCd9AdhWkO1gw57oo1mNEX1dMq2EGI+FbWz4B92pscSQg=="], "formidable": ["formidable@3.5.4", "", { "dependencies": { "@paralleldrive/cuid2": "^2.2.2", "dezalgo": "^1.0.4", "once": "^1.4.0" } }, "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug=="], "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="], "fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="], "fs-extra": ["fs-extra@11.3.4", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA=="], "fs-minipass": ["fs-minipass@3.0.3", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw=="], "fs-mkdirp-stream": ["fs-mkdirp-stream@2.0.1", "", { "dependencies": { "graceful-fs": "^4.2.8", "streamx": "^2.12.0" } }, "sha512-UTOY+59K6IA94tec8Wjqm0FSh5OVudGNB0NL/P6fB3HiE3bYOY3VYBGijsnOHNkQSwC1FKkU77pmq7xp9CskLw=="], "fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="], "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], "get-east-asian-width": ["get-east-asian-width@1.5.0", "", {}, "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA=="], "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], "get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="], "git-raw-commits": ["git-raw-commits@5.0.1", "", { "dependencies": { "@conventional-changelog/git-client": "^2.6.0", "meow": "^13.0.0" }, "bin": { "git-raw-commits": "src/cli.js" } }, "sha512-Y+csSm2GD/PCSh6Isd/WiMjNAydu0VBiG9J7EdQsNA5P9uXvLayqjmTsNlK5Gs9IhblFZqOU0yid5Il5JPoLiQ=="], "glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="], "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], "glob-stream": ["glob-stream@8.0.3", "", { "dependencies": { "@gulpjs/to-absolute-glob": "^4.0.0", "anymatch": "^3.1.3", "fastq": "^1.13.0", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "is-negated-glob": "^1.0.0", "normalize-path": "^3.0.0", "streamx": "^2.12.5" } }, "sha512-fqZVj22LtFJkHODT+M4N1RJQ3TjnnQhfE9GwZI8qXscYarnhpip70poMldRnP8ipQ/w0B621kOhfc53/J9bd/A=="], "glob-watcher": ["glob-watcher@6.0.0", "", { "dependencies": { "async-done": "^2.0.0", "chokidar": "^3.5.3" } }, "sha512-wGM28Ehmcnk2NqRORXFOTOR064L4imSw3EeOqU5bIwUf62eXGwg89WivH6VMahL8zlQHeodzvHpXplrqzrz3Nw=="], "global-directory": ["global-directory@4.0.1", "", { "dependencies": { "ini": "4.1.1" } }, "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q=="], "global-modules": ["global-modules@1.0.0", "", { "dependencies": { "global-prefix": "^1.0.1", "is-windows": "^1.0.1", "resolve-dir": "^1.0.0" } }, "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg=="], "global-prefix": ["global-prefix@1.0.2", "", { "dependencies": { "expand-tilde": "^2.0.2", "homedir-polyfill": "^1.0.1", "ini": "^1.3.4", "is-windows": "^1.0.1", "which": "^1.2.14" } }, "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg=="], "globals": ["globals@17.4.0", "", {}, "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw=="], "glogg": ["glogg@2.2.0", "", { "dependencies": { "sparkles": "^2.1.0" } }, "sha512-eWv1ds/zAlz+M1ioHsyKJomfY7jbDDPpwSkv14KQj89bycx1nvK5/2Cj/T9g7kzJcX5Bc7Yv22FjfBZS/jl94A=="], "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], "gulp": ["gulp@5.0.1", "", { "dependencies": { "glob-watcher": "^6.0.0", "gulp-cli": "^3.1.0", "undertaker": "^2.0.0", "vinyl-fs": "^4.0.2" }, "bin": { "gulp": "bin/gulp.js" } }, "sha512-PErok3DZSA5WGMd6XXV3IRNO0mlB+wW3OzhFJLEec1jSERg2j1bxJ6e5Fh6N6fn3FH2T9AP4UYNb/pYlADB9sA=="], "gulp-cli": ["gulp-cli@3.1.0", "", { "dependencies": { "@gulpjs/messages": "^1.1.0", "chalk": "^4.1.2", "copy-props": "^4.0.0", "gulplog": "^2.2.0", "interpret": "^3.1.1", "liftoff": "^5.0.1", "mute-stdout": "^2.0.0", "replace-homedir": "^2.0.0", "semver-greatest-satisfied-range": "^2.0.0", "string-width": "^4.2.3", "v8flags": "^4.0.0", "yargs": "^16.2.0" }, "bin": { "gulp": "bin/gulp.js" } }, "sha512-zZzwlmEsTfXcxRKiCHsdyjZZnFvXWM4v1NqBJSYbuApkvVKivjcmOS2qruAJ+PkEHLFavcDKH40DPc1+t12a9Q=="], "gulplog": ["gulplog@2.2.0", "", { "dependencies": { "glogg": "^2.2.0" } }, "sha512-V2FaKiOhpR3DRXZuYdRLn/qiY0yI5XmqbTKrYbdemJ+xOh2d2MOweI/XFgMzd/9+1twdvMwllnZbWZNJ+BOm4A=="], "gzip-size": ["gzip-size@3.0.0", "", { "dependencies": { "duplexer": "^0.1.1" } }, "sha512-6s8trQiK+OMzSaCSVXX+iqIcLV9tC+E73jrJrJTyS4h/AJhlxHvzFKqM1YLDJWRGgHX8uLkBeXkA0njNj39L4w=="], "handlebars": ["handlebars@4.7.9", "", { "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, "optionalDependencies": { "uglify-js": "^3.1.4" }, "bin": { "handlebars": "bin/handlebars" } }, "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ=="], "has-ansi": ["has-ansi@2.0.0", "", { "dependencies": { "ansi-regex": "^2.0.0" } }, "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg=="], "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], "homedir-polyfill": ["homedir-polyfill@1.0.3", "", { "dependencies": { "parse-passwd": "^1.0.0" } }, "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA=="], "hosted-git-info": ["hosted-git-info@9.0.2", "", { "dependencies": { "lru-cache": "^11.1.0" } }, "sha512-M422h7o/BR3rmCQ8UHi7cyyMqKltdP9Uo+J2fXK+RSAY+wTcKOIRyhTuKv4qn+DJf3g+PL890AzId5KZpX+CBg=="], "http-cache-semantics": ["http-cache-semantics@4.2.0", "", {}, "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="], "http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="], "http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="], "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], "husky": ["husky@9.1.7", "", { "bin": { "husky": "bin.js" } }, "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA=="], "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="], "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], "ignore-walk": ["ignore-walk@8.0.0", "", { "dependencies": { "minimatch": "^10.0.3" } }, "sha512-FCeMZT4NiRQGh+YkeKMtWrOmBgWjHjMJ26WQWrRQyoyzqevdaGSakUaJW5xQYmjLlUVk2qUnCjYVBax9EKKg8A=="], "import-cwd": ["import-cwd@3.0.0", "", { "dependencies": { "import-from": "^3.0.0" } }, "sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg=="], "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], "import-from": ["import-from@3.0.0", "", { "dependencies": { "resolve-from": "^5.0.0" } }, "sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ=="], "import-meta-resolve": ["import-meta-resolve@4.2.0", "", {}, "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg=="], "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], "ini": ["ini@6.0.0", "", {}, "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ=="], "interpret": ["interpret@3.1.1", "", {}, "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ=="], "ip-address": ["ip-address@10.1.0", "", {}, "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q=="], "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], "is-absolute": ["is-absolute@1.0.0", "", { "dependencies": { "is-relative": "^1.0.0", "is-windows": "^1.0.1" } }, "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA=="], "is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="], "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="], "is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="], "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], "is-module": ["is-module@1.0.0", "", {}, "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g=="], "is-negated-glob": ["is-negated-glob@1.0.0", "", {}, "sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug=="], "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], "is-obj": ["is-obj@2.0.0", "", {}, "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w=="], "is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="], "is-plain-object": ["is-plain-object@5.0.0", "", {}, "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="], "is-promise": ["is-promise@2.2.2", "", {}, "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="], "is-reference": ["is-reference@1.2.1", "", { "dependencies": { "@types/estree": "*" } }, "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ=="], "is-relative": ["is-relative@1.0.0", "", { "dependencies": { "is-unc-path": "^1.0.0" } }, "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA=="], "is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="], "is-unc-path": ["is-unc-path@1.0.0", "", { "dependencies": { "unc-path-regex": "^0.1.2" } }, "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ=="], "is-valid-glob": ["is-valid-glob@1.0.0", "", {}, "sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA=="], "is-windows": ["is-windows@1.0.2", "", {}, "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA=="], "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], "isobject": ["isobject@3.0.1", "", {}, "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg=="], "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], "json-parse-even-better-errors": ["json-parse-even-better-errors@5.0.0", "", {}, "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ=="], "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], "jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], "jsonparse": ["jsonparse@1.3.1", "", {}, "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg=="], "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], "last-run": ["last-run@2.0.0", "", {}, "sha512-j+y6WhTLN4Itnf9j5ZQos1BGPCS8DAwmgMroR3OzfxAsBxam0hMw7J8M3KqZl0pLQJ1jNnwIexg5DYpC/ctwEQ=="], "lead": ["lead@4.0.0", "", {}, "sha512-DpMa59o5uGUWWjruMp71e6knmwKU3jRBBn1kjuLWN9EeIOxNeSAwvHf03WIl8g/ZMR2oSQC9ej3yeLBwdDc/pg=="], "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], "liftoff": ["liftoff@5.0.1", "", { "dependencies": { "extend": "^3.0.2", "findup-sync": "^5.0.0", "fined": "^2.0.0", "flagged-respawn": "^2.0.0", "is-plain-object": "^5.0.0", "rechoir": "^0.8.0", "resolve": "^1.20.0" } }, "sha512-wwLXMbuxSF8gMvubFcFRp56lkFV69twvbU5vDPbaw+Q+/rF8j0HKjGbIdlSi+LuJm9jf7k9PB+nTxnsLMPcv2Q=="], "lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="], "lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="], "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="], "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="], "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.32.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig=="], "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw=="], "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ=="], "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg=="], "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA=="], "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg=="], "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.32.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw=="], "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="], "limiter": ["limiter@1.1.5", "", {}, "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA=="], "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], "lint-staged": ["lint-staged@16.4.0", "", { "dependencies": { "commander": "^14.0.3", "listr2": "^9.0.5", "picomatch": "^4.0.3", "string-argv": "^0.3.2", "tinyexec": "^1.0.4", "yaml": "^2.8.2" }, "bin": { "lint-staged": "bin/lint-staged.js" } }, "sha512-lBWt8hujh/Cjysw5GYVmZpFHXDCgZzhrOm8vbcUdobADZNOK/bRshr2kM3DfgrrtR1DQhfupW9gnIXOfiFi+bw=="], "listr2": ["listr2@9.0.5", "", { "dependencies": { "cli-truncate": "^5.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.1.0", "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" } }, "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g=="], "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], "lodash.camelcase": ["lodash.camelcase@4.3.0", "", {}, "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="], "lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="], "lodash.kebabcase": ["lodash.kebabcase@4.1.1", "", {}, "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g=="], "lodash.mergewith": ["lodash.mergewith@4.6.2", "", {}, "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ=="], "lodash.snakecase": ["lodash.snakecase@4.1.1", "", {}, "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw=="], "lodash.startcase": ["lodash.startcase@4.4.0", "", {}, "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg=="], "lodash.upperfirst": ["lodash.upperfirst@4.3.1", "", {}, "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg=="], "log-update": ["log-update@6.1.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "cli-cursor": "^5.0.0", "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w=="], "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], "lru-queue": ["lru-queue@0.1.0", "", { "dependencies": { "es5-ext": "~0.10.2" } }, "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ=="], "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], "make-fetch-happen": ["make-fetch-happen@15.0.5", "", { "dependencies": { "@gar/promise-retry": "^1.0.0", "@npmcli/agent": "^4.0.0", "@npmcli/redact": "^4.0.0", "cacache": "^20.0.1", "http-cache-semantics": "^4.1.1", "minipass": "^7.0.2", "minipass-fetch": "^5.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^1.0.0", "proc-log": "^6.0.0", "ssri": "^13.0.0" } }, "sha512-uCbIa8jWWmQZt4dSnEStkVC6gdakiinAm4PiGsywIkguF0eWMdcjDz0ECYhUolFU3pFLOev9VNPCEygydXnddg=="], "map-cache": ["map-cache@0.2.2", "", {}, "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg=="], "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], "maxmin": ["maxmin@2.1.0", "", { "dependencies": { "chalk": "^1.0.0", "figures": "^1.0.1", "gzip-size": "^3.0.0", "pretty-bytes": "^3.0.0" } }, "sha512-NWlApBjW9az9qRPaeg7CX4sQBWwytqz32bIEo1PW9pRW+kBP9KLRfJO3UC+TV31EcQZEUq7eMzikC7zt3zPJcw=="], "media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="], "memoizee": ["memoizee@0.4.17", "", { "dependencies": { "d": "^1.0.2", "es5-ext": "^0.10.64", "es6-weak-map": "^2.0.3", "event-emitter": "^0.3.5", "is-promise": "^2.2.2", "lru-queue": "^0.1.0", "next-tick": "^1.1.0", "timers-ext": "^0.1.7" } }, "sha512-DGqD7Hjpi/1or4F/aYAspXKNm5Yili0QDAFAY4QYvpqpgiY6+1jOfqpmByzjxbWd/T9mChbCArXAbDAsTm5oXA=="], "meow": ["meow@13.2.0", "", {}, "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA=="], "merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="], "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], "mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], "mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="], "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="], "minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="], "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], "minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], "minipass-collect": ["minipass-collect@2.0.1", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw=="], "minipass-fetch": ["minipass-fetch@5.0.2", "", { "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^2.0.0", "minizlib": "^3.0.1" }, "optionalDependencies": { "iconv-lite": "^0.7.2" } }, "sha512-2d0q2a8eCi2IRg/IGubCNRJoYbA1+YPXAzQVRFmB45gdGZafyivnZ5YSEfo3JikbjGxOdntGFvBQGqaSMXlAFQ=="], "minipass-flush": ["minipass-flush@1.0.7", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA=="], "minipass-pipeline": ["minipass-pipeline@1.2.4", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A=="], "minipass-sized": ["minipass-sized@2.0.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-zSsHhto5BcUVM2m1LurnXY6M//cGhVaegT71OfOXoprxT6o780GZd792ea6FfrQkuU4usHZIUczAQMRUE2plzA=="], "minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="], "mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="], "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], "multer": ["multer@2.1.1", "", { "dependencies": { "append-field": "^1.0.0", "busboy": "^1.6.0", "concat-stream": "^2.0.0", "type-is": "^1.6.18" } }, "sha512-mo+QTzKlx8R7E5ylSXxWzGoXoZbOsRMpyitcht8By2KHvMbf3tjwosZ/Mu/XYU6UuJ3VZnODIrak5ZrPiPyB6A=="], "mute-stdout": ["mute-stdout@2.0.0", "", {}, "sha512-32GSKM3Wyc8dg/p39lWPKYu8zci9mJFzV1Np9Of0ZEpe6Fhssn/FbI7ywAMd40uX+p3ZKh3T5EeCFv81qS3HmQ=="], "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], "negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], "neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="], "next-tick": ["next-tick@1.1.0", "", {}, "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="], "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], "node-gyp": ["node-gyp@12.2.0", "", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "graceful-fs": "^4.2.6", "make-fetch-happen": "^15.0.0", "nopt": "^9.0.0", "proc-log": "^6.0.0", "semver": "^7.3.5", "tar": "^7.5.4", "tinyglobby": "^0.2.12", "which": "^6.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" } }, "sha512-q23WdzrQv48KozXlr0U1v9dwO/k59NHeSzn6loGcasyf0UnSrtzs8kRxM+mfwJSf0DkX0s43hcqgnSO4/VNthQ=="], "node-releases": ["node-releases@2.0.37", "", {}, "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg=="], "nopt": ["nopt@9.0.0", "", { "dependencies": { "abbrev": "^4.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw=="], "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], "now-and-later": ["now-and-later@3.0.0", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-pGO4pzSdaxhWTGkfSfHx3hVzJVslFPwBp2Myq9MYN/ChfJZF87ochMAXnvz6/58RJSf5ik2q9tXprBBrk2cpcg=="], "npm-bundled": ["npm-bundled@5.0.0", "", { "dependencies": { "npm-normalize-package-bin": "^5.0.0" } }, "sha512-JLSpbzh6UUXIEoqPsYBvVNVmyrjVZ1fzEFbqxKkTJQkWBO3xFzFT+KDnSKQWwOQNbuWRwt5LSD6HOTLGIWzfrw=="], "npm-install-checks": ["npm-install-checks@8.0.0", "", { "dependencies": { "semver": "^7.1.1" } }, "sha512-ScAUdMpyzkbpxoNekQ3tNRdFI8SJ86wgKZSQZdUxT+bj0wVFpsEMWnkXP0twVe1gJyNF5apBWDJhhIbgrIViRA=="], "npm-normalize-package-bin": ["npm-normalize-package-bin@5.0.0", "", {}, "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag=="], "npm-package-arg": ["npm-package-arg@13.0.2", "", { "dependencies": { "hosted-git-info": "^9.0.0", "proc-log": "^6.0.0", "semver": "^7.3.5", "validate-npm-package-name": "^7.0.0" } }, "sha512-IciCE3SY3uE84Ld8WZU23gAPPV9rIYod4F+rc+vJ7h7cwAJt9Vk6TVsK60ry7Uj3SRS3bqRRIGuTp9YVlk6WNA=="], "npm-packlist": ["npm-packlist@10.0.4", "", { "dependencies": { "ignore-walk": "^8.0.0", "proc-log": "^6.0.0" } }, "sha512-uMW73iajD8hiH4ZBxEV3HC+eTnppIqwakjOYuvgddnalIw2lJguKviK1pcUJDlIWm1wSJkchpDZDSVVsZEYRng=="], "npm-pick-manifest": ["npm-pick-manifest@11.0.3", "", { "dependencies": { "npm-install-checks": "^8.0.0", "npm-normalize-package-bin": "^5.0.0", "npm-package-arg": "^13.0.0", "semver": "^7.3.5" } }, "sha512-buzyCfeoGY/PxKqmBqn1IUJrZnUi1VVJTdSSRPGI60tJdUhUoSQFhs0zycJokDdOznQentgrpf8LayEHyyYlqQ=="], "npm-registry-fetch": ["npm-registry-fetch@19.1.1", "", { "dependencies": { "@npmcli/redact": "^4.0.0", "jsonparse": "^1.3.1", "make-fetch-happen": "^15.0.0", "minipass": "^7.0.2", "minipass-fetch": "^5.0.0", "minizlib": "^3.0.1", "npm-package-arg": "^13.0.0", "proc-log": "^6.0.0" } }, "sha512-TakBap6OM1w0H73VZVDf44iFXsOS3h+L4wVMXmbWOQroZgFhMch0juN6XSzBNlD965yIKvWg2dfu7NSiaYLxtw=="], "number-is-nan": ["number-is-nan@1.0.1", "", {}, "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ=="], "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], "object.defaults": ["object.defaults@1.1.0", "", { "dependencies": { "array-each": "^1.0.1", "array-slice": "^1.0.0", "for-own": "^1.0.0", "isobject": "^3.0.0" } }, "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA=="], "object.pick": ["object.pick@1.3.0", "", { "dependencies": { "isobject": "^3.0.1" } }, "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ=="], "obug": ["obug@2.1.1", "", {}, "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ=="], "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="], "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], "onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="], "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], "p-map": ["p-map@7.0.4", "", {}, "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ=="], "pacote": ["pacote@21.5.0", "", { "dependencies": { "@gar/promise-retry": "^1.0.0", "@npmcli/git": "^7.0.0", "@npmcli/installed-package-contents": "^4.0.0", "@npmcli/package-json": "^7.0.0", "@npmcli/promise-spawn": "^9.0.0", "@npmcli/run-script": "^10.0.0", "cacache": "^20.0.0", "fs-minipass": "^3.0.0", "minipass": "^7.0.2", "npm-package-arg": "^13.0.0", "npm-packlist": "^10.0.1", "npm-pick-manifest": "^11.0.1", "npm-registry-fetch": "^19.0.0", "proc-log": "^6.0.0", "sigstore": "^4.0.0", "ssri": "^13.0.0", "tar": "^7.4.3" }, "bin": { "pacote": "bin/index.js" } }, "sha512-VtZ0SB8mb5Tzw3dXDfVAIjhyVKUHZkS/ZH9/5mpKenwC9sFOXNI0JI7kEF7IMkwOnsWMFrvAZHzx1T5fmrp9FQ=="], "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], "parse-filepath": ["parse-filepath@1.0.2", "", { "dependencies": { "is-absolute": "^1.0.0", "map-cache": "^0.2.0", "path-root": "^0.1.1" } }, "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q=="], "parse-github-url": ["parse-github-url@1.0.4", "", { "bin": { "parse-github-url": "cli.js" } }, "sha512-CEtCOt55fHmd6DpBc/N7H5NC4vJpcquhzzs9Iw2mRj8bVxo1O5TQI5MXKOMO7+yBOqD+5dKCCRK4Kj1KskZc6Q=="], "parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], "parse-passwd": ["parse-passwd@1.0.0", "", {}, "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q=="], "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], "path-root": ["path-root@0.1.1", "", { "dependencies": { "path-root-regex": "^0.1.0" } }, "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg=="], "path-root-regex": ["path-root-regex@0.1.2", "", {}, "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ=="], "path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], "path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="], "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], "picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="], "pkijs": ["pkijs@3.4.0", "", { "dependencies": { "@noble/hashes": "1.4.0", "asn1js": "^3.0.6", "bytestreamjs": "^2.0.1", "pvtsutils": "^1.3.6", "pvutils": "^1.1.3", "tslib": "^2.8.1" } }, "sha512-emEcLuomt2j03vxD54giVB4SxTjnsqkU692xZOZXHDVoYyypEm+b3jpiTcc+Cf+myooc+/Ly0z01jqeNHVgJGw=="], "playwright": ["playwright@1.59.1", "", { "dependencies": { "playwright-core": "1.59.1" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw=="], "playwright-core": ["playwright-core@1.59.1", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg=="], "pngjs": ["pngjs@7.0.0", "", {}, "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow=="], "postcss": ["postcss@8.5.8", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg=="], "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], "prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="], "pretty-bytes": ["pretty-bytes@7.1.0", "", {}, "sha512-nODzvTiYVRGRqAOvE84Vk5JDPyyxsVk0/fbA/bq7RqlnhksGpset09XTxbpvLTIjoaF7K8Z8DG8yHtKGTPSYRw=="], "proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="], "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="], "proxy-from-env": ["proxy-from-env@2.1.0", "", {}, "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA=="], "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], "pvtsutils": ["pvtsutils@1.3.6", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg=="], "pvutils": ["pvutils@1.1.5", "", {}, "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA=="], "qs": ["qs@6.15.0", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ=="], "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], "raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="], "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], "rechoir": ["rechoir@0.8.0", "", { "dependencies": { "resolve": "^1.20.0" } }, "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ=="], "reflect-metadata": ["reflect-metadata@0.2.2", "", {}, "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q=="], "regenerate": ["regenerate@1.4.2", "", {}, "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A=="], "regenerate-unicode-properties": ["regenerate-unicode-properties@10.2.2", "", { "dependencies": { "regenerate": "^1.4.2" } }, "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g=="], "regexpu-core": ["regexpu-core@6.4.0", "", { "dependencies": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.2.2", "regjsgen": "^0.8.0", "regjsparser": "^0.13.0", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.2.1" } }, "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA=="], "regjsgen": ["regjsgen@0.8.0", "", {}, "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q=="], "regjsparser": ["regjsparser@0.13.1", "", { "dependencies": { "jsesc": "~3.1.0" }, "bin": { "regjsparser": "bin/parser" } }, "sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw=="], "remove-trailing-separator": ["remove-trailing-separator@1.1.0", "", {}, "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw=="], "replace-ext": ["replace-ext@2.0.0", "", {}, "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug=="], "replace-homedir": ["replace-homedir@2.0.0", "", {}, "sha512-bgEuQQ/BHW0XkkJtawzrfzHFSN70f/3cNOiHa2QsYxqrjaC30X1k74FJ6xswVBP0sr0SpGIdVFuPwfrYziVeyw=="], "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], "resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="], "resolve-dir": ["resolve-dir@1.0.1", "", { "dependencies": { "expand-tilde": "^2.0.0", "global-modules": "^1.0.0" } }, "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg=="], "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="], "resolve-options": ["resolve-options@2.0.0", "", { "dependencies": { "value-or-function": "^4.0.0" } }, "sha512-/FopbmmFOQCfsCx77BRFdKOniglTiHumLgwvd6IDPihy1GKkadZbgQJBcTb2lMzSR1pndzd96b1nZrreZ7+9/A=="], "restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="], "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], "rolldown": ["rolldown@1.0.0-rc.12", "", { "dependencies": { "@oxc-project/types": "=0.122.0", "@rolldown/pluginutils": "1.0.0-rc.12" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.12", "@rolldown/binding-darwin-arm64": "1.0.0-rc.12", "@rolldown/binding-darwin-x64": "1.0.0-rc.12", "@rolldown/binding-freebsd-x64": "1.0.0-rc.12", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.12", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.12", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.12", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.12", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.12", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.12", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.12", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.12", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.12", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.12", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.12" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-yP4USLIMYrwpPHEFB5JGH1uxhcslv6/hL0OyvTuY+3qlOSJvZ7ntYnoWpehBxufkgN0cvXxppuTu5hHa/zPh+A=="], "rollup": ["rollup@4.60.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.60.1", "@rollup/rollup-android-arm64": "4.60.1", "@rollup/rollup-darwin-arm64": "4.60.1", "@rollup/rollup-darwin-x64": "4.60.1", "@rollup/rollup-freebsd-arm64": "4.60.1", "@rollup/rollup-freebsd-x64": "4.60.1", "@rollup/rollup-linux-arm-gnueabihf": "4.60.1", "@rollup/rollup-linux-arm-musleabihf": "4.60.1", "@rollup/rollup-linux-arm64-gnu": "4.60.1", "@rollup/rollup-linux-arm64-musl": "4.60.1", "@rollup/rollup-linux-loong64-gnu": "4.60.1", "@rollup/rollup-linux-loong64-musl": "4.60.1", "@rollup/rollup-linux-ppc64-gnu": "4.60.1", "@rollup/rollup-linux-ppc64-musl": "4.60.1", "@rollup/rollup-linux-riscv64-gnu": "4.60.1", "@rollup/rollup-linux-riscv64-musl": "4.60.1", "@rollup/rollup-linux-s390x-gnu": "4.60.1", "@rollup/rollup-linux-x64-gnu": "4.60.1", "@rollup/rollup-linux-x64-musl": "4.60.1", "@rollup/rollup-openbsd-x64": "4.60.1", "@rollup/rollup-openharmony-arm64": "4.60.1", "@rollup/rollup-win32-arm64-msvc": "4.60.1", "@rollup/rollup-win32-ia32-msvc": "4.60.1", "@rollup/rollup-win32-x64-gnu": "4.60.1", "@rollup/rollup-win32-x64-msvc": "4.60.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w=="], "rollup-plugin-bundle-size": ["rollup-plugin-bundle-size@1.0.3", "", { "dependencies": { "chalk": "^1.1.3", "maxmin": "^2.1.0" } }, "sha512-aWj0Pvzq90fqbI5vN1IvUrlf4utOqy+AERYxwWjegH1G8PzheMnrRIgQ5tkwKVtQMDP0bHZEACW/zLDF+XgfXQ=="], "router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="], "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], "selfsigned": ["selfsigned@5.5.0", "", { "dependencies": { "@peculiar/x509": "^1.14.2", "pkijs": "^3.3.3" } }, "sha512-ftnu3TW4+3eBfLRFnDEkzGxSF/10BJBkaLJuBHZX0kiPS7bRdlpZGu6YGt4KngMkdTwJE6MbjavFpqHvqVt+Ew=="], "semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], "semver-greatest-satisfied-range": ["semver-greatest-satisfied-range@2.0.0", "", { "dependencies": { "sver": "^1.8.3" } }, "sha512-lH3f6kMbwyANB7HuOWRMlLCa2itaCrZJ+SAqqkSZrZKO/cAsk2EOyaKHUtNkVLFyFW9pct22SFesFp3Z7zpA0g=="], "send": ["send@1.2.1", "", { "dependencies": { "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.1", "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.2" } }, "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ=="], "serialize-javascript": ["serialize-javascript@7.0.5", "", {}, "sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw=="], "serve-static": ["serve-static@2.2.1", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw=="], "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="], "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="], "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], "sigstore": ["sigstore@4.1.0", "", { "dependencies": { "@sigstore/bundle": "^4.0.0", "@sigstore/core": "^3.1.0", "@sigstore/protobuf-specs": "^0.5.0", "@sigstore/sign": "^4.1.0", "@sigstore/tuf": "^4.0.1", "@sigstore/verify": "^3.1.0" } }, "sha512-/fUgUhYghuLzVT/gaJoeVehLCgZiUxPCPMcyVNY0lIf/cTCz58K/WTI7PefDarXxp9nUKpEwg1yyz3eSBMTtgA=="], "sirv": ["sirv@3.0.2", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g=="], "slice-ansi": ["slice-ansi@8.0.0", "", { "dependencies": { "ansi-styles": "^6.2.3", "is-fullwidth-code-point": "^5.1.0" } }, "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg=="], "smart-buffer": ["smart-buffer@4.2.0", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="], "smob": ["smob@1.6.1", "", {}, "sha512-KAkBqZl3c2GvNgNhcoyJae1aKldDW0LO279wF9bk1PnluRTETKBq0WyzRXxEhoQLk56yHaOY4JCBEKDuJIET5g=="], "socks": ["socks@2.8.7", "", { "dependencies": { "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" } }, "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A=="], "socks-proxy-agent": ["socks-proxy-agent@8.0.5", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" } }, "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw=="], "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="], "sparkles": ["sparkles@2.1.0", "", {}, "sha512-r7iW1bDw8R/cFifrD3JnQJX0K1jqT0kprL48BiBpLZLJPmAm34zsVBsK5lc7HirZYZqMW65dOXZgbAGt/I6frg=="], "spdx-exceptions": ["spdx-exceptions@2.5.0", "", {}, "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="], "spdx-expression-parse": ["spdx-expression-parse@4.0.0", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ=="], "spdx-license-ids": ["spdx-license-ids@3.0.23", "", {}, "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw=="], "ssri": ["ssri@13.0.1", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-QUiRf1+u9wPTL/76GTYlKttDEBWV1ga9ZXW8BG6kfdeyyM8LGPix9gROyg9V2+P0xNyF3X2Go526xKFdMZrHSQ=="], "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="], "statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], "std-env": ["std-env@4.0.0", "", {}, "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ=="], "stream-composer": ["stream-composer@1.0.2", "", { "dependencies": { "streamx": "^2.13.2" } }, "sha512-bnBselmwfX5K10AH6L4c8+S5lgZMWI7ZYrz2rvYjCPB2DIMC4Ig8OpxGpNJSxRZ58oti7y1IcNvjBAz9vW5m4w=="], "stream-exhaust": ["stream-exhaust@1.0.2", "", {}, "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw=="], "stream-throttle": ["stream-throttle@0.1.3", "", { "dependencies": { "commander": "^2.2.0", "limiter": "^1.0.5" }, "bin": { "throttleproxy": "./bin/throttleproxy.js" } }, "sha512-889+B9vN9dq7/vLbGyuHeZ6/ctf5sNuGWsDy89uNxkFTAgzy0eK7+w5fL3KLNRTkLle7EgZGvHUphZW0Q26MnQ=="], "streamsearch": ["streamsearch@1.1.0", "", {}, "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg=="], "streamx": ["streamx@2.25.0", "", { "dependencies": { "events-universal": "^1.0.0", "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" } }, "sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg=="], "string-argv": ["string-argv@0.3.2", "", {}, "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q=="], "string-replace-async": ["string-replace-async@3.0.2", "", {}, "sha512-s6hDtXJ7FKyRap/amefqrOMpkEQvxUDueyvJygQeHxCK5Za90dOMgdibCCrPdfdAYAkr8imrZ1PPXW7DOf0RzQ=="], "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], "strip-ansi": ["strip-ansi@3.0.1", "", { "dependencies": { "ansi-regex": "^2.0.0" } }, "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg=="], "supports-color": ["supports-color@2.0.0", "", {}, "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g=="], "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], "sver": ["sver@1.8.4", "", { "optionalDependencies": { "semver": "^6.3.0" } }, "sha512-71o1zfzyawLfIWBOmw8brleKyvnbn73oVHNCsu51uPMz/HWiKkkXsI31JjHW5zqXEqnPYkIiHd8ZmL7FCimLEA=="], "tar": ["tar@7.5.13", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-tOG/7GyXpFevhXVh8jOPJrmtRpOTsYqUIkVdVooZYJS/z8WhfQUX8RJILmeuJNinGAMSu1veBr4asSHFt5/hng=="], "tar-stream": ["tar-stream@3.1.8", "", { "dependencies": { "b4a": "^1.6.4", "bare-fs": "^4.5.5", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-U6QpVRyCGHva435KoNWy9PRoi2IFYCgtEhq9nmrPPpbRacPs9IH4aJ3gbrFC8dPcXvdSZ4XXfXT5Fshbp2MtlQ=="], "teex": ["teex@1.0.1", "", { "dependencies": { "streamx": "^2.12.5" } }, "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg=="], "terser": ["terser@5.46.1", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-vzCjQO/rgUuK9sf8VJZvjqiqiHFaZLnOiimmUuOKODxWL8mm/xua7viT7aqX7dgPY60otQjUotzFMmCB4VdmqQ=="], "text-decoder": ["text-decoder@1.2.7", "", { "dependencies": { "b4a": "^1.6.4" } }, "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ=="], "timers-ext": ["timers-ext@0.1.8", "", { "dependencies": { "es5-ext": "^0.10.64", "next-tick": "^1.1.0" } }, "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww=="], "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], "tinyexec": ["tinyexec@1.0.4", "", {}, "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw=="], "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], "tinyrainbow": ["tinyrainbow@3.1.0", "", {}, "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw=="], "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], "to-through": ["to-through@3.0.0", "", { "dependencies": { "streamx": "^2.12.5" } }, "sha512-y8MN937s/HVhEoBU1SxfHC+wxCHkV1a9gW8eAdTadYh/bGyesZIVcbjI+mSpFbSVwQici/XjBjuUyri1dnXwBw=="], "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], "totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="], "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "tsyringe": ["tsyringe@4.10.0", "", { "dependencies": { "tslib": "^1.9.3" } }, "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw=="], "tuf-js": ["tuf-js@4.1.0", "", { "dependencies": { "@tufjs/models": "4.1.0", "debug": "^4.4.3", "make-fetch-happen": "^15.0.1" } }, "sha512-50QV99kCKH5P/Vs4E2Gzp7BopNV+KzTXqWeaxrfu5IQJBOULRsTIS9seSsOVT8ZnGXzCyx55nYWAi4qJzpZKEQ=="], "type": ["type@2.7.3", "", {}, "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ=="], "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], "type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="], "typedarray": ["typedarray@0.0.6", "", {}, "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="], "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], "uglify-js": ["uglify-js@3.19.3", "", { "bin": { "uglifyjs": "bin/uglifyjs" } }, "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ=="], "unc-path-regex": ["unc-path-regex@0.1.2", "", {}, "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg=="], "undertaker": ["undertaker@2.0.0", "", { "dependencies": { "bach": "^2.0.1", "fast-levenshtein": "^3.0.0", "last-run": "^2.0.0", "undertaker-registry": "^2.0.0" } }, "sha512-tO/bf30wBbTsJ7go80j0RzA2rcwX6o7XPBpeFcb+jzoeb4pfMM2zUeSDIkY1AWqeZabWxaQZ/h8N9t35QKDLPQ=="], "undertaker-registry": ["undertaker-registry@2.0.0", "", {}, "sha512-+hhVICbnp+rlzZMgxXenpvTxpuvA67Bfgtt+O9WOE5jo7w/dyiF1VmoZVIHvP2EkUjsyKyTwYKlLhA+j47m1Ew=="], "undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], "unicode-canonical-property-names-ecmascript": ["unicode-canonical-property-names-ecmascript@2.0.1", "", {}, "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg=="], "unicode-match-property-ecmascript": ["unicode-match-property-ecmascript@2.0.0", "", { "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" } }, "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q=="], "unicode-match-property-value-ecmascript": ["unicode-match-property-value-ecmascript@2.2.1", "", {}, "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg=="], "unicode-property-aliases-ecmascript": ["unicode-property-aliases-ecmascript@2.2.0", "", {}, "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ=="], "universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], "v8flags": ["v8flags@4.0.1", "", {}, "sha512-fcRLaS4H/hrZk9hYwbdRM35D0U8IYMfEClhXxCivOojl+yTRAZH3Zy2sSy6qVCiGbV9YAtPssP6jaChqC9vPCg=="], "validate-npm-package-name": ["validate-npm-package-name@7.0.2", "", {}, "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A=="], "value-or-function": ["value-or-function@4.0.0", "", {}, "sha512-aeVK81SIuT6aMJfNo9Vte8Dw0/FZINGBV8BfCraGtqVxIeLAEhJyoWs8SmvRVmXfGss2PmmOwZCuBPbZR+IYWg=="], "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], "vinyl": ["vinyl@3.0.1", "", { "dependencies": { "clone": "^2.1.2", "remove-trailing-separator": "^1.1.0", "replace-ext": "^2.0.0", "teex": "^1.0.1" } }, "sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA=="], "vinyl-contents": ["vinyl-contents@2.0.0", "", { "dependencies": { "bl": "^5.0.0", "vinyl": "^3.0.0" } }, "sha512-cHq6NnGyi2pZ7xwdHSW1v4Jfnho4TEGtxZHw01cmnc8+i7jgR6bRnED/LbrKan/Q7CvVLbnvA5OepnhbpjBZ5Q=="], "vinyl-fs": ["vinyl-fs@4.0.2", "", { "dependencies": { "fs-mkdirp-stream": "^2.0.1", "glob-stream": "^8.0.3", "graceful-fs": "^4.2.11", "iconv-lite": "^0.6.3", "is-valid-glob": "^1.0.0", "lead": "^4.0.0", "normalize-path": "3.0.0", "resolve-options": "^2.0.0", "stream-composer": "^1.0.2", "streamx": "^2.14.0", "to-through": "^3.0.0", "value-or-function": "^4.0.0", "vinyl": "^3.0.1", "vinyl-sourcemap": "^2.0.0" } }, "sha512-XRFwBLLTl8lRAOYiBqxY279wY46tVxLaRhSwo3GzKEuLz1giffsOquWWboD/haGf5lx+JyTigCFfe7DWHoARIA=="], "vinyl-sourcemap": ["vinyl-sourcemap@2.0.0", "", { "dependencies": { "convert-source-map": "^2.0.0", "graceful-fs": "^4.2.10", "now-and-later": "^3.0.0", "streamx": "^2.12.5", "vinyl": "^3.0.0", "vinyl-contents": "^2.0.0" } }, "sha512-BAEvWxbBUXvlNoFQVFVHpybBbjW1r03WhohJzJDSfgrrK5xVYIDTan6xN14DlyImShgDRv2gl9qhM6irVMsV0Q=="], "vite": ["vite@8.0.3", "", { "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.8", "rolldown": "1.0.0-rc.12", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-B9ifbFudT1TFhfltfaIPgjo9Z3mDynBTJSUYxTjOQruf/zHH+ezCQKcoqO+h7a9Pw9Nm/OtlXAiGT1axBgwqrQ=="], "vitest": ["vitest@4.1.2", "", { "dependencies": { "@vitest/expect": "4.1.2", "@vitest/mocker": "4.1.2", "@vitest/pretty-format": "4.1.2", "@vitest/runner": "4.1.2", "@vitest/snapshot": "4.1.2", "@vitest/spy": "4.1.2", "@vitest/utils": "4.1.2", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.2", "@vitest/browser-preview": "4.1.2", "@vitest/browser-webdriverio": "4.1.2", "@vitest/ui": "4.1.2", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-xjR1dMTVHlFLh98JE3i/f/WePqJsah4A0FK9cc8Ehp9Udk0AZk6ccpIZhh1qJ/yxVWRZ+Q54ocnD8TXmkhspGg=="], "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="], "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], "wordwrap": ["wordwrap@1.0.0", "", {}, "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="], "wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="], "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], "ws": ["ws@8.20.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA=="], "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], "yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="], "yaml": ["yaml@2.8.3", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg=="], "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], "@commitlint/config-validator/ajv": ["ajv@8.18.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A=="], "@commitlint/is-ignored/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], "@conventional-changelog/git-client/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], "@npmcli/agent/lru-cache": ["lru-cache@11.2.7", "", {}, "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA=="], "@npmcli/fs/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], "@npmcli/git/lru-cache": ["lru-cache@11.2.7", "", {}, "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA=="], "@npmcli/git/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], "@npmcli/git/which": ["which@6.0.1", "", { "dependencies": { "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg=="], "@npmcli/package-json/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], "@npmcli/promise-spawn/which": ["which@6.0.1", "", { "dependencies": { "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg=="], "@vitest/mocker/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], "anymatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], "auto-changelog/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], "cacache/lru-cache": ["lru-cache@11.2.7", "", {}, "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA=="], "chokidar/fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], "chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "cli-truncate/string-width": ["string-width@8.2.0", "", { "dependencies": { "get-east-asian-width": "^1.5.0", "strip-ansi": "^7.1.2" } }, "sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw=="], "cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], "figures/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], "form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], "global-directory/ini": ["ini@4.1.1", "", {}, "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g=="], "global-prefix/ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="], "global-prefix/which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "which": "./bin/which" } }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="], "gulp-cli/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "gulp-cli/yargs": ["yargs@16.2.0", "", { "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" } }, "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw=="], "hosted-git-info/lru-cache": ["lru-cache@11.2.7", "", {}, "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA=="], "import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], "lint-staged/commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="], "log-update/slice-ansi": ["slice-ansi@7.1.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w=="], "log-update/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], "lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], "maxmin/chalk": ["chalk@1.1.3", "", { "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", "has-ansi": "^2.0.0", "strip-ansi": "^3.0.0", "supports-color": "^2.0.0" } }, "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A=="], "maxmin/pretty-bytes": ["pretty-bytes@3.0.1", "", { "dependencies": { "number-is-nan": "^1.0.0" } }, "sha512-eb7ZAeUTgfh294cElcu51w+OTRp/6ItW758LjwJSK72LDevcuJn0P4eD71PLMDGPwwatXmAmYHTkzvpKlJE3ow=="], "micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], "minipass-flush/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], "minipass-pipeline/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], "multer/type-is": ["type-is@1.6.18", "", { "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" } }, "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g=="], "node-gyp/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], "node-gyp/which": ["which@6.0.1", "", { "dependencies": { "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg=="], "npm-install-checks/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], "npm-package-arg/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], "npm-pick-manifest/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], "parse-json/json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], "path-scurry/lru-cache": ["lru-cache@11.2.7", "", {}, "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA=="], "readdirp/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], "rollup/fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], "rollup-plugin-bundle-size/chalk": ["chalk@1.1.3", "", { "dependencies": { "ansi-styles": "^2.2.1", "escape-string-regexp": "^1.0.2", "has-ansi": "^2.0.0", "strip-ansi": "^3.0.0", "supports-color": "^2.0.0" } }, "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A=="], "router/is-promise": ["is-promise@4.0.0", "", {}, "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="], "slice-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], "slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@5.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.1" } }, "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ=="], "stream-throttle/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], "string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], "tsyringe/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="], "undertaker/fast-levenshtein": ["fast-levenshtein@3.0.0", "", { "dependencies": { "fastest-levenshtein": "^1.0.7" } }, "sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ=="], "vinyl-fs/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], "vite/fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], "wrap-ansi/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], "wrap-ansi/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], "@commitlint/config-validator/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], "@npmcli/git/which/isexe": ["isexe@4.0.0", "", {}, "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw=="], "@npmcli/promise-spawn/which/isexe": ["isexe@4.0.0", "", {}, "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw=="], "cli-truncate/string-width/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], "cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "cliui/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], "gulp-cli/chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "gulp-cli/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], "gulp-cli/yargs/cliui": ["cliui@7.0.4", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="], "gulp-cli/yargs/yargs-parser": ["yargs-parser@20.2.9", "", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="], "log-update/slice-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], "log-update/slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@5.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.1" } }, "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ=="], "log-update/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], "maxmin/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], "minipass-flush/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], "minipass-pipeline/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], "multer/type-is/media-typer": ["media-typer@0.3.0", "", {}, "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="], "multer/type-is/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], "node-gyp/which/isexe": ["isexe@4.0.0", "", {}, "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw=="], "rollup-plugin-bundle-size/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], "string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "wrap-ansi/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], "cli-truncate/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], "gulp-cli/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "gulp-cli/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], "multer/type-is/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], "gulp-cli/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "gulp-cli/yargs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], } } axios-axios-2d06f96/tests/smoke/bun/package.json000066400000000000000000000002711521272452000216520ustar00rootroot00000000000000{ "name": "@axios/bun-smoke-tests", "type": "module", "private": true, "devDependencies": { "@types/bun": "latest" }, "peerDependencies": { "typescript": "^5" } } axios-axios-2d06f96/tests/smoke/bun/tests/000077500000000000000000000000001521272452000205265ustar00rootroot00000000000000axios-axios-2d06f96/tests/smoke/bun/tests/cancel.smoke.test.ts000066400000000000000000000041661521272452000244250ustar00rootroot00000000000000import { describe, expect, test } from 'bun:test'; import axios from 'axios'; const env = (fetch: typeof globalThis.fetch) => ({ fetch, Request, Response, }); describe('cancellation', () => { test('pre-aborted AbortController cancels before fetch is called', async () => { let fetchCallCount = 0; const fetch = async () => { fetchCallCount += 1; return new Response(JSON.stringify({ ok: true }), { status: 200, headers: { 'Content-Type': 'application/json' }, }); }; const controller = new AbortController(); controller.abort(); const err = await axios .get('https://example.com/cancel', { adapter: 'fetch', signal: controller.signal, env: env(fetch), }) .catch((e: any) => e); expect(axios.isCancel(err)).toBe(true); expect(err.code).toBe('ERR_CANCELED'); expect(fetchCallCount).toBe(0); }); test('in-flight AbortController abort cancels the request', async () => { const fetch = (_input: unknown, init?: RequestInit) => new Promise((_resolve, reject) => { const abortError = () => reject(new DOMException('The operation was aborted', 'AbortError')); const timeout = setTimeout(abortError, 20); if (init?.signal) { if (init.signal.aborted) { clearTimeout(timeout); abortError(); return; } init.signal.addEventListener( 'abort', () => { clearTimeout(timeout); abortError(); }, { once: true } ); } }); const controller = new AbortController(); const request = axios.get('https://example.com/in-flight', { adapter: 'fetch', signal: controller.signal, env: env(fetch), }); controller.abort(); const err = await request.catch((e: any) => e); expect(axios.isCancel(err)).toBe(true); expect(err.code).toBe('ERR_CANCELED'); }); test('axios.isCancel returns false for a plain Error', () => { expect(axios.isCancel(new Error('random'))).toBe(false); }); }); axios-axios-2d06f96/tests/smoke/bun/tests/error.smoke.test.ts000066400000000000000000000015701521272452000243250ustar00rootroot00000000000000import { describe, expect, test } from 'bun:test'; import axios from 'axios'; const env = (fetch: typeof globalThis.fetch) => ({ fetch, Request, Response, }); describe('errors', () => { test('non-2xx response rejects with AxiosError and status 404', async () => { const fetch = async () => new Response(JSON.stringify({ error: 'missing' }), { status: 404, statusText: 'Not Found', headers: { 'Content-Type': 'application/json' }, }); const err = await axios .get('https://example.com/missing', { adapter: 'fetch', env: env(fetch), }) .catch((e: any) => e); expect(axios.isAxiosError(err)).toBe(true); expect(err.response.status).toBe(404); }); test('axios.isAxiosError returns false for a plain Error', () => { expect(axios.isAxiosError(new Error('plain'))).toBe(false); }); }); axios-axios-2d06f96/tests/smoke/bun/tests/fetch.smoke.test.ts000066400000000000000000000064161521272452000242710ustar00rootroot00000000000000import { describe, expect, test } from 'bun:test'; import axios from 'axios'; const createFetchMock = ( responseFactory?: (input: unknown, init: RequestInit) => Response | Promise ) => { const calls: Array<{ input: unknown; init: RequestInit }> = []; const mockFetch = async (input: unknown, init: RequestInit = {}) => { calls.push({ input, init }); if (responseFactory) { return responseFactory(input, init); } return new Response(JSON.stringify({ ok: true }), { status: 200, headers: { 'Content-Type': 'application/json' }, }); }; return { mockFetch, getCalls: () => calls, }; }; const getRequestMeta = async (input: unknown, init: RequestInit = {}) => { const request = input instanceof Request ? input : new Request(input as string, init); return { url: request.url, method: request.method, body: request.method === 'GET' || request.method === 'HEAD' ? undefined : await request.clone().text(), }; }; const env = (fetch: typeof globalThis.fetch) => ({ fetch, Request, Response, }); describe('fetch adapter', () => { test('GET resolves JSON response via fetch adapter', async () => { const { mockFetch, getCalls } = createFetchMock(); const response = await axios.get('https://example.com/users', { adapter: 'fetch', env: env(mockFetch), }); expect(response.status).toBe(200); expect(response.data).toEqual({ ok: true }); expect(getCalls()).toHaveLength(1); }); test('POST serializes JSON body via fetch adapter', async () => { const { mockFetch, getCalls } = createFetchMock(); await axios.post( 'https://example.com/items', { name: 'widget' }, { adapter: 'fetch', env: env(mockFetch), } ); const { input, init } = getCalls()[0]; const meta = await getRequestMeta(input, init); expect(meta.body).toBe(JSON.stringify({ name: 'widget' })); }); test('HTTP methods are forwarded correctly', async () => { const run = async ( method: 'delete' | 'head' | 'options' | 'put' | 'patch', expected: string ) => { const { mockFetch, getCalls } = createFetchMock(); if (method === 'put' || method === 'patch') { await axios[method]( 'https://example.com/items', { name: 'widget' }, { adapter: 'fetch', env: env(mockFetch), } ); } else { await axios[method]('https://example.com/items', { adapter: 'fetch', env: env(mockFetch), }); } const { input, init } = getCalls()[0]; const meta = await getRequestMeta(input, init); expect(meta.method).toBe(expected); }; await run('delete', 'DELETE'); await run('head', 'HEAD'); await run('options', 'OPTIONS'); await run('put', 'PUT'); await run('patch', 'PATCH'); }); test('full URL is preserved in the fetch request', async () => { const { mockFetch, getCalls } = createFetchMock(); await axios.get('https://example.com/users', { adapter: 'fetch', env: env(mockFetch), }); const { input, init } = getCalls()[0]; const meta = await getRequestMeta(input, init); expect(meta.url).toBe('https://example.com/users'); }); }); axios-axios-2d06f96/tests/smoke/bun/tests/formData.smoke.test.ts000066400000000000000000000070421521272452000247310ustar00rootroot00000000000000import { describe, expect, test } from 'bun:test'; import { PassThrough, Writable } from 'node:stream'; import FormDataPackage from 'form-data'; import axios from 'axios'; const createTransportMock = ( responseFactory?: (body: Buffer, options: Record) => Record ) => { const transport = { request(options: Record, onResponse: (res: PassThrough) => void) { const chunks: Buffer[] = []; const req = new Writable({ write(chunk, _encoding, callback) { chunks.push(Buffer.from(chunk)); callback(); }, }) as Writable & Record; req.destroyed = false; req.setTimeout = () => {}; req.write = req.write.bind(req); req.destroy = () => { req.destroyed = true; return req; }; req.close = req.destroy; const originalEnd = req.end.bind(req); req.end = (...args: unknown[]) => { originalEnd(...(args as Parameters)); const body = Buffer.concat(chunks); const response = responseFactory ? responseFactory(body, options) : {}; const res = new PassThrough() as PassThrough & Record; res.statusCode = response.statusCode ?? 200; res.statusMessage = response.statusMessage ?? 'OK'; res.headers = response.headers ?? { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end(response.body ?? JSON.stringify({ ok: true })); return req; }; return req; }, }; return { transport }; }; const bodyAsUtf8 = (value: unknown) => { return Buffer.isBuffer(value) ? value.toString('utf8') : String(value); }; describe('form data', () => { test('native Bun FormData body produces multipart/form-data content-type', async () => { const form = new FormData(); form.append('username', 'janedoe'); form.append('role', 'admin'); const { transport } = createTransportMock((body, options) => ({ body: JSON.stringify({ contentType: options.headers && (options.headers['Content-Type'] || options.headers['content-type']), payload: bodyAsUtf8(body), }), })); const response = await axios.post('http://example.com/form', form, { adapter: 'http', proxy: false, transport, }); expect(response.data.contentType).toContain('multipart/form-data'); expect(response.data.payload).toContain('name="username"'); expect(response.data.payload).toContain('janedoe'); expect(response.data.payload).toContain('name="role"'); expect(response.data.payload).toContain('admin'); }); test('npm form-data package instance is serialized correctly', async () => { const form = new FormDataPackage(); form.append('project', 'axios'); form.append('mode', 'compat'); const { transport } = createTransportMock((body, options) => ({ body: JSON.stringify({ contentType: options.headers && (options.headers['Content-Type'] || options.headers['content-type']), payload: bodyAsUtf8(body), }), })); const response = await axios.post('http://example.com/npm-form-data', form as any, { adapter: 'http', proxy: false, transport, }); expect(response.data.contentType).toContain('multipart/form-data'); expect(response.data.payload).toContain('name="project"'); expect(response.data.payload).toContain('axios'); expect(response.data.payload).toContain('name="mode"'); expect(response.data.payload).toContain('compat'); }); }); axios-axios-2d06f96/tests/smoke/bun/tests/headers.smoke.test.ts000066400000000000000000000030211521272452000246000ustar00rootroot00000000000000import { describe, expect, test } from 'bun:test'; import axios from 'axios'; const createFetchCapture = () => { const calls: Request[] = []; const fetch = async (input: unknown, init?: RequestInit) => { const request = input instanceof Request ? input : new Request(input as string, init); calls.push(request); return new Response(JSON.stringify({ ok: true }), { status: 200, headers: { 'Content-Type': 'application/json' }, }); }; return { fetch, getCalls: () => calls, }; }; const env = (fetch: typeof globalThis.fetch) => ({ fetch, Request, Response, }); describe('headers', () => { test('custom X-Custom header is forwarded to mock fetch (case-insensitive)', async () => { const { fetch, getCalls } = createFetchCapture(); await axios.get('https://example.com/custom-headers', { adapter: 'fetch', headers: { 'X-Custom': 'trace-123', }, env: env(fetch), }); const request = getCalls()[0]; expect(request.headers.get('x-custom')).toBe('trace-123'); }); test('content-type application/json is inferred for JSON POST body', async () => { const { fetch, getCalls } = createFetchCapture(); await axios.post( 'https://example.com/post-json', { name: 'widget' }, { adapter: 'fetch', env: env(fetch), } ); const request = getCalls()[0]; const contentType = request.headers.get('content-type') || ''; expect(contentType.includes('application/json')).toBe(true); }); }); axios-axios-2d06f96/tests/smoke/bun/tests/http.smoke.test.ts000066400000000000000000000055101521272452000241510ustar00rootroot00000000000000import { describe, expect, test } from 'bun:test'; import { EventEmitter } from 'node:events'; import { PassThrough } from 'node:stream'; import axios from 'axios'; type TransportCall = { options: Record; body: Buffer; }; const createTransportMock = ( responseFactory?: (body: Buffer, options: Record) => Record ) => { const calls: TransportCall[] = []; const transport = { request(options: Record, onResponse: (res: PassThrough) => void) { const req = new EventEmitter() as Record; const chunks: Buffer[] = []; req.destroyed = false; req.setTimeout = () => {}; req.write = (chunk?: unknown) => { if (chunk !== undefined) { chunks.push(Buffer.from(chunk as string)); } return true; }; req.destroy = () => { req.destroyed = true; }; req.close = req.destroy; req.end = (chunk?: unknown) => { if (chunk !== undefined) { chunks.push(Buffer.from(chunk as string)); } const body = Buffer.concat(chunks); calls.push({ options, body }); const response = responseFactory ? responseFactory(body, options) : {}; const res = new PassThrough() as PassThrough & Record; res.statusCode = response.statusCode ?? 200; res.statusMessage = response.statusMessage ?? 'OK'; res.headers = response.headers ?? { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end(response.body ?? JSON.stringify({ ok: true })); }; return req; }, }; return { transport, getCalls: () => calls, }; }; describe('http adapter', () => { test('GET via http adapter returns mocked response data', async () => { const { transport, getCalls } = createTransportMock(); const response = await axios.get('http://example.com/users', { adapter: 'http', proxy: false, transport, }); expect(response.status).toBe(200); expect(response.data).toEqual({ ok: true }); expect(getCalls()).toHaveLength(1); }); test('POST sends JSON-serialized body via http adapter', async () => { const { transport, getCalls } = createTransportMock(); await axios.post( 'http://example.com/items', { name: 'widget' }, { adapter: 'http', proxy: false, transport, } ); const { body } = getCalls()[0]; expect(body.toString('utf8')).toBe(JSON.stringify({ name: 'widget' })); }); test('default adapter selection in Bun routes through http adapter', async () => { const { transport, getCalls } = createTransportMock(); await axios.get('http://example.com/default-adapter', { proxy: false, transport, }); expect(getCalls()).toHaveLength(1); }); }); axios-axios-2d06f96/tests/smoke/bun/tests/import.smoke.test.ts000066400000000000000000000013051521272452000245020ustar00rootroot00000000000000import { describe, expect, test } from 'bun:test'; import axios from 'axios'; describe('Bun importing', () => { test('default export is callable', () => { expect(typeof axios).toBe('function'); }); test('named exports are present', async () => { const exports = (await import('axios')) as Record; expect(typeof (exports.axios ?? exports.default)).toBe('function'); expect(typeof (exports.create ?? exports.default.create)).toBe('function'); expect(typeof exports.isCancel).toBe('function'); expect(typeof exports.isAxiosError).toBe('function'); expect(typeof exports.CancelToken).toBe('function'); expect(typeof exports.VERSION).toBe('string'); }); }); axios-axios-2d06f96/tests/smoke/bun/tests/interceptors.smoke.test.ts000066400000000000000000000033171521272452000257160ustar00rootroot00000000000000import { describe, expect, test } from 'bun:test'; import axios from 'axios'; const createFetchCapture = () => { const calls: Request[] = []; const fetch = async (input: unknown, init?: RequestInit) => { const request = input instanceof Request ? input : new Request(input as string, init); calls.push(request); return new Response(JSON.stringify({ value: 'ok' }), { status: 200, headers: { 'Content-Type': 'application/json' }, }); }; return { fetch, getCalls: () => calls, }; }; const env = (fetch: typeof globalThis.fetch) => ({ fetch, Request, Response, }); describe('interceptors', () => { test('request interceptor header is forwarded to fetch', async () => { const { fetch, getCalls } = createFetchCapture(); const client = axios.create({ adapter: 'fetch', env: env(fetch), }); client.interceptors.request.use((config: any) => { config.headers = config.headers || {}; config.headers['X-Added'] = 'yes'; return config; }); await client.get('https://example.com/interceptor-request'); expect(getCalls()).toHaveLength(1); expect(getCalls()[0].headers.get('x-added')).toBe('yes'); }); test('response interceptor transform is reflected in resolved value', async () => { const { fetch } = createFetchCapture(); const client = axios.create({ adapter: 'fetch', env: env(fetch), }); client.interceptors.response.use((response: any) => { response.data.value = String(response.data.value).toUpperCase(); return response; }); const response = await client.get('https://example.com/interceptor-response'); expect(response.data).toEqual({ value: 'OK' }); }); }); axios-axios-2d06f96/tests/smoke/bun/tests/progress.smoke.test.ts000066400000000000000000000022551521272452000250410ustar00rootroot00000000000000import { describe, expect, test } from 'bun:test'; import axios from 'axios'; const env = (fetch: typeof globalThis.fetch) => ({ fetch, Request, Response, }); describe('progress', () => { test('onDownloadProgress fires with loaded > 0 for streaming fetch response', async () => { const samples: number[] = []; const fetch = async () => { const stream = new ReadableStream({ start(controller) { controller.enqueue(new TextEncoder().encode('ab')); controller.enqueue(new TextEncoder().encode('cd')); controller.close(); }, }); return new Response(stream, { status: 200, headers: { 'Content-Type': 'text/plain', 'Content-Length': '4', }, }); }; const response = await axios.get('https://example.com/download', { adapter: 'fetch', responseType: 'text', onDownloadProgress: ({ loaded }: { loaded: number }) => { samples.push(loaded); }, env: env(fetch), }); expect(response.data).toBe('abcd'); expect(samples.length).toBeGreaterThan(0); expect(samples.some((loaded) => loaded > 0)).toBe(true); }); }); axios-axios-2d06f96/tests/smoke/bun/tests/timeout.smoke.test.ts000066400000000000000000000024371521272452000246650ustar00rootroot00000000000000import { describe, expect, test } from 'bun:test'; import axios from 'axios'; const env = (fetch: typeof globalThis.fetch) => ({ fetch, Request, Response, }); const createAbortedError = () => { const error = new Error('The operation was aborted') as Error & { code?: string; name: string }; error.name = 'AbortError'; error.code = 'ECONNABORTED'; return error; }; describe('timeout', () => { test('timeout: 50 with never-resolving fetch mock rejects with ETIMEDOUT', async () => { const fetch = (input: unknown, init?: RequestInit) => new Promise((_resolve, reject) => { const signal = init?.signal || (input instanceof Request ? input.signal : undefined); if (signal) { if (signal.aborted) { reject(createAbortedError()); return; } signal.addEventListener( 'abort', () => { reject(createAbortedError()); }, { once: true } ); } }); const err = await axios .get('https://example.com/timeout', { adapter: 'fetch', timeout: 50, env: env(fetch), }) .catch((e: any) => e); expect(axios.isAxiosError(err)).toBe(true); expect(err.code).toBe('ETIMEDOUT'); }); }); axios-axios-2d06f96/tests/smoke/cjs/000077500000000000000000000000001521272452000173575ustar00rootroot00000000000000axios-axios-2d06f96/tests/smoke/cjs/package-lock.json000066400000000000000000000515761521272452000226110ustar00rootroot00000000000000{ "name": "@axios/cjs-smoke-tests", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@axios/cjs-smoke-tests", "version": "1.0.0", "license": "MIT", "devDependencies": { "chai": "4.5.0", "mocha": "9.2.2" } }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "dev": true, "license": "ISC" }, "node_modules/ansi-colors": { "version": "4.1.1", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/ansi-regex": { "version": "5.0.1", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/ansi-styles": { "version": "4.3.0", "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/anymatch": { "version": "3.1.3", "dev": true, "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" }, "engines": { "node": ">= 8" } }, "node_modules/argparse": { "version": "2.0.1", "dev": true, "license": "Python-2.0" }, "node_modules/assertion-error": { "version": "1.1.0", "dev": true, "license": "MIT", "engines": { "node": "*" } }, "node_modules/balanced-match": { "version": "1.0.2", "dev": true, "license": "MIT" }, "node_modules/binary-extensions": { "version": "2.3.0", "dev": true, "license": "MIT", "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/brace-expansion": { "version": "1.1.12", "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "node_modules/braces": { "version": "3.0.3", "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, "node_modules/browser-stdout": { "version": "1.3.1", "dev": true, "license": "ISC" }, "node_modules/camelcase": { "version": "6.3.0", "dev": true, "license": "MIT", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/chai": { "version": "4.5.0", "dev": true, "license": "MIT", "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.3", "deep-eql": "^4.1.3", "get-func-name": "^2.0.2", "loupe": "^2.3.6", "pathval": "^1.1.1", "type-detect": "^4.1.0" }, "engines": { "node": ">=4" } }, "node_modules/chalk": { "version": "4.1.2", "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/chalk/node_modules/supports-color": { "version": "7.2.0", "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/check-error": { "version": "1.0.3", "dev": true, "license": "MIT", "dependencies": { "get-func-name": "^2.0.2" }, "engines": { "node": "*" } }, "node_modules/chokidar": { "version": "3.5.3", "dev": true, "funding": [ { "type": "individual", "url": "https://paulmillr.com/funding/" } ], "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "engines": { "node": ">= 8.10.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "node_modules/cliui": { "version": "7.0.4", "dev": true, "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "node_modules/color-convert": { "version": "2.0.1", "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, "engines": { "node": ">=7.0.0" } }, "node_modules/color-name": { "version": "1.1.4", "dev": true, "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", "dev": true, "license": "MIT" }, "node_modules/debug": { "version": "4.3.3", "dev": true, "license": "MIT", "dependencies": { "ms": "2.1.2" }, "engines": { "node": ">=6.0" }, "peerDependenciesMeta": { "supports-color": { "optional": true } } }, "node_modules/debug/node_modules/ms": { "version": "2.1.2", "dev": true, "license": "MIT" }, "node_modules/decamelize": { "version": "4.0.0", "dev": true, "license": "MIT", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/deep-eql": { "version": "4.1.4", "dev": true, "license": "MIT", "dependencies": { "type-detect": "^4.0.0" }, "engines": { "node": ">=6" } }, "node_modules/diff": { "version": "5.0.0", "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, "node_modules/emoji-regex": { "version": "8.0.0", "dev": true, "license": "MIT" }, "node_modules/escalade": { "version": "3.2.0", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/escape-string-regexp": { "version": "4.0.0", "dev": true, "license": "MIT", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/fill-range": { "version": "7.1.1", "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/find-up": { "version": "5.0.0", "dev": true, "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/flat": { "version": "5.0.2", "dev": true, "license": "BSD-3-Clause", "bin": { "flat": "cli.js" } }, "node_modules/fs.realpath": { "version": "1.0.0", "dev": true, "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, "node_modules/get-caller-file": { "version": "2.0.5", "dev": true, "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-func-name": { "version": "2.0.2", "dev": true, "license": "MIT", "engines": { "node": "*" } }, "node_modules/glob": { "version": "7.2.0", "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/glob-parent": { "version": "5.1.2", "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, "engines": { "node": ">= 6" } }, "node_modules/glob/node_modules/minimatch": { "version": "3.1.5", "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { "node": "*" } }, "node_modules/growl": { "version": "1.10.5", "dev": true, "license": "MIT", "engines": { "node": ">=4.x" } }, "node_modules/has-flag": { "version": "4.0.0", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/he": { "version": "1.2.0", "dev": true, "license": "MIT", "bin": { "he": "bin/he" } }, "node_modules/inflight": { "version": "1.0.6", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "node_modules/inherits": { "version": "2.0.4", "dev": true, "license": "ISC" }, "node_modules/is-binary-path": { "version": "2.1.0", "dev": true, "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, "engines": { "node": ">=8" } }, "node_modules/is-extglob": { "version": "2.1.1", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-glob": { "version": "4.0.3", "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-number": { "version": "7.0.0", "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" } }, "node_modules/is-plain-obj": { "version": "2.1.0", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-unicode-supported": { "version": "0.1.0", "dev": true, "license": "MIT", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/isexe": { "version": "2.0.0", "dev": true, "license": "ISC" }, "node_modules/js-yaml": { "version": "4.1.0", "dev": true, "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "node_modules/locate-path": { "version": "6.0.0", "dev": true, "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/log-symbols": { "version": "4.1.0", "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/loupe": { "version": "2.3.7", "dev": true, "license": "MIT", "dependencies": { "get-func-name": "^2.0.1" } }, "node_modules/minimatch": { "version": "4.2.1", "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { "node": ">=10" } }, "node_modules/mocha": { "version": "9.2.2", "dev": true, "license": "MIT", "dependencies": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", "chokidar": "3.5.3", "debug": "4.3.3", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", "glob": "7.2.0", "growl": "1.10.5", "he": "1.2.0", "js-yaml": "4.1.0", "log-symbols": "4.1.0", "minimatch": "4.2.1", "ms": "2.1.3", "nanoid": "3.3.1", "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", "workerpool": "6.2.0", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" }, "bin": { "_mocha": "bin/_mocha", "mocha": "bin/mocha" }, "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/mochajs" } }, "node_modules/ms": { "version": "2.1.3", "dev": true, "license": "MIT" }, "node_modules/nanoid": { "version": "3.3.1", "dev": true, "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, "engines": { "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, "node_modules/normalize-path": { "version": "3.0.0", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/once": { "version": "1.4.0", "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" } }, "node_modules/p-limit": { "version": "3.1.0", "dev": true, "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { "version": "5.0.0", "dev": true, "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/path-exists": { "version": "4.0.0", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-is-absolute": { "version": "1.0.1", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/pathval": { "version": "1.1.1", "dev": true, "license": "MIT", "engines": { "node": "*" } }, "node_modules/picomatch": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { "node": ">=8.6" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/randombytes": { "version": "2.1.0", "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } }, "node_modules/readdirp": { "version": "3.6.0", "dev": true, "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, "engines": { "node": ">=8.10.0" } }, "node_modules/require-directory": { "version": "2.1.1", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/safe-buffer": { "version": "5.2.1", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ], "license": "MIT" }, "node_modules/serialize-javascript": { "version": "6.0.0", "dev": true, "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } }, "node_modules/string-width": { "version": "4.2.3", "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8" } }, "node_modules/strip-ansi": { "version": "6.0.1", "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/strip-json-comments": { "version": "3.1.1", "dev": true, "license": "MIT", "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/supports-color": { "version": "8.1.1", "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/to-regex-range": { "version": "5.0.1", "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, "engines": { "node": ">=8.0" } }, "node_modules/type-detect": { "version": "4.1.0", "dev": true, "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/which": { "version": "2.0.2", "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" }, "engines": { "node": ">= 8" } }, "node_modules/workerpool": { "version": "6.2.0", "dev": true, "license": "Apache-2.0" }, "node_modules/wrap-ansi": { "version": "7.0.0", "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "node_modules/wrappy": { "version": "1.0.2", "dev": true, "license": "ISC" }, "node_modules/y18n": { "version": "5.0.8", "dev": true, "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yargs": { "version": "16.2.0", "dev": true, "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" }, "engines": { "node": ">=10" } }, "node_modules/yargs-parser": { "version": "20.2.4", "dev": true, "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yargs-unparser": { "version": "2.0.0", "dev": true, "license": "MIT", "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", "flat": "^5.0.2", "is-plain-obj": "^2.1.0" }, "engines": { "node": ">=10" } }, "node_modules/yocto-queue": { "version": "0.1.0", "dev": true, "license": "MIT", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } } } } axios-axios-2d06f96/tests/smoke/cjs/package.json000066400000000000000000000005311521272452000216440ustar00rootroot00000000000000{ "name": "@axios/cjs-smoke-tests", "version": "1.0.0", "description": "CJS smoke tests for axios", "private": true, "scripts": { "test:smoke:cjs:mocha": "mocha \"tests/**/*.smoke.test.cjs\"" }, "keywords": [], "author": "axios team", "license": "MIT", "devDependencies": { "mocha": "9.2.2", "chai": "4.5.0" } }axios-axios-2d06f96/tests/smoke/cjs/tests/000077500000000000000000000000001521272452000205215ustar00rootroot00000000000000axios-axios-2d06f96/tests/smoke/cjs/tests/auth.smoke.test.cjs000066400000000000000000000065741521272452000242720ustar00rootroot00000000000000const http = require('http'); const axios = require('axios'); const { describe, it, afterEach } = require('mocha'); const { expect } = require('chai'); const startServer = (handler) => { return new Promise((resolve) => { const server = http.createServer(handler); server.listen(0, '127.0.0.1', () => { resolve(server); }); }); }; const stopServer = (server) => { if (!server || !server.listening) { return Promise.resolve(); } return new Promise((resolve, reject) => { server.close((error) => { if (error) { reject(error); return; } resolve(); }); }); }; describe('auth compat (dist export only)', () => { let server; afterEach(async () => { await stopServer(server); server = undefined; }); const requestWithConfig = async (config) => { server = await startServer((req, res) => { res.setHeader('Content-Type', 'text/plain'); res.end(req.headers.authorization || ''); }); const { port } = server.address(); return axios.get( `http://127.0.0.1:${port}/`, Object.assign( { proxy: false, }, config || {} ) ); }; it('sets Basic Authorization header from auth credentials', async () => { const response = await requestWithConfig({ auth: { username: 'janedoe', password: 's00pers3cret', }, }); const expected = `Basic ${Buffer.from('janedoe:s00pers3cret', 'utf8').toString('base64')}`; expect(response.data).to.equal(expected); }); it('supports auth without password', async () => { const response = await requestWithConfig({ auth: { username: 'Aladdin', }, }); const expected = `Basic ${Buffer.from('Aladdin:', 'utf8').toString('base64')}`; expect(response.data).to.equal(expected); }); it('overwrites an existing Authorization header when auth is provided', async () => { const response = await requestWithConfig({ headers: { Authorization: 'Bearer token-123', }, auth: { username: 'foo', password: 'bar', }, }); const expected = `Basic ${Buffer.from('foo:bar', 'utf8').toString('base64')}`; expect(response.data).to.equal(expected); }); it('uses URL credentials when auth config is not provided (node adapter behavior)', async () => { server = await startServer((req, res) => { res.setHeader('Content-Type', 'text/plain'); res.end(req.headers.authorization || ''); }); const { port } = server.address(); const response = await axios.get(`http://urluser:urlpass@127.0.0.1:${port}/`, { proxy: false, }); const expected = `Basic ${Buffer.from('urluser:urlpass', 'utf8').toString('base64')}`; expect(response.data).to.equal(expected); }); it('prefers auth config over URL credentials', async () => { server = await startServer((req, res) => { res.setHeader('Content-Type', 'text/plain'); res.end(req.headers.authorization || ''); }); const { port } = server.address(); const response = await axios.get(`http://urluser:urlpass@127.0.0.1:${port}/`, { proxy: false, auth: { username: 'configuser', password: 'configpass', }, }); const expected = `Basic ${Buffer.from('configuser:configpass', 'utf8').toString('base64')}`; expect(response.data).to.equal(expected); }); }); axios-axios-2d06f96/tests/smoke/cjs/tests/basic.smoke.test.cjs000066400000000000000000000071551521272452000244060ustar00rootroot00000000000000const { EventEmitter } = require('events'); const { PassThrough } = require('stream'); const axios = require('axios'); const { describe, it } = require('mocha'); const { expect } = require('chai'); const createTransportCapture = () => { let capturedOptions; const transport = { request(options, onResponse) { capturedOptions = options; const req = new EventEmitter(); req.destroyed = false; req.setTimeout = () => {}; req.write = () => true; req.end = () => { const res = new PassThrough(); res.statusCode = 200; res.statusMessage = 'OK'; res.headers = { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end('{"ok":true}'); }; req.destroy = () => { req.destroyed = true; }; req.close = req.destroy; return req; }, }; return { transport, getCapturedOptions: () => capturedOptions, }; }; const runRequest = async (run) => { const { transport, getCapturedOptions } = createTransportCapture(); await run(transport); return getCapturedOptions(); }; describe('basic compat (dist export only)', () => { it('supports the simplest axios(url) request pattern', async () => { const options = await runRequest((transport) => axios('http://example.com/users', { transport, proxy: false, }) ); expect(options.method).to.equal('GET'); expect(options.path).to.equal('/users'); }); it('supports get()', async () => { const options = await runRequest((transport) => axios.get('http://example.com/items?limit=10', { transport, proxy: false }) ); expect(options.method).to.equal('GET'); expect(options.path).to.equal('/items?limit=10'); }); it('supports delete()', async () => { const options = await runRequest((transport) => axios.delete('http://example.com/items/1', { transport, proxy: false }) ); expect(options.method).to.equal('DELETE'); expect(options.path).to.equal('/items/1'); }); it('supports head()', async () => { const options = await runRequest((transport) => axios.head('http://example.com/health', { transport, proxy: false }) ); expect(options.method).to.equal('HEAD'); expect(options.path).to.equal('/health'); }); it('supports options()', async () => { const options = await runRequest((transport) => axios.options('http://example.com/items', { transport, proxy: false }) ); expect(options.method).to.equal('OPTIONS'); expect(options.path).to.equal('/items'); }); it('supports post()', async () => { const options = await runRequest((transport) => axios.post( 'http://example.com/items', { name: 'widget' }, { transport, proxy: false, } ) ); expect(options.method).to.equal('POST'); expect(options.path).to.equal('/items'); }); it('supports put()', async () => { const options = await runRequest((transport) => axios.put( 'http://example.com/items/1', { name: 'updated-widget' }, { transport, proxy: false, } ) ); expect(options.method).to.equal('PUT'); expect(options.path).to.equal('/items/1'); }); it('supports patch()', async () => { const options = await runRequest((transport) => axios.patch( 'http://example.com/items/1', { status: 'active' }, { transport, proxy: false, } ) ); expect(options.method).to.equal('PATCH'); expect(options.path).to.equal('/items/1'); }); }); axios-axios-2d06f96/tests/smoke/cjs/tests/cancel.smoke.test.cjs000066400000000000000000000062101521272452000245410ustar00rootroot00000000000000const { EventEmitter } = require('events'); const axios = require('axios'); const { describe, it } = require('mocha'); const { expect } = require('chai'); const NODE_VERSION = parseInt(process.versions.node.split('.')[0]); const itWithAbortController = NODE_VERSION < 16 ? it.skip : it; const createPendingTransport = () => { let requestCount = 0; const transport = { request() { requestCount += 1; const req = new EventEmitter(); req.destroyed = false; req.setTimeout = () => {}; req.write = () => true; req.end = () => {}; req.destroy = () => { req.destroyed = true; }; req.close = req.destroy; return req; }, }; return { transport, getRequestCount: () => requestCount, }; }; describe('cancel compat (dist export only)', () => { itWithAbortController( 'supports cancellation with AbortController (pre-aborted signal)', async () => { const { transport, getRequestCount } = createPendingTransport(); const controller = new AbortController(); controller.abort(); try { const request = axios.get('http://example.com/resource', { signal: controller.signal, transport, proxy: false, }); controller.abort(); await request; } catch (error) { expect(error).to.have.property('code', 'ERR_CANCELED'); } expect(getRequestCount()).to.equal(0); } ); itWithAbortController('supports cancellation with AbortController (in-flight)', async () => { const { transport, getRequestCount } = createPendingTransport(); const controller = new AbortController(); try { const request = axios.get('http://example.com/resource', { signal: controller.signal, transport, proxy: false, }); controller.abort(); await request; } catch (error) { expect(error).to.have.property('code', 'ERR_CANCELED'); } expect(getRequestCount()).to.equal(1); }); it('supports cancellation with CancelToken (pre-canceled token)', async () => { const { transport, getRequestCount } = createPendingTransport(); const source = axios.CancelToken.source(); source.cancel('Operation canceled by the user.'); const error = await axios .get('http://example.com/resource', { cancelToken: source.token, transport, proxy: false, }) .catch((err) => err); expect(axios.isCancel(error)).to.be.true; expect(error.code).to.equal('ERR_CANCELED'); expect(getRequestCount()).to.equal(0); }); it('supports cancellation with CancelToken (in-flight)', async () => { const { transport, getRequestCount } = createPendingTransport(); const source = axios.CancelToken.source(); const request = axios.get('http://example.com/resource', { cancelToken: source.token, transport, proxy: false, }); source.cancel('Operation canceled by the user.'); const error = await request.catch((err) => err); expect(axios.isCancel(error)).to.be.true; expect(error.code).to.equal('ERR_CANCELED'); expect(getRequestCount()).to.equal(1); }); }); axios-axios-2d06f96/tests/smoke/cjs/tests/error.smoke.test.cjs000066400000000000000000000075471521272452000244630ustar00rootroot00000000000000const { EventEmitter } = require('events'); const { PassThrough } = require('stream'); const axios = require('axios'); const { describe, it } = require('mocha'); const { expect } = require('chai'); const createTransport = (config) => { const opts = config || {}; return { request(options, onResponse) { const req = new EventEmitter(); req.destroyed = false; req.write = () => true; req.destroy = () => { req.destroyed = true; }; req.close = req.destroy; req.setTimeout = (_ms, cb) => { if (opts.timeout) { req._timeoutCallback = cb; } }; req.end = () => { if (opts.error) { req.emit('error', opts.error); return; } if (opts.timeout && req._timeoutCallback) { req._timeoutCallback(); return; } const res = new PassThrough(); res.statusCode = opts.response && opts.response.statusCode !== undefined ? opts.response.statusCode : 200; res.statusMessage = opts.response && opts.response.statusMessage ? opts.response.statusMessage : 'OK'; res.headers = opts.response && opts.response.headers ? opts.response.headers : { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end(opts.response && opts.response.body ? opts.response.body : '{"ok":true}'); }; return req; }, }; }; describe('error compat (dist export only)', () => { it('rejects with AxiosError for non-2xx responses by default', async () => { const err = await axios .get('http://example.com/fail', { proxy: false, transport: createTransport({ response: { statusCode: 500, statusMessage: 'Internal Server Error', body: '{"error":"boom"}', }, }), }) .catch((e) => e); expect(axios.isAxiosError(err)).to.be.true; expect(err.response.status).to.equal(500); expect(err.message).to.include('500'); }); it('resolves when validateStatus allows non-2xx responses', async () => { const response = await axios.get('http://example.com/allowed', { proxy: false, validateStatus: () => true, transport: createTransport({ response: { statusCode: 500, statusMessage: 'Internal Server Error', body: '{"ok":false}', }, }), }); expect(response.status).to.equal(500); expect(response.data).to.deep.equal({ ok: false }); }); it('wraps transport errors as AxiosError', async () => { const err = await axios .get('http://example.com/network', { proxy: false, transport: createTransport({ error: new Error('socket hang up'), }), }) .catch((e) => e); expect(axios.isAxiosError(err)).to.be.true; expect(err.message).to.include('socket hang up'); expect(err.toJSON).to.be.a('function'); }); it('rejects with ECONNABORTED on timeout', async () => { const err = await axios .get('http://example.com/timeout', { proxy: false, timeout: 10, transport: createTransport({ timeout: true }), }) .catch((e) => e); expect(axios.isAxiosError(err)).to.be.true; expect(err.code).to.equal('ECONNABORTED'); expect(err.message).to.equal('timeout of 10ms exceeded'); }); it('uses timeoutErrorMessage when provided', async () => { const err = await axios .get('http://example.com/timeout', { proxy: false, timeout: 25, timeoutErrorMessage: 'custom timeout message', transport: createTransport({ timeout: true }), }) .catch((e) => e); expect(axios.isAxiosError(err)).to.be.true; expect(err.code).to.equal('ECONNABORTED'); expect(err.message).to.equal('custom timeout message'); }); }); axios-axios-2d06f96/tests/smoke/cjs/tests/fetch.smoke.test.cjs000066400000000000000000000076561521272452000244240ustar00rootroot00000000000000const axios = require('axios'); const { it, describe } = require('mocha'); const { expect } = require('chai'); const NODE_VERSION = parseInt(process.versions.node.split('.')[0]); const describeWithFetch = NODE_VERSION < 18 ? describe.skip : describe; const createFetchMock = (responseFactory) => { const calls = []; const mockFetch = async (input, init) => { calls.push({ input, init: init || {} }); if (responseFactory) { return responseFactory(input, init || {}); } return new Response(JSON.stringify({ ok: true }), { status: 200, headers: { 'Content-Type': 'application/json' }, }); }; return { mockFetch, getCalls: () => calls, }; }; describeWithFetch('fetch compat (dist export only)', () => { it('uses fetch adapter and resolves JSON response', async () => { const { mockFetch, getCalls } = createFetchMock(); const response = await axios.get('https://example.com/users', { adapter: 'fetch', env: { fetch: mockFetch, Request, Response, }, }); expect(response.data).to.deep.equal({ ok: true }); expect(response.status).to.equal(200); expect(getCalls()).to.have.lengthOf(1); }); it('sends method, headers and body for post requests', async () => { const { mockFetch, getCalls } = createFetchMock(async (input, init) => { const requestInit = init || {}; const isRequest = input && typeof input !== 'string'; const method = isRequest ? input.method : requestInit.method; const body = isRequest && typeof input.clone === 'function' ? await input.clone().text() : requestInit.body; let contentType; if (isRequest && input.headers) { contentType = input.headers.get('content-type'); } else if (requestInit.headers) { contentType = requestInit.headers['Content-Type'] || requestInit.headers['content-type']; } return new Response( JSON.stringify({ url: typeof input === 'string' ? input : input.url, method, contentType, body, }), { status: 200, headers: { 'Content-Type': 'application/json' }, } ); }); const response = await axios.post( 'https://example.com/items', { name: 'widget' }, { adapter: 'fetch', env: { fetch: mockFetch, Request, Response, }, } ); expect(getCalls()).to.have.lengthOf(1); expect(response.data.url).to.equal('https://example.com/items'); expect(response.data.method).to.equal('POST'); expect(response.data.contentType).to.include('application/json'); expect(response.data.body).to.equal(JSON.stringify({ name: 'widget' })); }); it('rejects non-2xx fetch responses by default', async () => { const { mockFetch } = createFetchMock( () => new Response(JSON.stringify({ error: 'boom' }), { status: 500, statusText: 'Internal Server Error', headers: { 'Content-Type': 'application/json' }, }) ); const err = await axios .get('https://example.com/fail', { adapter: 'fetch', env: { fetch: mockFetch, Request, Response, }, }) .catch((e) => e); expect(axios.isAxiosError(err)).to.be.true; expect(err.response.status).to.equal(500); }); it('supports cancellation with AbortController in fetch mode', async () => { const { mockFetch } = createFetchMock(); const controller = new AbortController(); controller.abort(); const err = await axios .get('https://example.com/cancel', { adapter: 'fetch', signal: controller.signal, env: { fetch: mockFetch, Request, Response, }, }) .catch((e) => e); expect(axios.isCancel(err)).to.be.true; expect(err.code).to.equal('ERR_CANCELED'); }); }); axios-axios-2d06f96/tests/smoke/cjs/tests/files.smoke.test.cjs000066400000000000000000000071301521272452000244200ustar00rootroot00000000000000const { PassThrough, Readable, Writable } = require('stream'); const axios = require('axios'); const { describe, it } = require('mocha'); const { expect } = require('chai'); const createCaptureTransport = (buildResponse) => { return { request(options, onResponse) { const chunks = []; const req = new Writable({ write(chunk, _encoding, callback) { chunks.push(Buffer.from(chunk)); callback(); }, }); req.destroyed = false; req.setTimeout = () => {}; req.close = () => { req.destroyed = true; }; const originalDestroy = req.destroy.bind(req); req.destroy = (...args) => { req.destroyed = true; return originalDestroy(...args); }; const originalEnd = req.end.bind(req); req.end = (...args) => { originalEnd(...args); const body = Buffer.concat(chunks); const response = buildResponse ? buildResponse(body, options) : {}; const res = new PassThrough(); res.statusCode = response.statusCode !== undefined ? response.statusCode : 200; res.statusMessage = response.statusMessage || 'OK'; res.headers = response.headers || { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end(response.body || JSON.stringify({ size: body.length })); }; req.on('error', () => {}); return req; }, }; }; describe('files compat (dist export only)', () => { it('supports posting Buffer payloads', async () => { const source = Buffer.from('binary-\x00-data', 'utf8'); const response = await axios.post('http://example.com/upload', source, { proxy: false, transport: createCaptureTransport((body) => ({ body: JSON.stringify({ echoed: body.toString('base64') }), })), }); expect(response.data.echoed).to.equal(source.toString('base64')); }); it('supports posting Uint8Array payloads', async () => { const source = Uint8Array.from([1, 2, 3, 4, 255]); const response = await axios.post('http://example.com/upload', source, { proxy: false, transport: createCaptureTransport((body) => ({ body: JSON.stringify({ echoed: Array.from(body.values()) }), })), }); expect(response.data.echoed).to.deep.equal([1, 2, 3, 4, 255]); }); it('supports posting Readable stream payloads', async () => { const streamData = ['hello ', 'stream ', 'world']; const source = Readable.from(streamData); const response = await axios.post('http://example.com/upload', source, { proxy: false, headers: { 'Content-Type': 'application/octet-stream' }, transport: createCaptureTransport((body, options) => ({ body: JSON.stringify({ text: body.toString('utf8'), contentType: options.headers && (options.headers['Content-Type'] || options.headers['content-type']), }), })), }); expect(response.data.text).to.equal('hello stream world'); expect(response.data.contentType).to.contain('application/octet-stream'); }); it('supports binary downloads with responseType=arraybuffer', async () => { const binary = Buffer.from([0xde, 0xad, 0xbe, 0xef]); const response = await axios.get('http://example.com/file.bin', { proxy: false, responseType: 'arraybuffer', transport: createCaptureTransport(() => ({ headers: { 'content-type': 'application/octet-stream' }, body: binary, })), }); expect(Buffer.isBuffer(response.data)).to.equal(true); expect(response.data.equals(binary)).to.equal(true); }); }); axios-axios-2d06f96/tests/smoke/cjs/tests/formData.smoke.test.cjs000066400000000000000000000066521521272452000250630ustar00rootroot00000000000000const { Writable, PassThrough } = require('stream'); const axios = require('axios'); const { describe, it } = require('mocha'); const { expect } = require('chai'); const NODE_VERSION = parseInt(process.versions.node.split('.')[0]); const describeWithFormData = NODE_VERSION < 18 ? describe.skip : describe; const createCaptureTransport = (buildResponse) => { return { request(options, onResponse) { const chunks = []; const req = new Writable({ write(chunk, _encoding, callback) { chunks.push(Buffer.from(chunk)); callback(); }, }); req.destroyed = false; req.setTimeout = () => {}; req.write = req.write.bind(req); req.close = () => { req.destroyed = true; }; const originalDestroy = req.destroy.bind(req); req.destroy = (...args) => { req.destroyed = true; return originalDestroy(...args); }; const originalEnd = req.end.bind(req); req.end = (...args) => { originalEnd(...args); const body = Buffer.concat(chunks); const response = buildResponse ? buildResponse(body, options) : {}; const res = new PassThrough(); res.statusCode = response.statusCode !== undefined ? response.statusCode : 200; res.statusMessage = response.statusMessage || 'OK'; res.headers = response.headers || { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end(response.body || JSON.stringify({ ok: true })); }; return req; }, }; }; const bodyAsUtf8 = (value) => { return Buffer.isBuffer(value) ? value.toString('utf8') : String(value); }; describeWithFormData('formData compat (dist export only)', () => { it('supports posting FormData instances', async () => { const form = new FormData(); form.append('username', 'janedoe'); form.append('role', 'admin'); const response = await axios.post('http://example.com/form', form, { proxy: false, transport: createCaptureTransport((body, options) => ({ body: JSON.stringify({ contentType: options.headers && (options.headers['Content-Type'] || options.headers['content-type']), payload: bodyAsUtf8(body), }), })), }); expect(response.data.contentType).to.contain('multipart/form-data'); expect(response.data.payload).to.contain('name="username"'); expect(response.data.payload).to.contain('janedoe'); expect(response.data.payload).to.contain('name="role"'); expect(response.data.payload).to.contain('admin'); }); it('supports axios.postForm helper', async () => { const response = await axios.postForm( 'http://example.com/post-form', { project: 'axios', mode: 'compat', }, { proxy: false, transport: createCaptureTransport((body, options) => ({ body: JSON.stringify({ contentType: options.headers && (options.headers['Content-Type'] || options.headers['content-type']), payload: bodyAsUtf8(body), }), })), } ); expect(response.data.contentType).to.contain('multipart/form-data'); expect(response.data.payload).to.contain('name="project"'); expect(response.data.payload).to.contain('axios'); expect(response.data.payload).to.contain('name="mode"'); expect(response.data.payload).to.contain('compat'); }); }); axios-axios-2d06f96/tests/smoke/cjs/tests/headers.smoke.test.cjs000066400000000000000000000065631521272452000247420ustar00rootroot00000000000000const { EventEmitter } = require('events'); const { PassThrough } = require('stream'); const axios = require('axios'); const { describe, it } = require('mocha'); const { expect } = require('chai'); const normalizeHeaders = (headers) => { const result = {}; Object.entries(headers || {}).forEach(([key, value]) => { result[key.toLowerCase()] = value; }); return result; }; const createTransportCapture = () => { let capturedOptions; const transport = { request(options, onResponse) { capturedOptions = options; const req = new EventEmitter(); req.destroyed = false; req.setTimeout = () => {}; req.write = () => true; req.destroy = () => { req.destroyed = true; }; req.close = req.destroy; req.end = () => { const res = new PassThrough(); res.statusCode = 200; res.statusMessage = 'OK'; res.headers = { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end('{"ok":true}'); }; return req; }, }; return { transport, getCapturedOptions: () => capturedOptions, }; }; describe('headers compat (dist export only)', () => { it('sends default Accept header', async () => { const { transport, getCapturedOptions } = createTransportCapture(); await axios.get('http://example.com/default-headers', { transport, proxy: false, }); const headers = normalizeHeaders(getCapturedOptions().headers); expect(headers.accept).to.equal('application/json, text/plain, */*'); }); it('supports custom headers', async () => { const { transport, getCapturedOptions } = createTransportCapture(); await axios.get('http://example.com/custom-headers', { transport, proxy: false, headers: { 'X-Trace-Id': 'trace-123', Authorization: 'Bearer token-abc', }, }); const headers = normalizeHeaders(getCapturedOptions().headers); expect(headers['x-trace-id']).to.equal('trace-123'); expect(headers.authorization).to.equal('Bearer token-abc'); }); it('treats header names as case-insensitive when overriding', async () => { const { transport, getCapturedOptions } = createTransportCapture(); await axios.get('http://example.com/case-insensitive', { transport, proxy: false, headers: { authorization: 'Bearer old-token', AuThOrIzAtIoN: 'Bearer new-token', }, }); const headers = normalizeHeaders(getCapturedOptions().headers); expect(headers.authorization).to.equal('Bearer new-token'); }); it('sets content-type for json post payloads', async () => { const { transport, getCapturedOptions } = createTransportCapture(); await axios.post( 'http://example.com/post-json', { name: 'widget' }, { transport, proxy: false, } ); const headers = normalizeHeaders(getCapturedOptions().headers); expect(headers['content-type']).to.contain('application/json'); }); it('does not force content-type for get requests without body', async () => { const { transport, getCapturedOptions } = createTransportCapture(); await axios.get('http://example.com/get-no-body', { transport, proxy: false, }); const headers = normalizeHeaders(getCapturedOptions().headers); expect(headers['content-type']).to.be.undefined; }); }); axios-axios-2d06f96/tests/smoke/cjs/tests/http2.smoke.test.cjs000066400000000000000000000041201521272452000243530ustar00rootroot00000000000000const axios = require('axios'); const { describe, it } = require('mocha'); const { expect } = require('chai'); describe('http2 compat (dist export only)', () => { it('keeps instance-level httpVersion and http2Options in request config', async () => { const client = axios.create({ baseURL: 'https://example.com', httpVersion: 2, http2Options: { rejectUnauthorized: false, }, }); const response = await client.get('/resource', { adapter: async (config) => ({ data: { httpVersion: config.httpVersion, http2Options: config.http2Options, }, status: 200, statusText: 'OK', headers: {}, config, }), }); expect(response.data.httpVersion).to.equal(2); expect(response.data.http2Options).to.deep.equal({ rejectUnauthorized: false, }); }); it('merges request http2Options with instance http2Options', async () => { const client = axios.create({ baseURL: 'https://example.com', httpVersion: 2, http2Options: { rejectUnauthorized: false, sessionTimeout: 1000, }, }); const response = await client.get('/resource', { http2Options: { sessionTimeout: 5000, customFlag: true, }, adapter: async (config) => ({ data: config.http2Options, status: 200, statusText: 'OK', headers: {}, config, }), }); expect(response.data).to.deep.equal({ rejectUnauthorized: false, sessionTimeout: 5000, customFlag: true, }); }); it('allows request-level httpVersion override', async () => { const client = axios.create({ baseURL: 'https://example.com', httpVersion: 2, }); const response = await client.get('/resource', { httpVersion: 1, adapter: async (config) => ({ data: { httpVersion: config.httpVersion, }, status: 200, statusText: 'OK', headers: {}, config, }), }); expect(response.data.httpVersion).to.equal(1); }); }); axios-axios-2d06f96/tests/smoke/cjs/tests/import.smoke.test.cjs000066400000000000000000000011621521272452000246270ustar00rootroot00000000000000const axios = require('axios'); const { describe, it } = require('mocha'); const { expect } = require('chai'); const { CanceledError, AxiosError, AxiosHeaders } = axios; describe('CommonJS importing', () => { it('should import axios', () => { expect(typeof axios).to.be.equal('function'); }); it('should import CanceledError', () => { expect(typeof CanceledError).to.be.equal('function'); }); it('should import AxiosError', () => { expect(typeof AxiosError).to.be.equal('function'); }); it('should import AxiosHeaders', () => { expect(typeof AxiosHeaders).to.be.equal('function'); }); }); axios-axios-2d06f96/tests/smoke/cjs/tests/instance.smoke.test.cjs000066400000000000000000000074151521272452000251300ustar00rootroot00000000000000const { EventEmitter } = require('events'); const { PassThrough } = require('stream'); const axios = require('axios'); const { describe, it } = require('mocha'); const { expect } = require('chai'); const createTransportCapture = (responseBody) => { const calls = []; const transport = { request(options, onResponse) { calls.push(options); const req = new EventEmitter(); req.destroyed = false; req.setTimeout = () => {}; req.write = () => true; req.destroy = () => { req.destroyed = true; }; req.close = req.destroy; req.end = () => { const res = new PassThrough(); res.statusCode = 200; res.statusMessage = 'OK'; res.headers = { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end(responseBody || '{"ok":true}'); }; return req; }, }; return { transport, getCalls: () => calls, }; }; describe('instance compat (dist export only)', () => { it('creates isolated instances with separate defaults', async () => { const { transport, getCalls } = createTransportCapture(); const clientA = axios.create({ baseURL: 'http://example.com/api-a', headers: { 'X-App': 'A', }, }); const clientB = axios.create({ baseURL: 'http://example.com/api-b', headers: { 'X-App': 'B', }, }); await clientA.get('/users', { transport, proxy: false }); await clientB.get('/users', { transport, proxy: false }); const [callA, callB] = getCalls(); expect(callA.path).to.equal('/api-a/users'); expect(callB.path).to.equal('/api-b/users'); expect(callA.headers['X-App']).to.equal('A'); expect(callB.headers['X-App']).to.equal('B'); }); it('supports callable instance form instance(config)', async () => { const { transport, getCalls } = createTransportCapture(); const client = axios.create({ baseURL: 'http://example.com', }); await client({ url: '/status', method: 'get', transport, proxy: false, }); expect(getCalls()).to.have.lengthOf(1); expect(getCalls()[0].method).to.equal('GET'); expect(getCalls()[0].path).to.equal('/status'); }); it('applies instance request interceptors', async () => { const { transport, getCalls } = createTransportCapture(); const client = axios.create({ baseURL: 'http://example.com', }); client.interceptors.request.use((config) => { config.headers = config.headers || {}; config.headers['X-From-Interceptor'] = 'yes'; return config; }); await client.get('/intercepted', { transport, proxy: false }); expect(getCalls()).to.have.lengthOf(1); expect(getCalls()[0].headers['X-From-Interceptor']).to.equal('yes'); }); it('applies instance response interceptors', async () => { const { transport } = createTransportCapture('{"name":"axios"}'); const client = axios.create({ baseURL: 'http://example.com', }); client.interceptors.response.use((response) => { response.data = Object.assign({}, response.data, { intercepted: true, }); return response; }); const response = await client.get('/response-interceptor', { transport, proxy: false, }); expect(response.data).to.deep.equal({ name: 'axios', intercepted: true, }); }); it('builds URLs with getUri from instance defaults and request params', () => { const client = axios.create({ baseURL: 'http://example.com/api', params: { apiKey: 'abc', }, }); const uri = client.getUri({ url: '/users', params: { page: 2, }, }); expect(uri).to.equal('http://example.com/api/users?apiKey=abc&page=2'); }); }); axios-axios-2d06f96/tests/smoke/cjs/tests/interceptors.smoke.test.cjs000066400000000000000000000076021521272452000260430ustar00rootroot00000000000000const { EventEmitter } = require('events'); const { PassThrough } = require('stream'); const axios = require('axios'); const { describe, it } = require('mocha'); const { expect } = require('chai'); const createTransport = (responseBody) => { const calls = []; const transport = { request(options, onResponse) { calls.push(options); const req = new EventEmitter(); req.destroyed = false; req.setTimeout = () => {}; req.write = () => true; req.destroy = () => { req.destroyed = true; }; req.close = req.destroy; req.end = () => { const res = new PassThrough(); res.statusCode = 200; res.statusMessage = 'OK'; res.headers = { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end(responseBody || '{"value":"ok"}'); }; return req; }, }; return { transport, getCalls: () => calls, }; }; describe('interceptors compat (dist export only)', () => { it('applies request interceptors before dispatch', async () => { const { transport, getCalls } = createTransport(); const client = axios.create(); client.interceptors.request.use((config) => { config.headers = config.headers || {}; config.headers['X-One'] = '1'; return config; }); client.interceptors.request.use((config) => { config.headers['X-Two'] = '2'; return config; }); await client.get('http://example.com/resource', { transport, proxy: false, }); expect(getCalls()).to.have.lengthOf(1); expect(getCalls()[0].headers['X-One']).to.equal('1'); expect(getCalls()[0].headers['X-Two']).to.equal('2'); }); it('applies response interceptors in registration order', async () => { const { transport } = createTransport('{"n":1}'); const client = axios.create(); client.interceptors.response.use((response) => { response.data.n += 1; return response; }); client.interceptors.response.use((response) => { response.data.n *= 10; return response; }); const response = await client.get('http://example.com/resource', { transport, proxy: false, }); expect(response.data.n).to.equal(20); }); it('supports ejecting request interceptors', async () => { const { transport, getCalls } = createTransport(); const client = axios.create(); const id = client.interceptors.request.use((config) => { config.headers = config.headers || {}; config.headers['X-Ejected'] = 'yes'; return config; }); client.interceptors.request.eject(id); await client.get('http://example.com/resource', { transport, proxy: false, }); expect(getCalls()).to.have.lengthOf(1); expect(getCalls()[0].headers['X-Ejected']).to.be.undefined; }); it('supports async request interceptors', async () => { const { transport, getCalls } = createTransport(); const client = axios.create(); client.interceptors.request.use(async (config) => { await Promise.resolve(); config.headers = config.headers || {}; config.headers['X-Async'] = 'true'; return config; }); await client.get('http://example.com/resource', { transport, proxy: false, }); expect(getCalls()[0].headers['X-Async']).to.equal('true'); }); it('propagates errors thrown by request interceptors', async () => { const { transport, getCalls } = createTransport(); const client = axios.create(); client.interceptors.request.use(() => { throw new Error('blocked-by-interceptor'); }); const err = await client .get('http://example.com/resource', { transport, proxy: false, }) .catch((e) => e); expect(err).to.be.instanceOf(Error); expect(err.message).to.contain('blocked-by-interceptor'); expect(getCalls()).to.have.lengthOf(0); }); }); axios-axios-2d06f96/tests/smoke/cjs/tests/progress.smoke.test.cjs000066400000000000000000000057221521272452000251670ustar00rootroot00000000000000const { Readable, Writable, PassThrough } = require('stream'); const axios = require('axios'); const { describe, it } = require('mocha'); const { expect } = require('chai'); const createProgressTransport = (config) => { const opts = config || {}; const responseChunks = opts.responseChunks || ['ok']; const responseHeaders = opts.responseHeaders || {}; return { request(_options, onResponse) { const req = new Writable({ write(_chunk, _encoding, callback) { callback(); }, }); req.destroyed = false; req.setTimeout = () => {}; req.close = () => { req.destroyed = true; }; const originalDestroy = req.destroy.bind(req); req.destroy = (...args) => { req.destroyed = true; return originalDestroy(...args); }; const originalEnd = req.end.bind(req); req.end = (...args) => { originalEnd(...args); const res = new PassThrough(); res.statusCode = 200; res.statusMessage = 'OK'; res.headers = Object.assign( { 'content-type': 'text/plain', }, responseHeaders ); res.req = req; onResponse(res); responseChunks.forEach((chunk) => { res.write(chunk); }); res.end(); }; return req; }, }; }; describe('progress compat (dist export only)', () => { it('emits upload progress events for stream payloads', async () => { const samples = []; const payload = ['abc', 'def', 'ghi']; const total = payload.join('').length; await axios.post('http://example.com/upload', Readable.from(payload), { proxy: false, headers: { 'Content-Length': String(total), }, onUploadProgress: ({ loaded, total: reportedTotal, upload }) => { samples.push({ loaded, total: reportedTotal, upload }); }, transport: createProgressTransport({ responseChunks: ['uploaded'], }), }); expect(samples.length).to.be.greaterThan(0); expect(samples[samples.length - 1]).to.deep.include({ loaded: total, total, upload: true, }); }); it('emits download progress events', async () => { const samples = []; const chunks = ['ab', 'cd', 'ef']; const total = chunks.join('').length; const response = await axios.get('http://example.com/download', { proxy: false, responseType: 'text', onDownloadProgress: ({ loaded, total: reportedTotal, download }) => { samples.push({ loaded, total: reportedTotal, download }); }, transport: createProgressTransport({ responseChunks: chunks, responseHeaders: { 'content-length': String(total), }, }), }); expect(response.data).to.equal('abcdef'); expect(samples.length).to.be.greaterThan(0); expect(samples[samples.length - 1]).to.deep.include({ loaded: total, total, download: true, }); }); }); axios-axios-2d06f96/tests/smoke/cjs/tests/rateLimit.smoke.test.cjs000066400000000000000000000053201521272452000252470ustar00rootroot00000000000000const { EventEmitter } = require('events'); const { PassThrough } = require('stream'); const axios = require('axios'); const { describe, it } = require('mocha'); const { expect } = require('chai'); const createTransportCapture = () => { let capturedOptions; const transport = { request(options, onResponse) { capturedOptions = options; const req = new EventEmitter(); req.destroyed = false; req.setTimeout = () => {}; req.write = () => true; req.destroy = () => { req.destroyed = true; }; req.close = req.destroy; req.end = () => { const res = new PassThrough(); res.statusCode = 200; res.statusMessage = 'OK'; res.headers = { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end('{"ok":true}'); }; return req; }, }; return { transport, getCapturedOptions: () => capturedOptions, }; }; describe('rateLimit compat (dist export only)', () => { it('accepts numeric maxRate config', async () => { const response = await axios.get('http://example.com/rate', { maxRate: 1024, adapter: async (config) => ({ data: { maxRate: config.maxRate }, status: 200, statusText: 'OK', headers: {}, config, }), }); expect(response.data.maxRate).to.equal(1024); }); it('accepts tuple maxRate config [upload, download]', async () => { const response = await axios.get('http://example.com/rate', { maxRate: [2048, 4096], adapter: async (config) => ({ data: { maxRate: config.maxRate }, status: 200, statusText: 'OK', headers: {}, config, }), }); expect(response.data.maxRate).to.deep.equal([2048, 4096]); }); it('merges instance and request maxRate values', async () => { const client = axios.create({ maxRate: [1000, 2000], }); const response = await client.get('http://example.com/rate', { maxRate: [3000, 4000], adapter: async (config) => ({ data: { maxRate: config.maxRate }, status: 200, statusText: 'OK', headers: {}, config, }), }); expect(response.data.maxRate).to.deep.equal([3000, 4000]); }); it('supports maxRate in node transport flow without errors', async () => { const { transport, getCapturedOptions } = createTransportCapture(); const response = await axios.get('http://example.com/rate', { proxy: false, maxRate: [1500, 2500], transport, }); expect(response.status).to.equal(200); expect(getCapturedOptions().method).to.equal('GET'); expect(getCapturedOptions().path).to.equal('/rate'); }); }); axios-axios-2d06f96/tests/smoke/cjs/tests/timeout.smoke.test.cjs000066400000000000000000000063731521272452000250140ustar00rootroot00000000000000const { EventEmitter } = require('events'); const { PassThrough } = require('stream'); const axios = require('axios'); const { describe, it } = require('mocha'); const { expect } = require('chai'); const createTransport = (config) => { const opts = config || {}; return { request(_options, onResponse) { const req = new EventEmitter(); req.destroyed = false; req._timeoutCallback = null; req.setTimeout = (_ms, callback) => { req._timeoutCallback = callback; }; req.write = () => true; req.destroy = () => { req.destroyed = true; }; req.close = req.destroy; req.end = () => { if (opts.triggerTimeout && req._timeoutCallback) { req._timeoutCallback(); return; } const res = new PassThrough(); res.statusCode = 200; res.statusMessage = 'OK'; res.headers = { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end(opts.body || '{"ok":true}'); }; return req; }, }; }; describe('timeout compat (dist export only)', () => { it('rejects with ECONNABORTED on timeout', async () => { const err = await axios .get('http://example.com/timeout', { proxy: false, timeout: 25, transport: createTransport({ triggerTimeout: true }), }) .catch((e) => e); expect(axios.isAxiosError(err)).to.equal(true); expect(err.code).to.equal('ECONNABORTED'); expect(err.message).to.equal('timeout of 25ms exceeded'); }); it('uses timeoutErrorMessage when provided', async () => { const err = await axios .get('http://example.com/timeout', { proxy: false, timeout: 25, timeoutErrorMessage: 'custom timeout', transport: createTransport({ triggerTimeout: true }), }) .catch((e) => e); expect(axios.isAxiosError(err)).to.equal(true); expect(err.code).to.equal('ECONNABORTED'); expect(err.message).to.equal('custom timeout'); }); it('accepts timeout as a numeric string', async () => { const err = await axios .get('http://example.com/timeout', { proxy: false, timeout: '30', transport: createTransport({ triggerTimeout: true }), }) .catch((e) => e); expect(axios.isAxiosError(err)).to.equal(true); expect(err.code).to.equal('ECONNABORTED'); expect(err.message).to.equal('timeout of 30ms exceeded'); }); it('rejects with ERR_BAD_OPTION_VALUE when timeout is not parsable', async () => { const err = await axios .get('http://example.com/timeout', { proxy: false, timeout: { invalid: true }, transport: createTransport(), }) .catch((e) => e); expect(axios.isAxiosError(err)).to.equal(true); expect(err.code).to.equal('ERR_BAD_OPTION_VALUE'); expect(err.message).to.equal('error trying to parse `config.timeout` to int'); }); it('does not time out when timeout is 0', async () => { const response = await axios.get('http://example.com/no-timeout', { proxy: false, timeout: 0, transport: createTransport({ body: '{"ok":true}' }), }); expect(response.status).to.equal(200); expect(response.data).to.deep.equal({ ok: true }); }); }); axios-axios-2d06f96/tests/smoke/cjs/tests/urlencode.smoke.test.cjs000066400000000000000000000074241521272452000253040ustar00rootroot00000000000000const { EventEmitter } = require('events'); const { PassThrough } = require('stream'); const axios = require('axios'); const { describe, it } = require('mocha'); const { expect } = require('chai'); const createEchoTransport = () => { let capturedOptions; const transport = { request(options, onResponse) { capturedOptions = options; const chunks = []; const req = new EventEmitter(); req.destroyed = false; req.setTimeout = () => {}; req.destroy = () => { req.destroyed = true; }; req.close = req.destroy; req.write = (chunk) => { chunks.push(Buffer.from(chunk)); return true; }; req.end = (chunk) => { if (chunk) { chunks.push(Buffer.from(chunk)); } const res = new PassThrough(); res.statusCode = 200; res.statusMessage = 'OK'; res.headers = { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end( JSON.stringify({ path: options.path, body: Buffer.concat(chunks).toString('utf8'), contentType: options.headers && (options.headers['Content-Type'] || options.headers['content-type']), }) ); }; return req; }, }; return { transport, getCapturedOptions: () => capturedOptions, }; }; describe('urlencode compat (dist export only)', () => { it('serializes params into request URL', async () => { const { transport } = createEchoTransport(); const response = await axios.get('http://example.com/search', { proxy: false, transport, params: { q: 'axios docs', page: 2, }, }); expect(response.data.path).to.equal('/search?q=axios+docs&page=2'); }); it('supports custom paramsSerializer function', async () => { const { transport } = createEchoTransport(); const response = await axios.get('http://example.com/search', { proxy: false, transport, params: { q: 'ignored' }, paramsSerializer: () => 'fixed=1', }); expect(response.data.path).to.equal('/search?fixed=1'); }); it('supports URLSearchParams payloads', async () => { const { transport } = createEchoTransport(); const payload = new URLSearchParams(); payload.append('name', 'axios'); payload.append('mode', 'compat'); const response = await axios.post('http://example.com/form', payload, { proxy: false, transport, }); expect(response.data.body).to.equal('name=axios&mode=compat'); expect(response.data.contentType).to.contain('application/x-www-form-urlencoded'); }); it('serializes object payload when content-type is application/x-www-form-urlencoded', async () => { const { transport } = createEchoTransport(); const response = await axios.post( 'http://example.com/form', { name: 'axios', mode: 'compat', }, { proxy: false, transport, headers: { 'content-type': 'application/x-www-form-urlencoded', }, } ); expect(response.data.body).to.equal('name=axios&mode=compat'); expect(response.data.contentType).to.contain('application/x-www-form-urlencoded'); }); it('respects formSerializer options for index formatting', async () => { const { transport } = createEchoTransport(); const response = await axios.post( 'http://example.com/form', { arr: ['1', '2'], }, { proxy: false, transport, headers: { 'content-type': 'application/x-www-form-urlencoded', }, formSerializer: { indexes: true, }, } ); expect(response.data.body).to.equal('arr%5B0%5D=1&arr%5B1%5D=2'); }); }); axios-axios-2d06f96/tests/smoke/deno/000077500000000000000000000000001521272452000175255ustar00rootroot00000000000000axios-axios-2d06f96/tests/smoke/deno/deno.json000066400000000000000000000003511521272452000213440ustar00rootroot00000000000000{ "imports": { "@std/assert": "jsr:@std/assert@1.0.19", "axios": "../../../dist/esm/axios.js" }, "tasks": { "test": "deno test --allow-read tests/" }, "test": { "include": ["tests/**/*.smoke.test.ts"] } } axios-axios-2d06f96/tests/smoke/deno/deno.lock000066400000000000000000000010171521272452000213230ustar00rootroot00000000000000{ "version": "5", "specifiers": { "jsr:@std/assert@1.0.19": "1.0.19", "jsr:@std/internal@^1.0.12": "1.0.12" }, "jsr": { "@std/assert@1.0.19": { "integrity": "eaada96ee120cb980bc47e040f82814d786fe8162ecc53c91d8df60b8755991e", "dependencies": [ "jsr:@std/internal" ] }, "@std/internal@1.0.12": { "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" } }, "workspace": { "dependencies": [ "jsr:@std/assert@1.0.19" ] } } axios-axios-2d06f96/tests/smoke/deno/tests/000077500000000000000000000000001521272452000206675ustar00rootroot00000000000000axios-axios-2d06f96/tests/smoke/deno/tests/cancel.smoke.test.ts000066400000000000000000000040131521272452000245550ustar00rootroot00000000000000import { assertEquals } from '@std/assert'; import axios from 'axios'; const env = (fetch: any) => ({ fetch, Request, Response, }); Deno.test('cancel: pre-aborted AbortController cancels request', async () => { let fetchCallCount = 0; const fetch = async () => { fetchCallCount += 1; return new Response(JSON.stringify({ ok: true }), { status: 200, headers: { 'Content-Type': 'application/json' }, }); }; const controller = new AbortController(); controller.abort(); const err = await axios .get('https://example.com/cancel', { adapter: 'fetch', signal: controller.signal, env: env(fetch), }) .catch((e: any) => e); assertEquals(axios.isCancel(err), true); assertEquals(err.code, 'ERR_CANCELED'); assertEquals(fetchCallCount, 0); }); Deno.test('cancel: in-flight abort cancels request', async () => { const fetch = (_input: any, init?: any) => new Promise((_resolve, reject) => { const timeout = setTimeout(() => { reject(new DOMException('The operation was aborted', 'AbortError')); }, 20); if (init?.signal) { if (init.signal.aborted) { clearTimeout(timeout); reject(new DOMException('The operation was aborted', 'AbortError')); return; } init.signal.addEventListener( 'abort', () => { clearTimeout(timeout); reject(new DOMException('The operation was aborted', 'AbortError')); }, { once: true } ); } }); const controller = new AbortController(); const request = axios.get('https://example.com/in-flight', { adapter: 'fetch', signal: controller.signal, env: env(fetch), }); controller.abort(); const err = await request.catch((e: any) => e); assertEquals(axios.isCancel(err), true); assertEquals(err.code, 'ERR_CANCELED'); }); Deno.test('cancel: isCancel returns false for plain Error', () => { assertEquals(axios.isCancel(new Error('random')), false); }); axios-axios-2d06f96/tests/smoke/deno/tests/error.smoke.test.ts000066400000000000000000000025171521272452000244700ustar00rootroot00000000000000import { assertEquals } from '@std/assert'; import axios from 'axios'; const env = (fetch: any) => ({ fetch, Request, Response, }); Deno.test('errors: rejects with AxiosError for 500', async () => { const fetch = async () => new Response(JSON.stringify({ error: 'boom' }), { status: 500, statusText: 'Internal Server Error', headers: { 'Content-Type': 'application/json' }, }); const err = await axios .get('https://example.com/fail', { adapter: 'fetch', env: env(fetch), }) .catch((e: any) => e); assertEquals(axios.isAxiosError(err), true); assertEquals(err.response.status, 500); assertEquals(err.response.data, { error: 'boom' }); }); Deno.test('errors: rejects with AxiosError for 404', async () => { const fetch = async () => new Response(JSON.stringify({ error: 'missing' }), { status: 404, statusText: 'Not Found', headers: { 'Content-Type': 'application/json' }, }); const err = await axios .get('https://example.com/missing', { adapter: 'fetch', env: env(fetch), }) .catch((e: any) => e); assertEquals(axios.isAxiosError(err), true); assertEquals(err.response.status, 404); }); Deno.test('errors: isAxiosError returns false for plain Error', () => { assertEquals(axios.isAxiosError(new Error('plain')), false); }); axios-axios-2d06f96/tests/smoke/deno/tests/fetch.smoke.test.ts000066400000000000000000000061221521272452000244240ustar00rootroot00000000000000import { assertEquals } from '@std/assert'; import axios from 'axios'; const createFetchMock = ( responseFactory?: (input: any, init: any) => Response | Promise ) => { const calls: Array<{ input: any; init: any }> = []; const mockFetch = async (input: any, init: any = {}) => { calls.push({ input, init }); if (responseFactory) { return responseFactory(input, init); } return new Response(JSON.stringify({ ok: true }), { status: 200, headers: { 'Content-Type': 'application/json' }, }); }; return { mockFetch, getCalls: () => calls, }; }; const getRequestMeta = async (input: any, init: any) => { const request = input instanceof Request ? input : new Request(input, init); return { url: request.url, method: request.method, body: request.method === 'GET' || request.method === 'HEAD' ? undefined : await request.clone().text(), }; }; const env = (fetch: any) => ({ fetch, Request, Response, }); Deno.test('fetch adapter: GET resolves JSON response', async () => { const { mockFetch, getCalls } = createFetchMock(); const response = await axios.get('https://example.com/users', { adapter: 'fetch', env: env(mockFetch), }); assertEquals(response.status, 200); assertEquals(response.data, { ok: true }); assertEquals(getCalls().length, 1); }); Deno.test('fetch adapter: forwards HTTP methods', async () => { const run = async ( method: 'delete' | 'head' | 'options' | 'post' | 'put' | 'patch', expected: string ) => { const { mockFetch, getCalls } = createFetchMock(); if (method === 'post' || method === 'put' || method === 'patch') { await axios[method]( 'https://example.com/items', { name: 'widget' }, { adapter: 'fetch', env: env(mockFetch), } ); } else { await axios[method]('https://example.com/items', { adapter: 'fetch', env: env(mockFetch), }); } const { input, init } = getCalls()[0]; const meta = await getRequestMeta(input, init); assertEquals(meta.method, expected); }; await run('delete', 'DELETE'); await run('head', 'HEAD'); await run('options', 'OPTIONS'); await run('post', 'POST'); await run('put', 'PUT'); await run('patch', 'PATCH'); }); Deno.test('fetch adapter: serializes JSON body for POST', async () => { const { mockFetch, getCalls } = createFetchMock(); await axios.post( 'https://example.com/items', { name: 'widget' }, { adapter: 'fetch', env: env(mockFetch), } ); const { input, init } = getCalls()[0]; const meta = await getRequestMeta(input, init); assertEquals(meta.body, JSON.stringify({ name: 'widget' })); }); Deno.test('fetch adapter: forwards full URL', async () => { const { mockFetch, getCalls } = createFetchMock(); await axios.get('https://example.com/users', { adapter: 'fetch', env: env(mockFetch), }); const { input, init } = getCalls()[0]; const meta = await getRequestMeta(input, init); assertEquals(meta.url, 'https://example.com/users'); }); axios-axios-2d06f96/tests/smoke/deno/tests/headers.smoke.test.ts000066400000000000000000000042161521272452000247500ustar00rootroot00000000000000import { assertEquals } from '@std/assert'; import axios from 'axios'; const createFetchCapture = () => { const calls: Request[] = []; const fetch = async (input: any, init?: any) => { const request = input instanceof Request ? input : new Request(input, init); calls.push(request); return new Response(JSON.stringify({ ok: true }), { status: 200, headers: { 'Content-Type': 'application/json' }, }); }; return { fetch, getCalls: () => calls, }; }; const env = (fetch: any) => ({ fetch, Request, Response, }); Deno.test('headers: default Accept header is sent', async () => { const { fetch, getCalls } = createFetchCapture(); await axios.get('https://example.com/default-headers', { adapter: 'fetch', env: env(fetch), }); const request = getCalls()[0]; assertEquals(request.headers.get('accept'), 'application/json, text/plain, */*'); }); Deno.test('headers: custom headers are forwarded', async () => { const { fetch, getCalls } = createFetchCapture(); await axios.get('https://example.com/custom-headers', { adapter: 'fetch', headers: { 'X-Trace-Id': 'trace-123', Authorization: 'Bearer token-abc', }, env: env(fetch), }); const request = getCalls()[0]; assertEquals(request.headers.get('x-trace-id'), 'trace-123'); assertEquals(request.headers.get('authorization'), 'Bearer token-abc'); }); Deno.test('headers: content-type is set for JSON POST payload', async () => { const { fetch, getCalls } = createFetchCapture(); await axios.post( 'https://example.com/post-json', { name: 'widget' }, { adapter: 'fetch', env: env(fetch), } ); const request = getCalls()[0]; const contentType = request.headers.get('content-type') || ''; assertEquals(contentType.includes('application/json'), true); }); Deno.test('headers: content-type is absent for bodyless GET', async () => { const { fetch, getCalls } = createFetchCapture(); await axios.get('https://example.com/get-no-body', { adapter: 'fetch', env: env(fetch), }); const request = getCalls()[0]; assertEquals(request.headers.get('content-type'), null); }); axios-axios-2d06f96/tests/smoke/deno/tests/import.smoke.test.ts000066400000000000000000000012361521272452000246460ustar00rootroot00000000000000import { assertEquals } from '@std/assert'; import axios, { AxiosError, AxiosHeaders, CanceledError } from 'axios'; Deno.test('Deno importing: default export is callable', () => { assertEquals(typeof axios, 'function'); }); Deno.test('Deno importing: named exports are functions', () => { assertEquals(typeof AxiosError, 'function'); assertEquals(typeof CanceledError, 'function'); assertEquals(typeof AxiosHeaders, 'function'); }); Deno.test('Deno importing: named exports match axios properties', () => { assertEquals(axios.AxiosError, AxiosError); assertEquals(axios.CanceledError, CanceledError); assertEquals(axios.AxiosHeaders, AxiosHeaders); }); axios-axios-2d06f96/tests/smoke/esm/000077500000000000000000000000001521272452000173645ustar00rootroot00000000000000axios-axios-2d06f96/tests/smoke/esm/package-lock.json000066400000000000000000001223471521272452000226110ustar00rootroot00000000000000{ "name": "@axios/esm-smoke-tests", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@axios/esm-smoke-tests", "version": "1.0.0", "license": "MIT", "devDependencies": { "vitest": "4.1.5" } }, "node_modules/@emnapi/core": { "version": "1.9.2", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz", "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==", "dev": true, "license": "MIT", "optional": true, "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "node_modules/@emnapi/runtime": { "version": "1.9.2", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz", "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==", "dev": true, "license": "MIT", "optional": true, "dependencies": { "tslib": "^2.4.0" } }, "node_modules/@emnapi/wasi-threads": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", "dev": true, "license": "MIT", "optional": true, "dependencies": { "tslib": "^2.4.0" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "dev": true, "license": "MIT" }, "node_modules/@napi-rs/wasm-runtime": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", "dev": true, "license": "MIT", "optional": true, "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "funding": { "type": "github", "url": "https://github.com/sponsors/Brooooooklyn" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "node_modules/@oxc-project/types": { "version": "0.126.0", "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.126.0.tgz", "integrity": "sha512-oGfVtjAgwQVVpfBrbtk4e1XDyWHRFta6BS3GWVzrF8xYBT2VGQAk39yJS/wFSMrZqoiCU4oghT3Ch0HaHGIHcQ==", "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/Boshen" } }, "node_modules/@rolldown/binding-android-arm64": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.16.tgz", "integrity": "sha512-rhY3k7Bsae9qQfOtph2Pm2jZEA+s8Gmjoz4hhmx70K9iMQ/ddeae+xhRQcM5IuVx5ry1+bGfkvMn7D6MJggVSA==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "android" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-darwin-arm64": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.16.tgz", "integrity": "sha512-rNz0yK078yrNn3DrdgN+PKiMOW8HfQ92jQiXxwX8yW899ayV00MLVdaCNeVBhG/TbH3ouYVObo8/yrkiectkcQ==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-darwin-x64": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.16.tgz", "integrity": "sha512-r/OmdR00HmD4i79Z//xO06uEPOq5hRXdhw7nzkxQxwSavs3PSHa1ijntdpOiZ2mzOQ3fVVu8C1M19FoNM+dMUQ==", "cpu": [ "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-freebsd-x64": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.16.tgz", "integrity": "sha512-KcRE5w8h0OnjUatG8pldyD14/CQ5Phs1oxfR+3pKDjboHRo9+MkqQaiIZlZRpsxC15paeXme/I127tUa9TXJ6g==", "cpu": [ "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "freebsd" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.16.tgz", "integrity": "sha512-bT0guA1bpxEJ/ZhTRniQf7rNF8ybvXOuWbNIeLABaV5NGjx4EtOWBTSRGWFU9ZWVkPOZ+HNFP8RMcBokBiZ0Kg==", "cpu": [ "arm" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.16.tgz", "integrity": "sha512-+tHktCHWV8BDQSjemUqm/Jl/TPk3QObCTIjmdDy/nlupcujZghmKK2962LYrqFpWu+ai01AN/REOH3NEpqvYQg==", "cpu": [ "arm64" ], "dev": true, "libc": [ "glibc" ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-arm64-musl": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.16.tgz", "integrity": "sha512-3fPzdREH806oRLxpTWW1Gt4tQHs0TitZFOECB2xzCFLPKnSOy90gwA7P29cksYilFO6XVRY1kzga0cL2nRjKPg==", "cpu": [ "arm64" ], "dev": true, "libc": [ "musl" ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.16.tgz", "integrity": "sha512-EKwI1tSrLs7YVw+JPJT/G2dJQ1jl9qlTTTEG0V2Ok/RdOenRfBw2PQdLPyjhIu58ocdBfP7vIRN/pvMsPxs/AQ==", "cpu": [ "ppc64" ], "dev": true, "libc": [ "glibc" ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.16.tgz", "integrity": "sha512-Uknladnb3Sxqu6SEcqBldQyJUpk8NleooZEc0MbRBJ4inEhRYWZX0NJu12vNf2mqAq7gsofAxHrGghiUYjhaLQ==", "cpu": [ "s390x" ], "dev": true, "libc": [ "glibc" ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-x64-gnu": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.16.tgz", "integrity": "sha512-FIb8+uG49sZBtLTn+zt1AJ20TqVcqWeSIyoVt0or7uAWesgKaHbiBh6OpA/k9v0LTt+PTrb1Lao133kP4uVxkg==", "cpu": [ "x64" ], "dev": true, "libc": [ "glibc" ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-x64-musl": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.16.tgz", "integrity": "sha512-RuERhF9/EgWxZEXYWCOaViUWHIboceK4/ivdtQ3R0T44NjLkIIlGIAVAuCddFxsZ7vnRHtNQUrt2vR2n2slB2w==", "cpu": [ "x64" ], "dev": true, "libc": [ "musl" ], "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-openharmony-arm64": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.16.tgz", "integrity": "sha512-mXcXnvd9GpazCxeUCCnZ2+YF7nut+ZOEbE4GtaiPtyY6AkhZWbK70y1KK3j+RDhjVq5+U8FySkKRb/+w0EeUwA==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "openharmony" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-wasm32-wasi": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.16.tgz", "integrity": "sha512-3Q2KQxnC8IJOLqXmUMoYwyIPZU9hzRbnHaoV3Euz+VVnjZKcY8ktnNP8T9R4/GGQtb27C/UYKABxesKWb8lsvQ==", "cpu": [ "wasm32" ], "dev": true, "license": "MIT", "optional": true, "dependencies": { "@emnapi/core": "1.9.2", "@emnapi/runtime": "1.9.2", "@napi-rs/wasm-runtime": "^1.1.4" }, "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.16.tgz", "integrity": "sha512-tj7XRemQcOcFwv7qhpUxMTBbI5mWMlE4c1Omhg5+h8GuLXzyj8HviYgR+bB2DMDgRqUE+jiDleqSCRjx4aYk/Q==", "cpu": [ "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-win32-x64-msvc": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.16.tgz", "integrity": "sha512-PH5DRZT+F4f2PTXRXR8uJxnBq2po/xFtddyabTJVJs/ZYVHqXPEgNIr35IHTEa6bpa0Q8Awg+ymkTaGnKITw4g==", "cpu": [ "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.16.tgz", "integrity": "sha512-45+YtqxLYKDWQouLKCrpIZhke+nXxhsw+qAHVzHDVwttyBlHNBVs2K25rDXrZzhpTp9w1FlAlvweV1H++fdZoA==", "dev": true, "license": "MIT" }, "node_modules/@standard-schema/spec": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", "dev": true, "license": "MIT" }, "node_modules/@tybys/wasm-util": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", "dev": true, "license": "MIT", "optional": true, "dependencies": { "tslib": "^2.4.0" } }, "node_modules/@types/chai": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", "dev": true, "license": "MIT", "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "node_modules/@types/deep-eql": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", "dev": true, "license": "MIT" }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, "license": "MIT" }, "node_modules/@vitest/expect": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.5.tgz", "integrity": "sha512-PWBaRY5JoKuRnHlUHfpV/KohFylaDZTupcXN1H9vYryNLOnitSw60Mw9IAE2r67NbwwzBw/Cc/8q9BK3kIX8Kw==", "dev": true, "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.5", "@vitest/utils": "4.1.5", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/mocker": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.5.tgz", "integrity": "sha512-/x2EmFC4mT4NNzqvC3fmesuV97w5FC903KPmey4gsnJiMQ3Be1IlDKVaDaG8iqaLFHqJ2FVEkxZk5VmeLjIItw==", "dev": true, "license": "MIT", "dependencies": { "@vitest/spy": "4.1.5", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "msw": { "optional": true }, "vite": { "optional": true } } }, "node_modules/@vitest/pretty-format": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.5.tgz", "integrity": "sha512-7I3q6l5qr03dVfMX2wCo9FxwSJbPdwKjy2uu/YPpU3wfHvIL4QHwVRp57OfGrDFeUJ8/8QdfBKIV12FTtLn00g==", "dev": true, "license": "MIT", "dependencies": { "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/runner": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.5.tgz", "integrity": "sha512-2D+o7Pr82IEO46YPpoA/YU0neeyr6FTerQb5Ro7BUnBuv6NQtT/kmVnczngiMEBhzgqz2UZYl5gArejsyERDSQ==", "dev": true, "license": "MIT", "dependencies": { "@vitest/utils": "4.1.5", "pathe": "^2.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/snapshot": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.5.tgz", "integrity": "sha512-zypXEt4KH/XgKGPUz4eC2AvErYx0My5hfL8oDb1HzGFpEk1P62bxSohdyOmvz+d9UJwanI68MKwr2EquOaOgMQ==", "dev": true, "license": "MIT", "dependencies": { "@vitest/pretty-format": "4.1.5", "@vitest/utils": "4.1.5", "magic-string": "^0.30.21", "pathe": "^2.0.3" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/spy": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.5.tgz", "integrity": "sha512-2lNOsh6+R2Idnf1TCZqSwYlKN2E/iDlD8sgU59kYVl+OMDmvldO1VDk39smRfpUNwYpNRVn3w4YfuC7KfbBnkQ==", "dev": true, "license": "MIT", "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/utils": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.5.tgz", "integrity": "sha512-76wdkrmfXfqGjueGgnb45ITPyUi1ycZ4IHgC2bhPDUfWHklY/q3MdLOAB+TF1e6xfl8NxNY0ZYaPCFNWSsw3Ug==", "dev": true, "license": "MIT", "dependencies": { "@vitest/pretty-format": "4.1.5", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, "license": "MIT", "engines": { "node": ">=12" } }, "node_modules/chai": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", "dev": true, "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, "license": "MIT" }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, "license": "Apache-2.0", "engines": { "node": ">=8" } }, "node_modules/es-module-lexer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", "dev": true, "license": "MIT" }, "node_modules/estree-walker": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dev": true, "license": "MIT", "dependencies": { "@types/estree": "^1.0.0" } }, "node_modules/expect-type": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", "dev": true, "license": "Apache-2.0", "engines": { "node": ">=12.0.0" } }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", "engines": { "node": ">=12.0.0" }, "peerDependencies": { "picomatch": "^3 || ^4" }, "peerDependenciesMeta": { "picomatch": { "optional": true } } }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, "node_modules/lightningcss": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", "dev": true, "license": "MPL-2.0", "dependencies": { "detect-libc": "^2.0.3" }, "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "node_modules/lightningcss-android-arm64": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", "cpu": [ "arm64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "android" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-darwin-arm64": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", "cpu": [ "arm64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "darwin" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-darwin-x64": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", "cpu": [ "x64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "darwin" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-freebsd-x64": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", "cpu": [ "x64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "freebsd" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-linux-arm-gnueabihf": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", "cpu": [ "arm" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "linux" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-linux-arm64-gnu": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", "cpu": [ "arm64" ], "dev": true, "libc": [ "glibc" ], "license": "MPL-2.0", "optional": true, "os": [ "linux" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-linux-arm64-musl": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", "cpu": [ "arm64" ], "dev": true, "libc": [ "musl" ], "license": "MPL-2.0", "optional": true, "os": [ "linux" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-linux-x64-gnu": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", "cpu": [ "x64" ], "dev": true, "libc": [ "glibc" ], "license": "MPL-2.0", "optional": true, "os": [ "linux" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-linux-x64-musl": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", "cpu": [ "x64" ], "dev": true, "libc": [ "musl" ], "license": "MPL-2.0", "optional": true, "os": [ "linux" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-win32-arm64-msvc": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", "cpu": [ "arm64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "win32" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/lightningcss-win32-x64-msvc": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", "cpu": [ "x64" ], "dev": true, "license": "MPL-2.0", "optional": true, "os": [ "win32" ], "engines": { "node": ">= 12.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/parcel" } }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/ai" } ], "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, "engines": { "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, "node_modules/obug": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", "dev": true, "funding": [ "https://github.com/sponsors/sxzz", "https://opencollective.com/debug" ], "license": "MIT" }, "node_modules/pathe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, "license": "MIT" }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, "license": "ISC" }, "node_modules/picomatch": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/postcss": { "version": "8.5.10", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz", "integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/postcss/" }, { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" }, { "type": "github", "url": "https://github.com/sponsors/ai" } ], "license": "MIT", "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" } }, "node_modules/rolldown": { "version": "1.0.0-rc.16", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.16.tgz", "integrity": "sha512-rzi5WqKzEZw3SooTt7cgm4eqIoujPIyGcJNGFL7iPEuajQw7vxMHUkXylu4/vhCkJGXsgRmxqMKXUpT6FEgl0g==", "dev": true, "license": "MIT", "dependencies": { "@oxc-project/types": "=0.126.0", "@rolldown/pluginutils": "1.0.0-rc.16" }, "bin": { "rolldown": "bin/cli.mjs" }, "engines": { "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.16", "@rolldown/binding-darwin-arm64": "1.0.0-rc.16", "@rolldown/binding-darwin-x64": "1.0.0-rc.16", "@rolldown/binding-freebsd-x64": "1.0.0-rc.16", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.16", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.16", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.16", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.16", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.16", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.16", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.16", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.16", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.16", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.16", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.16" } }, "node_modules/siginfo": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true, "license": "ISC" }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true, "license": "MIT" }, "node_modules/std-env": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz", "integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==", "dev": true, "license": "MIT" }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", "dev": true, "license": "MIT" }, "node_modules/tinyexec": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz", "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==", "dev": true, "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/tinyglobby": { "version": "0.2.16", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" }, "engines": { "node": ">=12.0.0" }, "funding": { "url": "https://github.com/sponsors/SuperchupuDev" } }, "node_modules/tinyrainbow": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", "dev": true, "license": "MIT", "engines": { "node": ">=14.0.0" } }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "dev": true, "license": "0BSD", "optional": true }, "node_modules/vite": { "version": "8.0.9", "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.9.tgz", "integrity": "sha512-t7g7GVRpMXjNpa67HaVWI/8BWtdVIQPCL2WoozXXA7LBGEFK4AkkKkHx2hAQf5x1GZSlcmEDPkVLSGahxnEEZw==", "dev": true, "license": "MIT", "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.4", "postcss": "^8.5.10", "rolldown": "1.0.0-rc.16", "tinyglobby": "^0.2.16" }, "bin": { "vite": "bin/vite.js" }, "engines": { "node": "^20.19.0 || >=22.12.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.1.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "peerDependenciesMeta": { "@types/node": { "optional": true }, "@vitejs/devtools": { "optional": true }, "esbuild": { "optional": true }, "jiti": { "optional": true }, "less": { "optional": true }, "sass": { "optional": true }, "sass-embedded": { "optional": true }, "stylus": { "optional": true }, "sugarss": { "optional": true }, "terser": { "optional": true }, "tsx": { "optional": true }, "yaml": { "optional": true } } }, "node_modules/vitest": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.5.tgz", "integrity": "sha512-9Xx1v3/ih3m9hN+SbfkUyy0JAs72ap3r7joc87XL6jwF0jGg6mFBvQ1SrwaX+h8BlkX6Hz9shdd1uo6AF+ZGpg==", "dev": true, "license": "MIT", "dependencies": { "@vitest/expect": "4.1.5", "@vitest/mocker": "4.1.5", "@vitest/pretty-format": "4.1.5", "@vitest/runner": "4.1.5", "@vitest/snapshot": "4.1.5", "@vitest/spy": "4.1.5", "@vitest/utils": "4.1.5", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "bin": { "vitest": "vitest.mjs" }, "engines": { "node": "^20.0.0 || ^22.0.0 || >=24.0.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.5", "@vitest/browser-preview": "4.1.5", "@vitest/browser-webdriverio": "4.1.5", "@vitest/coverage-istanbul": "4.1.5", "@vitest/coverage-v8": "4.1.5", "@vitest/ui": "4.1.5", "happy-dom": "*", "jsdom": "*", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "@edge-runtime/vm": { "optional": true }, "@opentelemetry/api": { "optional": true }, "@types/node": { "optional": true }, "@vitest/browser-playwright": { "optional": true }, "@vitest/browser-preview": { "optional": true }, "@vitest/browser-webdriverio": { "optional": true }, "@vitest/coverage-istanbul": { "optional": true }, "@vitest/coverage-v8": { "optional": true }, "@vitest/ui": { "optional": true }, "happy-dom": { "optional": true }, "jsdom": { "optional": true }, "vite": { "optional": false } } }, "node_modules/why-is-node-running": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", "dev": true, "license": "MIT", "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" }, "engines": { "node": ">=8" } } } } axios-axios-2d06f96/tests/smoke/esm/package.json000066400000000000000000000005301521272452000216500ustar00rootroot00000000000000{ "name": "@axios/esm-smoke-tests", "version": "1.0.0", "description": "ESM smoke tests for axios", "private": true, "scripts": { "test:smoke:esm:vitest": "vitest run --config vitest.config.js --project smoke" }, "keywords": [], "author": "axios team", "license": "MIT", "devDependencies": { "vitest": "4.1.5" } } axios-axios-2d06f96/tests/smoke/esm/tests/000077500000000000000000000000001521272452000205265ustar00rootroot00000000000000axios-axios-2d06f96/tests/smoke/esm/tests/auth.smoke.test.js000066400000000000000000000064771521272452000241360ustar00rootroot00000000000000import { afterEach, describe, expect, it } from 'vitest'; import http from 'http'; import axios from 'axios'; const startServer = (handler) => { return new Promise((resolve) => { const server = http.createServer(handler); server.listen(0, '127.0.0.1', () => { resolve(server); }); }); }; const stopServer = (server) => { if (!server || !server.listening) { return Promise.resolve(); } return new Promise((resolve, reject) => { server.close((error) => { if (error) { reject(error); return; } resolve(); }); }); }; describe('auth compat (dist export only)', () => { let server; afterEach(async () => { await stopServer(server); server = undefined; }); const requestWithConfig = async (config) => { server = await startServer((req, res) => { res.setHeader('Content-Type', 'text/plain'); res.end(req.headers.authorization || ''); }); const { port } = server.address(); return axios.get( `http://127.0.0.1:${port}/`, Object.assign( { proxy: false, }, config || {} ) ); }; it('sets Basic Authorization header from auth credentials', async () => { const response = await requestWithConfig({ auth: { username: 'janedoe', password: 's00pers3cret', }, }); const expected = `Basic ${Buffer.from('janedoe:s00pers3cret', 'utf8').toString('base64')}`; expect(response.data).toBe(expected); }); it('supports auth without password', async () => { const response = await requestWithConfig({ auth: { username: 'Aladdin', }, }); const expected = `Basic ${Buffer.from('Aladdin:', 'utf8').toString('base64')}`; expect(response.data).toBe(expected); }); it('overwrites an existing Authorization header when auth is provided', async () => { const response = await requestWithConfig({ headers: { Authorization: 'Bearer token-123', }, auth: { username: 'foo', password: 'bar', }, }); const expected = `Basic ${Buffer.from('foo:bar', 'utf8').toString('base64')}`; expect(response.data).toBe(expected); }); it('uses URL credentials when auth config is not provided (node adapter behavior)', async () => { server = await startServer((req, res) => { res.setHeader('Content-Type', 'text/plain'); res.end(req.headers.authorization || ''); }); const { port } = server.address(); const response = await axios.get(`http://urluser:urlpass@127.0.0.1:${port}/`, { proxy: false, }); const expected = `Basic ${Buffer.from('urluser:urlpass', 'utf8').toString('base64')}`; expect(response.data).toBe(expected); }); it('prefers auth config over URL credentials', async () => { server = await startServer((req, res) => { res.setHeader('Content-Type', 'text/plain'); res.end(req.headers.authorization || ''); }); const { port } = server.address(); const response = await axios.get(`http://urluser:urlpass@127.0.0.1:${port}/`, { proxy: false, auth: { username: 'configuser', password: 'configpass', }, }); const expected = `Basic ${Buffer.from('configuser:configpass', 'utf8').toString('base64')}`; expect(response.data).toBe(expected); }); }); axios-axios-2d06f96/tests/smoke/esm/tests/basic.smoke.test.js000066400000000000000000000067771521272452000242610ustar00rootroot00000000000000import { describe, expect, it } from 'vitest'; import { EventEmitter } from 'events'; import { PassThrough } from 'stream'; import axios from 'axios'; const createTransportCapture = () => { let capturedOptions; const transport = { request(options, onResponse) { capturedOptions = options; const req = new EventEmitter(); req.destroyed = false; req.setTimeout = () => {}; req.write = () => true; req.end = () => { const res = new PassThrough(); res.statusCode = 200; res.statusMessage = 'OK'; res.headers = { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end('{"ok":true}'); }; req.destroy = () => { req.destroyed = true; }; req.close = req.destroy; return req; }, }; return { transport, getCapturedOptions: () => capturedOptions, }; }; const runRequest = async (run) => { const { transport, getCapturedOptions } = createTransportCapture(); await run(transport); return getCapturedOptions(); }; describe('basic compat (dist export only)', () => { it('supports the simplest axios(url) request pattern', async () => { const options = await runRequest((transport) => axios('http://example.com/users', { transport, proxy: false, }) ); expect(options.method).toBe('GET'); expect(options.path).toBe('/users'); }); it('supports get()', async () => { const options = await runRequest((transport) => axios.get('http://example.com/items?limit=10', { transport, proxy: false }) ); expect(options.method).toBe('GET'); expect(options.path).toBe('/items?limit=10'); }); it('supports delete()', async () => { const options = await runRequest((transport) => axios.delete('http://example.com/items/1', { transport, proxy: false }) ); expect(options.method).toBe('DELETE'); expect(options.path).toBe('/items/1'); }); it('supports head()', async () => { const options = await runRequest((transport) => axios.head('http://example.com/health', { transport, proxy: false }) ); expect(options.method).toBe('HEAD'); expect(options.path).toBe('/health'); }); it('supports options()', async () => { const options = await runRequest((transport) => axios.options('http://example.com/items', { transport, proxy: false }) ); expect(options.method).toBe('OPTIONS'); expect(options.path).toBe('/items'); }); it('supports post()', async () => { const options = await runRequest((transport) => axios.post( 'http://example.com/items', { name: 'widget' }, { transport, proxy: false, } ) ); expect(options.method).toBe('POST'); expect(options.path).toBe('/items'); }); it('supports put()', async () => { const options = await runRequest((transport) => axios.put( 'http://example.com/items/1', { name: 'updated-widget' }, { transport, proxy: false, } ) ); expect(options.method).toBe('PUT'); expect(options.path).toBe('/items/1'); }); it('supports patch()', async () => { const options = await runRequest((transport) => axios.patch( 'http://example.com/items/1', { status: 'active' }, { transport, proxy: false, } ) ); expect(options.method).toBe('PATCH'); expect(options.path).toBe('/items/1'); }); }); axios-axios-2d06f96/tests/smoke/esm/tests/cancel.smoke.test.js000066400000000000000000000055221521272452000244100ustar00rootroot00000000000000import { describe, expect, it } from 'vitest'; import { EventEmitter } from 'events'; import axios from 'axios'; const createPendingTransport = () => { let requestCount = 0; const transport = { request() { requestCount += 1; const req = new EventEmitter(); req.destroyed = false; req.setTimeout = () => {}; req.write = () => true; req.end = () => {}; req.destroy = () => { req.destroyed = true; }; req.close = req.destroy; return req; }, }; return { transport, getRequestCount: () => requestCount, }; }; describe('cancel compat (dist export only)', () => { it('supports cancellation with AbortController (pre-aborted signal)', async () => { const { transport, getRequestCount } = createPendingTransport(); const controller = new AbortController(); controller.abort(); try { const request = axios.get('http://example.com/resource', { signal: controller.signal, transport, proxy: false, }); controller.abort(); await request; } catch (error) { expect(error.code).toBe('ERR_CANCELED'); } expect(getRequestCount()).toBe(0); }); it('supports cancellation with AbortController (in-flight)', async () => { const { transport, getRequestCount } = createPendingTransport(); const controller = new AbortController(); try { const request = axios.get('http://example.com/resource', { signal: controller.signal, transport, proxy: false, }); controller.abort(); await request; } catch (error) { expect(error.code).toBe('ERR_CANCELED'); } expect(getRequestCount()).toBe(1); }); it('supports cancellation with CancelToken (pre-canceled token)', async () => { const { transport, getRequestCount } = createPendingTransport(); const source = axios.CancelToken.source(); source.cancel('Operation canceled by the user.'); const error = await axios .get('http://example.com/resource', { cancelToken: source.token, transport, proxy: false, }) .catch((err) => err); expect(axios.isCancel(error)).toBe(true); expect(error.code).toBe('ERR_CANCELED'); expect(getRequestCount()).toBe(0); }); it('supports cancellation with CancelToken (in-flight)', async () => { const { transport, getRequestCount } = createPendingTransport(); const source = axios.CancelToken.source(); const request = axios.get('http://example.com/resource', { cancelToken: source.token, transport, proxy: false, }); source.cancel('Operation canceled by the user.'); const error = await request.catch((err) => err); expect(axios.isCancel(error)).toBe(true); expect(error.code).toBe('ERR_CANCELED'); expect(getRequestCount()).toBe(1); }); }); axios-axios-2d06f96/tests/smoke/esm/tests/error.smoke.test.js000066400000000000000000000074761521272452000243260ustar00rootroot00000000000000import { describe, expect, it } from 'vitest'; import { EventEmitter } from 'events'; import { PassThrough } from 'stream'; import axios from 'axios'; const createTransport = (config) => { const opts = config || {}; return { request(options, onResponse) { const req = new EventEmitter(); req.destroyed = false; req.write = () => true; req.destroy = () => { req.destroyed = true; }; req.close = req.destroy; req.setTimeout = (_ms, cb) => { if (opts.timeout) { req._timeoutCallback = cb; } }; req.end = () => { if (opts.error) { req.emit('error', opts.error); return; } if (opts.timeout && req._timeoutCallback) { req._timeoutCallback(); return; } const res = new PassThrough(); res.statusCode = opts.response && opts.response.statusCode !== undefined ? opts.response.statusCode : 200; res.statusMessage = opts.response && opts.response.statusMessage ? opts.response.statusMessage : 'OK'; res.headers = opts.response && opts.response.headers ? opts.response.headers : { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end( opts.response && opts.response.body !== undefined ? opts.response.body : '{"ok":true}' ); }; return req; }, }; }; describe('error compat (dist export only)', () => { it('rejects with AxiosError for non-2xx responses by default', async () => { const err = await axios .get('http://example.com/fail', { proxy: false, transport: createTransport({ response: { statusCode: 500, statusMessage: 'Internal Server Error', body: '{"error":"boom"}', }, }), }) .catch((e) => e); expect(axios.isAxiosError(err)).toBe(true); expect(err.response.status).toBe(500); expect(err.message).toContain('500'); }); it('resolves when validateStatus allows non-2xx responses', async () => { const response = await axios.get('http://example.com/allowed', { proxy: false, validateStatus: () => true, transport: createTransport({ response: { statusCode: 500, statusMessage: 'Internal Server Error', body: '{"ok":false}', }, }), }); expect(response.status).toBe(500); expect(response.data).toEqual({ ok: false }); }); it('wraps transport errors as AxiosError', async () => { const err = await axios .get('http://example.com/network', { proxy: false, transport: createTransport({ error: new Error('socket hang up'), }), }) .catch((e) => e); expect(axios.isAxiosError(err)).toBe(true); expect(err.message).toContain('socket hang up'); expect(err.toJSON).toBeTypeOf('function'); }); it('rejects with ECONNABORTED on timeout', async () => { const err = await axios .get('http://example.com/timeout', { proxy: false, timeout: 10, transport: createTransport({ timeout: true }), }) .catch((e) => e); expect(axios.isAxiosError(err)).toBe(true); expect(err.code).toBe('ECONNABORTED'); expect(err.message).toBe('timeout of 10ms exceeded'); }); it('uses timeoutErrorMessage when provided', async () => { const err = await axios .get('http://example.com/timeout', { proxy: false, timeout: 25, timeoutErrorMessage: 'custom timeout message', transport: createTransport({ timeout: true }), }) .catch((e) => e); expect(axios.isAxiosError(err)).toBe(true); expect(err.code).toBe('ECONNABORTED'); expect(err.message).toBe('custom timeout message'); }); }); axios-axios-2d06f96/tests/smoke/esm/tests/fetch.smoke.test.js000066400000000000000000000073151521272452000242560ustar00rootroot00000000000000import { describe, expect, it } from 'vitest'; import axios from 'axios'; const createFetchMock = (responseFactory) => { const calls = []; const mockFetch = async (input, init) => { calls.push({ input, init: init || {} }); if (responseFactory) { return responseFactory(input, init || {}); } return new Response(JSON.stringify({ ok: true }), { status: 200, headers: { 'Content-Type': 'application/json' }, }); }; return { mockFetch, getCalls: () => calls, }; }; describe('fetch compat (dist export only)', () => { it('uses fetch adapter and resolves JSON response', async () => { const { mockFetch, getCalls } = createFetchMock(); const response = await axios.get('https://example.com/users', { adapter: 'fetch', env: { fetch: mockFetch, Request, Response, }, }); expect(response.data).toEqual({ ok: true }); expect(response.status).toBe(200); expect(getCalls()).toHaveLength(1); }); it('sends method, headers and body for post requests', async () => { const { mockFetch, getCalls } = createFetchMock(async (input, init) => { const requestInit = init || {}; const isRequest = input && typeof input !== 'string'; const method = isRequest ? input.method : requestInit.method; const body = isRequest && typeof input.clone === 'function' ? await input.clone().text() : requestInit.body; let contentType; if (isRequest && input.headers) { contentType = input.headers.get('content-type'); } else if (requestInit.headers) { contentType = requestInit.headers['Content-Type'] || requestInit.headers['content-type']; } return new Response( JSON.stringify({ url: typeof input === 'string' ? input : input.url, method, contentType, body, }), { status: 200, headers: { 'Content-Type': 'application/json' }, } ); }); const response = await axios.post( 'https://example.com/items', { name: 'widget' }, { adapter: 'fetch', env: { fetch: mockFetch, Request, Response, }, } ); expect(getCalls()).toHaveLength(1); expect(response.data.url).toBe('https://example.com/items'); expect(response.data.method).toBe('POST'); expect(response.data.contentType).toContain('application/json'); expect(response.data.body).toBe(JSON.stringify({ name: 'widget' })); }); it('rejects non-2xx fetch responses by default', async () => { const { mockFetch } = createFetchMock( () => new Response(JSON.stringify({ error: 'boom' }), { status: 500, statusText: 'Internal Server Error', headers: { 'Content-Type': 'application/json' }, }) ); const err = await axios .get('https://example.com/fail', { adapter: 'fetch', env: { fetch: mockFetch, Request, Response, }, }) .catch((e) => e); expect(axios.isAxiosError(err)).toBe(true); expect(err.response.status).toBe(500); }); it('supports cancellation with AbortController in fetch mode', async () => { const { mockFetch } = createFetchMock(); const controller = new AbortController(); controller.abort(); const err = await axios .get('https://example.com/cancel', { adapter: 'fetch', signal: controller.signal, env: { fetch: mockFetch, Request, Response, }, }) .catch((e) => e); expect(axios.isCancel(err)).toBe(true); expect(err.code).toBe('ERR_CANCELED'); }); }); axios-axios-2d06f96/tests/smoke/esm/tests/files.smoke.test.js000066400000000000000000000070301521272452000242610ustar00rootroot00000000000000import { describe, expect, it } from 'vitest'; import { PassThrough, Readable, Writable } from 'stream'; import axios from 'axios'; const createCaptureTransport = (buildResponse) => { return { request(options, onResponse) { const chunks = []; const req = new Writable({ write(chunk, _encoding, callback) { chunks.push(Buffer.from(chunk)); callback(); }, }); req.destroyed = false; req.setTimeout = () => {}; req.close = () => { req.destroyed = true; }; const originalDestroy = req.destroy.bind(req); req.destroy = (...args) => { req.destroyed = true; return originalDestroy(...args); }; const originalEnd = req.end.bind(req); req.end = (...args) => { originalEnd(...args); const body = Buffer.concat(chunks); const response = buildResponse ? buildResponse(body, options) : {}; const res = new PassThrough(); res.statusCode = response.statusCode !== undefined ? response.statusCode : 200; res.statusMessage = response.statusMessage || 'OK'; res.headers = response.headers || { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end(response.body || JSON.stringify({ size: body.length })); }; req.on('error', () => {}); return req; }, }; }; describe('files compat (dist export only)', () => { it('supports posting Buffer payloads', async () => { const source = Buffer.from('binary-\x00-data', 'utf8'); const response = await axios.post('http://example.com/upload', source, { proxy: false, transport: createCaptureTransport((body) => ({ body: JSON.stringify({ echoed: body.toString('base64') }), })), }); expect(response.data.echoed).toBe(source.toString('base64')); }); it('supports posting Uint8Array payloads', async () => { const source = Uint8Array.from([1, 2, 3, 4, 255]); const response = await axios.post('http://example.com/upload', source, { proxy: false, transport: createCaptureTransport((body) => ({ body: JSON.stringify({ echoed: Array.from(body.values()) }), })), }); expect(response.data.echoed).toEqual([1, 2, 3, 4, 255]); }); it('supports posting Readable stream payloads', async () => { const streamData = ['hello ', 'stream ', 'world']; const source = Readable.from(streamData); const response = await axios.post('http://example.com/upload', source, { proxy: false, headers: { 'Content-Type': 'application/octet-stream' }, transport: createCaptureTransport((body, options) => ({ body: JSON.stringify({ text: body.toString('utf8'), contentType: options.headers && (options.headers['Content-Type'] || options.headers['content-type']), }), })), }); expect(response.data.text).toBe('hello stream world'); expect(response.data.contentType).toContain('application/octet-stream'); }); it('supports binary downloads with responseType=arraybuffer', async () => { const binary = Buffer.from([0xde, 0xad, 0xbe, 0xef]); const response = await axios.get('http://example.com/file.bin', { proxy: false, responseType: 'arraybuffer', transport: createCaptureTransport(() => ({ headers: { 'content-type': 'application/octet-stream' }, body: binary, })), }); expect(Buffer.isBuffer(response.data)).toBe(true); expect(response.data.equals(binary)).toBe(true); }); }); axios-axios-2d06f96/tests/smoke/esm/tests/formData.smoke.test.js000066400000000000000000000063331521272452000247210ustar00rootroot00000000000000import { describe, expect, it } from 'vitest'; import { Writable, PassThrough } from 'stream'; import axios from 'axios'; const createCaptureTransport = (buildResponse) => { return { request(options, onResponse) { const chunks = []; const req = new Writable({ write(chunk, _encoding, callback) { chunks.push(Buffer.from(chunk)); callback(); }, }); req.destroyed = false; req.setTimeout = () => {}; req.write = req.write.bind(req); req.close = () => { req.destroyed = true; }; const originalDestroy = req.destroy.bind(req); req.destroy = (...args) => { req.destroyed = true; return originalDestroy(...args); }; const originalEnd = req.end.bind(req); req.end = (...args) => { originalEnd(...args); const body = Buffer.concat(chunks); const response = buildResponse ? buildResponse(body, options) : {}; const res = new PassThrough(); res.statusCode = response.statusCode !== undefined ? response.statusCode : 200; res.statusMessage = response.statusMessage || 'OK'; res.headers = response.headers || { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end(response.body || JSON.stringify({ ok: true })); }; return req; }, }; }; const bodyAsUtf8 = (value) => { return Buffer.isBuffer(value) ? value.toString('utf8') : String(value); }; describe('formData compat (dist export only)', () => { it('supports posting FormData instances', async () => { const form = new FormData(); form.append('username', 'janedoe'); form.append('role', 'admin'); const response = await axios.post('http://example.com/form', form, { proxy: false, transport: createCaptureTransport((body, options) => ({ body: JSON.stringify({ contentType: options.headers && (options.headers['Content-Type'] || options.headers['content-type']), payload: bodyAsUtf8(body), }), })), }); expect(response.data.contentType).toContain('multipart/form-data'); expect(response.data.payload).toContain('name="username"'); expect(response.data.payload).toContain('janedoe'); expect(response.data.payload).toContain('name="role"'); expect(response.data.payload).toContain('admin'); }); it('supports axios.postForm helper', async () => { const response = await axios.postForm( 'http://example.com/post-form', { project: 'axios', mode: 'compat', }, { proxy: false, transport: createCaptureTransport((body, options) => ({ body: JSON.stringify({ contentType: options.headers && (options.headers['Content-Type'] || options.headers['content-type']), payload: bodyAsUtf8(body), }), })), } ); expect(response.data.contentType).toContain('multipart/form-data'); expect(response.data.payload).toContain('name="project"'); expect(response.data.payload).toContain('axios'); expect(response.data.payload).toContain('name="mode"'); expect(response.data.payload).toContain('compat'); }); }); axios-axios-2d06f96/tests/smoke/esm/tests/headers.smoke.test.js000066400000000000000000000064641521272452000246040ustar00rootroot00000000000000import { describe, expect, it } from 'vitest'; import { EventEmitter } from 'events'; import { PassThrough } from 'stream'; import axios from 'axios'; const normalizeHeaders = (headers) => { const result = {}; Object.entries(headers || {}).forEach(([key, value]) => { result[key.toLowerCase()] = value; }); return result; }; const createTransportCapture = () => { let capturedOptions; const transport = { request(options, onResponse) { capturedOptions = options; const req = new EventEmitter(); req.destroyed = false; req.setTimeout = () => {}; req.write = () => true; req.destroy = () => { req.destroyed = true; }; req.close = req.destroy; req.end = () => { const res = new PassThrough(); res.statusCode = 200; res.statusMessage = 'OK'; res.headers = { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end('{"ok":true}'); }; return req; }, }; return { transport, getCapturedOptions: () => capturedOptions, }; }; describe('headers compat (dist export only)', () => { it('sends default Accept header', async () => { const { transport, getCapturedOptions } = createTransportCapture(); await axios.get('http://example.com/default-headers', { transport, proxy: false, }); const headers = normalizeHeaders(getCapturedOptions().headers); expect(headers.accept).toBe('application/json, text/plain, */*'); }); it('supports custom headers', async () => { const { transport, getCapturedOptions } = createTransportCapture(); await axios.get('http://example.com/custom-headers', { transport, proxy: false, headers: { 'X-Trace-Id': 'trace-123', Authorization: 'Bearer token-abc', }, }); const headers = normalizeHeaders(getCapturedOptions().headers); expect(headers['x-trace-id']).toBe('trace-123'); expect(headers.authorization).toBe('Bearer token-abc'); }); it('treats header names as case-insensitive when overriding', async () => { const { transport, getCapturedOptions } = createTransportCapture(); await axios.get('http://example.com/case-insensitive', { transport, proxy: false, headers: { authorization: 'Bearer old-token', AuThOrIzAtIoN: 'Bearer new-token', }, }); const headers = normalizeHeaders(getCapturedOptions().headers); expect(headers.authorization).toBe('Bearer new-token'); }); it('sets content-type for json post payloads', async () => { const { transport, getCapturedOptions } = createTransportCapture(); await axios.post( 'http://example.com/post-json', { name: 'widget' }, { transport, proxy: false, } ); const headers = normalizeHeaders(getCapturedOptions().headers); expect(headers['content-type']).toContain('application/json'); }); it('does not force content-type for get requests without body', async () => { const { transport, getCapturedOptions } = createTransportCapture(); await axios.get('http://example.com/get-no-body', { transport, proxy: false, }); const headers = normalizeHeaders(getCapturedOptions().headers); expect(headers['content-type']).toBeUndefined(); }); }); axios-axios-2d06f96/tests/smoke/esm/tests/http2.smoke.test.js000066400000000000000000000040301521272452000242150ustar00rootroot00000000000000import { describe, expect, it } from 'vitest'; import axios from 'axios'; describe('http2 compat (dist export only)', () => { it('keeps instance-level httpVersion and http2Options in request config', async () => { const client = axios.create({ baseURL: 'https://example.com', httpVersion: 2, http2Options: { rejectUnauthorized: false, }, }); const response = await client.get('/resource', { adapter: async (config) => ({ data: { httpVersion: config.httpVersion, http2Options: config.http2Options, }, status: 200, statusText: 'OK', headers: {}, config, }), }); expect(response.data.httpVersion).toBe(2); expect(response.data.http2Options).toEqual({ rejectUnauthorized: false, }); }); it('merges request http2Options with instance http2Options', async () => { const client = axios.create({ baseURL: 'https://example.com', httpVersion: 2, http2Options: { rejectUnauthorized: false, sessionTimeout: 1000, }, }); const response = await client.get('/resource', { http2Options: { sessionTimeout: 5000, customFlag: true, }, adapter: async (config) => ({ data: config.http2Options, status: 200, statusText: 'OK', headers: {}, config, }), }); expect(response.data).toEqual({ rejectUnauthorized: false, sessionTimeout: 5000, customFlag: true, }); }); it('allows request-level httpVersion override', async () => { const client = axios.create({ baseURL: 'https://example.com', httpVersion: 2, }); const response = await client.get('/resource', { httpVersion: 1, adapter: async (config) => ({ data: { httpVersion: config.httpVersion, }, status: 200, statusText: 'OK', headers: {}, config, }), }); expect(response.data.httpVersion).toBe(1); }); }); axios-axios-2d06f96/tests/smoke/esm/tests/import.smoke.test.js000066400000000000000000000020741521272452000244740ustar00rootroot00000000000000import { describe, expect, it } from 'vitest'; import axios, { CanceledError, AxiosError, AxiosHeaders } from 'axios'; import settle from 'axios/unsafe/core/settle.js'; describe('ESM importing', () => { it('should import axios', () => { expect(typeof axios).toStrictEqual('function'); }); it('should import CanceledError', () => { expect(typeof CanceledError).toStrictEqual('function'); }); it('should import AxiosError', () => { expect(typeof AxiosError).toStrictEqual('function'); }); it('should import AxiosHeaders', () => { expect(typeof AxiosHeaders).toStrictEqual('function'); }); it('should import settle', () => { expect(typeof settle).toStrictEqual('function'); }); it('should import CanceledError from axios', () => { expect(axios.CanceledError).toStrictEqual(CanceledError); }); it('should import AxiosError from axios', () => { expect(axios.AxiosError).toStrictEqual(AxiosError); }); it('should import AxiosHeaders from axios', () => { expect(axios.AxiosHeaders).toStrictEqual(AxiosHeaders); }); }); axios-axios-2d06f96/tests/smoke/esm/tests/instance.smoke.test.js000066400000000000000000000072771521272452000250000ustar00rootroot00000000000000import { describe, expect, it } from 'vitest'; import { EventEmitter } from 'events'; import { PassThrough } from 'stream'; import axios from 'axios'; const createTransportCapture = (responseBody) => { const calls = []; const transport = { request(options, onResponse) { calls.push(options); const req = new EventEmitter(); req.destroyed = false; req.setTimeout = () => {}; req.write = () => true; req.destroy = () => { req.destroyed = true; }; req.close = req.destroy; req.end = () => { const res = new PassThrough(); res.statusCode = 200; res.statusMessage = 'OK'; res.headers = { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end(responseBody ? responseBody : '{"ok":true}'); }; return req; }, }; return { transport, getCalls: () => calls, }; }; describe('instance compat (dist export only)', () => { it('creates isolated instances with separate defaults', async () => { const { transport, getCalls } = createTransportCapture(); const clientA = axios.create({ baseURL: 'http://example.com/api-a', headers: { 'X-App': 'A', }, }); const clientB = axios.create({ baseURL: 'http://example.com/api-b', headers: { 'X-App': 'B', }, }); await clientA.get('/users', { transport, proxy: false }); await clientB.get('/users', { transport, proxy: false }); const [callA, callB] = getCalls(); expect(callA.path).toBe('/api-a/users'); expect(callB.path).toBe('/api-b/users'); expect(callA.headers['X-App']).toBe('A'); expect(callB.headers['X-App']).toBe('B'); }); it('supports callable instance form instance(config)', async () => { const { transport, getCalls } = createTransportCapture(); const client = axios.create({ baseURL: 'http://example.com', }); await client({ url: '/status', method: 'get', transport, proxy: false, }); expect(getCalls()).toHaveLength(1); expect(getCalls()[0].method).toBe('GET'); expect(getCalls()[0].path).toBe('/status'); }); it('applies instance request interceptors', async () => { const { transport, getCalls } = createTransportCapture(); const client = axios.create({ baseURL: 'http://example.com', }); client.interceptors.request.use((config) => { config.headers = config.headers || {}; config.headers['X-From-Interceptor'] = 'yes'; return config; }); await client.get('/intercepted', { transport, proxy: false }); expect(getCalls()).toHaveLength(1); expect(getCalls()[0].headers['X-From-Interceptor']).toBe('yes'); }); it('applies instance response interceptors', async () => { const { transport } = createTransportCapture('{"name":"axios"}'); const client = axios.create({ baseURL: 'http://example.com', }); client.interceptors.response.use((response) => { response.data = Object.assign({}, response.data, { intercepted: true, }); return response; }); const response = await client.get('/response-interceptor', { transport, proxy: false, }); expect(response.data).toEqual({ name: 'axios', intercepted: true, }); }); it('builds URLs with getUri from instance defaults and request params', () => { const client = axios.create({ baseURL: 'http://example.com/api', params: { apiKey: 'abc', }, }); const uri = client.getUri({ url: '/users', params: { page: 2, }, }); expect(uri).toBe('http://example.com/api/users?apiKey=abc&page=2'); }); }); axios-axios-2d06f96/tests/smoke/esm/tests/interceptors.smoke.test.js000066400000000000000000000075031521272452000257050ustar00rootroot00000000000000import { describe, expect, it } from 'vitest'; import { EventEmitter } from 'events'; import { PassThrough } from 'stream'; import axios from 'axios'; const createTransport = (responseBody) => { const calls = []; const transport = { request(options, onResponse) { calls.push(options); const req = new EventEmitter(); req.destroyed = false; req.setTimeout = () => {}; req.write = () => true; req.destroy = () => { req.destroyed = true; }; req.close = req.destroy; req.end = () => { const res = new PassThrough(); res.statusCode = 200; res.statusMessage = 'OK'; res.headers = { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end(responseBody ? responseBody : '{"value":"ok"}'); }; return req; }, }; return { transport, getCalls: () => calls, }; }; describe('interceptors compat (dist export only)', () => { it('applies request interceptors before dispatch', async () => { const { transport, getCalls } = createTransport(); const client = axios.create(); client.interceptors.request.use((config) => { config.headers = config.headers || {}; config.headers['X-One'] = '1'; return config; }); client.interceptors.request.use((config) => { config.headers['X-Two'] = '2'; return config; }); await client.get('http://example.com/resource', { transport, proxy: false, }); expect(getCalls()).toHaveLength(1); expect(getCalls()[0].headers['X-One']).toBe('1'); expect(getCalls()[0].headers['X-Two']).toBe('2'); }); it('applies response interceptors in registration order', async () => { const { transport } = createTransport('{"n":1}'); const client = axios.create(); client.interceptors.response.use((response) => { response.data.n += 1; return response; }); client.interceptors.response.use((response) => { response.data.n *= 10; return response; }); const response = await client.get('http://example.com/resource', { transport, proxy: false, }); expect(response.data.n).toBe(20); }); it('supports ejecting request interceptors', async () => { const { transport, getCalls } = createTransport(); const client = axios.create(); const id = client.interceptors.request.use((config) => { config.headers = config.headers || {}; config.headers['X-Ejected'] = 'yes'; return config; }); client.interceptors.request.eject(id); await client.get('http://example.com/resource', { transport, proxy: false, }); expect(getCalls()).toHaveLength(1); expect(getCalls()[0].headers['X-Ejected']).toBeUndefined(); }); it('supports async request interceptors', async () => { const { transport, getCalls } = createTransport(); const client = axios.create(); client.interceptors.request.use(async (config) => { await Promise.resolve(); config.headers = config.headers || {}; config.headers['X-Async'] = 'true'; return config; }); await client.get('http://example.com/resource', { transport, proxy: false, }); expect(getCalls()[0].headers['X-Async']).toBe('true'); }); it('propagates errors thrown by request interceptors', async () => { const { transport, getCalls } = createTransport(); const client = axios.create(); client.interceptors.request.use(() => { throw new Error('blocked-by-interceptor'); }); const err = await client .get('http://example.com/resource', { transport, proxy: false, }) .catch((e) => e); expect(err).toBeInstanceOf(Error); expect(err.message).toContain('blocked-by-interceptor'); expect(getCalls()).toHaveLength(0); }); }); axios-axios-2d06f96/tests/smoke/esm/tests/progress.smoke.test.js000066400000000000000000000056351521272452000250340ustar00rootroot00000000000000import { describe, expect, it } from 'vitest'; import { Readable, Writable, PassThrough } from 'stream'; import axios from 'axios'; const createProgressTransport = (config) => { const opts = config || {}; const responseChunks = opts.responseChunks || ['ok']; const responseHeaders = opts.responseHeaders || {}; return { request(_options, onResponse) { const req = new Writable({ write(_chunk, _encoding, callback) { callback(); }, }); req.destroyed = false; req.setTimeout = () => {}; req.close = () => { req.destroyed = true; }; const originalDestroy = req.destroy.bind(req); req.destroy = (...args) => { req.destroyed = true; return originalDestroy(...args); }; const originalEnd = req.end.bind(req); req.end = (...args) => { originalEnd(...args); const res = new PassThrough(); res.statusCode = 200; res.statusMessage = 'OK'; res.headers = Object.assign( { 'content-type': 'text/plain', }, responseHeaders ); res.req = req; onResponse(res); responseChunks.forEach((chunk) => { res.write(chunk); }); res.end(); }; return req; }, }; }; describe('progress compat (dist export only)', () => { it('emits upload progress events for stream payloads', async () => { const samples = []; const payload = ['abc', 'def', 'ghi']; const total = payload.join('').length; await axios.post('http://example.com/upload', Readable.from(payload), { proxy: false, headers: { 'Content-Length': String(total), }, onUploadProgress: ({ loaded, total: reportedTotal, upload }) => { samples.push({ loaded, total: reportedTotal, upload }); }, transport: createProgressTransport({ responseChunks: ['uploaded'], }), }); expect(samples.length).toBeGreaterThan(0); expect(samples[samples.length - 1]).toMatchObject({ loaded: total, total, upload: true, }); }); it('emits download progress events', async () => { const samples = []; const chunks = ['ab', 'cd', 'ef']; const total = chunks.join('').length; const response = await axios.get('http://example.com/download', { proxy: false, responseType: 'text', onDownloadProgress: ({ loaded, total: reportedTotal, download }) => { samples.push({ loaded, total: reportedTotal, download }); }, transport: createProgressTransport({ responseChunks: chunks, responseHeaders: { 'content-length': String(total), }, }), }); expect(response.data).toBe('abcdef'); expect(samples.length).toBeGreaterThan(0); expect(samples[samples.length - 1]).toMatchObject({ loaded: total, total, download: true, }); }); }); axios-axios-2d06f96/tests/smoke/esm/tests/rateLimit.smoke.test.js000066400000000000000000000052061521272452000251140ustar00rootroot00000000000000import { describe, expect, it } from 'vitest'; import { EventEmitter } from 'events'; import { PassThrough } from 'stream'; import axios from 'axios'; const createTransportCapture = () => { let capturedOptions; const transport = { request(options, onResponse) { capturedOptions = options; const req = new EventEmitter(); req.destroyed = false; req.setTimeout = () => {}; req.write = () => true; req.destroy = () => { req.destroyed = true; }; req.close = req.destroy; req.end = () => { const res = new PassThrough(); res.statusCode = 200; res.statusMessage = 'OK'; res.headers = { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end('{"ok":true}'); }; return req; }, }; return { transport, getCapturedOptions: () => capturedOptions, }; }; describe('rateLimit compat (dist export only)', () => { it('accepts numeric maxRate config', async () => { const response = await axios.get('http://example.com/rate', { maxRate: 1024, adapter: async (config) => ({ data: { maxRate: config.maxRate }, status: 200, statusText: 'OK', headers: {}, config, }), }); expect(response.data.maxRate).toBe(1024); }); it('accepts tuple maxRate config [upload, download]', async () => { const response = await axios.get('http://example.com/rate', { maxRate: [2048, 4096], adapter: async (config) => ({ data: { maxRate: config.maxRate }, status: 200, statusText: 'OK', headers: {}, config, }), }); expect(response.data.maxRate).toEqual([2048, 4096]); }); it('merges instance and request maxRate values', async () => { const client = axios.create({ maxRate: [1000, 2000], }); const response = await client.get('http://example.com/rate', { maxRate: [3000, 4000], adapter: async (config) => ({ data: { maxRate: config.maxRate }, status: 200, statusText: 'OK', headers: {}, config, }), }); expect(response.data.maxRate).toEqual([3000, 4000]); }); it('supports maxRate in node transport flow without errors', async () => { const { transport, getCapturedOptions } = createTransportCapture(); const response = await axios.get('http://example.com/rate', { proxy: false, maxRate: [1500, 2500], transport, }); expect(response.status).toBe(200); expect(getCapturedOptions().method).toBe('GET'); expect(getCapturedOptions().path).toBe('/rate'); }); }); axios-axios-2d06f96/tests/smoke/esm/tests/timeout.smoke.test.js000066400000000000000000000062541521272452000246540ustar00rootroot00000000000000import { describe, expect, it } from 'vitest'; import { EventEmitter } from 'events'; import { PassThrough } from 'stream'; import axios from 'axios'; const createTransport = (config) => { const opts = config || {}; return { request(_options, onResponse) { const req = new EventEmitter(); req.destroyed = false; req._timeoutCallback = null; req.setTimeout = (_ms, callback) => { req._timeoutCallback = callback; }; req.write = () => true; req.destroy = () => { req.destroyed = true; }; req.close = req.destroy; req.end = () => { if (opts.triggerTimeout && req._timeoutCallback) { req._timeoutCallback(); return; } const res = new PassThrough(); res.statusCode = 200; res.statusMessage = 'OK'; res.headers = { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end(opts.body === undefined ? '{"ok":true}' : opts.body); }; return req; }, }; }; describe('timeout compat (dist export only)', () => { it('rejects with ECONNABORTED on timeout', async () => { const err = await axios .get('http://example.com/timeout', { proxy: false, timeout: 25, transport: createTransport({ triggerTimeout: true }), }) .catch((e) => e); expect(axios.isAxiosError(err)).toBe(true); expect(err.code).toBe('ECONNABORTED'); expect(err.message).toBe('timeout of 25ms exceeded'); }); it('uses timeoutErrorMessage when provided', async () => { const err = await axios .get('http://example.com/timeout', { proxy: false, timeout: 25, timeoutErrorMessage: 'custom timeout', transport: createTransport({ triggerTimeout: true }), }) .catch((e) => e); expect(axios.isAxiosError(err)).toBe(true); expect(err.code).toBe('ECONNABORTED'); expect(err.message).toBe('custom timeout'); }); it('accepts timeout as a numeric string', async () => { const err = await axios .get('http://example.com/timeout', { proxy: false, timeout: '30', transport: createTransport({ triggerTimeout: true }), }) .catch((e) => e); expect(axios.isAxiosError(err)).toBe(true); expect(err.code).toBe('ECONNABORTED'); expect(err.message).toBe('timeout of 30ms exceeded'); }); it('rejects with ERR_BAD_OPTION_VALUE when timeout is not parsable', async () => { const err = await axios .get('http://example.com/timeout', { proxy: false, timeout: { invalid: true }, transport: createTransport(), }) .catch((e) => e); expect(axios.isAxiosError(err)).toBe(true); expect(err.code).toBe('ERR_BAD_OPTION_VALUE'); expect(err.message).toBe('error trying to parse `config.timeout` to int'); }); it('does not time out when timeout is 0', async () => { const response = await axios.get('http://example.com/no-timeout', { proxy: false, timeout: 0, transport: createTransport({ body: '{"ok":true}' }), }); expect(response.status).toBe(200); expect(response.data).toEqual({ ok: true }); }); }); axios-axios-2d06f96/tests/smoke/esm/tests/urlencode.smoke.test.js000066400000000000000000000073201521272452000251410ustar00rootroot00000000000000import { describe, expect, it } from 'vitest'; import { EventEmitter } from 'events'; import { PassThrough } from 'stream'; import axios from 'axios'; const createEchoTransport = () => { let capturedOptions; const transport = { request(options, onResponse) { capturedOptions = options; const chunks = []; const req = new EventEmitter(); req.destroyed = false; req.setTimeout = () => {}; req.destroy = () => { req.destroyed = true; }; req.close = req.destroy; req.write = (chunk) => { chunks.push(Buffer.from(chunk)); return true; }; req.end = (chunk) => { if (chunk) { chunks.push(Buffer.from(chunk)); } const res = new PassThrough(); res.statusCode = 200; res.statusMessage = 'OK'; res.headers = { 'content-type': 'application/json' }; res.req = req; onResponse(res); res.end( JSON.stringify({ path: options.path, body: Buffer.concat(chunks).toString('utf8'), contentType: options.headers && (options.headers['Content-Type'] || options.headers['content-type']), }) ); }; return req; }, }; return { transport, getCapturedOptions: () => capturedOptions, }; }; describe('urlencode compat (dist export only)', () => { it('serializes params into request URL', async () => { const { transport } = createEchoTransport(); const response = await axios.get('http://example.com/search', { proxy: false, transport, params: { q: 'axios docs', page: 2, }, }); expect(response.data.path).toBe('/search?q=axios+docs&page=2'); }); it('supports custom paramsSerializer function', async () => { const { transport } = createEchoTransport(); const response = await axios.get('http://example.com/search', { proxy: false, transport, params: { q: 'ignored' }, paramsSerializer: () => 'fixed=1', }); expect(response.data.path).toBe('/search?fixed=1'); }); it('supports URLSearchParams payloads', async () => { const { transport } = createEchoTransport(); const payload = new URLSearchParams(); payload.append('name', 'axios'); payload.append('mode', 'compat'); const response = await axios.post('http://example.com/form', payload, { proxy: false, transport, }); expect(response.data.body).toBe('name=axios&mode=compat'); expect(response.data.contentType).toContain('application/x-www-form-urlencoded'); }); it('serializes object payload when content-type is application/x-www-form-urlencoded', async () => { const { transport } = createEchoTransport(); const response = await axios.post( 'http://example.com/form', { name: 'axios', mode: 'compat', }, { proxy: false, transport, headers: { 'content-type': 'application/x-www-form-urlencoded', }, } ); expect(response.data.body).toBe('name=axios&mode=compat'); expect(response.data.contentType).toContain('application/x-www-form-urlencoded'); }); it('respects formSerializer options for index formatting', async () => { const { transport } = createEchoTransport(); const response = await axios.post( 'http://example.com/form', { arr: ['1', '2'], }, { proxy: false, transport, headers: { 'content-type': 'application/x-www-form-urlencoded', }, formSerializer: { indexes: true, }, } ); expect(response.data.body).toBe('arr%5B0%5D=1&arr%5B1%5D=2'); }); }); axios-axios-2d06f96/tests/smoke/esm/vitest.config.js000066400000000000000000000004761521272452000225130ustar00rootroot00000000000000import { defineConfig } from 'vitest/config'; export default defineConfig({ test: { testTimeout: 10000, projects: [ { test: { name: 'smoke', environment: 'node', include: ['tests/**/*.smoke.test.js'], setupFiles: [], }, }, ], }, }); axios-axios-2d06f96/tests/unit/000077500000000000000000000000001521272452000164415ustar00rootroot00000000000000axios-axios-2d06f96/tests/unit/adapters/000077500000000000000000000000001521272452000202445ustar00rootroot00000000000000axios-axios-2d06f96/tests/unit/adapters/adapters.test.js000066400000000000000000000026171521272452000233710ustar00rootroot00000000000000import { beforeEach, describe, it } from 'vitest'; import assert from 'assert'; import adapters from '../../../lib/adapters/adapters.js'; describe('adapters', () => { const store = { ...adapters.adapters }; beforeEach(() => { Object.keys(adapters.adapters).forEach((name) => { delete adapters.adapters[name]; }); Object.assign(adapters.adapters, store); }); it('should support loading by fn handle', () => { const adapter = () => {}; assert.strictEqual(adapters.getAdapter(adapter), adapter); }); it('should support loading by name', () => { const adapter = () => {}; adapters.adapters.testadapter = adapter; assert.strictEqual(adapters.getAdapter('testAdapter'), adapter); }); it('should detect adapter unavailable status', () => { adapters.adapters.testadapter = null; assert.throws(() => adapters.getAdapter('testAdapter'), /is not available in the build/); }); it('should detect adapter unsupported status', () => { adapters.adapters.testadapter = false; assert.throws(() => adapters.getAdapter('testAdapter'), /is not supported by the environment/); }); it('should pick suitable adapter from the list', () => { const adapter = () => {}; Object.assign(adapters.adapters, { foo: false, bar: null, baz: adapter, }); assert.strictEqual(adapters.getAdapter(['foo', 'bar', 'baz']), adapter); }); }); axios-axios-2d06f96/tests/unit/adapters/axios.png000066400000000000000000000032641521272452000221020ustar00rootroot00000000000000PNG  IHDR2SA'sRGBgAMA a pHYsttfxIIDATx^-5 i> %gK ,(K'= $$H,~>Q4$Nb_fOf38Һ+fɪ{T(wsB;6P%G\rggF4R$E;e C! ۙUIABl0vGx -$E;ͳ_Nm#+Nuz-NeZ>SCdDY;f8irͦwrxԻ!UngNeN' $f皥~5'Hϝ8fR c;k SK$K;vУY;AϝeK4]$"ÝȖhWDSPAe- tCi[wՙZ)0Kc"Ý=1a6pBĦv|rN8?^fpxP܉ T.^5;82SLlwNa=pYRtP *6kܝ?Y0UX+1pڝq %t'G^&wo}Ur6λ(,S0!JA%rNgFn;\7&&FFgGlηNiERzP*8$iYb(HXX[a2m,2L_U ;ܩ]!B= X9;dWH̫;9bJMjehAsD[q%dba`wA%`ug+l#fv4ӔLO3lP$Zw!3!<)ċ;IT,`q@ L=\zc$!@>X/43,U(账n8ds(fUTpa<6‹;O˲6 p *p6z\X6dAJY D .wY<8x;΃8>[x4IENDB`axios-axios-2d06f96/tests/unit/adapters/cert.pem000066400000000000000000000017211521272452000217050ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIICpDCCAYwCCQDbqELLwgbPdDANBgkqhkiG9w0BAQUFADAUMRIwEAYDVQQDDAls b2NhbGhvc3QwHhcNMjAwNjI2MjIxMTQ3WhcNNDcxMTExMjIxMTQ3WjAUMRIwEAYD VQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD6 Ogt99/dZ0UgbCuVV1RZ9n28Ov3DzrJCkjperQoXomIq3Fr4RUI1a2rwe3mtl3UzE 1IVZVvWPGdEsEQHwXfAsP/jFGTwI3HDyOhcqzFQSKsjvqJWYkOOb+2r3SBrFlRZW 09k/3lC+hx2XtuuG68u4Xgn3AlUvm2vplgCN7eiYcGeNwVuf2eHdOqTRTqiYCZLi T8GtdYMDXOrwsGZs/jUKd9U0ar/lqwMhmw07yzlVDM2MWM2tyq/asQ7Sf7vuoMFu oAtDJ3E+bK1k/7SNhdyP4RonhyUCkWG+mzoKDS1qgXroTiQSDUksAvOCTcj8BNIT ee+Lcn9FaTKNJiKiU9q/AgMBAAEwDQYJKoZIhvcNAQEFBQADggEBAFi5ZpaUj+mU dsgOka+j2/njgNXux3cOjhm7z/N7LeTuDENAOrYa5b+j5JX/YM7RKHrkbXHsQbfs GB3ufH6QhSiCd/AdsXp/TbCE/8gdq8ykkjwVP1bvBle9oPH7x1aO/WP/odsepYUv o9aOZW4iNQVmwamU62ezglf3QD7HPeE4LnZueaFtuzRoC+aWT9v0MIeUPJLe3WDQ FEySwUuthMDJEv92/TeK0YOiunmseCu2mvdiDj6E3C9xa5q2DWgl+msu7+bPgvYO GuWaoNeQQGk7ebBO3Hk3IyaGx6Cbd8ty+YaZW7dUT+m7KCs1VkxdcDMjZJVWiJy4 4HcEcKboG4Y= -----END CERTIFICATE----- axios-axios-2d06f96/tests/unit/adapters/errorDetails.test.js000066400000000000000000000055061521272452000242250ustar00rootroot00000000000000import { describe, it } from 'vitest'; import assert from 'assert'; import https from 'https'; import net from 'net'; import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; import axios from '../../../index.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const getClosedPort = async () => { return await new Promise((resolve) => { const srv = net.createServer(); srv.listen(0, '127.0.0.1', () => { const { port } = srv.address(); srv.close(() => resolve(port)); }); }); }; describe('adapters - network-error details', () => { it('should expose ECONNREFUSED and set error.cause on connection refusal', async () => { const port = await getClosedPort(); try { await axios.get(`http://127.0.0.1:${port}`, { timeout: 500 }); assert.fail('request unexpectedly succeeded'); } catch (err) { assert.ok(err instanceof Error, 'should be an Error'); assert.strictEqual(err.isAxiosError, true, 'isAxiosError should be true'); assert.strictEqual(err.code, 'ECONNREFUSED'); assert.ok('cause' in err, 'error.cause should exist'); assert.ok(err.cause instanceof Error, 'cause should be an Error'); assert.strictEqual(err.cause && err.cause.code, 'ECONNREFUSED'); assert.strictEqual(typeof err.message, 'string'); } }); it('should expose self-signed TLS error and set error.cause', async () => { const certsDir = path.resolve(__dirname, '../../../tests/unit/adapters/'); const keyPath = path.join(certsDir, 'key.pem'); const certPath = path.join(certsDir, 'cert.pem'); const key = fs.readFileSync(keyPath); const cert = fs.readFileSync(certPath); const httpsServer = https.createServer({ key, cert }, (req, res) => res.end('ok')); await new Promise((resolve) => httpsServer.listen(0, '127.0.0.1', resolve)); const { port } = httpsServer.address(); try { await axios.get(`https://127.0.0.1:${port}`, { timeout: 500, httpsAgent: new https.Agent({ rejectUnauthorized: true }), }); assert.fail('request unexpectedly succeeded'); } catch (err) { const codeStr = String(err.code); assert.ok( /SELF_SIGNED|UNABLE_TO_VERIFY_LEAF_SIGNATURE|DEPTH_ZERO/.test(codeStr), `unexpected TLS code: ${codeStr}` ); assert.ok('cause' in err, 'error.cause should exist'); assert.ok(err.cause instanceof Error, 'cause should be an Error'); const causeCode = String(err.cause && err.cause.code); assert.ok( /SELF_SIGNED|UNABLE_TO_VERIFY_LEAF_SIGNATURE|DEPTH_ZERO/.test(causeCode), `unexpected cause code: ${causeCode}` ); assert.strictEqual(typeof err.message, 'string'); } finally { await new Promise((resolve) => httpsServer.close(resolve)); } }); }); axios-axios-2d06f96/tests/unit/adapters/fetch.test.js000066400000000000000000001361161521272452000226610ustar00rootroot00000000000000import { describe, it, vi } from 'vitest'; import assert from 'assert'; import { startHTTPServer, stopHTTPServer, setTimeoutAsync, makeReadableStream, generateReadable, makeEchoStream, } from '../../setup/server.js'; import axios from '../../../index.js'; import AxiosError from '../../../lib/core/AxiosError.js'; import utils from '../../../lib/utils.js'; import { getFetch } from '../../../lib/adapters/fetch.js'; import stream from 'stream'; import { AbortController } from 'abortcontroller-polyfill/dist/cjs-ponyfill.js'; import util from 'util'; import NodeFormData from 'form-data'; import { VERSION } from '../../../lib/env/data.js'; const SERVER_PORT = 8010; const LOCAL_SERVER_URL = `http://localhost:${SERVER_PORT}`; const pipelineAsync = util.promisify(stream.pipeline); const fetchAxios = axios.create({ baseURL: LOCAL_SERVER_URL, adapter: 'fetch', }); const getFetchSignal = (input, init) => (init && init.signal) || (input && input.signal); const createBrokenDOMExceptionLikeError = () => Object.defineProperties( {}, { name: { get() { throw new TypeError( 'The DOMException.name getter can only be used on instances of DOMException' ); }, }, message: { get() { throw new TypeError( 'The DOMException.message getter can only be used on instances of DOMException' ); }, }, } ); describe.runIf(typeof fetch === 'function')('supports fetch with nodejs', () => { it('rejects malformed HTTP URLs before fetch normalization and preserves config', async () => { for (const url of ['\u0000https:example.com/users', 'h\nttp:example.com/users']) { await assert.rejects( () => axios.get(url, { adapter: 'fetch', headers: { 'X-Test': 'yes', }, }), (error) => { assert.ok(error instanceof AxiosError); assert.strictEqual(error.code, AxiosError.ERR_INVALID_URL); assert.strictEqual(error.message, 'Invalid URL: missing "//" after protocol'); assert.strictEqual(error.config.url, url); assert.strictEqual(error.config.headers.get('X-Test'), 'yes'); return true; } ); } }); it('should sanitize request headers containing CRLF characters', async () => { const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'application/json'); res.end( JSON.stringify({ xTest: req.headers['x-test'], injected: req.headers.injected ?? null, }) ); }, { port: SERVER_PORT, } ); try { const { data } = await fetchAxios.get(`${LOCAL_SERVER_URL}/`, { headers: { 'x-test': '\tok\r\nInjected: yes ', }, }); assert.strictEqual(data.xTest, 'okInjected: yes'); assert.strictEqual(data.injected, null); } finally { await stopHTTPServer(server); } }); it('should not use inherited Symbol.iterator for request headers', async () => { const server = await startHTTPServer((req, res) => { res.setHeader('Content-Type', 'application/json'); res.end( JSON.stringify({ authorization: req.headers.authorization, xApp: req.headers['x-app'], xInjected: req.headers['x-injected'] ?? null, }) ); }); try { Object.prototype[Symbol.iterator] = function* () { yield ['X-Injected', 'yes']; yield ['Authorization', 'Bearer CHANGED']; }; const { data } = await fetchAxios.get(`http://localhost:${server.address().port}/`, { headers: { Authorization: 'Bearer VALID_USER_TOKEN', 'X-App': 'safe', }, }); assert.strictEqual(data.authorization, 'Bearer VALID_USER_TOKEN'); assert.strictEqual(data.xApp, 'safe'); assert.strictEqual(data.xInjected, null); } finally { delete Object.prototype[Symbol.iterator]; await stopHTTPServer(server); } }); it('should allow request interceptors to encode Unicode header values before fetch sends them', async () => { const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'application/json'); res.end( JSON.stringify({ oprtName: req.headers.oprtname, }) ); }, { port: SERVER_PORT, } ); const instance = axios.create({ baseURL: LOCAL_SERVER_URL, adapter: 'fetch', }); instance.interceptors.request.use((config) => { config.headers.oprtName = encodeURIComponent(config.headers.oprtName); return config; }); try { const { data } = await instance.get('/', { headers: { oprtName: '请求用户', }, }); assert.strictEqual(data.oprtName, encodeURIComponent('请求用户')); } finally { await stopHTTPServer(server); } }); it('should sanitize unencoded Unicode headers before passing them to fetch', async () => { const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'application/json'); res.end( JSON.stringify({ xTest: req.headers['x-test'], }) ); }, { port: SERVER_PORT, } ); try { const { data } = await fetchAxios.get(`${LOCAL_SERVER_URL}/`, { headers: { 'x-test': '请求用户', }, }); assert.strictEqual(data.xTest, ''); } finally { await stopHTTPServer(server); } }); describe('responses', () => { it('should support text response type', async () => { const originalData = 'my data'; const server = await startHTTPServer((req, res) => res.end(originalData), { port: SERVER_PORT, }); try { const { data } = await fetchAxios.get(`http://localhost:${server.address().port}/`, { responseType: 'text', }); assert.deepStrictEqual(data, originalData); } finally { await stopHTTPServer(server); } }); it('should support arraybuffer response type', async () => { const originalData = 'my data'; const server = await startHTTPServer((req, res) => res.end(originalData), { port: SERVER_PORT, }); try { const { data } = await fetchAxios.get(`http://localhost:${server.address().port}/`, { responseType: 'arraybuffer', }); assert.deepStrictEqual( data, Uint8Array.from(await new TextEncoder().encode(originalData)).buffer ); } finally { await stopHTTPServer(server); } }); it('should support blob response type', async () => { const originalData = 'my data'; const server = await startHTTPServer((req, res) => res.end(originalData), { port: SERVER_PORT, }); try { const { data } = await fetchAxios.get(`http://localhost:${server.address().port}/`, { responseType: 'blob', }); assert.deepStrictEqual(data, new Blob([originalData])); } finally { await stopHTTPServer(server); } }); it('should support stream response type', async () => { const originalData = 'my data'; const server = await startHTTPServer((req, res) => res.end(originalData), { port: SERVER_PORT, }); try { const { data } = await fetchAxios.get(`http://localhost:${server.address().port}/`, { responseType: 'stream', }); assert.ok(data instanceof ReadableStream, 'data is not instanceof ReadableStream'); const response = new Response(data); assert.deepStrictEqual(await response.text(), originalData); } finally { await stopHTTPServer(server); } }); it('should support formData response type', async () => { const originalData = new FormData(); originalData.append('x', '123'); const server = await startHTTPServer( async (req, res) => { const response = await new Response(originalData); res.setHeader('Content-Type', response.headers.get('Content-Type')); res.end(await response.text()); }, { port: SERVER_PORT } ); try { const { data } = await fetchAxios.get(`http://localhost:${server.address().port}/`, { responseType: 'formdata', }); assert.ok(data instanceof FormData, 'data is not instanceof FormData'); assert.deepStrictEqual( Object.fromEntries(data.entries()), Object.fromEntries(originalData.entries()) ); } finally { await stopHTTPServer(server); } }, 5000); it('should support json response type', async () => { const originalData = { x: 'my data' }; const server = await startHTTPServer((req, res) => res.end(JSON.stringify(originalData)), { port: SERVER_PORT, }); try { const { data } = await fetchAxios.get(`http://localhost:${server.address().port}/`, { responseType: 'json', }); assert.deepStrictEqual(data, originalData); } finally { await stopHTTPServer(server); } }); }); describe('progress', () => { describe('upload', () => { it('should support upload progress capturing', async () => { const server = await startHTTPServer( { rate: 100 * 1024, }, { port: SERVER_PORT } ); try { let content = ''; const count = 10; const chunk = 'test'; const chunkLength = Buffer.byteLength(chunk); const contentLength = count * chunkLength; const readable = stream.Readable.from( (async function* () { let i = count; while (i-- > 0) { await setTimeoutAsync(1100); content += chunk; yield chunk; } })() ); const samples = []; const { data } = await fetchAxios.post( `http://localhost:${server.address().port}/`, readable, { onUploadProgress: ({ loaded, total, progress, bytes, upload }) => { console.log( `Upload Progress ${loaded} from ${total} bytes (${(progress * 100).toFixed(1)}%)` ); samples.push({ loaded, total, progress, bytes, upload, }); }, headers: { 'Content-Length': contentLength, }, responseType: 'text', } ); await setTimeoutAsync(500); assert.strictEqual(data, content); assert.deepStrictEqual( samples, Array.from( (function* () { for (let i = 1; i <= 10; i++) { yield { loaded: chunkLength * i, total: contentLength, progress: (chunkLength * i) / contentLength, bytes: 4, upload: true, }; } })() ) ); } finally { await stopHTTPServer(server); } }, 15000); it('should not fail with get method', async () => { const server = await startHTTPServer((req, res) => res.end('OK'), { port: SERVER_PORT }); try { const { data } = await fetchAxios.get(`http://localhost:${server.address().port}/`, { onUploadProgress() {}, }); assert.strictEqual(data, 'OK'); } finally { await stopHTTPServer(server); } }); }); describe('download', () => { it('should support download progress capturing', async () => { const server = await startHTTPServer( { rate: 100 * 1024, }, { port: SERVER_PORT, } ); try { let content = ''; const count = 10; const chunk = 'test'; const chunkLength = Buffer.byteLength(chunk); const contentLength = count * chunkLength; const readable = stream.Readable.from( (async function* () { let i = count; while (i-- > 0) { await setTimeoutAsync(1100); content += chunk; yield chunk; } })() ); const samples = []; const { data } = await fetchAxios.post( `http://localhost:${server.address().port}/`, readable, { onDownloadProgress: ({ loaded, total, progress, bytes, download }) => { console.log( `Download Progress ${loaded} from ${total} bytes (${(progress * 100).toFixed(1)}%)` ); samples.push({ loaded, total, progress, bytes, download, }); }, headers: { 'Content-Length': contentLength, }, responseType: 'text', maxRedirects: 0, } ); await setTimeoutAsync(500); assert.strictEqual(data, content); assert.deepStrictEqual( samples, Array.from( (function* () { for (let i = 1; i <= 10; i++) { yield { loaded: chunkLength * i, total: contentLength, progress: (chunkLength * i) / contentLength, bytes: 4, download: true, }; } })() ) ); } finally { await stopHTTPServer(server); } }, 15000); }); }); it('should support basic auth', async () => { const server = await startHTTPServer((req, res) => res.end(req.headers.authorization), { port: SERVER_PORT, }); try { const user = 'foo'; const headers = { Authorization: 'Bearer 1234' }; const res = await fetchAxios.get(`http://${user}@localhost:${server.address().port}/`, { headers, }); const base64 = Buffer.from(`${user}:`, 'utf8').toString('base64'); assert.equal(res.data, `Basic ${base64}`); } finally { await stopHTTPServer(server); } }); it('should decode basic auth credentials from the request URL', async () => { const server = await startHTTPServer( (req, res) => { res.end(req.headers.authorization); }, { port: SERVER_PORT } ); try { const response = await fetchAxios.get( `http://my%40email.com:pa%24ss@localhost:${server.address().port}/` ); const base64 = Buffer.from('my@email.com:pa$ss', 'utf8').toString('base64'); assert.strictEqual(response.data, `Basic ${base64}`); } finally { await stopHTTPServer(server); } }); it('should UTF-8 encode basic auth credentials from the request URL', async () => { const server = await startHTTPServer( (req, res) => { res.end(req.headers.authorization); }, { port: SERVER_PORT } ); try { const response = await fetchAxios.get( `http://%E7%94%A8%E6%88%B7:pa%C3%9F@localhost:${server.address().port}/` ); const base64 = Buffer.from('\u7528\u6237:pa\u00df', 'utf8').toString('base64'); assert.strictEqual(response.data, `Basic ${base64}`); } finally { await stopHTTPServer(server); } }); it('keeps malformed URL credentials percent-encoding and does not throw', async () => { const server = await startHTTPServer( (req, res) => { res.end(req.headers.authorization); }, { port: SERVER_PORT } ); try { const response = await fetchAxios.get(`http://user%:foo%zz@localhost:${server.address().port}/`); const base64 = Buffer.from('user%:foo%zz', 'utf8').toString('base64'); assert.strictEqual(response.data, `Basic ${base64}`); } finally { await stopHTTPServer(server); } }); it('should support password-only basic auth credentials from the request URL', async () => { const server = await startHTTPServer( (req, res) => { res.end(req.headers.authorization); }, { port: SERVER_PORT } ); try { const response = await fetchAxios.get(`http://:secret@localhost:${server.address().port}/`); const base64 = Buffer.from(':secret', 'utf8').toString('base64'); assert.strictEqual(response.data, `Basic ${base64}`); } finally { await stopHTTPServer(server); } }); it('should prefer config auth over basic auth credentials from the request URL', async () => { const server = await startHTTPServer( (req, res) => { res.end(req.headers.authorization); }, { port: SERVER_PORT } ); try { const auth = { username: 'config-user', password: 'config-pass' }; const response = await fetchAxios.get( `http://url-user:url-pass@localhost:${server.address().port}/`, { auth } ); const base64 = Buffer.from('config-user:config-pass', 'utf8').toString('base64'); assert.strictEqual(response.data, `Basic ${base64}`); } finally { await stopHTTPServer(server); } }); it('should support basic auth with a header', async () => { const server = await startHTTPServer( (req, res) => { res.end(req.headers.authorization); }, { port: SERVER_PORT } ); try { const auth = { username: 'foo', password: 'bar' }; const headers = { AuThOrIzAtIoN: 'Bearer 1234' }; // wonky casing to ensure caseless comparison const response = await fetchAxios.get(`http://localhost:${server.address().port}/`, { auth, headers, }); const base64 = Buffer.from('foo:bar', 'utf8').toString('base64'); assert.strictEqual(response.data, `Basic ${base64}`); } finally { await stopHTTPServer(server); } }); it('should ignore inherited nested auth fields', async () => { const server = await startHTTPServer((req, res) => res.end(req.headers.authorization), { port: SERVER_PORT, }); Object.defineProperty(Object.prototype, 'username', { value: 'inherited-user', configurable: true, }); Object.defineProperty(Object.prototype, 'password', { value: 'inherited-pass', configurable: true, }); try { const response = await fetchAxios.get(`http://localhost:${server.address().port}/`, { auth: {}, }); assert.strictEqual(response.data, 'Basic Og=='); } finally { delete Object.prototype.username; delete Object.prototype.password; await stopHTTPServer(server); } }); it('should support stream.Readable as a payload', async () => { const server = await startHTTPServer(async (req, res) => res.end('OK'), { port: SERVER_PORT }); try { const { data } = await fetchAxios.post( `http://localhost:${server.address().port}/`, stream.Readable.from('OK') ); assert.strictEqual(data, 'OK'); } finally { await stopHTTPServer(server); } }); describe('request aborting', () => { it('should be able to abort the request stream', async () => { const server = await startHTTPServer( { rate: 100000, useBuffering: true, }, { port: SERVER_PORT } ); try { const controller = new AbortController(); setTimeout(() => { controller.abort(); }, 500); await assert.rejects(async () => { await fetchAxios.post( `http://localhost:${server.address().port}/`, makeReadableStream(), { responseType: 'stream', signal: controller.signal, } ); }, /CanceledError/); } finally { await stopHTTPServer(server); } }); it('should be able to abort the response stream', async () => { const server = await startHTTPServer( (req, res) => { pipelineAsync(generateReadable(10000, 10), res).catch(() => { // Client-side abort intentionally closes the stream early in this test. }); }, { port: SERVER_PORT } ); try { const controller = new AbortController(); setTimeout(() => { controller.abort(new Error('test')); }, 800); const { data } = await fetchAxios.get(`http://localhost:${server.address().port}/`, { responseType: 'stream', signal: controller.signal, }); await assert.rejects(async () => { await data.pipeTo(makeEchoStream()); }, /^(AbortError|CanceledError):/); } finally { await stopHTTPServer(server); } }); }); it('should support a timeout', async () => { const server = await startHTTPServer( async (req, res) => { await setTimeoutAsync(1000); res.end('OK'); }, { port: 0 } ); try { const timeout = 500; const ts = Date.now(); await assert.rejects(async () => { await fetchAxios(`http://localhost:${server.address().port}/`, { timeout, }); }, /timeout/); const passed = Date.now() - ts; assert.ok(passed >= timeout - 5, `early cancellation detected (${passed} ms)`); } finally { await stopHTTPServer(server); } }); describe('fetch adapter - timeout normalization', () => { it('should reject with an AxiosError(ETIMEDOUT) on timeout', async () => { const server = await startHTTPServer( async (req, res) => { await setTimeoutAsync(1000); res.end('OK'); }, { port: 0 } ); try { await assert.rejects( () => fetchAxios(`http://localhost:${server.address().port}/`, { timeout: 200, }), (err) => { assert.strictEqual(err.name, 'AxiosError'); assert.strictEqual(err.code, 'ETIMEDOUT'); assert.match(err.message, /timeout of 200ms exceeded/); return true; } ); } finally { await stopHTTPServer(server); } }); it('should not classify a user-initiated abort as a timeout', async () => { const safariFetch = (url, init) => { const signal = getFetchSignal(url, init); return new Promise((_resolve, reject) => { const onAbort = () => { signal.removeEventListener('abort', onAbort); reject(createBrokenDOMExceptionLikeError()); }; if (signal.aborted) return onAbort(); signal.addEventListener('abort', onAbort); }); }; const controller = new AbortController(); const request = fetchAxios.get('/', { signal: controller.signal, env: { fetch: safariFetch }, }); controller.abort(); await assert.rejects( () => request, (err) => { assert.strictEqual(err.name, 'CanceledError'); assert.strictEqual(err.code, 'ERR_CANCELED'); assert.strictEqual(axios.isCancel(err), true); return true; } ); }); // Timing-sensitive: a 50ms abort race observed by a fake fetch can flake // under CI runner load even though the production code is fine. Retry as // a backstop. it( 'should surface ETIMEDOUT when fetch rejects with a broken DOMException on abort (Safari)', { retry: 2 }, async () => { const safariFetch = (url, init) => { const signal = getFetchSignal(url, init); return new Promise((_resolve, reject) => { const onAbort = () => { signal.removeEventListener('abort', onAbort); reject(createBrokenDOMExceptionLikeError()); }; if (signal.aborted) return onAbort(); signal.addEventListener('abort', onAbort); }); }; await assert.rejects( () => fetchAxios.get('/', { timeout: 50, env: { fetch: safariFetch }, }), (err) => { assert.strictEqual(err.name, 'AxiosError'); assert.strictEqual(err.code, 'ETIMEDOUT'); assert.match(err.message, /timeout of 50ms exceeded/); return true; } ); } ); }); it('should combine baseURL and url', async () => { const server = await startHTTPServer(async (req, res) => res.end('OK'), { port: SERVER_PORT }); try { const res = await fetchAxios('/foo'); assert.equal(res.config.baseURL, LOCAL_SERVER_URL); assert.equal(res.config.url, '/foo'); } finally { await stopHTTPServer(server); } }); it('should send QUERY requests with a body through the fetch adapter', async () => { const server = await startHTTPServer( (req, res) => { let body = ''; req.on('data', (chunk) => { body += chunk; }); req.on('end', () => { res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ method: req.method, url: req.url, body })); }); }, { port: 0 } ); try { const { data } = await fetchAxios.query(`http://localhost:${server.address().port}/search`, { selector: 'field1', }); assert.strictEqual(data.method, 'QUERY'); assert.strictEqual(data.url, '/search'); assert.deepStrictEqual(JSON.parse(data.body), { selector: 'field1' }); } finally { await stopHTTPServer(server); } }); it('should support params', async () => { const server = await startHTTPServer((req, res) => res.end(req.url), { port: SERVER_PORT }); try { const { data } = await fetchAxios.get(`http://localhost:${server.address().port}/?test=1`, { params: { foo: 1, bar: 2, }, }); assert.strictEqual(data, '/?test=1&foo=1&bar=2'); } finally { await stopHTTPServer(server); } }); it('should handle fetch failed error as an AxiosError with ERR_NETWORK code', async () => { try { await fetchAxios('http://notExistsUrl.in.nowhere'); assert.fail('should fail'); } catch (err) { assert.strictEqual(String(err), 'AxiosError: Network Error'); assert.strictEqual(err.cause && err.cause.code, 'ENOTFOUND'); } }); it('should get response headers', async () => { const server = await startHTTPServer( (req, res) => { res.setHeader('foo', 'bar'); res.end(req.url); }, { port: SERVER_PORT } ); try { const { headers } = await fetchAxios.get(`http://localhost:${server.address().port}/`, { responseType: 'stream', }); assert.strictEqual(headers.get('foo'), 'bar'); } finally { await stopHTTPServer(server); } }); describe('fetch adapter - Content-Type handling', () => { it('should set correct Content-Type for FormData automatically', async () => { const form = new NodeFormData(); form.append('foo', 'bar'); const server = await startHTTPServer( (req, res) => { const contentType = req.headers['content-type']; assert.match(contentType, /^multipart\/form-data; boundary=/i); res.end('OK'); }, { port: SERVER_PORT } ); try { await fetchAxios.post(`http://localhost:${server.address().port}/form`, form); } finally { await stopHTTPServer(server); } }); it('should remove manually set Content-Type without boundary for FormData', async () => { const form = new FormData(); form.append('foo', 'bar'); const server = await startHTTPServer( (req, res) => { const contentType = req.headers['content-type']; assert.match(contentType, /^multipart\/form-data; boundary=/i); res.end('OK'); }, { port: SERVER_PORT } ); try { await fetchAxios.post(`http://localhost:${server.address().port}/form`, form, { headers: { 'Content-Type': 'multipart/form-data' }, }); } finally { await stopHTTPServer(server); } }); it('should preserve Content-Type if it already has boundary', async () => { const form = new FormData(); form.append('foo', 'bar'); const customBoundary = '----CustomBoundary123'; const server = await startHTTPServer( (req, res) => { const contentType = req.headers['content-type']; assert.ok(contentType.includes(customBoundary)); res.end('OK'); }, { port: SERVER_PORT } ); try { await fetchAxios.post(`http://localhost:${server.address().port}/form`, form, { headers: { 'Content-Type': `multipart/form-data; boundary=${customBoundary}`, }, }); } finally { await stopHTTPServer(server); } }); }); describe('fetch adapter - User-Agent header', () => { it('should set User-Agent header to axios/ by default', async () => { const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ userAgent: req.headers['user-agent'] })); }, { port: SERVER_PORT } ); try { const { data } = await fetchAxios.post(`http://localhost:${server.address().port}/`, { payload: 'test', }); assert.strictEqual(data.userAgent, `axios/${VERSION}`); } finally { await stopHTTPServer(server); } }); it('should not override a user-provided User-Agent header', async () => { const customUA = 'my-custom-agent/1.0'; const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ userAgent: req.headers['user-agent'] })); }, { port: SERVER_PORT } ); try { const { data } = await fetchAxios.post( `http://localhost:${server.address().port}/`, { payload: 'test' }, { headers: { 'User-Agent': customUA } } ); assert.strictEqual(data.userAgent, customUA); } finally { await stopHTTPServer(server); } }); }); describe('env config', () => { it('should fallback to globalThis when utils.global is temporarily undefined', () => { const originalGlobal = utils.global; try { utils.global = undefined; assert.doesNotThrow(() => getFetch({ env: { fetch() {}, }, }) ); } finally { utils.global = originalGlobal; } }); it('should respect env fetch API configuration', async () => { const { data, headers } = await fetchAxios.get('/', { env: { fetch() { return { headers: { foo: '1', }, text: async () => 'test', }; }, }, }); assert.strictEqual(headers.get('foo'), '1'); assert.strictEqual(data, 'test'); }); it('should be able to request with lack of Request object', async () => { const form = new FormData(); form.append('x', '1'); const { data, headers } = await fetchAxios.post('/', form, { onUploadProgress() { // dummy listener to activate streaming }, env: { Request: null, fetch() { return { headers: { foo: '1', }, text: async () => 'test', }; }, }, }); assert.strictEqual(headers.get('foo'), '1'); assert.strictEqual(data, 'test'); }); it('should be able to handle response with lack of Response object', async () => { const { data, headers } = await fetchAxios.get('/', { onDownloadProgress() { // dummy listener to activate streaming }, env: { Request: null, Response: null, fetch() { return { headers: { foo: '1', }, text: async () => 'test', }; }, }, }); assert.strictEqual(headers.get('foo'), '1'); assert.strictEqual(data, 'test'); }); it('should fallback to the global on undefined env value', async () => { const server = await startHTTPServer((req, res) => res.end('OK'), { port: SERVER_PORT }); try { const { data } = await fetchAxios.get(`http://localhost:${server.address().port}/`, { env: { fetch: undefined, }, }); assert.strictEqual(data, 'OK'); } finally { await stopHTTPServer(server); } }); it('should use current global fetch when env fetch is not specified', async () => { const globalFetch = global.fetch; vi.stubGlobal('fetch', async () => { return { headers: { foo: '1', }, text: async () => 'global', }; }); const server = await startHTTPServer((req, res) => res.end('OK'), { port: SERVER_PORT }); try { const { data } = await fetchAxios.get(`http://localhost:${server.address().port}/`, { env: { fetch: undefined, }, }); assert.strictEqual(data, 'global'); } finally { vi.stubGlobal('fetch', globalFetch); await stopHTTPServer(server); } }); }); describe('size limits', () => { const makeUploadStream = (totalBytes, chunkSize = 512) => { let remaining = totalBytes; return new ReadableStream({ pull(controller) { if (remaining <= 0) { controller.close(); return; } const size = Math.min(chunkSize, remaining); remaining -= size; controller.enqueue(new Uint8Array(size)); }, }); }; it('should reject an outbound body that exceeds maxBodyLength with ERR_BAD_REQUEST', async () => { const server = await startHTTPServer( (req, res) => { res.end('ok'); }, { port: SERVER_PORT } ); try { await assert.rejects( fetchAxios.post(`${LOCAL_SERVER_URL}/`, 'A'.repeat(2048), { maxBodyLength: 1024, }), (err) => { assert.strictEqual(err.code, 'ERR_BAD_REQUEST'); assert.match(err.message, /Request body larger than maxBodyLength limit/); return true; } ); } finally { await stopHTTPServer(server); } }); it('should reject a streamed outbound body that exceeds maxBodyLength during upload', async () => { let bytesReceived = 0; const server = await startHTTPServer( (req, res) => { req.on('data', (chunk) => { bytesReceived += chunk.length; }); req.on('error', () => {}); req.on('end', () => { res.end('ok'); }); }, { port: SERVER_PORT } ); try { await assert.rejects( fetchAxios.post(`${LOCAL_SERVER_URL}/`, makeUploadStream(2048), { maxBodyLength: 1024, headers: { 'Content-Type': 'application/octet-stream' }, }), (err) => { assert.strictEqual(err.code, 'ERR_BAD_REQUEST'); assert.strictEqual(err.message, 'Request body larger than maxBodyLength limit'); return true; } ); assert.ok( bytesReceived <= 1024, `server should not receive more than maxBodyLength; got ${bytesReceived}` ); } finally { await stopHTTPServer(server); } }); it('should enforce maxBodyLength on a stream even when a smaller Content-Length is declared', async () => { let bytesReceived = 0; const server = await startHTTPServer( (req, res) => { req.on('data', (chunk) => { bytesReceived += chunk.length; }); req.on('error', () => {}); req.on('end', () => { res.end('ok'); }); }, { port: SERVER_PORT } ); try { await assert.rejects( // A caller-declared Content-Length that under-reports the real body // must not let an oversized stream slip past the limit. fetchAxios.post(`${LOCAL_SERVER_URL}/`, makeUploadStream(8192), { maxBodyLength: 1024, headers: { 'Content-Type': 'application/octet-stream', 'Content-Length': '500', }, }), (err) => { assert.strictEqual(err.code, 'ERR_BAD_REQUEST'); assert.strictEqual(err.message, 'Request body larger than maxBodyLength limit'); return true; } ); assert.ok( bytesReceived <= 1024, `server should not receive more than maxBodyLength; got ${bytesReceived}` ); } finally { await stopHTTPServer(server); } }); it('should enforce maxBodyLength with custom fetch when Request is unavailable', async () => { let bytesRead = 0; await assert.rejects( fetchAxios.post('/', makeUploadStream(2048), { maxBodyLength: 1024, headers: { 'Content-Type': 'application/octet-stream', 'Content-Length': '1', }, env: { Request: null, async fetch(_url, options) { for await (const chunk of options.body) { bytesRead += chunk.byteLength; } return { headers: {}, status: 200, statusText: 'OK', text: async () => 'ok', }; }, }, }), (err) => { assert.strictEqual(err.code, 'ERR_BAD_REQUEST'); assert.strictEqual(err.message, 'Request body larger than maxBodyLength limit'); return true; } ); assert.ok(bytesRead <= 1024, `custom fetch read too many bytes; got ${bytesRead}`); }); it('should not force ReadableStream bodies when Request does not support request streams', async () => { let fetchCalled = false; class NoStreamRequest { constructor(_url, init) { if (init && utils.isReadableStream(init.body)) { throw new TypeError('ReadableStream request bodies are unsupported'); } } } await assert.rejects( fetchAxios.post('/', stream.Readable.from([Buffer.alloc(2048)]), { maxBodyLength: 1024, headers: { 'Content-Type': 'application/octet-stream', }, env: { Request: NoStreamRequest, Response: null, async fetch() { fetchCalled = true; return { headers: {}, status: 200, statusText: 'OK', text: async () => 'ok', }; }, }, }), (err) => { assert.strictEqual(err.code, 'ERR_NOT_SUPPORT'); assert.strictEqual( err.message, 'Stream request bodies are not supported by the current fetch implementation' ); return true; } ); assert.strictEqual(fetchCalled, false, 'fetch must not receive a forced ReadableStream body'); }); it('should reject a response whose Content-Length exceeds maxContentLength with ERR_BAD_RESPONSE', async () => { const payload = 'A'.repeat(8 * 1024); const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Length', Buffer.byteLength(payload)); res.end(payload); }, { port: SERVER_PORT } ); try { await assert.rejects( fetchAxios.get(`${LOCAL_SERVER_URL}/`, { maxContentLength: 1024, }), (err) => { assert.strictEqual(err.code, 'ERR_BAD_RESPONSE'); assert.match(err.message, /maxContentLength size of 1024 exceeded/); return true; } ); } finally { await stopHTTPServer(server); } }); it('should handle plain object response headers while enforcing maxContentLength', async () => { const { data, headers } = await fetchAxios.get('/', { maxContentLength: 10, env: { async fetch() { return { status: 200, statusText: 'OK', headers: { 'content-length': '4', foo: 'bar', }, body: new ReadableStream({ start(controller) { controller.enqueue(new Uint8Array([116, 101, 115, 116])); controller.close(); }, }), }; }, }, }); assert.strictEqual(data, 'test'); assert.strictEqual(headers.get('foo'), 'bar'); }); it('should reject a chunked response that exceeds maxContentLength during streaming', async () => { const server = await startHTTPServer( (req, res) => { // Omit content-length so the cheap pre-check cannot fire; force // the stream-based enforcement path. res.setHeader('Transfer-Encoding', 'chunked'); const chunk = 'B'.repeat(1024); let sent = 0; const writeNext = () => { if (sent >= 8) { return res.end(); } sent++; res.write(chunk, writeNext); }; writeNext(); }, { port: SERVER_PORT } ); try { await assert.rejects( fetchAxios.get(`${LOCAL_SERVER_URL}/`, { maxContentLength: 512, }), (err) => { assert.strictEqual(err.code, 'ERR_BAD_RESPONSE'); assert.match(err.message, /maxContentLength size of 512 exceeded/); return true; } ); } finally { await stopHTTPServer(server); } }); it('should reject a data: URL whose decoded size exceeds maxContentLength (base64)', async () => { const payload = 'A'.repeat(4096); const dataUrl = 'data:application/octet-stream;base64,' + Buffer.from(payload).toString('base64'); // Use a dedicated instance without baseURL — combineURLs would otherwise // prepend baseURL to a data: URL and neutralise the pre-check. const bareAxios = axios.create({ adapter: 'fetch' }); await assert.rejects(bareAxios.get(dataUrl, { maxContentLength: 16 }), (err) => { assert.strictEqual(err.code, 'ERR_BAD_RESPONSE'); assert.match(err.message, /maxContentLength size of 16 exceeded/); return true; }); }); it('should reject a data: URL whose body size exceeds maxContentLength (non-base64)', async () => { const dataUrl = 'data:text/plain,' + 'X'.repeat(4096); const bareAxios = axios.create({ adapter: 'fetch' }); await assert.rejects(bareAxios.get(dataUrl, { maxContentLength: 16 }), (err) => { assert.strictEqual(err.code, 'ERR_BAD_RESPONSE'); assert.match(err.message, /maxContentLength size of 16 exceeded/); return true; }); }); it('should allow a percent-encoded data: URL within decoded maxContentLength', async () => { const bareAxios = axios.create({ adapter: 'fetch' }); const { data } = await bareAxios.get('data:text/plain,%E2%82%AC', { maxContentLength: 4, }); assert.strictEqual(data, '\u20ac'); }); it('should allow a response at or below maxContentLength', async () => { const payload = 'ok'; const server = await startHTTPServer( (req, res) => { res.end(payload); }, { port: SERVER_PORT } ); try { const { data } = await fetchAxios.get(`${LOCAL_SERVER_URL}/`, { maxContentLength: 1024, }); assert.strictEqual(data, payload); } finally { await stopHTTPServer(server); } }); it('should allow a streamed outbound body at or below maxBodyLength', async () => { const payloadLength = 1024; let bytesReceived = 0; const server = await startHTTPServer( (req, res) => { req.on('data', (chunk) => { bytesReceived += chunk.length; }); req.on('end', () => { res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ received: bytesReceived })); }); }, { port: SERVER_PORT } ); try { const { data } = await fetchAxios.post( `${LOCAL_SERVER_URL}/`, makeUploadStream(payloadLength), { maxBodyLength: 1024, headers: { 'Content-Type': 'application/octet-stream' }, } ); assert.strictEqual(data.received, payloadLength); } finally { await stopHTTPServer(server); } }); it('should allow a body at or below maxBodyLength', async () => { const payload = 'hello'; let received; const server = await startHTTPServer( (req, res) => { const chunks = []; req.on('data', (c) => chunks.push(c)); req.on('end', () => { received = Buffer.concat(chunks).toString(); res.end('ok'); }); }, { port: SERVER_PORT } ); try { await fetchAxios.post(`${LOCAL_SERVER_URL}/`, payload, { maxBodyLength: 1024, }); assert.strictEqual(received, payload); } finally { await stopHTTPServer(server); } }); }); describe('capability probe cleanup', () => { it('should cancel the ReadableStream created during the request stream probe', () => { // The fetch adapter factory probes for request-stream support by creating // a ReadableStream as a Request body. Previously the stream was never // cancelled, leaving a dangling pull-algorithm promise (async resource leak // visible via `--detect-async-leaks` or Node.js async_hooks). // // Calling getFetch with a unique env triggers a fresh factory() execution // (including the probe). We spy on ReadableStream.prototype.cancel to // verify it is invoked during the probe. const cancelSpy = vi.spyOn(ReadableStream.prototype, 'cancel'); try { // Unique fetch function ensures cache miss → factory() re-runs the probe. const uniqueFetch = async () => new Response('ok'); getFetch({ env: { fetch: uniqueFetch } }); assert.ok( cancelSpy.mock.calls.length > 0, 'ReadableStream.prototype.cancel should be called during the capability probe' ); } finally { cancelSpy.mockRestore(); } }); }); }); axios-axios-2d06f96/tests/unit/adapters/http.test.js000066400000000000000000006033671521272452000225560ustar00rootroot00000000000000import { describe, it } from 'vitest'; import assert from 'assert'; import { startHTTPServer, stopHTTPServer, SERVER_HANDLER_STREAM_ECHO, handleFormData, setTimeoutAsync, generateReadable, } from '../../setup/server.js'; import axios from '../../../index.js'; import AxiosError from '../../../lib/core/AxiosError.js'; import httpAdapter, { __isSameOriginRedirect, __setProxy } from '../../../lib/adapters/http.js'; import HttpsProxyAgent from 'https-proxy-agent'; import http from 'http'; import https from 'https'; import net from 'net'; import stream from 'stream'; import zlib from 'zlib'; import fs from 'fs'; import os from 'os'; import path from 'path'; import devNull from 'dev-null'; import FormDataLegacy from 'form-data'; import { IncomingForm } from 'formidable'; import { FormData as FormDataPolyfill, Blob as BlobPolyfill } from 'formdata-node'; import express from 'express'; import multer from 'multer'; import getStream from 'get-stream'; import bodyParser from 'body-parser'; import { AbortController } from 'abortcontroller-polyfill/dist/cjs-ponyfill.js'; import { lookup } from 'dns'; import { EventEmitter } from 'events'; const OPEN_WEB_PORT = 80; const SERVER_PORT = 8020; const PROXY_PORT = 8030; const ALTERNATE_SERVER_PORT = 8040; describe('supports http with nodejs', () => { const adaptersTestsDir = path.join(process.cwd(), 'tests/unit/adapters'); const thisTestFilePath = path.join(adaptersTestsDir, 'http.test.js'); const FormDataSpecCompliant = typeof FormData !== 'undefined' ? FormData : FormDataPolyfill; const BlobSpecCompliant = typeof Blob !== 'undefined' ? Blob : BlobPolyfill; const isBlobSupported = typeof Blob !== 'undefined'; function toleranceRange(positive, negative) { const p = 1 + positive / 100; const n = 1 - negative / 100; return (actualValue, value) => { return actualValue > value ? actualValue <= value * p : actualValue >= value * n; }; } class HangingConnectSocket extends stream.Duplex { constructor() { super(); this.connecting = true; } _read() {} _write(_chunk, _encoding, callback) { callback(); } setKeepAlive() { return this; } setNoDelay() { return this; } setTimeout() { return this; } } class HangingConnectAgent extends http.Agent { createConnection() { return new HangingConnectSocket(); } } it('should support IPv4 literal strings', async () => { const data = { firstName: 'Fred', lastName: 'Flintstone', emailAddr: 'fred@example.com', }; const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify(data)); }, { port: SERVER_PORT } ); try { const { data: responseData } = await axios.get(`http://127.0.0.1:${server.address().port}`); assert.deepStrictEqual(responseData, data); } finally { await stopHTTPServer(server); } }); it('should support IPv6 literal strings', async () => { var data = { firstName: 'Fred', lastName: 'Flintstone', emailAddr: 'fred@example.com', }; const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify(data)); }, { port: SERVER_PORT } ); try { const { data: responseData } = await axios.get(`http://[::1]:${server.address().port}`, { proxy: false, }); assert.deepStrictEqual(responseData, data); } finally { await stopHTTPServer(server); } }); it('should throw an error if the timeout property is not parsable as a number', async () => { const server = await startHTTPServer( (req, res) => { setTimeout(() => { res.end(); }, 1000); }, { port: SERVER_PORT } ); try { await assert.rejects( axios.get(`http://localhost:${server.address().port}`, { timeout: { strangeTimeout: 250 }, }), (error) => { assert.strictEqual(error.code, AxiosError.ERR_BAD_OPTION_VALUE); assert.strictEqual(error.message, 'error trying to parse `config.timeout` to int'); return true; } ); } finally { await stopHTTPServer(server); } }); it('should sanitize request headers containing CRLF characters', async () => { const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'application/json'); res.end( JSON.stringify({ xTest: req.headers['x-test'], injected: req.headers.injected ?? null, }) ); }, { port: SERVER_PORT } ); try { const { data } = await axios.get(`http://localhost:${server.address().port}/`, { headers: { 'x-test': '\tok\r\nInjected: yes ', }, }); assert.strictEqual(data.xTest, 'okInjected: yes'); assert.strictEqual(data.injected, null); } finally { await stopHTTPServer(server); } }); it('should allow request interceptors to encode Unicode header values before Node sends them', async () => { const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'application/json'); res.end( JSON.stringify({ oprtName: req.headers.oprtname, }) ); }, { port: SERVER_PORT } ); const instance = axios.create({ proxy: false }); instance.interceptors.request.use((config) => { config.headers.oprtName = encodeURIComponent(config.headers.oprtName); return config; }); try { const { data } = await instance.get(`http://localhost:${server.address().port}/`, { headers: { oprtName: '请求用户', }, }); assert.strictEqual(data.oprtName, encodeURIComponent('请求用户')); } finally { await stopHTTPServer(server); } }); it('should sanitize unencoded Unicode request headers before passing them to Node', async () => { const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'application/json'); res.end( JSON.stringify({ xTest: req.headers['x-test'], }) ); }, { port: SERVER_PORT } ); try { const { data } = await axios.get(`http://localhost:${server.address().port}/`, { proxy: false, headers: { 'x-test': '请求用户', }, }); assert.strictEqual(data.xTest, ''); } finally { await stopHTTPServer(server); } }); it('should parse the timeout property', async () => { const server = await startHTTPServer( (req, res) => { setTimeout(() => { res.end(); }, 1000); }, { port: SERVER_PORT } ); try { await assert.rejects( axios.get(`http://localhost:${server.address().port}`, { timeout: '250', }), (error) => { assert.strictEqual(error.code, 'ECONNABORTED'); assert.strictEqual(error.message, 'timeout of 250ms exceeded'); return true; } ); } finally { await stopHTTPServer(server); } }); it('should respect the timeout property', async () => { const server = await startHTTPServer( (req, res) => { setTimeout(() => { res.end(); }, 1000); }, { port: SERVER_PORT } ); try { await assert.rejects( axios.get(`http://localhost:${server.address().port}`, { timeout: 250, }), (error) => { assert.strictEqual(error.code, 'ECONNABORTED'); assert.strictEqual(error.message, 'timeout of 250ms exceeded'); return true; } ); } finally { await stopHTTPServer(server); } }); it('should respect the timeout property during TCP connect with maxRedirects set to 0', async () => { const timeout = 100; const guardTimeout = 1000; const started = Date.now(); const controller = new AbortController(); const agent = new HangingConnectAgent(); let guardTimer; const request = axios.get('http://connect-timeout.test/', { httpAgent: agent, maxRedirects: 0, proxy: false, signal: controller.signal, timeout, }); const guard = new Promise((_resolve, reject) => { guardTimer = setTimeout(() => { controller.abort(); reject(new Error('request did not honor timeout during connect')); }, guardTimeout); }); try { await assert.rejects(Promise.race([request, guard]), (error) => { const elapsed = Date.now() - started; assert.strictEqual(error.code, 'ECONNABORTED'); assert.strictEqual(error.message, `timeout of ${timeout}ms exceeded`); assert.ok(elapsed < guardTimeout, `request timed out after ${elapsed}ms`); return true; }); } finally { clearTimeout(guardTimer); controller.abort(); agent.destroy(); } }); it('should not time out immediately for timeout set to zero during TCP connect', async () => { const controller = new AbortController(); const agent = new HangingConnectAgent(); const request = axios .get('http://connect-timeout.test/', { httpAgent: agent, maxRedirects: 0, proxy: false, signal: controller.signal, timeout: '0', }) .then( () => null, (error) => error ); try { await setTimeoutAsync(50); controller.abort(); const error = await request; assert.strictEqual(error.code, AxiosError.ERR_CANCELED); } finally { controller.abort(); agent.destroy(); } }); it('should respect the timeoutErrorMessage property', async () => { const server = await startHTTPServer( (req, res) => { setTimeout(() => { res.end(); }, 1000); }, { port: SERVER_PORT } ); try { await assert.rejects( axios.get(`http://localhost:${server.address().port}`, { timeout: 250, timeoutErrorMessage: 'oops, timeout', }), (error) => { assert.strictEqual(error.code, 'ECONNABORTED'); assert.strictEqual(error.message, 'oops, timeout'); return true; } ); } finally { await stopHTTPServer(server); } }); it('should allow passing JSON', async () => { const data = { firstName: 'Fred', lastName: 'Flintstone', emailAddr: 'fred@example.com', }; const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify(data)); }, { port: SERVER_PORT } ); try { const { data: responseData } = await axios.get(`http://localhost:${server.address().port}`); assert.deepStrictEqual(responseData, data); } finally { await stopHTTPServer(server); } }); it('should allow passing JSON with BOM', async () => { const data = { firstName: 'Fred', lastName: 'Flintstone', emailAddr: 'fred@example.com', }; const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'application/json'); const bomBuffer = Buffer.from([0xef, 0xbb, 0xbf]); const jsonBuffer = Buffer.from(JSON.stringify(data)); res.end(Buffer.concat([bomBuffer, jsonBuffer])); }, { port: SERVER_PORT } ); try { const { data: responseData } = await axios.get(`http://localhost:${server.address().port}`); assert.deepStrictEqual(responseData, data); } finally { await stopHTTPServer(server); } }); it('should redirect', async () => { const expectedResponse = 'test response'; const server = await startHTTPServer( (req, res) => { if (req.url === '/one') { res.setHeader('Location', '/two'); res.statusCode = 302; res.end(); return; } res.end(expectedResponse); }, { port: SERVER_PORT } ); try { const response = await axios.get(`http://localhost:${server.address().port}/one`, { maxRedirects: 1, }); assert.strictEqual(response.data, expectedResponse); assert.strictEqual(response.request.path, '/two'); } finally { await stopHTTPServer(server); } }); it('should not redirect', async () => { const server = await startHTTPServer( (req, res) => { res.setHeader('Location', '/foo'); res.statusCode = 302; res.end(); }, { port: SERVER_PORT } ); try { const response = await axios.get(`http://localhost:${server.address().port}/one`, { maxRedirects: 0, }); assert.strictEqual(response.status, 302); assert.strictEqual(response.headers.location, '/foo'); } catch (error) { assert.strictEqual(error.message, 'Request failed with status code 302'); assert.strictEqual(error.response.status, 302); assert.strictEqual(error.response.headers.location, '/foo'); } finally { await stopHTTPServer(server); } }); it('should support max redirects', async () => { var i = 1; const server = await startHTTPServer( (req, res) => { res.setHeader('Location', `/${i}`); res.statusCode = 302; res.end(); i++; }, { port: SERVER_PORT } ); try { await axios.get(`http://localhost:${server.address().port}`, { maxRedirects: 3, }); } catch (error) { assert.strictEqual(error.code, AxiosError.ERR_FR_TOO_MANY_REDIRECTS); assert.strictEqual(error.message, 'Maximum number of redirects exceeded'); } finally { await stopHTTPServer(server); } }); it('should support beforeRedirect', async () => { const server = await startHTTPServer( (req, res) => { res.setHeader('Location', '/foo'); res.statusCode = 302; res.end(); }, { port: SERVER_PORT } ); try { await axios.get(`http://localhost:${server.address().port}/one`, { maxRedirects: 3, beforeRedirect: (options, responseDetails) => { if (options.path === '/foo' && responseDetails.headers.location === '/foo') { throw new Error('Provided path is not allowed'); } }, }); } catch (error) { assert.strictEqual(error.message, 'Redirected request failed: Provided path is not allowed'); } finally { await stopHTTPServer(server); } }); it('should pass requestDetails to beforeRedirect with the original URL', async () => { const server = await startHTTPServer( (req, res) => { res.setHeader('Location', '/foo'); res.statusCode = 302; res.end(); }, { port: SERVER_PORT } ); const originalUrl = `http://localhost:${server.address().port}/bar`; let capturedUrl; try { await axios.get(originalUrl, { maxRedirects: 3, beforeRedirect: (options, responseDetails, requestDetails) => { if (options.path === '/foo' && responseDetails.headers.location === '/foo') { capturedUrl = requestDetails.url; throw new Error('Provided path is not allowed'); } }, }); } catch (error) { assert.strictEqual(error.message, 'Redirected request failed: Provided path is not allowed'); assert.strictEqual(capturedUrl, originalUrl); } finally { await stopHTTPServer(server); } }); it('should support beforeRedirect and proxy with redirect', async () => { let requestCount = 0; let proxyUseCount = 0; let totalRedirectCount = 5; let configBeforeRedirectCount = 0; const server = await startHTTPServer( (req, res) => { requestCount += 1; if (requestCount <= totalRedirectCount) { res.setHeader('Location', `http://localhost:${SERVER_PORT}`); res.writeHead(302); } res.end(); }, { port: SERVER_PORT } ); const proxy = await startHTTPServer( (req, res) => { proxyUseCount += 1; const targetUrl = new URL(req.url, `http://localhost:${server.address().port}`); const opts = { host: targetUrl.hostname, port: targetUrl.port, path: targetUrl.path, method: req.method, }; const request = http.get(opts, (response) => { res.writeHead(response.statusCode, response.headers); stream.pipeline(response, res, () => {}); }); request.on('error', (err) => { console.warn('request error', err); res.statusCode = 500; res.end(); }); }, { port: PROXY_PORT } ); await axios.get(`http://localhost:${server.address().port}/`, { proxy: { host: 'localhost', port: PROXY_PORT, }, maxRedirects: totalRedirectCount, beforeRedirect: (options) => { configBeforeRedirectCount += 1; }, }); assert.strictEqual(totalRedirectCount, configBeforeRedirectCount); assert.strictEqual(totalRedirectCount + 1, proxyUseCount); await stopHTTPServer(server); await stopHTTPServer(proxy); }); it('should strip sensitiveHeaders on cross-origin redirect', async () => { let capturedHeaders; // destination server — different port means different origin const destination = await startHTTPServer((req, res) => { capturedHeaders = req.headers; res.statusCode = 200; res.end('ok'); }); // origin server — redirects to destination (cross-origin) const origin = await startHTTPServer((req, res) => { res.setHeader('Location', `http://localhost:${destination.address().port}/dest`); res.statusCode = 302; res.end(); }); try { await axios.get(`http://localhost:${origin.address().port}/src`, { maxRedirects: 5, headers: { 'X-API-Key': 'secret', 'X-Other': 'keep' }, sensitiveHeaders: ['X-API-Key'], }); assert.strictEqual(capturedHeaders['x-api-key'], undefined, 'X-API-Key should be stripped'); assert.strictEqual(capturedHeaders['x-other'], 'keep', 'X-Other should be preserved'); } finally { await stopHTTPServer(origin); await stopHTTPServer(destination); } }); it('should preserve sensitiveHeaders on same-origin redirect', async () => { let capturedHeaders; let requestCount = 0; const server = await startHTTPServer((req, res) => { requestCount++; if (requestCount === 1) { res.setHeader('Location', '/dest'); res.statusCode = 302; res.end(); } else { capturedHeaders = req.headers; res.statusCode = 200; res.end('ok'); } }); try { await axios.get(`http://localhost:${server.address().port}/src`, { maxRedirects: 5, headers: { 'X-API-Key': 'secret' }, sensitiveHeaders: ['X-API-Key'], }); assert.strictEqual(capturedHeaders['x-api-key'], 'secret', 'X-API-Key should be preserved on same-origin redirect'); } finally { await stopHTTPServer(server); } }); it('should strip sensitiveHeaders case-insensitively on cross-origin redirect', async () => { let capturedHeaders; const destination = await startHTTPServer((req, res) => { capturedHeaders = req.headers; res.statusCode = 200; res.end('ok'); }); const origin = await startHTTPServer((req, res) => { res.setHeader('Location', `http://localhost:${destination.address().port}/dest`); res.statusCode = 302; res.end(); }); try { await axios.get(`http://localhost:${origin.address().port}/src`, { maxRedirects: 5, // Header sent with mixed casing; sensitiveHeaders list uses different casing headers: { 'X-Api-Key': 'secret' }, sensitiveHeaders: ['x-api-key'], }); assert.strictEqual(capturedHeaders['x-api-key'], undefined, 'X-Api-Key should be stripped case-insensitively'); } finally { await stopHTTPServer(origin); await stopHTTPServer(destination); } }); it('should strip sensitiveHeaders configured on an instance', async () => { let capturedHeaders; const destination = await startHTTPServer((req, res) => { capturedHeaders = req.headers; res.statusCode = 200; res.end('ok'); }); const origin = await startHTTPServer((req, res) => { res.setHeader('Location', `http://localhost:${destination.address().port}/dest`); res.statusCode = 302; res.end(); }); const client = axios.create({ headers: { 'X-API-Key': 'secret', 'X-Other': 'keep' }, sensitiveHeaders: ['X-API-Key'], }); try { await client.get(`http://localhost:${origin.address().port}/src`, { maxRedirects: 5, }); assert.strictEqual(capturedHeaders['x-api-key'], undefined, 'X-API-Key should be stripped'); assert.strictEqual(capturedHeaders['x-other'], 'keep', 'X-Other should be preserved'); } finally { await stopHTTPServer(origin); await stopHTTPServer(destination); } }); it('should reject invalid sensitiveHeaders config', async () => { await assert.rejects( axios.get('http://localhost:1/', { sensitiveHeaders: 'X-API-Key' }), (error) => { assert.strictEqual(error.code, AxiosError.ERR_BAD_OPTION_VALUE); assert.strictEqual(error.message, 'sensitiveHeaders must be an array of strings'); return true; } ); await assert.rejects( axios.get('http://localhost:1/', { sensitiveHeaders: [null] }), (error) => { assert.strictEqual(error.code, AxiosError.ERR_BAD_OPTION_VALUE); assert.strictEqual(error.message, 'sensitiveHeaders must be an array of strings'); return true; } ); }); it('should fail closed when sensitiveHeaders redirect origin cannot be parsed', () => { assert.strictEqual( __isSameOriginRedirect( { href: 'http://localhost/final' }, { url: 'http://localhost/start' } ), true ); assert.strictEqual( __isSameOriginRedirect({ href: 'http://[::1' }, { url: 'http://localhost/start' }), false ); assert.strictEqual(__isSameOriginRedirect({ href: 'http://localhost/final' }), false); }); it('should wrap HTTP errors and keep stack', async () => { const server = await startHTTPServer( (req, res) => { res.statusCode = 400; res.end(); }, { port: SERVER_PORT } ); try { await assert.rejects( async function stackTraceTest() { await axios.get(`http://localhost:${server.address().port}/`); }, (error) => { const matches = [...error.stack.matchAll(/stackTraceTest/g)]; assert.strictEqual(error.name, 'AxiosError'); assert.strictEqual(error.isAxiosError, true); assert.strictEqual(error.code, AxiosError.ERR_BAD_REQUEST); assert.strictEqual(error.message, 'Request failed with status code 400'); assert.strictEqual(matches.length, 1, error.stack); return true; } ); } finally { await stopHTTPServer(server); } }); it('should wrap interceptor errors and keep stack', async () => { const axiosInstance = axios.create(); axiosInstance.interceptors.request.use((res) => { throw new Error('from request interceptor'); }); const server = await startHTTPServer( (req, res) => { res.end(); }, { port: SERVER_PORT } ); try { await assert.rejects( async function stackTraceTest() { await axiosInstance.get(`http://localhost:${server.address().port}/one`); }, (error) => { const matches = [...error.stack.matchAll(/stackTraceTest/g)]; assert.strictEqual(error.name, 'Error'); assert.strictEqual(error.message, 'from request interceptor'); assert.strictEqual(matches.length, 1, error.stack); return true; } ); } finally { await stopHTTPServer(server); } }); it('should preserve the HTTP verb on redirect', async () => { const server = await startHTTPServer( (req, res) => { if (req.method.toLowerCase() !== 'head') { res.statusCode = 400; res.end(); return; } var parsed = new URL(req.url, 'http://localhost'); if (parsed.pathname === '/one') { res.setHeader('Location', '/two'); res.statusCode = 302; res.end(); } else { res.end(); } }, { port: SERVER_PORT } ); try { const response = await axios.head(`http://localhost:${server.address().port}/one`); assert.strictEqual(response.status, 200); } finally { await stopHTTPServer(server); } }); describe('compression', async () => { const isZstdSupported = typeof zlib.createZstdDecompress === 'function' && typeof zlib.zstdCompress === 'function'; it('should support transparent gunzip', async () => { const data = { firstName: 'Fred', lastName: 'Flintstone', emailAddr: 'fred@example.com', }; const zipped = await new Promise((resolve, reject) => { zlib.gzip(JSON.stringify(data), (error, compressed) => { if (error) { reject(error); return; } resolve(compressed); }); }); const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Encoding', 'gzip'); res.end(zipped); }, { port: SERVER_PORT } ); try { const { data: responseData } = await axios.get( `http://localhost:${server.address().port}/` ); assert.deepStrictEqual(responseData, data); } finally { await stopHTTPServer(server); } }); it('should support gunzip error handling', async () => { const server = await startHTTPServer( (req, res) => { res.statusCode = 206; res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Encoding', 'gzip'); res.setHeader('X-Stream-Error', 'yes'); res.end('invalid response'); }, { port: SERVER_PORT } ); try { await assert.rejects( async () => { await axios.get(`http://localhost:${server.address().port}/`); }, (error) => { assert.strictEqual(error.response.status, 206); assert.strictEqual(error.response.headers.get('x-stream-error'), 'yes'); assert.strictEqual(error.status, 206); return true; } ); } finally { await stopHTTPServer(server); } }); it('should support disabling automatic decompression of response data', async () => { const data = 'Test data'; const zipped = await new Promise((resolve, reject) => { zlib.gzip(data, (error, compressed) => { if (error) { reject(error); return; } resolve(compressed); }); }); const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'text/html;charset=utf-8'); res.setHeader('Content-Encoding', 'gzip'); res.end(zipped); }, { port: SERVER_PORT } ); try { const response = await axios.get(`http://localhost:${server.address().port}/`, { decompress: false, responseType: 'arraybuffer', }); assert.strictEqual(response.data.toString('base64'), zipped.toString('base64')); } finally { await stopHTTPServer(server); } }); it('should not advertise zstd by default', async () => { let acceptEncoding; const server = await startHTTPServer( (req, res) => { acceptEncoding = req.headers['accept-encoding']; res.end('ok'); }, { port: SERVER_PORT } ); try { await axios.get(`http://localhost:${server.address().port}/`); assert.strictEqual(acceptEncoding.includes('zstd'), false); } finally { await stopHTTPServer(server); } }); it('should advertise zstd when enabled through transitional config and supported', async () => { if (!isZstdSupported) { return; } let acceptEncoding; const server = await startHTTPServer( (req, res) => { acceptEncoding = req.headers['accept-encoding']; res.end('ok'); }, { port: SERVER_PORT } ); try { await axios.get(`http://localhost:${server.address().port}/`, { transitional: { advertiseZstdAcceptEncoding: true, }, }); assert.strictEqual(acceptEncoding.includes('zstd'), true); } finally { await stopHTTPServer(server); } }); describe('algorithms', () => { const responseBody = 'str'; const gzip = (value) => new Promise((resolve, reject) => { zlib.gzip(value, (error, compressed) => { if (error) { reject(error); return; } resolve(compressed); }); }); const deflate = (value) => new Promise((resolve, reject) => { zlib.deflate(value, (error, compressed) => { if (error) { reject(error); return; } resolve(compressed); }); }); const deflateRaw = (value) => new Promise((resolve, reject) => { zlib.deflateRaw(value, (error, compressed) => { if (error) { reject(error); return; } resolve(compressed); }); }); const brotliCompress = (value) => new Promise((resolve, reject) => { zlib.brotliCompress(value, (error, compressed) => { if (error) { reject(error); return; } resolve(compressed); }); }); const zstdCompress = (value) => new Promise((resolve, reject) => { zlib.zstdCompress(value, (error, compressed) => { if (error) { reject(error); return; } resolve(compressed); }); }); for (const [typeName, zipped] of Object.entries({ gzip: gzip(responseBody), GZIP: gzip(responseBody), compress: gzip(responseBody), deflate: deflate(responseBody), 'deflate-raw': deflateRaw(responseBody), br: brotliCompress(responseBody), ...(isZstdSupported ? { zstd: zstdCompress(responseBody) } : {}), })) { const type = typeName.split('-')[0]; describe(`${typeName} decompression`, () => { it('should support decompression', async () => { const server = await startHTTPServer( async (req, res) => { res.setHeader('Content-Encoding', type); res.end(await zipped); }, { port: SERVER_PORT } ); try { const { data } = await axios.get(`http://localhost:${server.address().port}`); assert.strictEqual(data, responseBody); } finally { await stopHTTPServer(server); } }); it(`should not fail if response content-length header is missing (${type})`, async () => { const server = await startHTTPServer( async (req, res) => { res.setHeader('Content-Encoding', type); res.removeHeader('Content-Length'); res.end(await zipped); }, { port: SERVER_PORT } ); try { const { data } = await axios.get(`http://localhost:${server.address().port}`); assert.strictEqual(data, responseBody); } finally { await stopHTTPServer(server); } }); it('should not fail with chunked responses (without Content-Length header)', async () => { const server = await startHTTPServer( async (req, res) => { res.setHeader('Content-Encoding', type); res.setHeader('Transfer-Encoding', 'chunked'); res.removeHeader('Content-Length'); res.write(await zipped); res.end(); }, { port: SERVER_PORT } ); try { const { data } = await axios.get(`http://localhost:${server.address().port}`); assert.strictEqual(data, responseBody); } finally { await stopHTTPServer(server); } }); it('should not fail with an empty response without content-length header (Z_BUF_ERROR)', async () => { const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Encoding', type); res.removeHeader('Content-Length'); res.end(); }, { port: SERVER_PORT } ); try { const { data } = await axios.get(`http://localhost:${server.address().port}`); assert.strictEqual(data, ''); } finally { await stopHTTPServer(server); } }); it('should not fail with an empty response with content-length header (Z_BUF_ERROR)', async () => { const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Encoding', type); res.end(); }, { port: SERVER_PORT } ); try { await axios.get(`http://localhost:${server.address().port}`); } finally { await stopHTTPServer(server); } }); it('should reject when the server aborts mid-stream and maxRedirects is 0', async () => { const server = await startHTTPServer( async (req, res) => { res.setHeader('Content-Encoding', type); res.setHeader('Transfer-Encoding', 'chunked'); res.removeHeader('Content-Length'); res.write(await zipped); setTimeout(() => res.socket.destroy(), 10); }, { port: SERVER_PORT } ); try { await assert.rejects( axios.get(`http://localhost:${server.address().port}`, { maxRedirects: 0 }), (err) => err && err.code === 'ECONNRESET' ); } finally { await stopHTTPServer(server); } }); }); } }); }); it('should support UTF8', async () => { const str = Array(100000).join('ж'); const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end(str); }, { port: SERVER_PORT } ); try { const response = await axios.get(`http://localhost:${server.address().port}/`); assert.strictEqual(response.data, str); } finally { await stopHTTPServer(server); } }); it('should support basic auth', async () => { const server = await startHTTPServer( (req, res) => { res.end(req.headers.authorization); }, { port: SERVER_PORT } ); try { const user = 'foo'; const headers = { Authorization: 'Bearer 1234' }; const response = await axios.get(`http://${user}@localhost:${server.address().port}/`, { headers, }); const base64 = Buffer.from(`${user}:`, 'utf8').toString('base64'); assert.strictEqual(response.data, `Basic ${base64}`); } finally { await stopHTTPServer(server); } }); it('should decode basic auth credentials from the request URL', async () => { const server = await startHTTPServer( (req, res) => { res.end(req.headers.authorization); }, { port: SERVER_PORT } ); try { const response = await axios.get( `http://my%40email.com:pa%24ss@localhost:${server.address().port}/` ); const base64 = Buffer.from('my@email.com:pa$ss', 'utf8').toString('base64'); assert.strictEqual(response.data, `Basic ${base64}`); } finally { await stopHTTPServer(server); } }); it('keeps malformed URL credentials percent-encoding and does not throw', async () => { const server = await startHTTPServer( (req, res) => { res.end(req.headers.authorization); }, { port: SERVER_PORT } ); try { const response = await axios.get(`http://user%:foo%zz@localhost:${server.address().port}/`); const base64 = Buffer.from('user%:foo%zz', 'utf8').toString('base64'); assert.strictEqual(response.data, `Basic ${base64}`); } finally { await stopHTTPServer(server); } }); it('should support password-only basic auth credentials from the request URL', async () => { const server = await startHTTPServer( (req, res) => { res.end(req.headers.authorization); }, { port: SERVER_PORT } ); try { const response = await axios.get(`http://:secret@localhost:${server.address().port}/`); const base64 = Buffer.from(':secret', 'utf8').toString('base64'); assert.strictEqual(response.data, `Basic ${base64}`); } finally { await stopHTTPServer(server); } }); it('should support basic auth with a header', async () => { const server = await startHTTPServer( (req, res) => { res.end(req.headers.authorization); }, { port: SERVER_PORT } ); try { const auth = { username: 'foo', password: 'bar' }; const headers = { AuThOrIzAtIoN: 'Bearer 1234' }; // wonky casing to ensure caseless comparison const response = await axios.get(`http://localhost:${server.address().port}/`, { auth, headers, }); const base64 = Buffer.from('foo:bar', 'utf8').toString('base64'); assert.strictEqual(response.data, `Basic ${base64}`); } finally { await stopHTTPServer(server); } }); it('should ignore inherited nested request option fields in http adapter', async () => { const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'application/json'); res.end( JSON.stringify({ authorization: req.headers.authorization, url: req.url, }) ); }, { port: SERVER_PORT } ); Object.defineProperty(Object.prototype, 'username', { value: 'inherited-user', configurable: true, }); Object.defineProperty(Object.prototype, 'password', { value: 'inherited-pass', configurable: true, }); Object.defineProperty(Object.prototype, 'serialize', { value() { return 'inherited=1'; }, configurable: true, }); try { const response = await axios.get(`http://localhost:${server.address().port}/demo`, { auth: {}, params: { value: 'a b' }, paramsSerializer: {}, }); assert.deepStrictEqual(response.data, { authorization: 'Basic Og==', url: '/demo?value=a+b', }); } finally { delete Object.prototype.username; delete Object.prototype.password; delete Object.prototype.serialize; await stopHTTPServer(server); } }); it('should ignore inherited proxy when http adapter receives a plain config', async () => { const proxyEnvKeys = ['http_proxy', 'HTTP_PROXY', 'https_proxy', 'HTTPS_PROXY']; const originalProxyEnv = Object.create(null); let proxy; let target; let proxyHits = 0; let targetHits = 0; for (const key of proxyEnvKeys) { originalProxyEnv[key] = process.env[key]; delete process.env[key]; } try { proxy = await startHTTPServer((req, res) => { proxyHits += 1; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ via: 'proxy', url: req.url })); }); target = await startHTTPServer((req, res) => { targetHits += 1; res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ via: 'target', url: req.url })); }); Object.defineProperty(Object.prototype, 'proxy', { value: { protocol: 'http', host: '127.0.0.1', port: proxy.address().port, }, configurable: true, }); const response = await httpAdapter({ method: 'get', url: `http://127.0.0.1:${target.address().port}/direct`, headers: {}, maxRedirects: 0, maxContentLength: -1, maxBodyLength: -1, timeout: 0, }); const data = JSON.parse(response.data); assert.strictEqual(proxyHits, 0); assert.strictEqual(targetHits, 1); assert.deepStrictEqual(data, { via: 'target', url: '/direct' }); } finally { delete Object.prototype.proxy; for (const key of proxyEnvKeys) { if (originalProxyEnv[key] === undefined) { delete process.env[key]; } else { process.env[key] = originalProxyEnv[key]; } } await stopHTTPServer(target); await stopHTTPServer(proxy); } }); it('should ignore inherited paramsSerializer when http adapter receives a plain config', async () => { let server; let serializerInvoked = false; Object.defineProperty(Object.prototype, 'paramsSerializer', { value() { serializerInvoked = true; return 'inherited=1'; }, configurable: true, }); try { server = await startHTTPServer((req, res) => { res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ url: req.url })); }); const response = await httpAdapter({ method: 'get', url: `http://127.0.0.1:${server.address().port}/direct`, headers: {}, params: { value: 'a b' }, proxy: false, maxRedirects: 0, maxContentLength: -1, maxBodyLength: -1, timeout: 0, }); const data = JSON.parse(response.data); assert.strictEqual(serializerInvoked, false); assert.deepStrictEqual(data, { url: '/direct?value=a+b' }); } finally { delete Object.prototype.paramsSerializer; await stopHTTPServer(server); } }); it('should preserve basic auth across same-origin 303 POST -> GET redirect', async () => { const server = await startHTTPServer( (req, res) => { if (req.url === '/login') { res.setHeader('Location', '/profile'); res.statusCode = 303; res.end(); return; } res.end(req.headers.authorization || ''); }, { port: SERVER_PORT } ); try { const auth = { username: 'foo', password: 'bar' }; const response = await axios.post( `http://localhost:${server.address().port}/login`, { hello: 'world' }, { auth, maxRedirects: 1 } ); const base64 = Buffer.from('foo:bar', 'utf8').toString('base64'); assert.strictEqual(response.data, `Basic ${base64}`); assert.strictEqual(response.request.path, '/profile'); } finally { await stopHTTPServer(server); } }); it('should strip basic auth on cross-origin redirect', async () => { const targetServer = await startHTTPServer( (req, res) => { res.end(req.headers.authorization || 'no-auth'); }, { port: ALTERNATE_SERVER_PORT } ); const redirectServer = await startHTTPServer( (req, res) => { res.setHeader('Location', `http://127.0.0.1:${targetServer.address().port}/`); res.statusCode = 302; res.end(); }, { port: SERVER_PORT } ); try { const auth = { username: 'foo', password: 'bar' }; const response = await axios.get(`http://localhost:${redirectServer.address().port}/start`, { auth, maxRedirects: 1, }); assert.strictEqual(response.data, 'no-auth'); } finally { await stopHTTPServer(redirectServer); await stopHTTPServer(targetServer); } }); it('should preserve basic auth across multi-hop same-origin redirects', async () => { const server = await startHTTPServer( (req, res) => { if (req.url === '/a') { res.setHeader('Location', '/b'); res.statusCode = 302; res.end(); return; } if (req.url === '/b') { res.setHeader('Location', '/c'); res.statusCode = 302; res.end(); return; } res.end(req.headers.authorization || ''); }, { port: SERVER_PORT } ); try { const auth = { username: 'foo', password: 'bar' }; const response = await axios.get(`http://localhost:${server.address().port}/a`, { auth, maxRedirects: 5, }); const base64 = Buffer.from('foo:bar', 'utf8').toString('base64'); assert.strictEqual(response.data, `Basic ${base64}`); assert.strictEqual(response.request.path, '/c'); } finally { await stopHTTPServer(server); } }); it('should provides a default User-Agent header', async () => { const server = await startHTTPServer( (req, res) => { res.end(req.headers['user-agent']); }, { port: SERVER_PORT } ); try { const response = await axios.get(`http://localhost:${server.address().port}/`); assert.ok( /^axios\/[\d.]+[-]?[a-z]*[.]?[\d]+$/.test(response.data), `User-Agent header does not match: ${response.data}` ); } finally { await stopHTTPServer(server); } }); it('should allow the User-Agent header to be overridden', async () => { const server = await startHTTPServer( (req, res) => { res.end(req.headers['user-agent']); }, { port: SERVER_PORT } ); try { const headers = { 'UsEr-AgEnT': 'foo bar' }; // wonky casing to ensure caseless comparison const response = await axios.get(`http://localhost:${server.address().port}/`, { headers }); assert.strictEqual(response.data, 'foo bar'); } finally { await stopHTTPServer(server); } }); it('should allow the Content-Length header to be overridden', async () => { const server = await startHTTPServer( (req, res) => { assert.strictEqual(req.headers['content-length'], '42'); res.end(); }, { port: SERVER_PORT } ); try { const headers = { 'CoNtEnT-lEnGtH': '42' }; // wonky casing to ensure caseless comparison await axios.post(`http://localhost:${server.address().port}/`, 'foo', { headers }); } finally { await stopHTTPServer(server); } }); it('should support max content length', async () => { const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end(Array(5000).join('#')); }, { port: SERVER_PORT } ); try { await assert.rejects( axios.get(`http://localhost:${server.address().port}/`, { maxContentLength: 2000, maxRedirects: 0, }), /maxContentLength size of 2000 exceeded/ ); } finally { await stopHTTPServer(server); } }); it('should support max content length for redirected', async () => { const str = Array(100000).join('ж'); const server = await startHTTPServer( (req, res) => { const parsed = new URL(req.url, 'http://localhost'); if (parsed.pathname === '/two') { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end(str); return; } res.setHeader('Location', '/two'); res.statusCode = 302; res.end(); }, { port: SERVER_PORT } ); try { await assert.rejects( axios.get(`http://localhost:${server.address().port}/one`, { maxContentLength: 2000, }), (error) => { assert.strictEqual(error.message, 'maxContentLength size of 2000 exceeded'); return true; } ); } finally { await stopHTTPServer(server); } }); it('should support max body length', async () => { const data = Array(100000).join('ж'); const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end(); }, { port: SERVER_PORT } ); try { await assert.rejects( axios.post( `http://localhost:${server.address().port}/`, { data, }, { maxBodyLength: 2000, } ), (error) => { assert.strictEqual(error.message, 'Request body larger than maxBodyLength limit'); return true; } ); } finally { await stopHTTPServer(server); } }); it('should enforce maxContentLength for streamed responses', async () => { const size = 2 * 1024 * 1024; const body = Buffer.alloc(size, 0x63); const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'application/octet-stream'); res.end(body); }, { port: SERVER_PORT } ); try { const response = await axios.get(`http://localhost:${server.address().port}/`, { responseType: 'stream', maxContentLength: 1024, }); let bytesRead = 0; const err = await new Promise((resolve) => { response.data.on('data', (chunk) => { bytesRead += chunk.length; }); response.data.on('error', resolve); response.data.on('end', () => resolve(null)); }); assert.ok(err, 'stream should emit an error'); assert.strictEqual(err.message, 'maxContentLength size of 1024 exceeded'); assert.ok(bytesRead <= 1024 * 64, `stream should not deliver full payload; got ${bytesRead}`); } finally { await stopHTTPServer(server); } }); it('should allow streamed responses under maxContentLength', async () => { const body = Buffer.alloc(512, 0x64); const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'application/octet-stream'); res.end(body); }, { port: SERVER_PORT } ); try { const response = await axios.get(`http://localhost:${server.address().port}/`, { responseType: 'stream', maxContentLength: 1024, }); const chunks = []; await new Promise((resolve, reject) => { response.data.on('data', (chunk) => chunks.push(chunk)); response.data.on('error', reject); response.data.on('end', resolve); }); assert.strictEqual(Buffer.concat(chunks).length, body.length); } finally { await stopHTTPServer(server); } }); it('should enforce maxBodyLength for streamed uploads with maxRedirects: 0', async () => { let bytesReceived = 0; const server = await startHTTPServer( (req, res) => { req.on('data', (chunk) => { bytesReceived += chunk.length; }); req.on('end', () => { res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ received: bytesReceived })); }); }, { port: SERVER_PORT } ); try { const size = 2 * 1024 * 1024; const buf = Buffer.alloc(size, 0x61); const source = stream.Readable.from([buf]); await assert.rejects( axios.post(`http://localhost:${server.address().port}/`, source, { maxBodyLength: 1024, maxRedirects: 0, headers: { 'Content-Type': 'application/octet-stream' }, }), (error) => { assert.strictEqual(error.message, 'Request body larger than maxBodyLength limit'); return true; } ); assert.ok( bytesReceived <= 1024 * 4, `server should not receive full payload; got ${bytesReceived}` ); } finally { await stopHTTPServer(server); } }); it('should allow streamed uploads under maxBodyLength with maxRedirects: 0', async () => { let bytesReceived = 0; const server = await startHTTPServer( (req, res) => { req.on('data', (chunk) => { bytesReceived += chunk.length; }); req.on('end', () => { res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ received: bytesReceived })); }); }, { port: SERVER_PORT } ); try { const payload = Buffer.alloc(512, 0x62); const source = stream.Readable.from([payload]); const response = await axios.post(`http://localhost:${server.address().port}/`, source, { maxBodyLength: 1024, maxRedirects: 0, headers: { 'Content-Type': 'application/octet-stream' }, }); assert.strictEqual(response.data.received, payload.length); } finally { await stopHTTPServer(server); } }); it('should properly support default max body length (follow-redirects as well)', async () => { // Taken from follow-redirects defaults. const followRedirectsMaxBodyDefaults = 10 * 1024 * 1024; const data = Array(2 * followRedirectsMaxBodyDefaults).join('ж'); const server = await startHTTPServer( (req, res) => { // Consume the req stream before responding to avoid ECONNRESET. req.on('data', () => {}); req.on('end', () => { res.end('OK'); }); }, { port: SERVER_PORT } ); try { const response = await axios.post(`http://localhost:${server.address().port}/`, { data, }); assert.strictEqual(response.data, 'OK', 'should handle response'); } finally { await stopHTTPServer(server); } }); it('should display error while parsing params', async () => { const server = await startHTTPServer(() => {}, { port: SERVER_PORT }); try { await assert.rejects( axios.get(`http://localhost:${server.address().port}/`, { params: { errorParam: new Date(undefined), }, }), (error) => { assert.deepStrictEqual(error.exists, true); return true; } ); } finally { await stopHTTPServer(server); } }); it('should support sockets', async () => { let socketName = path.join( os.tmpdir(), `axios-test-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}.sock` ); if (process.platform === 'win32') { socketName = '\\\\.\\pipe\\libuv-test'; } let server; try { server = await new Promise((resolve, reject) => { const socketServer = net .createServer((socket) => { socket.on('data', () => { socket.end('HTTP/1.1 200 OK\r\n\r\n'); }); }) .listen(socketName, () => resolve(socketServer)); socketServer.on('error', reject); }); } catch (error) { if (error && error.code === 'EPERM') { return; } throw error; } try { const response = await axios({ socketPath: socketName, url: 'http://localhost:4444/socket', }); assert.strictEqual(response.status, 200); assert.strictEqual(response.statusText, 'OK'); } finally { await new Promise((resolve, reject) => { server.close((error) => { if (error) { reject(error); return; } resolve(); }); }); } }); describe('streams', () => { it('should support streams', async () => { const server = await startHTTPServer( (req, res) => { req.pipe(res); }, { port: SERVER_PORT } ); try { const response = await axios.post( `http://localhost:${server.address().port}/`, fs.createReadStream(thisTestFilePath), { responseType: 'stream', } ); const responseText = await new Promise((resolve, reject) => { const chunks = []; response.data.on('data', (chunk) => { chunks.push(chunk); }); response.data.on('end', () => { resolve(Buffer.concat(chunks).toString('utf8')); }); response.data.on('error', reject); }); assert.strictEqual(responseText, fs.readFileSync(thisTestFilePath, 'utf8')); } finally { await stopHTTPServer(server); } }); it('should pass errors for a failed stream', async () => { const server = await startHTTPServer(() => {}, { port: SERVER_PORT }); const notExistPath = path.join(adaptersTestsDir, 'does_not_exist'); try { await assert.rejects( axios.post( `http://localhost:${server.address().port}/`, fs.createReadStream(notExistPath) ), (error) => { assert.strictEqual( error.message, `ENOENT: no such file or directory, open '${notExistPath}'` ); return true; } ); } finally { await stopHTTPServer(server); } }); it('should destroy the response stream with an error on request stream destroying', async () => { const server = await startHTTPServer(); const requestStream = generateReadable(); setTimeout(() => { requestStream.destroy(); }, 1000); const { data } = await axios.post( `http://localhost:${server.address().port}/`, requestStream, { responseType: 'stream', } ); let streamError; data.on('error', (error) => { streamError = error; }); try { await new Promise((resolve, reject) => { stream.pipeline(data, devNull(), (error) => { if (error) { reject(error); return; } resolve(); }); }); assert.fail('stream was not aborted'); } catch (error) { // Expected: the request stream is destroyed before completion. } finally { assert.strictEqual(streamError && streamError.code, 'ERR_CANCELED'); await stopHTTPServer(server); } }); }); it('should support buffers', async () => { const buf = Buffer.alloc(1024, 'x'); // Unsafe buffer < Buffer.poolSize (8192 bytes) const server = await startHTTPServer( (req, res) => { assert.strictEqual(req.headers['content-length'], buf.length.toString()); req.pipe(res); }, { port: SERVER_PORT } ); try { const response = await axios.post(`http://localhost:${server.address().port}/`, buf, { responseType: 'stream', }); const responseText = await new Promise((resolve, reject) => { const chunks = []; response.data.on('data', (chunk) => { chunks.push(chunk); }); response.data.on('end', () => { resolve(Buffer.concat(chunks).toString('utf8')); }); response.data.on('error', reject); }); assert.strictEqual(responseText, buf.toString()); } finally { await stopHTTPServer(server); } }); it('should support HTTP proxies', async () => { const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end('12345'); }, { port: SERVER_PORT } ); let connectAttempts = 0; const proxy = await startHTTPServer( (request, response) => { const parsed = new URL(request.url); const opts = { host: parsed.hostname, port: parsed.port, path: `${parsed.pathname}${parsed.search}`, }; http.get(opts, (res) => { let body = ''; res.on('data', (data) => { body += data; }); res.on('end', () => { response.setHeader('Content-Type', 'text/html; charset=UTF-8'); response.end(body + '6789'); }); }); }, { port: PROXY_PORT } ); proxy.on('connect', (req, sock) => { connectAttempts += 1; sock.end(); }); try { const response = await axios.get(`http://localhost:${server.address().port}/`, { proxy: { host: 'localhost', port: proxy.address().port, }, }); assert.strictEqual(Number(response.data), 123456789, 'should pass through proxy'); assert.strictEqual(connectAttempts, 0, 'HTTP targets must use forward-proxy mode, not CONNECT'); } finally { await stopHTTPServer(server); await stopHTTPServer(proxy); } }); it('should support HTTPS proxies', async () => { const tlsOptions = { key: fs.readFileSync(path.join(adaptersTestsDir, 'key.pem')), cert: fs.readFileSync(path.join(adaptersTestsDir, 'cert.pem')), }; const closeServer = (server) => new Promise((resolve, reject) => { server.close((error) => { if (error) { reject(error); return; } resolve(); }); }); const server = await new Promise((resolve, reject) => { const httpsServer = https.createServer(tlsOptions, (req, res) => { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end('12345'); }); httpsServer.listen(0, 'localhost', () => resolve(httpsServer)); httpsServer.on('error', reject); }); let plaintextRequests = 0; const connectTargets = []; const upstreamSockets = []; const proxy = await new Promise((resolve, reject) => { const httpsProxy = https.createServer(tlsOptions, () => { plaintextRequests += 1; }); httpsProxy.on('connect', (req, clientSocket, head) => { connectTargets.push(req.url); const [targetHost, targetPort] = req.url.split(':'); const upstream = net.connect(Number(targetPort), targetHost, () => { clientSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n'); if (head && head.length) upstream.write(head); upstream.pipe(clientSocket); clientSocket.pipe(upstream); }); upstreamSockets.push(upstream); upstream.on('error', () => clientSocket.destroy()); clientSocket.on('error', () => upstream.destroy()); }); httpsProxy.listen(0, '127.0.0.1', () => resolve(httpsProxy)); httpsProxy.on('error', reject); }); const originalReject = process.env.NODE_TLS_REJECT_UNAUTHORIZED; process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; const tunnelingAgent = new HttpsProxyAgent({ protocol: 'https:', host: '127.0.0.1', port: proxy.address().port, ALPNProtocols: ['http/1.1'], rejectUnauthorized: false, }); try { const response = await axios.get(`https://localhost:${server.address().port}/`, { httpsAgent: tunnelingAgent, }); // axios may auto-parse the body as JSON; compare as number to tolerate either form. assert.strictEqual(Number(response.data), 12345, 'origin body should be received unmodified'); assert.strictEqual(plaintextRequests, 0, 'proxy must not see plaintext requests'); assert.strictEqual(connectTargets.length, 1, 'proxy should see exactly one CONNECT'); assert.ok( connectTargets[0].startsWith(`localhost:${server.address().port}`), `CONNECT should target the origin: ${connectTargets[0]}` ); } finally { if (originalReject === undefined) { delete process.env.NODE_TLS_REJECT_UNAUTHORIZED; } else { process.env.NODE_TLS_REJECT_UNAUTHORIZED = originalReject; } tunnelingAgent.destroy(); // Tear down everything synchronously. server.close() on tls.Server can hang // when CONNECT-tunneled sockets have been pumped through, even after // closeAllConnections — destroy the underlying handles directly so the // test doesn't wait on a graceful shutdown. for (const s of upstreamSockets) s.destroy(); server.closeAllConnections?.(); proxy.closeAllConnections?.(); server.close(); proxy.close(); server.unref?.(); proxy.unref?.(); } }); it('should CONNECT-tunnel HTTPS targets through an HTTP proxy by default (issue #6320)', async () => { const tlsOptions = { key: fs.readFileSync(path.join(adaptersTestsDir, 'key.pem')), cert: fs.readFileSync(path.join(adaptersTestsDir, 'cert.pem')), }; const origin = await new Promise((resolve, reject) => { const s = https.createServer(tlsOptions, (req, res) => { if (req.headers['proxy-authorization']) { // Proxy-Authorization MUST NOT reach the origin under tunneling. res.writeHead(500); res.end('LEAKED:' + req.headers['proxy-authorization']); return; } res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end('secret-body-12345'); }); s.listen(0, 'localhost', () => resolve(s)); s.on('error', reject); }); const captured = { plaintext: 0, connectTargets: [], connectAuth: [] }; const upstreamSockets = []; const proxy = await new Promise((resolve, reject) => { const p = http.createServer((req) => { // Plaintext arrival = tunneling regression. Capture URL/headers so // assertions below can show what leaked. captured.plaintext += 1; captured.plaintextUrl = req.url; }); p.on('connect', (req, clientSocket, head) => { captured.connectTargets.push(req.url); captured.connectAuth.push(req.headers['proxy-authorization'] || null); const [host, port] = req.url.split(':'); const upstream = net.connect(Number(port), host, () => { clientSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n'); if (head && head.length) upstream.write(head); upstream.pipe(clientSocket); clientSocket.pipe(upstream); }); upstreamSockets.push(upstream); upstream.on('error', () => clientSocket.destroy()); clientSocket.on('error', () => upstream.destroy()); }); p.listen(0, '127.0.0.1', () => resolve(p)); p.on('error', reject); }); const originalReject = process.env.NODE_TLS_REJECT_UNAUTHORIZED; process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; try { const response = await axios.post( `https://localhost:${origin.address().port}/path?token=abc123`, { sensitive: 'leak-canary' }, { proxy: { host: '127.0.0.1', port: proxy.address().port, protocol: 'http', auth: { username: 'admin', password: 'secret' }, }, validateStatus: () => true, } ); assert.strictEqual(response.data, 'secret-body-12345', 'origin body should arrive unmodified through the tunnel'); assert.strictEqual(captured.plaintext, 0, 'proxy must not see any plaintext request line'); assert.strictEqual(captured.connectTargets.length, 1, 'proxy should see exactly one CONNECT'); assert.ok( captured.connectTargets[0].startsWith(`localhost:${origin.address().port}`), `CONNECT should target the origin host:port, got ${captured.connectTargets[0]}` ); assert.ok(captured.connectAuth[0], 'Proxy-Authorization should be present on the CONNECT request'); assert.match( captured.connectAuth[0], /^Basic /, 'CONNECT auth should be Basic-encoded' ); const decoded = Buffer.from(captured.connectAuth[0].slice(6), 'base64').toString('utf8'); assert.strictEqual(decoded, 'admin:secret', 'Proxy-Authorization credentials should match'); } finally { if (originalReject === undefined) { delete process.env.NODE_TLS_REJECT_UNAUTHORIZED; } else { process.env.NODE_TLS_REJECT_UNAUTHORIZED = originalReject; } for (const s of upstreamSockets) s.destroy(); origin.closeAllConnections?.(); proxy.closeAllConnections?.(); origin.close(); proxy.close(); origin.unref?.(); proxy.unref?.(); } }); it('should apply httpsAgent TLS options to CONNECT-tunneled origins (issue #10953)', async () => { const tlsOptions = { key: fs.readFileSync(path.join(adaptersTestsDir, 'key.pem')), cert: fs.readFileSync(path.join(adaptersTestsDir, 'cert.pem')), }; const origin = await new Promise((resolve, reject) => { const s = https.createServer(tlsOptions, (req, res) => { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end('trusted-through-agent'); }); s.listen(0, 'localhost', () => resolve(s)); s.on('error', reject); }); const captured = { plaintext: 0, connectTargets: [] }; const upstreamSockets = []; const proxy = await new Promise((resolve, reject) => { const p = http.createServer(() => { captured.plaintext += 1; }); p.on('connect', (req, clientSocket, head) => { captured.connectTargets.push(req.url); const [host, port] = req.url.split(':'); const upstream = net.connect(Number(port), host, () => { clientSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n'); if (head && head.length) upstream.write(head); upstream.pipe(clientSocket); clientSocket.pipe(upstream); }); upstreamSockets.push(upstream); upstream.on('error', () => clientSocket.destroy()); clientSocket.on('error', () => upstream.destroy()); }); p.listen(0, '127.0.0.1', () => resolve(p)); p.on('error', reject); }); const httpsAgent = new https.Agent({ ca: tlsOptions.cert }); try { const response = await axios.get(`https://localhost:${origin.address().port}/`, { httpsAgent, proxy: { host: '127.0.0.1', port: proxy.address().port, protocol: 'http', }, }); assert.strictEqual(response.data, 'trusted-through-agent'); assert.strictEqual(captured.plaintext, 0, 'proxy must not see plaintext HTTPS requests'); assert.strictEqual(captured.connectTargets.length, 1, 'proxy should see exactly one CONNECT'); assert.ok( captured.connectTargets[0].startsWith(`localhost:${origin.address().port}`), `CONNECT should target the origin host:port, got ${captured.connectTargets[0]}` ); } finally { httpsAgent.destroy(); for (const s of upstreamSockets) s.destroy(); origin.closeAllConnections?.(); proxy.closeAllConnections?.(); origin.close(); proxy.close(); origin.unref?.(); proxy.unref?.(); } }); it('should surface a CONNECT 407 from the proxy as an AxiosError (issue #6320)', async () => { const proxy = await new Promise((resolve, reject) => { const p = http.createServer(); p.on('connect', (req, clientSocket) => { clientSocket.write( 'HTTP/1.1 407 Proxy Authentication Required\r\n' + 'Proxy-Authenticate: Basic realm="proxy"\r\n' + 'Content-Length: 0\r\n' + '\r\n' ); clientSocket.end(); }); p.listen(0, '127.0.0.1', () => resolve(p)); p.on('error', reject); }); try { await assert.rejects( async () => { await axios.get('https://127.0.0.1:1/', { proxy: { host: '127.0.0.1', port: proxy.address().port, protocol: 'http', }, timeout: 4000, }); }, (err) => { assert.ok(err instanceof AxiosError, 'rejection should be an AxiosError'); return true; } ); } finally { proxy.closeAllConnections?.(); proxy.close(); proxy.unref?.(); } }); it('should not pass through disabled proxy', async () => { const originalHttpProxy = process.env.http_proxy; process.env.http_proxy = 'http://does-not-exists.example.com:4242/'; const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end('123456789'); }, { port: SERVER_PORT } ); try { const response = await axios.get(`http://localhost:${server.address().port}/`, { proxy: false, }); assert.strictEqual(Number(response.data), 123456789, 'should not pass through proxy'); } finally { await stopHTTPServer(server); if (originalHttpProxy === undefined) { delete process.env.http_proxy; } else { process.env.http_proxy = originalHttpProxy; } } }); it('should support proxy set via env var', async () => { const originalHttpProxy = process.env.http_proxy; const originalHTTPProxy = process.env.HTTP_PROXY; const originalNoProxy = process.env.no_proxy; const originalNOProxy = process.env.NO_PROXY; const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end('4567'); }, { port: SERVER_PORT } ); const proxy = await startHTTPServer( (request, response) => { const parsed = new URL(request.url); const opts = { host: parsed.hostname, port: parsed.port, path: `${parsed.pathname}${parsed.search}`, }; http.get(opts, (res) => { let body = ''; res.on('data', (data) => { body += data; }); res.on('end', () => { response.setHeader('Content-Type', 'text/html; charset=UTF-8'); response.end(body + '1234'); }); }); }, { port: PROXY_PORT } ); const proxyUrl = `http://localhost:${proxy.address().port}/`; process.env.http_proxy = proxyUrl; process.env.HTTP_PROXY = proxyUrl; process.env.no_proxy = ''; process.env.NO_PROXY = ''; try { const response = await axios.get(`http://localhost:${server.address().port}/`); assert.strictEqual( String(response.data), '45671234', 'should use proxy set by process.env.http_proxy' ); } finally { await stopHTTPServer(server); await stopHTTPServer(proxy); if (originalHttpProxy === undefined) { delete process.env.http_proxy; } else { process.env.http_proxy = originalHttpProxy; } if (originalHTTPProxy === undefined) { delete process.env.HTTP_PROXY; } else { process.env.HTTP_PROXY = originalHTTPProxy; } if (originalNoProxy === undefined) { delete process.env.no_proxy; } else { process.env.no_proxy = originalNoProxy; } if (originalNOProxy === undefined) { delete process.env.NO_PROXY; } else { process.env.NO_PROXY = originalNOProxy; } } }); it('should support HTTPS proxy set via env var', async () => { const originalHttpsProxy = process.env.https_proxy; const originalHTTPSProxy = process.env.HTTPS_PROXY; const originalNoProxy = process.env.no_proxy; const originalNOProxy = process.env.NO_PROXY; const tlsOptions = { key: fs.readFileSync(path.join(adaptersTestsDir, 'key.pem')), cert: fs.readFileSync(path.join(adaptersTestsDir, 'cert.pem')), }; const closeServer = (server) => new Promise((resolve, reject) => { server.close((error) => { if (error) { reject(error); return; } resolve(); }); }); const server = await new Promise((resolve, reject) => { const httpsServer = https.createServer(tlsOptions, (req, res) => { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end('12345'); }); httpsServer.listen(0, 'localhost', () => resolve(httpsServer)); httpsServer.on('error', reject); }); let plaintextRequests = 0; const connectTargets = []; const upstreamSockets = []; const proxy = await new Promise((resolve, reject) => { const httpsProxy = https.createServer(tlsOptions, () => { plaintextRequests += 1; }); httpsProxy.on('connect', (req, clientSocket, head) => { connectTargets.push(req.url); const [targetHost, targetPort] = req.url.split(':'); const upstream = net.connect(Number(targetPort), targetHost, () => { clientSocket.write('HTTP/1.1 200 Connection Established\r\n\r\n'); if (head && head.length) upstream.write(head); upstream.pipe(clientSocket); clientSocket.pipe(upstream); }); upstreamSockets.push(upstream); upstream.on('error', () => clientSocket.destroy()); clientSocket.on('error', () => upstream.destroy()); }); httpsProxy.listen(0, '127.0.0.1', () => resolve(httpsProxy)); httpsProxy.on('error', reject); }); const proxyUrl = `https://127.0.0.1:${proxy.address().port}/`; process.env.https_proxy = proxyUrl; process.env.HTTPS_PROXY = proxyUrl; process.env.no_proxy = ''; process.env.NO_PROXY = ''; const originalReject = process.env.NODE_TLS_REJECT_UNAUTHORIZED; process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; try { const response = await axios.get(`https://localhost:${server.address().port}/`); assert.strictEqual(Number(response.data), 12345, 'origin body should be received unmodified'); assert.strictEqual(plaintextRequests, 0, 'proxy must not see plaintext requests'); assert.strictEqual(connectTargets.length, 1, 'proxy should see exactly one CONNECT'); } finally { if (originalReject === undefined) { delete process.env.NODE_TLS_REJECT_UNAUTHORIZED; } else { process.env.NODE_TLS_REJECT_UNAUTHORIZED = originalReject; } for (const s of upstreamSockets) s.destroy(); server.closeAllConnections?.(); proxy.closeAllConnections?.(); server.close(); proxy.close(); server.unref?.(); proxy.unref?.(); if (originalHttpsProxy === undefined) { delete process.env.https_proxy; } else { process.env.https_proxy = originalHttpsProxy; } if (originalHTTPSProxy === undefined) { delete process.env.HTTPS_PROXY; } else { process.env.HTTPS_PROXY = originalHTTPSProxy; } if (originalNoProxy === undefined) { delete process.env.no_proxy; } else { process.env.no_proxy = originalNoProxy; } if (originalNOProxy === undefined) { delete process.env.NO_PROXY; } else { process.env.NO_PROXY = originalNOProxy; } } }); it('should re-evaluate proxy on redirect when proxy set via env var', async () => { const originalHttpProxy = process.env.http_proxy; const originalHTTPProxy = process.env.HTTP_PROXY; const originalNoProxy = process.env.no_proxy; const originalNOProxy = process.env.NO_PROXY; let proxyUseCount = 0; const server = await startHTTPServer( (req, res) => { res.setHeader('Location', `http://localhost:${proxy.address().port}/redirected`); res.statusCode = 302; res.end(); }, { port: SERVER_PORT } ); const proxy = await startHTTPServer( (request, response) => { const parsed = new URL(request.url, 'http://localhost'); if (parsed.pathname === '/redirected') { response.statusCode = 200; response.end(); return; } proxyUseCount += 1; const opts = { host: parsed.hostname, port: parsed.port, path: `${parsed.pathname}${parsed.search}`, protocol: parsed.protocol, }; http.get(opts, (res) => { let body = ''; res.on('data', (data) => { body += data; }); res.on('end', () => { response.setHeader('Content-Type', 'text/html; charset=UTF-8'); response.setHeader('Location', res.headers.location); response.end(body); }); }); }, { port: PROXY_PORT } ); const proxyUrl = `http://localhost:${proxy.address().port}`; process.env.http_proxy = proxyUrl; process.env.HTTP_PROXY = proxyUrl; process.env.no_proxy = `localhost:${proxy.address().port}`; process.env.NO_PROXY = `localhost:${proxy.address().port}`; try { const response = await axios.get(`http://localhost:${server.address().port}/`); assert.equal(response.status, 200); assert.equal(proxyUseCount, 1); } finally { await stopHTTPServer(server); await stopHTTPServer(proxy); if (originalHttpProxy === undefined) { delete process.env.http_proxy; } else { process.env.http_proxy = originalHttpProxy; } if (originalHTTPProxy === undefined) { delete process.env.HTTP_PROXY; } else { process.env.HTTP_PROXY = originalHTTPProxy; } if (originalNoProxy === undefined) { delete process.env.no_proxy; } else { process.env.no_proxy = originalNoProxy; } if (originalNOProxy === undefined) { delete process.env.NO_PROXY; } else { process.env.NO_PROXY = originalNOProxy; } } }); it('should not use proxy for domains in no_proxy', async () => { const originalHttpProxy = process.env.http_proxy; const originalHTTPProxy = process.env.HTTP_PROXY; const originalNoProxy = process.env.no_proxy; const originalNOProxy = process.env.NO_PROXY; const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end('4567'); }, { port: SERVER_PORT } ); const proxy = await startHTTPServer( (request, response) => { const parsed = new URL(request.url); const opts = { host: parsed.hostname, port: parsed.port, path: `${parsed.pathname}${parsed.search}`, }; http.get(opts, (res) => { let body = ''; res.on('data', (data) => { body += data; }); res.on('end', () => { response.setHeader('Content-Type', 'text/html; charset=UTF-8'); response.end(body + '1234'); }); }); }, { port: PROXY_PORT } ); const noProxyValue = 'foo.com, localhost,bar.net , , quix.co'; const proxyUrl = `http://localhost:${proxy.address().port}/`; process.env.http_proxy = proxyUrl; process.env.HTTP_PROXY = proxyUrl; process.env.no_proxy = noProxyValue; process.env.NO_PROXY = noProxyValue; try { const response = await axios.get(`http://localhost:${server.address().port}/`); assert.equal(response.data, '4567', 'should not use proxy for domains in no_proxy'); } finally { await stopHTTPServer(server); await stopHTTPServer(proxy); if (originalHttpProxy === undefined) { delete process.env.http_proxy; } else { process.env.http_proxy = originalHttpProxy; } if (originalHTTPProxy === undefined) { delete process.env.HTTP_PROXY; } else { process.env.HTTP_PROXY = originalHTTPProxy; } if (originalNoProxy === undefined) { delete process.env.no_proxy; } else { process.env.no_proxy = originalNoProxy; } if (originalNOProxy === undefined) { delete process.env.NO_PROXY; } else { process.env.NO_PROXY = originalNOProxy; } } }); it('should not use proxy for localhost with trailing dot when listed in no_proxy', async () => { const originalHttpProxy = process.env.http_proxy; const originalHTTPProxy = process.env.HTTP_PROXY; const originalNoProxy = process.env.no_proxy; const originalNOProxy = process.env.NO_PROXY; let proxyRequests = 0; const proxy = await startHTTPServer( (_, response) => { proxyRequests += 1; response.end('proxied'); }, { port: PROXY_PORT } ); const noProxyValue = 'localhost,127.0.0.1,::1'; const proxyUrl = `http://localhost:${proxy.address().port}/`; process.env.http_proxy = proxyUrl; process.env.HTTP_PROXY = proxyUrl; process.env.no_proxy = noProxyValue; process.env.NO_PROXY = noProxyValue; try { await assert.rejects(axios.get('http://localhost.:1/', { timeout: 100 })); assert.equal(proxyRequests, 0, 'should not use proxy for localhost with trailing dot'); } finally { await stopHTTPServer(proxy); if (originalHttpProxy === undefined) { delete process.env.http_proxy; } else { process.env.http_proxy = originalHttpProxy; } if (originalHTTPProxy === undefined) { delete process.env.HTTP_PROXY; } else { process.env.HTTP_PROXY = originalHTTPProxy; } if (originalNoProxy === undefined) { delete process.env.no_proxy; } else { process.env.no_proxy = originalNoProxy; } if (originalNOProxy === undefined) { delete process.env.NO_PROXY; } else { process.env.NO_PROXY = originalNOProxy; } } }); it('should not use proxy for bracketed IPv6 loopback when listed in no_proxy', async () => { const originalHttpProxy = process.env.http_proxy; const originalHTTPProxy = process.env.HTTP_PROXY; const originalNoProxy = process.env.no_proxy; const originalNOProxy = process.env.NO_PROXY; let proxyRequests = 0; const proxy = await startHTTPServer( (_, response) => { proxyRequests += 1; response.end('proxied'); }, { port: PROXY_PORT } ); const noProxyValue = 'localhost,127.0.0.1,::1'; const proxyUrl = `http://localhost:${proxy.address().port}/`; process.env.http_proxy = proxyUrl; process.env.HTTP_PROXY = proxyUrl; process.env.no_proxy = noProxyValue; process.env.NO_PROXY = noProxyValue; try { await assert.rejects(axios.get('http://[::1]:1/', { timeout: 100 })); assert.equal(proxyRequests, 0, 'should not use proxy for IPv6 loopback'); } finally { await stopHTTPServer(proxy); if (originalHttpProxy === undefined) { delete process.env.http_proxy; } else { process.env.http_proxy = originalHttpProxy; } if (originalHTTPProxy === undefined) { delete process.env.HTTP_PROXY; } else { process.env.HTTP_PROXY = originalHTTPProxy; } if (originalNoProxy === undefined) { delete process.env.no_proxy; } else { process.env.no_proxy = originalNoProxy; } if (originalNOProxy === undefined) { delete process.env.NO_PROXY; } else { process.env.NO_PROXY = originalNOProxy; } } }); it('should use proxy for domains not in no_proxy', async () => { const originalHttpProxy = process.env.http_proxy; const originalHTTPProxy = process.env.HTTP_PROXY; const originalNoProxy = process.env.no_proxy; const originalNOProxy = process.env.NO_PROXY; const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'text/html; charset=UTF-8'); res.end('4567'); }, { port: SERVER_PORT } ); const proxy = await startHTTPServer( (request, response) => { const parsed = new URL(request.url); const opts = { host: parsed.hostname, port: parsed.port, path: `${parsed.pathname}${parsed.search}`, }; http.get(opts, (res) => { let body = ''; res.on('data', (data) => { body += data; }); res.on('end', () => { response.setHeader('Content-Type', 'text/html; charset=UTF-8'); response.end(body + '1234'); }); }); }, { port: PROXY_PORT } ); const noProxyValue = 'foo.com, ,bar.net , quix.co'; const proxyUrl = `http://localhost:${proxy.address().port}/`; process.env.http_proxy = proxyUrl; process.env.HTTP_PROXY = proxyUrl; process.env.no_proxy = noProxyValue; process.env.NO_PROXY = noProxyValue; try { const response = await axios.get(`http://localhost:${server.address().port}/`); assert.equal(response.data, '45671234', 'should use proxy for domains not in no_proxy'); } finally { await stopHTTPServer(server); await stopHTTPServer(proxy); if (originalHttpProxy === undefined) { delete process.env.http_proxy; } else { process.env.http_proxy = originalHttpProxy; } if (originalHTTPProxy === undefined) { delete process.env.HTTP_PROXY; } else { process.env.HTTP_PROXY = originalHTTPProxy; } if (originalNoProxy === undefined) { delete process.env.no_proxy; } else { process.env.no_proxy = originalNoProxy; } if (originalNOProxy === undefined) { delete process.env.NO_PROXY; } else { process.env.NO_PROXY = originalNOProxy; } } }); it('should support HTTP proxy auth', async () => { const server = await startHTTPServer( (req, res) => { res.end(); }, { port: SERVER_PORT } ); const proxy = await startHTTPServer( (request, response) => { const parsed = new URL(request.url); const opts = { host: parsed.hostname, port: parsed.port, path: `${parsed.pathname}${parsed.search}`, }; const proxyAuth = request.headers['proxy-authorization']; http.get(opts, (res) => { res.on('data', () => {}); res.on('end', () => { response.setHeader('Content-Type', 'text/html; charset=UTF-8'); response.end(proxyAuth); }); }); }, { port: PROXY_PORT } ); try { const response = await axios.get(`http://localhost:${server.address().port}/`, { proxy: { host: 'localhost', port: proxy.address().port, auth: { username: 'user', password: 'pass', }, }, }); const base64 = Buffer.from('user:pass', 'utf8').toString('base64'); assert.equal(response.data, `Basic ${base64}`, 'should authenticate to the proxy'); } finally { await stopHTTPServer(server); await stopHTTPServer(proxy); } }); it('should support proxy auth from env', async () => { const originalHttpProxy = process.env.http_proxy; const originalHTTPProxy = process.env.HTTP_PROXY; const originalNoProxy = process.env.no_proxy; const originalNOProxy = process.env.NO_PROXY; const server = await startHTTPServer( (req, res) => { res.end(); }, { port: SERVER_PORT } ); const proxy = await startHTTPServer( (request, response) => { const parsed = new URL(request.url); const opts = { host: parsed.hostname, port: parsed.port, path: `${parsed.pathname}${parsed.search}`, }; const proxyAuth = request.headers['proxy-authorization']; http.get(opts, (res) => { res.on('data', () => {}); res.on('end', () => { response.setHeader('Content-Type', 'text/html; charset=UTF-8'); response.end(proxyAuth); }); }); }, { port: PROXY_PORT } ); const proxyUrl = `http://user:pass@localhost:${proxy.address().port}/`; process.env.http_proxy = proxyUrl; process.env.HTTP_PROXY = proxyUrl; process.env.no_proxy = ''; process.env.NO_PROXY = ''; try { const response = await axios.get(`http://localhost:${server.address().port}/`); const base64 = Buffer.from('user:pass', 'utf8').toString('base64'); assert.equal( response.data, `Basic ${base64}`, 'should authenticate to the proxy set by process.env.http_proxy' ); } finally { await stopHTTPServer(server); await stopHTTPServer(proxy); if (originalHttpProxy === undefined) { delete process.env.http_proxy; } else { process.env.http_proxy = originalHttpProxy; } if (originalHTTPProxy === undefined) { delete process.env.HTTP_PROXY; } else { process.env.HTTP_PROXY = originalHTTPProxy; } if (originalNoProxy === undefined) { delete process.env.no_proxy; } else { process.env.no_proxy = originalNoProxy; } if (originalNOProxy === undefined) { delete process.env.NO_PROXY; } else { process.env.NO_PROXY = originalNOProxy; } } }); describe('when invalid proxy options are provided', () => { it('should throw error', async () => { const proxy = { protocol: 'http:', host: 'hostname.abc.xyz', port: PROXY_PORT, auth: { username: '', password: '', }, }; await assert.rejects(axios.get('https://test-domain.abc', { proxy }), (error) => { assert.strictEqual(error.message, 'Invalid proxy authorization'); assert.strictEqual(error.code, 'ERR_BAD_OPTION'); assert.deepStrictEqual(error.config.proxy, proxy); return true; }); }); }); describe('different options for direct proxy configuration (without env variables)', () => { const destination = 'www.example.com'; const testCases = [ { description: 'hostname and trailing colon in protocol', proxyConfig: { hostname: '127.0.0.1', protocol: 'http:', port: OPEN_WEB_PORT }, expectedOptions: { host: '127.0.0.1', protocol: 'http:', port: OPEN_WEB_PORT, path: destination, }, }, { description: 'hostname and no trailing colon in protocol', proxyConfig: { hostname: '127.0.0.1', protocol: 'http', port: OPEN_WEB_PORT }, expectedOptions: { host: '127.0.0.1', protocol: 'http:', port: OPEN_WEB_PORT, path: destination, }, }, { description: 'both hostname and host -> hostname takes precedence', proxyConfig: { hostname: '127.0.0.1', host: '0.0.0.0', protocol: 'http', port: OPEN_WEB_PORT, }, expectedOptions: { host: '127.0.0.1', protocol: 'http:', port: OPEN_WEB_PORT, path: destination, }, }, { description: 'only host and https protocol', proxyConfig: { host: '0.0.0.0', protocol: 'https', port: OPEN_WEB_PORT }, expectedOptions: { host: '0.0.0.0', protocol: 'https:', port: OPEN_WEB_PORT, path: destination, }, }, ]; for (const test of testCases) { it(test.description, () => { const options = { headers: {}, beforeRedirects: {} }; __setProxy(options, test.proxyConfig, destination); for (const [key, expected] of Object.entries(test.expectedOptions)) { assert.strictEqual(options[key], expected); } }); } }); describe('Host header preservation when forwarding through a proxy (#10805)', () => { const proxyConfig = { hostname: '127.0.0.1', protocol: 'http:', port: 8888 }; it('defaults the Host header to the request target when the user does not set one', () => { const options = { headers: {}, beforeRedirects: {}, hostname: '127.0.0.1', port: 4000, }; __setProxy(options, proxyConfig, 'http://127.0.0.1:4000/'); assert.strictEqual(options.headers.host, '127.0.0.1:4000'); }); it('preserves a user-supplied lowercase host header', () => { const options = { headers: { host: 'example.com' }, beforeRedirects: {}, hostname: '127.0.0.1', port: 4000, }; __setProxy(options, proxyConfig, 'http://127.0.0.1:4000/'); assert.strictEqual(options.headers.host, 'example.com'); }); it('preserves a user-supplied Host header regardless of casing', () => { const options = { headers: { Host: 'example.com' }, beforeRedirects: {}, hostname: '127.0.0.1', port: 4000, }; __setProxy(options, proxyConfig, 'http://127.0.0.1:4000/'); assert.strictEqual(options.headers.Host, 'example.com'); assert.strictEqual(options.headers.host, undefined); }); it('preserves a user-supplied Host header across a redirect re-invocation', () => { const options = { headers: { Host: 'example.com' }, beforeRedirects: {}, hostname: '127.0.0.1', port: 4000, }; __setProxy(options, proxyConfig, 'http://127.0.0.1:4000/', true); assert.strictEqual(options.headers.Host, 'example.com'); assert.strictEqual(options.headers.host, undefined); }); it('ignores polluted prototype Host fields when detecting user-supplied headers', () => { Object.prototype.host = 'polluted.example.com'; const options = { headers: {}, beforeRedirects: {}, hostname: '127.0.0.1', port: 4000, }; try { __setProxy(options, proxyConfig, 'http://127.0.0.1:4000/'); assert.strictEqual(options.headers.host, '127.0.0.1:4000'); } finally { delete Object.prototype.host; } }); }); describe('Proxy-Authorization header leak on redirect', () => { it('clears a stale Proxy-Authorization header when redirected request resolves to no proxy (configProxy=false)', () => { const options = { headers: {}, beforeRedirects: {}, hostname: 'initial.example.com', host: 'initial.example.com', port: 80, }; __setProxy( options, { host: '127.0.0.1', port: 8030, auth: { username: 'user', password: 'pass' } }, 'http://initial.example.com/start' ); assert.strictEqual( options.headers['Proxy-Authorization'], 'Basic ' + Buffer.from('user:pass', 'utf8').toString('base64'), 'initial request should carry Proxy-Authorization' ); // Simulate redirect re-invocation where the redirected request is resolved to no proxy. // This mirrors the beforeRedirects.proxy hook being called with configProxy=false. const redirectOptions = { headers: { ...options.headers }, beforeRedirects: {}, hostname: 'attacker.example.com', host: 'attacker.example.com', port: 443, }; __setProxy(redirectOptions, false, 'https://attacker.example.com/final', true); assert.strictEqual( redirectOptions.headers['Proxy-Authorization'], undefined, 'stale Proxy-Authorization must be stripped when redirected request no longer uses a proxy' ); }); it('clears a stale Proxy-Authorization header when environment-derived proxy is bypassed on redirect (NO_PROXY)', () => { const originalHttpProxy = process.env.http_proxy; const originalHttpsProxy = process.env.https_proxy; const originalNoProxy = process.env.no_proxy; process.env.http_proxy = 'http://user:pass@127.0.0.1:8030'; process.env.https_proxy = 'http://user:pass@127.0.0.1:8030'; process.env.no_proxy = 'attacker.example.com'; try { const options = { headers: {}, beforeRedirects: {}, hostname: 'initial.example.com', host: 'initial.example.com', port: 80, }; __setProxy(options, undefined, 'http://initial.example.com/start'); assert.strictEqual( options.headers['Proxy-Authorization'], 'Basic ' + Buffer.from('user:pass', 'utf8').toString('base64'), 'initial request should pick up proxy credentials from env' ); const redirectOptions = { headers: { ...options.headers }, beforeRedirects: {}, hostname: 'attacker.example.com', host: 'attacker.example.com', port: 443, protocol: 'https:', }; __setProxy(redirectOptions, undefined, 'https://attacker.example.com/final', true); assert.strictEqual( redirectOptions.headers['Proxy-Authorization'], undefined, 'stale Proxy-Authorization must be stripped when redirect target is covered by NO_PROXY' ); } finally { if (originalHttpProxy === undefined) delete process.env.http_proxy; else process.env.http_proxy = originalHttpProxy; if (originalHttpsProxy === undefined) delete process.env.https_proxy; else process.env.https_proxy = originalHttpsProxy; if (originalNoProxy === undefined) delete process.env.no_proxy; else process.env.no_proxy = originalNoProxy; } }); it('replaces Proxy-Authorization when redirect target resolves to a different proxy without credentials', () => { const options = { headers: {}, beforeRedirects: {}, hostname: 'initial.example.com', host: 'initial.example.com', port: 80, }; __setProxy( options, { host: '127.0.0.1', port: 8030, auth: { username: 'user', password: 'pass' } }, 'http://initial.example.com/start' ); assert.ok( options.headers['Proxy-Authorization'], 'precondition: initial proxy auth header set' ); const redirectOptions = { headers: { ...options.headers }, beforeRedirects: {}, hostname: 'second.example.com', host: 'second.example.com', port: 80, }; __setProxy( redirectOptions, { host: '127.0.0.2', port: 8031 }, 'http://second.example.com/final', true ); assert.strictEqual( redirectOptions.headers['Proxy-Authorization'], undefined, 'stale credentials from previous proxy must not leak to a new proxy without credentials' ); }); it('strips stale Proxy-Authorization when the beforeRedirects.proxy hook is invoked with configProxy=false', () => { const options = { headers: { 'Proxy-Authorization': 'Basic ' + Buffer.from('user:pass', 'utf8').toString('base64'), }, beforeRedirects: {}, hostname: 'initial.example.com', host: 'initial.example.com', port: 80, }; __setProxy(options, false, 'http://initial.example.com/start'); assert.strictEqual( typeof options.beforeRedirects.proxy, 'function', 'initial setProxy must install redirect hook' ); const redirectOptions = { headers: { 'Proxy-Authorization': 'Basic ' + Buffer.from('user:pass', 'utf8').toString('base64'), }, beforeRedirects: {}, hostname: 'attacker.example.com', host: 'attacker.example.com', port: 443, href: 'https://attacker.example.com/final', }; options.beforeRedirects.proxy(redirectOptions); assert.strictEqual( redirectOptions.headers['Proxy-Authorization'], undefined, 'beforeRedirects.proxy hook must strip stale Proxy-Authorization when redirect target has no proxy' ); }); it('preserves a user-supplied Proxy-Authorization header on the initial request when no proxy is configured', () => { const userValue = 'Basic ' + Buffer.from('alice:secret', 'utf8').toString('base64'); const options = { headers: { 'Proxy-Authorization': userValue }, beforeRedirects: {}, hostname: 'example.com', host: 'example.com', port: 80, }; __setProxy(options, false, 'http://example.com/start'); assert.strictEqual( options.headers['Proxy-Authorization'], userValue, 'user-supplied Proxy-Authorization must not be stripped on the initial request' ); }); it('strips stale Proxy-Authorization regardless of header key casing', () => { const staleValue = 'Basic ' + Buffer.from('user:pass', 'utf8').toString('base64'); const casings = [ 'proxy-authorization', 'PROXY-AUTHORIZATION', 'Proxy-authorization', 'pRoXy-AuThOrIzAtIoN', ]; for (const casing of casings) { const redirectOptions = { headers: { [casing]: staleValue }, beforeRedirects: {}, hostname: 'attacker.example.com', host: 'attacker.example.com', port: 443, }; __setProxy(redirectOptions, false, 'https://attacker.example.com/final', true); const leaked = Object.keys(redirectOptions.headers).filter( (name) => name.toLowerCase() === 'proxy-authorization' ); assert.deepStrictEqual( leaked, [], `stale Proxy-Authorization with key "${casing}" must be stripped regardless of casing` ); } }); // End-to-end exercise of the redirect leak. An // authenticated env-supplied proxy sees the initial request, 302s the // client to a target that NO_PROXY excludes, and the redirected request // must not carry the stale Proxy-Authorization to the direct target. it('does not forward Proxy-Authorization to a redirect target that resolves to no-proxy', async () => { const startServer = (handler) => new Promise((resolve) => { const s = http.createServer(handler); s.listen(0, '127.0.0.1', () => resolve(s)); }); const stop = (s) => new Promise((r) => s.close(r)); let attackerPort; const proxySaw = []; const attackerSaw = []; // The proxy receives the absolute-form URL (`GET http://target/path`) on // the initial request, then forwards to the destination. We short-circuit // by responding directly with the redirect. const corpProxy = await startServer((req, res) => { proxySaw.push({ url: req.url, proxyAuth: req.headers['proxy-authorization'] }); res.writeHead(302, { Location: `http://127.0.0.1:${attackerPort}/final` }); res.end(); }); const attacker = await startServer((req, res) => { attackerSaw.push({ url: req.url, proxyAuth: req.headers['proxy-authorization'], authorization: req.headers.authorization, }); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end('{"final":true}'); }); attackerPort = attacker.address().port; const corpProxyPort = corpProxy.address().port; const originalHttpProxy = process.env.http_proxy; const originalNoProxy = process.env.no_proxy; process.env.http_proxy = `http://user:pass@127.0.0.1:${corpProxyPort}`; // NO_PROXY entry covers only the attacker target (port-specific), so the // initial request still uses the proxy but the redirect resolves direct. process.env.no_proxy = `127.0.0.1:${attackerPort}`; try { await axios.get('http://example.com/start'); assert.ok( proxySaw.some((h) => h.proxyAuth), 'precondition: corp proxy must see Proxy-Authorization on the initial request' ); assert.strictEqual( attackerSaw.length, 1, 'attacker target must receive exactly the redirected request' ); assert.strictEqual( attackerSaw[0].proxyAuth, undefined, 'stale Proxy-Authorization must not leak to the redirect target' ); } finally { if (originalHttpProxy === undefined) delete process.env.http_proxy; else process.env.http_proxy = originalHttpProxy; if (originalNoProxy === undefined) delete process.env.no_proxy; else process.env.no_proxy = originalNoProxy; await stop(corpProxy); await stop(attacker); } }, 10000); }); it('should support cancel', async () => { const source = axios.CancelToken.source(); const server = await startHTTPServer( (req, res) => { // Call cancel() when the request has been sent but no response received. source.cancel('Operation has been canceled.'); }, { port: SERVER_PORT } ); try { await assert.rejects( async function stackTraceTest() { await axios.get(`http://localhost:${server.address().port}/`, { cancelToken: source.token, }); }, (thrown) => { assert.ok( thrown instanceof axios.Cancel, 'Promise must be rejected with a CanceledError object' ); assert.equal(thrown.message, 'Operation has been canceled.'); return true; } ); } finally { await stopHTTPServer(server); } }); it('should combine baseURL and url', async () => { const server = await startHTTPServer( (req, res) => { res.end(); }, { port: SERVER_PORT } ); try { const response = await axios.get('/foo', { baseURL: `http://localhost:${server.address().port}/`, }); assert.equal(response.config.baseURL, `http://localhost:${server.address().port}/`); assert.equal(response.config.url, '/foo'); } finally { await stopHTTPServer(server); } }); it('should support HTTP protocol', async () => { const server = await startHTTPServer( (req, res) => { setTimeout(() => { res.end(); }, 1000); }, { port: SERVER_PORT } ); try { const response = await axios.get(`http://localhost:${server.address().port}`); assert.equal(response.request.agent.protocol, 'http:'); } finally { await stopHTTPServer(server); } }); it('should support HTTPS protocol', async () => { const tlsOptions = { key: fs.readFileSync(path.join(adaptersTestsDir, 'key.pem')), cert: fs.readFileSync(path.join(adaptersTestsDir, 'cert.pem')), }; const server = await new Promise((resolve, reject) => { const httpsServer = https .createServer( tlsOptions, (req, res) => { setTimeout(() => { res.end(); }, 1000); }, { port: SERVER_PORT } ) .listen(SERVER_PORT, () => resolve(httpsServer)); httpsServer.on('error', reject); }); try { const response = await axios.get(`https://localhost:${server.address().port}`, { httpsAgent: new https.Agent({ rejectUnauthorized: false, }), }); assert.equal(response.request.agent.protocol, 'https:'); } finally { await new Promise((resolve, reject) => { server.close((error) => { if (error) { reject(error); return; } resolve(); }); }); } }); describe('HTTPS CONNECT tunneling agent management', () => { const buildOptions = () => ({ headers: {}, beforeRedirects: {}, hostname: 'example.com', host: 'example.com', port: 443, path: '/', protocol: 'https:', }); const proxyConfig = { host: '127.0.0.1', port: 8030, protocol: 'http' }; it('reuses the same tunneling agent for repeated requests through the same proxy', () => { const a = buildOptions(); const b = buildOptions(); __setProxy(a, proxyConfig, 'https://example.com/'); __setProxy(b, proxyConfig, 'https://example.com/'); assert.ok(a.agent, 'first request must install a tunneling agent'); assert.strictEqual( a.agent, b.agent, 'subsequent requests through the same proxy must share one tunneling agent so socket pooling works' ); }); it('still tunnels through the proxy when a non-proxy httpsAgent is supplied', () => { const userAgent = new https.Agent({ rejectUnauthorized: false }); const options = buildOptions(); __setProxy(options, proxyConfig, 'https://example.com/', false, userAgent); assert.ok(options.agent, 'proxy must not be silently bypassed when a custom httpsAgent is set'); assert.notStrictEqual( options.agent, userAgent, 'tunneling agent must be installed in place of the user agent (its TLS options are forwarded internally)' ); assert.ok(options.agent instanceof HttpsProxyAgent); }); it('includes user httpsAgent options in the tunneling agent constructor options', () => { const userAgent = new https.Agent({ rejectUnauthorized: false, ca: 'sentinel-ca' }); const options = buildOptions(); __setProxy(options, proxyConfig, 'https://example.com/', false, userAgent); // Origin TLS behavior is covered by the issue #10953 integration test. assert.strictEqual(options.agent.proxy.rejectUnauthorized, false); assert.strictEqual(options.agent.proxy.ca, 'sentinel-ca'); }); it('respects a user-supplied HttpsProxyAgent without installing its own', () => { const userTunnel = new HttpsProxyAgent({ protocol: 'http:', hostname: '127.0.0.1', port: 9999, }); const options = buildOptions(); __setProxy(options, proxyConfig, 'https://example.com/', false, userTunnel); // The user is handling tunneling end-to-end; setProxy must not overwrite agent. assert.strictEqual(options.agent, undefined, 'must not install a competing tunneling agent'); }); it('does not strip a user-supplied HttpsProxyAgent on redirect', () => { const userTunnel = new HttpsProxyAgent({ protocol: 'http:', hostname: '127.0.0.1', port: 9999, }); const redirectOptions = { headers: {}, beforeRedirects: {}, hostname: 'redirect.example.com', host: 'redirect.example.com', port: 443, path: '/', protocol: 'https:', agent: userTunnel, }; __setProxy(redirectOptions, false, 'https://redirect.example.com/', true); assert.strictEqual( redirectOptions.agent, userTunnel, 'user-supplied HttpsProxyAgent must survive redirects (no proxy on redirect target)' ); }); it('strips its own tunneling agent on redirect when the redirect target has no proxy', () => { const initial = buildOptions(); __setProxy(initial, proxyConfig, 'https://example.com/'); assert.ok(initial.agent instanceof HttpsProxyAgent, 'precondition: tunneling agent installed'); const redirectOptions = { headers: {}, beforeRedirects: {}, hostname: 'final.example.com', host: 'final.example.com', port: 443, path: '/', protocol: 'https:', agent: initial.agent, }; __setProxy(redirectOptions, false, 'https://final.example.com/', true); assert.strictEqual( redirectOptions.agent, undefined, 'axios-installed tunneling agent must be cleared when redirect drops the proxy' ); }); it('handles IPv6 literal proxy hosts', () => { const options = buildOptions(); __setProxy( options, { host: '::1', port: 8030, protocol: 'http' }, 'https://example.com/' ); assert.ok(options.agent instanceof HttpsProxyAgent, 'must build a tunneling agent for an IPv6 proxy host'); }); }); it('should return malformed URL', async () => { await assert.rejects(axios.get('tel:484-695-3408'), (error) => { assert.equal(error.message, 'Unsupported protocol tel:'); return true; }); }); it('should return unsupported protocol', async () => { await assert.rejects(axios.get('ftp:google.com'), (error) => { assert.equal(error.message, 'Unsupported protocol ftp:'); return true; }); }); it('rejects malformed HTTP URLs before Node URL normalization and preserves config', async () => { for (const url of ['\u0000https:example.com/users', 'h\nttp:example.com/users']) { await assert.rejects( () => axios.get(url, { adapter: 'http', headers: { 'X-Test': 'yes', }, }), (error) => { assert.ok(error instanceof AxiosError); assert.strictEqual(error.code, AxiosError.ERR_INVALID_URL); assert.strictEqual(error.message, 'Invalid URL: missing "//" after protocol'); assert.strictEqual(error.config.url, url); assert.strictEqual(error.config.headers.get('X-Test'), 'yes'); return true; } ); } }); it('should supply a user-agent if one is not specified', async () => { const server = await startHTTPServer( (req, res) => { assert.equal(req.headers['user-agent'], `axios/${axios.VERSION}`); res.end(); }, { port: SERVER_PORT } ); try { await axios.get(`http://localhost:${server.address().port}/`); } finally { await stopHTTPServer(server); } }); it('should omit a user-agent if one is explicitly disclaimed', async () => { const server = await startHTTPServer( (req, res) => { assert.equal('user-agent' in req.headers, false); assert.equal('User-Agent' in req.headers, false); res.end(); }, { port: SERVER_PORT } ); try { await axios.get(`http://localhost:${server.address().port}/`, { headers: { 'User-Agent': null, }, }); } finally { await stopHTTPServer(server); } }); it('should throw an error if http server that aborts a chunked request', async () => { const server = await startHTTPServer( (req, res) => { res.writeHead(200, { 'Content-Type': 'text/plain', 'X-Stream-Aborted': 'yes' }); res.write('chunk 1'); setTimeout(() => { res.write('chunk 2'); }, 100); setTimeout(() => { res.destroy(); }, 200); }, { port: SERVER_PORT } ); try { await assert.rejects( axios.get(`http://localhost:${server.address().port}/aborted`, { timeout: 500, }), (error) => { assert.strictEqual(error.code, 'ERR_BAD_RESPONSE'); assert.strictEqual(error.message, 'stream has been aborted'); assert.strictEqual(error.response.status, 200); assert.strictEqual(error.response.headers.get('x-stream-aborted'), 'yes'); assert.strictEqual(error.status, 200); return true; } ); } finally { await stopHTTPServer(server); } }); it('should able to cancel multiple requests with CancelToken', async () => { const server = await startHTTPServer( (req, res) => { res.end('ok'); }, { port: SERVER_PORT } ); try { const source = axios.CancelToken.source(); const canceledStack = []; const requests = [1, 2, 3, 4, 5].map(async (id) => { try { await axios.get('/foo/bar', { baseURL: `http://localhost:${server.address().port}`, cancelToken: source.token, }); } catch (error) { if (!axios.isCancel(error)) { throw error; } canceledStack.push(id); } }); source.cancel('Aborted by user'); await Promise.all(requests); assert.deepStrictEqual(canceledStack.sort(), [1, 2, 3, 4, 5]); } finally { await stopHTTPServer(server); } }); describe('FormData', () => { describe('form-data instance (https://www.npmjs.com/package/form-data)', () => { it('should allow passing FormData', async () => { const form = new FormDataLegacy(); const file1 = Buffer.from('foo', 'utf8'); const image = path.resolve(adaptersTestsDir, './axios.png'); const fileStream = fs.createReadStream(image); const stat = fs.statSync(image); form.append('foo', 'bar'); form.append('file1', file1, { filename: 'bar.jpg', filepath: 'temp/bar.jpg', contentType: 'image/jpeg', }); form.append('fileStream', fileStream); const server = await startHTTPServer( (req, res) => { const receivedForm = new IncomingForm(); assert.ok(req.rawHeaders.some((header) => header.toLowerCase() === 'content-length')); receivedForm.parse(req, (error, fields, files) => { if (error) { res.statusCode = 500; res.end(error.message); return; } res.end( JSON.stringify({ fields, files, }) ); }); }, { port: SERVER_PORT } ); try { const response = await axios.post(`http://localhost:${server.address().port}/`, form, { headers: { 'Content-Type': 'multipart/form-data', }, }); assert.deepStrictEqual(response.data.fields, { foo: ['bar'] }); assert.strictEqual(response.data.files.file1[0].mimetype, 'image/jpeg'); assert.strictEqual(response.data.files.file1[0].originalFilename, 'temp/bar.jpg'); assert.strictEqual(response.data.files.file1[0].size, 3); assert.strictEqual(response.data.files.fileStream[0].mimetype, 'image/png'); assert.strictEqual(response.data.files.fileStream[0].originalFilename, 'axios.png'); assert.strictEqual(response.data.files.fileStream[0].size, stat.size); } finally { await stopHTTPServer(server); } }); }); describe('SpecCompliant FormData', () => { it('should allow passing FormData', { retry: 2 }, async () => { // Use an ephemeral port and a non-keep-alive agent. Sharing the fixed // SERVER_PORT across tests can leave keep-alive sockets in the global // pool that a follow-up test picks up just as the server FINs them, // which surfaces here as EPIPE on the multipart write. const server = await startHTTPServer( async (req, res) => { const { fields, files } = await handleFormData(req); res.end( JSON.stringify({ fields, files, }) ); }, { port: 0 } ); const oneShotAgent = new http.Agent({ keepAlive: false }); try { const form = new FormDataSpecCompliant(); const blobContent = 'blob-content'; const blob = new BlobSpecCompliant([blobContent], { type: 'image/jpeg' }); form.append('foo1', 'bar1'); form.append('foo2', 'bar2'); form.append('file1', blob); const { data } = await axios.post(`http://localhost:${server.address().port}`, form, { maxRedirects: 0, httpAgent: oneShotAgent, headers: { Connection: 'close' }, }); assert.deepStrictEqual(data.fields, { foo1: ['bar1'], foo2: ['bar2'] }); assert.deepStrictEqual(typeof data.files.file1[0], 'object'); const { size, mimetype, originalFilename } = data.files.file1[0]; assert.deepStrictEqual( { size, mimetype, originalFilename }, { mimetype: 'image/jpeg', originalFilename: 'blob', size: Buffer.from(blobContent).byteLength, } ); } finally { oneShotAgent.destroy(); await stopHTTPServer(server); } }); }); describe('prototype pollution', () => { const pollutedKeys = ['getHeaders', 'append', 'pipe', 'on', 'once']; const toStringTagSym = Symbol.toStringTag; it('should not use inherited Symbol.iterator for request or response headers', async () => { let capturedHeaders; const stubTransport = { request(options, handleResponse) { capturedHeaders = { ...options.headers }; const req = new EventEmitter(); req.write = () => true; req.setTimeout = () => {}; req.destroy = () => {}; req.end = () => { const res = new stream.Readable({ read() {} }); res.statusCode = 200; res.statusMessage = 'OK'; res.headers = { 'x-server': 'real' }; res.rawHeaders = []; res.req = req; process.nextTick(() => { handleResponse(res); res.push(null); }); }; return req; }, }; try { Object.prototype[Symbol.iterator] = function* () { yield ['X-Injected', 'yes']; yield ['Authorization', 'Bearer CHANGED']; }; const response = await axios.get('http://stub.invalid/', { headers: { Authorization: 'Bearer VALID_USER_TOKEN', 'X-App': 'safe', }, transport: stubTransport, maxRedirects: 0, }); assert.ok(capturedHeaders, 'transport was not invoked'); assert.strictEqual(capturedHeaders['X-App'], 'safe'); assert.strictEqual( capturedHeaders.Authorization || capturedHeaders.authorization, 'Bearer VALID_USER_TOKEN' ); assert.strictEqual(capturedHeaders['X-Injected'] || capturedHeaders['x-injected'], undefined); assert.strictEqual(response.headers.get('x-server'), 'real'); assert.strictEqual(response.headers.get('x-injected'), undefined); } finally { delete Object.prototype[Symbol.iterator]; } }); function pollute() { Object.prototype[toStringTagSym] = 'FormData'; Object.prototype.append = () => {}; Object.prototype.getHeaders = () => ({ 'x-injected': 'attacker', authorization: 'Bearer ATTACKER_TOKEN', }); Object.prototype.pipe = function (d) { if (d && d.end) d.end(); return d; }; Object.prototype.on = function () { return this; }; Object.prototype.once = function () { return this; }; } function cleanup() { for (const k of pollutedKeys) delete Object.prototype[k]; delete Object.prototype[toStringTagSym]; } it('should not merge prototype-polluted getHeaders into outgoing request', async () => { // Use a stub transport rather than a real HTTP server: polluting // Object.prototype in-process can destabilise Node's HTTP server // internals and cause spurious ECONNRESET. The stub captures the final // outgoing headers axios constructs, which is what this test asserts on. let capturedHeaders; const stubTransport = { request(options, handleResponse) { capturedHeaders = { ...options.headers }; const req = new EventEmitter(); req.write = () => true; req.setTimeout = () => {}; req.destroy = () => {}; req.end = () => { const res = new stream.Readable({ read() {} }); res.statusCode = 200; res.statusMessage = 'OK'; res.headers = {}; res.rawHeaders = []; res.req = req; process.nextTick(() => { handleResponse(res); res.push(null); }); }; return req; }, }; try { pollute(); await axios.post( 'http://stub.invalid/', { userId: 42 }, { headers: { Authorization: 'Bearer VALID_USER_TOKEN' }, transport: stubTransport, maxRedirects: 0, } ); } finally { cleanup(); } assert.ok(capturedHeaders, 'transport was not invoked'); assert.strictEqual(capturedHeaders['x-injected'], undefined); assert.notStrictEqual(capturedHeaders['Authorization'], 'Bearer ATTACKER_TOKEN'); assert.notStrictEqual(capturedHeaders['authorization'], 'Bearer ATTACKER_TOKEN'); }); }); describe('formDataHeaderPolicy', () => { function createStubTransport(captureHeaders) { return { request(options, handleResponse) { captureHeaders({ ...options.headers }); const req = new EventEmitter(); req.write = () => true; req.setTimeout = () => {}; req.destroy = () => {}; req.end = () => { const res = new stream.Readable({ read() {} }); res.statusCode = 200; res.statusMessage = 'OK'; res.headers = {}; res.rawHeaders = []; res.req = req; process.nextTick(() => { handleResponse(res); res.push(null); }); }; return req; }, }; } class CustomFormData extends stream.Readable { _read() { this.push(null); } append() {} getHeaders() { return { 'content-type': 'multipart/form-data; boundary=----fake', 'x-injected': 'custom', 'x-forwarded-for': '10.0.0.1', authorization: 'Bearer CUSTOM_TOKEN', host: 'custom.example.com', }; } get [Symbol.toStringTag]() { return 'FormData'; } } it('preserves legacy getHeaders() propagation by default', async () => { let capturedHeaders; await axios.post('http://stub.invalid/', new CustomFormData(), { transport: createStubTransport((headers) => { capturedHeaders = headers; }), maxRedirects: 0, }); assert.ok(capturedHeaders, 'transport was not invoked'); const ct = capturedHeaders['Content-Type'] || capturedHeaders['content-type']; assert.match(ct, /multipart\/form-data/); assert.strictEqual(capturedHeaders['x-injected'], 'custom'); assert.strictEqual(capturedHeaders['x-forwarded-for'], '10.0.0.1'); assert.strictEqual( capturedHeaders.Authorization || capturedHeaders.authorization, 'Bearer CUSTOM_TOKEN' ); assert.strictEqual(capturedHeaders.Host || capturedHeaders.host, 'custom.example.com'); }); it('only copies content headers when formDataHeaderPolicy is content-only', async () => { let capturedHeaders; await axios.post('http://stub.invalid/', new CustomFormData(), { transport: createStubTransport((headers) => { capturedHeaders = headers; }), maxRedirects: 0, formDataHeaderPolicy: 'content-only', }); assert.ok(capturedHeaders, 'transport was not invoked'); const ct = capturedHeaders['Content-Type'] || capturedHeaders['content-type']; assert.match(ct, /multipart\/form-data/); assert.strictEqual(capturedHeaders['x-injected'], undefined); assert.strictEqual(capturedHeaders['x-forwarded-for'], undefined); assert.strictEqual( capturedHeaders.Authorization || capturedHeaders.authorization, undefined ); assert.strictEqual(capturedHeaders.Host || capturedHeaders.host, undefined); }); }); }); describe('toFormData helper', () => { it('should properly serialize nested objects for parsing with multer.js (express.js)', async () => { const app = express(); const obj = { arr1: ['1', '2', '3'], arr2: ['1', ['2'], '3'], obj: { x: '1', y: { z: '1' } }, users: [ { name: 'Peter', surname: 'griffin' }, { name: 'Thomas', surname: 'Anderson' }, ], }; app.post('/', multer().none(), (req, res) => { res.send(JSON.stringify(req.body)); }); const server = await new Promise( (resolve, reject) => { const expressServer = app.listen(0, () => resolve(expressServer)); expressServer.on('error', reject); }, { port: SERVER_PORT } ); try { await Promise.all( [null, false, true].map((mode) => axios .postForm(`http://localhost:${server.address().port}/`, obj, { formSerializer: { indexes: mode }, }) .then((response) => { assert.deepStrictEqual(response.data, obj, `Index mode ${mode}`); }) ) ); } finally { await new Promise((resolve, reject) => { server.close((error) => { if (error) { reject(error); return; } resolve(); }); }); } }); it('should only match explicit routes for express 5 form handlers', async () => { const app = express(); app.post('/', multer().none(), (req, res) => { res.status(200).send(JSON.stringify({ route: 'root', body: req.body })); }); app.post('/unexpected', multer().none(), (req, res) => { res.status(418).send('wrong-route'); }); const server = await new Promise( (resolve, reject) => { const expressServer = app.listen(0, () => resolve(expressServer)); expressServer.on('error', reject); }, { port: SERVER_PORT } ); const rootUrl = `http://localhost:${server.address().port}`; try { const rootResponse = await axios.postForm(rootUrl, { foo: 'bar' }); assert.strictEqual(rootResponse.status, 200); assert.deepStrictEqual(rootResponse.data, { route: 'root', body: { foo: 'bar' } }); await assert.rejects( () => axios.postForm(`${rootUrl}/unexpected`, { foo: 'bar' }), (error) => { assert.strictEqual(error.response.status, 418); assert.strictEqual(error.response.data, 'wrong-route'); return true; } ); } finally { await new Promise((resolve, reject) => { server.close((error) => { if (error) { reject(error); return; } resolve(); }); }); } }); }); describe('Blob', () => { it('should support Blob', async () => { const server = await startHTTPServer( async (req, res) => { res.end(await getStream(req)); }, { port: SERVER_PORT } ); try { const blobContent = 'blob-content'; const blob = new BlobSpecCompliant([blobContent], { type: 'image/jpeg' }); const { data } = await axios.post(`http://localhost:${server.address().port}`, blob, { maxRedirects: 0, }); assert.deepStrictEqual(data, blobContent); } finally { await stopHTTPServer(server); } }); }); describe('URLEncoded Form', () => { it('should post object data as url-encoded form regardless of content-type header casing', async () => { const app = express(); const obj = { arr1: ['1', '2', '3'], arr2: ['1', ['2'], '3'], obj: { x: '1', y: { z: '1' } }, users: [ { name: 'Peter', surname: 'griffin' }, { name: 'Thomas', surname: 'Anderson' }, ], }; app.use(bodyParser.urlencoded({ extended: true })); app.post('/', (req, res) => { res.send(JSON.stringify(req.body)); }); const server = await new Promise( (resolve, reject) => { const expressServer = app.listen(0, () => resolve(expressServer)); expressServer.on('error', reject); }, { port: SERVER_PORT } ); try { for (const headerName of ['content-type', 'Content-Type']) { const response = await axios.post(`http://localhost:${server.address().port}/`, obj, { headers: { [headerName]: 'application/x-www-form-urlencoded', }, }); assert.deepStrictEqual(response.data, obj); } } finally { await new Promise((resolve, reject) => { server.close((error) => { if (error) { reject(error); return; } resolve(); }); }); } }); it('should respect formSerializer config', async () => { const obj = { arr1: ['1', '2', '3'], arr2: ['1', ['2'], '3'], }; const form = new URLSearchParams(); form.append('arr1[0]', '1'); form.append('arr1[1]', '2'); form.append('arr1[2]', '3'); form.append('arr2[0]', '1'); form.append('arr2[1][0]', '2'); form.append('arr2[2]', '3'); const server = await startHTTPServer( (req, res) => { req.pipe(res); }, { port: SERVER_PORT } ); try { const response = await axios.post(`http://localhost:${server.address().port}/`, obj, { headers: { 'content-type': 'application/x-www-form-urlencoded', }, formSerializer: { indexes: true, }, }); assert.strictEqual(response.data, form.toString()); } finally { await stopHTTPServer(server); } }); it('should parse nested urlencoded payloads and ignore mismatched content-type', async () => { const app = express(); app.use(bodyParser.urlencoded({ extended: true })); app.post('/', (req, res) => { const parserRanBeforeHandler = Boolean(req.body && Object.keys(req.body).length); res.send( JSON.stringify({ parserRanBeforeHandler, body: req.body, }) ); }); const server = await new Promise( (resolve, reject) => { const expressServer = app.listen(0, () => resolve(expressServer)); expressServer.on('error', reject); }, { port: SERVER_PORT } ); const rootUrl = `http://localhost:${server.address().port}/`; const payload = 'user[name]=Peter&tags[]=a&tags[]=b'; try { const parsedResponse = await axios.post(rootUrl, payload, { headers: { 'content-type': 'application/x-www-form-urlencoded', }, }); assert.deepStrictEqual(parsedResponse.data, { parserRanBeforeHandler: true, body: { user: { name: 'Peter' }, tags: ['a', 'b'], }, }); const ignoredResponse = await axios.post(rootUrl, payload, { headers: { 'content-type': 'text/plain', }, }); assert.strictEqual(ignoredResponse.data.parserRanBeforeHandler, false); assert.notDeepStrictEqual(ignoredResponse.data.body, { user: { name: 'Peter' }, tags: ['a', 'b'], }); } finally { await new Promise((resolve, reject) => { server.close((error) => { if (error) { reject(error); return; } resolve(); }); }); } }); }); describe('Data URL', () => { it('should support requesting data URL as a Buffer', async () => { const buffer = Buffer.from('123'); const dataURI = `data:application/octet-stream;base64,${buffer.toString('base64')}`; const { data } = await axios.get(dataURI); assert.deepStrictEqual(data, buffer); }); it('should support requesting data URL as a Blob (if supported by the environment)', async () => { if (!isBlobSupported) { return; } const buffer = Buffer.from('123'); const dataURI = `data:application/octet-stream;base64,${buffer.toString('base64')}`; const { data } = await axios.get(dataURI, { responseType: 'blob' }); assert.strictEqual(data.type, 'application/octet-stream'); assert.deepStrictEqual(await data.text(), '123'); }); it('should support requesting data URL as a String (text)', async () => { const buffer = Buffer.from('123', 'utf-8'); const dataURI = `data:application/octet-stream;base64,${buffer.toString('base64')}`; const { data } = await axios.get(dataURI, { responseType: 'text' }); assert.deepStrictEqual(data, '123'); }); it('should support requesting data URL as a Stream', async () => { const buffer = Buffer.from('123', 'utf-8'); const dataURI = `data:application/octet-stream;base64,${buffer.toString('base64')}`; const { data } = await axios.get(dataURI, { responseType: 'stream' }); assert.strictEqual(await getStream(data), '123'); }); }); describe('progress', () => { describe('upload', () => { it('should support upload progress capturing', async () => { const server = await startHTTPServer( { rate: 100 * 1024, }, { port: SERVER_PORT } ); try { let content = ''; const count = 10; const chunk = 'test'; const chunkLength = Buffer.byteLength(chunk); const contentLength = count * chunkLength; const readable = stream.Readable.from( (async function* () { let i = count; while (i-- > 0) { await setTimeoutAsync(1100); content += chunk; yield chunk; } })() ); const samples = []; const { data } = await axios.post(`http://localhost:${server.address().port}`, readable, { onUploadProgress: ({ loaded, total, progress, bytes, upload }) => { samples.push({ loaded, total, progress, bytes, upload, }); }, headers: { 'Content-Length': contentLength, }, responseType: 'text', }); assert.strictEqual(data, content); assert.deepStrictEqual( samples, Array.from( (function* () { for (let i = 1; i <= 10; i++) { yield { loaded: chunkLength * i, total: contentLength, progress: (chunkLength * i) / contentLength, bytes: 4, upload: true, }; } })() ) ); } finally { await stopHTTPServer(server); } }, 15000); }); describe('download', () => { it('should support download progress capturing', async () => { const server = await startHTTPServer( { rate: 100 * 1024, }, { port: SERVER_PORT } ); try { let content = ''; const count = 10; const chunk = 'test'; const chunkLength = Buffer.byteLength(chunk); const contentLength = count * chunkLength; const readable = stream.Readable.from( (async function* () { let i = count; while (i-- > 0) { await setTimeoutAsync(1100); content += chunk; yield chunk; } })() ); const samples = []; const { data } = await axios.post(`http://localhost:${server.address().port}`, readable, { onDownloadProgress: ({ loaded, total, progress, bytes, download }) => { samples.push({ loaded, total, progress, bytes, download, }); }, headers: { 'Content-Length': contentLength, }, responseType: 'text', maxRedirects: 0, }); assert.strictEqual(data, content); assert.deepStrictEqual( samples, Array.from( (function* () { for (let i = 1; i <= 10; i++) { yield { loaded: chunkLength * i, total: contentLength, progress: (chunkLength * i) / contentLength, bytes: 4, download: true, }; } })() ) ); } finally { await stopHTTPServer(server); } }, 15000); }); }); describe('Rate limit', () => { it('should support upload rate limit', async () => { const secs = 10; const configRate = 100000; const chunkLength = configRate * secs; const server = await startHTTPServer(); try { const buf = Buffer.alloc(chunkLength).fill('s'); const samples = []; const skip = 4; const compareValues = toleranceRange(50, 50); const { data } = await axios.post(`http://localhost:${server.address().port}`, buf, { onUploadProgress: ({ loaded, total, progress, bytes, rate }) => { samples.push({ loaded, total, progress, bytes, rate, }); }, maxRate: [configRate], responseType: 'text', maxRedirects: 0, }); samples.slice(skip).forEach(({ rate, progress }, i, _samples) => { assert.ok( compareValues(rate, configRate), `Rate sample at index ${i} is out of the expected range (${rate} / ${configRate}) [${_samples .map((sample) => sample.rate) .join(', ')}]` ); const progressTicksRate = 2; const expectedProgress = (i + skip) / secs / progressTicksRate; assert.ok( Math.abs(expectedProgress - progress) < 0.25, `Progress sample at index ${i} is out of the expected range (${progress} / ${expectedProgress}) [${_samples .map((sample) => sample.progress) .join(', ')}]` ); }); assert.strictEqual(data, buf.toString(), 'content corrupted'); } finally { await stopHTTPServer(server); } }, 30000); it('should support download rate limit', async () => { const secs = 10; const configRate = 100000; const chunkLength = configRate * secs; const server = await startHTTPServer(); try { const buf = Buffer.alloc(chunkLength).fill('s'); const samples = []; const skip = 4; const compareValues = toleranceRange(50, 50); const { data } = await axios.post(`http://localhost:${server.address().port}`, buf, { onDownloadProgress: ({ loaded, total, progress, bytes, rate }) => { samples.push({ loaded, total, progress, bytes, rate, }); }, maxRate: [0, configRate], responseType: 'text', maxRedirects: 0, }); samples.slice(skip).forEach(({ rate, progress }, i, _samples) => { assert.ok( compareValues(rate, configRate), `Rate sample at index ${i} is out of the expected range (${rate} / ${configRate}) [${_samples .map((sample) => sample.rate) .join(', ')}]` ); const progressTicksRate = 3; const expectedProgress = (i + skip) / secs / progressTicksRate; assert.ok( Math.abs(expectedProgress - progress) < 0.25, `Progress sample at index ${i} is out of the expected range (${progress} / ${expectedProgress}) [${_samples .map((sample) => sample.progress) .join(', ')}]` ); }); assert.strictEqual(data, buf.toString(), 'content corrupted'); } finally { await stopHTTPServer(server); } }, 30000); }); describe('request aborting', () => { it('should be able to abort the response stream', async () => { const server = await startHTTPServer( { rate: 100000, useBuffering: true, }, { port: SERVER_PORT } ); try { const buf = Buffer.alloc(1024 * 1024); const controller = new AbortController(); const { data } = await axios.post(`http://localhost:${server.address().port}`, buf, { responseType: 'stream', signal: controller.signal, maxRedirects: 0, }); setTimeout(() => { controller.abort(); }, 500); let streamError; data.on('error', (error) => { streamError = error; }); await assert.rejects( new Promise((resolve, reject) => { stream.pipeline(data, devNull(), (error) => { if (error) { reject(error); return; } resolve(); }); }) ); assert.strictEqual(streamError && streamError.code, 'ERR_CANCELED'); } finally { await stopHTTPServer(server); } }); }); it('should properly handle synchronous errors inside the adapter', async () => { await assert.rejects(() => axios.get('http://192.168.0.285'), /Invalid URL/); }); it('should support function as paramsSerializer value', async () => { const server = await startHTTPServer((req, res) => res.end(req.url), { port: SERVER_PORT }); try { const { data } = await axios.post(`http://localhost:${server.address().port}`, 'test', { params: { x: 1, }, paramsSerializer: () => 'foo', maxRedirects: 0, }); assert.strictEqual(data, '/?foo'); } finally { await stopHTTPServer(server); } }); describe('DNS', () => { it('should support a custom DNS lookup function', async () => { const server = await startHTTPServer(SERVER_HANDLER_STREAM_ECHO); const payload = 'test'; let isCalled = false; try { const { data } = await axios.post( `http://fake-name.axios:${server.address().port}`, payload, { lookup: (hostname, opt, cb) => { isCalled = true; cb(null, '127.0.0.1', 4); }, } ); assert.ok(isCalled); assert.strictEqual(data, payload); } finally { await stopHTTPServer(server); } }); it('should support a custom DNS lookup function with address entry passing', async () => { const server = await startHTTPServer(SERVER_HANDLER_STREAM_ECHO); const payload = 'test'; let isCalled = false; try { const { data } = await axios.post( `http://fake-name.axios:${server.address().port}`, payload, { lookup: (hostname, opt, cb) => { isCalled = true; cb(null, { address: '127.0.0.1', family: 4 }); }, } ); assert.ok(isCalled); assert.strictEqual(data, payload); } finally { await stopHTTPServer(server); } }); it('should support a custom DNS lookup function (async)', async () => { const server = await startHTTPServer(SERVER_HANDLER_STREAM_ECHO); const payload = 'test'; let isCalled = false; try { const { data } = await axios.post( `http://fake-name.axios:${server.address().port}`, payload, { lookup: async (hostname, opt) => { isCalled = true; return ['127.0.0.1', 4]; }, } ); assert.ok(isCalled); assert.strictEqual(data, payload); } finally { await stopHTTPServer(server); } }); it('should support a custom DNS lookup function with address entry (async)', async () => { const server = await startHTTPServer(SERVER_HANDLER_STREAM_ECHO); const payload = 'test'; let isCalled = false; try { const { data } = await axios.post( `http://fake-name.axios:${server.address().port}`, payload, { lookup: async (hostname, opt) => { isCalled = true; return { address: '127.0.0.1', family: 4 }; }, } ); assert.ok(isCalled); assert.strictEqual(data, payload); } finally { await stopHTTPServer(server); } }); it('should support a custom DNS lookup function that returns only IP address (async)', async () => { const server = await startHTTPServer(SERVER_HANDLER_STREAM_ECHO); const payload = 'test'; let isCalled = false; try { const { data } = await axios.post( `http://fake-name.axios:${server.address().port}`, payload, { lookup: async (hostname, opt) => { isCalled = true; return '127.0.0.1'; }, } ); assert.ok(isCalled); assert.strictEqual(data, payload); } finally { await stopHTTPServer(server); } }); it('should handle errors', async () => { await assert.rejects(async () => { await axios.get('https://no-such-domain-987654.com', { lookup, }); }, /ENOTFOUND/); }); }); describe('JSON', () => { it('should support reviver on JSON.parse', async () => { const server = await startHTTPServer( async (_, res) => { res.end( JSON.stringify({ foo: 'bar', }) ); }, { port: SERVER_PORT } ); try { const { data } = await axios.get(`http://localhost:${server.address().port}`, { parseReviver: (key, value) => { return key === 'foo' ? 'success' : value; }, }); assert.deepStrictEqual(data, { foo: 'success' }); } finally { await stopHTTPServer(server); } }); }); describe('HTTP2', () => { const createHttp2Axios = (baseURL) => axios.create({ baseURL, httpVersion: 2, http2Options: { rejectUnauthorized: false, }, }); it('should merge request http2Options with its instance config', async () => { const http2Axios = createHttp2Axios('https://localhost:8080'); const { data } = await http2Axios.get('/', { http2Options: { foo: 'test', }, adapter: async (config) => { return { data: config.http2Options, }; }, }); assert.deepStrictEqual(data, { rejectUnauthorized: false, foo: 'test', }); }); it('should support http2 transport', async () => { const server = await startHTTPServer( (req, res) => { res.end('OK'); }, { useHTTP2: true, port: SERVER_PORT, } ); try { const localServerURL = `https://localhost:${server.address().port}`; const http2Axios = createHttp2Axios(localServerURL); const { data } = await http2Axios.get(localServerURL); assert.deepStrictEqual(data, 'OK'); } finally { await stopHTTPServer(server); } }); it('should support request payload', async () => { const server = await startHTTPServer(null, { useHTTP2: true, port: SERVER_PORT, }); try { const localServerURL = `https://localhost:${server.address().port}`; const http2Axios = createHttp2Axios(localServerURL); const payload = 'DATA'; const { data } = await http2Axios.post(localServerURL, payload); assert.deepStrictEqual(data, payload); } finally { await stopHTTPServer(server); } }); it('should enforce maxBodyLength for HTTP/2 streamed uploads', async () => { let bytesReceived = 0; const server = await startHTTPServer( (req, res) => { req.on('data', (chunk) => { bytesReceived += chunk.length; }); req.on('error', () => {}); req.on('end', () => { res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ received: bytesReceived })); }); }, { useHTTP2: true, port: SERVER_PORT, } ); try { const localServerURL = `https://localhost:${server.address().port}`; const http2Axios = createHttp2Axios(localServerURL); const payload = Buffer.alloc(2 * 1024 * 1024, 0x63); const source = stream.Readable.from([payload]); await assert.rejects( http2Axios.post(localServerURL, source, { maxBodyLength: 1024, headers: { 'Content-Type': 'application/octet-stream' }, }), (error) => { assert.strictEqual(error.message, 'Request body larger than maxBodyLength limit'); assert.strictEqual(error.code, AxiosError.ERR_BAD_REQUEST); return true; } ); assert.ok( bytesReceived <= 1024 * 4, `server should not receive full payload; got ${bytesReceived}` ); } finally { if (server.closeAllSessions) { server.closeAllSessions(); } await stopHTTPServer(server); } }); it('should support FormData as a payload', async () => { if (typeof FormData !== 'function') { return; } const server = await startHTTPServer( async (req, res) => { const { fields, files } = await handleFormData(req); res.end( JSON.stringify({ fields, files, }) ); }, { useHTTP2: true, port: SERVER_PORT, } ); try { const localServerURL = `https://localhost:${server.address().port}`; const http2Axios = createHttp2Axios(localServerURL); const form = new FormData(); form.append('x', 'foo'); form.append('y', 'bar'); const { data } = await http2Axios.post(localServerURL, form); assert.deepStrictEqual(data, { fields: { x: ['foo'], y: ['bar'], }, files: {}, }); } finally { await stopHTTPServer(server); } }); describe('response types', () => { const originalData = '{"test": "OK"}'; const fixtures = { text: (value) => assert.strictEqual(value, originalData), arraybuffer: (value) => assert.deepStrictEqual(value, Buffer.from(originalData)), stream: async (value) => assert.deepStrictEqual(await getStream(value), originalData), json: async (value) => assert.deepStrictEqual(value, JSON.parse(originalData)), }; for (const [responseType, assertValue] of Object.entries(fixtures)) { it(`should support ${responseType} response type`, async () => { const server = await startHTTPServer( (req, res) => { res.end(originalData); }, { useHTTP2: true, port: SERVER_PORT, } ); try { const localServerURL = `https://localhost:${server.address().port}`; const http2Axios = createHttp2Axios(localServerURL); const { data } = await http2Axios.get(localServerURL, { responseType, }); await assertValue(data); } finally { await stopHTTPServer(server); } }); } }); it('should support request timeout', async () => { let isAborted = false; let aborted; const promise = new Promise((resolve) => (aborted = resolve)); const server = await startHTTPServer( (req, res) => { setTimeout(() => { res.end('OK'); }, 15000); }, { useHTTP2: true, port: SERVER_PORT, } ); try { const localServerURL = `https://localhost:${server.address().port}`; const http2Axios = createHttp2Axios(localServerURL); server.on('stream', (http2Stream) => { http2Stream.once('aborted', () => { isAborted = true; aborted(); }); }); await assert.rejects(async () => { await http2Axios.get(localServerURL, { timeout: 500, }); }, /timeout/); await promise; assert.ok(isAborted); } finally { await stopHTTPServer(server); } }); it('should support request cancellation', async () => { if (typeof AbortSignal !== 'function' || !AbortSignal.timeout) { return; } let isAborted = false; let aborted; const promise = new Promise((resolve) => (aborted = resolve)); const server = await startHTTPServer( (req, res) => { setTimeout(() => { res.end('OK'); }, 15000); }, { useHTTP2: true, port: SERVER_PORT, } ); try { const localServerURL = `https://localhost:${server.address().port}`; const http2Axios = createHttp2Axios(localServerURL); server.on('stream', (http2Stream) => { http2Stream.once('aborted', () => { isAborted = true; aborted(); }); }); await assert.rejects(async () => { await http2Axios.get(localServerURL, { signal: AbortSignal.timeout(500), }); }, /CanceledError: canceled/); await promise; assert.ok(isAborted); } finally { await stopHTTPServer(server); } }); it('should support stream response cancellation', async () => { let isAborted = false; const source = axios.CancelToken.source(); let aborted; const promise = new Promise((resolve) => (aborted = resolve)); const server = await startHTTPServer( (req, res) => { generateReadable(10000, 100, 100).pipe(res); }, { useHTTP2: true, port: SERVER_PORT, } ); try { const localServerURL = `https://localhost:${server.address().port}`; const http2Axios = createHttp2Axios(localServerURL); server.on('stream', (http2Stream) => { http2Stream.once('aborted', () => { isAborted = true; aborted(); }); }); const { data } = await http2Axios.get(localServerURL, { cancelToken: source.token, responseType: 'stream', }); setTimeout(() => source.cancel()); await assert.rejects( new Promise((resolve, reject) => { stream.pipeline(data, devNull(), (error) => { if (error) { reject(error); return; } resolve(); }); }), /CanceledError: canceled/ ); await promise; assert.ok(isAborted); } finally { await stopHTTPServer(server); } }); describe('session', () => { // HTTP2 session tests are sensitive to cross-test port reuse: when one // test's server is torn down (closeAllSessions destroys h2 sessions), // a follow-up test binding the same port can observe a "Premature // close" on its own stream. Use ephemeral ports (port: 0, the default // from startHTTPServer) and a small retry budget as a backstop. it('should reuse session for the target authority', { retry: 2 }, async () => { const server = await startHTTPServer( (req, res) => { setTimeout(() => res.end('OK'), 1000); }, { useHTTP2: true, } ); try { const localServerURL = `https://localhost:${server.address().port}`; const http2Axios = createHttp2Axios(localServerURL); const [response1, response2] = await Promise.all([ http2Axios.get(localServerURL, { responseType: 'stream', }), http2Axios.get(localServerURL, { responseType: 'stream', }), ]); assert.strictEqual(response1.data.session, response2.data.session); assert.deepStrictEqual( await Promise.all([getStream(response1.data), getStream(response2.data)]), ['OK', 'OK'] ); } finally { await stopHTTPServer(server); } }); it('should use different sessions for different authorities', { retry: 2 }, async () => { const server = await startHTTPServer( (req, res) => { setTimeout(() => { res.end('OK'); }, 2000); }, { useHTTP2: true, } ); const server2 = await startHTTPServer( (req, res) => { setTimeout(() => { res.end('OK'); }, 2000); }, { useHTTP2: true, } ); try { const localServerURL = `https://localhost:${server.address().port}`; const localServerURL2 = `https://localhost:${server2.address().port}`; const http2Axios = createHttp2Axios(localServerURL); const [response1, response2] = await Promise.all([ http2Axios.get(localServerURL, { responseType: 'stream', }), http2Axios.get(localServerURL2, { responseType: 'stream', }), ]); assert.notStrictEqual(response1.data.session, response2.data.session); assert.deepStrictEqual( await Promise.all([getStream(response1.data), getStream(response2.data)]), ['OK', 'OK'] ); } finally { await Promise.all([stopHTTPServer(server), stopHTTPServer(server2)]); } }); it( 'should use different sessions for requests with different http2Options set', { retry: 2 }, async () => { const server = await startHTTPServer( (req, res) => { setTimeout(() => { res.end('OK'); }, 1000); }, { useHTTP2: true, } ); try { const localServerURL = `https://localhost:${server.address().port}`; const http2Axios = createHttp2Axios(localServerURL); const [response1, response2] = await Promise.all([ http2Axios.get(localServerURL, { http2Options: { sessionTimeout: 2000, }, }), http2Axios.get(localServerURL, { http2Options: { sessionTimeout: 4000, }, }), ]); assert.notStrictEqual(response1.request.session, response2.request.session); assert.deepStrictEqual([response1.data, response2.data], ['OK', 'OK']); } finally { await stopHTTPServer(server); } } ); it( 'should use the same session for request with the same resolved http2Options set', { retry: 2 }, async () => { const server = await startHTTPServer( (req, res) => { setTimeout(() => res.end('OK'), 1000); }, { useHTTP2: true, } ); try { const localServerURL = `https://localhost:${server.address().port}`; const http2Axios = createHttp2Axios(localServerURL); const responses = await Promise.all([ http2Axios.get(localServerURL, { responseType: 'stream', }), http2Axios.get(localServerURL, { responseType: 'stream', http2Options: undefined, }), http2Axios.get(localServerURL, { responseType: 'stream', http2Options: {}, }), ]); assert.strictEqual(responses[1].data.session, responses[0].data.session); assert.strictEqual(responses[2].data.session, responses[0].data.session); assert.deepStrictEqual( await Promise.all(responses.map(({ data }) => getStream(data))), ['OK', 'OK', 'OK'] ); } finally { await stopHTTPServer(server); } } ); it( 'should use different sessions after previous session timeout', { retry: 2, timeout: 15000 }, async () => { const server = await startHTTPServer( (req, res) => { setTimeout(() => res.end('OK'), 100); }, { useHTTP2: true, } ); try { const localServerURL = `https://localhost:${server.address().port}`; const http2Axios = createHttp2Axios(localServerURL); const response1 = await http2Axios.get(localServerURL, { responseType: 'stream', http2Options: { sessionTimeout: 1000, }, }); const session1 = response1.data.session; const data1 = await getStream(response1.data); await setTimeoutAsync(5000); const response2 = await http2Axios.get(localServerURL, { responseType: 'stream', http2Options: { sessionTimeout: 1000, }, }); const session2 = response2.data.session; const data2 = await getStream(response2.data); assert.notStrictEqual(session1, session2); assert.strictEqual(data1, 'OK'); assert.strictEqual(data2, 'OK'); } finally { await stopHTTPServer(server); } } ); }); }); it('should not abort stream on settle rejection', async () => { const server = await startHTTPServer( (req, res) => { res.statusCode = 404; res.end('OK'); }, { port: SERVER_PORT } ); try { let error; try { await axios.get(`http://localhost:${server.address().port}`, { responseType: 'stream', }); } catch (err) { error = err; } assert.ok(error, 'request should be rejected'); assert.strictEqual(await getStream(error.response.data), 'OK'); } finally { await stopHTTPServer(server); } }); it('should reject when only the request socket emits an error', async () => { const noop = () => {}; const socket = new EventEmitter(); socket.setKeepAlive = noop; socket.on('error', noop); const transport = { request() { return new (class MockRequest extends EventEmitter { constructor() { super(); this.destroyed = false; } setTimeout() {} write() {} end() { this.emit('socket', socket); setImmediate(() => { socket.emit('error', Object.assign(new Error('write EPIPE'), { code: 'EPIPE' })); }); } destroy(err) { if (this.destroyed) { return; } this.destroyed = true; err && this.emit('error', err); this.emit('close'); } })(); }, }; const error = await Promise.race([ axios.post('http://example.com/', 'test', { transport, maxRedirects: 0, }), setTimeoutAsync(200).then(() => { throw new Error('socket error did not reject the request'); }), ]).catch((err) => err); assert.ok(error instanceof AxiosError); assert.strictEqual(error.code, 'EPIPE'); assert.strictEqual(error.message, 'write EPIPE'); }); describe('keep-alive', () => { it('should not emit MaxListenersExceededWarning under concurrent requests through a pooled keep-alive agent (regression #10780)', async () => { const server = await startHTTPServer( (req, res) => { // Small delay forces concurrent requests to queue on the single pooled socket. setTimeout(() => { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('ok'); }, 5); }, { port: SERVER_PORT } ); const warnings = []; const warningHandler = (warning) => { if (warning && warning.name === 'MaxListenersExceededWarning') { warnings.push(warning); } }; process.on('warning', warningHandler); const agent = new http.Agent({ keepAlive: true, maxSockets: 1 }); try { const baseURL = `http://localhost:${server.address().port}`; const CONCURRENCY = 30; const results = await Promise.all( Array.from({ length: CONCURRENCY }, (_, i) => axios.get(`/req-${i}`, { baseURL, httpAgent: agent }) ) ); assert.strictEqual(results.length, CONCURRENCY); for (const r of results) { assert.strictEqual(r.status, 200); assert.strictEqual(r.data, 'ok'); } // Allow any deferred process 'warning' emissions to flush. await setTimeoutAsync(50); assert.strictEqual( warnings.length, 0, `expected no MaxListenersExceededWarning, got ${warnings.length}: ${warnings.map((w) => w.message).join('; ')}` ); // Inspect live sockets on the agent: none should have more than one // axios-installed error listener, regardless of how many requests ran. const allSockets = [] .concat(...Object.values(agent.sockets || {})) .concat(...Object.values(agent.freeSockets || {})); for (const sock of allSockets) { assert.ok( sock.listenerCount('error') <= 2, `socket should have at most a couple of error listeners (agent + axios), got ${sock.listenerCount('error')}` ); } } finally { process.removeListener('warning', warningHandler); agent.destroy(); await stopHTTPServer(server); } }, 30000); it('should not leak memory via retained request closures under a long burst of keep-alive requests (regression #10780)', async () => { // This guards against stage88's report of OOM at ~480k sequential requests: // if the per-request closure leaked, heap would grow linearly. We simulate // a shorter burst and verify retained closures are released (via WeakRef // reachability check after GC, if exposed). if (typeof global.gc !== 'function') { // Skip when GC is not exposed (run with `node --expose-gc`). return; } const server = await startHTTPServer( (req, res) => { res.writeHead(200); res.end('ok'); }, { port: SERVER_PORT } ); const agent = new http.Agent({ keepAlive: true, maxSockets: 4 }); try { const baseURL = `http://localhost:${server.address().port}`; const refs = []; for (let i = 0; i < 200; i += 1) { // eslint-disable-next-line no-await-in-loop const response = await axios.get('/', { baseURL, httpAgent: agent }); refs.push(new WeakRef(response.request)); } // Drop strong refs and force GC. global.gc(); await setTimeoutAsync(10); global.gc(); const retained = refs.filter((r) => r.deref() !== undefined).length; // Some trailing requests may still be referenced in internal buffers. // The fix's correctness: retained count scales with agent socket count, // NOT with request count. A pre-fix leak would keep >>socket count. assert.ok( retained <= 20, `expected most request objects to be collectible after GC; ${retained}/200 retained suggests a closure leak` ); } finally { agent.destroy(); await stopHTTPServer(server); } }, 30000); it('should not fail with "socket hang up" when using timeouts', async () => { const server = await startHTTPServer( async (req, res) => { if (req.url === '/wait') { await new Promise((resolve) => setTimeout(resolve, 5000)); } res.end('ok'); }, { port: SERVER_PORT } ); try { const baseURL = `http://localhost:${server.address().port}`; await axios.get('/1', { baseURL, timeout: 1000 }); await axios.get('/wait', { baseURL, timeout: 0 }); } finally { await stopHTTPServer(server); } }, 15000); it('should install at most one socket error listener across reused keep-alive sockets', async () => { const noop = () => {}; const socket = new EventEmitter(); socket.setKeepAlive = noop; socket.on('error', noop); const baseErrorListenerCount = socket.listenerCount('error'); const transport = { request(_, cb) { return new (class MockRequest extends EventEmitter { constructor() { super(); this.destroyed = false; } setTimeout() {} write() {} end() { this.emit('socket', socket); setImmediate(() => { const response = stream.Readable.from(['ok']); response.statusCode = 200; response.headers = {}; cb(response); this.emit('close'); }); } destroy(err) { if (this.destroyed) { return; } this.destroyed = true; err && this.emit('error', err); this.emit('close'); } })(); }, }; // First request: axios installs its single per-socket listener. await axios.get('http://example.com/first', { transport, maxRedirects: 0, }); await setTimeoutAsync(0); assert.strictEqual( socket.listenerCount('error'), baseErrorListenerCount + 1, 'axios should install exactly one socket error listener' ); // Many subsequent requests reusing the same socket must not add more listeners. for (let i = 0; i < 20; i += 1) { // eslint-disable-next-line no-await-in-loop await axios.get(`http://example.com/next-${i}`, { transport, maxRedirects: 0, }); // eslint-disable-next-line no-await-in-loop await setTimeoutAsync(0); assert.strictEqual( socket.listenerCount('error'), baseErrorListenerCount + 1, 'listener count must stay constant across keep-alive reuse' ); } }); it('should not accumulate socket error listeners when a pooled socket is reassigned before the previous request closes (regression #10780)', async () => { const noop = () => {}; const socket = new EventEmitter(); socket.setKeepAlive = noop; socket.on('error', noop); const baseErrorListenerCount = socket.listenerCount('error'); // Each request defers its 'close' emission so that the socket is // reassigned to the next request before the previous one closes. // This reproduces the race condition described in #10780. const pendingRequests = []; const transport = { request(_, cb) { const req = new (class MockRequest extends EventEmitter { constructor() { super(); this.destroyed = false; } setTimeout() {} write() {} end() { // Share the single pooled socket across every request. this.emit('socket', socket); setImmediate(() => { const response = stream.Readable.from(['ok']); response.statusCode = 200; response.headers = {}; cb(response); // Intentionally do NOT emit 'close' yet. Collect the req // so close can be emitted later, after other reqs have // already claimed the socket. pendingRequests.push(this); }); } destroy(err) { if (this.destroyed) return; this.destroyed = true; err && this.emit('error', err); this.emit('close'); } })(); return req; }, }; const results = await Promise.all( Array.from({ length: 20 }, (_, i) => axios.get(`http://example.com/concurrent-${i}`, { transport, maxRedirects: 0, }) ) ); assert.strictEqual(results.length, 20); // Critical assertion: despite 20 concurrent requests all claiming the // same pooled socket before any emitted 'close', only ONE axios listener // must be attached. This is the difference between the pre-fix // behaviour (20 listeners, MaxListenersExceededWarning) and the fix. assert.strictEqual( socket.listenerCount('error'), baseErrorListenerCount + 1, `expected a single axios socket error listener under concurrent reuse, got ${socket.listenerCount('error') - baseErrorListenerCount}` ); // Now drain the queued close events. Listener count must still be 1. for (const req of pendingRequests) { req.emit('close'); } await setTimeoutAsync(0); assert.strictEqual( socket.listenerCount('error'), baseErrorListenerCount + 1, 'listener must persist on the socket after requests close (cleanup is per-request ownership, not per-listener removal)' ); }); it('should route a socket error to the currently-active request after the socket has been reassigned', async () => { const noop = () => {}; const socket = new EventEmitter(); socket.setKeepAlive = noop; socket.on('error', noop); const createdReqs = []; // First transport: completes cleanly (emits response then close). const cleanTransport = { request(_, cb) { const emitter = new (class MockRequest extends EventEmitter { constructor() { super(); this.destroyed = false; createdReqs.push(this); } setTimeout() {} write() {} end() { this.emit('socket', socket); setImmediate(() => { const response = stream.Readable.from(['ok']); response.statusCode = 200; response.headers = {}; cb(response); this.emit('close'); }); } destroy(err) { if (this.destroyed) return; this.destroyed = true; err && this.emit('error', err); this.emit('close'); } })(); return emitter; }, }; // Second transport: emits socket error instead of a response. const errorTransport = { request() { const emitter = new (class MockRequest extends EventEmitter { constructor() { super(); this.destroyed = false; createdReqs.push(this); } setTimeout() {} write() {} end() { this.emit('socket', socket); setImmediate(() => { socket.emit('error', Object.assign(new Error('boom'), { code: 'EPIPE' })); }); } destroy(err) { if (this.destroyed) return; this.destroyed = true; err && this.emit('error', err); this.emit('close'); } })(); return emitter; }, }; // First request completes successfully; socket is released. await axios.get('http://example.com/first', { transport: cleanTransport, maxRedirects: 0 }); await setTimeoutAsync(0); const firstReq = createdReqs[0]; assert.ok( firstReq && firstReq.destroyed === false, 'first request must not have been destroyed by a socket error' ); // Stray socket error after first req has closed: must not destroy firstReq. socket.emit('error', new Error('stray error after close')); assert.strictEqual( firstReq.destroyed, false, 'socket error after close must not destroy the old request' ); // Second request claims the socket, then its socket errors. It should reject. const err = await axios .get('http://example.com/second', { transport: errorTransport, maxRedirects: 0 }) .catch((e) => e); assert.ok(err instanceof AxiosError, 'second request should reject with an AxiosError'); assert.strictEqual(err.code, 'EPIPE'); const secondReq = createdReqs[1]; assert.strictEqual( secondReq.destroyed, true, 'second request should be destroyed by its own active socket error' ); }); }); describe('redirect listener accumulation', () => { it('should not emit MaxListenersExceededWarning when a single request follows >= 11 redirects', async () => { const REDIRECT_COUNT = 11; const server = await startHTTPServer( (req, res) => { const match = req.url.match(/^\/redirect\/(\d+)$/); if (match) { const n = Number(match[1]); if (n < REDIRECT_COUNT) { res.writeHead(302, { Location: `/redirect/${n + 1}` }); } else { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ redirects: n })); return; } res.end(); return; } res.writeHead(302, { Location: '/redirect/1' }); res.end(); }, { port: SERVER_PORT } ); const warnings = []; const warningHandler = (warning) => { if (warning && warning.name === 'MaxListenersExceededWarning') { warnings.push(warning); } }; process.on('warning', warningHandler); try { const baseURL = `http://localhost:${server.address().port}`; const response = await axios.get('/start', { baseURL, maxRedirects: REDIRECT_COUNT + 5, }); assert.strictEqual(response.status, 200); assert.deepStrictEqual(response.data, { redirects: REDIRECT_COUNT }); // Allow any deferred process 'warning' emissions to flush. await setTimeoutAsync(50); assert.strictEqual( warnings.length, 0, `expected no MaxListenersExceededWarning across ${REDIRECT_COUNT} redirects, got ${warnings.length}: ${warnings.map((w) => w.message).join('; ')}` ); } finally { process.removeListener('warning', warningHandler); await stopHTTPServer(server); } }, 30000); it('should attach at most one close listener to the outer request across a long redirect chain', async () => { const REDIRECT_COUNT = 20; const maxObservedCloseListeners = { value: 0 }; const server = await startHTTPServer( (req, res) => { const match = req.url.match(/^\/r\/(\d+)$/); if (match) { const n = Number(match[1]); if (n < REDIRECT_COUNT) { res.writeHead(302, { Location: `/r/${n + 1}` }); } else { res.writeHead(200); res.end('done'); return; } res.end(); return; } res.writeHead(302, { Location: '/r/1' }); res.end(); }, { port: SERVER_PORT } ); try { const baseURL = `http://localhost:${server.address().port}`; // Patch EventEmitter.prototype.on briefly to observe the peak close-listener // count on any emitter. The outer RedirectableRequest is the only target // that would accumulate listeners under the bug. Other emitters in the // process (server sockets, etc.) will also be observed but are irrelevant // as long as the peak stays within a small bound. const originalOn = EventEmitter.prototype.on; const originalOnce = EventEmitter.prototype.once; function record(eventName) { if (eventName === 'close') { const count = this.listenerCount('close'); if (count > maxObservedCloseListeners.value) { maxObservedCloseListeners.value = count; } } } EventEmitter.prototype.on = function patchedOn(eventName, listener) { const res = originalOn.call(this, eventName, listener); record.call(this, eventName); return res; }; EventEmitter.prototype.once = function patchedOnce(eventName, listener) { const res = originalOnce.call(this, eventName, listener); record.call(this, eventName); return res; }; try { const response = await axios.get('/start', { baseURL, maxRedirects: REDIRECT_COUNT + 5, }); assert.strictEqual(response.status, 200); } finally { EventEmitter.prototype.on = originalOn; EventEmitter.prototype.once = originalOnce; } // Pre-fix: peak would be >= REDIRECT_COUNT (one axios close listener per hop // on the outer RedirectableRequest). Post-fix: axios attaches exactly one // close listener to the outer request; framework internals typically add // a couple more. A generous bound of 10 distinguishes the behaviours. assert.ok( maxObservedCloseListeners.value < 10, `close listener count should stay below 10 across ${REDIRECT_COUNT} redirects, peak was ${maxObservedCloseListeners.value}` ); } finally { await stopHTTPServer(server); } }, 30000); }); describe('socketPath security', () => { function makeSocketPath() { const pipe = `axios-socketpath-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`; return os.platform() === 'win32' ? `\\\\.\\pipe\\${pipe}` : path.join(os.tmpdir(), `${pipe}.sock`); } function startUnixServer(socketPath) { return new Promise((resolveStart, rejectStart) => { const server = http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ ok: true, url: req.url })); }); try { fs.unlinkSync(socketPath); } catch (_) { /* noop */ } server.once('error', rejectStart); server.listen(socketPath, () => resolveStart(server)); }); } function stopUnixServer(server, socketPath) { return new Promise((done) => { server.close(() => { try { fs.unlinkSync(socketPath); } catch (_) { /* noop */ } done(); }); }); } it('allows socketPath when no allowedSocketPaths is set (backwards compatible)', async () => { const socketPath = makeSocketPath(); const server = await startUnixServer(socketPath); try { const res = await axios.get('http://localhost/echo', { socketPath }); assert.strictEqual(res.status, 200); assert.strictEqual(res.data.ok, true); } finally { await stopUnixServer(server, socketPath); } }); it('allows socketPath when it matches an allowedSocketPaths string', async () => { const socketPath = makeSocketPath(); const server = await startUnixServer(socketPath); try { const res = await axios.get('http://localhost/echo', { socketPath, allowedSocketPaths: socketPath, }); assert.strictEqual(res.status, 200); } finally { await stopUnixServer(server, socketPath); } }); it('allows socketPath when it matches an entry in allowedSocketPaths array', async () => { const socketPath = makeSocketPath(); const server = await startUnixServer(socketPath); try { const res = await axios.get('http://localhost/echo', { socketPath, allowedSocketPaths: ['/var/run/does-not-exist.sock', socketPath], }); assert.strictEqual(res.status, 200); } finally { await stopUnixServer(server, socketPath); } }); it('rejects socketPath not in allowedSocketPaths', async () => { await assert.rejects( axios.get('http://localhost/echo', { socketPath: '/var/run/docker.sock', allowedSocketPaths: ['/tmp/allowed.sock'], }), (err) => { assert.ok(err instanceof AxiosError); assert.strictEqual(err.code, AxiosError.ERR_BAD_OPTION_VALUE); assert.match(err.message, /allowedSocketPaths/); return true; } ); }); it('rejects socketPath attempting path traversal that escapes allowlist', async () => { const allowedDir = path.join(os.tmpdir(), 'axios-allowed'); const allowed = path.join(allowedDir, 'app.sock'); await assert.rejects( axios.get('http://localhost/echo', { socketPath: path.join(allowedDir, '..', 'other.sock'), allowedSocketPaths: [allowed], }), (err) => { assert.strictEqual(err.code, AxiosError.ERR_BAD_OPTION_VALUE); return true; } ); }); it('treats relative and absolute allowedSocketPaths entries equivalently', async () => { const socketPath = makeSocketPath(); const server = await startUnixServer(socketPath); try { const relative = path.relative(process.cwd(), socketPath); const res = await axios.get('http://localhost/echo', { socketPath, allowedSocketPaths: [relative], }); assert.strictEqual(res.status, 200); } finally { await stopUnixServer(server, socketPath); } }); it('rejects non-string socketPath', async () => { await assert.rejects(axios.get('http://localhost/echo', { socketPath: 12345 }), (err) => { assert.ok(err instanceof AxiosError); assert.strictEqual(err.code, AxiosError.ERR_BAD_OPTION_VALUE); assert.match(err.message, /socketPath must be a string/); return true; }); }); it('empty allowedSocketPaths array blocks all socketPath values', async () => { await assert.rejects( axios.get('http://localhost/echo', { socketPath: '/tmp/anything.sock', allowedSocketPaths: [], }), (err) => { assert.strictEqual(err.code, AxiosError.ERR_BAD_OPTION_VALUE); return true; } ); }); }); }); axios-axios-2d06f96/tests/unit/adapters/key.pem000066400000000000000000000032131521272452000215360ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIIEogIBAAKCAQEA+joLfff3WdFIGwrlVdUWfZ9vDr9w86yQpI6Xq0KF6JiKtxa+ EVCNWtq8Ht5rZd1MxNSFWVb1jxnRLBEB8F3wLD/4xRk8CNxw8joXKsxUEirI76iV mJDjm/tq90gaxZUWVtPZP95Qvocdl7brhuvLuF4J9wJVL5tr6ZYAje3omHBnjcFb n9nh3Tqk0U6omAmS4k/BrXWDA1zq8LBmbP41CnfVNGq/5asDIZsNO8s5VQzNjFjN rcqv2rEO0n+77qDBbqALQydxPmytZP+0jYXcj+EaJ4clApFhvps6Cg0taoF66E4k Eg1JLALzgk3I/ATSE3nvi3J/RWkyjSYiolPavwIDAQABAoIBAEbMi5ndwjfAlkVI hPEPNKjgpnymwB/CEL7utY04akkQeBcrsSWXBBfT0exuBDczMVhzxTMs/pe5t0xf l4vaGG18wDeMV0cukCqJMyrh21u0jVv5+DHNtQjaTz6eQSzsbQCuOkbu8SuncUEO +X8YUnDc8rbYCyBIOnVCAvAlg201uW0G5G9NEwJOu6cAKMKkogdHqv+FRX96C5hm gtbGEzpGV2vVClgMwMcX49ucluZvqLvit/yehNVd0VOtW/kuLup4R6q0abHRapDd 95rJAhPvar4mzP+UgJrGQ9hozqhizDthBjnsmGeMBUiBCkay7OXIZpvLoCpQkti1 WIWuikkCgYEA/oZqq71RT1nPuI7rlcjx3AeWe2EUQtKhQMJBiPx5eLLP6gII8+v2 pD1qlmJM2eyIK0lzuskLIulTAA5Z+ejORDbvmn/DdT0CSvdrUFrcvnrRQnt2M5M2 9VDRp6nvPE0H4kRZJrtITyLn0dv5ABf2L32i4dPCMePjKjSUygJSHrsCgYEA+61A cIqch/lrQTk8hG7Y6p0EJzSInFVaKuZoMYpLhlDQcVvSDIQbGgRAN6BKTdxeQ+tK hSxBSm2mze11aHig8GBGgdBFLaJOZRo6G+2fl+s1t1FCHfsaFhHwheZJONHMpKKd Qm/7L/V35QV9YG0lPZ01TM6d5lXuKsmUNvBJTc0CgYASYajAgGqn3WeX/5JZ/eoh ptaiUG+DJ+0HXUAYYYtwQRGs57q3yvnEAL963tyH/IIVBjf6bFyGh+07ms26s6p5 2LHTKZj3FZHd0iKI6hb5FquYLoxpyx7z9oM9pZMmerWwDJmXp3zgYjf1uvovnItm AJ/LyVxD+B5GxQdd028U0wKBgG4OllZglxDzJk7wa6FyI9N89Fr8oxzSSkrmVPwN APfskSpxP8qPXpai8z4gDz47NtG2q/DOqIKWrtHwnF4iGibjwxFzdTz+dA/MR0r9 P8QcbHIMy7/2lbK/B5JWYQDC5h28qs5pz8tqKZLyMqCfOiDWhX9f/zbBrxPw8KqR q0ylAoGAL/0kemA/Tmxpwmp0S0oCqnA4gbCgS7qnApxB09xTewc/tuvraXc3Mzea EvqDXLXK0R7O4E3vo0Mr23SodRVlFPevsmUUJLPJMJcxdfnSJgX+qE/UC8Ux+UMi eYufYRDYSslfL2rt9D7abnnbqSfsHymJKukWpElIgJTklQUru4k= -----END RSA PRIVATE KEY----- axios-axios-2d06f96/tests/unit/api.test.js000066400000000000000000000143711521272452000205340ustar00rootroot00000000000000import { describe, it } from 'vitest'; import assert from 'assert'; import axios, { create } from '../../index.js'; describe('static api', () => { it('should have request method helpers', () => { assert.strictEqual(typeof axios.request, 'function'); assert.strictEqual(typeof axios.get, 'function'); assert.strictEqual(typeof axios.head, 'function'); assert.strictEqual(typeof axios.options, 'function'); assert.strictEqual(typeof axios.delete, 'function'); assert.strictEqual(typeof axios.post, 'function'); assert.strictEqual(typeof axios.put, 'function'); assert.strictEqual(typeof axios.patch, 'function'); assert.strictEqual(typeof axios.query, 'function'); }); it('should have promise method helpers', async () => { const promise = axios.request({ url: '/test', adapter: (config) => Promise.resolve({ data: null, status: 200, statusText: 'OK', headers: {}, config, request: {}, }), }); assert.strictEqual(typeof promise.then, 'function'); assert.strictEqual(typeof promise.catch, 'function'); await promise; }); it('should have defaults', () => { assert.strictEqual(typeof axios.defaults, 'object'); assert.strictEqual(typeof axios.defaults.headers, 'object'); }); it('should have interceptors', () => { assert.strictEqual(typeof axios.interceptors.request, 'object'); assert.strictEqual(typeof axios.interceptors.response, 'object'); }); it('should have all/spread helpers', () => { assert.strictEqual(typeof axios.all, 'function'); assert.strictEqual(typeof axios.spread, 'function'); }); it('should have factory method', () => { assert.strictEqual(typeof axios.create, 'function'); }); it('should expose create as a named export', () => { assert.strictEqual(typeof create, 'function'); assert.strictEqual(create, axios.create); }); it('should have CanceledError, CancelToken, and isCancel properties', () => { assert.strictEqual(typeof axios.Cancel, 'function'); assert.strictEqual(typeof axios.CancelToken, 'function'); assert.strictEqual(typeof axios.isCancel, 'function'); }); it('should have getUri method', () => { assert.strictEqual(typeof axios.getUri, 'function'); }); it('should ignore inherited data for bodyless method helpers', async () => { Object.defineProperty(Object.prototype, 'data', { value: 'inherited-body', configurable: true, }); try { await Promise.all( ['delete', 'get', 'head', 'options'].map(async (method) => { let seenData = 'unset'; await axios[method]('/test', { adapter(config) { seenData = config.data; return Promise.resolve({ data: null, status: 200, statusText: 'OK', headers: {}, config, request: {}, }); }, }); assert.strictEqual(seenData, undefined); }) ); } finally { delete Object.prototype.data; } }); it('should ignore inherited nested serializer fields in getUri', () => { let serializeInvoked = false; Object.defineProperty(Object.prototype, 'serialize', { value() { serializeInvoked = true; return 'inherited=1'; }, configurable: true, }); try { assert.strictEqual( axios.getUri({ url: '/foo', params: { value: 'a b' }, paramsSerializer: {}, }), '/foo?value=a+b' ); assert.strictEqual(serializeInvoked, false); } finally { delete Object.prototype.serialize; } }); it('should have isAxiosError properties', () => { assert.strictEqual(typeof axios.isAxiosError, 'function'); }); it('should have mergeConfig properties', () => { assert.strictEqual(typeof axios.mergeConfig, 'function'); }); it('should have getAdapter properties', () => { assert.strictEqual(typeof axios.getAdapter, 'function'); }); it('should pass symbol keys to transformRequest', async () => { const symbolKey = Symbol('example'); let transformedData; await axios.post( '/test', { [symbolKey]: 'value', stringKey: 'value', }, { transformRequest(data) { transformedData = data; return ''; }, adapter: (config) => Promise.resolve({ data: null, status: 200, statusText: 'OK', headers: {}, config, request: {}, }), } ); assert.strictEqual(transformedData[symbolKey], 'value'); }); }); describe('instance api', () => { const instance = axios.create(); it('should have request methods', () => { assert.strictEqual(typeof instance.request, 'function'); assert.strictEqual(typeof instance.get, 'function'); assert.strictEqual(typeof instance.options, 'function'); assert.strictEqual(typeof instance.head, 'function'); assert.strictEqual(typeof instance.delete, 'function'); assert.strictEqual(typeof instance.post, 'function'); assert.strictEqual(typeof instance.put, 'function'); assert.strictEqual(typeof instance.patch, 'function'); assert.strictEqual(typeof instance.query, 'function'); }); it('should have interceptors', () => { assert.strictEqual(typeof instance.interceptors.request, 'object'); assert.strictEqual(typeof instance.interceptors.response, 'object'); }); it('should pass symbol keys to transformRequest through axios.create', async () => { const symbolKey = Symbol('example'); let transformedData; const client = axios.create({ transformRequest: [ (data) => { transformedData = data; return ''; }, ], adapter: (config) => Promise.resolve({ data: null, status: 200, statusText: 'OK', headers: {}, config, request: {}, }), }); await client.post('/test', { [symbolKey]: 'value', stringKey: 'value', }); assert.strictEqual(transformedData[symbolKey], 'value'); assert.strictEqual(transformedData.stringKey, 'value'); }); }); axios-axios-2d06f96/tests/unit/axios.test.js000066400000000000000000000032721521272452000211040ustar00rootroot00000000000000import { describe, it } from 'vitest'; import assert from 'assert'; import Axios from '../../lib/core/Axios.js'; describe('Axios', () => { describe('handle un-writable error stack', () => { const testUnwritableErrorStack = async (stackAttributes) => { const axios = new Axios({}); // Mock axios._request to return an Error with an un-writable stack property. axios._request = () => { const mockError = new Error('test-error'); Object.defineProperty(mockError, 'stack', stackAttributes); throw mockError; }; try { await axios.request('test-url', {}); } catch (e) { assert.strictEqual(e.message, 'test-error'); } }; it('should support errors with a defined but un-writable stack', async () => { await testUnwritableErrorStack({ value: {}, writable: false }); }); it('should support errors with an undefined and un-writable stack', async () => { await testUnwritableErrorStack({ value: undefined, writable: false }); }); it('should support errors with a custom getter/setter for the stack property', async () => { await testUnwritableErrorStack({ get: () => ({}), set: () => { throw new Error('read-only'); }, }); }); it('should support errors with a custom getter/setter for the stack property (null case)', async () => { await testUnwritableErrorStack({ get: () => null, set: () => { throw new Error('read-only'); }, }); }); }); it('should not throw if the config argument is omitted', () => { const axios = new Axios(); assert.deepStrictEqual(axios.defaults, {}); }); }); axios-axios-2d06f96/tests/unit/axiosHeaders.test.js000066400000000000000000000443431521272452000224040ustar00rootroot00000000000000import { describe, it } from 'vitest'; import assert from 'assert'; import AxiosHeaders from '../../lib/core/AxiosHeaders.js'; const [nodeMajorVersion] = process.versions.node.split('.').map((v) => parseInt(v, 10)); describe('AxiosHeaders', () => { it('should support headers argument', () => { const headers = new AxiosHeaders({ x: 1, y: 2, }); assert.strictEqual(headers.get('x'), '1'); assert.strictEqual(headers.get('y'), '2'); }); describe('set', () => { it('should support adding a single header', () => { const headers = new AxiosHeaders(); headers.set('foo', 'bar'); assert.strictEqual(headers.get('foo'), 'bar'); }); it('should support adding multiple headers', () => { const headers = new AxiosHeaders(); headers.set({ foo: 'value1', bar: 'value2', }); assert.strictEqual(headers.get('foo'), 'value1'); assert.strictEqual(headers.get('bar'), 'value2'); }); it('should support adding multiple headers from raw headers string', () => { const headers = new AxiosHeaders(); headers.set(`foo:value1\nbar:value2`); assert.strictEqual(headers.get('foo'), 'value1'); assert.strictEqual(headers.get('bar'), 'value2'); }); it('should not rewrite header the header if the value is false', () => { const headers = new AxiosHeaders(); headers.set('foo', 'value1'); headers.set('foo', 'value2', false); assert.strictEqual(headers.get('foo'), 'value1'); headers.set('foo', 'value2'); assert.strictEqual(headers.get('foo'), 'value2'); headers.set('foo', 'value3', true); assert.strictEqual(headers.get('foo'), 'value3'); }); it('should not rewrite the header if its value is false, unless rewrite options is set to true', () => { const headers = new AxiosHeaders(); headers.set('foo', false); headers.set('foo', 'value2'); assert.strictEqual(headers.get('foo'), false); headers.set('foo', 'value2', true); assert.strictEqual(headers.get('foo'), 'value2'); }); it('should support iterables as a key-value source object', () => { const headers = new AxiosHeaders(); headers.set(new Map([['x', '123']])); assert.strictEqual(headers.get('x'), '123'); }); it('should not merge Object.prototype values into iterable headers', () => { const descriptor = Object.getOwnPropertyDescriptor(Object.prototype, 'Authorization'); Object.prototype.Authorization = 'polluted'; try { const headers = new AxiosHeaders(new Map([['Authorization', 'real']])); assert.strictEqual(headers.get('authorization'), 'real'); } finally { descriptor ? Object.defineProperty(Object.prototype, 'Authorization', descriptor) : delete Object.prototype.Authorization; } }); it('should support objects with an own iterator as a key-value source object', () => { const headers = new AxiosHeaders(); headers.set({ *[Symbol.iterator]() { yield ['x', '123']; }, }); assert.strictEqual(headers.get('x'), '123'); }); it('should not use inherited Symbol.iterator as a key-value source object', () => { try { Object.prototype[Symbol.iterator] = function* () { yield ['x-app', 'changed']; yield ['x-injected', 'yes']; }; const headers = new AxiosHeaders({ 'x-app': 'safe', }); assert.strictEqual(headers.get('x-app'), 'safe'); assert.strictEqual(headers.get('x-injected'), undefined); } finally { delete Object.prototype[Symbol.iterator]; } }); it('should not read polluted Object.prototype Symbol.iterator accessors', () => { let accessed = false; try { Object.defineProperty(Object.prototype, Symbol.iterator, { configurable: true, get() { accessed = true; throw new Error('polluted iterator accessor'); } }); const headers = new AxiosHeaders({ 'x-app': 'safe', }); assert.strictEqual(headers.get('x-app'), 'safe'); assert.strictEqual(accessed, false); } finally { delete Object.prototype[Symbol.iterator]; } }); it('should not consume an inherited Symbol.iterator for non-plain header sources', () => { try { Object.prototype[Symbol.iterator] = function* () { yield ['x-injected', 'yes']; yield ['authorization', 'Bearer CHANGED']; }; // A class instance and an Object.create(...) object both have a direct // prototype other than Object.prototype, yet their only iterator comes // from the polluted Object.prototype — they must not be iterated. class HeaderBag { constructor() { this['authorization'] = 'Bearer VALID'; } } const fromClass = new AxiosHeaders(new HeaderBag()); assert.strictEqual(fromClass.get('x-injected'), undefined); assert.notStrictEqual(fromClass.get('authorization'), 'Bearer CHANGED'); const created = Object.create({ 'x-app': 'safe' }); created['authorization'] = 'Bearer VALID'; const fromCreate = new AxiosHeaders(created); assert.strictEqual(fromCreate.get('x-injected'), undefined); assert.notStrictEqual(fromCreate.get('authorization'), 'Bearer CHANGED'); } finally { delete Object.prototype[Symbol.iterator]; } }); const runIfNode18OrHigher = nodeMajorVersion >= 18 ? it : it.skip; runIfNode18OrHigher( 'should support setting multiple header values from an iterable source', () => { const headers = new AxiosHeaders(); const nativeHeaders = new Headers(); nativeHeaders.append('set-cookie', 'foo'); nativeHeaders.append('set-cookie', 'bar'); nativeHeaders.append('set-cookie', 'baz'); nativeHeaders.append('y', 'qux'); headers.set(nativeHeaders); assert.deepStrictEqual(headers.get('set-cookie'), ['foo', 'bar', 'baz']); assert.strictEqual(headers.get('y'), 'qux'); } ); it('should sanitize invalid characters in header value', () => { const headers = new AxiosHeaders(); headers.set('x-test', '\t safe\r\nInjected: true \u0000'); assert.strictEqual(headers.get('x-test'), 'safeInjected: true'); }); it('should sanitize invalid characters in any array header value', () => { const headers = new AxiosHeaders(); headers.set('set-cookie', ['safe=1', ' \tunsafe=1\nInjected: true\r\n ']); assert.deepStrictEqual(headers.get('set-cookie'), ['safe=1', 'unsafe=1Injected: true']); }); // Regression: https://github.com/axios/axios/issues/10849 // Non-control Unicode header values must round-trip through set/get so // request interceptors can encode them (e.g. encodeURIComponent) before // the adapter sanitizes to byte-safe values at send time. it('should preserve non-control Unicode characters in header values', () => { const headers = new AxiosHeaders(); headers.set('x-name', '请求用户'); assert.strictEqual(headers.get('x-name'), '请求用户'); }); it('should preserve non-control Unicode characters in array header values', () => { const headers = new AxiosHeaders(); headers.set('x-names', ['请求用户', 'naïve', 'プロジェクト']); assert.deepStrictEqual(headers.get('x-names'), ['请求用户', 'naïve', 'プロジェクト']); }); it('should still strip CR/LF from Unicode header values to prevent header injection', () => { const headers = new AxiosHeaders(); headers.set('x-name', '请求\r\nInjected: true用户'); assert.strictEqual(headers.get('x-name'), '请求Injected: true用户'); }); // Regression: https://github.com/axios/axios/issues/6959 it('should silently skip empty header names', () => { const headers = new AxiosHeaders(); assert.doesNotThrow(() => headers.set('', 'a')); assert.doesNotThrow(() => headers.set(' ', 'b')); assert.doesNotThrow(() => headers.set({ '': 'c', ' ': 'd', foo: 'bar' })); assert.doesNotThrow(() => headers.set( new Map([ ['', 'e'], [' ', 'f'], ['x', 'y'], ]) ) ); assert.strictEqual(headers.has(''), false); assert.strictEqual(headers.get('foo'), 'bar'); assert.strictEqual(headers.get('x'), 'y'); assert.strictEqual(Object.keys(headers).length, 2); }); }); it('should support uppercase name mapping for names overlapped by class methods', () => { const headers = new AxiosHeaders({ set: 'foo', }); headers.set('get', 'bar'); assert.strictEqual(headers.get('Set'), 'foo'); assert.strictEqual(headers.get('Get'), 'bar'); }); describe('get', () => { describe('filter', () => { it('should support RegExp', () => { const headers = new AxiosHeaders(); headers.set('foo', 'bar=value1'); assert.strictEqual(headers.get('foo', /^bar=(\w+)/)[1], 'value1'); assert.strictEqual(headers.get('foo', /^foo=/), null); }); it('should support function', () => { const headers = new AxiosHeaders(); headers.set('foo', 'bar=value1'); assert.strictEqual( headers.get('foo', (value, header) => { assert.strictEqual(value, 'bar=value1'); assert.strictEqual(header, 'foo'); return value; }), 'bar=value1' ); assert.strictEqual( headers.get('foo', () => false), false ); }); }); }); describe('has', () => { it('should return true if the header is defined, otherwise false', () => { const headers = new AxiosHeaders(); headers.set('foo', 'bar=value1'); assert.strictEqual(headers.has('foo'), true); assert.strictEqual(headers.has('bar'), false); }); describe('filter', () => { it('should support RegExp', () => { const headers = new AxiosHeaders(); headers.set('foo', 'bar=value1'); assert.strictEqual(headers.has('foo', /^bar=(\w+)/), true); assert.strictEqual(headers.has('foo', /^foo=/), false); }); it('should support function', () => { const headers = new AxiosHeaders(); headers.set('foo', 'bar=value1'); assert.strictEqual( headers.has('foo', (value, header) => { assert.strictEqual(value, 'bar=value1'); assert.strictEqual(header, 'foo'); return true; }), true ); assert.strictEqual( headers.has('foo', () => false), false ); }); it('should support string pattern', () => { const headers = new AxiosHeaders(); headers.set('foo', 'bar=value1'); assert.strictEqual(headers.has('foo', 'value1'), true); assert.strictEqual(headers.has('foo', 'value2'), false); }); }); }); describe('delete', () => { it('should delete the header', () => { const headers = new AxiosHeaders(); headers.set('foo', 'bar=value1'); assert.strictEqual(headers.has('foo'), true); headers.delete('foo'); assert.strictEqual(headers.has('foo'), false); }); it('should return true if the header has been deleted, otherwise false', () => { const headers = new AxiosHeaders(); headers.set('foo', 'bar=value1'); assert.strictEqual(headers.delete('bar'), false); assert.strictEqual(headers.delete('foo'), true); }); it('should support headers array', () => { const headers = new AxiosHeaders(); headers.set('foo', 'x'); headers.set('bar', 'y'); headers.set('baz', 'z'); assert.strictEqual(headers.delete(['foo', 'baz']), true); assert.strictEqual(headers.has('foo'), false); assert.strictEqual(headers.has('bar'), true); assert.strictEqual(headers.has('baa'), false); }); describe('filter', () => { it('should support RegExp', () => { const headers = new AxiosHeaders(); headers.set('foo', 'bar=value1'); assert.strictEqual(headers.has('foo'), true); headers.delete('foo', /baz=/); assert.strictEqual(headers.has('foo'), true); headers.delete('foo', /bar=/); assert.strictEqual(headers.has('foo'), false); }); it('should support function', () => { const headers = new AxiosHeaders(); headers.set('foo', 'bar=value1'); headers.delete('foo', (value, header) => { assert.strictEqual(value, 'bar=value1'); assert.strictEqual(header, 'foo'); return false; }); assert.strictEqual(headers.has('foo'), true); assert.strictEqual( headers.delete('foo', () => true), true ); assert.strictEqual(headers.has('foo'), false); }); it('should support string pattern', () => { const headers = new AxiosHeaders(); headers.set('foo', 'bar=value1'); assert.strictEqual(headers.has('foo'), true); headers.delete('foo', 'baz'); assert.strictEqual(headers.has('foo'), true); headers.delete('foo', 'bar'); assert.strictEqual(headers.has('foo'), false); }); }); }); describe('clear', () => { it('should clear all headers', () => { const headers = new AxiosHeaders({ x: 1, y: 2 }); headers.clear(); assert.deepStrictEqual({ ...headers.toJSON() }, {}); }); it('should clear matching headers if a matcher was specified', () => { const headers = new AxiosHeaders({ foo: 1, 'x-foo': 2, bar: 3 }); assert.deepStrictEqual({ ...headers.toJSON() }, { foo: '1', 'x-foo': '2', bar: '3' }); headers.clear(/^x-/); assert.deepStrictEqual({ ...headers.toJSON() }, { foo: '1', bar: '3' }); }); }); describe('toJSON', () => { it('should return headers object with original headers case', () => { const headers = new AxiosHeaders({ Foo: 'x', bAr: 'y', }); assert.deepStrictEqual( { ...headers.toJSON() }, { Foo: 'x', bAr: 'y', } ); }); }); describe('accessors', () => { it('should support get accessor', () => { const headers = new AxiosHeaders({ foo: 1, }); headers.constructor.accessor('foo'); assert.strictEqual(typeof headers.getFoo, 'function'); assert.strictEqual(headers.getFoo(), '1'); }); it('should support set accessor', () => { const headers = new AxiosHeaders({ foo: 1, }); headers.constructor.accessor('foo'); assert.strictEqual(typeof headers.setFoo, 'function'); headers.setFoo(2); assert.strictEqual(headers.getFoo(), '2'); }); it('should support has accessor', () => { const headers = new AxiosHeaders({ foo: 1, }); headers.constructor.accessor('foo'); assert.strictEqual(typeof headers.hasFoo, 'function'); assert.strictEqual(headers.hasFoo(), true); }); }); it('should be caseless', () => { const headers = new AxiosHeaders({ fOo: 1, }); assert.strictEqual(headers.get('Foo'), '1'); assert.strictEqual(headers.get('foo'), '1'); headers.set('foo', 2); assert.strictEqual(headers.get('foO'), '2'); assert.strictEqual(headers.get('fOo'), '2'); assert.strictEqual(headers.has('fOo'), true); headers.delete('FOO'); assert.strictEqual(headers.has('fOo'), false); }); describe('normalize()', () => { it('should support auto-formatting', () => { const headers = new AxiosHeaders({ fOo: 1, 'x-foo': 2, 'y-bar-bAz': 3, }); assert.deepStrictEqual( { ...headers.normalize(true).toJSON() }, { Foo: '1', 'X-Foo': '2', 'Y-Bar-Baz': '3', } ); }); it('should support external defined values', () => { const headers = new AxiosHeaders({ foo: '1', }); headers.Foo = 2; headers.bar = 3; assert.deepStrictEqual( { ...headers.normalize().toJSON() }, { foo: '2', bar: '3', } ); }); it('should support array values', () => { const headers = new AxiosHeaders({ foo: [1, 2, 3], }); assert.deepStrictEqual( { ...headers.normalize().toJSON() }, { foo: ['1', '2', '3'], } ); }); }); describe('AxiosHeaders.concat', () => { it('should concatenate plain headers into an AxiosHeader instance', () => { const a = { a: 1 }; const b = { b: 2 }; const c = { c: 3 }; const headers = AxiosHeaders.concat(a, b, c); assert.deepStrictEqual( { ...headers.toJSON() }, { a: '1', b: '2', c: '3', } ); }); it('should concatenate raw headers into an AxiosHeader instance', () => { const a = 'a:1\nb:2'; const b = 'c:3\nx:4'; const headers = AxiosHeaders.concat(a, b); assert.deepStrictEqual( { ...headers.toJSON() }, { a: '1', b: '2', c: '3', x: '4', } ); }); it('should concatenate Axios headers into a new AxiosHeader instance', () => { const a = new AxiosHeaders({ x: 1 }); const b = new AxiosHeaders({ y: 2 }); const headers = AxiosHeaders.concat(a, b); assert.deepStrictEqual( { ...headers.toJSON() }, { x: '1', y: '2', } ); }); }); describe('toString', () => { it('should serialize AxiosHeader instance to a raw headers string', () => { assert.deepStrictEqual(new AxiosHeaders({ x: 1, y: 2 }).toString(), 'x: 1\ny: 2'); }); }); describe('getSetCookie', () => { it('should return set-cookie', () => { const headers = new AxiosHeaders('Set-Cookie: key=val;\n' + 'Set-Cookie: key2=val2;\n'); assert.deepStrictEqual(headers.getSetCookie(), ['key=val;', 'key2=val2;']); }); it('should return empty set-cookie', () => { assert.deepStrictEqual(new AxiosHeaders().getSetCookie(), []); }); }); }); axios-axios-2d06f96/tests/unit/cancel/000077500000000000000000000000001521272452000176665ustar00rootroot00000000000000axios-axios-2d06f96/tests/unit/cancel/canceledError.test.js000066400000000000000000000014761521272452000237620ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import { isNativeError } from 'node:util/types'; import CanceledError from '../../../lib/cancel/CanceledError.js'; describe('cancel::CanceledError', () => { describe('toString', () => { it('returns the default message when message is not specified', () => { const cancel = new CanceledError(); expect(cancel.toString()).toBe('CanceledError: canceled'); }); it('returns the provided message when message is specified', () => { const cancel = new CanceledError('Operation has been canceled.'); expect(cancel.toString()).toBe('CanceledError: Operation has been canceled.'); }); }); it('is recognized as a native error by Node util/types', () => { expect(isNativeError(new CanceledError('My Canceled Error'))).toBe(true); }); }); axios-axios-2d06f96/tests/unit/cancel/isCancel.test.js000066400000000000000000000006741521272452000227320ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import isCancel from '../../../lib/cancel/isCancel.js'; import CanceledError from '../../../lib/cancel/CanceledError.js'; describe('cancel::isCancel', () => { it('returns true when value is a CanceledError', () => { expect(isCancel(new CanceledError())).toBe(true); }); it('returns false when value is not canceled', () => { expect(isCancel({ foo: 'bar' })).toBe(false); }); }); axios-axios-2d06f96/tests/unit/composeSignals.test.js000066400000000000000000000021561521272452000227470ustar00rootroot00000000000000import { describe, it } from 'vitest'; import assert from 'assert'; import composeSignals from '../../lib/helpers/composeSignals.js'; describe('helpers::composeSignals', () => { const runIfAbortController = typeof AbortController === 'function' ? it : it.skip; runIfAbortController('should abort when any of the signals abort', () => { let called; const controllerA = new AbortController(); const controllerB = new AbortController(); const signal = composeSignals([controllerA.signal, controllerB.signal]); signal.addEventListener('abort', () => { called = true; }); controllerA.abort(new Error('test')); assert.ok(called); }); runIfAbortController('should abort on timeout', async () => { const signal = composeSignals([], 100); await new Promise((resolve) => { signal.addEventListener('abort', resolve); }); assert.match(String(signal.reason), /timeout of 100ms exceeded/); }); it('should return undefined if signals and timeout are not provided', () => { const signal = composeSignals([]); assert.strictEqual(signal, undefined); }); }); axios-axios-2d06f96/tests/unit/core/000077500000000000000000000000001521272452000173715ustar00rootroot00000000000000axios-axios-2d06f96/tests/unit/core/AxiosError.test.js000066400000000000000000000311141521272452000230020ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import { isNativeError } from 'node:util/types'; import AxiosError from '../../../lib/core/AxiosError.js'; import AxiosHeaders from '../../../lib/core/AxiosHeaders.js'; describe('core::AxiosError', () => { it('creates an error with message, config, code, request, response, stack and isAxiosError', () => { const request = { path: '/foo' }; const response = { status: 200, data: { foo: 'bar' } }; const error = new AxiosError('Boom!', 'ESOMETHING', { foo: 'bar' }, request, response); expect(error).toBeInstanceOf(Error); expect(error.message).toBe('Boom!'); expect(error.config).toEqual({ foo: 'bar' }); expect(error.code).toBe('ESOMETHING'); expect(error.request).toBe(request); expect(error.response).toBe(response); expect(error.isAxiosError).toBe(true); expect(error.stack).toBeDefined(); }); it('serializes to JSON safely', () => { // request/response are intentionally omitted from the serialized shape // to avoid circular-reference problems. const request = { path: '/foo' }; const response = { status: 200, data: { foo: 'bar' } }; const error = new AxiosError('Boom!', 'ESOMETHING', { foo: 'bar' }, request, response); const json = error.toJSON(); expect(json.message).toBe('Boom!'); expect(json.config).toEqual({ foo: 'bar' }); expect(json.code).toBe('ESOMETHING'); expect(json.status).toBe(200); expect(json.request).toBeUndefined(); expect(json.response).toBeUndefined(); }); describe('AxiosError.from', () => { it('adds config, code, request and response to the wrapped error', () => { const error = new Error('Boom!'); const request = { path: '/foo' }; const response = { status: 200, data: { foo: 'bar' } }; const axiosError = AxiosError.from(error, 'ESOMETHING', { foo: 'bar' }, request, response); expect(axiosError.config).toEqual({ foo: 'bar' }); expect(axiosError.code).toBe('ESOMETHING'); expect(axiosError.request).toBe(request); expect(axiosError.response).toBe(response); expect(axiosError.isAxiosError).toBe(true); }); it('returns an AxiosError instance', () => { const axiosError = AxiosError.from(new Error('Boom!'), 'ESOMETHING', { foo: 'bar' }); expect(axiosError).toBeInstanceOf(AxiosError); }); it('preserves status from the original error when response is not provided', () => { const error = new Error('Network Error'); error.status = 404; const axiosError = AxiosError.from(error, 'ERR_NETWORK', { foo: 'bar' }); expect(axiosError.status).toBe(404); }); it('prefers response.status over error.status when response is provided', () => { const error = new Error('Error'); error.status = 500; const response = { status: 404 }; const axiosError = AxiosError.from(error, 'ERR_BAD_REQUEST', {}, null, response); expect(axiosError.status).toBe(404); }); }); it('is recognized as a native error by Node util/types', () => { expect(isNativeError(new AxiosError('My Axios Error'))).toBe(true); }); it('supports static error-code properties', () => { const error = new AxiosError('My Axios Error', AxiosError.ECONNABORTED); expect(error.code).toBe(AxiosError.ECONNABORTED); }); it('sets status when response is passed to constructor', () => { const error = new AxiosError('test', 'foo', {}, {}, { status: 400 }); expect(error.status).toBe(400); }); describe('status field behaviour (issue #5330)', () => { it('error.status equals response.status for 4xx errors', () => { // Regression test: error.status must be directly accessible without // going through error.response.status. const error = new AxiosError( 'Request failed with status code 404', AxiosError.ERR_BAD_REQUEST, {}, {}, { status: 404, statusText: 'Not Found' } ); expect(error.status).toBe(404); expect(error.status).toBe(error.response.status); }); it('error.status equals response.status for 5xx errors', () => { const error = new AxiosError( 'Request failed with status code 503', AxiosError.ERR_BAD_RESPONSE, {}, {}, { status: 503, statusText: 'Service Unavailable' } ); expect(error.status).toBe(503); }); it('error.status is undefined when no response is provided (network errors)', () => { // Network errors (ECONNREFUSED, ETIMEDOUT, etc.) have no HTTP response, // so error.status must be undefined — not 0 or null. const error = new AxiosError('Network Error', AxiosError.ERR_NETWORK, {}, {}); expect(error.status).toBeUndefined(); expect(error.response).toBeUndefined(); }); it('error.status is included in toJSON output', () => { const error = new AxiosError('test', 'ERR_BAD_REQUEST', {}, {}, { status: 401 }); expect(error.toJSON().status).toBe(401); }); }); it('keeps message enumerable for backward compatibility', () => { const error = new AxiosError('Test error message', 'ERR_TEST', { foo: 'bar' }); expect(Object.keys(error)).toContain('message'); expect(Object.entries(error).find(([key]) => key === 'message')?.[1]).toBe('Test error message'); expect({ ...error }.message).toBe('Test error message'); expect(Object.getOwnPropertyDescriptor(error, 'message')?.enumerable).toBe(true); }); // Opt-in redaction: when `config.redact` is an array of key names, every // matching key (case-insensitive, at any depth) has its value replaced with // the redaction marker in the toJSON snapshot. Undefined leaves the legacy // serialization untouched so existing consumers see no behavior change. describe('toJSON redaction via config.redact', () => { it('leaves config untouched when redact is undefined', () => { const config = { url: '/api', auth: { username: 'alice', password: 'secret' }, }; const error = new AxiosError('Boom', 'ECODE', config); const json = error.toJSON(); expect(json.config.auth.username).toBe('alice'); expect(json.config.auth.password).toBe('secret'); }); it('ignores inherited redact accessors', () => { const prototype = {}; Object.defineProperty(prototype, 'redact', { get() { throw new Error('inherited redact getter should not run'); }, }); const config = Object.create(prototype); config.auth = { username: 'alice', password: 'secret' }; const error = new AxiosError('Boom', 'ECODE', config); const json = error.toJSON(); expect(json.config.auth.username).toBe('alice'); expect(json.config.auth.password).toBe('secret'); }); it('leaves config untouched when redact is an empty array', () => { const config = { auth: { username: 'alice', password: 'secret' }, redact: [], }; const error = new AxiosError('Boom', 'ECODE', config); expect(error.toJSON().config.auth.password).toBe('secret'); }); it('replaces top-level matching keys with the redaction marker', () => { const config = { url: '/api', auth: { username: 'alice', password: 'secret' }, redact: ['auth'], }; const error = new AxiosError('Boom', 'ECODE', config); const json = error.toJSON(); expect(json.config.url).toBe('/api'); expect(json.config.auth).toBe('[REDACTED ****]'); }); it('replaces matching keys at any nesting depth', () => { const config = { auth: { username: 'alice', password: 'secret' }, proxy: { auth: { username: 'pu', password: 'pp' } }, redact: ['password'], }; const error = new AxiosError('Boom', 'ECODE', config); const json = error.toJSON(); expect(json.config.auth.username).toBe('alice'); expect(json.config.auth.password).toBe('[REDACTED ****]'); expect(json.config.proxy.auth.password).toBe('[REDACTED ****]'); expect(json.config.proxy.auth.username).toBe('pu'); }); it('matches case-insensitively', () => { const config = { headers: { Authorization: 'Bearer abc' }, redact: ['authorization'], }; const error = new AxiosError('Boom', 'ECODE', config); expect(error.toJSON().config.headers.Authorization).toBe('[REDACTED ****]'); }); it('redacts headers stored in an AxiosHeaders instance', () => { const headers = new AxiosHeaders(); headers.set('Authorization', 'Bearer abc'); headers.set('X-Trace', 'trace-id'); const config = { headers, redact: ['Authorization'] }; const error = new AxiosError('Boom', 'ECODE', config); const serialized = error.toJSON().config.headers; expect(serialized.Authorization).toBe('[REDACTED ****]'); expect(serialized['X-Trace']).toBe('trace-id'); }); it('redacts inside arrays of objects', () => { const config = { items: [{ token: 't1' }, { token: 't2', name: 'keep' }], redact: ['token'], }; const error = new AxiosError('Boom', 'ECODE', config); const json = error.toJSON(); expect(json.config.items[0].token).toBe('[REDACTED ****]'); expect(json.config.items[1].token).toBe('[REDACTED ****]'); expect(json.config.items[1].name).toBe('keep'); }); it('does not crash on circular config references', () => { const config = { auth: { password: 'secret' }, redact: ['password'] }; config.self = config; const error = new AxiosError('Boom', 'ECODE', config); const json = error.toJSON(); expect(json.config.auth.password).toBe('[REDACTED ****]'); expect(Object.prototype.hasOwnProperty.call(json.config, 'self')).toBe(false); }); it('preserves legacy toJSONObject handling for values with toJSON', () => { const issuedAt = new Date('2026-01-01T00:00:00.000Z'); const endpoint = new URL('https://example.com/users'); const config = { issuedAt, endpoint, auth: { password: 'secret' }, redact: ['password'], }; const error = new AxiosError('Boom', 'ECODE', config); const json = error.toJSON(); expect(json.config.issuedAt).toBe(issuedAt); expect(json.config.endpoint).toBe(endpoint); expect(json.config.auth.password).toBe('[REDACTED ****]'); }); it('does not let a polluted Object.prototype.toJSON bypass redaction', () => { class Credentials { constructor() { this.password = 'secret'; } } Object.prototype.toJSON = function () { return this; }; const config = { auth: { password: 'secret' }, credentials: new Credentials(), items: [{ token: 't1' }], redact: ['password', 'token'], }; const error = new AxiosError('Boom', 'ECODE', config); try { const json = error.toJSON(); expect(json.config.auth.password).toBe('[REDACTED ****]'); expect(json.config.credentials.password).toBe('[REDACTED ****]'); expect(json.config.items[0].token).toBe('[REDACTED ****]'); } finally { delete Object.prototype.toJSON; } }); it('copies __proto__ as data without changing the redaction output prototype', () => { const config = { redact: ['password'] }; Object.defineProperty(config, '__proto__', { value: { password: 'secret' }, enumerable: true, configurable: true, }); const error = new AxiosError('Boom', 'ECODE', config); const json = error.toJSON(); expect(Object.getPrototypeOf(json.config)).toBe(null); expect(Object.prototype.hasOwnProperty.call(json.config, '__proto__')).toBe(true); expect(json.config.__proto__.password).toBe('[REDACTED ****]'); }); it('does not mutate the original config or AxiosHeaders', () => { const headers = new AxiosHeaders(); headers.set('Authorization', 'Bearer abc'); const config = { auth: { username: 'alice', password: 'secret' }, headers, redact: ['password', 'Authorization'], }; const error = new AxiosError('Boom', 'ECODE', config); error.toJSON(); expect(config.auth.password).toBe('secret'); expect(headers.get('Authorization')).toBe('Bearer abc'); }); it('keeps the redact array itself visible in the snapshot', () => { const config = { auth: { password: 'secret' }, redact: ['password'], }; const error = new AxiosError('Boom', 'ECODE', config); // Useful for debugging — operators can see what was being redacted. expect(error.toJSON().config.redact).toEqual(['password']); }); }); }); axios-axios-2d06f96/tests/unit/core/buildFullPath.test.js000066400000000000000000000056301521272452000234500ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import buildFullPath from '../../../lib/core/buildFullPath.js'; import AxiosError from '../../../lib/core/AxiosError.js'; describe('core::buildFullPath', () => { it('combines URLs when the requested URL is relative', () => { expect(buildFullPath('https://api.github.com', '/users')).toBe('https://api.github.com/users'); }); it('does not combine URLs when the requested URL is absolute', () => { expect(buildFullPath('https://api.github.com', 'https://api.example.com/users')).toBe( 'https://api.example.com/users' ); }); it('combines URLs when requested URL is absolute and allowAbsoluteUrls is false', () => { expect(buildFullPath('https://api.github.com', 'https://api.example.com/users', false)).toBe( 'https://api.github.com/https://api.example.com/users' ); }); it('does not combine URLs when baseURL is missing and allowAbsoluteUrls is false', () => { expect(buildFullPath(undefined, 'https://api.example.com/users', false)).toBe( 'https://api.example.com/users' ); }); it('does not combine URLs when baseURL is not configured', () => { expect(buildFullPath(undefined, '/users')).toBe('/users'); }); it('combines URLs when baseURL and requested URL are both relative', () => { expect(buildFullPath('/api', '/users')).toBe('/api/users'); }); it('rejects HTTP URLs missing slashes after the protocol', () => { for (const call of [ () => buildFullPath(undefined, 'https:example.com/users'), () => buildFullPath(undefined, '\thttps:example.com/users'), () => buildFullPath(undefined, '\u0000https:example.com/users'), () => buildFullPath(undefined, 'h\nttp:example.com/users'), () => buildFullPath(undefined, 'ht\ttp:example.com/users'), () => buildFullPath(undefined, 'htt\rp:example.com/users'), () => buildFullPath(undefined, 'http:/example.com/users'), () => buildFullPath('http:example.com/api', '/users'), ]) { let error; try { call(); } catch (err) { error = err; } expect(error).toBeInstanceOf(AxiosError); expect(error.code).toBe(AxiosError.ERR_INVALID_URL); expect(error.message).toBe('Invalid URL: missing "//" after protocol'); } }); it('does not reject an unused malformed baseURL for absolute requests', () => { expect(buildFullPath('http:example.com/api', 'https://api.example.com/users')).toBe( 'https://api.example.com/users' ); }); it('rejects a malformed baseURL when absolute requests are forced through baseURL', () => { let error; try { buildFullPath('http:example.com/api', 'https://api.example.com/users', false); } catch (err) { error = err; } expect(error).toBeInstanceOf(AxiosError); expect(error.code).toBe(AxiosError.ERR_INVALID_URL); expect(error.message).toBe('Invalid URL: missing "//" after protocol'); }); }); axios-axios-2d06f96/tests/unit/core/dispatchRequest.test.js000066400000000000000000000155271521272452000240670ustar00rootroot00000000000000import { describe, it } from 'vitest'; import assert from 'assert'; import dispatchRequest from '../../../lib/core/dispatchRequest.js'; import AxiosError from '../../../lib/core/AxiosError.js'; import defaults from '../../../lib/defaults/index.js'; import resolveConfig from '../../../lib/helpers/resolveConfig.js'; class ReactNativeFormData { append() {} getParts() { return []; } get [Symbol.toStringTag]() { return 'FormData'; } } function baseConfig(overrides = {}) { return { method: 'get', url: '/test', headers: {}, transformRequest: defaults.transformRequest, transformResponse: defaults.transformResponse, transitional: { silentJSONParsing: false, forcedJSONParsing: true }, responseType: 'json', ...overrides, }; } describe('core::dispatchRequest', () => { describe('JSON FormData transform', () => { it('rejects deeply nested field paths before adapter dispatch', async () => { const data = new FormData(); let adapterCalled = false; data.append('foo' + '[bar]'.repeat(101), '123'); const config = baseConfig({ data, headers: { 'Content-Type': 'application/json' }, method: 'post', adapter(adapterConfig) { adapterCalled = true; return Promise.resolve({ data: null, status: 200, statusText: 'OK', headers: {}, config: adapterConfig, request: {}, }); }, }); let thrown; try { await dispatchRequest(config); } catch (e) { thrown = e; } assert.ok(thrown instanceof AxiosError, 'must be AxiosError'); assert.strictEqual(thrown.code, AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED); assert.strictEqual(adapterCalled, false); }); }); describe('JSON parse failure on adapter resolution', () => { it('rejects with AxiosError carrying response and status', async () => { const response = { data: '{bad json', status: 418, statusText: "I'm a teapot", headers: {}, config: null, request: {}, }; const config = baseConfig({ adapter: () => Promise.resolve(response) }); let thrown; try { await dispatchRequest(config); } catch (e) { thrown = e; } assert.ok(thrown instanceof AxiosError, 'must be AxiosError'); assert.strictEqual(thrown.code, AxiosError.ERR_BAD_RESPONSE); assert.strictEqual(thrown.response, response, 'error.response must be the original response'); assert.strictEqual(thrown.status, 418, 'error.status must equal response status'); }); it('cleans up config.response after the transform throws', async () => { const response = { data: '{bad json', status: 200, statusText: 'OK', headers: {}, config: null, request: {}, }; const config = baseConfig({ adapter: () => Promise.resolve(response) }); try { await dispatchRequest(config); } catch (_) { // expected } assert.strictEqual( Object.prototype.hasOwnProperty.call(config, 'response'), false, 'config.response must be deleted in finally' ); }); }); describe('JSON parse failure on adapter rejection', () => { it('rejects with AxiosError carrying response and status (rejection path)', async () => { const response = { data: '{bad json', status: 500, statusText: 'Internal Server Error', headers: {}, config: null, request: {}, }; const reason = new AxiosError('Request failed', AxiosError.ERR_BAD_RESPONSE); reason.response = response; const config = baseConfig({ adapter: () => Promise.reject(reason) }); let thrown; try { await dispatchRequest(config); } catch (e) { thrown = e; } assert.ok(thrown instanceof AxiosError, 'must be AxiosError'); assert.strictEqual(thrown.response, response, 'error.response must be the original response'); assert.strictEqual(thrown.status, 500, 'error.status must equal response status'); }); it('cleans up config.response after the rejection-path transform', async () => { const response = { data: '{bad json', status: 500, statusText: 'Internal Server Error', headers: {}, config: null, request: {}, }; const reason = new AxiosError('Request failed', AxiosError.ERR_BAD_RESPONSE); reason.response = response; const config = baseConfig({ adapter: () => Promise.reject(reason) }); try { await dispatchRequest(config); } catch (_) { // expected } assert.strictEqual( Object.prototype.hasOwnProperty.call(config, 'response'), false, 'config.response must be deleted in finally on the rejection path' ); }); }); describe('happy path', () => { it('clears default Content-Type for React Native FormData before adapter headers are sent', async () => { const data = new ReactNativeFormData(); const response = { data: '{"ok":true}', status: 200, statusText: 'OK', headers: {}, config: null, request: {}, }; const config = baseConfig({ method: 'post', data, adapter: (adapterConfig) => { assert.strictEqual( adapterConfig.headers.getContentType(), 'application/x-www-form-urlencoded', 'dispatchRequest should apply the default POST Content-Type first' ); const resolvedConfig = resolveConfig(adapterConfig); assert.strictEqual(resolvedConfig.data, data); assert.strictEqual(resolvedConfig.headers.getContentType(), undefined); assert.strictEqual( Object.prototype.hasOwnProperty.call(resolvedConfig.headers.toJSON(), 'Content-Type'), false, 'resolved adapter headers must omit Content-Type for React Native FormData' ); return Promise.resolve(response); }, }); const result = await dispatchRequest(config); assert.deepStrictEqual(result.data, { ok: true }); }); it('cleans up config.response after a successful resolution', async () => { const response = { data: '{"ok":true}', status: 200, statusText: 'OK', headers: {}, config: null, request: {}, }; const config = baseConfig({ adapter: () => Promise.resolve(response) }); const result = await dispatchRequest(config); assert.deepStrictEqual(result.data, { ok: true }); assert.strictEqual( Object.prototype.hasOwnProperty.call(config, 'response'), false, 'config.response must not be left set after a successful request' ); }); }); }); axios-axios-2d06f96/tests/unit/core/mergeConfig.test.js000066400000000000000000000320561521272452000231400ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import defaults from '../../../lib/defaults/index.js'; import mergeConfig from '../../../lib/core/mergeConfig.js'; import { AxiosHeaders } from '../../../index.js'; describe('core::mergeConfig', () => { it('accepts undefined for second argument', () => { expect(mergeConfig(defaults, undefined)).toEqual(defaults); }); it('accepts an object for second argument', () => { expect(mergeConfig(defaults, {})).toEqual(defaults); }); it('does not leave references', () => { const merged = mergeConfig(defaults, {}); expect(merged).not.toBe(defaults); expect(merged.headers).not.toBe(defaults.headers); }); it('allows setting request options', () => { const config = { url: '__sample url__', method: '__sample method__', params: '__sample params__', data: { foo: true }, }; const merged = mergeConfig(defaults, config); expect(merged.url).toBe(config.url); expect(merged.method).toBe(config.method); expect(merged.params).toBe(config.params); expect(merged.data).toEqual(config.data); }); it('does not inherit request options', () => { const localDefaults = { method: '__sample method__', data: { foo: true }, }; const merged = mergeConfig(localDefaults, {}); expect(merged.method).toBeUndefined(); expect(merged.data).toBeUndefined(); }); for (const key of ['auth', 'headers', 'params', 'proxy']) { it(`sets new config for ${key} without default`, () => { const config1 = { [key]: undefined }; const config2 = { [key]: { user: 'foo', pass: 'test' } }; const expected = { [key]: { user: 'foo', pass: 'test' } }; expect(mergeConfig(config1, config2)).toEqual(expected); }); it(`merges ${key} with defaults`, () => { const config1 = { [key]: { user: 'foo', pass: 'bar' } }; const config2 = { [key]: { pass: 'test' } }; const expected = { [key]: { user: 'foo', pass: 'test' } }; expect(mergeConfig(config1, config2)).toEqual(expected); }); it.each([false, null, 123])(`overwrites default ${key} with %p`, (value) => { const config1 = { [key]: { user: 'foo', pass: 'test' } }; const config2 = { [key]: value }; const expected = { [key]: value }; expect(mergeConfig(config1, config2)).toEqual(expected); }); } it('allows setting other options', () => { const merged = mergeConfig(defaults, { timeout: 123 }); expect(merged.timeout).toBe(123); }); it('allows setting custom options', () => { const merged = mergeConfig(defaults, { foo: 'bar' }); expect(merged.foo).toBe('bar'); }); it('allows setting custom default options', () => { const merged = mergeConfig({ foo: 'bar' }, {}); expect(merged.foo).toBe('bar'); }); it('allows merging custom objects in config', () => { const merged = mergeConfig( { nestedConfig: { propertyOnDefaultConfig: true, }, }, { nestedConfig: { propertyOnRequestConfig: true, }, } ); expect(merged.nestedConfig.propertyOnDefaultConfig).toBe(true); expect(merged.nestedConfig.propertyOnRequestConfig).toBe(true); }); describe('headers', () => { it('allows merging with AxiosHeaders instances', () => { const merged = mergeConfig( { headers: new AxiosHeaders({ x: 1, y: 2, }), }, { headers: new AxiosHeaders({ X: 1, Y: 2, }), } ); expect(merged.headers).toEqual({ x: '1', y: '2', }); }); }); describe('valueFromConfig2Keys', () => { const config1 = { url: '/foo', method: 'post', data: { a: 3 } }; it('skips if config2 does not define the key', () => { expect(mergeConfig(config1, {})).toEqual({}); }); it('clones config2 when it is a plain object', () => { const data = { a: 1, b: 2 }; const merged = mergeConfig(config1, { data }); expect(merged.data).toEqual(data); expect(merged.data).not.toBe(data); }); it('clones config2 when it is an array', () => { const data = [1, 2, 3]; const merged = mergeConfig(config1, { data }); expect(merged.data).toEqual(data); expect(merged.data).not.toBe(data); }); it('sets config2 value directly for non-mergeable values', () => { const obj = Object.create({}); expect(mergeConfig(config1, { data: 1 }).data).toBe(1); expect(mergeConfig(config1, { data: 'str' }).data).toBe('str'); expect(mergeConfig(config1, { data: obj }).data).toBe(obj); expect(mergeConfig(config1, { data: null }).data).toBe(null); }); }); describe('mergeDeepPropertiesKeys', () => { it('skips when both config1 and config2 values are undefined', () => { expect(mergeConfig({ headers: undefined }, { headers: undefined })).toEqual({}); }); it('merges when both values are plain objects', () => { expect(mergeConfig({ headers: { a: 1, b: 1 } }, { headers: { b: 2, c: 2 } })).toEqual({ headers: { a: 1, b: 2, c: 2 }, }); }); it('clones config2 when it is a plain object', () => { const config1 = { headers: [1, 2, 3] }; const config2 = { headers: { a: 1, b: 2 } }; const merged = mergeConfig(config1, config2); expect(merged.headers).toEqual(config2.headers); expect(merged.headers).not.toBe(config2.headers); }); it('clones config2 when it is an array', () => { const config1 = { headers: { a: 1, b: 1 } }; const config2 = { headers: [1, 2, 3] }; const merged = mergeConfig(config1, config2); expect(merged.headers).toEqual(config2.headers); expect(merged.headers).not.toBe(config2.headers); }); it('sets config2 value directly for non-mergeable values', () => { const config1 = { headers: { a: 1, b: 1 } }; const obj = Object.create({}); expect(mergeConfig(config1, { headers: 1 }).headers).toBe(1); expect(mergeConfig(config1, { headers: 'str' }).headers).toBe('str'); expect(mergeConfig(config1, { headers: obj }).headers).toBe(obj); expect(mergeConfig(config1, { headers: null }).headers).toBe(null); }); it('clones config1 when it is a plain object', () => { const config1 = { headers: { a: 1, b: 2 } }; const merged = mergeConfig(config1, {}); expect(merged.headers).toEqual(config1.headers); expect(merged.headers).not.toBe(config1.headers); }); it('clones config1 when it is an array', () => { const config1 = { headers: [1, 2, 3] }; const merged = mergeConfig(config1, {}); expect(merged.headers).toEqual(config1.headers); expect(merged.headers).not.toBe(config1.headers); }); it('sets config1 value directly for non-mergeable values', () => { const obj = Object.create({}); expect(mergeConfig({ headers: 1 }, {}).headers).toBe(1); expect(mergeConfig({ headers: 'str' }, {}).headers).toBe('str'); expect(mergeConfig({ headers: obj }, {}).headers).toBe(obj); expect(mergeConfig({ headers: null }, {}).headers).toBe(null); }); }); describe('defaultToConfig2Keys', () => { it('skips when both config1 and config2 values are undefined', () => { expect(mergeConfig({ transformRequest: undefined }, { transformRequest: undefined })).toEqual( {} ); }); it('clones config2 when both values are plain objects', () => { const config1 = { transformRequest: { a: 1, b: 1 } }; const config2 = { transformRequest: { b: 2, c: 2 } }; const merged = mergeConfig(config1, config2); expect(merged.transformRequest).toEqual(config2.transformRequest); expect(merged.transformRequest).not.toBe(config2.transformRequest); }); it('clones config2 when it is an array', () => { const config1 = { transformRequest: { a: 1, b: 1 } }; const config2 = { transformRequest: [1, 2, 3] }; const merged = mergeConfig(config1, config2); expect(merged.transformRequest).toEqual(config2.transformRequest); expect(merged.transformRequest).not.toBe(config2.transformRequest); }); it('sets config2 value directly for non-mergeable values', () => { const config1 = { transformRequest: { a: 1, b: 1 } }; const obj = Object.create({}); expect(mergeConfig(config1, { transformRequest: 1 }).transformRequest).toBe(1); expect(mergeConfig(config1, { transformRequest: 'str' }).transformRequest).toBe('str'); expect(mergeConfig(config1, { transformRequest: obj }).transformRequest).toBe(obj); expect(mergeConfig(config1, { transformRequest: null }).transformRequest).toBe(null); }); it('clones config1 when it is a plain object', () => { const config1 = { transformRequest: { a: 1, b: 2 } }; const merged = mergeConfig(config1, {}); expect(merged.transformRequest).toEqual(config1.transformRequest); expect(merged.transformRequest).not.toBe(config1.transformRequest); }); it('clones config1 when it is an array', () => { const config1 = { transformRequest: [1, 2, 3] }; const merged = mergeConfig(config1, {}); expect(merged.transformRequest).toEqual(config1.transformRequest); expect(merged.transformRequest).not.toBe(config1.transformRequest); }); it('sets config1 value directly for non-mergeable values', () => { const obj = Object.create({}); expect(mergeConfig({ transformRequest: 1 }, {}).transformRequest).toBe(1); expect(mergeConfig({ transformRequest: 'str' }, {}).transformRequest).toBe('str'); expect(mergeConfig({ transformRequest: obj }, {}).transformRequest).toBe(obj); expect(mergeConfig({ transformRequest: null }, {}).transformRequest).toBe(null); }); }); describe('directMergeKeys', () => { it('merges when config2 defines the key', () => { expect(mergeConfig({}, { validateStatus: undefined })).toEqual({ validateStatus: undefined }); }); it('merges when both values are plain objects', () => { expect( mergeConfig({ validateStatus: { a: 1, b: 1 } }, { validateStatus: { b: 2, c: 2 } }) ).toEqual({ validateStatus: { a: 1, b: 2, c: 2 } }); }); it('clones config2 when it is a plain object', () => { const config1 = { validateStatus: [1, 2, 3] }; const config2 = { validateStatus: { a: 1, b: 2 } }; const merged = mergeConfig(config1, config2); expect(merged.validateStatus).toEqual(config2.validateStatus); expect(merged.validateStatus).not.toBe(config2.validateStatus); }); it('clones config2 when it is an array', () => { const config1 = { validateStatus: { a: 1, b: 2 } }; const config2 = { validateStatus: [1, 2, 3] }; const merged = mergeConfig(config1, config2); expect(merged.validateStatus).toEqual(config2.validateStatus); expect(merged.validateStatus).not.toBe(config2.validateStatus); }); it('sets config2 value directly for non-mergeable values', () => { const config1 = { validateStatus: { a: 1, b: 2 } }; const obj = Object.create({}); expect(mergeConfig(config1, { validateStatus: 1 }).validateStatus).toBe(1); expect(mergeConfig(config1, { validateStatus: 'str' }).validateStatus).toBe('str'); expect(mergeConfig(config1, { validateStatus: obj }).validateStatus).toBe(obj); expect(mergeConfig(config1, { validateStatus: null }).validateStatus).toBe(null); }); it('clones config1 when it is a plain object', () => { const config1 = { validateStatus: { a: 1, b: 2 } }; const merged = mergeConfig(config1, {}); expect(merged.validateStatus).toEqual(config1.validateStatus); expect(merged.validateStatus).not.toBe(config1.validateStatus); }); it('clones config1 when it is an array', () => { const config1 = { validateStatus: [1, 2, 3] }; const merged = mergeConfig(config1, {}); expect(merged.validateStatus).toEqual(config1.validateStatus); expect(merged.validateStatus).not.toBe(config1.validateStatus); }); it('sets config1 value directly for non-mergeable values', () => { const obj = Object.create({}); expect(mergeConfig({ validateStatus: 1 }, {}).validateStatus).toBe(1); expect(mergeConfig({ validateStatus: 'str' }, {}).validateStatus).toBe('str'); expect(mergeConfig({ validateStatus: obj }, {}).validateStatus).toBe(obj); expect(mergeConfig({ validateStatus: null }, {}).validateStatus).toBe(null); }); it('keeps legacy undefined behavior by default', () => { expect(mergeConfig(defaults, { validateStatus: undefined }).validateStatus).toBeUndefined(); }); it('keeps config1 value when the transitional option is disabled (issue #6688)', () => { const validateStatus = () => false; expect( mergeConfig( { validateStatus }, { validateStatus: undefined, transitional: { validateStatusUndefinedResolves: false }, } ).validateStatus ).toBe(validateStatus); expect(mergeConfig(defaults, { validateStatus: null }).validateStatus).toBe(null); }); }); }); axios-axios-2d06f96/tests/unit/core/settle.test.js000066400000000000000000000112251521272452000222060ustar00rootroot00000000000000import { describe, it, expect, vi } from 'vitest'; import settle from '../../../lib/core/settle.js'; import AxiosError from '../../../lib/core/AxiosError.js'; /** * Builds a minimal response object that settle() expects. * @param {number} status - HTTP status code * @param {Function} [validateStatus] - optional custom validator */ function makeResponse(status, validateStatus = (s) => s >= 200 && s < 300) { return { status, config: { validateStatus }, request: {}, data: null, headers: {}, }; } describe('core::settle', () => { describe('resolves the promise', () => { it('resolves for a 200 status by default', () => { const resolve = vi.fn(); const reject = vi.fn(); settle(resolve, reject, makeResponse(200)); expect(resolve).toHaveBeenCalledTimes(1); expect(reject).not.toHaveBeenCalled(); }); it('resolves when validateStatus is not provided', () => { const resolve = vi.fn(); const reject = vi.fn(); const response = makeResponse(500); response.config.validateStatus = null; settle(resolve, reject, response); expect(resolve).toHaveBeenCalledTimes(1); }); it('resolves when status is 0 (no response, e.g. network error)', () => { const resolve = vi.fn(); const reject = vi.fn(); const response = makeResponse(0); settle(resolve, reject, response); expect(resolve).toHaveBeenCalledTimes(1); }); }); describe('error code assignment', () => { it('assigns ERR_BAD_REQUEST for a 400 status', () => { const resolve = vi.fn(); const reject = vi.fn(); settle(resolve, reject, makeResponse(400, () => false)); expect(reject).toHaveBeenCalledTimes(1); const error = reject.mock.calls[0][0]; expect(error).toBeInstanceOf(AxiosError); expect(error.code).toBe(AxiosError.ERR_BAD_REQUEST); }); it('assigns ERR_BAD_REQUEST for a 404 status', () => { const resolve = vi.fn(); const reject = vi.fn(); settle(resolve, reject, makeResponse(404, () => false)); const error = reject.mock.calls[0][0]; expect(error.code).toBe(AxiosError.ERR_BAD_REQUEST); }); it('assigns ERR_BAD_REQUEST for a 499 status (top of 4xx range)', () => { const resolve = vi.fn(); const reject = vi.fn(); settle(resolve, reject, makeResponse(499, () => false)); const error = reject.mock.calls[0][0]; expect(error.code).toBe(AxiosError.ERR_BAD_REQUEST); }); it('assigns ERR_BAD_RESPONSE for a 500 status', () => { const resolve = vi.fn(); const reject = vi.fn(); settle(resolve, reject, makeResponse(500, () => false)); const error = reject.mock.calls[0][0]; expect(error.code).toBe(AxiosError.ERR_BAD_RESPONSE); }); it('assigns ERR_BAD_RESPONSE for a 503 status', () => { const resolve = vi.fn(); const reject = vi.fn(); settle(resolve, reject, makeResponse(503, () => false)); const error = reject.mock.calls[0][0]; expect(error.code).toBe(AxiosError.ERR_BAD_RESPONSE); }); // A custom validateStatus can reject any status — including 1xx, 2xx, 3xx, // or ≥ 600 — and the resulting AxiosError must always have a defined code. it('assigns ERR_BAD_RESPONSE for a 3xx status rejected via custom validateStatus', () => { const resolve = vi.fn(); const reject = vi.fn(); settle(resolve, reject, makeResponse(301, () => false)); const error = reject.mock.calls[0][0]; expect(error.code).toBeDefined(); expect(error.code).toBe(AxiosError.ERR_BAD_RESPONSE); }); it('assigns ERR_BAD_RESPONSE for a 2xx status rejected via custom validateStatus', () => { const resolve = vi.fn(); const reject = vi.fn(); settle(resolve, reject, makeResponse(200, () => false)); const error = reject.mock.calls[0][0]; expect(error.code).toBeDefined(); expect(error.code).toBe(AxiosError.ERR_BAD_RESPONSE); }); it('assigns ERR_BAD_RESPONSE for a 6xx status rejected via custom validateStatus', () => { const resolve = vi.fn(); const reject = vi.fn(); settle(resolve, reject, makeResponse(600, () => false)); const error = reject.mock.calls[0][0]; expect(error.code).toBeDefined(); expect(error.code).toBe(AxiosError.ERR_BAD_RESPONSE); }); }); describe('error message', () => { it('includes the status code in the error message', () => { const resolve = vi.fn(); const reject = vi.fn(); settle(resolve, reject, makeResponse(404, () => false)); const error = reject.mock.calls[0][0]; expect(error.message).toBe('Request failed with status code 404'); }); }); }); axios-axios-2d06f96/tests/unit/core/transformData.test.js000066400000000000000000000021711521272452000235130ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import transformData from '../../../lib/core/transformData.js'; describe('core::transformData', () => { it('supports a single transformer', () => { const data = transformData.call({}, (value) => { value = 'foo'; return value; }); expect(data).toBe('foo'); }); it('supports an array of transformers', () => { const data = transformData.call({ data: '' }, [ (value) => value + 'f', (value) => value + 'o', (value) => value + 'o', ]); expect(data).toBe('foo'); }); it('passes headers through to transformers', () => { const headers = { 'content-type': 'foo/bar', }; const data = transformData.call( { data: '', headers, }, [(value, currentHeaders) => value + currentHeaders['content-type']] ); expect(data).toBe('foo/bar'); }); it('passes status code through to transformers', () => { const data = transformData.call( {}, [(value, _headers, status) => value + status], { data: '', status: 200 } ); expect(data).toBe('200'); }); }); axios-axios-2d06f96/tests/unit/estimateDataURLDecodedBytes.test.js000066400000000000000000000031401521272452000252220ustar00rootroot00000000000000import { describe, it } from 'vitest'; import assert from 'assert'; import estimateDataURLDecodedBytes from '../../lib/helpers/estimateDataURLDecodedBytes.js'; describe('estimateDataURLDecodedBytes', () => { it('should return 0 for non-data URLs', () => { assert.strictEqual(estimateDataURLDecodedBytes('http://example.com'), 0); }); it('should calculate length for simple non-base64 data URL', () => { const url = 'data:,Hello'; assert.strictEqual(estimateDataURLDecodedBytes(url), Buffer.byteLength('Hello', 'utf8')); }); it('should calculate decoded length for percent-encoded non-base64 data URL', () => { const url = 'data:text/plain,%E2%82%AC'; assert.strictEqual(estimateDataURLDecodedBytes(url), Buffer.byteLength('\u20ac', 'utf8')); }); it('should count percent-encoded ASCII as one decoded byte', () => { const url = 'data:text/plain,hello%20world'; assert.strictEqual(estimateDataURLDecodedBytes(url), Buffer.byteLength('hello world', 'utf8')); }); it('should calculate decoded length for base64 data URL', () => { const str = 'Hello'; const b64 = Buffer.from(str, 'utf8').toString('base64'); const url = `data:text/plain;base64,${b64}`; assert.strictEqual(estimateDataURLDecodedBytes(url), str.length); }); it('should handle base64 with = padding', () => { const url = 'data:text/plain;base64,TQ=='; assert.strictEqual(estimateDataURLDecodedBytes(url), 1); }); it('should handle base64 with %3D padding', () => { const url = 'data:text/plain;base64,TQ%3D%3D'; assert.strictEqual(estimateDataURLDecodedBytes(url), 1); }); }); axios-axios-2d06f96/tests/unit/fromDataURI.test.js000066400000000000000000000057331521272452000221020ustar00rootroot00000000000000import { describe, it } from 'vitest'; import assert from 'assert'; import fromDataURI from '../../lib/helpers/fromDataURI.js'; describe('helpers::fromDataURI', () => { it('should return buffer from data uri', () => { const buffer = Buffer.from('123'); const dataURI = 'data:application/octet-stream;base64,' + buffer.toString('base64'); assert.deepStrictEqual(fromDataURI(dataURI, false), buffer); }); it('should parse data URI with no mediatype and base64', () => { const buffer = Buffer.from('123'); const dataURI = 'data:;base64,' + buffer.toString('base64'); assert.deepStrictEqual(fromDataURI(dataURI, false), buffer); }); it('should parse data URI with mediatype and no base64', () => { const buffer = Buffer.from('123'); const dataURI = 'data:application/octet-stream,123'; assert.deepStrictEqual(fromDataURI(dataURI, false), buffer); }); it('should parse full form data URI with text/plain and base64', () => { const buffer = Buffer.from('hello'); const dataURI = 'data:text/plain;base64,' + buffer.toString('base64'); assert.deepStrictEqual(fromDataURI(dataURI, false), buffer); }); it('should parse minimal valid data URI', () => { const buffer = Buffer.from(''); const dataURI = 'data:,'; assert.deepStrictEqual(fromDataURI(dataURI, false), buffer); }); it('should parse data URI with spaces in data', () => { const buffer = Buffer.from('hello world'); const dataURI = 'data:text/plain,hello world'; assert.deepStrictEqual(fromDataURI(dataURI, false), buffer); }); it('should parse canonical RFC example with charset parameter', () => { const buffer = Buffer.from('123'); const dataURI = 'data:text/plain;charset=US-ASCII,123'; assert.deepStrictEqual(fromDataURI(dataURI, false), buffer); }); it('should decode URL-encoded body', () => { const buffer = Buffer.from('hello world'); const dataURI = 'data:text/plain,hello%20world'; assert.deepStrictEqual(fromDataURI(dataURI, false), buffer); }); it('should preserve full content type with parameters in Blob', () => { const dataURI = 'data:text/plain;charset=utf-8;base64,' + Buffer.from('hello').toString('base64'); const blob = fromDataURI(dataURI, true, { Blob }); assert.strictEqual(blob.type, 'text/plain;charset=utf-8'); }); it('should normalize omitted mediatype to text/plain per RFC 2397', () => { const dataURI = 'data:;charset=UTF-8,hello'; const blob = fromDataURI(dataURI, true, { Blob }); assert.strictEqual(blob.type, 'text/plain;charset=utf-8'); }); it('should reject data URI with unsupported protocol prefix', () => { assert.throws(() => { fromDataURI('datax:,hi', false); }, (err) => err.code === 'ERR_NOT_SUPPORT' && err.message.includes('Unsupported protocol')); }); it('should reject data URI without comma separator', () => { assert.throws(() => { fromDataURI('data:hi', false); }, (err) => err.code === 'ERR_INVALID_URL'); }); }); axios-axios-2d06f96/tests/unit/helpers/000077500000000000000000000000001521272452000201035ustar00rootroot00000000000000axios-axios-2d06f96/tests/unit/helpers/Http2Sessions.test.js000066400000000000000000000135071521272452000241550ustar00rootroot00000000000000import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { EventEmitter } from 'events'; import http2 from 'http2'; import Http2Sessions from '../../../lib/helpers/Http2Sessions.js'; function createFakeSession() { const session = new EventEmitter(); session.destroyed = false; session.closed = false; session.close = vi.fn(() => { session.closed = true; session.emit('close'); }); const originalRequest = vi.fn(() => { const stream = new EventEmitter(); stream.endStream = vi.fn(); return stream; }); session.request = originalRequest; session._originalRequest = originalRequest; return session; } describe('helpers::Http2Sessions', () => { let connectSpy; let pool; beforeEach(() => { connectSpy = vi.spyOn(http2, 'connect').mockImplementation(() => createFakeSession()); pool = new Http2Sessions(); }); afterEach(() => { connectSpy.mockRestore(); vi.useRealTimers(); }); it('reuses a cached session for the same authority and options', () => { const a = pool.getSession('https://example.test', { sessionTimeout: 1000 }); const b = pool.getSession('https://example.test', { sessionTimeout: 1000 }); expect(a).toBe(b); expect(connectSpy).toHaveBeenCalledTimes(1); }); it('creates a separate session for a different authority', () => { pool.getSession('https://example.test'); pool.getSession('https://other.test'); expect(connectSpy).toHaveBeenCalledTimes(2); }); it('creates a new session when options differ for the same authority', () => { pool.getSession('https://example.test', { sessionTimeout: 1000 }); pool.getSession('https://example.test', { sessionTimeout: 5000 }); expect(connectSpy).toHaveBeenCalledTimes(2); }); it('does not reuse a destroyed session', () => { const first = pool.getSession('https://example.test'); first.destroyed = true; const second = pool.getSession('https://example.test'); expect(second).not.toBe(first); expect(connectSpy).toHaveBeenCalledTimes(2); }); it('does not reuse a closed session', () => { const first = pool.getSession('https://example.test'); first.closed = true; const second = pool.getSession('https://example.test'); expect(second).not.toBe(first); expect(connectSpy).toHaveBeenCalledTimes(2); }); it('drops a session from the pool when its close event fires', () => { const first = pool.getSession('https://example.test'); first.emit('close'); const second = pool.getSession('https://example.test'); expect(second).not.toBe(first); expect(connectSpy).toHaveBeenCalledTimes(2); }); it('keeps unrelated authorities cached when one session closes', () => { const first = pool.getSession('https://example.test'); const other = pool.getSession('https://other.test'); first.emit('close'); const otherAgain = pool.getSession('https://other.test'); expect(otherAgain).toBe(other); expect(connectSpy).toHaveBeenCalledTimes(2); }); it('closes and removes the session after sessionTimeout once the last stream ends', () => { vi.useFakeTimers(); const session = pool.getSession('https://example.test', { sessionTimeout: 1000 }); const stream = session.request(); stream.emit('close'); expect(session.closed).toBe(false); vi.advanceTimersByTime(1000); expect(session.close).toHaveBeenCalledTimes(1); const next = pool.getSession('https://example.test', { sessionTimeout: 1000 }); expect(next).not.toBe(session); expect(connectSpy).toHaveBeenCalledTimes(2); }); it('cancels the pending sessionTimeout when a new stream opens', () => { vi.useFakeTimers(); const session = pool.getSession('https://example.test', { sessionTimeout: 1000 }); const first = session.request(); first.emit('close'); session.request(); vi.advanceTimersByTime(5000); expect(session.close).not.toHaveBeenCalled(); }); it('keeps the session alive while streams are still open', () => { vi.useFakeTimers(); const session = pool.getSession('https://example.test', { sessionTimeout: 1000 }); const a = session.request(); const b = session.request(); a.emit('close'); vi.advanceTimersByTime(5000); expect(session.close).not.toHaveBeenCalled(); b.emit('close'); vi.advanceTimersByTime(1000); expect(session.close).toHaveBeenCalledTimes(1); }); it('defaults sessionTimeout to 1000ms when no options are passed', () => { vi.useFakeTimers(); const session = pool.getSession('https://example.test'); const stream = session.request(); stream.emit('close'); vi.advanceTimersByTime(999); expect(session.close).not.toHaveBeenCalled(); vi.advanceTimersByTime(1); expect(session.close).toHaveBeenCalledTimes(1); }); it('installs a request wrapper when sessionTimeout is set', () => { const session = pool.getSession('https://example.test', { sessionTimeout: 1000 }); expect(session.request).not.toBe(session._originalRequest); }); it('does not install the request wrapper when sessionTimeout is null', () => { const session = pool.getSession('https://example.test', { sessionTimeout: null }); expect(session.request).toBe(session._originalRequest); }); it('cancels the pending idle timer when the session itself closes', () => { vi.useFakeTimers(); const clearTimeoutSpy = vi.spyOn(globalThis, 'clearTimeout'); const session = pool.getSession('https://example.test', { sessionTimeout: 1000 }); const stream = session.request(); stream.emit('close'); // An idle-removal timer is now pending. clearTimeoutSpy.mockClear(); session.emit('close'); // Closing the session must cancel the pending idle timer; otherwise it // keeps Node's event loop refed for up to sessionTimeout ms past close. expect(clearTimeoutSpy).toHaveBeenCalled(); }); }); axios-axios-2d06f96/tests/unit/helpers/bind.test.js000066400000000000000000000005001521272452000223260ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import bind from '../../../lib/helpers/bind.js'; describe('bind', () => { it('should bind an object to a function', () => { const o = { val: 123 }; const f = bind(function (num) { return this.val * num; }, o); expect(f(2)).toEqual(246); }); }); axios-axios-2d06f96/tests/unit/helpers/buildURL.test.js000066400000000000000000000112201521272452000230750ustar00rootroot00000000000000import { describe, it, expect, vi } from 'vitest'; import buildURL, { encode } from '../../../lib/helpers/buildURL.js'; describe('helpers::buildURL', () => { it('should support null params', () => { expect(buildURL('/foo')).toEqual('/foo'); }); it('should support params', () => { expect( buildURL('/foo', { foo: 'bar', isUndefined: undefined, isNull: null, }) ).toEqual('/foo?foo=bar'); }); it('should support sending raw params to custom serializer func', () => { const serializer = vi.fn().mockReturnValue('foo=bar'); const params = { foo: 'bar' }; const options = { serialize: serializer, }; expect( buildURL( '/foo', { foo: 'bar', }, options ) ).toEqual('/foo?foo=bar'); expect(serializer).toHaveBeenCalledTimes(1); expect(serializer).toHaveBeenCalledWith(params, options); }); it('should support object params', () => { expect( buildURL('/foo', { foo: { bar: 'baz', }, }) ).toEqual('/foo?foo%5Bbar%5D=baz'); }); it('should support date params', () => { const date = new Date(); expect( buildURL('/foo', { date, }) ).toEqual('/foo?date=' + date.toISOString()); }); it('should support array params with encode', () => { expect( buildURL('/foo', { foo: ['bar', 'baz'], }) ).toEqual('/foo?foo%5B%5D=bar&foo%5B%5D=baz'); }); it('should support special char params', () => { expect( buildURL('/foo', { foo: ':$, ', }) ).toEqual('/foo?foo=:$,+'); }); it('should support existing params', () => { expect( buildURL('/foo?foo=bar', { bar: 'baz', }) ).toEqual('/foo?foo=bar&bar=baz'); }); it('should support "length" parameter', () => { expect( buildURL('/foo', { query: 'bar', start: 0, length: 5, }) ).toEqual('/foo?query=bar&start=0&length=5'); }); it('should correct discard url hash mark', () => { expect( buildURL('/foo?foo=bar#hash', { query: 'baz', }) ).toEqual('/foo?foo=bar&query=baz'); }); it('should support URLSearchParams', () => { expect(buildURL('/foo', new URLSearchParams('bar=baz'))).toEqual('/foo?bar=baz'); }); it('should support custom serialize function', () => { const params = { x: 1, }; const options = { serialize: (thisParams, thisOptions) => { expect(thisParams).toEqual(params); expect(thisOptions).toEqual(options); return 'rendered'; }, }; expect(buildURL('/foo', params, options)).toEqual('/foo?rendered'); const customSerializer = (thisParams) => { expect(thisParams).toEqual(params); return 'rendered'; }; expect(buildURL('/foo', params, customSerializer)).toEqual('/foo?rendered'); }); it('should ignore inherited serializer options', () => { let serializeInvoked = false; let encodeInvoked = false; Object.defineProperty(Object.prototype, 'serialize', { value() { serializeInvoked = true; return 'inherited=1'; }, configurable: true, }); Object.defineProperty(Object.prototype, 'encode', { value() { encodeInvoked = true; return 'inherited'; }, configurable: true, }); try { expect(buildURL('/foo', { value: 'a b' }, {})).toEqual('/foo?value=a+b'); expect(serializeInvoked).toBe(false); expect(encodeInvoked).toBe(false); } finally { delete Object.prototype.serialize; delete Object.prototype.encode; } }); }); describe('helpers::encode', () => { it('should be exported as a named export', () => { expect(typeof encode).toBe('function'); }); it('should leave plain ASCII unchanged', () => { expect(encode('foo')).toEqual('foo'); }); it('should preserve `:` rather than percent-encoding it', () => { expect(encode(':')).toEqual(':'); }); it('should preserve `$` rather than percent-encoding it', () => { expect(encode('$')).toEqual('$'); }); it('should preserve `,` rather than percent-encoding it', () => { expect(encode(',')).toEqual(','); }); it('should encode space as `+` (form-style) rather than `%20`', () => { expect(encode(' ')).toEqual('+'); }); it('should still percent-encode characters outside the preserved set', () => { expect(encode('a/b')).toEqual('a%2Fb'); expect(encode('a&b')).toEqual('a%26b'); expect(encode('a=b')).toEqual('a%3Db'); }); it('should apply all substitutions together', () => { expect(encode('a:b$c,d e')).toEqual('a:b$c,d+e'); }); }); axios-axios-2d06f96/tests/unit/helpers/combineURLs.test.js000066400000000000000000000016571521272452000236120ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import combineURLs from '../../../lib/helpers/combineURLs.js'; describe('helpers::combineURLs', () => { it('should combine URLs', () => { expect(combineURLs('https://api.github.com', '/users')).toBe('https://api.github.com/users'); }); it('should remove duplicate slashes', () => { expect(combineURLs('https://api.github.com/', '/users')).toBe('https://api.github.com/users'); }); it('should insert missing slash', () => { expect(combineURLs('https://api.github.com', 'users')).toBe('https://api.github.com/users'); }); it('should not insert slash when relative url missing/empty', () => { expect(combineURLs('https://api.github.com/users', '')).toBe('https://api.github.com/users'); }); it('should allow a single slash for relative url', () => { expect(combineURLs('https://api.github.com/users', '/')).toBe('https://api.github.com/users/'); }); }); axios-axios-2d06f96/tests/unit/helpers/formDataToJSON.test.js000066400000000000000000000102241521272452000241500ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import formDataToJSON from '../../../lib/helpers/formDataToJSON.js'; import AxiosError from '../../../lib/core/AxiosError.js'; describe('formDataToJSON', () => { it('should convert a FormData Object to JSON Object', () => { const formData = new FormData(); formData.append('foo[bar][baz]', '123'); expect(formDataToJSON(formData)).toEqual({ foo: { bar: { baz: '123', }, }, }); }); it('should convert repeatable values as an array', () => { const formData = new FormData(); formData.append('foo', '1'); formData.append('foo', '2'); expect(formDataToJSON(formData)).toEqual({ foo: ['1', '2'], }); }); it('should keep repeatable values flat for 3+ entries', () => { const formData = new FormData(); formData.append('select3', '301'); formData.append('select3', '302'); formData.append('select3', '303'); expect(formDataToJSON(formData)).toEqual({ select3: ['301', '302', '303'], }); }); it('should keep nested repeatable values flat for 3+ entries', () => { const formData = new FormData(); formData.append('foo[bar]', '1'); formData.append('foo[bar]', '2'); formData.append('foo[bar]', '3'); expect(formDataToJSON(formData)).toEqual({ foo: { bar: ['1', '2', '3'], }, }); }); it('should convert props with empty brackets to arrays', () => { const formData = new FormData(); formData.append('foo[]', '1'); formData.append('foo[]', '2'); expect(formDataToJSON(formData)).toEqual({ foo: ['1', '2'], }); }); it('should supported indexed arrays', () => { const formData = new FormData(); formData.append('foo[0]', '1'); formData.append('foo[1]', '2'); expect(formDataToJSON(formData)).toEqual({ foo: ['1', '2'], }); }); it('should resist prototype pollution CVE', () => { const formData = new FormData(); formData.append('foo[0]', '1'); formData.append('foo[1]', '2'); formData.append('__proto__.x', 'hack'); formData.append('constructor.prototype.y', 'value'); expect(formDataToJSON(formData)).toEqual({ foo: ['1', '2'], constructor: { prototype: { y: 'value', }, }, }); expect({}.x).toEqual(undefined); expect({}.y).toEqual(undefined); }); it('should not write through to inherited objects on Object.prototype', () => { Object.defineProperty(Object.prototype, 'injected', { value: { hijack: true }, configurable: true, writable: true, }); try { const formData = new FormData(); formData.append('injected.hijack', 'STOLEN'); const result = formDataToJSON(formData); expect(result.injected).toEqual({ hijack: 'STOLEN' }); expect(Object.prototype.injected.hijack).toBe(true); } finally { delete Object.prototype.injected; } }); it('should throw AxiosError when a field path exceeds the default depth limit', () => { const formData = new FormData(); formData.append('foo' + '[bar]'.repeat(101), '123'); try { formDataToJSON(formData); throw new Error('Should have thrown'); } catch (err) { expect(err).toBeInstanceOf(AxiosError); expect(err.code).toBe(AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED); expect(err).not.toBeInstanceOf(RangeError); } }); it('should throw AxiosError while tokenizing very deep field paths', () => { const formData = new FormData(); formData.append('foo' + '[bar]'.repeat(10000), '123'); try { formDataToJSON(formData); throw new Error('Should have thrown'); } catch (err) { expect(err).toBeInstanceOf(AxiosError); expect(err.code).toBe(AxiosError.ERR_FORM_DATA_DEPTH_EXCEEDED); expect(err).not.toBeInstanceOf(RangeError); } }); it('should convert a field path at the default depth limit', () => { const formData = new FormData(); formData.append('foo' + '[bar]'.repeat(100), '123'); let value = formDataToJSON(formData).foo; for (let i = 0; i < 100; i++) { value = value.bar; } expect(value).toBe('123'); }); }); axios-axios-2d06f96/tests/unit/helpers/formDataToStream.test.js000066400000000000000000000073601521272452000246410ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import formDataToStream from '../../../lib/helpers/formDataToStream.js'; class SpecFormData { constructor() { this._entries = []; this[Symbol.toStringTag] = 'FormData'; } append(name, value) { this._entries.push([name, value]); } entries() { return this._entries[Symbol.iterator](); } [Symbol.iterator]() { return this._entries[Symbol.iterator](); } } const makeBlobLike = ({ type, name, size, payload }) => ({ type, name, size: size ?? payload.byteLength, [Symbol.asyncIterator]: async function* () { yield payload; }, }); const collect = async (stream) => { const chunks = []; for await (const chunk of stream) { chunks.push(Buffer.from(chunk)); } return Buffer.concat(chunks).toString('utf8'); }; describe('formDataToStream', () => { it('should strip CRLF sequences from blob.type to prevent multipart header injection', async () => { const fd = new SpecFormData(); fd.append( 'photo', makeBlobLike({ type: 'image/jpeg\r\nX-Injected-Header: PWNED\r\nX-Evil: bad', name: 'photo.jpg', payload: Buffer.from('PAYLOAD'), }) ); const body = await collect(formDataToStream(fd, () => {})); expect(body).not.toContain('\r\nX-Injected-Header'); expect(body).not.toContain('\r\nX-Evil'); expect(body).toContain('Content-Type: image/jpegX-Injected-Header: PWNEDX-Evil: bad\r\n'); }); it('should strip bare \\r and bare \\n from blob.type', async () => { const fd = new SpecFormData(); fd.append( 'f', makeBlobLike({ type: 'text/plain\rX-A: 1\nX-B: 2', name: 'f.txt', payload: Buffer.from('x'), }) ); const body = await collect(formDataToStream(fd, () => {})); expect(body).not.toMatch(/^X-A:/m); expect(body).not.toMatch(/^X-B:/m); }); it('should preserve legitimate Content-Type values', async () => { const fd = new SpecFormData(); fd.append( 'doc', makeBlobLike({ type: 'application/json; charset=utf-8', name: 'doc.json', payload: Buffer.from('{}'), }) ); const body = await collect(formDataToStream(fd, () => {})); expect(body).toContain('Content-Type: application/json; charset=utf-8\r\n'); }); it('should default missing blob.type to application/octet-stream', async () => { const fd = new SpecFormData(); fd.append( 'bin', makeBlobLike({ type: '', name: 'bin', payload: Buffer.from([0x00, 0x01]), }) ); const body = await collect(formDataToStream(fd, () => {})); expect(body).toContain('Content-Type: application/octet-stream\r\n'); }); it('should escape CRLF and quotes in blob.name (Content-Disposition)', async () => { const fd = new SpecFormData(); fd.append( 'up', makeBlobLike({ type: 'text/plain', name: 'evil\r\nX-Bad: 1".jpg', payload: Buffer.from('x'), }) ); const body = await collect(formDataToStream(fd, () => {})); expect(body).not.toContain('\r\nX-Bad: 1'); expect(body).toContain('filename="evil%0D%0AX-Bad: 1%22.jpg"'); }); it('should report stable contentLength that matches emitted bytes', async () => { const fd = new SpecFormData(); fd.append( 'photo', makeBlobLike({ type: 'image/jpeg\r\nX-Injected: PWNED', name: 'photo.jpg', payload: Buffer.from('PAYLOAD'), }) ); let reportedLength; const stream = formDataToStream( fd, (h) => { reportedLength = h['Content-Length']; }, { boundary: 'test-boundary-abc' } ); const body = await collect(stream); expect(Buffer.byteLength(body, 'utf8')).toBe(reportedLength); }); }); axios-axios-2d06f96/tests/unit/helpers/isAbsoluteURL.test.js000066400000000000000000000016461521272452000241230ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import isAbsoluteURL from '../../../lib/helpers/isAbsoluteURL.js'; describe('helpers::isAbsoluteURL', () => { it('should return true if URL begins with valid scheme name', () => { expect(isAbsoluteURL('https://api.github.com/users')).toBe(true); expect(isAbsoluteURL('custom-scheme-v1.0://example.com/')).toBe(true); expect(isAbsoluteURL('HTTP://example.com/')).toBe(true); }); it('should return false if URL begins with invalid scheme name', () => { expect(isAbsoluteURL('123://example.com/')).toBe(false); expect(isAbsoluteURL('!valid://example.com/')).toBe(false); }); it('should return true if URL is protocol-relative', () => { expect(isAbsoluteURL('//example.com/')).toBe(true); }); it('should return false if URL is relative', () => { expect(isAbsoluteURL('/foo')).toBe(false); expect(isAbsoluteURL('foo')).toBe(false); }); }); axios-axios-2d06f96/tests/unit/helpers/isAxiosError.test.js000066400000000000000000000014651521272452000240560ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import AxiosError from '../../../lib/core/AxiosError.js'; import isAxiosError from '../../../lib/helpers/isAxiosError.js'; describe('helpers::isAxiosError', () => { it('should return true if the error is created by core::createError', () => { expect(isAxiosError(new AxiosError('Boom!', null, { foo: 'bar' }))).toBe(true); }); it('should return true if the error is enhanced by core::enhanceError', () => { expect(isAxiosError(AxiosError.from(new Error('Boom!'), null, { foo: 'bar' }))).toBe(true); }); it('should return false if the error is a normal Error instance', () => { expect(isAxiosError(new Error('Boom!'))).toBe(false); }); it('should return false if the error is null', () => { expect(isAxiosError(null)).toBe(false); }); }); axios-axios-2d06f96/tests/unit/helpers/parseHeaders.test.js000066400000000000000000000025701521272452000240310ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import parseHeaders from '../../../lib/helpers/parseHeaders.js'; describe('helpers::parseHeaders', () => { it('should parse headers', () => { const date = new Date(); const parsed = parseHeaders( 'Date: ' + date.toISOString() + '\n' + 'Content-Type: application/json\n' + 'Connection: keep-alive\n' + 'Transfer-Encoding: chunked' ); expect(parsed.date).toEqual(date.toISOString()); expect(parsed['content-type']).toEqual('application/json'); expect(parsed.connection).toEqual('keep-alive'); expect(parsed['transfer-encoding']).toEqual('chunked'); }); it('should use array for set-cookie', () => { const parsedZero = parseHeaders(''); const parsedSingle = parseHeaders('Set-Cookie: key=val;'); const parsedMulti = parseHeaders('Set-Cookie: key=val;\n' + 'Set-Cookie: key2=val2;\n'); expect(parsedZero['set-cookie']).toBeUndefined(); expect(parsedSingle['set-cookie']).toEqual(['key=val;']); expect(parsedMulti['set-cookie']).toEqual(['key=val;', 'key2=val2;']); }); it('should handle duplicates', () => { const parsed = parseHeaders( 'Age: age-a\n' + 'Age: age-b\n' + 'Foo: foo-a\n' + 'Foo: foo-b\n' ); expect(parsed.age).toEqual('age-a'); expect(parsed.foo).toEqual('foo-a, foo-b'); }); }); axios-axios-2d06f96/tests/unit/helpers/progressEventReducer.test.js000066400000000000000000000032251521272452000256010ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import { progressEventReducer } from '../../../lib/helpers/progressEventReducer.js'; describe('helpers::progressEventReducer', () => { it('should clamp loaded/progress and avoid negative bytes for out-of-order events', () => { const events = []; const [onProgress, flush] = progressEventReducer((data) => { events.push(data); }, false, Number.POSITIVE_INFINITY); onProgress({ lengthComputable: true, loaded: 80, total: 100 }); onProgress({ lengthComputable: true, loaded: 60, total: 100 }); onProgress({ lengthComputable: true, loaded: 180, total: 100 }); flush(); expect(events.length).toBe(3); expect(events[0].bytes).toBe(80); expect(events[1].bytes).toBe(0); const last = events[events.length - 1]; expect(last.loaded).toBe(100); expect(last.total).toBe(100); expect(last.progress).toBe(1); expect(last.upload).toBe(true); expect(last.bytes).toBe(20); }); it('should ignore malformed events that lack a numeric loaded value', () => { const events = []; const [onProgress, flush] = progressEventReducer((data) => { events.push(data); }, false, Number.POSITIVE_INFINITY); onProgress(undefined); onProgress(null); onProgress({}); onProgress({ loaded: null, total: 100, lengthComputable: true }); onProgress({ loaded: 'abc', total: 100, lengthComputable: true }); flush(); expect(events.length).toBe(0); onProgress({ lengthComputable: true, loaded: 50, total: 100 }); flush(); expect(events.length).toBe(1); expect(events[0].loaded).toBe(50); expect(events[0].bytes).toBe(50); }); }); axios-axios-2d06f96/tests/unit/helpers/resolveConfig.test.js000066400000000000000000000044171521272452000242320ustar00rootroot00000000000000import { describe, it } from 'vitest'; import assert from 'assert'; import resolveConfig from '../../../lib/helpers/resolveConfig.js'; class ReactNativeFormData { append() {} getParts() { return []; } get [Symbol.toStringTag]() { return 'FormData'; } } describe('helpers::resolveConfig', () => { it('clears Content-Type for React Native FormData', () => { const data = new ReactNativeFormData(); const config = resolveConfig({ url: '/upload', data, headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, }); assert.strictEqual(config.data, data); assert.strictEqual(config.headers.getContentType(), undefined); assert.strictEqual( Object.prototype.hasOwnProperty.call(config.headers.toJSON(), 'Content-Type'), false ); }); it('should ignore inherited nested auth fields', () => { Object.defineProperty(Object.prototype, 'username', { value: 'inherited-user', configurable: true, }); Object.defineProperty(Object.prototype, 'password', { value: 'inherited-pass', configurable: true, }); try { const config = resolveConfig({ url: '/foo', auth: {}, }); assert.strictEqual(config.headers.get('Authorization'), 'Basic Og=='); } finally { delete Object.prototype.username; delete Object.prototype.password; } }); it('should ignore inherited nested serializer fields', () => { let serializeInvoked = false; let encodeInvoked = false; Object.defineProperty(Object.prototype, 'serialize', { value() { serializeInvoked = true; return 'inherited=1'; }, configurable: true, }); Object.defineProperty(Object.prototype, 'encode', { value() { encodeInvoked = true; return 'inherited'; }, configurable: true, }); try { const config = resolveConfig({ url: '/foo', params: { value: 'a b' }, paramsSerializer: {}, }); assert.strictEqual(config.url, '/foo?value=a+b'); assert.strictEqual(serializeInvoked, false); assert.strictEqual(encodeInvoked, false); } finally { delete Object.prototype.serialize; delete Object.prototype.encode; } }); }); axios-axios-2d06f96/tests/unit/helpers/shouldBypassProxy.test.js000066400000000000000000000261661521272452000251540ustar00rootroot00000000000000import { afterEach, describe, expect, it } from 'vitest'; import shouldBypassProxy from '../../../lib/helpers/shouldBypassProxy.js'; const originalNoProxy = process.env.no_proxy; const originalNOProxy = process.env.NO_PROXY; const setNoProxy = (value) => { process.env.no_proxy = value; process.env.NO_PROXY = value; }; afterEach(() => { if (originalNoProxy === undefined) { delete process.env.no_proxy; } else { process.env.no_proxy = originalNoProxy; } if (originalNOProxy === undefined) { delete process.env.NO_PROXY; } else { process.env.NO_PROXY = originalNOProxy; } }); describe('helpers::shouldBypassProxy', () => { it('should bypass proxy for localhost with a trailing dot', () => { setNoProxy('localhost,127.0.0.1,::1'); expect(shouldBypassProxy('http://localhost.:8080/')).toBe(true); }); it('should bypass proxy for bracketed ipv6 loopback', () => { setNoProxy('localhost,127.0.0.1,::1'); expect(shouldBypassProxy('http://[::1]:8080/')).toBe(true); }); it('should support bracketed ipv6 entries in no_proxy', () => { setNoProxy('[::1]'); expect(shouldBypassProxy('http://[::1]:8080/')).toBe(true); }); it('should bypass proxy for 127.0.0.1 when no_proxy contains localhost', () => { setNoProxy('localhost'); expect(shouldBypassProxy('http://127.0.0.1:7777/')).toBe(true); }); it('should bypass proxy for [::1] when no_proxy contains localhost', () => { setNoProxy('localhost'); expect(shouldBypassProxy('http://[::1]:7777/')).toBe(true); }); it('should bypass proxy for localhost when no_proxy contains 127.0.0.1', () => { setNoProxy('127.0.0.1'); expect(shouldBypassProxy('http://localhost:7777/')).toBe(true); }); it('should bypass proxy for localhost when no_proxy contains ::1', () => { setNoProxy('::1'); expect(shouldBypassProxy('http://localhost:7777/')).toBe(true); }); it('should bypass proxy for 0.0.0.0 when no_proxy contains a local entry', () => { for (const entry of ['localhost', '127.0.0.1', '::1']) { setNoProxy(entry); expect(shouldBypassProxy('http://0.0.0.0:7777/')).toBe(true); } }); it('should respect explicit ports for 0.0.0.0 local matching', () => { setNoProxy('localhost:8080'); expect(shouldBypassProxy('http://0.0.0.0:8080/')).toBe(true); expect(shouldBypassProxy('http://0.0.0.0:9090/')).toBe(false); }); it('should bypass proxy for the IPv6 unspecified address symmetrically with 0.0.0.0', () => { for (const entry of ['localhost', '127.0.0.1', '::1']) { setNoProxy(entry); expect(shouldBypassProxy('http://[::]:7777/')).toBe(true); expect(shouldBypassProxy('http://[0:0:0:0:0:0:0:0]:7777/')).toBe(true); } }); it('should bypass proxy for compressed IPv6 unspecified request forms', () => { setNoProxy('localhost,127.0.0.1,::1'); for (const host of ['0::', '::0', '0:0::', '::0:0', '0::0']) { expect(shouldBypassProxy(`http://[${host}]:7777/`)).toBe(true); } }); it('should bypass proxy for compressed IPv6 unspecified no_proxy entries', () => { for (const entry of ['0::', '::0', '0:0::', '::0:0', '0::0']) { setNoProxy(entry); expect(shouldBypassProxy('http://[::]:7777/')).toBe(true); expect(shouldBypassProxy('http://[0:0:0:0:0:0:0:0]:7777/')).toBe(true); } }); it('should respect explicit ports on compressed IPv6 unspecified no_proxy entries', () => { setNoProxy('[0::]:8080'); expect(shouldBypassProxy('http://[::]:8080/')).toBe(true); expect(shouldBypassProxy('http://[::]:9090/')).toBe(false); }); it('should not treat nonzero compressed IPv6 addresses as unspecified', () => { setNoProxy('0::2'); expect(shouldBypassProxy('http://[::]:7777/')).toBe(false); }); it('should still route a real public IPv6 host through the proxy', () => { setNoProxy('localhost'); expect(shouldBypassProxy('http://[2001:db8::1]:7777/')).toBe(false); }); it('should match wildcard and explicit ports', () => { setNoProxy('*.example.com,localhost:8080'); expect(shouldBypassProxy('http://api.example.com/')).toBe(true); expect(shouldBypassProxy('http://localhost:8080/')).toBe(true); expect(shouldBypassProxy('http://localhost:8081/')).toBe(false); }); it('should bypass proxy for any host when no_proxy is *', () => { setNoProxy('*'); expect(shouldBypassProxy('http://example.com/')).toBe(true); expect(shouldBypassProxy('http://localhost:1234/')).toBe(true); expect(shouldBypassProxy('http://[::1]:8080/')).toBe(true); }); it('should support bracketed ipv6 with explicit port in no_proxy', () => { setNoProxy('[::1]:8080'); expect(shouldBypassProxy('http://[::1]:8080/')).toBe(true); expect(shouldBypassProxy('http://[::1]:8081/')).toBe(false); }); it('should not bypass when no_proxy is empty', () => { setNoProxy(''); expect(shouldBypassProxy('http://localhost:8080/')).toBe(false); }); it('should not bypass for malformed URLs', () => { setNoProxy('localhost,127.0.0.1,::1'); expect(shouldBypassProxy('not a url')).toBe(false); }); it('should bypass proxy for 127.0.0.0/8 subnet when no_proxy contains 127.0.0.1', () => { setNoProxy('localhost,127.0.0.1,::1'); expect(shouldBypassProxy('http://127.0.0.2:9191/secret')).toBe(true); expect(shouldBypassProxy('http://127.0.0.100:9191/secret')).toBe(true); expect(shouldBypassProxy('http://127.1.2.3:9191/secret')).toBe(true); expect(shouldBypassProxy('http://127.255.255.254:9191/secret')).toBe(true); }); it('should bypass proxy for 127.0.0.0/8 subnet when no_proxy contains localhost', () => { setNoProxy('localhost'); expect(shouldBypassProxy('http://127.0.0.2:7777/')).toBe(true); expect(shouldBypassProxy('http://127.1.2.3:7777/')).toBe(true); }); it('should NOT bypass for non-loopback IPv4 addresses', () => { setNoProxy('localhost,127.0.0.1,::1'); expect(shouldBypassProxy('http://128.0.0.1:9191/')).toBe(false); expect(shouldBypassProxy('http://126.255.255.255:9191/')).toBe(false); expect(shouldBypassProxy('http://10.0.0.1:9191/')).toBe(false); expect(shouldBypassProxy('http://192.168.1.1:9191/')).toBe(false); }); it('should NOT treat malformed 127-prefixed values as loopback', () => { setNoProxy('localhost,127.0.0.1,::1'); // bracketed IPv6 that happens to contain 127 dotted-form must not match IPv4 loopback expect(shouldBypassProxy('http://example.com/')).toBe(false); }); it('should bypass proxy for full-form IPv6 loopback 0:0:0:0:0:0:0:1', () => { setNoProxy('localhost,127.0.0.1,::1'); expect(shouldBypassProxy('http://[0:0:0:0:0:0:0:1]:8080/')).toBe(true); }); it('should bypass proxy for IPv4-mapped IPv6 loopback ::ffff:127.0.0.1', () => { setNoProxy('localhost,127.0.0.1,::1'); expect(shouldBypassProxy('http://[::ffff:127.0.0.1]:8080/')).toBe(true); }); it('should treat 127.x.x.x as cross-equivalent to localhost and ::1', () => { setNoProxy('::1'); expect(shouldBypassProxy('http://127.0.0.5:7777/')).toBe(true); }); it('should still respect explicit port mismatch on no_proxy entries', () => { setNoProxy('127.0.0.1:8080'); // same-port → bypass via cross-loopback equivalence expect(shouldBypassProxy('http://127.0.0.2:8080/')).toBe(true); // different port → no bypass expect(shouldBypassProxy('http://127.0.0.2:9090/')).toBe(false); }); it('should not bypass for hosts that merely contain 127 in other octets', () => { setNoProxy('localhost,127.0.0.1,::1'); expect(shouldBypassProxy('http://10.0.0.127:8080/')).toBe(false); expect(shouldBypassProxy('http://200.127.0.1:8080/')).toBe(false); }); // IPv4-mapped IPv6 normalization: an attacker (or naive caller) can use the // IPv4-mapped IPv6 representation of an address (e.g. ::ffff:192.168.1.5) // to dodge a NO_PROXY policy expressed in IPv4 form, or vice-versa. After // canonicalising both sides, equivalent addresses compare equal. describe('IPv4-mapped IPv6 normalization', () => { it('should bypass via IPv4-mapped IPv6 request when NO_PROXY uses the IPv4 form', () => { setNoProxy('192.168.1.5'); expect(shouldBypassProxy('http://[::ffff:192.168.1.5]/')).toBe(true); }); it('should bypass via Node-normalised IPv4-mapped hex request against an IPv4 NO_PROXY', () => { // Node's URL parser canonicalises [::ffff:192.168.1.5] → [::ffff:c0a8:105]. // The hex form must unmap to 192.168.1.5 to match the entry. setNoProxy('192.168.1.5'); expect(shouldBypassProxy('http://[::ffff:c0a8:105]/')).toBe(true); }); it('should bypass via plain IPv4 request when NO_PROXY uses the IPv4-mapped IPv6 dotted form', () => { setNoProxy('::ffff:192.168.1.5'); expect(shouldBypassProxy('http://192.168.1.5/')).toBe(true); }); it('should bypass via plain IPv4 request when NO_PROXY uses the IPv4-mapped IPv6 hex form', () => { setNoProxy('::ffff:a00:1'); expect(shouldBypassProxy('http://10.0.0.1/')).toBe(true); }); it('should bypass via plain IPv4 request when NO_PROXY uses a bracketed IPv4-mapped IPv6 entry', () => { setNoProxy('[::ffff:192.168.1.5]'); expect(shouldBypassProxy('http://192.168.1.5/')).toBe(true); }); it('should treat the uncompressed 0:0:0:0:0:ffff: form as equivalent', () => { setNoProxy('0:0:0:0:0:ffff:10.0.0.1'); expect(shouldBypassProxy('http://10.0.0.1/')).toBe(true); expect(shouldBypassProxy('http://[::ffff:10.0.0.1]/')).toBe(true); }); it('should treat compressed zero-prefix IPv4-mapped IPv6 dotted forms as equivalent', () => { for (const entry of [ '0::ffff:192.168.1.5', '0:0::ffff:192.168.1.5', '0:0:0::ffff:192.168.1.5', '0:0:0:0::ffff:192.168.1.5', ]) { setNoProxy(entry); expect(shouldBypassProxy('http://192.168.1.5/')).toBe(true); } }); it('should treat compressed zero-prefix IPv4-mapped IPv6 hex forms as equivalent', () => { for (const entry of [ '0::ffff:c0a8:105', '0:0::ffff:c0a8:105', '0:0:0::ffff:c0a8:105', '0:0:0:0::ffff:c0a8:105', ]) { setNoProxy(entry); expect(shouldBypassProxy('http://192.168.1.5/')).toBe(true); } }); it('should support compressed bracketed IPv4-mapped IPv6 entries with explicit ports', () => { setNoProxy('[0:0::ffff:192.168.1.5]:8080'); expect(shouldBypassProxy('http://192.168.1.5:8080/')).toBe(true); expect(shouldBypassProxy('http://192.168.1.5:9090/')).toBe(false); }); it('should NOT cross-match unrelated addresses', () => { setNoProxy('192.168.1.5'); // Different IPv4 address inside an IPv4-mapped form must not bypass. expect(shouldBypassProxy('http://[::ffff:192.168.1.6]/')).toBe(false); // Non-mapped IPv6 must not be treated as IPv4. expect(shouldBypassProxy('http://[2001:db8::1]/')).toBe(false); }); it('should leave non-mapped IPv6 addresses comparing as IPv6', () => { setNoProxy('2001:db8::1'); expect(shouldBypassProxy('http://[2001:db8::1]/')).toBe(true); expect(shouldBypassProxy('http://[2001:db8::2]/')).toBe(false); }); }); }); axios-axios-2d06f96/tests/unit/helpers/spread.test.js000066400000000000000000000007231521272452000226770ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import spread from '../../../lib/helpers/spread.js'; describe('helpers::spread', () => { it('should spread array to arguments', () => { let value = 0; spread((a, b) => { value = a * b; })([5, 10]); expect(value).toEqual(50); }); it('should return callback result', () => { const value = spread((a, b) => { return a * b; })([5, 10]); expect(value).toEqual(50); }); }); axios-axios-2d06f96/tests/unit/helpers/validator.test.js000066400000000000000000000031001521272452000233760ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import AxiosError from '../../../lib/core/AxiosError.js'; import validator from '../../../lib/helpers/validator.js'; describe('validator::assertOptions', () => { it('should throw only if unknown an option was passed', () => { let error; try { validator.assertOptions( { x: true, }, { y: validator.validators.boolean, } ); } catch (err) { error = err; } expect(error).toBeInstanceOf(AxiosError); expect(error.message).toBe('Unknown option x'); expect(error.code).toBe(AxiosError.ERR_BAD_OPTION); expect(() => { validator.assertOptions( { x: true, }, { x: validator.validators.boolean, y: validator.validators.boolean, } ); }).not.toThrow(new Error('Unknown option x')); }); it("should throw TypeError only if option type doesn't match", () => { let error; try { validator.assertOptions( { x: 123, }, { x: validator.validators.boolean, } ); } catch (err) { error = err; } expect(error).toBeInstanceOf(AxiosError); expect(error.message).toBe('option x must be a boolean'); expect(error.code).toBe(AxiosError.ERR_BAD_OPTION_VALUE); expect(() => { validator.assertOptions( { x: true, }, { x: validator.validators.boolean, y: validator.validators.boolean, } ); }).not.toThrow(); }); }); axios-axios-2d06f96/tests/unit/parseProtocol.test.js000066400000000000000000000021301521272452000226050ustar00rootroot00000000000000import { describe, it } from 'vitest'; import assert from 'assert'; import utils from '../../lib/utils.js'; import parseProtocol from '../../lib/helpers/parseProtocol.js'; describe('helpers::parseProtocol', () => { it('should parse protocol part if it exists', () => { utils.forEach( { 'http://username:password@example.com/': 'http', 'ftp:google.com': 'ftp', 'sms:+15105550101?body=hello%20there': 'sms', 'tel:0123456789': 'tel', '//google.com': '', 'google.com': '', 'admin://etc/default/grub': 'admin', 'stratum+tcp://server:port': 'stratum+tcp', '/api/resource:customVerb': '', 'https://stackoverflow.com/questions/': 'https', 'mailto:jsmith@example.com': 'mailto', 'chrome-extension://1234/.html': 'chrome-extension', }, (expectedProtocol, url) => { assert.strictEqual(parseProtocol(url), expectedProtocol); } ); }); it('should not match URLs without a colon separator', () => { assert.strictEqual(parseProtocol('http//example.com'), ''); }); }); axios-axios-2d06f96/tests/unit/platform.test.js000066400000000000000000000013151521272452000216010ustar00rootroot00000000000000import { describe, it } from 'vitest'; import platform from '../../lib/platform/index.js'; import assert from 'assert'; describe('generateString', () => { it('should generate a string of the specified length using the default alphabet', () => { const size = 10; const str = platform.generateString(size); assert.strictEqual(str.length, size); }); it('should generate a string using only characters from the default alphabet', () => { const size = 10; const alphabet = platform.ALPHABET.ALPHA_DIGIT; const str = platform.generateString(size, alphabet); for (let char of str) { assert.ok(alphabet.includes(char), `Character ${char} is not in the alphabet`); } }); }); axios-axios-2d06f96/tests/unit/prototypePollution.test.js000066400000000000000000001305731521272452000237410ustar00rootroot00000000000000/* eslint-disable no-prototype-builtins */ import { afterEach, describe, it } from 'vitest'; import assert from 'assert'; import http from 'http'; import utils from '../../lib/utils.js'; import mergeConfig from '../../lib/core/mergeConfig.js'; import defaults from '../../lib/defaults/index.js'; import AxiosError from '../../lib/core/AxiosError.js'; import AxiosHeaders from '../../lib/core/AxiosHeaders.js'; import resolveConfig from '../../lib/helpers/resolveConfig.js'; import axios from '../../index.js'; describe('Prototype Pollution Protection', () => { afterEach(() => { // Clean up any pollution that might have occurred. delete Object.prototype.polluted; delete Object.prototype.parseReviver; delete Object.prototype.transport; delete Object.prototype.transformRequest; delete Object.prototype.transformResponse; delete Object.prototype.formSerializer; delete Object.prototype.httpVersion; delete Object.prototype.lookup; delete Object.prototype.family; delete Object.prototype.http2Options; delete Object.prototype.validateStatus; delete Object.prototype.auth; delete Object.prototype.baseURL; delete Object.prototype.socketPath; delete Object.prototype.beforeRedirect; delete Object.prototype.sensitiveHeaders; delete Object.prototype.insecureHTTPParser; delete Object.prototype.adapter; delete Object.prototype.httpAgent; delete Object.prototype.httpsAgent; delete Object.prototype.proxy; delete Object.prototype.maxContentLength; delete Object.prototype.maxBodyLength; delete Object.prototype.maxRedirects; delete Object.prototype.maxRate; delete Object.prototype.timeout; delete Object.prototype.transitional; delete Object.prototype.timeoutErrorMessage; delete Object.prototype.env; delete Object.prototype.cancelToken; delete Object.prototype.signal; delete Object.prototype.decompress; delete Object.prototype.params; delete Object.prototype.paramsSerializer; delete Object.prototype.method; delete Object.prototype.withCredentials; delete Object.prototype.responseType; delete Object.prototype.fetchOptions; delete Object.prototype.username; delete Object.prototype.password; delete Object.prototype.hostname; delete Object.prototype.host; delete Object.prototype.port; delete Object.prototype.protocol; delete Object.prototype.get; delete Object.prototype.set; delete Object.prototype.headers; delete Object.prototype.customNested; }); describe('utils.merge', () => { it('should filter __proto__ key at top level', () => { const result = utils.merge({}, { __proto__: { polluted: 'yes' }, safe: 'value' }); assert.strictEqual(Object.prototype.polluted, undefined); assert.strictEqual(result.safe, 'value'); assert.strictEqual(result.hasOwnProperty('__proto__'), false); }); it('should filter constructor key at top level', () => { const result = utils.merge({}, { constructor: { polluted: 'yes' }, safe: 'value' }); assert.strictEqual(result.safe, 'value'); assert.strictEqual(result.hasOwnProperty('constructor'), false); }); it('should filter prototype key at top level', () => { const result = utils.merge({}, { prototype: { polluted: 'yes' }, safe: 'value' }); assert.strictEqual(result.safe, 'value'); assert.strictEqual(result.hasOwnProperty('prototype'), false); }); it('should filter __proto__ key in nested objects', () => { const result = utils.merge( {}, { headers: { __proto__: { polluted: 'nested' }, 'Content-Type': 'application/json', }, } ); assert.strictEqual(Object.prototype.polluted, undefined); assert.strictEqual(result.headers['Content-Type'], 'application/json'); assert.strictEqual(result.headers.hasOwnProperty('__proto__'), false); }); it('should filter constructor key in nested objects', () => { const result = utils.merge( {}, { headers: { constructor: { prototype: { polluted: 'nested' } }, 'Content-Type': 'application/json', }, } ); assert.strictEqual(Object.prototype.polluted, undefined); assert.strictEqual(result.headers['Content-Type'], 'application/json'); assert.strictEqual(result.headers.hasOwnProperty('constructor'), false); }); it('should filter prototype key in nested objects', () => { const result = utils.merge( {}, { headers: { prototype: { polluted: 'nested' }, 'Content-Type': 'application/json', }, } ); assert.strictEqual(result.headers['Content-Type'], 'application/json'); assert.strictEqual(result.headers.hasOwnProperty('prototype'), false); }); it('should filter dangerous keys in deeply nested objects', () => { const result = utils.merge( {}, { level1: { level2: { __proto__: { polluted: 'deep' }, prototype: { polluted: 'deep' }, safe: 'value', }, }, } ); assert.strictEqual(Object.prototype.polluted, undefined); assert.strictEqual(result.level1.level2.safe, 'value'); assert.strictEqual(result.level1.level2.hasOwnProperty('__proto__'), false); }); it('should still merge regular properties correctly', () => { const result = utils.merge({ a: 1, b: { c: 2 } }, { b: { d: 3 }, e: 4 }); assert.strictEqual(result.a, 1); assert.strictEqual(result.b.c, 2); assert.strictEqual(result.b.d, 3); assert.strictEqual(result.e, 4); }); it('should handle JSON.parse payloads safely', () => { const malicious = JSON.parse('{"__proto__": {"polluted": "yes"}}'); const result = utils.merge({}, malicious); assert.strictEqual(Object.prototype.polluted, undefined); assert.strictEqual(result.hasOwnProperty('__proto__'), false); }); it('should handle nested JSON.parse payloads safely', () => { const malicious = JSON.parse( '{"headers": {"constructor": {"prototype": {"polluted": "yes"}}}}' ); const result = utils.merge({}, malicious); assert.strictEqual(Object.prototype.polluted, undefined); assert.strictEqual(result.headers.hasOwnProperty('constructor'), false); }); }); describe('mergeConfig', () => { it('should filter dangerous keys at top level', () => { const result = mergeConfig( {}, { __proto__: { polluted: 'yes' }, constructor: { polluted: 'yes' }, prototype: { polluted: 'yes' }, url: '/api/test', } ); assert.strictEqual(Object.prototype.polluted, undefined); assert.strictEqual(result.url, '/api/test'); assert.strictEqual(result.hasOwnProperty('__proto__'), false); assert.strictEqual(result.hasOwnProperty('constructor'), false); assert.strictEqual(result.hasOwnProperty('prototype'), false); }); it('should filter dangerous keys in headers', () => { const result = mergeConfig( {}, { headers: { __proto__: { polluted: 'yes' }, 'Content-Type': 'application/json', }, } ); assert.strictEqual(Object.prototype.polluted, undefined); assert.strictEqual(result.headers['Content-Type'], 'application/json'); assert.strictEqual(result.headers.hasOwnProperty('__proto__'), false); }); it('should filter dangerous keys in custom config properties', () => { const result = mergeConfig( {}, { customProp: { __proto__: { polluted: 'yes' }, safe: 'value', }, } ); assert.strictEqual(Object.prototype.polluted, undefined); assert.strictEqual(result.customProp.safe, 'value'); assert.strictEqual(result.customProp.hasOwnProperty('__proto__'), false); }); it('should still merge configs correctly', () => { const config1 = { baseURL: 'https://api.example.com', timeout: 1000, headers: { common: { Accept: 'application/json', }, }, }; const config2 = { url: '/users', timeout: 5000, headers: { common: { 'Content-Type': 'application/json', }, }, }; const result = mergeConfig(config1, config2); assert.strictEqual(result.baseURL, 'https://api.example.com'); assert.strictEqual(result.url, '/users'); assert.strictEqual(result.timeout, 5000); assert.strictEqual(result.headers.common.Accept, 'application/json'); assert.strictEqual(result.headers.common['Content-Type'], 'application/json'); }); // Polluted transformRequest/Response must not // replace the safe defaults through inherited reads during merge. it('should not inherit polluted transformRequest from Object.prototype', () => { const polluted = () => 'attacker'; Object.prototype.transformRequest = polluted; const result = mergeConfig({ transformRequest: [(d) => d] }, { url: '/x' }); assert.notStrictEqual(result.transformRequest, polluted); assert.ok(Array.isArray(result.transformRequest)); }); it('should not inherit polluted transformResponse from Object.prototype', () => { const polluted = () => 'attacker'; Object.prototype.transformResponse = polluted; const result = mergeConfig({ transformResponse: [(d) => d] }, { url: '/x' }); assert.notStrictEqual(result.transformResponse, polluted); assert.ok(Array.isArray(result.transformResponse)); }); }); // parseReviver read via prototype chain. describe('defaults.transformResponse parseReviver', () => { it('should ignore Object.prototype.parseReviver when parsing JSON', () => { let reviverCalled = false; Object.prototype.parseReviver = function polluted(k, v) { reviverCalled = true; if (k === 'role') return 'admin'; return v; }; const ctx = { transitional: defaults.transitional }; const result = defaults.transformResponse[0].call(ctx, '{"role":"user","balance":100}'); assert.strictEqual(reviverCalled, false); assert.strictEqual(result.role, 'user'); assert.strictEqual(result.balance, 100); }); it('should ignore Object.prototype.responseType', () => { Object.prototype.responseType = 'json'; const ctx = { transitional: defaults.transitional }; // Non-JSON string body must be returned as-is; polluted responseType must // not force strict JSON parsing. const result = defaults.transformResponse[0].call(ctx, 'plain text'); assert.strictEqual(result, 'plain text'); delete Object.prototype.responseType; }); }); // mergeDirectKeys must not inherit validateStatus from // Object.prototype (was using the `in` operator which traverses the chain). describe('validateStatus merge', () => { it('should not inherit a polluted validateStatus during mergeConfig', () => { Object.prototype.validateStatus = () => true; const merged = mergeConfig(defaults, { url: '/x' }); assert.strictEqual(merged.validateStatus, defaults.validateStatus); }); it('should keep 4xx/5xx responses rejected when Object.prototype.validateStatus is polluted', async () => { Object.prototype.validateStatus = () => true; const server = http.createServer((req, res) => { res.writeHead(401, { 'Content-Type': 'application/json' }); res.end('{"error":"unauthorized"}'); }); await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve)); const { port } = server.address(); try { let threw = false; try { await axios.get(`http://127.0.0.1:${port}/`); } catch (err) { threw = true; assert.strictEqual(err.response.status, 401); } assert.strictEqual(threw, true); } finally { await new Promise((resolve) => server.close(resolve)); } }, 10000); }); // end-to-end check that a polluted parseReviver does not // tamper with JSON response bodies through the full axios.get pipeline. describe('parseReviver end-to-end', () => { it('should not let Object.prototype.parseReviver tamper with JSON responses', async () => { let reviverCalled = false; const stolen = {}; Object.prototype.parseReviver = function polluted(key, value) { reviverCalled = true; if (key && typeof value !== 'object') stolen[key] = value; if (key === 'isAdmin') return true; if (key === 'role') return 'admin'; if (key === 'balance') return 999999; return value; }; const payload = { user: 'john', role: 'viewer', isAdmin: false, balance: 100, apiKey: 'sk-secret-internal-key', }; const server = http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(payload)); }); await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve)); const { port } = server.address(); try { const res = await axios.get(`http://127.0.0.1:${port}/`); assert.strictEqual(reviverCalled, false); assert.deepStrictEqual(res.data, payload); assert.deepStrictEqual(stolen, {}); } finally { await new Promise((resolve) => server.close(resolve)); } }, 10000); }); // http adapter must not read config.transport // (or related keys) from Object.prototype. describe('http adapter prototype reads', () => { it('should not invoke Object.prototype.transport on a request', async () => { let hijackCalled = false; Object.prototype.transport = { request(options, handleResponse) { hijackCalled = true; return http.request(options, handleResponse); }, }; const server = http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end('{"ok":true}'); }); await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve)); const { port } = server.address(); try { const res = await axios.get(`http://127.0.0.1:${port}/`); assert.strictEqual(res.data.ok, true); assert.strictEqual(hijackCalled, false); } finally { await new Promise((resolve) => server.close(resolve)); } }, 10000); }); // Five config properties were read via direct property // access in the http adapter and resolveConfig, bypassing hasOwnProperty and // allowing prototype pollution gadgets (auth, baseURL, socketPath, // beforeRedirect, insecureHTTPParser). describe('http adapter gadgets', () => { function startServer(handler) { return new Promise((resolve) => { const server = http.createServer( handler || ((req, res) => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ headers: req.headers, url: req.url })); }) ); server.listen(0, '127.0.0.1', () => resolve(server)); }); } function stopServer(server) { return new Promise((resolve) => server.close(resolve)); } it('should not pick up Object.prototype.auth as an Authorization header', async () => { Object.prototype.auth = { username: 'attacker', password: 'exfil' }; const server = await startServer(); const { port } = server.address(); try { const res = await axios.get(`http://127.0.0.1:${port}/api`); assert.strictEqual(res.data.headers.authorization, undefined); } finally { await stopServer(server); } }, 10000); it('should not pick up Object.prototype.socketPath and redirect the request', async () => { Object.prototype.socketPath = '/tmp/axios-should-never-be-used.sock'; const server = await startServer(); const { port } = server.address(); try { const res = await axios.get(`http://127.0.0.1:${port}/api`); assert.strictEqual(res.status, 200); assert.strictEqual(res.data.url, '/api'); } finally { await stopServer(server); } }, 10000); it('should not invoke Object.prototype.beforeRedirect during redirects', async () => { let hijackCalled = false; Object.prototype.beforeRedirect = function polluted() { hijackCalled = true; }; const target = await startServer(); const { port: targetPort } = target.address(); const redirector = await startServer((req, res) => { res.writeHead(302, { Location: `http://127.0.0.1:${targetPort}/final` }); res.end(); }); const { port: redirectorPort } = redirector.address(); try { const res = await axios.get(`http://127.0.0.1:${redirectorPort}/start`); assert.strictEqual(res.status, 200); assert.strictEqual(hijackCalled, false); } finally { await stopServer(redirector); await stopServer(target); } }, 10000); it('should not pick up Object.prototype.sensitiveHeaders during redirects', async () => { Object.prototype.sensitiveHeaders = ['X-Secret']; let capturedHeaders; const target = await startServer((req, res) => { capturedHeaders = req.headers; res.writeHead(200, { 'Content-Type': 'application/json' }); res.end('{"ok":true}'); }); const { port: targetPort } = target.address(); const redirector = await startServer((req, res) => { res.writeHead(302, { Location: `http://127.0.0.1:${targetPort}/final` }); res.end(); }); const { port: redirectorPort } = redirector.address(); try { await axios.get(`http://127.0.0.1:${redirectorPort}/start`, { headers: { 'X-Secret': 'keep' }, }); assert.strictEqual(capturedHeaders['x-secret'], 'keep'); } finally { await stopServer(redirector); await stopServer(target); } }, 10000); it('should not enable insecureHTTPParser via Object.prototype', async () => { // A raw TCP server emits a response that uses LF-only line terminators // instead of CRLF. Node's strict HTTP parser rejects this payload with // HPE_CR_EXPECTED; the insecure parser accepts it. Verified: with an // explicit `insecureHTTPParser: true` on the request config, this // payload is parsed successfully — so if Object.prototype.insecureHTTPParser // were picked up, the request would succeed. The request must fail when // the gadget is properly blocked. Object.prototype.insecureHTTPParser = true; const net = await import('net'); const malformedPayload = 'HTTP/1.1 200 OK\n' + 'Content-Type: application/json\n' + 'Content-Length: 2\n' + '\n' + '{}'; const malformed = await new Promise((resolve) => { const srv = net.createServer((socket) => { socket.once('data', () => socket.end(malformedPayload)); }); srv.listen(0, '127.0.0.1', () => resolve(srv)); }); const { port } = malformed.address(); try { let threw = false; let caughtCode = ''; try { await axios.get(`http://127.0.0.1:${port}/`, { transitional: { clarifyTimeoutError: false }, }); } catch (err) { threw = true; caughtCode = String(err && (err.code || err.message)); } assert.strictEqual( threw, true, `request should be rejected by the strict HTTP parser (got: ${caughtCode || 'success'})` ); // The exact llhttp code for LF-only line terminators varies across // Node versions (historically HPE_LF_EXPECTED, more recently // HPE_CR_EXPECTED). Match any parser error to remain stable across // Node releases while still confirming the strict parser rejected // the payload. assert.match(caughtCode, /^HPE_/, `expected an HPE_* parser error, got: ${caughtCode}`); } finally { await new Promise((resolve) => malformed.close(resolve)); } }, 10000); it('should not inject Proxy-Authorization from polluted Object.prototype.auth', async () => { // setProxy reads `proxy.auth` directly. When `proxy` is a // URL instance from the environment proxy or a plain object without an own `auth`, // a polluted Object.prototype.auth would otherwise be base64-encoded into the // Proxy-Authorization header, leaking attacker-controlled credentials. Object.prototype.auth = { username: 'attacker', password: 'exfil' }; const proxy = await startServer(); const { port: proxyPort } = proxy.address(); const target = await startServer(); const { port: targetPort } = target.address(); try { const res = await axios.get(`http://127.0.0.1:${targetPort}/api`, { proxy: { host: '127.0.0.1', port: proxyPort, protocol: 'http' }, }); assert.strictEqual(res.status, 200); assert.strictEqual( res.data.headers['proxy-authorization'], undefined, 'polluted Object.prototype.auth must not produce a Proxy-Authorization header' ); } finally { await stopServer(target); await stopServer(proxy); } }, 10000); it('should not inject Proxy-Authorization from polluted Object.prototype.username', async () => { // The setProxy username/password branch builds basic creds from `proxy.username` // and `proxy.password`. For a plain object proxy, both reads must be guarded // against prototype pollution. Object.prototype.username = 'attacker'; Object.prototype.password = 'exfil'; const proxy = await startServer(); const { port: proxyPort } = proxy.address(); const target = await startServer(); const { port: targetPort } = target.address(); try { const res = await axios.get(`http://127.0.0.1:${targetPort}/api`, { proxy: { host: '127.0.0.1', port: proxyPort, protocol: 'http' }, }); assert.strictEqual(res.status, 200); assert.strictEqual( res.data.headers['proxy-authorization'], undefined, 'polluted Object.prototype.username must not produce a Proxy-Authorization header' ); } finally { await stopServer(target); await stopServer(proxy); } }, 10000); }); describe('resolveConfig baseURL gadget', () => { // The baseURL branch in buildFullPath only runs when the requested URL is // relative (or allowAbsoluteUrls === false). An absolute URL would skip // baseURL regardless of pollution and would not exercise the gadget. We // therefore issue a relative GET and assert that either: // - the request fails (no host to resolve) because baseURL is correctly // absent from the merged config, OR // - the request is fulfilled without hitting the hijacker. // Critically, hijackHit must always be false. it('should not hijack relative-URL requests via Object.prototype.baseURL', async () => { let hijackHit = false; const hijacker = http.createServer((req, res) => { hijackHit = true; res.writeHead(200, { 'Content-Type': 'application/json' }); res.end('{"hijacked":true}'); }); await new Promise((resolve) => hijacker.listen(0, '127.0.0.1', resolve)); const { port: hijackerPort } = hijacker.address(); Object.prototype.baseURL = `http://127.0.0.1:${hijackerPort}`; try { let threw = false; try { await axios.get('/api'); } catch (_err) { threw = true; } // Either the request fails (desired — no baseURL means no host) or it // resolves, but it must NOT hit the polluted hijacker. assert.strictEqual(hijackHit, false); assert.strictEqual(threw, true); } finally { await new Promise((resolve) => hijacker.close(resolve)); } }, 10000); // Second variant using allowAbsoluteUrls: false to force the baseURL path // even for a fully-qualified requested URL. it('should not hijack requests via Object.prototype.baseURL with allowAbsoluteUrls:false', async () => { let hijackHit = false; const hijacker = http.createServer((req, res) => { hijackHit = true; res.writeHead(200, { 'Content-Type': 'application/json' }); res.end('{"hijacked":true}'); }); await new Promise((resolve) => hijacker.listen(0, '127.0.0.1', resolve)); const { port: hijackerPort } = hijacker.address(); const target = http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end('{"ok":true}'); }); await new Promise((resolve) => target.listen(0, '127.0.0.1', resolve)); const { port: targetPort } = target.address(); Object.prototype.baseURL = `http://127.0.0.1:${hijackerPort}`; try { // If the gadget were picked up, combineURLs(hijacker, `http://target`) // would route to the hijacker. It must not. let threw = false; try { await axios.get(`http://127.0.0.1:${targetPort}/api`, { allowAbsoluteUrls: false, }); } catch (_err) { threw = true; } assert.strictEqual(hijackHit, false); // allowAbsoluteUrls:false + no baseURL → combineURLs not invoked // (baseURL falsy) → returns requested URL as-is → target receives it. // If baseURL were inherited from prototype, it would be truthy and // combineURLs would be invoked, routing to the hijacker. assert.strictEqual(threw, false); } finally { await new Promise((resolve) => hijacker.close(resolve)); await new Promise((resolve) => target.close(resolve)); } }, 10000); }); describe('resolveConfig params and paramsSerializer gadget', () => { it('should not inherit polluted params via resolveConfig', () => { Object.prototype.params = { injected: 'yes' }; try { const resolved = resolveConfig({ url: '/api', method: 'get' }); assert.ok(resolved.url.indexOf('injected') === -1, 'polluted params must not appear in URL'); assert.strictEqual(resolved.url, '/api', 'URL must remain unchanged'); } finally { delete Object.prototype.params; } }); it('should not invoke polluted paramsSerializer via resolveConfig', () => { let serializerInvoked = false; Object.prototype.paramsSerializer = function polluted() { serializerInvoked = true; return 'injected=yes'; }; try { const resolved = resolveConfig({ url: '/api', method: 'get', params: { legit: 'true' } }); assert.strictEqual(serializerInvoked, false, 'polluted paramsSerializer must not be called'); // The URL should have legit param serialized normally assert.ok(resolved.url.indexOf('legit=true') !== -1, 'legitimate params must still be serialized'); } finally { delete Object.prototype.paramsSerializer; } }); }); // Structural defense: mergeConfig returns a null-prototype object, so any // property read that is not an own property of config cannot inherit from // Object.prototype. Adding a new key to Object.prototype must never appear // as a property of the merged config. describe('mergeConfig null-prototype structural defense', () => { it('should return an object whose prototype is null', () => { const merged = mergeConfig({ url: '/x' }, { method: 'get' }); assert.strictEqual(Object.getPrototypeOf(merged), null); }); it('should preserve hasOwnProperty as a callable own slot', () => { const merged = mergeConfig({}, { url: '/x', method: 'get' }); assert.strictEqual(typeof merged.hasOwnProperty, 'function'); assert.strictEqual(merged.hasOwnProperty('url'), true); assert.strictEqual(merged.hasOwnProperty('method'), true); assert.strictEqual(merged.hasOwnProperty('bogus'), false); }); it('should not serialize hasOwnProperty slot via Object.keys', () => { const merged = mergeConfig({ url: '/x' }, {}); assert.ok(!Object.keys(merged).includes('hasOwnProperty')); }); it('should not expose arbitrary polluted keys as inherited properties', () => { Object.prototype.polluted = 'attacker'; try { const merged = mergeConfig({ url: '/x' }, {}); assert.strictEqual(merged.polluted, undefined); } finally { delete Object.prototype.polluted; } }); }); // Verify every gadget enumerated in the audit // is neutralized end-to-end by the null-prototype config. describe('Full gadget coverage via null-prototype config', () => { function startEcho(handler) { return new Promise((resolve) => { const server = http.createServer( handler || ((req, res) => { let body = ''; req.on('data', (c) => (body += c)); req.on('end', () => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end( JSON.stringify({ url: req.url, method: req.method, headers: req.headers, body, }) ); }); }) ); server.listen(0, '127.0.0.1', () => resolve(server)); }); } const stop = (s) => new Promise((r) => s.close(r)); it('should ignore polluted transformRequest', async () => { let invoked = false; Object.prototype.transformRequest = function polluted(data) { invoked = true; return 'INJECTED'; }; const server = await startEcho(); const { port } = server.address(); try { const res = await axios.post(`http://127.0.0.1:${port}/`, { hello: 'world' }); assert.strictEqual(invoked, false); assert.notStrictEqual(res.data.body, 'INJECTED'); } finally { await stop(server); } }, 10000); it('should ignore polluted transformResponse', async () => { let invoked = false; Object.prototype.transformResponse = function polluted() { invoked = true; return 'HIJACKED'; }; const server = await startEcho(); const { port } = server.address(); try { const res = await axios.get(`http://127.0.0.1:${port}/`); assert.strictEqual(invoked, false); assert.notStrictEqual(res.data, 'HIJACKED'); } finally { await stop(server); } }, 10000); it('should ignore polluted adapter', async () => { let hijacked = false; Object.prototype.adapter = function pollutedAdapter() { hijacked = true; return Promise.resolve({ data: 'pwned', status: 200, statusText: 'OK', headers: {}, config: {}, request: {}, }); }; const server = await startEcho(); const { port } = server.address(); try { const res = await axios.get(`http://127.0.0.1:${port}/ok`); assert.strictEqual(hijacked, false); assert.notStrictEqual(res.data, 'pwned'); } finally { await stop(server); } }, 10000); it('should ignore polluted httpAgent', async () => { let agentUsed = false; Object.prototype.httpAgent = new http.Agent({ keepAlive: false, }); // Wrap createConnection to detect usage const origCreate = Object.prototype.httpAgent.createConnection; Object.prototype.httpAgent.createConnection = function (...args) { agentUsed = true; return origCreate.apply(this, args); }; const server = await startEcho(); const { port } = server.address(); try { const res = await axios.get(`http://127.0.0.1:${port}/`); assert.strictEqual(res.status, 200); assert.strictEqual(agentUsed, false); } finally { await stop(server); } }, 10000); it('should ignore polluted proxy', async () => { Object.prototype.proxy = { protocol: 'http', host: '127.0.0.1', port: 1, // would fail if actually used }; const server = await startEcho(); const { port } = server.address(); try { const res = await axios.get(`http://127.0.0.1:${port}/`); assert.strictEqual(res.status, 200); } finally { await stop(server); } }, 10000); it('should ignore polluted maxContentLength', async () => { // Polluted tiny limit would reject a normal response if applied. Object.prototype.maxContentLength = 1; const server = await startEcho(); const { port } = server.address(); try { const res = await axios.get(`http://127.0.0.1:${port}/`); assert.strictEqual(res.status, 200); } finally { await stop(server); } }, 10000); it('should ignore polluted maxRedirects', async () => { // Pollute with 0 — if picked up, follow-redirects path would be skipped. // We make sure regular requests still succeed via the expected path. Object.prototype.maxRedirects = 0; const server = await startEcho(); const { port } = server.address(); try { const res = await axios.get(`http://127.0.0.1:${port}/`); assert.strictEqual(res.status, 200); } finally { await stop(server); } }, 10000); it('should ignore polluted timeout at the merged config level', () => { Object.prototype.timeout = 1; const merged = mergeConfig({}, { url: '/x' }); assert.strictEqual(Object.prototype.hasOwnProperty.call(merged, 'timeout'), false); assert.strictEqual(merged.timeout, undefined); }); it('should ignore polluted timeoutErrorMessage', async () => { Object.prototype.timeoutErrorMessage = 'INJECTED_TIMEOUT'; // Not easy to assert without triggering a real timeout; just confirm // normal requests still succeed and do not read the polluted key. const server = await startEcho(); const { port } = server.address(); try { const res = await axios.get(`http://127.0.0.1:${port}/`); assert.strictEqual(res.status, 200); } finally { await stop(server); } }, 10000); it('should ignore polluted transitional', async () => { Object.prototype.transitional = { forcedJSONParsing: true, silentJSONParsing: false }; const server = await startEcho(); const { port } = server.address(); try { const res = await axios.get(`http://127.0.0.1:${port}/`); assert.strictEqual(res.status, 200); } finally { await stop(server); } }, 10000); it('should ignore polluted params and paramsSerializer', async () => { let serializerInvoked = false; Object.prototype.params = { injected: 'yes' }; Object.prototype.paramsSerializer = function polluted() { serializerInvoked = true; return 'injected=yes'; }; const server = await startEcho(); const { port } = server.address(); try { const res = await axios.get(`http://127.0.0.1:${port}/x`); assert.strictEqual(serializerInvoked, false); assert.strictEqual(res.data.url, '/x'); } finally { await stop(server); } }, 10000); it('should ignore polluted method', async () => { Object.prototype.method = 'DELETE'; const server = await startEcho(); const { port } = server.address(); try { // axios.get should still send GET, not DELETE. const res = await axios.get(`http://127.0.0.1:${port}/ok`); assert.strictEqual(res.data.method, 'GET'); } finally { await stop(server); } }, 10000); it('should ignore polluted decompress', async () => { Object.prototype.decompress = false; const server = await startEcho(); const { port } = server.address(); try { const res = await axios.get(`http://127.0.0.1:${port}/`); assert.strictEqual(res.status, 200); } finally { await stop(server); } }, 10000); it('should ignore polluted responseType', async () => { Object.prototype.responseType = 'arraybuffer'; const server = await startEcho(); const { port } = server.address(); try { const res = await axios.get(`http://127.0.0.1:${port}/`); // When responseType is not set on config, json parsing should apply // and res.data should be an object, not an ArrayBuffer/Buffer. assert.strictEqual(typeof res.data, 'object'); assert.ok(!Buffer.isBuffer(res.data)); } finally { await stop(server); } }, 10000); }); // utils.merge previously read `result[targetKey]` directly, which walks the // prototype chain. A polluted Object.prototype. object would surface as // the existing value and be merged into the result. describe('utils.merge prototype-chain read', () => { it('should not pick up polluted Object.prototype. as the existing value', () => { Object.prototype.headers = { evil: 'yes' }; const result = utils.merge({}, { headers: { 'Content-Type': 'application/json' } }); assert.strictEqual(result.headers.evil, undefined); assert.strictEqual(result.headers['Content-Type'], 'application/json'); }); it('should not absorb polluted nested objects when the key is absent from inputs', () => { // When the source does not carry `customNested`, the merged result should // not surface it either, even if Object.prototype carries it. Object.prototype.customNested = { evil: 'yes' }; const result = utils.merge({}, { safe: 'value' }); assert.strictEqual(result.hasOwnProperty('customNested'), false); assert.strictEqual(result.safe, 'value'); }); }); // Object.defineProperty calls a HasProperty check on `get`/`set` of the // descriptor. A polluted Object.prototype.get with a non-function value would // throw TypeError at every defineProperty site that uses a plain literal // descriptor. Each fixed site should be shielded with `__proto__: null`. describe('Object.defineProperty descriptor literals', () => { it('should construct AxiosError when Object.prototype.get is polluted', () => { Object.prototype.get = 'attacker'; const err = new AxiosError('hello', 'ECODE'); assert.strictEqual(err.message, 'hello'); assert.strictEqual(err.code, 'ECODE'); }); it('should construct AxiosHeaders accessor methods when Object.prototype.get is polluted', () => { Object.prototype.get = 'attacker'; // AxiosHeaders.accessor uses Object.defineProperty on the prototype. // Triggering a fresh accessor definition exercises the descriptor literal. AxiosHeaders.accessor('X-Pp-Test'); const h = new AxiosHeaders(); h.setXPpTest('value'); assert.strictEqual(h.getXPpTest(), 'value'); }); it('should not throw in mergeConfig when Object.prototype.get is polluted', () => { Object.prototype.get = 'attacker'; const result = mergeConfig({}, { url: '/x', method: 'get' }); assert.strictEqual(result.url, '/x'); assert.strictEqual(result.method, 'get'); assert.strictEqual(typeof result.hasOwnProperty, 'function'); }); it('should not throw in utils.extend when Object.prototype.get is polluted', () => { Object.prototype.get = 'attacker'; const a = {}; const b = { x: 1, fn() {} }; utils.extend(a, b); assert.strictEqual(a.x, 1); assert.strictEqual(typeof a.fn, 'function'); }); it('should not throw in utils.extend with thisArg when Object.prototype.get is polluted', () => { Object.prototype.get = 'attacker'; const a = {}; const ctx = { tag: 'ctx' }; const b = { method() { return this.tag; }, }; utils.extend(a, b, ctx); assert.strictEqual(a.method(), 'ctx'); }); it('should not throw in utils.inherits when Object.prototype.get is polluted', () => { Object.prototype.get = 'attacker'; function Parent() {} function Child() {} utils.inherits(Child, Parent); assert.strictEqual(Child.prototype.constructor, Child); assert.strictEqual(Child.super, Parent.prototype); }); it('should also be shielded against a polluted Object.prototype.set', () => { Object.prototype.set = 'attacker'; // Same surface as `get` — ToPropertyDescriptor checks both. One spot-check // covers them all since they share the same fix. const err = new AxiosError('hello'); assert.strictEqual(err.message, 'hello'); }); }); // End-to-end regressions covering published advisory PoCs against full axios // request flow. Each test mirrors the exploit scenario from the advisory and // asserts the attack does not succeed. describe('advisory regression — full request flow', () => { function startServer(handler) { return new Promise((resolve) => { const server = http.createServer(handler); server.listen(0, '127.0.0.1', () => resolve(server)); }); } const stop = (s) => new Promise((r) => s.close(r)); // Full MITM via prototype pollution gadget in // `config.proxy`. mergeConfig must not surface a polluted Object.prototype.proxy // as the merged config's proxy, otherwise every request would route through // an attacker-controlled host. it('polluted Object.prototype.proxy must not redirect requests through an attacker proxy', async () => { const proxyHits = []; const attackerProxy = await startServer((req, res) => { proxyHits.push({ url: req.url, authorization: req.headers.authorization, host: req.headers.host, }); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end('{"hijacked":true}'); }); const realHits = []; const realServer = await startServer((req, res) => { realHits.push({ url: req.url }); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end('{"data":"real"}'); }); try { Object.prototype.proxy = { protocol: 'http', host: '127.0.0.1', port: attackerProxy.address().port, }; const realPort = realServer.address().port; const res = await axios.get(`http://127.0.0.1:${realPort}/api/secrets`, { auth: { username: 'admin', password: 'SuperSecret123!' }, }); assert.strictEqual(proxyHits.length, 0, 'attacker proxy must not receive any request'); assert.strictEqual(realHits.length, 1, 'request must reach the real target'); assert.deepStrictEqual(res.data, { data: 'real' }); } finally { await stop(attackerProxy); await stop(realServer); } }, 10000); // Credential theft and response hijacking via // prototype pollution gadget in config merge. A polluted // Object.prototype.transformResponse function would otherwise execute with // `this = config`, exposing `auth.username`/`auth.password` to the attacker. it('polluted Object.prototype.transformResponse must not be invoked or leak request credentials', async () => { let invoked = false; let stolen = null; Object.prototype.transformResponse = function pollutedTransform(data) { invoked = true; stolen = { url: this && this.url, username: this && this.auth && this.auth.username, password: this && this.auth && this.auth.password, data, }; return true; }; const server = await startServer((req, res) => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end('{"secret":"keep-me"}'); }); try { const { port } = server.address(); const res = await axios.get(`http://127.0.0.1:${port}/users`, { auth: { username: 'svc-account', password: 'prod-secret-key-123!' }, }); assert.strictEqual(invoked, false, 'polluted transformResponse must not run'); assert.strictEqual(stolen, null, 'no request context must be captured'); assert.deepStrictEqual( res.data, { secret: 'keep-me' }, 'response data must reach the caller untampered' ); } finally { await stop(server); } }, 10000); }); }); axios-axios-2d06f96/tests/unit/query.test.js000066400000000000000000000174131521272452000211300ustar00rootroot00000000000000import { describe, it } from 'vitest'; import assert from 'assert'; import axios from '../../index.js'; import { startHTTPServer, stopHTTPServer } from '../setup/server.js'; describe('QUERY method', () => { describe('static axios.query()', () => { it('should make a request with the QUERY HTTP method', async () => { const response = await axios.query('/test', null, { adapter: (config) => { assert.strictEqual(config.method, 'query'); return Promise.resolve({ data: null, status: 200, statusText: 'OK', headers: {}, config, request: {}, }); }, }); assert.strictEqual(response.status, 200); }); it('should support a request body', async () => { const requestBody = { selector: 'field1, field2', filter: { active: true } }; await axios.query('/search', requestBody, { adapter: (config) => { assert.deepStrictEqual(config.data, JSON.stringify(requestBody)); return Promise.resolve({ data: null, status: 200, statusText: 'OK', headers: {}, config, request: {}, }); }, }); }); it('should support custom headers', async () => { await axios.query('/test', null, { headers: { 'X-Custom-Header': 'custom-value', Authorization: 'Bearer token-abc', }, adapter: (config) => { assert.strictEqual(config.headers.get('X-Custom-Header'), 'custom-value'); assert.strictEqual(config.headers.get('Authorization'), 'Bearer token-abc'); return Promise.resolve({ data: null, status: 200, statusText: 'OK', headers: {}, config, request: {}, }); }, }); }); it('should work with baseURL configuration', async () => { const instance = axios.create({ baseURL: 'http://example.com/api' }); await instance.query('/resources', { fields: ['name'] }, { adapter: (config) => { assert.strictEqual(config.baseURL, 'http://example.com/api'); assert.strictEqual(config.url, '/resources'); assert.strictEqual(config.method, 'query'); return Promise.resolve({ data: null, status: 200, statusText: 'OK', headers: {}, config, request: {}, }); }, }); }); it('should set Content-Type to application/json for object bodies', async () => { await axios.query('/test', { key: 'value' }, { adapter: (config) => { assert.ok( config.headers.get('Content-Type').includes('application/json'), 'Expected Content-Type to include application/json' ); return Promise.resolve({ data: null, status: 200, statusText: 'OK', headers: {}, config, request: {}, }); }, }); }); }); describe('instance.query()', () => { it('should make a request with the QUERY HTTP method on an instance', async () => { const instance = axios.create(); const response = await instance.query('/test', null, { adapter: (config) => { assert.strictEqual(config.method, 'query'); return Promise.resolve({ data: null, status: 200, statusText: 'OK', headers: {}, config, request: {}, }); }, }); assert.strictEqual(response.status, 200); }); it('should merge instance defaults with request config', async () => { const instance = axios.create({ headers: { 'X-Instance-Header': 'from-instance' }, }); await instance.query('/test', null, { headers: { 'X-Request-Header': 'from-request' }, adapter: (config) => { assert.strictEqual(config.headers.get('X-Instance-Header'), 'from-instance'); assert.strictEqual(config.headers.get('X-Request-Header'), 'from-request'); return Promise.resolve({ data: null, status: 200, statusText: 'OK', headers: {}, config, request: {}, }); }, }); }); }); describe('axios({ method: "query" })', () => { it('should support the generic request form', async () => { const response = await axios({ method: 'query', url: '/test', data: { selector: '*' }, adapter: (config) => { assert.strictEqual(config.method, 'query'); assert.deepStrictEqual(config.data, JSON.stringify({ selector: '*' })); return Promise.resolve({ data: { result: 'ok' }, status: 200, statusText: 'OK', headers: {}, config, request: {}, }); }, }); assert.deepStrictEqual(response.data, { result: 'ok' }); }); }); describe('with HTTP server', () => { it('should send QUERY requests with a body to a real server', async () => { const server = await startHTTPServer( (req, res) => { let body = ''; req.on('data', (chunk) => { body += chunk; }); req.on('end', () => { res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ method: req.method, url: req.url, body, headers: req.headers, })); }); }, { port: 0 } ); try { const { data } = await axios.query( `http://localhost:${server.address().port}/search`, { selector: 'field1' } ); assert.strictEqual(data.method, 'QUERY'); assert.strictEqual(data.url, '/search'); const parsedBody = JSON.parse(data.body); assert.deepStrictEqual(parsedBody, { selector: 'field1' }); assert.ok( data.headers['content-type'].includes('application/json'), 'Expected server to receive application/json content-type' ); } finally { await stopHTTPServer(server); } }); it('should send QUERY requests with custom headers to a real server', async () => { const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ method: req.method, headers: req.headers, })); }, { port: 0 } ); try { const { data } = await axios.query( `http://localhost:${server.address().port}/test`, null, { headers: { 'X-Custom': 'test-value', }, } ); assert.strictEqual(data.method, 'QUERY'); assert.strictEqual(data.headers['x-custom'], 'test-value'); } finally { await stopHTTPServer(server); } }); it('should send QUERY requests with baseURL to a real server', async () => { const server = await startHTTPServer( (req, res) => { res.setHeader('Content-Type', 'application/json'); res.end(JSON.stringify({ method: req.method, url: req.url, })); }, { port: 0 } ); try { const instance = axios.create({ baseURL: `http://localhost:${server.address().port}/api`, }); const { data } = await instance.query('/resources', { fields: ['name'] }); assert.strictEqual(data.method, 'QUERY'); assert.strictEqual(data.url, '/api/resources'); } finally { await stopHTTPServer(server); } }); }); }); axios-axios-2d06f96/tests/unit/regression.test.js000066400000000000000000000165621521272452000221470ustar00rootroot00000000000000/** * Combined regression tests (issues 4999, 5028, 7364 + SSRF SNYK-1038255, SNYK-7361793). */ import { describe, it, beforeEach, afterEach, vi } from 'vitest'; import assert from 'assert'; import http from 'http'; import axios from '../../index.js'; import platform from '../../lib/platform/index.js'; describe('regression', () => { describe('issues', () => { describe('4999', () => { // Depends on network: https://postman-echo.com it('should not fail with query parsing', async () => { const { data } = await axios.get('https://postman-echo.com/get?foo1=bar1&foo2=bar2'); assert.strictEqual(data.args.foo1, 'bar1'); assert.strictEqual(data.args.foo2, 'bar2'); }); }); describe('5028', () => { it('should handle set-cookie headers as an array', async () => { const cookie1 = 'something=else; path=/; expires=Wed, 12 Apr 2023 12:03:42 GMT; samesite=lax; secure; httponly'; const cookie2 = 'something-ssr.sig=n4MlwVAaxQAxhbdJO5XbUpDw-lA; path=/; expires=Wed, 12 Apr 2023 12:03:42 GMT; samesite=lax; secure; httponly'; const server = http .createServer((req, res) => { res.setHeader('Set-Cookie', [cookie1, cookie2]); res.writeHead(200); res.write('Hi there'); res.end(); }) .listen(0); const request = axios.create(); request.interceptors.response.use((res) => { assert.deepStrictEqual(res.headers['set-cookie'], [cookie1, cookie2]); }); try { await request({ url: `http://localhost:${server.address().port}` }); } finally { server.close(); } }); }); describe('7364', () => { it('fetch: should have status code in axios error', async () => { const isFetchSupported = typeof fetch === 'function'; if (!isFetchSupported) { vi.skip(); } const server = http .createServer((req, res) => { res.statusCode = 400; res.end(); }) .listen(0); const instance = axios.create({ baseURL: `http://localhost:${server.address().port}`, adapter: 'fetch', }); try { await instance.get('/status/400'); } catch (error) { assert.equal(error.name, 'AxiosError'); assert.equal(error.isAxiosError, true); assert.equal(error.status, 400); } finally { server.close(); } }); it('http: should have status code in axios error', async () => { const server = http .createServer((req, res) => { res.statusCode = 400; res.end(); }) .listen(0); const instance = axios.create({ baseURL: `http://localhost:${server.address().port}`, adapter: 'http', }); try { await instance.get('/status/400'); } catch (error) { assert.equal(error.name, 'AxiosError'); assert.equal(error.isAxiosError, true); assert.equal(error.status, 400); } finally { server.close(); } }); }); }); // https://snyk.io/vuln/SNYK-JS-AXIOS-1038255 // https://github.com/axios/axios/issues/3407 // https://github.com/axios/axios/issues/3369 describe('SSRF SNYK-JS-AXIOS-1038255', () => { let fail = false; let proxy; let server; let location; let evilPort; let proxyPort; beforeEach(() => { fail = false; server = http .createServer((req, res) => { fail = true; res.end('rm -rf /'); }) .listen(0); evilPort = server.address().port; proxy = http .createServer((req, res) => { if ( new URL(req.url, 'http://' + req.headers.host).toString() === 'http://localhost:' + evilPort + '/' ) { return res.end( JSON.stringify({ msg: 'Protected', headers: req.headers, }) ); } res.writeHead(302, { location }); res.end(); }) .listen(0); proxyPort = proxy.address().port; location = 'http://localhost:' + evilPort; }); afterEach(() => { server.close(); proxy.close(); }); it('obeys proxy settings when following redirects', async () => { const response = await axios({ method: 'get', url: 'http://www.google.com/', proxy: { host: 'localhost', port: proxyPort, auth: { username: 'sam', password: 'password', }, }, }); assert.strictEqual(fail, false); assert.strictEqual(response.data.msg, 'Protected'); assert.strictEqual(response.data.headers.host, 'localhost:' + evilPort); assert.strictEqual( response.data.headers['proxy-authorization'], 'Basic ' + Buffer.from('sam:password').toString('base64') ); return response; }); }); // https://security.snyk.io/vuln/SNYK-JS-AXIOS-7361793 // https://github.com/axios/axios/issues/6463 describe('SSRF SNYK-JS-AXIOS-7361793', () => { let goodServer; let badServer; let goodPort; let badPort; beforeEach(() => { goodServer = http .createServer((req, res) => { res.write('good'); res.end(); }) .listen(0); goodPort = goodServer.address().port; badServer = http .createServer((req, res) => { res.write('bad'); res.end(); }) .listen(0); badPort = badServer.address().port; }); afterEach(() => { goodServer.close(); badServer.close(); }); it('should not fetch in server-side mode', async () => { const ssrfAxios = axios.create({ baseURL: 'http://localhost:' + String(goodPort), }); const userId = '/localhost:' + String(badPort); try { await ssrfAxios.get(`/${userId}`); } catch (error) { assert.ok(error.message.startsWith('Invalid URL')); return; } assert.fail('Expected an error to be thrown'); }); describe('client-side mode', () => { let savedHasBrowserEnv; let savedOrigin; beforeEach(() => { assert.ok(platform.hasBrowserEnv !== undefined); savedHasBrowserEnv = platform.hasBrowserEnv; savedOrigin = platform.origin; platform.hasBrowserEnv = true; platform.origin = 'http://localhost:' + String(goodPort); }); afterEach(() => { platform.hasBrowserEnv = savedHasBrowserEnv; platform.origin = savedOrigin; }); it('resolves URL relative to origin and returns bad server body', async () => { const ssrfAxios = axios.create({ baseURL: 'http://localhost:' + String(goodPort), }); const userId = '/localhost:' + String(badPort); const response = await ssrfAxios.get(`/${userId}`); assert.strictEqual(response.data, 'bad'); assert.strictEqual(response.config.baseURL, 'http://localhost:' + String(goodPort)); assert.strictEqual(response.config.url, '//localhost:' + String(badPort)); assert.strictEqual( response.request.res.responseUrl, 'http://localhost:' + String(badPort) + '/' ); }); }); }); }); axios-axios-2d06f96/tests/unit/syntaxCompat.test.js000066400000000000000000000016121521272452000224470ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import { readFileSync, readdirSync, statSync } from 'node:fs'; import { join } from 'node:path'; import { fileURLToPath } from 'node:url'; import { Parser } from 'acorn'; const LIB_DIR = fileURLToPath(new URL('../../lib/', import.meta.url)); const ECMA_VERSION = 2018; function walk(dir) { const out = []; for (const name of readdirSync(dir)) { const full = join(dir, name); if (statSync(full).isDirectory()) out.push(...walk(full)); else if (full.endsWith('.js')) out.push(full); } return out; } describe('lib/ source files parse as ES2018', () => { for (const file of walk(LIB_DIR)) { const rel = file.slice(LIB_DIR.length); it(rel, () => { const src = readFileSync(file, 'utf8'); expect(() => Parser.parse(src, { ecmaVersion: ECMA_VERSION, sourceType: 'module' }) ).not.toThrow(); }); } }); axios-axios-2d06f96/tests/unit/toFormData.test.js000066400000000000000000000212301521272452000220130ustar00rootroot00000000000000import { describe, it } from 'vitest'; import assert from 'assert'; import FormData from 'form-data'; import toFormData from '../../lib/helpers/toFormData.js'; import AxiosError from '../../lib/core/AxiosError.js'; import AxiosURLSearchParams from '../../lib/helpers/AxiosURLSearchParams.js'; describe('helpers::toFormData', () => { const createRNFormDataSpy = () => { const calls = []; return { calls, append: (key, value) => { calls.push([key, value]); }, getParts: () => { return []; }, }; }; it('should convert a flat object to FormData', () => { const data = { foo: 'bar', baz: 123, }; const formData = toFormData(data, new FormData()); assert.ok(formData instanceof FormData); assert.ok(formData._streams.length > 0); }); it('should convert a nested object to FormData', () => { const data = { foo: { bar: 'baz', }, }; const formData = toFormData(data, new FormData()); assert.ok(formData instanceof FormData); }); it('should throw Error on circular reference', () => { const data = { foo: 'bar', }; data.self = data; try { toFormData(data, new FormData()); assert.fail('Should have thrown an error'); } catch (err) { assert.strictEqual(err.message, 'Circular reference detected in self'); } }); it('should handle arrays', () => { const data = { arr: [1, 2, 3], }; const formData = toFormData(data, new FormData()); assert.ok(formData instanceof FormData); }); it('should append root-level React Native blob without recursion', () => { const formData = createRNFormDataSpy(); const blob = { uri: 'file://test.png', type: 'image/png', name: 'test.png', }; toFormData({ file: blob }, formData); assert.strictEqual(formData.calls.length, 1); assert.strictEqual(formData.calls[0][0], 'file'); assert.strictEqual(formData.calls[0][1], blob); }); it('should append nested React Native blob without recursion', () => { const formData = createRNFormDataSpy(); const blob = { uri: 'file://nested.png', type: 'image/png', name: 'nested.png', }; toFormData({ nested: { file: blob } }, formData); assert.strictEqual(formData.calls.length, 1); assert.strictEqual(formData.calls[0][0], 'nested[file]'); assert.strictEqual(formData.calls[0][1], blob); }); it('should append deeply nested React Native blob without recursion', () => { const formData = createRNFormDataSpy(); const blob = { uri: 'file://deep.png', name: 'deep.png', }; toFormData({ a: { b: { c: blob } } }, formData); assert.strictEqual(formData.calls.length, 1); assert.strictEqual(formData.calls[0][0], 'a[b][c]'); assert.strictEqual(formData.calls[0][1], blob); }); // --- Depth limit tests --- function nest(depth) { let o = { leaf: 1 }; for (let i = 0; i < depth; i++) o = { a: o }; return o; } describe('maxDepth option', () => { it('should throw AxiosError when payload exceeds default depth limit (100)', () => { try { toFormData(nest(101), new FormData()); assert.fail('Should have thrown'); } catch (err) { assert.ok(err instanceof AxiosError, 'error must be AxiosError, not RangeError'); assert.strictEqual(err.code, 'ERR_FORM_DATA_DEPTH_EXCEEDED'); assert.ok(!(err instanceof RangeError)); } }); it('should succeed when payload is exactly at the default depth limit (100)', () => { const formData = toFormData(nest(100), new FormData()); assert.ok(formData instanceof FormData); }); it('should succeed for a shallow payload (no regression)', () => { const formData = toFormData(nest(5), new FormData()); assert.ok(formData instanceof FormData); }); it('should allow deeper payloads when maxDepth is raised', () => { const formData = toFormData(nest(150), new FormData(), { maxDepth: 200 }); assert.ok(formData instanceof FormData); }); it('should reject shallower payloads when maxDepth is lowered', () => { try { toFormData(nest(10), new FormData(), { maxDepth: 5 }); assert.fail('Should have thrown'); } catch (err) { assert.ok(err instanceof AxiosError); assert.strictEqual(err.code, 'ERR_FORM_DATA_DEPTH_EXCEEDED'); } }); it('should not throw for depth guard when maxDepth is Infinity (guard disabled)', () => { // Use 500 levels — deep enough to prove the guard is off, shallow enough not to overflow V8 const formData = toFormData(nest(500), new FormData(), { maxDepth: Infinity }); assert.ok(formData instanceof FormData); }); it('should still detect circular references when depth guard is active', () => { const data = { foo: 'bar' }; data.self = data; try { toFormData(data, new FormData()); assert.fail('Should have thrown'); } catch (err) { assert.ok( err.message.includes('Circular reference detected'), 'must be circular-ref error' ); assert.ok(!(err instanceof AxiosError) || err.code !== 'ERR_FORM_DATA_DEPTH_EXCEEDED'); } }); it('depth limit error is catchable as AxiosError with correct code', () => { let caught; try { toFormData(nest(101), new FormData()); } catch (err) { caught = err; } assert.ok(caught instanceof AxiosError); assert.strictEqual(caught.code, 'ERR_FORM_DATA_DEPTH_EXCEEDED'); assert.ok(!(caught instanceof RangeError)); }); it('should reject deeply nested {} metatoken values before JSON.stringify overflows', () => { try { toFormData({ 'evil{}': nest(10000) }, new FormData()); assert.fail('Should have thrown'); } catch (err) { assert.ok(err instanceof AxiosError, 'error must be AxiosError, not RangeError'); assert.strictEqual(err.code, 'ERR_FORM_DATA_DEPTH_EXCEEDED'); assert.ok(!(err instanceof RangeError)); } }); it('should allow {} metatoken values at the same boundary as normal top-level properties', () => { const formData = toFormData({ 'safe{}': nest(99) }, new FormData()); assert.ok(formData instanceof FormData); }); it('should reject {} metatoken values beyond the normal top-level property boundary', () => { try { toFormData({ 'evil{}': nest(100) }, new FormData()); assert.fail('Should have thrown'); } catch (err) { assert.ok(err instanceof AxiosError); assert.strictEqual(err.code, 'ERR_FORM_DATA_DEPTH_EXCEEDED'); } }); }); describe('maxDepth — params serialization via AxiosURLSearchParams', () => { it('should throw AxiosError for deeply nested params object (default limit)', () => { try { new AxiosURLSearchParams(nest(101)); assert.fail('Should have thrown'); } catch (err) { assert.ok(err instanceof AxiosError); assert.strictEqual(err.code, 'ERR_FORM_DATA_DEPTH_EXCEEDED'); } }); it('should build query string for deep params when maxDepth is raised', () => { const params = new AxiosURLSearchParams(nest(150), { maxDepth: 200 }); const qs = params.toString(); assert.ok(typeof qs === 'string' && qs.length > 0); }); it('should reject deeply nested {} metatoken params before JSON.stringify overflows', () => { try { new AxiosURLSearchParams({ 'evil{}': nest(10000) }); assert.fail('Should have thrown'); } catch (err) { assert.ok(err instanceof AxiosError, 'error must be AxiosError, not RangeError'); assert.strictEqual(err.code, 'ERR_FORM_DATA_DEPTH_EXCEEDED'); assert.ok(!(err instanceof RangeError)); } }); it('should reject {} metatoken params beyond the normal property boundary', () => { try { new AxiosURLSearchParams({ 'evil{}': nest(100) }); assert.fail('Should have thrown'); } catch (err) { assert.ok(err instanceof AxiosError); assert.strictEqual(err.code, 'ERR_FORM_DATA_DEPTH_EXCEEDED'); } }); }); it('should NOT recurse into React Native blob properties', () => { const formData = createRNFormDataSpy(); const blob = { uri: 'file://nope.png', type: 'image/png', name: 'nope.png', }; toFormData({ file: blob }, formData); const keys = formData.calls.map((call) => call[0]); assert.deepStrictEqual(keys, ['file']); assert.ok(!keys.some((key) => key.includes('uri'))); assert.ok(!keys.some((key) => key.includes('type'))); assert.ok(!keys.some((key) => key.includes('name'))); }); }); axios-axios-2d06f96/tests/unit/transformResponse.test.js000066400000000000000000000065461521272452000235220ustar00rootroot00000000000000import { describe, it } from 'vitest'; import defaults from '../../lib/defaults/index.js'; import transformData from '../../lib/core/transformData.js'; import AxiosError from '../../lib/core/AxiosError.js'; import assert from 'assert'; describe('transformResponse', () => { describe('200 request', () => { it('parses json', () => { const data = '{"message": "hello, world"}'; const result = transformData.call( { data, response: { headers: { 'content-type': 'application/json' }, status: 200, }, }, defaults.transformResponse ); assert.strictEqual(result.message, 'hello, world'); }); it('ignores XML', () => { const data = 'hello, world'; const result = transformData.call( { data, response: { headers: { 'content-type': 'text/xml' }, status: 200, }, }, defaults.transformResponse ); assert.strictEqual(result, data); }); }); describe('malformed JSON with responseType: json', () => { it('throws AxiosError with ERR_BAD_RESPONSE code', () => { const response = { status: 200, headers: {}, data: '{bad json' }; const config = { responseType: 'json', transitional: { silentJSONParsing: false, forcedJSONParsing: true }, response, }; assert.throws( () => transformData.call(config, defaults.transformResponse, response), (e) => e instanceof AxiosError && e.code === AxiosError.ERR_BAD_RESPONSE ); }); it('attaches response to AxiosError so error.status and error.response are available', () => { // Regression test for https://github.com/axios/axios/issues/7224 // When JSON.parse fails in strict mode, the thrown AxiosError must carry // the original response so callers can inspect error.status and // error.response without having to re-examine the raw response. const response = { status: 200, headers: {}, data: '{bad json' }; const config = { responseType: 'json', transitional: { silentJSONParsing: false, forcedJSONParsing: true }, response, }; let thrown; try { transformData.call(config, defaults.transformResponse, response); } catch (e) { thrown = e; } assert.ok(thrown instanceof AxiosError, 'must be AxiosError'); assert.strictEqual(thrown.status, 200, 'error.status must equal response status'); assert.strictEqual(thrown.response, response, 'error.response must be the original response'); }); }); describe('204 request', () => { it('does not parse the empty string', () => { const data = ''; const result = transformData.call( { data, response: { headers: { 'content-type': undefined }, status: 204, }, }, defaults.transformResponse ); assert.strictEqual(result, ''); }); it('does not parse undefined', () => { const data = undefined; const result = transformData.call( { data, response: { headers: { 'content-type': undefined }, status: 200, }, }, defaults.transformResponse ); assert.strictEqual(result, data); }); }); }); axios-axios-2d06f96/tests/unit/utils.test.js000066400000000000000000000165361521272452000211300ustar00rootroot00000000000000import { describe, it } from 'vitest'; import assert from 'assert'; import utils from '../../lib/utils.js'; import FormData from 'form-data'; import stream from 'stream'; describe('utils', () => { it('should validate Stream', () => { assert.strictEqual(utils.isStream(new stream.Readable()), true); assert.strictEqual(utils.isStream({ foo: 'bar' }), false); }); it('should validate Buffer', () => { assert.strictEqual(utils.isBuffer(Buffer.from('a')), true); assert.strictEqual(utils.isBuffer(null), false); assert.strictEqual(utils.isBuffer(undefined), false); }); describe('utils::isFormData', () => { it('should detect the FormData instance provided by the `form-data` package', () => { [1, 'str', {}, new RegExp()].forEach((thing) => { assert.equal(utils.isFormData(thing), false); }); assert.equal(utils.isFormData(new FormData()), true); }); it('should not call toString method on built-in objects instances', () => { const buf = Buffer.from('123'); buf.toString = () => assert.fail('should not be called'); assert.equal(utils.isFormData(buf), false); }); it('should not call toString method on built-in objects instances, even if append method exists', () => { const buf = Buffer.from('123'); buf.append = () => {}; buf.toString = () => assert.fail('should not be called'); assert.equal(utils.isFormData(buf), false); }); it('should detect custom FormData instances by toStringTag signature and append method presence', () => { class FormData { append() {} get [Symbol.toStringTag]() { return 'FormData'; } } assert.equal(utils.isFormData(new FormData()), true); }); }); describe('toJSON', () => { it('should convert to a plain object without circular references', () => { const obj = { a: [0] }; const source = { x: 1, y: 2, obj }; source.circular1 = source; obj.a[1] = obj; assert.deepStrictEqual(utils.toJSONObject(source), { x: 1, y: 2, obj: { a: [0] }, }); }); it('should use objects with defined toJSON method without rebuilding', () => { const objProp = {}; const obj = { objProp, toJSON() { return { ok: 1 }; }, }; const source = { x: 1, y: 2, obj }; const jsonObject = utils.toJSONObject(source); assert.strictEqual(jsonObject.obj.objProp, objProp); assert.strictEqual( JSON.stringify(jsonObject), JSON.stringify({ x: 1, y: 2, obj: { ok: 1 } }) ); }); describe('cycle / DAG handling', () => { it('should serialize a shared sibling object at every occurrence (DAG, not cycle)', () => { const shared = { val: 42 }; const source = { x: shared, y: shared }; const result = utils.toJSONObject(source); // Both branches must serialize — shared reference is not a cycle assert.deepStrictEqual(result, { x: { val: 42 }, y: { val: 42 } }); }); it('should serialize a shared sibling array at every occurrence (DAG, not cycle)', () => { const shared = [1, 2, 3]; const source = { a: shared, b: shared }; const result = utils.toJSONObject(source); assert.deepStrictEqual(result, { a: [1, 2, 3], b: [1, 2, 3] }); }); it('should serialize shared sibling that itself contains a self-cycle', () => { const shared = { v: 1 }; shared.self = shared; // self-cycle inside the shared node const source = { x: shared, y: shared }; const result = utils.toJSONObject(source); // The self-cycle is stripped, but both x and y must be serialized assert.deepStrictEqual(result, { x: { v: 1 }, y: { v: 1 } }); }); it('should serialize non-cyclic structures deeper than the old Array(10) cap', () => { // The previous implementation used a fixed-size Array(10) for path tracking. // A non-cyclic chain deeper than 10 levels must serialise end-to-end. let leaf = { v: 'leaf' }; let source = leaf; for (let i = 0; i < 25; i++) { source = { next: source }; } const result = utils.toJSONObject(source); let cursor = result; for (let i = 0; i < 25; i++) { cursor = cursor.next; } assert.deepStrictEqual(cursor, { v: 'leaf' }); }); }); }); describe('Buffer RangeError Fix', () => { it('should handle large Buffer in isEmptyObject without RangeError', () => { const largeBuffer = Buffer.alloc(1024 * 1024 * 200); const result = utils.isEmptyObject(largeBuffer); assert.strictEqual(result, false); }); it('should handle large Buffer in forEach without RangeError', () => { const largeBuffer = Buffer.alloc(1024 * 1024 * 200); let count = 0; utils.forEach(largeBuffer, () => count++); assert.strictEqual(count, 0); }); it('should handle large Buffer in findKey without RangeError', () => { const largeBuffer = Buffer.alloc(1024 * 1024 * 200); const result = utils.findKey(largeBuffer, 'test'); assert.strictEqual(result, null); }); }); describe('utils::isReactNativeBlob', () => { it('should return true for objects with uri property', () => { assert.strictEqual(utils.isReactNativeBlob({ uri: 'file://path/to/file' }), true); assert.strictEqual(utils.isReactNativeBlob({ uri: 'content://media/image' }), true); }); it('should return true for React Native blob-like objects with optional name and type', () => { assert.strictEqual( utils.isReactNativeBlob({ uri: 'file://path/to/file', name: 'image.png', type: 'image/png', }), true ); }); it('should return false for objects without uri property', () => { assert.strictEqual(utils.isReactNativeBlob({ path: 'file://path' }), false); assert.strictEqual(utils.isReactNativeBlob({ url: 'http://example.com' }), false); assert.strictEqual(utils.isReactNativeBlob({}), false); }); it('should return false for non-objects', () => { assert.strictEqual(utils.isReactNativeBlob(null), false); assert.strictEqual(utils.isReactNativeBlob(undefined), false); assert.strictEqual(utils.isReactNativeBlob('string'), false); assert.strictEqual(utils.isReactNativeBlob(123), false); assert.strictEqual(utils.isReactNativeBlob(false), false); }); it('should return true even if uri is empty string', () => { assert.strictEqual(utils.isReactNativeBlob({ uri: '' }), true); }); }); describe('utils::isReactNative', () => { it('should return true for FormData with getParts method', () => { const mockReactNativeFormData = { append: () => {}, getParts: () => { return []; }, }; assert.strictEqual(utils.isReactNative(mockReactNativeFormData), true); }); it('should return false for standard FormData without getParts method', () => { const standardFormData = new FormData(); assert.strictEqual(utils.isReactNative(standardFormData), false); }); it('should return false for objects without getParts method', () => { assert.strictEqual(utils.isReactNative({ append: () => {} }), false); assert.strictEqual(utils.isReactNative({}), false); }); }); }); axios-axios-2d06f96/tests/unit/utils/000077500000000000000000000000001521272452000176015ustar00rootroot00000000000000axios-axios-2d06f96/tests/unit/utils/endsWith.test.js000066400000000000000000000005351521272452000227050ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import utils from '../../../lib/utils.js'; const { kindOf } = utils; describe('utils::kindOf', () => { it('should return object tag', () => { expect(kindOf({})).toEqual('object'); // cached result expect(kindOf({})).toEqual('object'); expect(kindOf([])).toEqual('array'); }); }); axios-axios-2d06f96/tests/unit/utils/extend.test.js000066400000000000000000000014551521272452000224110ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import utils from '../../../lib/utils.js'; const { extend } = utils; describe('utils::extend', () => { it('should be mutable', () => { const a = {}; const b = { foo: 123 }; extend(a, b); expect(a.foo).toEqual(b.foo); }); it('should extend properties', () => { let a = { foo: 123, bar: 456 }; const b = { bar: 789 }; a = extend(a, b); expect(a.foo).toEqual(123); expect(a.bar).toEqual(789); }); it('should bind to thisArg', () => { const a = {}; const b = { getFoo: function getFoo() { return this.foo; }, }; const thisArg = { foo: 'barbaz' }; extend(a, b, thisArg); expect(typeof a.getFoo).toEqual('function'); expect(a.getFoo()).toEqual(thisArg.foo); }); }); axios-axios-2d06f96/tests/unit/utils/forEach.test.js000066400000000000000000000022511521272452000224640ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import utils from '../../../lib/utils.js'; const { forEach } = utils; describe('utils::forEach', () => { it('should loop over an array', () => { let sum = 0; forEach([1, 2, 3, 4, 5], (val) => { sum += val; }); expect(sum).toEqual(15); }); it('should loop over object keys', () => { let keys = ''; let vals = 0; const obj = { b: 1, a: 2, r: 3, }; forEach(obj, (v, k) => { keys += k; vals += v; }); expect(keys).toEqual('bar'); expect(vals).toEqual(6); }); it('should handle undefined gracefully', () => { let count = 0; forEach(undefined, () => { count++; }); expect(count).toEqual(0); }); it('should make an array out of non-array argument', () => { let count = 0; forEach( () => {}, () => { count++; } ); expect(count).toEqual(1); }); it('should handle non object prototype gracefully', () => { let count = 0; const data = Object.create(null); data.foo = 'bar'; forEach(data, () => { count++; }); expect(count).toEqual(1); }); }); axios-axios-2d06f96/tests/unit/utils/isX.test.js000066400000000000000000000111421521272452000216570ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import utils from '../../../lib/utils.js'; describe('utils::isX', () => { it('should validate Array', () => { expect(utils.isArray([])).toEqual(true); expect(utils.isArray({ length: 5 })).toEqual(false); }); it('should validate ArrayBuffer', () => { expect(utils.isArrayBuffer(new ArrayBuffer(2))).toEqual(true); expect(utils.isArrayBuffer({})).toEqual(false); }); it('should validate ArrayBufferView', () => { expect(utils.isArrayBufferView(new DataView(new ArrayBuffer(2)))).toEqual(true); }); it('should validate FormData', () => { expect(utils.isFormData(new FormData())).toEqual(true); }); it('should validate Blob', () => { expect(utils.isBlob(new Blob())).toEqual(true); }); it('should validate String', () => { expect(utils.isString('')).toEqual(true); expect( utils.isString({ toString: function () { return ''; }, }) ).toEqual(false); }); it('should validate Number', () => { expect(utils.isNumber(123)).toEqual(true); expect(utils.isNumber('123')).toEqual(false); }); it('should validate Undefined', () => { expect(utils.isUndefined()).toEqual(true); expect(utils.isUndefined(null)).toEqual(false); }); it('should validate Object', () => { expect(utils.isObject({})).toEqual(true); expect(utils.isObject([])).toEqual(true); expect(utils.isObject(null)).toEqual(false); }); it('should validate plain Object', () => { expect(utils.isPlainObject({})).toEqual(true); expect(utils.isPlainObject([])).toEqual(false); expect(utils.isPlainObject(null)).toEqual(false); expect(utils.isPlainObject(Object.create({}))).toEqual(false); }); it('should ignore inherited symbol properties when validating plain Object', () => { try { Object.prototype[Symbol.iterator] = function* () { yield ['x-injected', 'yes']; }; Object.prototype[Symbol.toStringTag] = 'Custom'; expect(utils.isPlainObject({})).toEqual(true); expect(utils.isPlainObject([])).toEqual(false); expect( utils.isPlainObject({ [Symbol.iterator]: function* () { yield ['x-own', 'yes']; }, }) ).toEqual(false); expect( utils.isPlainObject({ [Symbol.toStringTag]: 'Custom', }) ).toEqual(false); } finally { delete Object.prototype[Symbol.iterator]; delete Object.prototype[Symbol.toStringTag]; } }); it('should treat an object with a genuinely inherited iterator as non-plain', () => { // Iterator inherited from a custom (non-Object.prototype) source: this is a // real iterable, not prototype pollution, so it must not be classified plain. const proto = Object.create(null); proto[Symbol.iterator] = function* () { yield ['x', '1']; }; expect(utils.isPlainObject(Object.create(proto))).toEqual(false); }); it('should not read polluted Object.prototype iterator accessors for safe iterable checks', () => { let accessed = false; try { Object.defineProperty(Object.prototype, Symbol.iterator, { configurable: true, get() { accessed = true; throw new Error('polluted iterator accessor'); } }); expect(utils.isSafeIterable({})).toEqual(false); expect(accessed).toEqual(false); } finally { delete Object.prototype[Symbol.iterator]; } }); it('should stop safe prototype-chain reads on cyclic Proxy prototypes', () => { let calls = 0; let proxy; proxy = new Proxy({}, { getPrototypeOf() { calls += 1; if (calls > 5) { throw new Error('cycled'); } return proxy; } }); expect(utils.hasOwnInPrototypeChain(proxy, 'missing')).toEqual(false); expect(utils.getSafeProp(proxy, 'missing')).toEqual(undefined); expect(calls).toBeLessThanOrEqual(2); }); it('should validate Date', () => { expect(utils.isDate(new Date())).toEqual(true); expect(utils.isDate(Date.now())).toEqual(false); }); it('should validate Function', () => { expect(utils.isFunction(function () {})).toEqual(true); expect(utils.isFunction('function')).toEqual(false); }); it('should validate URLSearchParams', () => { expect(utils.isURLSearchParams(new URLSearchParams())).toEqual(true); expect(utils.isURLSearchParams('foo=1&bar=2')).toEqual(false); }); it('should validate TypedArray instance', () => { expect(utils.isTypedArray(new Uint8Array([1, 2, 3]))).toEqual(true); expect(utils.isTypedArray([1, 2, 3])).toEqual(false); }); }); axios-axios-2d06f96/tests/unit/utils/kindOf.test.js000066400000000000000000000005351521272452000223320ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import utils from '../../../lib/utils.js'; const { kindOf } = utils; describe('utils::kindOf', () => { it('should return object tag', () => { expect(kindOf({})).toEqual('object'); // cached result expect(kindOf({})).toEqual('object'); expect(kindOf([])).toEqual('array'); }); }); axios-axios-2d06f96/tests/unit/utils/kindOfTest.test.js000066400000000000000000000005341521272452000231710ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import utils from '../../../lib/utils.js'; describe('utils::kindOfTest', () => { it('should return true if the type is matched', () => { const { kindOfTest } = utils; const test = kindOfTest('number'); expect(test(123)).toEqual(true); expect(test('123')).toEqual(false); }); }); axios-axios-2d06f96/tests/unit/utils/merge.test.js000066400000000000000000000106701521272452000222200ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import utils from '../../../lib/utils.js'; const { merge } = utils; describe('utils::merge', () => { it('should be immutable', () => { const a = {}; const b = { foo: 123 }; const c = { bar: 456 }; merge(a, b, c); expect(typeof a.foo).toEqual('undefined'); expect(typeof a.bar).toEqual('undefined'); expect(typeof b.bar).toEqual('undefined'); expect(typeof c.foo).toEqual('undefined'); }); it('should merge properties', () => { const a = { foo: 123 }; const b = { bar: 456 }; const c = { foo: 789 }; const d = merge(a, b, c); expect(d.foo).toEqual(789); expect(d.bar).toEqual(456); }); it('should merge recursively', () => { const a = { foo: { bar: 123 } }; const b = { foo: { baz: 456 }, bar: { qux: 789 } }; expect(merge(a, b)).toEqual({ foo: { bar: 123, baz: 456, }, bar: { qux: 789, }, }); }); it('should remove all references from nested objects', () => { const a = { foo: { bar: 123 } }; const b = {}; const d = merge(a, b); expect(d).toEqual({ foo: { bar: 123, }, }); expect(d.foo).not.toBe(a.foo); }); it('handles null and undefined arguments', () => { expect(merge(undefined, undefined)).toEqual({}); expect(merge(undefined, { foo: 123 })).toEqual({ foo: 123 }); expect(merge({ foo: 123 }, undefined)).toEqual({ foo: 123 }); expect(merge(null, null)).toEqual({}); expect(merge(null, { foo: 123 })).toEqual({ foo: 123 }); expect(merge({ foo: 123 }, null)).toEqual({ foo: 123 }); }); it('should replace properties with null', () => { expect(merge({}, { a: null })).toEqual({ a: null }); expect(merge({ a: null }, {})).toEqual({ a: null }); }); it('should replace properties with arrays', () => { expect(merge({}, { a: [1, 2, 3] })).toEqual({ a: [1, 2, 3] }); expect(merge({ a: 2 }, { a: [1, 2, 3] })).toEqual({ a: [1, 2, 3] }); expect(merge({ a: { b: 2 } }, { a: [1, 2, 3] })).toEqual({ a: [1, 2, 3] }); }); it('should replace properties with cloned arrays', () => { const a = [1, 2, 3]; const d = merge({}, { a }); expect(d).toEqual({ a: [1, 2, 3] }); expect(d.a).not.toBe(a); }); it('should support caseless option', () => { const a = { x: 1 }; const b = { X: 2 }; const merged = merge.call({ caseless: true }, a, b); expect(merged).toEqual({ x: 2, }); }); it('should merge enumerable symbol keys', () => { const key = Symbol('key'); const nestedKey = Symbol('nested'); const first = { [key]: { first: true } }; const second = { [key]: { second: true }, nested: { [nestedKey]: 'value', }, }; const merged = merge(first, second); expect(merged[key]).toEqual({ first: true, second: true }); expect(merged[key]).not.toBe(first[key]); expect(merged.nested[nestedKey]).toBe('value'); expect(merged.nested).not.toBe(second.nested); }); it('should skip non-enumerable symbol keys', () => { const key = Symbol('key'); const source = {}; Object.defineProperty(source, key, { value: 'hidden', enumerable: false, }); const merged = merge(source); expect(merged[key]).toBeUndefined(); expect(Object.getOwnPropertySymbols(merged)).toEqual([]); }); it('should support caseless string keys with symbol keys', () => { const key = Symbol('key'); const merged = merge.call( { caseless: true }, { x: 1, [key]: 'first' }, { X: 2, [key]: 'second' } ); expect(merged.x).toBe(2); expect(merged.X).toBeUndefined(); expect(merged[key]).toBe('second'); }); it('should ignore symbol keys on buffers', () => { const key = Symbol('key'); const buffer = Buffer.from('value'); buffer[key] = 'symbol value'; const merged = merge({ x: 1 }, buffer); expect(merged).toEqual({ x: 1 }); }); it('should ignore symbol keys on arrays', () => { const key = Symbol('key'); const array = ['value']; array[key] = 'symbol value'; const merged = merge({ x: 1 }, array); expect(merged).toEqual({ 0: 'value', x: 1 }); expect(merged[key]).toBeUndefined(); }); it('should honor skipUndefined for symbol keys', () => { const key = Symbol('key'); const merged = merge.call({ skipUndefined: true }, { [key]: 'first' }, { [key]: undefined }); expect(merged[key]).toBe('first'); }); }); axios-axios-2d06f96/tests/unit/utils/toArray.test.js000066400000000000000000000006171521272452000225420ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import utils from '../../../lib/utils.js'; const { toArray } = utils; describe('utils::toArray', () => { it('should return null or an array copy depending on input', () => { expect(toArray()).toEqual(null); expect(toArray([])).toEqual([]); expect(toArray([1])).toEqual([1]); expect(toArray([1, 2, 3])).toEqual([1, 2, 3]); }); }); axios-axios-2d06f96/tests/unit/utils/toFlatObject.test.js000066400000000000000000000006751521272452000235050ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import utils from '../../../lib/utils.js'; const { toFlatObject } = utils; describe('utils::toFlatObject', () => { it('should resolve object proto chain to a flat object representation', () => { const a = { x: 1 }; const b = Object.create(a, { y: { value: 2 } }); const c = Object.create(b, { z: { value: 3 } }); expect(toFlatObject(c)).toEqual({ x: 1, y: 2, z: 3 }); }); }); axios-axios-2d06f96/tests/unit/utils/trim.test.js000066400000000000000000000004641521272452000220740ustar00rootroot00000000000000import { describe, it, expect } from 'vitest'; import utils from '../../../lib/utils.js'; describe('utils::trim', () => { it('should trim spaces', () => { expect(utils.trim(' foo ')).toEqual('foo'); }); it('should trim tabs', () => { expect(utils.trim('\tfoo\t')).toEqual('foo'); }); }); axios-axios-2d06f96/tsconfig.json000066400000000000000000000002151521272452000170250ustar00rootroot00000000000000{ "compilerOptions": { "module": "node16", "lib": ["dom", "es2015"], "types": [], "strict": true, "noEmit": true } } axios-axios-2d06f96/tslint.json000066400000000000000000000002471521272452000165330ustar00rootroot00000000000000{ "extends": "dtslint/dtslint.json", "rules": { "no-unnecessary-generics": false }, "linterOptions": { "exclude": [ "test/module/**" ] } } axios-axios-2d06f96/vitest.config.js000066400000000000000000000022601521272452000174400ustar00rootroot00000000000000import { defineConfig } from 'vitest/config'; import { playwright } from '@vitest/browser-playwright'; export default defineConfig({ test: { testTimeout: 10000, projects: [ { test: { name: 'unit', environment: 'node', include: ['tests/unit/**/*.test.js'], setupFiles: [], }, }, { test: { name: 'browser', include: ['tests/browser/**/*.browser.test.js'], browser: { enabled: true, provider: playwright(), instances: [{ browser: 'chromium' }], }, setupFiles: ['tests/setup/browser.setup.js'], }, }, { test: { name: 'browser-headless', include: ['tests/browser/**/*.browser.test.js'], browser: { enabled: true, provider: playwright(), instances: [ { browser: 'chromium', headless: true }, { browser: 'firefox', headless: true }, { browser: 'webkit', headless: true }, ], }, setupFiles: ['tests/setup/browser.setup.js'], }, }, ], }, }); axios-axios-2d06f96/webpack.config.js000066400000000000000000000010771521272452000175430ustar00rootroot00000000000000var config = {}; function generateConfig(name) { var compress = name.indexOf('min') > -1; var config = { entry: './index.js', output: { path: __dirname + '/dist/', filename: name + '.js', sourceMapFilename: name + '.map', library: 'axios', libraryTarget: 'umd', globalObject: 'this', }, node: false, devtool: 'source-map', mode: compress ? 'production' : 'development', }; return config; } ['axios', 'axios.min'].forEach(function (key) { config[key] = generateConfig(key); }); module.exports = config;