shelving 1.24.0 → 1.27.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.
Files changed (74) hide show
  1. package/db/Database.d.ts +10 -21
  2. package/db/Database.js +15 -32
  3. package/db/Pagination.d.ts +2 -10
  4. package/db/Pagination.js +16 -39
  5. package/db/Write.d.ts +28 -12
  6. package/db/Write.js +42 -18
  7. package/feedback/hydrations.d.ts +5 -5
  8. package/feedback/hydrations.js +5 -5
  9. package/firestore/client/FirestoreClientProvider.d.ts +7 -3
  10. package/firestore/client/FirestoreClientProvider.js +46 -41
  11. package/firestore/lite/FirestoreLiteProvider.d.ts +7 -3
  12. package/firestore/lite/FirestoreLiteProvider.js +45 -40
  13. package/firestore/server/FirestoreServerProvider.d.ts +7 -3
  14. package/firestore/server/FirestoreServerProvider.js +57 -52
  15. package/index.d.ts +4 -4
  16. package/index.js +4 -4
  17. package/package.json +3 -1
  18. package/provider/CacheProvider.d.ts +7 -3
  19. package/provider/CacheProvider.js +29 -14
  20. package/provider/MemoryProvider.d.ts +7 -3
  21. package/provider/MemoryProvider.js +44 -14
  22. package/provider/Provider.d.ts +47 -19
  23. package/provider/ThroughProvider.d.ts +7 -3
  24. package/provider/ThroughProvider.js +16 -4
  25. package/provider/ValidationProvider.d.ts +5 -3
  26. package/provider/ValidationProvider.js +11 -9
  27. package/query/Filter.js +2 -2
  28. package/query/Filters.js +2 -2
  29. package/stream/ArrayState.d.ts +1 -1
  30. package/stream/ArrayState.js +1 -1
  31. package/stream/DataState.d.ts +2 -2
  32. package/stream/State.d.ts +2 -2
  33. package/stream/State.js +3 -3
  34. package/update/DataUpdate.d.ts +25 -0
  35. package/update/DataUpdate.js +25 -0
  36. package/update/EntriesUpdate.d.ts +29 -0
  37. package/update/EntriesUpdate.js +45 -0
  38. package/update/Increment.d.ts +14 -0
  39. package/{transform/IncrementTransform.js → update/Increment.js} +6 -4
  40. package/update/ItemsUpdate.d.ts +21 -0
  41. package/update/ItemsUpdate.js +34 -0
  42. package/update/Update.d.ts +9 -0
  43. package/update/Update.js +6 -0
  44. package/update/hydrations.d.ts +11 -0
  45. package/update/hydrations.js +12 -0
  46. package/update/index.d.ts +7 -0
  47. package/update/index.js +7 -0
  48. package/update/util.d.ts +7 -0
  49. package/update/util.js +42 -0
  50. package/util/filter.d.ts +4 -5
  51. package/util/filter.js +6 -7
  52. package/util/object.d.ts +2 -2
  53. package/util/object.js +2 -2
  54. package/util/transform.d.ts +14 -19
  55. package/util/transform.js +25 -24
  56. package/transform/AddEntriesTransform.d.ts +0 -10
  57. package/transform/AddEntriesTransform.js +0 -16
  58. package/transform/AddItemsTransform.d.ts +0 -10
  59. package/transform/AddItemsTransform.js +0 -16
  60. package/transform/DataTransform.d.ts +0 -24
  61. package/transform/DataTransform.js +0 -24
  62. package/transform/IncrementTransform.d.ts +0 -12
  63. package/transform/RemoveEntriesTransform.d.ts +0 -10
  64. package/transform/RemoveEntriesTransform.js +0 -16
  65. package/transform/RemoveItemsTransform.d.ts +0 -10
  66. package/transform/RemoveItemsTransform.js +0 -16
  67. package/transform/Transform.d.ts +0 -9
  68. package/transform/Transform.js +0 -6
  69. package/transform/hydrations.d.ts +0 -15
  70. package/transform/hydrations.js +0 -16
  71. package/transform/index.d.ts +0 -9
  72. package/transform/index.js +0 -9
  73. package/transform/util.d.ts +0 -7
  74. package/transform/util.js +0 -42
