shelving 1.23.1 → 1.26.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 (72) hide show
  1. package/db/Database.d.ts +12 -21
  2. package/db/Database.js +25 -35
  3. package/db/Write.d.ts +30 -14
  4. package/db/Write.js +44 -19
  5. package/feedback/hydrations.d.ts +5 -5
  6. package/feedback/hydrations.js +5 -5
  7. package/firestore/client/FirestoreClientProvider.d.ts +7 -3
  8. package/firestore/client/FirestoreClientProvider.js +47 -38
  9. package/firestore/lite/FirestoreLiteProvider.d.ts +7 -3
  10. package/firestore/lite/FirestoreLiteProvider.js +42 -40
  11. package/firestore/server/FirestoreServerProvider.d.ts +7 -3
  12. package/firestore/server/FirestoreServerProvider.js +54 -52
  13. package/index.d.ts +4 -4
  14. package/index.js +4 -4
  15. package/package.json +3 -1
  16. package/provider/CacheProvider.d.ts +7 -3
  17. package/provider/CacheProvider.js +26 -14
  18. package/provider/MemoryProvider.d.ts +7 -3
  19. package/provider/MemoryProvider.js +31 -13
  20. package/provider/Provider.d.ts +44 -19
  21. package/provider/ThroughProvider.d.ts +7 -3
  22. package/provider/ThroughProvider.js +16 -4
  23. package/provider/ValidationProvider.d.ts +5 -3
  24. package/provider/ValidationProvider.js +11 -9
  25. package/query/Filter.js +2 -2
  26. package/query/Filters.js +2 -2
  27. package/stream/ArrayState.d.ts +1 -1
  28. package/stream/ArrayState.js +1 -1
  29. package/stream/DataState.d.ts +2 -2
  30. package/stream/State.d.ts +2 -2
  31. package/stream/State.js +3 -3
  32. package/update/DataUpdate.d.ts +25 -0
  33. package/update/DataUpdate.js +25 -0
  34. package/update/EntriesUpdate.d.ts +29 -0
  35. package/update/EntriesUpdate.js +45 -0
  36. package/update/Increment.d.ts +14 -0
  37. package/{transform/IncrementTransform.js → update/Increment.js} +6 -4
  38. package/update/ItemsUpdate.d.ts +21 -0
  39. package/update/ItemsUpdate.js +34 -0
  40. package/update/Update.d.ts +9 -0
  41. package/update/Update.js +6 -0
  42. package/update/hydrations.d.ts +11 -0
  43. package/update/hydrations.js +12 -0
  44. package/update/index.d.ts +7 -0
  45. package/update/index.js +7 -0
  46. package/update/util.d.ts +7 -0
  47. package/update/util.js +42 -0
  48. package/util/filter.d.ts +4 -5
  49. package/util/filter.js +6 -7
  50. package/util/object.d.ts +2 -2
  51. package/util/object.js +2 -2
  52. package/util/transform.d.ts +15 -31
  53. package/util/transform.js +25 -24
  54. package/transform/AddEntriesTransform.d.ts +0 -10
  55. package/transform/AddEntriesTransform.js +0 -16
  56. package/transform/AddItemsTransform.d.ts +0 -10
  57. package/transform/AddItemsTransform.js +0 -16
  58. package/transform/DataTransform.d.ts +0 -24
  59. package/transform/DataTransform.js +0 -24
  60. package/transform/IncrementTransform.d.ts +0 -12
  61. package/transform/RemoveEntriesTransform.d.ts +0 -10
  62. package/transform/RemoveEntriesTransform.js +0 -16
  63. package/transform/RemoveItemsTransform.d.ts +0 -10
  64. package/transform/RemoveItemsTransform.js +0 -16
  65. package/transform/Transform.d.ts +0 -9
  66. package/transform/Transform.js +0 -6
  67. package/transform/hydrations.d.ts +0 -15
  68. package/transform/hydrations.js +0 -16
  69. package/transform/index.d.ts +0 -9
  70. package/transform/index.js +0 -9
  71. package/transform/util.d.ts +0 -7
  72. 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 } 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
  *
