Skip to content

Commit

Permalink
Merge pull request #22 from cdeutsch/sync-query-string-v6.14.1
Browse files Browse the repository at this point in the history
Sync query string v6.14.1
  • Loading branch information
cdeutsch authored Jul 27, 2021
2 parents 7c16897 + cdc4729 commit a85633c
Show file tree
Hide file tree
Showing 11 changed files with 307 additions and 11 deletions.
24 changes: 24 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: CI
on:
- push
- pull_request
jobs:
test:
name: Node.js ${{ matrix.node-version }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version:
- 14
- 12
- 10
- 8
- 6
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm test
7 changes: 0 additions & 7 deletions .travis.yml

This file was deleted.

56 changes: 56 additions & 0 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ var decodeComponent = __webpack_require__(2);

var splitOnFirst = __webpack_require__(3);

var filterObject = __webpack_require__(4);

var isNullOrUndefined = function isNullOrUndefined(value) {
return value === null || value === undefined;
};
Expand Down Expand Up @@ -362,6 +364,10 @@ function parse(query, options) {
for (var _iterator = query.split('&')[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var param = _step.value;

if (param === '') {
continue;
}

var _splitOnFirst = splitOnFirst(options.decode ? param.replace(/\+/g, ' ') : param, '='),
_splitOnFirst2 = _slicedToArray(_splitOnFirst, 2),
key = _splitOnFirst2[0],
Expand Down Expand Up @@ -521,6 +527,32 @@ exports.stringifyUrl = function (object, options) {
return "".concat(url).concat(queryString).concat(hash);
};

exports.pick = function (input, filter, options) {
options = Object.assign({
parseFragmentIdentifier: true
}, options);

var _exports$parseUrl = exports.parseUrl(input, options),
url = _exports$parseUrl.url,
query = _exports$parseUrl.query,
fragmentIdentifier = _exports$parseUrl.fragmentIdentifier;

return exports.stringifyUrl({
url: url,
query: filterObject(query, filter),
fragmentIdentifier: fragmentIdentifier
}, options);
};

exports.exclude = function (input, filter, options) {
var exclusionFilter = Array.isArray(filter) ? function (key) {
return !filter.includes(key);
} : function (key, value) {
return !filter(key, value);
};
return exports.pick(input, exclusionFilter, options);
};

/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
Expand Down Expand Up @@ -656,5 +688,29 @@ module.exports = function (string, separator) {
return [string.slice(0, separatorIndex), string.slice(separatorIndex + separator.length)];
};

/***/ }),
/* 4 */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


module.exports = function (obj, predicate) {
var ret = {};
var keys = Object.keys(obj);
var isArr = Array.isArray(predicate);

for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var val = obj[key];

if (isArr ? predicate.indexOf(key) !== -1 : predicate(key, val, obj)) {
ret[key] = val;
}
}

return ret;
};

/***/ })
/******/ ]);
87 changes: 85 additions & 2 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,12 @@ export type StringifiableRecord = Record<
Stringify an object into a query string and sort the keys.
*/
export function stringify(
object: StringifiableRecord,
// TODO: Use the below instead when the following TS issues are fixed:
// - https://github.com/microsoft/TypeScript/issues/15300
// - https://github.com/microsoft/TypeScript/issues/42021
// Context: https://github.com/sindresorhus/query-string/issues/298
// object: StringifiableRecord,
object: Record<string, any>,
options?: StringifyOptions
): string;

