shelving 1.91.2 → 1.92.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/db/Change.d.ts +19 -20
- package/db/Change.js +22 -21
- package/db/CollectionReference.d.ts +103 -0
- package/db/CollectionReference.js +127 -0
- package/db/Database.d.ts +21 -23
- package/db/Database.js +18 -18
- package/db/{Item.d.ts → ItemReference.d.ts} +13 -14
- package/db/{Item.js → ItemReference.js} +14 -17
- package/db/ItemState.d.ts +3 -3
- package/db/{Query.d.ts → QueryReference.d.ts} +25 -33
- package/db/QueryReference.js +101 -0
- package/db/QueryState.d.ts +10 -10
- package/db/QueryState.js +20 -18
- package/db/index.d.ts +3 -3
- package/db/index.js +3 -3
- package/firestore/client/FirestoreClientProvider.d.ts +13 -13
- package/firestore/client/FirestoreClientProvider.js +55 -84
- package/firestore/lite/FirestoreLiteProvider.d.ts +11 -11
- package/firestore/lite/FirestoreLiteProvider.js +52 -83
- package/firestore/server/FirestoreServerProvider.d.ts +13 -13
- package/firestore/server/FirestoreServerProvider.js +51 -84
- package/index.d.ts +0 -2
- package/index.js +0 -2
- package/package.json +1 -3
- package/provider/CacheProvider.d.ts +7 -7
- package/provider/CacheProvider.js +14 -14
- package/provider/DebugProvider.d.ts +11 -11
- package/provider/DebugProvider.js +28 -29
- package/provider/MemoryProvider.d.ts +17 -17
- package/provider/MemoryProvider.js +41 -43
- package/provider/Provider.d.ts +15 -15
- package/provider/ThroughProvider.d.ts +12 -12
- package/provider/ThroughProvider.js +20 -20
- package/provider/ValidationProvider.d.ts +11 -11
- package/provider/ValidationProvider.js +16 -12
- package/react/useData.d.ts +5 -5
- package/react/useData.js +2 -2
- package/state/DataState.d.ts +4 -8
- package/state/DataState.js +6 -16
- package/state/DictionaryState.d.ts +4 -6
- package/state/DictionaryState.js +4 -9
- package/test/basics.d.ts +1 -1
- package/test/people.d.ts +1 -1
- package/test/util.d.ts +1 -1
- package/test/util.js +1 -1
- package/util/data.d.ts +2 -2
- package/util/equal.js +5 -5
- package/util/hydrate.d.ts +13 -26
- package/util/hydrate.js +44 -60
- package/util/index.d.ts +2 -0
- package/util/index.js +2 -0
- package/util/iterate.d.ts +2 -0
- package/util/match.d.ts +2 -10
- package/util/match.js +4 -8
- package/util/query.d.ts +83 -0
- package/util/query.js +129 -0
- package/util/sort.d.ts +8 -15
- package/util/sort.js +15 -19
- package/util/transform.d.ts +26 -45
- package/util/transform.js +24 -29
- package/util/update.d.ts +22 -0
- package/util/update.js +42 -0
- package/util/validate.js +2 -2
- package/constraint/Constraint.d.ts +0 -7
- package/constraint/Constraint.js +0 -3
- package/constraint/Constraints.d.ts +0 -20
- package/constraint/Constraints.js +0 -34
- package/constraint/Filter.d.ts +0 -34
- package/constraint/Filter.js +0 -89
- package/constraint/Filters.d.ts +0 -27
- package/constraint/Filters.js +0 -41
- package/constraint/Sort.d.ts +0 -18
- package/constraint/Sort.js +0 -33
- package/constraint/Sorts.d.ts +0 -26
- package/constraint/Sorts.js +0 -47
- package/constraint/Statement.d.ts +0 -45
- package/constraint/Statement.js +0 -79
- package/constraint/index.d.ts +0 -7
- package/constraint/index.js +0 -7
- package/db/Collection.d.ts +0 -64
- package/db/Collection.js +0 -83
- package/db/Query.js +0 -94
- package/update/ArrayUpdate.d.ts +0 -17
- package/update/ArrayUpdate.js +0 -31
- package/update/DataUpdate.d.ts +0 -37
- package/update/DataUpdate.js +0 -44
- package/update/Delete.d.ts +0 -10
- package/update/Delete.js +0 -12
- package/update/DictionaryUpdate.d.ts +0 -31
- package/update/DictionaryUpdate.js +0 -62
- package/update/Increment.d.ts +0 -18
- package/update/Increment.js +0 -22
- package/update/Update.d.ts +0 -8
- package/update/Update.js +0 -6
- package/update/hydrations.d.ts +0 -3
- package/update/hydrations.js +0 -13
- package/update/index.d.ts +0 -7
- package/update/index.js +0 -7
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ValidationError } from "../error/ValidationError.js";
|
|
2
2
|
import { Feedback } from "../feedback/Feedback.js";
|
|
3
|
-
import {
|
|
3
|
+
import { updateData } from "../util/update.js";
|
|
4
4
|
import { validate, validateWithContext } from "../util/validate.js";
|
|
5
5
|
// Constants.
|
|
6
|
-
const VALIDATION_CONTEXT_GET = { action: "get" };
|
|
6
|
+
const VALIDATION_CONTEXT_GET = { action: "get", id: true };
|
|
7
7
|
const VALIDATION_CONTEXT_ADD = { action: "add" };
|
|
8
8
|
const VALIDATION_CONTEXT_SET = { action: "set" };
|
|
9
9
|
const VALIDATION_CONTEXT_UPDATE = { action: "update", partial: true };
|
|
@@ -42,7 +42,8 @@ export class ValidationProvider extends BaseValidationProvider {
|
|
|
42
42
|
return this.source.setItem(collection, id, validateWithContext(value, this.getSchema(collection), VALIDATION_CONTEXT_SET));
|
|
43
43
|
}
|
|
44
44
|
updateItem(collection, id, updates) {
|
|
45
|
-
|
|
45
|
+
validateWithContext(updateData({}, updates), this.getSchema(collection), VALIDATION_CONTEXT_UPDATE);
|
|
46
|
+
return this.source.updateItem(collection, id, updates);
|
|
46
47
|
}
|
|
47
48
|
deleteItem(collection, id) {
|
|
48
49
|
return this.source.deleteItem(collection, id);
|
|
@@ -54,7 +55,8 @@ export class ValidationProvider extends BaseValidationProvider {
|
|
|
54
55
|
return this.source.setQuery(collection, constraints, validate(value, this.getSchema(collection)));
|
|
55
56
|
}
|
|
56
57
|
updateQuery(collection, constraints, updates) {
|
|
57
|
-
|
|
58
|
+
validateWithContext(updateData({}, updates), this.getSchema(collection), VALIDATION_CONTEXT_UPDATE);
|
|
59
|
+
return this.source.updateQuery(collection, constraints, updates);
|
|
58
60
|
}
|
|
59
61
|
deleteQuery(collection, constraints) {
|
|
60
62
|
return this.source.deleteQuery(collection, constraints);
|
|
@@ -76,7 +78,8 @@ export class AsyncValidationProvider extends BaseValidationProvider {
|
|
|
76
78
|
return this.source.setItem(collection, id, validateWithContext(value, this.getSchema(collection), VALIDATION_CONTEXT_SET));
|
|
77
79
|
}
|
|
78
80
|
updateItem(collection, id, updates) {
|
|
79
|
-
|
|
81
|
+
validateWithContext(updateData({}, updates), this.getSchema(collection), VALIDATION_CONTEXT_UPDATE);
|
|
82
|
+
return this.source.updateItem(collection, id, updates);
|
|
80
83
|
}
|
|
81
84
|
deleteItem(collection, id) {
|
|
82
85
|
return this.source.deleteItem(collection, id);
|
|
@@ -88,7 +91,8 @@ export class AsyncValidationProvider extends BaseValidationProvider {
|
|
|
88
91
|
return this.source.setQuery(collection, constraints, validateWithContext(value, this.getSchema(collection), VALIDATION_CONTEXT_SET));
|
|
89
92
|
}
|
|
90
93
|
updateQuery(collection, constraints, updates) {
|
|
91
|
-
|
|
94
|
+
validateWithContext(updateData({}, updates), this.getSchema(collection), VALIDATION_CONTEXT_UPDATE);
|
|
95
|
+
return this.source.updateQuery(collection, constraints, updates);
|
|
92
96
|
}
|
|
93
97
|
deleteQuery(collection, constraints) {
|
|
94
98
|
return this.source.deleteQuery(collection, constraints);
|
|
@@ -99,12 +103,12 @@ function _validateItem(collection, unsafeEntity, schema) {
|
|
|
99
103
|
if (!unsafeEntity)
|
|
100
104
|
return null;
|
|
101
105
|
try {
|
|
102
|
-
return
|
|
106
|
+
return validateWithContext(unsafeEntity, schema, VALIDATION_CONTEXT_GET);
|
|
103
107
|
}
|
|
104
108
|
catch (thrown) {
|
|
105
109
|
if (!(thrown instanceof Feedback))
|
|
106
110
|
throw thrown;
|
|
107
|
-
throw new ValidationError(`Invalid data for "${collection}"`,
|
|
111
|
+
throw new ValidationError(`Invalid data for "${collection}"`, thrown.message);
|
|
108
112
|
}
|
|
109
113
|
}
|
|
110
114
|
/** Validate a set of entities for this query reference. */
|
|
@@ -113,18 +117,18 @@ function _validateItems(collection, unsafeEntities, schema) {
|
|
|
113
117
|
}
|
|
114
118
|
function* _yieldValidItems(collection, unsafeEntities, schema) {
|
|
115
119
|
let invalid = false;
|
|
116
|
-
const
|
|
120
|
+
const messages = {};
|
|
117
121
|
for (const unsafeEntity of unsafeEntities) {
|
|
118
122
|
try {
|
|
119
|
-
yield
|
|
123
|
+
yield validateWithContext(unsafeEntity, schema, VALIDATION_CONTEXT_GET);
|
|
120
124
|
}
|
|
121
125
|
catch (thrown) {
|
|
122
126
|
if (!(thrown instanceof Feedback))
|
|
123
127
|
throw thrown;
|
|
124
128
|
invalid = true;
|
|
125
|
-
|
|
129
|
+
messages[unsafeEntity.id] = thrown.message;
|
|
126
130
|
}
|
|
127
131
|
}
|
|
128
132
|
if (invalid)
|
|
129
|
-
throw new ValidationError(`Invalid data for "${collection}"`,
|
|
133
|
+
throw new ValidationError(`Invalid data for "${collection}"`, messages);
|
|
130
134
|
}
|
package/react/useData.d.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import type {
|
|
2
|
+
import type { AsyncQueryReference } from "../db/QueryReference.js";
|
|
3
3
|
import type { ImmutableArray } from "../util/array.js";
|
|
4
|
-
import {
|
|
4
|
+
import { AsyncItemReference } from "../db/ItemReference.js";
|
|
5
5
|
import { ItemState } from "../db/ItemState.js";
|
|
6
6
|
import { QueryState } from "../db/QueryState.js";
|
|
7
|
-
type RefToState<T> = T extends undefined ? undefined : T extends
|
|
7
|
+
type RefToState<T> = T extends undefined ? undefined : T extends AsyncItemReference<infer X> ? ItemState<X> : T extends AsyncQueryReference<infer X> ? QueryState<X> : never;
|
|
8
8
|
/** Use one or more data items or queries. */
|
|
9
|
-
export declare function useData<T extends
|
|
10
|
-
export declare function useData<T extends ImmutableArray<
|
|
9
|
+
export declare function useData<T extends AsyncItemReference | AsyncQueryReference | undefined>(ref: T): RefToState<T>;
|
|
10
|
+
export declare function useData<T extends ImmutableArray<AsyncItemReference | AsyncQueryReference | undefined>>(...refs: T): {
|
|
11
11
|
[K in keyof T]: RefToState<T[K]>;
|
|
12
12
|
};
|
|
13
13
|
/** Wrap components with `<DataCache>` to allow the use of `useData()`. */
|
package/react/useData.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AsyncItemReference } from "../db/ItemReference.js";
|
|
2
2
|
import { ItemState } from "../db/ItemState.js";
|
|
3
3
|
import { QueryState } from "../db/QueryState.js";
|
|
4
4
|
import { setMapItem } from "../util/map.js";
|
|
@@ -15,7 +15,7 @@ export function useData(...refs) {
|
|
|
15
15
|
/** Get the corresponding `ItemState` or `QueryState` instance from the cache for a given `Item` or `Query`. */
|
|
16
16
|
function _getRefState(ref, cache) {
|
|
17
17
|
const key = ref === null || ref === void 0 ? void 0 : ref.toString();
|
|
18
|
-
return ref && key ? cache.get(key) || setMapItem(cache, key, ref instanceof
|
|
18
|
+
return ref && key ? cache.get(key) || setMapItem(cache, key, ref instanceof AsyncItemReference ? new ItemState(ref) : new QueryState(ref)) : undefined;
|
|
19
19
|
}
|
|
20
20
|
/** Wrap components with `<DataCache>` to allow the use of `useData()`. */
|
|
21
21
|
export const DataCache = Cache;
|
package/state/DataState.d.ts
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import type { Data, DataKey } from "../util/data.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { Updates } from "../util/update.js";
|
|
3
3
|
import { State } from "./State.js";
|
|
4
4
|
/** State that stores a data object and has additional methods to help with that. */
|
|
5
5
|
export declare class DataState<T extends Data> extends State<T> {
|
|
6
6
|
/** Get the data value of this state. */
|
|
7
7
|
get data(): T;
|
|
8
|
+
/** Update several props in this data. */
|
|
9
|
+
update(updates: Updates<T>): void;
|
|
8
10
|
/** Update a single named prop in this data. */
|
|
9
11
|
getProp<K extends DataKey<T>>(name: K): T[K];
|
|
10
12
|
/** Update a single named prop in this data. */
|
|
11
13
|
setProp<K extends DataKey<T>>(name: K, value: T[K]): void;
|
|
12
|
-
/** Update a single named prop in this data. */
|
|
13
|
-
updateProp<K extends DataKey<T>>(name: K, update: Transformer<T[K], T[K]>): void;
|
|
14
|
-
/** Update several props in this data. */
|
|
15
|
-
update(updates: Transformers<T, T>): void;
|
|
16
14
|
}
|
|
17
15
|
/** State that stores an optional data object and has additional methods to help with that. */
|
|
18
16
|
export declare class OptionalDataState<T extends Data> extends State<T | null> {
|
|
@@ -21,13 +19,11 @@ export declare class OptionalDataState<T extends Data> extends State<T | null> {
|
|
|
21
19
|
/** Does the data exist or not? */
|
|
22
20
|
get exists(): boolean;
|
|
23
21
|
/** Update several props in this data. */
|
|
24
|
-
update(updates:
|
|
22
|
+
update(updates: Updates<T>): void;
|
|
25
23
|
/** Update a single named prop in this data. */
|
|
26
24
|
getProp<K extends DataKey<T>>(name: K): T[K];
|
|
27
25
|
/** Update a single named prop in this data. */
|
|
28
26
|
setProp<K extends DataKey<T>>(name: K, value: T[K]): void;
|
|
29
|
-
/** Update a single named prop in this data. */
|
|
30
|
-
updateProp<K extends DataKey<T>>(name: K, update: Transformer<T[K], T[K]>): void;
|
|
31
27
|
/** Set the data to `null`. */
|
|
32
28
|
unset(): void;
|
|
33
29
|
}
|
package/state/DataState.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getData } from "../util/data.js";
|
|
2
2
|
import { withProp } from "../util/object.js";
|
|
3
|
-
import {
|
|
3
|
+
import { updateData } from "../util/update.js";
|
|
4
4
|
import { State } from "./State.js";
|
|
5
5
|
/** State that stores a data object and has additional methods to help with that. */
|
|
6
6
|
export class DataState extends State {
|
|
@@ -8,6 +8,10 @@ export class DataState extends State {
|
|
|
8
8
|
get data() {
|
|
9
9
|
return this.value;
|
|
10
10
|
}
|
|
11
|
+
/** Update several props in this data. */
|
|
12
|
+
update(updates) {
|
|
13
|
+
this.set(updateData(this.data, updates));
|
|
14
|
+
}
|
|
11
15
|
/** Update a single named prop in this data. */
|
|
12
16
|
getProp(name) {
|
|
13
17
|
return this.data[name];
|
|
@@ -16,15 +20,6 @@ export class DataState extends State {
|
|
|
16
20
|
setProp(name, value) {
|
|
17
21
|
this.set(withProp(this.data, name, value));
|
|
18
22
|
}
|
|
19
|
-
/** Update a single named prop in this data. */
|
|
20
|
-
updateProp(name, update) {
|
|
21
|
-
const data = this.data;
|
|
22
|
-
this.set(withProp(data, name, transform(data[name], update)));
|
|
23
|
-
}
|
|
24
|
-
/** Update several props in this data. */
|
|
25
|
-
update(updates) {
|
|
26
|
-
this.set(transformObject(this.data, updates));
|
|
27
|
-
}
|
|
28
23
|
}
|
|
29
24
|
/** State that stores an optional data object and has additional methods to help with that. */
|
|
30
25
|
export class OptionalDataState extends State {
|
|
@@ -38,7 +33,7 @@ export class OptionalDataState extends State {
|
|
|
38
33
|
}
|
|
39
34
|
/** Update several props in this data. */
|
|
40
35
|
update(updates) {
|
|
41
|
-
this.set(
|
|
36
|
+
this.set(updateData(this.data, updates));
|
|
42
37
|
}
|
|
43
38
|
/** Update a single named prop in this data. */
|
|
44
39
|
getProp(name) {
|
|
@@ -48,11 +43,6 @@ export class OptionalDataState extends State {
|
|
|
48
43
|
setProp(name, value) {
|
|
49
44
|
this.set(withProp(this.data, name, value));
|
|
50
45
|
}
|
|
51
|
-
/** Update a single named prop in this data. */
|
|
52
|
-
updateProp(name, update) {
|
|
53
|
-
const data = this.data;
|
|
54
|
-
this.set(withProp(data, name, transform(data[name], update)));
|
|
55
|
-
}
|
|
56
46
|
/** Set the data to `null`. */
|
|
57
47
|
unset() {
|
|
58
48
|
this.set(null);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DictionaryItem, ImmutableDictionary } from "../util/dictionary.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { Updates } from "../util/update.js";
|
|
3
3
|
import { State } from "./State.js";
|
|
4
4
|
/** State that stores a dictionary object and has additional methods to help with that. */
|
|
5
5
|
export declare class DictionaryState<T> extends State<ImmutableDictionary<T>> implements Iterable<DictionaryItem<T>> {
|
|
@@ -7,15 +7,13 @@ export declare class DictionaryState<T> extends State<ImmutableDictionary<T>> im
|
|
|
7
7
|
/** Get the length of the current value of this state. */
|
|
8
8
|
get count(): number;
|
|
9
9
|
/** Set a named entry in this object with a different value. */
|
|
10
|
-
update(updates:
|
|
10
|
+
update(updates: Updates<ImmutableDictionary<T>>): void;
|
|
11
11
|
/** Remove a named entry from this object. */
|
|
12
12
|
delete(...keys: string[]): void;
|
|
13
|
-
/**
|
|
13
|
+
/** Get an item in this dictionary. */
|
|
14
14
|
getItem(name: string): T | undefined;
|
|
15
|
-
/**
|
|
15
|
+
/** Set an item in this dictionary. */
|
|
16
16
|
setItem(name: string, value: T): void;
|
|
17
|
-
/** Update a single named prop in this data. */
|
|
18
|
-
updateItem(name: string, update: Transformer<T | undefined, T>): void;
|
|
19
17
|
/** Iterate over the entries of the object. */
|
|
20
18
|
[Symbol.iterator](): Iterator<DictionaryItem<T>>;
|
|
21
19
|
}
|
package/state/DictionaryState.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { omitDictionaryItems } from "../util/dictionary.js";
|
|
2
2
|
import { withProp } from "../util/object.js";
|
|
3
|
-
import {
|
|
3
|
+
import { updateData } from "../util/update.js";
|
|
4
4
|
import { State } from "./State.js";
|
|
5
5
|
/** State that stores a dictionary object and has additional methods to help with that. */
|
|
6
6
|
export class DictionaryState extends State {
|
|
@@ -13,25 +13,20 @@ export class DictionaryState extends State {
|
|
|
13
13
|
}
|
|
14
14
|
/** Set a named entry in this object with a different value. */
|
|
15
15
|
update(updates) {
|
|
16
|
-
this.set(
|
|
16
|
+
this.set(updateData(this.value, updates));
|
|
17
17
|
}
|
|
18
18
|
/** Remove a named entry from this object. */
|
|
19
19
|
delete(...keys) {
|
|
20
20
|
this.set(omitDictionaryItems(this.value, ...keys));
|
|
21
21
|
}
|
|
22
|
-
/**
|
|
22
|
+
/** Get an item in this dictionary. */
|
|
23
23
|
getItem(name) {
|
|
24
24
|
return this.value[name];
|
|
25
25
|
}
|
|
26
|
-
/**
|
|
26
|
+
/** Set an item in this dictionary. */
|
|
27
27
|
setItem(name, value) {
|
|
28
28
|
this.set(withProp(this.value, name, value));
|
|
29
29
|
}
|
|
30
|
-
/** Update a single named prop in this data. */
|
|
31
|
-
updateItem(name, update) {
|
|
32
|
-
const value = this.value;
|
|
33
|
-
this.set(withProp(value, name, transform(value[name], update)));
|
|
34
|
-
}
|
|
35
30
|
/** Iterate over the entries of the object. */
|
|
36
31
|
[Symbol.iterator]() {
|
|
37
32
|
return Object.entries(this.value)[Symbol.iterator]();
|
package/test/basics.d.ts
CHANGED
package/test/people.d.ts
CHANGED
package/test/util.d.ts
CHANGED
package/test/util.js
CHANGED
package/util/data.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export type DataKey<T extends Data> = keyof T & string;
|
|
|
10
10
|
export type DataValue<T extends Data> = T[keyof T & string];
|
|
11
11
|
/** Prop for a data object. */
|
|
12
12
|
export type DataProp<T extends Data> = {
|
|
13
|
-
readonly [K in DataKey<T>]: [K, T[K]];
|
|
13
|
+
readonly [K in DataKey<T>]: readonly [K, T[K]];
|
|
14
14
|
}[DataKey<T>];
|
|
15
15
|
/** Data or `null` to indicate the data doesn't exist. */
|
|
16
16
|
export type OptionalData<T extends Data> = T | null;
|
|
@@ -26,7 +26,7 @@ export type FlatDataKey<T extends Data> = FlatDataProp<T>[0];
|
|
|
26
26
|
export type FlatDataValue<T extends Data> = FlatDataProp<T>[1];
|
|
27
27
|
/** Prop for a flattened data object with deep keys flattened into `a.c.b` format. */
|
|
28
28
|
export type FlatDataProp<T extends Data> = {
|
|
29
|
-
readonly [K in DataKey<T>]: (T[K] extends Data ? FlatDataProp<T[K]> : [null, T[K]]) extends infer E ? E extends [infer KK, infer VV] ? [KK extends string ? `${K}.${KK}` : K, VV] : never : never;
|
|
29
|
+
readonly [K in DataKey<T>]: (T[K] extends Data ? FlatDataProp<T[K]> : readonly [null, T[K]]) extends infer E ? E extends readonly [infer KK, infer VV] ? readonly [KK extends string ? `${K}.${KK}` : K, VV] : never : never;
|
|
30
30
|
}[DataKey<T>];
|
|
31
31
|
/** Is an unknown value a data object? */
|
|
32
32
|
export declare const isData: <T extends Data>(value: unknown) => value is T;
|
package/util/equal.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { isArray } from "./array.js";
|
|
2
2
|
import { isMap } from "./map.js";
|
|
3
3
|
import { isObject, isProp } from "./object.js";
|
|
4
|
-
import {
|
|
4
|
+
import { compareAscending } from "./sort.js";
|
|
5
5
|
/** Is unknown value `left` exactly equal to `right`? */
|
|
6
6
|
export const isEqual = (left, right) => left === right;
|
|
7
7
|
/** Is unknown value `left` not exactly equal to `right`? */
|
|
8
8
|
export const notEqual = (left, right) => !isEqual(left, right);
|
|
9
9
|
/** Is unknown value `left` less than `right`? */
|
|
10
|
-
export const isLess = (left, right) =>
|
|
10
|
+
export const isLess = (left, right) => compareAscending(left, right) < 0;
|
|
11
11
|
/** Is unknown value `left` less than or equal to `right`? */
|
|
12
|
-
export const isEqualLess = (left, right) =>
|
|
12
|
+
export const isEqualLess = (left, right) => compareAscending(left, right) <= 0;
|
|
13
13
|
/** Is unknown value `left` greater than `right`? */
|
|
14
|
-
export const isGreater = (left, right) =>
|
|
14
|
+
export const isGreater = (left, right) => compareAscending(left, right) > 0;
|
|
15
15
|
/** Is unknown value `left` greater than or equal to `right`? */
|
|
16
|
-
export const isEqualGreater = (left, right) =>
|
|
16
|
+
export const isEqualGreater = (left, right) => compareAscending(left, right) >= 0;
|
|
17
17
|
// Internal shared by shallow/deep equal.
|
|
18
18
|
function _isEqualRecursively(left, right, recursor) {
|
|
19
19
|
if (left === right)
|
package/util/hydrate.d.ts
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
import type { Class } from "./class.js";
|
|
2
2
|
import type { ImmutableDictionary } from "./dictionary.js";
|
|
3
|
-
import type { Transformable } from "./transform.js";
|
|
4
3
|
/**
|
|
5
4
|
* A set of hydrations describes a set of string keys and the class constructor to be dehydrated and rehydrated.
|
|
6
5
|
* - We can't use `class.name` because we don't know that the name of the class will survive minification.
|
|
7
6
|
*/
|
|
8
7
|
export type Hydrations = ImmutableDictionary<Class<unknown>>;
|
|
8
|
+
/** A dehydrated object with a `$type` key. */
|
|
9
|
+
export type DehydratedObject = {
|
|
10
|
+
readonly $type: string;
|
|
11
|
+
readonly $value: unknown;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Deeply hydrate a class instance based on a set of `Hydrations`
|
|
15
|
+
* - Hydration allows a client to receive class instances from a server.
|
|
16
|
+
* - By its nature hydration is an unsafe operation.
|
|
17
|
+
* - Deeply iterates into arrays and plain objects to hydrate their items and props too.
|
|
18
|
+
* - Note: the recursion in this function does not currently protect against infinite loops.
|
|
19
|
+
*/
|
|
20
|
+
export declare function hydrate(value: unknown, hydrations: Hydrations): unknown;
|
|
9
21
|
/**
|
|
10
22
|
* Deeply dehydrate a class instance based on a set of `Hydrations`
|
|
11
23
|
* - Dehydration allows you to pass class instances from a server back to a client.
|
|
@@ -17,28 +29,3 @@ export type Hydrations = ImmutableDictionary<Class<unknown>>;
|
|
|
17
29
|
* @throws `Error` if the value is a class instance that cannot be dehydrated (i.e. is not matched by any constructor in `hydrations`).
|
|
18
30
|
*/
|
|
19
31
|
export declare function dehydrate(value: unknown, hydrations: Hydrations): unknown;
|
|
20
|
-
/**
|
|
21
|
-
* Deeply hydrate a class instance based on a set of `Hydrations`
|
|
22
|
-
* - Hydration allows a client to receive class instances from a server.
|
|
23
|
-
* - By its nature hydration is an unsafe operation.
|
|
24
|
-
* - Deeply iterates into arrays and plain objects to hydrate their items and props too.
|
|
25
|
-
* - Note: the recursion in this function does not currently protect against infinite loops.
|
|
26
|
-
*/
|
|
27
|
-
export declare function hydrate(value: unknown, hydrations: Hydrations): unknown;
|
|
28
|
-
/** A dehydrated object with a `$type` key. */
|
|
29
|
-
export type DehydratedObject = {
|
|
30
|
-
readonly $type: string;
|
|
31
|
-
readonly $value: unknown;
|
|
32
|
-
};
|
|
33
|
-
/** Hydrates a value with a set of hydrations. */
|
|
34
|
-
export declare class Hydrator implements Transformable<unknown, unknown> {
|
|
35
|
-
private _hydrations;
|
|
36
|
-
constructor(hydrations: Hydrations);
|
|
37
|
-
transform(value: unknown): unknown;
|
|
38
|
-
}
|
|
39
|
-
/** Dehydrates a value with a set of hydrations. */
|
|
40
|
-
export declare class Dehydrator implements Transformable<unknown, unknown> {
|
|
41
|
-
private _hydrations;
|
|
42
|
-
constructor(hydrations: Hydrations);
|
|
43
|
-
transform(value: unknown): unknown;
|
|
44
|
-
}
|
package/util/hydrate.js
CHANGED
|
@@ -2,10 +2,39 @@ import { AssertionError } from "../error/AssertionError.js";
|
|
|
2
2
|
import { isArray } from "./array.js";
|
|
3
3
|
import { isDate } from "./date.js";
|
|
4
4
|
import { isMap } from "./map.js";
|
|
5
|
-
import { getPrototype, isObject, isPlainObject } from "./object.js";
|
|
5
|
+
import { getProps, getPrototype, isObject, isPlainObject } from "./object.js";
|
|
6
6
|
import { isSet } from "./set.js";
|
|
7
7
|
import { isString } from "./string.js";
|
|
8
|
-
import { mapArray,
|
|
8
|
+
import { mapArray, mapObject } from "./transform.js";
|
|
9
|
+
/** Is an unknown value a dehydrated object with a `$type` key. */
|
|
10
|
+
const isDehydrated = (value) => isString(value.$type);
|
|
11
|
+
/**
|
|
12
|
+
* Deeply hydrate a class instance based on a set of `Hydrations`
|
|
13
|
+
* - Hydration allows a client to receive class instances from a server.
|
|
14
|
+
* - By its nature hydration is an unsafe operation.
|
|
15
|
+
* - Deeply iterates into arrays and plain objects to hydrate their items and props too.
|
|
16
|
+
* - Note: the recursion in this function does not currently protect against infinite loops.
|
|
17
|
+
*/
|
|
18
|
+
export function hydrate(value, hydrations) {
|
|
19
|
+
if (isArray(value))
|
|
20
|
+
return mapArray(value, hydrate, hydrations);
|
|
21
|
+
if (isPlainObject(value)) {
|
|
22
|
+
if (!isDehydrated(value))
|
|
23
|
+
return mapObject(value, hydrate, hydrations);
|
|
24
|
+
const { $type, $value } = value;
|
|
25
|
+
if ($type === "Map")
|
|
26
|
+
return new Map($value);
|
|
27
|
+
if ($type === "Set")
|
|
28
|
+
return new Set($value);
|
|
29
|
+
if ($type === "Date")
|
|
30
|
+
return new Date($value);
|
|
31
|
+
const hydration = hydrations[$type];
|
|
32
|
+
if (hydration)
|
|
33
|
+
return { __proto__: hydration.prototype, ...mapObject($value, hydrate, hydrations) };
|
|
34
|
+
throw new AssertionError(`Cannot hydrate "${$type}" object`, value);
|
|
35
|
+
}
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
9
38
|
/**
|
|
10
39
|
* Deeply dehydrate a class instance based on a set of `Hydrations`
|
|
11
40
|
* - Dehydration allows you to pass class instances from a server back to a client.
|
|
@@ -17,69 +46,24 @@ import { mapArray, mapEntries, mapItems, mapObject } from "./transform.js";
|
|
|
17
46
|
* @throws `Error` if the value is a class instance that cannot be dehydrated (i.e. is not matched by any constructor in `hydrations`).
|
|
18
47
|
*/
|
|
19
48
|
export function dehydrate(value, hydrations) {
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Deeply hydrate a class instance based on a set of `Hydrations`
|
|
24
|
-
* - Hydration allows a client to receive class instances from a server.
|
|
25
|
-
* - By its nature hydration is an unsafe operation.
|
|
26
|
-
* - Deeply iterates into arrays and plain objects to hydrate their items and props too.
|
|
27
|
-
* - Note: the recursion in this function does not currently protect against infinite loops.
|
|
28
|
-
*/
|
|
29
|
-
export function hydrate(value, hydrations) {
|
|
30
|
-
return new Hydrator(hydrations).transform(value);
|
|
31
|
-
}
|
|
32
|
-
/** Is an unknown value a dehydrated object with a `$type` key. */
|
|
33
|
-
const isDehydrated = (value) => isString(value.$type);
|
|
34
|
-
/** Hydrates a value with a set of hydrations. */
|
|
35
|
-
export class Hydrator {
|
|
36
|
-
constructor(hydrations) {
|
|
37
|
-
this._hydrations = hydrations;
|
|
38
|
-
}
|
|
39
|
-
transform(value) {
|
|
40
|
-
if (isArray(value))
|
|
41
|
-
return mapArray(value, this);
|
|
42
|
-
if (isPlainObject(value)) {
|
|
43
|
-
if (!isDehydrated(value))
|
|
44
|
-
return mapObject(value, this);
|
|
45
|
-
const { $type, $value } = value;
|
|
46
|
-
if ($type === "Map")
|
|
47
|
-
return new Map($value);
|
|
48
|
-
if ($type === "Set")
|
|
49
|
-
return new Set($value);
|
|
50
|
-
if ($type === "Date")
|
|
51
|
-
return new Date($value);
|
|
52
|
-
const hydration = this._hydrations[$type];
|
|
53
|
-
if (hydration)
|
|
54
|
-
return { __proto__: hydration.prototype, ...mapObject($value, this) };
|
|
55
|
-
throw new AssertionError(`Cannot hydrate "${$type}" object`, value);
|
|
56
|
-
}
|
|
57
|
-
return value;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
/** Dehydrates a value with a set of hydrations. */
|
|
61
|
-
export class Dehydrator {
|
|
62
|
-
constructor(hydrations) {
|
|
63
|
-
this._hydrations = hydrations;
|
|
64
|
-
}
|
|
65
|
-
transform(value) {
|
|
49
|
+
if (isObject(value)) {
|
|
66
50
|
if (isArray(value))
|
|
67
|
-
return mapArray(value,
|
|
68
|
-
if (isMap(value))
|
|
69
|
-
return { $type: "Map", $value:
|
|
70
|
-
if (isSet(value))
|
|
71
|
-
return { $type: "Set", $value:
|
|
72
|
-
if (isDate(value))
|
|
51
|
+
return mapArray(value, dehydrate, hydrations);
|
|
52
|
+
else if (isMap(value))
|
|
53
|
+
return { $type: "Map", $value: mapArray(value.entries(), dehydrate, hydrations) };
|
|
54
|
+
else if (isSet(value))
|
|
55
|
+
return { $type: "Set", $value: mapArray(value.values(), dehydrate, hydrations) };
|
|
56
|
+
else if (isDate(value))
|
|
73
57
|
return { $type: "Date", $value: value.getTime() };
|
|
74
|
-
if (
|
|
58
|
+
else if (isPlainObject(value))
|
|
59
|
+
return mapObject(value, dehydrate, hydrations);
|
|
60
|
+
else {
|
|
75
61
|
const proto = getPrototype(value);
|
|
76
|
-
|
|
77
|
-
return mapObject(value, this);
|
|
78
|
-
for (const [$type, hydration] of Object.entries(this._hydrations))
|
|
62
|
+
for (const [$type, hydration] of getProps(hydrations))
|
|
79
63
|
if (proto === hydration.prototype)
|
|
80
|
-
return { $type, $value: mapObject(value,
|
|
64
|
+
return { $type, $value: mapObject(value, dehydrate, hydrations) };
|
|
81
65
|
throw new AssertionError(`Cannot dehydrate object`, value);
|
|
82
66
|
}
|
|
83
|
-
return value;
|
|
84
67
|
}
|
|
68
|
+
return value;
|
|
85
69
|
}
|
package/util/index.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ export * from "./merge.js";
|
|
|
26
26
|
export * from "./null.js";
|
|
27
27
|
export * from "./number.js";
|
|
28
28
|
export * from "./object.js";
|
|
29
|
+
export * from "./query.js";
|
|
29
30
|
export * from "./random.js";
|
|
30
31
|
export * from "./regexp.js";
|
|
31
32
|
export * from "./sequence.js";
|
|
@@ -39,5 +40,6 @@ export * from "./timeout.js";
|
|
|
39
40
|
export * from "./transform.js";
|
|
40
41
|
export * from "./undefined.js";
|
|
41
42
|
export * from "./units.js";
|
|
43
|
+
export * from "./update.js";
|
|
42
44
|
export * from "./url.js";
|
|
43
45
|
export * from "./validate.js";
|
package/util/index.js
CHANGED
|
@@ -26,6 +26,7 @@ export * from "./merge.js";
|
|
|
26
26
|
export * from "./null.js";
|
|
27
27
|
export * from "./number.js";
|
|
28
28
|
export * from "./object.js";
|
|
29
|
+
export * from "./query.js";
|
|
29
30
|
export * from "./random.js";
|
|
30
31
|
export * from "./regexp.js";
|
|
31
32
|
export * from "./sequence.js";
|
|
@@ -39,5 +40,6 @@ export * from "./timeout.js";
|
|
|
39
40
|
export * from "./transform.js";
|
|
40
41
|
export * from "./undefined.js";
|
|
41
42
|
export * from "./units.js";
|
|
43
|
+
export * from "./update.js";
|
|
42
44
|
export * from "./url.js";
|
|
43
45
|
export * from "./validate.js";
|
package/util/iterate.d.ts
CHANGED
|
@@ -35,6 +35,8 @@ export declare function omitItems<T>(items: Iterable<T>, ...omit: T[]): Iterable
|
|
|
35
35
|
/** Reduce an iterable set of items using a reducer function. */
|
|
36
36
|
export declare function reduceItems<T>(items: Iterable<T>, reducer: (previous: T, item: T) => T, initial: T): T;
|
|
37
37
|
export declare function reduceItems<T>(items: Iterable<T>, reducer: (previous: T | undefined, item: T) => T, initial?: T): T | undefined;
|
|
38
|
+
export declare function reduceItems<I, O>(items: Iterable<I>, reducer: (previous: O, item: I) => O, initial: O): O;
|
|
39
|
+
export declare function reduceItems<I, O>(items: Iterable<I>, reducer: (previous: O | undefined, item: I) => O, initial?: O): O | undefined;
|
|
38
40
|
/** Yield chunks of a given size. */
|
|
39
41
|
export declare function getChunks<T>(items: Iterable<T>, size: 1): Iterable<readonly [T]>;
|
|
40
42
|
export declare function getChunks<T>(items: Iterable<T>, size: 2): Iterable<readonly [T, T]>;
|
package/util/match.d.ts
CHANGED
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
import type { ImmutableArray } from "./array.js";
|
|
2
2
|
import type { Arguments } from "./function.js";
|
|
3
|
-
/** Object that can match an item against a target with its `match()` function. */
|
|
4
|
-
export interface Matchable<A extends Arguments = unknown[]> {
|
|
5
|
-
match(...args: A): boolean;
|
|
6
|
-
}
|
|
7
3
|
/** Function that can match an item against a target. */
|
|
8
4
|
export type Match<A extends Arguments = unknown[]> = (...args: A) => boolean;
|
|
9
|
-
/** Match is either a `Matcherable` object, or matcher function. */
|
|
10
|
-
export type Matcher<A extends Arguments = unknown[]> = Matchable<A> | Match<A>;
|
|
11
|
-
/** Match two values using a `Matcher`. */
|
|
12
|
-
export declare function match<A extends Arguments>(matcher: Matcher<A>, ...args: A): boolean;
|
|
13
5
|
/** Filter an iterable set of items using a matcher. */
|
|
14
|
-
export declare function filterItems<T, A extends Arguments = []>(items: Iterable<T>,
|
|
6
|
+
export declare function filterItems<T, A extends Arguments = []>(items: Iterable<T>, match: Match<[T, ...A]>, ...args: A): Iterable<T>;
|
|
15
7
|
/** Filter an array (immutably) using a matcher. */
|
|
16
|
-
export declare function filterArray<T, A extends Arguments = []>(input: ImmutableArray<T>,
|
|
8
|
+
export declare function filterArray<T, A extends Arguments = []>(input: ImmutableArray<T>, match: Match<[T, ...A]>, ...args: A): ImmutableArray<T>;
|
package/util/match.js
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
/** Match two values using a `Matcher`. */
|
|
2
|
-
export function match(matcher, ...args) {
|
|
3
|
-
return typeof matcher === "function" ? matcher(...args) : matcher.match(...args);
|
|
4
|
-
}
|
|
5
1
|
/** Filter an iterable set of items using a matcher. */
|
|
6
|
-
export function* filterItems(items,
|
|
2
|
+
export function* filterItems(items, match, ...args) {
|
|
7
3
|
for (const item of items)
|
|
8
|
-
if (match(
|
|
4
|
+
if (match(item, ...args))
|
|
9
5
|
yield item;
|
|
10
6
|
}
|
|
11
7
|
/** Filter an array (immutably) using a matcher. */
|
|
12
|
-
export function filterArray(input,
|
|
8
|
+
export function filterArray(input, match, ...args) {
|
|
13
9
|
if (!input.length)
|
|
14
10
|
return input;
|
|
15
|
-
const output = Array.from(filterItems(input,
|
|
11
|
+
const output = Array.from(filterItems(input, match, ...args));
|
|
16
12
|
return output.length === input.length ? input : output;
|
|
17
13
|
}
|