query-string 6.14.0 → 7.1.0

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 (4) hide show
  1. package/index.d.ts +78 -4
  2. package/index.js +84 -6
  3. package/package.json +1 -1
  4. package/readme.md +126 -2
package/index.d.ts CHANGED
@@ -45,6 +45,39 @@ export interface ParseOptions {
45
45
  //=> {foo: ['1', '2', '3']}
46
46
  ```
47
47
 
48
+ - `bracket-separator`: Parse arrays (that are explicitly marked with brackets) with elements separated by a custom character:
49
+
50
+ ```
51
+ import queryString = require('query-string');
52
+
53
+ queryString.parse('foo[]', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
54
+ //=> {foo: []}
55
+
56
+ queryString.parse('foo[]=', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
57
+ //=> {foo: ['']}
58
+
59
+ queryString.parse('foo[]=1', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
60
+ //=> {foo: ['1']}
61
+
62
+ queryString.parse('foo[]=1|2|3', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
63
+ //=> {foo: ['1', '2', '3']}
64
+
65
+ queryString.parse('foo[]=1||3|||6', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
66
+ //=> {foo: ['1', '', 3, '', '', '6']}
67
+
68
+ queryString.parse('foo[]=1|2|3&bar=fluffy&baz[]=4', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
69
+ //=> {foo: ['1', '2', '3'], bar: 'fluffy', baz:['4']}
70
+ ```
71
+
72
+ - `colon-list-separator`: Parse arrays with parameter names that are explicitly marked with `:list`:
73
+
74
+ ```
75
+ import queryString = require('query-string');
76
+
77
+ queryString.parse('foo:list=one&foo:list=two', {arrayFormat: 'colon-list-separator'});
78
+ //=> {foo: ['one', 'two']}
79
+ ```
80
+
48
81
  - `none`: Parse arrays with elements using duplicate keys:
49
82
 
50
83
  ```
@@ -54,7 +87,7 @@ export interface ParseOptions {
54
87
  //=> {foo: ['1', '2', '3']}
55
88
  ```
56
89
  */
57
- readonly arrayFormat?: 'bracket' | 'index' | 'comma' | 'separator' | 'none';
90
+ readonly arrayFormat?: 'bracket' | 'index' | 'comma' | 'separator' | 'bracket-separator' | 'colon-list-separator' | 'none';
58
91
 
59
92
  /**
60
93
  The character used to separate array elements when using `{arrayFormat: 'separator'}`.
@@ -229,9 +262,14 @@ export interface StringifyOptions {
229
262
 
230
263
  queryString.stringify({foo: [1, 2, 3]}, {arrayFormat: 'comma'});
231
264
  //=> 'foo=1,2,3'
265
+
266
+ queryString.stringify({foo: [1, null, '']}, {arrayFormat: 'comma'});
267
+ //=> 'foo=1,,'
268
+ // Note that typing information for null values is lost
269
+ // and `.parse('foo=1,,')` would return `{foo: [1, '', '']}`.
232
270
  ```
233
271
 
234
- - `separator`: Serialize arrays by separating elements with character:
272
+ - `separator`: Serialize arrays by separating elements with character:
235
273
 
236
274
  ```
237
275
  import queryString = require('query-string');
@@ -240,6 +278,42 @@ export interface StringifyOptions {
240
278
  //=> 'foo=1|2|3'
241
279
  ```
242
280
 
281
+ - `bracket-separator`: Serialize arrays by explicitly post-fixing array names with brackets and separating elements with a custom character:
282
+
283
+ ```
284
+ import queryString = require('query-string');
285
+
286
+ queryString.stringify({foo: []}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
287
+ //=> 'foo[]'
288
+
289
+ queryString.stringify({foo: ['']}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
290
+ //=> 'foo[]='
291
+
292
+ queryString.stringify({foo: [1]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
293
+ //=> 'foo[]=1'
294
+
295
+ queryString.stringify({foo: [1, 2, 3]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
296
+ //=> 'foo[]=1|2|3'
297
+
298
+ queryString.stringify({foo: [1, '', 3, null, null, 6]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
299
+ //=> 'foo[]=1||3|||6'
300
+
301
+ queryString.stringify({foo: [1, '', 3, null, null, 6]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|', skipNull: true});
302
+ //=> 'foo[]=1||3|6'
303
+
304
+ queryString.stringify({foo: [1, 2, 3], bar: 'fluffy', baz: [4]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
305
+ //=> 'foo[]=1|2|3&bar=fluffy&baz[]=4'
306
+ ```
307
+
308
+ - `colon-list-separator`: Serialize arrays with parameter names that are explicitly marked with `:list`:
309
+
310
+ ```js
311
+ import queryString = require('query-string');
312
+
313
+ queryString.stringify({foo: ['one', 'two']}, {arrayFormat: 'colon-list-separator'});
314
+ //=> 'foo:list=one&foo:list=two'
315
+ ```
316
+
243
317
  - `none`: Serialize arrays by using duplicate keys:
244
318
 
245
319
  ```
@@ -249,7 +323,7 @@ export interface StringifyOptions {
249
323
  //=> 'foo=1&foo=2&foo=3'
250
324
  ```
251
325
  */
252
- readonly arrayFormat?: 'bracket' | 'index' | 'comma' | 'separator' | 'none';
326
+ readonly arrayFormat?: 'bracket' | 'index' | 'comma' | 'separator' | 'bracket-separator' | 'colon-list-separator' | 'none';
253
327
 
254
328
  /**
255
329
  The character used to separate array elements when using `{arrayFormat: 'separator'}`.
@@ -372,7 +446,7 @@ export interface UrlObject {
372
446
  /**
373
447
  Overrides queries in the `url` property.
374
448
  */
375
- readonly query: StringifiableRecord;
449
+ readonly query?: StringifiableRecord;
376
450
 
377
451
  /**
378
452
  Overrides the fragment identifier in the `url` property.
package/index.js CHANGED
@@ -6,6 +6,8 @@ const filterObject = require('filter-obj');
6
6
 
7
7
  const isNullOrUndefined = value => value === null || value === undefined;
8
8
 
9
+ const encodeFragmentIdentifier = Symbol('encodeFragmentIdentifier');
10
+
9
11
  function encoderForArrayFormat(options) {
10
12
  switch (options.arrayFormat) {
11
13
  case 'index':
@@ -47,19 +49,49 @@ function encoderForArrayFormat(options) {
47
49
  return [...result, [encode(key, options), '[]=', encode(value, options)].join('')];
48
50
  };
49
51
 
52
+ case 'colon-list-separator':
53
+ return key => (result, value) => {
54
+ if (
55
+ value === undefined ||
56
+ (options.skipNull && value === null) ||
57
+ (options.skipEmptyString && value === '')
58
+ ) {
59
+ return result;
60
+ }
61
+
62
+ if (value === null) {
63
+ return [...result, [encode(key, options), ':list='].join('')];
64
+ }
65
+
66
+ return [...result, [encode(key, options), ':list=', encode(value, options)].join('')];
67
+ };
68
+
50
69
  case 'comma':
51
70
  case 'separator':
71
+ case 'bracket-separator': {
72
+ const keyValueSep = options.arrayFormat === 'bracket-separator' ?
73
+ '[]=' :
74
+ '=';
75
+
52
76
  return key => (result, value) => {
53
- if (value === null || value === undefined || value.length === 0) {
77
+ if (
78
+ value === undefined ||
79
+ (options.skipNull && value === null) ||
80
+ (options.skipEmptyString && value === '')
81
+ ) {
54
82
  return result;
55
83
  }
56
84
 
85
+ // Translate null to an empty string so that it doesn't serialize as 'null'
86
+ value = value === null ? '' : value;
87
+
57
88
  if (result.length === 0) {
58
- return [[encode(key, options), '=', encode(value, options)].join('')];
89
+ return [[encode(key, options), keyValueSep, encode(value, options)].join('')];
59
90
  }
60
91
 
61
92
  return [[result, encode(value, options)].join(options.arrayFormatSeparator)];
62
93
  };
94
+ }
63
95
 
64
96
  default:
65
97
  return key => (result, value) => {
@@ -120,6 +152,24 @@ function parserForArrayFormat(options) {
120
152
  accumulator[key] = [].concat(accumulator[key], value);
121
153
  };
122
154
 
155
+ case 'colon-list-separator':
156
+ return (key, value, accumulator) => {
157
+ result = /(:list)$/.exec(key);
158
+ key = key.replace(/:list$/, '');
159
+
160
+ if (!result) {
161
+ accumulator[key] = value;
162
+ return;
163
+ }
164
+
165
+ if (accumulator[key] === undefined) {
166
+ accumulator[key] = [value];
167
+ return;
168
+ }
169
+
170
+ accumulator[key] = [].concat(accumulator[key], value);
171
+ };
172
+
123
173
  case 'comma':
124
174
  case 'separator':
125
175
  return (key, value, accumulator) => {
@@ -130,6 +180,28 @@ function parserForArrayFormat(options) {
130
180
  accumulator[key] = newValue;
131
181
  };
132
182
 
183
+ case 'bracket-separator':
184
+ return (key, value, accumulator) => {
185
+ const isArray = /(\[\])$/.test(key);
186
+ key = key.replace(/\[\]$/, '');
187
+
188
+ if (!isArray) {
189
+ accumulator[key] = value ? decode(value, options) : value;
190
+ return;
191
+ }
192
+
193
+ const arrayValue = value === null ?
194
+ [] :
195
+ value.split(options.arrayFormatSeparator).map(item => decode(item, options));
196
+
197
+ if (accumulator[key] === undefined) {
198
+ accumulator[key] = arrayValue;
199
+ return;
200
+ }
201
+
202
+ accumulator[key] = [].concat(accumulator[key], arrayValue);
203
+ };
204
+
133
205
  default:
134
206
  return (key, value, accumulator) => {
135
207
  if (accumulator[key] === undefined) {
@@ -253,7 +325,7 @@ function parse(query, options) {
253
325
 
254
326
  // Missing `=` should be `null`:
255
327
  // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
256
- value = value === undefined ? null : ['comma', 'separator'].includes(options.arrayFormat) ? value : decode(value, options);
328
+ value = value === undefined ? null : ['comma', 'separator', 'bracket-separator'].includes(options.arrayFormat) ? value : decode(value, options);
257
329
  formatter(decode(key, options), value, ret);
258
330
  }
259
331
 
@@ -335,6 +407,10 @@ exports.stringify = (object, options) => {
335
407
  }
336
408
 
337
409
  if (Array.isArray(value)) {
410
+ if (value.length === 0 && options.arrayFormat === 'bracket-separator') {
411
+ return encode(key, options) + '[]';
412
+ }
413
+
338
414
  return value
339
415
  .reduce(formatter(key), [])
340
416
  .join('&');
@@ -363,7 +439,8 @@ exports.parseUrl = (url, options) => {
363
439
  exports.stringifyUrl = (object, options) => {
364
440
  options = Object.assign({
365
441
  encode: true,
366
- strict: true
442
+ strict: true,
443
+ [encodeFragmentIdentifier]: true
367
444
  }, options);
368
445
 
369
446
  const url = removeHash(object.url).split('?')[0] || '';
@@ -378,7 +455,7 @@ exports.stringifyUrl = (object, options) => {
378
455
 
379
456
  let hash = getHash(object.url);
380
457
  if (object.fragmentIdentifier) {
381
- hash = `#${encode(object.fragmentIdentifier, options)}`;
458
+ hash = `#${options[encodeFragmentIdentifier] ? encode(object.fragmentIdentifier, options) : object.fragmentIdentifier}`;
382
459
  }
383
460
 
384
461
  return `${url}${queryString}${hash}`;
@@ -386,7 +463,8 @@ exports.stringifyUrl = (object, options) => {
386
463
 
387
464
  exports.pick = (input, filter, options) => {
388
465
  options = Object.assign({
389
- parseFragmentIdentifier: true
466
+ parseFragmentIdentifier: true,
467
+ [encodeFragmentIdentifier]: false
390
468
  }, options);
391
469
 
392
470
  const {url, query, fragmentIdentifier} = exports.parseUrl(input, options);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "query-string",
3
- "version": "6.14.0",
3
+ "version": "7.1.0",
4
4
  "description": "Parse and stringify URL query strings",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/query-string",
package/readme.md CHANGED
@@ -17,7 +17,40 @@
17
17
  <br>
18
18
  <br>
19
19
  <a href="https://standardresume.co/tech">
20
- <img src="https://sindresorhus.com/assets/thanks/standard-resume-logo.svg" width="200"/>
20
+ <img src="https://sindresorhus.com/assets/thanks/standard-resume-logo.svg" width="180"/>
21
+ </a>
22
+ <br>
23
+ <br>
24
+ <br>
25
+ <a href="https://doppler.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=query-string&utm_source=github">
26
+ <div>
27
+ <img src="https://dashboard.doppler.com/imgs/logo-long.svg" width="240" alt="Doppler">
28
+ </div>
29
+ <b>All your environment variables, in one place</b>
30
+ <div>
31
+ <span>Stop struggling with scattered API keys, hacking together home-brewed tools,</span>
32
+ <br>
33
+ <span>and avoiding access controls. Keep your team and servers in sync with Doppler.</span>
34
+ </div>
35
+ </a>
36
+ <br>
37
+ <a href="https://strapi.io/?ref=sindresorhus">
38
+ <div>
39
+ <img src="https://sindresorhus.com/assets/thanks/strapi-logo-white-bg.png" width="200" alt="Strapi">
40
+ </div>
41
+ <b>Strapi is the leading open-source headless CMS.</b>
42
+ <div>
43
+ <sup>It’s 100% JavaScript, fully customizable, and developer-first.</sup>
44
+ </div>
45
+ </a>
46
+ <br>
47
+ <a href="https://oss.capital">
48
+ <div>
49
+ <img src="https://sindresorhus.com/assets/thanks/oss-capital-logo-white-bg.svg" width="300" alt="OSS Capital">
50
+ </div>
51
+ <div>
52
+ <sup><b>Founded in 2018, OSS Capital is the first and only venture capital platform focused<br>exclusively on supporting early-stage COSS (commercial open source) startup founders.</b></sup>
53
+ </div>
21
54
  </a>
22
55
  </p>
23
56
  </div>
@@ -32,7 +65,9 @@
32
65
  $ npm install query-string
33
66
  ```
34
67
 
35
- This module targets Node.js 6 or later and the latest version of Chrome, Firefox, and Safari. If you want support for older browsers, or, if your project is using create-react-app v1, use version 5: `npm install query-string@5`.
68
+ **Not `npm install querystring`!!!!!**
69
+
70
+ This module targets Node.js 6 or later and the latest version of Chrome, Firefox, and Safari.
36
71
 
37
72
  ## Usage
38
73
 
@@ -125,6 +160,39 @@ queryString.parse('foo=1|2|3', {arrayFormat: 'separator', arrayFormatSeparator:
125
160
  //=> {foo: ['1', '2', '3']}
126
161
  ```
127
162
 
163
+ - `'bracket-separator'`: Parse arrays (that are explicitly marked with brackets) with elements separated by a custom character:
164
+
165
+ ```js
166
+ const queryString = require('query-string');
167
+
168
+ queryString.parse('foo[]', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
169
+ //=> {foo: []}
170
+
171
+ queryString.parse('foo[]=', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
172
+ //=> {foo: ['']}
173
+
174
+ queryString.parse('foo[]=1', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
175
+ //=> {foo: ['1']}
176
+
177
+ queryString.parse('foo[]=1|2|3', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
178
+ //=> {foo: ['1', '2', '3']}
179
+
180
+ queryString.parse('foo[]=1||3|||6', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
181
+ //=> {foo: ['1', '', 3, '', '', '6']}
182
+
183
+ queryString.parse('foo[]=1|2|3&bar=fluffy&baz[]=4', {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
184
+ //=> {foo: ['1', '2', '3'], bar: 'fluffy', baz:['4']}
185
+ ```
186
+
187
+ - `'colon-list-separator'`: Parse arrays with parameter names that are explicitly marked with `:list`:
188
+
189
+ ```js
190
+ const queryString = require('query-string');
191
+
192
+ queryString.parse('foo:list=one&foo:list=two', {arrayFormat: 'colon-list-separator'});
193
+ //=> {foo: ['one', 'two']}
194
+ ```
195
+
128
196
  - `'none'`: Parse arrays with elements using duplicate keys:
129
197
 
130
198
  ```js
@@ -228,6 +296,56 @@ const queryString = require('query-string');
228
296
 
229
297
  queryString.stringify({foo: [1, 2, 3]}, {arrayFormat: 'comma'});
230
298
  //=> 'foo=1,2,3'
299
+
300
+ queryString.stringify({foo: [1, null, '']}, {arrayFormat: 'comma'});
301
+ //=> 'foo=1,,'
302
+ // Note that typing information for null values is lost
303
+ // and `.parse('foo=1,,')` would return `{foo: [1, '', '']}`.
304
+ ```
305
+
306
+ - `'separator'`: Serialize arrays by separating elements with a custom character:
307
+
308
+ ```js
309
+ const queryString = require('query-string');
310
+
311
+ queryString.stringify({foo: [1, 2, 3]}, {arrayFormat: 'separator', arrayFormatSeparator: '|'});
312
+ //=> 'foo=1|2|3'
313
+ ```
314
+
315
+ - `'bracket-separator'`: Serialize arrays by explicitly post-fixing array names with brackets and separating elements with a custom character:
316
+
317
+ ```js
318
+ const queryString = require('query-string');
319
+
320
+ queryString.stringify({foo: []}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
321
+ //=> 'foo[]'
322
+
323
+ queryString.stringify({foo: ['']}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
324
+ //=> 'foo[]='
325
+
326
+ queryString.stringify({foo: [1]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
327
+ //=> 'foo[]=1'
328
+
329
+ queryString.stringify({foo: [1, 2, 3]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
330
+ //=> 'foo[]=1|2|3'
331
+
332
+ queryString.stringify({foo: [1, '', 3, null, null, 6]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
333
+ //=> 'foo[]=1||3|||6'
334
+
335
+ queryString.stringify({foo: [1, '', 3, null, null, 6]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|', skipNull: true});
336
+ //=> 'foo[]=1||3|6'
337
+
338
+ queryString.stringify({foo: [1, 2, 3], bar: 'fluffy', baz: [4]}, {arrayFormat: 'bracket-separator', arrayFormatSeparator: '|'});
339
+ //=> 'foo[]=1|2|3&bar=fluffy&baz[]=4'
340
+ ```
341
+
342
+ - `'colon-list-separator'`: Serialize arrays with parameter names that are explicitly marked with `:list`:
343
+
344
+ ```js
345
+ const queryString = require('query-string');
346
+
347
+ queryString.stringify({foo: ['one', 'two']}, {arrayFormat: 'colon-list-separator'});
348
+ //=> 'foo:list=one&foo:list=two'
231
349
  ```
232
350
 
233
351
  - `'none'`: Serialize arrays by using duplicate keys:
@@ -520,6 +638,12 @@ queryString.stringify({foo: undefined});
520
638
  //=> ''
521
639
  ```
522
640
 
641
+ ## FAQ
642
+
643
+ ### Why is it parsing `+` as a space?
644
+
645
+ See [this answer](https://github.com/sindresorhus/query-string/issues/305).
646
+
523
647
  ## query-string for enterprise
524
648
 
525
649
  Available as part of the Tidelift Subscription.