shelving 1.91.2 → 1.92.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/db/Change.d.ts +19 -20
  2. package/db/Change.js +22 -21
  3. package/db/CollectionReference.d.ts +103 -0
  4. package/db/CollectionReference.js +127 -0
  5. package/db/Database.d.ts +21 -23
  6. package/db/Database.js +18 -18
  7. package/db/{Item.d.ts → ItemReference.d.ts} +13 -14
  8. package/db/{Item.js → ItemReference.js} +14 -17
  9. package/db/ItemState.d.ts +3 -3
  10. package/db/{Query.d.ts → QueryReference.d.ts} +25 -33
  11. package/db/QueryReference.js +101 -0
  12. package/db/QueryState.d.ts +10 -10
  13. package/db/QueryState.js +20 -18
  14. package/db/index.d.ts +3 -3
  15. package/db/index.js +3 -3
  16. package/firestore/client/FirestoreClientProvider.d.ts +13 -13
  17. package/firestore/client/FirestoreClientProvider.js +55 -84
  18. package/firestore/lite/FirestoreLiteProvider.d.ts +11 -11
  19. package/firestore/lite/FirestoreLiteProvider.js +52 -83
  20. package/firestore/server/FirestoreServerProvider.d.ts +13 -13
  21. package/firestore/server/FirestoreServerProvider.js +51 -84
  22. package/index.d.ts +0 -2
  23. package/index.js +0 -2
  24. package/package.json +1 -3
  25. package/provider/CacheProvider.d.ts +7 -7
  26. package/provider/CacheProvider.js +14 -14
  27. package/provider/DebugProvider.d.ts +11 -11
  28. package/provider/DebugProvider.js +28 -29
  29. package/provider/MemoryProvider.d.ts +17 -17
  30. package/provider/MemoryProvider.js +41 -43
  31. package/provider/Provider.d.ts +15 -15
  32. package/provider/ThroughProvider.d.ts +12 -12
  33. package/provider/ThroughProvider.js +20 -20
  34. package/provider/ValidationProvider.d.ts +11 -11
  35. package/provider/ValidationProvider.js +16 -12
  36. package/react/useData.d.ts +5 -5
  37. package/react/useData.js +2 -2
  38. package/state/DataState.d.ts +4 -8
  39. package/state/DataState.js +6 -16
  40. package/state/DictionaryState.d.ts +4 -6
  41. package/state/DictionaryState.js +4 -9
  42. package/test/basics.d.ts +1 -1
  43. package/test/people.d.ts +1 -1
  44. package/test/util.d.ts +1 -1
  45. package/test/util.js +1 -1
  46. package/util/data.d.ts +2 -2
  47. package/util/equal.js +5 -5
  48. package/util/hydrate.d.ts +13 -26
  49. package/util/hydrate.js +44 -60
  50. package/util/index.d.ts +2 -0
  51. package/util/index.js +2 -0
  52. package/util/iterate.d.ts +2 -0
  53. package/util/match.d.ts +2 -10
  54. package/util/match.js +4 -8
  55. package/util/query.d.ts +83 -0
  56. package/util/query.js +129 -0
  57. package/util/sort.d.ts +8 -15
  58. package/util/sort.js +15 -19
  59. package/util/transform.d.ts +26 -45
  60. package/util/transform.js +24 -29
  61. package/util/update.d.ts +22 -0
  62. package/util/update.js +42 -0
  63. package/util/validate.js +2 -2
  64. package/constraint/Constraint.d.ts +0 -7
  65. package/constraint/Constraint.js +0 -3
  66. package/constraint/Constraints.d.ts +0 -20
  67. package/constraint/Constraints.js +0 -34
  68. package/constraint/Filter.d.ts +0 -34
  69. package/constraint/Filter.js +0 -89
  70. package/constraint/Filters.d.ts +0 -27
  71. package/constraint/Filters.js +0 -41
  72. package/constraint/Sort.d.ts +0 -18
  73. package/constraint/Sort.js +0 -33
  74. package/constraint/Sorts.d.ts +0 -26
  75. package/constraint/Sorts.js +0 -47
  76. package/constraint/Statement.d.ts +0 -45
  77. package/constraint/Statement.js +0 -79
  78. package/constraint/index.d.ts +0 -7
  79. package/constraint/index.js +0 -7
  80. package/db/Collection.d.ts +0 -64
  81. package/db/Collection.js +0 -83
  82. package/db/Query.js +0 -94
  83. package/update/ArrayUpdate.d.ts +0 -17
  84. package/update/ArrayUpdate.js +0 -31
  85. package/update/DataUpdate.d.ts +0 -37
  86. package/update/DataUpdate.js +0 -44
  87. package/update/Delete.d.ts +0 -10
  88. package/update/Delete.js +0 -12
  89. package/update/DictionaryUpdate.d.ts +0 -31
  90. package/update/DictionaryUpdate.js +0 -62
  91. package/update/Increment.d.ts +0 -18
  92. package/update/Increment.js +0 -22
  93. package/update/Update.d.ts +0 -8
  94. package/update/Update.js +0 -6
  95. package/update/hydrations.d.ts +0 -3
  96. package/update/hydrations.js +0 -13
  97. package/update/index.d.ts +0 -7
  98. package/update/index.js +0 -7
