shelving 1.70.0 → 1.72.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 (121) hide show
  1. package/db/Changes.d.ts +21 -0
  2. package/db/Changes.js +36 -0
  3. package/db/Database.d.ts +30 -19
  4. package/db/Database.js +27 -27
  5. package/db/DatabaseDocument.d.ts +87 -0
  6. package/db/DatabaseDocument.js +91 -0
  7. package/db/DatabaseQuery.d.ts +120 -0
  8. package/db/DatabaseQuery.js +120 -0
  9. package/db/index.d.ts +3 -2
  10. package/db/index.js +3 -2
  11. package/error/ValidationError.js +2 -1
  12. package/feedback/ErrorFeedback.d.ts +1 -1
  13. package/feedback/ErrorFeedback.js +1 -0
  14. package/feedback/Feedback.d.ts +16 -27
  15. package/feedback/Feedback.js +18 -51
  16. package/feedback/InvalidFeedback.d.ts +1 -1
  17. package/feedback/InvalidFeedback.js +1 -0
  18. package/feedback/SuccessFeedback.d.ts +1 -1
  19. package/feedback/SuccessFeedback.js +1 -0
  20. package/feedback/WarningFeedback.d.ts +1 -1
  21. package/feedback/WarningFeedback.js +1 -0
  22. package/firestore/client/FirestoreClientProvider.d.ts +14 -15
  23. package/firestore/client/FirestoreClientProvider.js +48 -46
  24. package/firestore/lite/FirestoreLiteProvider.d.ts +12 -13
  25. package/firestore/lite/FirestoreLiteProvider.js +44 -41
  26. package/firestore/server/FirestoreServerProvider.d.ts +14 -15
  27. package/firestore/server/FirestoreServerProvider.js +44 -42
  28. package/markup/index.d.ts +1 -0
  29. package/markup/index.js +1 -0
  30. package/markup/regexp.d.ts +47 -0
  31. package/markup/regexp.js +48 -0
  32. package/markup/rules.d.ts +44 -55
  33. package/markup/rules.js +62 -122
  34. package/package.json +6 -6
  35. package/provider/BatchProvider.d.ts +11 -14
  36. package/provider/BatchProvider.js +29 -41
  37. package/provider/CacheProvider.d.ts +20 -21
  38. package/provider/CacheProvider.js +40 -29
  39. package/provider/DebugProvider.d.ts +36 -16
  40. package/provider/DebugProvider.js +150 -101
  41. package/provider/MemoryProvider.d.ts +19 -19
  42. package/provider/MemoryProvider.js +6 -9
  43. package/provider/Provider.d.ts +47 -50
  44. package/provider/Provider.js +7 -1
  45. package/provider/ThroughProvider.d.ts +38 -28
  46. package/provider/ThroughProvider.js +49 -6
  47. package/provider/ValidationProvider.d.ts +40 -14
  48. package/provider/ValidationProvider.js +84 -29
  49. package/query/Filter.d.ts +7 -3
  50. package/query/Filter.js +59 -37
  51. package/query/Filters.d.ts +5 -12
  52. package/query/Filters.js +10 -10
  53. package/query/Query.d.ts +11 -16
  54. package/query/Query.js +30 -30
  55. package/query/Rules.d.ts +0 -1
  56. package/query/Rules.js +0 -4
  57. package/query/Sort.d.ts +6 -3
  58. package/query/Sort.js +25 -7
  59. package/query/Sorts.d.ts +5 -5
  60. package/query/Sorts.js +9 -6
  61. package/react/useDocument.d.ts +8 -8
  62. package/react/useDocument.js +2 -3
  63. package/react/useQuery.d.ts +9 -13
  64. package/react/useQuery.js +6 -15
  65. package/react/useSubscribe.js +1 -2
  66. package/schema/AllowSchema.js +2 -2
  67. package/state/ObjectState.d.ts +2 -2
  68. package/state/State.d.ts +7 -4
  69. package/state/State.js +12 -9
  70. package/test/index.d.ts +2 -0
  71. package/test/util.d.ts +3 -3
  72. package/update/DataUpdate.d.ts +1 -1
  73. package/update/DataUpdate.js +7 -9
  74. package/update/ObjectUpdate.d.ts +2 -2
  75. package/update/ObjectUpdate.js +14 -4
  76. package/util/array.d.ts +0 -1
  77. package/util/array.js +1 -0
  78. package/util/async.d.ts +14 -35
  79. package/util/async.js +48 -63
  80. package/util/clone.js +2 -2
  81. package/util/data.d.ts +11 -17
  82. package/util/data.js +18 -4
  83. package/util/date.d.ts +11 -11
  84. package/util/debug.d.ts +15 -1
  85. package/util/debug.js +62 -22
  86. package/util/diff.d.ts +2 -1
  87. package/util/diff.js +2 -1
  88. package/util/entry.d.ts +14 -26
  89. package/util/entry.js +7 -6
  90. package/util/filter.d.ts +2 -2
  91. package/util/function.d.ts +2 -0
  92. package/util/hydrate.d.ts +4 -4
  93. package/util/hydrate.js +30 -13
  94. package/util/index.d.ts +0 -1
  95. package/util/index.js +0 -1
  96. package/util/iterate.d.ts +11 -33
  97. package/util/iterate.js +26 -61
  98. package/util/jsx.d.ts +1 -1
  99. package/util/number.d.ts +2 -2
  100. package/util/number.js +5 -1
  101. package/util/object.d.ts +2 -6
  102. package/util/object.js +10 -9
  103. package/util/regexp.d.ts +7 -24
  104. package/util/regexp.js +6 -24
  105. package/util/set.d.ts +14 -0
  106. package/util/set.js +17 -0
  107. package/util/sort.d.ts +2 -4
  108. package/util/sort.js +7 -8
  109. package/util/string.d.ts +18 -16
  110. package/util/string.js +43 -70
  111. package/util/transform.d.ts +13 -9
  112. package/util/transform.js +5 -1
  113. package/util/units.d.ts +8 -8
  114. package/util/validate.d.ts +2 -2
  115. package/util/validate.js +16 -22
  116. package/db/Operation.d.ts +0 -79
  117. package/db/Operation.js +0 -129
  118. package/db/Reference.d.ts +0 -151
  119. package/db/Reference.js +0 -216
  120. package/util/constants.d.ts +0 -12
  121. package/util/constants.js +0 -12
