query-string 6.10.1 → 6.12.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 (4) hide show
  1. package/index.d.ts +61 -2
  2. package/index.js +47 -14
  3. package/package.json +1 -1
  4. package/readme.md +48 -0
package/index.d.ts CHANGED
@@ -36,6 +36,15 @@ export interface ParseOptions {
36
36
  //=> {foo: ['1', '2', '3']}
37
37
  ```
38
38
 
39
+ - `separator`: Parse arrays with elements separated by a custom character:
40
+
41
+ ```
42
+ import queryString = require('query-string');
43
+
44
+ queryString.parse('foo=1|2|3', {arrayFormat: 'separator', arrayFormatSeparator: '|'});
45
+ //=> {foo: ['1', '2', '3']}
46
+ ```
47
+
39
48
  - `none`: Parse arrays with elements using duplicate keys:
40
49
 
41
50
  ```
@@ -45,7 +54,14 @@ export interface ParseOptions {
45
54
  //=> {foo: ['1', '2', '3']}
46
55
  ```
47
56
  */
48
- readonly arrayFormat?: 'bracket' | 'index' | 'comma' | 'none';
57
+ readonly arrayFormat?: 'bracket' | 'index' | 'comma' | 'separator' | 'none';
58
+
59
+ /**
60
+ The character used to separate array elements when using `{arrayFormat: 'separator'}`.
61
+
62
+ @default ,
63
+ */
64
+ readonly arrayFormatSeparator?: string;
49
65
 
50
66
  /**
51
67
  Supports both `Function` as a custom sorting function or `false` to disable sorting.
@@ -188,6 +204,15 @@ export interface StringifyOptions {
188
204
  //=> 'foo=1,2,3'
189
205
  ```
190
206
 
207
+ - `separator`: Serialize arrays by separating elements with character:
208
+
209
+ ```
210
+ import queryString = require('query-string');
211
+
212
+ queryString.stringify({foo: [1, 2, 3]}, {arrayFormat: 'separator', arrayFormatSeparator: '|'});
213
+ //=> 'foo=1|2|3'
214
+ ```
215
+
191
216
  - `none`: Serialize arrays by using duplicate keys:
192
217
 
193
218
  ```
@@ -197,7 +222,14 @@ export interface StringifyOptions {
197
222
  //=> 'foo=1&foo=2&foo=3'
198
223
  ```
199
224
  */
200
- readonly arrayFormat?: 'bracket' | 'index' | 'comma' | 'none';
225
+ readonly arrayFormat?: 'bracket' | 'index' | 'comma' | 'separator' | 'none';
226
+
227
+ /**
228
+ The character used to separate array elements when using `{arrayFormat: 'separator'}`.
229
+
230
+ @default ,
231
+ */
232
+ readonly arrayFormatSeparator?: string;
201
233
 
202
234
  /**
203
235
  Supports both `Function` as a custom sorting function or `false` to disable sorting.
@@ -251,6 +283,33 @@ export interface StringifyOptions {
251
283
  ```
252
284
  */
253
285
  readonly skipNull?: boolean;
286
+
287
+ /**
288
+ Skip keys with an empty string as the value.
289
+
290
+ @default false
291
+
292
+ @example
293
+ ```
294
+ import queryString = require('query-string');
295
+
296
+ queryString.stringify({a: 1, b: '', c: '', d: 4}, {
297
+ skipEmptyString: true
298
+ });
299
+ //=> 'a=1&d=4'
300
+ ```
301
+
302
+ @example
303
+ ```
304
+ import queryString = require('query-string');
305
+
306
+ queryString.stringify({a: '', b: ''}, {
307
+ skipEmptyString: true
308
+ });
309
+ //=> ''
310
+ ```
311
+ */
312
+ readonly skipEmptyString?: boolean;
254
313
  }
255
314
 
256
315
  /**
package/index.js CHANGED
@@ -3,12 +3,19 @@ const strictUriEncode = require('strict-uri-encode');
3
3
  const decodeComponent = require('decode-uri-component');
4
4
  const splitOnFirst = require('split-on-first');
5
5
 
6
+ const isNullOrUndefined = value => value === null || value === undefined;
7
+
6
8
  function encoderForArrayFormat(options) {
7
9
  switch (options.arrayFormat) {
8
10
  case 'index':
9
11
  return key => (result, value) => {
10
12
  const index = result.length;
11
- if (value === undefined || (options.skipNull && value === null)) {
13
+
14
+ if (
15
+ value === undefined ||
16
+ (options.skipNull && value === null) ||
17
+ (options.skipEmptyString && value === '')
18
+ ) {
12
19
  return result;
13
20
  }
14
21
 
@@ -24,7 +31,11 @@ function encoderForArrayFormat(options) {
24
31
 
25
32
  case 'bracket':
26
33
  return key => (result, value) => {
27
- if (value === undefined || (options.skipNull && value === null)) {
34
+ if (
35
+ value === undefined ||
36
+ (options.skipNull && value === null) ||
37
+ (options.skipEmptyString && value === '')
38
+ ) {
28
39
  return result;
29
40
  }
30
41
 
@@ -36,6 +47,7 @@ function encoderForArrayFormat(options) {
36
47
  };
37
48
 
38
49
  case 'comma':
50
+ case 'separator':
39
51
  return key => (result, value) => {
40
52
  if (value === null || value === undefined || value.length === 0) {
41
53
  return result;
@@ -45,12 +57,16 @@ function encoderForArrayFormat(options) {
45
57
  return [[encode(key, options), '=', encode(value, options)].join('')];
46
58
  }
47
59
 
48
- return [[result, encode(value, options)].join(',')];
60
+ return [[result, encode(value, options)].join(options.arrayFormatSeparator)];
49
61
  };
50
62
 
51
63
  default:
52
64
  return key => (result, value) => {
53
- if (value === undefined || (options.skipNull && value === null)) {
65
+ if (
66
+ value === undefined ||
67
+ (options.skipNull && value === null) ||
68
+ (options.skipEmptyString && value === '')
69
+ ) {
54
70
  return result;
55
71
  }
56
72
 
@@ -104,9 +120,10 @@ function parserForArrayFormat(options) {
104
120
  };
105
121
 
106
122
  case 'comma':
123
+ case 'separator':
107
124
  return (key, value, accumulator) => {
108
- const isArray = typeof value === 'string' && value.split('').indexOf(',') > -1;
109
- const newValue = isArray ? value.split(',') : value;
125
+ const isArray = typeof value === 'string' && value.split('').indexOf(options.arrayFormatSeparator) > -1;
126
+ const newValue = isArray ? value.split(options.arrayFormatSeparator).map(item => decode(item, options)) : value === null ? value : decode(value, options);
110
127
  accumulator[key] = newValue;
111
128
  };
112
129
 
@@ -122,6 +139,12 @@ function parserForArrayFormat(options) {
122
139
  }
123
140
  }
124
141
 
142
+ function validateArrayFormatSeparator(value) {
143
+ if (typeof value !== 'string' || value.length !== 1) {
144
+ throw new TypeError('arrayFormatSeparator must be single character string');
145
+ }
146
+ }
147
+
125
148
  function encode(value, options) {
126
149
  if (options.encode) {
127
150
  return options.strict ? strictUriEncode(value) : encodeURIComponent(value);
@@ -196,10 +219,13 @@ function parse(input, options) {
196
219
  decode: true,
197
220
  sort: true,
198
221
  arrayFormat: 'none',
222
+ arrayFormatSeparator: ',',
199
223
  parseNumbers: false,
200
224
  parseBooleans: false
201
225
  }, options);
202
226
 
227
+ validateArrayFormatSeparator(options.arrayFormatSeparator);
228
+
203
229
  const formatter = parserForArrayFormat(options);
204
230
 
205
231
  // Create an object with no prototype
@@ -220,7 +246,7 @@ function parse(input, options) {
220
246
 
221
247
  // Missing `=` should be `null`:
222
248
  // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters
223
- value = value === undefined ? null : decode(value, options);
249
+ value = value === undefined ? null : ['comma', 'separator'].includes(options.arrayFormat) ? value : decode(value, options);
224
250
  formatter(decode(key, options), value, ret);
225
251
  }
226
252
 
@@ -263,17 +289,24 @@ exports.stringify = (object, options) => {
263
289
  options = Object.assign({
264
290
  encode: true,
265
291
  strict: true,
266
- arrayFormat: 'none'
292
+ arrayFormat: 'none',
293
+ arrayFormatSeparator: ','
267
294
  }, options);
268
295
 
296
+ validateArrayFormatSeparator(options.arrayFormatSeparator);
297
+
298
+ const shouldFilter = key => (
299
+ (options.skipNull && isNullOrUndefined(object[key])) ||
300
+ (options.skipEmptyString && object[key] === '')
301
+ );
302
+
269
303
  const formatter = encoderForArrayFormat(options);
270
304
 
271
- const objectCopy = Object.assign({}, object);
272
- if (options.skipNull) {
273
- for (const key of Object.keys(objectCopy)) {
274
- if (objectCopy[key] === undefined || objectCopy[key] === null) {
275
- delete objectCopy[key];
276
- }
305
+ const objectCopy = {};
306
+
307
+ for (const key of Object.keys(object)) {
308
+ if (!shouldFilter(key)) {
309
+ objectCopy[key] = object[key];
277
310
  }
278
311
  }
279
312
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "query-string",
3
- "version": "6.10.1",
3
+ "version": "6.12.1",
4
4
  "description": "Parse and stringify URL query strings",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/query-string",
package/readme.md CHANGED
@@ -121,6 +121,15 @@ queryString.parse('foo=1,2,3', {arrayFormat: 'comma'});
121
121
  //=> {foo: ['1', '2', '3']}
122
122
  ```
123
123
 
124
+ - `'separator'`: Parse arrays with elements separated by a custom character:
125
+
126
+ ```js
127
+ const queryString = require('query-string');
128
+
129
+ queryString.parse('foo=1|2|3', {arrayFormat: 'separator', arrayFormatSeparator: '|'});
130
+ //=> {foo: ['1', '2', '3']}
131
+ ```
132
+
124
133
  - `'none'`: Parse arrays with elements using duplicate keys:
125
134
 
126
135
  ```js
@@ -130,6 +139,13 @@ queryString.parse('foo=1&foo=2&foo=3');
130
139
  //=> {foo: ['1', '2', '3']}
131
140
  ```
132
141
 
142
+ ##### arrayFormatSeparator
143
+
144
+ Type: `string`\
145
+ Default: `','`
146
+
147
+ The character used to separate array elements when using `{arrayFormat: 'separator'}`.
148
+
133
149
  ##### sort
134
150
 
135
151
  Type: `Function | boolean`\
@@ -228,6 +244,13 @@ queryString.stringify({foo: [1, 2, 3]});
228
244
  //=> 'foo=1&foo=2&foo=3'
229
245
  ```
230
246
 
247
+ ##### arrayFormatSeparator
248
+
249
+ Type: `string`\
250
+ Default: `','`
251
+
252
+ The character used to separate array elements when using `{arrayFormat: 'separator'}`.
253
+
231
254
  ##### sort
232
255
 
233
256
  Type: `Function | boolean`
@@ -281,6 +304,31 @@ queryString.stringify({a: undefined, b: null}, {
281
304
  //=> ''
282
305
  ```
283
306
 
307
+ ##### skipEmptyString
308
+
309
+ Skip keys with an empty string as the value.
310
+
311
+ Type: `boolean`\
312
+ Default: `false`
313
+
314
+ ```js
315
+ const queryString = require('query-string');
316
+
317
+ queryString.stringify({a: 1, b: '', c: '', d: 4}, {
318
+ skipEmptyString: true
319
+ });
320
+ //=> 'a=1&d=4'
321
+ ```
322
+
323
+ ```js
324
+ const queryString = require('query-string');
325
+
326
+ queryString.stringify({a: '', b: ''}, {
327
+ skipEmptyString: true
328
+ });
329
+ //=> ''
330
+ ```
331
+
284
332
  ### .extract(string)
285
333
 
286
334
  Extract a query string from a URL that can be passed into `.parse()`.