@oscarpalmer/atoms 0.187.0 → 0.187.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.
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +26 -18
- package/dist/internal/value/set.mjs +1 -1
- package/dist/query.mjs +25 -17
- package/package.json +4 -4
- package/src/internal/value/set.ts +1 -1
- package/src/query.ts +37 -28
package/dist/index.d.mts
CHANGED
|
@@ -8179,4 +8179,4 @@ declare class SizedSet<Value = unknown> extends Set<Value> {
|
|
|
8179
8179
|
get(value: Value, update?: boolean): Value | undefined;
|
|
8180
8180
|
}
|
|
8181
8181
|
//#endregion
|
|
8182
|
-
export { AnyResult, ArrayComparison, ArrayComparisonSorter, ArrayKeySorter, ArrayOrPlainObject, ArrayValueSorter, AssertProperty, Asserter, AssignOptions, Assigner, AsyncCancelableCallback, AttemptFlow, AttemptFlowPromise, type Beacon, type BeaconOptions, BuiltIns, CancelableCallback, CancelablePromise, type Color, Constructor, DiffOptions, DiffResult, DiffValue, EqualOptions, Err, EventPosition, type Events, ExtendedErr, ExtendedResult, Flow, FlowPromise, Frozen, FulfilledPromise, FuzzyConfiguration, FuzzyOptions, FuzzyResult, FuzzySearchOptions, GenericAsyncCallback, GenericCallback, type HSLAColor, type HSLColor, type Herald, Key$1 as Key, type KeyedQueue, KeyedValue, type Logger, type Memoized, type MemoizedOptions, MergeOptions, Merger, NestedArray, NestedKeys, NestedPartial, NestedValue, NestedValues, NormalizeOptions, Normalizer, NumericalKeys, NumericalValues, type Observable, type Observer, Ok, OnceAsyncCallback, OnceCallback, PROMISE_ABORT_EVENT, PROMISE_ABORT_OPTIONS, PROMISE_ERROR_NAME, PROMISE_MESSAGE_EXPECTATION_ATTEMPT, PROMISE_MESSAGE_EXPECTATION_RESULT, PROMISE_MESSAGE_EXPECTATION_TIMED, PROMISE_MESSAGE_TIMEOUT, PROMISE_STRATEGY_ALL, PROMISE_STRATEGY_DEFAULT, PROMISE_TYPE_FULFILLED, PROMISE_TYPE_REJECTED, PlainObject, Primitive, PromiseData, PromiseHandlers, PromiseOptions, PromiseParameters, PromiseStrategy, PromiseTimeoutError, PromisesItems, PromisesOptions, PromisesResult, PromisesUnwrapped, PromisesValue, PromisesValues, type Queue, type QueueError, type QueueOptions, type Queued, type QueuedResult, type RGBAColor, type RGBColor, RejectedPromise, RequiredKeys, Result, ResultMatch, RetryError, RetryOptions, SORT_DIRECTION_ASCENDING, SORT_DIRECTION_DESCENDING, Shaken, Simplify, SizedMap, SizedSet, Smushed, SortDirection, Sorter, type Subscription, TemplateOptions, type Timed, ToString, Transformer, TypedArray, UnionToIntersection, Unsmushed, Unsubscriber, UnwrapValue, assert, assertCondition, assertDefined, assertInstanceOf, assertIs, assertProperty, assign, asyncAttempt, asyncDebounce, asyncFlow, asyncMatchResult, asyncOnce, asyncPipe, asyncThrottle, attempt, attemptAsyncFlow, attemptAsyncPipe, attemptFlow, attemptPipe, attemptPromise, average, beacon, between, camelCase, cancelable, capitalize, ceil, chunk, clamp, clone, compact, compare, copy, count, debounce, deburr, dedent, delay, deregisterCloner, deregisterComparator, deregisterEqualizer, diff, difference, drop, endsWith, endsWithArray, equal, error, exclude, exists, filter, find, findLast, first, firstOrDefault, flatFreeze, flatten, floor, flow, freeze, fromQuery, toPromise as fromResult, toPromise, fuzzy, fuzzyMatch, getArray, getArrayComparison, getColor, getError, getForegroundColor, getHexColor, getHexaColor, getHslColor, getHslaColor, getNormalizedHex, getNumber, getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloatingNumber as getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems, getRgbColor, getRgbaColor, getSortedIndex, getString, getTimedPromise, getUuid, getValue, groupArraysBy, groupBy, handleResult, hasValue, hasValueResult, herald, hexToHsl, hexToHsla, hexToRgb, hexToRgba, hslToHex, hslToRgb, hslToRgba, ignoreKey, inMap, inSet, includes, includesArray, indexOf, indexOfArray, initializeAssigner, initializeEqualizer, initializeMerger, initializeNormalizer, initializeSorter, initializeTemplater, initializeTransformer, insert, interpolate, intersection, isArrayOrPlainObject, isColor, isConstructor, isEmpty, isError, isFrozen, isFulfilled, isHexColor, isHslColor, isHslLike, isHslaColor, isInstanceOf, isKey, isNonArrayOrPlainObject, isNonConstructor, isNonEmpty, isNonInstanceOf, isNonKey, isNonNullable, isNonNullableOrEmpty, isNonNullableOrWhitespace, isNonNumber, isNonNumerical, isNonObject, isNonPlainObject, isNonPrimitive, isNonTypedArray, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isOk, isPlainObject, isPrimitive, isRejected, isResult, isRgbColor, isRgbLike, isRgbaColor, isSorted, isTypedArray, join, kebabCase, keyedQueue, last, lastIndexOf, lastOrDefault, logger, lowerCase, matchResult, max, median, memoize, merge, min, move, moveIndices, moveToIndex, noop, normalize, ok, omit, once, parse, partition, pascalCase, pick, pipe, promises, push, queue, range, registerCloner, registerComparator, registerEqualizer, resultPromises, retry, reverse, rgbToHex, rgbToHsl, rgbToHsla, round, select, setValue, settlePromise, shake, shuffle, single, slice, smush, snakeCase, sort, splice, startsWith, startsWithArray, sum, swap, take, template, throttle, timed, times, titleCase, toMap, toMapArrays, toQuery, toRecord, toRecordArrays, toResult, toSet, toggle, transform, trim, truncate, tryDecode, tryEncode, union, unique, unsmush, unwrap, update, upperCase, words };
|
|
8182
|
+
export { AnyResult, ArrayComparison, ArrayComparisonSorter, ArrayKeySorter, ArrayOrPlainObject, ArrayValueSorter, AssertProperty, Asserter, AssignOptions, Assigner, AsyncCancelableCallback, AttemptFlow, AttemptFlowPromise, type Beacon, type BeaconOptions, BuiltIns, CancelableCallback, CancelablePromise, type Color, Constructor, DiffOptions, DiffResult, DiffValue, EqualOptions, Err, EventPosition, type Events, ExtendedErr, ExtendedResult, Flow, FlowPromise, Frozen, FulfilledPromise, FuzzyConfiguration, FuzzyOptions, FuzzyResult, FuzzySearchOptions, GenericAsyncCallback, GenericCallback, type HSLAColor, type HSLColor, type Herald, Key$1 as Key, type KeyedQueue, KeyedValue, type Logger, type Memoized, type MemoizedOptions, MergeOptions, Merger, NestedArray, NestedKeys, NestedPartial, NestedValue, NestedValues, NormalizeOptions, Normalizer, NumericalKeys, NumericalValues, type Observable, type Observer, Ok, OnceAsyncCallback, OnceCallback, PROMISE_ABORT_EVENT, PROMISE_ABORT_OPTIONS, PROMISE_ERROR_NAME, PROMISE_MESSAGE_EXPECTATION_ATTEMPT, PROMISE_MESSAGE_EXPECTATION_RESULT, PROMISE_MESSAGE_EXPECTATION_TIMED, PROMISE_MESSAGE_TIMEOUT, PROMISE_STRATEGY_ALL, PROMISE_STRATEGY_DEFAULT, PROMISE_TYPE_FULFILLED, PROMISE_TYPE_REJECTED, PlainObject, Primitive, PromiseData, PromiseHandlers, PromiseOptions, PromiseParameters, PromiseStrategy, PromiseTimeoutError, PromisesItems, PromisesOptions, PromisesResult, PromisesUnwrapped, PromisesValue, PromisesValues, type Queue, type QueueError, type QueueOptions, type Queued, type QueuedResult, type RGBAColor, type RGBColor, RejectedPromise, RequiredKeys, Result, ResultMatch, RetryError, RetryOptions, SORT_DIRECTION_ASCENDING, SORT_DIRECTION_DESCENDING, type Shaken, Simplify, SizedMap, SizedSet, type Smushed, SortDirection, Sorter, type Subscription, TemplateOptions, type Timed, ToString, Transformer, TypedArray, UnionToIntersection, type Unsmushed, Unsubscriber, UnwrapValue, assert, assertCondition, assertDefined, assertInstanceOf, assertIs, assertProperty, assign, asyncAttempt, asyncDebounce, asyncFlow, asyncMatchResult, asyncOnce, asyncPipe, asyncThrottle, attempt, attemptAsyncFlow, attemptAsyncPipe, attemptFlow, attemptPipe, attemptPromise, average, beacon, between, camelCase, cancelable, capitalize, ceil, chunk, clamp, clone, compact, compare, copy, count, debounce, deburr, dedent, delay, deregisterCloner, deregisterComparator, deregisterEqualizer, diff, difference, drop, endsWith, endsWithArray, equal, error, exclude, exists, filter, find, findLast, first, firstOrDefault, flatFreeze, flatten, floor, flow, freeze, fromQuery, toPromise as fromResult, toPromise, fuzzy, fuzzyMatch, getArray, getArrayComparison, getColor, getError, getForegroundColor, getHexColor, getHexaColor, getHslColor, getHslaColor, getNormalizedHex, getNumber, getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloatingNumber as getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems, getRgbColor, getRgbaColor, getSortedIndex, getString, getTimedPromise, getUuid, getValue, groupArraysBy, groupBy, handleResult, hasValue, hasValueResult, herald, hexToHsl, hexToHsla, hexToRgb, hexToRgba, hslToHex, hslToRgb, hslToRgba, ignoreKey, inMap, inSet, includes, includesArray, indexOf, indexOfArray, initializeAssigner, initializeEqualizer, initializeMerger, initializeNormalizer, initializeSorter, initializeTemplater, initializeTransformer, insert, interpolate, intersection, isArrayOrPlainObject, isColor, isConstructor, isEmpty, isError, isFrozen, isFulfilled, isHexColor, isHslColor, isHslLike, isHslaColor, isInstanceOf, isKey, isNonArrayOrPlainObject, isNonConstructor, isNonEmpty, isNonInstanceOf, isNonKey, isNonNullable, isNonNullableOrEmpty, isNonNullableOrWhitespace, isNonNumber, isNonNumerical, isNonObject, isNonPlainObject, isNonPrimitive, isNonTypedArray, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isOk, isPlainObject, isPrimitive, isRejected, isResult, isRgbColor, isRgbLike, isRgbaColor, isSorted, isTypedArray, join, kebabCase, keyedQueue, last, lastIndexOf, lastOrDefault, logger, lowerCase, matchResult, max, median, memoize, merge, min, move, moveIndices, moveToIndex, noop, normalize, ok, omit, once, parse, partition, pascalCase, pick, pipe, promises, push, queue, range, registerCloner, registerComparator, registerEqualizer, resultPromises, retry, reverse, rgbToHex, rgbToHsl, rgbToHsla, round, select, setValue, settlePromise, shake, shuffle, single, slice, smush, snakeCase, sort, splice, startsWith, startsWithArray, sum, swap, take, template, throttle, timed, times, titleCase, toMap, toMapArrays, toQuery, toRecord, toRecordArrays, toResult, toSet, toggle, transform, trim, truncate, tryDecode, tryEncode, union, unique, unsmush, unwrap, update, upperCase, words };
|
package/dist/index.mjs
CHANGED
|
@@ -2535,7 +2535,7 @@ function setValue(data, path, value, ignoreCase) {
|
|
|
2535
2535
|
let next = handleValue(target, currentPath, null, true, shouldIgnoreCase).value;
|
|
2536
2536
|
if (typeof next !== "object" || next === null) {
|
|
2537
2537
|
const nextPath = paths[index + 1];
|
|
2538
|
-
if (EXPRESSION_INDEX.test(nextPath)) next = Array.from({ length: Number
|
|
2538
|
+
if (EXPRESSION_INDEX.test(nextPath)) next = Array.from({ length: Number(nextPath) + 1 }, () => void 0);
|
|
2539
2539
|
else next = {};
|
|
2540
2540
|
target[currentPath] = next;
|
|
2541
2541
|
}
|
|
@@ -5322,13 +5322,26 @@ async function resultPromises(items, signal) {
|
|
|
5322
5322
|
*/
|
|
5323
5323
|
function fromQuery(query) {
|
|
5324
5324
|
if (typeof query !== "string" || query.trim().length === 0) return {};
|
|
5325
|
-
const parts = query.split(AMPERSAND);
|
|
5325
|
+
const parts = query.split(AMPERSAND).map((part) => part.split(EQUAL).map(tryDecode)).sort(([first], [second]) => first.localeCompare(second));
|
|
5326
5326
|
const { length } = parts;
|
|
5327
5327
|
const parameters = {};
|
|
5328
|
+
let position = 0;
|
|
5329
|
+
let array;
|
|
5328
5330
|
for (let index = 0; index < length; index += 1) {
|
|
5329
|
-
const
|
|
5330
|
-
|
|
5331
|
-
|
|
5331
|
+
const [key, value] = parts[index];
|
|
5332
|
+
if (EXPRESSION_ARRAY_SUFFIX.test(key)) {
|
|
5333
|
+
const named = key.replace(EXPRESSION_ARRAY_SUFFIX, "");
|
|
5334
|
+
if (named !== array) {
|
|
5335
|
+
array = named;
|
|
5336
|
+
position = 0;
|
|
5337
|
+
}
|
|
5338
|
+
} else {
|
|
5339
|
+
array = void 0;
|
|
5340
|
+
position = 0;
|
|
5341
|
+
}
|
|
5342
|
+
const full = array == null ? key : `${array}.${position}`;
|
|
5343
|
+
if (!ignoreKey(full)) setValue(parameters, full, getQueryValue(value));
|
|
5344
|
+
position += 1;
|
|
5332
5345
|
}
|
|
5333
5346
|
return parameters;
|
|
5334
5347
|
}
|
|
@@ -5339,11 +5352,13 @@ function getParts(value, fromArray, prefix) {
|
|
|
5339
5352
|
for (let index = 0; index < length; index += 1) {
|
|
5340
5353
|
const key = keys[index];
|
|
5341
5354
|
const val = value[key];
|
|
5342
|
-
const
|
|
5343
|
-
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
else if (val
|
|
5355
|
+
const fullKey = join([prefix, fromArray ? void 0 : key], DOT);
|
|
5356
|
+
const encodedKey = getString(tryEncode(fullKey));
|
|
5357
|
+
const prefixedKey = fromArray ? join([encodedKey, index], DOT) : encodedKey;
|
|
5358
|
+
if (Array.isArray(val)) parts.push(...getParts(val, true, fullKey));
|
|
5359
|
+
else if (isPlainObject(val)) parts.push(...getParts(val, false, fullKey));
|
|
5360
|
+
else if (isDecodable(val)) parts.push(`${prefixedKey}=${getString(tryEncode(val))}`);
|
|
5361
|
+
else if (val instanceof Date) parts.push(`${prefixedKey}=${val.toJSON()}`);
|
|
5347
5362
|
}
|
|
5348
5363
|
return parts;
|
|
5349
5364
|
}
|
|
@@ -5359,13 +5374,6 @@ function getQueryValue(value) {
|
|
|
5359
5374
|
function isDecodable(value) {
|
|
5360
5375
|
return TYPES.has(typeof value);
|
|
5361
5376
|
}
|
|
5362
|
-
function setQueryValue(parameters, key, value) {
|
|
5363
|
-
if (EXPRESSION_DOT.test(key)) setValue(parameters, key, getQueryValue(value));
|
|
5364
|
-
else if (key in parameters) {
|
|
5365
|
-
if (!Array.isArray(parameters[key])) parameters[key] = [parameters[key]];
|
|
5366
|
-
parameters[key].push(getQueryValue(value));
|
|
5367
|
-
} else parameters[key] = getQueryValue(value);
|
|
5368
|
-
}
|
|
5369
5377
|
/**
|
|
5370
5378
|
* Convert a plain _(nested)_ object to a query string
|
|
5371
5379
|
*
|
|
@@ -5376,10 +5384,10 @@ function toQuery(parameters) {
|
|
|
5376
5384
|
return isPlainObject(parameters) ? join(getParts(parameters, false).filter((part) => part.length > 0), AMPERSAND) : "";
|
|
5377
5385
|
}
|
|
5378
5386
|
const AMPERSAND = "&";
|
|
5387
|
+
const DOT = ".";
|
|
5379
5388
|
const EQUAL = "=";
|
|
5380
5389
|
const EXPRESSION_ARRAY_SUFFIX = /\[\]$/;
|
|
5381
5390
|
const EXPRESSION_BOOLEAN = /^(false|true)$/;
|
|
5382
|
-
const EXPRESSION_DOT = /\./g;
|
|
5383
5391
|
const TRUE = "true";
|
|
5384
5392
|
const TYPES = new Set([
|
|
5385
5393
|
"boolean",
|
|
@@ -20,7 +20,7 @@ function setValue(data, path, value, ignoreCase) {
|
|
|
20
20
|
let next = handleValue(target, currentPath, null, true, shouldIgnoreCase).value;
|
|
21
21
|
if (typeof next !== "object" || next === null) {
|
|
22
22
|
const nextPath = paths[index + 1];
|
|
23
|
-
if (EXPRESSION_INDEX.test(nextPath)) next = Array.from({ length: Number
|
|
23
|
+
if (EXPRESSION_INDEX.test(nextPath)) next = Array.from({ length: Number(nextPath) + 1 }, () => void 0);
|
|
24
24
|
else next = {};
|
|
25
25
|
target[currentPath] = next;
|
|
26
26
|
}
|
package/dist/query.mjs
CHANGED
|
@@ -11,13 +11,26 @@ import { setValue } from "./internal/value/set.mjs";
|
|
|
11
11
|
*/
|
|
12
12
|
function fromQuery(query) {
|
|
13
13
|
if (typeof query !== "string" || query.trim().length === 0) return {};
|
|
14
|
-
const parts = query.split(AMPERSAND);
|
|
14
|
+
const parts = query.split(AMPERSAND).map((part) => part.split(EQUAL).map(tryDecode)).sort(([first], [second]) => first.localeCompare(second));
|
|
15
15
|
const { length } = parts;
|
|
16
16
|
const parameters = {};
|
|
17
|
+
let position = 0;
|
|
18
|
+
let array;
|
|
17
19
|
for (let index = 0; index < length; index += 1) {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
const [key, value] = parts[index];
|
|
21
|
+
if (EXPRESSION_ARRAY_SUFFIX.test(key)) {
|
|
22
|
+
const named = key.replace(EXPRESSION_ARRAY_SUFFIX, "");
|
|
23
|
+
if (named !== array) {
|
|
24
|
+
array = named;
|
|
25
|
+
position = 0;
|
|
26
|
+
}
|
|
27
|
+
} else {
|
|
28
|
+
array = void 0;
|
|
29
|
+
position = 0;
|
|
30
|
+
}
|
|
31
|
+
const full = array == null ? key : `${array}.${position}`;
|
|
32
|
+
if (!ignoreKey(full)) setValue(parameters, full, getQueryValue(value));
|
|
33
|
+
position += 1;
|
|
21
34
|
}
|
|
22
35
|
return parameters;
|
|
23
36
|
}
|
|
@@ -28,11 +41,13 @@ function getParts(value, fromArray, prefix) {
|
|
|
28
41
|
for (let index = 0; index < length; index += 1) {
|
|
29
42
|
const key = keys[index];
|
|
30
43
|
const val = value[key];
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
else if (val
|
|
44
|
+
const fullKey = join([prefix, fromArray ? void 0 : key], DOT);
|
|
45
|
+
const encodedKey = getString(tryEncode(fullKey));
|
|
46
|
+
const prefixedKey = fromArray ? join([encodedKey, index], DOT) : encodedKey;
|
|
47
|
+
if (Array.isArray(val)) parts.push(...getParts(val, true, fullKey));
|
|
48
|
+
else if (isPlainObject(val)) parts.push(...getParts(val, false, fullKey));
|
|
49
|
+
else if (isDecodable(val)) parts.push(`${prefixedKey}=${getString(tryEncode(val))}`);
|
|
50
|
+
else if (val instanceof Date) parts.push(`${prefixedKey}=${val.toJSON()}`);
|
|
36
51
|
}
|
|
37
52
|
return parts;
|
|
38
53
|
}
|
|
@@ -48,13 +63,6 @@ function getQueryValue(value) {
|
|
|
48
63
|
function isDecodable(value) {
|
|
49
64
|
return TYPES.has(typeof value);
|
|
50
65
|
}
|
|
51
|
-
function setQueryValue(parameters, key, value) {
|
|
52
|
-
if (EXPRESSION_DOT.test(key)) setValue(parameters, key, getQueryValue(value));
|
|
53
|
-
else if (key in parameters) {
|
|
54
|
-
if (!Array.isArray(parameters[key])) parameters[key] = [parameters[key]];
|
|
55
|
-
parameters[key].push(getQueryValue(value));
|
|
56
|
-
} else parameters[key] = getQueryValue(value);
|
|
57
|
-
}
|
|
58
66
|
/**
|
|
59
67
|
* Convert a plain _(nested)_ object to a query string
|
|
60
68
|
*
|
|
@@ -65,10 +73,10 @@ function toQuery(parameters) {
|
|
|
65
73
|
return isPlainObject(parameters) ? join(getParts(parameters, false).filter((part) => part.length > 0), AMPERSAND) : "";
|
|
66
74
|
}
|
|
67
75
|
const AMPERSAND = "&";
|
|
76
|
+
const DOT = ".";
|
|
68
77
|
const EQUAL = "=";
|
|
69
78
|
const EXPRESSION_ARRAY_SUFFIX = /\[\]$/;
|
|
70
79
|
const EXPRESSION_BOOLEAN = /^(false|true)$/;
|
|
71
|
-
const EXPRESSION_DOT = /\./g;
|
|
72
80
|
const TRUE = "true";
|
|
73
81
|
const TYPES = new Set([
|
|
74
82
|
"boolean",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oscarpalmer/atoms",
|
|
3
|
-
"version": "0.187.
|
|
3
|
+
"version": "0.187.1",
|
|
4
4
|
"description": "Atomic utilities for making your JavaScript better.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"helper",
|
|
@@ -257,10 +257,10 @@
|
|
|
257
257
|
"watch": "npx vite build --watch"
|
|
258
258
|
},
|
|
259
259
|
"devDependencies": {
|
|
260
|
-
"@oxlint/plugins": "^1.
|
|
261
|
-
"@types/node": "^25.
|
|
260
|
+
"@oxlint/plugins": "^1.66",
|
|
261
|
+
"@types/node": "^25.9",
|
|
262
262
|
"@vitest/coverage-istanbul": "^4.1",
|
|
263
|
-
"eslint": "^10.
|
|
263
|
+
"eslint": "^10.4",
|
|
264
264
|
"jsdom": "^29.1",
|
|
265
265
|
"tsdown": "^0.22",
|
|
266
266
|
"typescript": "^6",
|
|
@@ -109,7 +109,7 @@ export function setValue(data: object, path: string, value: unknown, ignoreCase?
|
|
|
109
109
|
const nextPath = paths[index + 1];
|
|
110
110
|
|
|
111
111
|
if (EXPRESSION_INDEX.test(nextPath)) {
|
|
112
|
-
next = Array.from({length: Number
|
|
112
|
+
next = Array.from({length: Number(nextPath) + 1}, () => undefined);
|
|
113
113
|
} else {
|
|
114
114
|
next = {};
|
|
115
115
|
}
|
package/src/query.ts
CHANGED
|
@@ -17,18 +17,40 @@ export function fromQuery(query: string): PlainObject {
|
|
|
17
17
|
return {};
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
const parts = query
|
|
20
|
+
const parts = query
|
|
21
|
+
.split(AMPERSAND)
|
|
22
|
+
.map(part => part.split(EQUAL).map(tryDecode))
|
|
23
|
+
.sort(([first], [second]) => first.localeCompare(second));
|
|
24
|
+
|
|
21
25
|
const {length} = parts;
|
|
22
26
|
|
|
23
27
|
const parameters: PlainObject = {};
|
|
24
28
|
|
|
29
|
+
let position = 0;
|
|
30
|
+
let array: string | undefined;
|
|
31
|
+
|
|
25
32
|
for (let index = 0; index < length; index += 1) {
|
|
26
|
-
const
|
|
27
|
-
|
|
33
|
+
const [key, value] = parts[index];
|
|
34
|
+
|
|
35
|
+
if (EXPRESSION_ARRAY_SUFFIX.test(key)) {
|
|
36
|
+
const named = key.replace(EXPRESSION_ARRAY_SUFFIX, '');
|
|
37
|
+
|
|
38
|
+
if (named !== array) {
|
|
39
|
+
array = named;
|
|
40
|
+
position = 0;
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
array = undefined;
|
|
44
|
+
position = 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const full = array == null ? key : `${array}.${position}`;
|
|
28
48
|
|
|
29
|
-
if (!ignoreKey(
|
|
30
|
-
|
|
49
|
+
if (!ignoreKey(full)) {
|
|
50
|
+
setValue(parameters, full, getQueryValue(value));
|
|
31
51
|
}
|
|
52
|
+
|
|
53
|
+
position += 1;
|
|
32
54
|
}
|
|
33
55
|
|
|
34
56
|
return parameters;
|
|
@@ -44,16 +66,19 @@ function getParts(value: ArrayOrPlainObject, fromArray: boolean, prefix?: string
|
|
|
44
66
|
const key = keys[index];
|
|
45
67
|
const val = value[key as never];
|
|
46
68
|
|
|
47
|
-
const
|
|
69
|
+
const fullKey = join([prefix, fromArray ? undefined : key], DOT);
|
|
70
|
+
|
|
71
|
+
const encodedKey = getString(tryEncode(fullKey));
|
|
72
|
+
const prefixedKey = fromArray ? join([encodedKey, index], DOT) : encodedKey;
|
|
48
73
|
|
|
49
74
|
if (Array.isArray(val)) {
|
|
50
|
-
parts.push(...getParts(val, true,
|
|
75
|
+
parts.push(...getParts(val, true, fullKey));
|
|
51
76
|
} else if (isPlainObject(val)) {
|
|
52
|
-
parts.push(...getParts(val, false,
|
|
77
|
+
parts.push(...getParts(val, false, fullKey));
|
|
53
78
|
} else if (isDecodable(val)) {
|
|
54
|
-
parts.push(`${
|
|
79
|
+
parts.push(`${prefixedKey}=${getString(tryEncode(val))}`);
|
|
55
80
|
} else if (val instanceof Date) {
|
|
56
|
-
parts.push(`${
|
|
81
|
+
parts.push(`${prefixedKey}=${val.toJSON()}`);
|
|
57
82
|
}
|
|
58
83
|
}
|
|
59
84
|
|
|
@@ -86,22 +111,6 @@ function isDecodable(value: unknown): value is boolean | number | string {
|
|
|
86
111
|
return TYPES.has(typeof value);
|
|
87
112
|
}
|
|
88
113
|
|
|
89
|
-
function setQueryValue(parameters: PlainObject, key: string, value: string): void {
|
|
90
|
-
if (EXPRESSION_DOT.test(key)) {
|
|
91
|
-
setValue(parameters, key, getQueryValue(value));
|
|
92
|
-
} else {
|
|
93
|
-
if (key in parameters) {
|
|
94
|
-
if (!Array.isArray(parameters[key])) {
|
|
95
|
-
parameters[key] = [parameters[key]];
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
(parameters[key] as unknown[]).push(getQueryValue(value) as never);
|
|
99
|
-
} else {
|
|
100
|
-
parameters[key] = getQueryValue(value) as never;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
114
|
/**
|
|
106
115
|
* Convert a plain _(nested)_ object to a query string
|
|
107
116
|
*
|
|
@@ -123,14 +132,14 @@ export function toQuery(parameters: PlainObject): string {
|
|
|
123
132
|
|
|
124
133
|
const AMPERSAND = '&';
|
|
125
134
|
|
|
135
|
+
const DOT = '.';
|
|
136
|
+
|
|
126
137
|
const EQUAL = '=';
|
|
127
138
|
|
|
128
139
|
const EXPRESSION_ARRAY_SUFFIX = /\[\]$/;
|
|
129
140
|
|
|
130
141
|
const EXPRESSION_BOOLEAN = /^(false|true)$/;
|
|
131
142
|
|
|
132
|
-
const EXPRESSION_DOT = /\./g;
|
|
133
|
-
|
|
134
143
|
const TRUE = 'true';
|
|
135
144
|
|
|
136
145
|
const TYPES = new Set(['boolean', 'number', 'string']);
|