shelving 1.138.0 → 1.139.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/db/Provider.js +3 -3
- package/error/BaseError.d.ts +3 -1
- package/error/index.d.ts +0 -1
- package/error/index.js +0 -1
- package/markup/rule/link.js +3 -2
- package/package.json +1 -1
- package/schema/AllowSchema.js +4 -4
- package/schema/DateSchema.js +2 -1
- package/schema/EntitySchema.js +4 -4
- package/schema/NumberSchema.js +3 -2
- package/store/ArrayStore.js +5 -5
- package/util/array.d.ts +67 -66
- package/util/array.js +90 -30
- package/util/async.js +4 -4
- package/util/base64.d.ts +7 -7
- package/util/base64.js +40 -31
- package/util/boolean.d.ts +6 -5
- package/util/boolean.js +11 -11
- package/util/bytes.d.ts +4 -1
- package/util/bytes.js +7 -3
- package/util/class.js +2 -2
- package/util/color.d.ts +4 -3
- package/util/color.js +5 -6
- package/util/crypto.d.ts +21 -0
- package/util/crypto.js +80 -0
- package/util/data.d.ts +6 -13
- package/util/data.js +8 -12
- package/util/date.d.ts +35 -27
- package/util/date.js +90 -82
- package/util/dictionary.d.ts +13 -7
- package/util/dictionary.js +12 -12
- package/util/entity.d.ts +8 -7
- package/util/entity.js +8 -8
- package/util/equal.d.ts +3 -2
- package/util/equal.js +5 -5
- package/util/file.d.ts +2 -1
- package/util/file.js +3 -3
- package/util/format.d.ts +51 -0
- package/util/format.js +113 -0
- package/util/function.js +2 -2
- package/util/index.d.ts +2 -0
- package/util/index.js +2 -0
- package/util/iterate.d.ts +0 -15
- package/util/iterate.js +0 -55
- package/util/jwt.d.ts +4 -2
- package/util/jwt.js +50 -41
- package/util/link.d.ts +26 -10
- package/util/link.js +34 -21
- package/util/map.d.ts +8 -7
- package/util/map.js +17 -18
- package/util/null.d.ts +7 -6
- package/util/null.js +13 -13
- package/util/number.d.ts +36 -42
- package/util/number.js +60 -82
- package/util/object.d.ts +0 -7
- package/util/object.js +4 -24
- package/util/optional.d.ts +2 -1
- package/util/optional.js +2 -2
- package/util/path.d.ts +7 -6
- package/util/path.js +10 -10
- package/util/query.js +3 -3
- package/util/random.js +2 -2
- package/util/regexp.js +2 -2
- package/util/set.d.ts +7 -6
- package/util/set.js +13 -13
- package/util/string.d.ts +26 -37
- package/util/string.js +40 -69
- package/util/template.d.ts +5 -4
- package/util/template.js +14 -13
- package/util/time.d.ts +7 -8
- package/util/time.js +14 -21
- package/util/transform.d.ts +3 -2
- package/util/transform.js +0 -1
- package/util/undefined.d.ts +4 -3
- package/util/undefined.js +8 -6
- package/util/units.d.ts +1 -2
- package/util/units.js +1 -1
- package/util/update.js +3 -3
- package/util/url.d.ts +6 -7
- package/util/url.js +7 -17
- package/util/validate.d.ts +2 -2
- package/error/AssertionError.d.ts +0 -8
- package/error/AssertionError.js +0 -12
package/util/null.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AnyCaller } from "../error/BaseError.js";
|
|
1
2
|
/** Function that always returns null. */
|
|
2
3
|
export declare function getNull(): null;
|
|
3
4
|
/** Nullable is the value or `null` */
|
|
@@ -5,22 +6,22 @@ export type Nullable<T> = T | null;
|
|
|
5
6
|
/** Is a value null? */
|
|
6
7
|
export declare function isNull(value: unknown): value is null;
|
|
7
8
|
/** Assert that a value is not null. */
|
|
8
|
-
export declare function assertNull<T>(value: Nullable<T
|
|
9
|
+
export declare function assertNull<T>(value: Nullable<T>, caller?: AnyCaller): asserts value is T;
|
|
9
10
|
/** Is a value not null? */
|
|
10
11
|
export declare function notNull<T>(value: Nullable<T>): value is T;
|
|
11
12
|
/** Assert that a value is not null. */
|
|
12
|
-
export declare function assertNotNull<T>(value: Nullable<T
|
|
13
|
+
export declare function assertNotNull<T>(value: Nullable<T>, caller?: AnyCaller): asserts value is T;
|
|
13
14
|
/** Get the not-nullish version of value. */
|
|
14
|
-
export declare function
|
|
15
|
+
export declare function requireNotNull<T>(value: Nullable<T>, caller?: AnyCaller): T;
|
|
15
16
|
/** Nullish is the value or `null` or `undefined` */
|
|
16
17
|
export type Nullish<T> = T | null | undefined;
|
|
17
18
|
/** Is a value nullish? */
|
|
18
19
|
export declare function isNullish<T>(value: Nullish<T>): value is null | undefined;
|
|
19
20
|
/** Assert that a value is not nullish. */
|
|
20
|
-
export declare function assertNullish<T>(value: Nullish<T
|
|
21
|
+
export declare function assertNullish<T>(value: Nullish<T>, caller?: AnyCaller): asserts value is T;
|
|
21
22
|
/** Is a value not nullish? */
|
|
22
23
|
export declare function notNullish<T>(value: Nullish<T>): value is T;
|
|
23
24
|
/** Assert that a value is not nullish. */
|
|
24
|
-
export declare function assertNotNullish<T>(value: Nullish<T
|
|
25
|
+
export declare function assertNotNullish<T>(value: Nullish<T>, caller?: AnyCaller): asserts value is T;
|
|
25
26
|
/** Get the not-nullish version of value. */
|
|
26
|
-
export declare function
|
|
27
|
+
export declare function requireNotNullish<T>(value: Nullish<T>, caller?: AnyCaller): T;
|
package/util/null.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RequiredError } from "../error/RequiredError.js";
|
|
2
2
|
/** Function that always returns null. */
|
|
3
3
|
export function getNull() {
|
|
4
4
|
return null;
|
|
@@ -8,22 +8,22 @@ export function isNull(value) {
|
|
|
8
8
|
return value === null;
|
|
9
9
|
}
|
|
10
10
|
/** Assert that a value is not null. */
|
|
11
|
-
export function assertNull(value) {
|
|
11
|
+
export function assertNull(value, caller = assertNull) {
|
|
12
12
|
if (value !== null)
|
|
13
|
-
throw new
|
|
13
|
+
throw new RequiredError("Must be null", { received: value, caller });
|
|
14
14
|
}
|
|
15
15
|
/** Is a value not null? */
|
|
16
16
|
export function notNull(value) {
|
|
17
17
|
return value !== null;
|
|
18
18
|
}
|
|
19
19
|
/** Assert that a value is not null. */
|
|
20
|
-
export function assertNotNull(value) {
|
|
20
|
+
export function assertNotNull(value, caller = assertNotNull) {
|
|
21
21
|
if (value === null)
|
|
22
|
-
throw new
|
|
22
|
+
throw new RequiredError("Must not be null", { received: value, caller });
|
|
23
23
|
}
|
|
24
24
|
/** Get the not-nullish version of value. */
|
|
25
|
-
export function
|
|
26
|
-
assertNotNull(value);
|
|
25
|
+
export function requireNotNull(value, caller = requireNotNull) {
|
|
26
|
+
assertNotNull(value, caller);
|
|
27
27
|
return value;
|
|
28
28
|
}
|
|
29
29
|
/** Is a value nullish? */
|
|
@@ -31,21 +31,21 @@ export function isNullish(value) {
|
|
|
31
31
|
return value === null || value === undefined;
|
|
32
32
|
}
|
|
33
33
|
/** Assert that a value is not nullish. */
|
|
34
|
-
export function assertNullish(value) {
|
|
34
|
+
export function assertNullish(value, caller = assertNullish) {
|
|
35
35
|
if (value !== null && value !== undefined)
|
|
36
|
-
throw new
|
|
36
|
+
throw new RequiredError("Must be null or undefined", { received: value, caller });
|
|
37
37
|
}
|
|
38
38
|
/** Is a value not nullish? */
|
|
39
39
|
export function notNullish(value) {
|
|
40
40
|
return value !== null && value !== undefined;
|
|
41
41
|
}
|
|
42
42
|
/** Assert that a value is not nullish. */
|
|
43
|
-
export function assertNotNullish(value) {
|
|
43
|
+
export function assertNotNullish(value, caller = assertNotNullish) {
|
|
44
44
|
if (value === null || value === undefined)
|
|
45
|
-
throw new
|
|
45
|
+
throw new RequiredError("Must not be null or undefined", { received: value, caller });
|
|
46
46
|
}
|
|
47
47
|
/** Get the not-nullish version of value. */
|
|
48
|
-
export function
|
|
49
|
-
assertNotNullish(value);
|
|
48
|
+
export function requireNotNullish(value, caller = requireNotNullish) {
|
|
49
|
+
assertNotNullish(value, caller);
|
|
50
50
|
return value;
|
|
51
51
|
}
|
package/util/number.d.ts
CHANGED
|
@@ -1,40 +1,51 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import type { AnyCaller } from "../error/BaseError.js";
|
|
2
|
+
/** Values that can be converted to a number. */
|
|
3
|
+
export type PossibleNumber = number | string | Date;
|
|
4
|
+
/** Is a value a finite number? */
|
|
5
|
+
export declare function isNumber(value: unknown, min?: number, max?: number): value is number;
|
|
6
|
+
/** Assert that a value is a finite number. */
|
|
7
|
+
export declare function assertNumber(value: unknown, min?: number, max?: number, caller?: AnyCaller): asserts value is number;
|
|
7
8
|
/**
|
|
8
|
-
*
|
|
9
|
+
* Convert an unknown value to a finite number, or return `undefined` if it cannot be converted.
|
|
10
|
+
* - Note: numbers can be non-finite numbers like `NaN` or `Infinity`. These are detected and will always return `undefined`
|
|
9
11
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
12
|
+
* Conversion rules:
|
|
13
|
+
* - Finite numbers return numbers.
|
|
14
|
+
* - `-0` is normalised to `0`
|
|
15
|
+
* - Strings are parsed as numbers using `Number.parseFloat()` after removing all non-numeric characters.
|
|
16
|
+
* - Dates return their milliseconds (e.g. `date.getTime()`).
|
|
17
|
+
* - Everything else returns `undefined`
|
|
13
18
|
*/
|
|
14
|
-
export declare
|
|
15
|
-
/** Assert that a value is a number greater than. */
|
|
16
|
-
export declare function assertBetween(value: unknown, min: number, max: number): asserts value is number;
|
|
17
|
-
/** Assert that a value is a number greater than. */
|
|
18
|
-
export declare function assertMax(value: unknown, max: number): asserts value is number;
|
|
19
|
-
/** Assert that a value is a number less than. */
|
|
20
|
-
export declare function assertMin(value: unknown, min: number): asserts value is number;
|
|
19
|
+
export declare function getNumber(value: unknown): number | undefined;
|
|
21
20
|
/**
|
|
22
|
-
* Convert
|
|
23
|
-
|
|
21
|
+
* Convert a possible number to a finite number, or throw `ValueError` if the value cannot be converted.
|
|
22
|
+
*/
|
|
23
|
+
export declare function requireNumber(value: PossibleNumber, min?: number, max?: number, caller?: AnyCaller): number;
|
|
24
|
+
/** Is an unknown value an integer (optionally with specified min/max values). */
|
|
25
|
+
export declare function isInteger(value: unknown, min?: number, max?: number): value is number;
|
|
26
|
+
/** Assert that a value is an integer. */
|
|
27
|
+
export declare function assertInteger(value: unknown, min?: number, max?: number, caller?: AnyCaller): asserts value is number;
|
|
28
|
+
/**
|
|
29
|
+
* Convert an unknown value to an integer, or return `undefined` if it cannot be converted.
|
|
24
30
|
*
|
|
25
31
|
* Conversion rules:
|
|
26
|
-
* -
|
|
32
|
+
* - Integers return integers.
|
|
27
33
|
* - `-0` is normalised to `0`
|
|
28
|
-
* - Strings are parsed as
|
|
34
|
+
* - Strings are parsed as integers using `parseInt()` after removing non-numeric characters.
|
|
29
35
|
* - Dates return their milliseconds (e.g. `date.getTime()`).
|
|
30
36
|
* - Everything else returns `undefined`
|
|
31
37
|
*/
|
|
32
|
-
export declare function
|
|
38
|
+
export declare function getInteger(value: unknown): number | undefined;
|
|
39
|
+
/** Convert a possible number to an integer, or throw `ValueError` if the value cannot be converted. */
|
|
40
|
+
export declare function requireInteger(value: PossibleNumber, min?: number, max?: number, caller?: AnyCaller): number;
|
|
33
41
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
42
|
+
* Is a number within a specified range?
|
|
43
|
+
*
|
|
44
|
+
* @param num The number to test, e.g. `17`
|
|
45
|
+
* @param min The start of the range, e.g. `10`
|
|
46
|
+
* @param max The end of the range, e.g. `20`
|
|
36
47
|
*/
|
|
37
|
-
export declare function
|
|
48
|
+
export declare function isBetween(num: number, min: number, max: number): boolean;
|
|
38
49
|
/**
|
|
39
50
|
* Round numbers to a given step.
|
|
40
51
|
*
|
|
@@ -77,14 +88,6 @@ export declare function boundNumber(num: number, min: number, max: number): numb
|
|
|
77
88
|
* - e.g. `-2` bounded by `2` and `8` is `4`
|
|
78
89
|
*/
|
|
79
90
|
export declare function wrapNumber(num: number, min: number, max: number): number;
|
|
80
|
-
/** Format a number (based on the user's browser language settings). */
|
|
81
|
-
export declare function formatNumber(num: number, options?: Intl.NumberFormatOptions): string;
|
|
82
|
-
/** Format a number range (based on the user's browser language settings). */
|
|
83
|
-
export declare function formatRange(min: number, max: number, options?: Intl.NumberFormatOptions): string;
|
|
84
|
-
/** Format a number with a short suffix, e.g. `1,000 kg` */
|
|
85
|
-
export declare function formatQuantity(num: number, abbr: string, options?: Intl.NumberFormatOptions): string;
|
|
86
|
-
/** Format a number with a longer full-word suffix. */
|
|
87
|
-
export declare function pluralizeQuantity(num: number, singular: string, plural: string, options?: Intl.NumberFormatOptions): string;
|
|
88
91
|
/**
|
|
89
92
|
* Get a number as a percentage of another number.
|
|
90
93
|
*
|
|
@@ -92,15 +95,6 @@ export declare function pluralizeQuantity(num: number, singular: string, plural:
|
|
|
92
95
|
* @param denumerator The number representing the whole amount.
|
|
93
96
|
*/
|
|
94
97
|
export declare function getPercent(numerator: number, denumerator: number): number;
|
|
95
|
-
/**
|
|
96
|
-
* Format a percentage (combines `getPercent()` and `formatQuantity()` for convenience).
|
|
97
|
-
* - Defaults to showing no decimal places.
|
|
98
|
-
* - Defaults to rounding closer to zero (so that 99.99% is shown as 99%).
|
|
99
|
-
*
|
|
100
|
-
* @param numerator Number representing the amount of progress.
|
|
101
|
-
* @param denumerator The number representing the whole amount.
|
|
102
|
-
*/
|
|
103
|
-
export declare function formatPercent(numerator: number, denumerator: number, options?: Intl.NumberFormatOptions): string;
|
|
104
98
|
/** Sum an iterable set of numbers and return the total. */
|
|
105
99
|
export declare function sumNumbers(nums: Iterable<number>): number;
|
|
106
100
|
/** Find the number that's closest to a target in an iterable set of numbers. */
|
package/util/number.js
CHANGED
|
@@ -1,72 +1,85 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RequiredError } from "../error/RequiredError.js";
|
|
2
2
|
import { ValueError } from "../error/ValueError.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
return typeof value === "number";
|
|
3
|
+
/** Is a value a finite number? */
|
|
4
|
+
export function isNumber(value, min = Number.NEGATIVE_INFINITY, max = Number.POSITIVE_INFINITY) {
|
|
5
|
+
return Number.isFinite(value) && value >= min && value <= max;
|
|
7
6
|
}
|
|
8
|
-
/** Assert that a value is a number. */
|
|
9
|
-
export function assertNumber(value) {
|
|
10
|
-
if (
|
|
11
|
-
throw new
|
|
12
|
-
}
|
|
13
|
-
/** Assert that a value is a finite number (i.e. not `NaN` or positive/negative `Infinity`). */
|
|
14
|
-
export function assertFinite(value) {
|
|
15
|
-
if (typeof value !== "number" || !Number.isFinite(value))
|
|
16
|
-
throw new AssertionError("Must be finite number", { received: value, caller: assertFinite });
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Is a finite number within a specified range?
|
|
20
|
-
*
|
|
21
|
-
* @param num The number to test, e.g. `17`
|
|
22
|
-
* @param min The start of the range, e.g. `10`
|
|
23
|
-
* @param max The end of the range, e.g. `20`
|
|
24
|
-
*/
|
|
25
|
-
export const isBetween = (num, min, max) => num >= min && num <= max;
|
|
26
|
-
/** Assert that a value is a number greater than. */
|
|
27
|
-
export function assertBetween(value, min, max) {
|
|
28
|
-
if (typeof value !== "number" || isBetween(value, min, max))
|
|
29
|
-
throw new AssertionError(`Must be number between ${min} and ${max}`, { received: value, caller: assertBetween });
|
|
30
|
-
}
|
|
31
|
-
/** Assert that a value is a number greater than. */
|
|
32
|
-
export function assertMax(value, max) {
|
|
33
|
-
if (typeof value !== "number" || value > max)
|
|
34
|
-
throw new AssertionError(`Must be number with maximum ${max}`, { received: value, caller: assertMax });
|
|
35
|
-
}
|
|
36
|
-
/** Assert that a value is a number less than. */
|
|
37
|
-
export function assertMin(value, min) {
|
|
38
|
-
if (typeof value !== "number" || value < min)
|
|
39
|
-
throw new AssertionError(`Must be number with minimum ${min}`, { received: value, caller: assertMin });
|
|
7
|
+
/** Assert that a value is a finite number. */
|
|
8
|
+
export function assertNumber(value, min, max, caller = assertNumber) {
|
|
9
|
+
if (!isNumber(value, min, max))
|
|
10
|
+
throw new RequiredError(`Must be finite number${max !== undefined ? ` between ${min ?? 0} and ${max}` : min !== undefined ? ` above ${min}` : ""}`, { received: value, caller });
|
|
40
11
|
}
|
|
41
12
|
/**
|
|
42
|
-
* Convert an unknown value to a finite number or `undefined`
|
|
13
|
+
* Convert an unknown value to a finite number, or return `undefined` if it cannot be converted.
|
|
43
14
|
* - Note: numbers can be non-finite numbers like `NaN` or `Infinity`. These are detected and will always return `undefined`
|
|
44
15
|
*
|
|
45
16
|
* Conversion rules:
|
|
46
17
|
* - Finite numbers return numbers.
|
|
47
18
|
* - `-0` is normalised to `0`
|
|
48
|
-
* - Strings are parsed as numbers.
|
|
19
|
+
* - Strings are parsed as numbers using `Number.parseFloat()` after removing all non-numeric characters.
|
|
49
20
|
* - Dates return their milliseconds (e.g. `date.getTime()`).
|
|
50
21
|
* - Everything else returns `undefined`
|
|
51
22
|
*/
|
|
52
|
-
export function
|
|
23
|
+
export function getNumber(value) {
|
|
53
24
|
if (typeof value === "number" && Number.isFinite(value))
|
|
54
25
|
return value === 0 ? 0 : value;
|
|
55
26
|
if (typeof value === "string")
|
|
56
|
-
return
|
|
27
|
+
return getNumber(Number.parseFloat(value.replace(NOT_NUMERIC_REGEXP, "")));
|
|
57
28
|
if (value instanceof Date)
|
|
58
|
-
|
|
29
|
+
getNumber(value.getTime());
|
|
59
30
|
}
|
|
60
31
|
const NOT_NUMERIC_REGEXP = /[^0-9-.]/g;
|
|
61
32
|
/**
|
|
62
|
-
*
|
|
63
|
-
* @throws `ValueError` if the value cannot be converted.
|
|
33
|
+
* Convert a possible number to a finite number, or throw `ValueError` if the value cannot be converted.
|
|
64
34
|
*/
|
|
65
|
-
export function
|
|
66
|
-
const num =
|
|
67
|
-
|
|
35
|
+
export function requireNumber(value, min, max, caller) {
|
|
36
|
+
const num = getNumber(value);
|
|
37
|
+
assertNumber(num, min, max, caller);
|
|
68
38
|
return num;
|
|
69
39
|
}
|
|
40
|
+
/** Is an unknown value an integer (optionally with specified min/max values). */
|
|
41
|
+
export function isInteger(value, min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER) {
|
|
42
|
+
return Number.isInteger(value) && value >= min && value <= max;
|
|
43
|
+
}
|
|
44
|
+
/** Assert that a value is an integer. */
|
|
45
|
+
export function assertInteger(value, min, max, caller = assertInteger) {
|
|
46
|
+
if (!isInteger(value, min, max))
|
|
47
|
+
throw new RequiredError(`Must be integer${max !== undefined ? ` between ${min ?? 0} and ${max}` : min !== undefined ? ` above ${min}` : ""}`, { received: value, caller });
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Convert an unknown value to an integer, or return `undefined` if it cannot be converted.
|
|
51
|
+
*
|
|
52
|
+
* Conversion rules:
|
|
53
|
+
* - Integers return integers.
|
|
54
|
+
* - `-0` is normalised to `0`
|
|
55
|
+
* - Strings are parsed as integers using `parseInt()` after removing non-numeric characters.
|
|
56
|
+
* - Dates return their milliseconds (e.g. `date.getTime()`).
|
|
57
|
+
* - Everything else returns `undefined`
|
|
58
|
+
*/
|
|
59
|
+
export function getInteger(value) {
|
|
60
|
+
if (typeof value === "number" && Number.isInteger(value))
|
|
61
|
+
return value === 0 ? 0 : value;
|
|
62
|
+
if (typeof value === "string")
|
|
63
|
+
return getInteger(Number.parseInt(value.replace(NOT_NUMERIC_REGEXP, ""), 10));
|
|
64
|
+
if (value instanceof Date)
|
|
65
|
+
return getInteger(value.getTime());
|
|
66
|
+
}
|
|
67
|
+
/** Convert a possible number to an integer, or throw `ValueError` if the value cannot be converted. */
|
|
68
|
+
export function requireInteger(value, min, max, caller = requireInteger) {
|
|
69
|
+
const num = getNumber(value);
|
|
70
|
+
assertInteger(num, min, max, caller);
|
|
71
|
+
return num;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Is a number within a specified range?
|
|
75
|
+
*
|
|
76
|
+
* @param num The number to test, e.g. `17`
|
|
77
|
+
* @param min The start of the range, e.g. `10`
|
|
78
|
+
* @param max The end of the range, e.g. `20`
|
|
79
|
+
*/
|
|
80
|
+
export function isBetween(num, min, max) {
|
|
81
|
+
return num >= min && num <= max;
|
|
82
|
+
}
|
|
70
83
|
/**
|
|
71
84
|
* Round numbers to a given step.
|
|
72
85
|
*
|
|
@@ -127,29 +140,6 @@ export function wrapNumber(num, min, max) {
|
|
|
127
140
|
return ((num - min) % (min - max)) + max;
|
|
128
141
|
return num;
|
|
129
142
|
}
|
|
130
|
-
/** Format a number (based on the user's browser language settings). */
|
|
131
|
-
export function formatNumber(num, options) {
|
|
132
|
-
if (!Number.isFinite(num))
|
|
133
|
-
return Number.isNaN(num) ? "-" : "∞";
|
|
134
|
-
return new Intl.NumberFormat(undefined, options).format(num).replace(/ /, NNBSP);
|
|
135
|
-
}
|
|
136
|
-
/** Format a number range (based on the user's browser language settings). */
|
|
137
|
-
export function formatRange(min, max, options) {
|
|
138
|
-
return `${formatNumber(min, options)}–${formatNumber(max, options)}`;
|
|
139
|
-
}
|
|
140
|
-
/** Format a number with a short suffix, e.g. `1,000 kg` */
|
|
141
|
-
export function formatQuantity(num, abbr, options) {
|
|
142
|
-
const o = { unitDisplay: "short", ...options, style: "decimal" };
|
|
143
|
-
const str = formatNumber(num, o);
|
|
144
|
-
const sep = o.unitDisplay === "narrow" ? "" : NNBSP;
|
|
145
|
-
return `${str}${sep}${abbr}`;
|
|
146
|
-
}
|
|
147
|
-
/** Format a number with a longer full-word suffix. */
|
|
148
|
-
export function pluralizeQuantity(num, singular, plural, options) {
|
|
149
|
-
const o = { ...options, style: "decimal" };
|
|
150
|
-
const qty = formatNumber(num, o);
|
|
151
|
-
return `${qty}${NNBSP}${num === 1 ? singular : plural}`;
|
|
152
|
-
}
|
|
153
143
|
/**
|
|
154
144
|
* Get a number as a percentage of another number.
|
|
155
145
|
*
|
|
@@ -159,18 +149,6 @@ export function pluralizeQuantity(num, singular, plural, options) {
|
|
|
159
149
|
export function getPercent(numerator, denumerator) {
|
|
160
150
|
return Math.max(0, Math.min(100, (100 / denumerator) * numerator));
|
|
161
151
|
}
|
|
162
|
-
/**
|
|
163
|
-
* Format a percentage (combines `getPercent()` and `formatQuantity()` for convenience).
|
|
164
|
-
* - Defaults to showing no decimal places.
|
|
165
|
-
* - Defaults to rounding closer to zero (so that 99.99% is shown as 99%).
|
|
166
|
-
*
|
|
167
|
-
* @param numerator Number representing the amount of progress.
|
|
168
|
-
* @param denumerator The number representing the whole amount.
|
|
169
|
-
*/
|
|
170
|
-
export function formatPercent(numerator, denumerator, options) {
|
|
171
|
-
const fullOptions = { style: "percent", maximumFractionDigits: 0, roundingMode: "trunc", ...options };
|
|
172
|
-
return formatNumber(getPercent(numerator, denumerator), fullOptions);
|
|
173
|
-
}
|
|
174
152
|
/** Sum an iterable set of numbers and return the total. */
|
|
175
153
|
export function sumNumbers(nums) {
|
|
176
154
|
let sum = 0;
|
package/util/object.d.ts
CHANGED
|
@@ -98,13 +98,6 @@ export declare function setProp<T extends MutableObject, K extends Key<T>>(obj:
|
|
|
98
98
|
export declare function setProps<T extends MutableObject>(obj: T, entries: T | Partial<T> | Iterable<Prop<T>>): void;
|
|
99
99
|
/** Remove several key/value entries from an object (by reference). */
|
|
100
100
|
export declare function deleteProps<T extends MutableObject>(obj: T, ...keys: Key<T>[]): void;
|
|
101
|
-
/**
|
|
102
|
-
* Format an unknown object as a string.
|
|
103
|
-
* - Use the custom `.toString()` function if it exists (don't use built in `Object.prototype.toString` because it's useless.
|
|
104
|
-
* - Use `.title` or `.name` or `.id` if they exist and are strings.
|
|
105
|
-
* - Use `Object` otherwise.
|
|
106
|
-
*/
|
|
107
|
-
export declare function formatObject(obj: ImmutableObject): string;
|
|
108
101
|
/**
|
|
109
102
|
* Get the prototype of an object instance.
|
|
110
103
|
* - Recommend to use this because Typescript's default lib specifies `Object.getPrototypeOf()` returning `any`.
|
package/util/object.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RequiredError } from "../error/RequiredError.js";
|
|
2
2
|
import { isIterable } from "./iterate.js";
|
|
3
3
|
/** Is an unknown value an unknown object? */
|
|
4
4
|
export function isObject(value) {
|
|
@@ -7,7 +7,7 @@ export function isObject(value) {
|
|
|
7
7
|
/** Assert that a value is an object */
|
|
8
8
|
export function assertObject(value) {
|
|
9
9
|
if (!isObject(value))
|
|
10
|
-
throw new
|
|
10
|
+
throw new RequiredError("Must be object", { received: value, caller: assertObject });
|
|
11
11
|
}
|
|
12
12
|
/** Is an unknown value a plain object? */
|
|
13
13
|
export function isPlainObject(value) {
|
|
@@ -20,14 +20,14 @@ export function isPlainObject(value) {
|
|
|
20
20
|
/** Assert that an unknown value is a plain object */
|
|
21
21
|
export function assertPlainObject(value) {
|
|
22
22
|
if (!isPlainObject(value))
|
|
23
|
-
throw new
|
|
23
|
+
throw new RequiredError("Must be plain object", { received: value, caller: assertPlainObject });
|
|
24
24
|
}
|
|
25
25
|
/** Is an unknown value the key for an own prop of an object. */
|
|
26
26
|
export const isProp = (obj, key) => Object.hasOwn(obj, key);
|
|
27
27
|
/** Assert that an unknown value is the key for an own prop of an object. */
|
|
28
28
|
export function assertProp(obj, key) {
|
|
29
29
|
if (!isProp(obj, key))
|
|
30
|
-
throw new
|
|
30
|
+
throw new RequiredError("Key must exist in object", { key, obj, caller: assertProp });
|
|
31
31
|
}
|
|
32
32
|
/** Turn a possible object into an object. */
|
|
33
33
|
export function getObject(obj) {
|
|
@@ -87,26 +87,6 @@ export function deleteProps(obj, ...keys) {
|
|
|
87
87
|
for (const key of keys)
|
|
88
88
|
delete obj[key];
|
|
89
89
|
}
|
|
90
|
-
/**
|
|
91
|
-
* Format an unknown object as a string.
|
|
92
|
-
* - Use the custom `.toString()` function if it exists (don't use built in `Object.prototype.toString` because it's useless.
|
|
93
|
-
* - Use `.title` or `.name` or `.id` if they exist and are strings.
|
|
94
|
-
* - Use `Object` otherwise.
|
|
95
|
-
*/
|
|
96
|
-
export function formatObject(obj) {
|
|
97
|
-
if (typeof obj.toString === "function" && obj.toString !== Object.prototype.toString)
|
|
98
|
-
return obj.toString();
|
|
99
|
-
const name = obj.name;
|
|
100
|
-
if (typeof name === "string")
|
|
101
|
-
return name;
|
|
102
|
-
const title = obj.title;
|
|
103
|
-
if (typeof title === "string")
|
|
104
|
-
return title;
|
|
105
|
-
const id = obj.id;
|
|
106
|
-
if (typeof id === "string")
|
|
107
|
-
return id;
|
|
108
|
-
return "Object";
|
|
109
|
-
}
|
|
110
90
|
/**
|
|
111
91
|
* Get the prototype of an object instance.
|
|
112
92
|
* - Recommend to use this because Typescript's default lib specifies `Object.getPrototypeOf()` returning `any`.
|
package/util/optional.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import type { AnyCaller } from "../error/BaseError.js";
|
|
1
2
|
/** Optional is the value or `null` or `undefined` (synonym for `Nullish`). */
|
|
2
3
|
export type Optional<T> = T | null | undefined;
|
|
3
4
|
/** Get a required value. */
|
|
4
|
-
export declare function getRequired<T>(value: Optional<T
|
|
5
|
+
export declare function getRequired<T>(value: Optional<T>, caller?: AnyCaller): T;
|
|
5
6
|
/** Is a value not optional? */
|
|
6
7
|
export declare function notOptional<T>(value: Optional<T>): value is T;
|
package/util/optional.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { RequiredError } from "../error/RequiredError.js";
|
|
2
2
|
/** Get a required value. */
|
|
3
|
-
export function getRequired(value) {
|
|
3
|
+
export function getRequired(value, caller = getRequired) {
|
|
4
4
|
if (value === null || value === undefined)
|
|
5
|
-
throw new RequiredError("Value is required", { received: value, caller
|
|
5
|
+
throw new RequiredError("Value is required", { received: value, caller });
|
|
6
6
|
return value;
|
|
7
7
|
}
|
|
8
8
|
/** Is a value not optional? */
|
package/util/path.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AnyCaller } from "../error/BaseError.js";
|
|
1
2
|
import { type Optional } from "./optional.js";
|
|
2
3
|
/** Absolute path string starts with `/` slash. */
|
|
3
4
|
export type AbsolutePath = `/` | `/${string}`;
|
|
@@ -10,25 +11,25 @@ export declare function isAbsolutePath(path: string): path is AbsolutePath;
|
|
|
10
11
|
/** Is a string path an absolute path? */
|
|
11
12
|
export declare function isRelativePath(path: string): path is RelativePath;
|
|
12
13
|
/**
|
|
13
|
-
* Resolve a relative or absolute path and return the path, or `undefined` if not a valid path.
|
|
14
|
-
* - Uses `new URL` to do path processing, so URL strings
|
|
14
|
+
* Resolve a relative or absolute path and return the absolute path, or `undefined` if not a valid path.
|
|
15
|
+
* - Uses `new URL` to do path processing, so URL strings can also be resolved.
|
|
15
16
|
* - Returned paths are cleaned with `cleanPath()` so runs of slashes and trailing slashes are removed.
|
|
16
17
|
*
|
|
17
|
-
* @param
|
|
18
|
+
* @param value Absolute path e.g. `/a/b/c`, relative path e.g. `./a` or `b` or `../c`, URL string e.g. `http://shax.com/a/b/c`, or `URL` instance.
|
|
18
19
|
* @param base Absolute path used for resolving relative paths in `possible`
|
|
19
20
|
* @return Absolute path with a leading trailing slash, e.g. `/a/c/b`
|
|
20
21
|
*/
|
|
21
|
-
export declare function getPath(
|
|
22
|
+
export declare function getPath(value: Optional<string | URL>, base?: AbsolutePath | undefined): AbsolutePath | undefined;
|
|
22
23
|
/**
|
|
23
24
|
* Resolve a relative or absolute path and return the path, or throw `RequiredError` if not a valid path.
|
|
24
25
|
* - Internally uses `new URL` to do path processing but shouldn't ever reveal that fact.
|
|
25
26
|
* - Returned paths are cleaned with `cleanPath()` so runs of slashes and trailing slashes are removed.
|
|
26
27
|
*
|
|
27
|
-
* @param
|
|
28
|
+
* @param value Absolute path e.g. `/a/b/c`, relative path e.g. `./a` or `b` or `../c`, URL string e.g. `http://shax.com/a/b/c`, or `URL` instance.
|
|
28
29
|
* @param base Absolute path used for resolving relative paths in `possible`
|
|
29
30
|
* @return Absolute path with a leading trailing slash, e.g. `/a/c/b`
|
|
30
31
|
*/
|
|
31
|
-
export declare function requirePath(
|
|
32
|
+
export declare function requirePath(value: string, base?: AbsolutePath, caller?: AnyCaller): AbsolutePath;
|
|
32
33
|
/** Is a target path active? */
|
|
33
34
|
export declare function isPathActive(target: AbsolutePath, current: AbsolutePath): boolean;
|
|
34
35
|
/** Is a target path proud (i.e. is the current path, or is a child of the current path)? */
|
package/util/path.js
CHANGED
|
@@ -14,18 +14,18 @@ function _cleanPath(path) {
|
|
|
14
14
|
.replace(/(?!^)\/$/g, ""); // Trailing slashes.
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
|
-
* Resolve a relative or absolute path and return the path, or `undefined` if not a valid path.
|
|
18
|
-
* - Uses `new URL` to do path processing, so URL strings
|
|
17
|
+
* Resolve a relative or absolute path and return the absolute path, or `undefined` if not a valid path.
|
|
18
|
+
* - Uses `new URL` to do path processing, so URL strings can also be resolved.
|
|
19
19
|
* - Returned paths are cleaned with `cleanPath()` so runs of slashes and trailing slashes are removed.
|
|
20
20
|
*
|
|
21
|
-
* @param
|
|
21
|
+
* @param value Absolute path e.g. `/a/b/c`, relative path e.g. `./a` or `b` or `../c`, URL string e.g. `http://shax.com/a/b/c`, or `URL` instance.
|
|
22
22
|
* @param base Absolute path used for resolving relative paths in `possible`
|
|
23
23
|
* @return Absolute path with a leading trailing slash, e.g. `/a/c/b`
|
|
24
24
|
*/
|
|
25
|
-
export function getPath(
|
|
26
|
-
if (notOptional(
|
|
25
|
+
export function getPath(value, base = "/") {
|
|
26
|
+
if (notOptional(value)) {
|
|
27
27
|
try {
|
|
28
|
-
const { pathname, search, hash } = new URL(
|
|
28
|
+
const { pathname, search, hash } = new URL(value, `http://j.com${base}/`);
|
|
29
29
|
if (isAbsolutePath(pathname))
|
|
30
30
|
return `${_cleanPath(pathname)}${search}${hash}`;
|
|
31
31
|
}
|
|
@@ -39,14 +39,14 @@ export function getPath(possible, base = "/") {
|
|
|
39
39
|
* - Internally uses `new URL` to do path processing but shouldn't ever reveal that fact.
|
|
40
40
|
* - Returned paths are cleaned with `cleanPath()` so runs of slashes and trailing slashes are removed.
|
|
41
41
|
*
|
|
42
|
-
* @param
|
|
42
|
+
* @param value Absolute path e.g. `/a/b/c`, relative path e.g. `./a` or `b` or `../c`, URL string e.g. `http://shax.com/a/b/c`, or `URL` instance.
|
|
43
43
|
* @param base Absolute path used for resolving relative paths in `possible`
|
|
44
44
|
* @return Absolute path with a leading trailing slash, e.g. `/a/c/b`
|
|
45
45
|
*/
|
|
46
|
-
export function requirePath(
|
|
47
|
-
const path = getPath(
|
|
46
|
+
export function requirePath(value, base, caller = requirePath) {
|
|
47
|
+
const path = getPath(value, base);
|
|
48
48
|
if (!path)
|
|
49
|
-
throw new RequiredError("Invalid URL", { received:
|
|
49
|
+
throw new RequiredError("Invalid URL", { received: value, caller });
|
|
50
50
|
return path;
|
|
51
51
|
}
|
|
52
52
|
/** Is a target path active? */
|
package/util/query.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isArray, limitArray } from "./array.js";
|
|
2
|
+
import { requireLast } from "./array.js";
|
|
2
3
|
import { getDataProp } from "./data.js";
|
|
3
4
|
import { isArrayWith, isEqual, isEqualGreater, isEqualLess, isGreater, isInArray, isLess, notEqual, notInArray } from "./equal.js";
|
|
4
|
-
import { requireLastItem } from "./iterate.js";
|
|
5
5
|
import { limitItems } from "./iterate.js";
|
|
6
6
|
import { getProps } from "./object.js";
|
|
7
7
|
import { compareAscending, compareDescending, sortArray } from "./sort.js";
|
|
@@ -105,7 +105,7 @@ export function limitQueryItems(items, limit) {
|
|
|
105
105
|
/** Get a query for items that appear before a specified item. */
|
|
106
106
|
export function getBeforeQuery(query, item) {
|
|
107
107
|
const sorts = getOrders(query);
|
|
108
|
-
const lastSort =
|
|
108
|
+
const lastSort = requireLast(sorts);
|
|
109
109
|
const newQuery = { ...query };
|
|
110
110
|
for (const sort of sorts) {
|
|
111
111
|
const { key, direction } = sort;
|
|
@@ -117,7 +117,7 @@ export function getBeforeQuery(query, item) {
|
|
|
117
117
|
/** Get a query for items that appear after a specified item. */
|
|
118
118
|
export function getAfterQuery(query, item) {
|
|
119
119
|
const sorts = getOrders(query);
|
|
120
|
-
const lastSort =
|
|
120
|
+
const lastSort = requireLast(sorts);
|
|
121
121
|
const newQuery = { ...query };
|
|
122
122
|
for (const sort of sorts) {
|
|
123
123
|
const { key, direction } = sort;
|
package/util/random.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { requireDefined } from "./undefined.js";
|
|
2
2
|
/** Generate a random integer between two numbers. */
|
|
3
3
|
export function getRandom(min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER) {
|
|
4
4
|
return Math.round(Math.random() * (max - min) + min);
|
|
@@ -30,5 +30,5 @@ export function getRandomCharacter(str) {
|
|
|
30
30
|
}
|
|
31
31
|
/** Get a random item from an array or random character from a string string. */
|
|
32
32
|
export function getRandomItem(arr) {
|
|
33
|
-
return
|
|
33
|
+
return requireDefined(arr[getRandom(0, arr.length - 1)]);
|
|
34
34
|
}
|
package/util/regexp.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RequiredError } from "../error/RequiredError.js";
|
|
2
2
|
import { ValueError } from "../error/ValueError.js";
|
|
3
3
|
import { getArray } from "./array.js";
|
|
4
4
|
/** Regular expression that always matches everything. */
|
|
@@ -12,7 +12,7 @@ export function isRegExp(value) {
|
|
|
12
12
|
/** Assert that an unknown value is a `RegExp` instance. */
|
|
13
13
|
export function assertRegExp(value) {
|
|
14
14
|
if (!(value instanceof RegExp))
|
|
15
|
-
throw new
|
|
15
|
+
throw new RequiredError("Must be regular expression", { received: value, caller: assertRegExp });
|
|
16
16
|
}
|
|
17
17
|
export function getRegExp(pattern, flags) {
|
|
18
18
|
return typeof pattern === "string" ? new RegExp(pattern, flags) : pattern;
|