shelving 1.25.0 → 1.28.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 (81) hide show
  1. package/db/Database.d.ts +15 -26
  2. package/db/Database.js +22 -40
  3. package/db/Pagination.d.ts +2 -10
  4. package/db/Pagination.js +16 -39
  5. package/db/Write.d.ts +29 -13
  6. package/db/Write.js +42 -17
  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 +18 -3
  32. package/stream/DataState.js +35 -4
  33. package/stream/State.d.ts +2 -4
  34. package/stream/State.js +4 -12
  35. package/update/DataUpdate.d.ts +25 -0
  36. package/update/DataUpdate.js +25 -0
  37. package/update/EntriesUpdate.d.ts +29 -0
  38. package/update/EntriesUpdate.js +45 -0
  39. package/update/Increment.d.ts +14 -0
  40. package/{transform/IncrementTransform.js → update/Increment.js} +6 -4
  41. package/update/ItemsUpdate.d.ts +21 -0
  42. package/update/ItemsUpdate.js +34 -0
  43. package/update/Update.d.ts +9 -0
  44. package/update/Update.js +6 -0
  45. package/update/hydrations.d.ts +11 -0
  46. package/update/hydrations.js +12 -0
  47. package/update/index.d.ts +7 -0
  48. package/update/index.js +7 -0
  49. package/update/util.d.ts +7 -0
  50. package/update/util.js +42 -0
  51. package/util/data.d.ts +0 -3
  52. package/util/data.js +0 -5
  53. package/util/filter.d.ts +4 -5
  54. package/util/filter.js +6 -7
  55. package/util/null.d.ts +11 -0
  56. package/util/null.js +10 -0
  57. package/util/object.d.ts +2 -2
  58. package/util/object.js +2 -2
  59. package/util/transform.d.ts +14 -19
  60. package/util/transform.js +25 -24
  61. package/util/url.d.ts +8 -9
  62. package/util/url.js +16 -15
  63. package/transform/AddEntriesTransform.d.ts +0 -10
  64. package/transform/AddEntriesTransform.js +0 -16
  65. package/transform/AddItemsTransform.d.ts +0 -10
  66. package/transform/AddItemsTransform.js +0 -16
  67. package/transform/DataTransform.d.ts +0 -27
  68. package/transform/DataTransform.js +0 -29
  69. package/transform/IncrementTransform.d.ts +0 -12
  70. package/transform/RemoveEntriesTransform.d.ts +0 -10
  71. package/transform/RemoveEntriesTransform.js +0 -16
  72. package/transform/RemoveItemsTransform.d.ts +0 -10
  73. package/transform/RemoveItemsTransform.js +0 -16
  74. package/transform/Transform.d.ts +0 -9
  75. package/transform/Transform.js +0 -6
  76. package/transform/hydrations.d.ts +0 -15
  77. package/transform/hydrations.js +0 -16
  78. package/transform/index.d.ts +0 -9
  79. package/transform/index.js +0 -9
  80. package/transform/util.d.ts +0 -7
  81. package/transform/util.js +0 -42
package/db/Database.d.ts CHANGED
@@ -1,8 +1,8 @@
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";
1
+ import { Entry, Observable, Observer, Result, Unsubscriber, ResultsMap, Validatable, Validator, Key, Data, Results, Datas, Validators, ValidatorType, Dispatcher, Nullish } from "../util/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 } from "./Write.js";
6
6
  /**
7
7
  * Combines a database model and a provider.
8
8
  *
@@ -18,10 +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 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>;
21
+ /** Create a writer for this database from a set of separate writes. */
22
+ writer(...writes: Nullish<Write>[]): Write;
23
+ /** Perform one or more writes on this database and return the `Writes` instance representing the combined changes. */
24
+ write(...writes: Nullish<Write>[]): Promise<Write>;
25
25
  }
26
26
  /** A documents reference within a specific database. */
