aboutsummaryrefslogtreecommitdiffstats
path: root/node_modules/qs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--node_modules/qs/.editorconfig46
-rw-r--r--node_modules/qs/.github/FUNDING.yml12
-rw-r--r--node_modules/qs/.github/SECURITY.md11
-rw-r--r--node_modules/qs/.github/THREAT_MODEL.md78
-rw-r--r--node_modules/qs/.nycrc13
-rw-r--r--node_modules/qs/CHANGELOG.md833
-rw-r--r--node_modules/qs/LICENSE.md29
-rw-r--r--node_modules/qs/README.md758
-rw-r--r--node_modules/qs/dist/qs.js141
-rw-r--r--node_modules/qs/eslint.config.mjs57
-rw-r--r--node_modules/qs/lib/formats.js23
-rw-r--r--node_modules/qs/lib/index.js11
-rw-r--r--node_modules/qs/lib/parse.js414
-rw-r--r--node_modules/qs/lib/stringify.js363
-rw-r--r--node_modules/qs/lib/utils.js381
-rw-r--r--node_modules/qs/package.json95
-rw-r--r--node_modules/qs/test/empty-keys-cases.js267
-rw-r--r--node_modules/qs/test/parse.js1933
-rw-r--r--node_modules/qs/test/stringify.js1448
-rw-r--r--node_modules/qs/test/utils.js626
20 files changed, 0 insertions, 7539 deletions
diff --git a/node_modules/qs/.editorconfig b/node_modules/qs/.editorconfig
deleted file mode 100644
index dd5a8d8..0000000
--- a/node_modules/qs/.editorconfig
+++ /dev/null
@@ -1,46 +0,0 @@
-root = true
-
-[*]
-indent_style = space
-indent_size = 4
-end_of_line = lf
-charset = utf-8
-trim_trailing_whitespace = true
-insert_final_newline = true
-max_line_length = 180
-quote_type = single
-
-[test/*]
-max_line_length = off
-
-[LICENSE.md]
-indent_size = off
-
-[*.md]
-max_line_length = off
-
-[*.json]
-max_line_length = off
-
-[Makefile]
-max_line_length = off
-
-[CHANGELOG.md]
-indent_style = space
-indent_size = 2
-
-[LICENSE]
-indent_size = 2
-max_line_length = off
-
-[coverage/**/*]
-indent_size = off
-indent_style = off
-indent = off
-max_line_length = off
-
-[.nycrc]
-indent_style = tab
-
-[tea.yaml]
-indent_size = 2
diff --git a/node_modules/qs/.github/FUNDING.yml b/node_modules/qs/.github/FUNDING.yml
deleted file mode 100644
index 0355f4f..0000000
--- a/node_modules/qs/.github/FUNDING.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-# These are supported funding model platforms
-
-github: [ljharb]
-patreon: # Replace with a single Patreon username
-open_collective: # Replace with a single Open Collective username
-ko_fi: # Replace with a single Ko-fi username
-tidelift: npm/qs
-community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
-liberapay: # Replace with a single Liberapay username
-issuehunt: # Replace with a single IssueHunt username
-otechie: # Replace with a single Otechie username
-custom: # Replace with a single custom sponsorship URL
diff --git a/node_modules/qs/.github/SECURITY.md b/node_modules/qs/.github/SECURITY.md
deleted file mode 100644
index b499cb6..0000000
--- a/node_modules/qs/.github/SECURITY.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Security
-
-Please file a private vulnerability report via GitHub, email [@ljharb](https://github.com/ljharb), or see https://tidelift.com/security if you have a potential security vulnerability to report.
-
-## Incident Response Plan
-
-Please see our [Incident Response Plan](https://github.com/ljharb/.github/blob/main/INCIDENT_RESPONSE_PLAN.md).
-
-## Threat Model
-
-Please see [THREAT_MODEL.md](./THREAT_MODEL.md).
diff --git a/node_modules/qs/.github/THREAT_MODEL.md b/node_modules/qs/.github/THREAT_MODEL.md
deleted file mode 100644
index 7e6fef1..0000000
--- a/node_modules/qs/.github/THREAT_MODEL.md
+++ /dev/null
@@ -1,78 +0,0 @@
-## Threat Model for qs (querystring parsing library)
-
-### 1. Library Overview
-
-- **Library Name:** qs
-- **Brief Description:** A JavaScript library for parsing and stringifying URL query strings, supporting nested objects and arrays. It is widely used in Node.js and web applications for processing query parameters[2][6][8].
-- **Key Public APIs/Functions:** `qs.parse()`, `qs.stringify()`
-
-### 2. Define Scope
-
-This threat model focuses on the core parsing and stringifying functionality, specifically the handling of nested objects and arrays, option validation, and cycle management in stringification.
-
-### 3. Conceptual System Diagram
-
-```
-Caller Application → qs.parse(input, options) → Parsing Engine → Output Object
- │
- └→ Options Handling
-
-Caller Application → qs.stringify(obj, options) → Stringifying Engine → Output String
- │
- └→ Options Handling
- └→ Cycle Tracking
-```
-
-**Trust Boundaries:**
-- **Input string (parse):** May come from untrusted sources (e.g., user input, network requests)
-- **Input object (stringify):** May contain cycles, which can lead to infinite loops during stringification
-- **Options:** Provided by the caller
-- **Cycle Tracking:** Used only during stringification to detect and handle circular references
-
-### 4. Identify Assets
-
-- **Integrity of parsed output:** Prevent malicious manipulation of the output object structure, especially ensuring builtins/globals are not modified as a result of parse[3][4][8].
-- **Confidentiality of processed data:** Avoid leaking sensitive information through errors or output.
-- **Availability/performance for host application:** Prevent crashes or resource exhaustion in the consuming application.
-- **Security of host application:** Prevent the library from being a vector for attacks (e.g., prototype pollution, DoS).
-- **Reputation of library:** Maintain trust by avoiding supply chain attacks and vulnerabilities[1].
-
-### 5. Identify Threats
-
-| Component / API / Interaction | S | T | R | I | D | E |
-|---------------------------------------|----|----|----|----|----|----|
-| Public API Call (`parse`) | – | ✓ | – | ✓ | ✓ | ✓ |
-| Public API Call (`stringify`) | – | ✓ | – | ✓ | ✓ | – |
-| Options Handling | ✓ | ✓ | – | ✓ | – | ✓ |
-| Dependency Interaction | – | – | – | – | ✓ | – |
-
-**Key Threats:**
-- **Tampering:** Malicious input can, if not prevented, alter parsed output (e.g., prototype pollution via `__proto__`, modification of builtins/globals)[3][4][8].
-- **Information Disclosure:** Error messages may expose internal details or sensitive data.
-- **Denial of Service:** Large or malformed input can exhaust memory or CPU.
-- **Elevation of Privilege:** Prototype pollution can lead to unintended privilege escalation in the host application[3][4][8].
-
-### 6. Mitigation/Countermeasures
-
-| Threat Identified | Proposed Mitigation |
-|---------------------------------------------------|---------------------|
-| Tampering (malicious input, prototype pollution) | Strict input validation; keep `allowPrototypes: false` by default; use `plainObjects` for output; ensure builtins/globals are never modified by parse[4][8]. |
-| Information Disclosure (error messages) | Generic error messages without stack traces or internal paths. |
-| Denial of Service (memory/CPU exhaustion) | Enforce `arrayLimit` and `parameterLimit` with safe defaults; enable `throwOnLimitExceeded`; limit nesting depth[7]. |
-| Elevation of Privilege (prototype pollution) | Keep `allowPrototypes: false`; validate options against allowlist; use `plainObjects` to avoid prototype pollution[4][8]. |
-
-### 7. Risk Ranking
-
-- **High:** Denial of Service via array parsing or malformed input (historical vulnerability)
-- **Medium:** Prototype pollution via options or input (if `allowPrototypes` enabled)
-- **Low:** Information disclosure in errors
-
-### 8. Next Steps & Review
-
-1. **Audit option validation logic.**
-2. **Add depth limiting to nested parsing and stringification.**
-3. **Implement fuzz testing for parser and stringifier edge cases.**
-4. **Regularly review dependencies for vulnerabilities.**
-5. **Keep documentation and threat model up to date.**
-6. **Ensure builtins/globals are never modified as a result of parse.**
-7. **Support round-trip consistency between parse and stringify as a non-security goal, with the right options[5][9].**
diff --git a/node_modules/qs/.nycrc b/node_modules/qs/.nycrc
deleted file mode 100644
index 1d57cab..0000000
--- a/node_modules/qs/.nycrc
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "all": true,
- "check-coverage": false,
- "reporter": ["text-summary", "text", "html", "json"],
- "lines": 86,
- "statements": 85.93,
- "functions": 82.43,
- "branches": 76.06,
- "exclude": [
- "coverage",
- "dist"
- ]
-}
diff --git a/node_modules/qs/CHANGELOG.md b/node_modules/qs/CHANGELOG.md
deleted file mode 100644
index 14953a4..0000000
--- a/node_modules/qs/CHANGELOG.md
+++ /dev/null
@@ -1,833 +0,0 @@
-## **6.15.3**
-- [Fix] `parse`: enforce `throwOnLimitExceeded` for cumulative array growth via `combine`/`merge`
-- [Fix] `utils`: respect encoding of surrogate pairs across chunks (#559)
-- [Robustness] `parse`: throw the `arrayLimit` error before splitting oversized comma values
-- [Robustness] `utils.merge` / `utils.assign`: avoid invoking `__proto__` setter when copying own properties
-- [Robustness] `utils`: enforce `arrayLimit` consistently across `merge`'s array paths
-- [Perf] `utils`: make `compact` O(n) via a side-channel visited-set instead of `Array.indexOf`
-- [Deps] update `side-channel`
-- [Dev Deps] update `eslint`, `mock-property`, `tape`
-- [Tests] `parse`: characterize current lenient handling of unbalanced bracket keys (#558)
-
-## **6.15.2**
-- [Fix] `stringify`: skip null/undefined entries in `arrayFormat: 'comma'` + `encodeValuesOnly` instead of crashing in `encoder`
-- [Fix] `stringify`: use configured `delimiter` after `charsetSentinel` (#555)
-- [Fix] `stringify`: apply `formatter` to encoded key under `strictNullHandling` (#554)
-- [Fix] `stringify`: skip null/undefined filter-array entries instead of crashing in `encoder` (#551)
-- [Fix] `parse`: handle nested bracket groups and add regression tests (#530)
-- [readme] fix grammar (#550)
-- [Dev Deps] update `@ljharb/eslint-config`
-- [Tests] add regression tests for keys containing percent-encoded bracket text
-
-## **6.15.1**
-- [Fix] `parse`: `parameterLimit: Infinity` with `throwOnLimitExceeded: true` silently drops all parameters
-- [Deps] update `@ljharb/eslint-config`
-- [Dev Deps] update `@ljharb/eslint-config`, `iconv-lite`
-- [Tests] increase coverage
-
-## **6.15.0**
-- [New] `parse`: add `strictMerge` option to wrap object/primitive conflicts in an array (#425, #122)
-- [Fix] `duplicates` option should not apply to bracket notation keys (#514)
-
-## **6.14.2**
-- [Fix] `parse`: mark overflow objects for indexed notation exceeding `arrayLimit` (#546)
-- [Fix] `arrayLimit` means max count, not max index, in `combine`/`merge`/`parseArrayValue`
-- [Fix] `parse`: throw on `arrayLimit` exceeded with indexed notation when `throwOnLimitExceeded` is true (#529)
-- [Fix] `parse`: enforce `arrayLimit` on `comma`-parsed values
-- [Fix] `parse`: fix error message to reflect arrayLimit as max index; remove extraneous comments (#545)
-- [Robustness] avoid `.push`, use `void`
-- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
-- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
-- [readme] replace runkit CI badge with shields.io check-runs badge
-- [meta] fix changelog typo (`arrayLength` → `arrayLimit`)
-- [actions] fix rebase workflow permissions
-
-## **6.14.1**
-- [Fix] ensure `arrayLimit` applies to `[]` notation as well
-- [Fix] `parse`: when a custom decoder returns `null` for a key, ignore that key
-- [Refactor] `parse`: extract key segment splitting helper
-- [meta] add threat model
-- [actions] add workflow permissions
-- [Tests] `stringify`: increase coverage
-- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `npmignore`, `es-value-fixtures`, `for-each`, `object-inspect`
-
-## **6.14.0**
-- [New] `parse`: add `throwOnParameterLimitExceeded` option (#517)
-- [Refactor] `parse`: use `utils.combine` more
-- [patch] `parse`: add explicit `throwOnLimitExceeded` default
-- [actions] use shared action; re-add finishers
-- [meta] Fix changelog formatting bug
-- [Deps] update `side-channel`
-- [Dev Deps] update `es-value-fixtures`, `has-bigints`, `has-proto`, `has-symbols`
-- [Tests] increase coverage
-
-## **6.13.3**
-[Fix] fix regressions from robustness refactor
-[actions] update reusable workflows
-
-## **6.13.2**
-- [Robustness] avoid `.push`, use `void`
-- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
-- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
-- [readme] replace runkit CI badge with shields.io check-runs badge
-- [actions] fix rebase workflow permissions
-
-## **6.13.1**
-- [Fix] `stringify`: avoid a crash when a `filter` key is `null`
-- [Fix] `utils.merge`: functions should not be stringified into keys
-- [Fix] `parse`: avoid a crash with interpretNumericEntities: true, comma: true, and iso charset
-- [Fix] `stringify`: ensure a non-string `filter` does not crash
-- [Refactor] use `__proto__` syntax instead of `Object.create` for null objects
-- [Refactor] misc cleanup
-- [Tests] `utils.merge`: add some coverage
-- [Tests] fix a test case
-- [actions] split out node 10-20, and 20+
-- [Dev Deps] update `es-value-fixtures`, `mock-property`, `object-inspect`, `tape`
-
-## **6.13.0**
-- [New] `parse`: add `strictDepth` option (#511)
-- [Tests] use `npm audit` instead of `aud`
-
-## **6.12.5**
-- [Fix] fix regressions from robustness refactor
-- [actions] update reusable workflows
-
-## **6.12.4**
-- [Robustness] avoid `.push`, use `void`
-- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
-- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
-- [readme] replace runkit CI badge with shields.io check-runs badge
-- [actions] fix rebase workflow permissions
-
-## **6.12.3**
-- [Fix] `parse`: properly account for `strictNullHandling` when `allowEmptyArrays`
-- [meta] fix changelog indentation
-
-## **6.12.2**
-- [Fix] `parse`: parse encoded square brackets (#506)
-- [readme] add CII best practices badge
-
-## **6.12.1**
-- [Fix] `parse`: Disable `decodeDotInKeys` by default to restore previous behavior (#501)
-- [Performance] `utils`: Optimize performance under large data volumes, reduce memory usage, and speed up processing (#502)
-- [Refactor] `utils`: use `+=`
-- [Tests] increase coverage
-
-## **6.12.0**
-
-- [New] `parse`/`stringify`: add `decodeDotInKeys`/`encodeDotKeys` options (#488)
-- [New] `parse`: add `duplicates` option
-- [New] `parse`/`stringify`: add `allowEmptyArrays` option to allow [] in object values (#487)
-- [Refactor] `parse`/`stringify`: move allowDots config logic to its own variable
-- [Refactor] `stringify`: move option-handling code into `normalizeStringifyOptions`
-- [readme] update readme, add logos (#484)
-- [readme] `stringify`: clarify default `arrayFormat` behavior
-- [readme] fix line wrapping
-- [readme] remove dead badges
-- [Deps] update `side-channel`
-- [meta] make the dist build 50% smaller
-- [meta] add `sideEffects` flag
-- [meta] run build in prepack, not prepublish
-- [Tests] `parse`: remove useless tests; add coverage
-- [Tests] `stringify`: increase coverage
-- [Tests] use `mock-property`
-- [Tests] `stringify`: improve coverage
-- [Dev Deps] update `@ljharb/eslint-config `, `aud`, `has-override-mistake`, `has-property-descriptors`, `mock-property`, `npmignore`, `object-inspect`, `tape`
-- [Dev Deps] pin `glob`, since v10.3.8+ requires a broken `jackspeak`
-- [Dev Deps] pin `jackspeak` since 2.1.2+ depends on npm aliases, which kill the install process in npm < 6
-
-## **6.11.4**
-- [Fix] fix regressions from robustness refactor
-- [actions] update reusable workflows
-
-## **6.11.3**
-- [Robustness] avoid `.push`, use `void`
-- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
-- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
-- [readme] replace runkit CI badge with shields.io check-runs badge
-- [actions] fix rebase workflow permissions
-
-## **6.11.2**
-- [Fix] `parse`: Fix parsing when the global Object prototype is frozen (#473)
-- [Tests] add passing test cases with empty keys (#473)
-
-## **6.11.1**
-- [Fix] `stringify`: encode comma values more consistently (#463)
-- [readme] add usage of `filter` option for injecting custom serialization, i.e. of custom types (#447)
-- [meta] remove extraneous code backticks (#457)
-- [meta] fix changelog markdown
-- [actions] update checkout action
-- [actions] restrict action permissions
-- [Dev Deps] update `@ljharb/eslint-config`, `aud`, `object-inspect`, `tape`
-
-## **6.11.0**
-- [New] [Fix] `stringify`: revert 0e903c0; add `commaRoundTrip` option (#442)
-- [readme] fix version badge
-
-## **6.10.7**
-- [Fix] fix regressions from robustness refactor
-- [actions] update reusable workflows
-
-## **6.10.6**
-- [Robustness] avoid `.push`, use `void`
-- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
-- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
-- [readme] replace runkit CI badge with shields.io check-runs badge
-- [actions] fix rebase workflow permissions
-
-## **6.10.5**
-- [Fix] `stringify`: with `arrayFormat: comma`, properly include an explicit `[]` on a single-item array (#434)
-
-## **6.10.4**
-- [Fix] `stringify`: with `arrayFormat: comma`, include an explicit `[]` on a single-item array (#441)
-- [meta] use `npmignore` to autogenerate an npmignore file
-- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `has-symbol`, `object-inspect`, `tape`
-
-## **6.10.3**
-- [Fix] `parse`: ignore `__proto__` keys (#428)
-- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
-- [actions] reuse common workflows
-- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `object-inspect`, `tape`
-
-## **6.10.2**
-- [Fix] `stringify`: actually fix cyclic references (#426)
-- [Fix] `stringify`: avoid encoding arrayformat comma when `encodeValuesOnly = true` (#424)
-- [readme] remove travis badge; add github actions/codecov badges; update URLs
-- [Docs] add note and links for coercing primitive values (#408)
-- [actions] update codecov uploader
-- [actions] update workflows
-- [Tests] clean up stringify tests slightly
-- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `object-inspect`, `safe-publish-latest`, `tape`
-
-## **6.10.1**
-- [Fix] `stringify`: avoid exception on repeated object values (#402)
-
-## **6.10.0**
-- [New] `stringify`: throw on cycles, instead of an infinite loop (#395, #394, #393)
-- [New] `parse`: add `allowSparse` option for collapsing arrays with missing indices (#312)
-- [meta] fix README.md (#399)
-- [meta] only run `npm run dist` in publish, not install
-- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `has-symbols`, `tape`
-- [Tests] fix tests on node v0.6
-- [Tests] use `ljharb/actions/node/install` instead of `ljharb/actions/node/run`
-- [Tests] Revert "[meta] ignore eclint transitive audit warning"
-
-## **6.9.9**
-- [Fix] fix regressions from robustness refactor
-- [meta] add `npmignore` to autogenerate an npmignore file
-- [actions] update reusable workflows
-
-## **6.9.8**
-- [Robustness] avoid `.push`, use `void`
-- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
-- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
-- [readme] replace runkit CI badge with shields.io check-runs badge
-- [actions] fix rebase workflow permissions
-
-## **6.9.7**
-- [Fix] `parse`: ignore `__proto__` keys (#428)
-- [Fix] `stringify`: avoid encoding arrayformat comma when `encodeValuesOnly = true` (#424)
-- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
-- [readme] remove travis badge; add github actions/codecov badges; update URLs
-- [Docs] add note and links for coercing primitive values (#408)
-- [Tests] clean up stringify tests slightly
-- [meta] fix README.md (#399)
-- Revert "[meta] ignore eclint transitive audit warning"
-- [actions] backport actions from main
-- [Dev Deps] backport updates from main
-
-## **6.9.6**
-- [Fix] restore `dist` dir; mistakenly removed in d4f6c32
-
-## **6.9.5**
-- [Fix] `stringify`: do not encode parens for RFC1738
-- [Fix] `stringify`: fix arrayFormat comma with empty array/objects (#350)
-- [Refactor] `format`: remove `util.assign` call
-- [meta] add "Allow Edits" workflow; update rebase workflow
-- [actions] switch Automatic Rebase workflow to `pull_request_target` event
-- [Tests] `stringify`: add tests for #378
-- [Tests] migrate tests to Github Actions
-- [Tests] run `nyc` on all tests; use `tape` runner
-- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `browserify`, `mkdirp`, `object-inspect`, `tape`; add `aud`
-
-## **6.9.4**
-- [Fix] `stringify`: when `arrayFormat` is `comma`, respect `serializeDate` (#364)
-- [Refactor] `stringify`: reduce branching (part of #350)
-- [Refactor] move `maybeMap` to `utils`
-- [Dev Deps] update `browserify`, `tape`
-
-## **6.9.3**
-- [Fix] proper comma parsing of URL-encoded commas (#361)
-- [Fix] parses comma delimited array while having percent-encoded comma treated as normal text (#336)
-
-## **6.9.2**
-- [Fix] `parse`: Fix parsing array from object with `comma` true (#359)
-- [Fix] `parse`: throw a TypeError instead of an Error for bad charset (#349)
-- [meta] ignore eclint transitive audit warning
-- [meta] fix indentation in package.json
-- [meta] add tidelift marketing copy
-- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `object-inspect`, `has-symbols`, `tape`, `mkdirp`, `iconv-lite`
-- [actions] add automatic rebasing / merge commit blocking
-
-## **6.9.1**
-- [Fix] `parse`: with comma true, handle field that holds an array of arrays (#335)
-- [Fix] `parse`: with comma true, do not split non-string values (#334)
-- [meta] add `funding` field
-- [Dev Deps] update `eslint`, `@ljharb/eslint-config`
-- [Tests] use shared travis-ci config
-
-## **6.9.0**
-- [New] `parse`/`stringify`: Pass extra key/value argument to `decoder` (#333)
-- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `evalmd`
-- [Tests] `parse`: add passing `arrayFormat` tests
-- [Tests] add `posttest` using `npx aud` to run `npm audit` without a lockfile
-- [Tests] up to `node` `v12.10`, `v11.15`, `v10.16`, `v8.16`
-- [Tests] `Buffer.from` in node v5.0-v5.9 and v4.0-v4.4 requires a TypedArray
-
-## **6.8.5**
-- [Fix] fix regressions from robustness refactor
-- [meta] add `npmignore` to autogenerate an npmignore file
-- [actions] update reusable workflows
-
-## **6.8.4**
-- [Robustness] avoid `.push`, use `void`
-- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
-- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
-- [readme] replace runkit CI badge with shields.io check-runs badge
-- [actions] fix rebase workflow permissions
-
-## **6.8.3**
-- [Fix] `parse`: ignore `__proto__` keys (#428)
-- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
-- [Fix] `stringify`: avoid encoding arrayformat comma when `encodeValuesOnly = true` (#424)
-- [readme] remove travis badge; add github actions/codecov badges; update URLs
-- [Tests] clean up stringify tests slightly
-- [Docs] add note and links for coercing primitive values (#408)
-- [meta] fix README.md (#399)
-- [actions] backport actions from main
-- [Dev Deps] backport updates from main
-- [Refactor] `stringify`: reduce branching
-- [meta] do not publish workflow files
-
-## **6.8.2**
-- [Fix] proper comma parsing of URL-encoded commas (#361)
-- [Fix] parses comma delimited array while having percent-encoded comma treated as normal text (#336)
-
-## **6.8.1**
-- [Fix] `parse`: Fix parsing array from object with `comma` true (#359)
-- [Fix] `parse`: throw a TypeError instead of an Error for bad charset (#349)
-- [Fix] `parse`: with comma true, handle field that holds an array of arrays (#335)
-- [fix] `parse`: with comma true, do not split non-string values (#334)
-- [meta] add tidelift marketing copy
-- [meta] add `funding` field
-- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `tape`, `safe-publish-latest`, `evalmd`, `has-symbols`, `iconv-lite`, `mkdirp`, `object-inspect`
-- [Tests] `parse`: add passing `arrayFormat` tests
-- [Tests] use shared travis-ci configs
-- [Tests] `Buffer.from` in node v5.0-v5.9 and v4.0-v4.4 requires a TypedArray
-- [actions] add automatic rebasing / merge commit blocking
-
-## **6.8.0**
-- [New] add `depth=false` to preserve the original key; [Fix] `depth=0` should preserve the original key (#326)
-- [New] [Fix] stringify symbols and bigints
-- [Fix] ensure node 0.12 can stringify Symbols
-- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
-- [Refactor] `formats`: tiny bit of cleanup.
-- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `browserify`, `safe-publish-latest`, `iconv-lite`, `tape`
-- [Tests] add tests for `depth=0` and `depth=false` behavior, both current and intuitive/intended (#326)
-- [Tests] use `eclint` instead of `editorconfig-tools`
-- [docs] readme: add security note
-- [meta] add github sponsorship
-- [meta] add FUNDING.yml
-- [meta] Clean up license text so it’s properly detected as BSD-3-Clause
-
-## **6.7.5**
-- [Fix] fix regressions from robustness refactor
-- [meta] add `npmignore` to autogenerate an npmignore file
-- [actions] update reusable workflows
-
-## **6.7.4**
-- [Robustness] avoid `.push`, use `void`
-- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
-- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
-- [readme] replace runkit CI badge with shields.io check-runs badge
-- [actions] fix rebase workflow permissions
-
-## **6.7.3**
-- [Fix] `parse`: ignore `__proto__` keys (#428)
-- [Fix] `stringify`: avoid encoding arrayformat comma when `encodeValuesOnly = true` (#424)
-- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
-- [readme] remove travis badge; add github actions/codecov badges; update URLs
-- [Docs] add note and links for coercing primitive values (#408)
-- [meta] fix README.md (#399)
-- [meta] do not publish workflow files
-- [actions] backport actions from main
-- [Dev Deps] backport updates from main
-- [Tests] use `nyc` for coverage
-- [Tests] clean up stringify tests slightly
-
-## **6.7.2**
-- [Fix] proper comma parsing of URL-encoded commas (#361)
-- [Fix] parses comma delimited array while having percent-encoded comma treated as normal text (#336)
-
-## **6.7.1**
-- [Fix] `parse`: Fix parsing array from object with `comma` true (#359)
-- [Fix] `parse`: with comma true, handle field that holds an array of arrays (#335)
-- [fix] `parse`: with comma true, do not split non-string values (#334)
-- [Fix] `parse`: throw a TypeError instead of an Error for bad charset (#349)
-- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
-- [Refactor] `formats`: tiny bit of cleanup.
-- readme: add security note
-- [meta] add tidelift marketing copy
-- [meta] add `funding` field
-- [meta] add FUNDING.yml
-- [meta] Clean up license text so it’s properly detected as BSD-3-Clause
-- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `tape`, `safe-publish-latest`, `evalmd`, `iconv-lite`, `mkdirp`, `object-inspect`, `browserify`
-- [Tests] `parse`: add passing `arrayFormat` tests
-- [Tests] use shared travis-ci configs
-- [Tests] `Buffer.from` in node v5.0-v5.9 and v4.0-v4.4 requires a TypedArray
-- [Tests] add tests for `depth=0` and `depth=false` behavior, both current and intuitive/intended
-- [Tests] use `eclint` instead of `editorconfig-tools`
-- [actions] add automatic rebasing / merge commit blocking
-
-## **6.7.0**
-- [New] `stringify`/`parse`: add `comma` as an `arrayFormat` option (#276, #219)
-- [Fix] correctly parse nested arrays (#212)
-- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source, also with an array source
-- [Robustness] `stringify`: cache `Object.prototype.hasOwnProperty`
-- [Refactor] `utils`: `isBuffer`: small tweak; add tests
-- [Refactor] use cached `Array.isArray`
-- [Refactor] `parse`/`stringify`: make a function to normalize the options
-- [Refactor] `utils`: reduce observable [[Get]]s
-- [Refactor] `stringify`/`utils`: cache `Array.isArray`
-- [Tests] always use `String(x)` over `x.toString()`
-- [Tests] fix Buffer tests to work in node < 4.5 and node < 5.10
-- [Tests] temporarily allow coverage to fail
-
-## **6.6.3**
-- [Fix] fix regressions from robustness refactor
-- [meta] add `npmignore` to autogenerate an npmignore file
-- [actions] update reusable workflows
-
-## **6.6.2**
-- [Robustness] avoid `.push`, use `void`
-- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
-- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
-- [readme] replace runkit CI badge with shields.io check-runs badge
-- [actions] fix rebase workflow permissions
-
-## **6.6.1**
-- [Fix] `parse`: ignore `__proto__` keys (#428)
-- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
-- [Fix] `utils.merge`: avoid a crash with a null target and an array source
-- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source
-- [Fix] correctly parse nested arrays
-- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
-- [Robustness] `stringify`: cache `Object.prototype.hasOwnProperty`
-- [Refactor] `formats`: tiny bit of cleanup.
-- [Refactor] `utils`: `isBuffer`: small tweak; add tests
-- [Refactor]: `stringify`/`utils`: cache `Array.isArray`
-- [Refactor] `utils`: reduce observable [[Get]]s
-- [Refactor] use cached `Array.isArray`
-- [Refactor] `parse`/`stringify`: make a function to normalize the options
-- [readme] remove travis badge; add github actions/codecov badges; update URLs
-- [Docs] Clarify the need for "arrayLimit" option
-- [meta] fix README.md (#399)
-- [meta] do not publish workflow files
-- [meta] Clean up license text so it’s properly detected as BSD-3-Clause
-- [meta] add FUNDING.yml
-- [meta] Fixes typo in CHANGELOG.md
-- [actions] backport actions from main
-- [Tests] fix Buffer tests to work in node < 4.5 and node < 5.10
-- [Tests] always use `String(x)` over `x.toString()`
-- [Dev Deps] backport from main
-
-## **6.6.0**
-- [New] Add support for iso-8859-1, utf8 "sentinel" and numeric entities (#268)
-- [New] move two-value combine to a `utils` function (#189)
-- [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279)
-- [Fix] when `parseArrays` is false, properly handle keys ending in `[]` (#260)
-- [Fix] `stringify`: do not crash in an obscure combo of `interpretNumericEntities`, a bad custom `decoder`, & `iso-8859-1`
-- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided
-- [refactor] `stringify`: Avoid arr = arr.concat(...), push to the existing instance (#269)
-- [Refactor] `parse`: only need to reassign the var once
-- [Refactor] `parse`/`stringify`: clean up `charset` options checking; fix defaults
-- [Refactor] add missing defaults
-- [Refactor] `parse`: one less `concat` call
-- [Refactor] `utils`: `compactQueue`: make it explicitly side-effecting
-- [Dev Deps] update `browserify`, `eslint`, `@ljharb/eslint-config`, `iconv-lite`, `safe-publish-latest`, `tape`
-- [Tests] up to `node` `v10.10`, `v9.11`, `v8.12`, `v6.14`, `v4.9`; pin included builds to LTS
-
-## **6.5.5**
-- [Fix] fix regressions from robustness refactor
-- [meta] add `npmignore` to autogenerate an npmignore file
-- [actions] update reusable workflows
-
-## **6.5.4**
-- [Robustness] avoid `.push`, use `void`
-- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
-- [readme] document that `addQueryPrefix` does not add `?` to empty output (#418)
-- [readme] replace runkit CI badge with shields.io check-runs badge
-- [actions] fix rebase workflow permissions
-
-## **6.5.3**
-- [Fix] `parse`: ignore `__proto__` keys (#428)
-- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source
-- [Fix] correctly parse nested arrays
-- [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279)
-- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided
-- [Fix] when `parseArrays` is false, properly handle keys ending in `[]`
-- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
-- [Fix] `utils.merge`: avoid a crash with a null target and an array source
-- [Refactor] `utils`: reduce observable [[Get]]s
-- [Refactor] use cached `Array.isArray`
-- [Refactor] `stringify`: Avoid arr = arr.concat(...), push to the existing instance (#269)
-- [Refactor] `parse`: only need to reassign the var once
-- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
-- [readme] remove travis badge; add github actions/codecov badges; update URLs
-- [Docs] Clean up license text so it’s properly detected as BSD-3-Clause
-- [Docs] Clarify the need for "arrayLimit" option
-- [meta] fix README.md (#399)
-- [meta] add FUNDING.yml
-- [actions] backport actions from main
-- [Tests] always use `String(x)` over `x.toString()`
-- [Tests] remove nonexistent tape option
-- [Dev Deps] backport from main
-
-## **6.5.2**
-- [Fix] use `safer-buffer` instead of `Buffer` constructor
-- [Refactor] utils: `module.exports` one thing, instead of mutating `exports` (#230)
-- [Dev Deps] update `browserify`, `eslint`, `iconv-lite`, `safer-buffer`, `tape`, `browserify`
-
-## **6.5.1**
-- [Fix] Fix parsing & compacting very deep objects (#224)
-- [Refactor] name utils functions
-- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `tape`
-- [Tests] up to `node` `v8.4`; use `nvm install-latest-npm` so newer npm doesn’t break older node
-- [Tests] Use precise dist for Node.js 0.6 runtime (#225)
-- [Tests] make 0.6 required, now that it’s passing
-- [Tests] on `node` `v8.2`; fix npm on node 0.6
-
-## **6.5.0**
-- [New] add `utils.assign`
-- [New] pass default encoder/decoder to custom encoder/decoder functions (#206)
-- [New] `parse`/`stringify`: add `ignoreQueryPrefix`/`addQueryPrefix` options, respectively (#213)
-- [Fix] Handle stringifying empty objects with addQueryPrefix (#217)
-- [Fix] do not mutate `options` argument (#207)
-- [Refactor] `parse`: cache index to reuse in else statement (#182)
-- [Docs] add various badges to readme (#208)
-- [Dev Deps] update `eslint`, `browserify`, `iconv-lite`, `tape`
-- [Tests] up to `node` `v8.1`, `v7.10`, `v6.11`; npm v4.6 breaks on node < v1; npm v5+ breaks on node < v4
-- [Tests] add `editorconfig-tools`
-
-## **6.4.3**
-- [Fix] fix regressions from robustness refactor
-- [meta] add `npmignore` to autogenerate an npmignore file
-- [actions] update reusable workflows
-
-## **6.4.2**
-- [Robustness] avoid `.push`, use `void`
-- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
-- [readme] replace runkit CI badge with shields.io check-runs badge
-- [readme] replace travis CI badge with shields.io check-runs badge
-- [actions] fix rebase workflow permissions
-
-## **6.4.1**
-- [Fix] `parse`: ignore `__proto__` keys (#428)
-- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
-- [Fix] use `safer-buffer` instead of `Buffer` constructor
-- [Fix] `utils.merge`: avoid a crash with a null target and an array source
-- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source
-- [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279)
-- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided
-- [Fix] when `parseArrays` is false, properly handle keys ending in `[]`
-- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
-- [Refactor] use cached `Array.isArray`
-- [Refactor] `stringify`: Avoid arr = arr.concat(...), push to the existing instance (#269)
-- [readme] remove travis badge; add github actions/codecov badges; update URLs
-- [Docs] Clarify the need for "arrayLimit" option
-- [meta] fix README.md (#399)
-- [meta] Clean up license text so it’s properly detected as BSD-3-Clause
-- [meta] add FUNDING.yml
-- [actions] backport actions from main
-- [Tests] remove nonexistent tape option
-- [Dev Deps] backport from main
-
-## **6.4.0**
-- [New] `qs.stringify`: add `encodeValuesOnly` option
-- [Fix] follow `allowPrototypes` option during merge (#201, #201)
-- [Fix] support keys starting with brackets (#202, #200)
-- [Fix] chmod a-x
-- [Dev Deps] update `eslint`
-- [Tests] up to `node` `v7.7`, `v6.10`,` v4.8`; disable osx builds since they block linux builds
-- [eslint] reduce warnings
-
-## **6.3.5**
-- [Fix] fix regressions from robustness refactor
-- [meta] add `npmignore` to autogenerate an npmignore file
-- [actions] update reusable workflows
-
-## **6.3.4**
-- [Robustness] avoid `.push`, use `void`
-- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
-- [readme] replace travis CI badge with shields.io check-runs badge
-- [actions] fix rebase workflow permissions
-
-## **6.3.3**
-- [Fix] `parse`: ignore `__proto__` keys (#428)
-- [Fix] fix for an impossible situation: when the formatter is called with a non-string value
-- [Fix] `utils.merge`: avoid a crash with a null target and an array source
-- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source
-- [Fix] `stringify`: fix a crash with `strictNullHandling` and a custom `filter`/`serializeDate` (#279)
-- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided
-- [Fix] when `parseArrays` is false, properly handle keys ending in `[]`
-- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
-- [Refactor] use cached `Array.isArray`
-- [Refactor] `stringify`: Avoid arr = arr.concat(...), push to the existing instance (#269)
-- [Docs] Clarify the need for "arrayLimit" option
-- [meta] fix README.md (#399)
-- [meta] Clean up license text so it’s properly detected as BSD-3-Clause
-- [meta] add FUNDING.yml
-- [actions] backport actions from main
-- [Tests] use `safer-buffer` instead of `Buffer` constructor
-- [Tests] remove nonexistent tape option
-- [Dev Deps] backport from main
-
-## **6.3.2**
-- [Fix] follow `allowPrototypes` option during merge (#201, #200)
-- [Dev Deps] update `eslint`
-- [Fix] chmod a-x
-- [Fix] support keys starting with brackets (#202, #200)
-- [Tests] up to `node` `v7.7`, `v6.10`,` v4.8`; disable osx builds since they block linux builds
-
-## **6.3.1**
-- [Fix] ensure that `allowPrototypes: false` does not ever shadow Object.prototype properties (thanks, @snyk!)
-- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `browserify`, `iconv-lite`, `qs-iconv`, `tape`
-- [Tests] on all node minors; improve test matrix
-- [Docs] document stringify option `allowDots` (#195)
-- [Docs] add empty object and array values example (#195)
-- [Docs] Fix minor inconsistency/typo (#192)
-- [Docs] document stringify option `sort` (#191)
-- [Refactor] `stringify`: throw faster with an invalid encoder
-- [Refactor] remove unnecessary escapes (#184)
-- Remove contributing.md, since `qs` is no longer part of `hapi` (#183)
-
-## **6.3.0**
-- [New] Add support for RFC 1738 (#174, #173)
-- [New] `stringify`: Add `serializeDate` option to customize Date serialization (#159)
-- [Fix] ensure `utils.merge` handles merging two arrays
-- [Refactor] only constructors should be capitalized
-- [Refactor] capitalized var names are for constructors only
-- [Refactor] avoid using a sparse array
-- [Robustness] `formats`: cache `String#replace`
-- [Dev Deps] update `browserify`, `eslint`, `@ljharb/eslint-config`; add `safe-publish-latest`
-- [Tests] up to `node` `v6.8`, `v4.6`; improve test matrix
-- [Tests] flesh out arrayLimit/arrayFormat tests (#107)
-- [Tests] skip Object.create tests when null objects are not available
-- [Tests] Turn on eslint for test files (#175)
-
-## **6.2.6**
-- [Fix] fix regression from robustness refactor
-- [meta] add `npmignore` to autogenerate an npmignore file
-- [actions] update reusable workflows
-
-## **6.2.5**
-- [Robustness] avoid `.push`, use `void`
-- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
-- [readme] replace travis CI badge with shields.io check-runs badge
-- [actions] fix rebase workflow permissions
-
-## **6.2.4**
-- [Fix] `parse`: ignore `__proto__` keys (#428)
-- [Fix] `utils.merge`: avoid a crash with a null target and an array source
-- [Fix] `utils.merge`: avoid a crash with a null target and a truthy non-array source
-- [Fix] `utils`: `merge`: fix crash when `source` is a truthy primitive & no options are provided
-- [Fix] when `parseArrays` is false, properly handle keys ending in `[]`
-- [Robustness] `stringify`: avoid relying on a global `undefined` (#427)
-- [Refactor] use cached `Array.isArray`
-- [Docs] Clarify the need for "arrayLimit" option
-- [meta] fix README.md (#399)
-- [meta] Clean up license text so it’s properly detected as BSD-3-Clause
-- [meta] add FUNDING.yml
-- [actions] backport actions from main
-- [Tests] use `safer-buffer` instead of `Buffer` constructor
-- [Tests] remove nonexistent tape option
-- [Dev Deps] backport from main
-
-## **6.2.3**
-- [Fix] follow `allowPrototypes` option during merge (#201, #200)
-- [Fix] chmod a-x
-- [Fix] support keys starting with brackets (#202, #200)
-- [Tests] up to `node` `v7.7`, `v6.10`,` v4.8`; disable osx builds since they block linux builds
-
-## **6.2.2**
-- [Fix] ensure that `allowPrototypes: false` does not ever shadow Object.prototype properties
-
-## **6.2.1**
-- [Fix] ensure `key[]=x&key[]&key[]=y` results in 3, not 2, values
-- [Refactor] Be explicit and use `Object.prototype.hasOwnProperty.call`
-- [Tests] remove `parallelshell` since it does not reliably report failures
-- [Tests] up to `node` `v6.3`, `v5.12`
-- [Dev Deps] update `tape`, `eslint`, `@ljharb/eslint-config`, `qs-iconv`
-
-## [**6.2.0**](https://github.com/ljharb/qs/issues?milestone=36&state=closed)
-- [New] pass Buffers to the encoder/decoder directly (#161)
-- [New] add "encoder" and "decoder" options, for custom param encoding/decoding (#160)
-- [Fix] fix compacting of nested sparse arrays (#150)
-
-## **6.1.4**
-- [Fix] fix regression from robustness refactor
-- [meta] add `npmignore` to autogenerate an npmignore file
-- [actions] update reusable workflows
-
-## **6.1.3**
-- [Robustness] avoid `.push`, use `void`
-- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
-- [readme] replace travis CI badge with shields.io check-runs badge
-
-## **6.1.2**
-- [Fix] follow `allowPrototypes` option during merge (#201, #200)
-- [Fix] chmod a-x
-- [Fix] support keys starting with brackets (#202, #200)
-- [Tests] up to `node` `v7.7`, `v6.10`,` v4.8`; disable osx builds since they block linux builds
-
-## **6.1.1**
-- [Fix] ensure that `allowPrototypes: false` does not ever shadow Object.prototype properties
-
-## [**6.1.0**](https://github.com/ljharb/qs/issues?milestone=35&state=closed)
-- [New] allowDots option for `stringify` (#151)
-- [Fix] "sort" option should work at a depth of 3 or more (#151)
-- [Fix] Restore `dist` directory; will be removed in v7 (#148)
-
-## **6.0.6**
-- [Fix] fix regression from robustness refactor
-- [meta] add `npmignore` to autogenerate an npmignore file
-- [actions] update reusable workflows
-
-## **6.0.5**
-- [Robustness] avoid `.push`, use `void`
-- [readme] clarify `parseArrays` and `arrayLimit` documentation (#543)
-- [readme] replace travis CI badge with shields.io check-runs badge
-
-## **6.0.4**
-- [Fix] follow `allowPrototypes` option during merge (#201, #200)
-- [Fix] chmod a-x
-- [Fix] support keys starting with brackets (#202, #200)
-- [Tests] up to `node` `v7.7`, `v6.10`,` v4.8`; disable osx builds since they block linux builds
-
-## **6.0.3**
-- [Fix] ensure that `allowPrototypes: false` does not ever shadow Object.prototype properties
-- [Fix] Restore `dist` directory; will be removed in v7 (#148)
-
-## [**6.0.2**](https://github.com/ljharb/qs/issues?milestone=33&state=closed)
-- Revert ES6 requirement and restore support for node down to v0.8.
-
-## [**6.0.1**](https://github.com/ljharb/qs/issues?milestone=32&state=closed)
-- [**#127**](https://github.com/ljharb/qs/pull/127) Fix engines definition in package.json
-
-## [**6.0.0**](https://github.com/ljharb/qs/issues?milestone=31&state=closed)
-- [**#124**](https://github.com/ljharb/qs/issues/124) Use ES6 and drop support for node < v4
-
-## **5.2.1**
-- [Fix] ensure `key[]=x&key[]&key[]=y` results in 3, not 2, values
-
-## [**5.2.0**](https://github.com/ljharb/qs/issues?milestone=30&state=closed)
-- [**#64**](https://github.com/ljharb/qs/issues/64) Add option to sort object keys in the query string
-
-## [**5.1.0**](https://github.com/ljharb/qs/issues?milestone=29&state=closed)
-- [**#117**](https://github.com/ljharb/qs/issues/117) make URI encoding stringified results optional
-- [**#106**](https://github.com/ljharb/qs/issues/106) Add flag `skipNulls` to optionally skip null values in stringify
-
-## [**5.0.0**](https://github.com/ljharb/qs/issues?milestone=28&state=closed)
-- [**#114**](https://github.com/ljharb/qs/issues/114) default allowDots to false
-- [**#100**](https://github.com/ljharb/qs/issues/100) include dist to npm
-
-## [**4.0.0**](https://github.com/ljharb/qs/issues?milestone=26&state=closed)
-- [**#98**](https://github.com/ljharb/qs/issues/98) make returning plain objects and allowing prototype overwriting properties optional
-
-## [**3.1.0**](https://github.com/ljharb/qs/issues?milestone=24&state=closed)
-- [**#89**](https://github.com/ljharb/qs/issues/89) Add option to disable "Transform dot notation to bracket notation"
-
-## [**3.0.0**](https://github.com/ljharb/qs/issues?milestone=23&state=closed)
-- [**#80**](https://github.com/ljharb/qs/issues/80) qs.parse silently drops properties
-- [**#77**](https://github.com/ljharb/qs/issues/77) Perf boost
-- [**#60**](https://github.com/ljharb/qs/issues/60) Add explicit option to disable array parsing
-- [**#74**](https://github.com/ljharb/qs/issues/74) Bad parse when turning array into object
-- [**#81**](https://github.com/ljharb/qs/issues/81) Add a `filter` option
-- [**#68**](https://github.com/ljharb/qs/issues/68) Fixed issue with recursion and passing strings into objects.
-- [**#66**](https://github.com/ljharb/qs/issues/66) Add mixed array and object dot notation support Closes: #47
-- [**#76**](https://github.com/ljharb/qs/issues/76) RFC 3986
-- [**#85**](https://github.com/ljharb/qs/issues/85) No equal sign
-- [**#84**](https://github.com/ljharb/qs/issues/84) update license attribute
-
-## [**2.4.1**](https://github.com/ljharb/qs/issues?milestone=20&state=closed)
-- [**#73**](https://github.com/ljharb/qs/issues/73) Property 'hasOwnProperty' of object #<Object> is not a function
-
-## [**2.4.0**](https://github.com/ljharb/qs/issues?milestone=19&state=closed)
-- [**#70**](https://github.com/ljharb/qs/issues/70) Add arrayFormat option
-
-## [**2.3.3**](https://github.com/ljharb/qs/issues?milestone=18&state=closed)
-- [**#59**](https://github.com/ljharb/qs/issues/59) make sure array indexes are >= 0, closes #57
-- [**#58**](https://github.com/ljharb/qs/issues/58) make qs usable for browser loader
-
-## [**2.3.2**](https://github.com/ljharb/qs/issues?milestone=17&state=closed)
-- [**#55**](https://github.com/ljharb/qs/issues/55) allow merging a string into an object
-
-## [**2.3.1**](https://github.com/ljharb/qs/issues?milestone=16&state=closed)
-- [**#52**](https://github.com/ljharb/qs/issues/52) Return "undefined" and "false" instead of throwing "TypeError".
-
-## [**2.3.0**](https://github.com/ljharb/qs/issues?milestone=15&state=closed)
-- [**#50**](https://github.com/ljharb/qs/issues/50) add option to omit array indices, closes #46
-
-## [**2.2.5**](https://github.com/ljharb/qs/issues?milestone=14&state=closed)
-- [**#39**](https://github.com/ljharb/qs/issues/39) Is there an alternative to Buffer.isBuffer?
-- [**#49**](https://github.com/ljharb/qs/issues/49) refactor utils.merge, fixes #45
-- [**#41**](https://github.com/ljharb/qs/issues/41) avoid browserifying Buffer, for #39
-
-## [**2.2.4**](https://github.com/ljharb/qs/issues?milestone=13&state=closed)
-- [**#38**](https://github.com/ljharb/qs/issues/38) how to handle object keys beginning with a number
-
-## [**2.2.3**](https://github.com/ljharb/qs/issues?milestone=12&state=closed)
-- [**#37**](https://github.com/ljharb/qs/issues/37) parser discards first empty value in array
-- [**#36**](https://github.com/ljharb/qs/issues/36) Update to lab 4.x
-
-## [**2.2.2**](https://github.com/ljharb/qs/issues?milestone=11&state=closed)
-- [**#33**](https://github.com/ljharb/qs/issues/33) Error when plain object in a value
-- [**#34**](https://github.com/ljharb/qs/issues/34) use Object.prototype.hasOwnProperty.call instead of obj.hasOwnProperty
-- [**#24**](https://github.com/ljharb/qs/issues/24) Changelog? Semver?
-
-## [**2.2.1**](https://github.com/ljharb/qs/issues?milestone=10&state=closed)
-- [**#32**](https://github.com/ljharb/qs/issues/32) account for circular references properly, closes #31
-- [**#31**](https://github.com/ljharb/qs/issues/31) qs.parse stackoverflow on circular objects
-
-## [**2.2.0**](https://github.com/ljharb/qs/issues?milestone=9&state=closed)
-- [**#26**](https://github.com/ljharb/qs/issues/26) Don't use Buffer global if it's not present
-- [**#30**](https://github.com/ljharb/qs/issues/30) Bug when merging non-object values into arrays
-- [**#29**](https://github.com/ljharb/qs/issues/29) Don't call Utils.clone at the top of Utils.merge
-- [**#23**](https://github.com/ljharb/qs/issues/23) Ability to not limit parameters?
-
-## [**2.1.0**](https://github.com/ljharb/qs/issues?milestone=8&state=closed)
-- [**#22**](https://github.com/ljharb/qs/issues/22) Enable using a RegExp as delimiter
-
-## [**2.0.0**](https://github.com/ljharb/qs/issues?milestone=7&state=closed)
-- [**#18**](https://github.com/ljharb/qs/issues/18) Why is there arrayLimit?
-- [**#20**](https://github.com/ljharb/qs/issues/20) Configurable parametersLimit
-- [**#21**](https://github.com/ljharb/qs/issues/21) make all limits optional, for #18, for #20
-
-## [**1.2.2**](https://github.com/ljharb/qs/issues?milestone=6&state=closed)
-- [**#19**](https://github.com/ljharb/qs/issues/19) Don't overwrite null values
-
-## [**1.2.1**](https://github.com/ljharb/qs/issues?milestone=5&state=closed)
-- [**#16**](https://github.com/ljharb/qs/issues/16) ignore non-string delimiters
-- [**#15**](https://github.com/ljharb/qs/issues/15) Close code block
-
-## [**1.2.0**](https://github.com/ljharb/qs/issues?milestone=4&state=closed)
-- [**#12**](https://github.com/ljharb/qs/issues/12) Add optional delim argument
-- [**#13**](https://github.com/ljharb/qs/issues/13) fix #11: flattened keys in array are now correctly parsed
-
-## [**1.1.0**](https://github.com/ljharb/qs/issues?milestone=3&state=closed)
-- [**#7**](https://github.com/ljharb/qs/issues/7) Empty values of a POST array disappear after being submitted
-- [**#9**](https://github.com/ljharb/qs/issues/9) Should not omit equals signs (=) when value is null
-- [**#6**](https://github.com/ljharb/qs/issues/6) Minor grammar fix in README
-
-## [**1.0.2**](https://github.com/ljharb/qs/issues?milestone=2&state=closed)
-- [**#5**](https://github.com/ljharb/qs/issues/5) array holes incorrectly copied into object on large index
diff --git a/node_modules/qs/LICENSE.md b/node_modules/qs/LICENSE.md
deleted file mode 100644
index fecf6b6..0000000
--- a/node_modules/qs/LICENSE.md
+++ /dev/null
@@ -1,29 +0,0 @@
-BSD 3-Clause License
-
-Copyright (c) 2014, Nathan LaFreniere and other [contributors](https://github.com/ljharb/qs/graphs/contributors)
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-3. Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/node_modules/qs/README.md b/node_modules/qs/README.md
deleted file mode 100644
index fd64e3c..0000000
--- a/node_modules/qs/README.md
+++ /dev/null
@@ -1,758 +0,0 @@
-<p align="center">
- <img alt="qs" src="./logos/banner_default.png" width="800" />
-</p>
-
-# qs <sup>[![Version Badge][npm-version-svg]][package-url]</sup>
-
-[![github actions][actions-image]][actions-url]
-[![coverage][codecov-image]][codecov-url]
-[![License][license-image]][license-url]
-[![Downloads][downloads-image]][downloads-url]
-[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/9058/badge)](https://bestpractices.coreinfrastructure.org/projects/9058)
-
-[![npm badge][npm-badge-png]][package-url]
-
-A querystring parsing and stringifying library with some added security.
-
-Lead Maintainer: [Jordan Harband](https://github.com/ljharb)
-
-The **qs** module was originally created and maintained by [TJ Holowaychuk](https://github.com/visionmedia/node-querystring).
-
-## Usage
-
-```javascript
-var qs = require('qs');
-var assert = require('assert');
-
-var obj = qs.parse('a=c');
-assert.deepEqual(obj, { a: 'c' });
-
-var str = qs.stringify(obj);
-assert.equal(str, 'a=c');
-```
-
-### Parsing Objects
-
-[](#preventEval)
-```javascript
-qs.parse(string, [options]);
-```
-
-**qs** allows you to create nested objects within your query strings, by surrounding the name of sub-keys with square brackets `[]`.
-For example, the string `'foo[bar]=baz'` converts to:
-
-```javascript
-assert.deepEqual(qs.parse('foo[bar]=baz'), {
- foo: {
- bar: 'baz'
- }
-});
-```
-
-When using the `plainObjects` option the parsed value is returned as a null object, created via `{ __proto__: null }` and as such you should be aware that prototype methods will not exist on it and a user may set those names to whatever value they like:
-
-```javascript
-var nullObject = qs.parse('a[hasOwnProperty]=b', { plainObjects: true });
-assert.deepEqual(nullObject, { a: { hasOwnProperty: 'b' } });
-```
-
-By default parameters that would overwrite properties on the object prototype are ignored, if you wish to keep the data from those fields either use `plainObjects` as mentioned above, or set `allowPrototypes` to `true` which will allow user input to overwrite those properties.
-*WARNING* It is generally a bad idea to enable this option as it can cause problems when attempting to use the properties that have been overwritten.
-Always be careful with this option.
-
-```javascript
-var protoObject = qs.parse('a[hasOwnProperty]=b', { allowPrototypes: true });
-assert.deepEqual(protoObject, { a: { hasOwnProperty: 'b' } });
-```
-
-URI encoded strings work too:
-
-```javascript
-assert.deepEqual(qs.parse('a%5Bb%5D=c'), {
- a: { b: 'c' }
-});
-```
-
-You can also nest your objects, like `'foo[bar][baz]=foobarbaz'`:
-
-```javascript
-assert.deepEqual(qs.parse('foo[bar][baz]=foobarbaz'), {
- foo: {
- bar: {
- baz: 'foobarbaz'
- }
- }
-});
-```
-
-By default, when nesting objects **qs** will only parse up to 5 children deep.
-This means if you attempt to parse a string like `'a[b][c][d][e][f][g][h][i]=j'` your resulting object will be:
-
-```javascript
-var expected = {
- a: {
- b: {
- c: {
- d: {
- e: {
- f: {
- '[g][h][i]': 'j'
- }
- }
- }
- }
- }
- }
-};
-var string = 'a[b][c][d][e][f][g][h][i]=j';
-assert.deepEqual(qs.parse(string), expected);
-```
-
-This depth can be overridden by passing a `depth` option to `qs.parse(string, [options])`:
-
-```javascript
-var deep = qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1 });
-assert.deepEqual(deep, { a: { b: { '[c][d][e][f][g][h][i]': 'j' } } });
-```
-
-You can configure **qs** to throw an error when parsing nested input beyond this depth using the `strictDepth` option (defaulted to false):
-
-```javascript
-try {
- qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1, strictDepth: true });
-} catch (err) {
- assert(err instanceof RangeError);
- assert.strictEqual(err.message, 'Input depth exceeded depth option of 1 and strictDepth is true');
-}
-```
-
-The depth limit helps mitigate abuse when **qs** is used to parse user input, and it is recommended to keep it a reasonably small number. The strictDepth option adds a layer of protection by throwing an error when the limit is exceeded, allowing you to catch and handle such cases.
-
-For similar reasons, by default **qs** will only parse up to 1000 parameters. This can be overridden by passing a `parameterLimit` option:
-
-```javascript
-var limited = qs.parse('a=b&c=d', { parameterLimit: 1 });
-assert.deepEqual(limited, { a: 'b' });
-```
-
-If you want an error to be thrown whenever the a limit is exceeded (eg, `parameterLimit`, `arrayLimit`), set the `throwOnLimitExceeded` option to `true`. This option will generate a descriptive error if the query string exceeds a configured limit.
-```javascript
-try {
- qs.parse('a=1&b=2&c=3&d=4', { parameterLimit: 3, throwOnLimitExceeded: true });
-} catch (err) {
- assert(err instanceof Error);
- assert.strictEqual(err.message, 'Parameter limit exceeded. Only 3 parameters allowed.');
-}
-```
-
-When `throwOnLimitExceeded` is set to `false` (default), **qs** will parse up to the specified `parameterLimit` and ignore the rest without throwing an error.
-
-To bypass the leading question mark, use `ignoreQueryPrefix`:
-
-```javascript
-var prefixed = qs.parse('?a=b&c=d', { ignoreQueryPrefix: true });
-assert.deepEqual(prefixed, { a: 'b', c: 'd' });
-```
-
-An optional delimiter can also be passed:
-
-```javascript
-var delimited = qs.parse('a=b;c=d', { delimiter: ';' });
-assert.deepEqual(delimited, { a: 'b', c: 'd' });
-```
-
-Delimiters can be a regular expression too:
-
-```javascript
-var regexed = qs.parse('a=b;c=d,e=f', { delimiter: /[;,]/ });
-assert.deepEqual(regexed, { a: 'b', c: 'd', e: 'f' });
-```
-
-Option `allowDots` can be used to enable dot notation:
-
-```javascript
-var withDots = qs.parse('a.b=c', { allowDots: true });
-assert.deepEqual(withDots, { a: { b: 'c' } });
-```
-
-Option `decodeDotInKeys` can be used to decode dots in keys
-Note: it implies `allowDots`, so `parse` will error if you set `decodeDotInKeys` to `true`, and `allowDots` to `false`.
-
-```javascript
-var withDots = qs.parse('name%252Eobj.first=John&name%252Eobj.last=Doe', { decodeDotInKeys: true });
-assert.deepEqual(withDots, { 'name.obj': { first: 'John', last: 'Doe' }});
-```
-
-Option `allowEmptyArrays` can be used to allow empty array values in an object
-```javascript
-var withEmptyArrays = qs.parse('foo[]&bar=baz', { allowEmptyArrays: true });
-assert.deepEqual(withEmptyArrays, { foo: [], bar: 'baz' });
-```
-
-Option `duplicates` can be used to change the behavior when duplicate keys are encountered
-```javascript
-assert.deepEqual(qs.parse('foo=bar&foo=baz'), { foo: ['bar', 'baz'] });
-assert.deepEqual(qs.parse('foo=bar&foo=baz', { duplicates: 'combine' }), { foo: ['bar', 'baz'] });
-assert.deepEqual(qs.parse('foo=bar&foo=baz', { duplicates: 'first' }), { foo: 'bar' });
-assert.deepEqual(qs.parse('foo=bar&foo=baz', { duplicates: 'last' }), { foo: 'baz' });
-```
-
-Note that keys with bracket notation (`[]`) always combine into arrays, regardless of the `duplicates` setting:
-```javascript
-assert.deepEqual(qs.parse('a=1&a=2&b[]=1&b[]=2', { duplicates: 'last' }), { a: '2', b: ['1', '2'] });
-```
-
-If you have to deal with legacy browsers or services, there's also support for decoding percent-encoded octets as iso-8859-1:
-
-```javascript
-var oldCharset = qs.parse('a=%A7', { charset: 'iso-8859-1' });
-assert.deepEqual(oldCharset, { a: '§' });
-```
-
-Some services add an initial `utf8=✓` value to forms so that old Internet Explorer versions are more likely to submit the form as utf-8.
-Additionally, the server can check the value against wrong encodings of the checkmark character and detect that a query string or `application/x-www-form-urlencoded` body was *not* sent as utf-8, eg. if the form had an `accept-charset` parameter or the containing page had a different character set.
-
-**qs** supports this mechanism via the `charsetSentinel` option.
-If specified, the `utf8` parameter will be omitted from the returned object.
-It will be used to switch to `iso-8859-1`/`utf-8` mode depending on how the checkmark is encoded.
-
-**Important**: When you specify both the `charset` option and the `charsetSentinel` option, the `charset` will be overridden when the request contains a `utf8` parameter from which the actual charset can be deduced.
-In that sense the `charset` will behave as the default charset rather than the authoritative charset.
-
-```javascript
-var detectedAsUtf8 = qs.parse('utf8=%E2%9C%93&a=%C3%B8', {
- charset: 'iso-8859-1',
- charsetSentinel: true
-});
-assert.deepEqual(detectedAsUtf8, { a: 'ø' });
-
-// Browsers encode the checkmark as &#10003; when submitting as iso-8859-1:
-var detectedAsIso8859_1 = qs.parse('utf8=%26%2310003%3B&a=%F8', {
- charset: 'utf-8',
- charsetSentinel: true
-});
-assert.deepEqual(detectedAsIso8859_1, { a: 'ø' });
-```
-
-If you want to decode the `&#...;` syntax to the actual character, you can specify the `interpretNumericEntities` option as well:
-
-```javascript
-var detectedAsIso8859_1 = qs.parse('a=%26%239786%3B', {
- charset: 'iso-8859-1',
- interpretNumericEntities: true
-});
-assert.deepEqual(detectedAsIso8859_1, { a: '☺' });
-```
-
-It also works when the charset has been detected in `charsetSentinel` mode.
-
-### Parsing Arrays
-
-**qs** can also parse arrays using a similar `[]` notation:
-
-```javascript
-var withArray = qs.parse('a[]=b&a[]=c');
-assert.deepEqual(withArray, { a: ['b', 'c'] });
-```
-
-You may specify an index as well:
-
-```javascript
-var withIndexes = qs.parse('a[1]=c&a[0]=b');
-assert.deepEqual(withIndexes, { a: ['b', 'c'] });
-```
-
-Note that the only difference between an index in an array and a key in an object is that the value between the brackets must be a number to create an array.
-When creating arrays with specific indices, **qs** will compact a sparse array to only the existing values preserving their order:
-
-```javascript
-var noSparse = qs.parse('a[1]=b&a[15]=c');
-assert.deepEqual(noSparse, { a: ['b', 'c'] });
-```
-
-You may also use `allowSparse` option to parse sparse arrays:
-
-```javascript
-var sparseArray = qs.parse('a[1]=2&a[3]=5', { allowSparse: true });
-assert.deepEqual(sparseArray, { a: [, '2', , '5'] });
-```
-
-Note that an empty string is also a value, and will be preserved:
-
-```javascript
-var withEmptyString = qs.parse('a[]=&a[]=b');
-assert.deepEqual(withEmptyString, { a: ['', 'b'] });
-
-var withIndexedEmptyString = qs.parse('a[0]=b&a[1]=&a[2]=c');
-assert.deepEqual(withIndexedEmptyString, { a: ['b', '', 'c'] });
-```
-
-**qs** will also limit arrays to a maximum of `20` elements.
-Any array members with an index of `20` or greater will instead be converted to an object with the index as the key.
-This is needed to handle cases when someone sent, for example, `a[999999999]` and it will take significant time to iterate over this huge array.
-
-```javascript
-var withMaxIndex = qs.parse('a[100]=b');
-assert.deepEqual(withMaxIndex, { a: { '100': 'b' } });
-```
-
-This limit can be overridden by passing an `arrayLimit` option:
-
-```javascript
-var withArrayLimit = qs.parse('a[1]=b', { arrayLimit: 0 });
-assert.deepEqual(withArrayLimit, { a: { '1': 'b' } });
-```
-
-If you want to throw an error whenever the array limit is exceeded, set the `throwOnLimitExceeded` option to `true`. This option will generate a descriptive error if the query string exceeds a configured limit.
-```javascript
-try {
- qs.parse('a[1]=b', { arrayLimit: 0, throwOnLimitExceeded: true });
-} catch (err) {
- assert(err instanceof Error);
- assert.strictEqual(err.message, 'Array limit exceeded. Only 0 elements allowed in an array.');
-}
-```
-
-When `throwOnLimitExceeded` is set to `false` (default), **qs** will parse up to the specified `arrayLimit` and if the limit is exceeded, the array will instead be converted to an object with the index as the key
-
-To prevent array syntax (`a[]`, `a[0]`) from being parsed as arrays, set `parseArrays` to `false`.
-Note that duplicate keys (e.g. `a=b&a=c`) may still produce arrays when `duplicates` is `'combine'` (the default).
-
-```javascript
-var noParsingArrays = qs.parse('a[]=b', { parseArrays: false });
-assert.deepEqual(noParsingArrays, { a: { '0': 'b' } });
-```
-
-If you mix notations, **qs** will merge the two items into an object:
-
-```javascript
-var mixedNotation = qs.parse('a[0]=b&a[b]=c');
-assert.deepEqual(mixedNotation, { a: { '0': 'b', b: 'c' } });
-```
-
-When a key appears as both a plain value and an object, **qs** will by default wrap the conflicting values in an array (`strictMerge` defaults to `true`):
-
-```javascript
-assert.deepEqual(qs.parse('a[b]=c&a=d'), { a: [{ b: 'c' }, 'd'] });
-assert.deepEqual(qs.parse('a=d&a[b]=c'), { a: ['d', { b: 'c' }] });
-```
-
-To restore the legacy behavior (where the primitive is used as a key with value `true`), set `strictMerge` to `false`:
-
-```javascript
-assert.deepEqual(qs.parse('a[b]=c&a=d', { strictMerge: false }), { a: { b: 'c', d: true } });
-```
-
-You can also create arrays of objects:
-
-```javascript
-var arraysOfObjects = qs.parse('a[][b]=c');
-assert.deepEqual(arraysOfObjects, { a: [{ b: 'c' }] });
-```
-
-Some people use comma to join array, **qs** can parse it:
-```javascript
-var arraysOfObjects = qs.parse('a=b,c', { comma: true })
-assert.deepEqual(arraysOfObjects, { a: ['b', 'c'] })
-```
-(_this cannot convert nested objects, such as `a={b:1},{c:d}`_)
-
-### Parsing primitive/scalar values (numbers, booleans, null, etc)
-
-By default, all values are parsed as strings.
-This behavior will not change and is explained in [issue #91](https://github.com/ljharb/qs/issues/91).
-
-```javascript
-var primitiveValues = qs.parse('a=15&b=true&c=null');
-assert.deepEqual(primitiveValues, { a: '15', b: 'true', c: 'null' });
-```
-
-If you wish to auto-convert values which look like numbers, booleans, and other values into their primitive counterparts, you can use the [query-types Express JS middleware](https://github.com/xpepermint/query-types) which will auto-convert all request query parameters.
-
-### Stringifying
-
-[](#preventEval)
-```javascript
-qs.stringify(object, [options]);
-```
-
-When stringifying, **qs** by default URI encodes output. Objects are stringified as you would expect:
-
-```javascript
-assert.equal(qs.stringify({ a: 'b' }), 'a=b');
-assert.equal(qs.stringify({ a: { b: 'c' } }), 'a%5Bb%5D=c');
-```
-
-This encoding can be disabled by setting the `encode` option to `false`:
-
-```javascript
-var unencoded = qs.stringify({ a: { b: 'c' } }, { encode: false });
-assert.equal(unencoded, 'a[b]=c');
-```
-
-Encoding can be disabled for keys by setting the `encodeValuesOnly` option to `true`:
-```javascript
-var encodedValues = qs.stringify(
- { a: 'b', c: ['d', 'e=f'], f: [['g'], ['h']] },
- { encodeValuesOnly: true }
-);
-assert.equal(encodedValues,'a=b&c[0]=d&c[1]=e%3Df&f[0][0]=g&f[1][0]=h');
-```
-
-This encoding can also be replaced by a custom encoding method set as `encoder` option:
-
-```javascript
-var encoded = qs.stringify({ a: { b: 'c' } }, { encoder: function (str) {
- // Passed in values `a`, `b`, `c`
- return // Return encoded string
-}})
-```
-
-_(Note: the `encoder` option does not apply if `encode` is `false`)_
-
-Analogue to the `encoder` there is a `decoder` option for `parse` to override decoding of properties and values:
-
-```javascript
-var decoded = qs.parse('x=z', { decoder: function (str) {
- // Passed in values `x`, `z`
- return // Return decoded string
-}})
-```
-
-You can encode keys and values using different logic by using the type argument provided to the encoder:
-
-```javascript
-var encoded = qs.stringify({ a: { b: 'c' } }, { encoder: function (str, defaultEncoder, charset, type) {
- if (type === 'key') {
- return // Encoded key
- } else if (type === 'value') {
- return // Encoded value
- }
-}})
-```
-
-The type argument is also provided to the decoder:
-
-```javascript
-var decoded = qs.parse('x=z', { decoder: function (str, defaultDecoder, charset, type) {
- if (type === 'key') {
- return // Decoded key
- } else if (type === 'value') {
- return // Decoded value
- }
-}})
-```
-
-Examples beyond this point will be shown as though the output is not URI encoded for clarity.
-Please note that the return values in these cases *will* be URI encoded during real usage.
-
-When arrays are stringified, they follow the `arrayFormat` option, which defaults to `indices`:
-
-```javascript
-qs.stringify({ a: ['b', 'c', 'd'] });
-// 'a[0]=b&a[1]=c&a[2]=d'
-```
-
-You may override this by setting the `indices` option to `false`, or to be more explicit, the `arrayFormat` option to `repeat`:
-
-```javascript
-qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false });
-// 'a=b&a=c&a=d'
-```
-
-You may use the `arrayFormat` option to specify the format of the output array:
-
-```javascript
-qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' })
-// 'a[0]=b&a[1]=c'
-qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' })
-// 'a[]=b&a[]=c'
-qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' })
-// 'a=b&a=c'
-qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'comma' })
-// 'a=b,c'
-```
-
-Note: when using `arrayFormat` set to `'comma'`, you can also pass the `commaRoundTrip` option set to `true` or `false`, to append `[]` on single-item arrays, so that they can round trip through a parse.
-
-When objects are stringified, by default they use bracket notation:
-
-```javascript
-qs.stringify({ a: { b: { c: 'd', e: 'f' } } });
-// 'a[b][c]=d&a[b][e]=f'
-```
-
-You may override this to use dot notation by setting the `allowDots` option to `true`:
-
-```javascript
-qs.stringify({ a: { b: { c: 'd', e: 'f' } } }, { allowDots: true });
-// 'a.b.c=d&a.b.e=f'
-```
-
-You may encode the dot notation in the keys of object with option `encodeDotInKeys` by setting it to `true`:
-Note: it implies `allowDots`, so `stringify` will error if you set `decodeDotInKeys` to `true`, and `allowDots` to `false`.
-Caveat: when `encodeValuesOnly` is `true` as well as `encodeDotInKeys`, only dots in keys and nothing else will be encoded.
-```javascript
-qs.stringify({ "name.obj": { "first": "John", "last": "Doe" } }, { allowDots: true, encodeDotInKeys: true })
-// 'name%252Eobj.first=John&name%252Eobj.last=Doe'
-```
-
-You may allow empty array values by setting the `allowEmptyArrays` option to `true`:
-```javascript
-qs.stringify({ foo: [], bar: 'baz' }, { allowEmptyArrays: true });
-// 'foo[]&bar=baz'
-```
-
-Empty strings and null values will omit the value, but the equals sign (=) remains in place:
-
-```javascript
-assert.equal(qs.stringify({ a: '' }), 'a=');
-```
-
-Key with no values (such as an empty object or array) will return nothing:
-
-```javascript
-assert.equal(qs.stringify({ a: [] }), '');
-assert.equal(qs.stringify({ a: {} }), '');
-assert.equal(qs.stringify({ a: [{}] }), '');
-assert.equal(qs.stringify({ a: { b: []} }), '');
-assert.equal(qs.stringify({ a: { b: {}} }), '');
-```
-
-Properties that are set to `undefined` will be omitted entirely:
-
-```javascript
-assert.equal(qs.stringify({ a: null, b: undefined }), 'a=');
-```
-
-The query string may optionally be prepended with a question mark:
-
-```javascript
-assert.equal(qs.stringify({ a: 'b', c: 'd' }, { addQueryPrefix: true }), '?a=b&c=d');
-```
-
-Note that when the output is an empty string, the prefix will not be added:
-
-```javascript
-assert.equal(qs.stringify({}, { addQueryPrefix: true }), '');
-```
-
-The delimiter may be overridden with stringify as well:
-
-```javascript
-assert.equal(qs.stringify({ a: 'b', c: 'd' }, { delimiter: ';' }), 'a=b;c=d');
-```
-
-If you only want to override the serialization of `Date` objects, you can provide a `serializeDate` option:
-
-```javascript
-var date = new Date(7);
-assert.equal(qs.stringify({ a: date }), 'a=1970-01-01T00:00:00.007Z'.replace(/:/g, '%3A'));
-assert.equal(
- qs.stringify({ a: date }, { serializeDate: function (d) { return d.getTime(); } }),
- 'a=7'
-);
-```
-
-You may use the `sort` option to affect the order of parameter keys:
-
-```javascript
-function alphabeticalSort(a, b) {
- return a.localeCompare(b);
-}
-assert.equal(qs.stringify({ a: 'c', z: 'y', b : 'f' }, { sort: alphabeticalSort }), 'a=c&b=f&z=y');
-```
-
-Finally, you can use the `filter` option to restrict which keys will be included in the stringified output.
-If you pass a function, it will be called for each key to obtain the replacement value.
-Otherwise, if you pass an array, it will be used to select properties and array indices for stringification:
-
-```javascript
-function filterFunc(prefix, value) {
- if (prefix == 'b') {
- // Return an `undefined` value to omit a property.
- return;
- }
- if (prefix == 'e[f]') {
- return value.getTime();
- }
- if (prefix == 'e[g][0]') {
- return value * 2;
- }
- return value;
-}
-qs.stringify({ a: 'b', c: 'd', e: { f: new Date(123), g: [2] } }, { filter: filterFunc });
-// 'a=b&c=d&e[f]=123&e[g][0]=4'
-qs.stringify({ a: 'b', c: 'd', e: 'f' }, { filter: ['a', 'e'] });
-// 'a=b&e=f'
-qs.stringify({ a: ['b', 'c', 'd'], e: 'f' }, { filter: ['a', 0, 2] });
-// 'a[0]=b&a[2]=d'
-```
-
-You could also use `filter` to inject custom serialization for user defined types.
-Consider you're working with some api that expects query strings of the format for ranges:
-
-```
-https://domain.com/endpoint?range=30...70
-```
-
-For which you model as:
-
-```javascript
-class Range {
- constructor(from, to) {
- this.from = from;
- this.to = to;
- }
-}
-```
-
-You could _inject_ a custom serializer to handle values of this type:
-
-```javascript
-qs.stringify(
- {
- range: new Range(30, 70),
- },
- {
- filter: (prefix, value) => {
- if (value instanceof Range) {
- return `${value.from}...${value.to}`;
- }
- // serialize the usual way
- return value;
- },
- }
-);
-// range=30...70
-```
-
-### Handling of `null` values
-
-By default, `null` values are treated like empty strings:
-
-```javascript
-var withNull = qs.stringify({ a: null, b: '' });
-assert.equal(withNull, 'a=&b=');
-```
-
-Parsing does not distinguish between parameters with and without equal signs.
-Both are converted to empty strings.
-
-```javascript
-var equalsInsensitive = qs.parse('a&b=');
-assert.deepEqual(equalsInsensitive, { a: '', b: '' });
-```
-
-To distinguish between `null` values and empty strings use the `strictNullHandling` flag. In the result string the `null`
-values have no `=` sign:
-
-```javascript
-var strictNull = qs.stringify({ a: null, b: '' }, { strictNullHandling: true });
-assert.equal(strictNull, 'a&b=');
-```
-
-To parse values without `=` back to `null` use the `strictNullHandling` flag:
-
-```javascript
-var parsedStrictNull = qs.parse('a&b=', { strictNullHandling: true });
-assert.deepEqual(parsedStrictNull, { a: null, b: '' });
-```
-
-To completely skip rendering keys with `null` values, use the `skipNulls` flag:
-
-```javascript
-var nullsSkipped = qs.stringify({ a: 'b', c: null}, { skipNulls: true });
-assert.equal(nullsSkipped, 'a=b');
-```
-
-If you're communicating with legacy systems, you can switch to `iso-8859-1` using the `charset` option:
-
-```javascript
-var iso = qs.stringify({ æ: 'æ' }, { charset: 'iso-8859-1' });
-assert.equal(iso, '%E6=%E6');
-```
-
-Characters that don't exist in `iso-8859-1` will be converted to numeric entities, similar to what browsers do:
-
-```javascript
-var numeric = qs.stringify({ a: '☺' }, { charset: 'iso-8859-1' });
-assert.equal(numeric, 'a=%26%239786%3B');
-```
-
-You can use the `charsetSentinel` option to announce the character by including an `utf8=✓` parameter with the proper encoding if the checkmark, similar to what Ruby on Rails and others do when submitting forms.
-
-```javascript
-var sentinel = qs.stringify({ a: '☺' }, { charsetSentinel: true });
-assert.equal(sentinel, 'utf8=%E2%9C%93&a=%E2%98%BA');
-
-var isoSentinel = qs.stringify({ a: 'æ' }, { charsetSentinel: true, charset: 'iso-8859-1' });
-assert.equal(isoSentinel, 'utf8=%26%2310003%3B&a=%E6');
-```
-
-### Dealing with special character sets
-
-By default the encoding and decoding of characters is done in `utf-8`, and `iso-8859-1` support is also built in via the `charset` parameter.
-
-If you wish to encode querystrings to a different character set (i.e.
-[Shift JIS](https://en.wikipedia.org/wiki/Shift_JIS)) you can use the
-[`qs-iconv`](https://github.com/martinheidegger/qs-iconv) library:
-
-```javascript
-var encoder = require('qs-iconv/encoder')('shift_jis');
-var shiftJISEncoded = qs.stringify({ a: 'こんにちは!' }, { encoder: encoder });
-assert.equal(shiftJISEncoded, 'a=%82%B1%82%F1%82%C9%82%BF%82%CD%81I');
-```
-
-This also works for decoding of query strings:
-
-```javascript
-var decoder = require('qs-iconv/decoder')('shift_jis');
-var obj = qs.parse('a=%82%B1%82%F1%82%C9%82%BF%82%CD%81I', { decoder: decoder });
-assert.deepEqual(obj, { a: 'こんにちは!' });
-```
-
-### RFC 3986 and RFC 1738 space encoding
-
-RFC3986 used as default option and encodes ' ' to *%20* which is backward compatible.
-In the same time, output can be stringified as per RFC1738 with ' ' equal to '+'.
-
-```
-assert.equal(qs.stringify({ a: 'b c' }), 'a=b%20c');
-assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC3986' }), 'a=b%20c');
-assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC1738' }), 'a=b+c');
-```
-
-## Security
-
-Please email [@ljharb](https://github.com/ljharb) or see https://tidelift.com/security if you have a potential security vulnerability to report.
-
-## qs for enterprise
-
-Available as part of the Tidelift Subscription
-
-The maintainers of qs and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications.
-Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use.
-[Learn more.](https://tidelift.com/subscription/pkg/npm-qs?utm_source=npm-qs&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
-
-[package-url]: https://npmjs.org/package/qs
-[npm-version-svg]: https://versionbadg.es/ljharb/qs.svg
-[deps-svg]: https://david-dm.org/ljharb/qs.svg
-[deps-url]: https://david-dm.org/ljharb/qs
-[dev-deps-svg]: https://david-dm.org/ljharb/qs/dev-status.svg
-[dev-deps-url]: https://david-dm.org/ljharb/qs#info=devDependencies
-[npm-badge-png]: https://nodei.co/npm/qs.png?downloads=true&stars=true
-[license-image]: https://img.shields.io/npm/l/qs.svg
-[license-url]: LICENSE
-[downloads-image]: https://img.shields.io/npm/dm/qs.svg
-[downloads-url]: https://npm-stat.com/charts.html?package=qs
-[codecov-image]: https://codecov.io/gh/ljharb/qs/branch/main/graphs/badge.svg
-[codecov-url]: https://app.codecov.io/gh/ljharb/qs/
-[actions-image]: https://img.shields.io/github/check-runs/ljharb/qs/main
-[actions-url]: https://github.com/ljharb/qs/actions
-
-## Acknowledgements
-
-qs logo by [NUMI](https://github.com/numi-hq/open-design):
-
-[<img src="https://raw.githubusercontent.com/numi-hq/open-design/main/assets/numi-lockup.png" alt="NUMI Logo" style="width: 200px;"/>](https://numi.tech/?ref=qs)
diff --git a/node_modules/qs/dist/qs.js b/node_modules/qs/dist/qs.js
deleted file mode 100644
index 829e020..0000000
--- a/node_modules/qs/dist/qs.js
+++ /dev/null
@@ -1,141 +0,0 @@
-(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Qs = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
-"use strict";var replace=String.prototype.replace,percentTwenties=/%20/g,Format={RFC1738:"RFC1738",RFC3986:"RFC3986"};module.exports={default:Format.RFC3986,formatters:{RFC1738:function(e){return replace.call(e,percentTwenties,"+")},RFC3986:function(e){return String(e)}},RFC1738:Format.RFC1738,RFC3986:Format.RFC3986};
-
-},{}],2:[function(require,module,exports){
-"use strict";var stringify=require(4),parse=require(3),formats=require(1);module.exports={formats:formats,parse:parse,stringify:stringify};
-
-},{"1":1,"3":3,"4":4}],3:[function(require,module,exports){
-"use strict";var utils=require(5),has=Object.prototype.hasOwnProperty,isArray=Array.isArray,defaults={allowDots:!1,allowEmptyArrays:!1,allowPrototypes:!1,allowSparse:!1,arrayLimit:20,charset:"utf-8",charsetSentinel:!1,comma:!1,decodeDotInKeys:!1,decoder:utils.decode,delimiter:"&",depth:5,duplicates:"combine",ignoreQueryPrefix:!1,interpretNumericEntities:!1,parameterLimit:1e3,parseArrays:!0,plainObjects:!1,strictDepth:!1,strictMerge:!0,strictNullHandling:!1,throwOnLimitExceeded:!1},interpretNumericEntities=function(e){return e.replace(/&#(\d+);/g,function(e,t){return String.fromCharCode(parseInt(t,10))})},parseArrayValue=function(e,t,r,i){if(e&&"string"==typeof e&&t.comma&&e.indexOf(",")>-1){if(i&&t.throwOnLimitExceeded)for(var a=0,o=e.indexOf(",");o>-1;){if((a+=1)>=t.arrayLimit)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");o=e.indexOf(",",o+1)}return e.split(",")}if(t.throwOnLimitExceeded&&r>=t.arrayLimit)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");return e},isoSentinel="utf8=%26%2310003%3B",charsetSentinel="utf8=%E2%9C%93",parseValues=function parseQueryStringValues(e,t){var r={__proto__:null},i=t.ignoreQueryPrefix?e.replace(/^\?/,""):e;i=i.replace(/%5B/gi,"[").replace(/%5D/gi,"]");var a=t.parameterLimit===1/0?void 0:t.parameterLimit,o=i.split(t.delimiter,t.throwOnLimitExceeded&&void 0!==a?a+1:a);if(t.throwOnLimitExceeded&&void 0!==a&&o.length>a)throw new RangeError("Parameter limit exceeded. Only "+a+" parameter"+(1===a?"":"s")+" allowed.");var l,n=-1,s=t.charset;if(t.charsetSentinel)for(l=0;l<o.length;++l)0===o[l].indexOf("utf8=")&&(o[l]===charsetSentinel?s="utf-8":o[l]===isoSentinel&&(s="iso-8859-1"),n=l,l=o.length);for(l=0;l<o.length;++l)if(l!==n){var d,c,p=o[l],u=p.indexOf("]="),y=-1===u?p.indexOf("="):u+1;if(-1===y?(d=t.decoder(p,defaults.decoder,s,"key"),c=t.strictNullHandling?null:""):null!==(d=t.decoder(p.slice(0,y),defaults.decoder,s,"key"))&&(c=utils.maybeMap(parseArrayValue(p.slice(y+1),t,isArray(r[d])?r[d].length:0,-1===p.indexOf("[]=")),function(e){return t.decoder(e,defaults.decoder,s,"value")})),c&&t.interpretNumericEntities&&"iso-8859-1"===s&&(c=interpretNumericEntities(String(c))),p.indexOf("[]=")>-1&&(c=isArray(c)?[c]:c),t.comma&&isArray(c)&&c.length>t.arrayLimit&&(c=utils.combine([],c,t.arrayLimit,t.plainObjects,t.throwOnLimitExceeded)),null!==d){var f=has.call(r,d);f&&("combine"===t.duplicates||p.indexOf("[]=")>-1)?r[d]=utils.combine(r[d],c,t.arrayLimit,t.plainObjects,t.throwOnLimitExceeded):f&&"last"!==t.duplicates||(r[d]=c)}}return r},parseObject=function(e,t,r,i){var a=0;if(e.length>0&&"[]"===e[e.length-1]){var o=e.slice(0,-1).join("");a=Array.isArray(t)&&t[o]?t[o].length:0}for(var l=i?t:parseArrayValue(t,r,a),n=e.length-1;n>=0;--n){var s,d=e[n];if("[]"===d&&r.parseArrays)s=utils.isOverflow(l)?l:r.allowEmptyArrays&&(""===l||r.strictNullHandling&&null===l)?[]:utils.combine([],l,r.arrayLimit,r.plainObjects,r.throwOnLimitExceeded);else{s=r.plainObjects?{__proto__:null}:{};var c="["===d.charAt(0)&&"]"===d.charAt(d.length-1)?d.slice(1,-1):d,p=r.decodeDotInKeys?c.replace(/%2E/g,"."):c,u=parseInt(p,10),y=!isNaN(u)&&d!==p&&String(u)===p&&u>=0&&r.parseArrays;if(r.parseArrays||""!==p)if(y&&u<r.arrayLimit)(s=[])[u]=l;else{if(y&&r.throwOnLimitExceeded)throw new RangeError("Array limit exceeded. Only "+r.arrayLimit+" element"+(1===r.arrayLimit?"":"s")+" allowed in an array.");y?(s[u]=l,utils.markOverflow(s,u)):"__proto__"!==p&&(s[p]=l)}else s={0:l}}l=s}return l},splitKeyIntoSegments=function splitKeyIntoSegments(e,t){var r=t.allowDots?e.replace(/\.([^.[]+)/g,"[$1]"):e;if(t.depth<=0){if(!t.plainObjects&&has.call(Object.prototype,r)&&!t.allowPrototypes)return;return[r]}var i=[],a=r.indexOf("["),o=a>=0?r.slice(0,a):r;if(o){if(!t.plainObjects&&has.call(Object.prototype,o)&&!t.allowPrototypes)return;i[i.length]=o}for(var l=r.length,n=a,s=0;n>=0&&s<t.depth;){for(var d=1,c=n+1,p=-1;c<l&&p<0;){var u=r.charCodeAt(c);91===u?d+=1:93===u&&0==(d-=1)&&(p=c),c+=1}if(p<0)return i[i.length]="["+r.slice(n)+"]",i;var y=r.slice(n,p+1),f=y.slice(1,-1);if(!t.plainObjects&&has.call(Object.prototype,f)&&!t.allowPrototypes)return;i[i.length]=y,s+=1,n=r.indexOf("[",p+1)}if(n>=0){if(!0===t.strictDepth)throw new RangeError("Input depth exceeded depth option of "+t.depth+" and strictDepth is true");i[i.length]="["+r.slice(n)+"]"}return i},parseKeys=function parseQueryStringKeys(e,t,r,i){if(e){var a=splitKeyIntoSegments(e,r);if(a)return parseObject(a,t,r,i)}},normalizeParseOptions=function normalizeParseOptions(e){if(!e)return defaults;if(void 0!==e.allowEmptyArrays&&"boolean"!=typeof e.allowEmptyArrays)throw new TypeError("`allowEmptyArrays` option can only be `true` or `false`, when provided");if(void 0!==e.decodeDotInKeys&&"boolean"!=typeof e.decodeDotInKeys)throw new TypeError("`decodeDotInKeys` option can only be `true` or `false`, when provided");if(null!==e.decoder&&void 0!==e.decoder&&"function"!=typeof e.decoder)throw new TypeError("Decoder has to be a function.");if(void 0!==e.charset&&"utf-8"!==e.charset&&"iso-8859-1"!==e.charset)throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined");if(void 0!==e.throwOnLimitExceeded&&"boolean"!=typeof e.throwOnLimitExceeded)throw new TypeError("`throwOnLimitExceeded` option must be a boolean");var t=void 0===e.charset?defaults.charset:e.charset,r=void 0===e.duplicates?defaults.duplicates:e.duplicates;if("combine"!==r&&"first"!==r&&"last"!==r)throw new TypeError("The duplicates option must be either combine, first, or last");return{allowDots:void 0===e.allowDots?!0===e.decodeDotInKeys||defaults.allowDots:!!e.allowDots,allowEmptyArrays:"boolean"==typeof e.allowEmptyArrays?!!e.allowEmptyArrays:defaults.allowEmptyArrays,allowPrototypes:"boolean"==typeof e.allowPrototypes?e.allowPrototypes:defaults.allowPrototypes,allowSparse:"boolean"==typeof e.allowSparse?e.allowSparse:defaults.allowSparse,arrayLimit:"number"==typeof e.arrayLimit?e.arrayLimit:defaults.arrayLimit,charset:t,charsetSentinel:"boolean"==typeof e.charsetSentinel?e.charsetSentinel:defaults.charsetSentinel,comma:"boolean"==typeof e.comma?e.comma:defaults.comma,decodeDotInKeys:"boolean"==typeof e.decodeDotInKeys?e.decodeDotInKeys:defaults.decodeDotInKeys,decoder:"function"==typeof e.decoder?e.decoder:defaults.decoder,delimiter:"string"==typeof e.delimiter||utils.isRegExp(e.delimiter)?e.delimiter:defaults.delimiter,depth:"number"==typeof e.depth||!1===e.depth?+e.depth:defaults.depth,duplicates:r,ignoreQueryPrefix:!0===e.ignoreQueryPrefix,interpretNumericEntities:"boolean"==typeof e.interpretNumericEntities?e.interpretNumericEntities:defaults.interpretNumericEntities,parameterLimit:"number"==typeof e.parameterLimit?e.parameterLimit:defaults.parameterLimit,parseArrays:!1!==e.parseArrays,plainObjects:"boolean"==typeof e.plainObjects?e.plainObjects:defaults.plainObjects,strictDepth:"boolean"==typeof e.strictDepth?!!e.strictDepth:defaults.strictDepth,strictMerge:"boolean"==typeof e.strictMerge?!!e.strictMerge:defaults.strictMerge,strictNullHandling:"boolean"==typeof e.strictNullHandling?e.strictNullHandling:defaults.strictNullHandling,throwOnLimitExceeded:"boolean"==typeof e.throwOnLimitExceeded&&e.throwOnLimitExceeded}};module.exports=function(e,t){var r=normalizeParseOptions(t);if(""===e||null==e)return r.plainObjects?{__proto__:null}:{};for(var i="string"==typeof e?parseValues(e,r):e,a=r.plainObjects?{__proto__:null}:{},o=Object.keys(i),l=0;l<o.length;++l){var n=o[l],s=parseKeys(n,i[n],r,"string"==typeof e);a=utils.merge(a,s,r)}return!0===r.allowSparse?a:utils.compact(a)};
-
-},{"5":5}],4:[function(require,module,exports){
-"use strict";var getSideChannel=require(46),utils=require(5),formats=require(1),has=Object.prototype.hasOwnProperty,arrayPrefixGenerators={brackets:function brackets(e){return e+"[]"},comma:"comma",indices:function indices(e,r){return e+"["+r+"]"},repeat:function repeat(e){return e}},isArray=Array.isArray,push=Array.prototype.push,pushToArray=function(e,r){push.apply(e,isArray(r)?r:[r])},toISO=Date.prototype.toISOString,defaultFormat=formats.default,defaults={addQueryPrefix:!1,allowDots:!1,allowEmptyArrays:!1,arrayFormat:"indices",charset:"utf-8",charsetSentinel:!1,commaRoundTrip:!1,delimiter:"&",encode:!0,encodeDotInKeys:!1,encoder:utils.encode,encodeValuesOnly:!1,filter:void 0,format:defaultFormat,formatter:formats.formatters[defaultFormat],indices:!1,serializeDate:function serializeDate(e){return toISO.call(e)},skipNulls:!1,strictNullHandling:!1},isNonNullishPrimitive=function isNonNullishPrimitive(e){return"string"==typeof e||"number"==typeof e||"boolean"==typeof e||"symbol"==typeof e||"bigint"==typeof e},sentinel={},stringify=function stringify(e,r,t,o,a,n,i,l,s,f,u,d,y,c,p,m,h,v){for(var g=e,w=v,b=0,A=!1;void 0!==(w=w.get(sentinel))&&!A;){var D=w.get(e);if(b+=1,void 0!==D){if(D===b)throw new RangeError("Cyclic object value");A=!0}void 0===w.get(sentinel)&&(b=0)}if("function"==typeof f?g=f(r,g):g instanceof Date?g=y(g):"comma"===t&&isArray(g)&&(g=utils.maybeMap(g,function(e){return e instanceof Date?y(e):e})),null===g){if(n)return p(s&&!m?s(r,defaults.encoder,h,"key",c):r);g=""}if(isNonNullishPrimitive(g)||utils.isBuffer(g))return s?[p(m?r:s(r,defaults.encoder,h,"key",c))+"="+p(s(g,defaults.encoder,h,"value",c))]:[p(r)+"="+p(String(g))];var S,E=[];if(void 0===g)return E;if("comma"===t&&isArray(g))m&&s&&(g=utils.maybeMap(g,function(e){return null==e?e:s(e)})),S=[{value:g.length>0?g.join(",")||null:void 0}];else if(isArray(f))S=f;else{var N=Object.keys(g);S=u?N.sort(u):N}var T=l?String(r).replace(/\./g,"%2E"):String(r),O=o&&isArray(g)&&1===g.length?T+"[]":T;if(a&&isArray(g)&&0===g.length)return O+"[]";for(var k=0;k<S.length;++k){var I=S[k],P="object"==typeof I&&I&&void 0!==I.value?I.value:g[I];if(!i||null!==P){var x=d&&l?String(I).replace(/\./g,"%2E"):String(I),z=isArray(g)?"function"==typeof t?t(O,x):O:O+(d?"."+x:"["+x+"]");v.set(e,b);var K=getSideChannel();K.set(sentinel,v),pushToArray(E,stringify(P,z,t,o,a,n,i,l,"comma"===t&&m&&isArray(g)?null:s,f,u,d,y,c,p,m,h,K))}}return E},normalizeStringifyOptions=function normalizeStringifyOptions(e){if(!e)return defaults;if(void 0!==e.allowEmptyArrays&&"boolean"!=typeof e.allowEmptyArrays)throw new TypeError("`allowEmptyArrays` option can only be `true` or `false`, when provided");if(void 0!==e.encodeDotInKeys&&"boolean"!=typeof e.encodeDotInKeys)throw new TypeError("`encodeDotInKeys` option can only be `true` or `false`, when provided");if(null!==e.encoder&&void 0!==e.encoder&&"function"!=typeof e.encoder)throw new TypeError("Encoder has to be a function.");var r=e.charset||defaults.charset;if(void 0!==e.charset&&"utf-8"!==e.charset&&"iso-8859-1"!==e.charset)throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined");var t=formats.default;if(void 0!==e.format){if(!has.call(formats.formatters,e.format))throw new TypeError("Unknown format option provided.");t=e.format}var o,a=formats.formatters[t],n=defaults.filter;if(("function"==typeof e.filter||isArray(e.filter))&&(n=e.filter),o=e.arrayFormat in arrayPrefixGenerators?e.arrayFormat:"indices"in e?e.indices?"indices":"repeat":defaults.arrayFormat,"commaRoundTrip"in e&&"boolean"!=typeof e.commaRoundTrip)throw new TypeError("`commaRoundTrip` must be a boolean, or absent");var i=void 0===e.allowDots?!0===e.encodeDotInKeys||defaults.allowDots:!!e.allowDots;return{addQueryPrefix:"boolean"==typeof e.addQueryPrefix?e.addQueryPrefix:defaults.addQueryPrefix,allowDots:i,allowEmptyArrays:"boolean"==typeof e.allowEmptyArrays?!!e.allowEmptyArrays:defaults.allowEmptyArrays,arrayFormat:o,charset:r,charsetSentinel:"boolean"==typeof e.charsetSentinel?e.charsetSentinel:defaults.charsetSentinel,commaRoundTrip:!!e.commaRoundTrip,delimiter:void 0===e.delimiter?defaults.delimiter:e.delimiter,encode:"boolean"==typeof e.encode?e.encode:defaults.encode,encodeDotInKeys:"boolean"==typeof e.encodeDotInKeys?e.encodeDotInKeys:defaults.encodeDotInKeys,encoder:"function"==typeof e.encoder?e.encoder:defaults.encoder,encodeValuesOnly:"boolean"==typeof e.encodeValuesOnly?e.encodeValuesOnly:defaults.encodeValuesOnly,filter:n,format:t,formatter:a,serializeDate:"function"==typeof e.serializeDate?e.serializeDate:defaults.serializeDate,skipNulls:"boolean"==typeof e.skipNulls?e.skipNulls:defaults.skipNulls,sort:"function"==typeof e.sort?e.sort:null,strictNullHandling:"boolean"==typeof e.strictNullHandling?e.strictNullHandling:defaults.strictNullHandling}};module.exports=function(e,r){var t,o=e,a=normalizeStringifyOptions(r);"function"==typeof a.filter?o=(0,a.filter)("",o):isArray(a.filter)&&(t=a.filter);var n=[];if("object"!=typeof o||null===o)return"";var i=arrayPrefixGenerators[a.arrayFormat],l="comma"===i&&a.commaRoundTrip;t||(t=Object.keys(o)),a.sort&&t.sort(a.sort);for(var s=getSideChannel(),f=0;f<t.length;++f){var u=t[f];if(null!=u){var d=o[u];a.skipNulls&&null===d||pushToArray(n,stringify(d,u,i,l,a.allowEmptyArrays,a.strictNullHandling,a.skipNulls,a.encodeDotInKeys,a.encode?a.encoder:null,a.filter,a.sort,a.allowDots,a.serializeDate,a.format,a.formatter,a.encodeValuesOnly,a.charset,s))}}var y=n.join(a.delimiter),c=!0===a.addQueryPrefix?"?":"";return a.charsetSentinel&&("iso-8859-1"===a.charset?c+="utf8=%26%2310003%3B"+a.delimiter:c+="utf8=%E2%9C%93"+a.delimiter),y.length>0?c+y:""};
-
-},{"1":1,"46":46,"5":5}],5:[function(require,module,exports){
-"use strict";var formats=require(1),getSideChannel=require(46),defineProperty=require(14),has=Object.prototype.hasOwnProperty,isArray=Array.isArray,overflowChannel=getSideChannel(),markOverflow=function markOverflow(e,r){return overflowChannel.set(e,r),e},isOverflow=function isOverflow(e){return overflowChannel.has(e)},getMaxIndex=function getMaxIndex(e){return overflowChannel.get(e)},setMaxIndex=function setMaxIndex(e,r){overflowChannel.set(e,r)},hexTable=function(){for(var e=[],r=0;r<256;++r)e[e.length]="%"+((r<16?"0":"")+r.toString(16)).toUpperCase();return e}(),compactQueue=function compactQueue(e){for(;e.length>1;){var r=e.pop(),t=r.obj[r.prop];if(isArray(t)){for(var n=[],a=0;a<t.length;++a)void 0!==t[a]&&(n[n.length]=t[a]);r.obj[r.prop]=n}}},arrayToObject=function arrayToObject(e,r){for(var t=r&&r.plainObjects?{__proto__:null}:{},n=0;n<e.length;++n)void 0!==e[n]&&(t[n]=e[n]);return t},setProperty=function setProperty(e,r,t){"__proto__"===r&&defineProperty?defineProperty(e,r,{configurable:!0,enumerable:!0,value:t,writable:!0}):e[r]=t},merge=function merge(e,r,t){if(!r)return e;if("object"!=typeof r&&"function"!=typeof r){if(isArray(e)){var n=e.length;if(t&&"number"==typeof t.arrayLimit&&n>=t.arrayLimit){if(t.throwOnLimitExceeded)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");return markOverflow(arrayToObject(e.concat(r),t),n)}e[n]=r}else{if(!e||"object"!=typeof e)return[e,r];if(isOverflow(e)){var a=getMaxIndex(e)+1;e[a]=r,setMaxIndex(e,a)}else{if(t&&t.strictMerge)return[e,r];(t&&(t.plainObjects||t.allowPrototypes)||!has.call(Object.prototype,r))&&(e[r]=!0)}}return e}if(!e||"object"!=typeof e){if(isOverflow(r)){for(var o=Object.keys(r),i=t&&t.plainObjects?{__proto__:null,0:e}:{0:e},l=0;l<o.length;l++)i[parseInt(o[l],10)+1]=r[o[l]];return markOverflow(i,getMaxIndex(r)+1)}var c=[e].concat(r);if(t&&"number"==typeof t.arrayLimit&&c.length>t.arrayLimit){if(t.throwOnLimitExceeded)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");return markOverflow(arrayToObject(c,t),c.length-1)}return c}var f=e;if(isArray(e)&&!isArray(r)&&(f=arrayToObject(e,t)),isArray(e)&&isArray(r)){if(r.forEach(function(r,n){if(has.call(e,n)){var a=e[n];a&&"object"==typeof a&&r&&"object"==typeof r?e[n]=merge(a,r,t):e[e.length]=r}else e[n]=r}),t&&"number"==typeof t.arrayLimit&&e.length>t.arrayLimit){if(t.throwOnLimitExceeded)throw new RangeError("Array limit exceeded. Only "+t.arrayLimit+" element"+(1===t.arrayLimit?"":"s")+" allowed in an array.");return markOverflow(arrayToObject(e,t),e.length-1)}return e}return Object.keys(r).reduce(function(e,n){var a=r[n];if(has.call(e,n)?setProperty(e,n,merge(e[n],a,t)):setProperty(e,n,a),isOverflow(r)&&!isOverflow(e)&&markOverflow(e,getMaxIndex(r)),isOverflow(e)){var o=parseInt(n,10);String(o)===n&&o>=0&&o>getMaxIndex(e)&&setMaxIndex(e,o)}return e},f)},assign=function assignSingleSource(e,r){return Object.keys(r).reduce(function(e,t){return setProperty(e,t,r[t]),e},e)},decode=function(e,r,t){var n=e.replace(/\+/g," ");if("iso-8859-1"===t)return n.replace(/%[0-9a-f]{2}/gi,unescape);try{return decodeURIComponent(n)}catch(e){return n}},limit=1024,encode=function encode(e,r,t,n,a){if(0===e.length)return e;var o=e;if("symbol"==typeof e?o=Symbol.prototype.toString.call(e):"string"!=typeof e&&(o=String(e)),"iso-8859-1"===t)return escape(o).replace(/%u[0-9a-f]{4}/gi,function(e){return"%26%23"+parseInt(e.slice(2),16)+"%3B"});for(var i="",l=0;l<o.length;l+=limit){var c=o.length>=limit?o.slice(l,l+limit):o;if(l+limit<o.length){var f=c.charCodeAt(c.length-1);f>=55296&&f<=56319&&(c=c.slice(0,-1),l-=1)}for(var s=[],u=0;u<c.length;++u){var y=c.charCodeAt(u);45===y||46===y||95===y||126===y||y>=48&&y<=57||y>=65&&y<=90||y>=97&&y<=122||a===formats.RFC1738&&(40===y||41===y)?s[s.length]=c.charAt(u):y<128?s[s.length]=hexTable[y]:y<2048?s[s.length]=hexTable[192|y>>6]+hexTable[128|63&y]:y<55296||y>=57344?s[s.length]=hexTable[224|y>>12]+hexTable[128|y>>6&63]+hexTable[128|63&y]:(u+=1,y=65536+((1023&y)<<10|1023&c.charCodeAt(u)),s[s.length]=hexTable[240|y>>18]+hexTable[128|y>>12&63]+hexTable[128|y>>6&63]+hexTable[128|63&y])}i+=s.join("")}return i},compact=function compact(e){for(var r=[{obj:{o:e},prop:"o"}],t=getSideChannel(),n=0;n<r.length;++n)for(var a=r[n],o=a.obj[a.prop],i=Object.keys(o),l=0;l<i.length;++l){var c=i[l],f=o[c];"object"!=typeof f||null===f||t.has(f)||(r[r.length]={obj:o,prop:c},t.set(f,!0))}return compactQueue(r),e},isRegExp=function isRegExp(e){return"[object RegExp]"===Object.prototype.toString.call(e)},isBuffer=function isBuffer(e){return!(!e||"object"!=typeof e||!(e.constructor&&e.constructor.isBuffer&&e.constructor.isBuffer(e)))},combine=function combine(e,r,t,n,a){if(isOverflow(e)){if(a)throw new RangeError("Array limit exceeded. Only "+t+" element"+(1===t?"":"s")+" allowed in an array.");var o=getMaxIndex(e)+1;return e[o]=r,setMaxIndex(e,o),e}var i=[].concat(e,r);if(i.length>t){if(a)throw new RangeError("Array limit exceeded. Only "+t+" element"+(1===t?"":"s")+" allowed in an array.");return markOverflow(arrayToObject(i,{plainObjects:n}),i.length-1)}return i},maybeMap=function maybeMap(e,r){if(isArray(e)){for(var t=[],n=0;n<e.length;n+=1)t[t.length]=r(e[n]);return t}return r(e)};module.exports={/* common-shake removed: arrayToObject:arrayToObject *//* common-shake removed: assign:assign */combine:combine,compact:compact,decode:decode,encode:encode,isBuffer:isBuffer,isOverflow:isOverflow,isRegExp:isRegExp,markOverflow:markOverflow,maybeMap:maybeMap,merge:merge};
-
-},{"1":1,"14":14,"46":46}],46:[function(require,module,exports){
-"use strict";var $TypeError=require(20),inspect=require(42),getSideChannelList=require(43),getSideChannelMap=require(44),getSideChannelWeakMap=require(45),makeChannel=getSideChannelWeakMap||getSideChannelMap||getSideChannelList;module.exports=function getSideChannel(){var e,n={assert:function(e){if(!n.has(e)){var t=e&&Object(e)===e?"the given object key":inspect(e);throw new $TypeError("Side channel does not contain "+t)}},delete:function(n){return!!e&&e.delete(n)},get:function(n){return e&&e.get(n)},has:function(n){return!!e&&e.has(n)},set:function(n,t){e||(e=makeChannel()),e.set(n,t)}};return n};
-
-},{"20":20,"42":42,"43":43,"44":44,"45":45}],14:[function(require,module,exports){
-"use strict";var $defineProperty=Object.defineProperty||!1;if($defineProperty)try{$defineProperty({},"a",{value:1})}catch(e){$defineProperty=!1}module.exports=$defineProperty;
-
-},{}],6:[function(require,module,exports){
-
-},{}],7:[function(require,module,exports){
-"use strict";var bind=require(24),$apply=require(8),$call=require(9),$reflectApply=require(11);module.exports=$reflectApply||bind.call($call,$apply);
-
-},{"11":11,"24":24,"8":8,"9":9}],9:[function(require,module,exports){
-"use strict";module.exports=Function.prototype.call;
-
-},{}],8:[function(require,module,exports){
-"use strict";module.exports=Function.prototype.apply;
-
-},{}],24:[function(require,module,exports){
-"use strict";var implementation=require(23);module.exports=Function.prototype.bind||implementation;
-
-},{"23":23}],11:[function(require,module,exports){
-"use strict";module.exports="undefined"!=typeof Reflect&&Reflect&&Reflect.apply;
-
-},{}],10:[function(require,module,exports){
-"use strict";var bind=require(24),$TypeError=require(20),$call=require(9),$actualApply=require(7);module.exports=function callBindBasic(r){if(r.length<1||"function"!=typeof r[0])throw new $TypeError("a function is required");return $actualApply(bind,$call,r)};
-
-},{"20":20,"24":24,"7":7,"9":9}],20:[function(require,module,exports){
-"use strict";module.exports=TypeError;
-
-},{}],12:[function(require,module,exports){
-"use strict";var GetIntrinsic=require(25),callBindBasic=require(10),$indexOf=callBindBasic([GetIntrinsic("%String.prototype.indexOf%")]);module.exports=function callBoundIntrinsic(i,n){var t=GetIntrinsic(i,!!n);return"function"==typeof t&&$indexOf(i,".prototype.")>-1?callBindBasic([t]):t};
-
-},{"10":10,"25":25}],25:[function(require,module,exports){
-"use strict";var undefined,$Object=require(22),$Error=require(16),$EvalError=require(15),$RangeError=require(17),$ReferenceError=require(18),$SyntaxError=require(19),$TypeError=require(20),$URIError=require(21),abs=require(34),floor=require(35),max=require(37),min=require(38),pow=require(39),round=require(40),sign=require(41),$Function=Function,getEvalledConstructor=function(r){try{return $Function('"use strict"; return ('+r+").constructor;")()}catch(r){}},$gOPD=require(30),$defineProperty=require(14),throwTypeError=function(){throw new $TypeError},ThrowTypeError=$gOPD?function(){try{return throwTypeError}catch(r){try{return $gOPD(arguments,"callee").get}catch(r){return throwTypeError}}}():throwTypeError,hasSymbols=require(31)(),getProto=require(28),$ObjectGPO=require(26),$ReflectGPO=require(27),$apply=require(8),$call=require(9),needsEval={},TypedArray="undefined"!=typeof Uint8Array&&getProto?getProto(Uint8Array):undefined,INTRINSICS={__proto__:null,"%AggregateError%":"undefined"==typeof AggregateError?undefined:AggregateError,"%Array%":Array,"%ArrayBuffer%":"undefined"==typeof ArrayBuffer?undefined:ArrayBuffer,"%ArrayIteratorPrototype%":hasSymbols&&getProto?getProto([][Symbol.iterator]()):undefined,"%AsyncFromSyncIteratorPrototype%":undefined,"%AsyncFunction%":needsEval,"%AsyncGenerator%":needsEval,"%AsyncGeneratorFunction%":needsEval,"%AsyncIteratorPrototype%":needsEval,"%Atomics%":"undefined"==typeof Atomics?undefined:Atomics,"%BigInt%":"undefined"==typeof BigInt?undefined:BigInt,"%BigInt64Array%":"undefined"==typeof BigInt64Array?undefined:BigInt64Array,"%BigUint64Array%":"undefined"==typeof BigUint64Array?undefined:BigUint64Array,"%Boolean%":Boolean,"%DataView%":"undefined"==typeof DataView?undefined:DataView,"%Date%":Date,"%decodeURI%":decodeURI,"%decodeURIComponent%":decodeURIComponent,"%encodeURI%":encodeURI,"%encodeURIComponent%":encodeURIComponent,"%Error%":$Error,"%eval%":eval,"%EvalError%":$EvalError,"%Float16Array%":"undefined"==typeof Float16Array?undefined:Float16Array,"%Float32Array%":"undefined"==typeof Float32Array?undefined:Float32Array,"%Float64Array%":"undefined"==typeof Float64Array?undefined:Float64Array,"%FinalizationRegistry%":"undefined"==typeof FinalizationRegistry?undefined:FinalizationRegistry,"%Function%":$Function,"%GeneratorFunction%":needsEval,"%Int8Array%":"undefined"==typeof Int8Array?undefined:Int8Array,"%Int16Array%":"undefined"==typeof Int16Array?undefined:Int16Array,"%Int32Array%":"undefined"==typeof Int32Array?undefined:Int32Array,"%isFinite%":isFinite,"%isNaN%":isNaN,"%IteratorPrototype%":hasSymbols&&getProto?getProto(getProto([][Symbol.iterator]())):undefined,"%JSON%":"object"==typeof JSON?JSON:undefined,"%Map%":"undefined"==typeof Map?undefined:Map,"%MapIteratorPrototype%":"undefined"!=typeof Map&&hasSymbols&&getProto?getProto((new Map)[Symbol.iterator]()):undefined,"%Math%":Math,"%Number%":Number,"%Object%":$Object,"%Object.getOwnPropertyDescriptor%":$gOPD,"%parseFloat%":parseFloat,"%parseInt%":parseInt,"%Promise%":"undefined"==typeof Promise?undefined:Promise,"%Proxy%":"undefined"==typeof Proxy?undefined:Proxy,"%RangeError%":$RangeError,"%ReferenceError%":$ReferenceError,"%Reflect%":"undefined"==typeof Reflect?undefined:Reflect,"%RegExp%":RegExp,"%Set%":"undefined"==typeof Set?undefined:Set,"%SetIteratorPrototype%":"undefined"!=typeof Set&&hasSymbols&&getProto?getProto((new Set)[Symbol.iterator]()):undefined,"%SharedArrayBuffer%":"undefined"==typeof SharedArrayBuffer?undefined:SharedArrayBuffer,"%String%":String,"%StringIteratorPrototype%":hasSymbols&&getProto?getProto(""[Symbol.iterator]()):undefined,"%Symbol%":hasSymbols?Symbol:undefined,"%SyntaxError%":$SyntaxError,"%ThrowTypeError%":ThrowTypeError,"%TypedArray%":TypedArray,"%TypeError%":$TypeError,"%Uint8Array%":"undefined"==typeof Uint8Array?undefined:Uint8Array,"%Uint8ClampedArray%":"undefined"==typeof Uint8ClampedArray?undefined:Uint8ClampedArray,"%Uint16Array%":"undefined"==typeof Uint16Array?undefined:Uint16Array,"%Uint32Array%":"undefined"==typeof Uint32Array?undefined:Uint32Array,"%URIError%":$URIError,"%WeakMap%":"undefined"==typeof WeakMap?undefined:WeakMap,"%WeakRef%":"undefined"==typeof WeakRef?undefined:WeakRef,"%WeakSet%":"undefined"==typeof WeakSet?undefined:WeakSet,"%Function.prototype.call%":$call,"%Function.prototype.apply%":$apply,"%Object.defineProperty%":$defineProperty,"%Object.getPrototypeOf%":$ObjectGPO,"%Math.abs%":abs,"%Math.floor%":floor,"%Math.max%":max,"%Math.min%":min,"%Math.pow%":pow,"%Math.round%":round,"%Math.sign%":sign,"%Reflect.getPrototypeOf%":$ReflectGPO};if(getProto)try{null.error}catch(r){var errorProto=getProto(getProto(r));INTRINSICS["%Error.prototype%"]=errorProto}var doEval=function doEval(r){var e;if("%AsyncFunction%"===r)e=getEvalledConstructor("async function () {}");else if("%GeneratorFunction%"===r)e=getEvalledConstructor("function* () {}");else if("%AsyncGeneratorFunction%"===r)e=getEvalledConstructor("async function* () {}");else if("%AsyncGenerator%"===r){var t=doEval("%AsyncGeneratorFunction%");t&&(e=t.prototype)}else if("%AsyncIteratorPrototype%"===r){var o=doEval("%AsyncGenerator%");o&&getProto&&(e=getProto(o.prototype))}return INTRINSICS[r]=e,e},LEGACY_ALIASES={__proto__:null,"%ArrayBufferPrototype%":["ArrayBuffer","prototype"],"%ArrayPrototype%":["Array","prototype"],"%ArrayProto_entries%":["Array","prototype","entries"],"%ArrayProto_forEach%":["Array","prototype","forEach"],"%ArrayProto_keys%":["Array","prototype","keys"],"%ArrayProto_values%":["Array","prototype","values"],"%AsyncFunctionPrototype%":["AsyncFunction","prototype"],"%AsyncGenerator%":["AsyncGeneratorFunction","prototype"],"%AsyncGeneratorPrototype%":["AsyncGeneratorFunction","prototype","prototype"],"%BooleanPrototype%":["Boolean","prototype"],"%DataViewPrototype%":["DataView","prototype"],"%DatePrototype%":["Date","prototype"],"%ErrorPrototype%":["Error","prototype"],"%EvalErrorPrototype%":["EvalError","prototype"],"%Float32ArrayPrototype%":["Float32Array","prototype"],"%Float64ArrayPrototype%":["Float64Array","prototype"],"%FunctionPrototype%":["Function","prototype"],"%Generator%":["GeneratorFunction","prototype"],"%GeneratorPrototype%":["GeneratorFunction","prototype","prototype"],"%Int8ArrayPrototype%":["Int8Array","prototype"],"%Int16ArrayPrototype%":["Int16Array","prototype"],"%Int32ArrayPrototype%":["Int32Array","prototype"],"%JSONParse%":["JSON","parse"],"%JSONStringify%":["JSON","stringify"],"%MapPrototype%":["Map","prototype"],"%NumberPrototype%":["Number","prototype"],"%ObjectPrototype%":["Object","prototype"],"%ObjProto_toString%":["Object","prototype","toString"],"%ObjProto_valueOf%":["Object","prototype","valueOf"],"%PromisePrototype%":["Promise","prototype"],"%PromiseProto_then%":["Promise","prototype","then"],"%Promise_all%":["Promise","all"],"%Promise_reject%":["Promise","reject"],"%Promise_resolve%":["Promise","resolve"],"%RangeErrorPrototype%":["RangeError","prototype"],"%ReferenceErrorPrototype%":["ReferenceError","prototype"],"%RegExpPrototype%":["RegExp","prototype"],"%SetPrototype%":["Set","prototype"],"%SharedArrayBufferPrototype%":["SharedArrayBuffer","prototype"],"%StringPrototype%":["String","prototype"],"%SymbolPrototype%":["Symbol","prototype"],"%SyntaxErrorPrototype%":["SyntaxError","prototype"],"%TypedArrayPrototype%":["TypedArray","prototype"],"%TypeErrorPrototype%":["TypeError","prototype"],"%Uint8ArrayPrototype%":["Uint8Array","prototype"],"%Uint8ClampedArrayPrototype%":["Uint8ClampedArray","prototype"],"%Uint16ArrayPrototype%":["Uint16Array","prototype"],"%Uint32ArrayPrototype%":["Uint32Array","prototype"],"%URIErrorPrototype%":["URIError","prototype"],"%WeakMapPrototype%":["WeakMap","prototype"],"%WeakSetPrototype%":["WeakSet","prototype"]},bind=require(24),hasOwn=require(33),$concat=bind.call($call,Array.prototype.concat),$spliceApply=bind.call($apply,Array.prototype.splice),$replace=bind.call($call,String.prototype.replace),$strSlice=bind.call($call,String.prototype.slice),$exec=bind.call($call,RegExp.prototype.exec),rePropName=/[^%.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|%$))/g,reEscapeChar=/\\(\\)?/g,stringToPath=function stringToPath(r){var e=$strSlice(r,0,1),t=$strSlice(r,-1);if("%"===e&&"%"!==t)throw new $SyntaxError("invalid intrinsic syntax, expected closing `%`");if("%"===t&&"%"!==e)throw new $SyntaxError("invalid intrinsic syntax, expected opening `%`");var o=[];return $replace(r,rePropName,function(r,e,t,n){o[o.length]=t?$replace(n,reEscapeChar,"$1"):e||r}),o},getBaseIntrinsic=function getBaseIntrinsic(r,e){var t,o=r;if(hasOwn(LEGACY_ALIASES,o)&&(o="%"+(t=LEGACY_ALIASES[o])[0]+"%"),hasOwn(INTRINSICS,o)){var n=INTRINSICS[o];if(n===needsEval&&(n=doEval(o)),void 0===n&&!e)throw new $TypeError("intrinsic "+r+" exists, but is not available. Please file an issue!");return{alias:t,name:o,value:n}}throw new $SyntaxError("intrinsic "+r+" does not exist!")};module.exports=function GetIntrinsic(r,e){if("string"!=typeof r||0===r.length)throw new $TypeError("intrinsic name must be a non-empty string");if(arguments.length>1&&"boolean"!=typeof e)throw new $TypeError('"allowMissing" argument must be a boolean');if(null===$exec(/^%?[^%]*%?$/,r))throw new $SyntaxError("`%` may not be present anywhere but at the beginning and end of the intrinsic name");var t=stringToPath(r),o=t.length>0?t[0]:"",n=getBaseIntrinsic("%"+o+"%",e),a=n.name,i=n.value,y=!1,p=n.alias;p&&(o=p[0],$spliceApply(t,$concat([0,1],p)));for(var d=1,s=!0;d<t.length;d+=1){var f=t[d],l=$strSlice(f,0,1),u=$strSlice(f,-1);if(('"'===l||"'"===l||"`"===l||'"'===u||"'"===u||"`"===u)&&l!==u)throw new $SyntaxError("property names with quotes must have matching quotes");if("constructor"!==f&&s||(y=!0),hasOwn(INTRINSICS,a="%"+(o+="."+f)+"%"))i=INTRINSICS[a];else if(null!=i){if(!(f in i)){if(!e)throw new $TypeError("base intrinsic for "+r+" exists, but the property is not available.");return}if($gOPD&&d+1>=t.length){var c=$gOPD(i,f);i=(s=!!c)&&"get"in c&&!("originalValue"in c.get)?c.get:i[f]}else s=hasOwn(i,f),i=i[f];s&&!y&&(INTRINSICS[a]=i)}}return i};
-
-},{"14":14,"15":15,"16":16,"17":17,"18":18,"19":19,"20":20,"21":21,"22":22,"24":24,"26":26,"27":27,"28":28,"30":30,"31":31,"33":33,"34":34,"35":35,"37":37,"38":38,"39":39,"40":40,"41":41,"8":8,"9":9}],13:[function(require,module,exports){
-"use strict";var hasProtoAccessor,callBind=require(10),gOPD=require(30);try{hasProtoAccessor=[].__proto__===Array.prototype}catch(t){if(!t||"object"!=typeof t||!("code"in t)||"ERR_PROTO_ACCESS"!==t.code)throw t}var desc=!!hasProtoAccessor&&gOPD&&gOPD(Object.prototype,"__proto__"),$Object=Object,$getPrototypeOf=$Object.getPrototypeOf;module.exports=desc&&"function"==typeof desc.get?callBind([desc.get]):"function"==typeof $getPrototypeOf&&function getDunder(t){return $getPrototypeOf(null==t?t:$Object(t))};
-
-},{"10":10,"30":30}],30:[function(require,module,exports){
-"use strict";var $gOPD=require(29);if($gOPD)try{$gOPD([],"length")}catch(g){$gOPD=null}module.exports=$gOPD;
-
-},{"29":29}],15:[function(require,module,exports){
-"use strict";module.exports=EvalError;
-
-},{}],16:[function(require,module,exports){
-"use strict";module.exports=Error;
-
-},{}],17:[function(require,module,exports){
-"use strict";module.exports=RangeError;
-
-},{}],18:[function(require,module,exports){
-"use strict";module.exports=ReferenceError;
-
-},{}],19:[function(require,module,exports){
-"use strict";module.exports=SyntaxError;
-
-},{}],21:[function(require,module,exports){
-"use strict";module.exports=URIError;
-
-},{}],22:[function(require,module,exports){
-"use strict";module.exports=Object;
-
-},{}],23:[function(require,module,exports){
-"use strict";var ERROR_MESSAGE="Function.prototype.bind called on incompatible ",toStr=Object.prototype.toString,max=Math.max,funcType="[object Function]",concatty=function concatty(t,n){for(var r=[],o=0;o<t.length;o+=1)r[o]=t[o];for(var e=0;e<n.length;e+=1)r[e+t.length]=n[e];return r},slicy=function slicy(t,n){for(var r=[],o=n||0,e=0;o<t.length;o+=1,e+=1)r[e]=t[o];return r},joiny=function(t,n){for(var r="",o=0;o<t.length;o+=1)r+=t[o],o+1<t.length&&(r+=n);return r};module.exports=function bind(t){var n=this;if("function"!=typeof n||toStr.apply(n)!==funcType)throw new TypeError(ERROR_MESSAGE+n);for(var r,o=slicy(arguments,1),e=max(0,n.length-o.length),i=[],c=0;c<e;c++)i[c]="$"+c;if(r=Function("binder","return function ("+joiny(i,",")+"){ return binder.apply(this,arguments); }")(function(){if(this instanceof r){var e=n.apply(this,concatty(o,arguments));return Object(e)===e?e:this}return n.apply(t,concatty(o,arguments))}),n.prototype){var p=function Empty(){};p.prototype=n.prototype,r.prototype=new p,p.prototype=null}return r};
-
-},{}],37:[function(require,module,exports){
-"use strict";module.exports=Math.max;
-
-},{}],40:[function(require,module,exports){
-"use strict";module.exports=Math.round;
-
-},{}],34:[function(require,module,exports){
-"use strict";module.exports=Math.abs;
-
-},{}],38:[function(require,module,exports){
-"use strict";module.exports=Math.min;
-
-},{}],39:[function(require,module,exports){
-"use strict";module.exports=Math.pow;
-
-},{}],35:[function(require,module,exports){
-"use strict";module.exports=Math.floor;
-
-},{}],27:[function(require,module,exports){
-"use strict";module.exports="undefined"!=typeof Reflect&&Reflect.getPrototypeOf||null;
-
-},{}],26:[function(require,module,exports){
-"use strict";var $Object=require(22);module.exports=$Object.getPrototypeOf||null;
-
-},{"22":22}],33:[function(require,module,exports){
-"use strict";var call=Function.prototype.call,$hasOwn=Object.prototype.hasOwnProperty,bind=require(24);module.exports=bind.call(call,$hasOwn);
-
-},{"24":24}],41:[function(require,module,exports){
-"use strict";var $isNaN=require(36);module.exports=function sign(i){return $isNaN(i)||0===i?i:i<0?-1:1};
-
-},{"36":36}],31:[function(require,module,exports){
-"use strict";var origSymbol="undefined"!=typeof Symbol&&Symbol,hasSymbolSham=require(32);module.exports=function hasNativeSymbols(){return"function"==typeof origSymbol&&"function"==typeof Symbol&&"symbol"==typeof origSymbol("foo")&&"symbol"==typeof Symbol("bar")&&hasSymbolSham()};
-
-},{"32":32}],28:[function(require,module,exports){
-"use strict";var reflectGetProto=require(27),originalGetProto=require(26),getDunderProto=require(13);module.exports=reflectGetProto?function getProto(t){return reflectGetProto(t)}:originalGetProto?function getProto(t){if(!t||"object"!=typeof t&&"function"!=typeof t)throw new TypeError("getProto: not an object");return originalGetProto(t)}:getDunderProto?function getProto(t){return getDunderProto(t)}:null;
-
-},{"13":13,"26":26,"27":27}],29:[function(require,module,exports){
-"use strict";module.exports=Object.getOwnPropertyDescriptor;
-
-},{}],32:[function(require,module,exports){
-"use strict";module.exports=function hasSymbols(){if("function"!=typeof Symbol||"function"!=typeof Object.getOwnPropertySymbols)return!1;if("symbol"==typeof Symbol.iterator)return!0;var t={},e=Symbol("test"),r=Object(e);if("string"==typeof e)return!1;if("[object Symbol]"!==Object.prototype.toString.call(e))return!1;if("[object Symbol]"!==Object.prototype.toString.call(r))return!1;for(var o in t[e]=42,t)return!1;if("function"==typeof Object.keys&&0!==Object.keys(t).length)return!1;if("function"==typeof Object.getOwnPropertyNames&&0!==Object.getOwnPropertyNames(t).length)return!1;var n=Object.getOwnPropertySymbols(t);if(1!==n.length||n[0]!==e)return!1;if(!Object.prototype.propertyIsEnumerable.call(t,e))return!1;if("function"==typeof Object.getOwnPropertyDescriptor){var y=Object.getOwnPropertyDescriptor(t,e);if(42!==y.value||!0!==y.enumerable)return!1}return!0};
-
-},{}],36:[function(require,module,exports){
-"use strict";module.exports=Number.isNaN||function isNaN(e){return e!=e};
-
-},{}],42:[function(require,module,exports){
-(function (global){(function (){
-var hasMap="function"==typeof Map&&Map.prototype,mapSizeDescriptor=Object.getOwnPropertyDescriptor&&hasMap?Object.getOwnPropertyDescriptor(Map.prototype,"size"):null,mapSize=hasMap&&mapSizeDescriptor&&"function"==typeof mapSizeDescriptor.get?mapSizeDescriptor.get:null,mapForEach=hasMap&&Map.prototype.forEach,hasSet="function"==typeof Set&&Set.prototype,setSizeDescriptor=Object.getOwnPropertyDescriptor&&hasSet?Object.getOwnPropertyDescriptor(Set.prototype,"size"):null,setSize=hasSet&&setSizeDescriptor&&"function"==typeof setSizeDescriptor.get?setSizeDescriptor.get:null,setForEach=hasSet&&Set.prototype.forEach,hasWeakMap="function"==typeof WeakMap&&WeakMap.prototype,weakMapHas=hasWeakMap?WeakMap.prototype.has:null,hasWeakSet="function"==typeof WeakSet&&WeakSet.prototype,weakSetHas=hasWeakSet?WeakSet.prototype.has:null,hasWeakRef="function"==typeof WeakRef&&WeakRef.prototype,weakRefDeref=hasWeakRef?WeakRef.prototype.deref:null,booleanValueOf=Boolean.prototype.valueOf,objectToString=Object.prototype.toString,functionToString=Function.prototype.toString,$match=String.prototype.match,$slice=String.prototype.slice,$replace=String.prototype.replace,$toUpperCase=String.prototype.toUpperCase,$toLowerCase=String.prototype.toLowerCase,$test=RegExp.prototype.test,$concat=Array.prototype.concat,$join=Array.prototype.join,$arrSlice=Array.prototype.slice,$floor=Math.floor,bigIntValueOf="function"==typeof BigInt?BigInt.prototype.valueOf:null,gOPS=Object.getOwnPropertySymbols,symToString="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?Symbol.prototype.toString:null,hasShammedSymbols="function"==typeof Symbol&&"object"==typeof Symbol.iterator,toStringTag="function"==typeof Symbol&&Symbol.toStringTag&&(Symbol.toStringTag,1)?Symbol.toStringTag:null,isEnumerable=Object.prototype.propertyIsEnumerable,gPO=("function"==typeof Reflect?Reflect.getPrototypeOf:Object.getPrototypeOf)||([].__proto__===Array.prototype?function(t){return t.__proto__}:null);function addNumericSeparator(t,e){if(t===1/0||t===-1/0||t!=t||t&&t>-1e3&&t<1e3||$test.call(/e/,e))return e;var r=/[0-9](?=(?:[0-9]{3})+(?![0-9]))/g;if("number"==typeof t){var n=t<0?-$floor(-t):$floor(t);if(n!==t){var o=String(n),i=$slice.call(e,o.length+1);return $replace.call(o,r,"$&_")+"."+$replace.call($replace.call(i,/([0-9]{3})/g,"$&_"),/_$/,"")}}return $replace.call(e,r,"$&_")}var utilInspect=require(6),inspectCustom=utilInspect.custom,inspectSymbol=isSymbol(inspectCustom)?inspectCustom:null,quotes={__proto__:null,double:'"',single:"'"},quoteREs={__proto__:null,double:/(["\\])/g,single:/(['\\])/g};function wrapQuotes(t,e,r){var n=r.quoteStyle||e,o=quotes[n];return o+t+o}function quote(t){return $replace.call(String(t),/"/g,"&quot;")}function canTrustToString(t){return!toStringTag||!("object"==typeof t&&(toStringTag in t||void 0!==t[toStringTag]))}function isArray(t){return"[object Array]"===toStr(t)&&canTrustToString(t)}function isDate(t){return"[object Date]"===toStr(t)&&canTrustToString(t)}function isRegExp(t){return"[object RegExp]"===toStr(t)&&canTrustToString(t)}function isError(t){return"[object Error]"===toStr(t)&&canTrustToString(t)}function isString(t){return"[object String]"===toStr(t)&&canTrustToString(t)}function isNumber(t){return"[object Number]"===toStr(t)&&canTrustToString(t)}function isBoolean(t){return"[object Boolean]"===toStr(t)&&canTrustToString(t)}function isSymbol(t){if(hasShammedSymbols)return t&&"object"==typeof t&&t instanceof Symbol;if("symbol"==typeof t)return!0;if(!t||"object"!=typeof t||!symToString)return!1;try{return symToString.call(t),!0}catch(t){}return!1}function isBigInt(t){if(!t||"object"!=typeof t||!bigIntValueOf)return!1;try{return bigIntValueOf.call(t),!0}catch(t){}return!1}module.exports=function inspect_(t,e,r,n){var o=e||{};if(has(o,"quoteStyle")&&!has(quotes,o.quoteStyle))throw new TypeError('option "quoteStyle" must be "single" or "double"');if(has(o,"maxStringLength")&&("number"==typeof o.maxStringLength?o.maxStringLength<0&&o.maxStringLength!==1/0:null!==o.maxStringLength))throw new TypeError('option "maxStringLength", if provided, must be a positive integer, Infinity, or `null`');var i=!has(o,"customInspect")||o.customInspect;if("boolean"!=typeof i&&"symbol"!==i)throw new TypeError("option \"customInspect\", if provided, must be `true`, `false`, or `'symbol'`");if(has(o,"indent")&&null!==o.indent&&"\t"!==o.indent&&!(parseInt(o.indent,10)===o.indent&&o.indent>0))throw new TypeError('option "indent" must be "\\t", an integer > 0, or `null`');if(has(o,"numericSeparator")&&"boolean"!=typeof o.numericSeparator)throw new TypeError('option "numericSeparator", if provided, must be `true` or `false`');var a=o.numericSeparator;if(void 0===t)return"undefined";if(null===t)return"null";if("boolean"==typeof t)return t?"true":"false";if("string"==typeof t)return inspectString(t,o);if("number"==typeof t){if(0===t)return 1/0/t>0?"0":"-0";var c=String(t);return a?addNumericSeparator(t,c):c}if("bigint"==typeof t){var l=String(t)+"n";return a?addNumericSeparator(t,l):l}var u=void 0===o.depth?5:o.depth;if(void 0===r&&(r=0),r>=u&&u>0&&"object"==typeof t)return isArray(t)?"[Array]":"[Object]";var p=getIndent(o,r);if(void 0===n)n=[];else if(indexOf(n,t)>=0)return"[Circular]";function inspect(t,e,i){if(e&&(n=$arrSlice.call(n)).push(e),i){var a={depth:o.depth};return has(o,"quoteStyle")&&(a.quoteStyle=o.quoteStyle),inspect_(t,a,r+1,n)}return inspect_(t,o,r+1,n)}if("function"==typeof t&&!isRegExp(t)){var s=nameOf(t),f=arrObjKeys(t,inspect);return"[Function"+(s?": "+s:" (anonymous)")+"]"+(f.length>0?" { "+$join.call(f,", ")+" }":"")}if(isSymbol(t)){var y=hasShammedSymbols?$replace.call(String(t),/^(Symbol\(.*\))_[^)]*$/,"$1"):symToString.call(t);return"object"!=typeof t||hasShammedSymbols?y:markBoxed(y)}if(isElement(t)){for(var S="<"+$toLowerCase.call(String(t.nodeName)),g=t.attributes||[],m=0;m<g.length;m++)S+=" "+g[m].name+"="+wrapQuotes(quote(g[m].value),"double",o);return S+=">",t.childNodes&&t.childNodes.length&&(S+="..."),S+"</"+$toLowerCase.call(String(t.nodeName))+">"}if(isArray(t)){if(0===t.length)return"[]";var b=arrObjKeys(t,inspect);return p&&!singleLineValues(b)?"["+indentedJoin(b,p)+"]":"[ "+$join.call(b,", ")+" ]"}if(isError(t)){var h=arrObjKeys(t,inspect);return"cause"in Error.prototype||!("cause"in t)||isEnumerable.call(t,"cause")?0===h.length?"["+String(t)+"]":"{ ["+String(t)+"] "+$join.call(h,", ")+" }":"{ ["+String(t)+"] "+$join.call($concat.call("[cause]: "+inspect(t.cause),h),", ")+" }"}if("object"==typeof t&&i){if(inspectSymbol&&"function"==typeof t[inspectSymbol]&&utilInspect)return utilInspect(t,{depth:u-r});if("symbol"!==i&&"function"==typeof t.inspect)return t.inspect()}if(isMap(t)){var d=[];return mapForEach&&mapForEach.call(t,function(e,r){d.push(inspect(r,t,!0)+" => "+inspect(e,t))}),collectionOf("Map",mapSize.call(t),d,p)}if(isSet(t)){var O=[];return setForEach&&setForEach.call(t,function(e){O.push(inspect(e,t))}),collectionOf("Set",setSize.call(t),O,p)}if(isWeakMap(t))return weakCollectionOf("WeakMap");if(isWeakSet(t))return weakCollectionOf("WeakSet");if(isWeakRef(t))return weakCollectionOf("WeakRef");if(isNumber(t))return markBoxed(inspect(Number(t)));if(isBigInt(t))return markBoxed(inspect(bigIntValueOf.call(t)));if(isBoolean(t))return markBoxed(booleanValueOf.call(t));if(isString(t))return markBoxed(inspect(String(t)));if("undefined"!=typeof window&&t===window)return"{ [object Window] }";if("undefined"!=typeof globalThis&&t===globalThis||"undefined"!=typeof global&&t===global)return"{ [object globalThis] }";if(!isDate(t)&&!isRegExp(t)){var j=arrObjKeys(t,inspect),w=gPO?gPO(t)===Object.prototype:t instanceof Object||t.constructor===Object,$=t instanceof Object?"":"null prototype",v=!w&&toStringTag&&Object(t)===t&&toStringTag in t?$slice.call(toStr(t),8,-1):$?"Object":"",k=(w||"function"!=typeof t.constructor?"":t.constructor.name?t.constructor.name+" ":"")+(v||$?"["+$join.call($concat.call([],v||[],$||[]),": ")+"] ":"");return 0===j.length?k+"{}":p?k+"{"+indentedJoin(j,p)+"}":k+"{ "+$join.call(j,", ")+" }"}return String(t)};var hasOwn=Object.prototype.hasOwnProperty||function(t){return t in this};function has(t,e){return hasOwn.call(t,e)}function toStr(t){return objectToString.call(t)}function nameOf(t){if(t.name)return t.name;var e=$match.call(functionToString.call(t),/^function\s*([\w$]+)/);return e?e[1]:null}function indexOf(t,e){if(t.indexOf)return t.indexOf(e);for(var r=0,n=t.length;r<n;r++)if(t[r]===e)return r;return-1}function isMap(t){if(!mapSize||!t||"object"!=typeof t)return!1;try{mapSize.call(t);try{setSize.call(t)}catch(t){return!0}return t instanceof Map}catch(t){}return!1}function isWeakMap(t){if(!weakMapHas||!t||"object"!=typeof t)return!1;try{weakMapHas.call(t,weakMapHas);try{weakSetHas.call(t,weakSetHas)}catch(t){return!0}return t instanceof WeakMap}catch(t){}return!1}function isWeakRef(t){if(!weakRefDeref||!t||"object"!=typeof t)return!1;try{return weakRefDeref.call(t),!0}catch(t){}return!1}function isSet(t){if(!setSize||!t||"object"!=typeof t)return!1;try{setSize.call(t);try{mapSize.call(t)}catch(t){return!0}return t instanceof Set}catch(t){}return!1}function isWeakSet(t){if(!weakSetHas||!t||"object"!=typeof t)return!1;try{weakSetHas.call(t,weakSetHas);try{weakMapHas.call(t,weakMapHas)}catch(t){return!0}return t instanceof WeakSet}catch(t){}return!1}function isElement(t){return!(!t||"object"!=typeof t)&&("undefined"!=typeof HTMLElement&&t instanceof HTMLElement||"string"==typeof t.nodeName&&"function"==typeof t.getAttribute)}function inspectString(t,e){if(t.length>e.maxStringLength){var r=t.length-e.maxStringLength,n="... "+r+" more character"+(r>1?"s":"");return inspectString($slice.call(t,0,e.maxStringLength),e)+n}var o=quoteREs[e.quoteStyle||"single"];return o.lastIndex=0,wrapQuotes($replace.call($replace.call(t,o,"\\$1"),/[\x00-\x1f]/g,lowbyte),"single",e)}function lowbyte(t){var e=t.charCodeAt(0),r={8:"b",9:"t",10:"n",12:"f",13:"r"}[e];return r?"\\"+r:"\\x"+(e<16?"0":"")+$toUpperCase.call(e.toString(16))}function markBoxed(t){return"Object("+t+")"}function weakCollectionOf(t){return t+" { ? }"}function collectionOf(t,e,r,n){return t+" ("+e+") {"+(n?indentedJoin(r,n):$join.call(r,", "))+"}"}function singleLineValues(t){for(var e=0;e<t.length;e++)if(indexOf(t[e],"\n")>=0)return!1;return!0}function getIndent(t,e){var r;if("\t"===t.indent)r="\t";else{if(!("number"==typeof t.indent&&t.indent>0))return null;r=$join.call(Array(t.indent+1)," ")}return{base:r,prev:$join.call(Array(e+1),r)}}function indentedJoin(t,e){if(0===t.length)return"";var r="\n"+e.prev+e.base;return r+$join.call(t,","+r)+"\n"+e.prev}function arrObjKeys(t,e){var r=isArray(t),n=[];if(r){n.length=t.length;for(var o=0;o<t.length;o++)n[o]=has(t,o)?e(t[o],t):""}var i,a="function"==typeof gOPS?gOPS(t):[];if(hasShammedSymbols){i={};for(var c=0;c<a.length;c++)i["$"+a[c]]=a[c]}for(var l in t)has(t,l)&&(r&&String(Number(l))===l&&l<t.length||hasShammedSymbols&&i["$"+l]instanceof Symbol||($test.call(/[^\w$]/,l)?n.push(e(l,t)+": "+e(t[l],t)):n.push(l+": "+e(t[l],t))));if("function"==typeof gOPS)for(var u=0;u<a.length;u++)isEnumerable.call(t,a[u])&&n.push("["+e(a[u])+"]: "+e(t[a[u]],t));return n}
-
-}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"6":6}],43:[function(require,module,exports){
-"use strict";var inspect=require(42),$TypeError=require(20),listGetNode=function(e,t,n){for(var i,r=e;null!=(i=r.next);r=i)if(i.key===t)return r.next=i.next,n||(i.next=e.next,e.next=i),i},listGet=function(e,t){if(e){var n=listGetNode(e,t);return n&&n.value}},listSet=function(e,t,n){var i=listGetNode(e,t);i?i.value=n:e.next={key:t,next:e.next,value:n}},listHas=function(e,t){return!!e&&!!listGetNode(e,t)},listDelete=function(e,t){if(e)return listGetNode(e,t,!0)};module.exports=function getSideChannelList(){var e,t={assert:function(e){if(!t.has(e))throw new $TypeError("Side channel does not contain "+inspect(e))},delete:function(t){var n=listDelete(e,t);return n&&e&&!e.next&&(e=void 0),!!n},get:function(t){return listGet(e,t)},has:function(t){return listHas(e,t)},set:function(t,n){e||(e={next:void 0}),listSet(e,t,n)}};return t};
-
-},{"20":20,"42":42}],44:[function(require,module,exports){
-"use strict";var GetIntrinsic=require(25),callBound=require(12),inspect=require(42),$TypeError=require(20),$Map=GetIntrinsic("%Map%",!0),$mapGet=callBound("Map.prototype.get",!0),$mapSet=callBound("Map.prototype.set",!0),$mapHas=callBound("Map.prototype.has",!0),$mapDelete=callBound("Map.prototype.delete",!0),$mapSize=callBound("Map.prototype.size",!0);module.exports=!!$Map&&function getSideChannelMap(){var e,t={assert:function(e){if(!t.has(e))throw new $TypeError("Side channel does not contain "+inspect(e))},delete:function(t){if(e){var n=$mapDelete(e,t);return 0===$mapSize(e)&&(e=void 0),n}return!1},get:function(t){if(e)return $mapGet(e,t)},has:function(t){return!!e&&$mapHas(e,t)},set:function(t,n){e||(e=new $Map),$mapSet(e,t,n)}};return t};
-
-},{"12":12,"20":20,"25":25,"42":42}],45:[function(require,module,exports){
-"use strict";var GetIntrinsic=require(25),callBound=require(12),inspect=require(42),getSideChannelMap=require(44),$TypeError=require(20),$WeakMap=GetIntrinsic("%WeakMap%",!0),$weakMapGet=callBound("WeakMap.prototype.get",!0),$weakMapSet=callBound("WeakMap.prototype.set",!0),$weakMapHas=callBound("WeakMap.prototype.has",!0),$weakMapDelete=callBound("WeakMap.prototype.delete",!0);module.exports=$WeakMap?function getSideChannelWeakMap(){var e,t,a={assert:function(e){if(!a.has(e))throw new $TypeError("Side channel does not contain "+inspect(e))},delete:function(a){if($WeakMap&&a&&("object"==typeof a||"function"==typeof a)){if(e)return $weakMapDelete(e,a)}else if(getSideChannelMap&&t)return t.delete(a);return!1},get:function(a){return $WeakMap&&a&&("object"==typeof a||"function"==typeof a)&&e?$weakMapGet(e,a):t&&t.get(a)},has:function(a){return $WeakMap&&a&&("object"==typeof a||"function"==typeof a)&&e?$weakMapHas(e,a):!!t&&t.has(a)},set:function(a,n){$WeakMap&&a&&("object"==typeof a||"function"==typeof a)?(e||(e=new $WeakMap),$weakMapSet(e,a,n)):getSideChannelMap&&(t||(t=getSideChannelMap()),t.set(a,n))}};return a}:getSideChannelMap;
-
-},{"12":12,"20":20,"25":25,"42":42,"44":44}]},{},[2])(2)
-});
diff --git a/node_modules/qs/eslint.config.mjs b/node_modules/qs/eslint.config.mjs
deleted file mode 100644
index 5c9fc1f..0000000
--- a/node_modules/qs/eslint.config.mjs
+++ /dev/null
@@ -1,57 +0,0 @@
-import ljharbConfig from '@ljharb/eslint-config/flat';
-
-export default [
- {
- ignores: ['dist/'],
- },
-
- ...ljharbConfig,
-
- {
- rules: {
- complexity: 'off',
- 'consistent-return': 'warn',
- eqeqeq: ['error', 'allow-null'],
- 'func-name-matching': 'off',
- 'id-length': [
- 'error',
- {
- max: 25,
- min: 1,
- properties: 'never',
- },
- ],
- indent: ['error', 4],
- 'max-lines': 'off',
- 'max-lines-per-function': [
- 'error',
- { max: 150 },
- ],
- 'max-params': ['error', 18],
- 'max-statements': ['error', 100],
- 'multiline-comment-style': 'off',
- 'no-continue': 'warn',
- 'no-magic-numbers': 'off',
- 'no-restricted-syntax': [
- 'error',
- 'BreakStatement',
- 'DebuggerStatement',
- 'ForInStatement',
- 'LabeledStatement',
- 'WithStatement',
- ],
- },
- },
-
- {
- files: ['test/**'],
- rules: {
- 'function-paren-newline': 'off',
- 'max-lines-per-function': 'off',
- 'max-statements': 'off',
- 'no-buffer-constructor': 'off',
- 'no-extend-native': 'off',
- 'no-throw-literal': 'off',
- },
- },
-];
diff --git a/node_modules/qs/lib/formats.js b/node_modules/qs/lib/formats.js
deleted file mode 100644
index f36cf20..0000000
--- a/node_modules/qs/lib/formats.js
+++ /dev/null
@@ -1,23 +0,0 @@
-'use strict';
-
-var replace = String.prototype.replace;
-var percentTwenties = /%20/g;
-
-var Format = {
- RFC1738: 'RFC1738',
- RFC3986: 'RFC3986'
-};
-
-module.exports = {
- 'default': Format.RFC3986,
- formatters: {
- RFC1738: function (value) {
- return replace.call(value, percentTwenties, '+');
- },
- RFC3986: function (value) {
- return String(value);
- }
- },
- RFC1738: Format.RFC1738,
- RFC3986: Format.RFC3986
-};
diff --git a/node_modules/qs/lib/index.js b/node_modules/qs/lib/index.js
deleted file mode 100644
index 0d6a97d..0000000
--- a/node_modules/qs/lib/index.js
+++ /dev/null
@@ -1,11 +0,0 @@
-'use strict';
-
-var stringify = require('./stringify');
-var parse = require('./parse');
-var formats = require('./formats');
-
-module.exports = {
- formats: formats,
- parse: parse,
- stringify: stringify
-};
diff --git a/node_modules/qs/lib/parse.js b/node_modules/qs/lib/parse.js
deleted file mode 100644
index 0ccb70c..0000000
--- a/node_modules/qs/lib/parse.js
+++ /dev/null
@@ -1,414 +0,0 @@
-'use strict';
-
-var utils = require('./utils');
-
-var has = Object.prototype.hasOwnProperty;
-var isArray = Array.isArray;
-
-var defaults = {
- allowDots: false,
- allowEmptyArrays: false,
- allowPrototypes: false,
- allowSparse: false,
- arrayLimit: 20,
- charset: 'utf-8',
- charsetSentinel: false,
- comma: false,
- decodeDotInKeys: false,
- decoder: utils.decode,
- delimiter: '&',
- depth: 5,
- duplicates: 'combine',
- ignoreQueryPrefix: false,
- interpretNumericEntities: false,
- parameterLimit: 1000,
- parseArrays: true,
- plainObjects: false,
- strictDepth: false,
- strictMerge: true,
- strictNullHandling: false,
- throwOnLimitExceeded: false
-};
-
-var interpretNumericEntities = function (str) {
- return str.replace(/&#(\d+);/g, function ($0, numberStr) {
- return String.fromCharCode(parseInt(numberStr, 10));
- });
-};
-
-var parseArrayValue = function (val, options, currentArrayLength, isFlatArrayValue) {
- if (val && typeof val === 'string' && options.comma && val.indexOf(',') > -1) {
- if (isFlatArrayValue && options.throwOnLimitExceeded) {
- var commaCount = 0;
- var commaIndex = val.indexOf(',');
- while (commaIndex > -1) {
- commaCount += 1;
- if (commaCount >= options.arrayLimit) {
- throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
- }
- commaIndex = val.indexOf(',', commaIndex + 1);
- }
- }
- return val.split(',');
- }
-
- if (options.throwOnLimitExceeded && currentArrayLength >= options.arrayLimit) {
- throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
- }
-
- return val;
-};
-
-// This is what browsers will submit when the ✓ character occurs in an
-// application/x-www-form-urlencoded body and the encoding of the page containing
-// the form is iso-8859-1, or when the submitted form has an accept-charset
-// attribute of iso-8859-1. Presumably also with other charsets that do not contain
-// the ✓ character, such as us-ascii.
-var isoSentinel = 'utf8=%26%2310003%3B'; // encodeURIComponent('&#10003;')
-
-// These are the percent-encoded utf-8 octets representing a checkmark, indicating that the request actually is utf-8 encoded.
-var charsetSentinel = 'utf8=%E2%9C%93'; // encodeURIComponent('✓')
-
-var parseValues = function parseQueryStringValues(str, options) {
- var obj = { __proto__: null };
-
- var cleanStr = options.ignoreQueryPrefix ? str.replace(/^\?/, '') : str;
- cleanStr = cleanStr.replace(/%5B/gi, '[').replace(/%5D/gi, ']');
-
- var limit = options.parameterLimit === Infinity ? void undefined : options.parameterLimit;
- var parts = cleanStr.split(
- options.delimiter,
- options.throwOnLimitExceeded && typeof limit !== 'undefined' ? limit + 1 : limit
- );
-
- if (options.throwOnLimitExceeded && typeof limit !== 'undefined' && parts.length > limit) {
- throw new RangeError('Parameter limit exceeded. Only ' + limit + ' parameter' + (limit === 1 ? '' : 's') + ' allowed.');
- }
-
- var skipIndex = -1; // Keep track of where the utf8 sentinel was found
- var i;
-
- var charset = options.charset;
- if (options.charsetSentinel) {
- for (i = 0; i < parts.length; ++i) {
- if (parts[i].indexOf('utf8=') === 0) {
- if (parts[i] === charsetSentinel) {
- charset = 'utf-8';
- } else if (parts[i] === isoSentinel) {
- charset = 'iso-8859-1';
- }
- skipIndex = i;
- i = parts.length; // The eslint settings do not allow break;
- }
- }
- }
-
- for (i = 0; i < parts.length; ++i) {
- if (i === skipIndex) {
- continue;
- }
- var part = parts[i];
-
- var bracketEqualsPos = part.indexOf(']=');
- var pos = bracketEqualsPos === -1 ? part.indexOf('=') : bracketEqualsPos + 1;
-
- var key;
- var val;
- if (pos === -1) {
- key = options.decoder(part, defaults.decoder, charset, 'key');
- val = options.strictNullHandling ? null : '';
- } else {
- key = options.decoder(part.slice(0, pos), defaults.decoder, charset, 'key');
-
- if (key !== null) {
- val = utils.maybeMap(
- parseArrayValue(
- part.slice(pos + 1),
- options,
- isArray(obj[key]) ? obj[key].length : 0,
- part.indexOf('[]=') === -1
- ),
- function (encodedVal) {
- return options.decoder(encodedVal, defaults.decoder, charset, 'value');
- }
- );
- }
- }
-
- if (val && options.interpretNumericEntities && charset === 'iso-8859-1') {
- val = interpretNumericEntities(String(val));
- }
-
- if (part.indexOf('[]=') > -1) {
- val = isArray(val) ? [val] : val;
- }
-
- if (options.comma && isArray(val) && val.length > options.arrayLimit) {
- val = utils.combine([], val, options.arrayLimit, options.plainObjects, options.throwOnLimitExceeded);
- }
-
- if (key !== null) {
- var existing = has.call(obj, key);
- if (existing && (options.duplicates === 'combine' || part.indexOf('[]=') > -1)) {
- obj[key] = utils.combine(
- obj[key],
- val,
- options.arrayLimit,
- options.plainObjects,
- options.throwOnLimitExceeded
- );
- } else if (!existing || options.duplicates === 'last') {
- obj[key] = val;
- }
- }
- }
-
- return obj;
-};
-
-var parseObject = function (chain, val, options, valuesParsed) {
- var currentArrayLength = 0;
- if (chain.length > 0 && chain[chain.length - 1] === '[]') {
- var parentKey = chain.slice(0, -1).join('');
- currentArrayLength = Array.isArray(val) && val[parentKey] ? val[parentKey].length : 0;
- }
-
- var leaf = valuesParsed ? val : parseArrayValue(val, options, currentArrayLength);
-
- for (var i = chain.length - 1; i >= 0; --i) {
- var obj;
- var root = chain[i];
-
- if (root === '[]' && options.parseArrays) {
- if (utils.isOverflow(leaf)) {
- // leaf is already an overflow object, preserve it
- obj = leaf;
- } else {
- obj = options.allowEmptyArrays && (leaf === '' || (options.strictNullHandling && leaf === null))
- ? []
- : utils.combine(
- [],
- leaf,
- options.arrayLimit,
- options.plainObjects,
- options.throwOnLimitExceeded
- );
- }
- } else {
- obj = options.plainObjects ? { __proto__: null } : {};
- var cleanRoot = root.charAt(0) === '[' && root.charAt(root.length - 1) === ']' ? root.slice(1, -1) : root;
- var decodedRoot = options.decodeDotInKeys ? cleanRoot.replace(/%2E/g, '.') : cleanRoot;
- var index = parseInt(decodedRoot, 10);
- var isValidArrayIndex = !isNaN(index)
- && root !== decodedRoot
- && String(index) === decodedRoot
- && index >= 0
- && options.parseArrays;
- if (!options.parseArrays && decodedRoot === '') {
- obj = { 0: leaf };
- } else if (isValidArrayIndex && index < options.arrayLimit) {
- obj = [];
- obj[index] = leaf;
- } else if (isValidArrayIndex && options.throwOnLimitExceeded) {
- throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
- } else if (isValidArrayIndex) {
- obj[index] = leaf;
- utils.markOverflow(obj, index);
- } else if (decodedRoot !== '__proto__') {
- obj[decodedRoot] = leaf;
- }
- }
-
- leaf = obj;
- }
-
- return leaf;
-};
-
-// Split a key like "a[b][c[]]" into ['a', '[b]', '[c[]]'] while preserving
-// qs parse semantics for depth/prototype guards.
-var splitKeyIntoSegments = function splitKeyIntoSegments(originalKey, options) {
- var key = options.allowDots ? originalKey.replace(/\.([^.[]+)/g, '[$1]') : originalKey;
-
- // depth <= 0 keeps the whole key as one segment
- if (options.depth <= 0) {
- if (!options.plainObjects && has.call(Object.prototype, key)) {
- if (!options.allowPrototypes) {
- return;
- }
- }
-
- return [key];
- }
-
- var segments = [];
-
- // parent before the first '[' (may be empty if key starts with '[')
- var first = key.indexOf('[');
- var parent = first >= 0 ? key.slice(0, first) : key;
- if (parent) {
- if (!options.plainObjects && has.call(Object.prototype, parent)) {
- if (!options.allowPrototypes) {
- return;
- }
- }
-
- segments[segments.length] = parent;
- }
-
- var n = key.length;
- var open = first;
- var collected = 0;
-
- while (open >= 0 && collected < options.depth) {
- var level = 1;
- var i = open + 1;
- var close = -1;
-
- // balance nested '[' and ']' inside this bracket group using a nesting level counter
- while (i < n && close < 0) {
- var cu = key.charCodeAt(i);
- if (cu === 0x5B) { // '['
- level += 1;
- } else if (cu === 0x5D) { // ']'
- level -= 1;
- if (level === 0) {
- close = i; // found matching close; loop will exit by condition
- }
- }
- i += 1;
- }
-
- if (close < 0) {
- // Unterminated group: wrap the raw remainder in one bracket pair so it stays
- // a single literal segment (e.g. "[[]b" -> "[[]b]"); we do not infer missing ']'.
- segments[segments.length] = '[' + key.slice(open) + ']';
- return segments;
- }
-
- var seg = key.slice(open, close + 1);
- // prototype guard for the content of this group
- var content = seg.slice(1, -1);
- if (!options.plainObjects && has.call(Object.prototype, content) && !options.allowPrototypes) {
- return;
- }
-
- segments[segments.length] = seg;
- collected += 1;
-
- // find the next '[' after this balanced group
- open = key.indexOf('[', close + 1);
- }
-
- if (open >= 0) {
- if (options.strictDepth === true) {
- throw new RangeError('Input depth exceeded depth option of ' + options.depth + ' and strictDepth is true');
- }
-
- segments[segments.length] = '[' + key.slice(open) + ']';
- }
-
- return segments;
-};
-
-var parseKeys = function parseQueryStringKeys(givenKey, val, options, valuesParsed) {
- if (!givenKey) {
- return;
- }
-
- var keys = splitKeyIntoSegments(givenKey, options);
-
- if (!keys) {
- return;
- }
-
- return parseObject(keys, val, options, valuesParsed);
-};
-
-var normalizeParseOptions = function normalizeParseOptions(opts) {
- if (!opts) {
- return defaults;
- }
-
- if (typeof opts.allowEmptyArrays !== 'undefined' && typeof opts.allowEmptyArrays !== 'boolean') {
- throw new TypeError('`allowEmptyArrays` option can only be `true` or `false`, when provided');
- }
-
- if (typeof opts.decodeDotInKeys !== 'undefined' && typeof opts.decodeDotInKeys !== 'boolean') {
- throw new TypeError('`decodeDotInKeys` option can only be `true` or `false`, when provided');
- }
-
- if (opts.decoder !== null && typeof opts.decoder !== 'undefined' && typeof opts.decoder !== 'function') {
- throw new TypeError('Decoder has to be a function.');
- }
-
- if (typeof opts.charset !== 'undefined' && opts.charset !== 'utf-8' && opts.charset !== 'iso-8859-1') {
- throw new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined');
- }
-
- if (typeof opts.throwOnLimitExceeded !== 'undefined' && typeof opts.throwOnLimitExceeded !== 'boolean') {
- throw new TypeError('`throwOnLimitExceeded` option must be a boolean');
- }
-
- var charset = typeof opts.charset === 'undefined' ? defaults.charset : opts.charset;
-
- var duplicates = typeof opts.duplicates === 'undefined' ? defaults.duplicates : opts.duplicates;
-
- if (duplicates !== 'combine' && duplicates !== 'first' && duplicates !== 'last') {
- throw new TypeError('The duplicates option must be either combine, first, or last');
- }
-
- var allowDots = typeof opts.allowDots === 'undefined' ? opts.decodeDotInKeys === true ? true : defaults.allowDots : !!opts.allowDots;
-
- return {
- allowDots: allowDots,
- allowEmptyArrays: typeof opts.allowEmptyArrays === 'boolean' ? !!opts.allowEmptyArrays : defaults.allowEmptyArrays,
- allowPrototypes: typeof opts.allowPrototypes === 'boolean' ? opts.allowPrototypes : defaults.allowPrototypes,
- allowSparse: typeof opts.allowSparse === 'boolean' ? opts.allowSparse : defaults.allowSparse,
- arrayLimit: typeof opts.arrayLimit === 'number' ? opts.arrayLimit : defaults.arrayLimit,
- charset: charset,
- charsetSentinel: typeof opts.charsetSentinel === 'boolean' ? opts.charsetSentinel : defaults.charsetSentinel,
- comma: typeof opts.comma === 'boolean' ? opts.comma : defaults.comma,
- decodeDotInKeys: typeof opts.decodeDotInKeys === 'boolean' ? opts.decodeDotInKeys : defaults.decodeDotInKeys,
- decoder: typeof opts.decoder === 'function' ? opts.decoder : defaults.decoder,
- delimiter: typeof opts.delimiter === 'string' || utils.isRegExp(opts.delimiter) ? opts.delimiter : defaults.delimiter,
- // eslint-disable-next-line no-implicit-coercion, no-extra-parens
- depth: (typeof opts.depth === 'number' || opts.depth === false) ? +opts.depth : defaults.depth,
- duplicates: duplicates,
- ignoreQueryPrefix: opts.ignoreQueryPrefix === true,
- interpretNumericEntities: typeof opts.interpretNumericEntities === 'boolean' ? opts.interpretNumericEntities : defaults.interpretNumericEntities,
- parameterLimit: typeof opts.parameterLimit === 'number' ? opts.parameterLimit : defaults.parameterLimit,
- parseArrays: opts.parseArrays !== false,
- plainObjects: typeof opts.plainObjects === 'boolean' ? opts.plainObjects : defaults.plainObjects,
- strictDepth: typeof opts.strictDepth === 'boolean' ? !!opts.strictDepth : defaults.strictDepth,
- strictMerge: typeof opts.strictMerge === 'boolean' ? !!opts.strictMerge : defaults.strictMerge,
- strictNullHandling: typeof opts.strictNullHandling === 'boolean' ? opts.strictNullHandling : defaults.strictNullHandling,
- throwOnLimitExceeded: typeof opts.throwOnLimitExceeded === 'boolean' ? opts.throwOnLimitExceeded : false
- };
-};
-
-module.exports = function (str, opts) {
- var options = normalizeParseOptions(opts);
-
- if (str === '' || str === null || typeof str === 'undefined') {
- return options.plainObjects ? { __proto__: null } : {};
- }
-
- var tempObj = typeof str === 'string' ? parseValues(str, options) : str;
- var obj = options.plainObjects ? { __proto__: null } : {};
-
- // Iterate over the keys and setup the new object
-
- var keys = Object.keys(tempObj);
- for (var i = 0; i < keys.length; ++i) {
- var key = keys[i];
- var newObj = parseKeys(key, tempObj[key], options, typeof str === 'string');
- obj = utils.merge(obj, newObj, options);
- }
-
- if (options.allowSparse === true) {
- return obj;
- }
-
- return utils.compact(obj);
-};
diff --git a/node_modules/qs/lib/stringify.js b/node_modules/qs/lib/stringify.js
deleted file mode 100644
index b661691..0000000
--- a/node_modules/qs/lib/stringify.js
+++ /dev/null
@@ -1,363 +0,0 @@
-'use strict';
-
-var getSideChannel = require('side-channel');
-var utils = require('./utils');
-var formats = require('./formats');
-var has = Object.prototype.hasOwnProperty;
-
-var arrayPrefixGenerators = {
- brackets: function brackets(prefix) {
- return prefix + '[]';
- },
- comma: 'comma',
- indices: function indices(prefix, key) {
- return prefix + '[' + key + ']';
- },
- repeat: function repeat(prefix) {
- return prefix;
- }
-};
-
-var isArray = Array.isArray;
-var push = Array.prototype.push;
-var pushToArray = function (arr, valueOrArray) {
- push.apply(arr, isArray(valueOrArray) ? valueOrArray : [valueOrArray]);
-};
-
-var toISO = Date.prototype.toISOString;
-
-var defaultFormat = formats['default'];
-var defaults = {
- addQueryPrefix: false,
- allowDots: false,
- allowEmptyArrays: false,
- arrayFormat: 'indices',
- charset: 'utf-8',
- charsetSentinel: false,
- commaRoundTrip: false,
- delimiter: '&',
- encode: true,
- encodeDotInKeys: false,
- encoder: utils.encode,
- encodeValuesOnly: false,
- filter: void undefined,
- format: defaultFormat,
- formatter: formats.formatters[defaultFormat],
- // deprecated
- indices: false,
- serializeDate: function serializeDate(date) {
- return toISO.call(date);
- },
- skipNulls: false,
- strictNullHandling: false
-};
-
-var isNonNullishPrimitive = function isNonNullishPrimitive(v) {
- return typeof v === 'string'
- || typeof v === 'number'
- || typeof v === 'boolean'
- || typeof v === 'symbol'
- || typeof v === 'bigint';
-};
-
-var sentinel = {};
-
-var stringify = function stringify(
- object,
- prefix,
- generateArrayPrefix,
- commaRoundTrip,
- allowEmptyArrays,
- strictNullHandling,
- skipNulls,
- encodeDotInKeys,
- encoder,
- filter,
- sort,
- allowDots,
- serializeDate,
- format,
- formatter,
- encodeValuesOnly,
- charset,
- sideChannel
-) {
- var obj = object;
-
- var tmpSc = sideChannel;
- var step = 0;
- var findFlag = false;
- while ((tmpSc = tmpSc.get(sentinel)) !== void undefined && !findFlag) {
- // Where object last appeared in the ref tree
- var pos = tmpSc.get(object);
- step += 1;
- if (typeof pos !== 'undefined') {
- if (pos === step) {
- throw new RangeError('Cyclic object value');
- } else {
- findFlag = true; // Break while
- }
- }
- if (typeof tmpSc.get(sentinel) === 'undefined') {
- step = 0;
- }
- }
-
- if (typeof filter === 'function') {
- obj = filter(prefix, obj);
- } else if (obj instanceof Date) {
- obj = serializeDate(obj);
- } else if (generateArrayPrefix === 'comma' && isArray(obj)) {
- obj = utils.maybeMap(obj, function (value) {
- if (value instanceof Date) {
- return serializeDate(value);
- }
- return value;
- });
- }
-
- if (obj === null) {
- if (strictNullHandling) {
- return formatter(encoder && !encodeValuesOnly ? encoder(prefix, defaults.encoder, charset, 'key', format) : prefix);
- }
-
- obj = '';
- }
-
- if (isNonNullishPrimitive(obj) || utils.isBuffer(obj)) {
- if (encoder) {
- var keyValue = encodeValuesOnly ? prefix : encoder(prefix, defaults.encoder, charset, 'key', format);
- return [formatter(keyValue) + '=' + formatter(encoder(obj, defaults.encoder, charset, 'value', format))];
- }
- return [formatter(prefix) + '=' + formatter(String(obj))];
- }
-
- var values = [];
-
- if (typeof obj === 'undefined') {
- return values;
- }
-
- var objKeys;
- if (generateArrayPrefix === 'comma' && isArray(obj)) {
- // we need to join elements in
- if (encodeValuesOnly && encoder) {
- obj = utils.maybeMap(obj, function (v) {
- return v == null ? v : encoder(v);
- });
- }
- objKeys = [{ value: obj.length > 0 ? obj.join(',') || null : void undefined }];
- } else if (isArray(filter)) {
- objKeys = filter;
- } else {
- var keys = Object.keys(obj);
- objKeys = sort ? keys.sort(sort) : keys;
- }
-
- var encodedPrefix = encodeDotInKeys ? String(prefix).replace(/\./g, '%2E') : String(prefix);
-
- var adjustedPrefix = commaRoundTrip && isArray(obj) && obj.length === 1 ? encodedPrefix + '[]' : encodedPrefix;
-
- if (allowEmptyArrays && isArray(obj) && obj.length === 0) {
- return adjustedPrefix + '[]';
- }
-
- for (var j = 0; j < objKeys.length; ++j) {
- var key = objKeys[j];
- var value = typeof key === 'object' && key && typeof key.value !== 'undefined'
- ? key.value
- : obj[key];
-
- if (skipNulls && value === null) {
- continue;
- }
-
- var encodedKey = allowDots && encodeDotInKeys ? String(key).replace(/\./g, '%2E') : String(key);
- var keyPrefix = isArray(obj)
- ? typeof generateArrayPrefix === 'function' ? generateArrayPrefix(adjustedPrefix, encodedKey) : adjustedPrefix
- : adjustedPrefix + (allowDots ? '.' + encodedKey : '[' + encodedKey + ']');
-
- sideChannel.set(object, step);
- var valueSideChannel = getSideChannel();
- valueSideChannel.set(sentinel, sideChannel);
- pushToArray(values, stringify(
- value,
- keyPrefix,
- generateArrayPrefix,
- commaRoundTrip,
- allowEmptyArrays,
- strictNullHandling,
- skipNulls,
- encodeDotInKeys,
- generateArrayPrefix === 'comma' && encodeValuesOnly && isArray(obj) ? null : encoder,
- filter,
- sort,
- allowDots,
- serializeDate,
- format,
- formatter,
- encodeValuesOnly,
- charset,
- valueSideChannel
- ));
- }
-
- return values;
-};
-
-var normalizeStringifyOptions = function normalizeStringifyOptions(opts) {
- if (!opts) {
- return defaults;
- }
-
- if (typeof opts.allowEmptyArrays !== 'undefined' && typeof opts.allowEmptyArrays !== 'boolean') {
- throw new TypeError('`allowEmptyArrays` option can only be `true` or `false`, when provided');
- }
-
- if (typeof opts.encodeDotInKeys !== 'undefined' && typeof opts.encodeDotInKeys !== 'boolean') {
- throw new TypeError('`encodeDotInKeys` option can only be `true` or `false`, when provided');
- }
-
- if (opts.encoder !== null && typeof opts.encoder !== 'undefined' && typeof opts.encoder !== 'function') {
- throw new TypeError('Encoder has to be a function.');
- }
-
- var charset = opts.charset || defaults.charset;
- if (typeof opts.charset !== 'undefined' && opts.charset !== 'utf-8' && opts.charset !== 'iso-8859-1') {
- throw new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined');
- }
-
- var format = formats['default'];
- if (typeof opts.format !== 'undefined') {
- if (!has.call(formats.formatters, opts.format)) {
- throw new TypeError('Unknown format option provided.');
- }
- format = opts.format;
- }
- var formatter = formats.formatters[format];
-
- var filter = defaults.filter;
- if (typeof opts.filter === 'function' || isArray(opts.filter)) {
- filter = opts.filter;
- }
-
- var arrayFormat;
- if (opts.arrayFormat in arrayPrefixGenerators) {
- arrayFormat = opts.arrayFormat;
- } else if ('indices' in opts) {
- arrayFormat = opts.indices ? 'indices' : 'repeat';
- } else {
- arrayFormat = defaults.arrayFormat;
- }
-
- if ('commaRoundTrip' in opts && typeof opts.commaRoundTrip !== 'boolean') {
- throw new TypeError('`commaRoundTrip` must be a boolean, or absent');
- }
-
- var allowDots = typeof opts.allowDots === 'undefined' ? opts.encodeDotInKeys === true ? true : defaults.allowDots : !!opts.allowDots;
-
- return {
- addQueryPrefix: typeof opts.addQueryPrefix === 'boolean' ? opts.addQueryPrefix : defaults.addQueryPrefix,
- allowDots: allowDots,
- allowEmptyArrays: typeof opts.allowEmptyArrays === 'boolean' ? !!opts.allowEmptyArrays : defaults.allowEmptyArrays,
- arrayFormat: arrayFormat,
- charset: charset,
- charsetSentinel: typeof opts.charsetSentinel === 'boolean' ? opts.charsetSentinel : defaults.charsetSentinel,
- commaRoundTrip: !!opts.commaRoundTrip,
- delimiter: typeof opts.delimiter === 'undefined' ? defaults.delimiter : opts.delimiter,
- encode: typeof opts.encode === 'boolean' ? opts.encode : defaults.encode,
- encodeDotInKeys: typeof opts.encodeDotInKeys === 'boolean' ? opts.encodeDotInKeys : defaults.encodeDotInKeys,
- encoder: typeof opts.encoder === 'function' ? opts.encoder : defaults.encoder,
- encodeValuesOnly: typeof opts.encodeValuesOnly === 'boolean' ? opts.encodeValuesOnly : defaults.encodeValuesOnly,
- filter: filter,
- format: format,
- formatter: formatter,
- serializeDate: typeof opts.serializeDate === 'function' ? opts.serializeDate : defaults.serializeDate,
- skipNulls: typeof opts.skipNulls === 'boolean' ? opts.skipNulls : defaults.skipNulls,
- sort: typeof opts.sort === 'function' ? opts.sort : null,
- strictNullHandling: typeof opts.strictNullHandling === 'boolean' ? opts.strictNullHandling : defaults.strictNullHandling
- };
-};
-
-module.exports = function (object, opts) {
- var obj = object;
- var options = normalizeStringifyOptions(opts);
-
- var objKeys;
- var filter;
-
- if (typeof options.filter === 'function') {
- filter = options.filter;
- obj = filter('', obj);
- } else if (isArray(options.filter)) {
- filter = options.filter;
- objKeys = filter;
- }
-
- var keys = [];
-
- if (typeof obj !== 'object' || obj === null) {
- return '';
- }
-
- var generateArrayPrefix = arrayPrefixGenerators[options.arrayFormat];
- var commaRoundTrip = generateArrayPrefix === 'comma' && options.commaRoundTrip;
-
- if (!objKeys) {
- objKeys = Object.keys(obj);
- }
-
- if (options.sort) {
- objKeys.sort(options.sort);
- }
-
- var sideChannel = getSideChannel();
- for (var i = 0; i < objKeys.length; ++i) {
- var key = objKeys[i];
-
- if (typeof key === 'undefined' || key === null) {
- continue;
- }
-
- var value = obj[key];
-
- if (options.skipNulls && value === null) {
- continue;
- }
- pushToArray(keys, stringify(
- value,
- key,
- generateArrayPrefix,
- commaRoundTrip,
- options.allowEmptyArrays,
- options.strictNullHandling,
- options.skipNulls,
- options.encodeDotInKeys,
- options.encode ? options.encoder : null,
- options.filter,
- options.sort,
- options.allowDots,
- options.serializeDate,
- options.format,
- options.formatter,
- options.encodeValuesOnly,
- options.charset,
- sideChannel
- ));
- }
-
- var joined = keys.join(options.delimiter);
- var prefix = options.addQueryPrefix === true ? '?' : '';
-
- if (options.charsetSentinel) {
- if (options.charset === 'iso-8859-1') {
- // encodeURIComponent('&#10003;'), the "numeric entity" representation of a checkmark
- prefix += 'utf8=%26%2310003%3B' + options.delimiter;
- } else {
- // encodeURIComponent('✓')
- prefix += 'utf8=%E2%9C%93' + options.delimiter;
- }
- }
-
- return joined.length > 0 ? prefix + joined : '';
-};
diff --git a/node_modules/qs/lib/utils.js b/node_modules/qs/lib/utils.js
deleted file mode 100644
index 6fce590..0000000
--- a/node_modules/qs/lib/utils.js
+++ /dev/null
@@ -1,381 +0,0 @@
-'use strict';
-
-var formats = require('./formats');
-var getSideChannel = require('side-channel');
-var defineProperty = require('es-define-property');
-
-var has = Object.prototype.hasOwnProperty;
-var isArray = Array.isArray;
-
-// Track objects created from arrayLimit overflow using side-channel
-// Stores the current max numeric index for O(1) lookup
-var overflowChannel = getSideChannel();
-
-var markOverflow = function markOverflow(obj, maxIndex) {
- overflowChannel.set(obj, maxIndex);
- return obj;
-};
-
-var isOverflow = function isOverflow(obj) {
- return overflowChannel.has(obj);
-};
-
-var getMaxIndex = function getMaxIndex(obj) {
- return overflowChannel.get(obj);
-};
-
-var setMaxIndex = function setMaxIndex(obj, maxIndex) {
- overflowChannel.set(obj, maxIndex);
-};
-
-var hexTable = (function () {
- var array = [];
- for (var i = 0; i < 256; ++i) {
- array[array.length] = '%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase();
- }
-
- return array;
-}());
-
-var compactQueue = function compactQueue(queue) {
- while (queue.length > 1) {
- var item = queue.pop();
- var obj = item.obj[item.prop];
-
- if (isArray(obj)) {
- var compacted = [];
-
- for (var j = 0; j < obj.length; ++j) {
- if (typeof obj[j] !== 'undefined') {
- compacted[compacted.length] = obj[j];
- }
- }
-
- item.obj[item.prop] = compacted;
- }
- }
-};
-
-var arrayToObject = function arrayToObject(source, options) {
- var obj = options && options.plainObjects ? { __proto__: null } : {};
- for (var i = 0; i < source.length; ++i) {
- if (typeof source[i] !== 'undefined') {
- obj[i] = source[i];
- }
- }
-
- return obj;
-};
-
-var setProperty = function setProperty(obj, key, value) {
- if (key === '__proto__' && defineProperty) {
- defineProperty(obj, key, {
- configurable: true,
- enumerable: true,
- value: value,
- writable: true
- });
- } else {
- obj[key] = value;
- }
-};
-
-var merge = function merge(target, source, options) {
- /* eslint no-param-reassign: 0 */
- if (!source) {
- return target;
- }
-
- if (typeof source !== 'object' && typeof source !== 'function') {
- if (isArray(target)) {
- var nextIndex = target.length;
- if (options && typeof options.arrayLimit === 'number' && nextIndex >= options.arrayLimit) {
- if (options.throwOnLimitExceeded) {
- throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
- }
- return markOverflow(arrayToObject(target.concat(source), options), nextIndex);
- }
- target[nextIndex] = source;
- } else if (target && typeof target === 'object') {
- if (isOverflow(target)) {
- // Add at next numeric index for overflow objects
- var newIndex = getMaxIndex(target) + 1;
- target[newIndex] = source;
- setMaxIndex(target, newIndex);
- } else if (options && options.strictMerge) {
- return [target, source];
- } else if (
- (options && (options.plainObjects || options.allowPrototypes))
- || !has.call(Object.prototype, source)
- ) {
- target[source] = true;
- }
- } else {
- return [target, source];
- }
-
- return target;
- }
-
- if (!target || typeof target !== 'object') {
- if (isOverflow(source)) {
- // Create new object with target at 0, source values shifted by 1
- var sourceKeys = Object.keys(source);
- var result = options && options.plainObjects
- ? { __proto__: null, 0: target }
- : { 0: target };
- for (var m = 0; m < sourceKeys.length; m++) {
- var oldKey = parseInt(sourceKeys[m], 10);
- result[oldKey + 1] = source[sourceKeys[m]];
- }
- return markOverflow(result, getMaxIndex(source) + 1);
- }
- var combined = [target].concat(source);
- if (options && typeof options.arrayLimit === 'number' && combined.length > options.arrayLimit) {
- if (options.throwOnLimitExceeded) {
- throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
- }
- return markOverflow(arrayToObject(combined, options), combined.length - 1);
- }
- return combined;
- }
-
- var mergeTarget = target;
- if (isArray(target) && !isArray(source)) {
- mergeTarget = arrayToObject(target, options);
- }
-
- if (isArray(target) && isArray(source)) {
- source.forEach(function (item, i) {
- if (has.call(target, i)) {
- var targetItem = target[i];
- if (targetItem && typeof targetItem === 'object' && item && typeof item === 'object') {
- target[i] = merge(targetItem, item, options);
- } else {
- target[target.length] = item;
- }
- } else {
- target[i] = item;
- }
- });
- if (options && typeof options.arrayLimit === 'number' && target.length > options.arrayLimit) {
- if (options.throwOnLimitExceeded) {
- throw new RangeError('Array limit exceeded. Only ' + options.arrayLimit + ' element' + (options.arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
- }
- return markOverflow(arrayToObject(target, options), target.length - 1);
- }
- return target;
- }
-
- return Object.keys(source).reduce(function (acc, key) {
- var value = source[key];
-
- if (has.call(acc, key)) {
- setProperty(acc, key, merge(acc[key], value, options));
- } else {
- setProperty(acc, key, value);
- }
-
- if (isOverflow(source) && !isOverflow(acc)) {
- markOverflow(acc, getMaxIndex(source));
- }
- if (isOverflow(acc)) {
- var keyNum = parseInt(key, 10);
- if (String(keyNum) === key && keyNum >= 0 && keyNum > getMaxIndex(acc)) {
- setMaxIndex(acc, keyNum);
- }
- }
-
- return acc;
- }, mergeTarget);
-};
-
-var assign = function assignSingleSource(target, source) {
- return Object.keys(source).reduce(function (acc, key) {
- setProperty(acc, key, source[key]);
- return acc;
- }, target);
-};
-
-var decode = function (str, defaultDecoder, charset) {
- var strWithoutPlus = str.replace(/\+/g, ' ');
- if (charset === 'iso-8859-1') {
- // unescape never throws, no try...catch needed:
- return strWithoutPlus.replace(/%[0-9a-f]{2}/gi, unescape);
- }
- // utf-8
- try {
- return decodeURIComponent(strWithoutPlus);
- } catch (e) {
- return strWithoutPlus;
- }
-};
-
-var limit = 1024;
-
-/* eslint operator-linebreak: [2, "before"] */
-
-var encode = function encode(str, defaultEncoder, charset, kind, format) {
- // This code was originally written by Brian White (mscdex) for the io.js core querystring library.
- // It has been adapted here for stricter adherence to RFC 3986
- if (str.length === 0) {
- return str;
- }
-
- var string = str;
- if (typeof str === 'symbol') {
- string = Symbol.prototype.toString.call(str);
- } else if (typeof str !== 'string') {
- string = String(str);
- }
-
- if (charset === 'iso-8859-1') {
- return escape(string).replace(/%u[0-9a-f]{4}/gi, function ($0) {
- return '%26%23' + parseInt($0.slice(2), 16) + '%3B';
- });
- }
-
- var out = '';
- for (var j = 0; j < string.length; j += limit) {
- var segment = string.length >= limit ? string.slice(j, j + limit) : string;
- if (j + limit < string.length) {
- var last = segment.charCodeAt(segment.length - 1);
- if (last >= 0xD800 && last <= 0xDBFF) {
- segment = segment.slice(0, -1);
- j -= 1;
- }
- }
- var arr = [];
-
- for (var i = 0; i < segment.length; ++i) {
- var c = segment.charCodeAt(i);
- if (
- c === 0x2D // -
- || c === 0x2E // .
- || c === 0x5F // _
- || c === 0x7E // ~
- || (c >= 0x30 && c <= 0x39) // 0-9
- || (c >= 0x41 && c <= 0x5A) // a-z
- || (c >= 0x61 && c <= 0x7A) // A-Z
- || (format === formats.RFC1738 && (c === 0x28 || c === 0x29)) // ( )
- ) {
- arr[arr.length] = segment.charAt(i);
- continue;
- }
-
- if (c < 0x80) {
- arr[arr.length] = hexTable[c];
- continue;
- }
-
- if (c < 0x800) {
- arr[arr.length] = hexTable[0xC0 | (c >> 6)]
- + hexTable[0x80 | (c & 0x3F)];
- continue;
- }
-
- if (c < 0xD800 || c >= 0xE000) {
- arr[arr.length] = hexTable[0xE0 | (c >> 12)]
- + hexTable[0x80 | ((c >> 6) & 0x3F)]
- + hexTable[0x80 | (c & 0x3F)];
- continue;
- }
-
- i += 1;
- c = 0x10000 + (((c & 0x3FF) << 10) | (segment.charCodeAt(i) & 0x3FF));
-
- arr[arr.length] = hexTable[0xF0 | (c >> 18)]
- + hexTable[0x80 | ((c >> 12) & 0x3F)]
- + hexTable[0x80 | ((c >> 6) & 0x3F)]
- + hexTable[0x80 | (c & 0x3F)];
- }
-
- out += arr.join('');
- }
-
- return out;
-};
-
-var compact = function compact(value) {
- var queue = [{ obj: { o: value }, prop: 'o' }];
- var refs = getSideChannel();
-
- for (var i = 0; i < queue.length; ++i) {
- var item = queue[i];
- var obj = item.obj[item.prop];
-
- var keys = Object.keys(obj);
- for (var j = 0; j < keys.length; ++j) {
- var key = keys[j];
- var val = obj[key];
- if (typeof val === 'object' && val !== null && !refs.has(val)) {
- queue[queue.length] = { obj: obj, prop: key };
- refs.set(val, true);
- }
- }
- }
-
- compactQueue(queue);
-
- return value;
-};
-
-var isRegExp = function isRegExp(obj) {
- return Object.prototype.toString.call(obj) === '[object RegExp]';
-};
-
-var isBuffer = function isBuffer(obj) {
- if (!obj || typeof obj !== 'object') {
- return false;
- }
-
- return !!(obj.constructor && obj.constructor.isBuffer && obj.constructor.isBuffer(obj));
-};
-
-var combine = function combine(a, b, arrayLimit, plainObjects, throwOnLimitExceeded) {
- // If 'a' is already an overflow object, add to it
- if (isOverflow(a)) {
- if (throwOnLimitExceeded) {
- throw new RangeError('Array limit exceeded. Only ' + arrayLimit + ' element' + (arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
- }
- var newIndex = getMaxIndex(a) + 1;
- a[newIndex] = b;
- setMaxIndex(a, newIndex);
- return a;
- }
-
- var result = [].concat(a, b);
- if (result.length > arrayLimit) {
- if (throwOnLimitExceeded) {
- throw new RangeError('Array limit exceeded. Only ' + arrayLimit + ' element' + (arrayLimit === 1 ? '' : 's') + ' allowed in an array.');
- }
- return markOverflow(arrayToObject(result, { plainObjects: plainObjects }), result.length - 1);
- }
- return result;
-};
-
-var maybeMap = function maybeMap(val, fn) {
- if (isArray(val)) {
- var mapped = [];
- for (var i = 0; i < val.length; i += 1) {
- mapped[mapped.length] = fn(val[i]);
- }
- return mapped;
- }
- return fn(val);
-};
-
-module.exports = {
- arrayToObject: arrayToObject,
- assign: assign,
- combine: combine,
- compact: compact,
- decode: decode,
- encode: encode,
- isBuffer: isBuffer,
- isOverflow: isOverflow,
- isRegExp: isRegExp,
- markOverflow: markOverflow,
- maybeMap: maybeMap,
- merge: merge
-};
diff --git a/node_modules/qs/package.json b/node_modules/qs/package.json
deleted file mode 100644
index baa6795..0000000
--- a/node_modules/qs/package.json
+++ /dev/null
@@ -1,95 +0,0 @@
-{
- "name": "qs",
- "description": "A querystring parser that supports nesting and arrays, with a depth limit",
- "homepage": "https://github.com/ljharb/qs",
- "version": "6.15.3",
- "repository": {
- "type": "git",
- "url": "https://github.com/ljharb/qs.git"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- },
- "main": "lib/index.js",
- "sideEffects": false,
- "contributors": [
- {
- "name": "Jordan Harband",
- "email": "ljharb@gmail.com",
- "url": "http://ljharb.codes"
- }
- ],
- "keywords": [
- "querystring",
- "qs",
- "query",
- "url",
- "parse",
- "stringify"
- ],
- "engines": {
- "node": ">=0.6"
- },
- "dependencies": {
- "es-define-property": "^1.0.1",
- "side-channel": "^1.1.1"
- },
- "devDependencies": {
- "@browserify/envify": "^6.0.0",
- "@browserify/uglifyify": "^6.0.0",
- "@ljharb/eslint-config": "^22.2.3",
- "browserify": "^16.5.2",
- "bundle-collapser": "^1.4.0",
- "common-shakeify": "~1.0.0",
- "eclint": "^2.8.1",
- "es-value-fixtures": "^1.7.1",
- "eslint": "^10.5.0",
- "evalmd": "^0.0.19",
- "for-each": "^0.3.5",
- "glob": "=10.3.7",
- "has-bigints": "^1.1.0",
- "has-override-mistake": "^1.0.1",
- "has-property-descriptors": "^1.0.2",
- "has-proto": "^1.2.0",
- "has-symbols": "^1.1.0",
- "iconv-lite": "^0.5.2",
- "in-publish": "^2.0.1",
- "jackspeak": "=2.1.1",
- "jiti": "^0.0.0",
- "mkdirp": "^0.5.5",
- "mock-property": "^1.1.2",
- "module-deps": "^6.2.3",
- "npmignore": "^0.3.5",
- "nyc": "^10.3.2",
- "object-inspect": "^1.13.4",
- "qs-iconv": "^1.0.4",
- "safe-publish-latest": "^2.0.0",
- "safer-buffer": "^2.1.2",
- "tape": "^5.10.2",
- "unassertify": "^3.0.1"
- },
- "scripts": {
- "prepack": "npmignore --auto --commentLines=autogenerated && npm run dist",
- "prepublishOnly": "safe-publish-latest",
- "prepublish": "not-in-publish || npm run prepublishOnly",
- "pretest": "npm run --silent readme && npm run --silent lint",
- "test": "npm run tests-only",
- "tests-only": "nyc tape 'test/**/*.js'",
- "posttest": "npx npm@'>=10.2' audit --production",
- "readme": "evalmd README.md",
- "postlint": "eclint check $(git ls-files | xargs find 2> /dev/null | grep -vE 'node_modules|\\.git' | grep -v dist/)",
- "lint": "eslint .",
- "dist": "mkdirp dist && browserify --standalone Qs -g unassertify -g @browserify/envify -g [@browserify/uglifyify --mangle.keep_fnames --compress.keep_fnames --format.indent_level=1 --compress.arrows=false --compress.passes=4 --compress.typeofs=false] -p common-shakeify -p bundle-collapser/plugin lib/index.js > dist/qs.js"
- },
- "license": "BSD-3-Clause",
- "publishConfig": {
- "ignore": [
- "!dist/*",
- "bower.json",
- "component.json",
- ".github/workflows",
- "logos",
- "tea.yaml"
- ]
- }
-}
diff --git a/node_modules/qs/test/empty-keys-cases.js b/node_modules/qs/test/empty-keys-cases.js
deleted file mode 100644
index 2b1190e..0000000
--- a/node_modules/qs/test/empty-keys-cases.js
+++ /dev/null
@@ -1,267 +0,0 @@
-'use strict';
-
-module.exports = {
- emptyTestCases: [
- {
- input: '&',
- withEmptyKeys: {},
- stringifyOutput: {
- brackets: '',
- indices: '',
- repeat: ''
- },
- noEmptyKeys: {}
- },
- {
- input: '&&',
- withEmptyKeys: {},
- stringifyOutput: {
- brackets: '',
- indices: '',
- repeat: ''
- },
- noEmptyKeys: {}
- },
- {
- input: '&=',
- withEmptyKeys: { '': '' },
- stringifyOutput: {
- brackets: '=',
- indices: '=',
- repeat: '='
- },
- noEmptyKeys: {}
- },
- {
- input: '&=&',
- withEmptyKeys: { '': '' },
- stringifyOutput: {
- brackets: '=',
- indices: '=',
- repeat: '='
- },
- noEmptyKeys: {}
- },
- {
- input: '&=&=',
- withEmptyKeys: { '': ['', ''] },
- stringifyOutput: {
- brackets: '[]=&[]=',
- indices: '[0]=&[1]=',
- repeat: '=&='
- },
- noEmptyKeys: {}
- },
- {
- input: '&=&=&',
- withEmptyKeys: { '': ['', ''] },
- stringifyOutput: {
- brackets: '[]=&[]=',
- indices: '[0]=&[1]=',
- repeat: '=&='
- },
- noEmptyKeys: {}
- },
- {
- input: '=',
- withEmptyKeys: { '': '' },
- noEmptyKeys: {},
- stringifyOutput: {
- brackets: '=',
- indices: '=',
- repeat: '='
- }
- },
- {
- input: '=&',
- withEmptyKeys: { '': '' },
- stringifyOutput: {
- brackets: '=',
- indices: '=',
- repeat: '='
- },
- noEmptyKeys: {}
- },
- {
- input: '=&&&',
- withEmptyKeys: { '': '' },
- stringifyOutput: {
- brackets: '=',
- indices: '=',
- repeat: '='
- },
- noEmptyKeys: {}
- },
- {
- input: '=&=&=&',
- withEmptyKeys: { '': ['', '', ''] },
- stringifyOutput: {
- brackets: '[]=&[]=&[]=',
- indices: '[0]=&[1]=&[2]=',
- repeat: '=&=&='
- },
- noEmptyKeys: {}
- },
- {
- input: '=&a[]=b&a[1]=c',
- withEmptyKeys: { '': '', a: ['b', 'c'] },
- stringifyOutput: {
- brackets: '=&a[]=b&a[]=c',
- indices: '=&a[0]=b&a[1]=c',
- repeat: '=&a=b&a=c'
- },
- noEmptyKeys: { a: ['b', 'c'] }
- },
- {
- input: '=a',
- withEmptyKeys: { '': 'a' },
- noEmptyKeys: {},
- stringifyOutput: {
- brackets: '=a',
- indices: '=a',
- repeat: '=a'
- }
- },
- {
- input: 'a==a',
- withEmptyKeys: { a: '=a' },
- noEmptyKeys: { a: '=a' },
- stringifyOutput: {
- brackets: 'a==a',
- indices: 'a==a',
- repeat: 'a==a'
- }
- },
- {
- input: '=&a[]=b',
- withEmptyKeys: { '': '', a: ['b'] },
- stringifyOutput: {
- brackets: '=&a[]=b',
- indices: '=&a[0]=b',
- repeat: '=&a=b'
- },
- noEmptyKeys: { a: ['b'] }
- },
- {
- input: '=&a[]=b&a[]=c&a[2]=d',
- withEmptyKeys: { '': '', a: ['b', 'c', 'd'] },
- stringifyOutput: {
- brackets: '=&a[]=b&a[]=c&a[]=d',
- indices: '=&a[0]=b&a[1]=c&a[2]=d',
- repeat: '=&a=b&a=c&a=d'
- },
- noEmptyKeys: { a: ['b', 'c', 'd'] }
- },
- {
- input: '=a&=b',
- withEmptyKeys: { '': ['a', 'b'] },
- stringifyOutput: {
- brackets: '[]=a&[]=b',
- indices: '[0]=a&[1]=b',
- repeat: '=a&=b'
- },
- noEmptyKeys: {}
- },
- {
- input: '=a&foo=b',
- withEmptyKeys: { '': 'a', foo: 'b' },
- noEmptyKeys: { foo: 'b' },
- stringifyOutput: {
- brackets: '=a&foo=b',
- indices: '=a&foo=b',
- repeat: '=a&foo=b'
- }
- },
- {
- input: 'a[]=b&a=c&=',
- withEmptyKeys: { '': '', a: ['b', 'c'] },
- stringifyOutput: {
- brackets: '=&a[]=b&a[]=c',
- indices: '=&a[0]=b&a[1]=c',
- repeat: '=&a=b&a=c'
- },
- noEmptyKeys: { a: ['b', 'c'] }
- },
- {
- input: 'a[]=b&a=c&=',
- withEmptyKeys: { '': '', a: ['b', 'c'] },
- stringifyOutput: {
- brackets: '=&a[]=b&a[]=c',
- indices: '=&a[0]=b&a[1]=c',
- repeat: '=&a=b&a=c'
- },
- noEmptyKeys: { a: ['b', 'c'] }
- },
- {
- input: 'a[0]=b&a=c&=',
- withEmptyKeys: { '': '', a: ['b', 'c'] },
- stringifyOutput: {
- brackets: '=&a[]=b&a[]=c',
- indices: '=&a[0]=b&a[1]=c',
- repeat: '=&a=b&a=c'
- },
- noEmptyKeys: { a: ['b', 'c'] }
- },
- {
- input: 'a=b&a[]=c&=',
- withEmptyKeys: { '': '', a: ['b', 'c'] },
- stringifyOutput: {
- brackets: '=&a[]=b&a[]=c',
- indices: '=&a[0]=b&a[1]=c',
- repeat: '=&a=b&a=c'
- },
- noEmptyKeys: { a: ['b', 'c'] }
- },
- {
- input: 'a=b&a[0]=c&=',
- withEmptyKeys: { '': '', a: ['b', 'c'] },
- stringifyOutput: {
- brackets: '=&a[]=b&a[]=c',
- indices: '=&a[0]=b&a[1]=c',
- repeat: '=&a=b&a=c'
- },
- noEmptyKeys: { a: ['b', 'c'] }
- },
- {
- input: '[]=a&[]=b& []=1',
- withEmptyKeys: { '': ['a', 'b'], ' ': ['1'] },
- stringifyOutput: {
- brackets: '[]=a&[]=b& []=1',
- indices: '[0]=a&[1]=b& [0]=1',
- repeat: '=a&=b& =1'
- },
- noEmptyKeys: { 0: 'a', 1: 'b', ' ': ['1'] }
- },
- {
- input: '[0]=a&[1]=b&a[0]=1&a[1]=2',
- withEmptyKeys: { '': ['a', 'b'], a: ['1', '2'] },
- noEmptyKeys: { 0: 'a', 1: 'b', a: ['1', '2'] },
- stringifyOutput: {
- brackets: '[]=a&[]=b&a[]=1&a[]=2',
- indices: '[0]=a&[1]=b&a[0]=1&a[1]=2',
- repeat: '=a&=b&a=1&a=2'
- }
- },
- {
- input: '[deep]=a&[deep]=2',
- withEmptyKeys: { '': { deep: ['a', '2'] }
- },
- stringifyOutput: {
- brackets: '[deep][]=a&[deep][]=2',
- indices: '[deep][0]=a&[deep][1]=2',
- repeat: '[deep]=a&[deep]=2'
- },
- noEmptyKeys: { deep: ['a', '2'] }
- },
- {
- input: '%5B0%5D=a&%5B1%5D=b',
- withEmptyKeys: { '': ['a', 'b'] },
- stringifyOutput: {
- brackets: '[]=a&[]=b',
- indices: '[0]=a&[1]=b',
- repeat: '=a&=b'
- },
- noEmptyKeys: { 0: 'a', 1: 'b' }
- }
- ]
-};
diff --git a/node_modules/qs/test/parse.js b/node_modules/qs/test/parse.js
deleted file mode 100644
index 17f30b6..0000000
--- a/node_modules/qs/test/parse.js
+++ /dev/null
@@ -1,1933 +0,0 @@
-'use strict';
-
-var test = require('tape');
-var hasPropertyDescriptors = require('has-property-descriptors')();
-var iconv = require('iconv-lite');
-var mockProperty = require('mock-property');
-var hasOverrideMistake = require('has-override-mistake')();
-var SaferBuffer = require('safer-buffer').Buffer;
-var v = require('es-value-fixtures');
-var inspect = require('object-inspect');
-var emptyTestCases = require('./empty-keys-cases').emptyTestCases;
-var hasProto = require('has-proto')();
-
-var qs = require('../');
-var utils = require('../lib/utils');
-
-var characterizeParse = function characterizeParse(st, input, opts, expected, label) {
- var result;
- st.doesNotThrow(function () { result = qs.parse(input, opts); }, label + ': does not throw');
- st.deepEqual(result, expected, label + ': parses to the current lenient output');
-};
-
-test('parse()', function (t) {
- t.test('parses a simple string', function (st) {
- st.deepEqual(qs.parse('0=foo'), { 0: 'foo' });
- st.deepEqual(qs.parse('foo=c++'), { foo: 'c ' });
- st.deepEqual(qs.parse('a[>=]=23'), { a: { '>=': '23' } });
- st.deepEqual(qs.parse('a[<=>]==23'), { a: { '<=>': '=23' } });
- st.deepEqual(qs.parse('a[==]=23'), { a: { '==': '23' } });
- st.deepEqual(qs.parse('foo', { strictNullHandling: true }), { foo: null });
- st.deepEqual(qs.parse('foo'), { foo: '' });
- st.deepEqual(qs.parse('foo='), { foo: '' });
- st.deepEqual(qs.parse('foo=bar'), { foo: 'bar' });
- st.deepEqual(qs.parse(' foo = bar = baz '), { ' foo ': ' bar = baz ' });
- st.deepEqual(qs.parse('foo=bar=baz'), { foo: 'bar=baz' });
- st.deepEqual(qs.parse('foo=bar&bar=baz'), { foo: 'bar', bar: 'baz' });
- st.deepEqual(qs.parse('foo2=bar2&baz2='), { foo2: 'bar2', baz2: '' });
- st.deepEqual(qs.parse('foo=bar&baz', { strictNullHandling: true }), { foo: 'bar', baz: null });
- st.deepEqual(qs.parse('foo=bar&baz'), { foo: 'bar', baz: '' });
- st.deepEqual(qs.parse('cht=p3&chd=t:60,40&chs=250x100&chl=Hello|World'), {
- cht: 'p3',
- chd: 't:60,40',
- chs: '250x100',
- chl: 'Hello|World'
- });
- st.end();
- });
-
- t.test('comma: false', function (st) {
- st.deepEqual(qs.parse('a[]=b&a[]=c'), { a: ['b', 'c'] });
- st.deepEqual(qs.parse('a[0]=b&a[1]=c'), { a: ['b', 'c'] });
- st.deepEqual(qs.parse('a=b,c'), { a: 'b,c' });
- st.deepEqual(qs.parse('a=b&a=c'), { a: ['b', 'c'] });
- st.end();
- });
-
- t.test('comma: true', function (st) {
- st.deepEqual(qs.parse('a[]=b&a[]=c', { comma: true }), { a: ['b', 'c'] });
- st.deepEqual(qs.parse('a[0]=b&a[1]=c', { comma: true }), { a: ['b', 'c'] });
- st.deepEqual(qs.parse('a=b,c', { comma: true }), { a: ['b', 'c'] });
- st.deepEqual(qs.parse('a=b&a=c', { comma: true }), { a: ['b', 'c'] });
- st.end();
- });
-
- t.test('allows enabling dot notation', function (st) {
- st.deepEqual(qs.parse('a.b=c'), { 'a.b': 'c' });
- st.deepEqual(qs.parse('a.b=c', { allowDots: true }), { a: { b: 'c' } });
-
- st.end();
- });
-
- t.test('decode dot keys correctly', function (st) {
- st.deepEqual(
- qs.parse('name%252Eobj.first=John&name%252Eobj.last=Doe', { allowDots: false, decodeDotInKeys: false }),
- { 'name%2Eobj.first': 'John', 'name%2Eobj.last': 'Doe' },
- 'with allowDots false and decodeDotInKeys false'
- );
- st.deepEqual(
- qs.parse('name.obj.first=John&name.obj.last=Doe', { allowDots: true, decodeDotInKeys: false }),
- { name: { obj: { first: 'John', last: 'Doe' } } },
- 'with allowDots false and decodeDotInKeys false'
- );
- st.deepEqual(
- qs.parse('name%252Eobj.first=John&name%252Eobj.last=Doe', { allowDots: true, decodeDotInKeys: false }),
- { 'name%2Eobj': { first: 'John', last: 'Doe' } },
- 'with allowDots true and decodeDotInKeys false'
- );
- st.deepEqual(
- qs.parse('name%252Eobj.first=John&name%252Eobj.last=Doe', { allowDots: true, decodeDotInKeys: true }),
- { 'name.obj': { first: 'John', last: 'Doe' } },
- 'with allowDots true and decodeDotInKeys true'
- );
-
- st.deepEqual(
- qs.parse(
- 'name%252Eobj%252Esubobject.first%252Egodly%252Ename=John&name%252Eobj%252Esubobject.last=Doe',
- { allowDots: false, decodeDotInKeys: false }
- ),
- { 'name%2Eobj%2Esubobject.first%2Egodly%2Ename': 'John', 'name%2Eobj%2Esubobject.last': 'Doe' },
- 'with allowDots false and decodeDotInKeys false'
- );
- st.deepEqual(
- qs.parse(
- 'name.obj.subobject.first.godly.name=John&name.obj.subobject.last=Doe',
- { allowDots: true, decodeDotInKeys: false }
- ),
- { name: { obj: { subobject: { first: { godly: { name: 'John' } }, last: 'Doe' } } } },
- 'with allowDots true and decodeDotInKeys false'
- );
- st.deepEqual(
- qs.parse(
- 'name%252Eobj%252Esubobject.first%252Egodly%252Ename=John&name%252Eobj%252Esubobject.last=Doe',
- { allowDots: true, decodeDotInKeys: true }
- ),
- { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } },
- 'with allowDots true and decodeDotInKeys true'
- );
- st.deepEqual(
- qs.parse('name%252Eobj.first=John&name%252Eobj.last=Doe'),
- { 'name%2Eobj.first': 'John', 'name%2Eobj.last': 'Doe' },
- 'with allowDots and decodeDotInKeys undefined'
- );
-
- st.end();
- });
-
- t.test('decodes dot in key of object, and allow enabling dot notation when decodeDotInKeys is set to true and allowDots is undefined', function (st) {
- st.deepEqual(
- qs.parse(
- 'name%252Eobj%252Esubobject.first%252Egodly%252Ename=John&name%252Eobj%252Esubobject.last=Doe',
- { decodeDotInKeys: true }
- ),
- { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } },
- 'with allowDots undefined and decodeDotInKeys true'
- );
-
- st.end();
- });
-
- t.test('throws when decodeDotInKeys is not of type boolean', function (st) {
- st['throws'](
- function () { qs.parse('foo[]&bar=baz', { decodeDotInKeys: 'foobar' }); },
- TypeError
- );
-
- st['throws'](
- function () { qs.parse('foo[]&bar=baz', { decodeDotInKeys: 0 }); },
- TypeError
- );
- st['throws'](
- function () { qs.parse('foo[]&bar=baz', { decodeDotInKeys: NaN }); },
- TypeError
- );
-
- st['throws'](
- function () { qs.parse('foo[]&bar=baz', { decodeDotInKeys: null }); },
- TypeError
- );
-
- st.end();
- });
-
- t.test('allows empty arrays in obj values', function (st) {
- st.deepEqual(qs.parse('foo[]&bar=baz', { allowEmptyArrays: true }), { foo: [], bar: 'baz' });
- st.deepEqual(qs.parse('foo[]&bar=baz', { allowEmptyArrays: false }), { foo: [''], bar: 'baz' });
-
- st.end();
- });
-
- t.test('throws when allowEmptyArrays is not of type boolean', function (st) {
- st['throws'](
- function () { qs.parse('foo[]&bar=baz', { allowEmptyArrays: 'foobar' }); },
- TypeError
- );
-
- st['throws'](
- function () { qs.parse('foo[]&bar=baz', { allowEmptyArrays: 0 }); },
- TypeError
- );
- st['throws'](
- function () { qs.parse('foo[]&bar=baz', { allowEmptyArrays: NaN }); },
- TypeError
- );
-
- st['throws'](
- function () { qs.parse('foo[]&bar=baz', { allowEmptyArrays: null }); },
- TypeError
- );
-
- st.end();
- });
-
- t.test('allowEmptyArrays + strictNullHandling', function (st) {
- st.deepEqual(
- qs.parse('testEmptyArray[]', { strictNullHandling: true, allowEmptyArrays: true }),
- { testEmptyArray: [] }
- );
-
- st.end();
- });
-
- t.deepEqual(qs.parse('a[b]=c'), { a: { b: 'c' } }, 'parses a single nested string');
- t.deepEqual(qs.parse('a[b][c]=d'), { a: { b: { c: 'd' } } }, 'parses a double nested string');
- t.deepEqual(
- qs.parse('a[b][c][d][e][f][g][h]=i'),
- { a: { b: { c: { d: { e: { f: { '[g][h]': 'i' } } } } } } },
- 'defaults to a depth of 5'
- );
-
- t.test('only parses one level when depth = 1', function (st) {
- st.deepEqual(qs.parse('a[b][c]=d', { depth: 1 }), { a: { b: { '[c]': 'd' } } });
- st.deepEqual(qs.parse('a[b][c][d]=e', { depth: 1 }), { a: { b: { '[c][d]': 'e' } } });
- st.end();
- });
-
- t.test('uses original key when depth = 0', function (st) {
- st.deepEqual(qs.parse('a[0]=b&a[1]=c', { depth: 0 }), { 'a[0]': 'b', 'a[1]': 'c' });
- st.deepEqual(qs.parse('a[0][0]=b&a[0][1]=c&a[1]=d&e=2', { depth: 0 }), { 'a[0][0]': 'b', 'a[0][1]': 'c', 'a[1]': 'd', e: '2' });
- st.deepEqual(qs.parse('a.b=c', { depth: 0, allowDots: true }), { 'a[b]': 'c' }, 'normalizes dots before applying depth-0 behavior');
- st.deepEqual(qs.parse('toString=foo', { depth: 0 }), {}, 'respects prototype guard at depth 0');
- st.deepEqual(qs.parse('toString=foo', { depth: 0, allowPrototypes: true }), { toString: 'foo' }, 'allows prototypes at depth 0 when enabled');
- st.end();
- });
-
- t.test('ignores prototype keys when depth = 0 and allowPrototypes is false', function (st) {
- st.deepEqual(qs.parse('toString=foo', { depth: 0 }), {});
- st.deepEqual(qs.parse('hasOwnProperty=bar', { depth: 0 }), {});
- st.deepEqual(qs.parse('toString=foo&a=b', { depth: 0 }), { a: 'b' });
- st.end();
- });
-
- t.test('allows prototype keys when depth = 0 and allowPrototypes is true', function (st) {
- st.deepEqual(qs.parse('toString=foo', { depth: 0, allowPrototypes: true }), { toString: 'foo' });
- st.end();
- });
-
- t.test('uses original key when depth = false', function (st) {
- st.deepEqual(qs.parse('a[0]=b&a[1]=c', { depth: false }), { 'a[0]': 'b', 'a[1]': 'c' });
- st.deepEqual(qs.parse('a[0][0]=b&a[0][1]=c&a[1]=d&e=2', { depth: false }), { 'a[0][0]': 'b', 'a[0][1]': 'c', 'a[1]': 'd', e: '2' });
- st.end();
- });
-
- t.deepEqual(qs.parse('a=b&a=c'), { a: ['b', 'c'] }, 'parses a simple array');
-
- t.test('parses an explicit array', function (st) {
- st.deepEqual(qs.parse('a[]=b'), { a: ['b'] });
- st.deepEqual(qs.parse('a[]=b&a[]=c'), { a: ['b', 'c'] });
- st.deepEqual(qs.parse('a[]=b&a[]=c&a[]=d'), { a: ['b', 'c', 'd'] });
- st.end();
- });
-
- t.test('parses a mix of simple and explicit arrays', function (st) {
- st.deepEqual(qs.parse('a=b&a[]=c'), { a: ['b', 'c'] });
- st.deepEqual(qs.parse('a[]=b&a=c'), { a: ['b', 'c'] });
- st.deepEqual(qs.parse('a[0]=b&a=c'), { a: ['b', 'c'] });
- st.deepEqual(qs.parse('a=b&a[0]=c'), { a: ['b', 'c'] });
-
- st.deepEqual(qs.parse('a[1]=b&a=c', { arrayLimit: 20 }), { a: ['b', 'c'] });
- st.deepEqual(qs.parse('a[]=b&a=c', { arrayLimit: 0 }), { a: { 0: 'b', 1: 'c' } });
- st.deepEqual(qs.parse('a[]=b&a=c'), { a: ['b', 'c'] });
-
- st.deepEqual(qs.parse('a=b&a[1]=c', { arrayLimit: 20 }), { a: ['b', 'c'] });
- st.deepEqual(qs.parse('a=b&a[]=c', { arrayLimit: 0 }), { a: { 0: 'b', 1: 'c' } });
- st.deepEqual(qs.parse('a=b&a[]=c'), { a: ['b', 'c'] });
-
- st.end();
- });
-
- t.test('parses a nested array', function (st) {
- st.deepEqual(qs.parse('a[b][]=c&a[b][]=d'), { a: { b: ['c', 'd'] } });
- st.deepEqual(qs.parse('a[>=]=25'), { a: { '>=': '25' } });
- st.end();
- });
-
- t.test('parses keys with literal [] inside a bracket group (#493)', function (st) {
- // A bracket pair inside a bracket group should be treated literally as part of the key
- st.deepEqual(
- qs.parse('search[withbracket[]]=foobar'),
- { search: { 'withbracket[]': 'foobar' } },
- 'treats inner [] literally when inside a bracket group'
- );
-
- // Single-level variant
- st.deepEqual(
- qs.parse('a[b[]]=c'),
- { a: { 'b[]': 'c' } },
- 'keeps "b[]" as a literal key'
- );
-
- // Nested with an array push on the outer level
- st.deepEqual(
- qs.parse('list[][x[]]=y'),
- { list: [{ 'x[]': 'y' }] },
- 'preserves inner [] while still treating outer [] as array push'
- );
-
- // Multiple nested bracket pairs: inner [] remains literal as part of the key
- st.deepEqual(
- qs.parse('a[b[c[]]]=d'),
- { a: { 'b[c[]]': 'd' } },
- 'treats "b[c[]]" as a literal key inside the bracket group'
- );
-
- // Depth limits with literal brackets: preserve inner [] while limiting bracket-group parsing
- st.deepEqual(
- qs.parse('a[b[c[]]][d]=e', { depth: 1 }),
- { a: { 'b[c[]]': { '[d]': 'e' } } },
- 'respects depth: 1 and preserves literal inner [] in the parsed key'
- );
-
- // Unterminated inner bracket group is wrapped as a literal remainder segment
- st.deepEqual(
- qs.parse('a[[]b=c'),
- { a: { '[[]b': 'c' } },
- 'handles unterminated inner bracket groups without throwing'
- );
-
- st.end();
- });
-
- t.test('currently parses unbalanced bracket keys after a parent leniently to literal segments (issue #558)', function (st) {
- characterizeParse(st, 'a[bc=v', undefined, { a: { '[bc': 'v' } }, 'unclosed group after a parent');
- characterizeParse(st, 'a[=v', undefined, { a: { '[': 'v' } }, 'bare unclosed bracket after a parent');
- characterizeParse(st, 'a[b][c=v', undefined, { a: { b: { '[c': 'v' } } }, 'unclosed group after a valid one');
- characterizeParse(st, 'a[b]c[d=v', undefined, { a: { b: { '[d': 'v' } } }, 'unclosed group after text following a valid one');
- characterizeParse(st, 'filters[customtags:Env: Prod=v', undefined, { filters: { '[customtags:Env: Prod': 'v' } }, 'the issue #558 reproduction');
- characterizeParse(st, '][a=v', undefined, { ']': { '[a': 'v' } }, 'stray close bracket before an unclosed group');
- characterizeParse(st, 'a][b=v', undefined, { 'a]': { '[b': 'v' } }, 'stray close bracket inside the parent');
- st.end();
- });
-
- t.test('currently parses unbalanced bracket keys containing inner brackets leniently (issue #558)', function (st) {
- characterizeParse(st, 'a[b[c=v', undefined, { a: { '[b[c': 'v' } }, 'unclosed group containing an inner bracket');
- characterizeParse(st, 'a[b[c]=v', undefined, { a: { '[b[c]': 'v' } }, 'unbalanced group with an inner bracket and one close');
- characterizeParse(st, 'a[b][c[d=v', undefined, { a: { b: { '[c[d': 'v' } } }, 'unclosed inner-bracket group after a valid one');
- st.end();
- });
-
- t.test('currently parses bracket-prefixed unbalanced keys leniently (issue #558)', function (st) {
- characterizeParse(st, '[abc=v', undefined, { '[abc': 'v' }, 'key starting with an unclosed bracket');
- characterizeParse(st, '[[]b=v', undefined, { '[[]b': 'v' }, 'key starting with an unbalanced bracket group');
- st.end();
- });
-
- t.test('lenient unbalanced-bracket handling currently depends on the depth option (issue #558)', function (st) {
- characterizeParse(st, 'a[b]c[d]e[f=v', { depth: 5 }, { a: { b: { d: { '[f': 'v' } } } }, 'consumes groups up to the depth budget then keeps the unclosed remainder literal');
- characterizeParse(st, 'a[b]c[d]e[f=v', { depth: 1 }, { a: { b: { '[d]e[f': 'v' } } }, 'a lower depth keeps more of the unclosed remainder literal');
- characterizeParse(st, 'a[bc=v', { depth: 0 }, { 'a[bc': 'v' }, 'depth 0 keeps the entire key literal');
- st.end();
- });
-
- t.test('currently parses an allowDots key with a trailing unclosed bracket leniently (issue #558)', function (st) {
- characterizeParse(st, 'a.b[c=v', { allowDots: true }, { a: { b: { '[c': 'v' } } }, 'allowDots expands the dot then keeps the unclosed bracket literal');
- st.end();
- });
-
- t.test('valid and stray-close bracket keys are unaffected by unbalanced-bracket handling', function (st) {
- characterizeParse(st, 'a]b=v', undefined, { 'a]b': 'v' }, 'stray close bracket with no open bracket stays a flat key');
- characterizeParse(st, 'a[b]extra=v', undefined, { a: { b: 'v' } }, 'text after a balanced group is ignored');
- st.end();
- });
-
- t.test('allows to specify array indices', function (st) {
- st.deepEqual(qs.parse('a[1]=c&a[0]=b&a[2]=d'), { a: ['b', 'c', 'd'] });
- st.deepEqual(qs.parse('a[1]=c&a[0]=b'), { a: ['b', 'c'] });
- st.deepEqual(qs.parse('a[1]=c', { arrayLimit: 20 }), { a: ['c'] });
- st.deepEqual(qs.parse('a[1]=c', { arrayLimit: 0 }), { a: { 1: 'c' } });
- st.deepEqual(qs.parse('a[1]=c'), { a: ['c'] });
- st.end();
- });
-
- t.test('limits specific array indices to arrayLimit', function (st) {
- st.deepEqual(qs.parse('a[19]=a', { arrayLimit: 20 }), { a: ['a'] });
- st.deepEqual(qs.parse('a[20]=a', { arrayLimit: 20 }), { a: { 20: 'a' } });
-
- st.deepEqual(qs.parse('a[19]=a'), { a: ['a'] });
- st.deepEqual(qs.parse('a[20]=a'), { a: { 20: 'a' } });
- st.end();
- });
-
- t.deepEqual(qs.parse('a[12b]=c'), { a: { '12b': 'c' } }, 'supports keys that begin with a number');
-
- t.test('supports encoded = signs', function (st) {
- st.deepEqual(qs.parse('he%3Dllo=th%3Dere'), { 'he=llo': 'th=ere' });
- st.end();
- });
-
- t.test('is ok with url encoded strings', function (st) {
- st.deepEqual(qs.parse('a[b%20c]=d'), { a: { 'b c': 'd' } });
- st.deepEqual(qs.parse('a[b]=c%20d'), { a: { b: 'c d' } });
- st.end();
- });
-
- t.test('allows brackets in the value', function (st) {
- st.deepEqual(qs.parse('pets=["tobi"]'), { pets: '["tobi"]' });
- st.deepEqual(qs.parse('operators=[">=", "<="]'), { operators: '[">=", "<="]' });
- st.end();
- });
-
- t.test('allows empty values', function (st) {
- st.deepEqual(qs.parse(''), {});
- st.deepEqual(qs.parse(null), {});
- st.deepEqual(qs.parse(undefined), {});
- st.end();
- });
-
- t.test('transforms arrays to objects', function (st) {
- st.deepEqual(qs.parse('foo[0]=bar&foo[bad]=baz'), { foo: { 0: 'bar', bad: 'baz' } });
- st.deepEqual(qs.parse('foo[bad]=baz&foo[0]=bar'), { foo: { bad: 'baz', 0: 'bar' } });
- st.deepEqual(qs.parse('foo[bad]=baz&foo[]=bar'), { foo: { bad: 'baz', 0: 'bar' } });
- st.deepEqual(qs.parse('foo[]=bar&foo[bad]=baz'), { foo: { 0: 'bar', bad: 'baz' } });
- st.deepEqual(qs.parse('foo[bad]=baz&foo[]=bar&foo[]=foo'), { foo: { bad: 'baz', 0: 'bar', 1: 'foo' } });
- st.deepEqual(qs.parse('foo[0][a]=a&foo[0][b]=b&foo[1][a]=aa&foo[1][b]=bb'), { foo: [{ a: 'a', b: 'b' }, { a: 'aa', b: 'bb' }] });
-
- st.deepEqual(qs.parse('a[]=b&a[t]=u&a[hasOwnProperty]=c', { allowPrototypes: false }), { a: { 0: 'b', t: 'u' } });
- st.deepEqual(qs.parse('a[]=b&a[t]=u&a[hasOwnProperty]=c', { allowPrototypes: true }), { a: { 0: 'b', t: 'u', hasOwnProperty: 'c' } });
- st.deepEqual(qs.parse('a[]=b&a[hasOwnProperty]=c&a[x]=y', { allowPrototypes: false }), { a: { 0: 'b', x: 'y' } });
- st.deepEqual(qs.parse('a[]=b&a[hasOwnProperty]=c&a[x]=y', { allowPrototypes: true }), { a: { 0: 'b', hasOwnProperty: 'c', x: 'y' } });
- st.end();
- });
-
- t.test('transforms arrays to objects (dot notation)', function (st) {
- st.deepEqual(qs.parse('foo[0].baz=bar&fool.bad=baz', { allowDots: true }), { foo: [{ baz: 'bar' }], fool: { bad: 'baz' } });
- st.deepEqual(qs.parse('foo[0].baz=bar&fool.bad.boo=baz', { allowDots: true }), { foo: [{ baz: 'bar' }], fool: { bad: { boo: 'baz' } } });
- st.deepEqual(qs.parse('foo[0][0].baz=bar&fool.bad=baz', { allowDots: true }), { foo: [[{ baz: 'bar' }]], fool: { bad: 'baz' } });
- st.deepEqual(qs.parse('foo[0].baz[0]=15&foo[0].bar=2', { allowDots: true }), { foo: [{ baz: ['15'], bar: '2' }] });
- st.deepEqual(qs.parse('foo[0].baz[0]=15&foo[0].baz[1]=16&foo[0].bar=2', { allowDots: true }), { foo: [{ baz: ['15', '16'], bar: '2' }] });
- st.deepEqual(qs.parse('foo.bad=baz&foo[0]=bar', { allowDots: true }), { foo: { bad: 'baz', 0: 'bar' } });
- st.deepEqual(qs.parse('foo.bad=baz&foo[]=bar', { allowDots: true }), { foo: { bad: 'baz', 0: 'bar' } });
- st.deepEqual(qs.parse('foo[]=bar&foo.bad=baz', { allowDots: true }), { foo: { 0: 'bar', bad: 'baz' } });
- st.deepEqual(qs.parse('foo.bad=baz&foo[]=bar&foo[]=foo', { allowDots: true }), { foo: { bad: 'baz', 0: 'bar', 1: 'foo' } });
- st.deepEqual(qs.parse('foo[0].a=a&foo[0].b=b&foo[1].a=aa&foo[1].b=bb', { allowDots: true }), { foo: [{ a: 'a', b: 'b' }, { a: 'aa', b: 'bb' }] });
- st.end();
- });
-
- t.test('correctly prunes undefined values when converting an array to an object', function (st) {
- st.deepEqual(qs.parse('a[2]=b&a[99999999]=c'), { a: { 2: 'b', 99999999: 'c' } });
- st.end();
- });
-
- t.test('supports malformed uri characters', function (st) {
- st.deepEqual(qs.parse('{%:%}', { strictNullHandling: true }), { '{%:%}': null });
- st.deepEqual(qs.parse('{%:%}='), { '{%:%}': '' });
- st.deepEqual(qs.parse('foo=%:%}'), { foo: '%:%}' });
- st.end();
- });
-
- t.test('doesn\'t produce empty keys', function (st) {
- st.deepEqual(qs.parse('_r=1&'), { _r: '1' });
- st.end();
- });
-
- t.test('cannot access Object prototype', function (st) {
- qs.parse('constructor[prototype][bad]=bad');
- qs.parse('bad[constructor][prototype][bad]=bad');
- st.equal(typeof Object.prototype.bad, 'undefined');
- st.end();
- });
-
- t.test('parses arrays of objects', function (st) {
- st.deepEqual(qs.parse('a[][b]=c'), { a: [{ b: 'c' }] });
- st.deepEqual(qs.parse('a[0][b]=c'), { a: [{ b: 'c' }] });
- st.end();
- });
-
- t.test('allows for empty strings in arrays', function (st) {
- st.deepEqual(qs.parse('a[]=b&a[]=&a[]=c'), { a: ['b', '', 'c'] });
-
- st.deepEqual(
- qs.parse('a[0]=b&a[1]&a[2]=c&a[19]=', { strictNullHandling: true, arrayLimit: 20 }),
- { a: ['b', null, 'c', ''] },
- 'with arrayLimit 20 + array indices: null then empty string works'
- );
- st.deepEqual(
- qs.parse('a[]=b&a[]&a[]=c&a[]=', { strictNullHandling: true, arrayLimit: 0 }),
- { a: { 0: 'b', 1: null, 2: 'c', 3: '' } },
- 'with arrayLimit 0 + array brackets: null then empty string works'
- );
-
- st.deepEqual(
- qs.parse('a[0]=b&a[1]=&a[2]=c&a[19]', { strictNullHandling: true, arrayLimit: 20 }),
- { a: ['b', '', 'c', null] },
- 'with arrayLimit 20 + array indices: empty string then null works'
- );
- st.deepEqual(
- qs.parse('a[]=b&a[]=&a[]=c&a[]', { strictNullHandling: true, arrayLimit: 0 }),
- { a: { 0: 'b', 1: '', 2: 'c', 3: null } },
- 'with arrayLimit 0 + array brackets: empty string then null works'
- );
-
- st.deepEqual(
- qs.parse('a[]=&a[]=b&a[]=c'),
- { a: ['', 'b', 'c'] },
- 'array brackets: empty strings work'
- );
- st.end();
- });
-
- t.test('compacts sparse arrays', function (st) {
- st.deepEqual(qs.parse('a[10]=1&a[2]=2', { arrayLimit: 20 }), { a: ['2', '1'] });
- st.deepEqual(qs.parse('a[1][b][2][c]=1', { arrayLimit: 20 }), { a: [{ b: [{ c: '1' }] }] });
- st.deepEqual(qs.parse('a[1][2][3][c]=1', { arrayLimit: 20 }), { a: [[[{ c: '1' }]]] });
- st.deepEqual(qs.parse('a[1][2][3][c][1]=1', { arrayLimit: 20 }), { a: [[[{ c: ['1'] }]]] });
- st.end();
- });
-
- t.test('parses sparse arrays', function (st) {
- /* eslint no-sparse-arrays: 0 */
- st.deepEqual(qs.parse('a[4]=1&a[1]=2', { allowSparse: true }), { a: [, '2', , , '1'] });
- st.deepEqual(qs.parse('a[1][b][2][c]=1', { allowSparse: true }), { a: [, { b: [, , { c: '1' }] }] });
- st.deepEqual(qs.parse('a[1][2][3][c]=1', { allowSparse: true }), { a: [, [, , [, , , { c: '1' }]]] });
- st.deepEqual(qs.parse('a[1][2][3][c][1]=1', { allowSparse: true }), { a: [, [, , [, , , { c: [, '1'] }]]] });
- st.end();
- });
-
- t.test('parses semi-parsed strings', function (st) {
- st.deepEqual(qs.parse({ 'a[b]': 'c' }), { a: { b: 'c' } });
- st.deepEqual(qs.parse({ 'a[b]': 'c', 'a[d]': 'e' }), { a: { b: 'c', d: 'e' } });
- st.end();
- });
-
- t.test('parses buffers correctly', function (st) {
- var b = SaferBuffer.from('test');
- st.deepEqual(qs.parse({ a: b }), { a: b });
- st.end();
- });
-
- t.test('parses jquery-param strings', function (st) {
- // readable = 'filter[0][]=int1&filter[0][]==&filter[0][]=77&filter[]=and&filter[2][]=int2&filter[2][]==&filter[2][]=8'
- var encoded = 'filter%5B0%5D%5B%5D=int1&filter%5B0%5D%5B%5D=%3D&filter%5B0%5D%5B%5D=77&filter%5B%5D=and&filter%5B2%5D%5B%5D=int2&filter%5B2%5D%5B%5D=%3D&filter%5B2%5D%5B%5D=8';
- var expected = { filter: [['int1', '=', '77'], 'and', ['int2', '=', '8']] };
- st.deepEqual(qs.parse(encoded), expected);
- st.end();
- });
-
- t.test('continues parsing when no parent is found', function (st) {
- st.deepEqual(qs.parse('[]=&a=b'), { 0: '', a: 'b' });
- st.deepEqual(qs.parse('[]&a=b', { strictNullHandling: true }), { 0: null, a: 'b' });
- st.deepEqual(qs.parse('[foo]=bar'), { foo: 'bar' });
- st.end();
- });
-
- t.test('does not error when parsing a very long array', function (st) {
- var str = 'a[]=a';
- while (Buffer.byteLength(str) < 128 * 1024) {
- str = str + '&' + str;
- }
-
- st.doesNotThrow(function () {
- qs.parse(str);
- });
-
- st.end();
- });
-
- t.test('does not throw when a native prototype has an enumerable property', function (st) {
- st.intercept(Object.prototype, 'crash', { value: '' });
- st.intercept(Array.prototype, 'crash', { value: '' });
-
- st.doesNotThrow(qs.parse.bind(null, 'a=b'));
- st.deepEqual(qs.parse('a=b'), { a: 'b' });
- st.doesNotThrow(qs.parse.bind(null, 'a[][b]=c'));
- st.deepEqual(qs.parse('a[][b]=c'), { a: [{ b: 'c' }] });
-
- st.end();
- });
-
- t.test('parses a string with an alternative string delimiter', function (st) {
- st.deepEqual(qs.parse('a=b;c=d', { delimiter: ';' }), { a: 'b', c: 'd' });
- st.end();
- });
-
- t.test('parses a string with an alternative RegExp delimiter', function (st) {
- st.deepEqual(qs.parse('a=b; c=d', { delimiter: /[;,] */ }), { a: 'b', c: 'd' });
- st.end();
- });
-
- t.test('does not use non-splittable objects as delimiters', function (st) {
- st.deepEqual(qs.parse('a=b&c=d', { delimiter: true }), { a: 'b', c: 'd' });
- st.end();
- });
-
- t.test('allows overriding parameter limit', function (st) {
- st.deepEqual(qs.parse('a=b&c=d', { parameterLimit: 1 }), { a: 'b' });
- st.end();
- });
-
- t.test('allows setting the parameter limit to Infinity', function (st) {
- st.deepEqual(qs.parse('a=b&c=d', { parameterLimit: Infinity }), { a: 'b', c: 'd' });
- st.end();
- });
-
- t.test('allows overriding array limit', function (st) {
- st.deepEqual(qs.parse('a[0]=b', { arrayLimit: -1 }), { a: { 0: 'b' } });
- st.deepEqual(qs.parse('a[0]=b', { arrayLimit: 0 }), { a: { 0: 'b' } });
-
- st.deepEqual(qs.parse('a[-1]=b', { arrayLimit: -1 }), { a: { '-1': 'b' } });
- st.deepEqual(qs.parse('a[-1]=b', { arrayLimit: 0 }), { a: { '-1': 'b' } });
-
- st.deepEqual(qs.parse('a[0]=b&a[1]=c', { arrayLimit: -1 }), { a: { 0: 'b', 1: 'c' } });
- st.deepEqual(qs.parse('a[0]=b&a[1]=c', { arrayLimit: 0 }), { a: { 0: 'b', 1: 'c' } });
-
- st.end();
- });
-
- t.test('allows disabling array parsing', function (st) {
- var indices = qs.parse('a[0]=b&a[1]=c', { parseArrays: false });
- st.deepEqual(indices, { a: { 0: 'b', 1: 'c' } });
- st.equal(Array.isArray(indices.a), false, 'parseArrays:false, indices case is not an array');
-
- var emptyBrackets = qs.parse('a[]=b', { parseArrays: false });
- st.deepEqual(emptyBrackets, { a: { 0: 'b' } });
- st.equal(Array.isArray(emptyBrackets.a), false, 'parseArrays:false, empty brackets case is not an array');
-
- st.end();
- });
-
- t.test('allows for query string prefix', function (st) {
- st.deepEqual(qs.parse('?foo=bar', { ignoreQueryPrefix: true }), { foo: 'bar' });
- st.deepEqual(qs.parse('foo=bar', { ignoreQueryPrefix: true }), { foo: 'bar' });
- st.deepEqual(qs.parse('?foo=bar', { ignoreQueryPrefix: false }), { '?foo': 'bar' });
-
- st.end();
- });
-
- t.test('parses an object', function (st) {
- var input = {
- 'user[name]': { 'pop[bob]': 3 },
- 'user[email]': null
- };
-
- var expected = {
- user: {
- name: { 'pop[bob]': 3 },
- email: null
- }
- };
-
- var result = qs.parse(input);
-
- st.deepEqual(result, expected);
- st.end();
- });
-
- t.test('parses string with comma as array divider', function (st) {
- st.deepEqual(qs.parse('foo=bar,tee', { comma: true }), { foo: ['bar', 'tee'] });
- st.deepEqual(qs.parse('foo[bar]=coffee,tee', { comma: true }), { foo: { bar: ['coffee', 'tee'] } });
- st.deepEqual(qs.parse('foo=', { comma: true }), { foo: '' });
- st.deepEqual(qs.parse('foo', { comma: true }), { foo: '' });
- st.deepEqual(qs.parse('foo', { comma: true, strictNullHandling: true }), { foo: null });
-
- // test cases inversed from from stringify tests
- st.deepEqual(qs.parse('a[0]=c'), { a: ['c'] });
- st.deepEqual(qs.parse('a[]=c'), { a: ['c'] });
- st.deepEqual(qs.parse('a[]=c', { comma: true }), { a: ['c'] });
-
- st.deepEqual(qs.parse('a[0]=c&a[1]=d'), { a: ['c', 'd'] });
- st.deepEqual(qs.parse('a[]=c&a[]=d'), { a: ['c', 'd'] });
- st.deepEqual(qs.parse('a=c,d', { comma: true }), { a: ['c', 'd'] });
-
- st.end();
- });
-
- t.test('parses values with comma as array divider', function (st) {
- st.deepEqual(qs.parse({ foo: 'bar,tee' }, { comma: false }), { foo: 'bar,tee' });
- st.deepEqual(qs.parse({ foo: 'bar,tee' }, { comma: true }), { foo: ['bar', 'tee'] });
- st.end();
- });
-
- t.test('use number decoder, parses string that has one number with comma option enabled', function (st) {
- var decoder = function (str, defaultDecoder, charset, type) {
- if (!isNaN(Number(str))) {
- return parseFloat(str);
- }
- return defaultDecoder(str, defaultDecoder, charset, type);
- };
-
- st.deepEqual(qs.parse('foo=1', { comma: true, decoder: decoder }), { foo: 1 });
- st.deepEqual(qs.parse('foo=0', { comma: true, decoder: decoder }), { foo: 0 });
-
- st.end();
- });
-
- t.test('parses brackets holds array of arrays when having two parts of strings with comma as array divider', function (st) {
- st.deepEqual(qs.parse('foo[]=1,2,3&foo[]=4,5,6', { comma: true }), { foo: [['1', '2', '3'], ['4', '5', '6']] });
- st.deepEqual(qs.parse('foo[]=1,2,3&foo[]=', { comma: true }), { foo: [['1', '2', '3'], ''] });
- st.deepEqual(qs.parse('foo[]=1,2,3&foo[]=,', { comma: true }), { foo: [['1', '2', '3'], ['', '']] });
- st.deepEqual(qs.parse('foo[]=1,2,3&foo[]=a', { comma: true }), { foo: [['1', '2', '3'], 'a'] });
-
- st.end();
- });
-
- t.test('parses url-encoded brackets holds array of arrays when having two parts of strings with comma as array divider', function (st) {
- st.deepEqual(qs.parse('foo%5B%5D=1,2,3&foo%5B%5D=4,5,6', { comma: true }), { foo: [['1', '2', '3'], ['4', '5', '6']] });
- st.deepEqual(qs.parse('foo%5B%5D=1,2,3&foo%5B%5D=', { comma: true }), { foo: [['1', '2', '3'], ''] });
- st.deepEqual(qs.parse('foo%5B%5D=1,2,3&foo%5B%5D=,', { comma: true }), { foo: [['1', '2', '3'], ['', '']] });
- st.deepEqual(qs.parse('foo%5B%5D=1,2,3&foo%5B%5D=a', { comma: true }), { foo: [['1', '2', '3'], 'a'] });
-
- st.end();
- });
-
- t.test('parses comma delimited array while having percent-encoded comma treated as normal text', function (st) {
- st.deepEqual(qs.parse('foo=a%2Cb', { comma: true }), { foo: 'a,b' });
- st.deepEqual(qs.parse('foo=a%2C%20b,d', { comma: true }), { foo: ['a, b', 'd'] });
- st.deepEqual(qs.parse('foo=a%2C%20b,c%2C%20d', { comma: true }), { foo: ['a, b', 'c, d'] });
-
- st.end();
- });
-
- t.test('parses an object in dot notation', function (st) {
- var input = {
- 'user.name': { 'pop[bob]': 3 },
- 'user.email.': null
- };
-
- var expected = {
- user: {
- name: { 'pop[bob]': 3 },
- email: null
- }
- };
-
- var result = qs.parse(input, { allowDots: true });
-
- st.deepEqual(result, expected);
- st.end();
- });
-
- t.test('parses an object and not child values', function (st) {
- var input = {
- 'user[name]': { 'pop[bob]': { test: 3 } },
- 'user[email]': null
- };
-
- var expected = {
- user: {
- name: { 'pop[bob]': { test: 3 } },
- email: null
- }
- };
-
- var result = qs.parse(input);
-
- st.deepEqual(result, expected);
- st.end();
- });
-
- t.test('does not blow up when Buffer global is missing', function (st) {
- var restore = mockProperty(global, 'Buffer', { 'delete': true });
-
- var result = qs.parse('a=b&c=d');
-
- restore();
-
- st.deepEqual(result, { a: 'b', c: 'd' });
- st.end();
- });
-
- t.test('does not crash when parsing circular references', function (st) {
- var a = {};
- a.b = a;
-
- var parsed;
-
- st.doesNotThrow(function () {
- parsed = qs.parse({ 'foo[bar]': 'baz', 'foo[baz]': a });
- });
-
- st.equal('foo' in parsed, true, 'parsed has "foo" property');
- st.equal('bar' in parsed.foo, true);
- st.equal('baz' in parsed.foo, true);
- st.equal(parsed.foo.bar, 'baz');
- st.deepEqual(parsed.foo.baz, a);
- st.end();
- });
-
- t.test('does not crash on multi-step circular references', function (st) {
- var a = {};
- a.b = { c: { d: a } };
-
- var parsed;
-
- st.doesNotThrow(function () {
- parsed = qs.parse({ foo: a });
- });
-
- st.equal('foo' in parsed, true, 'parsed has "foo" property');
- st.equal(parsed.foo.b.c.d, parsed.foo, 'the multi-step cycle is preserved');
- st.end();
- });
-
- t.test('does not crash when parsing deep objects', function (st) {
- var parsed;
- var str = 'foo';
-
- for (var i = 0; i < 5000; i++) {
- str += '[p]';
- }
-
- str += '=bar';
-
- st.doesNotThrow(function () {
- parsed = qs.parse(str, { depth: 5000 });
- });
-
- st.equal('foo' in parsed, true, 'parsed has "foo" property');
-
- var depth = 0;
- var ref = parsed.foo;
- while ((ref = ref.p)) {
- depth += 1;
- }
-
- st.equal(depth, 5000, 'parsed is 5000 properties deep');
-
- st.end();
- });
-
- t.test('parses null objects correctly', { skip: !hasProto }, function (st) {
- var a = { __proto__: null, b: 'c' };
-
- st.deepEqual(qs.parse(a), { b: 'c' });
- var result = qs.parse({ a: a });
- st.equal('a' in result, true, 'result has "a" property');
- st.deepEqual(result.a, a);
- st.end();
- });
-
- t.test('parses dates correctly', function (st) {
- var now = new Date();
- st.deepEqual(qs.parse({ a: now }), { a: now });
- st.end();
- });
-
- t.test('parses regular expressions correctly', function (st) {
- var re = /^test$/;
- st.deepEqual(qs.parse({ a: re }), { a: re });
- st.end();
- });
-
- t.test('does not allow overwriting prototype properties', function (st) {
- st.deepEqual(qs.parse('a[hasOwnProperty]=b', { allowPrototypes: false }), {});
- st.deepEqual(qs.parse('hasOwnProperty=b', { allowPrototypes: false }), {});
-
- st.deepEqual(
- qs.parse('toString', { allowPrototypes: false }),
- {},
- 'bare "toString" results in {}'
- );
-
- st.end();
- });
-
- t.test('can allow overwriting prototype properties', function (st) {
- st.deepEqual(qs.parse('a[hasOwnProperty]=b', { allowPrototypes: true }), { a: { hasOwnProperty: 'b' } });
- st.deepEqual(qs.parse('hasOwnProperty=b', { allowPrototypes: true }), { hasOwnProperty: 'b' });
-
- st.deepEqual(
- qs.parse('toString', { allowPrototypes: true }),
- { toString: '' },
- 'bare "toString" results in { toString: "" }'
- );
-
- st.end();
- });
-
- t.test('does not crash when the global Object prototype is frozen', { skip: !hasPropertyDescriptors || !hasOverrideMistake }, function (st) {
- // We can't actually freeze the global Object prototype as that will interfere with other tests, and once an object is frozen, it
- // can't be unfrozen. Instead, we add a new non-writable property to simulate this.
- st.teardown(mockProperty(Object.prototype, 'frozenProp', { value: 'foo', nonWritable: true, nonEnumerable: true }));
-
- st['throws'](
- function () {
- var obj = {};
- obj.frozenProp = 'bar';
- },
- // node < 6 has a different error message
- /^TypeError: Cannot assign to read only property 'frozenProp' of (?:object '#<Object>'|#<Object>)/,
- 'regular assignment of an inherited non-writable property throws'
- );
-
- var parsed;
- st.doesNotThrow(
- function () {
- parsed = qs.parse('frozenProp', { allowPrototypes: false });
- },
- 'parsing a nonwritable Object.prototype property does not throw'
- );
-
- st.deepEqual(parsed, {}, 'bare "frozenProp" results in {}');
-
- st.end();
- });
-
- t.test('params starting with a closing bracket', function (st) {
- st.deepEqual(qs.parse(']=toString'), { ']': 'toString' });
- st.deepEqual(qs.parse(']]=toString'), { ']]': 'toString' });
- st.deepEqual(qs.parse(']hello]=toString'), { ']hello]': 'toString' });
- st.end();
- });
-
- t.test('params starting with a starting bracket', function (st) {
- st.deepEqual(qs.parse('[=toString'), { '[': 'toString' });
- st.deepEqual(qs.parse('[[=toString'), { '[[': 'toString' });
- st.deepEqual(qs.parse('[hello[=toString'), { '[hello[': 'toString' });
- st.end();
- });
-
- t.test('add keys to objects', function (st) {
- st.deepEqual(
- qs.parse('a[b]=c&a=d', { strictMerge: false }),
- { a: { b: 'c', d: true } },
- 'can add keys to objects'
- );
-
- st.deepEqual(
- qs.parse('a[b]=c&a=toString', { strictMerge: false }),
- { a: { b: 'c' } },
- 'can not overwrite prototype'
- );
-
- st.deepEqual(
- qs.parse('a[b]=c&a=toString', { strictMerge: false, allowPrototypes: true }),
- { a: { b: 'c', toString: true } },
- 'can overwrite prototype with allowPrototypes true'
- );
-
- st.deepEqual(
- qs.parse('a[b]=c&a=toString', { strictMerge: false, plainObjects: true }),
- { __proto__: null, a: { __proto__: null, b: 'c', toString: true } },
- 'can overwrite prototype with plainObjects true'
- );
-
- st.end();
- });
-
- t.test('strictMerge wraps object and primitive into an array', function (st) {
- st.deepEqual(
- qs.parse('a[b]=c&a=d'),
- { a: [{ b: 'c' }, 'd'] },
- 'object then primitive produces array'
- );
-
- st.deepEqual(
- qs.parse('a=d&a[b]=c'),
- { a: ['d', { b: 'c' }] },
- 'primitive then object produces array'
- );
-
- st.deepEqual(
- qs.parse('a[b]=c&a=toString'),
- { a: [{ b: 'c' }, 'toString'] },
- 'prototype-colliding value is preserved in array'
- );
-
- st.deepEqual(
- qs.parse('a[b]=c&a=toString', { plainObjects: true }),
- { __proto__: null, a: [{ __proto__: null, b: 'c' }, 'toString'] },
- 'plainObjects preserved in array wrapping'
- );
-
- st.end();
- });
-
- t.test('dunder proto is ignored', function (st) {
- var payload = 'categories[__proto__]=login&categories[__proto__]&categories[length]=42';
- var result = qs.parse(payload, { allowPrototypes: true });
-
- st.deepEqual(
- result,
- {
- categories: {
- length: '42'
- }
- },
- 'silent [[Prototype]] payload'
- );
-
- var plainResult = qs.parse(payload, { allowPrototypes: true, plainObjects: true });
-
- st.deepEqual(
- plainResult,
- {
- __proto__: null,
- categories: {
- __proto__: null,
- length: '42'
- }
- },
- 'silent [[Prototype]] payload: plain objects'
- );
-
- var query = qs.parse('categories[__proto__]=cats&categories[__proto__]=dogs&categories[some][json]=toInject', { allowPrototypes: true });
-
- st.notOk(Array.isArray(query.categories), 'is not an array');
- st.notOk(query.categories instanceof Array, 'is not instanceof an array');
- st.deepEqual(query.categories, { some: { json: 'toInject' } });
- st.equal(JSON.stringify(query.categories), '{"some":{"json":"toInject"}}', 'stringifies as a non-array');
-
- st.deepEqual(
- qs.parse('foo[__proto__][hidden]=value&foo[bar]=stuffs', { allowPrototypes: true }),
- {
- foo: {
- bar: 'stuffs'
- }
- },
- 'hidden values'
- );
-
- st.deepEqual(
- qs.parse('foo[__proto__][hidden]=value&foo[bar]=stuffs', { allowPrototypes: true, plainObjects: true }),
- {
- __proto__: null,
- foo: {
- __proto__: null,
- bar: 'stuffs'
- }
- },
- 'hidden values: plain objects'
- );
-
- st.end();
- });
-
- t.test('object-valued input with own `__proto__` does not mutate sub-object [[Prototype]]', function (st) {
- // JSON.parse creates own data `__proto__` properties (via CreateDataProperty),
- // which would trigger the Object.prototype.__proto__ accessor if merged via `acc[key] = value`.
- var out = qs.parse({
- 'user[name]': 'alice',
- user: JSON.parse('{"__proto__":{"isAdmin":true}}')
- }, { allowPrototypes: false });
-
- st.equal(out.user.name, 'alice', 'name from bracket key is preserved');
- st.equal(out.user.isAdmin, undefined, 'attacker-controlled inherited property is not exposed');
- st.equal(Object.getPrototypeOf(out.user), Object.prototype, 'sub-object [[Prototype]] is unchanged');
- st.equal(Object.prototype.isAdmin, undefined, 'Object.prototype is not polluted');
-
- st.end();
- });
-
- t.test('can return null objects', { skip: !hasProto }, function (st) {
- var expected = {
- __proto__: null,
- a: {
- __proto__: null,
- b: 'c',
- hasOwnProperty: 'd'
- }
- };
- st.deepEqual(qs.parse('a[b]=c&a[hasOwnProperty]=d', { plainObjects: true }), expected);
- st.deepEqual(qs.parse(null, { plainObjects: true }), { __proto__: null });
- var expectedArray = {
- __proto__: null,
- a: {
- __proto__: null,
- 0: 'b',
- c: 'd'
- }
- };
- st.deepEqual(qs.parse('a[]=b&a[c]=d', { plainObjects: true }), expectedArray);
- st.end();
- });
-
- t.test('can parse with custom encoding', function (st) {
- st.deepEqual(qs.parse('%8c%a7=%91%e5%8d%e3%95%7b', {
- decoder: function (str) {
- var reg = /%([0-9A-F]{2})/ig;
- var result = [];
- var parts = reg.exec(str);
- while (parts) {
- result.push(parseInt(parts[1], 16));
- parts = reg.exec(str);
- }
- return String(iconv.decode(SaferBuffer.from(result), 'shift_jis'));
- }
- }), { 県: '大阪府' });
- st.end();
- });
-
- t.test('receives the default decoder as a second argument', function (st) {
- st.plan(1);
- qs.parse('a', {
- decoder: function (str, defaultDecoder) {
- st.equal(defaultDecoder, utils.decode);
- }
- });
- st.end();
- });
-
- t.test('throws error with wrong decoder', function (st) {
- st['throws'](function () {
- qs.parse({}, { decoder: 'string' });
- }, new TypeError('Decoder has to be a function.'));
- st.end();
- });
-
- t.test('does not mutate the options argument', function (st) {
- var options = {};
- qs.parse('a[b]=true', options);
- st.deepEqual(options, {});
- st.end();
- });
-
- t.test('throws if an invalid charset is specified', function (st) {
- st['throws'](function () {
- qs.parse('a=b', { charset: 'foobar' });
- }, new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined'));
- st.end();
- });
-
- t.test('parses an iso-8859-1 string if asked to', function (st) {
- st.deepEqual(qs.parse('%A2=%BD', { charset: 'iso-8859-1' }), { '¢': '½' });
- st.end();
- });
-
- var urlEncodedCheckmarkInUtf8 = '%E2%9C%93';
- var urlEncodedOSlashInUtf8 = '%C3%B8';
- var urlEncodedNumCheckmark = '%26%2310003%3B';
- var urlEncodedNumSmiley = '%26%239786%3B';
-
- t.test('prefers an utf-8 charset specified by the utf8 sentinel to a default charset of iso-8859-1', function (st) {
- st.deepEqual(qs.parse('utf8=' + urlEncodedCheckmarkInUtf8 + '&' + urlEncodedOSlashInUtf8 + '=' + urlEncodedOSlashInUtf8, { charsetSentinel: true, charset: 'iso-8859-1' }), { ø: 'ø' });
- st.end();
- });
-
- t.test('prefers an iso-8859-1 charset specified by the utf8 sentinel to a default charset of utf-8', function (st) {
- st.deepEqual(qs.parse('utf8=' + urlEncodedNumCheckmark + '&' + urlEncodedOSlashInUtf8 + '=' + urlEncodedOSlashInUtf8, { charsetSentinel: true, charset: 'utf-8' }), { 'ø': 'ø' });
- st.end();
- });
-
- t.test('does not require the utf8 sentinel to be defined before the parameters whose decoding it affects', function (st) {
- st.deepEqual(qs.parse('a=' + urlEncodedOSlashInUtf8 + '&utf8=' + urlEncodedNumCheckmark, { charsetSentinel: true, charset: 'utf-8' }), { a: 'ø' });
- st.end();
- });
-
- t.test('ignores an utf8 sentinel with an unknown value', function (st) {
- st.deepEqual(qs.parse('utf8=foo&' + urlEncodedOSlashInUtf8 + '=' + urlEncodedOSlashInUtf8, { charsetSentinel: true, charset: 'utf-8' }), { ø: 'ø' });
- st.end();
- });
-
- t.test('uses the utf8 sentinel to switch to utf-8 when no default charset is given', function (st) {
- st.deepEqual(qs.parse('utf8=' + urlEncodedCheckmarkInUtf8 + '&' + urlEncodedOSlashInUtf8 + '=' + urlEncodedOSlashInUtf8, { charsetSentinel: true }), { ø: 'ø' });
- st.end();
- });
-
- t.test('uses the utf8 sentinel to switch to iso-8859-1 when no default charset is given', function (st) {
- st.deepEqual(qs.parse('utf8=' + urlEncodedNumCheckmark + '&' + urlEncodedOSlashInUtf8 + '=' + urlEncodedOSlashInUtf8, { charsetSentinel: true }), { 'ø': 'ø' });
- st.end();
- });
-
- t.test('interprets numeric entities in iso-8859-1 when `interpretNumericEntities`', function (st) {
- st.deepEqual(qs.parse('foo=' + urlEncodedNumSmiley, { charset: 'iso-8859-1', interpretNumericEntities: true }), { foo: '☺' });
- st.end();
- });
-
- t.test('handles a custom decoder returning `null`, in the `iso-8859-1` charset, when `interpretNumericEntities`', function (st) {
- st.deepEqual(qs.parse('foo=&bar=' + urlEncodedNumSmiley, {
- charset: 'iso-8859-1',
- decoder: function (str, defaultDecoder, charset) {
- return str ? defaultDecoder(str, defaultDecoder, charset) : null;
- },
- interpretNumericEntities: true
- }), { foo: null, bar: '☺' });
- st.end();
- });
-
- t.test('handles a custom decoder returning `null`, with a string key of `null`', function (st) {
- st.deepEqual(
- qs.parse('null=1&ToNull=2', {
- decoder: function (str, defaultDecoder, charset) {
- return str === 'ToNull' ? null : defaultDecoder(str, defaultDecoder, charset);
- }
- }),
- { 'null': '1' },
- '"null" key is not overridden by `null` decoder result'
- );
-
- st.end();
- });
-
- t.test('does not interpret numeric entities in iso-8859-1 when `interpretNumericEntities` is absent', function (st) {
- st.deepEqual(qs.parse('foo=' + urlEncodedNumSmiley, { charset: 'iso-8859-1' }), { foo: '&#9786;' });
- st.end();
- });
-
- t.test('does not interpret numeric entities when the charset is utf-8, even when `interpretNumericEntities`', function (st) {
- st.deepEqual(qs.parse('foo=' + urlEncodedNumSmiley, { charset: 'utf-8', interpretNumericEntities: true }), { foo: '&#9786;' });
- st.end();
- });
-
- t.test('interpretNumericEntities with comma:true and iso charset does not crash', function (st) {
- st.deepEqual(
- qs.parse('b&a[]=1,' + urlEncodedNumSmiley, { comma: true, charset: 'iso-8859-1', interpretNumericEntities: true }),
- { b: '', a: ['1,☺'] }
- );
-
- st.end();
- });
-
- t.test('does not interpret %uXXXX syntax in iso-8859-1 mode', function (st) {
- st.deepEqual(qs.parse('%u263A=%u263A', { charset: 'iso-8859-1' }), { '%u263A': '%u263A' });
- st.end();
- });
-
- t.test('allows for decoding keys and values differently', function (st) {
- var decoder = function (str, defaultDecoder, charset, type) {
- if (type === 'key') {
- return defaultDecoder(str, defaultDecoder, charset, type).toLowerCase();
- }
- if (type === 'value') {
- return defaultDecoder(str, defaultDecoder, charset, type).toUpperCase();
- }
- throw 'this should never happen! type: ' + type;
- };
-
- st.deepEqual(qs.parse('KeY=vAlUe', { decoder: decoder }), { key: 'VALUE' });
-
- var noopDecoder = function () { return 'x'; };
- noopDecoder();
- st['throws'](
- function () { decoder('x', noopDecoder, 'utf-8', 'unknown'); },
- 'this should never happen! type: unknown',
- 'decoder throws for unexpected type'
- );
-
- st.end();
- });
-
- t.test('parameter limit tests', function (st) {
- st.test('does not throw error when within parameter limit', function (sst) {
- var result = qs.parse('a=1&b=2&c=3', { parameterLimit: 5, throwOnLimitExceeded: true });
- sst.deepEqual(result, { a: '1', b: '2', c: '3' }, 'parses without errors');
- sst.end();
- });
-
- st.test('throws error when throwOnLimitExceeded is present but not boolean', function (sst) {
- sst['throws'](
- function () {
- qs.parse('a=1&b=2&c=3&d=4&e=5&f=6', { parameterLimit: 3, throwOnLimitExceeded: 'true' });
- },
- new TypeError('`throwOnLimitExceeded` option must be a boolean'),
- 'throws error when throwOnLimitExceeded is present and not boolean'
- );
- sst.end();
- });
-
- st.test('throws error when parameter limit exceeded', function (sst) {
- sst['throws'](
- function () {
- qs.parse('a=1&b=2&c=3&d=4&e=5&f=6', { parameterLimit: 3, throwOnLimitExceeded: true });
- },
- new RangeError('Parameter limit exceeded. Only 3 parameters allowed.'),
- 'throws error when parameter limit is exceeded'
- );
-
- sst['throws'](
- function () {
- qs.parse('a=1&b=2', { parameterLimit: 1, throwOnLimitExceeded: true });
- },
- new RangeError('Parameter limit exceeded. Only 1 parameter allowed.'),
- 'throws error with singular "parameter" when parameterLimit is 1'
- );
- sst.end();
- });
-
- st.test('silently truncates when throwOnLimitExceeded is not given', function (sst) {
- var result = qs.parse('a=1&b=2&c=3&d=4&e=5', { parameterLimit: 3 });
- sst.deepEqual(result, { a: '1', b: '2', c: '3' }, 'parses and truncates silently');
- sst.end();
- });
-
- st.test('silently truncates when parameter limit exceeded without error', function (sst) {
- var result = qs.parse('a=1&b=2&c=3&d=4&e=5', { parameterLimit: 3, throwOnLimitExceeded: false });
- sst.deepEqual(result, { a: '1', b: '2', c: '3' }, 'parses and truncates silently');
- sst.end();
- });
-
- st.test('allows unlimited parameters when parameterLimit set to Infinity', function (sst) {
- var result = qs.parse('a=1&b=2&c=3&d=4&e=5&f=6', { parameterLimit: Infinity });
- sst.deepEqual(result, { a: '1', b: '2', c: '3', d: '4', e: '5', f: '6' }, 'parses all parameters without truncation');
- sst.end();
- });
-
- st.test('allows unlimited parameters when parameterLimit is Infinity and throwOnLimitExceeded is true', function (sst) {
- var result = qs.parse('a=1&b=2&c=3&d=4&e=5&f=6', { parameterLimit: Infinity, throwOnLimitExceeded: true });
- sst.deepEqual(result, { a: '1', b: '2', c: '3', d: '4', e: '5', f: '6' }, 'parses all parameters without truncation or throwing');
- sst.end();
- });
-
- st.end();
- });
-
- t.test('array limit tests', function (st) {
- st.test('does not throw error when array is within limit', function (sst) {
- var result = qs.parse('a[]=1&a[]=2&a[]=3', { arrayLimit: 5, throwOnLimitExceeded: true });
- sst.deepEqual(result, { a: ['1', '2', '3'] }, 'parses array without errors');
- sst.end();
- });
-
- st.test('throws error when throwOnLimitExceeded is present but not boolean for array limit', function (sst) {
- sst['throws'](
- function () {
- qs.parse('a[]=1&a[]=2&a[]=3&a[]=4', { arrayLimit: 3, throwOnLimitExceeded: 'true' });
- },
- new TypeError('`throwOnLimitExceeded` option must be a boolean'),
- 'throws error when throwOnLimitExceeded is present and not boolean for array limit'
- );
- sst.end();
- });
-
- st.test('throws error when array limit exceeded', function (sst) {
- // 4 elements exceeds limit of 3
- sst['throws'](
- function () {
- qs.parse('a[]=1&a[]=2&a[]=3&a[]=4', { arrayLimit: 3, throwOnLimitExceeded: true });
- },
- new RangeError('Array limit exceeded. Only 3 elements allowed in an array.'),
- 'throws error when array limit is exceeded'
- );
- sst.end();
- });
-
- st.test('does not throw when at limit', function (sst) {
- // 3 elements = limit of 3, should not throw
- var result = qs.parse('a[]=1&a[]=2&a[]=3', { arrayLimit: 3, throwOnLimitExceeded: true });
- sst.ok(Array.isArray(result.a), 'result is an array');
- sst.deepEqual(result.a, ['1', '2', '3'], 'all values present');
- sst.end();
- });
-
- st.test('converts array to object if length is greater than limit', function (sst) {
- var result = qs.parse('a[1]=1&a[2]=2&a[3]=3&a[4]=4&a[5]=5&a[6]=6', { arrayLimit: 5 });
-
- sst.deepEqual(result, { a: { 1: '1', 2: '2', 3: '3', 4: '4', 5: '5', 6: '6' } }, 'parses into object if array length is greater than limit');
- sst.end();
- });
-
- st.test('throws error when indexed notation exceeds arrayLimit with throwOnLimitExceeded', function (sst) {
- sst['throws'](
- function () {
- qs.parse('a[1001]=b', { arrayLimit: 1000, throwOnLimitExceeded: true });
- },
- new RangeError('Array limit exceeded. Only 1000 elements allowed in an array.'),
- 'throws error for a single index exceeding arrayLimit'
- );
-
- sst['throws'](
- function () {
- qs.parse('a[0]=1&a[1]=2&a[2]=3&a[10]=4', { arrayLimit: 6, throwOnLimitExceeded: true, allowSparse: true });
- },
- new RangeError('Array limit exceeded. Only 6 elements allowed in an array.'),
- 'throws error when a sparse index exceeds arrayLimit'
- );
-
- sst['throws'](
- function () {
- qs.parse('a[2]=b', { arrayLimit: 1, throwOnLimitExceeded: true });
- },
- new RangeError('Array limit exceeded. Only 1 element allowed in an array.'),
- 'throws error with singular "element" when arrayLimit is 1'
- );
-
- sst.end();
- });
-
- st.test('does not throw for indexed notation within arrayLimit with throwOnLimitExceeded', function (sst) {
- var result = qs.parse('a[4]=b', { arrayLimit: 5, throwOnLimitExceeded: true, allowSparse: true });
- sst.ok(Array.isArray(result.a), 'result is an array');
- sst.equal(result.a.length, 5, 'array has correct length');
- sst.equal(result.a[4], 'b', 'value at index 4 is correct');
- sst.end();
- });
-
- st.test('silently converts to object for indexed notation exceeding arrayLimit without throwOnLimitExceeded', function (sst) {
- var result = qs.parse('a[1001]=b', { arrayLimit: 1000 });
- sst.deepEqual(result, { a: { 1001: 'b' } }, 'converts to object without throwing');
- sst.end();
- });
-
- st.test('throws when duplicate bracket keys exceed arrayLimit with throwOnLimitExceeded', function (sst) {
- sst['throws'](
- function () {
- qs.parse('a[]=1&a[]=2&a[]=3&a[]=4&a[]=5&a[]=6', { arrayLimit: 5, throwOnLimitExceeded: true });
- },
- new RangeError('Array limit exceeded. Only 5 elements allowed in an array.'),
- 'throws error when duplicate bracket notation exceeds array limit'
- );
- sst.end();
- });
-
- st.test('throws when cumulative comma + duplicate-key combine exceeds arrayLimit', function (sst) {
- sst['throws'](
- function () {
- qs.parse('a=1,2,3&a=4,5,6', { comma: true, arrayLimit: 5, throwOnLimitExceeded: true });
- },
- new RangeError('Array limit exceeded. Only 5 elements allowed in an array.'),
- 'throws when comma groups within the limit cumulatively exceed it across duplicate keys'
- );
-
- sst['throws'](
- function () {
- qs.parse('a=v,v,v,v,v&a=v,v,v,v,v&a=v,v,v,v,v', { comma: true, arrayLimit: 5, throwOnLimitExceeded: true });
- },
- new RangeError('Array limit exceeded. Only 5 elements allowed in an array.'),
- 'throws on a subsequent part once the cumulative array is already over the limit'
- );
- sst.end();
- });
-
- st.test('throws when plain duplicate keys combine past arrayLimit at the boundary', function (sst) {
- sst['throws'](
- function () { qs.parse('a=x&a=y', { arrayLimit: 1, throwOnLimitExceeded: true }); },
- new RangeError('Array limit exceeded. Only 1 element allowed in an array.'),
- 'duplicate scalar keys'
- );
-
- sst['throws'](
- function () { qs.parse('a[]=x&a[]=y', { arrayLimit: 1, throwOnLimitExceeded: true }); },
- new RangeError('Array limit exceeded. Only 1 element allowed in an array.'),
- 'duplicate bracket keys'
- );
- sst.end();
- });
-
- st.test('throws when mixed index and key notation merge past arrayLimit', function (sst) {
- sst['throws'](
- function () { qs.parse('a=x&a[0]=y', { arrayLimit: 1, throwOnLimitExceeded: true }); },
- new RangeError('Array limit exceeded. Only 1 element allowed in an array.'),
- 'scalar then index that overflows on merge'
- );
-
- sst['throws'](
- function () { qs.parse('a[0]=1&a[1]=2&a=3', { arrayLimit: 1, throwOnLimitExceeded: true }); },
- new RangeError('Array limit exceeded. Only 1 element allowed in an array.'),
- 'indexed array then scalar that overflows on merge'
- );
- sst.end();
- });
-
- st.test('enforces arrayLimit on merge at the boundary, consistently with combine', function (sst) {
- sst['throws'](
- function () { qs.parse('a[0]=x&a=y', { arrayLimit: 1, throwOnLimitExceeded: true }); },
- new RangeError('Array limit exceeded. Only 1 element allowed in an array.'),
- 'a trailing scalar merged into an at-limit array throws'
- );
- sst.deepEqual(
- qs.parse('a[0]=x&a=y', { arrayLimit: 1 }),
- { a: { 0: 'x', 1: 'y' } },
- 'and converts to an overflow object without throwOnLimitExceeded'
- );
-
- sst['throws'](
- function () { qs.parse('a[0]=x&a[]=y', { arrayLimit: 1, throwOnLimitExceeded: true }); },
- new RangeError('Array limit exceeded. Only 1 element allowed in an array.'),
- 'mixed index and bracket notation merged past the limit throws'
- );
- sst.deepEqual(
- qs.parse('a[0]=x&a[]=y', { arrayLimit: 1 }),
- { a: { 0: 'x', 1: 'y' } },
- 'mixed index and bracket notation converts like duplicate-bracket combine'
- );
-
- sst.end();
- });
-
- st.test('does not throw when cumulative comma combine stays within arrayLimit', function (sst) {
- var result = qs.parse('a=1,2,3&a=4', { comma: true, arrayLimit: 5, throwOnLimitExceeded: true });
- sst.deepEqual(result, { a: ['1', '2', '3', '4'] }, 'combined array within limit is preserved');
- sst.end();
- });
-
- st.test('silently combines to an overflow object when throwOnLimitExceeded is not set', function (sst) {
- var result = qs.parse('a=1,2,3&a=4,5,6', { comma: true, arrayLimit: 5 });
- sst.deepEqual(result, { a: { 0: '1', 1: '2', 2: '3', 3: '4', 4: '5', 5: '6' } }, 'converts to object without throwing');
- sst.end();
- });
-
- st.test('does not throw for comma groups nested under bracket notation, counting each group as one element', function (sst) {
- var result = qs.parse('a[]=1,2,3&a[]=4,5,6', { comma: true, arrayLimit: 5, throwOnLimitExceeded: true });
- sst.deepEqual(result, { a: [['1', '2', '3'], ['4', '5', '6']] }, 'nested comma groups count as one element each');
- sst.end();
- });
-
- st.test('throws before splitting when a single comma value exceeds arrayLimit', function (sst) {
- sst['throws'](
- function () {
- qs.parse('a=1,2,3,4,5,6', { comma: true, arrayLimit: 5, throwOnLimitExceeded: true });
- },
- new RangeError('Array limit exceeded. Only 5 elements allowed in an array.'),
- 'a flat comma value over the limit throws'
- );
-
- sst['throws'](
- function () {
- qs.parse('a=1,2', { comma: true, arrayLimit: 1, throwOnLimitExceeded: true });
- },
- new RangeError('Array limit exceeded. Only 1 element allowed in an array.'),
- 'singular message at arrayLimit 1'
- );
-
- sst['throws'](
- function () {
- qs.parse('a[b]=1,2,3,4,5,6', { comma: true, arrayLimit: 5, throwOnLimitExceeded: true });
- },
- new RangeError('Array limit exceeded. Only 5 elements allowed in an array.'),
- 'a non-bracket nested key comma value over the limit throws'
- );
- sst.end();
- });
-
- st.test('does not throw for a single comma value within arrayLimit', function (sst) {
- sst.deepEqual(
- qs.parse('a=1,2,3', { comma: true, arrayLimit: 5, throwOnLimitExceeded: true }),
- { a: ['1', '2', '3'] },
- 'within the limit'
- );
- sst.deepEqual(
- qs.parse('a=1,2,3,4,5', { comma: true, arrayLimit: 5, throwOnLimitExceeded: true }),
- { a: ['1', '2', '3', '4', '5'] },
- 'exactly at the limit'
- );
- sst.end();
- });
-
- st.test('does not throw for a bracketed comma group within arrayLimit', function (sst) {
- var result = qs.parse('a[]=1,2,3,4,5,6', { comma: true, arrayLimit: 5, throwOnLimitExceeded: true });
- sst.deepEqual(result, { a: [['1', '2', '3', '4', '5', '6']] }, 'a bracketed comma group is a single element');
- sst.end();
- });
-
- st.test('throws for a bracketed comma group when arrayLimit is 0', function (sst) {
- sst['throws'](
- function () {
- qs.parse('a[]=1,2,3', { comma: true, arrayLimit: 0, throwOnLimitExceeded: true });
- },
- new RangeError('Array limit exceeded. Only 0 elements allowed in an array.'),
- 'a single bracketed element still exceeds arrayLimit 0'
- );
- sst.end();
- });
-
- st.end();
- });
-
- t.end();
-});
-
-test('parses empty keys', function (t) {
- emptyTestCases.forEach(function (testCase) {
- t.test('skips empty string key with ' + testCase.input, function (st) {
- st.deepEqual(qs.parse(testCase.input), testCase.noEmptyKeys);
-
- st.end();
- });
- });
-});
-
-test('`duplicates` option', function (t) {
- v.nonStrings.concat('not a valid option').forEach(function (invalidOption) {
- if (typeof invalidOption !== 'undefined') {
- t['throws'](
- function () { qs.parse('', { duplicates: invalidOption }); },
- TypeError,
- 'throws on invalid option: ' + inspect(invalidOption)
- );
- }
- });
-
- t.deepEqual(
- qs.parse('foo=bar&foo=baz'),
- { foo: ['bar', 'baz'] },
- 'duplicates: default, combine'
- );
-
- t.deepEqual(
- qs.parse('foo=bar&foo=baz', { duplicates: 'combine' }),
- { foo: ['bar', 'baz'] },
- 'duplicates: combine'
- );
-
- t.deepEqual(
- qs.parse('foo=bar&foo=baz', { duplicates: 'first' }),
- { foo: 'bar' },
- 'duplicates: first'
- );
-
- t.deepEqual(
- qs.parse('foo=bar&foo=baz', { duplicates: 'last' }),
- { foo: 'baz' },
- 'duplicates: last'
- );
-
- t.test('bracket notation always combines regardless of duplicates', function (st) {
- st.deepEqual(
- qs.parse('a=1&a=2&b[]=1&b[]=2', { duplicates: 'last' }),
- { a: '2', b: ['1', '2'] },
- 'duplicates last: unbracketed takes last, bracketed combines'
- );
-
- st.deepEqual(
- qs.parse('b[]=1&b[]=2', { duplicates: 'last' }),
- { b: ['1', '2'] },
- 'duplicates last: bracketed always combines'
- );
-
- st.deepEqual(
- qs.parse('b[]=1&b[]=2', { duplicates: 'first' }),
- { b: ['1', '2'] },
- 'duplicates first: bracketed always combines'
- );
-
- st.deepEqual(
- qs.parse('a=1&a=2&b[]=1&b[]=2', { duplicates: 'first' }),
- { a: '1', b: ['1', '2'] },
- 'duplicates first: unbracketed takes first, bracketed combines'
- );
-
- st.end();
- });
-
- t.end();
-});
-
-test('qs strictDepth option - throw cases', function (t) {
- t.test('throws an exception when depth exceeds the limit with strictDepth: true', function (st) {
- st['throws'](
- function () {
- qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1, strictDepth: true });
- },
- RangeError,
- 'throws RangeError'
- );
- st.end();
- });
-
- t.test('throws an exception for multiple nested arrays with strictDepth: true', function (st) {
- st['throws'](
- function () {
- qs.parse('a[0][1][2][3][4]=b', { depth: 3, strictDepth: true });
- },
- RangeError,
- 'throws RangeError'
- );
- st.end();
- });
-
- t.test('throws an exception for nested objects and arrays with strictDepth: true', function (st) {
- st['throws'](
- function () {
- qs.parse('a[b][c][0][d][e]=f', { depth: 3, strictDepth: true });
- },
- RangeError,
- 'throws RangeError'
- );
- st.end();
- });
-
- t.test('throws an exception for different types of values with strictDepth: true', function (st) {
- st['throws'](
- function () {
- qs.parse('a[b][c][d][e]=true&a[b][c][d][f]=42', { depth: 3, strictDepth: true });
- },
- RangeError,
- 'throws RangeError'
- );
- st.end();
- });
-
-});
-
-test('qs strictDepth option - non-throw cases', function (t) {
- t.test('when depth is 0 and strictDepth true, do not throw', function (st) {
- st.doesNotThrow(
- function () {
- qs.parse('a[b][c][d][e]=true&a[b][c][d][f]=42', { depth: 0, strictDepth: true });
- },
- RangeError,
- 'does not throw RangeError'
- );
- st.end();
- });
-
- t.test('parses successfully when depth is within the limit with strictDepth: true', function (st) {
- st.doesNotThrow(
- function () {
- var result = qs.parse('a[b]=c', { depth: 1, strictDepth: true });
- st.deepEqual(result, { a: { b: 'c' } }, 'parses correctly');
- }
- );
- st.end();
- });
-
- t.test('does not throw an exception when depth exceeds the limit with strictDepth: false', function (st) {
- st.doesNotThrow(
- function () {
- var result = qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1 });
- st.deepEqual(result, { a: { b: { '[c][d][e][f][g][h][i]': 'j' } } }, 'parses with depth limit');
- }
- );
- st.end();
- });
-
- t.test('parses successfully when depth is within the limit with strictDepth: false', function (st) {
- st.doesNotThrow(
- function () {
- var result = qs.parse('a[b]=c', { depth: 1 });
- st.deepEqual(result, { a: { b: 'c' } }, 'parses correctly');
- }
- );
- st.end();
- });
-
- t.test('does not throw when depth is exactly at the limit with strictDepth: true', function (st) {
- st.doesNotThrow(
- function () {
- var result = qs.parse('a[b][c]=d', { depth: 2, strictDepth: true });
- st.deepEqual(result, { a: { b: { c: 'd' } } }, 'parses correctly');
- }
- );
- st.end();
- });
-});
-
-test('DOS', function (t) {
- var arr = [];
- for (var i = 0; i < 105; i++) {
- arr[arr.length] = 'x';
- }
- var attack = 'a[]=' + arr.join('&a[]=');
- var result = qs.parse(attack, { arrayLimit: 100 });
-
- t.notOk(Array.isArray(result.a), 'arrayLimit is respected: result is an object, not an array');
- t.equal(Object.keys(result.a).length, 105, 'all values are preserved');
-
- t.end();
-});
-
-test('arrayLimit boundary conditions', function (t) {
- // arrayLimit is the max number of elements allowed in an array
- t.test('exactly at the limit stays as array', function (st) {
- // 3 elements = limit of 3
- var result = qs.parse('a[]=1&a[]=2&a[]=3', { arrayLimit: 3 });
- st.ok(Array.isArray(result.a), 'result is an array when count equals limit');
- st.deepEqual(result.a, ['1', '2', '3'], 'all values present');
- st.end();
- });
-
- t.test('one over the limit converts to object', function (st) {
- // 4 elements exceeds limit of 3
- var result = qs.parse('a[]=1&a[]=2&a[]=3&a[]=4', { arrayLimit: 3 });
- st.notOk(Array.isArray(result.a), 'result is not an array when over limit');
- st.deepEqual(result.a, { 0: '1', 1: '2', 2: '3', 3: '4' }, 'all values preserved as object');
- st.end();
- });
-
- t.test('arrayLimit 1 with one value', function (st) {
- // 1 element = limit of 1
- var result = qs.parse('a[]=1', { arrayLimit: 1 });
- st.ok(Array.isArray(result.a), 'result is an array when count equals limit');
- st.deepEqual(result.a, ['1'], 'value preserved as array');
- st.end();
- });
-
- t.test('arrayLimit 1 with two values converts to object', function (st) {
- // 2 elements exceeds limit of 1
- var result = qs.parse('a[]=1&a[]=2', { arrayLimit: 1 });
- st.notOk(Array.isArray(result.a), 'result is not an array');
- st.deepEqual(result.a, { 0: '1', 1: '2' }, 'all values preserved as object');
- st.end();
- });
-
- t.end();
-});
-
-test('comma + arrayLimit', function (t) {
- t.test('comma-separated values within arrayLimit stay as array', function (st) {
- var result = qs.parse('a=1,2,3', { comma: true, arrayLimit: 5 });
- st.ok(Array.isArray(result.a), 'result is an array');
- st.deepEqual(result.a, ['1', '2', '3'], 'all values present');
- st.end();
- });
-
- t.test('comma-separated values exceeding arrayLimit convert to object', function (st) {
- var result = qs.parse('a=1,2,3,4', { comma: true, arrayLimit: 3 });
- st.notOk(Array.isArray(result.a), 'result is not an array when over limit');
- st.deepEqual(result.a, { 0: '1', 1: '2', 2: '3', 3: '4' }, 'all values preserved as object');
- st.end();
- });
-
- t.test('comma-separated values exceeding arrayLimit with throwOnLimitExceeded throws', function (st) {
- st['throws'](
- function () {
- qs.parse('a=1,2,3,4', { comma: true, arrayLimit: 3, throwOnLimitExceeded: true });
- },
- new RangeError('Array limit exceeded. Only 3 elements allowed in an array.'),
- 'throws error when comma-split exceeds array limit'
- );
-
- st['throws'](
- function () {
- qs.parse('a=1,2,3', { comma: true, arrayLimit: 1, throwOnLimitExceeded: true });
- },
- new RangeError('Array limit exceeded. Only 1 element allowed in an array.'),
- 'throws error with singular "element" when arrayLimit is 1'
- );
- st.end();
- });
-
- t.test('comma-separated values at exactly arrayLimit stay as array', function (st) {
- var result = qs.parse('a=1,2,3', { comma: true, arrayLimit: 3 });
- st.ok(Array.isArray(result.a), 'result is an array when exactly at limit');
- st.deepEqual(result.a, ['1', '2', '3'], 'all values present');
- st.end();
- });
-
- t.end();
-});
-
-test('mixed array and object notation', function (t) {
- t.test('array brackets with object key - under limit', function (st) {
- st.deepEqual(
- qs.parse('a[]=b&a[c]=d'),
- { a: { 0: 'b', c: 'd' } },
- 'mixing [] and [key] converts to object'
- );
- st.end();
- });
-
- t.test('array index with object key - under limit', function (st) {
- st.deepEqual(
- qs.parse('a[0]=b&a[c]=d'),
- { a: { 0: 'b', c: 'd' } },
- 'mixing [0] and [key] produces object'
- );
- st.end();
- });
-
- t.test('plain value with array brackets - under limit', function (st) {
- st.deepEqual(
- qs.parse('a=b&a[]=c', { arrayLimit: 20 }),
- { a: ['b', 'c'] },
- 'plain value combined with [] stays as array under limit'
- );
- st.end();
- });
-
- t.test('array brackets with plain value - under limit', function (st) {
- st.deepEqual(
- qs.parse('a[]=b&a=c', { arrayLimit: 20 }),
- { a: ['b', 'c'] },
- '[] combined with plain value stays as array under limit'
- );
- st.end();
- });
-
- t.test('plain value with array index - under limit', function (st) {
- st.deepEqual(
- qs.parse('a=b&a[0]=c', { arrayLimit: 20 }),
- { a: ['b', 'c'] },
- 'plain value combined with [0] stays as array under limit'
- );
- st.end();
- });
-
- t.test('multiple plain values with duplicates combine', function (st) {
- st.deepEqual(
- qs.parse('a=b&a=c&a=d', { arrayLimit: 20 }),
- { a: ['b', 'c', 'd'] },
- 'duplicate plain keys combine into array'
- );
- st.end();
- });
-
- t.test('multiple plain values exceeding limit', function (st) {
- // 3 elements (indices 0-2), max index 2 > limit 1
- st.deepEqual(
- qs.parse('a=b&a=c&a=d', { arrayLimit: 1 }),
- { a: { 0: 'b', 1: 'c', 2: 'd' } },
- 'duplicate plain keys convert to object when exceeding limit'
- );
- st.end();
- });
-
- t.test('mixed notation produces consistent results when arrayLimit is exceeded', function (st) {
- var expected = { a: { 0: 'b', 1: 'c', 2: 'd' } };
-
- st.deepEqual(
- qs.parse('a[]=b&a[1]=c&a=d', { arrayLimit: -1 }),
- expected,
- 'arrayLimit -1'
- );
-
- st.deepEqual(
- qs.parse('a[]=b&a[1]=c&a=d', { arrayLimit: 0 }),
- expected,
- 'arrayLimit 0'
- );
-
- st.deepEqual(
- qs.parse('a[]=b&a[1]=c&a=d', { arrayLimit: 1 }),
- expected,
- 'arrayLimit 1'
- );
-
- st.end();
- });
-
- t.test('uses existing array length for currentArrayLength when parsing object input with bracket keys', function (st) {
- var input = {};
- var arr = ['x', 'y'];
- arr.a = ['z', 'w'];
- input['a[]'] = arr;
- st.deepEqual(qs.parse(input), { a: ['x', 'y'] }, 'parses object input with bracket keys using existing array values');
- st.end();
- });
-
- t.test('throws with singular message when object input bracket key exceeds arrayLimit of 1', function (st) {
- var input = {};
- var arr = ['x'];
- arr.a = ['z', 'w'];
- input['a[]'] = arr;
- st['throws'](
- function () {
- qs.parse(input, { throwOnLimitExceeded: true, arrayLimit: 1 });
- },
- new RangeError('Array limit exceeded. Only 1 element allowed in an array.'),
- 'throws singular error for object input exceeding arrayLimit 1'
- );
- st.end();
- });
-
- t.end();
-});
diff --git a/node_modules/qs/test/stringify.js b/node_modules/qs/test/stringify.js
deleted file mode 100644
index 07324cf..0000000
--- a/node_modules/qs/test/stringify.js
+++ /dev/null
@@ -1,1448 +0,0 @@
-'use strict';
-
-var test = require('tape');
-var qs = require('../');
-var utils = require('../lib/utils');
-var iconv = require('iconv-lite');
-var SaferBuffer = require('safer-buffer').Buffer;
-var hasSymbols = require('has-symbols');
-var mockProperty = require('mock-property');
-var emptyTestCases = require('./empty-keys-cases').emptyTestCases;
-var hasProto = require('has-proto')();
-var hasBigInt = require('has-bigints')();
-
-test('stringify()', function (t) {
- t.test('stringifies a querystring object', function (st) {
- st.equal(qs.stringify({ a: 'b' }), 'a=b');
- st.equal(qs.stringify({ a: 1 }), 'a=1');
- st.equal(qs.stringify({ a: 1, b: 2 }), 'a=1&b=2');
- st.equal(qs.stringify({ a: 'A_Z' }), 'a=A_Z');
- st.equal(qs.stringify({ a: '€' }), 'a=%E2%82%AC');
- st.equal(qs.stringify({ a: '' }), 'a=%EE%80%80');
- st.equal(qs.stringify({ a: 'א' }), 'a=%D7%90');
- st.equal(qs.stringify({ a: '𐐷' }), 'a=%F0%90%90%B7');
- st.end();
- });
-
- t.test('stringifies falsy values', function (st) {
- st.equal(qs.stringify(undefined), '');
- st.equal(qs.stringify(null), '');
- st.equal(qs.stringify(null, { strictNullHandling: true }), '');
- st.equal(qs.stringify(false), '');
- st.equal(qs.stringify(0), '');
- st.end();
- });
-
- t.test('stringifies symbols', { skip: !hasSymbols() }, function (st) {
- st.equal(qs.stringify(Symbol.iterator), '');
- st.equal(qs.stringify([Symbol.iterator]), '0=Symbol%28Symbol.iterator%29');
- st.equal(qs.stringify({ a: Symbol.iterator }), 'a=Symbol%28Symbol.iterator%29');
- st.equal(
- qs.stringify({ a: [Symbol.iterator] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }),
- 'a[]=Symbol%28Symbol.iterator%29'
- );
- st.end();
- });
-
- t.test('stringifies bigints', { skip: !hasBigInt }, function (st) {
- var three = BigInt(3);
- var encodeWithN = function (value, defaultEncoder, charset) {
- var result = defaultEncoder(value, defaultEncoder, charset);
- return typeof value === 'bigint' ? result + 'n' : result;
- };
- st.equal(qs.stringify(three), '');
- st.equal(qs.stringify([three]), '0=3');
- st.equal(qs.stringify([three], { encoder: encodeWithN }), '0=3n');
- st.equal(qs.stringify({ a: three }), 'a=3');
- st.equal(qs.stringify({ a: three }, { encoder: encodeWithN }), 'a=3n');
- st.equal(
- qs.stringify({ a: [three] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }),
- 'a[]=3'
- );
- st.equal(
- qs.stringify({ a: [three] }, { encodeValuesOnly: true, encoder: encodeWithN, arrayFormat: 'brackets' }),
- 'a[]=3n'
- );
- st.end();
- });
-
- t.test('encodes dot in key of object when encodeDotInKeys and allowDots is provided', function (st) {
- st.equal(
- qs.stringify(
- { 'name.obj': { first: 'John', last: 'Doe' } },
- { allowDots: false, encodeDotInKeys: false }
- ),
- 'name.obj%5Bfirst%5D=John&name.obj%5Blast%5D=Doe',
- 'with allowDots false and encodeDotInKeys false'
- );
- st.equal(
- qs.stringify(
- { 'name.obj': { first: 'John', last: 'Doe' } },
- { allowDots: true, encodeDotInKeys: false }
- ),
- 'name.obj.first=John&name.obj.last=Doe',
- 'with allowDots true and encodeDotInKeys false'
- );
- st.equal(
- qs.stringify(
- { 'name.obj': { first: 'John', last: 'Doe' } },
- { allowDots: false, encodeDotInKeys: true }
- ),
- 'name%252Eobj%5Bfirst%5D=John&name%252Eobj%5Blast%5D=Doe',
- 'with allowDots false and encodeDotInKeys true'
- );
- st.equal(
- qs.stringify(
- { 'name.obj': { first: 'John', last: 'Doe' } },
- { allowDots: true, encodeDotInKeys: true }
- ),
- 'name%252Eobj.first=John&name%252Eobj.last=Doe',
- 'with allowDots true and encodeDotInKeys true'
- );
-
- st.equal(
- qs.stringify(
- { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } },
- { allowDots: false, encodeDotInKeys: false }
- ),
- 'name.obj.subobject%5Bfirst.godly.name%5D=John&name.obj.subobject%5Blast%5D=Doe',
- 'with allowDots false and encodeDotInKeys false'
- );
- st.equal(
- qs.stringify(
- { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } },
- { allowDots: true, encodeDotInKeys: false }
- ),
- 'name.obj.subobject.first.godly.name=John&name.obj.subobject.last=Doe',
- 'with allowDots false and encodeDotInKeys false'
- );
- st.equal(
- qs.stringify(
- { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } },
- { allowDots: false, encodeDotInKeys: true }
- ),
- 'name%252Eobj%252Esubobject%5Bfirst.godly.name%5D=John&name%252Eobj%252Esubobject%5Blast%5D=Doe',
- 'with allowDots false and encodeDotInKeys true'
- );
- st.equal(
- qs.stringify(
- { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } },
- { allowDots: true, encodeDotInKeys: true }
- ),
- 'name%252Eobj%252Esubobject.first%252Egodly%252Ename=John&name%252Eobj%252Esubobject.last=Doe',
- 'with allowDots true and encodeDotInKeys true'
- );
-
- st.end();
- });
-
- t.test('should encode dot in key of object, and automatically set allowDots to `true` when encodeDotInKeys is true and allowDots in undefined', function (st) {
- st.equal(
- qs.stringify(
- { 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } },
- { encodeDotInKeys: true }
- ),
- 'name%252Eobj%252Esubobject.first%252Egodly%252Ename=John&name%252Eobj%252Esubobject.last=Doe',
- 'with allowDots undefined and encodeDotInKeys true'
- );
- st.end();
- });
-
- t.test('should encode dot in key of object when encodeDotInKeys and allowDots is provided, and nothing else when encodeValuesOnly is provided', function (st) {
- st.equal(
- qs.stringify({ 'name.obj': { first: 'John', last: 'Doe' } }, {
- encodeDotInKeys: true, allowDots: true, encodeValuesOnly: true
- }),
- 'name%2Eobj.first=John&name%2Eobj.last=Doe'
- );
-
- st.equal(
- qs.stringify({ 'name.obj.subobject': { 'first.godly.name': 'John', last: 'Doe' } }, { allowDots: true, encodeDotInKeys: true, encodeValuesOnly: true }),
- 'name%2Eobj%2Esubobject.first%2Egodly%2Ename=John&name%2Eobj%2Esubobject.last=Doe'
- );
-
- st.end();
- });
-
- t.test('throws when `commaRoundTrip` is not a boolean', function (st) {
- st['throws'](
- function () { qs.stringify({}, { commaRoundTrip: 'not a boolean' }); },
- TypeError,
- 'throws when `commaRoundTrip` is not a boolean'
- );
-
- st.end();
- });
-
- t.test('throws when `encodeDotInKeys` is not a boolean', function (st) {
- st['throws'](
- function () { qs.stringify({ a: [], b: 'zz' }, { encodeDotInKeys: 'foobar' }); },
- TypeError
- );
-
- st['throws'](
- function () { qs.stringify({ a: [], b: 'zz' }, { encodeDotInKeys: 0 }); },
- TypeError
- );
-
- st['throws'](
- function () { qs.stringify({ a: [], b: 'zz' }, { encodeDotInKeys: NaN }); },
- TypeError
- );
-
- st['throws'](
- function () { qs.stringify({ a: [], b: 'zz' }, { encodeDotInKeys: null }); },
- TypeError
- );
-
- st.end();
- });
-
- t.test('adds query prefix', function (st) {
- st.equal(qs.stringify({ a: 'b' }, { addQueryPrefix: true }), '?a=b');
- st.end();
- });
-
- t.test('with query prefix, outputs blank string given an empty object', function (st) {
- st.equal(qs.stringify({}, { addQueryPrefix: true }), '');
- st.end();
- });
-
- t.test('stringifies nested falsy values', function (st) {
- st.equal(qs.stringify({ a: { b: { c: null } } }), 'a%5Bb%5D%5Bc%5D=');
- st.equal(qs.stringify({ a: { b: { c: null } } }, { strictNullHandling: true }), 'a%5Bb%5D%5Bc%5D');
- st.equal(qs.stringify({ a: { b: { c: false } } }), 'a%5Bb%5D%5Bc%5D=false');
- st.end();
- });
-
- t.test('stringifies a nested object', function (st) {
- st.equal(qs.stringify({ a: { b: 'c' } }), 'a%5Bb%5D=c');
- st.equal(qs.stringify({ a: { b: { c: { d: 'e' } } } }), 'a%5Bb%5D%5Bc%5D%5Bd%5D=e');
- st.end();
- });
-
- t.test('`allowDots` option: stringifies a nested object with dots notation', function (st) {
- st.equal(qs.stringify({ a: { b: 'c' } }, { allowDots: true }), 'a.b=c');
- st.equal(qs.stringify({ a: { b: { c: { d: 'e' } } } }, { allowDots: true }), 'a.b.c.d=e');
- st.end();
- });
-
- t.test('stringifies an array value', function (st) {
- st.equal(
- qs.stringify({ a: ['b', 'c', 'd'] }, { arrayFormat: 'indices' }),
- 'a%5B0%5D=b&a%5B1%5D=c&a%5B2%5D=d',
- 'indices => indices'
- );
- st.equal(
- qs.stringify({ a: ['b', 'c', 'd'] }, { arrayFormat: 'brackets' }),
- 'a%5B%5D=b&a%5B%5D=c&a%5B%5D=d',
- 'brackets => brackets'
- );
- st.equal(
- qs.stringify({ a: ['b', 'c', 'd'] }, { arrayFormat: 'comma' }),
- 'a=b%2Cc%2Cd',
- 'comma => comma'
- );
- st.equal(
- qs.stringify({ a: ['b', 'c', 'd'] }, { arrayFormat: 'comma', commaRoundTrip: true }),
- 'a=b%2Cc%2Cd',
- 'comma round trip => comma'
- );
- st.equal(
- qs.stringify({ a: ['b', 'c', 'd'] }),
- 'a%5B0%5D=b&a%5B1%5D=c&a%5B2%5D=d',
- 'default => indices'
- );
- st.end();
- });
-
- t.test('`skipNulls` option', function (st) {
- st.equal(
- qs.stringify({ a: 'b', c: null }, { skipNulls: true }),
- 'a=b',
- 'omits nulls when asked'
- );
-
- st.equal(
- qs.stringify({ a: { b: 'c', d: null } }, { skipNulls: true }),
- 'a%5Bb%5D=c',
- 'omits nested nulls when asked'
- );
-
- st.end();
- });
-
- t.test('omits array indices when asked', function (st) {
- st.equal(qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false }), 'a=b&a=c&a=d');
-
- st.end();
- });
-
- t.test('omits object key/value pair when value is empty array', function (st) {
- st.equal(qs.stringify({ a: [], b: 'zz' }), 'b=zz');
-
- st.end();
- });
-
- t.test('should not omit object key/value pair when value is empty array and when asked', function (st) {
- st.equal(qs.stringify({ a: [], b: 'zz' }), 'b=zz');
- st.equal(qs.stringify({ a: [], b: 'zz' }, { allowEmptyArrays: false }), 'b=zz');
- st.equal(qs.stringify({ a: [], b: 'zz' }, { allowEmptyArrays: true }), 'a[]&b=zz');
-
- st.end();
- });
-
- t.test('should throw when allowEmptyArrays is not of type boolean', function (st) {
- st['throws'](
- function () { qs.stringify({ a: [], b: 'zz' }, { allowEmptyArrays: 'foobar' }); },
- TypeError
- );
-
- st['throws'](
- function () { qs.stringify({ a: [], b: 'zz' }, { allowEmptyArrays: 0 }); },
- TypeError
- );
-
- st['throws'](
- function () { qs.stringify({ a: [], b: 'zz' }, { allowEmptyArrays: NaN }); },
- TypeError
- );
-
- st['throws'](
- function () { qs.stringify({ a: [], b: 'zz' }, { allowEmptyArrays: null }); },
- TypeError
- );
-
- st.end();
- });
-
- t.test('allowEmptyArrays + strictNullHandling', function (st) {
- st.equal(
- qs.stringify(
- { testEmptyArray: [] },
- { strictNullHandling: true, allowEmptyArrays: true }
- ),
- 'testEmptyArray[]'
- );
-
- st.end();
- });
-
- t.test('stringifies an array value with one item vs multiple items', function (st) {
- st.test('non-array item', function (s2t) {
- s2t.equal(qs.stringify({ a: 'c' }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a=c');
- s2t.equal(qs.stringify({ a: 'c' }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a=c');
- s2t.equal(qs.stringify({ a: 'c' }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=c');
- s2t.equal(qs.stringify({ a: 'c' }, { encodeValuesOnly: true }), 'a=c');
-
- s2t.end();
- });
-
- st.test('array with a single item', function (s2t) {
- s2t.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[0]=c');
- s2t.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[]=c');
- s2t.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=c');
- s2t.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true, arrayFormat: 'comma', commaRoundTrip: true }), 'a[]=c'); // so it parses back as an array
- s2t.equal(qs.stringify({ a: ['c'] }, { encodeValuesOnly: true }), 'a[0]=c');
-
- s2t.end();
- });
-
- st.test('array with multiple items', function (s2t) {
- s2t.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[0]=c&a[1]=d');
- s2t.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[]=c&a[]=d');
- s2t.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=c,d');
- s2t.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true, arrayFormat: 'comma', commaRoundTrip: true }), 'a=c,d');
- s2t.equal(qs.stringify({ a: ['c', 'd'] }, { encodeValuesOnly: true }), 'a[0]=c&a[1]=d');
-
- s2t.end();
- });
-
- st.test('array with multiple items with a comma inside', function (s2t) {
- s2t.equal(qs.stringify({ a: ['c,d', 'e'] }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=c%2Cd,e');
- s2t.equal(qs.stringify({ a: ['c,d', 'e'] }, { arrayFormat: 'comma' }), 'a=c%2Cd%2Ce');
-
- s2t.equal(qs.stringify({ a: ['c,d', 'e'] }, { encodeValuesOnly: true, arrayFormat: 'comma', commaRoundTrip: true }), 'a=c%2Cd,e');
- s2t.equal(qs.stringify({ a: ['c,d', 'e'] }, { arrayFormat: 'comma', commaRoundTrip: true }), 'a=c%2Cd%2Ce');
-
- s2t.end();
- });
-
- st.end();
- });
-
- t.test('stringifies a nested array value', function (st) {
- st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[b][0]=c&a[b][1]=d');
- st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[b][]=c&a[b][]=d');
- st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { encodeValuesOnly: true, arrayFormat: 'comma' }), 'a[b]=c,d');
- st.equal(qs.stringify({ a: { b: ['c', 'd'] } }, { encodeValuesOnly: true }), 'a[b][0]=c&a[b][1]=d');
- st.end();
- });
-
- t.test('stringifies comma and empty array values', function (st) {
- st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'indices' }), 'a[0]=,&a[1]=&a[2]=c,d%');
- st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'brackets' }), 'a[]=,&a[]=&a[]=c,d%');
- st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'comma' }), 'a=,,,c,d%');
- st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: false, arrayFormat: 'repeat' }), 'a=,&a=&a=c,d%');
-
- st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[0]=%2C&a[1]=&a[2]=c%2Cd%25');
- st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[]=%2C&a[]=&a[]=c%2Cd%25');
- st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=%2C,,c%2Cd%25');
- st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: true, arrayFormat: 'repeat' }), 'a=%2C&a=&a=c%2Cd%25');
-
- st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'indices' }), 'a%5B0%5D=%2C&a%5B1%5D=&a%5B2%5D=c%2Cd%25');
- st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'brackets' }), 'a%5B%5D=%2C&a%5B%5D=&a%5B%5D=c%2Cd%25');
- st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'comma' }), 'a=%2C%2C%2Cc%2Cd%25');
- st.equal(qs.stringify({ a: [',', '', 'c,d%'] }, { encode: true, encodeValuesOnly: false, arrayFormat: 'repeat' }), 'a=%2C&a=&a=c%2Cd%25');
-
- st.end();
- });
-
- t.test('stringifies comma and empty non-array values', function (st) {
- st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'indices' }), 'a=,&b=&c=c,d%');
- st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'brackets' }), 'a=,&b=&c=c,d%');
- st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'comma' }), 'a=,&b=&c=c,d%');
- st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: false, arrayFormat: 'repeat' }), 'a=,&b=&c=c,d%');
-
- st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: true, arrayFormat: 'indices' }), 'a=%2C&b=&c=c%2Cd%25');
- st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a=%2C&b=&c=c%2Cd%25');
- st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: true, arrayFormat: 'comma' }), 'a=%2C&b=&c=c%2Cd%25');
- st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: true, arrayFormat: 'repeat' }), 'a=%2C&b=&c=c%2Cd%25');
-
- st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: false, arrayFormat: 'indices' }), 'a=%2C&b=&c=c%2Cd%25');
- st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: false, arrayFormat: 'brackets' }), 'a=%2C&b=&c=c%2Cd%25');
- st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: false, arrayFormat: 'comma' }), 'a=%2C&b=&c=c%2Cd%25');
- st.equal(qs.stringify({ a: ',', b: '', c: 'c,d%' }, { encode: true, encodeValuesOnly: false, arrayFormat: 'repeat' }), 'a=%2C&b=&c=c%2Cd%25');
-
- st.end();
- });
-
- t.test('stringifies a nested array value with dots notation', function (st) {
- st.equal(
- qs.stringify(
- { a: { b: ['c', 'd'] } },
- { allowDots: true, encodeValuesOnly: true, arrayFormat: 'indices' }
- ),
- 'a.b[0]=c&a.b[1]=d',
- 'indices: stringifies with dots + indices'
- );
- st.equal(
- qs.stringify(
- { a: { b: ['c', 'd'] } },
- { allowDots: true, encodeValuesOnly: true, arrayFormat: 'brackets' }
- ),
- 'a.b[]=c&a.b[]=d',
- 'brackets: stringifies with dots + brackets'
- );
- st.equal(
- qs.stringify(
- { a: { b: ['c', 'd'] } },
- { allowDots: true, encodeValuesOnly: true, arrayFormat: 'comma' }
- ),
- 'a.b=c,d',
- 'comma: stringifies with dots + comma'
- );
- st.equal(
- qs.stringify(
- { a: { b: ['c', 'd'] } },
- { allowDots: true, encodeValuesOnly: true }
- ),
- 'a.b[0]=c&a.b[1]=d',
- 'default: stringifies with dots + indices'
- );
- st.end();
- });
-
- t.test('stringifies an object inside an array', function (st) {
- st.equal(
- qs.stringify({ a: [{ b: 'c' }] }, { arrayFormat: 'indices', encodeValuesOnly: true }),
- 'a[0][b]=c',
- 'indices => indices'
- );
- st.equal(
- qs.stringify({ a: [{ b: 'c' }] }, { arrayFormat: 'repeat', encodeValuesOnly: true }),
- 'a[b]=c',
- 'repeat => repeat'
- );
- st.equal(
- qs.stringify({ a: [{ b: 'c' }] }, { arrayFormat: 'brackets', encodeValuesOnly: true }),
- 'a[][b]=c',
- 'brackets => brackets'
- );
- st.equal(
- qs.stringify({ a: [{ b: 'c' }] }, { encodeValuesOnly: true }),
- 'a[0][b]=c',
- 'default => indices'
- );
-
- st.equal(
- qs.stringify({ a: [{ b: { c: [1] } }] }, { arrayFormat: 'indices', encodeValuesOnly: true }),
- 'a[0][b][c][0]=1',
- 'indices => indices'
- );
- st.equal(
- qs.stringify({ a: [{ b: { c: [1] } }] }, { arrayFormat: 'repeat', encodeValuesOnly: true }),
- 'a[b][c]=1',
- 'repeat => repeat'
- );
- st.equal(
- qs.stringify({ a: [{ b: { c: [1] } }] }, { arrayFormat: 'brackets', encodeValuesOnly: true }),
- 'a[][b][c][]=1',
- 'brackets => brackets'
- );
- st.equal(
- qs.stringify({ a: [{ b: { c: [1] } }] }, { encodeValuesOnly: true }),
- 'a[0][b][c][0]=1',
- 'default => indices'
- );
-
- st.end();
- });
-
- t.test('stringifies an array with mixed objects and primitives', function (st) {
- st.equal(
- qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true, arrayFormat: 'indices' }),
- 'a[0][b]=1&a[1]=2&a[2]=3',
- 'indices => indices'
- );
- st.equal(
- qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }),
- 'a[][b]=1&a[]=2&a[]=3',
- 'brackets => brackets'
- );
- st.equal(
- qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true, arrayFormat: 'comma' }),
- '???',
- 'brackets => brackets',
- { skip: 'TODO: figure out what this should do' }
- );
- st.equal(
- qs.stringify({ a: [{ b: 1 }, 2, 3] }, { encodeValuesOnly: true }),
- 'a[0][b]=1&a[1]=2&a[2]=3',
- 'default => indices'
- );
-
- st.end();
- });
-
- t.test('stringifies an object inside an array with dots notation', function (st) {
- st.equal(
- qs.stringify(
- { a: [{ b: 'c' }] },
- { allowDots: true, encode: false, arrayFormat: 'indices' }
- ),
- 'a[0].b=c',
- 'indices => indices'
- );
- st.equal(
- qs.stringify(
- { a: [{ b: 'c' }] },
- { allowDots: true, encode: false, arrayFormat: 'brackets' }
- ),
- 'a[].b=c',
- 'brackets => brackets'
- );
- st.equal(
- qs.stringify(
- { a: [{ b: 'c' }] },
- { allowDots: true, encode: false }
- ),
- 'a[0].b=c',
- 'default => indices'
- );
-
- st.equal(
- qs.stringify(
- { a: [{ b: { c: [1] } }] },
- { allowDots: true, encode: false, arrayFormat: 'indices' }
- ),
- 'a[0].b.c[0]=1',
- 'indices => indices'
- );
- st.equal(
- qs.stringify(
- { a: [{ b: { c: [1] } }] },
- { allowDots: true, encode: false, arrayFormat: 'brackets' }
- ),
- 'a[].b.c[]=1',
- 'brackets => brackets'
- );
- st.equal(
- qs.stringify(
- { a: [{ b: { c: [1] } }] },
- { allowDots: true, encode: false }
- ),
- 'a[0].b.c[0]=1',
- 'default => indices'
- );
-
- st.end();
- });
-
- t.test('does not omit object keys when indices = false', function (st) {
- st.equal(qs.stringify({ a: [{ b: 'c' }] }, { indices: false }), 'a%5Bb%5D=c');
- st.end();
- });
-
- t.test('uses indices notation for arrays when indices=true', function (st) {
- st.equal(qs.stringify({ a: ['b', 'c'] }, { indices: true }), 'a%5B0%5D=b&a%5B1%5D=c');
- st.end();
- });
-
- t.test('uses indices notation for arrays when no arrayFormat is specified', function (st) {
- st.equal(qs.stringify({ a: ['b', 'c'] }), 'a%5B0%5D=b&a%5B1%5D=c');
- st.end();
- });
-
- t.test('uses indices notation for arrays when arrayFormat=indices', function (st) {
- st.equal(qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' }), 'a%5B0%5D=b&a%5B1%5D=c');
- st.end();
- });
-
- t.test('uses repeat notation for arrays when arrayFormat=repeat', function (st) {
- st.equal(qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' }), 'a=b&a=c');
- st.end();
- });
-
- t.test('uses brackets notation for arrays when arrayFormat=brackets', function (st) {
- st.equal(qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' }), 'a%5B%5D=b&a%5B%5D=c');
- st.end();
- });
-
- t.test('stringifies a complicated object', function (st) {
- st.equal(qs.stringify({ a: { b: 'c', d: 'e' } }), 'a%5Bb%5D=c&a%5Bd%5D=e');
- st.end();
- });
-
- t.test('stringifies an empty value', function (st) {
- st.equal(qs.stringify({ a: '' }), 'a=');
- st.equal(qs.stringify({ a: null }, { strictNullHandling: true }), 'a');
-
- st.equal(qs.stringify({ a: '', b: '' }), 'a=&b=');
- st.equal(qs.stringify({ a: null, b: '' }, { strictNullHandling: true }), 'a&b=');
-
- st.equal(qs.stringify({ a: { b: '' } }), 'a%5Bb%5D=');
- st.equal(qs.stringify({ a: { b: null } }, { strictNullHandling: true }), 'a%5Bb%5D');
- st.equal(qs.stringify({ a: { b: null } }, { strictNullHandling: false }), 'a%5Bb%5D=');
-
- st.end();
- });
-
- t.test('stringifies an empty array in different arrayFormat', function (st) {
- st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false }), 'b[0]=&c=c');
- // arrayFormat default
- st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'indices' }), 'b[0]=&c=c');
- st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'brackets' }), 'b[]=&c=c');
- st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'repeat' }), 'b=&c=c');
- st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma' }), 'b=&c=c');
- st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma', commaRoundTrip: true }), 'b[]=&c=c');
- // with strictNullHandling
- st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'indices', strictNullHandling: true }), 'b[0]&c=c');
- st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'brackets', strictNullHandling: true }), 'b[]&c=c');
- st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'repeat', strictNullHandling: true }), 'b&c=c');
- st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma', strictNullHandling: true }), 'b&c=c');
- st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma', strictNullHandling: true, commaRoundTrip: true }), 'b[]&c=c');
- // with skipNulls
- st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'indices', skipNulls: true }), 'c=c');
- st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'brackets', skipNulls: true }), 'c=c');
- st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'repeat', skipNulls: true }), 'c=c');
- st.equal(qs.stringify({ a: [], b: [null], c: 'c' }, { encode: false, arrayFormat: 'comma', skipNulls: true }), 'c=c');
-
- st.end();
- });
-
- t.test('does not crash on null/undefined entries in arrayFormat=comma with encodeValuesOnly', function (st) {
- st.doesNotThrow(
- function () { qs.stringify({ a: [null, 'b'] }, { arrayFormat: 'comma', encodeValuesOnly: true }); },
- 'does not pass a raw null array entry to the encoder'
- );
- st.doesNotThrow(
- function () { qs.stringify({ a: [undefined, 'b'] }, { arrayFormat: 'comma', encodeValuesOnly: true }); },
- 'does not pass a raw undefined array entry to the encoder'
- );
- st.doesNotThrow(
- function () { qs.stringify({ a: [null] }, { arrayFormat: 'comma', encodeValuesOnly: true }); },
- 'does not crash on a single-null array'
- );
-
- st.equal(
- qs.stringify({ a: [null, 'b'] }, { arrayFormat: 'comma', encodeValuesOnly: true }),
- 'a=,b',
- 'null entry joins as empty, comma stays unencoded under encodeValuesOnly'
- );
- st.equal(
- qs.stringify({ a: [undefined, 'b'] }, { arrayFormat: 'comma', encodeValuesOnly: true }),
- 'a=,b',
- 'undefined entry joins as empty, comma stays unencoded under encodeValuesOnly'
- );
- st.equal(
- qs.stringify({ a: [null] }, { arrayFormat: 'comma', encodeValuesOnly: true }),
- 'a=',
- 'single-null array stringifies as empty value'
- );
- st.equal(
- qs.stringify({ a: [null] }, { arrayFormat: 'comma', encodeValuesOnly: true, strictNullHandling: true }),
- 'a',
- 'strictNullHandling drops the equals sign for a single-null array'
- );
- st.equal(
- qs.stringify({ a: [null] }, { arrayFormat: 'comma', encodeValuesOnly: true, skipNulls: true }),
- '',
- 'skipNulls drops a single-null array entirely'
- );
-
- st.end();
- });
-
- t.test('stringifies a null object', { skip: !hasProto }, function (st) {
- st.equal(qs.stringify({ __proto__: null, a: 'b' }), 'a=b');
- st.end();
- });
-
- t.test('returns an empty string for invalid input', function (st) {
- st.equal(qs.stringify(undefined), '');
- st.equal(qs.stringify(false), '');
- st.equal(qs.stringify(null), '');
- st.equal(qs.stringify(''), '');
- st.end();
- });
-
- t.test('stringifies an object with a null object as a child', { skip: !hasProto }, function (st) {
- st.equal(qs.stringify({ a: { __proto__: null, b: 'c' } }), 'a%5Bb%5D=c');
- st.end();
- });
-
- t.test('drops keys with a value of undefined', function (st) {
- st.equal(qs.stringify({ a: undefined }), '');
-
- st.equal(qs.stringify({ a: { b: undefined, c: null } }, { strictNullHandling: true }), 'a%5Bc%5D');
- st.equal(qs.stringify({ a: { b: undefined, c: null } }, { strictNullHandling: false }), 'a%5Bc%5D=');
- st.equal(qs.stringify({ a: { b: undefined, c: '' } }), 'a%5Bc%5D=');
- st.end();
- });
-
- t.test('url encodes values', function (st) {
- st.equal(qs.stringify({ a: 'b c' }), 'a=b%20c');
- st.end();
- });
-
- t.test('stringifies a date', function (st) {
- var now = new Date();
- var str = 'a=' + encodeURIComponent(now.toISOString());
- st.equal(qs.stringify({ a: now }), str);
- st.end();
- });
-
- t.test('stringifies the weird object from qs', function (st) {
- st.equal(qs.stringify({ 'my weird field': '~q1!2"\'w$5&7/z8)?' }), 'my%20weird%20field=~q1%212%22%27w%245%267%2Fz8%29%3F');
- st.end();
- });
-
- t.test('skips properties that are part of the object prototype', function (st) {
- st.intercept(Object.prototype, 'crash', { value: 'test' });
-
- st.equal(qs.stringify({ a: 'b' }), 'a=b');
- st.equal(qs.stringify({ a: { b: 'c' } }), 'a%5Bb%5D=c');
-
- st.end();
- });
-
- t.test('stringifies boolean values', function (st) {
- st.equal(qs.stringify({ a: true }), 'a=true');
- st.equal(qs.stringify({ a: { b: true } }), 'a%5Bb%5D=true');
- st.equal(qs.stringify({ b: false }), 'b=false');
- st.equal(qs.stringify({ b: { c: false } }), 'b%5Bc%5D=false');
- st.end();
- });
-
- t.test('stringifies buffer values', function (st) {
- st.equal(qs.stringify({ a: SaferBuffer.from('test') }), 'a=test');
- st.equal(qs.stringify({ a: { b: SaferBuffer.from('test') } }), 'a%5Bb%5D=test');
- st.end();
- });
-
- t.test('stringifies an object using an alternative delimiter', function (st) {
- st.equal(qs.stringify({ a: 'b', c: 'd' }, { delimiter: ';' }), 'a=b;c=d');
- st.end();
- });
-
- t.test('does not blow up when Buffer global is missing', function (st) {
- var restore = mockProperty(global, 'Buffer', { 'delete': true });
-
- var result = qs.stringify({ a: 'b', c: 'd' });
-
- restore();
-
- st.equal(result, 'a=b&c=d');
- st.end();
- });
-
- t.test('does not crash when parsing circular references', function (st) {
- var a = {};
- a.b = a;
-
- st['throws'](
- function () { qs.stringify({ 'foo[bar]': 'baz', 'foo[baz]': a }); },
- /RangeError: Cyclic object value/,
- 'cyclic values throw'
- );
-
- var circular = {
- a: 'value'
- };
- circular.a = circular;
- st['throws'](
- function () { qs.stringify(circular); },
- /RangeError: Cyclic object value/,
- 'cyclic values throw'
- );
-
- var arr = ['a'];
- st.doesNotThrow(
- function () { qs.stringify({ x: arr, y: arr }); },
- 'non-cyclic values do not throw'
- );
-
- st.end();
- });
-
- t.test('non-circular duplicated references can still work', function (st) {
- var hourOfDay = {
- 'function': 'hour_of_day'
- };
-
- var p1 = {
- 'function': 'gte',
- arguments: [hourOfDay, 0]
- };
- var p2 = {
- 'function': 'lte',
- arguments: [hourOfDay, 23]
- };
-
- st.equal(
- qs.stringify({ filters: { $and: [p1, p2] } }, { encodeValuesOnly: true, arrayFormat: 'indices' }),
- 'filters[$and][0][function]=gte&filters[$and][0][arguments][0][function]=hour_of_day&filters[$and][0][arguments][1]=0&filters[$and][1][function]=lte&filters[$and][1][arguments][0][function]=hour_of_day&filters[$and][1][arguments][1]=23'
- );
- st.equal(
- qs.stringify({ filters: { $and: [p1, p2] } }, { encodeValuesOnly: true, arrayFormat: 'brackets' }),
- 'filters[$and][][function]=gte&filters[$and][][arguments][][function]=hour_of_day&filters[$and][][arguments][]=0&filters[$and][][function]=lte&filters[$and][][arguments][][function]=hour_of_day&filters[$and][][arguments][]=23'
- );
- st.equal(
- qs.stringify({ filters: { $and: [p1, p2] } }, { encodeValuesOnly: true, arrayFormat: 'repeat' }),
- 'filters[$and][function]=gte&filters[$and][arguments][function]=hour_of_day&filters[$and][arguments]=0&filters[$and][function]=lte&filters[$and][arguments][function]=hour_of_day&filters[$and][arguments]=23'
- );
-
- st.end();
- });
-
- t.test('selects properties when filter=array', function (st) {
- st.equal(qs.stringify({ a: 'b' }, { filter: ['a'] }), 'a=b');
- st.equal(qs.stringify({ a: 1 }, { filter: [] }), '');
-
- st.equal(
- qs.stringify(
- { a: { b: [1, 2, 3, 4], c: 'd' }, c: 'f' },
- { filter: ['a', 'b', 0, 2], arrayFormat: 'indices' }
- ),
- 'a%5Bb%5D%5B0%5D=1&a%5Bb%5D%5B2%5D=3',
- 'indices => indices'
- );
- st.equal(
- qs.stringify(
- { a: { b: [1, 2, 3, 4], c: 'd' }, c: 'f' },
- { filter: ['a', 'b', 0, 2], arrayFormat: 'brackets' }
- ),
- 'a%5Bb%5D%5B%5D=1&a%5Bb%5D%5B%5D=3',
- 'brackets => brackets'
- );
- st.equal(
- qs.stringify(
- { a: { b: [1, 2, 3, 4], c: 'd' }, c: 'f' },
- { filter: ['a', 'b', 0, 2] }
- ),
- 'a%5Bb%5D%5B0%5D=1&a%5Bb%5D%5B2%5D=3',
- 'default => indices'
- );
-
- st.end();
- });
-
- t.test('skips null/undefined entries in filter=array', function (st) {
- st.doesNotThrow(
- function () { qs.stringify({ a: 'b', undefined: 'x' }, { filter: ['a', undefined] }); },
- 'does not pass a raw undefined filter entry to the encoder'
- );
- st.doesNotThrow(
- function () { qs.stringify({ a: 'b', 'null': 'x' }, { filter: ['a', null] }); },
- 'does not pass a raw null filter entry to the encoder'
- );
-
- st.equal(
- qs.stringify({ a: 'b', undefined: 'x', c: 'd' }, { filter: ['a', undefined, 'c'] }),
- 'a=b&c=d',
- 'undefined filter entry is skipped, remaining keys are kept'
- );
- st.equal(
- qs.stringify({ a: 'b', 'null': 'x', c: 'd' }, { filter: ['a', null, 'c'] }),
- 'a=b&c=d',
- 'null filter entry is skipped, remaining keys are kept'
- );
- st.equal(
- qs.stringify({ a: 'b', 'null': 'x' }, { filter: [null] }),
- '',
- 'filter array containing only null yields empty string'
- );
-
- st.end();
- });
-
- t.test('supports custom representations when filter=function', function (st) {
- var calls = 0;
- var obj = { a: 'b', c: 'd', e: { f: new Date(1257894000000) } };
- var filterFunc = function (prefix, value) {
- calls += 1;
- if (calls === 1) {
- st.equal(prefix, '', 'prefix is empty');
- st.equal(value, obj);
- } else if (prefix === 'c') {
- return void 0;
- } else if (value instanceof Date) {
- st.equal(prefix, 'e[f]');
- return value.getTime();
- }
- return value;
- };
-
- st.equal(qs.stringify(obj, { filter: filterFunc }), 'a=b&e%5Bf%5D=1257894000000');
- st.equal(calls, 5);
- st.end();
- });
-
- t.test('can disable uri encoding', function (st) {
- st.equal(qs.stringify({ a: 'b' }, { encode: false }), 'a=b');
- st.equal(qs.stringify({ a: { b: 'c' } }, { encode: false }), 'a[b]=c');
- st.equal(qs.stringify({ a: 'b', c: null }, { strictNullHandling: true, encode: false }), 'a=b&c');
- st.end();
- });
-
- t.test('can sort the keys', function (st) {
- var sort = function (a, b) {
- return a.localeCompare(b);
- };
- st.equal(qs.stringify({ a: 'c', z: 'y', b: 'f' }, { sort: sort }), 'a=c&b=f&z=y');
- st.equal(qs.stringify({ a: 'c', z: { j: 'a', i: 'b' }, b: 'f' }, { sort: sort }), 'a=c&b=f&z%5Bi%5D=b&z%5Bj%5D=a');
- st.end();
- });
-
- t.test('can sort the keys at depth 3 or more too', function (st) {
- var sort = function (a, b) {
- return a.localeCompare(b);
- };
- st.equal(
- qs.stringify(
- { a: 'a', z: { zj: { zjb: 'zjb', zja: 'zja' }, zi: { zib: 'zib', zia: 'zia' } }, b: 'b' },
- { sort: sort, encode: false }
- ),
- 'a=a&b=b&z[zi][zia]=zia&z[zi][zib]=zib&z[zj][zja]=zja&z[zj][zjb]=zjb'
- );
- st.equal(
- qs.stringify(
- { a: 'a', z: { zj: { zjb: 'zjb', zja: 'zja' }, zi: { zib: 'zib', zia: 'zia' } }, b: 'b' },
- { sort: null, encode: false }
- ),
- 'a=a&z[zj][zjb]=zjb&z[zj][zja]=zja&z[zi][zib]=zib&z[zi][zia]=zia&b=b'
- );
- st.end();
- });
-
- t.test('can stringify with custom encoding', function (st) {
- st.equal(qs.stringify({ 県: '大阪府', '': '' }, {
- encoder: function (str) {
- if (str.length === 0) {
- return '';
- }
- var buf = iconv.encode(str, 'shiftjis');
- var result = [];
- for (var i = 0; i < buf.length; ++i) {
- result.push(buf.readUInt8(i).toString(16));
- }
- return '%' + result.join('%');
- }
- }), '%8c%a7=%91%e5%8d%e3%95%7b&=');
- st.end();
- });
-
- t.test('receives the default encoder as a second argument', function (st) {
- st.plan(8);
-
- qs.stringify({ a: 1, b: new Date(), c: true, d: [1] }, {
- encoder: function (str) {
- st.match(typeof str, /^(?:string|number|boolean)$/);
- return '';
- }
- });
-
- st.end();
- });
-
- t.test('receives the default encoder as a second argument', function (st) {
- st.plan(2);
-
- qs.stringify({ a: 1 }, {
- encoder: function (str, defaultEncoder) {
- st.equal(defaultEncoder, utils.encode);
- }
- });
-
- st.end();
- });
-
- t.test('throws error with wrong encoder', function (st) {
- st['throws'](function () {
- qs.stringify({}, { encoder: 'string' });
- }, new TypeError('Encoder has to be a function.'));
- st.end();
- });
-
- t.test('can use custom encoder for a buffer object', { skip: typeof Buffer === 'undefined' }, function (st) {
- st.equal(qs.stringify({ a: SaferBuffer.from([1]) }, {
- encoder: function (buffer) {
- if (typeof buffer === 'string') {
- return buffer;
- }
- return String.fromCharCode(buffer.readUInt8(0) + 97);
- }
- }), 'a=b');
-
- st.equal(qs.stringify({ a: SaferBuffer.from('a b') }, {
- encoder: function (buffer) {
- return buffer;
- }
- }), 'a=a b');
- st.end();
- });
-
- t.test('serializeDate option', function (st) {
- var date = new Date();
- st.equal(
- qs.stringify({ a: date }),
- 'a=' + date.toISOString().replace(/:/g, '%3A'),
- 'default is toISOString'
- );
-
- var mutatedDate = new Date();
- mutatedDate.toISOString = function () {
- throw new SyntaxError();
- };
- st['throws'](function () {
- mutatedDate.toISOString();
- }, SyntaxError);
- st.equal(
- qs.stringify({ a: mutatedDate }),
- 'a=' + Date.prototype.toISOString.call(mutatedDate).replace(/:/g, '%3A'),
- 'toISOString works even when method is not locally present'
- );
-
- var specificDate = new Date(6);
- st.equal(
- qs.stringify(
- { a: specificDate },
- { serializeDate: function (d) { return d.getTime() * 7; } }
- ),
- 'a=42',
- 'custom serializeDate function called'
- );
-
- st.equal(
- qs.stringify(
- { a: [date] },
- {
- serializeDate: function (d) { return d.getTime(); },
- arrayFormat: 'comma'
- }
- ),
- 'a=' + date.getTime(),
- 'works with arrayFormat comma'
- );
- st.equal(
- qs.stringify(
- { a: [date] },
- {
- serializeDate: function (d) { return d.getTime(); },
- arrayFormat: 'comma',
- commaRoundTrip: true
- }
- ),
- 'a%5B%5D=' + date.getTime(),
- 'works with arrayFormat comma'
- );
-
- st.end();
- });
-
- t.test('RFC 1738 serialization', function (st) {
- st.equal(qs.stringify({ a: 'b c' }, { format: qs.formats.RFC1738 }), 'a=b+c');
- st.equal(qs.stringify({ 'a b': 'c d' }, { format: qs.formats.RFC1738 }), 'a+b=c+d');
- st.equal(qs.stringify({ 'a b': SaferBuffer.from('a b') }, { format: qs.formats.RFC1738 }), 'a+b=a+b');
-
- st.equal(qs.stringify({ 'foo(ref)': 'bar' }, { format: qs.formats.RFC1738 }), 'foo(ref)=bar');
-
- st.end();
- });
-
- t.test('RFC 3986 spaces serialization', function (st) {
- st.equal(qs.stringify({ a: 'b c' }, { format: qs.formats.RFC3986 }), 'a=b%20c');
- st.equal(qs.stringify({ 'a b': 'c d' }, { format: qs.formats.RFC3986 }), 'a%20b=c%20d');
- st.equal(qs.stringify({ 'a b': SaferBuffer.from('a b') }, { format: qs.formats.RFC3986 }), 'a%20b=a%20b');
-
- st.end();
- });
-
- t.test('Backward compatibility to RFC 3986', function (st) {
- st.equal(qs.stringify({ a: 'b c' }), 'a=b%20c');
- st.equal(qs.stringify({ 'a b': SaferBuffer.from('a b') }), 'a%20b=a%20b');
-
- st.end();
- });
-
- t.test('Edge cases and unknown formats', function (st) {
- ['UFO1234', false, 1234, null, {}, []].forEach(function (format) {
- st['throws'](
- function () {
- qs.stringify({ a: 'b c' }, { format: format });
- },
- new TypeError('Unknown format option provided.')
- );
- });
- st.end();
- });
-
- t.test('encodeValuesOnly', function (st) {
- st.equal(
- qs.stringify(
- { a: 'b', c: ['d', 'e=f'], f: [['g'], ['h']] },
- { encodeValuesOnly: true, arrayFormat: 'indices' }
- ),
- 'a=b&c[0]=d&c[1]=e%3Df&f[0][0]=g&f[1][0]=h',
- 'encodeValuesOnly + indices'
- );
- st.equal(
- qs.stringify(
- { a: 'b', c: ['d', 'e=f'], f: [['g'], ['h']] },
- { encodeValuesOnly: true, arrayFormat: 'brackets' }
- ),
- 'a=b&c[]=d&c[]=e%3Df&f[][]=g&f[][]=h',
- 'encodeValuesOnly + brackets'
- );
- st.equal(
- qs.stringify(
- { a: 'b', c: ['d', 'e=f'], f: [['g'], ['h']] },
- { encodeValuesOnly: true, arrayFormat: 'repeat' }
- ),
- 'a=b&c=d&c=e%3Df&f=g&f=h',
- 'encodeValuesOnly + repeat'
- );
-
- st.equal(
- qs.stringify(
- { a: 'b', c: ['d', 'e'], f: [['g'], ['h']] },
- { arrayFormat: 'indices' }
- ),
- 'a=b&c%5B0%5D=d&c%5B1%5D=e&f%5B0%5D%5B0%5D=g&f%5B1%5D%5B0%5D=h',
- 'no encodeValuesOnly + indices'
- );
- st.equal(
- qs.stringify(
- { a: 'b', c: ['d', 'e'], f: [['g'], ['h']] },
- { arrayFormat: 'brackets' }
- ),
- 'a=b&c%5B%5D=d&c%5B%5D=e&f%5B%5D%5B%5D=g&f%5B%5D%5B%5D=h',
- 'no encodeValuesOnly + brackets'
- );
- st.equal(
- qs.stringify(
- { a: 'b', c: ['d', 'e'], f: [['g'], ['h']] },
- { arrayFormat: 'repeat' }
- ),
- 'a=b&c=d&c=e&f=g&f=h',
- 'no encodeValuesOnly + repeat'
- );
-
- st.end();
- });
-
- t.test('encodeValuesOnly - strictNullHandling', function (st) {
- st.equal(
- qs.stringify(
- { a: { b: null } },
- { encodeValuesOnly: true, strictNullHandling: true }
- ),
- 'a[b]'
- );
- st.end();
- });
-
- t.test('strictNullHandling: applies the formatter to the encoded key (RFC1738)', function (st) {
- st.equal(
- qs.stringify(
- { 'a b': null, 'c d': 'e f' },
- { strictNullHandling: false, format: 'RFC1738' }
- ),
- 'a+b=&c+d=e+f',
- 'without: as expected'
- );
-
- st.equal(
- qs.stringify(
- { 'a b': null, 'c d': 'e f' },
- { strictNullHandling: true, format: 'RFC1738' }
- ),
- 'a+b&c+d=e+f',
- 'with: as expected'
- );
-
- st.end();
- });
-
- t.test('throws if an invalid charset is specified', function (st) {
- st['throws'](function () {
- qs.stringify({ a: 'b' }, { charset: 'foobar' });
- }, new TypeError('The charset option must be either utf-8, iso-8859-1, or undefined'));
- st.end();
- });
-
- t.test('respects a charset of iso-8859-1', function (st) {
- st.equal(qs.stringify({ æ: 'æ' }, { charset: 'iso-8859-1' }), '%E6=%E6');
- st.end();
- });
-
- t.test('encodes unrepresentable chars as numeric entities in iso-8859-1 mode', function (st) {
- st.equal(qs.stringify({ a: '☺' }, { charset: 'iso-8859-1' }), 'a=%26%239786%3B');
- st.end();
- });
-
- t.test('respects an explicit charset of utf-8 (the default)', function (st) {
- st.equal(qs.stringify({ a: 'æ' }, { charset: 'utf-8' }), 'a=%C3%A6');
- st.end();
- });
-
- t.test('`charsetSentinel` option', function (st) {
- st.equal(
- qs.stringify({ a: 'æ' }, { charsetSentinel: true, charset: 'utf-8' }),
- 'utf8=%E2%9C%93&a=%C3%A6',
- 'adds the right sentinel when instructed to and the charset is utf-8'
- );
-
- st.equal(
- qs.stringify({ a: 'æ' }, { charsetSentinel: true, charset: 'iso-8859-1' }),
- 'utf8=%26%2310003%3B&a=%E6',
- 'adds the right sentinel when instructed to and the charset is iso-8859-1'
- );
-
- st.equal(
- qs.stringify({ a: 1, b: 2 }, { charsetSentinel: true, delimiter: ';' }),
- 'utf8=%E2%9C%93;a=1;b=2',
- 'uses the configured delimiter after the sentinel'
- );
-
- st.end();
- });
-
- t.test('does not mutate the options argument', function (st) {
- var options = {};
- qs.stringify({}, options);
- st.deepEqual(options, {});
- st.end();
- });
-
- t.test('strictNullHandling works with custom filter', function (st) {
- var filter = function (prefix, value) {
- return value;
- };
-
- var options = { strictNullHandling: true, filter: filter };
- st.equal(qs.stringify({ key: null }, options), 'key');
- st.end();
- });
-
- t.test('strictNullHandling works with null serializeDate', function (st) {
- var serializeDate = function () {
- return null;
- };
- var options = { strictNullHandling: true, serializeDate: serializeDate };
- var date = new Date();
- st.equal(qs.stringify({ key: date }, options), 'key');
- st.end();
- });
-
- t.test('allows for encoding keys and values differently', function (st) {
- var encoder = function (str, defaultEncoder, charset, type) {
- if (type === 'key') {
- return defaultEncoder(str, defaultEncoder, charset, type).toLowerCase();
- }
- if (type === 'value') {
- return defaultEncoder(str, defaultEncoder, charset, type).toUpperCase();
- }
- throw 'this should never happen! type: ' + type;
- };
-
- st.deepEqual(qs.stringify({ KeY: 'vAlUe' }, { encoder: encoder }), 'key=VALUE');
-
- var noopEncoder = function () { return 'x'; };
- noopEncoder();
- st['throws'](
- function () { encoder('x', noopEncoder, 'utf-8', 'unknown'); },
- 'this should never happen! type: unknown',
- 'encoder throws for unexpected type'
- );
-
- st.end();
- });
-
- t.test('objects inside arrays', function (st) {
- var obj = { a: { b: { c: 'd', e: 'f' } } };
- var withArray = { a: { b: [{ c: 'd', e: 'f' }] } };
-
- st.equal(qs.stringify(obj, { encode: false }), 'a[b][c]=d&a[b][e]=f', 'no array, no arrayFormat');
- st.equal(qs.stringify(obj, { encode: false, arrayFormat: 'brackets' }), 'a[b][c]=d&a[b][e]=f', 'no array, bracket');
- st.equal(qs.stringify(obj, { encode: false, arrayFormat: 'indices' }), 'a[b][c]=d&a[b][e]=f', 'no array, indices');
- st.equal(qs.stringify(obj, { encode: false, arrayFormat: 'repeat' }), 'a[b][c]=d&a[b][e]=f', 'no array, repeat');
- st.equal(qs.stringify(obj, { encode: false, arrayFormat: 'comma' }), 'a[b][c]=d&a[b][e]=f', 'no array, comma');
-
- st.equal(qs.stringify(withArray, { encode: false }), 'a[b][0][c]=d&a[b][0][e]=f', 'array, no arrayFormat');
- st.equal(qs.stringify(withArray, { encode: false, arrayFormat: 'brackets' }), 'a[b][][c]=d&a[b][][e]=f', 'array, bracket');
- st.equal(qs.stringify(withArray, { encode: false, arrayFormat: 'indices' }), 'a[b][0][c]=d&a[b][0][e]=f', 'array, indices');
- st.equal(qs.stringify(withArray, { encode: false, arrayFormat: 'repeat' }), 'a[b][c]=d&a[b][e]=f', 'array, repeat');
- st.equal(
- qs.stringify(withArray, { encode: false, arrayFormat: 'comma' }),
- '???',
- 'array, comma',
- { skip: 'TODO: figure out what this should do' }
- );
-
- st.end();
- });
-
- t.test('stringifies sparse arrays', function (st) {
- /* eslint no-sparse-arrays: 0 */
- st.equal(qs.stringify({ a: [, '2', , , '1'] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[1]=2&a[4]=1');
- st.equal(qs.stringify({ a: [, '2', , , '1'] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[]=2&a[]=1');
- st.equal(qs.stringify({ a: [, '2', , , '1'] }, { encodeValuesOnly: true, arrayFormat: 'repeat' }), 'a=2&a=1');
-
- st.equal(qs.stringify({ a: [, { b: [, , { c: '1' }] }] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[1][b][2][c]=1');
- st.equal(qs.stringify({ a: [, { b: [, , { c: '1' }] }] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[][b][][c]=1');
- st.equal(qs.stringify({ a: [, { b: [, , { c: '1' }] }] }, { encodeValuesOnly: true, arrayFormat: 'repeat' }), 'a[b][c]=1');
-
- st.equal(qs.stringify({ a: [, [, , [, , , { c: '1' }]]] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[1][2][3][c]=1');
- st.equal(qs.stringify({ a: [, [, , [, , , { c: '1' }]]] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[][][][c]=1');
- st.equal(qs.stringify({ a: [, [, , [, , , { c: '1' }]]] }, { encodeValuesOnly: true, arrayFormat: 'repeat' }), 'a[c]=1');
-
- st.equal(qs.stringify({ a: [, [, , [, , , { c: [, '1'] }]]] }, { encodeValuesOnly: true, arrayFormat: 'indices' }), 'a[1][2][3][c][1]=1');
- st.equal(qs.stringify({ a: [, [, , [, , , { c: [, '1'] }]]] }, { encodeValuesOnly: true, arrayFormat: 'brackets' }), 'a[][][][c][]=1');
- st.equal(qs.stringify({ a: [, [, , [, , , { c: [, '1'] }]]] }, { encodeValuesOnly: true, arrayFormat: 'repeat' }), 'a[c]=1');
-
- st.end();
- });
-
- t.test('encodes a very long string', function (st) {
- var chars = [];
- var expected = [];
- for (var i = 0; i < 5e3; i++) {
- chars.push(' ' + i);
-
- expected.push('%20' + i);
- }
-
- var obj = {
- foo: chars.join('')
- };
-
- st.equal(
- qs.stringify(obj, { arrayFormat: 'brackets', charset: 'utf-8' }),
- 'foo=' + expected.join('')
- );
-
- st.end();
- });
-
- t.end();
-});
-
-test('stringifies empty keys', function (t) {
- emptyTestCases.forEach(function (testCase) {
- t.test('stringifies an object with empty string key with ' + testCase.input, function (st) {
- st.deepEqual(
- qs.stringify(testCase.withEmptyKeys, { encode: false, arrayFormat: 'indices' }),
- testCase.stringifyOutput.indices,
- 'test case: ' + testCase.input + ', indices'
- );
- st.deepEqual(
- qs.stringify(testCase.withEmptyKeys, { encode: false, arrayFormat: 'brackets' }),
- testCase.stringifyOutput.brackets,
- 'test case: ' + testCase.input + ', brackets'
- );
- st.deepEqual(
- qs.stringify(testCase.withEmptyKeys, { encode: false, arrayFormat: 'repeat' }),
- testCase.stringifyOutput.repeat,
- 'test case: ' + testCase.input + ', repeat'
- );
-
- st.end();
- });
- });
-
- t.test('edge case with object/arrays', function (st) {
- st.deepEqual(qs.stringify({ '': { '': [2, 3] } }, { encode: false }), '[][0]=2&[][1]=3');
- st.deepEqual(qs.stringify({ '': { '': [2, 3], a: 2 } }, { encode: false }), '[][0]=2&[][1]=3&[a]=2');
- st.deepEqual(qs.stringify({ '': { '': [2, 3] } }, { encode: false, arrayFormat: 'indices' }), '[][0]=2&[][1]=3');
- st.deepEqual(qs.stringify({ '': { '': [2, 3], a: 2 } }, { encode: false, arrayFormat: 'indices' }), '[][0]=2&[][1]=3&[a]=2');
-
- st.end();
- });
-
- t.test('stringifies non-string keys', function (st) {
- var S = Object('abc');
- S.toString = function () {
- return 'd';
- };
- var actual = qs.stringify({ a: 'b', 'false': {}, 1e+22: 'c', d: 'e' }, {
- filter: ['a', false, null, 10000000000000000000000, S],
- allowDots: true,
- encodeDotInKeys: true
- });
-
- st.equal(actual, 'a=b&1e%2B22=c&d=e', 'stringifies correctly');
-
- st.end();
- });
-
- t.test('round-trips keys containing percent-encoded bracket text', function (st) {
- var cases = [
- { 'a%5Bb': 'c' },
- { 'a%5Db': 'c' },
- { 'a%255Bb': 'c' },
- { 'a%255Db': 'c' },
- { a: { 'b%5Bc': 'd' } },
- { a: { 'b%255Bc': 'd' } },
- { 'a%5B%255Bb': 'c' }
- ];
- for (var i = 0; i < cases.length; i++) {
- st.deepEqual(
- qs.parse(qs.stringify(cases[i])),
- cases[i],
- 'round-trips ' + JSON.stringify(cases[i])
- );
- }
-
- st.end();
- });
-
- t.test('parses input containing percent-encoded bracket text without mangling', function (st) {
- st.deepEqual(qs.parse('a%25255Bb=c'), { 'a%255Bb': 'c' }, 'a%25255Bb decodes to a%255Bb, not a%5Bb');
- st.deepEqual(qs.parse('a%25255Db=c'), { 'a%255Db': 'c' }, 'a%25255Db decodes to a%255Db, not a%5Db');
- st.deepEqual(qs.parse('a%5Bb%25255Bc%5D=d'), { a: { 'b%255Bc': 'd' } }, 'nested %25255B decodes to %255B inside segment, not %5B');
-
- st.end();
- });
-});
diff --git a/node_modules/qs/test/utils.js b/node_modules/qs/test/utils.js
deleted file mode 100644
index 713b89b..0000000
--- a/node_modules/qs/test/utils.js
+++ /dev/null
@@ -1,626 +0,0 @@
-'use strict';
-
-var test = require('tape');
-var inspect = require('object-inspect');
-var SaferBuffer = require('safer-buffer').Buffer;
-var forEach = require('for-each');
-var v = require('es-value-fixtures');
-
-var utils = require('../lib/utils');
-
-test('merge()', function (t) {
- t.deepEqual(utils.merge(null, true), [null, true], 'merges true into null');
-
- t.deepEqual(utils.merge(null, [42]), [null, 42], 'merges null into an array');
-
- t.deepEqual(utils.merge({ a: 'b' }, { a: 'c' }), { a: ['b', 'c'] }, 'merges two objects with the same key');
-
- var oneMerged = utils.merge({ foo: 'bar' }, { foo: { first: '123' } });
- t.deepEqual(oneMerged, { foo: ['bar', { first: '123' }] }, 'merges a standalone and an object into an array');
-
- var twoMerged = utils.merge({ foo: ['bar', { first: '123' }] }, { foo: { second: '456' } });
- t.deepEqual(twoMerged, { foo: { 0: 'bar', 1: { first: '123' }, second: '456' } }, 'merges a standalone and two objects into an array');
-
- var sandwiched = utils.merge({ foo: ['bar', { first: '123', second: '456' }] }, { foo: 'baz' });
- t.deepEqual(sandwiched, { foo: ['bar', { first: '123', second: '456' }, 'baz'] }, 'merges an object sandwiched by two standalones into an array');
-
- var nestedArrays = utils.merge({ foo: ['baz'] }, { foo: ['bar', 'xyzzy'] });
- t.deepEqual(nestedArrays, { foo: ['baz', 'bar', 'xyzzy'] });
-
- var noOptionsNonObjectSource = utils.merge({ foo: 'baz' }, 'bar');
- t.deepEqual(noOptionsNonObjectSource, { foo: 'baz', bar: true });
-
- var func = function f() {};
- func();
- t.deepEqual(
- utils.merge(func, { foo: 'bar' }),
- [func, { foo: 'bar' }],
- 'functions can not be merged into'
- );
-
- func.bar = 'baz';
- t.deepEqual(
- utils.merge({ foo: 'bar' }, func),
- { foo: 'bar', bar: 'baz' },
- 'functions can be merge sources'
- );
-
- t.test(
- 'avoids invoking array setters unnecessarily',
- { skip: typeof Object.defineProperty !== 'function' },
- function (st) {
- var setCount = 0;
- var getCount = 0;
- var observed = [];
- Object.defineProperty(observed, 0, {
- get: function () {
- getCount += 1;
- return { bar: 'baz' };
- },
- set: function () { setCount += 1; }
- });
- utils.merge(observed, [null]);
- st.equal(setCount, 0);
- st.equal(getCount, 1);
- observed[0] = observed[0]; // eslint-disable-line no-self-assign
- st.equal(setCount, 1);
- st.equal(getCount, 2);
-
- st.end();
- }
- );
-
- t.test('with overflow objects (from arrayLimit)', function (st) {
- // arrayLimit is max index, so with limit 0, max index 0 is allowed (1 element)
- // To create overflow, need 2+ elements with limit 0, or 3+ with limit 1, etc.
- st.test('merges primitive into overflow object at next index', function (s2t) {
- // Create an overflow object via combine: 3 elements (indices 0-2) with limit 0
- var overflow = utils.combine(['a', 'b'], 'c', 0, false);
- s2t.ok(utils.isOverflow(overflow), 'overflow object is marked');
- var merged = utils.merge(overflow, 'd');
- s2t.deepEqual(merged, { 0: 'a', 1: 'b', 2: 'c', 3: 'd' }, 'adds primitive at next numeric index');
-
- s2t.end();
- });
-
- st.test('merges primitive into regular object with numeric keys normally', function (s2t) {
- var obj = { 0: 'a', 1: 'b' };
- s2t.notOk(utils.isOverflow(obj), 'plain object is not marked as overflow');
- var merged = utils.merge(obj, 'c');
- s2t.deepEqual(merged, { 0: 'a', 1: 'b', c: true }, 'adds primitive as key (not at next index)');
- s2t.end();
- });
-
- st.test('merges primitive into object with non-numeric keys normally', function (s2t) {
- var obj = { foo: 'bar' };
- var merged = utils.merge(obj, 'baz');
- s2t.deepEqual(merged, { foo: 'bar', baz: true }, 'adds primitive as key with value true');
-
- s2t.end();
- });
-
- st.test('with strictMerge, wraps object and primitive in array', function (s2t) {
- var obj = { foo: 'bar' };
- var merged = utils.merge(obj, 'baz', { strictMerge: true });
- s2t.deepEqual(merged, [{ foo: 'bar' }, 'baz'], 'wraps in array with strictMerge');
- s2t.end();
- });
-
- st.test('merges overflow object into primitive', function (s2t) {
- // Create an overflow object via combine: 2 elements (indices 0-1) with limit 0
- var overflow = utils.combine(['a'], 'b', 0, false);
- s2t.ok(utils.isOverflow(overflow), 'overflow object is marked');
- var merged = utils.merge('c', overflow);
- s2t.ok(utils.isOverflow(merged), 'result is also marked as overflow');
- s2t.deepEqual(merged, { 0: 'c', 1: 'a', 2: 'b' }, 'creates object with primitive at 0, source values shifted');
-
- s2t.end();
- });
-
- st.test('merges overflow object into primitive with plainObjects', function (s2t) {
- var overflow = utils.combine(['a'], 'b', 0, false);
- s2t.ok(utils.isOverflow(overflow), 'overflow object is marked');
- var merged = utils.merge('c', overflow, { plainObjects: true });
- s2t.ok(utils.isOverflow(merged), 'result is also marked as overflow');
- s2t.deepEqual(merged, { __proto__: null, 0: 'c', 1: 'a', 2: 'b' }, 'creates null-proto object with primitive at 0');
-
- s2t.end();
- });
-
- st.test('merges overflow object with multiple values into primitive', function (s2t) {
- // Create an overflow object via combine: 3 elements (indices 0-2) with limit 0
- var overflow = utils.combine(['b', 'c'], 'd', 0, false);
- s2t.ok(utils.isOverflow(overflow), 'overflow object is marked');
- var merged = utils.merge('a', overflow);
- s2t.deepEqual(merged, { 0: 'a', 1: 'b', 2: 'c', 3: 'd' }, 'shifts all source indices by 1');
-
- s2t.end();
- });
-
- st.test('merges regular object into primitive as array', function (s2t) {
- var obj = { foo: 'bar' };
- var merged = utils.merge('a', obj);
- s2t.deepEqual(merged, ['a', { foo: 'bar' }], 'creates array with primitive and object');
-
- s2t.end();
- });
-
- st.test('merges primitive into array that exceeds arrayLimit', function (s2t) {
- var arr = ['a', 'b', 'c'];
- var merged = utils.merge(arr, 'd', { arrayLimit: 1 });
- s2t.ok(utils.isOverflow(merged), 'result is marked as overflow');
- s2t.deepEqual(merged, { 0: 'a', 1: 'b', 2: 'c', 3: 'd' }, 'converts to overflow object with primitive appended');
-
- s2t.end();
- });
-
- st.test('merges array into primitive that exceeds arrayLimit', function (s2t) {
- var merged = utils.merge('a', ['b', 'c'], { arrayLimit: 1 });
- s2t.ok(utils.isOverflow(merged), 'result is marked as overflow');
- s2t.deepEqual(merged, { 0: 'a', 1: 'b', 2: 'c' }, 'converts to overflow object');
-
- s2t.end();
- });
-
- st.test('merges primitive into array at the arrayLimit boundary, consistently with combine', function (s2t) {
- var merged = utils.merge(['a'], 'b', { arrayLimit: 1 });
- s2t.ok(utils.isOverflow(merged), 'result is marked as overflow at the boundary');
- s2t.deepEqual(merged, { 0: 'a', 1: 'b' }, 'converts to overflow object instead of a length-2 array');
-
- s2t.end();
- });
-
- st.test('merges two arrays that exceed arrayLimit into an overflow object', function (s2t) {
- var merged = utils.merge(['a'], ['b'], { arrayLimit: 1 });
- s2t.ok(utils.isOverflow(merged), 'result is marked as overflow');
- s2t.deepEqual(merged, { 0: 'a', 1: 'b' }, 'array-into-array merge enforces arrayLimit like combine');
-
- s2t.end();
- });
-
- st.test('throws at the arrayLimit boundary when merging a primitive into an array with throwOnLimitExceeded', function (s2t) {
- s2t['throws'](
- function () { utils.merge(['a'], 'b', { arrayLimit: 1, throwOnLimitExceeded: true }); },
- new RangeError('Array limit exceeded. Only 1 element allowed in an array.'),
- 'throws when the resulting length would exceed arrayLimit'
- );
-
- s2t.end();
- });
-
- st.test('throws when merging two arrays past arrayLimit with throwOnLimitExceeded', function (s2t) {
- s2t['throws'](
- function () { utils.merge(['a'], ['b'], { arrayLimit: 1, throwOnLimitExceeded: true }); },
- new RangeError('Array limit exceeded. Only 1 element allowed in an array.'),
- 'array-into-array merge throws rather than silently exceeding arrayLimit'
- );
- s2t['throws'](
- function () { utils.merge(['a', 'b', 'c'], ['d', 'e', 'f'], { arrayLimit: 2, throwOnLimitExceeded: true }); },
- new RangeError('Array limit exceeded. Only 2 elements allowed in an array.'),
- 'uses the plural message when arrayLimit is not 1'
- );
-
- s2t.end();
- });
-
- st.test('throws instead of merging primitive into over-limit array when throwOnLimitExceeded is set', function (s2t) {
- s2t['throws'](
- function () { utils.merge(['a', 'b', 'c'], 'd', { arrayLimit: 1, throwOnLimitExceeded: true }); },
- new RangeError('Array limit exceeded. Only 1 element allowed in an array.'),
- 'throws rather than converting to an overflow object'
- );
- s2t['throws'](
- function () { utils.merge(['a', 'b', 'c'], 'd', { arrayLimit: 2, throwOnLimitExceeded: true }); },
- new RangeError('Array limit exceeded. Only 2 elements allowed in an array.'),
- 'uses the plural message when arrayLimit is not 1'
- );
-
- s2t.end();
- });
-
- st.test('throws instead of merging array into primitive when throwOnLimitExceeded is set', function (s2t) {
- s2t['throws'](
- function () { utils.merge('a', ['b', 'c'], { arrayLimit: 1, throwOnLimitExceeded: true }); },
- new RangeError('Array limit exceeded. Only 1 element allowed in an array.'),
- 'throws rather than converting to an overflow object'
- );
- s2t['throws'](
- function () { utils.merge('a', ['b', 'c', 'd'], { arrayLimit: 2, throwOnLimitExceeded: true }); },
- new RangeError('Array limit exceeded. Only 2 elements allowed in an array.'),
- 'uses the plural message when arrayLimit is not 1'
- );
-
- s2t.end();
- });
-
- st.end();
- });
-
- t.end();
-});
-
-test('assign()', function (t) {
- var target = { a: 1, b: 2 };
- var source = { b: 3, c: 4 };
- var result = utils.assign(target, source);
-
- t.equal(result, target, 'returns the target');
- t.deepEqual(target, { a: 1, b: 3, c: 4 }, 'target and source are merged');
- t.deepEqual(source, { b: 3, c: 4 }, 'source is untouched');
-
- t.end();
-});
-
-test('combine()', function (t) {
- t.test('both arrays', function (st) {
- var a = [1];
- var b = [2];
- var combined = utils.combine(a, b);
-
- st.deepEqual(a, [1], 'a is not mutated');
- st.deepEqual(b, [2], 'b is not mutated');
- st.notEqual(a, combined, 'a !== combined');
- st.notEqual(b, combined, 'b !== combined');
- st.deepEqual(combined, [1, 2], 'combined is a + b');
-
- st.end();
- });
-
- t.test('one array, one non-array', function (st) {
- var aN = 1;
- var a = [aN];
- var bN = 2;
- var b = [bN];
-
- var combinedAnB = utils.combine(aN, b);
- st.deepEqual(b, [bN], 'b is not mutated');
- st.notEqual(aN, combinedAnB, 'aN + b !== aN');
- st.notEqual(a, combinedAnB, 'aN + b !== a');
- st.notEqual(bN, combinedAnB, 'aN + b !== bN');
- st.notEqual(b, combinedAnB, 'aN + b !== b');
- st.deepEqual([1, 2], combinedAnB, 'first argument is array-wrapped when not an array');
-
- var combinedABn = utils.combine(a, bN);
- st.deepEqual(a, [aN], 'a is not mutated');
- st.notEqual(aN, combinedABn, 'a + bN !== aN');
- st.notEqual(a, combinedABn, 'a + bN !== a');
- st.notEqual(bN, combinedABn, 'a + bN !== bN');
- st.notEqual(b, combinedABn, 'a + bN !== b');
- st.deepEqual([1, 2], combinedABn, 'second argument is array-wrapped when not an array');
-
- st.end();
- });
-
- t.test('neither is an array', function (st) {
- var combined = utils.combine(1, 2);
- st.notEqual(1, combined, '1 + 2 !== 1');
- st.notEqual(2, combined, '1 + 2 !== 2');
- st.deepEqual([1, 2], combined, 'both arguments are array-wrapped when not an array');
-
- st.end();
- });
-
- t.test('with arrayLimit', function (st) {
- st.test('under the limit', function (s2t) {
- var combined = utils.combine(['a', 'b'], 'c', 10, false);
- s2t.deepEqual(combined, ['a', 'b', 'c'], 'returns array when under limit');
- s2t.ok(Array.isArray(combined), 'result is an array');
- s2t.end();
- });
-
- st.test('exactly at the limit stays as array', function (s2t) {
- var combined = utils.combine(['a', 'b'], 'c', 3, false);
- s2t.deepEqual(combined, ['a', 'b', 'c'], 'stays as array when count equals limit');
- s2t.ok(Array.isArray(combined), 'result is an array');
- s2t.end();
- });
-
- st.test('over the limit', function (s2t) {
- var combined = utils.combine(['a', 'b', 'c'], 'd', 3, false);
- s2t.deepEqual(combined, { 0: 'a', 1: 'b', 2: 'c', 3: 'd' }, 'converts to object when over limit');
- s2t.notOk(Array.isArray(combined), 'result is not an array');
- s2t.end();
- });
-
- st.test('with arrayLimit 1', function (s2t) {
- var combined = utils.combine([], 'a', 1, false);
- s2t.deepEqual(combined, ['a'], 'stays as array when count equals limit');
- s2t.ok(Array.isArray(combined), 'result is an array');
- s2t.end();
- });
-
- st.test('with arrayLimit 0 converts single element to object', function (s2t) {
- var combined = utils.combine([], 'a', 0, false);
- s2t.deepEqual(combined, { 0: 'a' }, 'converts to object when count exceeds limit');
- s2t.notOk(Array.isArray(combined), 'result is not an array');
- s2t.end();
- });
-
- st.test('with arrayLimit 0 and two elements converts to object', function (s2t) {
- var combined = utils.combine(['a'], 'b', 0, false);
- s2t.deepEqual(combined, { 0: 'a', 1: 'b' }, 'converts to object when count exceeds limit');
- s2t.notOk(Array.isArray(combined), 'result is not an array');
- s2t.end();
- });
-
- st.test('with plainObjects option', function (s2t) {
- var combined = utils.combine(['a', 'b'], 'c', 1, true);
- var expected = { __proto__: null, 0: 'a', 1: 'b', 2: 'c' };
- s2t.deepEqual(combined, expected, 'converts to object with null prototype');
- s2t.equal(Object.getPrototypeOf(combined), null, 'result has null prototype when plainObjects is true');
- s2t.end();
- });
-
- st.end();
- });
-
- t.test('with throwOnLimitExceeded', function (st) {
- st.test('throws when concatenation exceeds the limit', function (s2t) {
- s2t['throws'](
- function () { utils.combine(['a', 'b', 'c'], 'd', 3, false, true); },
- new RangeError('Array limit exceeded. Only 3 elements allowed in an array.'),
- 'throws instead of converting to an overflow object'
- );
- s2t['throws'](
- function () { utils.combine([], 'a', 0, false, true); },
- new RangeError('Array limit exceeded. Only 0 elements allowed in an array.'),
- 'throws with the correct count at arrayLimit 0'
- );
- s2t.end();
- });
-
- st.test('throws when adding to an existing overflow object', function (s2t) {
- var overflow = utils.combine(['a', 'b'], 'c', 0, false);
- s2t.ok(utils.isOverflow(overflow), 'initial object is marked as overflow');
-
- s2t['throws'](
- function () { utils.combine(overflow, 'd', 0, false, true); },
- new RangeError('Array limit exceeded. Only 0 elements allowed in an array.'),
- 'throws rather than appending to the overflow object'
- );
- s2t['throws'](
- function () { utils.combine(overflow, 'd', 1, false, true); },
- new RangeError('Array limit exceeded. Only 1 element allowed in an array.'),
- 'uses the singular message at arrayLimit 1'
- );
- s2t.end();
- });
-
- st.test('does not throw when within the limit', function (s2t) {
- var combined = utils.combine(['a'], 'b', 5, false, true);
- s2t.deepEqual(combined, ['a', 'b'], 'returns the array unchanged when under the limit');
- s2t.end();
- });
-
- st.end();
- });
-
- t.test('with existing overflow object', function (st) {
- st.test('adds to existing overflow object at next index', function (s2t) {
- // Create overflow object first via combine: 3 elements (indices 0-2) with limit 0
- var overflow = utils.combine(['a', 'b'], 'c', 0, false);
- s2t.ok(utils.isOverflow(overflow), 'initial object is marked as overflow');
-
- var combined = utils.combine(overflow, 'd', 10, false);
- s2t.equal(combined, overflow, 'returns the same object (mutated)');
- s2t.deepEqual(combined, { 0: 'a', 1: 'b', 2: 'c', 3: 'd' }, 'adds value at next numeric index');
- s2t.end();
- });
-
- st.test('does not treat plain object with numeric keys as overflow', function (s2t) {
- var plainObj = { 0: 'a', 1: 'b' };
- s2t.notOk(utils.isOverflow(plainObj), 'plain object is not marked as overflow');
-
- // combine treats this as a regular value, not an overflow object to append to
- var combined = utils.combine(plainObj, 'c', 10, false);
- s2t.deepEqual(combined, [{ 0: 'a', 1: 'b' }, 'c'], 'concatenates as regular values');
- s2t.end();
- });
-
- st.end();
- });
-
- t.end();
-});
-
-test('decode', function (t) {
- t.equal(
- utils.decode('a+b'),
- 'a b',
- 'decodes + to space'
- );
-
- t.equal(
- utils.decode('name%2Eobj'),
- 'name.obj',
- 'decodes a string'
- );
- t.equal(
- utils.decode('name%2Eobj%2Efoo', null, 'iso-8859-1'),
- 'name.obj.foo',
- 'decodes a string in iso-8859-1'
- );
-
- t.end();
-});
-
-test('encode', function (t) {
- forEach(v.nullPrimitives, function (nullish) {
- t['throws'](
- function () { utils.encode(nullish); },
- TypeError,
- inspect(nullish) + ' is not a string'
- );
- });
-
- t.equal(utils.encode(''), '', 'empty string returns itself');
- t.deepEqual(utils.encode([]), [], 'empty array returns itself');
- t.deepEqual(utils.encode({ length: 0 }), { length: 0 }, 'empty arraylike returns itself');
-
- t.test('symbols', { skip: !v.hasSymbols }, function (st) {
- st.equal(utils.encode(Symbol('x')), 'Symbol%28x%29', 'symbol is encoded');
-
- st.end();
- });
-
- t.equal(
- utils.encode('(abc)'),
- '%28abc%29',
- 'encodes parentheses'
- );
- t.equal(
- utils.encode({ toString: function () { return '(abc)'; } }),
- '%28abc%29',
- 'toStrings and encodes parentheses'
- );
-
- t.equal(
- utils.encode('abc 123 💩', null, 'iso-8859-1'),
- 'abc%20123%20%26%2355357%3B%26%2356489%3B',
- 'encodes in iso-8859-1'
- );
-
- var longString = '';
- var expectedString = '';
- for (var i = 0; i < 1500; i++) {
- longString += ' ';
- expectedString += '%20';
- }
-
- t.equal(
- utils.encode(longString),
- expectedString,
- 'encodes a long string'
- );
-
- var boundary = '';
- var expected = '';
- for (var j = 0; j < 1023; j++) {
- boundary += 'a';
- expected += 'a';
- }
- boundary += '😀';
- expected += '%F0%9F%98%80';
-
- t.equal(
- utils.encode(boundary),
- expected,
- 'encodes a surrogate pair split across long-string chunks'
- );
-
- var laterBoundary = '';
- var laterExpected = '';
- for (var k = 0; k < 2047; k++) {
- laterBoundary += 'a';
- laterExpected += 'a';
- }
- laterBoundary += '😀';
- laterExpected += '%F0%9F%98%80';
-
- t.equal(
- utils.encode(laterBoundary),
- laterExpected,
- 'encodes a surrogate pair split across a later chunk boundary'
- );
-
- var twoPairs = '';
- for (k = 0; k < 1023; k++) {
- twoPairs += 'a';
- }
- twoPairs += '😀';
- for (k = 0; k < 1022; k++) {
- twoPairs += 'b';
- }
- twoPairs += '😀';
-
- t.equal(
- (utils.encode(twoPairs).match(/%F0%9F%98%80/g) || []).length,
- 2,
- 'encodes two surrogate pairs each split across a chunk boundary'
- );
-
- var roundTrip = '';
- for (k = 0; k < 1023; k++) {
- roundTrip += 'a';
- }
- roundTrip += '😀';
-
- t.equal(
- decodeURIComponent(utils.encode(roundTrip)),
- roundTrip,
- 'a boundary-split surrogate pair round-trips through decodeURIComponent'
- );
-
- var loneBoundary = '';
- var loneExpected = '';
- for (k = 0; k < 1023; k++) {
- loneBoundary += 'a';
- loneExpected += 'a';
- }
- loneBoundary += '\uD83DX';
- loneExpected += '%F0%9F%91%98';
-
- t.equal(
- utils.encode(loneBoundary),
- loneExpected,
- 'a lone high surrogate at a chunk boundary encodes the same as mid-chunk'
- );
-
- t.equal(
- utils.encode('\x28\x29'),
- '%28%29',
- 'encodes parens normally'
- );
- t.equal(
- utils.encode('\x28\x29', null, null, null, 'RFC1738'),
- '()',
- 'does not encode parens in RFC1738'
- );
-
- // todo RFC1738 format
-
- t.equal(
- utils.encode('Āက豈'),
- '%C4%80%E1%80%80%EF%A4%80',
- 'encodes multibyte chars'
- );
-
- t.equal(
- utils.encode('\uD83D \uDCA9'),
- '%F0%9F%90%A0%F0%BA%90%80',
- 'encodes lone surrogates'
- );
-
- t.end();
-});
-
-test('isBuffer()', function (t) {
- var fn = function () {};
- fn();
- forEach([null, undefined, true, false, '', 'abc', 42, 0, NaN, {}, [], fn, /a/g], function (x) {
- t.equal(utils.isBuffer(x), false, inspect(x) + ' is not a buffer');
- });
-
- var fakeBuffer = { constructor: Buffer };
- t.equal(utils.isBuffer(fakeBuffer), false, 'fake buffer is not a buffer');
-
- var saferBuffer = SaferBuffer.from('abc');
- t.equal(utils.isBuffer(saferBuffer), true, 'SaferBuffer instance is a buffer');
-
- var buffer = SaferBuffer.from('abc');
- t.notEqual(saferBuffer, buffer, 'different buffer instances');
- t.equal(utils.isBuffer(buffer), true, 'another Buffer instance is a buffer');
- t.end();
-});
-
-test('isRegExp()', function (t) {
- t.equal(utils.isRegExp(/a/g), true, 'RegExp is a RegExp');
- t.equal(utils.isRegExp(new RegExp('a', 'g')), true, 'new RegExp is a RegExp');
- t.equal(utils.isRegExp(new Date()), false, 'Date is not a RegExp');
-
- forEach(v.primitives, function (primitive) {
- t.equal(utils.isRegExp(primitive), false, inspect(primitive) + ' is not a RegExp');
- });
-
- t.end();
-});