query-string 9.3.0 → 9.4.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.
- package/base.d.ts +21 -6
- package/base.js +75 -47
- package/package.json +1 -1
- package/readme.md +16 -6
package/base.d.ts
CHANGED
|
@@ -182,14 +182,14 @@ export type ParseOptions = {
|
|
|
182
182
|
|
|
183
183
|
Use this option to explicitly define the type of a specific parameter—particularly useful in cases where the type might otherwise be ambiguous (e.g., phone numbers or IDs).
|
|
184
184
|
|
|
185
|
-
You can also provide a custom function to transform the value. The function will receive the raw string and should return the desired parsed result (
|
|
185
|
+
You can also provide a custom function to transform the value. The function will receive the raw string and should return the desired parsed result. When used with array formats (like `comma`, `separator`, `bracket`, etc.), the function is applied to each array element individually.
|
|
186
186
|
|
|
187
187
|
NOTE: Array types (`string[]`, `number[]`) are ignored if `arrayFormat` is set to `'none'`.
|
|
188
188
|
|
|
189
189
|
@default {}
|
|
190
190
|
|
|
191
191
|
@example
|
|
192
|
-
Parse `phoneNumber` as a string, overriding the `
|
|
192
|
+
Parse `phoneNumber` as a string, overriding the `parseNumbers` option:
|
|
193
193
|
```
|
|
194
194
|
import queryString from 'query-string';
|
|
195
195
|
|
|
@@ -203,12 +203,12 @@ export type ParseOptions = {
|
|
|
203
203
|
```
|
|
204
204
|
|
|
205
205
|
@example
|
|
206
|
-
Parse `items` as an array of strings, overriding the `
|
|
206
|
+
Parse `items` as an array of strings, overriding the `parseNumbers` option:
|
|
207
207
|
```
|
|
208
208
|
import queryString from 'query-string';
|
|
209
209
|
|
|
210
210
|
queryString.parse('?age=20&items=1%2C2%2C3', {
|
|
211
|
-
|
|
211
|
+
parseNumbers: true,
|
|
212
212
|
types: {
|
|
213
213
|
items: 'string[]',
|
|
214
214
|
}
|
|
@@ -236,12 +236,27 @@ export type ParseOptions = {
|
|
|
236
236
|
|
|
237
237
|
queryString.parse('?age=20&id=01234&zipcode=90210', {
|
|
238
238
|
types: {
|
|
239
|
-
age:
|
|
239
|
+
age: value => value * 2,
|
|
240
240
|
}
|
|
241
241
|
});
|
|
242
242
|
//=> {age: 40, id: '01234', zipcode: '90210'}
|
|
243
243
|
```
|
|
244
244
|
|
|
245
|
+
@example
|
|
246
|
+
Custom functions are applied to each array element when using array formats:
|
|
247
|
+
```
|
|
248
|
+
import queryString from 'query-string';
|
|
249
|
+
|
|
250
|
+
// With arrays, the function is applied to each element
|
|
251
|
+
queryString.parse('?scores=10,20,30', {
|
|
252
|
+
arrayFormat: 'comma',
|
|
253
|
+
types: {
|
|
254
|
+
scores: value => Number(value) * 2,
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
//=> {scores: [20, 40, 60]}
|
|
258
|
+
```
|
|
259
|
+
|
|
245
260
|
@example
|
|
246
261
|
Array types are ignored when `arrayFormat` is set to `'none'`:
|
|
247
262
|
```
|
|
@@ -267,7 +282,7 @@ export type ParseOptions = {
|
|
|
267
282
|
items: 'string[]',
|
|
268
283
|
price: 'string',
|
|
269
284
|
numbers: 'number[]',
|
|
270
|
-
double:
|
|
285
|
+
double: value => value * 2,
|
|
271
286
|
number: 'number',
|
|
272
287
|
},
|
|
273
288
|
});
|
package/base.js
CHANGED
|
@@ -24,15 +24,12 @@ function encoderForArrayFormat(options) {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
if (value === null) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
];
|
|
27
|
+
result.push([encode(key, options), '[', index, ']'].join(''));
|
|
28
|
+
return result;
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
[encode(key, options), '[', encode(index, options), ']=', encode(value, options)].join(''),
|
|
35
|
-
];
|
|
31
|
+
result.push([encode(key, options), '[', encode(index, options), ']=', encode(value, options)].join(''));
|
|
32
|
+
return result;
|
|
36
33
|
};
|
|
37
34
|
}
|
|
38
35
|
|
|
@@ -47,16 +44,12 @@ function encoderForArrayFormat(options) {
|
|
|
47
44
|
}
|
|
48
45
|
|
|
49
46
|
if (value === null) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
[encode(key, options), '[]'].join(''),
|
|
53
|
-
];
|
|
47
|
+
result.push([encode(key, options), '[]'].join(''));
|
|
48
|
+
return result;
|
|
54
49
|
}
|
|
55
50
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
[encode(key, options), '[]=', encode(value, options)].join(''),
|
|
59
|
-
];
|
|
51
|
+
result.push([encode(key, options), '[]=', encode(value, options)].join(''));
|
|
52
|
+
return result;
|
|
60
53
|
};
|
|
61
54
|
}
|
|
62
55
|
|
|
@@ -71,16 +64,12 @@ function encoderForArrayFormat(options) {
|
|
|
71
64
|
}
|
|
72
65
|
|
|
73
66
|
if (value === null) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
[encode(key, options), ':list='].join(''),
|
|
77
|
-
];
|
|
67
|
+
result.push([encode(key, options), ':list='].join(''));
|
|
68
|
+
return result;
|
|
78
69
|
}
|
|
79
70
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
[encode(key, options), ':list=', encode(value, options)].join(''),
|
|
83
|
-
];
|
|
71
|
+
result.push([encode(key, options), ':list=', encode(value, options)].join(''));
|
|
72
|
+
return result;
|
|
84
73
|
};
|
|
85
74
|
}
|
|
86
75
|
|
|
@@ -104,10 +93,12 @@ function encoderForArrayFormat(options) {
|
|
|
104
93
|
value = value === null ? '' : value;
|
|
105
94
|
|
|
106
95
|
if (result.length === 0) {
|
|
107
|
-
|
|
96
|
+
result.push([encode(key, options), keyValueSeparator, encode(value, options)].join(''));
|
|
97
|
+
return result;
|
|
108
98
|
}
|
|
109
99
|
|
|
110
|
-
|
|
100
|
+
result.push(encode(value, options));
|
|
101
|
+
return result;
|
|
111
102
|
};
|
|
112
103
|
}
|
|
113
104
|
|
|
@@ -122,16 +113,12 @@ function encoderForArrayFormat(options) {
|
|
|
122
113
|
}
|
|
123
114
|
|
|
124
115
|
if (value === null) {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
encode(key, options),
|
|
128
|
-
];
|
|
116
|
+
result.push(encode(key, options));
|
|
117
|
+
return result;
|
|
129
118
|
}
|
|
130
119
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
[encode(key, options), '=', encode(value, options)].join(''),
|
|
134
|
-
];
|
|
120
|
+
result.push([encode(key, options), '=', encode(value, options)].join(''));
|
|
121
|
+
return result;
|
|
135
122
|
};
|
|
136
123
|
}
|
|
137
124
|
}
|
|
@@ -175,7 +162,12 @@ function parserForArrayFormat(options) {
|
|
|
175
162
|
return;
|
|
176
163
|
}
|
|
177
164
|
|
|
178
|
-
|
|
165
|
+
if (!Array.isArray(accumulator[key])) {
|
|
166
|
+
accumulator[key] = [accumulator[key], value];
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
accumulator[key].push(value);
|
|
179
171
|
};
|
|
180
172
|
}
|
|
181
173
|
|
|
@@ -194,7 +186,12 @@ function parserForArrayFormat(options) {
|
|
|
194
186
|
return;
|
|
195
187
|
}
|
|
196
188
|
|
|
197
|
-
|
|
189
|
+
if (!Array.isArray(accumulator[key])) {
|
|
190
|
+
accumulator[key] = [accumulator[key], value];
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
accumulator[key].push(value);
|
|
198
195
|
};
|
|
199
196
|
}
|
|
200
197
|
|
|
@@ -226,7 +223,13 @@ function parserForArrayFormat(options) {
|
|
|
226
223
|
return;
|
|
227
224
|
}
|
|
228
225
|
|
|
229
|
-
|
|
226
|
+
if (!Array.isArray(accumulator[key])) {
|
|
227
|
+
accumulator[key] = [accumulator[key]];
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
for (const item of arrayValue) {
|
|
231
|
+
accumulator[key].push(item);
|
|
232
|
+
}
|
|
230
233
|
};
|
|
231
234
|
}
|
|
232
235
|
|
|
@@ -237,7 +240,12 @@ function parserForArrayFormat(options) {
|
|
|
237
240
|
return;
|
|
238
241
|
}
|
|
239
242
|
|
|
240
|
-
|
|
243
|
+
if (Array.isArray(accumulator[key])) {
|
|
244
|
+
accumulator[key].push(value);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
accumulator[key] = [accumulator[key], value];
|
|
241
249
|
};
|
|
242
250
|
}
|
|
243
251
|
}
|
|
@@ -298,6 +306,12 @@ function getHash(url) {
|
|
|
298
306
|
return hash;
|
|
299
307
|
}
|
|
300
308
|
|
|
309
|
+
function getUrlWithoutQuery(url) {
|
|
310
|
+
// Avoid `split('?')` so query-heavy URLs don't allocate large arrays.
|
|
311
|
+
const queryStart = url.indexOf('?');
|
|
312
|
+
return queryStart === -1 ? url : url.slice(0, queryStart);
|
|
313
|
+
}
|
|
314
|
+
|
|
301
315
|
function parseValue(value, options, type) {
|
|
302
316
|
if (type === 'string' && typeof value === 'string') {
|
|
303
317
|
return value;
|
|
@@ -381,11 +395,21 @@ export function parse(query, options) {
|
|
|
381
395
|
return returnValue;
|
|
382
396
|
}
|
|
383
397
|
|
|
384
|
-
|
|
385
|
-
|
|
398
|
+
// Avoid `split('&')` so separator-heavy inputs don't allocate large arrays of empty strings.
|
|
399
|
+
let parameterStart = 0;
|
|
400
|
+
|
|
401
|
+
for (let index = 0; index <= query.length; index++) {
|
|
402
|
+
if (index < query.length && query[index] !== '&') {
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
if (index === parameterStart) {
|
|
407
|
+
parameterStart = index + 1;
|
|
386
408
|
continue;
|
|
387
409
|
}
|
|
388
410
|
|
|
411
|
+
const parameter = query.slice(parameterStart, index);
|
|
412
|
+
parameterStart = index + 1;
|
|
389
413
|
const parameter_ = options.decode ? parameter.replaceAll('+', ' ') : parameter;
|
|
390
414
|
|
|
391
415
|
let [key, value] = splitOnFirst(parameter_, '=');
|
|
@@ -403,7 +427,8 @@ export function parse(query, options) {
|
|
|
403
427
|
for (const [key, value] of Object.entries(returnValue)) {
|
|
404
428
|
if (typeof value === 'object' && value !== null && options.types[key] !== 'string') {
|
|
405
429
|
for (const [key2, value2] of Object.entries(value)) {
|
|
406
|
-
const
|
|
430
|
+
const typeOption = options.types[key];
|
|
431
|
+
const type = typeof typeOption === 'function' ? typeOption : (typeOption ? typeOption.replace('[]', '') : undefined);
|
|
407
432
|
value[key2] = parseValue(value2, options, type);
|
|
408
433
|
}
|
|
409
434
|
} else if (typeof value === 'object' && value !== null && options.types[key] === 'string') {
|
|
@@ -497,9 +522,9 @@ export function stringify(object, options) {
|
|
|
497
522
|
).filter(item => item !== undefined);
|
|
498
523
|
}
|
|
499
524
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
525
|
+
const result = processedArray.reduce(formatter(key), []);
|
|
526
|
+
const arrayFormatSeparator = ['comma', 'separator', 'bracket-separator'].includes(options.arrayFormat) ? options.arrayFormatSeparator : '&';
|
|
527
|
+
return result.join(arrayFormatSeparator);
|
|
503
528
|
}
|
|
504
529
|
|
|
505
530
|
return encode(key, options) + '=' + encode(value, options);
|
|
@@ -519,7 +544,7 @@ export function parseUrl(url, options) {
|
|
|
519
544
|
}
|
|
520
545
|
|
|
521
546
|
return {
|
|
522
|
-
url: url_
|
|
547
|
+
url: getUrlWithoutQuery(url_ ?? ''),
|
|
523
548
|
query: parse(extract(url), options),
|
|
524
549
|
...(options && options.parseFragmentIdentifier && hash ? {fragmentIdentifier: decode(hash, options)} : {}),
|
|
525
550
|
};
|
|
@@ -533,7 +558,7 @@ export function stringifyUrl(object, options) {
|
|
|
533
558
|
...options,
|
|
534
559
|
};
|
|
535
560
|
|
|
536
|
-
const url = removeHash(object.url)
|
|
561
|
+
const url = getUrlWithoutQuery(removeHash(object.url)) || '';
|
|
537
562
|
const queryFromUrl = extract(object.url);
|
|
538
563
|
|
|
539
564
|
const query = {
|
|
@@ -571,7 +596,10 @@ export function pick(input, filter, options) {
|
|
|
571
596
|
}
|
|
572
597
|
|
|
573
598
|
export function exclude(input, filter, options) {
|
|
574
|
-
|
|
599
|
+
if (Array.isArray(filter)) {
|
|
600
|
+
const filterSet = new Set(filter);
|
|
601
|
+
return pick(input, key => !filterSet.has(key), options);
|
|
602
|
+
}
|
|
575
603
|
|
|
576
|
-
return pick(input,
|
|
604
|
+
return pick(input, (key, value) => !filter(key, value), options);
|
|
577
605
|
}
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -13,6 +13,9 @@ npm install query-string
|
|
|
13
13
|
|
|
14
14
|
For browser usage, this package targets the latest version of Chrome, Firefox, and Safari.
|
|
15
15
|
|
|
16
|
+
> [!TIP]
|
|
17
|
+
> Consider using [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) for simple use cases. It's a native browser API that handles basic query string operations.
|
|
18
|
+
|
|
16
19
|
## Usage
|
|
17
20
|
|
|
18
21
|
```js
|
|
@@ -201,13 +204,11 @@ Parse the value as a boolean type instead of string type if it's a boolean.
|
|
|
201
204
|
Type: `object`\
|
|
202
205
|
Default: `{}`
|
|
203
206
|
|
|
204
|
-
|
|
205
207
|
Specifies a schema for parsing query values with explicit type declarations. When defined, the types provided here take precedence over general parsing options such as `parseNumbers`, `parseBooleans`, and `arrayFormat`.
|
|
206
208
|
|
|
207
209
|
Use this option to explicitly define the type of a specific parameter—particularly useful in cases where the type might otherwise be ambiguous (e.g., phone numbers or IDs).
|
|
208
210
|
|
|
209
|
-
You can also provide a custom function to transform the value. The function will receive the raw string and should return the desired parsed result.
|
|
210
|
-
|
|
211
|
+
You can also provide a custom function to transform the value. The function will receive the raw string and should return the desired parsed result. When used with array formats (like `comma`, `separator`, `bracket`, etc.), the function is applied to each array element individually.
|
|
211
212
|
|
|
212
213
|
Supported Types:
|
|
213
214
|
|
|
@@ -281,17 +282,26 @@ queryString.parse('?age=20&items=1%2C2%2C3', {
|
|
|
281
282
|
//=> {age: '20', items: [1, 2, 3]}
|
|
282
283
|
```
|
|
283
284
|
|
|
284
|
-
- `'Function'`: Provide a custom function as the parameter type. The parameter's value will equal the function's return value.
|
|
285
|
+
- `'Function'`: Provide a custom function as the parameter type. The parameter's value will equal the function's return value. When used with array formats (like `comma`, `separator`, `bracket`, etc.), the function is applied to each array element individually.
|
|
285
286
|
|
|
286
287
|
```js
|
|
287
288
|
import queryString from 'query-string';
|
|
288
289
|
|
|
289
290
|
queryString.parse('?age=20&id=01234&zipcode=90210', {
|
|
290
291
|
types: {
|
|
291
|
-
age:
|
|
292
|
+
age: value => value * 2,
|
|
292
293
|
}
|
|
293
294
|
});
|
|
294
295
|
//=> {age: 40, id: '01234', zipcode: '90210'}
|
|
296
|
+
|
|
297
|
+
// With arrays, the function is applied to each element
|
|
298
|
+
queryString.parse('?scores=10,20,30', {
|
|
299
|
+
arrayFormat: 'comma',
|
|
300
|
+
types: {
|
|
301
|
+
scores: value => Number(value) * 2,
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
//=> {scores: [20, 40, 60]}
|
|
295
305
|
```
|
|
296
306
|
|
|
297
307
|
NOTE: Array types (`string[]`, `number[]`) are ignored if `arrayFormat` is set to `'none'`.
|
|
@@ -314,7 +324,7 @@ import queryString from 'query-string';
|
|
|
314
324
|
|
|
315
325
|
queryString.parse('?age=20&id=01234&zipcode=90210', {
|
|
316
326
|
types: {
|
|
317
|
-
age:
|
|
327
|
+
age: value => value * 2,
|
|
318
328
|
}
|
|
319
329
|
});
|
|
320
330
|
//=> {age: 40, id: '01234', zipcode: '90210'}
|