@sap/cds-dk 10.2.0 → 10.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/bin/bind.js +5 -4
  3. package/bin/completion/scripts/cds.fish +4 -3
  4. package/bin/completion/scripts/cds.ps1 +4 -4
  5. package/bin/completion/scripts/cds.sh +4 -4
  6. package/bin/completion/scripts/cds.zsh +4 -4
  7. package/bin/debug.js +3 -3
  8. package/bin/deploy/index.js +2 -2
  9. package/bin/deploy/to-hana/hana.js +1 -1
  10. package/bin/deploy/to-hana/hdiDeployUtil.js +25 -14
  11. package/bin/up.js +3 -3
  12. package/bin/version.js +1 -1
  13. package/bin/watch/vite-watch.js +12 -6
  14. package/lib/bind/shared.js +1 -1
  15. package/lib/init/index.js +1 -0
  16. package/lib/init/projectReader.js +3 -2
  17. package/lib/init/template/approuter/files/values.yaml.hbs +0 -9
  18. package/lib/init/template/approuter/files/xs-app.json.hbs +0 -22
  19. package/lib/init/template/approuter/index.js +8 -9
  20. package/lib/init/template/html5-repo/index.js +12 -0
  21. package/lib/init/template/react/files/vite.config.{{extension}}.hbs +2 -3
  22. package/lib/init/template/react/index.js +1 -3
  23. package/lib/init/template/sample/files/app/index.html.hbs +18 -0
  24. package/lib/init/template/sample/index.js +1 -0
  25. package/lib/init/template/vue/files/vite.config.{{extension}}.hbs +2 -3
  26. package/lib/init/template/vue/index.js +1 -3
  27. package/lib/mtx/push.js +7 -1
  28. package/node_modules/@cap-js/asyncapi/README.md +4 -14
  29. package/node_modules/@cap-js/asyncapi/cds-plugin.js +12 -0
  30. package/node_modules/@cap-js/asyncapi/index.js +3 -2
  31. package/node_modules/@cap-js/asyncapi/lib/compile/components/messages/index.js +4 -2
  32. package/node_modules/@cap-js/asyncapi/lib/compile/components/schemas/definition.js +11 -1
  33. package/node_modules/@cap-js/asyncapi/lib/compile/components/schemas/utils.js +16 -0
  34. package/node_modules/@cap-js/asyncapi/lib/compile/utils.js +4 -3
  35. package/node_modules/@cap-js/asyncapi/lib/import/importAsyncAPI.js +34 -0
  36. package/node_modules/@cap-js/asyncapi/lib/import/index.js +18 -0
  37. package/node_modules/@cap-js/asyncapi/lib/import/message.js +9 -0
  38. package/node_modules/@cap-js/asyncapi/lib/import/parserContext.js +368 -0
  39. package/node_modules/@cap-js/asyncapi/lib/import/utils.js +85 -0
  40. package/node_modules/@cap-js/asyncapi/package.json +89 -1
  41. package/node_modules/@sap/cds/CHANGELOG.md +10 -0
  42. package/node_modules/@sap/cds/app/index.js +1 -1
  43. package/node_modules/@sap/cds/lib/env/schemas/cds-package.js +0 -2
  44. package/node_modules/@sap/cds/lib/env/schemas/cds-rc.js +3 -3
  45. package/node_modules/@sap/cds/lib/env/schemas/index.js +4 -4
  46. package/node_modules/@sap/cds/lib/utils/cds-utils.js +21 -8
  47. package/node_modules/@sap/cds/libx/_runtime/messaging/common-utils/connections.js +45 -39
  48. package/node_modules/@sap/cds/libx/odata/ODataAdapter.js +1 -1
  49. package/node_modules/@sap/cds/libx/queue/TaskRunner.js +22 -5
  50. package/node_modules/@sap/cds/package.json +1 -1
  51. package/node_modules/@sap/cds-mtxs/CHANGELOG.md +8 -0
  52. package/node_modules/@sap/cds-mtxs/package.json +1 -1
  53. package/node_modules/@sap/cds-mtxs/srv/extensibility-service.js +57 -41
  54. package/node_modules/@sap/cds-mtxs/srv/jobs-service.js +27 -12
  55. package/node_modules/@sap/cds-mtxs/srv/plugins/hana.js +31 -25
  56. package/node_modules/body-parser/README.md +17 -13
  57. package/node_modules/body-parser/lib/read.js +74 -57
  58. package/node_modules/body-parser/lib/types/json.js +11 -11
  59. package/node_modules/body-parser/lib/types/urlencoded.js +5 -5
  60. package/node_modules/body-parser/lib/utils.js +0 -15
  61. package/node_modules/body-parser/package.json +7 -12
  62. package/node_modules/encodeurl/README.md +14 -0
  63. package/node_modules/encodeurl/index.js +5 -10
  64. package/node_modules/encodeurl/package.json +10 -6
  65. package/node_modules/on-finished/index.js +14 -2
  66. package/node_modules/on-finished/package.json +11 -7
  67. package/node_modules/qs/.editorconfig +1 -1
  68. package/node_modules/qs/CHANGELOG.md +87 -22
  69. package/node_modules/qs/README.md +63 -10
  70. package/node_modules/qs/dist/qs.js +17 -17
  71. package/node_modules/qs/eslint.config.mjs +61 -50
  72. package/node_modules/qs/lib/formats.js +7 -2
  73. package/node_modules/qs/lib/parse.js +29 -10
  74. package/node_modules/qs/lib/stringify.js +5 -3
  75. package/node_modules/qs/lib/utils.js +28 -9
  76. package/node_modules/qs/package.json +6 -6
  77. package/node_modules/qs/test/parse.js +335 -2
  78. package/node_modules/qs/test/stringify.js +222 -0
  79. package/node_modules/qs/test/utils.js +61 -3
  80. package/node_modules/semver/classes/range.js +2 -2
  81. package/node_modules/semver/internal/constants.js +30 -0
  82. package/node_modules/semver/internal/trim-comparator-whitespace.js +438 -0
  83. package/node_modules/semver/package.json +1 -1
  84. package/node_modules/ws/README.md +21 -29
  85. package/node_modules/ws/lib/buffer-util.js +13 -2
  86. package/node_modules/ws/lib/sender.js +4 -1
  87. package/node_modules/ws/lib/websocket.js +8 -3
  88. package/node_modules/ws/package.json +1 -1
  89. package/package.json +1 -1
  90. package/node_modules/on-finished/HISTORY.md +0 -98
