@common.js/query-string 8.2.0 → 9.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/README.md +1 -1
  2. package/base.d.ts +110 -1
  3. package/base.js +29 -17
  4. package/package.json +7 -7
package/README.md CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  The [query-string](https://www.npmjs.com/package/query-string) package exported as CommonJS modules.
4
4
 
5
- Exported from [query-string@8.2.0](https://www.npmjs.com/package/query-string/v/8.2.0) using https://github.com/etienne-martin/common.js.
5
+ Exported from [query-string@9.1.0](https://www.npmjs.com/package/query-string/v/9.1.0) using https://github.com/etienne-martin/common.js.
package/base.d.ts CHANGED
@@ -87,7 +87,14 @@ export type ParseOptions = {
87
87
  //=> {foo: ['1', '2', '3']}
88
88
  ```
89
89
  */
90
- readonly arrayFormat?: 'bracket' | 'index' | 'comma' | 'separator' | 'bracket-separator' | 'colon-list-separator' | 'none';
90
+ readonly arrayFormat?:
91
+ | 'bracket'
92
+ | 'index'
93
+ | 'comma'
94
+ | 'separator'
95
+ | 'bracket-separator'
96
+ | 'colon-list-separator'
97
+ | 'none';
91
98
 
92
99
  /**
93
100
  The character used to separate array elements when using `{arrayFormat: 'separator'}`.
@@ -169,6 +176,108 @@ export type ParseOptions = {
169
176
  ```
170
177
  */
171
178
  readonly parseFragmentIdentifier?: boolean;
179
+
180
+ /**
181
+ Specify a pre-defined schema to be used when parsing values. The types specified will take precedence over options such as: `parseNumber`, `parseBooleans`, and `arrayFormat`.
182
+
183
+ Use this feature to override the type of a value. This can be useful when the type is ambiguous such as a phone number (see example 1 and 2).
184
+
185
+ It is possible to provide a custom function as the parameter type. The parameter's value will equal the function's return value (see example 4).
186
+
187
+ NOTE: Array types (`string[]` and `number[]`) will have no effect if `arrayFormat` is set to `none` (see example 5).
188
+
189
+ @default {}
190
+
191
+ @example
192
+ Parse `phoneNumber` as a string, overriding the `parseNumber` option:
193
+ ```
194
+ import queryString from 'query-string';
195
+
196
+ queryString.parse('?phoneNumber=%2B380951234567&id=1', {
197
+ parseNumbers: true,
198
+ types: {
199
+ phoneNumber: 'string',
200
+ }
201
+ });
202
+ //=> {phoneNumber: '+380951234567', id: 1}
203
+ ```
204
+
205
+ @example
206
+ Parse `items` as an array of strings, overriding the `parseNumber` option:
207
+ ```
208
+ import queryString from 'query-string';
209
+
210
+ queryString.parse('?age=20&items=1%2C2%2C3', {
211
+ parseNumber: true,
212
+ types: {
213
+ items: 'string[]',
214
+ }
215
+ });
216
+ //=> {age: 20, items: ['1', '2', '3']}
217
+ ```
218
+
219
+ @example
220
+ Parse `age` as a number, even when `parseNumber` is false:
221
+ ```
222
+ import queryString from 'query-string';
223
+
224
+ queryString.parse('?age=20&id=01234&zipcode=90210', {
225
+ types: {
226
+ age: 'number',
227
+ }
228
+ });
229
+ //=> {age: 20, id: '01234', zipcode: '90210 }
230
+ ```
231
+
232
+ @example
233
+ Parse `age` using a custom value parser:
234
+ ```
235
+ import queryString from 'query-string';
236
+
237
+ queryString.parse('?age=20&id=01234&zipcode=90210', {
238
+ types: {
239
+ age: (value) => value * 2,
240
+ }
241
+ });
242
+ //=> {age: 40, id: '01234', zipcode: '90210 }
243
+ ```
244
+
245
+ @example
246
+ Array types will have no effect when `arrayFormat` is set to `none`
247
+ ```
248
+ queryString.parse('ids=001%2C002%2C003&foods=apple%2Corange%2Cmango', {
249
+ arrayFormat: 'none',
250
+ types: {
251
+ ids: 'number[]',
252
+ foods: 'string[]',
253
+ },
254
+ }
255
+ //=> {ids:'001,002,003', foods:'apple,orange,mango'}
256
+ ```
257
+
258
+ @example
259
+ Parse a query utilizing all types:
260
+ ```
261
+ import queryString from 'query-string';
262
+
263
+ queryString.parse('?ids=001%2C002%2C003&items=1%2C2%2C3&price=22%2E00&numbers=1%2C2%2C3&double=5&number=20', {
264
+ arrayFormat: 'comma',
265
+ types: {
266
+ ids: 'string',
267
+ items: 'string[]',
268
+ price: 'string',
269
+ numbers: 'number[]',
270
+ double: (value) => value * 2,
271
+ number: 'number',
272
+ },
273
+ });
274
+ //=> {ids: '001,002,003', items: ['1', '2', '3'], price: '22.00', numbers: [1, 2, 3], double: 10, number: 20}
275
+ ```
276
+ */
277
+ readonly types?: Record<
278
+ string,
279
+ 'number' | 'string' | 'string[]' | 'number[]' | ((value: string) => unknown)
280
+ >;
172
281
  };
173
282
 
174
283
  // eslint-disable-next-line @typescript-eslint/ban-types
package/base.js CHANGED
@@ -32,8 +32,8 @@ _export(exports, {
32
32
  }
33
33
  });
34
34
  var _decodeUriComponent = /*#__PURE__*/ _interopRequireDefault(require("decode-uri-component"));
35
- var _splitOnFirst = /*#__PURE__*/ _interopRequireDefault(require("split-on-first"));
36
35
  var _filterObj = require("filter-obj");
36
+ var _splitOnFirst = /*#__PURE__*/ _interopRequireDefault(require("split-on-first"));
37
37
  function _arrayLikeToArray(arr, len) {
38
38
  if (len == null || len > arr.length) len = arr.length;
39
39
  for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
@@ -130,7 +130,7 @@ var isNullOrUndefined = function(value) {
130
130
  };
131
131
  // eslint-disable-next-line unicorn/prefer-code-point
132
132
  var strictUriEncode = function(string) {
133
- return encodeURIComponent(string).replace(/[!'()*]/g, function(x) {
133
+ return encodeURIComponent(string).replaceAll(/[!'()*]/g, function(x) {
134
134
  return "%".concat(x.charCodeAt(0).toString(16).toUpperCase());
135
135
  });
136
136
  };
@@ -221,7 +221,7 @@ function encoderForArrayFormat(options) {
221
221
  case "separator":
222
222
  case "bracket-separator":
223
223
  {
224
- var keyValueSep = options.arrayFormat === "bracket-separator" ? "[]=" : "=";
224
+ var keyValueSeparator = options.arrayFormat === "bracket-separator" ? "[]=" : "=";
225
225
  return function(key) {
226
226
  return function(result, value) {
227
227
  if (value === undefined || options.skipNull && value === null || options.skipEmptyString && value === "") {
@@ -233,7 +233,7 @@ function encoderForArrayFormat(options) {
233
233
  return [
234
234
  [
235
235
  encode(key, options),
236
- keyValueSep,
236
+ keyValueSeparator,
237
237
  encode(value, options)
238
238
  ].join("")
239
239
  ];
@@ -422,11 +422,21 @@ function getHash(url) {
422
422
  }
423
423
  return hash;
424
424
  }
425
- function parseValue(value, options) {
425
+ function parseValue(value, options, type) {
426
+ if (type === "string" && typeof value === "string") {
427
+ return value;
428
+ }
429
+ if (typeof type === "function" && typeof value === "string") {
430
+ return type(value);
431
+ }
432
+ if (options.parseBooleans && value !== null && (value.toLowerCase() === "true" || value.toLowerCase() === "false")) {
433
+ return value.toLowerCase() === "true";
434
+ }
435
+ if (type === "number" && !Number.isNaN(Number(value)) && typeof value === "string" && value.trim() !== "") {
436
+ return Number(value);
437
+ }
426
438
  if (options.parseNumbers && !Number.isNaN(Number(value)) && typeof value === "string" && value.trim() !== "") {
427
- value = Number(value);
428
- } else if (options.parseBooleans && value !== null && (value.toLowerCase() === "true" || value.toLowerCase() === "false")) {
429
- value = value.toLowerCase() === "true";
439
+ return Number(value);
430
440
  }
431
441
  return value;
432
442
  }
@@ -445,7 +455,8 @@ function parse(query, options) {
445
455
  arrayFormat: "none",
446
456
  arrayFormatSeparator: ",",
447
457
  parseNumbers: false,
448
- parseBooleans: false
458
+ parseBooleans: false,
459
+ types: Object.create(null)
449
460
  }, options);
450
461
  validateArrayFormatSeparator(options.arrayFormatSeparator);
451
462
  var formatter = parserForArrayFormat(options);
@@ -465,7 +476,7 @@ function parse(query, options) {
465
476
  if (parameter === "") {
466
477
  continue;
467
478
  }
468
- var parameter_ = options.decode ? parameter.replace(/\+/g, " ") : parameter;
479
+ var parameter_ = options.decode ? parameter.replaceAll("+", " ") : parameter;
469
480
  var ref = _slicedToArray((0, _splitOnFirst.default)(parameter_, "="), 2), key = ref[0], value = ref[1];
470
481
  if (key === undefined) {
471
482
  key = parameter_;
@@ -497,12 +508,13 @@ function parse(query, options) {
497
508
  try {
498
509
  for(var _iterator1 = Object.entries(returnValue)[Symbol.iterator](), _step1; !(_iteratorNormalCompletion1 = (_step1 = _iterator1.next()).done); _iteratorNormalCompletion1 = true){
499
510
  var _value = _slicedToArray(_step1.value, 2), key1 = _value[0], value1 = _value[1];
500
- if (typeof value1 === "object" && value1 !== null) {
511
+ if (typeof value1 === "object" && value1 !== null && options.types[key1] !== "string") {
501
512
  var _iteratorNormalCompletion2 = true, _didIteratorError2 = false, _iteratorError2 = undefined;
502
513
  try {
503
514
  for(var _iterator2 = Object.entries(value1)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true){
504
515
  var _value1 = _slicedToArray(_step2.value, 2), key2 = _value1[0], value2 = _value1[1];
505
- value1[key2] = parseValue(value2, options);
516
+ var type = options.types[key1] ? options.types[key1].replace("[]", "") : undefined;
517
+ value1[key2] = parseValue(value2, options, type);
506
518
  }
507
519
  } catch (err) {
508
520
  _didIteratorError2 = true;
@@ -518,8 +530,10 @@ function parse(query, options) {
518
530
  }
519
531
  }
520
532
  }
533
+ } else if (typeof value1 === "object" && value1 !== null && options.types[key1] === "string") {
534
+ returnValue[key1] = Object.values(value1).join(options.arrayFormatSeparator);
521
535
  } else {
522
- returnValue[key1] = parseValue(value1, options);
536
+ returnValue[key1] = parseValue(value1, options, options.types[key1]);
523
537
  }
524
538
  }
525
539
  } catch (err) {
@@ -636,11 +650,9 @@ function stringifyUrl(object, options) {
636
650
  sort: false
637
651
  }), object.query);
638
652
  var queryString = stringify(query, options);
639
- if (queryString) {
640
- queryString = "?".concat(queryString);
641
- }
653
+ queryString && (queryString = "?".concat(queryString));
642
654
  var hash = getHash(object.url);
643
- if (object.fragmentIdentifier) {
655
+ if (typeof object.fragmentIdentifier === "string") {
644
656
  var urlObjectForFragmentEncode = new URL(url);
645
657
  urlObjectForFragmentEncode.hash = object.fragmentIdentifier;
646
658
  hash = options[encodeFragmentIdentifier] ? urlObjectForFragmentEncode.hash : "#".concat(object.fragmentIdentifier);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@common.js/query-string",
3
- "version": "8.2.0",
3
+ "version": "9.1.0",
4
4
  "description": "query-string package exported as CommonJS modules",
5
5
  "license": "MIT",
6
6
  "repository": "etienne-martin/common.js",
@@ -8,7 +8,7 @@
8
8
  "type": "commonjs",
9
9
  "sideEffects": false,
10
10
  "engines": {
11
- "node": ">=14.16"
11
+ "node": ">=18"
12
12
  },
13
13
  "scripts": {
14
14
  "benchmark": "node benchmark.js",
@@ -26,12 +26,12 @@
26
26
  "@common.js/split-on-first": "^3.0.0"
27
27
  },
28
28
  "devDependencies": {
29
- "ava": "^5.1.0",
29
+ "ava": "^6.1.1",
30
30
  "benchmark": "^2.1.4",
31
- "deep-equal": "^2.1.0",
32
- "fast-check": "^3.4.0",
33
- "tsd": "^0.25.0",
34
- "xo": "^0.54.2"
31
+ "deep-equal": "^2.2.3",
32
+ "fast-check": "^3.15.1",
33
+ "tsd": "^0.30.7",
34
+ "xo": "^0.57.0"
35
35
  },
36
36
  "tsd": {
37
37
  "compilerOptions": {