package/db/Database.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { Entry, Observable, Observer, Result, Unsubscriber, ResultsMap, Validatable, Validator, Key, Data, Results, Datas, Validators, ValidatorType, Dispatcher } from "../util/index.js";
2
- import { Transform, Transforms } from "../transform/index.js";
2
+ import { PropUpdates, Update } from "../update/index.js";
3
3
  import type { Provider } from "../provider/Provider.js";
4
4
  import { Filters, Sorts, Query } from "../query/index.js";
5
- import { DocumentWrite, Write, Writes } from "./Write.js";
5
+ import { DocumentDelete, DocumentSet, DocumentUpdate, Write, Writes } from "./Write.js";
6
6
  /**
7
7
  * Combines a database model and a provider.
8
8
  *
@@ -81,26 +81,19 @@ export declare class DataQuery<T extends Data = Data> extends Query<T> implement
81
81
  * @param data Complete data to set the document to.
82
82
  * @return Nothing (possibly promised).
83
83
  */
84
- set(data: T): void | PromiseLike<void>;
84
+ set(data: T): number | PromiseLike<number>;
85
85
  /**
86
86
  * Update all matching documents with the same partial value.
87
87
  *
88
- * @param transform `Transform` instance or set of transforms to apply to every matching document.
89
- * - Not all transforms may be supported by all providers.
90
- *
88
+ * @param updates `Update` instance or set of updates to apply to every matching document.
91
89
  * @return Nothing (possibly promised).
92
90
  */
93
- update(transform: Transform<T> | Transforms<T>): void | PromiseLike<void>;
91
+ update(updates: Update<T> | PropUpdates<T>): number | PromiseLike<number>;
94
92
  /**
95
93
  * Delete all matching documents.
96
94
  * @return Nothing (possibly promised).
97
95
  */
98
- delete(): void | PromiseLike<void>;
99
- /**
100
- * Combine `set()`, `update()`, `delete()` into a single method.
101
- * @return Nothing (possibly promised).
102
- */
103
- write(value: Result<T> | Transform<T>): void | PromiseLike<void>;
96
+ delete(): number | PromiseLike<number>;
104
97
  /** Iterate over the resuls (will throw `Promise` if the results are asynchronous). */
105
98
  [Symbol.iterator](): Iterator<Entry<T>, void>;
106
99
  /** Validate a set of results for this query reference. */
@@ -149,19 +142,15 @@ export declare class DataDocument<T extends Data = Data> implements Observable<R
149
142
  /** Set the complete data of this document. */
150
143
  set(data: T): void | PromiseLike<void>;
151
144
  /** Update this document. */
152
- update(transforms: Transform<T> | Transforms<T>): void | PromiseLike<void>;
145
+ update(updates: Update<T> | PropUpdates<T>): void | PromiseLike<void>;
153
146
  /** Delete this document. */
154
147
  delete(): void | PromiseLike<void>;
155
- /** Set, update, or delete this document. */
156
- write(value: Result<T> | Transform<T>): void | PromiseLike<void>;
157
148
  /** Represent a write that sets the complete data of this document in a database. */
158
- setter(data: T): DocumentWrite<T>;
149
+ setter(data: T): DocumentSet<T>;
159
150
  /** Represent a write that updates this document in a database. */
160
- updater(transforms: Transform<T> | Transforms<T>): DocumentWrite<T>;
151
+ updater(updates: Update<T> | PropUpdates<T>): DocumentUpdate<T>;
161
152
  /** Represent a write that deletes this document in a database. */
162
- deleter(): DocumentWrite<T>;
163
- /** Represent a write that sets, updates, or deletes this document in a database. */
164
- writer(value: Result<T> | Transform<T>): DocumentWrite<T>;
153
+ deleter(): DocumentDelete<T>;
165
154
  /** Validate data for this query reference. */
166
155
  validate(unsafeData: Data): T;
167
156
  toString(): string;
package/db/Database.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { callAsync, getFirstItem, throwAsync, validate, toMap, countItems, TransformObserver, } from "../util/index.js";
2
- import { DataTransform, Transform } from "../transform/index.js";
2
+ import { DataUpdate, Update } from "../update/index.js";
3
3
  import { Feedback, InvalidFeedback } from "../feedback/index.js";
4
4
  import { Filters, Query, EqualFilter } from "../query/index.js";
5
5
  import { DocumentRequiredError, DocumentValidationError, QueryValidationError } from "./errors.js";
