query-string 9.2.2 → 9.3.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/base.d.ts +79 -5
  2. package/base.js +22 -5
  3. package/package.json +1 -1
  4. package/readme.md +58 -1
package/base.d.ts CHANGED
@@ -184,7 +184,7 @@ export type ParseOptions = {
184
184
 
185
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 (see Example 4).
186
186
 
187
- NOTE: Array types (`string[]`, `number[]`) are ignored if `arrayFormat` is set to `'none'`. (See Example 5.)
187
+ NOTE: Array types (`string[]`, `number[]`) are ignored if `arrayFormat` is set to `'none'`.
188
188
 
189
189
  @default {}
190
190
 
@@ -325,9 +325,10 @@ export type ParsedUrl = {
325
325
  /**
326
326
  Extract the URL and the query string as an object.
327
327
 
328
- If the `parseFragmentIdentifier` option is `true`, the object will also contain a `fragmentIdentifier` property.
329
-
330
328
  @param url - The URL to parse.
329
+ @returns An object with a `url` and `query` property.
330
+
331
+ If the `parseFragmentIdentifier` option is `true`, the object will also contain a `fragmentIdentifier` property.
331
332
 
332
333
  @example
333
334
  ```
@@ -534,17 +535,80 @@ export type StringifyOptions = {
534
535
  ```
535
536
  */
536
537
  readonly skipEmptyString?: boolean;
538
+
539
+ /**
540
+ A function that transforms key-value pairs before stringification.
541
+
542
+ Similar to the `replacer` parameter of `JSON.stringify()`, this function is called for each key-value pair and can be used to transform values before they are stringified.
543
+
544
+ The function receives the key and value, and should return the transformed value. Returning `undefined` will omit the key-value pair from the resulting query string.
545
+
546
+ This is useful for custom serialization of non-primitive types like `Date`:
547
+
548
+ @example
549
+ ```
550
+ import queryString from 'query-string';
551
+
552
+ queryString.stringify({
553
+ date: new Date('2024-01-15T10:30:00Z'),
554
+ name: 'John'
555
+ }, {
556
+ replacer: (key, value) => {
557
+ if (value instanceof Date) {
558
+ return value.toISOString();
559
+ }
560
+
561
+ return value;
562
+ }
563
+ });
564
+ //=> 'date=2024-01-15T10%3A30%3A00.000Z&name=John'
565
+ ```
566
+
567
+ @example
568
+ ```
569
+ import queryString from 'query-string';
570
+
571
+ // Omit keys with null values using replacer instead of skipNull
572
+ queryString.stringify({
573
+ a: 1,
574
+ b: null,
575
+ c: 3
576
+ }, {
577
+ replacer: (key, value) => value === null ? undefined : value
578
+ });
579
+ //=> 'a=1&c=3'
580
+ ```
581
+ */
582
+ readonly replacer?: (key: string, value: unknown) => unknown;
537
583
  };
538
584
 
585
+ /**
586
+ Supported value types for query string parameters.
587
+
588
+ Note: `Symbol`, functions, and objects (except arrays) are not supported and will throw an error when stringified.
589
+ */
539
590
  export type Stringifiable = string | boolean | number | bigint | null | undefined; // eslint-disable-line @typescript-eslint/ban-types
540
591
 
592
+ /**
593
+ A record of stringifiable values.
594
+ */
541
595
  export type StringifiableRecord = Record<
542
596
  string,
543
597
  Stringifiable | readonly Stringifiable[]
544
598
  >;
545
599
 
546
600
  /**
547
- Stringify an object into a query string and sort the keys.
601
+ Stringify an object into a query string and sorting the keys.
602
+
603
+ @param object - Object to stringify. Supported value types are: `string`, `number`, `bigint`, `boolean`, `null`, `undefined`, and arrays of these types. Other types like `Symbol`, functions, or objects (except arrays) will throw an error.
604
+
605
+ @example
606
+ ```
607
+ import queryString from 'query-string';
608
+
609
+ queryString.stringify({foo: 'bar', baz: 42, qux: true});
610
+ //=> 'baz=42&foo=bar&qux=true'
611
+ ```
548
612
  */
549
613
  export function stringify(
550
614
  // TODO: Use the below instead when the following TS issues are fixed:
@@ -559,7 +623,13 @@ export function stringify(
559
623
  /**
560
624
  Extract a query string from a URL that can be passed into `.parse()`.
561
625
 
562
- Note: This behaviour can be changed with the `skipNull` option.
626
+ @example
627
+ ```
628
+ import queryString from 'query-string';
629
+
630
+ queryString.extract('https://foo.bar?foo=bar');
631
+ //=> 'foo=bar'
632
+ ```
563
633
  */
564
634
  export function extract(url: string): string;
565
635
 
@@ -580,6 +650,10 @@ export type UrlObject = {
580
650
  /**
581
651
  Stringify an object into a URL with a query string and sorting the keys. The inverse of [`.parseUrl()`](https://github.com/sindresorhus/query-string#parseurlstring-options)
582
652
 
653
+ The `options` are the same as for `.stringify()`.
654
+
655
+ @returns A string with the URL and a query string.
656
+
583
657
  Query items in the `query` property overrides queries in the `url` property.
584
658
 
585
659
  The `fragmentIdentifier` property overrides the fragment identifier in the `url` property.
package/base.js CHANGED
@@ -202,9 +202,7 @@ function parserForArrayFormat(options) {
202
202
  case 'separator': {
203
203
  return (key, value, accumulator) => {
204
204
  const isArray = typeof value === 'string' && value.includes(options.arrayFormatSeparator);
205
- const isEncodedArray = (typeof value === 'string' && !isArray && decode(value, options).includes(options.arrayFormatSeparator));
206
- value = isEncodedArray ? decode(value, options) : value;
207
- const newValue = isArray || isEncodedArray ? value.split(options.arrayFormatSeparator).map(item => decode(item, options)) : (value === null ? value : decode(value, options));
205
+ const newValue = isArray ? value.split(options.arrayFormatSeparator).map(item => decode(item, options)) : (value === null ? value : decode(value, options));
208
206
  accumulator[key] = newValue;
209
207
  };
210
208
  }
@@ -465,7 +463,17 @@ export function stringify(object, options) {
465
463
  }
466
464
 
467
465
  return keys.map(key => {
468
- const value = object[key];
466
+ let value = object[key];
467
+
468
+ // Apply replacer function if provided
469
+ if (options.replacer) {
470
+ value = options.replacer(key, value);
471
+
472
+ // If replacer returns undefined, skip this key
473
+ if (value === undefined) {
474
+ return '';
475
+ }
476
+ }
469
477
 
470
478
  if (value === undefined) {
471
479
  return '';
@@ -480,7 +488,16 @@ export function stringify(object, options) {
480
488
  return encode(key, options) + '[]';
481
489
  }
482
490
 
483
- return value
491
+ // Apply replacer to array elements if provided
492
+ // Note: We don't re-apply replacer to the array itself, only to elements
493
+ let processedArray = value;
494
+ if (options.replacer) {
495
+ processedArray = value.map((item, index) =>
496
+ options.replacer(`${key}[${index}]`, item),
497
+ ).filter(item => item !== undefined);
498
+ }
499
+
500
+ return processedArray
484
501
  .reduce(formatter(key), [])
485
502
  .join('&');
486
503
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "query-string",
3
- "version": "9.2.2",
3
+ "version": "9.3.0",
4
4
  "description": "Parse and stringify URL query strings",
5
5
  "license": "MIT",
6
6
  "repository": "sindresorhus/query-string",
package/readme.md CHANGED
@@ -52,6 +52,14 @@ Parse a query string into an object. Leading `?` or `#` are ignored, so you can
52
52
 
53
53
  The returned object is created with [`Object.create(null)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create) and thus does not have a `prototype`.
54
54
 
55
+ ```js
56
+ queryString.parse('?foo=bar');
57
+ //=> {foo: 'bar'}
58
+
59
+ queryString.parse('#token=secret&name=jhon');
60
+ //=> {token: 'secret', name: 'jhon'}
61
+ ```
62
+
55
63
  #### options
56
64
 
57
65
  Type: `object`
@@ -318,6 +326,8 @@ Parse the value as a boolean type instead of string type if it's a boolean.
318
326
 
319
327
  Stringify an object into a query string and sorting the keys.
320
328
 
329
+ **Supported value types:** `string`, `number`, `bigint`, `boolean`, `null`, `undefined`, and arrays of these types. Other types like `Symbol`, functions, or objects (except arrays) will throw an error.
330
+
321
331
  #### options
322
332
 
323
333
  Type: `object`
@@ -512,11 +522,58 @@ queryString.stringify({a: '', b: ''}, {
512
522
  //=> ''
513
523
  ```
514
524
 
525
+ ##### replacer
526
+
527
+ A function that transforms key-value pairs before stringification.
528
+
529
+ Type: `function`\
530
+ Default: `undefined`
531
+
532
+ Similar to the `replacer` parameter of `JSON.stringify()`, this function is called for each key-value pair and can be used to transform values before they are stringified. The function receives the key and value, and should return the transformed value. Returning `undefined` will omit the key-value pair from the resulting query string.
533
+
534
+ This is useful for custom serialization of non-primitive types like `Date`:
535
+
536
+ ```js
537
+ import queryString from 'query-string';
538
+
539
+ queryString.stringify({
540
+ date: new Date('2024-01-15T10:30:00Z'),
541
+ name: 'John'
542
+ }, {
543
+ replacer: (key, value) => {
544
+ if (value instanceof Date) {
545
+ return value.toISOString();
546
+ }
547
+
548
+ return value;
549
+ }
550
+ });
551
+ //=> 'date=2024-01-15T10%3A30%3A00.000Z&name=John'
552
+ ```
553
+
554
+ You can also use it to filter out keys:
555
+
556
+ ```js
557
+ import queryString from 'query-string';
558
+
559
+ queryString.stringify({
560
+ a: 1,
561
+ b: null,
562
+ c: 3
563
+ }, {
564
+ replacer: (key, value) => value === null ? undefined : value
565
+ });
566
+ //=> 'a=1&c=3'
567
+ ```
568
+
515
569
  ### .extract(string)
516
570
 
517
571
  Extract a query string from a URL that can be passed into `.parse()`.
518
572
 
519
- Note: This behaviour can be changed with the `skipNull` option.
573
+ ```js
574
+ queryString.extract('https://foo.bar?foo=bar');
575
+ //=> 'foo=bar'
576
+ ```
520
577
 
521
578
  ### .parseUrl(string, options?)
522
579