@@ -18,8 +18,10 @@ export declare class Database<V extends Validators<Datas> = Validators<Datas>> {
18
18
  query<K extends Key<V>>(collection: K, filters?: Filters<ValidatorType<V[K]>>, sorts?: Sorts<ValidatorType<V[K]>>, limit?: number | null): DataQuery<ValidatorType<V[K]>>;
19
19
  /** Reference a document in a collection in this model. */
20
20
  doc<K extends Key<V>>(collection: K, id: string): DataDocument<ValidatorType<V[K]>>;
21
- /** Perform a write on this database. */
22
- write(write: Write): void | PromiseLike<void>;
21
+ /** Perform a write on this database and return the `Write` instance representing the changes. */
22
+ write(write: Write): Promise<Write>;
23
+ /** Perform multiple writes on this database by combining them into a single `Writes` instance representing the changes. */
24
+ writes(...writes: (Write | undefined)[]): Promise<Writes>;
23
25
  }
24
26
  /** A documents reference within a specific database. */
25
27
  export declare class DataQuery<T extends Data = Data> extends Query<T> implements Observable<Results<T>>, Validatable<Results<T>>, Iterable<Entry<T>> {
@@ -83,22 +85,15 @@ export declare class DataQuery<T extends Data = Data> extends Query<T> implement
83
85
  /**
84
86
  * Update all matching documents with the same partial value.
85
87
  *
86
- * @param transform `Transform` instance or set of transforms to apply to every matching document.
87
- * - Not all transforms may be supported by all providers.
88
- *
88
+ * @param updates `Update` instance or set of updates to apply to every matching document.
89
89
  * @return Nothing (possibly promised).
90
90
  */
91
- update(transform: Transform<T> | Transforms<T>): void | PromiseLike<void>;
91
+ update(updates: Update<T> | PropUpdates<T>): void | PromiseLike<void>;
92
92
  /**
93
93
  * Delete all matching documents.
94
94
  * @return Nothing (possibly promised).
95
95
  */
96
96
  delete(): void | PromiseLike<void>;
97
- /**
98
- * Combine `set()`, `update()`, `delete()` into a single method.
99
- * @return Nothing (possibly promised).
100
- */
101
- write(value: Result<T> | Transform<T>): void | PromiseLike<void>;
102
97
  /** Iterate over the resuls (will throw `Promise` if the results are asynchronous). */
103
98
  [Symbol.iterator](): Iterator<Entry<T>, void>;
104
99
  /** Validate a set of results for this query reference. */
@@ -147,19 +142,15 @@ export declare class DataDocument<T extends Data = Data> implements Observable<R
147
142
  /** Set the complete data of this document. */
148
143
  set(data: T): void | PromiseLike<void>;
149
144
  /** Update this document. */
150
- update(transforms: Transform<T> | Transforms<T>): void | PromiseLike<void>;
145
+ update(updates: Update<T> | PropUpdates<T>): void | PromiseLike<void>;
151
146
  /** Delete this document. */
152
147
  delete(): void | PromiseLike<void>;
153
- /** Set, update, or delete this document. */
154
- write(value: Result<T> | Transform<T>): void | PromiseLike<void>;
155
148
  /** Represent a write that sets the complete data of this document in a database. */
156
- setter(data: T): DocumentWrite<T>;
149
+ setter(data: T): DocumentSet<T>;
157
150
  /** Represent a write that updates this document in a database. */
158
- updater(transforms: Transform<T> | Transforms<T>): DocumentWrite<T>;
151
+ updater(updates: Update<T> | PropUpdates<T>): DocumentUpdate<T>;
159
152
  /** Represent a write that deletes this document in a database. */
160
- deleter(): DocumentWrite<T>;
161
- /** Represent a write that sets, updates, or deletes this document in a database. */
162
- writer(value: Result<T> | Transform<T>): DocumentWrite<T>;
153
+ deleter(): DocumentDelete<T>;
163
154
  /** Validate data for this query reference. */
164
155
  validate(unsafeData: Data): T;
165
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 } 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
  *
