shelving 1.135.0 → 1.137.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/api/Resource.d.ts +2 -2
- package/api/Resource.js +4 -4
- package/db/ItemStore.js +9 -2
- package/db/Provider.js +29 -8
- package/db/QueryStore.js +16 -4
- package/db/ValidationProvider.js +26 -26
- package/error/AssertionError.d.ts +8 -0
- package/error/AssertionError.js +12 -0
- package/error/BaseError.d.ts +19 -0
- package/error/BaseError.js +18 -0
- package/error/NetworkError.d.ts +5 -0
- package/error/NetworkError.js +9 -0
- package/error/RequestError.d.ts +32 -0
- package/error/RequestError.js +50 -0
- package/error/RequiredError.d.ts +8 -0
- package/error/RequiredError.js +12 -0
- package/error/UnexpectedError.d.ts +5 -0
- package/error/UnexpectedError.js +9 -0
- package/error/UnimplementedError.d.ts +5 -0
- package/error/UnimplementedError.js +9 -0
- package/error/ValueError.d.ts +5 -0
- package/error/ValueError.js +9 -0
- package/error/index.d.ts +8 -8
- package/error/index.js +8 -8
- package/firestore/lite/FirestoreLiteProvider.js +3 -3
- package/iterate/InspectIterator.js +14 -4
- package/markup/rule/link.js +2 -2
- package/package.json +1 -1
- package/react/createCacheContext.js +12 -13
- package/react/createDataContext.js +2 -2
- package/schema/AllowSchema.js +2 -2
- package/schema/DateSchema.d.ts +1 -1
- package/schema/DateSchema.js +12 -12
- package/schema/FileSchema.js +2 -2
- package/schema/LinkSchema.js +2 -2
- package/schema/SlugSchema.js +2 -2
- package/schema/TimeSchema.js +4 -4
- package/sequence/InspectSequence.js +14 -4
- package/store/ArrayStore.js +6 -5
- package/store/PathStore.js +4 -4
- package/test/util.js +6 -3
- package/util/array.d.ts +39 -42
- package/util/array.js +48 -82
- package/util/async.d.ts +3 -3
- package/util/async.js +7 -7
- package/util/base64.d.ts +4 -4
- package/util/base64.js +6 -6
- package/util/boolean.js +6 -6
- package/util/buffer.d.ts +8 -0
- package/util/buffer.js +24 -0
- package/util/class.d.ts +4 -0
- package/util/class.js +14 -3
- package/util/color.d.ts +3 -3
- package/util/color.js +8 -8
- package/util/data.d.ts +3 -3
- package/util/data.js +3 -3
- package/util/date.d.ts +20 -15
- package/util/date.js +87 -37
- package/util/dictionary.d.ts +12 -12
- package/util/dictionary.js +20 -19
- package/util/entity.js +2 -2
- package/util/equal.d.ts +4 -0
- package/util/equal.js +12 -1
- package/util/error.d.ts +0 -2
- package/util/error.js +0 -20
- package/util/file.d.ts +3 -3
- package/util/file.js +6 -6
- package/util/function.js +2 -2
- package/util/hydrate.js +5 -3
- package/util/index.d.ts +1 -2
- package/util/index.js +1 -2
- package/util/iterate.d.ts +13 -0
- package/util/iterate.js +48 -0
- package/util/link.d.ts +4 -4
- package/util/link.js +8 -8
- package/util/map.d.ts +4 -4
- package/util/map.js +9 -9
- package/util/null.js +5 -5
- package/util/number.d.ts +6 -11
- package/util/number.js +23 -18
- package/util/object.js +4 -4
- package/util/optional.js +2 -2
- package/util/path.d.ts +3 -3
- package/util/path.js +6 -6
- package/util/query.d.ts +4 -4
- package/util/query.js +10 -9
- package/util/regexp.d.ts +12 -12
- package/util/regexp.js +13 -12
- package/util/sequence.d.ts +0 -2
- package/util/sequence.js +0 -7
- package/util/serialise.js +2 -2
- package/util/set.js +3 -3
- package/util/source.d.ts +4 -8
- package/util/source.js +8 -12
- package/util/string.d.ts +14 -22
- package/util/string.js +27 -29
- package/util/template.js +10 -11
- package/util/time.d.ts +2 -5
- package/util/time.js +12 -13
- package/util/undefined.js +2 -2
- package/util/units.d.ts +17 -12
- package/util/units.js +61 -40
- package/util/url.d.ts +3 -3
- package/util/url.js +11 -7
- package/util/validate.d.ts +4 -4
- package/util/validate.js +5 -9
- package/error/CodedError.d.ts +0 -13
- package/error/CodedError.js +0 -21
- package/error/ConflictError.d.ts +0 -6
- package/error/ConflictError.js +0 -11
- package/error/ConnectionError.d.ts +0 -5
- package/error/ConnectionError.js +0 -10
- package/error/ForbiddenError.d.ts +0 -6
- package/error/ForbiddenError.js +0 -11
- package/error/NotFoundError.d.ts +0 -6
- package/error/NotFoundError.js +0 -11
- package/error/NotImplementedError.d.ts +0 -6
- package/error/NotImplementedError.js +0 -11
- package/error/UnauthorizedError.d.ts +0 -6
- package/error/UnauthorizedError.js +0 -11
- package/error/ValidationError.d.ts +0 -6
- package/error/ValidationError.js +0 -11
- package/util/assert.d.ts +0 -4
- package/util/assert.js +0 -11
- package/util/duration.d.ts +0 -10
- package/util/duration.js +0 -50
package/util/link.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ValueError } from "../error/ValueError.js";
|
|
2
2
|
import { getOptionalURL, isURL } from "./url.js";
|
|
3
3
|
/** Default whitelist for URL schemes. */
|
|
4
4
|
const SCHEMES = ["http:", "https:"];
|
|
@@ -7,25 +7,25 @@ export function isLinkURL(value) {
|
|
|
7
7
|
return isURL(value) && !!value.protocol;
|
|
8
8
|
}
|
|
9
9
|
/** Convert a possible URL to a URL or return `undefined` if conversion fails. */
|
|
10
|
-
export function
|
|
10
|
+
export function getLinkURL(possible, base, schemes = SCHEMES, hosts) {
|
|
11
11
|
const url = getOptionalURL(possible, base);
|
|
12
12
|
if (url && schemes.includes(url.protocol) && (!hosts || hosts.includes(url.host)))
|
|
13
13
|
return url;
|
|
14
14
|
}
|
|
15
15
|
/** Convert a possible URL to a URL or return `undefined` if conversion fails. */
|
|
16
|
-
export function
|
|
17
|
-
const url =
|
|
16
|
+
export function requireLinkURL(possible, base, schemes, hosts) {
|
|
17
|
+
const url = getLinkURL(possible, base, schemes, hosts);
|
|
18
18
|
if (!url)
|
|
19
|
-
throw new
|
|
19
|
+
throw new ValueError("Invalid link", { received: possible, caller: requireLinkURL });
|
|
20
20
|
return url;
|
|
21
21
|
}
|
|
22
22
|
/** Convert a possible URL to a absolute URL string or return `undefined` if conversion fails. */
|
|
23
|
-
export function
|
|
23
|
+
export function getLink(possible, base, schemes = SCHEMES, hosts) {
|
|
24
24
|
const url = getOptionalURL(possible, base);
|
|
25
25
|
if (url && schemes.includes(url.protocol) && (!hosts || hosts.includes(url.host)))
|
|
26
26
|
return url.href;
|
|
27
27
|
}
|
|
28
28
|
/** Convert a possible URL to an absolute URL string. */
|
|
29
|
-
export function
|
|
30
|
-
return
|
|
29
|
+
export function requireLink(possible, base, schemes, hosts) {
|
|
30
|
+
return requireLinkURL(possible, base, schemes, hosts).href;
|
|
31
31
|
}
|
package/util/map.d.ts
CHANGED
|
@@ -38,7 +38,7 @@ export declare function setMapItem<K, T>(map: MutableMap<K, T>, key: K, value: T
|
|
|
38
38
|
export declare function setMapItems<K, T>(map: MutableMap<K, T>, items: Iterable<MapItem<ImmutableMap<K, T>>>): void;
|
|
39
39
|
/** Remove multiple items from a set (by reference). */
|
|
40
40
|
export declare function removeMapItems<K, T>(map: MutableMap<K, T>, ...keys: K[]): void;
|
|
41
|
-
/** Get an item in a map or throw
|
|
42
|
-
export declare function
|
|
43
|
-
/** Get an item in a map or `undefined` if it doesn't exist. */
|
|
44
|
-
export declare function
|
|
41
|
+
/** Get an item in a map, or throw `RequiredError` if it doesn't exist. */
|
|
42
|
+
export declare function requireMapItem<K, T>(map: ImmutableMap<K, T>, key: K): T;
|
|
43
|
+
/** Get an item in a map, or `undefined` if it doesn't exist. */
|
|
44
|
+
export declare function getMapItem<K, T>(map: ImmutableMap<K, T>, key: K): T | undefined;
|
package/util/map.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { AssertionError } from "../error/AssertionError.js";
|
|
2
|
+
import { RequiredError } from "../error/RequiredError.js";
|
|
3
3
|
import { isIterable, limitItems } from "./iterate.js";
|
|
4
4
|
/** Class for a `Map` that cannot be changed (so you can extend `Map` while implementing `ImmutableMap`). */
|
|
5
5
|
export const ImmutableMap = Map;
|
|
@@ -10,7 +10,7 @@ export function isMap(value) {
|
|
|
10
10
|
/** Assert that a value is a `Map` instance. */
|
|
11
11
|
export function assertMap(value) {
|
|
12
12
|
if (!isMap(value))
|
|
13
|
-
throw new
|
|
13
|
+
throw new AssertionError("Must be map", { received: value, caller: assertMap });
|
|
14
14
|
}
|
|
15
15
|
/** Is an unknown value a key for an item in a map? */
|
|
16
16
|
export function isMapItem(map, key) {
|
|
@@ -19,7 +19,7 @@ export function isMapItem(map, key) {
|
|
|
19
19
|
/** Assert that an unknown value is a key for an item in a map. */
|
|
20
20
|
export function assertMapItem(map, key) {
|
|
21
21
|
if (!isMapItem(map, key))
|
|
22
|
-
throw new
|
|
22
|
+
throw new AssertionError("Key must exist in map", { key, map, caller: assertMapItem });
|
|
23
23
|
}
|
|
24
24
|
export function getMap(input) {
|
|
25
25
|
return isMap(input) ? input : new Map(isIterable(input) ? input : Object.entries(input));
|
|
@@ -43,13 +43,13 @@ export function removeMapItems(map, ...keys) {
|
|
|
43
43
|
for (const key of keys)
|
|
44
44
|
map.delete(key);
|
|
45
45
|
}
|
|
46
|
-
/** Get an item in a map or throw
|
|
47
|
-
export function
|
|
46
|
+
/** Get an item in a map, or throw `RequiredError` if it doesn't exist. */
|
|
47
|
+
export function requireMapItem(map, key) {
|
|
48
48
|
if (!map.has(key))
|
|
49
|
-
throw new
|
|
49
|
+
throw new RequiredError("Key must exist in map", { key, map, caller: requireMapItem });
|
|
50
50
|
return map.get(key);
|
|
51
51
|
}
|
|
52
|
-
/** Get an item in a map or `undefined` if it doesn't exist. */
|
|
53
|
-
export function
|
|
52
|
+
/** Get an item in a map, or `undefined` if it doesn't exist. */
|
|
53
|
+
export function getMapItem(map, key) {
|
|
54
54
|
return map.get(key);
|
|
55
55
|
}
|
package/util/null.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AssertionError } from "../error/AssertionError.js";
|
|
2
2
|
/** Function that always returns null. */
|
|
3
3
|
export function getNull() {
|
|
4
4
|
return null;
|
|
@@ -10,7 +10,7 @@ export function isNull(value) {
|
|
|
10
10
|
/** Assert that a value is not null. */
|
|
11
11
|
export function assertNull(value) {
|
|
12
12
|
if (value !== null)
|
|
13
|
-
throw new
|
|
13
|
+
throw new AssertionError("Must be null", { received: value, caller: assertNull });
|
|
14
14
|
}
|
|
15
15
|
/** Is a value not null? */
|
|
16
16
|
export function notNull(value) {
|
|
@@ -19,7 +19,7 @@ export function notNull(value) {
|
|
|
19
19
|
/** Assert that a value is not null. */
|
|
20
20
|
export function assertNotNull(value) {
|
|
21
21
|
if (value === null)
|
|
22
|
-
throw new
|
|
22
|
+
throw new AssertionError("Must not be null", { received: value, caller: assertNotNull });
|
|
23
23
|
}
|
|
24
24
|
/** Get the not-nullish version of value. */
|
|
25
25
|
export function getNotNull(value) {
|
|
@@ -33,7 +33,7 @@ export function isNullish(value) {
|
|
|
33
33
|
/** Assert that a value is not nullish. */
|
|
34
34
|
export function assertNullish(value) {
|
|
35
35
|
if (value !== null && value !== undefined)
|
|
36
|
-
throw new
|
|
36
|
+
throw new AssertionError("Must be null or undefined", { received: value, caller: assertNullish });
|
|
37
37
|
}
|
|
38
38
|
/** Is a value not nullish? */
|
|
39
39
|
export function notNullish(value) {
|
|
@@ -42,7 +42,7 @@ export function notNullish(value) {
|
|
|
42
42
|
/** Assert that a value is not nullish. */
|
|
43
43
|
export function assertNotNullish(value) {
|
|
44
44
|
if (value === null || value === undefined)
|
|
45
|
-
throw new
|
|
45
|
+
throw new AssertionError("Must not be null or undefined", { received: value, caller: assertNotNullish });
|
|
46
46
|
}
|
|
47
47
|
/** Get the not-nullish version of value. */
|
|
48
48
|
export function getNotNullish(value) {
|
package/util/number.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export declare function isNumber(value: unknown): value is number;
|
|
3
3
|
/** Assert that a value is a number. */
|
|
4
4
|
export declare function assertNumber(value: unknown): asserts value is number;
|
|
5
|
-
/** Assert that a value is a number
|
|
5
|
+
/** Assert that a value is a finite number (i.e. not `NaN` or positive/negative `Infinity`). */
|
|
6
6
|
export declare function assertFinite(value: unknown): asserts value is number;
|
|
7
7
|
/**
|
|
8
8
|
* Is a finite number within a specified range?
|
|
@@ -77,19 +77,14 @@ export declare function boundNumber(num: number, min: number, max: number): numb
|
|
|
77
77
|
* - e.g. `-2` bounded by `2` and `8` is `4`
|
|
78
78
|
*/
|
|
79
79
|
export declare function wrapNumber(num: number, min: number, max: number): number;
|
|
80
|
-
/** Options for `formatNumber()` and `formatRange()`. */
|
|
81
|
-
export interface NumberOptions extends Intl.NumberFormatOptions {
|
|
82
|
-
roundingMode?: "ceil" | "floor" | "expand" | "trunc" | "halfCeil" | "halfFloor" | "halfExpand" | "halfTrunc" | "halfEven" | undefined;
|
|
83
|
-
roundingPriority?: "morePrecision" | "lessPrecision" | undefined;
|
|
84
|
-
}
|
|
85
80
|
/** Format a number (based on the user's browser language settings). */
|
|
86
|
-
export declare function formatNumber(num: number, options?:
|
|
81
|
+
export declare function formatNumber(num: number, options?: Intl.NumberFormatOptions): string;
|
|
87
82
|
/** Format a number range (based on the user's browser language settings). */
|
|
88
|
-
export declare function formatRange(min: number, max: number, options?:
|
|
83
|
+
export declare function formatRange(min: number, max: number, options?: Intl.NumberFormatOptions): string;
|
|
89
84
|
/** Format a number with a short suffix, e.g. `1,000 kg` */
|
|
90
|
-
export declare function formatQuantity(num: number, abbr: string, options?:
|
|
85
|
+
export declare function formatQuantity(num: number, abbr: string, options?: Intl.NumberFormatOptions): string;
|
|
91
86
|
/** Format a number with a longer full-word suffix. */
|
|
92
|
-
export declare function pluralizeQuantity(num: number, singular: string, plural: string, options?:
|
|
87
|
+
export declare function pluralizeQuantity(num: number, singular: string, plural: string, options?: Intl.NumberFormatOptions): string;
|
|
93
88
|
/**
|
|
94
89
|
* Get a number as a percentage of another number.
|
|
95
90
|
*
|
|
@@ -105,7 +100,7 @@ export declare function getPercent(numerator: number, denumerator: number): numb
|
|
|
105
100
|
* @param numerator Number representing the amount of progress.
|
|
106
101
|
* @param denumerator The number representing the whole amount.
|
|
107
102
|
*/
|
|
108
|
-
export declare function formatPercent(numerator: number, denumerator: number, options?:
|
|
103
|
+
export declare function formatPercent(numerator: number, denumerator: number, options?: Intl.NumberFormatOptions): string;
|
|
109
104
|
/** Sum an iterable set of numbers and return the total. */
|
|
110
105
|
export declare function sumNumbers(nums: Iterable<number>): number;
|
|
111
106
|
/** Find the number that's closest to a target in an iterable set of numbers. */
|
package/util/number.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AssertionError } from "../error/AssertionError.js";
|
|
2
|
+
import { ValueError } from "../error/ValueError.js";
|
|
2
3
|
import { NNBSP } from "./constants.js";
|
|
3
4
|
/** Is a value a number? */
|
|
4
5
|
export function isNumber(value) {
|
|
@@ -7,12 +8,12 @@ export function isNumber(value) {
|
|
|
7
8
|
/** Assert that a value is a number. */
|
|
8
9
|
export function assertNumber(value) {
|
|
9
10
|
if (typeof value !== "number")
|
|
10
|
-
throw new
|
|
11
|
+
throw new AssertionError("Must be number", { received: value, caller: assertNumber });
|
|
11
12
|
}
|
|
12
|
-
/** Assert that a value is a number
|
|
13
|
+
/** Assert that a value is a finite number (i.e. not `NaN` or positive/negative `Infinity`). */
|
|
13
14
|
export function assertFinite(value) {
|
|
14
15
|
if (typeof value !== "number" || !Number.isFinite(value))
|
|
15
|
-
throw new
|
|
16
|
+
throw new AssertionError("Must be finite number", { received: value, caller: assertFinite });
|
|
16
17
|
}
|
|
17
18
|
/**
|
|
18
19
|
* Is a finite number within a specified range?
|
|
@@ -25,17 +26,17 @@ export const isBetween = (num, min, max) => num >= min && num <= max;
|
|
|
25
26
|
/** Assert that a value is a number greater than. */
|
|
26
27
|
export function assertBetween(value, min, max) {
|
|
27
28
|
if (typeof value !== "number" || isBetween(value, min, max))
|
|
28
|
-
throw new
|
|
29
|
+
throw new AssertionError(`Must be number between ${min} and ${max}`, { received: value, caller: assertBetween });
|
|
29
30
|
}
|
|
30
31
|
/** Assert that a value is a number greater than. */
|
|
31
32
|
export function assertMax(value, max) {
|
|
32
33
|
if (typeof value !== "number" || value > max)
|
|
33
|
-
throw new
|
|
34
|
+
throw new AssertionError(`Must be number with maximum ${max}`, { received: value, caller: assertMax });
|
|
34
35
|
}
|
|
35
36
|
/** Assert that a value is a number less than. */
|
|
36
37
|
export function assertMin(value, min) {
|
|
37
38
|
if (typeof value !== "number" || value < min)
|
|
38
|
-
throw new
|
|
39
|
+
throw new AssertionError(`Must be number with minimum ${min}`, { received: value, caller: assertMin });
|
|
39
40
|
}
|
|
40
41
|
/**
|
|
41
42
|
* Convert an unknown value to a finite number or `undefined`
|
|
@@ -106,7 +107,8 @@ export function truncateNumber(num, precision = 0) {
|
|
|
106
107
|
* - e.g. `12` bounded by `2` and `8` is `8`
|
|
107
108
|
*/
|
|
108
109
|
export function boundNumber(num, min, max) {
|
|
109
|
-
|
|
110
|
+
if (max < min)
|
|
111
|
+
throw new ValueError("Max must be more than min", { min, max, caller: wrapNumber });
|
|
110
112
|
return Math.max(min, Math.min(max, num));
|
|
111
113
|
}
|
|
112
114
|
/**
|
|
@@ -117,7 +119,8 @@ export function boundNumber(num, min, max) {
|
|
|
117
119
|
* - e.g. `-2` bounded by `2` and `8` is `4`
|
|
118
120
|
*/
|
|
119
121
|
export function wrapNumber(num, min, max) {
|
|
120
|
-
|
|
122
|
+
if (max < min)
|
|
123
|
+
throw new ValueError("Max must be more than min", { min, max, caller: wrapNumber });
|
|
121
124
|
if (num >= max)
|
|
122
125
|
return ((num - max) % (max - min)) + min;
|
|
123
126
|
if (num < min)
|
|
@@ -126,11 +129,9 @@ export function wrapNumber(num, min, max) {
|
|
|
126
129
|
}
|
|
127
130
|
/** Format a number (based on the user's browser language settings). */
|
|
128
131
|
export function formatNumber(num, options) {
|
|
129
|
-
if (Number.isNaN(num))
|
|
130
|
-
return "None";
|
|
131
132
|
if (!Number.isFinite(num))
|
|
132
|
-
return "∞";
|
|
133
|
-
return new Intl.NumberFormat(undefined, options).format(num);
|
|
133
|
+
return Number.isNaN(num) ? "-" : "∞";
|
|
134
|
+
return new Intl.NumberFormat(undefined, options).format(num).replace(/ /, NNBSP);
|
|
134
135
|
}
|
|
135
136
|
/** Format a number range (based on the user's browser language settings). */
|
|
136
137
|
export function formatRange(min, max, options) {
|
|
@@ -138,13 +139,16 @@ export function formatRange(min, max, options) {
|
|
|
138
139
|
}
|
|
139
140
|
/** Format a number with a short suffix, e.g. `1,000 kg` */
|
|
140
141
|
export function formatQuantity(num, abbr, options) {
|
|
141
|
-
const
|
|
142
|
-
|
|
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}`;
|
|
143
146
|
}
|
|
144
147
|
/** Format a number with a longer full-word suffix. */
|
|
145
148
|
export function pluralizeQuantity(num, singular, plural, options) {
|
|
146
|
-
const
|
|
147
|
-
|
|
149
|
+
const o = { ...options, style: "decimal" };
|
|
150
|
+
const qty = formatNumber(num, o);
|
|
151
|
+
return `${qty}${NNBSP}${num === 1 ? singular : plural}`;
|
|
148
152
|
}
|
|
149
153
|
/**
|
|
150
154
|
* Get a number as a percentage of another number.
|
|
@@ -164,7 +168,8 @@ export function getPercent(numerator, denumerator) {
|
|
|
164
168
|
* @param denumerator The number representing the whole amount.
|
|
165
169
|
*/
|
|
166
170
|
export function formatPercent(numerator, denumerator, options) {
|
|
167
|
-
|
|
171
|
+
const fullOptions = { style: "percent", maximumFractionDigits: 0, roundingMode: "trunc", ...options };
|
|
172
|
+
return formatNumber(getPercent(numerator, denumerator), fullOptions);
|
|
168
173
|
}
|
|
169
174
|
/** Sum an iterable set of numbers and return the total. */
|
|
170
175
|
export function sumNumbers(nums) {
|
package/util/object.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AssertionError } from "../error/AssertionError.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 AssertionError("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 AssertionError("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 AssertionError("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) {
|
package/util/optional.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RequiredError } from "../error/RequiredError.js";
|
|
2
2
|
/** Get a required value. */
|
|
3
3
|
export function getRequired(value) {
|
|
4
4
|
if (value === null || value === undefined)
|
|
5
|
-
throw new
|
|
5
|
+
throw new RequiredError("Value is required", { received: value, caller: getRequired });
|
|
6
6
|
return value;
|
|
7
7
|
}
|
|
8
8
|
/** Is a value not optional? */
|
package/util/path.d.ts
CHANGED
|
@@ -18,9 +18,9 @@ export declare function isRelativePath(path: string): path is RelativePath;
|
|
|
18
18
|
* @param base Absolute path used for resolving relative paths in `possible`
|
|
19
19
|
* @return Absolute path with a leading trailing slash, e.g. `/a/c/b`
|
|
20
20
|
*/
|
|
21
|
-
export declare function
|
|
21
|
+
export declare function getPath(possible: Optional<string | URL>, base?: AbsolutePath | undefined): AbsolutePath | undefined;
|
|
22
22
|
/**
|
|
23
|
-
* Resolve a relative or absolute path and return the path, or throw `
|
|
23
|
+
* Resolve a relative or absolute path and return the path, or throw `RequiredError` if not a valid path.
|
|
24
24
|
* - Internally uses `new URL` to do path processing but shouldn't ever reveal that fact.
|
|
25
25
|
* - Returned paths are cleaned with `cleanPath()` so runs of slashes and trailing slashes are removed.
|
|
26
26
|
*
|
|
@@ -28,7 +28,7 @@ export declare function getOptionalPath(possible: Optional<string | URL>, base?:
|
|
|
28
28
|
* @param base Absolute path used for resolving relative paths in `possible`
|
|
29
29
|
* @return Absolute path with a leading trailing slash, e.g. `/a/c/b`
|
|
30
30
|
*/
|
|
31
|
-
export declare function
|
|
31
|
+
export declare function requirePath(possible: string, base?: AbsolutePath): AbsolutePath;
|
|
32
32
|
/** Is a target path active? */
|
|
33
33
|
export declare function isPathActive(target: AbsolutePath, current: AbsolutePath): boolean;
|
|
34
34
|
/** Is a target path proud (i.e. is the current path, or is a child of the current path)? */
|
package/util/path.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RequiredError } from "../error/RequiredError.js";
|
|
2
2
|
import { notOptional } from "./optional.js";
|
|
3
3
|
/** Is a string path an absolute path? */
|
|
4
4
|
export function isAbsolutePath(path) {
|
|
@@ -22,7 +22,7 @@ function _cleanPath(path) {
|
|
|
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
|
|
25
|
+
export function getPath(possible, base = "/") {
|
|
26
26
|
if (notOptional(possible)) {
|
|
27
27
|
try {
|
|
28
28
|
const { pathname, search, hash } = new URL(possible, `http://j.com${base}/`);
|
|
@@ -35,7 +35,7 @@ export function getOptionalPath(possible, base = "/") {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
|
-
* Resolve a relative or absolute path and return the path, or throw `
|
|
38
|
+
* Resolve a relative or absolute path and return the path, or throw `RequiredError` if not a valid path.
|
|
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
|
*
|
|
@@ -43,10 +43,10 @@ export function getOptionalPath(possible, base = "/") {
|
|
|
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
|
|
47
|
-
const path =
|
|
46
|
+
export function requirePath(possible, base) {
|
|
47
|
+
const path = getPath(possible, base);
|
|
48
48
|
if (!path)
|
|
49
|
-
throw new
|
|
49
|
+
throw new RequiredError("Invalid URL", { received: possible, caller: requirePath });
|
|
50
50
|
return path;
|
|
51
51
|
}
|
|
52
52
|
/** Is a target path active? */
|
package/util/query.d.ts
CHANGED
|
@@ -71,10 +71,10 @@ export declare function queryWritableItems<T extends Data>(items: Iterable<T>, q
|
|
|
71
71
|
export declare function matchQueryItem<T extends Data>(item: T, filters: ImmutableArray<Filter>): boolean;
|
|
72
72
|
/** Filter a set of data items using a set of filters. */
|
|
73
73
|
export declare function filterQueryItems<T extends Data>(items: Iterable<T>, filters: ImmutableArray<Filter>): Iterable<T>;
|
|
74
|
-
/** Compare two data items using a set of
|
|
75
|
-
export declare function compareQueryItems<T extends Data>(left: T, right: T,
|
|
76
|
-
/** Sort a set of data items using a set of
|
|
77
|
-
export declare function sortQueryItems<T extends Data>(items: Iterable<T>,
|
|
74
|
+
/** Compare two data items using a set of orders. */
|
|
75
|
+
export declare function compareQueryItems<T extends Data>(left: T, right: T, orders: ImmutableArray<Order>): number;
|
|
76
|
+
/** Sort a set of data items using a set of orders. */
|
|
77
|
+
export declare function sortQueryItems<T extends Data>(items: Iterable<T>, orders: ImmutableArray<Order>): Iterable<T>;
|
|
78
78
|
/** LImit a set of data items using a set of limit. */
|
|
79
79
|
export declare function limitQueryItems<T extends Data>(items: ImmutableArray<T> | Iterable<T>, limit: number | undefined): Iterable<T>;
|
|
80
80
|
/** Get a query for items that appear before a specified item. */
|
package/util/query.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isArray, limitArray } from "./array.js";
|
|
2
2
|
import { getDataProp } from "./data.js";
|
|
3
3
|
import { isArrayWith, isEqual, isEqualGreater, isEqualLess, isGreater, isInArray, isLess, notEqual, notInArray } from "./equal.js";
|
|
4
|
+
import { requireLastItem } from "./iterate.js";
|
|
4
5
|
import { limitItems } from "./iterate.js";
|
|
5
6
|
import { getProps } from "./object.js";
|
|
6
7
|
import { compareAscending, compareDescending, sortArray } from "./sort.js";
|
|
@@ -82,9 +83,9 @@ export function* filterQueryItems(items, filters) {
|
|
|
82
83
|
yield* items;
|
|
83
84
|
}
|
|
84
85
|
}
|
|
85
|
-
/** Compare two data items using a set of
|
|
86
|
-
export function compareQueryItems(left, right,
|
|
87
|
-
for (const { key, direction } of
|
|
86
|
+
/** Compare two data items using a set of orders. */
|
|
87
|
+
export function compareQueryItems(left, right, orders) {
|
|
88
|
+
for (const { key, direction } of orders) {
|
|
88
89
|
const l = getDataProp(left, key);
|
|
89
90
|
const r = getDataProp(right, key);
|
|
90
91
|
const c = direction === "asc" ? compareAscending(l, r) : compareDescending(l, r);
|
|
@@ -93,9 +94,9 @@ export function compareQueryItems(left, right, sorts) {
|
|
|
93
94
|
}
|
|
94
95
|
return 0;
|
|
95
96
|
}
|
|
96
|
-
/** Sort a set of data items using a set of
|
|
97
|
-
export function sortQueryItems(items,
|
|
98
|
-
return
|
|
97
|
+
/** Sort a set of data items using a set of orders. */
|
|
98
|
+
export function sortQueryItems(items, orders) {
|
|
99
|
+
return orders.length ? sortArray(items, compareQueryItems, orders) : items;
|
|
99
100
|
}
|
|
100
101
|
/** LImit a set of data items using a set of limit. */
|
|
101
102
|
export function limitQueryItems(items, limit) {
|
|
@@ -104,7 +105,7 @@ export function limitQueryItems(items, limit) {
|
|
|
104
105
|
/** Get a query for items that appear before a specified item. */
|
|
105
106
|
export function getBeforeQuery(query, item) {
|
|
106
107
|
const sorts = getOrders(query);
|
|
107
|
-
const lastSort =
|
|
108
|
+
const lastSort = requireLastItem(sorts);
|
|
108
109
|
const newQuery = { ...query };
|
|
109
110
|
for (const sort of sorts) {
|
|
110
111
|
const { key, direction } = sort;
|
|
@@ -116,7 +117,7 @@ export function getBeforeQuery(query, item) {
|
|
|
116
117
|
/** Get a query for items that appear after a specified item. */
|
|
117
118
|
export function getAfterQuery(query, item) {
|
|
118
119
|
const sorts = getOrders(query);
|
|
119
|
-
const lastSort =
|
|
120
|
+
const lastSort = requireLastItem(sorts);
|
|
120
121
|
const newQuery = { ...query };
|
|
121
122
|
for (const sort of sorts) {
|
|
122
123
|
const { key, direction } = sort;
|
package/util/regexp.d.ts
CHANGED
|
@@ -17,9 +17,9 @@ export declare function getRegExpSource(regexp: PossibleRegExp): string;
|
|
|
17
17
|
/** Escape special characters in a string regular expression. */
|
|
18
18
|
export declare function escapeRegExp(pattern: string): string;
|
|
19
19
|
/** Create regular expression that matches any of a list of other expressions. */
|
|
20
|
-
export declare function
|
|
20
|
+
export declare function createRegExpAny(patterns: Iterable<PossibleRegExp> & NotString, flags?: string): RegExp;
|
|
21
21
|
/** Create regular expression that matches all of a list of other expressions. */
|
|
22
|
-
export declare function
|
|
22
|
+
export declare function createRegExpAll(patterns: Iterable<PossibleRegExp> & NotString, flags?: string): RegExp;
|
|
23
23
|
/** Regular expression match array that matches a specific string format. */
|
|
24
24
|
export interface TypedRegExpExecArray<T extends string = string> extends RegExpExecArray {
|
|
25
25
|
0: T;
|
|
@@ -45,16 +45,16 @@ export declare function isMatch(str: string, regexp: RegExp): boolean;
|
|
|
45
45
|
/** Match function for finding strings that match against regular expressions (use with `filter()` to negatively filter iterable sets of items). */
|
|
46
46
|
export declare function notMatch(str: string, regexp: RegExp): boolean;
|
|
47
47
|
/** Get an optional regular expression match, or `undefined` if no match could be made. */
|
|
48
|
-
export declare function
|
|
49
|
-
export declare function
|
|
50
|
-
export declare function
|
|
48
|
+
export declare function getMatch<T extends NamedRegExpData>(str: string, regexp: NamedRegExp<T>): NamedRegExpExecArray<T> | undefined;
|
|
49
|
+
export declare function getMatch<T extends string>(str: string, regexp: TypedRegExp<T>): TypedRegExpExecArray<T> | undefined;
|
|
50
|
+
export declare function getMatch(str: string, regexp: RegExp): RegExpExecArray | undefined;
|
|
51
51
|
/** Get a required regular expression match, or throw `ValueError` if no match could be made. */
|
|
52
|
-
export declare function
|
|
53
|
-
export declare function
|
|
54
|
-
export declare function
|
|
52
|
+
export declare function requireMatch<T extends NamedRegExpData>(str: string, regexp: NamedRegExp<T>): NamedRegExpExecArray<T>;
|
|
53
|
+
export declare function requireMatch<T extends string>(str: string, regexp: TypedRegExp<T>): TypedRegExpExecArray<T>;
|
|
54
|
+
export declare function requireMatch(str: string, regexp: RegExp): RegExpExecArray;
|
|
55
55
|
/** Get an optional regular expression match, or `undefined` if no match could be made. */
|
|
56
|
-
export declare function
|
|
57
|
-
export declare function
|
|
56
|
+
export declare function getMatchGroups<T extends NamedRegExpData>(str: string, regexp: NamedRegExp<T>): T | undefined;
|
|
57
|
+
export declare function getMatchGroups(str: string, regexp: RegExp): NamedRegExpData | undefined;
|
|
58
58
|
/** Get a required regular expression match, or throw `ValueError` if no match could be made. */
|
|
59
|
-
export declare function
|
|
60
|
-
export declare function
|
|
59
|
+
export declare function requireMatchGroups<T extends NamedRegExpData>(str: string, regexp: NamedRegExp<T>): T;
|
|
60
|
+
export declare function requireMatchGroups(str: string, regexp: RegExp): NamedRegExpData;
|
package/util/regexp.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AssertionError } from "../error/AssertionError.js";
|
|
2
|
+
import { ValueError } from "../error/ValueError.js";
|
|
2
3
|
import { getArray } from "./array.js";
|
|
3
4
|
/** Regular expression that always matches everything. */
|
|
4
5
|
export const ALWAYS_REGEXP = /^.*$/;
|
|
@@ -11,7 +12,7 @@ export function isRegExp(value) {
|
|
|
11
12
|
/** Assert that an unknown value is a `RegExp` instance. */
|
|
12
13
|
export function assertRegExp(value) {
|
|
13
14
|
if (!(value instanceof RegExp))
|
|
14
|
-
throw new
|
|
15
|
+
throw new AssertionError("Must be regular expression", { received: value, caller: assertRegExp });
|
|
15
16
|
}
|
|
16
17
|
export function getRegExp(pattern, flags) {
|
|
17
18
|
return typeof pattern === "string" ? new RegExp(pattern, flags) : pattern;
|
|
@@ -26,7 +27,7 @@ export function escapeRegExp(pattern) {
|
|
|
26
27
|
}
|
|
27
28
|
const REPLACE_ESCAPED = /[-[\]/{}()*+?.\\^$|]/g;
|
|
28
29
|
/** Create regular expression that matches any of a list of other expressions. */
|
|
29
|
-
export function
|
|
30
|
+
export function createRegExpAny(patterns, flags) {
|
|
30
31
|
const arr = getArray(patterns).filter(Boolean);
|
|
31
32
|
// If there are no patterns to match against then _no_ string can ever match against any of nothing.
|
|
32
33
|
if (!arr.length)
|
|
@@ -35,7 +36,7 @@ export function getAnyRegExp(patterns, flags) {
|
|
|
35
36
|
return new RegExp(`(?:${getArray(patterns).map(getRegExpSource).join(")|(?:")})`, flags);
|
|
36
37
|
}
|
|
37
38
|
/** Create regular expression that matches all of a list of other expressions. */
|
|
38
|
-
export function
|
|
39
|
+
export function createRegExpAll(patterns, flags) {
|
|
39
40
|
const arr = getArray(patterns).filter(Boolean);
|
|
40
41
|
// If there are no patterns to match against then _every_ string will match against the entire list of nothing.
|
|
41
42
|
if (!arr.length)
|
|
@@ -51,21 +52,21 @@ export function isMatch(str, regexp) {
|
|
|
51
52
|
export function notMatch(str, regexp) {
|
|
52
53
|
return !regexp.test(str);
|
|
53
54
|
}
|
|
54
|
-
export function
|
|
55
|
+
export function getMatch(str, regexp) {
|
|
55
56
|
return regexp.exec(str) || undefined;
|
|
56
57
|
}
|
|
57
|
-
export function
|
|
58
|
-
const match =
|
|
58
|
+
export function requireMatch(str, regexp) {
|
|
59
|
+
const match = getMatch(str, regexp);
|
|
59
60
|
if (!match)
|
|
60
|
-
throw new
|
|
61
|
+
throw new ValueError("Must match regular expression", { received: str, expected: regexp, caller: requireMatch });
|
|
61
62
|
return match;
|
|
62
63
|
}
|
|
63
|
-
export function
|
|
64
|
+
export function getMatchGroups(str, regexp) {
|
|
64
65
|
return regexp.exec(str)?.groups || undefined;
|
|
65
66
|
}
|
|
66
|
-
export function
|
|
67
|
-
const groups =
|
|
67
|
+
export function requireMatchGroups(str, regexp) {
|
|
68
|
+
const groups = getMatchGroups(str, regexp);
|
|
68
69
|
if (!groups)
|
|
69
|
-
throw new
|
|
70
|
+
throw new ValueError("Must match regular expression", { received: str, expected: regexp, caller: requireMatchGroups });
|
|
70
71
|
return groups;
|
|
71
72
|
}
|
package/util/sequence.d.ts
CHANGED
|
@@ -14,7 +14,5 @@ export declare function repeatUntil<T>(source: AsyncIterable<T>, ...signals: [Pr
|
|
|
14
14
|
export declare function repeatDelay(ms: number): AsyncIterable<number>;
|
|
15
15
|
/** Dispatch items in a sequence to a (possibly async) callback. */
|
|
16
16
|
export declare function callSequence<T>(sequence: AsyncIterable<T>, callback: AsyncValueCallback<T>): AsyncIterable<T>;
|
|
17
|
-
/** Get the first value from an async iterator. **/
|
|
18
|
-
export declare function getNextValue<T>(sequence: AsyncIterable<T>): Promise<T>;
|
|
19
17
|
/** Pull values from a sequence until the returned function is called. */
|
|
20
18
|
export declare function runSequence<T>(sequence: AsyncIterable<T>, onNext?: ValueCallback<T>, onError?: Report): Stop;
|
package/util/sequence.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { NotFoundError } from "../error/NotFoundError.js";
|
|
2
1
|
import { getDeferred, getDelay } from "./async.js";
|
|
3
2
|
import { call, callMethod } from "./callback.js";
|
|
4
3
|
import { STOP } from "./constants.js";
|
|
@@ -40,12 +39,6 @@ export async function* callSequence(sequence, callback) {
|
|
|
40
39
|
yield item;
|
|
41
40
|
}
|
|
42
41
|
}
|
|
43
|
-
/** Get the first value from an async iterator. **/
|
|
44
|
-
export async function getNextValue(sequence) {
|
|
45
|
-
for await (const item of sequence)
|
|
46
|
-
return item;
|
|
47
|
-
throw new NotFoundError("First value is required");
|
|
48
|
-
}
|
|
49
42
|
/** Pull values from a sequence until the returned function is called. */
|
|
50
43
|
export function runSequence(sequence, onNext, onError) {
|
|
51
44
|
const { promise, resolve } = getDeferred();
|
package/util/serialise.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ValueError } from "../error/ValueError.js";
|
|
2
2
|
import { isArray } from "./array.js";
|
|
3
3
|
import { getPrototype, isObject } from "./object.js";
|
|
4
4
|
const R_QUOTE = /"/g;
|
|
@@ -39,7 +39,7 @@ export function serialise(value) {
|
|
|
39
39
|
const props = Object.entries(value).map(_serialiseEntry).sort();
|
|
40
40
|
return `{${type ? `"$type":${_escapeString(type)}${props.length ? "," : ""}` : ""}${props.join(",")}}`;
|
|
41
41
|
}
|
|
42
|
-
throw new
|
|
42
|
+
throw new ValueError("Cannot serialize value", { received: value, caller: serialise });
|
|
43
43
|
}
|
|
44
44
|
function _serialiseEntry([key, value]) {
|
|
45
45
|
return `${_escapeString(key)}:${serialise(value)}`;
|
package/util/set.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AssertionError } from "../error/AssertionError.js";
|
|
2
2
|
import { limitItems } from "./iterate.js";
|
|
3
3
|
/** Is an unknown value a set? */
|
|
4
4
|
export function isSet(value) {
|
|
@@ -7,7 +7,7 @@ export function isSet(value) {
|
|
|
7
7
|
/** Assert that a value is a `Set` instance. */
|
|
8
8
|
export function assertSet(value) {
|
|
9
9
|
if (!isSet(value))
|
|
10
|
-
throw new
|
|
10
|
+
throw new AssertionError("Must be set", { received: value, caller: assertSet });
|
|
11
11
|
}
|
|
12
12
|
/** Is an unknown value an item in a set? */
|
|
13
13
|
export function isSetItem(set, item) {
|
|
@@ -16,7 +16,7 @@ export function isSetItem(set, item) {
|
|
|
16
16
|
/** Assert that an unknown value is an item in a set. */
|
|
17
17
|
export function assertSetItem(set, item) {
|
|
18
18
|
if (!isSetItem(set, item))
|
|
19
|
-
throw new
|
|
19
|
+
throw new AssertionError("Item must exist in set", { item, set, caller: assertSetItem });
|
|
20
20
|
}
|
|
21
21
|
/** Convert an iterable to a `Set` (if it's already a `Set` it passes through unchanged). */
|
|
22
22
|
export function getSet(iterable) {
|