Expand All @@ -367,7 +372,7 @@ export interface UrlObject {
/**
Overrides queries in the `url` property.
*/
readonly query: StringifiableRecord;
readonly query?: StringifiableRecord;

/**
Overrides the fragment identifier in the `url` property.
Expand Down Expand Up @@ -404,3 +409,81 @@ export function stringifyUrl(
object: UrlObject,
options?: StringifyOptions
): string;

/**
Pick query parameters from a URL.
@param url - The URL containing the query parameters to pick.
@param keys - The names of the query parameters to keep. All other query parameters will be removed from the URL.
@param filter - A filter predicate that will be provided the name of each query parameter and its value. The `parseNumbers` and `parseBooleans` options also affect `value`.
@returns The URL with the picked query parameters.
@example
```
queryString.pick('https://foo.bar?foo=1&bar=2#hello', ['foo']);
//=> 'https://foo.bar?foo=1#hello'
queryString.pick('https://foo.bar?foo=1&bar=2#hello', (name, value) => value === 2, {parseNumbers: true});
//=> 'https://foo.bar?bar=2#hello'
```
*/
export function pick(
url: string,
keys: readonly string[],
options?: ParseOptions & StringifyOptions
): string
export function pick(
url: string,
filter: (key: string, value: string | boolean | number) => boolean,
options?: {parseBooleans: true, parseNumbers: true} & ParseOptions & StringifyOptions
): string
export function pick(
url: string,
filter: (key: string, value: string | boolean) => boolean,
options?: {parseBooleans: true} & ParseOptions & StringifyOptions
): string
export function pick(
url: string,
filter: (key: string, value: string | number) => boolean,
options?: {parseNumbers: true} & ParseOptions & StringifyOptions
): string

/**
Exclude query parameters from a URL. Like `.pick()` but reversed.
@param url - The URL containing the query parameters to exclude.
@param keys - The names of the query parameters to remove. All other query parameters will remain in the URL.
@param filter - A filter predicate that will be provided the name of each query parameter and its value. The `parseNumbers` and `parseBooleans` options also affect `value`.
@returns The URL without the excluded the query parameters.
@example
```
queryString.exclude('https://foo.bar?foo=1&bar=2#hello', ['foo']);
//=> 'https://foo.bar?bar=2#hello'
queryString.exclude('https://foo.bar?foo=1&bar=2#hello', (name, value) => value === 2, {parseNumbers: true});
//=> 'https://foo.bar?foo=1#hello'
```
*/
export function exclude(
url: string,
keys: readonly string[],
options?: ParseOptions & StringifyOptions
): string
export function exclude(
url: string,
filter: (key: string, value: string | boolean | number) => boolean,
options?: {parseBooleans: true, parseNumbers: true} & ParseOptions & StringifyOptions
): string
export function exclude(
url: string,
filter: (key: string, value: string | boolean) => boolean,
options?: {parseBooleans: true} & ParseOptions & StringifyOptions
): string
export function exclude(
url: string,
filter: (key: string, value: string | number) => boolean,
options?: {parseNumbers: true} & ParseOptions & StringifyOptions
): string
24 changes: 24 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
const strictUriEncode = require('strict-uri-encode');
const decodeComponent = require('decode-uri-component');
const splitOnFirst = require('split-on-first');
const filterObject = require('filter-obj');

const isNullOrUndefined = value => value === null || value === undefined;

Expand Down Expand Up @@ -244,6 +245,10 @@ function parse(query, options) {
}

for (const param of query.split('&')) {
if (param === '') {
continue;
}

let [key, value] = splitOnFirst(options.decode ? param.replace(/\+/g, ' ') : param, '=');

// Missing `=` should be `null`:
Expand Down Expand Up @@ -378,3 +383,22 @@ exports.stringifyUrl = (object, options) => {

return `${url}${queryString}${hash}`;
};

exports.pick = (input, filter, options) => {
options = Object.assign({
parseFragmentIdentifier: true
}, options);

const {url, query, fragmentIdentifier} = exports.parseUrl(input, options);
return exports.stringifyUrl({
url,
query: filterObject(query, filter),
fragmentIdentifier
}, options);
};

exports.exclude = (input, filter, options) => {
const exclusionFilter = Array.isArray(filter) ? key => !filter.includes(key) : (key, value) => !filter(key, value);

return exports.pick(input, exclusionFilter, options);
};
17 changes: 17 additions & 0 deletions index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ expectType<string>(
)
);

// Ensure it accepts an `interface`.
interface Query {
foo: string;
}

const query: Query = {
foo: 'bar'
};

queryString.stringify(query);

// Parse
expectType<queryString.ParsedQuery>(queryString.parse('?foo=bar'));

Expand Down Expand Up @@ -113,3 +124,9 @@ expectType<string>(
},
})
);

// Pick
expectType<string>(queryString.pick('http://foo.bar/?abc=def&hij=klm', ['abc']))

// Exclude
expectType<string>(queryString.exclude('http://foo.bar/?abc=def&hij=klm', ['abc']))
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "query-string-for-all",
"version": "6.13.7",
"version": "6.14.1",
"description": "Parse and stringify URL query strings",
"license": "MIT",
"repository": "cdeutsch/query-string-for-all",
Expand Down Expand Up @@ -36,7 +36,8 @@
"stringify",
"encode",
"decode",
"searchparams"
"searchparams",
"filter"
],
"dependencies": {},
"devDependencies": {
Expand All @@ -49,6 +50,7 @@
"benchmark": "^2.1.4",
"deep-equal": "^1.0.1",
"fast-check": "^1.5.0",
"filter-obj": "^1.1.0",
"split-on-first": "^1.0.0",
"strict-uri-encode": "^2.0.0",
"tsd": "^0.7.3",
Expand Down
58 changes: 58 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,64 @@ Type: `object`

Query items to add to the URL.

### .pick(url, keys, options?)
### .pick(url, filter, options?)

Pick query parameters from a URL.

Returns a string with the new URL.

```js
const queryString = require('query-string');

queryString.pick('https://foo.bar?foo=1&bar=2#hello', ['foo']);
//=> 'https://foo.bar?foo=1#hello'

queryString.pick('https://foo.bar?foo=1&bar=2#hello', (name, value) => value === 2, {parseNumbers: true});
//=> 'https://foo.bar?bar=2#hello'
```

### .exclude(url, keys, options?)
### .exclude(url, filter, options?)

Exclude query parameters from a URL.

Returns a string with the new URL.

```js
const queryString = require('query-string');

queryString.exclude('https://foo.bar?foo=1&bar=2#hello', ['foo']);
//=> 'https://foo.bar?bar=2#hello'

queryString.exclude('https://foo.bar?foo=1&bar=2#hello', (name, value) => value === 2, {parseNumbers: true});
//=> 'https://foo.bar?foo=1#hello'
```

#### url

Type: `string`

The URL containing the query parameters to filter.

#### keys

Type: `string[]`

The names of the query parameters to filter based on the function used.

#### filter

Type: `(key, value) => boolean`

A filter predicate that will be provided the name of each query parameter and its value. The `parseNumbers` and `parseBooleans` options also affect `value`.

#### options

Type: `object`

[Parse options](#options) and [stringify options](#options-1).

## Nesting

This module intentionally doesn't support nesting as it's not spec'd and varies between implementations, which causes a lot of [edge cases](https://github.com/visionmedia/node-querystring/issues).
Expand Down
Loading

0 comments on commit a85633c

Please sign in to comment.