27
27
  export declare class DataQuery<T extends Data = Data> extends Query<T> implements Observable<Results<T>>, Validatable<Results<T>>, Iterable<Entry<T>> {
@@ -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
- import { callAsync, getFirstItem, throwAsync, validate, toMap, countItems, TransformObserver, } from "../util/index.js";
2
- import { DataTransform, Transform } from "../transform/index.js";
1
+ import { callAsync, getFirstItem, throwAsync, validate, toMap, countItems, TransformObserver, NOT_NULLISH, } from "../util/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
  *
@@ -25,14 +25,13 @@ 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 and return the `Write` instance representing the changes. */
29
- async write(write) {
30
- await write.transform(this);
31
- return write;
28
+ /** Create a writer for this database from a set of separate writes. */
29
+ writer(...writes) {
30
+ return new Writes(...writes.filter(NOT_NULLISH));
32
31
  }
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);
32
+ /** Perform one or more writes on this database and return the `Writes` instance representing the combined changes. */
33
+ async write(...writes) {
34
+ const write = new Writes(...writes.filter(NOT_NULLISH));
36
35
  await write.transform(this);
37
36
  return write;
38
37
  }
@@ -114,32 +113,23 @@ export class DataQuery extends Query {
114
113
  * @return Nothing (possibly promised).
115
114
  */
116
115
  set(data) {
117
- return this.write(data);
116
+ return this.provider.setQuery(this, data);
118
117
  }
119
118
  /**
120
119
  * Update all matching documents with the same partial value.
121
120
  *
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
- *
121
+ * @param updates `Update` instance or set of updates to apply to every matching document.
125
122
  * @return Nothing (possibly promised).
126
123
  */
127
- update(transform) {
128
- return this.write(transform instanceof Transform ? transform : new DataTransform(transform));
124
+ update(updates) {
125
+ return this.provider.updateQuery(this, updates instanceof Update ? updates : new DataUpdate(updates));
129
126
  }
130
127
  /**
131
128
  * Delete all matching documents.
132
129
  * @return Nothing (possibly promised).
133
130
  */
134
131
  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);
132
+ return this.provider.deleteQuery(this);
143
133
  }
144
134
  /** Iterate over the resuls (will throw `Promise` if the results are asynchronous). */
145
135
  [Symbol.iterator]() {
@@ -222,35 +212,27 @@ export class DataDocument {
222
212
  }
223
213
  /** Set the complete data of this document. */
224
214
  set(data) {
225
- return this.write(data);
215
+ return this.provider.set(this, data);
226
216
  }
227
217
  /** Update this document. */
228
- update(transforms) {
229
- return this.write(transforms instanceof Transform ? transforms : new DataTransform(transforms));
218
+ update(updates) {
219
+ return this.provider.update(this, updates instanceof Update ? updates : new DataUpdate(updates));
230
220
  }
231
221
  /** Delete this document. */
232
222
  delete() {
233
- return this.write(undefined);
234
- }
235
- /** Set, update, or delete this document. */
236
- write(value) {
237
- return this.provider.write(this, value);
223
+ return this.provider.delete(this);
238
224
  }
239
225
  /** Represent a write that sets the complete data of this document in a database. */
240
226
  setter(data) {
241
- return this.writer(data);
227
+ return new DocumentSet(this, data);
242
228
  }
243
229
  /** Represent a write that updates this document in a database. */
244
- updater(transforms) {
245
- return this.writer(transforms instanceof Transform ? transforms : new DataTransform(transforms));
230
+ updater(updates) {
231
+ return new DocumentUpdate(this, updates);
246
232
  }
247
233
  /** Represent a write that deletes this document in a database. */
248
234
  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);
235
+ return new DocumentDelete(this);
254
236
  }
255
237
  /** Validate data for this query reference. */
256
238
  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.
@@ -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 | undefined)[]);
15
+ constructor(...writes: Write[]);
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
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, IS_DEFINED } from "../util/index.js";
2
- /** Write to a database. */
1
+ import { DataUpdate, Update } from "../update/index.js";
2
+ import { transform } 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.filter(IS_DEFINED);
14
+ this.writes = writes;
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
56
  export const WRITE_HYDRATIONS = {
34
- writes: Writes,
35
- write: DocumentWrite,
57
+ Writes,
58
+ DocumentSet,
59
+ DocumentUpdate,
60
+ DocumentDelete,
36
61
  };
37
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
  }