shelving 1.63.0 → 1.65.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.js +2 -2
- package/db/Database.d.ts +2 -1
- package/db/Reference.d.ts +46 -39
- package/db/Reference.js +70 -73
- package/db/index.d.ts +0 -3
- package/db/index.js +0 -3
- package/error/ThroughError.d.ts +8 -0
- package/error/ThroughError.js +13 -0
- package/firestore/client/FirestoreClientProvider.d.ts +11 -11
- package/firestore/client/FirestoreClientProvider.js +21 -15
- package/firestore/lite/FirestoreLiteProvider.d.ts +10 -11
- package/firestore/lite/FirestoreLiteProvider.js +21 -16
- package/firestore/server/FirestoreServerProvider.d.ts +11 -11
- package/firestore/server/FirestoreServerProvider.js +23 -17
- package/index.d.ts +2 -1
- package/index.js +2 -1
- package/markup/rules.js +4 -4
- package/observe/AbstractObserver.d.ts +15 -0
- package/observe/AbstractObserver.js +42 -0
- package/observe/AsyncObserver.d.ts +5 -0
- package/observe/AsyncObserver.js +8 -0
- package/{stream/LastStream.d.ts → observe/LastSubject.d.ts} +2 -2
- package/observe/LastSubject.js +12 -0
- package/observe/MatchObserver.d.ts +9 -0
- package/observe/MatchObserver.js +12 -0
- package/observe/MatchableObserver.d.ts +7 -0
- package/observe/MatchableObserver.js +10 -0
- package/observe/Observable.d.ts +20 -0
- package/observe/Observable.js +7 -0
- package/observe/Observer.d.ts +31 -0
- package/observe/Observer.js +48 -0
- package/observe/OnceObserver.d.ts +5 -0
- package/observe/OnceObserver.js +8 -0
- package/observe/Subject.d.ts +46 -0
- package/observe/Subject.js +110 -0
- package/observe/ThroughObserver.d.ts +5 -0
- package/observe/ThroughObserver.js +8 -0
- package/observe/TransformObserver.d.ts +9 -0
- package/observe/TransformObserver.js +12 -0
- package/observe/TransformableObserver.d.ts +7 -0
- package/observe/TransformableObserver.js +8 -0
- package/observe/index.d.ts +13 -0
- package/observe/index.js +13 -0
- package/observe/util.d.ts +24 -0
- package/observe/util.js +34 -0
- package/package.json +3 -3
- package/provider/BatchProvider.d.ts +8 -8
- package/provider/BatchProvider.js +26 -31
- package/provider/CacheProvider.d.ts +12 -24
- package/provider/CacheProvider.js +40 -67
- package/provider/DebugProvider.d.ts +20 -0
- package/provider/DebugProvider.js +170 -0
- package/provider/MemoryProvider.d.ts +43 -14
- package/provider/MemoryProvider.js +148 -115
- package/provider/Provider.d.ts +23 -23
- package/provider/ThroughProvider.d.ts +20 -12
- package/provider/ThroughProvider.js +12 -12
- package/provider/ValidationProvider.d.ts +10 -10
- package/provider/ValidationProvider.js +69 -14
- package/provider/index.d.ts +1 -1
- package/provider/index.js +1 -1
- package/query/Filter.d.ts +8 -16
- package/query/Filter.js +8 -7
- package/query/Filters.d.ts +6 -11
- package/query/Filters.js +5 -5
- package/query/Query.d.ts +10 -13
- package/query/Query.js +10 -10
- package/query/Rule.d.ts +2 -3
- package/query/Sort.d.ts +7 -8
- package/query/Sort.js +5 -5
- package/query/Sorts.d.ts +3 -4
- package/query/Sorts.js +2 -2
- package/query/index.d.ts +0 -1
- package/query/index.js +0 -1
- package/react/index.d.ts +0 -6
- package/react/index.js +3 -6
- package/react/useDocument.d.ts +32 -39
- package/react/useDocument.js +71 -75
- package/react/useInstance.d.ts +4 -7
- package/react/useInstance.js +6 -9
- package/react/useLazy.d.ts +5 -9
- package/react/useQuery.d.ts +48 -46
- package/react/useQuery.js +116 -87
- package/react/useReduce.d.ts +8 -1
- package/react/useReduce.js +1 -3
- package/react/useSubscribe.d.ts +5 -6
- package/react/useSubscribe.js +10 -11
- package/schema/AllowSchema.d.ts +3 -4
- package/schema/AllowSchema.js +1 -1
- package/schema/MapSchema.js +2 -2
- package/schema/ObjectSchema.js +2 -2
- package/{stream → state}/ArrayState.d.ts +1 -1
- package/{stream → state}/ArrayState.js +8 -10
- package/{stream → state}/BooleanState.d.ts +1 -1
- package/{stream → state}/BooleanState.js +3 -5
- package/{stream → state}/DataState.d.ts +3 -3
- package/{stream → state}/DataState.js +6 -6
- package/{stream → state}/ObjectState.d.ts +1 -1
- package/{stream → state}/ObjectState.js +6 -8
- package/state/SelfClosingState.d.ts +18 -0
- package/state/SelfClosingState.js +34 -0
- package/state/State.d.ts +32 -0
- package/state/State.js +69 -0
- package/{stream → state}/index.d.ts +1 -4
- package/{stream → state}/index.js +1 -4
- package/test/basics.d.ts +12 -15
- package/test/basics.js +10 -20
- package/test/people.d.ts +9 -14
- package/test/people.js +6 -12
- package/test/util.d.ts +3 -3
- package/test/util.js +7 -7
- package/update/ArrayUpdate.d.ts +2 -1
- package/update/ArrayUpdate.js +4 -4
- package/update/DataUpdate.d.ts +2 -1
- package/update/DataUpdate.js +3 -2
- package/update/ObjectUpdate.d.ts +2 -1
- package/update/ObjectUpdate.js +14 -5
- package/update/Update.d.ts +2 -2
- package/update/util.d.ts +1 -4
- package/update/util.js +3 -3
- package/util/async.d.ts +4 -5
- package/util/async.js +3 -2
- package/util/clone.js +3 -3
- package/util/data.d.ts +42 -44
- package/util/data.js +32 -33
- package/util/entry.d.ts +15 -28
- package/util/entry.js +19 -13
- package/util/equal.d.ts +4 -5
- package/util/filter.d.ts +5 -46
- package/util/filter.js +5 -47
- package/util/function.d.ts +5 -5
- package/util/function.js +3 -3
- package/util/hydrate.d.ts +1 -1
- package/util/hydrate.js +7 -7
- package/util/index.d.ts +1 -1
- package/util/index.js +1 -1
- package/util/iterate.d.ts +15 -19
- package/util/iterate.js +7 -17
- package/util/match.d.ts +20 -0
- package/util/match.js +14 -0
- package/util/random.js +2 -3
- package/util/search.d.ts +1 -1
- package/util/sort.d.ts +4 -30
- package/util/sort.js +0 -38
- package/util/string.d.ts +1 -1
- package/util/string.js +2 -7
- package/util/template.js +2 -2
- package/util/timeout.d.ts +2 -0
- package/util/timeout.js +8 -1
- package/util/transform.d.ts +39 -44
- package/util/transform.js +21 -34
- package/util/validate.d.ts +26 -20
- package/util/validate.js +20 -22
- package/api/errors.d.ts +0 -8
- package/api/errors.js +0 -9
- package/db/PaginationState.d.ts +0 -31
- package/db/PaginationState.js +0 -67
- package/db/errors.d.ts +0 -25
- package/db/errors.js +0 -34
- package/db/util.d.ts +0 -37
- package/db/util.js +0 -54
- package/provider/ErrorProvider.d.ts +0 -32
- package/provider/ErrorProvider.js +0 -175
- package/query/util.d.ts +0 -8
- package/query/util.js +0 -8
- package/react/useCompare.d.ts +0 -3
- package/react/useCompare.js +0 -8
- package/react/useFetch.d.ts +0 -17
- package/react/useFetch.js +0 -41
- package/react/usePagination.d.ts +0 -8
- package/react/usePagination.js +0 -22
- package/react/usePureEffect.d.ts +0 -10
- package/react/usePureEffect.js +0 -17
- package/react/usePureState.d.ts +0 -11
- package/react/usePureState.js +0 -16
- package/react/useState.d.ts +0 -39
- package/react/useState.js +0 -65
- package/stream/LastStream.js +0 -12
- package/stream/LazyState.d.ts +0 -11
- package/stream/LazyState.js +0 -28
- package/stream/LazyStream.d.ts +0 -12
- package/stream/LazyStream.js +0 -28
- package/stream/State.d.ts +0 -46
- package/stream/State.js +0 -66
- package/stream/Stream.d.ts +0 -66
- package/stream/Stream.js +0 -122
- package/util/observe.d.ts +0 -111
- package/util/observe.js +0 -159
package/api/Resource.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { validate } from "../util/validate.js";
|
|
2
2
|
import { getUndefined } from "../util/undefined.js";
|
|
3
3
|
import { Feedback } from "../feedback/Feedback.js";
|
|
4
|
-
import {
|
|
4
|
+
import { ValidationError } from "../error/ValidationError.js";
|
|
5
5
|
/**
|
|
6
6
|
* An abstract API resource definition, used to specify types for e.g. serverless functions..
|
|
7
7
|
*
|
|
@@ -34,7 +34,7 @@ export class Resource {
|
|
|
34
34
|
return validate(unsafeResult, this.result);
|
|
35
35
|
}
|
|
36
36
|
catch (thrown) {
|
|
37
|
-
throw thrown instanceof Feedback ? new
|
|
37
|
+
throw thrown instanceof Feedback ? new ValidationError(`Invalid result for resource`, thrown) : thrown;
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
}
|
package/db/Database.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { Key, Datas } from "../util/data.js";
|
|
|
3
3
|
import type { Provider } from "../provider/Provider.js";
|
|
4
4
|
import type { SortKeys } from "../query/Sort.js";
|
|
5
5
|
import type { FilterProps } from "../query/Filter.js";
|
|
6
|
+
import { Entity } from "../util/data.js";
|
|
6
7
|
import { DocumentReference, QueryReference } from "./Reference.js";
|
|
7
8
|
/**
|
|
8
9
|
* Combines a database model and a provider.
|
|
@@ -16,7 +17,7 @@ export declare class Database<V extends Validators<Datas> = Validators<Datas>> {
|
|
|
16
17
|
readonly provider: Provider;
|
|
17
18
|
constructor(validators: V, provider: Provider);
|
|
18
19
|
/** Create a query on a collection in this model. */
|
|
19
|
-
query<K extends Key<V>>(collection: K, filters?: FilterProps<ValidatorType<V[K]
|
|
20
|
+
query<K extends Key<V>>(collection: K, filters?: FilterProps<Entity<ValidatorType<V[K]>>>, sorts?: SortKeys<Entity<ValidatorType<V[K]>>>, limit?: number | null): QueryReference<ValidatorType<V[K]>>;
|
|
20
21
|
/** Reference a document in a collection in this model. */
|
|
21
22
|
doc<K extends Key<V>>(collection: K, id: string): DocumentReference<ValidatorType<V[K]>>;
|
|
22
23
|
/**
|
package/db/Reference.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import type { Data,
|
|
2
|
-
import type {
|
|
1
|
+
import type { Data, OptionalData, Entity, OptionalEntity, Entities } from "../util/data.js";
|
|
2
|
+
import type { Dispatch } from "../util/function.js";
|
|
3
3
|
import type { SortKeys } from "../query/Sort.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { ImmutableArray } from "../util/array.js";
|
|
5
|
+
import type { PartialObserver } from "../observe/Observer.js";
|
|
6
|
+
import type { Validator } from "../util/validate.js";
|
|
6
7
|
import { Query } from "../query/Query.js";
|
|
7
|
-
import { Entries, Entry } from "../util/entry.js";
|
|
8
8
|
import { Filters } from "../query/Filters.js";
|
|
9
9
|
import { Sorts } from "../query/Sorts.js";
|
|
10
10
|
import { DataUpdate, PropUpdates } from "../update/DataUpdate.js";
|
|
11
11
|
import { FilterProps } from "../query/Filter.js";
|
|
12
|
-
import {
|
|
12
|
+
import { Observable, Unsubscribe } from "../observe/Observable.js";
|
|
13
13
|
import type { Database } from "./Database.js";
|
|
14
14
|
/** A refence to a location in a database. */
|
|
15
15
|
export interface Reference {
|
|
@@ -17,11 +17,11 @@ export interface Reference {
|
|
|
17
17
|
toString(): string;
|
|
18
18
|
}
|
|
19
19
|
/** A query reference within a specific database. */
|
|
20
|
-
export declare class QueryReference<T extends Data = Data> extends Query<T
|
|
20
|
+
export declare class QueryReference<T extends Data = Data> extends Query<Entity<T>> implements Observable<ImmutableArray<Entity<T>>>, Reference {
|
|
21
21
|
readonly db: Database;
|
|
22
22
|
readonly validator: Validator<T>;
|
|
23
23
|
readonly collection: string;
|
|
24
|
-
constructor(db: Database, validator: Validator<T>, collection: string, filters?: Filters<T
|
|
24
|
+
constructor(db: Database, validator: Validator<T>, collection: string, filters?: Filters<Entity<T>>, sorts?: Sorts<Entity<T>>, limit?: number | null);
|
|
25
25
|
/** Reference a document in this query's collection. */
|
|
26
26
|
doc(id: string): DocumentReference<T>;
|
|
27
27
|
/**
|
|
@@ -33,15 +33,10 @@ export declare class QueryReference<T extends Data = Data> extends Query<T> impl
|
|
|
33
33
|
*/
|
|
34
34
|
add(data: T): string | PromiseLike<string>;
|
|
35
35
|
/**
|
|
36
|
-
* Get
|
|
37
|
-
* @return
|
|
36
|
+
* Get array of entities for this query.
|
|
37
|
+
* @return Array of entities.
|
|
38
38
|
*/
|
|
39
|
-
get
|
|
40
|
-
/**
|
|
41
|
-
* Get an iterable that yields the results of this entry.
|
|
42
|
-
* @return Map containing the results.
|
|
43
|
-
*/
|
|
44
|
-
get results(): Results<T> | PromiseLike<Results<T>>;
|
|
39
|
+
get value(): Entities<T> | PromiseLike<Entities<T>>;
|
|
45
40
|
/**
|
|
46
41
|
* Count the number of results of this set of documents.
|
|
47
42
|
* @return Number of documents matching the query (possibly promised).
|
|
@@ -53,19 +48,25 @@ export declare class QueryReference<T extends Data = Data> extends Query<T> impl
|
|
|
53
48
|
*/
|
|
54
49
|
get exists(): boolean | PromiseLike<boolean>;
|
|
55
50
|
/**
|
|
56
|
-
* Get
|
|
57
|
-
*
|
|
58
|
-
* @return Entry in `[id, data]` format for the first document.
|
|
51
|
+
* Get the first document matched by this query or `null` if this query has no results.
|
|
59
52
|
* @throws RequiredError if there were no results for this query.
|
|
60
53
|
*/
|
|
61
|
-
get
|
|
54
|
+
get firstValue(): OptionalEntity<T> | PromiseLike<OptionalEntity<T>>;
|
|
62
55
|
/**
|
|
63
|
-
* Get
|
|
64
|
-
*
|
|
65
|
-
|
|
56
|
+
* Get the first document matched by this query.
|
|
57
|
+
* @throws RequiredError if there were no results for this query.
|
|
58
|
+
*/
|
|
59
|
+
get firstData(): Entity<T> | PromiseLike<Entity<T>>;
|
|
60
|
+
/**
|
|
61
|
+
* Get the last document matched by this query or `null` if this query has no results.
|
|
62
|
+
* @throws RequiredError if there were no results for this query.
|
|
63
|
+
*/
|
|
64
|
+
get lastValue(): OptionalEntity<T> | PromiseLike<OptionalEntity<T>>;
|
|
65
|
+
/**
|
|
66
|
+
* Get the last document matched by this query.
|
|
66
67
|
* @throws RequiredError if there were no results for this query.
|
|
67
68
|
*/
|
|
68
|
-
get
|
|
69
|
+
get lastData(): Entity<T> | PromiseLike<Entity<T>>;
|
|
69
70
|
/**
|
|
70
71
|
* Subscribe to all matching documents.
|
|
71
72
|
* - `next()` is called once with the initial results, and again any time the results change.
|
|
@@ -73,7 +74,7 @@ export declare class QueryReference<T extends Data = Data> extends Query<T> impl
|
|
|
73
74
|
* @param next Observer with `next`, `error`, or `complete` methods or a `next()` dispatcher.
|
|
74
75
|
* @return Function that ends the subscription.
|
|
75
76
|
*/
|
|
76
|
-
subscribe(next:
|
|
77
|
+
subscribe(next: PartialObserver<ImmutableArray<Entity<T>>> | Dispatch<[ImmutableArray<Entity<T>>]>): Unsubscribe;
|
|
77
78
|
/**
|
|
78
79
|
* Set all matching documents to the same exact value.
|
|
79
80
|
*
|
|
@@ -93,21 +94,17 @@ export declare class QueryReference<T extends Data = Data> extends Query<T> impl
|
|
|
93
94
|
* @return Nothing (possibly promised).
|
|
94
95
|
*/
|
|
95
96
|
delete(): number | PromiseLike<number>;
|
|
96
|
-
/** Iterate over the resuls (will throw `Promise` if the results are asynchronous). */
|
|
97
|
-
[Symbol.iterator](): Iterator<Entry<T>, void>;
|
|
98
|
-
/** Validate a set of results for this query reference. */
|
|
99
|
-
validate(unsafeEntries: Entries): Entries<T>;
|
|
100
97
|
toString(): string;
|
|
101
98
|
}
|
|
102
99
|
/** A document reference within a specific database. */
|
|
103
|
-
export declare class DocumentReference<T extends Data = Data> implements Observable<
|
|
100
|
+
export declare class DocumentReference<T extends Data = Data> implements Observable<OptionalData<T>>, Reference {
|
|
104
101
|
readonly db: Database;
|
|
105
102
|
readonly validator: Validator<T>;
|
|
106
103
|
readonly collection: string;
|
|
107
104
|
readonly id: string;
|
|
108
105
|
constructor(db: Database, validator: Validator<T>, collection: string, id: string);
|
|
109
106
|
/** Create a query on this document's collection. */
|
|
110
|
-
query(filters?: FilterProps<T
|
|
107
|
+
query(filters?: FilterProps<Entity<T>>, sorts?: SortKeys<Entity<T>>, limit?: number | null): QueryReference<T>;
|
|
111
108
|
/** Get an 'optional' reference to this document (uses a `ModelQuery` with an `id` filter). */
|
|
112
109
|
get optional(): QueryReference<T>;
|
|
113
110
|
/**
|
|
@@ -116,18 +113,18 @@ export declare class DocumentReference<T extends Data = Data> implements Observa
|
|
|
116
113
|
*/
|
|
117
114
|
get exists(): boolean | PromiseLike<boolean>;
|
|
118
115
|
/**
|
|
119
|
-
* Get the
|
|
120
|
-
* @return Document's data, or `
|
|
116
|
+
* Get the optional data of this document.
|
|
117
|
+
* @return Document's data, or `null` if the document doesn't exist (possibly promised).
|
|
121
118
|
*/
|
|
122
|
-
get
|
|
119
|
+
get value(): OptionalEntity<T> | PromiseLike<OptionalEntity<T>>;
|
|
123
120
|
/**
|
|
124
121
|
* Get the data of this document.
|
|
125
122
|
* - Useful for destructuring, e.g. `{ name, title } = await documentThatMustExist.asyncData`
|
|
126
123
|
*
|
|
127
124
|
* @return Document's data (possibly promised).
|
|
128
|
-
* @throws RequiredError if the document
|
|
125
|
+
* @throws RequiredError if the document does not exist.
|
|
129
126
|
*/
|
|
130
|
-
get data():
|
|
127
|
+
get data(): Entity<T> | PromiseLike<Entity<T>>;
|
|
131
128
|
/**
|
|
132
129
|
* Subscribe to the result of this document (indefinitely).
|
|
133
130
|
* - `next()` is called once with the initial result, and again any time the result changes.
|
|
@@ -135,14 +132,24 @@ export declare class DocumentReference<T extends Data = Data> implements Observa
|
|
|
135
132
|
* @param next Observer with `next`, `error`, or `complete` methods or a `next()` dispatcher.
|
|
136
133
|
* @return Function that ends the subscription.
|
|
137
134
|
*/
|
|
138
|
-
subscribe(next:
|
|
135
|
+
subscribe(next: PartialObserver<OptionalEntity<T>> | Dispatch<[OptionalEntity<T>]>): Unsubscribe;
|
|
139
136
|
/** Set the complete data of this document. */
|
|
140
137
|
set(data: T): void | PromiseLike<void>;
|
|
141
138
|
/** Update this document. */
|
|
142
139
|
update(updates: DataUpdate<T> | PropUpdates<T>): void | PromiseLike<void>;
|
|
143
140
|
/** Delete this document. */
|
|
144
141
|
delete(): void | PromiseLike<void>;
|
|
145
|
-
/** Validate data for this query reference. */
|
|
146
|
-
validate(unsafeData: Data): T;
|
|
147
142
|
toString(): string;
|
|
148
143
|
}
|
|
144
|
+
/** Get the data for a document from a result for that document. */
|
|
145
|
+
export declare function getDocumentData<T extends Data>(entity: OptionalEntity<T>, ref: DocumentReference<T>): Entity<T>;
|
|
146
|
+
/** Get the data for a document from a set of queried entities. */
|
|
147
|
+
export declare function getQueryFirstData<T extends Data>(entities: Entities<T>, ref: QueryReference<T>): Entity<T>;
|
|
148
|
+
/** Get the data for a document from a set of queried entities. */
|
|
149
|
+
export declare function getQueryLastData<T extends Data>(entities: Entities<T>, ref: QueryReference<T>): Entity<T>;
|
|
150
|
+
/** Get the optional data for a document from a set of queried entities. */
|
|
151
|
+
export declare function getQueryFirstValue<T extends Data>(entities: Entities<T>): OptionalEntity<T>;
|
|
152
|
+
/** Get the optional data for a document from a set of queried entities. */
|
|
153
|
+
export declare function getQueryLastValue<T extends Data>(entities: Entities<T>): OptionalEntity<T>;
|
|
154
|
+
/** Are two database references equal? */
|
|
155
|
+
export declare const isSameReference: (left: Reference, right: Reference) => boolean;
|
package/db/Reference.js
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { validate } from "../util/validate.js";
|
|
1
|
+
import { getFirstItem, getLastItem } from "../util/array.js";
|
|
3
2
|
import { Query } from "../query/Query.js";
|
|
4
3
|
import { Filters } from "../query/Filters.js";
|
|
5
4
|
import { Sorts } from "../query/Sorts.js";
|
|
6
|
-
import { callAsync
|
|
7
|
-
import { getMap } from "../util/map.js";
|
|
5
|
+
import { callAsync } from "../util/async.js";
|
|
8
6
|
import { countItems, hasItems } from "../util/iterate.js";
|
|
9
7
|
import { DataUpdate } from "../update/DataUpdate.js";
|
|
10
|
-
import { Feedback } from "../feedback/Feedback.js";
|
|
11
|
-
import { InvalidFeedback } from "../feedback/InvalidFeedback.js";
|
|
12
8
|
import { Filter } from "../query/Filter.js";
|
|
13
|
-
import {
|
|
14
|
-
import { DocumentResultObserver, getDocumentData, getDocumentResult, getQueryData, getQueryResult } from "./util.js";
|
|
9
|
+
import { RequiredError } from "../error/RequiredError.js";
|
|
15
10
|
/** A query reference within a specific database. */
|
|
16
11
|
export class QueryReference extends Query {
|
|
17
12
|
constructor(db, validator, collection, filters, sorts, limit) {
|
|
@@ -32,28 +27,21 @@ export class QueryReference extends Query {
|
|
|
32
27
|
* @return String ID for the created document (possibly promised).
|
|
33
28
|
*/
|
|
34
29
|
add(data) {
|
|
35
|
-
return this.db.provider.
|
|
30
|
+
return this.db.provider.addDocument(this, data);
|
|
36
31
|
}
|
|
37
32
|
/**
|
|
38
|
-
* Get
|
|
39
|
-
* @return
|
|
33
|
+
* Get array of entities for this query.
|
|
34
|
+
* @return Array of entities.
|
|
40
35
|
*/
|
|
41
|
-
get
|
|
36
|
+
get value() {
|
|
42
37
|
return this.db.provider.getQuery(this);
|
|
43
38
|
}
|
|
44
|
-
/**
|
|
45
|
-
* Get an iterable that yields the results of this entry.
|
|
46
|
-
* @return Map containing the results.
|
|
47
|
-
*/
|
|
48
|
-
get results() {
|
|
49
|
-
return callAsync(getMap, this.db.provider.getQuery(this));
|
|
50
|
-
}
|
|
51
39
|
/**
|
|
52
40
|
* Count the number of results of this set of documents.
|
|
53
41
|
* @return Number of documents matching the query (possibly promised).
|
|
54
42
|
*/
|
|
55
43
|
get count() {
|
|
56
|
-
return callAsync(countItems, this.
|
|
44
|
+
return callAsync(countItems, this.value);
|
|
57
45
|
}
|
|
58
46
|
/**
|
|
59
47
|
* Does at least one document exist for this query?
|
|
@@ -63,22 +51,32 @@ export class QueryReference extends Query {
|
|
|
63
51
|
return callAsync(hasItems, this.db.provider.getQuery(this.max(1)));
|
|
64
52
|
}
|
|
65
53
|
/**
|
|
66
|
-
* Get
|
|
67
|
-
*
|
|
68
|
-
* @return Entry in `[id, data]` format for the first document.
|
|
54
|
+
* Get the first document matched by this query or `null` if this query has no results.
|
|
69
55
|
* @throws RequiredError if there were no results for this query.
|
|
70
56
|
*/
|
|
71
|
-
get
|
|
72
|
-
return callAsync(
|
|
57
|
+
get firstValue() {
|
|
58
|
+
return callAsync(getQueryFirstValue, this.db.provider.getQuery(this.max(1)));
|
|
73
59
|
}
|
|
74
60
|
/**
|
|
75
|
-
* Get
|
|
76
|
-
*
|
|
77
|
-
* @return Entry in `[id, data]` format for the first document.
|
|
61
|
+
* Get the first document matched by this query.
|
|
78
62
|
* @throws RequiredError if there were no results for this query.
|
|
79
63
|
*/
|
|
80
|
-
get
|
|
81
|
-
return callAsync(
|
|
64
|
+
get firstData() {
|
|
65
|
+
return callAsync(getQueryFirstData, this.db.provider.getQuery(this.max(1)), this);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get the last document matched by this query or `null` if this query has no results.
|
|
69
|
+
* @throws RequiredError if there were no results for this query.
|
|
70
|
+
*/
|
|
71
|
+
get lastValue() {
|
|
72
|
+
return callAsync(getQueryLastValue, this.db.provider.getQuery(this.max(1)));
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get the last document matched by this query.
|
|
76
|
+
* @throws RequiredError if there were no results for this query.
|
|
77
|
+
*/
|
|
78
|
+
get lastData() {
|
|
79
|
+
return callAsync(getQueryLastData, this.db.provider.getQuery(this.max(1)), this);
|
|
82
80
|
}
|
|
83
81
|
/**
|
|
84
82
|
* Subscribe to all matching documents.
|
|
@@ -88,7 +86,7 @@ export class QueryReference extends Query {
|
|
|
88
86
|
* @return Function that ends the subscription.
|
|
89
87
|
*/
|
|
90
88
|
subscribe(next) {
|
|
91
|
-
return this.db.provider.subscribeQuery(this,
|
|
89
|
+
return this.db.provider.subscribeQuery(this, typeof next === "function" ? { next } : next);
|
|
92
90
|
}
|
|
93
91
|
/**
|
|
94
92
|
* Set all matching documents to the same exact value.
|
|
@@ -115,28 +113,6 @@ export class QueryReference extends Query {
|
|
|
115
113
|
delete() {
|
|
116
114
|
return this.db.provider.deleteQuery(this);
|
|
117
115
|
}
|
|
118
|
-
/** Iterate over the resuls (will throw `Promise` if the results are asynchronous). */
|
|
119
|
-
[Symbol.iterator]() {
|
|
120
|
-
return throwAsync(this.entries)[Symbol.iterator]();
|
|
121
|
-
}
|
|
122
|
-
/** Validate a set of results for this query reference. */
|
|
123
|
-
*validate(unsafeEntries) {
|
|
124
|
-
let invalid = false;
|
|
125
|
-
const details = {};
|
|
126
|
-
for (const [id, unsafeValue] of unsafeEntries) {
|
|
127
|
-
try {
|
|
128
|
-
yield [id, validate(unsafeValue, this.validator)];
|
|
129
|
-
}
|
|
130
|
-
catch (thrown) {
|
|
131
|
-
if (!(thrown instanceof Feedback))
|
|
132
|
-
throw thrown;
|
|
133
|
-
invalid = true;
|
|
134
|
-
details[id] = thrown;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
if (invalid)
|
|
138
|
-
throw new QueryValidationError(this, new InvalidFeedback("Invalid results", details));
|
|
139
|
-
}
|
|
140
116
|
// Override to include the collection name.
|
|
141
117
|
toString() {
|
|
142
118
|
return `${this.collection}?${super.toString()}`;
|
|
@@ -163,24 +139,24 @@ export class DocumentReference {
|
|
|
163
139
|
* @return `true` if a document exists or `false` otherwise (possibly promised).
|
|
164
140
|
*/
|
|
165
141
|
get exists() {
|
|
166
|
-
return callAsync(Boolean, this.db.provider.
|
|
142
|
+
return callAsync(Boolean, this.db.provider.getDocument(this));
|
|
167
143
|
}
|
|
168
144
|
/**
|
|
169
|
-
* Get the
|
|
170
|
-
* @return Document's data, or `
|
|
145
|
+
* Get the optional data of this document.
|
|
146
|
+
* @return Document's data, or `null` if the document doesn't exist (possibly promised).
|
|
171
147
|
*/
|
|
172
|
-
get
|
|
173
|
-
return
|
|
148
|
+
get value() {
|
|
149
|
+
return this.db.provider.getDocument(this);
|
|
174
150
|
}
|
|
175
151
|
/**
|
|
176
152
|
* Get the data of this document.
|
|
177
153
|
* - Useful for destructuring, e.g. `{ name, title } = await documentThatMustExist.asyncData`
|
|
178
154
|
*
|
|
179
155
|
* @return Document's data (possibly promised).
|
|
180
|
-
* @throws RequiredError if the document
|
|
156
|
+
* @throws RequiredError if the document does not exist.
|
|
181
157
|
*/
|
|
182
158
|
get data() {
|
|
183
|
-
return callAsync(getDocumentData, this.db.provider.
|
|
159
|
+
return callAsync(getDocumentData, this.db.provider.getDocument(this), this);
|
|
184
160
|
}
|
|
185
161
|
/**
|
|
186
162
|
* Subscribe to the result of this document (indefinitely).
|
|
@@ -190,31 +166,52 @@ export class DocumentReference {
|
|
|
190
166
|
* @return Function that ends the subscription.
|
|
191
167
|
*/
|
|
192
168
|
subscribe(next) {
|
|
193
|
-
return this.db.provider.
|
|
169
|
+
return this.db.provider.subscribeDocument(this, typeof next === "function" ? { next } : next);
|
|
194
170
|
}
|
|
195
171
|
/** Set the complete data of this document. */
|
|
196
172
|
set(data) {
|
|
197
|
-
return this.db.provider.
|
|
173
|
+
return this.db.provider.setDocument(this, data);
|
|
198
174
|
}
|
|
199
175
|
/** Update this document. */
|
|
200
176
|
update(updates) {
|
|
201
|
-
return this.db.provider.
|
|
177
|
+
return this.db.provider.updateDocument(this, updates instanceof DataUpdate ? updates : new DataUpdate(updates));
|
|
202
178
|
}
|
|
203
179
|
/** Delete this document. */
|
|
204
180
|
delete() {
|
|
205
|
-
return this.db.provider.
|
|
206
|
-
}
|
|
207
|
-
/** Validate data for this query reference. */
|
|
208
|
-
validate(unsafeData) {
|
|
209
|
-
try {
|
|
210
|
-
return validate(unsafeData, this.validator);
|
|
211
|
-
}
|
|
212
|
-
catch (thrown) {
|
|
213
|
-
throw thrown instanceof Feedback ? new DocumentValidationError(this, thrown) : thrown;
|
|
214
|
-
}
|
|
181
|
+
return this.db.provider.deleteDocument(this);
|
|
215
182
|
}
|
|
216
183
|
// Implement toString()
|
|
217
184
|
toString() {
|
|
218
185
|
return `${this.collection}/${this.id}`;
|
|
219
186
|
}
|
|
220
187
|
}
|
|
188
|
+
/** Get the data for a document from a result for that document. */
|
|
189
|
+
export function getDocumentData(entity, ref) {
|
|
190
|
+
if (entity)
|
|
191
|
+
return entity;
|
|
192
|
+
throw new RequiredError(`Document "${ref}" does not exist`);
|
|
193
|
+
}
|
|
194
|
+
/** Get the data for a document from a set of queried entities. */
|
|
195
|
+
export function getQueryFirstData(entities, ref) {
|
|
196
|
+
const entity = getQueryFirstValue(entities);
|
|
197
|
+
if (entity)
|
|
198
|
+
return entity;
|
|
199
|
+
throw new RequiredError(`Query "${ref}" has no documents`);
|
|
200
|
+
}
|
|
201
|
+
/** Get the data for a document from a set of queried entities. */
|
|
202
|
+
export function getQueryLastData(entities, ref) {
|
|
203
|
+
const entity = getQueryLastValue(entities);
|
|
204
|
+
if (entity)
|
|
205
|
+
return entity;
|
|
206
|
+
throw new RequiredError(`Query "${ref}" has no documents`);
|
|
207
|
+
}
|
|
208
|
+
/** Get the optional data for a document from a set of queried entities. */
|
|
209
|
+
export function getQueryFirstValue(entities) {
|
|
210
|
+
return getFirstItem(entities) || null;
|
|
211
|
+
}
|
|
212
|
+
/** Get the optional data for a document from a set of queried entities. */
|
|
213
|
+
export function getQueryLastValue(entities) {
|
|
214
|
+
return getLastItem(entities) || null;
|
|
215
|
+
}
|
|
216
|
+
/** Are two database references equal? */
|
|
217
|
+
export const isSameReference = (left, right) => left === right || left.toString() === right.toString();
|
package/db/index.d.ts
CHANGED
package/db/index.js
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { debug } from "../util/debug.js";
|
|
2
|
+
/**
|
|
3
|
+
* Thrown to wrap an error with another error.
|
|
4
|
+
* - Merges the message and stack of the previous message.
|
|
5
|
+
*/
|
|
6
|
+
export class ThroughError extends Error {
|
|
7
|
+
constructor(message, cause) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.cause = cause;
|
|
10
|
+
this.stack = `${this.stack}\nCause: ${cause instanceof Error ? cause.stack : debug(cause)}`;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
ThroughError.prototype.name = "ThroughError";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { Firestore } from "firebase/firestore";
|
|
2
2
|
import type { DocumentReference, QueryReference } from "../../db/Reference.js";
|
|
3
|
-
import type { Data,
|
|
4
|
-
import type {
|
|
3
|
+
import type { Data, Entities, OptionalEntity } from "../../util/data.js";
|
|
4
|
+
import type { Unsubscribe } from "../../observe/Observable.js";
|
|
5
5
|
import { AsynchronousProvider, Provider } from "../../provider/Provider.js";
|
|
6
6
|
import { DataUpdate } from "../../update/DataUpdate.js";
|
|
7
|
-
import { Observer
|
|
7
|
+
import { Observer } from "../../observe/Observer.js";
|
|
8
8
|
/**
|
|
9
9
|
* Firestore client database provider.
|
|
10
10
|
* - Works with the Firebase JS SDK.
|
|
@@ -14,14 +14,14 @@ import { Observer, Unsubscriber } from "../../util/observe.js";
|
|
|
14
14
|
export declare class FirestoreClientProvider extends Provider implements AsynchronousProvider {
|
|
15
15
|
readonly firestore: Firestore;
|
|
16
16
|
constructor(firestore: Firestore);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
getQuery<T extends Data>(ref: QueryReference<T>): Promise<
|
|
24
|
-
subscribeQuery<T extends Data>(ref: QueryReference<T>, observer: Observer<
|
|
17
|
+
getDocument<T extends Data>(ref: DocumentReference<T>): Promise<OptionalEntity<T>>;
|
|
18
|
+
subscribeDocument<T extends Data>(ref: DocumentReference<T>, observer: Observer<OptionalEntity<T>>): Unsubscribe;
|
|
19
|
+
addDocument<T extends Data>(ref: QueryReference<T>, data: T): Promise<string>;
|
|
20
|
+
setDocument<T extends Data>(ref: DocumentReference<T>, data: T): Promise<void>;
|
|
21
|
+
updateDocument<T extends Data>(ref: DocumentReference<T>, update: DataUpdate<T>): Promise<void>;
|
|
22
|
+
deleteDocument<T extends Data>(ref: DocumentReference<T>): Promise<void>;
|
|
23
|
+
getQuery<T extends Data>(ref: QueryReference<T>): Promise<Entities<T>>;
|
|
24
|
+
subscribeQuery<T extends Data>(ref: QueryReference<T>, observer: Observer<Entities<T>>): Unsubscribe;
|
|
25
25
|
setQuery<T extends Data>(ref: QueryReference<T>, data: T): Promise<number>;
|
|
26
26
|
updateQuery<T extends Data>(ref: QueryReference<T>, update: DataUpdate<T>): Promise<number>;
|
|
27
27
|
deleteQuery<T extends Data>(ref: QueryReference<T>): Promise<number>;
|
|
@@ -5,7 +5,7 @@ import { ArrayUpdate } from "../../update/ArrayUpdate.js";
|
|
|
5
5
|
import { DataUpdate } from "../../update/DataUpdate.js";
|
|
6
6
|
import { Increment } from "../../update/Increment.js";
|
|
7
7
|
import { ObjectUpdate } from "../../update/ObjectUpdate.js";
|
|
8
|
-
import { dispatchError, dispatchNext } from "../../
|
|
8
|
+
import { dispatchError, dispatchNext } from "../../observe/Observer.js";
|
|
9
9
|
// Constants.
|
|
10
10
|
// const ID = "__name__"; // DH: `__name__` is the entire path of the document. `__id__` is just ID.
|
|
11
11
|
const ID = "__id__"; // Internal way Firestore Queries can reference the ID of the current document.
|
|
@@ -46,10 +46,16 @@ function getQuery(firestore, ref) {
|
|
|
46
46
|
constraints.push(firestoreLimit(limit));
|
|
47
47
|
return firestoreQuery(getCollection(firestore, ref), ...constraints);
|
|
48
48
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
function getEntities(snapshot) {
|
|
50
|
+
return snapshot.docs.map(getEntity);
|
|
51
|
+
}
|
|
52
|
+
function getEntity(snapshot) {
|
|
53
|
+
const data = snapshot.data();
|
|
54
|
+
return { ...data, id: snapshot.id };
|
|
55
|
+
}
|
|
56
|
+
function getOptionalEntity(snapshot) {
|
|
57
|
+
const data = snapshot.data();
|
|
58
|
+
return data ? { ...data, id: snapshot.id } : null;
|
|
53
59
|
}
|
|
54
60
|
/** Convert `Update` instances into corresponding Firestore `FieldValue` instances. */
|
|
55
61
|
function* yieldFieldValues(updates, prefix = "") {
|
|
@@ -83,31 +89,31 @@ export class FirestoreClientProvider extends Provider {
|
|
|
83
89
|
super();
|
|
84
90
|
this.firestore = firestore;
|
|
85
91
|
}
|
|
86
|
-
async
|
|
87
|
-
return (await getDoc(getDocument(this.firestore, ref)))
|
|
92
|
+
async getDocument(ref) {
|
|
93
|
+
return getOptionalEntity(await getDoc(getDocument(this.firestore, ref)));
|
|
88
94
|
}
|
|
89
|
-
|
|
90
|
-
return onSnapshot(getDocument(this.firestore, ref), snapshot => dispatchNext(observer, snapshot
|
|
95
|
+
subscribeDocument(ref, observer) {
|
|
96
|
+
return onSnapshot(getDocument(this.firestore, ref), snapshot => dispatchNext(observer, getOptionalEntity(snapshot)), thrown => dispatchError(observer, thrown));
|
|
91
97
|
}
|
|
92
|
-
async
|
|
98
|
+
async addDocument(ref, data) {
|
|
93
99
|
const reference = await addDoc(getCollection(this.firestore, ref), data);
|
|
94
100
|
return reference.id;
|
|
95
101
|
}
|
|
96
|
-
async
|
|
102
|
+
async setDocument(ref, data) {
|
|
97
103
|
await setDoc(getDocument(this.firestore, ref), data);
|
|
98
104
|
}
|
|
99
|
-
async
|
|
105
|
+
async updateDocument(ref, update) {
|
|
100
106
|
const fieldValues = Object.fromEntries(yieldFieldValues(update));
|
|
101
107
|
await updateDoc(getDocument(this.firestore, ref), fieldValues);
|
|
102
108
|
}
|
|
103
|
-
async
|
|
109
|
+
async deleteDocument(ref) {
|
|
104
110
|
await deleteDoc(getDocument(this.firestore, ref));
|
|
105
111
|
}
|
|
106
112
|
async getQuery(ref) {
|
|
107
|
-
return
|
|
113
|
+
return getEntities(await getDocs(getQuery(this.firestore, ref)));
|
|
108
114
|
}
|
|
109
115
|
subscribeQuery(ref, observer) {
|
|
110
|
-
return onSnapshot(getQuery(this.firestore, ref), snapshot => dispatchNext(observer,
|
|
116
|
+
return onSnapshot(getQuery(this.firestore, ref), snapshot => dispatchNext(observer, getEntities(snapshot)), thrown => dispatchError(observer, thrown));
|
|
111
117
|
}
|
|
112
118
|
async setQuery(ref, data) {
|
|
113
119
|
const snapshot = await getDocs(getQuery(this.firestore, ref));
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { Firestore } from "firebase/firestore/lite";
|
|
2
2
|
import type { DocumentReference, QueryReference } from "../../db/Reference.js";
|
|
3
|
-
import type { Data,
|
|
4
|
-
import type {
|
|
5
|
-
import type { Unsubscriber } from "../../util/observe.js";
|
|
3
|
+
import type { Data, Entities, OptionalEntity } from "../../util/data.js";
|
|
4
|
+
import type { Unsubscribe } from "../../observe/Observable.js";
|
|
6
5
|
import { AsynchronousProvider, Provider } from "../../provider/Provider.js";
|
|
7
6
|
import { DataUpdate } from "../../update/DataUpdate.js";
|
|
8
7
|
/**
|
|
@@ -14,14 +13,14 @@ import { DataUpdate } from "../../update/DataUpdate.js";
|
|
|
14
13
|
export declare class FirestoreClientProvider extends Provider implements AsynchronousProvider {
|
|
15
14
|
readonly firestore: Firestore;
|
|
16
15
|
constructor(firestore: Firestore);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
getQuery<T extends Data>(ref: QueryReference<T>): Promise<
|
|
24
|
-
subscribeQuery():
|
|
16
|
+
getDocument<T extends Data>(ref: DocumentReference<T>): Promise<OptionalEntity<T>>;
|
|
17
|
+
subscribeDocument(): Unsubscribe;
|
|
18
|
+
addDocument<T extends Data>(ref: QueryReference<T>, data: T): Promise<string>;
|
|
19
|
+
setDocument<T extends Data>(ref: DocumentReference<T>, data: T): Promise<void>;
|
|
20
|
+
updateDocument<T extends Data>(ref: DocumentReference<T>, update: DataUpdate<T>): Promise<void>;
|
|
21
|
+
deleteDocument<T extends Data>(ref: DocumentReference<T>): Promise<void>;
|
|
22
|
+
getQuery<T extends Data>(ref: QueryReference<T>): Promise<Entities<T>>;
|
|
23
|
+
subscribeQuery(): Unsubscribe;
|
|
25
24
|
setQuery<T extends Data>(ref: QueryReference<T>, data: T): Promise<number>;
|
|
26
25
|
updateQuery<T extends Data>(ref: QueryReference<T>, update: DataUpdate<T>): Promise<number>;
|
|
27
26
|
deleteQuery<T extends Data>(ref: QueryReference<T>): Promise<number>;
|