atomic-fns 1.1.7 → 2.0.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/README.md +405 -60
- package/dist/array/index.d.ts +9 -0
- package/dist/array/index.js +9 -0
- package/dist/array/list.d.ts +99 -0
- package/dist/array/list.js +133 -0
- package/dist/array/sets.d.ts +130 -0
- package/dist/array/sets.js +213 -0
- package/dist/async/index.d.ts +6 -0
- package/dist/async/index.js +6 -0
- package/dist/async/retry.d.ts +38 -0
- package/dist/async/retry.js +56 -0
- package/dist/async/sleep.d.ts +42 -0
- package/dist/async/sleep.js +76 -0
- package/dist/collections/bisect.d.ts +103 -0
- package/dist/collections/bisect.js +157 -0
- package/dist/collections/deque.d.ts +67 -97
- package/dist/collections/deque.js +197 -249
- package/dist/collections/entries.d.ts +89 -0
- package/dist/collections/entries.js +131 -0
- package/dist/collections/frozen-set.d.ts +42 -0
- package/dist/collections/frozen-set.js +64 -0
- package/dist/collections/group.d.ts +141 -0
- package/dist/collections/group.js +241 -0
- package/dist/collections/heap.d.ts +64 -0
- package/dist/collections/heap.js +205 -0
- package/dist/collections/index.d.ts +15 -642
- package/dist/collections/index.js +14 -716
- package/dist/collections/internal/arrayKeys.d.ts +19 -0
- package/dist/collections/internal/arrayKeys.js +83 -0
- package/dist/collections/internal/invariants.d.ts +4 -0
- package/dist/collections/internal/invariants.js +12 -0
- package/dist/collections/internal/iterable.d.ts +25 -0
- package/dist/collections/internal/iterable.js +62 -0
- package/dist/collections/iterate.d.ts +162 -0
- package/dist/collections/iterate.js +188 -0
- package/dist/collections/lru-cache.d.ts +58 -0
- package/dist/collections/lru-cache.js +164 -0
- package/dist/collections/order.d.ts +19 -0
- package/dist/collections/order.js +38 -0
- package/dist/collections/shape.d.ts +32 -0
- package/dist/collections/shape.js +86 -0
- package/dist/collections/sorted-map.d.ts +171 -0
- package/dist/collections/sorted-map.js +845 -0
- package/dist/collections/sorted-set.d.ts +103 -0
- package/dist/collections/sorted-set.js +147 -0
- package/dist/collections/splay-tree.d.ts +82 -0
- package/dist/collections/splay-tree.js +354 -0
- package/dist/collections/trie.d.ts +58 -0
- package/dist/collections/trie.js +196 -0
- package/dist/decimal/currency.d.ts +211 -0
- package/dist/decimal/currency.js +321 -0
- package/dist/decimal/decimal.d.ts +299 -0
- package/dist/decimal/decimal.js +660 -0
- package/dist/decimal/index.d.ts +11 -145
- package/dist/decimal/index.js +10 -374
- package/dist/decimal/internal/bits.d.ts +2 -0
- package/dist/decimal/internal/bits.js +7 -0
- package/dist/decimal/internal/echo.d.ts +4 -0
- package/dist/decimal/internal/echo.js +6 -0
- package/dist/decimal/internal/isqrt.d.ts +9 -0
- package/dist/decimal/internal/isqrt.js +34 -0
- package/dist/decimal/internal/locale.d.ts +7 -0
- package/dist/decimal/internal/locale.js +24 -0
- package/dist/decimal/internal/minor-units.d.ts +2 -0
- package/dist/decimal/internal/minor-units.js +33 -0
- package/dist/decimal/internal/pow10.d.ts +24 -0
- package/dist/decimal/internal/pow10.js +96 -0
- package/dist/encoding/base64.d.ts +39 -0
- package/dist/encoding/base64.js +53 -0
- package/dist/encoding/hex.d.ts +23 -0
- package/dist/encoding/hex.js +34 -0
- package/dist/encoding/index.d.ts +6 -0
- package/dist/encoding/index.js +6 -0
- package/dist/function/debounce.d.ts +68 -0
- package/dist/function/debounce.js +203 -0
- package/dist/function/index.d.ts +6 -0
- package/dist/function/index.js +6 -0
- package/dist/function/shared.d.ts +2 -0
- package/dist/function/shared.js +5 -0
- package/dist/function/wrap.d.ts +130 -0
- package/dist/function/wrap.js +113 -0
- package/dist/hash/digest.d.ts +18 -0
- package/dist/hash/digest.js +26 -0
- package/dist/hash/hash.d.ts +22 -0
- package/dist/hash/hash.js +252 -0
- package/dist/hash/hashString.d.ts +13 -0
- package/dist/hash/hashString.js +53 -0
- package/dist/hash/index.d.ts +8 -0
- package/dist/hash/index.js +8 -0
- package/dist/hash/stableStringify.d.ts +19 -0
- package/dist/hash/stableStringify.js +102 -0
- package/dist/id/index.d.ts +7 -0
- package/dist/id/index.js +7 -0
- package/dist/id/nanoid.d.ts +16 -0
- package/dist/id/nanoid.js +65 -0
- package/dist/id/uniqueId.d.ts +14 -0
- package/dist/id/uniqueId.js +20 -0
- package/dist/id/uuid.d.ts +25 -0
- package/dist/id/uuid.js +64 -0
- package/dist/index.d.ts +15 -8
- package/dist/index.js +15 -8
- package/dist/internal/bytes.d.ts +11 -0
- package/dist/internal/bytes.js +33 -0
- package/dist/internal/codec.d.ts +11 -0
- package/dist/internal/codec.js +84 -0
- package/dist/internal/compare.d.ts +10 -0
- package/dist/internal/compare.js +26 -0
- package/dist/internal/crypto.d.ts +5 -0
- package/dist/internal/crypto.js +11 -0
- package/dist/internal/keys.d.ts +12 -0
- package/dist/internal/keys.js +23 -0
- package/dist/internal/kind.d.ts +44 -0
- package/dist/internal/kind.js +139 -0
- package/dist/internal/sparse.d.ts +51 -0
- package/dist/internal/sparse.js +104 -0
- package/dist/internal/text.d.ts +7 -0
- package/dist/internal/text.js +15 -0
- package/dist/internal/timer.d.ts +10 -0
- package/dist/internal/timer.js +17 -0
- package/dist/internal/truncate.d.ts +10 -0
- package/dist/internal/truncate.js +22 -0
- package/dist/internal/walk.d.ts +47 -0
- package/dist/internal/walk.js +100 -0
- package/dist/is/index.d.ts +8 -0
- package/dist/is/index.js +8 -0
- package/dist/is/isArrayLike.d.ts +18 -0
- package/dist/is/isArrayLike.js +25 -0
- package/dist/is/isError.d.ts +13 -0
- package/dist/is/isError.js +18 -0
- package/dist/is/isNil.d.ts +12 -0
- package/dist/is/isNil.js +14 -0
- package/dist/is/isPlainObject.d.ts +15 -0
- package/dist/is/isPlainObject.js +34 -0
- package/dist/number/index.d.ts +7 -0
- package/dist/number/index.js +7 -0
- package/dist/number/round.d.ts +86 -0
- package/dist/number/round.js +130 -0
- package/dist/number/stats.d.ts +52 -0
- package/dist/number/stats.js +115 -0
- package/dist/object/cloneDeep.d.ts +28 -0
- package/dist/object/cloneDeep.js +200 -0
- package/dist/object/index.d.ts +14 -0
- package/dist/object/index.js +13 -0
- package/dist/object/isEqual.d.ts +64 -0
- package/dist/object/isEqual.js +289 -0
- package/dist/object/matches.d.ts +40 -0
- package/dist/object/matches.js +284 -0
- package/dist/object/merge.d.ts +66 -0
- package/dist/object/merge.js +272 -0
- package/dist/object/parsePath.d.ts +22 -0
- package/dist/object/parsePath.js +111 -0
- package/dist/object/path.d.ts +85 -0
- package/dist/object/path.js +208 -0
- package/dist/object/pick.d.ts +91 -0
- package/dist/object/pick.js +180 -0
- package/dist/object/reshape.d.ts +73 -0
- package/dist/object/reshape.js +144 -0
- package/dist/random/index.d.ts +96 -32
- package/dist/random/index.js +215 -50
- package/dist/string/case.d.ts +71 -0
- package/dist/string/case.js +152 -0
- package/dist/string/fold.d.ts +35 -0
- package/dist/string/fold.js +100 -0
- package/dist/string/index.d.ts +6 -187
- package/dist/string/index.js +6 -226
- package/dist/string/truncate.d.ts +25 -0
- package/dist/string/truncate.js +44 -0
- package/dist/string/words.d.ts +27 -0
- package/dist/string/words.js +241 -0
- package/package.json +101 -58
- package/dist/collections/BTree.d.ts +0 -229
- package/dist/collections/BTree.js +0 -1165
- package/dist/collections/Heap.d.ts +0 -69
- package/dist/collections/Heap.js +0 -181
- package/dist/collections/LRUCache.d.ts +0 -80
- package/dist/collections/LRUCache.js +0 -126
- package/dist/collections/SortedMap.d.ts +0 -92
- package/dist/collections/SortedMap.js +0 -131
- package/dist/collections/SortedSet.d.ts +0 -69
- package/dist/collections/SortedSet.js +0 -99
- package/dist/collections/SortedTree.d.ts +0 -103
- package/dist/collections/SortedTree.js +0 -141
- package/dist/collections/SplayTree.d.ts +0 -105
- package/dist/collections/SplayTree.js +0 -338
- package/dist/collections/Trie.d.ts +0 -42
- package/dist/collections/Trie.js +0 -104
- package/dist/collections/abc.d.ts +0 -152
- package/dist/collections/abc.js +0 -39
- package/dist/collections/frozenset.d.ts +0 -19
- package/dist/collections/frozenset.js +0 -30
- package/dist/functools/index.d.ts +0 -130
- package/dist/functools/index.js +0 -235
- package/dist/globals/index.d.ts +0 -285
- package/dist/globals/index.js +0 -463
- package/dist/i18n/currency.d.ts +0 -24
- package/dist/i18n/currency.js +0 -85
- package/dist/i18n/date/index.d.ts +0 -203
- package/dist/i18n/date/index.js +0 -531
- package/dist/i18n/date/utils.d.ts +0 -65
- package/dist/i18n/date/utils.js +0 -290
- package/dist/i18n/duration.d.ts +0 -112
- package/dist/i18n/duration.js +0 -392
- package/dist/i18n/format.d.ts +0 -31
- package/dist/i18n/format.js +0 -506
- package/dist/i18n/index.d.ts +0 -8
- package/dist/i18n/index.js +0 -8
- package/dist/itertools/index.d.ts +0 -255
- package/dist/itertools/index.js +0 -437
- package/dist/math/index.d.ts +0 -96
- package/dist/math/index.js +0 -98
- package/dist/mod.d.ts +0 -1
- package/dist/mod.js +0 -1
- package/dist/operators/index.d.ts +0 -152
- package/dist/operators/index.js +0 -305
- package/dist/types.d.ts +0 -19
- package/dist/types.js +0 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type ArrayWalkEvent } from '../../internal/sparse.js';
|
|
2
|
+
/**
|
|
3
|
+
* Walk `arr` without expanding huge hole runs index-by-index.
|
|
4
|
+
* Dense indices use `i in arr`. Once holes pass {@link HOLE_STREAK_BEFORE_KEYS} plus the elements
|
|
5
|
+
* seen so far, take `Object.keys` once and continue over remaining canonical indices only, so
|
|
6
|
+
* cost stays proportional to the elements however they are spaced.
|
|
7
|
+
* Holes are reported as a single `holeRun` event (`end` exclusive).
|
|
8
|
+
* Return `false` from `visit` to stop.
|
|
9
|
+
*/
|
|
10
|
+
export declare function walkArray(arr: unknown[], visit: (event: ArrayWalkEvent) => unknown): void;
|
|
11
|
+
/**
|
|
12
|
+
* True when `arr.length` is above {@link HUGE_SPARSE_MIN_LENGTH} and also exceeds
|
|
13
|
+
* `2 * visitedIndexCount + 1024`, so a dense `0..length` walk would spend most of its time on holes.
|
|
14
|
+
* Below {@link HUGE_SPARSE_MIN_LENGTH}, consumers walk with their existing hole semantics.
|
|
15
|
+
* Counts the values visited by {@link walkArray}; dense arrays exit early once they cannot qualify.
|
|
16
|
+
*/
|
|
17
|
+
export declare function isHugeSparse(arr: unknown[]): boolean;
|
|
18
|
+
/** Throw when `arr` is a huge sparse array that must not be expanded per-index. */
|
|
19
|
+
export declare function assertNotHugeSparse(arr: unknown[]): void;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { arrayIndicesFrom, HOLE_STREAK_BEFORE_KEYS, HUGE_SPARSE_MIN_LENGTH } from '../../internal/sparse.js';
|
|
2
|
+
/**
|
|
3
|
+
* Walk `arr` without expanding huge hole runs index-by-index.
|
|
4
|
+
* Dense indices use `i in arr`. Once holes pass {@link HOLE_STREAK_BEFORE_KEYS} plus the elements
|
|
5
|
+
* seen so far, take `Object.keys` once and continue over remaining canonical indices only, so
|
|
6
|
+
* cost stays proportional to the elements however they are spaced.
|
|
7
|
+
* Holes are reported as a single `holeRun` event (`end` exclusive).
|
|
8
|
+
* Return `false` from `visit` to stop.
|
|
9
|
+
*/
|
|
10
|
+
export function walkArray(arr, visit) {
|
|
11
|
+
const len = arr.length;
|
|
12
|
+
let i = 0;
|
|
13
|
+
let elements = 0;
|
|
14
|
+
let holes = 0;
|
|
15
|
+
while (i < len) {
|
|
16
|
+
if (i in arr) {
|
|
17
|
+
if (visit({ kind: 'value', index: i, value: arr[i] }) === false)
|
|
18
|
+
return;
|
|
19
|
+
i++;
|
|
20
|
+
elements++;
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
const holeStart = i;
|
|
24
|
+
while (i < len && !(i in arr) && holes < HOLE_STREAK_BEFORE_KEYS + elements) {
|
|
25
|
+
i++;
|
|
26
|
+
holes++;
|
|
27
|
+
}
|
|
28
|
+
if (holes >= HOLE_STREAK_BEFORE_KEYS + elements && i < len) {
|
|
29
|
+
const rest = arrayIndicesFrom(arr, i);
|
|
30
|
+
const holeEnd = rest.length > 0 ? rest[0] : len;
|
|
31
|
+
if (visit({ kind: 'holeRun', start: holeStart, end: holeEnd }) === false)
|
|
32
|
+
return;
|
|
33
|
+
for (let k = 0; k < rest.length; k++) {
|
|
34
|
+
const idx = rest[k];
|
|
35
|
+
if (k > 0) {
|
|
36
|
+
const prev = rest[k - 1];
|
|
37
|
+
if (idx > prev + 1) {
|
|
38
|
+
if (visit({ kind: 'holeRun', start: prev + 1, end: idx }) === false)
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (visit({ kind: 'value', index: idx, value: arr[idx] }) === false)
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (rest.length > 0) {
|
|
46
|
+
const last = rest[rest.length - 1];
|
|
47
|
+
if (last + 1 < len) {
|
|
48
|
+
if (visit({ kind: 'holeRun', start: last + 1, end: len }) === false)
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (visit({ kind: 'holeRun', start: holeStart, end: i }) === false)
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* True when `arr.length` is above {@link HUGE_SPARSE_MIN_LENGTH} and also exceeds
|
|
60
|
+
* `2 * visitedIndexCount + 1024`, so a dense `0..length` walk would spend most of its time on holes.
|
|
61
|
+
* Below {@link HUGE_SPARSE_MIN_LENGTH}, consumers walk with their existing hole semantics.
|
|
62
|
+
* Counts the values visited by {@link walkArray}; dense arrays exit early once they cannot qualify.
|
|
63
|
+
*/
|
|
64
|
+
export function isHugeSparse(arr) {
|
|
65
|
+
const len = arr.length;
|
|
66
|
+
if (len <= HUGE_SPARSE_MIN_LENGTH)
|
|
67
|
+
return false;
|
|
68
|
+
let own = 0;
|
|
69
|
+
walkArray(arr, (event) => {
|
|
70
|
+
if (event.kind !== 'value')
|
|
71
|
+
return;
|
|
72
|
+
own++;
|
|
73
|
+
if (len <= 2 * own + 1024)
|
|
74
|
+
return false;
|
|
75
|
+
});
|
|
76
|
+
return len > 2 * own + 1024;
|
|
77
|
+
}
|
|
78
|
+
/** Throw when `arr` is a huge sparse array that must not be expanded per-index. */
|
|
79
|
+
export function assertNotHugeSparse(arr) {
|
|
80
|
+
if (isHugeSparse(arr)) {
|
|
81
|
+
throw new RangeError('sparse array too large');
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Called once by `SortedMap`'s static block with access to its private structure check. */
|
|
2
|
+
export declare function registerSortedMapCheck(fn: (map: object) => void): void;
|
|
3
|
+
/** Throws when a `SortedMap`'s B+ tree breaks an invariant. For tests. */
|
|
4
|
+
export declare function checkSortedMap(map: object): void;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
let check;
|
|
2
|
+
/** Called once by `SortedMap`'s static block with access to its private structure check. */
|
|
3
|
+
export function registerSortedMapCheck(fn) {
|
|
4
|
+
check = fn;
|
|
5
|
+
}
|
|
6
|
+
/** Throws when a `SortedMap`'s B+ tree breaks an invariant. For tests. */
|
|
7
|
+
export function checkSortedMap(map) {
|
|
8
|
+
if (check === undefined) {
|
|
9
|
+
throw new Error('no SortedMap from this module graph has registered its invariant check');
|
|
10
|
+
}
|
|
11
|
+
check(map);
|
|
12
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** Return `value` typed as an iterable; throw `TypeError` before allocating when it is not one. */
|
|
2
|
+
export declare function requireIterable<T>(value: unknown): Iterable<T>;
|
|
3
|
+
/**
|
|
4
|
+
* True when `value` is an array that iterates with the built-in array iterator, so iterating it
|
|
5
|
+
* visits every index up to `length`, holes included. An array with its own or a subclass's
|
|
6
|
+
* `[Symbol.iterator]` iterates however that method says and is treated as any other iterable.
|
|
7
|
+
*/
|
|
8
|
+
export declare function iteratesAsArray(value: unknown): value is unknown[];
|
|
9
|
+
/**
|
|
10
|
+
* Copy an iterable into a new plain array, as iterating it yields the values (holes read as
|
|
11
|
+
* `undefined`). The copy never goes through `slice`, so an Array subclass's `Symbol.species`
|
|
12
|
+
* cannot choose its class. Non-iterables throw `TypeError` and huge sparse arrays throw
|
|
13
|
+
* `RangeError`, both before allocating.
|
|
14
|
+
*/
|
|
15
|
+
export declare function arrayFromIterable<T>(value: unknown): T[];
|
|
16
|
+
/**
|
|
17
|
+
* Map an iterable into a new array; non-iterables throw `TypeError` and huge sparse arrays throw
|
|
18
|
+
* `RangeError`, both before allocating.
|
|
19
|
+
*/
|
|
20
|
+
export declare function arrayFromIterableMap<U>(value: unknown, mapFn: (item: unknown, index: number) => U): U[];
|
|
21
|
+
/**
|
|
22
|
+
* Visit array elements in own-element time: each own value, and each hole run once as
|
|
23
|
+
* `undefined` at the run's start index. Return `false` from `visit` to stop.
|
|
24
|
+
*/
|
|
25
|
+
export declare function forEachArrayElement<T>(arr: T[], visit: (value: T, index: number) => boolean | undefined): void;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { assertNotHugeSparse, walkArray } from './arrayKeys.js';
|
|
2
|
+
function isIterable(x) {
|
|
3
|
+
if (x == null)
|
|
4
|
+
return false;
|
|
5
|
+
return typeof x[Symbol.iterator] === 'function';
|
|
6
|
+
}
|
|
7
|
+
/** Return `value` typed as an iterable; throw `TypeError` before allocating when it is not one. */
|
|
8
|
+
export function requireIterable(value) {
|
|
9
|
+
if (!isIterable(value))
|
|
10
|
+
throw new TypeError('expected an iterable');
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* True when `value` is an array that iterates with the built-in array iterator, so iterating it
|
|
15
|
+
* visits every index up to `length`, holes included. An array with its own or a subclass's
|
|
16
|
+
* `[Symbol.iterator]` iterates however that method says and is treated as any other iterable.
|
|
17
|
+
*/
|
|
18
|
+
export function iteratesAsArray(value) {
|
|
19
|
+
return Array.isArray(value) && value[Symbol.iterator] === Array.prototype.values;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Copy an iterable into a new plain array, as iterating it yields the values (holes read as
|
|
23
|
+
* `undefined`). The copy never goes through `slice`, so an Array subclass's `Symbol.species`
|
|
24
|
+
* cannot choose its class. Non-iterables throw `TypeError` and huge sparse arrays throw
|
|
25
|
+
* `RangeError`, both before allocating.
|
|
26
|
+
*/
|
|
27
|
+
export function arrayFromIterable(value) {
|
|
28
|
+
const it = requireIterable(value);
|
|
29
|
+
if (iteratesAsArray(it))
|
|
30
|
+
assertNotHugeSparse(it);
|
|
31
|
+
const out = [];
|
|
32
|
+
for (const x of it)
|
|
33
|
+
out.push(x);
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Map an iterable into a new array; non-iterables throw `TypeError` and huge sparse arrays throw
|
|
38
|
+
* `RangeError`, both before allocating.
|
|
39
|
+
*/
|
|
40
|
+
export function arrayFromIterableMap(value, mapFn) {
|
|
41
|
+
const it = requireIterable(value);
|
|
42
|
+
if (iteratesAsArray(it))
|
|
43
|
+
assertNotHugeSparse(it);
|
|
44
|
+
const out = [];
|
|
45
|
+
let i = 0;
|
|
46
|
+
for (const x of it) {
|
|
47
|
+
out.push(mapFn(x, i));
|
|
48
|
+
i++;
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Visit array elements in own-element time: each own value, and each hole run once as
|
|
54
|
+
* `undefined` at the run's start index. Return `false` from `visit` to stop.
|
|
55
|
+
*/
|
|
56
|
+
export function forEachArrayElement(arr, visit) {
|
|
57
|
+
walkArray(arr, (ev) => {
|
|
58
|
+
if (ev.kind === 'value')
|
|
59
|
+
return visit(ev.value, ev.index);
|
|
60
|
+
return visit(undefined, ev.start);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Iteration over every shape: `forEach`, `map`, `filter`, `find`, `some`, `reduce` and friends.
|
|
3
|
+
*/
|
|
4
|
+
import { type Collection, type CollectionCallback, type CollectionKey, type CollectionValue } from './shape.js';
|
|
5
|
+
/**
|
|
6
|
+
* Call `callback` with `(value, key, collection)` for every entry of `collection`, in order. Like
|
|
7
|
+
* the native `forEach`, it visits every entry and ignores what the callback returns; use
|
|
8
|
+
* {@link some}, {@link every} or `for...of` to stop early.
|
|
9
|
+
* @param collection The collection to walk.
|
|
10
|
+
* @param callback Called once per entry.
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* forEach({ a: 1, b: 2 }, (value, key) => console.log(key, value))
|
|
14
|
+
* // a 1
|
|
15
|
+
* // b 2
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function forEach<C extends Collection>(collection: C, callback: CollectionCallback<C, unknown>): void;
|
|
19
|
+
/**
|
|
20
|
+
* {@link forEach} from the last entry to the first.
|
|
21
|
+
* @param collection The collection to walk.
|
|
22
|
+
* @param callback Called once per entry.
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* forEachRight([1, 2], (value) => console.log(value))
|
|
26
|
+
* // 2
|
|
27
|
+
* // 1
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function forEachRight<C extends Collection>(collection: C, callback: CollectionCallback<C, unknown>): void;
|
|
31
|
+
/**
|
|
32
|
+
* The results of `callback` for every entry of `collection`, as an array.
|
|
33
|
+
* @param collection The collection to walk.
|
|
34
|
+
* @param callback Maps one entry.
|
|
35
|
+
* @returns A new array with one result per entry.
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* map({ a: 1, b: 2 }, (value) => value * 2) // [2, 4]
|
|
39
|
+
* map(new Map([['x', 1]]), (value, key) => `${key}=${value}`) // ['x=1']
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function map<C extends Collection, R>(collection: C, callback: CollectionCallback<C, R>): R[];
|
|
43
|
+
/**
|
|
44
|
+
* {@link map}, then one level of flattening, as `Array.prototype.flatMap` does: an array result
|
|
45
|
+
* is spread, anything else is kept as one element.
|
|
46
|
+
* @param collection The collection to walk.
|
|
47
|
+
* @param callback Maps one entry to an array or a value.
|
|
48
|
+
* @returns A new flat array.
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* flatMap({ a: 1, b: 2 }, (value, key) => [key, value]) // ['a', 1, 'b', 2]
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare function flatMap<C extends Collection, R>(collection: C, callback: CollectionCallback<C, R | readonly R[]>): R[];
|
|
55
|
+
/**
|
|
56
|
+
* The values of `collection` for which `predicate` is truthy, in order.
|
|
57
|
+
* @param collection The collection to walk.
|
|
58
|
+
* @param predicate Tests one entry.
|
|
59
|
+
* @returns A new array of values.
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* filter({ a: 1, b: 2, c: 3 }, (value) => value % 2 === 1) // [1, 3]
|
|
63
|
+
* filter(new Set(['x', 'yy']), (value) => value.length > 1) // ['yy']
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export declare function filter<C extends Collection, S extends CollectionValue<C>>(collection: C, predicate: (value: CollectionValue<C>, key: CollectionKey<C>, collection: C) => value is S): S[];
|
|
67
|
+
/** {@link filter} with a predicate that is not a type guard. */
|
|
68
|
+
export declare function filter<C extends Collection>(collection: C, predicate: CollectionCallback<C, unknown>): CollectionValue<C>[];
|
|
69
|
+
/**
|
|
70
|
+
* The values of `collection` for which `predicate` is falsy: the complement of {@link filter}.
|
|
71
|
+
* @param collection The collection to walk.
|
|
72
|
+
* @param predicate Tests one entry.
|
|
73
|
+
* @returns A new array of values.
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* reject([1, 2, 3], (value) => value > 1) // [1]
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export declare function reject<C extends Collection>(collection: C, predicate: CollectionCallback<C, unknown>): CollectionValue<C>[];
|
|
80
|
+
/**
|
|
81
|
+
* The first value of `collection` for which `predicate` is truthy, or `undefined`. It stops at
|
|
82
|
+
* that entry, so it works on an endless iterable that has a match.
|
|
83
|
+
* @param collection The collection to search.
|
|
84
|
+
* @param predicate Tests one entry.
|
|
85
|
+
* @returns The value found, or `undefined`.
|
|
86
|
+
* @example
|
|
87
|
+
* ```ts
|
|
88
|
+
* find({ a: 1, b: 2 }, (value) => value > 1) // 2
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
export declare function find<C extends Collection, S extends CollectionValue<C>>(collection: C, predicate: (value: CollectionValue<C>, key: CollectionKey<C>, collection: C) => value is S): S | undefined;
|
|
92
|
+
/** {@link find} with a predicate that is not a type guard. */
|
|
93
|
+
export declare function find<C extends Collection>(collection: C, predicate: CollectionCallback<C, unknown>): CollectionValue<C> | undefined;
|
|
94
|
+
/**
|
|
95
|
+
* {@link find} from the last entry to the first.
|
|
96
|
+
* @param collection The collection to search.
|
|
97
|
+
* @param predicate Tests one entry.
|
|
98
|
+
* @returns The value found, or `undefined`.
|
|
99
|
+
* @example
|
|
100
|
+
* ```ts
|
|
101
|
+
* findLast([1, 2, 3], (value) => value < 3) // 2
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
export declare function findLast<C extends Collection, S extends CollectionValue<C>>(collection: C, predicate: (value: CollectionValue<C>, key: CollectionKey<C>, collection: C) => value is S): S | undefined;
|
|
105
|
+
/** {@link findLast} with a predicate that is not a type guard. */
|
|
106
|
+
export declare function findLast<C extends Collection>(collection: C, predicate: CollectionCallback<C, unknown>): CollectionValue<C> | undefined;
|
|
107
|
+
/**
|
|
108
|
+
* True when `predicate` is truthy for some entry; stops at the first one.
|
|
109
|
+
* @param collection The collection to test.
|
|
110
|
+
* @param predicate Tests one entry.
|
|
111
|
+
* @returns Whether any entry passes. `false` for an empty collection.
|
|
112
|
+
* @example
|
|
113
|
+
* ```ts
|
|
114
|
+
* some({ a: 1, b: -1 }, (value) => value < 0) // true
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
export declare function some<C extends Collection>(collection: C, predicate: CollectionCallback<C, unknown>): boolean;
|
|
118
|
+
/**
|
|
119
|
+
* True when `predicate` is truthy for every entry; stops at the first that fails.
|
|
120
|
+
* @param collection The collection to test.
|
|
121
|
+
* @param predicate Tests one entry.
|
|
122
|
+
* @returns Whether every entry passes. `true` for an empty collection.
|
|
123
|
+
* @example
|
|
124
|
+
* ```ts
|
|
125
|
+
* every(new Set([2, 4]), (value) => value % 2 === 0) // true
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
export declare function every<C extends Collection>(collection: C, predicate: CollectionCallback<C, unknown>): boolean;
|
|
129
|
+
/** `(accumulator, value, key, collection)`, as `Array.prototype.reduce` passes them plus the key. */
|
|
130
|
+
export type CollectionReducer<C, A> = (accumulator: A, value: CollectionValue<C>, key: CollectionKey<C>, collection: C) => A;
|
|
131
|
+
/**
|
|
132
|
+
* Fold the entries of `collection` into one value, as `Array.prototype.reduce` does. Without
|
|
133
|
+
* `initial`, the first value starts the fold.
|
|
134
|
+
* @param collection The collection to fold.
|
|
135
|
+
* @param reducer Combines the accumulator with one entry.
|
|
136
|
+
* @param initial The starting accumulator.
|
|
137
|
+
* @returns The final accumulator.
|
|
138
|
+
* @throws {TypeError} when `collection` is empty and no `initial` is given, as the native method does.
|
|
139
|
+
* @example
|
|
140
|
+
* ```ts
|
|
141
|
+
* reduce({ a: 1, b: 2 }, (sum, value) => sum + value, 0) // 3
|
|
142
|
+
* reduce(new Map([['x', 1]]), (out, value, key) => `${out}${key}${value}`, '') // 'x1'
|
|
143
|
+
* ```
|
|
144
|
+
*/
|
|
145
|
+
export declare function reduce<C extends Collection, A>(collection: C, reducer: CollectionReducer<C, A>, initial: A): A;
|
|
146
|
+
/** {@link reduce} without `initial`: the first value starts the fold. */
|
|
147
|
+
export declare function reduce<C extends Collection>(collection: C, reducer: CollectionReducer<C, CollectionValue<C>>): CollectionValue<C>;
|
|
148
|
+
/**
|
|
149
|
+
* {@link reduce} from the last entry to the first, as `Array.prototype.reduceRight` does.
|
|
150
|
+
* @param collection The collection to fold.
|
|
151
|
+
* @param reducer Combines the accumulator with one entry.
|
|
152
|
+
* @param initial The starting accumulator.
|
|
153
|
+
* @returns The final accumulator.
|
|
154
|
+
* @throws {TypeError} when `collection` is empty and no `initial` is given.
|
|
155
|
+
* @example
|
|
156
|
+
* ```ts
|
|
157
|
+
* reduceRight(['a', 'b', 'c'], (out, value) => out + value, '') // 'cba'
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
export declare function reduceRight<C extends Collection, A>(collection: C, reducer: CollectionReducer<C, A>, initial: A): A;
|
|
161
|
+
/** {@link reduceRight} without `initial`: the last value starts the fold. */
|
|
162
|
+
export declare function reduceRight<C extends Collection>(collection: C, reducer: CollectionReducer<C, CollectionValue<C>>): CollectionValue<C>;
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Iteration over every shape: `forEach`, `map`, `filter`, `find`, `some`, `reduce` and friends.
|
|
3
|
+
*/
|
|
4
|
+
import { eachEntry, eachIndex, entryList } from './shape.js';
|
|
5
|
+
/**
|
|
6
|
+
* Call `callback` with `(value, key, collection)` for every entry of `collection`, in order. Like
|
|
7
|
+
* the native `forEach`, it visits every entry and ignores what the callback returns; use
|
|
8
|
+
* {@link some}, {@link every} or `for...of` to stop early.
|
|
9
|
+
* @param collection The collection to walk.
|
|
10
|
+
* @param callback Called once per entry.
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* forEach({ a: 1, b: 2 }, (value, key) => console.log(key, value))
|
|
14
|
+
* // a 1
|
|
15
|
+
* // b 2
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export function forEach(collection, callback) {
|
|
19
|
+
const fn = callback;
|
|
20
|
+
eachEntry(collection, (value, key) => {
|
|
21
|
+
fn(value, key, collection);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* {@link forEach} from the last entry to the first.
|
|
26
|
+
* @param collection The collection to walk.
|
|
27
|
+
* @param callback Called once per entry.
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* forEachRight([1, 2], (value) => console.log(value))
|
|
31
|
+
* // 2
|
|
32
|
+
* // 1
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export function forEachRight(collection, callback) {
|
|
36
|
+
const fn = callback;
|
|
37
|
+
const list = entryList(collection);
|
|
38
|
+
for (let i = list.length - 1; i >= 0; i--)
|
|
39
|
+
fn(list[i][1], list[i][0], collection);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The results of `callback` for every entry of `collection`, as an array.
|
|
43
|
+
* @param collection The collection to walk.
|
|
44
|
+
* @param callback Maps one entry.
|
|
45
|
+
* @returns A new array with one result per entry.
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* map({ a: 1, b: 2 }, (value) => value * 2) // [2, 4]
|
|
49
|
+
* map(new Map([['x', 1]]), (value, key) => `${key}=${value}`) // ['x=1']
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export function map(collection, callback) {
|
|
53
|
+
const fn = callback;
|
|
54
|
+
const out = [];
|
|
55
|
+
eachEntry(collection, (value, key) => {
|
|
56
|
+
out.push(fn(value, key, collection));
|
|
57
|
+
});
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* {@link map}, then one level of flattening, as `Array.prototype.flatMap` does: an array result
|
|
62
|
+
* is spread, anything else is kept as one element.
|
|
63
|
+
* @param collection The collection to walk.
|
|
64
|
+
* @param callback Maps one entry to an array or a value.
|
|
65
|
+
* @returns A new flat array.
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* flatMap({ a: 1, b: 2 }, (value, key) => [key, value]) // ['a', 1, 'b', 2]
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export function flatMap(collection, callback) {
|
|
72
|
+
const fn = callback;
|
|
73
|
+
const out = [];
|
|
74
|
+
eachEntry(collection, (value, key) => {
|
|
75
|
+
const result = fn(value, key, collection);
|
|
76
|
+
if (Array.isArray(result)) {
|
|
77
|
+
eachIndex(result, (item) => {
|
|
78
|
+
out.push(item);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
out.push(result);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
export function filter(collection, predicate) {
|
|
88
|
+
const fn = predicate;
|
|
89
|
+
const out = [];
|
|
90
|
+
eachEntry(collection, (value, key) => {
|
|
91
|
+
if (fn(value, key, collection))
|
|
92
|
+
out.push(value);
|
|
93
|
+
});
|
|
94
|
+
return out;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* The values of `collection` for which `predicate` is falsy: the complement of {@link filter}.
|
|
98
|
+
* @param collection The collection to walk.
|
|
99
|
+
* @param predicate Tests one entry.
|
|
100
|
+
* @returns A new array of values.
|
|
101
|
+
* @example
|
|
102
|
+
* ```ts
|
|
103
|
+
* reject([1, 2, 3], (value) => value > 1) // [1]
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
export function reject(collection, predicate) {
|
|
107
|
+
return filter(collection, (value, key, c) => !predicate(value, key, c));
|
|
108
|
+
}
|
|
109
|
+
export function find(collection, predicate) {
|
|
110
|
+
const fn = predicate;
|
|
111
|
+
let found;
|
|
112
|
+
eachEntry(collection, (value, key) => {
|
|
113
|
+
if (!fn(value, key, collection))
|
|
114
|
+
return false;
|
|
115
|
+
found = value;
|
|
116
|
+
return true;
|
|
117
|
+
});
|
|
118
|
+
return found;
|
|
119
|
+
}
|
|
120
|
+
export function findLast(collection, predicate) {
|
|
121
|
+
const fn = predicate;
|
|
122
|
+
const list = entryList(collection);
|
|
123
|
+
for (let i = list.length - 1; i >= 0; i--) {
|
|
124
|
+
if (fn(list[i][1], list[i][0], collection))
|
|
125
|
+
return list[i][1];
|
|
126
|
+
}
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* True when `predicate` is truthy for some entry; stops at the first one.
|
|
131
|
+
* @param collection The collection to test.
|
|
132
|
+
* @param predicate Tests one entry.
|
|
133
|
+
* @returns Whether any entry passes. `false` for an empty collection.
|
|
134
|
+
* @example
|
|
135
|
+
* ```ts
|
|
136
|
+
* some({ a: 1, b: -1 }, (value) => value < 0) // true
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
export function some(collection, predicate) {
|
|
140
|
+
const fn = predicate;
|
|
141
|
+
return eachEntry(collection, (value, key) => Boolean(fn(value, key, collection)));
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* True when `predicate` is truthy for every entry; stops at the first that fails.
|
|
145
|
+
* @param collection The collection to test.
|
|
146
|
+
* @param predicate Tests one entry.
|
|
147
|
+
* @returns Whether every entry passes. `true` for an empty collection.
|
|
148
|
+
* @example
|
|
149
|
+
* ```ts
|
|
150
|
+
* every(new Set([2, 4]), (value) => value % 2 === 0) // true
|
|
151
|
+
* ```
|
|
152
|
+
*/
|
|
153
|
+
export function every(collection, predicate) {
|
|
154
|
+
const fn = predicate;
|
|
155
|
+
return !eachEntry(collection, (value, key) => !fn(value, key, collection));
|
|
156
|
+
}
|
|
157
|
+
function emptyReduceError() {
|
|
158
|
+
return new TypeError('reduce of an empty collection with no initial value');
|
|
159
|
+
}
|
|
160
|
+
export function reduce(collection, reducer, ...initial) {
|
|
161
|
+
const fn = reducer;
|
|
162
|
+
let hasAcc = initial.length > 0;
|
|
163
|
+
let acc = initial[0];
|
|
164
|
+
eachEntry(collection, (value, key) => {
|
|
165
|
+
if (hasAcc) {
|
|
166
|
+
acc = fn(acc, value, key, collection);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
acc = value;
|
|
170
|
+
hasAcc = true;
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
if (!hasAcc)
|
|
174
|
+
throw emptyReduceError();
|
|
175
|
+
return acc;
|
|
176
|
+
}
|
|
177
|
+
export function reduceRight(collection, reducer, ...initial) {
|
|
178
|
+
const fn = reducer;
|
|
179
|
+
const list = entryList(collection);
|
|
180
|
+
const hasInitial = initial.length > 0;
|
|
181
|
+
if (!hasInitial && list.length === 0)
|
|
182
|
+
throw emptyReduceError();
|
|
183
|
+
let i = list.length - 1;
|
|
184
|
+
let acc = hasInitial ? initial[0] : list[i--][1];
|
|
185
|
+
for (; i >= 0; i--)
|
|
186
|
+
acc = fn(acc, list[i][1], list[i][0], collection);
|
|
187
|
+
return acc;
|
|
188
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A fixed-capacity least-recently-used cache with `Map`'s method names. `get` refreshes recency;
|
|
3
|
+
* `has` does not. Keys compare with SameValueZero, as in `Map`. Iterators and `forEach` walk a
|
|
4
|
+
* snapshot taken when they start, so `get` and `set` inside a loop are safe.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* const cache = new LRUCache<string, number>(2)
|
|
9
|
+
* cache.set('a', 1).set('b', 2)
|
|
10
|
+
* cache.get('a') // 1, so 'b' is now the least recent
|
|
11
|
+
* cache.set('c', 3)
|
|
12
|
+
* cache.has('b') // false
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare class LRUCache<K = unknown, V = unknown> {
|
|
16
|
+
private readonly state;
|
|
17
|
+
/**
|
|
18
|
+
* Create an empty cache.
|
|
19
|
+
* @param capacity Maximum number of entries; must be an integer >= 1. Defaults to 1024.
|
|
20
|
+
* @throws {TypeError} when capacity is not a number.
|
|
21
|
+
* @throws {RangeError} when capacity is not an integer >= 1.
|
|
22
|
+
*/
|
|
23
|
+
constructor(capacity?: number);
|
|
24
|
+
/**
|
|
25
|
+
* Set `key` to `value`. Setting an existing key updates its value and makes it the most recent,
|
|
26
|
+
* without evicting. Inserting a new key at capacity evicts the least recently used entry.
|
|
27
|
+
*/
|
|
28
|
+
set(key: K, value: V): this;
|
|
29
|
+
/** Whether `key` is cached. Does not refresh its recency. */
|
|
30
|
+
has(key: K): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Return the value for `key`, refreshing its recency. Missing keys return `undefined`.
|
|
33
|
+
*/
|
|
34
|
+
get(key: K): V | undefined;
|
|
35
|
+
/** Remove every entry. */
|
|
36
|
+
clear(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Remove `key`.
|
|
39
|
+
* @returns Whether it was present.
|
|
40
|
+
*/
|
|
41
|
+
delete(key: K): boolean;
|
|
42
|
+
/** The number of entries. */
|
|
43
|
+
get size(): number;
|
|
44
|
+
/** Maximum number of entries. */
|
|
45
|
+
get capacity(): number;
|
|
46
|
+
/** `'LRUCache'`, for `Object.prototype.toString`. */
|
|
47
|
+
get [Symbol.toStringTag](): string;
|
|
48
|
+
/** The keys, least to most recently used. */
|
|
49
|
+
keys(): IteratorObject<K>;
|
|
50
|
+
/** The values, least to most recently used. */
|
|
51
|
+
values(): IteratorObject<V>;
|
|
52
|
+
/** `[key, value]` pairs, least to most recently used. */
|
|
53
|
+
entries(): IteratorObject<[K, V]>;
|
|
54
|
+
/** Call `callback(value, key, cache)` for each entry, least to most recently used. */
|
|
55
|
+
forEach(callback: (value: V, key: K, cache: this) => void, thisArg?: unknown): void;
|
|
56
|
+
/** `[key, value]` pairs, least to most recently used. */
|
|
57
|
+
[Symbol.iterator](): IteratorObject<[K, V]>;
|
|
58
|
+
}
|