@@ -0,0 +1,21 @@
1
+ import type { Datas, Key } from "../util/data.js";
2
+ import { DataUpdate } from "../update/DataUpdate.js";
3
+ import type { Provider, AsyncProvider } from "../provider/Provider.js";
4
+ import type { SynchronousDatabase, AsynchronousDatabase } from "./Database.js";
5
+ /**
6
+ * Change set of operations to run against a database in `{ "collection/id": data | DataUpdate | null }` format.
7
+ * - If data is an object, sets the document.
8
+ * - If data is a `DataUpdate` instance, updates the document.
9
+ * - If data is null, deletes the document.
10
+ */
11
+ export declare type Changes<DB extends Datas> = {
12
+ [K in Key<DB> as `${K}/${string}`]: DB[K] | DataUpdate<DB[K]> | null;
13
+ };
14
+ /** Apply a set of changes to a synchronous database. */
15
+ export declare function changeSynchronousDatabase<T extends Datas>({ provider }: SynchronousDatabase<T>, changes: Changes<T>): Changes<T>;
16
+ /** Apply a set of changes to an asynchronous database. */
17
+ export declare function changeAsynchronousDatabase<T extends Datas>({ provider }: AsynchronousDatabase<T>, changes: Changes<T>): Promise<Changes<T>>;
18
+ /** Apply a set of changes to a synchronous provider. */
19
+ export declare function changeSynchronousProvider<T extends Datas>(provider: Provider<T>, changes: Changes<T>): Changes<T>;
20
+ /** Apply a set of changes to an asynchronous provider. */
21
+ export declare function changeAsynchronousProvider<T extends Datas>(provider: AsyncProvider<T>, changes: Changes<T>): Promise<Changes<T>>;
package/db/Changes.js ADDED
@@ -0,0 +1,36 @@
1
+ import { splitString } from "../util/string.js";
2
+ import { DataUpdate } from "../update/DataUpdate.js";
3
+ /** Apply a set of changes to a synchronous database. */
4
+ export function changeSynchronousDatabase({ provider }, changes) {
5
+ return changeSynchronousProvider(provider, changes);
6
+ }
7
+ /** Apply a set of changes to an asynchronous database. */
8
+ export function changeAsynchronousDatabase({ provider }, changes) {
9
+ return changeAsynchronousProvider(provider, changes);
10
+ }
11
+ /** Apply a set of changes to a synchronous provider. */
12
+ export function changeSynchronousProvider(provider, changes) {
13
+ for (const [key, change] of Object.entries(changes)) {
14
+ const [collection, id] = splitString(key, "/", 2);
15
+ if (!change)
16
+ provider.deleteDocument({ collection, id });
17
+ else if (change instanceof DataUpdate)
18
+ provider.updateDocument({ collection, id }, change);
19
+ else
20
+ provider.setDocument({ collection, id }, change);
21
+ }
22
+ return changes;
23
+ }
24
+ /** Apply a set of changes to an asynchronous provider. */
25
+ export async function changeAsynchronousProvider(provider, changes) {
26
+ for (const [key, change] of Object.entries(changes)) {
27
+ const [collection, id] = splitString(key, "/", 2);
28
+ if (!change)
29
+ await provider.deleteDocument({ collection, id });
30
+ else if (change instanceof DataUpdate)
31
+ await provider.updateDocument({ collection, id }, change);
32
+ else
33
+ await provider.setDocument({ collection, id }, change);
34
+ }
35
+ return changes;
36
+ }
package/db/Database.d.ts CHANGED
@@ -1,23 +1,17 @@
1
- import type { Validators, ValidatorType } from "../util/validate.js";
2
1
  import type { Key, Datas, Entity } from "../util/data.js";