@@ -65,10 +65,11 @@ function onFinished (msg, listener) {
65
65
 
66
66
  function isFinished (msg) {
67
67
  var socket = msg.socket
68
+ var finished = writableEnded(msg)
68
69
 
69
- if (typeof msg.finished === 'boolean') {
70
+ if (typeof finished === 'boolean') {
70
71
  // OutgoingMessage
71
- return Boolean(msg.finished || (socket && !socket.writable))
72
+ return Boolean(finished || (socket && !socket.writable))
72
73
  }
73
74
 
74
75
  if (typeof msg.complete === 'boolean') {
@@ -232,3 +233,14 @@ function wrap (fn) {
232
233
  // return bound function
233
234
  return res.runInAsyncScope.bind(res, fn, null)
234
235
  }
236
+
237
+ /**
238
+ * Determines if a writable stream has finished.
239
+ *
240
+ * @param {Object} res
241
+ * @returns {boolean}
242
+ * @private
243
+ */
244
+ function writableEnded (res) {
245
+ return typeof res.writableEnded === 'boolean' ? res.writableEnded : res.finished
246
+ }
@@ -1,38 +1,42 @@
1
1
  {
2
2
  "name": "on-finished",
3
3
  "description": "Execute a callback when a request closes, finishes, or errors",
4
- "version": "2.4.1",
4
+ "version": "2.4.2",
5
5
  "contributors": [
6
6
  "Douglas Christopher Wilson <doug@somethingdoug.com>",
7
7
  "Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)"
8
8
  ],
9
9
  "license": "MIT",
10
10
  "repository": "jshttp/on-finished",
11
+ "funding": {
12
+ "type": "opencollective",
13
+ "url": "https://opencollective.com/express"
14
+ },
15
+ "type": "commonjs",
11
16
  "dependencies": {
12
17
  "ee-first": "1.1.1"
13
18
  },
14
19
  "devDependencies": {
15
- "eslint": "7.32.0",
20
+ "eslint": "8.17.0",
16
21
  "eslint-config-standard": "14.1.1",
17
- "eslint-plugin-import": "2.25.4",
22
+ "eslint-plugin-import": "2.26.0",
18
23
  "eslint-plugin-markdown": "2.2.1",
19
24
  "eslint-plugin-node": "11.1.0",
20
- "eslint-plugin-promise": "5.2.0",
25
+ "eslint-plugin-promise": "6.0.0",
21
26
  "eslint-plugin-standard": "4.1.0",
22
- "mocha": "9.2.1",
27
+ "mocha": "12.0.3",
23
28
  "nyc": "15.1.0"
24
29
  },
25
30
  "engines": {
26
31
  "node": ">= 0.8"
27
32
  },
28
33
  "files": [
29
- "HISTORY.md",
30
34
  "LICENSE",
31
35
  "index.js"
32
36
  ],
33
37
  "scripts": {
34
38
  "lint": "eslint .",
35
- "test": "mocha --reporter spec --bail --check-leaks test/",
39
+ "test": "mocha --reporter spec --check-leaks test/",
36
40
  "test-ci": "nyc --reporter=lcovonly --reporter=text npm test",
37
41
  "test-cov": "nyc --reporter=html --reporter=text npm test"
38
42
  }
@@ -39,7 +39,7 @@ indent_style = off
39
39
  indent = off
40
40
  max_line_length = off
41
41
 
42
- [.nycrc]
42
+ [{.nycrc,*.mjs}]
43
43
  indent_style = tab
44
44
 
45
45
  [tea.yaml]
@@ -1,26 +1,64 @@
1
+ ## **6.17.1**
2
+ - [Fix] `parse`: `interpretNumericEntities`: decode code points above U+FFFF as surrogate pairs (#640)
3
+ - [Fix] `parse`: respect `plainObjects` for `[]` with `parseArrays: false` (#639)
4
+ - [Fix] `utils`: `merge`: count the elements of a sparse array against `arrayLimit`, not its holes
5
+ - [Fix] `parse`: guard bracket-wrapped prototype keys at depth 0 (#638)
6
+ - [Refactor] `parse`: extract wrapping-bracket stripping helper
7
+ - [readme] document that `depth: 0` and `depth: false` keep keys flat
8
+ - [Tests] `parse`: pin depth-0 bracket stripping and prototype keys kept by `allowPrototypes`/`plainObjects`
9
+
10
+ ## **6.17.0**
11
+ - [New] `stringify`: add `WHATWG` format (#623)
12
+ - [Fix] `stringify`: do not sort the caller's `filter` array in place (#637)
13
+ - [Fix] `parse`: copy an own `__proto__` key as data (#636)
14
+ - [Fix] `parse`: decode percent-encoded dots case-insensitively (#635)
15
+ - [Fix] `stringify`: encode keys when `allowEmptyArrays` is set (#561)
16
+ - [Fix] `parse`: preserve comma arrays when interpreting numeric entities (#630)
17
+ - [Fix] `parse`: allow scalar fields with a zero array limit (#627)
18
+ - [Fix] `parse`: do not count an existing comma array toward `arrayLimit` when `duplicates` discards or replaces it
19
+ - [Fix] `utils`: `encode`: encode lone surrogates as U+FFFD instead of consuming the next code unit (#624)
20
+ - [eslint] fix indentation
21
+ - [readme] document the encoder's `format` argument
22
+ - [meta] add changelog acknowledgement
23
+ - [meta] fix changelog indents
24
+ - [Dev Deps] update `eslint`, `evalmd`, `npmignore`
25
+ - [Tests] `stringify`: pin `allowEmptyArrays` output for keys that need no encoding
26
+ - [Tests] `stringify`: pin `sort` order for nested keys selected by an array `filter`
27
+ - [Tests] `parse`: cover `interpretNumericEntities` across value shapes, keys, and the charset sentinel
28
+ - [Tests] `parse`: cover more input that builds no array at a zero or negative `arrayLimit`
29
+ - [Tests] `parse`: cover `comma` with a zero or negative `arrayLimit`, and combining a full comma array
30
+ - [Tests] `parse`: pin the behavior of a zero or negative `arrayLimit`
31
+ - [Tests] `utils`/`stringify`: pin `~`, `*`, and parens encoding in RFC3986 and RFC1738
32
+
33
+ ## **6.16.2**
34
+ - [Fix] `stringify`: encode keys when `allowEmptyArrays` is set (#561)
35
+ - [meta] use double quotes for better OS support
36
+ - [Dev Deps] update `evalmd`, `npmignore`
37
+ - [Tests] `stringify`: pin `allowEmptyArrays` output for keys that need no encoding
38
+
1
39
  ## **6.16.1**
2
- - [Fix] `parse`: do not mutate an object input
3
- - [Fix] `stringify`: stop re-encoding structural separator dots when `encodeDotInKeys` is set (#564)
4
- - [Fix] `stringify`: `arrayFormat: 'comma'`: pass the full encoder arguments with `encodeValuesOnly`
5
- - [Fix] `utils`: encode `+` as `%2B` in iso-8859-1 mode so values round-trip (#565)
6
- - [Fix] parse: only convert top-level dots to brackets when allowDots is on (#621)
7
- - [Fix] `stringify`: ignore inherited array format names (#622)
8
- - [Fix] `stringify`: `arrayFormat: 'comma'`: do not throw on elements with no callable `toString`
9
- - [Fix] `utils`: `merge`: seed an overflow container's index from its own keys, not just the source
10
- - [Fix] `utils`: `merge`: keep a `strictMerge` conflict container's index and `arrayLimit` correct
11
- - [Fix] `parse`: only treat `[]` as array syntax when it ends the key
12
- - [Perf] `decode`: skip decoders when there is no percent sign (#583)
13
- - [Robustness] `utils`: `merge`: apply `arrayLimit` to the two-element array built for colliding values
14
- - [Robustness] `parse`: bound the nesting added by repeated `strictMerge` conflicts
15
- - [Docs] document that `qs` and flat parsers disagree about parameter names
16
- - [Docs] clarify that `throwOnLimitExceeded` limits each array, not the total number of values
17
- - [Docs] clarify 6.14.1/6.15.2 parse bracket behavior change (#567, #568)
18
- - [meta] fix changelog indents
19
- - [actions] set least-privilege `cache-mode`
20
- - [Tests] `utils`: `decode`: add missing cases
21
- - [Tests] `parse`: characterize the `]=` split when an `=` precedes any bracket group (#620)
22
- - [Tests] `parse`: `allowDots`: cover stray close brackets before a dot
23
- - [Dev Deps] update `@ljharb/eslint-config`, `eslint`, `tape`
40
+ - [Fix] `parse`: do not mutate an object input
41
+ - [Fix] `stringify`: stop re-encoding structural separator dots when `encodeDotInKeys` is set (#564)
42
+ - [Fix] `stringify`: `arrayFormat: 'comma'`: pass the full encoder arguments with `encodeValuesOnly`
43
+ - [Fix] `utils`: encode `+` as `%2B` in iso-8859-1 mode so values round-trip (#565)
44
+ - [Fix] parse: only convert top-level dots to brackets when allowDots is on (#621)
45
+ - [Fix] `stringify`: ignore inherited array format names (#622)
46
+ - [Fix] `stringify`: `arrayFormat: 'comma'`: do not throw on elements with no callable `toString`
47
+ - [Fix] `utils`: `merge`: seed an overflow container's index from its own keys, not just the source
48
+ - [Fix] `utils`: `merge`: keep a `strictMerge` conflict container's index and `arrayLimit` correct
49
+ - [Fix] `parse`: only treat `[]` as array syntax when it ends the key
50
+ - [Perf] `decode`: skip decoders when there is no percent sign (#583)
51
+ - [Robustness] `utils`: `merge`: apply `arrayLimit` to the two-element array built for colliding values
52
+ - [Robustness] `parse`: bound the nesting added by repeated `strictMerge` conflicts (credit @Yeaseen)
53
+ - [Docs] document that `qs` and flat parsers disagree about parameter names
54
+ - [Docs] clarify that `throwOnLimitExceeded` limits each array, not the total number of values
55
+ - [Docs] clarify 6.14.1/6.15.2 parse bracket behavior change (#567, #568)
56
+ - [meta] fix changelog indents
57
+ - [actions] set least-privilege `cache-mode`
58
+ - [Tests] `utils`: `decode`: add missing cases
59
+ - [Tests] `parse`: characterize the `]=` split when an `=` precedes any bracket group (#620)
60
+ - [Tests] `parse`: `allowDots`: cover stray close brackets before a dot
61
+ - [Dev Deps] update `@ljharb/eslint-config`, `eslint`, `tape`
24
62
 
25
63
  ## **6.16.0**
26
64
  - [New] `stringify`: add a `depth` option to bound recursion depth (default `Infinity`)
@@ -37,6 +75,12 @@
37
75
  - [Dev Deps] update `@ljharb/eslint-config`, `eslint`
38
76
  - [Dev Deps] update `eslint`, `evalmd`
39
77
 
78
+ ## **6.15.4**
79
+ - [Fix] `stringify`: encode keys when `allowEmptyArrays` is set (#561)
80
+ - [meta] use double quotes for better OS support
81
+ - [Dev Deps] update `@ljharb/eslint-config`, `evalmd`, `npmignore`, `tape`
82
+ - [Tests] `stringify`: pin `allowEmptyArrays` output for keys that need no encoding
83
+
40
84
  ## **6.15.3**
41
85
  - [Fix] `parse`: enforce `throwOnLimitExceeded` for cumulative array growth via `combine`/`merge`
42
86
  - [Fix] `utils`: respect encoding of surrogate pairs across chunks (#559)
@@ -68,6 +112,13 @@
68
112
  - [New] `parse`: add `strictMerge` option to wrap object/primitive conflicts in an array (#425, #122)
69
113
  - [Fix] `duplicates` option should not apply to bracket notation keys (#514)
70
114
 
115
+ ## **6.14.3**
116
+ - [Fix] `stringify`: encode keys when `allowEmptyArrays` is set (#561)
117
+ - [meta] use double quotes for better OS support
118
+ - [Deps] update `side-channel`
119
+ - [Dev Deps] update `@ljharb/eslint-config`, `es-value-fixtures`, `eslint`, `evalmd`, `mock-property`, `npmignore`, `tape`
120
+ - [Tests] `stringify`: pin `allowEmptyArrays` output for keys that need no encoding
121
+
71
122
  ## **6.14.2**
72
123
  - [Fix] `parse`: mark overflow objects for indexed notation exceeding `arrayLimit` (#546)
73
124
  - [Fix] `arrayLimit` means max count, not max index, in `combine`/`merge`/`parseArrayValue`
@@ -100,6 +151,13 @@
100
151
  - [Dev Deps] update `es-value-fixtures`, `has-bigints`, `has-proto`, `has-symbols`
101
152
  - [Tests] increase coverage
102
153
 
154
+ ## **6.13.4**
155
+ - [Fix] `stringify`: encode keys when `allowEmptyArrays` is set (#561)
156
+ - [meta] use double quotes for better OS support
157
+ - [Deps] update `side-channel`
158
+ - [Dev Deps] update `@ljharb/eslint-config`, `es-value-fixtures`, `eslint`, `evalmd`, `for-each`, `has-symbols`, `mock-property`, `npmignore`, `object-inspect`, `tape`
159
+ - [Tests] `stringify`: pin `allowEmptyArrays` output for keys that need no encoding
160
+
103
161
  ## **6.13.3**
104
162
  [Fix] fix regressions from robustness refactor
105
163
  [actions] update reusable workflows
@@ -127,6 +185,13 @@
127
185
  - [New] `parse`: add `strictDepth` option (#511)
128
186
  - [Tests] use `npm audit` instead of `aud`
129
187
 
188
+ ## **6.12.6**
189
+ - [Fix] `stringify`: encode keys when `allowEmptyArrays` is set (#561)
190
+ - [meta] use `npm audit` instead of `aud`
191
+ - [Deps] update `side-channel`
192
+ - [Dev Deps] update `@ljharb/eslint-config`, `es-value-fixtures`, `eslint`, `evalmd`, `for-each`, `has-symbols`, `mock-property`, `npmignore`, `object-inspect`, `tape`
193
+ - [Tests] `stringify`: pin `allowEmptyArrays` output for keys that need no encoding
194
+
130
195
  ## **6.12.5**
131
196
  - [Fix] fix regressions from robustness refactor
132
197
  - [actions] update reusable workflows
@@ -85,7 +85,9 @@ assert.deepEqual(qs.parse('foo[bar][baz]=foobarbaz'), {
85
85
  });
86
86
  ```
87
87
 
88
- Since v6.14.1 and v6.15.2, `parse` interprets nested bracket groups more consistently. Query strings with unbalanced `[`/`]` can produce different results than in 6.15.1; see [#558](https://github.com/ljharb/qs/issues/558).
88
+ Since v6.14.1 and v6.15.2, `parse` interprets nested bracket groups more consistently.
89
+ Query strings with unbalanced `[`/`]` can produce different results than in 6.15.1;
90
+ see [#558](https://github.com/ljharb/qs/issues/558).
89
91
 
90
92
  Because of that bracket grammar,
91
93
  **qs** does not agree with `URLSearchParams`,
@@ -132,6 +134,15 @@ var deep = qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1 });
132
134
  assert.deepEqual(deep, { a: { b: { '[c][d][e][f][g][h][i]': 'j' } } });
133
135
  ```
134
136
 
137
+ Setting `depth` to `0` or `false` turns off nesting,
138
+ so keys are never split into nested objects or arrays,
139
+ whether or not their brackets are percent-encoded:
140
+
141
+ ```javascript
142
+ assert.deepEqual(qs.parse('a[b][c]=d', { depth: 0 }), { 'a[b][c]': 'd' });
143
+ assert.deepEqual(qs.parse('a%5Bb%5D=c', { depth: false }), { 'a[b]': 'c' });
144
+ ```
145
+
135
146
  You can configure **qs** to throw an error when parsing nested input beyond this depth using the `strictDepth` option (defaulted to false):
136
147
 
137
148
  ```javascript
@@ -143,16 +154,22 @@ try {
143
154
  }
144
155
  ```
145
156
 
146
- 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.
157
+ The depth limit helps mitigate abuse when **qs** is used to parse user input,
158
+ and it is recommended to keep it a reasonably small number.
159
+ The strictDepth option adds a layer of protection by throwing an error when the limit is exceeded,
160
+ allowing you to catch and handle such cases.
147
161
 
148
- For similar reasons, by default **qs** will only parse up to 1000 parameters. This can be overridden by passing a `parameterLimit` option:
162
+ For similar reasons, by default **qs** will only parse up to 1000 parameters.
163
+ This can be overridden by passing a `parameterLimit` option:
149
164
 
150
165
  ```javascript
151
166
  var limited = qs.parse('a=b&c=d', { parameterLimit: 1 });
152
167
  assert.deepEqual(limited, { a: 'b' });
153
168
  ```
154
169
 
155
- If you want an error to be thrown whenever 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.
170
+ If you want an error to be thrown whenever a limit is exceeded (eg, `parameterLimit`, `arrayLimit`),
171
+ set the `throwOnLimitExceeded` option to `true`.
172
+ This option will generate a descriptive error if the query string exceeds a configured limit.
156
173
  ```javascript
157
174
  try {
158
175
  qs.parse('a=1&b=2&c=3&d=4', { parameterLimit: 3, throwOnLimitExceeded: true });
@@ -164,7 +181,10 @@ try {
164
181
 
165
182
  When `throwOnLimitExceeded` is set to `false` (default), **qs** will parse up to the specified `parameterLimit` and ignore the rest without throwing an error.
166
183
 
167
- Note that `parameterLimit` only bounds the number of `&`-delimited parameters; it does not limit how many values a single parameter expands into. In particular, when `comma: true` is enabled, a single parameter's value is split on commas into arbitrarily many elements, which `parameterLimit` does not constrain. Setting `throwOnLimitExceeded: true` (see `arrayLimit` below) makes **qs** reject a query string with more than `parameterLimit` parameters, one that uses an array index of `arrayLimit` or greater, or one that would produce any array longer than `arrayLimit`, including an array produced by comma splitting. `arrayLimit` applies to each array separately, including each parameter's comma-split value, so the total number of values across all parameters can still reach `parameterLimit` times `arrayLimit`, which is 20,000 at the default limits; always bound the input size at the transport layer as well (e.g. an HTTP body-size limit).
184
+ Note that `parameterLimit` only bounds the number of `&`-delimited parameters; it does not limit how many values a single parameter expands into.
185
+ In particular, when `comma: true` is enabled, a single parameter's value is split on commas into arbitrarily many elements, which `parameterLimit` does not constrain.
186
+ Setting `throwOnLimitExceeded: true` (see `arrayLimit` below) makes **qs** reject a query string with more than `parameterLimit` parameters, one that uses an array index of `arrayLimit` or greater, or one that would produce any array longer than `arrayLimit`, including an array produced by comma splitting.
187
+ `arrayLimit` applies to each array separately, including each parameter's comma-split value, so the total number of values across all parameters can still reach `parameterLimit` times `arrayLimit`, which is 20,000 at the default limits; always bound the input size at the transport layer as well (e.g. an HTTP body-size limit).
168
188
 
169
189
  To bypass the leading question mark, use `ignoreQueryPrefix`:
170
190
 
@@ -324,7 +344,8 @@ var withArrayLimit = qs.parse('a[1]=b', { arrayLimit: 0 });
324
344
  assert.deepEqual(withArrayLimit, { a: { '1': 'b' } });
325
345
  ```
326
346
 
327
- 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.
347
+ If you want to throw an error whenever the array limit is exceeded, set the `throwOnLimitExceeded` option to `true`.
348
+ This option will generate a descriptive error if the query string exceeds a configured limit.
328
349
  ```javascript
329
350
  try {
330
351
  qs.parse('a[1]=b', { arrayLimit: 0, throwOnLimitExceeded: true });
@@ -336,7 +357,11 @@ try {
336
357
 
337
358
  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.
338
359
 
339
- Note that `arrayLimit` is a *representation* threshold that controls when a numerically-indexed collection switches from an array to an object; it is **not** a hard cap on the total number of elements parsed. With the default `throwOnLimitExceeded: false`, exceeding `arrayLimit` never rejects or truncates input; it only changes the container type, and the resulting object still holds every element (so its size stays proportional to the input). This conversion is itself a safeguard: it avoids allocating a huge sparse array for input like `a[999999999]`. If you need a hard limit that rejects oversized arrays in untrusted query strings, set `throwOnLimitExceeded: true`. `throwOnLimitExceeded` still limits each array separately, not the total: with `comma: true`, each comma-separated group under `a[]=` counts as one element of the outer array, and can itself hold up to `arrayLimit` elements.
360
+ Note that `arrayLimit` is a *representation* threshold that controls when a numerically-indexed collection switches from an array to an object; it is **not** a hard cap on the total number of elements parsed.
361
+ With the default `throwOnLimitExceeded: false`, exceeding `arrayLimit` never rejects or truncates input; it only changes the container type, and the resulting object still holds every element (so its size stays proportional to the input).
362
+ This conversion is itself a safeguard: it avoids allocating a huge sparse array for input like `a[999999999]`.
363
+ If you need a hard limit that rejects oversized arrays in untrusted query strings, set `throwOnLimitExceeded: true`.
364
+ `throwOnLimitExceeded` still limits each array separately, not the total: with `comma: true`, each comma-separated group under `a[]=` counts as one element of the outer array, and can itself hold up to `arrayLimit` elements.
340
365
 
341
366
  To prevent array syntax (`a[]`, `a[0]`) from being parsed as arrays, set `parseArrays` to `false`.
342
367
  Note that duplicate keys (e.g. `a=b&a=c`) may still produce arrays when `duplicates` is `'combine'` (the default).
@@ -408,7 +433,8 @@ If you wish to auto-convert values which look like numbers, booleans, and other
408
433
  qs.stringify(object, [options]);
409
434
  ```
410
435
 
411
- When stringifying, **qs** by default URI encodes output. Objects are stringified as you would expect:
436
+ When stringifying, **qs** by default URI encodes output.
437
+ Objects are stringified as you would expect:
412
438
 
413
439
  ```javascript
414
440
  assert.equal(qs.stringify({ a: 'b' }), 'a=b');
@@ -477,6 +503,20 @@ var encoded = qs.stringify({ a: { b: 'c' } }, { encoder: function (str, defaultE
477
503
  }})
478
504
  ```
479
505
 
506
+ The encoder also receives the `format` option as a fifth argument.
507
+ An encoder that wraps `defaultEncoder` should pass all of its arguments through,
508
+ since the default encoding depends on `format` (for example, RFC1738 leaves parentheses unencoded):
509
+
510
+ ```javascript
511
+ var wrapped = qs.stringify({ a: 'b(c)' }, {
512
+ format: 'RFC1738',
513
+ encoder: function (str, defaultEncoder, charset, type, format) {
514
+ return defaultEncoder(str, defaultEncoder, charset, type, format);
515
+ }
516
+ });
517
+ assert.equal(wrapped, 'a=b(c)');
518
+ ```
519
+
480
520
  The type argument is also provided to the decoder:
481
521
 
482
522
  ```javascript
@@ -690,7 +730,8 @@ var equalsInsensitive = qs.parse('a&b=');
690
730
  assert.deepEqual(equalsInsensitive, { a: '', b: '' });
691
731
  ```
692
732
 
693
- To distinguish between `null` values and empty strings use the `strictNullHandling` flag. In the result string the `null`
733
+ To distinguish between `null` values and empty strings use the `strictNullHandling` flag.
734
+ In the result string the `null`
694
735
  values have no `=` sign:
695
736
 
696
737
  ```javascript
@@ -758,7 +799,8 @@ var obj = qs.parse('a=%82%B1%82%F1%82%C9%82%BF%82%CD%81I', { decoder: decoder })
758
799
  assert.deepEqual(obj, { a: 'こんにちは!' });
759
800
  ```
760
801
 
761
- ### RFC 3986 and RFC 1738 space encoding
802
+ <a name="rfc-3986-and-rfc-1738-space-encoding"></a>
803
+ ### Encoding formats: RFC 3986, RFC 1738, and WHATWG
762
804
 
763
805
  RFC3986 used as default option and encodes ' ' to *%20* which is backward compatible.
764
806
  In the same time, output can be stringified as per RFC1738 with ' ' equal to '+'.
@@ -769,6 +811,17 @@ assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC3986' }), 'a=b%20c');
769
811
  assert.equal(qs.stringify({ a: 'b c' }, { format : 'RFC1738' }), 'a=b+c');
770
812
  ```
771
813
 
814
+ To percent-encode keys and values the same way as the [WHATWG `application/x-www-form-urlencoded` serializer](https://url.spec.whatwg.org/#concept-urlencoded-serializer) (what `URLSearchParams` and HTML form submission use), use the `WHATWG` format.
815
+ Like RFC1738 it encodes ' ' as '+'; it also leaves `*` unencoded, but percent-encodes `~`, `(`, and `)`.
816
+ It only affects encoding; how `null`, dates, arrays, and objects are serialized is unchanged:
817
+
818
+ ```javascript
819
+ assert.equal(qs.stringify({ a: 'b c~*()' }, { format: 'WHATWG' }), 'a=b+c%7E*%28%29');
820
+ ```
821
+
822
+ _(Note: the `WHATWG` format matches `URLSearchParams` encoding only with the default `utf-8` charset, and only when keys are encoded too, so not with `encodeValuesOnly`.
823
+ With `charset: 'iso-8859-1'`, every format uses the same `escape`-based encoding, which leaves characters like `@` and `/` unencoded; only the space handling differs)_
824
+
772
825
  ## Security
773
826
 
774
827
  Please email [@ljharb](https://github.com/ljharb) or see https://tidelift.com/security if you have a potential security vulnerability to report.