@@ -25,9 +25,16 @@ export class Database {
25
25
  doc(collection, id) {
26
26
  return new DataDocument(this.provider, this.validators[collection], collection, id);
27
27
  }
28
- /** Perform a write on this database. */
29
- write(write) {
30
- return write.transform(this);
28
+ /** Perform a write on this database and return the `Write` instance representing the changes. */
29
+ async write(write) {
30
+ await write.transform(this);
31
+ return write;
32
+ }
33
+ /** Perform multiple writes on this database by combining them into a single `Writes` instance representing the changes. */
34
+ async writes(...writes) {
35
+ const write = new Writes(...writes);
36
+ await write.transform(this);
37
+ return write;
31
38
  }
32
39
  }
33
40
  /** A documents reference within a specific database. */
@@ -107,32 +114,23 @@ export class DataQuery extends Query {
107
114
  * @return Nothing (possibly promised).
108
115
  */
109
116
  set(data) {
110
- return this.write(data);
117
+ return this.provider.setQuery(this, data);
111
118
  }
112
119
  /**
113
120
  * Update all matching documents with the same partial value.
114
121
  *
115
- * @param transform `Transform` instance or set of transforms to apply to every matching document.
116
- * - Not all transforms may be supported by all providers.
117
- *
122
+ * @param updates `Update` instance or set of updates to apply to every matching document.
118
123
  * @return Nothing (possibly promised).
119
124
  */
120
- update(transform) {
121
- 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));
122
127
  }
123
128
  /**
124
129
  * Delete all matching documents.
125
130
  * @return Nothing (possibly promised).
126
131
  */
127
132
  delete() {
128
- return this.write(undefined);
129
- }
130
- /**
131
- * Combine `set()`, `update()`, `delete()` into a single method.
132
- * @return Nothing (possibly promised).
133
- */
134
- write(value) {
135
- return this.provider.writeQuery(this, value);
133
+ return this.provider.deleteQuery(this);
136
134
  }
137
135
  /** Iterate over the resuls (will throw `Promise` if the results are asynchronous). */
138
136
  [Symbol.iterator]() {
@@ -215,35 +213,27 @@ export class DataDocument {
215
213
  }
216
214
  /** Set the complete data of this document. */
217
215
  set(data) {
218
- return this.write(data);
216
+ return this.provider.set(this, data);
219
217
  }
220
218
  /** Update this document. */
221
- update(transforms) {
222
- 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));
223
221
  }
224
222
  /** Delete this document. */
225
223
  delete() {
226
- return this.write(undefined);
227
- }
228
- /** Set, update, or delete this document. */
229
- write(value) {
230
- return this.provider.write(this, value);
224
+ return this.provider.delete(this);
231
225
  }
232
226
  /** Represent a write that sets the complete data of this document in a database. */
233
227
  setter(data) {
234
- return this.writer(data);
228
+ return new DocumentSet(this, data);
235
229
  }
236
230
  /** Represent a write that updates this document in a database. */