6
- import { DocumentWrite, Writes } from "./Write.js";
6
+ import { DocumentDelete, DocumentSet, DocumentUpdate, Writes } from "./Write.js";
7
7
  /**
8
8
  * Combines a database model and a provider.
9
9
  *
@@ -114,32 +114,23 @@ export class DataQuery extends Query {
114
114
  * @return Nothing (possibly promised).
115
115
  */
116
116
  set(data) {
117
- return this.write(data);
117
+ return this.provider.setQuery(this, data);
118
118
  }
119
119
  /**
120
120
  * Update all matching documents with the same partial value.
121
121
  *
122
- * @param transform `Transform` instance or set of transforms to apply to every matching document.
123
- * - Not all transforms may be supported by all providers.
124
- *
122
+ * @param updates `Update` instance or set of updates to apply to every matching document.
125
123
  * @return Nothing (possibly promised).
126
124
  */
127
- update(transform) {
128
- return this.write(transform instanceof Transform ? transform : new DataTransform(transform));
125
+ update(updates) {
126
+ return this.provider.updateQuery(this, updates instanceof Update ? updates : new DataUpdate(updates));
129
127
  }
130
128
  /**
131
129
  * Delete all matching documents.
132
130
  * @return Nothing (possibly promised).
133
131
  */
134
132
  delete() {
135
- return this.write(undefined);
136
- }
137
- /**
138
- * Combine `set()`, `update()`, `delete()` into a single method.
139
- * @return Nothing (possibly promised).
140
- */
141
- write(value) {
142
- return this.provider.writeQuery(this, value);
133
+ return this.provider.deleteQuery(this);
143
134
  }
144
135
  /** Iterate over the resuls (will throw `Promise` if the results are asynchronous). */
145
136
  [Symbol.iterator]() {
@@ -222,35 +213,27 @@ export class DataDocument {
222
213
  }
223
214
  /** Set the complete data of this document. */
224
215
  set(data) {
225
- return this.write(data);
216
+ return this.provider.set(this, data);
226
217
  }
227
218
  /** Update this document. */
228
- update(transforms) {
229
- return this.write(transforms instanceof Transform ? transforms : new DataTransform(transforms));
219
+ update(updates) {
220
+ return this.provider.update(this, updates instanceof Update ? updates : new DataUpdate(updates));
230
221
  }
231
222
  /** Delete this document. */
232
223
  delete() {
233
- return this.write(undefined);
234
- }
235
- /** Set, update, or delete this document. */
236
- write(value) {
237
- return this.provider.write(this, value);
224
+ return this.provider.delete(this);
238
225
  }
239
226
  /** Represent a write that sets the complete data of this document in a database. */
240
227
  setter(data) {
241
- return this.writer(data);
228
+ return new DocumentSet(this, data);
242
229
  }
243
230
  /** Represent a write that updates this document in a database. */
244
- updater(transforms) {
245
- return this.writer(transforms instanceof Transform ? transforms : new DataTransform(transforms));
231
+ updater(updates) {
232
+ return new DocumentUpdate(this, updates);
246
233
  }
247
234
  /** Represent a write that deletes this document in a database. */
248
235
  deleter() {
249
- return this.writer(undefined);
250
- }
251
- /** Represent a write that sets, updates, or deletes this document in a database. */
252
- writer(value) {
253
- return new DocumentWrite(this, value);
236
+ return new DocumentDelete(this);
254
237
  }
255
238
  /** Validate data for this query reference. */
256
239
  validate(unsafeData) {
@@ -7,23 +7,15 @@ import { DataQuery } from "./Database.js";
7
7
  * - If you don't pass in initial values, it will autoload the first page.
8
8
  */
9
9
  export declare class Pagination<T extends Data> extends State<ResultsMap<T>> implements Iterable<Entry<T>> {
10
+ protected _pending: boolean;
10
11
  readonly ref: DataQuery<T>;
11
12
  readonly limit: number;
12
- readonly startLoading: boolean;
13
- readonly startDone: boolean;
14
- readonly endLoading: boolean;
15
- readonly endDone: boolean;
16
13
  constructor(ref: DataQuery<T>);
17
- /**
18
- * Load more results before the start.
19
- * - Promise that needs to be handled.
20
- */
21
- loadStart: () => Promise<void>;
22
14
  /**
23
15
  * Load more results after the end.
24
16
  * - Promise that needs to be handled.
25
17
  */
26
- loadEnd: () => Promise<void>;
18
+ more: () => Promise<void>;
27
19
  /**
28
20
  * Merge more results into this pagination.
29
21
  * @return The change in the number of results.
package/db/Pagination.js CHANGED
@@ -1,4 +1,4 @@
1
- import { getFirstItem, getLastItem, assertLength, assertNumber, yieldMerged, toMap } from "../util/index.js";
1
+ import { getLastItem, assertLength, assertNumber, yieldMerged, toMap, LOADING } from "../util/index.js";
2
2
  import { State } from "../stream/index.js";
3
3
  import { ConditionError } from "../index.js";
4
4
  /**
@@ -9,56 +9,33 @@ import { ConditionError } from "../index.js";
9
9
  export class Pagination extends State {
10
10
  constructor(ref) {
11
11
  super();
12
- this.startLoading = false;
13
- this.startDone = false;
14
- this.endLoading = false;
15
- this.endDone = false;
16
- /**
17
- * Load more results before the start.
18
- * - Promise that needs to be handled.
19
- */
20
- this.loadStart = async () => {
21
- if (this.closed)
22
- throw new ConditionError();
23
- if (!this.startLoading) {
24
- this.startLoading = true;
25
- if (!this.loading) {
26
- const firstItem = getFirstItem(this.value);
27
- if (firstItem) {
28
- const next = await this.ref.after(firstItem[0], firstItem[1]).resultsMap;
29
- this.startDone = next.size < this.limit;
30
- this.startLoading = false;
31
- return this.merge(next);
32
- }
33
- }
34
- const next = await this.ref.resultsMap;
35
- this.startDone = next.size < this.limit;
36
- this.startLoading = false;
37
- return this.next(next);
38
- }
39
- };
12
+ this._pending = false; // Prevents double-loading.
40
13
  /**
41
14
  * Load more results after the end.
42
15
  * - Promise that needs to be handled.
43
16
  */
44
- this.loadEnd = async () => {
17
+ this.more = async () => {
45
18
  if (this.closed)
46
- throw new ConditionError();
47
- if (!this.endLoading) {
48
- this.endLoading = true;
19
+ throw new ConditionError("Pagination is closed");
20
+ if (!this._pending) {
21
+ this._pending = true;
49
22
  if (!this.loading) {
50
23
  const lastItem = getLastItem(this.value);
51
24
  if (lastItem) {
52
25
  const next = await this.ref.after(lastItem[0], lastItem[1]).resultsMap;
53
- this.endDone = next.size < this.limit;
54
- this.endLoading = false;
55
- return this.merge(next);
26
+ this.merge(next);
27
+ if (next.size < this.limit)
28
+ this.complete();
29
+ this._pending = false;
30
+ return;
56
31
  }
57
32
  }
33
+ this._value === LOADING;
58
34
  const next = await this.ref.resultsMap;
59
- this.endDone = next.size < this.limit;
60
- this.endLoading = false;
61
- return this.next(next);
35
+ this.next(next);
36
+ if (next.size < this.limit)
37
+ this.complete();
38
+ this._pending = false;
62
39
  }
63
40
  };
64
41
  this.ref = ref;
package/db/Write.d.ts CHANGED
@@ -1,18 +1,10 @@
1
- import { Transform } from "../transform/index.js";
1
+ import { PropUpdates, Update } from "../update/index.js";
2
2
  import { ImmutableArray, Data, Transformable } from "../util/index.js";
3
3
  import type { Database, DataDocument } from "./Database.js";
4
- /** Write to a database. */
4
+ /** Represent a write made to a database. */
5
5
  export declare abstract class Write implements Transformable<Database, void | PromiseLike<void>> {
6
6
  abstract transform(db: Database): void | PromiseLike<void>;
7
7
  }
8
- /** Represent a write made to a single document in a database. */
9
- export declare class DocumentWrite<T extends Data> extends Write {
10
- readonly collection: string;
11
- readonly id: string;
12
- readonly value: Data | Transform<Data> | undefined;
13
- constructor({ collection, id }: DataDocument<T>, value: T | Transform<T> | undefined);
14
- transform(db: Database): Promise<void>;
15
- }
16
8
  /**
17
9
  * Represent a list of writes made to a database.
18
10
  * - Sets of writes are predictable and repeatable, so unpredictable operations like `create()` and query operations are not supported.
@@ -23,8 +15,32 @@ export declare class Writes extends Write {
23
15
  constructor(...writes: (Write | undefined)[]);
24
16
  transform(db: Database): Promise<void>;
25
17
  }
18
+ /** Represent a write made to a single document in a database. */
19
+ export declare abstract class DocumentWrite<T extends Data> extends Write {
20
+ readonly collection: string;
21
+ readonly id: string;
22
+ constructor({ collection, id }: DataDocument<T>);
23
+ }
24
+ /** Represent a set operation made to a single document in a database. */
25
+ export declare class DocumentSet<T extends Data> extends DocumentWrite<T> {
26
+ readonly data: T;
27
+ constructor(ref: DataDocument<T>, data: T);
28
+ transform(db: Database): Promise<void>;
29
+ }
30
+ /** Represent an update operation made to a single document in a database. */
31
+ export declare class DocumentUpdate<T extends Data> extends DocumentWrite<T> {
32
+ readonly updates: Update<T>;
33
+ constructor(ref: DataDocument<T>, updates: Update<T> | PropUpdates<T>);
34
+ transform(db: Database): Promise<void>;
35
+ }
36
+ /** Represent a delete operation made to a single document in a database. */
37
+ export declare class DocumentDelete<T extends Data> extends DocumentWrite<T> {
38
+ transform(db: Database): Promise<void>;
39
+ }
26
40
  /** Set of hydrations for all change classes. */
27
41
  export declare const WRITE_HYDRATIONS: {
28
- writes: typeof Writes;
29
- write: typeof DocumentWrite;
42
+ Writes: typeof Writes;
43
+ DocumentSet: typeof DocumentSet;
44
+ DocumentUpdate: typeof DocumentUpdate;
45
+ DocumentDelete: typeof DocumentDelete;
30
46
  };
package/db/Write.js CHANGED
@@ -1,19 +1,8 @@
1
- import { transform } from "../util/index.js";
2
- /** Write to a database. */
1
+ import { DataUpdate, Update } from "../update/index.js";
2
+ import { transform, IS_DEFINED } from "../util/index.js";
3
+ /** Represent a write made to a database. */
3
4
  export class Write {
4
5
  }
5
- /** Represent a write made to a single document in a database. */
6
- export class DocumentWrite extends Write {
7
- constructor({ collection, id }, value) {
8
- super();
9
- this.collection = collection;
10
- this.id = id;
11
- this.value = value;
12
- }
13
- async transform(db) {
14
- await db.doc(this.collection, this.id).write(this.value);
15
- }
16
- }
17
6
  /**
18
7
  * Represent a list of writes made to a database.
19
8
  * - Sets of writes are predictable and repeatable, so unpredictable operations like `create()` and query operations are not supported.
@@ -22,17 +11,52 @@ export class DocumentWrite extends Write {
22
11
  export class Writes extends Write {
23
12
  constructor(...writes) {
24
13
  super();
25
- this.writes = writes.filter(isWrite);
14
+ this.writes = writes.filter(IS_DEFINED);
26
15
  }
27
16
  async transform(db) {
28
17
  for (const writes of this.writes)
29
18
  await transform(db, writes);
30
19
  }
31
20
  }
32
- const isWrite = (v) => !!v;
21
+ /** Represent a write made to a single document in a database. */
22
+ export class DocumentWrite extends Write {
23
+ constructor({ collection, id }) {
24
+ super();
25
+ this.collection = collection;
26
+ this.id = id;
27
+ }
28
+ }
29
+ /** Represent a set operation made to a single document in a database. */
30
+ export class DocumentSet extends DocumentWrite {
31
+ constructor(ref, data) {
32
+ super(ref);
33
+ this.data = data;
34
+ }
35
+ async transform(db) {
36
+ await db.doc(this.collection, this.id).set(this.data);
37
+ }
38
+ }
39
+ /** Represent an update operation made to a single document in a database. */
40
+ export class DocumentUpdate extends DocumentWrite {
41
+ constructor(ref, updates) {
42
+ super(ref);
43
+ this.updates = updates instanceof Update ? updates : new DataUpdate(updates);
44
+ }
45
+ async transform(db) {
46
+ await db.doc(this.collection, this.id).update(this.updates);
47
+ }
48
+ }
49
+ /** Represent a delete operation made to a single document in a database. */
50
+ export class DocumentDelete extends DocumentWrite {
51
+ async transform(db) {
52
+ await db.doc(this.collection, this.id).delete();
53
+ }
54
+ }
33
55
  /** Set of hydrations for all change classes. */
34
56
  export const WRITE_HYDRATIONS = {
35
- writes: Writes,
36
- write: DocumentWrite,
57
+ Writes,
58
+ DocumentSet,
59
+ DocumentUpdate,
60
+ DocumentDelete,
37
61
  };
38
62
  WRITE_HYDRATIONS;
@@ -5,9 +5,9 @@ import { ErrorFeedback } from "./ErrorFeedback.js";
5
5
  import { InvalidFeedback } from "./InvalidFeedback.js";
6
6
  /** Set of hydrations for all feedback classes. */
7
7
  export declare const FEEDBACK_HYDRATIONS: {
8
- success: typeof SuccessFeedback;
9
- warning: typeof WarningFeedback;
10
- invalid: typeof InvalidFeedback;
11
- error: typeof ErrorFeedback;
12
- feedback: typeof Feedback;
8
+ SuccessFeedback: typeof SuccessFeedback;
9
+ WarningFeedback: typeof WarningFeedback;
10
+ InvalidFeedback: typeof InvalidFeedback;
11
+ ErrorFeedback: typeof ErrorFeedback;
12
+ Feedback: typeof Feedback;
13
13
  };
@@ -5,10 +5,10 @@ import { ErrorFeedback } from "./ErrorFeedback.js";
5
5
  import { InvalidFeedback } from "./InvalidFeedback.js";
6
6
  /** Set of hydrations for all feedback classes. */
7
7
  export const FEEDBACK_HYDRATIONS = {
8
- success: SuccessFeedback,
9
- warning: WarningFeedback,
10
- invalid: InvalidFeedback,
11
- error: ErrorFeedback,
12
- feedback: Feedback,
8
+ SuccessFeedback,
9
+ WarningFeedback,
10
+ InvalidFeedback,
11
+ ErrorFeedback,
12
+ Feedback,
13
13
  };
14
14
  FEEDBACK_HYDRATIONS;
@@ -1,5 +1,5 @@
1
1
  import type { Firestore } from "firebase/firestore";
2
- import { Results, Provider, DataDocument, DataQuery, Result, Observer, Transform, AsynchronousProvider, Data, Unsubscriber } from "../../index.js";
2
+ import { Results, Provider, DataDocument, DataQuery, Result, Observer, Update, AsynchronousProvider, Data, Unsubscriber } from "../../index.js";
3
3
  /**
4
4
  * Firestore client database provider.
5
5
  * - Works with the Firebase JS SDK.
@@ -12,8 +12,12 @@ export declare class FirestoreClientProvider extends Provider implements Asynchr
12
12
  get<T extends Data>(ref: DataDocument<T>): Promise<Result<T>>;
13
13
  subscribe<T extends Data>(ref: DataDocument<T>, observer: Observer<Result<T>>): Unsubscriber;
14
14
  add<T extends Data>(ref: DataQuery<T>, data: T): Promise<string>;
15
- write<T extends Data>(ref: DataDocument<T>, value: T | Transform<T> | undefined): Promise<void>;
15
+ set<T extends Data>(ref: DataDocument<T>, data: T): Promise<void>;
16
+ update<T extends Data>(ref: DataDocument<T>, updates: Update<T>): Promise<void>;
17
+ delete<T extends Data>(ref: DataDocument<T>): Promise<void>;
16
18
  getQuery<T extends Data>(ref: DataQuery<T>): Promise<Results<T>>;
17
19
  subscribeQuery<T extends Data>(ref: DataQuery<T>, observer: Observer<Results<T>>): Unsubscriber;
18
- writeQuery<T extends Data>(ref: DataQuery<T>, value: T | Transform<T> | undefined): Promise<void>;
20
+ setQuery<T extends Data>(ref: DataQuery<T>, data: T): Promise<number>;
21
+ updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>): Promise<number>;
22
+ deleteQuery<T extends Data>(ref: DataQuery<T>): Promise<number>;
19
23
  }
@@ -1,5 +1,5 @@
1
1
  import { orderBy as firestoreOrderBy, where as firestoreWhere, limit as firestoreLimit, increment as firestoreIncrement, arrayUnion as firestoreArrayUnion, arrayRemove as firestoreArrayRemove, deleteField as firestoreDeleteField, collection as firestoreCollection, doc as firestoreDocument, query as firestoreQuery, onSnapshot, addDoc, setDoc, updateDoc, deleteDoc, getDoc, getDocs, } from "firebase/firestore";
2
- import { Provider, dispatchNext, dispatchError, Transform, AddItemsTransform, AddEntriesTransform, IncrementTransform, RemoveItemsTransform, RemoveEntriesTransform, DataTransform, AssertionError, } from "../../index.js";
2
+ import { Provider, dispatchNext, dispatchError, Update, EntriesUpdate, Increment, DataUpdate, AssertionError, ItemsUpdate, UnsupportedError, } from "../../index.js";
3
3
  // Constants.
4
4
  // const ID = "__name__"; // DH: `__name__` is the entire path of the document. `__id__` is just ID.
5
5
  const ID = "__id__"; // Internal way Firestore Queries can reference the ID of the current document.
@@ -44,32 +44,30 @@ function* getResults(snapshot) {
44
44
  for (const s of snapshot.docs)
45
45
  yield [s.id, s.data()];
46
46
  }
47
- /** Convert `Transform` instances into corresponding Firestore `FieldValue` instances. */
48
- function getFieldValues(transform) {
49
- if (transform instanceof DataTransform)
50
- return Object.fromEntries(yieldFieldValues(transform));
51
- throw new AssertionError("Unsupported transform", transform);
47
+ /** Convert `Update` instances into corresponding Firestore `FieldValue` instances. */
48
+ function getFieldValues(update) {
49
+ if (update instanceof DataUpdate)
50
+ return Object.fromEntries(yieldFieldValues(update));
51
+ throw new AssertionError("Unsupported transform", update);
52
52
  }
53
- function* yieldFieldValues(transforms, prefix = "") {
54
- for (const [key, transform] of transforms) {
55
- if (!(transform instanceof Transform))
56
- yield [`${prefix}${key}`, transform];
57
- if (transform instanceof IncrementTransform)
58
- yield [`${prefix}${key}`, firestoreIncrement(transform.amount)];
59
- else if (transform instanceof AddItemsTransform)
60
- yield [`${prefix}${key}`, firestoreArrayUnion(...transform)];
61
- else if (transform instanceof RemoveItemsTransform)
62
- yield [`${prefix}${key}`, firestoreArrayRemove(...transform)];
63
- else if (transform instanceof AddEntriesTransform)
64
- for (const [k, v] of transform)
65
- yield [`${prefix}${key}.${k}`, v];
66
- else if (transform instanceof RemoveEntriesTransform)
67
- for (const k of transform)
68
- yield [`${prefix}${key}.${k}`, firestoreDeleteField()];
69
- else if (transform instanceof DataTransform)
70
- yield* yieldFieldValues(transform, `${prefix}${key}.`);
53
+ function* yieldFieldValues(updates, prefix = "") {
54
+ for (const [key, update] of updates) {
55
+ if (!(update instanceof Update))
56
+ yield [`${prefix}${key}`, update !== undefined ? update : firestoreDeleteField()];
57
+ else if (update instanceof Increment)
58
+ yield [`${prefix}${key}`, firestoreIncrement(update.amount)];
59
+ else if (update instanceof DataUpdate || update instanceof EntriesUpdate)
60
+ yield* yieldFieldValues(update, `${prefix}${key}.`);
61
+ else if (update instanceof ItemsUpdate) {
62
+ if (update.adds.length && update.deletes.length)
63
+ throw new UnsupportedError("Cannot add/delete array items in one update");
64
+ if (update.adds.length)
65
+ yield [`${prefix}${key}`, firestoreArrayUnion(...update.adds)];
66
+ else if (update.deletes.length)
67
+ yield [`${prefix}${key}`, firestoreArrayRemove(...update.deletes)];
68
+ }
71
69
  else
72
- throw new AssertionError("Unsupported transform", transform);
70
+ throw new AssertionError("Unsupported transform", update);
73
71
  }
74
72
  }
75
73
  /**
@@ -91,16 +89,17 @@ export class FirestoreClientProvider extends Provider {
91
89
  return onSnapshot(getDocument(this.firestore, ref), snapshot => dispatchNext(observer, snapshot.data()), thrown => dispatchError(observer, thrown));
92
90
  }
93
91
  async add(ref, data) {
94
- const reference = await addDoc(getCollection(this.firestore, ref), data); // eslint-disable-line @typescript-eslint/no-explicit-any
92
+ const reference = await addDoc(getCollection(this.firestore, ref), data);
95
93
  return reference.id;
96
94
  }
97
- async write(ref, value) {
98
- if (value instanceof Transform)
99
- await updateDoc(getDocument(this.firestore, ref), getFieldValues(value));
100
- else if (value)
101
- await setDoc(getDocument(this.firestore, ref), value);
102
- else
103
- await deleteDoc(getDocument(this.firestore, ref));
95
+ async set(ref, data) {
96
+ await setDoc(getDocument(this.firestore, ref), data);
97
+ }
98
+ async update(ref, updates) {
99
+ await updateDoc(getDocument(this.firestore, ref), getFieldValues(updates));
100
+ }
101
+ async delete(ref) {
102
+ await deleteDoc(getDocument(this.firestore, ref));
104
103
  }
105
104
  async getQuery(ref) {
106
105
  return getResults(await getDocs(getQuery(this.firestore, ref)));
@@ -108,14 +107,20 @@ export class FirestoreClientProvider extends Provider {
108
107
  subscribeQuery(ref, observer) {
109
108
  return onSnapshot(getQuery(this.firestore, ref), snapshot => dispatchNext(observer, getResults(snapshot)), thrown => dispatchError(observer, thrown));
110
109
  }
111
- async writeQuery(ref, value) {
110
+ async setQuery(ref, data) {
112
111
  const snapshot = await getDocs(getQuery(this.firestore, ref));
113
- const updates = value instanceof Transform && getFieldValues(value);
114
- if (updates)
115
- await Promise.all(snapshot.docs.map(s => updateDoc(s.ref, updates)));
116
- else if (value)
117
- await Promise.all(snapshot.docs.map(s => setDoc(s.ref, value)));
118
- else
119
- await Promise.all(snapshot.docs.map(s => deleteDoc(s.ref)));
112
+ await Promise.all(snapshot.docs.map(s => setDoc(s.ref, data)));
113
+ return snapshot.size;
114
+ }
115
+ async updateQuery(ref, updates) {
116
+ const snapshot = await getDocs(getQuery(this.firestore, ref));
117
+ const fieldValues = getFieldValues(updates);
118
+ await Promise.all(snapshot.docs.map(s => updateDoc(s.ref, fieldValues)));
119
+ return snapshot.size;
120
+ }
121
+ async deleteQuery(ref) {
122
+ const snapshot = await getDocs(getQuery(this.firestore, ref));
123
+ await Promise.all(snapshot.docs.map(s => deleteDoc(s.ref)));
124
+ return snapshot.size;
120
125
  }
121
126
  }
@@ -1,5 +1,5 @@
1
1
  import type { Firestore } from "firebase/firestore/lite";
2
- import { Provider, DataDocument, DataQuery, Result, Transform, AsynchronousProvider, Data, Results, Unsubscriber } from "../../index.js";
2
+ import { Provider, DataDocument, DataQuery, Result, Update, AsynchronousProvider, Data, Results, Unsubscriber } from "../../index.js";
3
3
  /**
4
4
  * Firestore Lite client database provider.
5
5
  * - Works with the Firebase JS SDK.
@@ -12,8 +12,12 @@ export declare class FirestoreClientProvider extends Provider implements Asynchr
12
12
  get<T extends Data>(ref: DataDocument<T>): Promise<Result<T>>;
13
13
  subscribe(): Unsubscriber;
14
14
  add<T extends Data>(ref: DataQuery<T>, data: T): Promise<string>;
15
- write<T extends Data>(ref: DataDocument<T>, value: T | Transform<T> | undefined): Promise<void>;
15
+ set<T extends Data>(ref: DataDocument<T>, data: T): Promise<void>;
16
+ update<T extends Data>(ref: DataDocument<T>, updates: Update<T>): Promise<void>;
17
+ delete<T extends Data>(ref: DataDocument<T>): Promise<void>;
16
18
  getQuery<T extends Data>(ref: DataQuery<T>): Promise<Results<T>>;
17
19
  subscribeQuery(): Unsubscriber;
18
- writeQuery<T extends Data>(ref: DataQuery<T>, value: T | Transform<T> | undefined): Promise<void>;
20
+ setQuery<T extends Data>(ref: DataQuery<T>, data: T | Update<T> | undefined): Promise<number>;
21
+ updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>): Promise<number>;
22
+ deleteQuery<T extends Data>(ref: DataQuery<T>): Promise<number>;
19
23
  }