firetender-admin 0.10.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.
- package/LICENSE +20 -0
- package/README.md +349 -0
- package/dist/FiretenderCollection.d.ts +116 -0
- package/dist/FiretenderCollection.js +225 -0
- package/dist/FiretenderCollection.js.map +1 -0
- package/dist/FiretenderDoc.d.ts +172 -0
- package/dist/FiretenderDoc.js +361 -0
- package/dist/FiretenderDoc.js.map +1 -0
- package/dist/errors.d.ts +30 -0
- package/dist/errors.js +49 -0
- package/dist/errors.js.map +1 -0
- package/dist/firestore-deps-admin.d.ts +26 -0
- package/dist/firestore-deps-admin.js +62 -0
- package/dist/firestore-deps-admin.js.map +1 -0
- package/dist/firestore-deps-web.d.ts +10 -0
- package/dist/firestore-deps-web.js +29 -0
- package/dist/firestore-deps-web.js.map +1 -0
- package/dist/firestore-deps.d.ts +26 -0
- package/dist/firestore-deps.js +62 -0
- package/dist/firestore-deps.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/proxies.d.ts +62 -0
- package/dist/proxies.js +243 -0
- package/dist/proxies.js.map +1 -0
- package/dist/timestamps.d.ts +37 -0
- package/dist/timestamps.js +58 -0
- package/dist/timestamps.js.map +1 -0
- package/dist/ts-helpers.d.ts +14 -0
- package/dist/ts-helpers.js +19 -0
- package/dist/ts-helpers.js.map +1 -0
- package/package.json +72 -0
- package/src/FiretenderCollection.ts +311 -0
- package/src/FiretenderDoc.ts +483 -0
- package/src/errors.ts +47 -0
- package/src/firestore-deps-admin.ts +111 -0
- package/src/firestore-deps-web.ts +14 -0
- package/src/firestore-deps.ts +111 -0
- package/src/index.ts +29 -0
- package/src/proxies.ts +286 -0
- package/src/timestamps.ts +62 -0
- package/src/ts-helpers.ts +39 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FiretenderCollection = void 0;
|
|
4
|
+
const errors_1 = require("./errors");
|
|
5
|
+
const firestore_deps_1 = require("./firestore-deps");
|
|
6
|
+
const FiretenderDoc_1 = require("./FiretenderDoc");
|
|
7
|
+
/**
|
|
8
|
+
* A representation of a Firestore collection or subcollection.
|
|
9
|
+
*
|
|
10
|
+
* It represents a given "collection path": the collection names from a document
|
|
11
|
+
* reference, sans IDs. All docs at /databases/{db}/documents/foo/{*}/bar/{*}
|
|
12
|
+
* are covered by a FiretenderCollection for the path ["foo", "bar"].
|
|
13
|
+
*/
|
|
14
|
+
class FiretenderCollection {
|
|
15
|
+
/**
|
|
16
|
+
* @param schema the Zod object schema describing the documents in this
|
|
17
|
+
* collection.
|
|
18
|
+
* @param firestore the thing you get from getFirestore().
|
|
19
|
+
* @param collectionPath the path of this collection in Firestore: the names
|
|
20
|
+
* of any parent collections and of this collection.
|
|
21
|
+
* @param baseInitialData (optional) an object or object factory providing
|
|
22
|
+
* default field values for this collection.
|
|
23
|
+
*/
|
|
24
|
+
constructor(schema, firestore, collectionPath, baseInitialData = undefined) {
|
|
25
|
+
this.schema = schema;
|
|
26
|
+
this.firestore = firestore;
|
|
27
|
+
this.collectionPath = [collectionPath].flat();
|
|
28
|
+
if (baseInitialData) {
|
|
29
|
+
if (typeof baseInitialData === "function") {
|
|
30
|
+
this.baseInitialDataFactory = baseInitialData;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
this.baseInitialDataFactory = () => baseInitialData;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Returns a FiretenderDoc representing a new document in this collection.
|
|
39
|
+
*
|
|
40
|
+
* This method initializes the FiretenderDoc but does not create it in
|
|
41
|
+
* Firestore. To do so, call the doc's write() method.
|
|
42
|
+
*
|
|
43
|
+
* @param id the ID or array of IDs giving the path of the new document.
|
|
44
|
+
* Firestore will generate a random doc ID if it is omitted. If this is a
|
|
45
|
+
* subcollection, the ID(s) for the parent collection(s) are required.
|
|
46
|
+
* @param initialData the document's initial data, which is merged with (and
|
|
47
|
+
* potentially overwrites) field values specified in the constructor.
|
|
48
|
+
* @param options optional parameters for the resulting FiretenderDoc; see
|
|
49
|
+
* FiretenderDocOptions for detail.
|
|
50
|
+
*/
|
|
51
|
+
newDoc(id = undefined, initialData = undefined, options = {}) {
|
|
52
|
+
const ids = id instanceof Array ? id : id ? [id] : [];
|
|
53
|
+
let ref = this.makeDocRefInternal(ids);
|
|
54
|
+
if (!ref) {
|
|
55
|
+
ref = this.makeCollectionRefInternal(ids);
|
|
56
|
+
}
|
|
57
|
+
if (!ref) {
|
|
58
|
+
throw new errors_1.FiretenderUsageError("newDoc() requires an ID path for all collections and subcollections, except optionally the last.");
|
|
59
|
+
}
|
|
60
|
+
const data = {};
|
|
61
|
+
if (this.baseInitialDataFactory) {
|
|
62
|
+
Object.assign(data, this.baseInitialDataFactory());
|
|
63
|
+
}
|
|
64
|
+
if (initialData) {
|
|
65
|
+
Object.assign(data, initialData);
|
|
66
|
+
}
|
|
67
|
+
return FiretenderDoc_1.FiretenderDoc.createNewDoc(this.schema, ref, data, options);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Returns a FiretenderDoc representing an existing Firestore document in this
|
|
71
|
+
* collection.
|
|
72
|
+
*
|
|
73
|
+
* This method initializes the FiretenderDoc but does not load its data. If
|
|
74
|
+
* the doc does not exist in Firestore, calling load() will throw an error.
|
|
75
|
+
*
|
|
76
|
+
* @param id the ID or array of IDs specifying the desired document.
|
|
77
|
+
* @param options optional parameters for the resulting FiretenderDoc; see
|
|
78
|
+
* FiretenderDocOptions for detail.
|
|
79
|
+
*/
|
|
80
|
+
existingDoc(id, options = {}) {
|
|
81
|
+
const ref = this.makeDocRefInternal([id].flat());
|
|
82
|
+
if (!ref) {
|
|
83
|
+
throw new errors_1.FiretenderUsageError("existingDoc() requires a full ID path for this collection and its parent collections, if any.");
|
|
84
|
+
}
|
|
85
|
+
return new FiretenderDoc_1.FiretenderDoc(this.schema, ref, options);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Returns an array of all the documents in this collection.
|
|
89
|
+
*
|
|
90
|
+
* If the collection may contain a large number of documents, use query() with
|
|
91
|
+
* the limit() and startAfter() constraints to paginate the results.
|
|
92
|
+
*
|
|
93
|
+
* @param id (optional) when querying a subcollection, the ID(s) of its parent
|
|
94
|
+
* collection(s).
|
|
95
|
+
*/
|
|
96
|
+
async getAllDocs(id = undefined) {
|
|
97
|
+
const ids = id instanceof Array ? id : id ? [id] : [];
|
|
98
|
+
const collectionRef = this.makeCollectionRefInternal(ids);
|
|
99
|
+
if (!collectionRef) {
|
|
100
|
+
throw new errors_1.FiretenderUsageError("When querying a subcollection, getAllDocs() requires the IDs of all parent collections.");
|
|
101
|
+
}
|
|
102
|
+
return this.getAndWrapDocs(collectionRef);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Returns an array of the documents matching the given query.
|
|
106
|
+
*
|
|
107
|
+
* @param id (optional) when querying a subcollection, the ID(s) of its parent
|
|
108
|
+
* collection(s); omit when querying a top-level collection or when querying
|
|
109
|
+
* all docs in this subcollection, regardless of parent.
|
|
110
|
+
* @param ...whereClauses the where(), limit(), orderBy(), startAfter(), etc.
|
|
111
|
+
* constraints defining this query.
|
|
112
|
+
*/
|
|
113
|
+
async query(idOrWhereClause, ...moreWhereClauses) {
|
|
114
|
+
let ids;
|
|
115
|
+
let whereClauses;
|
|
116
|
+
if (idOrWhereClause instanceof Array) {
|
|
117
|
+
ids = idOrWhereClause;
|
|
118
|
+
whereClauses = moreWhereClauses;
|
|
119
|
+
}
|
|
120
|
+
else if (typeof idOrWhereClause === "string") {
|
|
121
|
+
ids = [idOrWhereClause];
|
|
122
|
+
whereClauses = moreWhereClauses;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
ids = [];
|
|
126
|
+
whereClauses = [idOrWhereClause, ...moreWhereClauses];
|
|
127
|
+
}
|
|
128
|
+
let ref = this.makeCollectionRefInternal(ids);
|
|
129
|
+
if (!ref) {
|
|
130
|
+
ref = (0, firestore_deps_1.collectionGroup)(this.firestore, this.collectionPath[this.collectionPath.length - 1]);
|
|
131
|
+
}
|
|
132
|
+
return this.getAndWrapDocs((0, firestore_deps_1.query)(ref, ...whereClauses));
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Deletes the given document from this collection.
|
|
136
|
+
*
|
|
137
|
+
* The document's subcollections (if any) are not deleted. To delete them,
|
|
138
|
+
* first use query() to get its subcollection docs, then call delete() on each
|
|
139
|
+
* one. Please note that the Firestore guide recommends only performing such
|
|
140
|
+
* unbounded batched deletions from a trusted server environment.
|
|
141
|
+
*
|
|
142
|
+
* @param id full path ID of the target document.
|
|
143
|
+
*/
|
|
144
|
+
async delete(id) {
|
|
145
|
+
const ref = this.makeDocRefInternal([id].flat());
|
|
146
|
+
if (!ref) {
|
|
147
|
+
throw new errors_1.FiretenderUsageError("delete() requires the full ID path of the target document.");
|
|
148
|
+
}
|
|
149
|
+
try {
|
|
150
|
+
await (0, firestore_deps_1.deleteDoc)(ref);
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
(0, errors_1.addContextToError)(error, "deleteDoc", ref);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Returns a document reference for the specified ID.
|
|
158
|
+
*
|
|
159
|
+
* @param id the ID or array of IDs specifying the desired document.
|
|
160
|
+
*/
|
|
161
|
+
makeDocRef(id) {
|
|
162
|
+
const ids = [id].flat();
|
|
163
|
+
const ref = this.makeDocRefInternal(ids);
|
|
164
|
+
if (!ref) {
|
|
165
|
+
throw new errors_1.FiretenderUsageError(`Document refs for /${this.collectionPath.join("/*")}/* require ${this.collectionPath.length} document IDs; received ${ids.length}.`);
|
|
166
|
+
}
|
|
167
|
+
return ref;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Returns a collection reference for the specified ID.
|
|
171
|
+
*
|
|
172
|
+
* @param id the ID or array of IDs specifying the desired collection.
|
|
173
|
+
*/
|
|
174
|
+
makeCollectionRef(id = undefined) {
|
|
175
|
+
const ids = id ? [id].flat() : [];
|
|
176
|
+
const ref = this.makeCollectionRefInternal(ids);
|
|
177
|
+
if (!ref) {
|
|
178
|
+
throw new errors_1.FiretenderUsageError(`Collection refs for /${this.collectionPath.join("/*")} require ${this.collectionPath.length - 1} document IDs; received ${ids.length}.`);
|
|
179
|
+
}
|
|
180
|
+
return ref;
|
|
181
|
+
}
|
|
182
|
+
//////////////////////////////////////////////////////////////////////////////
|
|
183
|
+
// Private functions
|
|
184
|
+
/**
|
|
185
|
+
* Builds a doc ref from the given IDs, or returns "undefined" if the IDs do
|
|
186
|
+
* not correctly specify a doc path.
|
|
187
|
+
*/
|
|
188
|
+
makeDocRefInternal(ids) {
|
|
189
|
+
if (ids.length !== this.collectionPath.length) {
|
|
190
|
+
return undefined;
|
|
191
|
+
}
|
|
192
|
+
const path = ids.flatMap((id, i) => [this.collectionPath[i], id]);
|
|
193
|
+
return (0, firestore_deps_1.doc)(this.firestore, path[0], ...path.slice(1));
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Builds a collection ref from the given IDs, or returns "undefined" if the
|
|
197
|
+
* IDs do not correctly specify a collection path.
|
|
198
|
+
*/
|
|
199
|
+
makeCollectionRefInternal(ids) {
|
|
200
|
+
if (ids.length !== this.collectionPath.length - 1) {
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
203
|
+
const subPath = ids.flatMap((id, i) => [id, this.collectionPath[i + 1]]);
|
|
204
|
+
return (0, firestore_deps_1.collection)(this.firestore, this.collectionPath[0], ...subPath);
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Executes the given query and returns an array of the results, wrapped in
|
|
208
|
+
* FiretenderDoc objects.
|
|
209
|
+
*/
|
|
210
|
+
async getAndWrapDocs(query) {
|
|
211
|
+
let querySnapshot;
|
|
212
|
+
try {
|
|
213
|
+
querySnapshot = await (0, firestore_deps_1.getDocs)(query);
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
(0, errors_1.addContextToError)(error, "getDocs", query instanceof firestore_deps_1.CollectionReference ? query : undefined);
|
|
217
|
+
throw error;
|
|
218
|
+
}
|
|
219
|
+
return querySnapshot.docs.map((queryDoc) => new FiretenderDoc_1.FiretenderDoc(this.schema, queryDoc.ref, {
|
|
220
|
+
initialData: queryDoc.data(),
|
|
221
|
+
}));
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
exports.FiretenderCollection = FiretenderCollection;
|
|
225
|
+
//# sourceMappingURL=FiretenderCollection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FiretenderCollection.js","sourceRoot":"","sources":["../src/FiretenderCollection.ts"],"names":[],"mappings":";;;AAEA,qCAAmE;AACnE,qDAa0B;AAC1B,mDAAsE;AAGtE;;;;;;GAMG;AACH,MAAa,oBAAoB;IAe/B;;;;;;;;OAQG;IACH,YACE,MAAkB,EAClB,SAAoB,EACpB,cAA8C,EAC9C,kBAGgB,SAAS;QAEzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,cAAc,GAAG,CAAC,cAAc,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9C,IAAI,eAAe,EAAE;YACnB,IAAI,OAAO,eAAe,KAAK,UAAU,EAAE;gBACzC,IAAI,CAAC,sBAAsB,GAAG,eAAe,CAAC;aAC/C;iBAAM;gBACL,IAAI,CAAC,sBAAsB,GAAG,GAAG,EAAE,CAAC,eAAe,CAAC;aACrD;SACF;IACH,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,MAAM,CACJ,KAAoC,SAAS,EAC7C,cAA4D,SAAS,EACrE,UAAgC,EAAE;QAElC,MAAM,GAAG,GAAG,EAAE,YAAY,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,IAAI,GAAG,GACL,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,CAAC,GAAG,EAAE;YACR,GAAG,GAAG,IAAI,CAAC,yBAAyB,CAAC,GAAG,CAAC,CAAC;SAC3C;QACD,IAAI,CAAC,GAAG,EAAE;YACR,MAAM,IAAI,6BAAoB,CAC5B,kGAAkG,CACnG,CAAC;SACH;QACD,MAAM,IAAI,GAAG,EAAE,CAAC;QAChB,IAAI,IAAI,CAAC,sBAAsB,EAAE;YAC/B,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,sBAAsB,EAAE,CAAC,CAAC;SACpD;QACD,IAAI,WAAW,EAAE;YACf,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;SAClC;QACD,OAAO,6BAAa,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IACrE,CAAC;IAED;;;;;;;;;;OAUG;IACH,WAAW,CACT,EAAqB,EACrB,UAAgC,EAAE;QAElC,MAAM,GAAG,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACjD,IAAI,CAAC,GAAG,EAAE;YACR,MAAM,IAAI,6BAAoB,CAC5B,+FAA+F,CAChG,CAAC;SACH;QACD,OAAO,IAAI,6BAAa,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;IACtD,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,UAAU,CACd,KAAoC,SAAS;QAE7C,MAAM,GAAG,GAAG,EAAE,YAAY,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,MAAM,aAAa,GAAG,IAAI,CAAC,yBAAyB,CAAC,GAAG,CAAC,CAAC;QAC1D,IAAI,CAAC,aAAa,EAAE;YAClB,MAAM,IAAI,6BAAoB,CAC5B,yFAAyF,CAC1F,CAAC;SACH;QACD,OAAO,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;IAC5C,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,KAAK,CACT,eAAoD,EACpD,GAAG,gBAAmC;QAEtC,IAAI,GAAa,CAAC;QAClB,IAAI,YAA+B,CAAC;QACpC,IAAI,eAAe,YAAY,KAAK,EAAE;YACpC,GAAG,GAAG,eAAe,CAAC;YACtB,YAAY,GAAG,gBAAgB,CAAC;SACjC;aAAM,IAAI,OAAO,eAAe,KAAK,QAAQ,EAAE;YAC9C,GAAG,GAAG,CAAC,eAAe,CAAC,CAAC;YACxB,YAAY,GAAG,gBAAgB,CAAC;SACjC;aAAM;YACL,GAAG,GAAG,EAAE,CAAC;YACT,YAAY,GAAG,CAAC,eAAe,EAAE,GAAG,gBAAgB,CAAC,CAAC;SACvD;QACD,IAAI,GAAG,GACL,IAAI,CAAC,yBAAyB,CAAC,GAAG,CAAC,CAAC;QACtC,IAAI,CAAC,GAAG,EAAE;YACR,GAAG,GAAG,IAAA,gCAAe,EACnB,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CACpD,CAAC;SACH;QACD,OAAO,IAAI,CAAC,cAAc,CAAC,IAAA,sBAAK,EAAC,GAAG,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,MAAM,CAAC,EAAqB;QAChC,MAAM,GAAG,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACjD,IAAI,CAAC,GAAG,EAAE;YACR,MAAM,IAAI,6BAAoB,CAC5B,4DAA4D,CAC7D,CAAC;SACH;QACD,IAAI;YACF,MAAM,IAAA,0BAAS,EAAC,GAAG,CAAC,CAAC;SACtB;QAAC,OAAO,KAAK,EAAE;YACd,IAAA,0BAAiB,EAAC,KAAK,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;SAC5C;IACH,CAAC;IAED;;;;OAIG;IACH,UAAU,CAAC,EAAqB;QAC9B,MAAM,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC;QACzC,IAAI,CAAC,GAAG,EAAE;YACR,MAAM,IAAI,6BAAoB,CAC5B,sBAAsB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,cAClD,IAAI,CAAC,cAAc,CAAC,MACtB,2BAA2B,GAAG,CAAC,MAAM,GAAG,CACzC,CAAC;SACH;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;;;OAIG;IACH,iBAAiB,CACf,KAAoC,SAAS;QAE7C,MAAM,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,yBAAyB,CAAC,GAAG,CAAC,CAAC;QAChD,IAAI,CAAC,GAAG,EAAE;YACR,MAAM,IAAI,6BAAoB,CAC5B,wBAAwB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,YACpD,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAC/B,2BAA2B,GAAG,CAAC,MAAM,GAAG,CACzC,CAAC;SACH;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,8EAA8E;IAC9E,oBAAoB;IAEpB;;;OAGG;IACK,kBAAkB,CAAC,GAAa;QACtC,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE;YAC7C,OAAO,SAAS,CAAC;SAClB;QACD,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAClE,OAAO,IAAA,oBAAG,EAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACxD,CAAC;IAED;;;OAGG;IACK,yBAAyB,CAC/B,GAAa;QAEb,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE;YACjD,OAAO,SAAS,CAAC;SAClB;QACD,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACzE,OAAO,IAAA,2BAAU,EAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC;IACxE,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,cAAc,CAC1B,KAAkC;QAElC,IAAI,aAA4B,CAAC;QACjC,IAAI;YACF,aAAa,GAAG,MAAM,IAAA,wBAAO,EAAC,KAAK,CAAC,CAAC;SACtC;QAAC,OAAO,KAAK,EAAE;YACd,IAAA,0BAAiB,EACf,KAAK,EACL,SAAS,EACT,KAAK,YAAY,oCAAmB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CACzD,CAAC;YACF,MAAM,KAAK,CAAC;SACb;QACD,OAAO,aAAa,CAAC,IAAI,CAAC,GAAG,CAC3B,CAAC,QAAQ,EAAE,EAAE,CACX,IAAI,6BAAa,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,EAAE;YAC3C,WAAW,EAAE,QAAQ,CAAC,IAAI,EAAE;SAC7B,CAAC,CACL,CAAC;IACJ,CAAC;CACF;AA3RD,oDA2RC"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { CollectionReference, DocumentReference } from "./firestore-deps";
|
|
3
|
+
import { DeepReadonly } from "./ts-helpers";
|
|
4
|
+
/**
|
|
5
|
+
* Public options for initializing a FiretenderDoc object.
|
|
6
|
+
*
|
|
7
|
+
* These will be added as needed (e.g., "readonly" for issue #1, possibly
|
|
8
|
+
* "queryPageLength" for issue #21).
|
|
9
|
+
*/
|
|
10
|
+
export type FiretenderDocOptions = {};
|
|
11
|
+
/**
|
|
12
|
+
* All options when initializing a FiretenderDoc object.
|
|
13
|
+
*
|
|
14
|
+
* This type includes options meant for internal use (createDoc, initialData)
|
|
15
|
+
* as well as the options in FiretenderDocOptions.
|
|
16
|
+
*/
|
|
17
|
+
export type AllFiretenderDocOptions = FiretenderDocOptions & {
|
|
18
|
+
/**
|
|
19
|
+
* Does this FiretenderDoc represent a new document in Firestore?
|
|
20
|
+
*/
|
|
21
|
+
createDoc?: true;
|
|
22
|
+
/**
|
|
23
|
+
* The document's initial data, which must define a valid instance of the
|
|
24
|
+
* document according to its schema.
|
|
25
|
+
*/
|
|
26
|
+
initialData?: Record<string, any>;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* A local representation of a Firestore document.
|
|
30
|
+
*/
|
|
31
|
+
export declare class FiretenderDoc<SchemaType extends z.SomeZodObject> {
|
|
32
|
+
/** Zod schema used to parse and validate the document's data */
|
|
33
|
+
readonly schema: SchemaType;
|
|
34
|
+
/** Firestore reference to this doc, or collection in which to create it */
|
|
35
|
+
private ref;
|
|
36
|
+
/** Firestore document ID; undefined for new docs not yet on Firestore */
|
|
37
|
+
private docID;
|
|
38
|
+
/** Is this a doc we presume does not yet exist in Firestore? */
|
|
39
|
+
private isNewDoc;
|
|
40
|
+
/** Use addDoc or setDoc to write all the data? If not, use updateDoc. */
|
|
41
|
+
private isSettingNewContents;
|
|
42
|
+
/** Local copy of the document data, parsed into the Zod type */
|
|
43
|
+
private data;
|
|
44
|
+
/** Proxy to intercept write (.w) access to the data and track the changes */
|
|
45
|
+
private dataProxy;
|
|
46
|
+
/** Map from the dot-delimited field path (per updateDoc()) to new value */
|
|
47
|
+
private updates;
|
|
48
|
+
/**
|
|
49
|
+
* If a load() call is already in progress, this is a list of promise
|
|
50
|
+
* resolutions to be called once the load is complete. Otherwise undefined.
|
|
51
|
+
*/
|
|
52
|
+
private resolvesWaitingForLoad;
|
|
53
|
+
/**
|
|
54
|
+
* @param schema the Zod object schema describing this document's data.
|
|
55
|
+
* @param ref either a document reference specifying the full path of the
|
|
56
|
+
* document, or a collection reference specifying where a new document will
|
|
57
|
+
* be created.
|
|
58
|
+
* @param options optional parameters for the resulting FiretenderDoc; see
|
|
59
|
+
* FiretenderDocOptions for detail.
|
|
60
|
+
*/
|
|
61
|
+
constructor(schema: SchemaType, ref: DocumentReference | CollectionReference, options?: AllFiretenderDocOptions);
|
|
62
|
+
/**
|
|
63
|
+
* Returns a FiretenderDoc representing a new Firestore document.
|
|
64
|
+
*
|
|
65
|
+
* This method does not create the document in Firestore. To do so, call the
|
|
66
|
+
* write() method.
|
|
67
|
+
*
|
|
68
|
+
* @param schema the Zod object schema describing this document's data.
|
|
69
|
+
* @param ref either a document reference specifying the full path of the
|
|
70
|
+
* document, or a collection reference specifying where a new document will
|
|
71
|
+
* be created.
|
|
72
|
+
* @param initialData the document's initial data, which must define a valid
|
|
73
|
+
* instance of this document according to its schema.
|
|
74
|
+
* @param options optional parameters for the resulting FiretenderDoc; see
|
|
75
|
+
* FiretenderDocOptions for detail.
|
|
76
|
+
*/
|
|
77
|
+
static createNewDoc<SchemaType1 extends z.SomeZodObject>(schema: SchemaType1, ref: DocumentReference | CollectionReference, initialData: z.input<SchemaType1>, options?: FiretenderDocOptions): FiretenderDoc<SchemaType1>;
|
|
78
|
+
/**
|
|
79
|
+
* Creates a copy of this document. Returns a deep copy of its data with a
|
|
80
|
+
* specified or undefined Firestore ID and reference.
|
|
81
|
+
*
|
|
82
|
+
* This method does not create the document in Firestore. To do so, call the
|
|
83
|
+
* write() method. If a document ID or reference is not provided, those will
|
|
84
|
+
* be unset until the write.
|
|
85
|
+
*
|
|
86
|
+
* The location of the new document depends on the type of the `dest`
|
|
87
|
+
* argument:
|
|
88
|
+
* - `undefined` (default): It will be in the same collection and will be
|
|
89
|
+
* assigned a random ID when written to Firestore.
|
|
90
|
+
* - `string`: It will be in the same collection and have a document ID given
|
|
91
|
+
* by `dest`.
|
|
92
|
+
* - `string[]`: It will be in the specified subcollection and receive a
|
|
93
|
+
* random ID (if `type` does not give an ID for the deepest subcollection)
|
|
94
|
+
* or have the fully specified Firestore path (if `type` does).
|
|
95
|
+
* - `DocumentReference`: It will have the given Firestore reference.
|
|
96
|
+
* - `CollectionReference`: It will be in the given subcollection and have a
|
|
97
|
+
* randomly assigned ID upon writing.
|
|
98
|
+
*
|
|
99
|
+
* @param dest the location of the new document; see above for details.
|
|
100
|
+
* @param options optional parameters for the resulting FiretenderDoc; see
|
|
101
|
+
* FiretenderDocOptions for detail.
|
|
102
|
+
*/
|
|
103
|
+
copy(dest?: DocumentReference | CollectionReference | string | string[] | undefined, options?: AllFiretenderDocOptions): FiretenderDoc<SchemaType>;
|
|
104
|
+
/**
|
|
105
|
+
* The document's ID string.
|
|
106
|
+
*
|
|
107
|
+
* @throws Throws an error if the document does not yet have an ID.
|
|
108
|
+
*/
|
|
109
|
+
get id(): string;
|
|
110
|
+
/**
|
|
111
|
+
* The document's Firestore reference.
|
|
112
|
+
*
|
|
113
|
+
* @throws Throws an error if the document does not yet have a reference.
|
|
114
|
+
*/
|
|
115
|
+
get docRef(): DocumentReference;
|
|
116
|
+
/**
|
|
117
|
+
* Is this a new doc that has not yet been written to Firestore?
|
|
118
|
+
*/
|
|
119
|
+
isNew(): boolean;
|
|
120
|
+
/**
|
|
121
|
+
* Does the document contain data, either because it was successfully loaded
|
|
122
|
+
* or is newly created?
|
|
123
|
+
*/
|
|
124
|
+
isLoaded(): boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Does this document contain data that has not yet been written to Firestore?
|
|
127
|
+
*/
|
|
128
|
+
isPendingWrite(): boolean;
|
|
129
|
+
/**
|
|
130
|
+
* Loads this document's data from Firestore.
|
|
131
|
+
*
|
|
132
|
+
* @param force force a read from Firestore. Normally load() does nothing if
|
|
133
|
+
* the document already contains data.
|
|
134
|
+
*/
|
|
135
|
+
load(force?: boolean): Promise<this>;
|
|
136
|
+
/**
|
|
137
|
+
* Read-only accessor to the contents of this document.
|
|
138
|
+
*/
|
|
139
|
+
get r(): DeepReadonly<z.infer<SchemaType>>;
|
|
140
|
+
/**
|
|
141
|
+
* Writable accessor to update the contents of this document.
|
|
142
|
+
*
|
|
143
|
+
* Only use this accessor when making changes to the doc. The .r accessor is
|
|
144
|
+
* considerably more efficient when reading.
|
|
145
|
+
*/
|
|
146
|
+
get w(): z.infer<SchemaType>;
|
|
147
|
+
/**
|
|
148
|
+
* Writable accessor to overwrite all the document data.
|
|
149
|
+
*/
|
|
150
|
+
set w(newData: z.input<SchemaType>);
|
|
151
|
+
/**
|
|
152
|
+
* Writes the document or any updates to Firestore.
|
|
153
|
+
*/
|
|
154
|
+
write(): Promise<this>;
|
|
155
|
+
/**
|
|
156
|
+
* Updates the document's data with a single call.
|
|
157
|
+
*
|
|
158
|
+
* This function loads the document's data, if necessary; calls the given
|
|
159
|
+
* function to make changes to the data; then write the changes to Firestore.
|
|
160
|
+
* If nothing else, it helps you avoid forgetting to call .write()!
|
|
161
|
+
*
|
|
162
|
+
* @param mutator function that accepts a writable data object and makes
|
|
163
|
+
* changes to it.
|
|
164
|
+
*/
|
|
165
|
+
update(mutator: (data: z.infer<SchemaType>) => void): Promise<this>;
|
|
166
|
+
/**
|
|
167
|
+
* Adds a field and its new value to the list of updates to be passed to
|
|
168
|
+
* Firestore's updateDoc(). Called when the proxies detect changes to the
|
|
169
|
+
* document data.
|
|
170
|
+
*/
|
|
171
|
+
private addToUpdateList;
|
|
172
|
+
}
|