237
- updater(transforms) {
238
- return this.writer(transforms instanceof Transform ? transforms : new DataTransform(transforms));
231
+ updater(updates) {
232
+ return new DocumentUpdate(this, updates);
239
233
  }
240
234
  /** Represent a write that deletes this document in a database. */
241
235
  deleter() {
242
- return this.writer(undefined);
243
- }
244
- /** Represent a write that sets, updates, or deletes this document in a database. */
245
- writer(value) {
246
- return new DocumentWrite(this, value);
236
+ return new DocumentDelete(this);
247
237
  }
248
238
  /** Validate data for this query reference. */
249
239
  validate(unsafeData) {
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.
@@ -20,11 +12,35 @@ export declare class DocumentWrite<T extends Data> extends Write {
20
12
  */
21
13
  export declare class Writes extends Write {
22
14
  readonly writes: ImmutableArray<Write>;
23
- constructor(...writes: Write[]);
15
+ constructor(...writes: (Write | undefined)[]);
16
+ transform(db: Database): Promise<void>;
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> {
24
38
  transform(db: Database): Promise<void>;
25
39
  }
26
40
  /** Set of hydrations for all change classes. */
27
- export declare const DATABASE_HYDRATIONS: {
28
- writes: typeof Writes;
29
- write: typeof DocumentWrite;
41
+ export declare const WRITE_HYDRATIONS: {
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,16 +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;
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
  }
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
+ }
32
55
  /** Set of hydrations for all change classes. */
33
- export const DATABASE_HYDRATIONS = {
34
- writes: Writes,
35
- write: DocumentWrite,
56
+ export const WRITE_HYDRATIONS = {
57
+ Writes,
58
+ DocumentSet,
59
+ DocumentUpdate,
60
+ DocumentDelete,
36
61
  };
37
- DATABASE_HYDRATIONS;
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<void>;
21
+ updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>): Promise<void>;
22
+ deleteQuery<T extends Data>(ref: DataQuery<T>): Promise<void>;
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,24 @@ 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)
112
+ if (data instanceof Update) {
113
+ const updates = getFieldValues(data);
115
114
  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)));
115
+ }
116
+ else if (data)
117
+ await Promise.all(snapshot.docs.map(s => setDoc(s.ref, data)));
118
118
  else
119
119
  await Promise.all(snapshot.docs.map(s => deleteDoc(s.ref)));
120
120
  }
121
+ async updateQuery(ref, updates) {
122
+ const snapshot = await getDocs(getQuery(this.firestore, ref));
123
+ const fieldValues = getFieldValues(updates);
124
+ await Promise.all(snapshot.docs.map(s => updateDoc(s.ref, fieldValues)));
125
+ }
126
+ async deleteQuery(ref) {
127
+ const snapshot = await getDocs(getQuery(this.firestore, ref));
128
+ await Promise.all(snapshot.docs.map(s => deleteDoc(s.ref)));
129
+ }
121
130
  }
@@ -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<void>;
21
+ updateQuery<T extends Data>(ref: DataQuery<T>, updates: Update<T>): Promise<void>;
22
+ deleteQuery<T extends Data>(ref: DataQuery<T>): Promise<void>;
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, setDoc, addDoc, updateDoc, deleteDoc, getDoc, getDocs, } from "firebase/firestore/lite";
2
- import { Provider, Transform, AddItemsTransform, AddEntriesTransform, IncrementTransform, RemoveItemsTransform, RemoveEntriesTransform, AssertionError, DataTransform, } from "../../index.js";
2
+ import { Provider, Update, EntriesUpdate, Increment, AssertionError, DataUpdate, 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
  /**
@@ -94,13 +92,14 @@ export class FirestoreClientProvider extends Provider {
94
92
  const reference = await addDoc(getCollection(this.firestore, ref), data); // eslint-disable-line @typescript-eslint/no-explicit-any
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,17 @@ export class FirestoreClientProvider extends Provider {
108
107
  subscribeQuery() {
109
108
  throw new Error("FirestoreLiteProvider does not support realtime subscriptions");
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
+ }
114
+ async updateQuery(ref, updates) {
115
+ const snapshot = await getDocs(getQuery(this.firestore, ref));
116
+ const fieldValues = getFieldValues(updates);
117
+ await Promise.all(snapshot.docs.map(s => updateDoc(s.ref, fieldValues)));
118
+ }
119
+ async deleteQuery(ref) {
120
+ const snapshot = await getDocs(getQuery(this.firestore, ref));
121
+ await Promise.all(snapshot.docs.map(s => deleteDoc(s.ref)));
120
122
  }
121
123
  }