atomic-fns 1.2.0 → 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 +397 -91
- 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 -256
- 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 -623
- package/dist/collections/index.js +14 -844
- 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 -148
- package/dist/decimal/index.js +10 -410
- 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 -53
- 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 -224
- 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 +99 -51
- package/dist/collections/BTree.d.ts +0 -230
- package/dist/collections/BTree.js +0 -1143
- package/dist/collections/Heap.d.ts +0 -69
- package/dist/collections/Heap.js +0 -181
- package/dist/collections/LRUCache.d.ts +0 -83
- package/dist/collections/LRUCache.js +0 -139
- 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 -142
- package/dist/collections/SplayTree.d.ts +0 -107
- package/dist/collections/SplayTree.js +0 -351
- 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 -33
- package/dist/functools/index.d.ts +0 -106
- package/dist/functools/index.js +0 -203
- package/dist/globals/index.d.ts +0 -268
- package/dist/globals/index.js +0 -447
- package/dist/i18n/currency.d.ts +0 -27
- package/dist/i18n/currency.js +0 -100
- package/dist/i18n/date/index.d.ts +0 -210
- package/dist/i18n/date/index.js +0 -552
- package/dist/i18n/date/utils.d.ts +0 -64
- package/dist/i18n/date/utils.js +0 -192
- package/dist/i18n/duration.d.ts +0 -113
- package/dist/i18n/duration.js +0 -398
- package/dist/i18n/format.d.ts +0 -34
- package/dist/i18n/format.js +0 -378
- package/dist/i18n/index.d.ts +0 -9
- package/dist/i18n/index.js +0 -8
- package/dist/itertools/index.d.ts +0 -251
- package/dist/itertools/index.js +0 -434
- package/dist/math/index.d.ts +0 -79
- package/dist/math/index.js +0 -81
- package/dist/mod.d.ts +0 -1
- package/dist/mod.js +0 -1
- package/dist/operators/index.d.ts +0 -148
- package/dist/operators/index.js +0 -325
- package/dist/types.d.ts +0 -19
- package/dist/types.js +0 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const nativeIsError = Error.isError;
|
|
2
|
+
/**
|
|
3
|
+
* True for an error from any realm, as `Error.isError` decides. Where the runtime lacks
|
|
4
|
+
* `Error.isError`, the object tag decides; `DOMException` is not recognized by this fallback.
|
|
5
|
+
* Removed once `Error.isError` is Baseline.
|
|
6
|
+
* @param value Any value.
|
|
7
|
+
* @returns Whether `value` is an error.
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* isError(new TypeError('x')) // true
|
|
11
|
+
* isError({ name: 'Error', message: 'x' }) // false
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export function isError(value) {
|
|
15
|
+
if (nativeIsError !== undefined)
|
|
16
|
+
return nativeIsError(value);
|
|
17
|
+
return Object.prototype.toString.call(value) === '[object Error]';
|
|
18
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True for `null` and `undefined`.
|
|
3
|
+
* @param value Any value.
|
|
4
|
+
* @returns Whether `value` is `null` or `undefined`.
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* isNil(null) // true
|
|
8
|
+
* isNil(undefined) // true
|
|
9
|
+
* isNil(0) // false
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export declare function isNil(value: unknown): value is null | undefined;
|
package/dist/is/isNil.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True for `null` and `undefined`.
|
|
3
|
+
* @param value Any value.
|
|
4
|
+
* @returns Whether `value` is `null` or `undefined`.
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* isNil(null) // true
|
|
8
|
+
* isNil(undefined) // true
|
|
9
|
+
* isNil(0) // false
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export function isNil(value) {
|
|
13
|
+
return value == null;
|
|
14
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True when `value` is a plain object: an object literal, `Object.create(null)`, or either from
|
|
3
|
+
* another realm (an iframe, a worker, `vm`). Class instances, arrays, `Math`, `JSON`, `arguments`
|
|
4
|
+
* and objects with their own `Symbol.toStringTag` are not plain.
|
|
5
|
+
* @param value Any value.
|
|
6
|
+
* @returns Whether `value` is a plain object.
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* isPlainObject({ a: 1 }) // true
|
|
10
|
+
* isPlainObject(Object.create(null)) // true
|
|
11
|
+
* isPlainObject(new Date()) // false
|
|
12
|
+
* isPlainObject(new (class Point {})()) // false
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function isPlainObject(value: unknown): value is Record<PropertyKey, unknown>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const OBJECT_SOURCE = Function.prototype.toString.call(Object);
|
|
2
|
+
/**
|
|
3
|
+
* `Object.prototype` of this realm or of another one: its constructor has `Object`'s source.
|
|
4
|
+
*/
|
|
5
|
+
function isObjectPrototype(proto) {
|
|
6
|
+
if (proto === Object.prototype)
|
|
7
|
+
return true;
|
|
8
|
+
if (proto === null || Object.getPrototypeOf(proto) !== null)
|
|
9
|
+
return false;
|
|
10
|
+
const ctor = Object.getOwnPropertyDescriptor(proto, 'constructor')?.value;
|
|
11
|
+
return typeof ctor === 'function' && Function.prototype.toString.call(ctor) === OBJECT_SOURCE;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* True when `value` is a plain object: an object literal, `Object.create(null)`, or either from
|
|
15
|
+
* another realm (an iframe, a worker, `vm`). Class instances, arrays, `Math`, `JSON`, `arguments`
|
|
16
|
+
* and objects with their own `Symbol.toStringTag` are not plain.
|
|
17
|
+
* @param value Any value.
|
|
18
|
+
* @returns Whether `value` is a plain object.
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* isPlainObject({ a: 1 }) // true
|
|
22
|
+
* isPlainObject(Object.create(null)) // true
|
|
23
|
+
* isPlainObject(new Date()) // false
|
|
24
|
+
* isPlainObject(new (class Point {})()) // false
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export function isPlainObject(value) {
|
|
28
|
+
if (value === null || typeof value !== 'object')
|
|
29
|
+
return false;
|
|
30
|
+
if (Object.prototype.toString.call(value) !== '[object Object]')
|
|
31
|
+
return false;
|
|
32
|
+
const proto = Object.getPrototypeOf(value);
|
|
33
|
+
return proto === null || isObjectPrototype(proto);
|
|
34
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Number helpers: `clamp`, `inRange`, decimal `round`, `floor` and `ceil`, `sum`, `mean` and
|
|
3
|
+
* `formatBytes`.
|
|
4
|
+
* @module number
|
|
5
|
+
*/
|
|
6
|
+
export { ceil, clamp, floor, inRange, round } from './round.js';
|
|
7
|
+
export { type FormatBytesOptions, formatBytes, mean, sum } from './stats.js';
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rounds `n` to `digits` places after the decimal point, ties toward `+Infinity` as `Math.round`
|
|
3
|
+
* does. It rounds the decimal that `String(n)` prints, not the binary value, so `round(1.005, 2)`
|
|
4
|
+
* is `1.01` where `(1.005).toFixed(2)` is `'1.00'`. Negative `digits` round to tens, hundreds and
|
|
5
|
+
* so on. Infinities and NaN come back unchanged. A result too large for a number, such as
|
|
6
|
+
* `round(Number.MAX_VALUE, -308)`, is `Infinity`. `-0` becomes `0`, unlike `Math.round`, so a
|
|
7
|
+
* value that rounds to zero, such as `round(-0.004, 2)`, does not print as `-0` through
|
|
8
|
+
* `Intl.NumberFormat`.
|
|
9
|
+
* @param n The number to round.
|
|
10
|
+
* @param digits Places after the decimal point (default 0); may be negative.
|
|
11
|
+
* @returns The rounded number.
|
|
12
|
+
* @throws {TypeError} when `n` or `digits` is not a number.
|
|
13
|
+
* @throws {RangeError} when `digits` is not an integer.
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* round(4.006, 2) // 4.01
|
|
17
|
+
* round(4060, -2) // 4100
|
|
18
|
+
* round(-2.5) // -2
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function round(n: number, digits?: number): number;
|
|
22
|
+
/**
|
|
23
|
+
* Rounds `n` down, toward `-Infinity`, to `digits` places after the decimal point, on the decimal
|
|
24
|
+
* that `String(n)` prints, as {@link round} does.
|
|
25
|
+
* @param n The number to round down.
|
|
26
|
+
* @param digits Places after the decimal point (default 0); may be negative.
|
|
27
|
+
* @returns The rounded number.
|
|
28
|
+
* @throws {TypeError} when `n` or `digits` is not a number.
|
|
29
|
+
* @throws {RangeError} when `digits` is not an integer.
|
|
30
|
+
* @example
|
|
31
|
+
* ```ts
|
|
32
|
+
* floor(4.006, 2) // 4
|
|
33
|
+
* floor(0.29, 2) // 0.29
|
|
34
|
+
* floor(4060, -2) // 4000
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare function floor(n: number, digits?: number): number;
|
|
38
|
+
/**
|
|
39
|
+
* Rounds `n` up, toward `+Infinity`, to `digits` places after the decimal point, on the decimal
|
|
40
|
+
* that `String(n)` prints, as {@link round} does.
|
|
41
|
+
* @param n The number to round up.
|
|
42
|
+
* @param digits Places after the decimal point (default 0); may be negative.
|
|
43
|
+
* @returns The rounded number.
|
|
44
|
+
* @throws {TypeError} when `n` or `digits` is not a number.
|
|
45
|
+
* @throws {RangeError} when `digits` is not an integer.
|
|
46
|
+
* @example
|
|
47
|
+
* ```ts
|
|
48
|
+
* ceil(4.006, 2) // 4.01
|
|
49
|
+
* ceil(6040, -2) // 6100
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare function ceil(n: number, digits?: number): number;
|
|
53
|
+
/**
|
|
54
|
+
* Limits `n` to the range from `min` to `max`, both included. NaN stays NaN.
|
|
55
|
+
* @param n The number to clamp.
|
|
56
|
+
* @param min The lower bound.
|
|
57
|
+
* @param max The upper bound.
|
|
58
|
+
* @returns `n`, `min` or `max`.
|
|
59
|
+
* @throws {TypeError} when an argument is not a number.
|
|
60
|
+
* @throws {RangeError} when a bound is NaN or `min > max`.
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* clamp(-10, -5, 5) // -5
|
|
64
|
+
* clamp(10, -5, 5) // 5
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export declare function clamp(n: number, min: number, max: number): number;
|
|
68
|
+
/**
|
|
69
|
+
* Checks whether `n` is at least `start` and below `end`. With two arguments the range is
|
|
70
|
+
* `[0, end)`, and reversed bounds swap, as in lodash. A NaN `n` is never in range.
|
|
71
|
+
* @param n The number to check.
|
|
72
|
+
* @param start The lower bound (included).
|
|
73
|
+
* @param end The upper bound (excluded).
|
|
74
|
+
* @returns Whether `n` is in the range.
|
|
75
|
+
* @throws {TypeError} when an argument is not a number.
|
|
76
|
+
* @throws {RangeError} when a bound is NaN.
|
|
77
|
+
* @example
|
|
78
|
+
* ```ts
|
|
79
|
+
* inRange(3, 2, 4) // true
|
|
80
|
+
* inRange(4, 8) // true
|
|
81
|
+
* inRange(-3, -2, -6) // true
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export declare function inRange(n: number, start: number, end: number): boolean;
|
|
85
|
+
/** {@link inRange} from `0` to `end`. */
|
|
86
|
+
export declare function inRange(n: number, end: number): boolean;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
function assertNumber(n, name) {
|
|
2
|
+
if (typeof n !== 'number')
|
|
3
|
+
throw new TypeError(`${name} must be a number`);
|
|
4
|
+
}
|
|
5
|
+
/** The shortest round-trip decimal of `|n|` as integer digits and a base-10 exponent. */
|
|
6
|
+
function decimalParts(n) {
|
|
7
|
+
const [coefficient, exp = '0'] = String(Math.abs(n)).split('e');
|
|
8
|
+
const [whole, fraction = ''] = coefficient.split('.');
|
|
9
|
+
const digits = (whole + fraction).replace(/^0+(?=\d)/, '');
|
|
10
|
+
return { digits, exponent: Number(exp) - fraction.length };
|
|
11
|
+
}
|
|
12
|
+
function roundTo(n, digits, mode) {
|
|
13
|
+
assertNumber(n, 'n');
|
|
14
|
+
assertNumber(digits, 'digits');
|
|
15
|
+
if (!Number.isSafeInteger(digits))
|
|
16
|
+
throw new RangeError('digits must be an integer');
|
|
17
|
+
if (!Number.isFinite(n) || n === 0)
|
|
18
|
+
return n === 0 ? 0 : n;
|
|
19
|
+
const parts = decimalParts(n);
|
|
20
|
+
const drop = -digits - parts.exponent;
|
|
21
|
+
if (drop <= 0)
|
|
22
|
+
return n;
|
|
23
|
+
const negative = n < 0;
|
|
24
|
+
const { length } = parts.digits;
|
|
25
|
+
// Past the leading digit the dropped part is below half a unit, and it is never zero.
|
|
26
|
+
const head = length > drop ? parts.digits.slice(0, length - drop) : '0';
|
|
27
|
+
const tail = length >= drop ? parts.digits.slice(length - drop) : '';
|
|
28
|
+
const exact = drop <= length && /^0*$/.test(tail);
|
|
29
|
+
let up;
|
|
30
|
+
if (mode === 'floor')
|
|
31
|
+
up = negative && !exact;
|
|
32
|
+
else if (mode === 'ceil')
|
|
33
|
+
up = !negative && !exact;
|
|
34
|
+
else {
|
|
35
|
+
const half = '5'.padEnd(tail.length, '0');
|
|
36
|
+
up = tail > half || (tail === half && !negative);
|
|
37
|
+
}
|
|
38
|
+
const magnitude = BigInt(head) + (up ? 1n : 0n);
|
|
39
|
+
const result = Number(`${negative ? '-' : ''}${magnitude}e${-digits}`);
|
|
40
|
+
return result === 0 ? 0 : result;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Rounds `n` to `digits` places after the decimal point, ties toward `+Infinity` as `Math.round`
|
|
44
|
+
* does. It rounds the decimal that `String(n)` prints, not the binary value, so `round(1.005, 2)`
|
|
45
|
+
* is `1.01` where `(1.005).toFixed(2)` is `'1.00'`. Negative `digits` round to tens, hundreds and
|
|
46
|
+
* so on. Infinities and NaN come back unchanged. A result too large for a number, such as
|
|
47
|
+
* `round(Number.MAX_VALUE, -308)`, is `Infinity`. `-0` becomes `0`, unlike `Math.round`, so a
|
|
48
|
+
* value that rounds to zero, such as `round(-0.004, 2)`, does not print as `-0` through
|
|
49
|
+
* `Intl.NumberFormat`.
|
|
50
|
+
* @param n The number to round.
|
|
51
|
+
* @param digits Places after the decimal point (default 0); may be negative.
|
|
52
|
+
* @returns The rounded number.
|
|
53
|
+
* @throws {TypeError} when `n` or `digits` is not a number.
|
|
54
|
+
* @throws {RangeError} when `digits` is not an integer.
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* round(4.006, 2) // 4.01
|
|
58
|
+
* round(4060, -2) // 4100
|
|
59
|
+
* round(-2.5) // -2
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export function round(n, digits = 0) {
|
|
63
|
+
return roundTo(n, digits, 'halfCeil');
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Rounds `n` down, toward `-Infinity`, to `digits` places after the decimal point, on the decimal
|
|
67
|
+
* that `String(n)` prints, as {@link round} does.
|
|
68
|
+
* @param n The number to round down.
|
|
69
|
+
* @param digits Places after the decimal point (default 0); may be negative.
|
|
70
|
+
* @returns The rounded number.
|
|
71
|
+
* @throws {TypeError} when `n` or `digits` is not a number.
|
|
72
|
+
* @throws {RangeError} when `digits` is not an integer.
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* floor(4.006, 2) // 4
|
|
76
|
+
* floor(0.29, 2) // 0.29
|
|
77
|
+
* floor(4060, -2) // 4000
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export function floor(n, digits = 0) {
|
|
81
|
+
return roundTo(n, digits, 'floor');
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Rounds `n` up, toward `+Infinity`, to `digits` places after the decimal point, on the decimal
|
|
85
|
+
* that `String(n)` prints, as {@link round} does.
|
|
86
|
+
* @param n The number to round up.
|
|
87
|
+
* @param digits Places after the decimal point (default 0); may be negative.
|
|
88
|
+
* @returns The rounded number.
|
|
89
|
+
* @throws {TypeError} when `n` or `digits` is not a number.
|
|
90
|
+
* @throws {RangeError} when `digits` is not an integer.
|
|
91
|
+
* @example
|
|
92
|
+
* ```ts
|
|
93
|
+
* ceil(4.006, 2) // 4.01
|
|
94
|
+
* ceil(6040, -2) // 6100
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export function ceil(n, digits = 0) {
|
|
98
|
+
return roundTo(n, digits, 'ceil');
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Limits `n` to the range from `min` to `max`, both included. NaN stays NaN.
|
|
102
|
+
* @param n The number to clamp.
|
|
103
|
+
* @param min The lower bound.
|
|
104
|
+
* @param max The upper bound.
|
|
105
|
+
* @returns `n`, `min` or `max`.
|
|
106
|
+
* @throws {TypeError} when an argument is not a number.
|
|
107
|
+
* @throws {RangeError} when a bound is NaN or `min > max`.
|
|
108
|
+
* @example
|
|
109
|
+
* ```ts
|
|
110
|
+
* clamp(-10, -5, 5) // -5
|
|
111
|
+
* clamp(10, -5, 5) // 5
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export function clamp(n, min, max) {
|
|
115
|
+
assertNumber(n, 'n');
|
|
116
|
+
assertNumber(min, 'min');
|
|
117
|
+
assertNumber(max, 'max');
|
|
118
|
+
if (!(min <= max))
|
|
119
|
+
throw new RangeError('min and max must not be NaN, and min must be <= max');
|
|
120
|
+
return Math.min(Math.max(n, min), max);
|
|
121
|
+
}
|
|
122
|
+
export function inRange(n, first, last) {
|
|
123
|
+
assertNumber(n, 'n');
|
|
124
|
+
const [start, end] = last === undefined ? [0, first] : [first, last];
|
|
125
|
+
assertNumber(start, 'start');
|
|
126
|
+
assertNumber(end, 'end');
|
|
127
|
+
if (Number.isNaN(start) || Number.isNaN(end))
|
|
128
|
+
throw new RangeError('start and end must not be NaN');
|
|
129
|
+
return n >= Math.min(start, end) && n < Math.max(start, end);
|
|
130
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adds the numbers of an iterable from left to right, as a loop with `+` does; an empty iterable
|
|
3
|
+
* sums to `0`. For a correctly rounded total, use `Math.sumPrecise` where the runtime has it.
|
|
4
|
+
* @param values The numbers to add.
|
|
5
|
+
* @returns The total.
|
|
6
|
+
* @throws {TypeError} when `values` is not iterable, `null` and `undefined` included (lodash
|
|
7
|
+
* sums those to `0`), or holds a non-number.
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts
|
|
10
|
+
* sum([4, 2, 8, 6]) // 20
|
|
11
|
+
* sum(new Set([1, 2])) // 3
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare function sum(values: Iterable<number>): number;
|
|
15
|
+
/**
|
|
16
|
+
* Averages the numbers of an iterable; an empty iterable gives `NaN`, as in lodash.
|
|
17
|
+
* @param values The numbers to average.
|
|
18
|
+
* @returns The arithmetic mean.
|
|
19
|
+
* @throws {TypeError} when `values` is not iterable, `null` and `undefined` included (lodash
|
|
20
|
+
* averages those to `NaN`), or holds a non-number.
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* mean([4, 2, 8, 6]) // 5
|
|
24
|
+
* mean([]) // NaN
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function mean(values: Iterable<number>): number;
|
|
28
|
+
/** Options for {@link formatBytes}. */
|
|
29
|
+
export interface FormatBytesOptions {
|
|
30
|
+
/** A BCP 47 tag or list of tags for the number, as `Intl.NumberFormat` takes. */
|
|
31
|
+
locale?: Intl.LocalesArgument;
|
|
32
|
+
/** Use powers of 1024 and IEC units (`KiB`, `MiB`) instead of powers of 1000 (`kB`, `MB`). */
|
|
33
|
+
binary?: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Formats a byte count for people: powers of 1000 with SI units by default, or powers of 1024
|
|
37
|
+
* with IEC units when `binary` is set, rounded to about three significant digits. The number is
|
|
38
|
+
* formatted with `Intl.NumberFormat` for `locale`; the unit symbol follows after a space. Bytes
|
|
39
|
+
* past the yottabyte keep the largest unit.
|
|
40
|
+
* @param n The byte count; may be negative or fractional.
|
|
41
|
+
* @param options `locale` and `binary`.
|
|
42
|
+
* @returns The formatted size.
|
|
43
|
+
* @throws {TypeError} when `n` is not a number.
|
|
44
|
+
* @throws {RangeError} when `n` is not finite.
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* formatBytes(1536) // '1.54 kB'
|
|
48
|
+
* formatBytes(1536, { binary: true }) // '1.5 KiB'
|
|
49
|
+
* formatBytes(1234567, { locale: 'de' }) // '1,23 MB'
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export declare function formatBytes(n: number, options?: FormatBytesOptions): string;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { round } from './round.js';
|
|
2
|
+
/** Adds the numbers of `values` from left to right and counts them. */
|
|
3
|
+
function total(values, name) {
|
|
4
|
+
if (values == null || typeof values[Symbol.iterator] !== 'function') {
|
|
5
|
+
const received = values === null ? 'null' : typeof values;
|
|
6
|
+
throw new TypeError(`${name} expects an iterable of numbers, got ${received}`);
|
|
7
|
+
}
|
|
8
|
+
let sum = 0;
|
|
9
|
+
let count = 0;
|
|
10
|
+
for (const value of values) {
|
|
11
|
+
if (typeof value !== 'number')
|
|
12
|
+
throw new TypeError(`${name} expects numbers, got ${typeof value}`);
|
|
13
|
+
sum += value;
|
|
14
|
+
count++;
|
|
15
|
+
}
|
|
16
|
+
return { sum, count };
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Adds the numbers of an iterable from left to right, as a loop with `+` does; an empty iterable
|
|
20
|
+
* sums to `0`. For a correctly rounded total, use `Math.sumPrecise` where the runtime has it.
|
|
21
|
+
* @param values The numbers to add.
|
|
22
|
+
* @returns The total.
|
|
23
|
+
* @throws {TypeError} when `values` is not iterable, `null` and `undefined` included (lodash
|
|
24
|
+
* sums those to `0`), or holds a non-number.
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* sum([4, 2, 8, 6]) // 20
|
|
28
|
+
* sum(new Set([1, 2])) // 3
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export function sum(values) {
|
|
32
|
+
return total(values, 'sum').sum;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Averages the numbers of an iterable; an empty iterable gives `NaN`, as in lodash.
|
|
36
|
+
* @param values The numbers to average.
|
|
37
|
+
* @returns The arithmetic mean.
|
|
38
|
+
* @throws {TypeError} when `values` is not iterable, `null` and `undefined` included (lodash
|
|
39
|
+
* averages those to `NaN`), or holds a non-number.
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* mean([4, 2, 8, 6]) // 5
|
|
43
|
+
* mean([]) // NaN
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export function mean(values) {
|
|
47
|
+
const { sum, count } = total(values, 'mean');
|
|
48
|
+
return sum / count;
|
|
49
|
+
}
|
|
50
|
+
const DECIMAL_UNITS = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
|
51
|
+
const BINARY_UNITS = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
|
|
52
|
+
/** Fraction digits that show three significant digits below 1000 and none above. */
|
|
53
|
+
function fractionDigits(size) {
|
|
54
|
+
return size < 10 ? 2 : size < 100 ? 1 : 0;
|
|
55
|
+
}
|
|
56
|
+
/** Rounds a non-negative size to the digits {@link fractionDigits} picks for it. */
|
|
57
|
+
function roundSize(size) {
|
|
58
|
+
return round(size, fractionDigits(size));
|
|
59
|
+
}
|
|
60
|
+
const MAX_CACHED_FORMATS = 64;
|
|
61
|
+
/** Formats by fraction digits and locale tag, cleared when full since locales may come from requests. */
|
|
62
|
+
const formats = new Map();
|
|
63
|
+
function numberFormat(locale, digits) {
|
|
64
|
+
const options = { maximumFractionDigits: digits };
|
|
65
|
+
// Locale lists and Intl.Locale objects have no cheap exact key, so they are not cached.
|
|
66
|
+
if (locale !== undefined && typeof locale !== 'string')
|
|
67
|
+
return new Intl.NumberFormat(locale, options);
|
|
68
|
+
const key = locale === undefined ? `${digits}` : `${digits} ${locale}`;
|
|
69
|
+
let format = formats.get(key);
|
|
70
|
+
if (format === undefined) {
|
|
71
|
+
format = new Intl.NumberFormat(locale, options);
|
|
72
|
+
if (formats.size >= MAX_CACHED_FORMATS)
|
|
73
|
+
formats.clear();
|
|
74
|
+
formats.set(key, format);
|
|
75
|
+
}
|
|
76
|
+
return format;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Formats a byte count for people: powers of 1000 with SI units by default, or powers of 1024
|
|
80
|
+
* with IEC units when `binary` is set, rounded to about three significant digits. The number is
|
|
81
|
+
* formatted with `Intl.NumberFormat` for `locale`; the unit symbol follows after a space. Bytes
|
|
82
|
+
* past the yottabyte keep the largest unit.
|
|
83
|
+
* @param n The byte count; may be negative or fractional.
|
|
84
|
+
* @param options `locale` and `binary`.
|
|
85
|
+
* @returns The formatted size.
|
|
86
|
+
* @throws {TypeError} when `n` is not a number.
|
|
87
|
+
* @throws {RangeError} when `n` is not finite.
|
|
88
|
+
* @example
|
|
89
|
+
* ```ts
|
|
90
|
+
* formatBytes(1536) // '1.54 kB'
|
|
91
|
+
* formatBytes(1536, { binary: true }) // '1.5 KiB'
|
|
92
|
+
* formatBytes(1234567, { locale: 'de' }) // '1,23 MB'
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export function formatBytes(n, options) {
|
|
96
|
+
if (typeof n !== 'number')
|
|
97
|
+
throw new TypeError('n must be a number');
|
|
98
|
+
if (!Number.isFinite(n))
|
|
99
|
+
throw new RangeError('n must be finite');
|
|
100
|
+
const binary = options?.binary ?? false;
|
|
101
|
+
const units = binary ? BINARY_UNITS : DECIMAL_UNITS;
|
|
102
|
+
const base = binary ? 1024 : 1000;
|
|
103
|
+
const size = Math.abs(n);
|
|
104
|
+
let exponent = 0;
|
|
105
|
+
let rounded = roundSize(size);
|
|
106
|
+
while (exponent < 8 && rounded >= base) {
|
|
107
|
+
exponent++;
|
|
108
|
+
rounded = roundSize(size / base ** exponent);
|
|
109
|
+
}
|
|
110
|
+
// `|| 0` turns the -0 of a negative size that rounds to zero into 0.
|
|
111
|
+
const value = (n < 0 ? -rounded : rounded) || 0;
|
|
112
|
+
const formatted = numberFormat(options?.locale, fractionDigits(rounded)).format(value);
|
|
113
|
+
// Intl's `style: 'unit'` would localize the symbols, but it has no IEC units and stops at petabyte.
|
|
114
|
+
return `${formatted} ${units[exponent]}`;
|
|
115
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cloneDeep`: a structural copy that keeps prototypes, symbol keys, sharing and cycles.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* A deep copy of `value`. Plain objects, arrays, `Map`, `Set`, `Date`, `RegExp`, typed arrays,
|
|
6
|
+
* `DataView`, `ArrayBuffer`, `SharedArrayBuffer` and boxed primitives are copied with their
|
|
7
|
+
* prototype (a subclass stays a subclass) and their own enumerable symbol keys; all but typed
|
|
8
|
+
* arrays, `DataView` and `String` wrappers also keep their own enumerable string keys, and arrays
|
|
9
|
+
* keep their holes. `Map` keys keep their identity while values are copied. A subclass copy gets
|
|
10
|
+
* the prototype only: its constructor does not run, so it has none of its private fields. A
|
|
11
|
+
* resizable or growable buffer stays so, and a detached one copies as an empty buffer. Class
|
|
12
|
+
* instances, functions, errors, promises and every other object are kept by reference:
|
|
13
|
+
* `structuredClone` throws on them, and copying their fields would produce an object whose private
|
|
14
|
+
* state and invariants are gone. An object reached twice is copied once, so shared references and
|
|
15
|
+
* cycles stay shared and cyclic in the copy, and views over one buffer share one copied buffer.
|
|
16
|
+
* @param value The value to copy.
|
|
17
|
+
* @returns The copy.
|
|
18
|
+
* @throws {RangeError} past 1000 levels of nesting.
|
|
19
|
+
* @throws {TypeError} for a typed array kind this runtime has no constructor for.
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* const src = { when: new Date(0), tags: new Set(['a']), list: [{ id: 1 }] }
|
|
23
|
+
* const copy = cloneDeep(src)
|
|
24
|
+
* copy.list[0] === src.list[0] // false
|
|
25
|
+
* copy.when.getTime() // 0
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function cloneDeep<T>(value: T): T;
|