3
- import type { Provider } from "../provider/Provider.js";
2
+ import type { AsyncProvider, AbstractProvider, Provider } from "../provider/Provider.js";
4
3
  import type { QueryProps } from "../query/Query.js";
5
- import { DocumentReference, QueryReference } from "./Reference.js";
6
- /**
7
- * Combines a database model and a provider.
8
- *
9
- * @param documents Set of loci describing named documents at the root level of the database.
10
- * @param collections Set of loci describing collections at the root level of the database.
11
- * @param provider Provider that allows data to be read/written.
12
- */
13
- export declare class Database<V extends Validators<Datas> = Validators<Datas>> {
14
- readonly validators: V;
15
- readonly provider: Provider;
16
- constructor(validators: V, provider: Provider);
17
- /** Create a query on a collection in this model. */
18
- query<K extends Key<V>>(collection: K, query?: QueryProps<Entity<ValidatorType<V[K]>>>): QueryReference<ValidatorType<V[K]>>;
19
- /** Reference a document in a collection in this model. */
20
- doc<K extends Key<V>>(collection: K, id: string): DocumentReference<ValidatorType<V[K]>>;
4
+ import { DatabaseDocument, SynchronousDatabaseDocument, AsynchronousDatabaseDocument } from "./DatabaseDocument.js";
5
+ import { DatabaseQuery, SynchronousDatabaseQuery, AsynchronousDatabaseQuery } from "./DatabaseQuery.js";
6
+ /** Database with a provider. */
7
+ export declare type Database<T extends Datas = Datas> = _AbstractDatabase<T>;
8
+ /** Database with a synchronous or asynchronous provider. */
9
+ declare abstract class _AbstractDatabase<T extends Datas> {
10
+ abstract readonly provider: AbstractProvider<T>;
11
+ /** Create a query on a collection in this database. */
12
+ abstract query<K extends Key<T>>(collection: K, query?: QueryProps<Entity<T[K]>>): DatabaseQuery<T, K>;
13
+ /** Reference a document in a collection in this database. */
14
+ abstract doc<K extends Key<T>>(collection: K, id: string): DatabaseDocument<T, K>;
21
15
  /**
22
16
  * Create a new document with a random ID.
23
17
  * - Created document is guaranteed to have a unique ID.
@@ -26,5 +20,22 @@ export declare class Database<V extends Validators<Datas> = Validators<Datas>> {
26
20
  * @param data Complete data to set the document to.
27
21
  * @return String ID for the created document (possibly promised).
28
22
  */
29
- add<K extends Key<V>>(collection: K, data: ValidatorType<V[K]>): string | PromiseLike<string>;
23
+ abstract add<K extends Key<T>>(collection: K, data: T[K]): string | PromiseLike<string>;
30
24
  }
25
+ /** Database with a synchronous provider. */
26
+ export declare class SynchronousDatabase<T extends Datas> implements _AbstractDatabase<T> {
27
+ readonly provider: Provider<T>;
28
+ constructor(provider: Provider<T>);
29
+ query<K extends Key<T>>(collection: K, query?: QueryProps<Entity<T[K]>>): SynchronousDatabaseQuery<T, K>;
30
+ doc<K extends Key<T>>(collection: K, id: string): SynchronousDatabaseDocument<T, K>;
31
+ add<K extends Key<T>>(collection: K, data: T[K]): string;
32
+ }
33
+ /** Database with a synchronous provider. */
34
+ export declare class AsynchronousDatabase<T extends Datas> implements _AbstractDatabase<T> {
35
+ readonly provider: AsyncProvider<T>;
36
+ constructor(provider: AsyncProvider<T>);
37
+ query<K extends Key<T>>(collection: K, query?: QueryProps<Entity<T[K]>>): AsynchronousDatabaseQuery<T, K>;
38
+ doc<K extends Key<T>>(collection: K, id: string): AsynchronousDatabaseDocument<T, K>;
39
+ add<K extends Key<T>>(collection: K, data: T[K]): Promise<string>;
40
+ }
41
+ export {};
package/db/Database.js CHANGED
@@ -1,35 +1,35 @@
1
- import { DocumentReference, QueryReference } from "./Reference.js";
2
- /**
3
- * Combines a database model and a provider.
4
- *
5
- * @param documents Set of loci describing named documents at the root level of the database.
6
- * @param collections Set of loci describing collections at the root level of the database.
7
- * @param provider Provider that allows data to be read/written.
8
- */
9
- // Note: typing this with `Validators` rather than raw `Datas` works better for inference — type for props in each collection tends to get lost.
10
- export class Database {
11
- constructor(validators, provider) {
12
- this.validators = validators;
1
+ import { SynchronousDatabaseDocument, AsynchronousDatabaseDocument } from "./DatabaseDocument.js";
2
+ import { SynchronousDatabaseQuery, AsynchronousDatabaseQuery } from "./DatabaseQuery.js";
3
+ /** Database with a synchronous or asynchronous provider. */
4
+ class _AbstractDatabase {
5
+ }
6
+ /** Database with a synchronous provider. */
7
+ export class SynchronousDatabase {
8
+ constructor(provider) {
13
9
  this.provider = provider;
14
10
  }
15
- /** Create a query on a collection in this model. */
16
11
  query(collection, query) {
17
- const validator = this.validators[collection];
18
- return new QueryReference(this, validator, collection, query);
12
+ return new SynchronousDatabaseQuery(this, collection, query);
19
13
  }
20
- /** Reference a document in a collection in this model. */
21
14
  doc(collection, id) {
22
- return new DocumentReference(this, this.validators[collection], collection, id);
23
- }
24
- /**
25
- * Create a new document with a random ID.
26
- * - Created document is guaranteed to have a unique ID.
27
- *
28
- * @param collection Name of the collection to add the document to.
29
- * @param data Complete data to set the document to.
30
- * @return String ID for the created document (possibly promised).
31
- */
15
+ return new SynchronousDatabaseDocument(this, collection, id);
16
+ }
17
+ add(collection, data) {
18
+ return this.provider.addDocument({ collection }, data);
19
+ }
20
+ }
21
+ /** Database with a synchronous provider. */
22
+ export class AsynchronousDatabase {
23
+ constructor(provider) {
24
+ this.provider = provider;
25
+ }
26
+ query(collection, query) {
27
+ return new AsynchronousDatabaseQuery(this, collection, query);
28
+ }
29
+ doc(collection, id) {
30
+ return new AsynchronousDatabaseDocument(this, collection, id);
31
+ }
32
32
  add(collection, data) {
33
- return this.query(collection).add(data);
33
+ return this.provider.addDocument({ collection }, data);
34
34
  }
35
35
  }
@@ -0,0 +1,87 @@
1
+ import { OptionalData, Entity, OptionalEntity, Datas, Key } from "../util/data.js";
2
+ import type { Dispatch } from "../util/function.js";
3
+ import type { PartialObserver } from "../observe/Observer.js";
4
+ import { QueryProps } from "../query/Query.js";
5
+ import { DataUpdate, PropUpdates } from "../update/DataUpdate.js";
6
+ import type { Observable, Unsubscribe } from "../observe/Observable.js";
7
+ import type { ProviderDocument } from "../provider/Provider.js";
8
+ import type { Database, SynchronousDatabase, AsynchronousDatabase } from "./Database.js";
9
+ import type { DatabaseQuery, AsynchronousDatabaseQuery, SynchronousDatabaseQuery } from "./DatabaseQuery.js";
10
+ /** Reference to a document in a provider. */
11
+ export declare type DatabaseDocument<T extends Datas, K extends Key<T>> = _AbstractDatabaseDocument<T, K>;
12
+ /** Reference to a document in a synchronous or asynchronous provider. */
13
+ declare abstract class _AbstractDatabaseDocument<T extends Datas, K extends Key<T>> implements Observable<OptionalData<T[K]>>, ProviderDocument<T, K> {
14
+ abstract readonly db: Database<T>;
15
+ abstract readonly collection: K;
16
+ abstract readonly id: string;
17
+ /** Create a query on this document's collection. */
18
+ abstract query(query?: QueryProps<Entity<T[K]>>): DatabaseQuery<T, K>;
19
+ /** Get an 'optional' reference to this document (uses a `ModelQuery` with an `id` filter). */
20
+ abstract optional: DatabaseQuery<T, K>;
21
+ /**
22
+ * Does this document exist?
23
+ * @return `true` if a document exists or `false` otherwise (possibly promised).
24
+ */
25
+ abstract exists: boolean | PromiseLike<boolean>;
26
+ /**
27
+ * Get the optional data of this document.
28
+ * @return Document's data, or `null` if the document doesn't exist (possibly promised).
29
+ */
30
+ abstract value: OptionalEntity<T[K]> | PromiseLike<OptionalEntity<T[K]>>;
31
+ /**
32
+ * Get the data of this document.
33
+ * - Useful for destructuring, e.g. `{ name, title } = await documentThatMustExist.asyncData`
34
+ *
35
+ * @return Document's data (possibly promised).
36
+ * @throws RequiredError if the document does not exist.
37
+ */
38
+ abstract data: Entity<T[K]> | PromiseLike<Entity<T[K]>>;
39
+ /**
40
+ * Subscribe to the result of this document (indefinitely).
41
+ * - `next()` is called once with the initial result, and again any time the result changes.
42
+ *
43
+ * @param next Observer with `next`, `error`, or `complete` methods or a `next()` dispatcher.
44
+ * @return Function that ends the subscription.
45
+ */
46
+ subscribe(next: PartialObserver<OptionalEntity<T[K]>> | Dispatch<[OptionalEntity<T[K]>]>): Unsubscribe;
47
+ /** Set the complete data of this document. */
48
+ abstract set(data: T[K]): void | PromiseLike<void>;
49
+ /** Update this document. */
50
+ abstract update(updates: DataUpdate<T[K]> | PropUpdates<T[K]>): void | PromiseLike<void>;
51
+ /** Delete this document. */
52
+ abstract delete(): void | PromiseLike<void>;
53
+ toString(): string;
54
+ }
55
+ /** Reference to a document in a synchronous provider. */
56
+ export declare class SynchronousDatabaseDocument<T extends Datas, K extends Key<T>> extends _AbstractDatabaseDocument<T, K> {
57
+ readonly db: SynchronousDatabase<T>;
58
+ readonly collection: K;
59
+ readonly id: string;
60
+ constructor(db: SynchronousDatabase<T>, collection: K, id: string);
61
+ query(query?: QueryProps<Entity<T[K]>>): SynchronousDatabaseQuery<T, K>;
62
+ get optional(): SynchronousDatabaseQuery<T, K>;
63
+ get exists(): boolean;
64
+ get value(): OptionalEntity<T[K]>;
65
+ get data(): Entity<T[K]>;
66
+ set(data: T[K]): void;
67
+ update(updates: DataUpdate<T[K]> | PropUpdates<T[K]>): void;
68
+ delete(): void;
69
+ }
70
+ /** Reference to a document in an asynchronous provider. */
71
+ export declare class AsynchronousDatabaseDocument<T extends Datas, K extends Key<T>> extends _AbstractDatabaseDocument<T, K> {
72
+ readonly db: AsynchronousDatabase<T>;
73
+ readonly collection: K;
74
+ readonly id: string;
75
+ constructor(provider: AsynchronousDatabase<T>, collection: K, id: string);
76
+ query(query?: QueryProps<Entity<T[K]>>): AsynchronousDatabaseQuery<T, K>;
77
+ get optional(): AsynchronousDatabaseQuery<T, K>;
78
+ get exists(): Promise<boolean>;
79
+ get value(): Promise<OptionalEntity<T[K]>>;
80
+ get data(): Promise<Entity<T[K]>>;
81
+ set(data: T[K]): Promise<void>;
82
+ update(updates: DataUpdate<T[K]> | PropUpdates<T[K]>): Promise<void>;
83
+ delete(): Promise<void>;
84
+ }
85
+ /** Get the data for a document from a result for that document. */
86
+ export declare function getDocumentData<T extends Datas, K extends Key<T>>(entity: OptionalEntity<T[K]>, ref: _AbstractDatabaseDocument<T, K>): Entity<T[K]>;
87
+ export {};
@@ -0,0 +1,91 @@
1
+ import { DataUpdate } from "../update/DataUpdate.js";
2
+ import { RequiredError } from "../error/RequiredError.js";
3
+ /** Reference to a document in a synchronous or asynchronous provider. */
4
+ class _AbstractDatabaseDocument {
5
+ /**
6
+ * Subscribe to the result of this document (indefinitely).
7
+ * - `next()` is called once with the initial result, and again any time the result changes.
8
+ *
9
+ * @param next Observer with `next`, `error`, or `complete` methods or a `next()` dispatcher.
10
+ * @return Function that ends the subscription.
11
+ */
12
+ subscribe(next) {
13
+ return this.db.provider.subscribeDocument(this, typeof next === "function" ? { next } : next);
14
+ }
15
+ // Implement toString()
16
+ toString() {
17
+ return `${this.collection}/${this.id}`;
18
+ }
19
+ }
20
+ /** Reference to a document in a synchronous provider. */
21
+ export class SynchronousDatabaseDocument extends _AbstractDatabaseDocument {
22
+ constructor(db, collection, id) {
23
+ super();
24
+ this.db = db;
25
+ this.collection = collection;
26
+ this.id = id;
27
+ }
28
+ query(query) {
29
+ return this.db.query(this.collection, query);
30
+ }
31
+ get optional() {
32
+ return this.db.query(this.collection, { filter: { id: this.id }, limit: 1 });
33
+ }
34
+ get exists() {
35
+ return !!this.db.provider.getDocument(this);
36
+ }
37
+ get value() {
38
+ return this.db.provider.getDocument(this);
39
+ }
40
+ get data() {
41
+ return getDocumentData(this.value, this);
42
+ }
43
+ set(data) {
44
+ return this.db.provider.setDocument(this, data);
45
+ }
46
+ update(updates) {
47
+ return this.db.provider.updateDocument(this, updates instanceof DataUpdate ? updates : new DataUpdate(updates));
48
+ }
49
+ delete() {
50
+ return this.db.provider.deleteDocument(this);
51
+ }
52
+ }
53
+ /** Reference to a document in an asynchronous provider. */
54
+ export class AsynchronousDatabaseDocument extends _AbstractDatabaseDocument {
55
+ constructor(provider, collection, id) {
56
+ super();
57
+ this.db = provider;
58
+ this.collection = collection;
59
+ this.id = id;
60
+ }
61
+ query(query) {
62
+ return this.db.query(this.collection, query);
63
+ }
64
+ get optional() {
65
+ return this.db.query(this.collection, { filter: { id: this.id }, limit: 1 });
66
+ }
67
+ get exists() {
68
+ return this.db.provider.getDocument(this).then(Boolean);
69
+ }
70
+ get value() {
71
+ return this.db.provider.getDocument(this);
72
+ }
73
+ get data() {
74
+ return this.value.then(v => getDocumentData(v, this));
75
+ }
76
+ set(data) {
77
+ return this.db.provider.setDocument(this, data);
78
+ }
79
+ update(updates) {
80
+ return this.db.provider.updateDocument(this, updates instanceof DataUpdate ? updates : new DataUpdate(updates));
81
+ }
82
+ delete() {
83
+ return this.db.provider.deleteDocument(this);
84
+ }
85
+ }
86
+ /** Get the data for a document from a result for that document. */
87
+ export function getDocumentData(entity, ref) {
88
+ if (entity)
89
+ return entity;
90
+ throw new RequiredError(`Document "${ref}" does not exist`);
91
+ }
@@ -0,0 +1,120 @@
1
+ import { Entity, OptionalEntity, Entities, Key, Datas } from "../util/data.js";
2
+ import type { Dispatch } from "../util/function.js";
3
+ import { ImmutableArray } from "../util/array.js";
4
+ import type { PartialObserver } from "../observe/Observer.js";
5
+ import { Query, QueryProps } from "../query/Query.js";
6
+ import { DataUpdate, PropUpdates } from "../update/DataUpdate.js";
7
+ import type { Observable, Unsubscribe } from "../observe/Observable.js";
8
+ import type { Database, AsynchronousDatabase, SynchronousDatabase } from "./Database.js";
9
+ import type { DatabaseDocument, AsynchronousDatabaseDocument, SynchronousDatabaseDocument } from "./DatabaseDocument.js";
10
+ /** Reference to a set of documents in a provider. */
11
+ export declare type DatabaseQuery<T extends Datas, K extends Key<T>> = _AbstractDatabaseQuery<T, K>;
12
+ /** Reference to a set of documents in a sync or async provider. */
13
+ declare abstract class _AbstractDatabaseQuery<T extends Datas, K extends Key<T>> extends Query<Entity<T[K]>> implements Observable<ImmutableArray<Entity<T[K]>>> {
14
+ abstract readonly db: Database<T>;
15
+ abstract readonly collection: K;
16
+ /** Reference a document in this query's collection. */
17
+ abstract doc(id: string): DatabaseDocument<T, K>;
18
+ /**
19
+ * Create a new document with a random ID.
20
+ * - Created document is guaranteed to have a unique ID.
21
+ *
22
+ * @param data Complete data to set the document to.
23
+ * @return String ID for the created document (possibly promised).
24
+ */
25
+ abstract add(data: T[K]): string | PromiseLike<string>;
26
+ /**
27
+ * Get array of entities for this query.
28
+ * @return Array of entities.
29
+ */
30
+ abstract value: Entities<T[K]> | PromiseLike<Entities<T[K]>>;
31
+ /**
32
+ * Count the number of results of this set of documents.
33
+ * @return Number of documents matching the query (possibly promised).
34
+ */
35
+ abstract count: number | PromiseLike<number>;
36
+ /**
37
+ * Does at least one document exist for this query?
38
+ * @return `true` if a document exists or `false` otherwise (possibly promised).
39
+ */
40
+ abstract exists: boolean | PromiseLike<boolean>;
41
+ /**
42
+ * Get the first document matched by this query or `null` if this query has no results.
43
+ * @throws RequiredError if there were no results for this query.
44
+ */
45
+ abstract first: OptionalEntity<T[K]> | PromiseLike<OptionalEntity<T[K]>>;
46
+ /**
47
+ * Get the first document matched by this query.
48
+ * @throws RequiredError if there were no results for this query.
49
+ */
50
+ abstract data: Entity<T[K]> | PromiseLike<Entity<T[K]>>;
51
+ /**
52
+ * Subscribe to all matching documents.
53
+ * - `next()` is called once with the initial results, and again any time the results change.
54
+ *
55
+ * @param next Observer with `next`, `error`, or `complete` methods or a `next()` dispatcher.
56
+ * @return Function that ends the subscription.
57
+ */
58
+ subscribe(next: PartialObserver<Entities<T[K]>> | Dispatch<[Entities<T[K]>]>): Unsubscribe;
59
+ /**
60
+ * Set all matching documents to the same exact value.
61
+ *
62
+ * @param data Complete data to set the document to.
63
+ * @return Nothing (possibly promised).
64
+ */
65
+ abstract set(data: T[K]): number | PromiseLike<number>;
66
+ /**
67
+ * Update all matching documents with the same partial value.
68
+ *
69
+ * @param updates `Update` instance or set of updates to apply to every matching document.
70
+ * @return Nothing (possibly promised).
71
+ */
72
+ abstract update(updates: DataUpdate<T[K]> | PropUpdates<T[K]>): number | PromiseLike<number>;
73
+ /**
74
+ * Delete all matching documents.
75
+ * @return Nothing (possibly promised).
76
+ */
77
+ abstract delete(): number | PromiseLike<number>;
78
+ toString(): string;
79
+ }
80
+ /** Reference to a set of documents in a provider. */
81
+ export declare class SynchronousDatabaseQuery<T extends Datas, K extends Key<T>> extends _AbstractDatabaseQuery<T, K> {
82
+ readonly db: SynchronousDatabase<T>;
83
+ readonly collection: K;
84
+ constructor(db: SynchronousDatabase<T>, collection: K, props?: QueryProps<Entity<T[K]>>);
85
+ doc(id: string): SynchronousDatabaseDocument<T, K>;
86
+ add(data: T[K]): string;
87
+ get value(): Entities<T[K]>;
88
+ get count(): number;
89
+ get exists(): boolean;
90
+ get first(): OptionalEntity<T[K]>;
91
+ get data(): Entity<T[K]>;
92
+ set(data: T[K]): number;
93
+ update(updates: DataUpdate<T[K]> | PropUpdates<T[K]>): number;
94
+ delete(): number;
95
+ }
96
+ /** Reference to a set of documents in a provider. */
97
+ export declare class AsynchronousDatabaseQuery<T extends Datas, K extends Key<T>> extends _AbstractDatabaseQuery<T, K> {
98
+ readonly db: AsynchronousDatabase<T>;
99
+ readonly collection: K;
100
+ constructor(db: AsynchronousDatabase<T>, collection: K, props?: QueryProps<Entity<T[K]>>);
101
+ doc(id: string): AsynchronousDatabaseDocument<T, K>;
102
+ add(data: T[K]): Promise<string>;
103
+ get value(): Promise<Entities<T[K]>>;
104
+ get count(): Promise<number>;
105
+ get exists(): Promise<boolean>;
106
+ get first(): Promise<OptionalEntity<T[K]>>;
107
+ get data(): Promise<Entity<T[K]>>;
108
+ set(data: T[K]): Promise<number>;
109
+ update(updates: DataUpdate<T[K]> | PropUpdates<T[K]>): PromiseLike<number>;
110
+ delete(): PromiseLike<number>;
111
+ }
112
+ /** Get the optional data for a document from a set of queried entities. */
113
+ export declare function getQueryFirstItem<T extends Datas, K extends Key<T>>(entities: Entities<T[K]>): OptionalEntity<T[K]>;
114
+ /** Get the data for a document from a set of queried entities. */
115
+ export declare function getQueryFirstData<T extends Datas, K extends Key<T>>(entities: Entities<T[K]>, ref: _AbstractDatabaseQuery<T, K>): Entity<T[K]>;
116
+ /** Get the optional data for a document from a set of queried entities. */
117
+ export declare function getQueryLastValue<T extends Datas, K extends Key<T>>(entities: Entities<T[K]>): OptionalEntity<T[K]>;
118
+ /** Get the data for a document from a set of queried entities. */
119
+ export declare function getQueryLastItem<T extends Datas, K extends Key<T>>(entities: Entities<T[K]>, ref: _AbstractDatabaseQuery<T, K>): Entity<T[K]>;
120
+ export {};
@@ -0,0 +1,120 @@
1
+ import { getFirstItem, getLastItem } from "../util/array.js";
2
+ import { Query } from "../query/Query.js";
3
+ import { countItems, hasItems } from "../util/iterate.js";
4
+ import { DataUpdate } from "../update/DataUpdate.js";
5
+ import { RequiredError } from "../error/RequiredError.js";
6
+ /** Reference to a set of documents in a sync or async provider. */
7
+ class _AbstractDatabaseQuery extends Query {
8
+ /**
9
+ * Subscribe to all matching documents.
10
+ * - `next()` is called once with the initial results, and again any time the results change.
11
+ *
12
+ * @param next Observer with `next`, `error`, or `complete` methods or a `next()` dispatcher.
13
+ * @return Function that ends the subscription.
14
+ */
15
+ subscribe(next) {
16
+ return this.db.provider.subscribeQuery(this, typeof next === "function" ? { next } : next);
17
+ }
18
+ // Override to include the collection name.
19
+ toString() {
20
+ return `${this.collection}?${super.toString()}`;
21
+ }
22
+ }
23
+ /** Reference to a set of documents in a provider. */
24
+ export class SynchronousDatabaseQuery extends _AbstractDatabaseQuery {
25
+ constructor(db, collection, props) {
26
+ super(props);
27
+ this.db = db;
28
+ this.collection = collection;
29
+ }
30
+ doc(id) {
31
+ return this.db.doc(this.collection, id);
32
+ }
33
+ add(data) {
34
+ return this.db.provider.addDocument(this, data);
35
+ }
36
+ get value() {
37
+ return this.db.provider.getQuery(this);
38
+ }
39
+ get count() {
40
+ return this.value.length;
41
+ }
42
+ get exists() {
43
+ return hasItems(this.db.provider.getQuery(this.max(1)));
44
+ }
45
+ get first() {
46
+ return getQueryFirstItem(this.db.provider.getQuery(this.max(1)));
47
+ }
48
+ get data() {
49
+ return getQueryFirstData(this.db.provider.getQuery(this.max(1)), this);
50
+ }
51
+ set(data) {
52
+ return this.db.provider.setQuery(this, data);
53
+ }
54
+ update(updates) {
55
+ return this.db.provider.updateQuery(this, updates instanceof DataUpdate ? updates : new DataUpdate(updates));
56
+ }
57
+ delete() {
58
+ return this.db.provider.deleteQuery(this);
59
+ }
60
+ }
61
+ /** Reference to a set of documents in a provider. */
62
+ export class AsynchronousDatabaseQuery extends _AbstractDatabaseQuery {
63
+ constructor(db, collection, props) {
64
+ super(props);
65
+ this.db = db;
66
+ this.collection = collection;
67
+ }
68
+ doc(id) {
69
+ return this.db.doc(this.collection, id);
70
+ }
71
+ add(data) {
72
+ return this.db.provider.addDocument(this, data);
73
+ }
74
+ get value() {
75
+ return this.db.provider.getQuery(this);
76
+ }
77
+ get count() {
78
+ return this.value.then(countItems);
79
+ }
80
+ get exists() {
81
+ return this.db.provider.getQuery(this.max(1)).then(hasItems);
82
+ }
83
+ get first() {
84
+ return this.db.provider.getQuery(this.max(1)).then(getQueryFirstItem);
85
+ }
86
+ get data() {
87
+ return this.db.provider.getQuery(this.max(1)).then(v => getQueryFirstData(v, this));
88
+ }
89
+ set(data) {
90
+ return this.db.provider.setQuery(this, data);
91
+ }
92
+ update(updates) {
93
+ return this.db.provider.updateQuery(this, updates instanceof DataUpdate ? updates : new DataUpdate(updates));
94
+ }
95
+ delete() {
96
+ return this.db.provider.deleteQuery(this);
97
+ }
98
+ }
99
+ /** Get the optional data for a document from a set of queried entities. */
100
+ export function getQueryFirstItem(entities) {
101
+ return getFirstItem(entities) || null;
102
+ }
103
+ /** Get the data for a document from a set of queried entities. */
104
+ export function getQueryFirstData(entities, ref) {
105
+ const entity = getQueryFirstItem(entities);
106
+ if (entity)
107
+ return entity;
108
+ throw new RequiredError(`Query "${ref}" has no documents`);
109
+ }
110
+ /** Get the optional data for a document from a set of queried entities. */
111
+ export function getQueryLastValue(entities) {
112
+ return getLastItem(entities) || null;
113
+ }
114
+ /** Get the data for a document from a set of queried entities. */
115
+ export function getQueryLastItem(entities, ref) {
116
+ const entity = getQueryLastValue(entities);
117
+ if (entity)
118
+ return entity;
119
+ throw new RequiredError(`Query "${ref}" has no documents`);
120
+ }
package/db/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from "./Database.js";
2
- export * from "./Reference.js";
3
- export * from "./Operation.js";
2
+ export * from "./DatabaseDocument.js";
3
+ export * from "./DatabaseQuery.js";
4
+ export * from "./Changes.js";
package/db/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from "./Database.js";
2
- export * from "./Reference.js";
3
- export * from "./Operation.js";
2
+ export * from "./DatabaseDocument.js";
3
+ export * from "./DatabaseQuery.js";
4
+ export * from "./Changes.js";
@@ -1,7 +1,8 @@
1
+ import { debug } from "../util/debug.js";
1
2
  /** Thrown if a value isn't valid. */
2
3
  export class ValidationError extends Error {
3
4
  constructor(message, feedback) {
4
- super(`${message}:\n${feedback.toString()}`);
5
+ super(`${message}:\n${feedback.message} (received ${debug(feedback.value)})`);
5
6
  this.feedback = feedback;
6
7
  }
7
8
  }
@@ -1,4 +1,4 @@
1
1
  import { Feedback } from "./Feedback.js";
2
2
  /** Specific type of `Feedback` to indicate an error (something went wrong). */
3
- export declare class ErrorFeedback extends Feedback {
3
+ export declare class ErrorFeedback<T = unknown> extends Feedback<T> {
4
4
  }
@@ -2,3 +2,4 @@ import { Feedback } from "./Feedback.js";
2
2
  /** Specific type of `Feedback` to indicate an error (something went wrong). */
3
3
  export class ErrorFeedback extends Feedback {
4
4
  }
5
+ ErrorFeedback.prototype.name = "ErrorFeedback";