package/db/ItemState.d.ts CHANGED
@@ -1,17 +1,17 @@
1
- import type { AsyncItem, Item, ItemData, ItemValue } from "./Item.js";
1
+ import type { AsyncItemReference, ItemData, ItemReference, ItemValue } from "./ItemReference.js";
2
2
  import type { Data } from "../util/data.js";
3
3
  import type { Dispatch } from "../util/function.js";
4
4
  import { BooleanState } from "../state/BooleanState.js";
5
5
  import { State } from "../state/State.js";
6
6
  /** Hold the current state of a item. */
7
7
  export declare class ItemState<T extends Data = Data> extends State<ItemValue<T>> {
8
- readonly ref: Item<T> | AsyncItem<T>;
8
+ readonly ref: ItemReference<T> | AsyncItemReference<T>;
9
9
  readonly busy: BooleanState;
10
10
  /** Get the data of the item (throws `RequiredError` if item doesn't exist). */
11
11
  get data(): ItemData<T>;
12
12
  /** Does the item exist (i.e. its value isn't `null`)? */
13
13
  get exists(): boolean;
14
- constructor(ref: Item<T> | AsyncItem<T>);
14
+ constructor(ref: ItemReference<T> | AsyncItemReference<T>);
15
15
  /** Refresh this state from the source provider. */
16
16
  readonly refresh: () => void;
17
17
  private _refresh;
@@ -1,20 +1,21 @@
1
- import type { ItemArray, ItemData, ItemValue } from "./Item.js";
2
- import type { PossibleFilters } from "../constraint/Filters.js";
3
- import type { PossibleSorts } from "../constraint/Sorts.js";
1
+ import type { ItemArray, ItemData, ItemQuery, ItemValue } from "./ItemReference.js";
4
2
  import type { AsyncProvider, Provider } from "../provider/Provider.js";
5
- import type { Updates } from "../update/DataUpdate.js";
6
3
  import type { Data } from "../util/data.js";
7
4
  import type { Dispatch, Handler, Stop } from "../util/function.js";
8
- import { Statement } from "../constraint/Statement.js";
5
+ import type { Updates } from "../util/update.js";
9
6
  /** Reference to a set of items in a sync or async provider. */
10
- declare abstract class BaseQuery<T extends Data = Data> extends Statement<ItemData<T>> implements AsyncIterable<ItemArray<T>> {
7
+ declare abstract class AbstractQueryReference<T extends Data = Data> implements AsyncIterable<ItemArray<T>> {
11
8
  abstract readonly provider: Provider | AsyncProvider;
12
- abstract readonly collection: string;
9
+ readonly collection: string;
10
+ readonly query: ItemQuery<T>;
11
+ constructor(collection: string, query?: ItemQuery<T>);
12
+ /** Get a copy of this query reference with additional query props. */
13
+ with(query: ItemQuery<T>): this;
13
14
  /**
14
15
  * Get array of entities for this query.
15
16
  * @return Array of entities.
16
17
  */
17
- abstract value: ItemArray<T> | PromiseLike<ItemArray<T>>;
18
+ abstract items: ItemArray<T> | PromiseLike<ItemArray<T>>;
18
19
  /**
19
20
  * Count the number of results of this set of items.
20
21
  * @return Number of items matching the query (possibly promised).
@@ -29,22 +30,17 @@ declare abstract class BaseQuery<T extends Data = Data> extends Statement<ItemDa
29
30
  * Get the first item matched by this query or `null` if this query has no results.
30
31
  * @throws RequiredError if there were no results for this query.
31
32
  */
32
- abstract firstValue: ItemValue<T> | PromiseLike<ItemValue<T>>;
33
- /**
34
- * Get the first item matched by this query.
35
- * @throws RequiredError if there were no results for this query.
36
- */
37
- abstract firstData: ItemData<T> | PromiseLike<ItemData<T>>;
33
+ abstract first: ItemValue<T> | PromiseLike<ItemValue<T>>;
38
34
  /**
39
35
  * Get the last item matched by this query or `null` if this query has no results.
40
36
  * @throws RequiredError if there were no results for this query.
41
37
  */
42
- abstract lastValue: ItemValue<T> | PromiseLike<ItemValue<T>>;
38
+ abstract last: ItemValue<T> | PromiseLike<ItemValue<T>>;
43
39
  /**
44
- * Get the last item matched by this query.
40
+ * Get the first item matched by this query.
45
41
  * @throws RequiredError if there were no results for this query.
46
42
  */
47
- abstract lastData: ItemData<T> | PromiseLike<ItemData<T>>;
43
+ abstract data: ItemData<T> | PromiseLike<ItemData<T>>;
48
44
  /**
49
45
  * Set all matching items to the same exact value.
50
46
  *
@@ -70,33 +66,29 @@ declare abstract class BaseQuery<T extends Data = Data> extends Statement<ItemDa
70
66
  [Symbol.asyncIterator](): AsyncIterator<ItemArray<T>>;
71
67
  }
72
68
  /** Reference to a set of items in a provider. */
73
- export declare class Query<T extends Data = Data> extends BaseQuery<T> {
69
+ export declare class QueryReference<T extends Data = Data> extends AbstractQueryReference<T> {
74
70
  readonly provider: Provider;
75
- readonly collection: string;
76
- constructor(provider: Provider, collection: string, filters?: PossibleFilters<ItemData<T>>, sorts?: PossibleSorts<ItemData<T>>, limit?: number | null);
77
- get value(): ItemArray<T>;
71
+ constructor(provider: Provider, collection: string, query?: ItemQuery<T>);
72
+ get items(): ItemArray<T>;
78
73
  get count(): number;
79
74
  get exists(): boolean;
80
- get firstValue(): ItemValue<T>;
81
- get firstData(): ItemData<T>;
82
- get lastValue(): ItemValue<T>;
83
- get lastData(): ItemData<T>;
75
+ get first(): ItemValue<T>;
76
+ get last(): ItemValue<T>;
77
+ get data(): ItemData<T>;
84
78
  set(data: T): number;
85
79
  update(updates: Updates<T>): number;
86
80
  delete(): number;
87
81
  }
88
82
  /** Reference to a set of items in a provider. */
89
- export declare class AsyncQuery<T extends Data = Data> extends BaseQuery<T> {
83
+ export declare class AsyncQueryReference<T extends Data = Data> extends AbstractQueryReference<T> {
90
84
  readonly provider: AsyncProvider;
91
- readonly collection: string;
92
- constructor(provider: AsyncProvider, collection: string, filters?: PossibleFilters<ItemData<T>>, sorts?: PossibleSorts<ItemData<T>>, limit?: number | null);
93
- get value(): Promise<ItemArray<T>>;
85
+ constructor(provider: AsyncProvider, collection: string, query?: ItemQuery<T>);
86
+ get items(): Promise<ItemArray<T>>;
94
87
  get count(): Promise<number>;
95
88
  get exists(): Promise<boolean>;
96
- get firstValue(): Promise<ItemValue<T>>;
97
- get firstData(): Promise<ItemData<T>>;
98
- get lastValue(): Promise<ItemValue<T>>;
99
- get lastData(): Promise<ItemData<T>>;
89
+ get first(): Promise<ItemValue<T>>;
90
+ get last(): Promise<ItemValue<T>>;
91
+ get data(): Promise<ItemData<T>>;
100
92
  set(data: T): Promise<number>;
101
93
  update(updates: Updates<T>): PromiseLike<number>;
102
94
  delete(): PromiseLike<number>;
@@ -0,0 +1,101 @@
1
+ import { countArray, getOptionalFirstItem, getOptionalLastItem, isArrayLength } from "../util/array.js";
2
+ import { getData } from "../util/data.js";
3
+ import { cloneObjectWith } from "../util/object.js";
4
+ import { runSequence } from "../util/sequence.js";
5
+ /** Reference to a set of items in a sync or async provider. */
6
+ class AbstractQueryReference {
7
+ constructor(collection, query = {}) {
8
+ this.collection = collection;
9
+ this.query = query;
10
+ }
11
+ /** Get a copy of this query reference with additional query props. */
12
+ with(query) {
13
+ return cloneObjectWith(this, "query", { ...this.query, query });
14
+ }
15
+ // Implement toString()
16
+ toString() {
17
+ return `${this.collection}?{${JSON.stringify(this.query)}`;
18
+ }
19
+ /** Subscribe to this item. */
20
+ subscribe(onNext, onError) {
21
+ return runSequence(this, onNext, onError);
22
+ }
23
+ // Implement AsyncIterable
24
+ [Symbol.asyncIterator]() {
25
+ return this.provider.getQuerySequence(this.collection, this.query)[Symbol.asyncIterator]();
26
+ }
27
+ }
28
+ /** Reference to a set of items in a provider. */
29
+ export class QueryReference extends AbstractQueryReference {
30
+ constructor(provider, collection, query) {
31
+ super(collection, query);
32
+ this.provider = provider;
33
+ }
34
+ get items() {
35
+ return _getItemArray(this);
36
+ }
37
+ get count() {
38
+ return this.items.length;
39
+ }
40
+ get exists() {
41
+ return !!_getSingleItemArray(this).length;
42
+ }
43
+ get first() {
44
+ return getOptionalFirstItem(_getSingleItemArray(this));
45
+ }
46
+ get last() {
47
+ return getOptionalLastItem(this.items);
48
+ }
49
+ get data() {
50
+ return getData(this.first);
51
+ }
52
+ set(data) {
53
+ return this.provider.setQuery(this.collection, this.query, data);
54
+ }
55
+ update(updates) {
56
+ return this.provider.updateQuery(this.collection, this.query, updates);
57
+ }
58
+ delete() {
59
+ return this.provider.deleteQuery(this.collection, this.query);
60
+ }
61
+ }
62
+ /** Reference to a set of items in a provider. */
63
+ export class AsyncQueryReference extends AbstractQueryReference {
64
+ constructor(provider, collection, query) {
65
+ super(collection, query);
66
+ this.provider = provider;
67
+ }
68
+ get items() {
69
+ return _getItemArray(this);
70
+ }
71
+ get count() {
72
+ return this.items.then(countArray);
73
+ }
74
+ get exists() {
75
+ return _getSingleItemArray(this).then(isArrayLength);
76
+ }
77
+ get first() {
78
+ return _getSingleItemArray(this).then(getOptionalFirstItem);
79
+ }
80
+ get last() {
81
+ return this.items.then(getOptionalLastItem);
82
+ }
83
+ get data() {
84
+ return this.first.then(getData);
85
+ }
86
+ set(data) {
87
+ return this.provider.setQuery(this.collection, this.query, data);
88
+ }
89
+ update(updates) {
90
+ return this.provider.updateQuery(this.collection, this.query, updates);
91
+ }
92
+ delete() {
93
+ return this.provider.deleteQuery(this.collection, this.query);
94
+ }
95
+ }
96
+ function _getItemArray({ provider, collection, query }) {
97
+ return provider.getQuery(collection, query);
98
+ }
99
+ function _getSingleItemArray({ provider, collection, query }) {
100
+ return provider.getQuery(collection, { ...query, $limit: 1 });
101
+ }
@@ -1,30 +1,30 @@
1
- import type { ItemArray, ItemData, ItemValue } from "../db/Item.js";
2
- import type { AsyncQuery, Query } from "../db/Query.js";
1
+ import type { ItemArray, ItemData, ItemValue } from "./ItemReference.js";
2
+ import type { AsyncQueryReference, QueryReference } from "./QueryReference.js";
3
3
  import type { Data } from "../util/data.js";
4
4
  import type { Stop } from "../util/function.js";
5
5
  import { BooleanState } from "../state/BooleanState.js";
6
6
  import { State } from "../state/State.js";
7
7
  /** Hold the current state of a query. */
8
8
  export declare class QueryState<T extends Data = Data> extends State<ItemArray<T>> implements Iterable<ItemData<T>> {
9
- readonly ref: Query<T> | AsyncQuery<T>;
9
+ readonly ref: QueryReference<T> | AsyncQueryReference<T>;
10
10
  readonly busy: BooleanState;
11
11
  readonly limit: number;
12
12
  /** Can more items be loaded after the current result. */
13
13
  get hasMore(): boolean;
14
14
  private _hasMore;
15
+ /** Get the items currently stored in this query. */
16
+ get items(): ItemArray<T>;
15
17
  /** Get the first document matched by this query or `null` if this query has no items. */
16
- get firstValue(): ItemValue<T>;
17
- /** Get the first document matched by this query. */
18
- get firstData(): ItemData<T>;
18
+ get first(): ItemValue<T>;
19
19
  /** Get the last document matched by this query or `null` if this query has no items. */
20
- get lastValue(): ItemValue<T>;
21
- /** Get the last document matched by this query. */
22
- get lastData(): ItemData<T>;
20
+ get last(): ItemValue<T>;
21
+ /** Get the first document matched by this query. */
22
+ get data(): ItemData<T>;
23
23
  /** Does the document have at least one result. */
24
24
  get exists(): boolean;
25
25
  /** Get the number of items matching this query. */
26
26
  get count(): number;
27
- constructor(ref: Query<T> | AsyncQuery<T>);
27
+ constructor(ref: QueryReference<T> | AsyncQueryReference<T>);
28
28
  /** Refresh this state from the source provider. */
29
29
  readonly refresh: () => void;
30
30
  private _refresh;
package/db/QueryState.js CHANGED
@@ -2,7 +2,9 @@ import { CacheProvider } from "../provider/CacheProvider.js";
2
2
  import { LazyDeferredSequence } from "../sequence/LazyDeferredSequence.js";
3
3
  import { BooleanState } from "../state/BooleanState.js";
4
4
  import { State } from "../state/State.js";
5
- import { getFirstItem, getLastItem, getOptionalFirstItem, getOptionalLastItem } from "../util/array.js";
5
+ import { getOptionalFirstItem, getOptionalLastItem } from "../util/array.js";
6
+ import { getData } from "../util/data.js";
7
+ import { getAfterQuery, getLimit } from "../util/query.js";
6
8
  import { getOptionalSource } from "../util/source.js";
7
9
  /** Hold the current state of a query. */
8
10
  export class QueryState extends State {
@@ -10,21 +12,21 @@ export class QueryState extends State {
10
12
  get hasMore() {
11
13
  return this._hasMore;
12
14
  }
15
+ /** Get the items currently stored in this query. */
16
+ get items() {
17
+ return this.value;
18
+ }
13
19
  /** Get the first document matched by this query or `null` if this query has no items. */
14
- get firstValue() {
20
+ get first() {
15
21
  return getOptionalFirstItem(this.value);
16
22
  }
17
- /** Get the first document matched by this query. */
18
- get firstData() {
19
- return getFirstItem(this.value);
20
- }
21
23
  /** Get the last document matched by this query or `null` if this query has no items. */
22
- get lastValue() {
24
+ get last() {
23
25
  return getOptionalLastItem(this.value);
24
26
  }
25
- /** Get the last document matched by this query. */
26
- get lastData() {
27
- return getLastItem(this.value);
27
+ /** Get the first document matched by this query. */
28
+ get data() {
29
+ return getData(this.first);
28
30
  }
29
31
  /** Does the document have at least one result. */
30
32
  get exists() {
@@ -35,8 +37,8 @@ export class QueryState extends State {
35
37
  return this.value.length;
36
38
  }
37
39
  constructor(ref) {
38
- var _a;
39
- const { provider, collection, limit } = ref;
40
+ var _a, _b;
41
+ const { provider, collection, query } = ref;
40
42
  const table = (_a = getOptionalSource(CacheProvider, provider)) === null || _a === void 0 ? void 0 : _a.memory.getTable(collection);
41
43
  const time = table ? table.getQueryTime(ref) : null;
42
44
  const isCached = typeof time === "number";
@@ -58,7 +60,7 @@ export class QueryState extends State {
58
60
  };
59
61
  this._time = time;
60
62
  this.ref = ref;
61
- this.limit = limit !== null && limit !== void 0 ? limit : Infinity;
63
+ this.limit = (_b = getLimit(query)) !== null && _b !== void 0 ? _b : Infinity;
62
64
  // Queue a request to refresh the value if it doesn't exist.
63
65
  if (this.loading)
64
66
  this.refresh();
@@ -66,7 +68,7 @@ export class QueryState extends State {
66
68
  async _refresh() {
67
69
  this.busy.set(true);
68
70
  try {
69
- const items = await this.ref.value;
71
+ const items = await this.ref.items;
70
72
  this._hasMore = items.length >= this.limit; // If the query returned {limit} or more items, we can assume there are more items waiting to be queried.
71
73
  this.set(items);
72
74
  }
@@ -89,10 +91,10 @@ export class QueryState extends State {
89
91
  async _loadMore() {
90
92
  this.busy.set(true);
91
93
  try {
92
- const last = this.lastValue;
93
- const query = last ? this.ref.after(last) : this.ref;
94
- const items = await query.value;
95
- this.set([...this.value, ...items]);
94
+ const last = this.last;
95
+ const ref = last ? this.ref.with(getAfterQuery(this.ref.query, last)) : this.ref;
96
+ const items = await ref.items;
97
+ this.set([...this.items, ...items]);
96
98
  this._hasMore = items.length >= this.limit; // If the query returned {limit} or more items, we can assume there are more items waiting to be queried.
97
99
  }
98
100
  catch (thrown) {
package/db/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export * from "./Database.js";
2
- export * from "./Collection.js";
3
- export * from "./Item.js";
2
+ export * from "./CollectionReference.js";
3
+ export * from "./ItemReference.js";
4
4
  export * from "./ItemState.js";
5
- export * from "./Query.js";
5
+ export * from "./QueryReference.js";
6
6
  export * from "./QueryState.js";
7
7
  export * from "./Change.js";
package/db/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export * from "./Database.js";
2
- export * from "./Collection.js";
3
- export * from "./Item.js";
2
+ export * from "./CollectionReference.js";
3
+ export * from "./ItemReference.js";
4
4
  export * from "./ItemState.js";
5
- export * from "./Query.js";
5
+ export * from "./QueryReference.js";
6
6
  export * from "./QueryState.js";
7
7
  export * from "./Change.js";
@@ -1,7 +1,7 @@
1
- import type { ItemArray, ItemStatement, ItemValue } from "../../db/Item.js";
1
+ import type { ItemArray, ItemQuery, ItemValue } from "../../db/ItemReference.js";
2
2
  import type { AsyncProvider } from "../../provider/Provider.js";
3
- import type { Updates } from "../../update/DataUpdate.js";
4
3
  import type { Data } from "../../util/data.js";
4
+ import type { Updates } from "../../util/update.js";
5
5
  import type { Firestore } from "firebase/firestore";
6
6
  /**
7
7
  * Firestore client database provider.
@@ -12,15 +12,15 @@ import type { Firestore } from "firebase/firestore";
12
12
  export declare class FirestoreClientProvider implements AsyncProvider {
13
13
  private readonly _firestore;
14
14
  constructor(firestore: Firestore);
15
- getItem(collection: string, id: string): Promise<ItemValue>;
16
- getItemSequence(collection: string, id: string): AsyncIterable<ItemValue>;
17
- addItem(collection: string, data: Data): Promise<string>;
18
- setItem(collection: string, id: string, data: Data): Promise<void>;
19
- updateItem(collection: string, id: string, updates: Updates): Promise<void>;
20
- deleteItem(collection: string, id: string): Promise<void>;
21
- getQuery(collection: string, constraints: ItemStatement): Promise<ItemArray>;
22
- getQuerySequence(collection: string, constraints: ItemStatement): AsyncIterable<ItemArray>;
23
- setQuery(collection: string, constraints: ItemStatement, data: Data): Promise<number>;
24
- updateQuery(collection: string, constraints: ItemStatement, updates: Updates): Promise<number>;
25
- deleteQuery(collection: string, constraints: ItemStatement): Promise<number>;
15
+ getItem(c: string, id: string): Promise<ItemValue>;
16
+ getItemSequence(c: string, id: string): AsyncIterable<ItemValue>;
17
+ addItem(c: string, data: Data): Promise<string>;
18
+ setItem(c: string, id: string, data: Data): Promise<void>;
19
+ updateItem(c: string, id: string, updates: Updates): Promise<void>;
20
+ deleteItem(c: string, id: string): Promise<void>;
21
+ getQuery(c: string, q: ItemQuery): Promise<ItemArray>;
22
+ getQuerySequence(c: string, q: ItemQuery): AsyncIterable<ItemArray>;
23
+ setQuery(c: string, q: ItemQuery, data: Data): Promise<number>;
24
+ updateQuery(c: string, q: ItemQuery, updates: Updates): Promise<number>;
25
+ deleteQuery(c: string, q: ItemQuery): Promise<number>;
26
26
  }
@@ -1,41 +1,38 @@
1
- import { addDoc, deleteDoc, arrayRemove as firestoreArrayRemove, arrayUnion as firestoreArrayUnion, collection as firestoreCollection, deleteField as firestoreDeleteField, doc as firestoreDocument, documentId as firestoreDocumentId, increment as firestoreIncrement, limit as firestoreLimit, orderBy as firestoreOrderBy, query as firestoreQuery, where as firestoreWhere, getDoc, getDocs, onSnapshot, setDoc, updateDoc, } from "firebase/firestore";
1
+ import { addDoc, collection, deleteDoc, doc, documentId, getDoc, getDocs, increment, limit, onSnapshot, orderBy, query, setDoc, updateDoc, where } from "firebase/firestore";
2
2
  import { LazyDeferredSequence } from "../../sequence/LazyDeferredSequence.js";
3
- import { ArrayUpdate } from "../../update/ArrayUpdate.js";
4
- import { DataUpdate } from "../../update/DataUpdate.js";
5
- import { Delete } from "../../update/Delete.js";
6
- import { DictionaryUpdate } from "../../update/DictionaryUpdate.js";
7
- import { Increment } from "../../update/Increment.js";
8
- import { Update } from "../../update/Update.js";
3
+ import { getObject } from "../../util/object.js";
4
+ import { getFilters, getSorts } from "../../util/query.js";
5
+ import { mapItems } from "../../util/transform.js";
6
+ import { getUpdates } from "../../util/update.js";
9
7
  // Constants.
10
- const ID = firestoreDocumentId();
8
+ const ID = documentId();
11
9
  // Map `Filter.types` to `WhereFilterOp`
12
10
  const OPERATORS = {
13
- IS: "==",
14
- NOT: "!=",
15
- IN: "in",
16
- OUT: "not-in",
17
- CONTAINS: "array-contains",
18
- GT: ">",
19
- GTE: ">=",
20
- LT: "<",
21
- LTE: "<=",
22
- };
23
- // Map `Filter.types` to `OrderByDirection`
24
- const DIRECTIONS = {
25
- ASC: "asc",
26
- DESC: "desc",
11
+ is: "==",
12
+ not: "!=",
13
+ in: "in",
14
+ out: "not-in",
15
+ contains: "array-contains",
16
+ gt: ">",
17
+ gte: ">=",
18
+ lt: "<",
19
+ lte: "<=",
27
20
  };
28
21
  /** Get a Firestore QueryReference for a given query. */
29
- function _getQuery(firestore, collection, constraints) {
30
- return firestoreQuery(firestoreCollection(firestore, collection), ..._yieldConstraints(constraints));
22
+ function _getQuery(firestore, c, q) {
23
+ return query(collection(firestore, c), ..._getConstraints(q));
31
24
  }
32
- function* _yieldConstraints({ sorts, filters, limit }) {
33
- for (const { key, direction } of sorts)
34
- yield firestoreOrderBy(key === "id" ? ID : key, DIRECTIONS[direction]);
35
- for (const { operator, key, value } of filters)
36
- yield firestoreWhere(key, OPERATORS[operator], value);
37
- if (typeof limit === "number")
38
- yield firestoreLimit(limit);
25
+ function* _getConstraints(q) {
26
+ for (const { keys, direction } of getSorts(q)) {
27
+ const key = keys.join(".");
28
+ yield orderBy(key === "id" ? ID : key, direction);
29
+ }
30
+ for (const { keys, operator, value } of getFilters(q)) {
31
+ const key = keys.join(".");
32
+ yield where(key === "id" ? ID : key, OPERATORS[operator], value);
33
+ }
34
+ if (typeof q.$limit === "number")
35
+ yield limit(q.$limit);
39
36
  }
40
37
  function _getItems(snapshot) {
41
38
  return snapshot.docs.map(_getItemData);
@@ -48,35 +45,9 @@ function _getItemValue(snapshot) {
48
45
  const data = snapshot.data();
49
46
  return data ? { ...data, id: snapshot.id } : null;
50
47
  }
51
- /** Convert `Update` instances into corresponding Firestore `FieldValue` instances. */
52
- function* _getFieldValues(updates, prefix = "") {
53
- for (const [key, update] of updates) {
54
- if (update instanceof DataUpdate || update instanceof DictionaryUpdate) {
55
- yield* _getFieldValues(update, `${prefix}${key}.`);
56
- }
57
- else if (update instanceof ArrayUpdate) {
58
- if (update.adds.length) {
59
- yield `${prefix}${key}`;
60
- yield firestoreArrayUnion(...update.adds);
61
- }
62
- if (update.deletes.length) {
63
- yield `${prefix}${key}`;
64
- yield firestoreArrayRemove(...update.deletes);
65
- }
66
- }
67
- else {
68
- yield `${prefix}${key}`;
69
- if (!(update instanceof Update))
70
- yield update;
71
- else if (update instanceof Delete)
72
- yield firestoreDeleteField();
73
- else if (update instanceof Increment)
74
- yield firestoreIncrement(update.amount);
75
- else
76
- yield update.transform();
77
- }
78
- }
79
- }
48
+ /** Convert `Updates` object into corresponding Firestore `FieldValue` instances. */
49
+ const _getFieldValues = (updates) => getObject(mapItems(getUpdates(updates), _getFieldValue));
50
+ const _getFieldValue = ({ keys, action, value }) => [keys.join("."), action === "sum" ? increment(value) : action === "set" ? value : action];
80
51
  /**
81
52
  * Firestore client database provider.
82
53
  * - Works with the Firebase JS SDK.
@@ -87,48 +58,48 @@ export class FirestoreClientProvider {
87
58
  constructor(firestore) {
88
59
  this._firestore = firestore;
89
60
  }
90
- async getItem(collection, id) {
91
- return _getItemValue(await getDoc(firestoreDocument(this._firestore, collection, id)));
61
+ async getItem(c, id) {
62
+ return _getItemValue(await getDoc(doc(this._firestore, c, id)));
92
63
  }
93
- getItemSequence(collection, id) {
94
- return new LazyDeferredSequence(({ resolve, reject }) => onSnapshot(firestoreDocument(this._firestore, collection, id), //
64
+ getItemSequence(c, id) {
65
+ return new LazyDeferredSequence(({ resolve, reject }) => onSnapshot(doc(this._firestore, c, id), //
95
66
  //
96
67
  snapshot => resolve(_getItemValue(snapshot)), reject));
97
68
  }
98
- async addItem(collection, data) {
99
- const reference = await addDoc(firestoreCollection(this._firestore, collection), data);
69
+ async addItem(c, data) {
70
+ const reference = await addDoc(collection(this._firestore, c), data);
100
71
  return reference.id;
101
72
  }
102
- async setItem(collection, id, data) {
103
- await setDoc(firestoreDocument(this._firestore, collection, id), data);
73
+ async setItem(c, id, data) {
74
+ await setDoc(doc(this._firestore, c, id), data);
104
75
  }
105
- async updateItem(collection, id, updates) {
106
- await updateDoc(firestoreDocument(this._firestore, collection, id), ..._getFieldValues(Object.entries(updates)));
76
+ async updateItem(c, id, updates) {
77
+ await updateDoc(doc(this._firestore, c, id), _getFieldValues(updates));
107
78
  }
108
- async deleteItem(collection, id) {
109
- await deleteDoc(firestoreDocument(this._firestore, collection, id));
79
+ async deleteItem(c, id) {
80
+ await deleteDoc(doc(this._firestore, c, id));
110
81
  }
111
- async getQuery(collection, constraints) {
112
- return _getItems(await getDocs(_getQuery(this._firestore, collection, constraints)));
82
+ async getQuery(c, q) {
83
+ return _getItems(await getDocs(_getQuery(this._firestore, c, q)));
113
84
  }
114
- getQuerySequence(collection, constraints) {
115
- return new LazyDeferredSequence(({ resolve, reject }) => onSnapshot(_getQuery(this._firestore, collection, constraints), //
85
+ getQuerySequence(c, q) {
86
+ return new LazyDeferredSequence(({ resolve, reject }) => onSnapshot(_getQuery(this._firestore, c, q), //
116
87
  //
117
88
  snapshot => resolve(_getItems(snapshot)), reject));
118
89
  }
119
- async setQuery(collection, constraints, data) {
120
- const snapshot = await getDocs(_getQuery(this._firestore, collection, constraints));
90
+ async setQuery(c, q, data) {
91
+ const snapshot = await getDocs(_getQuery(this._firestore, c, q));
121
92
  await Promise.all(snapshot.docs.map(s => setDoc(s.ref, data)));
122
93
  return snapshot.size;
123
94
  }
124
- async updateQuery(collection, constraints, updates) {
125
- const snapshot = await getDocs(_getQuery(this._firestore, collection, constraints));
126
- const fieldValues = Array.from(_getFieldValues(Object.entries(updates)));
127
- await Promise.all(snapshot.docs.map(s => updateDoc(s.ref, ...fieldValues)));
95
+ async updateQuery(c, q, updates) {
96
+ const snapshot = await getDocs(_getQuery(this._firestore, c, q));
97
+ const fieldValues = _getFieldValues(updates);
98
+ await Promise.all(snapshot.docs.map(s => updateDoc(s.ref, fieldValues)));
128
99
  return snapshot.size;
129
100
  }
130
- async deleteQuery(collection, constraints) {
131
- const snapshot = await getDocs(_getQuery(this._firestore, collection, constraints));
101
+ async deleteQuery(c, q) {
102
+ const snapshot = await getDocs(_getQuery(this._firestore, c, q));
132
103
  await Promise.all(snapshot.docs.map(s => deleteDoc(s.ref)));
133
104
  return snapshot.size;
134
105
  }
@@ -1,7 +1,7 @@
1
- import type { ItemArray, ItemStatement, ItemValue } from "../../db/Item.js";
1
+ import type { ItemArray, ItemQuery, ItemValue } from "../../db/ItemReference.js";
2
2
  import type { AsyncProvider } from "../../provider/Provider.js";
3
- import type { Updates } from "../../update/DataUpdate.js";
4
3
  import type { Data } from "../../util/data.js";
4
+ import type { Updates } from "../../util/update.js";
5
5
  import type { Firestore } from "firebase/firestore/lite";
6
6
  /**
7
7
  * Firestore Lite client database provider.
@@ -12,15 +12,15 @@ import type { Firestore } from "firebase/firestore/lite";
12
12
  export declare class FirestoreLiteProvider implements AsyncProvider {
13
13
  private readonly _firestore;
14
14
  constructor(firestore: Firestore);
15
- getItem(collection: string, id: string): Promise<ItemValue>;
15
+ getItem(c: string, id: string): Promise<ItemValue>;
16
16
  getItemSequence(): AsyncIterableIterator<ItemValue>;
17
- addItem(collection: string, data: Data): Promise<string>;
18
- setItem(collection: string, id: string, data: Data): Promise<void>;
19
- updateItem(collection: string, id: string, updates: Updates): Promise<void>;
20
- deleteItem(collection: string, id: string): Promise<void>;
21
- getQuery(collection: string, constraints: ItemStatement): Promise<ItemArray>;
17
+ addItem(c: string, data: Data): Promise<string>;
18
+ setItem(c: string, id: string, data: Data): Promise<void>;
19
+ updateItem(c: string, id: string, updates: Updates): Promise<void>;
20
+ deleteItem(c: string, id: string): Promise<void>;
21
+ getQuery(c: string, q: ItemQuery): Promise<ItemArray>;
22
22
  getQuerySequence(): AsyncIterableIterator<ItemArray>;
23
- setQuery(collection: string, constraints: ItemStatement, data: Data): Promise<number>;
24
- updateQuery(collection: string, constraints: ItemStatement, updates: Updates): Promise<number>;
25
- deleteQuery(collection: string, constraints: ItemStatement): Promise<number>;
23
+ setQuery(c: string, q: ItemQuery, data: Data): Promise<number>;
24
+ updateQuery(c: string, q: ItemQuery, updates: Updates): Promise<number>;
25
+ deleteQuery(c: string, q: ItemQuery): Promise<number>;
26
26
  }