firesmelt 0.1.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.
@@ -0,0 +1,565 @@
1
+ // src/core/schema.ts
2
+ function collection(name, schema, options) {
3
+ if (options?.raw && options.raw.length > 0) {
4
+ return { name, schema, raw: options.raw };
5
+ }
6
+ return { name, schema };
7
+ }
8
+
9
+ // src/core/firestore.ts
10
+ function isTimestampLike(value) {
11
+ if (value === null || typeof value !== "object") {
12
+ return false;
13
+ }
14
+ const candidate = value;
15
+ return typeof candidate.seconds === "number" && typeof candidate.nanoseconds === "number" && typeof candidate.toDate === "function";
16
+ }
17
+ var Sentinel = class {
18
+ };
19
+ var ServerTimestampSentinel = class extends Sentinel {
20
+ kind = "serverTimestamp";
21
+ };
22
+ var IncrementSentinel = class extends Sentinel {
23
+ constructor(by) {
24
+ super();
25
+ this.by = by;
26
+ }
27
+ by;
28
+ kind = "increment";
29
+ };
30
+ var ArrayUnionSentinel = class extends Sentinel {
31
+ constructor(values) {
32
+ super();
33
+ this.values = values;
34
+ }
35
+ values;
36
+ kind = "arrayUnion";
37
+ };
38
+ var ArrayRemoveSentinel = class extends Sentinel {
39
+ constructor(values) {
40
+ super();
41
+ this.values = values;
42
+ }
43
+ values;
44
+ kind = "arrayRemove";
45
+ };
46
+ var DeleteFieldSentinel = class extends Sentinel {
47
+ kind = "deleteField";
48
+ };
49
+ function serverTimestamp() {
50
+ return new ServerTimestampSentinel();
51
+ }
52
+ function increment(by) {
53
+ return new IncrementSentinel(by);
54
+ }
55
+ function arrayUnion(...values) {
56
+ return new ArrayUnionSentinel(values);
57
+ }
58
+ function arrayRemove(...values) {
59
+ return new ArrayRemoveSentinel(values);
60
+ }
61
+ function deleteField() {
62
+ return new DeleteFieldSentinel();
63
+ }
64
+ function isSentinel(value) {
65
+ return value instanceof Sentinel;
66
+ }
67
+ var DocumentIdRef = class {
68
+ kind = "documentId";
69
+ };
70
+ var DOCUMENT_ID = new DocumentIdRef();
71
+ function documentId() {
72
+ return DOCUMENT_ID;
73
+ }
74
+
75
+ // src/core/errors.ts
76
+ var FiresmeltError = class extends Error {
77
+ name = "FiresmeltError";
78
+ };
79
+
80
+ // src/core/coerce.ts
81
+ function isPlainObject(value) {
82
+ if (value === null || typeof value !== "object") {
83
+ return false;
84
+ }
85
+ const proto = Object.getPrototypeOf(value);
86
+ return proto === Object.prototype || proto === null;
87
+ }
88
+ function isBytesLike(value) {
89
+ if (value === null || typeof value !== "object") {
90
+ return false;
91
+ }
92
+ const candidate = value;
93
+ return typeof candidate.toUint8Array === "function" && typeof candidate.toBase64 === "function";
94
+ }
95
+ function toNeutral(value, rawPaths, path = "") {
96
+ if (value === null || typeof value !== "object") {
97
+ return value;
98
+ }
99
+ if (rawPaths?.has(path)) {
100
+ return value;
101
+ }
102
+ if (isTimestampLike(value)) {
103
+ return value.toDate();
104
+ }
105
+ if (value instanceof Uint8Array) {
106
+ return new Uint8Array(value);
107
+ }
108
+ if (isBytesLike(value)) {
109
+ return value.toUint8Array();
110
+ }
111
+ if (Array.isArray(value)) {
112
+ return value.map((item) => toNeutral(item, rawPaths, path));
113
+ }
114
+ if (isPlainObject(value)) {
115
+ const out = {};
116
+ for (const key in value) {
117
+ const childPath = rawPaths ? path ? `${path}.${key}` : key : "";
118
+ out[key] = toNeutral(value[key], rawPaths, childPath);
119
+ }
120
+ return out;
121
+ }
122
+ return value;
123
+ }
124
+ function toNative(value, native) {
125
+ if (value === null || typeof value !== "object") {
126
+ return value;
127
+ }
128
+ if (isTimestampLike(value)) {
129
+ return value;
130
+ }
131
+ if (value instanceof Date) {
132
+ return native.timestampFromDate(value);
133
+ }
134
+ if (isSentinel(value)) {
135
+ return native.fieldValue(value);
136
+ }
137
+ if (value instanceof Uint8Array) {
138
+ return native.bytesFromUint8Array(value);
139
+ }
140
+ if (Array.isArray(value)) {
141
+ return value.map((v) => toNative(v, native));
142
+ }
143
+ if (isPlainObject(value)) {
144
+ const out = {};
145
+ for (const key in value) {
146
+ out[key] = toNative(value[key], native);
147
+ }
148
+ return out;
149
+ }
150
+ return value;
151
+ }
152
+ function toNeutralData(data, raw) {
153
+ const rawPaths = raw && raw.length > 0 ? new Set(raw) : void 0;
154
+ return toNeutral(data, rawPaths);
155
+ }
156
+ function toNativeData(data, native) {
157
+ return toNative(data, native);
158
+ }
159
+ function readSnapshot(def, snapshot) {
160
+ if (!snapshot.exists || snapshot.data === void 0) {
161
+ return null;
162
+ }
163
+ const coerced = toNeutralData(snapshot.data, def.raw);
164
+ return { ...coerced, id: snapshot.id };
165
+ }
166
+ function makeConverter(def, native) {
167
+ return {
168
+ toNative(data) {
169
+ const { id: _, ...fields } = data;
170
+ return toNativeData(fields, native);
171
+ },
172
+ fromNative(id, data) {
173
+ const coerced = toNeutralData(data, def.raw);
174
+ return { ...coerced, id };
175
+ }
176
+ };
177
+ }
178
+
179
+ // src/core/driver.ts
180
+ function docLocation(segments) {
181
+ return { kind: "doc", segments };
182
+ }
183
+ function collectionLocation(segments) {
184
+ return { kind: "collection", segments };
185
+ }
186
+
187
+ // src/core/query.ts
188
+ var QueryBuilder = class _QueryBuilder {
189
+ #ctx;
190
+ #constraints;
191
+ constructor(ctx, constraints = []) {
192
+ this.#ctx = ctx;
193
+ this.#constraints = constraints;
194
+ }
195
+ #append(constraint) {
196
+ return new _QueryBuilder(this.#ctx, [...this.#constraints, constraint]);
197
+ }
198
+ where(field, op, value) {
199
+ return this.#append({ type: "where", field, op, value });
200
+ }
201
+ orderBy(field, direction = "asc") {
202
+ return this.#append({ type: "orderBy", field, direction });
203
+ }
204
+ limit(limit) {
205
+ return this.#append({ type: "limit", limit });
206
+ }
207
+ startAt(...values) {
208
+ return this.#append({ type: "startAt", values });
209
+ }
210
+ startAfter(...values) {
211
+ return this.#append({ type: "startAfter", values });
212
+ }
213
+ endAt(...values) {
214
+ return this.#append({ type: "endAt", values });
215
+ }
216
+ endBefore(...values) {
217
+ return this.#append({ type: "endBefore", values });
218
+ }
219
+ async get() {
220
+ const snapshots = await this.#ctx.driver.runQuery(
221
+ this.#ctx.source,
222
+ this.#constraints
223
+ );
224
+ return this.#toDocs(snapshots);
225
+ }
226
+ list() {
227
+ return this.get();
228
+ }
229
+ count() {
230
+ return this.#ctx.driver.count(this.#ctx.source, this.#constraints);
231
+ }
232
+ sum(field) {
233
+ return this.#ctx.driver.sum(this.#ctx.source, this.#constraints, field);
234
+ }
235
+ average(field) {
236
+ return this.#ctx.driver.average(this.#ctx.source, this.#constraints, field);
237
+ }
238
+ onSnapshot(observer) {
239
+ const next = typeof observer === "function" ? observer : observer.next;
240
+ const onError = typeof observer === "function" ? void 0 : observer.error;
241
+ return this.#ctx.driver.onSnapshotQuery(
242
+ this.#ctx.source,
243
+ this.#constraints,
244
+ {
245
+ next: (snapshots) => next(this.#toDocs(snapshots)),
246
+ ...onError && { error: onError }
247
+ }
248
+ );
249
+ }
250
+ #toDocs(snapshots) {
251
+ const docs = [];
252
+ for (const snapshot of snapshots) {
253
+ const result = readSnapshot(this.#ctx.def, snapshot);
254
+ if (result !== null) {
255
+ docs.push(result);
256
+ }
257
+ }
258
+ return docs;
259
+ }
260
+ // Raw query with the coercing converter attached
261
+ get ref() {
262
+ return this.#ctx.driver.queryRef(
263
+ this.#ctx.source,
264
+ this.#constraints,
265
+ makeConverter(this.#ctx.def, this.#ctx.driver.native)
266
+ );
267
+ }
268
+ };
269
+
270
+ // src/core/handles.ts
271
+ var CollectionHandle = class {
272
+ #driver;
273
+ #def;
274
+ #segments;
275
+ constructor(driver, def, segments) {
276
+ this.#driver = driver;
277
+ this.#def = def;
278
+ this.#segments = segments;
279
+ }
280
+ doc(id) {
281
+ return new DocumentHandle(this.#driver, this.#def, [...this.#segments, id]);
282
+ }
283
+ get(id) {
284
+ return this.doc(id).get();
285
+ }
286
+ set(id, data, options) {
287
+ return this.doc(id).set(data, options);
288
+ }
289
+ update(id, data) {
290
+ return this.doc(id).update(data);
291
+ }
292
+ async add(data) {
293
+ const native = toNativeData(data, this.#driver.native);
294
+ return this.#driver.addDoc(collectionLocation(this.#segments), native);
295
+ }
296
+ delete(id) {
297
+ return this.doc(id).delete();
298
+ }
299
+ query() {
300
+ return new QueryBuilder({
301
+ driver: this.#driver,
302
+ def: this.#def,
303
+ source: collectionLocation(this.#segments)
304
+ });
305
+ }
306
+ where(field, op, value) {
307
+ return this.query().where(field, op, value);
308
+ }
309
+ orderBy(field, direction) {
310
+ return this.query().orderBy(field, direction);
311
+ }
312
+ limit(limit) {
313
+ return this.query().limit(limit);
314
+ }
315
+ count() {
316
+ return this.query().count();
317
+ }
318
+ sum(field) {
319
+ return this.query().sum(field);
320
+ }
321
+ average(field) {
322
+ return this.query().average(field);
323
+ }
324
+ onSnapshot(observer) {
325
+ return this.query().onSnapshot(observer);
326
+ }
327
+ // Raw ref with the coercing converter attached
328
+ get ref() {
329
+ return this.#driver.collectionRef(
330
+ collectionLocation(this.#segments),
331
+ makeConverter(this.#def, this.#driver.native)
332
+ );
333
+ }
334
+ };
335
+ var TxCollectionHandle = class {
336
+ #tx;
337
+ #driver;
338
+ #def;
339
+ #segments;
340
+ constructor(tx, driver, def, segments) {
341
+ this.#tx = tx;
342
+ this.#driver = driver;
343
+ this.#def = def;
344
+ this.#segments = segments;
345
+ }
346
+ doc(id) {
347
+ return new TxDocumentHandle(this.#tx, this.#driver, this.#def, [
348
+ ...this.#segments,
349
+ id
350
+ ]);
351
+ }
352
+ get(id) {
353
+ return this.doc(id).get();
354
+ }
355
+ set(id, data, options) {
356
+ this.doc(id).set(data, options);
357
+ }
358
+ update(id, data) {
359
+ this.doc(id).update(data);
360
+ }
361
+ delete(id) {
362
+ this.doc(id).delete();
363
+ }
364
+ };
365
+ var BatchCollectionHandle = class {
366
+ #batch;
367
+ #driver;
368
+ #segments;
369
+ constructor(batch, driver, segments) {
370
+ this.#batch = batch;
371
+ this.#driver = driver;
372
+ this.#segments = segments;
373
+ }
374
+ doc(id) {
375
+ return new BatchDocumentHandle(this.#batch, this.#driver, [
376
+ ...this.#segments,
377
+ id
378
+ ]);
379
+ }
380
+ set(id, data, options) {
381
+ this.doc(id).set(data, options);
382
+ }
383
+ update(id, data) {
384
+ this.doc(id).update(data);
385
+ }
386
+ delete(id) {
387
+ this.doc(id).delete();
388
+ }
389
+ };
390
+ var DocumentHandle = class {
391
+ #driver;
392
+ #def;
393
+ #segments;
394
+ constructor(driver, def, segments) {
395
+ this.#driver = driver;
396
+ this.#def = def;
397
+ this.#segments = segments;
398
+ }
399
+ get id() {
400
+ return this.#segments[this.#segments.length - 1];
401
+ }
402
+ collection(def) {
403
+ return new CollectionHandle(this.#driver, def, [
404
+ ...this.#segments,
405
+ def.name
406
+ ]);
407
+ }
408
+ async get() {
409
+ const snapshot = await this.#driver.getDoc(docLocation(this.#segments));
410
+ return readSnapshot(this.#def, snapshot);
411
+ }
412
+ async exists() {
413
+ const snapshot = await this.#driver.getDoc(docLocation(this.#segments));
414
+ return snapshot.exists;
415
+ }
416
+ async set(data, options) {
417
+ const native = toNativeData(data, this.#driver.native);
418
+ await this.#driver.setDoc(docLocation(this.#segments), native, options);
419
+ }
420
+ async update(data) {
421
+ const native = toNativeData(data, this.#driver.native);
422
+ await this.#driver.updateDoc(docLocation(this.#segments), native);
423
+ }
424
+ delete() {
425
+ return this.#driver.deleteDoc(docLocation(this.#segments));
426
+ }
427
+ onSnapshot(observer) {
428
+ const next = typeof observer === "function" ? observer : observer.next;
429
+ const onError = typeof observer === "function" ? void 0 : observer.error;
430
+ return this.#driver.onSnapshotDoc(docLocation(this.#segments), {
431
+ next: (snapshot) => next(readSnapshot(this.#def, snapshot)),
432
+ ...onError && { error: onError }
433
+ });
434
+ }
435
+ // Raw ref with the coercing converter attached
436
+ get ref() {
437
+ return this.#driver.docRef(
438
+ docLocation(this.#segments),
439
+ makeConverter(this.#def, this.#driver.native)
440
+ );
441
+ }
442
+ };
443
+ var TxDocumentHandle = class {
444
+ #tx;
445
+ #driver;
446
+ #def;
447
+ #segments;
448
+ constructor(tx, driver, def, segments) {
449
+ this.#tx = tx;
450
+ this.#driver = driver;
451
+ this.#def = def;
452
+ this.#segments = segments;
453
+ }
454
+ get id() {
455
+ return this.#segments[this.#segments.length - 1];
456
+ }
457
+ collection(def) {
458
+ return new TxCollectionHandle(this.#tx, this.#driver, def, [
459
+ ...this.#segments,
460
+ def.name
461
+ ]);
462
+ }
463
+ async get() {
464
+ const snapshot = await this.#tx.get(docLocation(this.#segments));
465
+ return readSnapshot(this.#def, snapshot);
466
+ }
467
+ set(data, options) {
468
+ const native = toNativeData(data, this.#driver.native);
469
+ this.#tx.set(docLocation(this.#segments), native, options);
470
+ }
471
+ update(data) {
472
+ const native = toNativeData(data, this.#driver.native);
473
+ this.#tx.update(docLocation(this.#segments), native);
474
+ }
475
+ delete() {
476
+ this.#tx.delete(docLocation(this.#segments));
477
+ }
478
+ };
479
+ var BatchDocumentHandle = class {
480
+ #batch;
481
+ #driver;
482
+ #segments;
483
+ constructor(batch, driver, segments) {
484
+ this.#batch = batch;
485
+ this.#driver = driver;
486
+ this.#segments = segments;
487
+ }
488
+ get id() {
489
+ return this.#segments[this.#segments.length - 1];
490
+ }
491
+ collection(def) {
492
+ return new BatchCollectionHandle(this.#batch, this.#driver, [
493
+ ...this.#segments,
494
+ def.name
495
+ ]);
496
+ }
497
+ set(data, options) {
498
+ const native = toNativeData(data, this.#driver.native);
499
+ this.#batch.set(docLocation(this.#segments), native, options);
500
+ }
501
+ update(data) {
502
+ const native = toNativeData(data, this.#driver.native);
503
+ this.#batch.update(docLocation(this.#segments), native);
504
+ }
505
+ delete() {
506
+ this.#batch.delete(docLocation(this.#segments));
507
+ }
508
+ };
509
+
510
+ // src/core/database.ts
511
+ var Transaction = class {
512
+ #tx;
513
+ #driver;
514
+ constructor(tx, driver) {
515
+ this.#tx = tx;
516
+ this.#driver = driver;
517
+ }
518
+ collection(def) {
519
+ return new TxCollectionHandle(this.#tx, this.#driver, def, [def.name]);
520
+ }
521
+ };
522
+ var Batch = class {
523
+ #batch;
524
+ #driver;
525
+ constructor(batch, driver) {
526
+ this.#batch = batch;
527
+ this.#driver = driver;
528
+ }
529
+ collection(def) {
530
+ return new BatchCollectionHandle(this.#batch, this.#driver, [def.name]);
531
+ }
532
+ commit() {
533
+ return this.#batch.commit();
534
+ }
535
+ };
536
+ var Database = class {
537
+ #driver;
538
+ constructor(driver) {
539
+ this.#driver = driver;
540
+ }
541
+ collection(def) {
542
+ return new CollectionHandle(this.#driver, def, [def.name]);
543
+ }
544
+ // Cross-parent query over every collection sharing this id
545
+ collectionGroup(def) {
546
+ return new QueryBuilder({
547
+ driver: this.#driver,
548
+ def,
549
+ source: { kind: "collectionGroup", collectionId: def.name }
550
+ });
551
+ }
552
+ runTransaction(fn, options) {
553
+ return this.#driver.runTransaction(
554
+ (tx) => fn(new Transaction(tx, this.#driver)),
555
+ options
556
+ );
557
+ }
558
+ batch() {
559
+ return new Batch(this.#driver.batch(), this.#driver);
560
+ }
561
+ };
562
+
563
+ export { ArrayRemoveSentinel, ArrayUnionSentinel, Batch, BatchCollectionHandle, BatchDocumentHandle, CollectionHandle, Database, DeleteFieldSentinel, DocumentHandle, FiresmeltError, IncrementSentinel, QueryBuilder, ServerTimestampSentinel, Transaction, TxCollectionHandle, TxDocumentHandle, arrayRemove, arrayUnion, collection, deleteField, documentId, increment, isTimestampLike, serverTimestamp, toNative };
564
+ //# sourceMappingURL=chunk-WEVOVXQQ.js.map
565
+ //# sourceMappingURL=chunk-WEVOVXQQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/schema.ts","../src/core/firestore.ts","../src/core/errors.ts","../src/core/coerce.ts","../src/core/driver.ts","../src/core/query.ts","../src/core/handles.ts","../src/core/database.ts"],"names":[],"mappings":"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","file":"chunk-WEVOVXQQ.js","sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nimport type { CollectionDef, InferOutput } from \"@/core/types\";\n\nexport interface CollectionOptions {\n raw?: readonly string[];\n}\n\nexport function collection<S extends StandardSchemaV1>(\n name: string,\n // Id comes from the path, reject a schema declaring its own\n schema: S & (\"id\" extends keyof InferOutput<S> ? never : unknown),\n options?: CollectionOptions,\n): CollectionDef<S> {\n if (options?.raw && options.raw.length > 0) {\n return { name, schema, raw: options.raw };\n }\n return { name, schema };\n}\n","export interface Timestamp {\n readonly seconds: number;\n readonly nanoseconds: number;\n toDate(): Date;\n toMillis(): number;\n isEqual(other: Timestamp): boolean;\n}\n\n// Duck-types both SDK Timestamps by shape so one schema can validate either\nexport function isTimestampLike(value: unknown): value is Timestamp {\n if (value === null || typeof value !== \"object\") {\n return false;\n }\n const candidate = value as Record<string, unknown>;\n return (\n typeof candidate.seconds === \"number\" &&\n typeof candidate.nanoseconds === \"number\" &&\n typeof candidate.toDate === \"function\"\n );\n}\n\nexport interface GeoPoint {\n readonly latitude: number;\n readonly longitude: number;\n isEqual(other: GeoPoint): boolean;\n}\n\n// Doc reference by id and path, no isEqual since web SDK uses refEqual()\nexport interface DocumentReference {\n readonly id: string;\n readonly path: string;\n}\n\nexport interface VectorValue {\n toArray(): number[];\n isEqual(other: VectorValue): boolean;\n}\n\n// Neutral write sentinels since a schema cannot reference an SDK FieldValue\nexport abstract class Sentinel {\n abstract readonly kind: string;\n}\n\nexport class ServerTimestampSentinel extends Sentinel {\n readonly kind = \"serverTimestamp\";\n}\n\nexport class IncrementSentinel extends Sentinel {\n readonly kind = \"increment\";\n constructor(readonly by: number) {\n super();\n }\n}\n\nexport class ArrayUnionSentinel<E = unknown> extends Sentinel {\n readonly kind = \"arrayUnion\";\n constructor(readonly values: ReadonlyArray<E>) {\n super();\n }\n}\n\nexport class ArrayRemoveSentinel<E = unknown> extends Sentinel {\n readonly kind = \"arrayRemove\";\n constructor(readonly values: ReadonlyArray<E>) {\n super();\n }\n}\n\nexport class DeleteFieldSentinel extends Sentinel {\n readonly kind = \"deleteField\";\n}\n\nexport function serverTimestamp(): ServerTimestampSentinel {\n return new ServerTimestampSentinel();\n}\n\nexport function increment(by: number): IncrementSentinel {\n return new IncrementSentinel(by);\n}\n\nexport function arrayUnion<E>(...values: Array<E>): ArrayUnionSentinel<E> {\n return new ArrayUnionSentinel(values);\n}\n\nexport function arrayRemove<E>(...values: Array<E>): ArrayRemoveSentinel<E> {\n return new ArrayRemoveSentinel(values);\n}\n\nexport function deleteField(): DeleteFieldSentinel {\n return new DeleteFieldSentinel();\n}\n\nexport function isSentinel(value: unknown): value is Sentinel {\n return value instanceof Sentinel;\n}\n\n// Neutral doc-id reference for where()/orderBy(), off the schema field surface\nexport class DocumentIdRef {\n readonly kind = \"documentId\";\n}\n\nconst DOCUMENT_ID = new DocumentIdRef();\n\n// Reference doc id in where()/orderBy(), though id is otherwise off the field surface\nexport function documentId(): DocumentIdRef {\n return DOCUMENT_ID;\n}\n","// Base for firesmelt's own failures, SDK and network errors propagate untouched\nexport class FiresmeltError extends Error {\n override readonly name: string = \"FiresmeltError\";\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nimport type {\n DocumentData,\n NativeAdapter,\n RawConverter,\n RawSnapshot,\n} from \"@/core/driver\";\nimport { isSentinel, isTimestampLike } from \"@/core/firestore\";\nimport type { CollectionDef, Doc } from \"@/core/types\";\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== \"object\") {\n return false;\n }\n const proto = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n// Web SDK Bytes, duck-typed so core imports no SDK (admin bytes are a Uint8Array)\nfunction isBytesLike(value: unknown): value is { toUint8Array(): Uint8Array } {\n if (value === null || typeof value !== \"object\") {\n return false;\n }\n const candidate = value as Record<string, unknown>;\n return (\n typeof candidate.toUint8Array === \"function\" &&\n typeof candidate.toBase64 === \"function\"\n );\n}\n\n// Read path, Firestore storage values to neutral domain values\nfunction toNeutral(\n value: unknown,\n rawPaths?: ReadonlySet<string>,\n path = \"\",\n): unknown {\n // Primitives never coerce, skip object guards on scalar fields\n if (value === null || typeof value !== \"object\") {\n return value;\n }\n // Listed path stays the raw SDK value, whole subtree, no recursion\n if (rawPaths?.has(path)) {\n return value;\n }\n if (isTimestampLike(value)) {\n return value.toDate();\n }\n // Admin bytes are a Buffer, normalise to a plain Uint8Array so neither leaks\n if (value instanceof Uint8Array) {\n return new Uint8Array(value);\n }\n if (isBytesLike(value)) {\n return value.toUint8Array();\n }\n if (Array.isArray(value)) {\n return value.map((item) => toNeutral(item, rawPaths, path));\n }\n if (isPlainObject(value)) {\n const out: Record<string, unknown> = {};\n for (const key in value) {\n const childPath = rawPaths ? (path ? `${path}.${key}` : key) : \"\";\n out[key] = toNeutral(value[key], rawPaths, childPath);\n }\n return out;\n }\n return value;\n}\n\n// Write path, neutral domain values to Firestore storage values\nexport function toNative(value: unknown, native: NativeAdapter): unknown {\n // Primitives never coerce, skip object guards on scalar fields\n if (value === null || typeof value !== \"object\") {\n return value;\n }\n if (isTimestampLike(value)) {\n return value;\n }\n if (value instanceof Date) {\n return native.timestampFromDate(value);\n }\n if (isSentinel(value)) {\n return native.fieldValue(value);\n }\n // Buffer is a Uint8Array, web needs its Bytes class, admin takes it as-is\n if (value instanceof Uint8Array) {\n return native.bytesFromUint8Array(value);\n }\n if (Array.isArray(value)) {\n return value.map((v) => toNative(v, native));\n }\n if (isPlainObject(value)) {\n const out: Record<string, unknown> = {};\n for (const key in value) {\n out[key] = toNative(value[key], native);\n }\n return out;\n }\n return value;\n}\n\nexport function toNeutralData(\n data: DocumentData,\n raw?: readonly string[],\n): DocumentData {\n const rawPaths = raw && raw.length > 0 ? new Set(raw) : undefined;\n return toNeutral(data, rawPaths) as DocumentData;\n}\n\nexport function toNativeData(\n data: unknown,\n native: NativeAdapter,\n): DocumentData {\n return toNative(data, native) as DocumentData;\n}\n\n// Reads coerce stored values to neutral types, then merge the doc id in flat\nexport function readSnapshot<S extends StandardSchemaV1>(\n def: CollectionDef<S>,\n snapshot: RawSnapshot,\n): Doc<S> | null {\n if (!snapshot.exists || snapshot.data === undefined) {\n return null;\n }\n const coerced = toNeutralData(snapshot.data, def.raw);\n return { ...(coerced as object), id: snapshot.id } as Doc<S>;\n}\n\n// Converter for .ref, coerces both ways so the SDK round-trips timestamps\nexport function makeConverter<S extends StandardSchemaV1>(\n def: CollectionDef<S>,\n native: NativeAdapter,\n): RawConverter {\n return {\n toNative(data: DocumentData): DocumentData {\n // Id comes from the path, never stored\n const { id: _, ...fields } = data;\n return toNativeData(fields, native);\n },\n fromNative(id: string, data: DocumentData): unknown {\n const coerced = toNeutralData(data, def.raw);\n return { ...(coerced as object), id };\n },\n };\n}\n","import type { DocumentIdRef, Sentinel } from \"@/core/firestore\";\nimport type { WhereFilterOp } from \"@/core/types\";\n\nexport type DocumentData = Record<string, unknown>;\n\n// Field for where()/orderBy(), dotted path or document id reference\nexport type FieldRef = string | DocumentIdRef;\n\n// Document location, even-length segments like [collection, id, ...]\nexport interface DocLocation {\n readonly kind: \"doc\";\n readonly segments: readonly string[];\n}\n\nexport function docLocation(segments: readonly string[]): DocLocation {\n return { kind: \"doc\", segments };\n}\n\n// Collection location, odd-length segments [collection, id, ..., collection]\nexport interface CollectionLocation {\n readonly kind: \"collection\";\n readonly segments: readonly string[];\n}\n\nexport function collectionLocation(\n segments: readonly string[],\n): CollectionLocation {\n return { kind: \"collection\", segments };\n}\n\nexport interface CollectionGroupLocation {\n readonly kind: \"collectionGroup\";\n readonly collectionId: string;\n}\n\nexport type QuerySource = CollectionLocation | CollectionGroupLocation;\n\n// Neutral query AST each driver translates to its SDK\nexport type Constraint =\n | { type: \"where\"; field: FieldRef; op: WhereFilterOp; value: unknown }\n | { type: \"orderBy\"; field: FieldRef; direction: \"asc\" | \"desc\" }\n | { type: \"limit\"; limit: number }\n | { type: \"startAt\"; values: readonly unknown[] }\n | { type: \"startAfter\"; values: readonly unknown[] }\n | { type: \"endAt\"; values: readonly unknown[] }\n | { type: \"endBefore\"; values: readonly unknown[] };\n\nexport interface RawSnapshot {\n readonly id: string;\n readonly exists: boolean;\n readonly data: DocumentData | undefined;\n}\n\nexport interface WriteOptions {\n readonly merge?: boolean;\n // Field paths to merge, exclusive with merge\n readonly mergeFields?: readonly string[];\n}\n\nexport interface TransactionOptions {\n readonly maxAttempts?: number;\n}\n\nexport type Unsubscribe = () => void;\n\n// Absent error handler must reach the SDK as absent, its default handling wins\nexport interface DocObserver {\n next(snapshot: RawSnapshot): void;\n error?(error: unknown): void;\n}\n\nexport interface QueryObserver {\n next(snapshots: readonly RawSnapshot[]): void;\n error?(error: unknown): void;\n}\n\n// Turns neutral values into SDK's Timestamp, FieldValue and bytes type\nexport interface NativeAdapter {\n timestampFromDate(date: Date): unknown;\n fieldValue(sentinel: Sentinel): unknown;\n bytesFromUint8Array(bytes: Uint8Array): unknown;\n}\n\nexport interface RawConverter {\n toNative(data: DocumentData): DocumentData;\n fromNative(id: string, data: DocumentData): unknown;\n}\n\n// Transaction writes buffer until commit, so only get awaits\nexport interface TxDriver {\n get(path: DocLocation): Promise<RawSnapshot>;\n set(path: DocLocation, data: DocumentData, options?: WriteOptions): void;\n update(path: DocLocation, data: DocumentData): void;\n delete(path: DocLocation): void;\n}\n\n// Blind batched writes, buffer synchronously until an explicit commit\nexport interface BatchDriver {\n set(path: DocLocation, data: DocumentData, options?: WriteOptions): void;\n update(path: DocLocation, data: DocumentData): void;\n delete(path: DocLocation): void;\n commit(): Promise<void>;\n}\n\nexport interface Driver {\n readonly native: NativeAdapter;\n\n getDoc(path: DocLocation): Promise<RawSnapshot>;\n setDoc(\n path: DocLocation,\n data: DocumentData,\n options?: WriteOptions,\n ): Promise<void>;\n updateDoc(path: DocLocation, data: DocumentData): Promise<void>;\n addDoc(path: CollectionLocation, data: DocumentData): Promise<string>;\n deleteDoc(path: DocLocation): Promise<void>;\n\n runQuery(\n source: QuerySource,\n constraints: readonly Constraint[],\n ): Promise<RawSnapshot[]>;\n count(\n source: QuerySource,\n constraints: readonly Constraint[],\n ): Promise<number>;\n sum(\n source: QuerySource,\n constraints: readonly Constraint[],\n field: string,\n ): Promise<number>;\n // Null when no document matches, empty set has no average\n average(\n source: QuerySource,\n constraints: readonly Constraint[],\n field: string,\n ): Promise<number | null>;\n\n onSnapshotDoc(path: DocLocation, observer: DocObserver): Unsubscribe;\n onSnapshotQuery(\n source: QuerySource,\n constraints: readonly Constraint[],\n observer: QueryObserver,\n ): Unsubscribe;\n\n runTransaction<T>(\n fn: (tx: TxDriver) => Promise<T>,\n options?: TransactionOptions,\n ): Promise<T>;\n\n batch(): BatchDriver;\n\n docRef(path: DocLocation, converter: RawConverter): unknown;\n collectionRef(path: CollectionLocation, converter: RawConverter): unknown;\n queryRef(\n source: QuerySource,\n constraints: readonly Constraint[],\n converter: RawConverter,\n ): unknown;\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nimport { makeConverter, readSnapshot } from \"@/core/coerce\";\nimport type {\n Constraint,\n Driver,\n FieldRef,\n QuerySource,\n RawSnapshot,\n Unsubscribe,\n} from \"@/core/driver\";\nimport type { DocumentIdRef } from \"@/core/firestore\";\nimport type {\n ArrayElement,\n CollectionDef,\n Doc,\n FieldPath,\n InferOutput,\n NumericFieldPath,\n OrderByDirection,\n ValueAtPath,\n WhereFilterOp,\n} from \"@/core/types\";\n\ninterface QueryContext<S extends StandardSchemaV1> {\n driver: Driver;\n def: CollectionDef<S>;\n source: QuerySource;\n}\n\n// where() and orderBy() field typing, dotted paths reach into nested maps\nexport type WhereField<S extends StandardSchemaV1> = FieldPath<InferOutput<S>>;\n// Exclude undefined only, null is queryable\nexport type WhereValue<\n S extends StandardSchemaV1,\n K extends WhereField<S>,\n> = Exclude<ValueAtPath<InferOutput<S>, K>, undefined>;\n\n// sum() and average() field typing, numeric dotted paths only\nexport type NumericField<S extends StandardSchemaV1> = NumericFieldPath<\n InferOutput<S>\n>;\n\nexport type QuerySnapshotObserver<S extends StandardSchemaV1> =\n | ((docs: Array<Doc<S>>) => void)\n | {\n next: (docs: Array<Doc<S>>) => void;\n error?: (error: unknown) => void;\n };\n\nexport class QueryBuilder<S extends StandardSchemaV1> {\n readonly #ctx: QueryContext<S>;\n readonly #constraints: readonly Constraint[];\n\n constructor(ctx: QueryContext<S>, constraints: readonly Constraint[] = []) {\n this.#ctx = ctx;\n this.#constraints = constraints;\n }\n\n #append(constraint: Constraint): QueryBuilder<S> {\n return new QueryBuilder(this.#ctx, [...this.#constraints, constraint]);\n }\n\n where<K extends WhereField<S>>(\n field: K,\n op: \"in\" | \"not-in\",\n value: Array<WhereValue<S, K>>,\n ): QueryBuilder<S>;\n where<K extends WhereField<S>>(\n field: K,\n op: \"array-contains\",\n value: ArrayElement<WhereValue<S, K>>,\n ): QueryBuilder<S>;\n where<K extends WhereField<S>>(\n field: K,\n op: \"array-contains-any\",\n value: Array<ArrayElement<WhereValue<S, K>>>,\n ): QueryBuilder<S>;\n where<K extends WhereField<S>>(\n field: K,\n op: \"==\" | \"!=\" | \"<\" | \"<=\" | \">\" | \">=\",\n value: WhereValue<S, K>,\n ): QueryBuilder<S>;\n // Document id queries, id values are plain strings\n where(\n field: DocumentIdRef,\n op: \"in\" | \"not-in\",\n value: string[],\n ): QueryBuilder<S>;\n where(\n field: DocumentIdRef,\n op: \"==\" | \"!=\" | \"<\" | \"<=\" | \">\" | \">=\",\n value: string,\n ): QueryBuilder<S>;\n where(field: FieldRef, op: WhereFilterOp, value: unknown): QueryBuilder<S> {\n return this.#append({ type: \"where\", field, op, value });\n }\n\n orderBy(field: WhereField<S>, direction?: OrderByDirection): QueryBuilder<S>;\n orderBy(field: DocumentIdRef, direction?: OrderByDirection): QueryBuilder<S>;\n orderBy(\n field: FieldRef,\n direction: OrderByDirection = \"asc\",\n ): QueryBuilder<S> {\n return this.#append({ type: \"orderBy\", field, direction });\n }\n\n limit(limit: number): QueryBuilder<S> {\n return this.#append({ type: \"limit\", limit });\n }\n\n startAt(...values: unknown[]): QueryBuilder<S> {\n return this.#append({ type: \"startAt\", values });\n }\n\n startAfter(...values: unknown[]): QueryBuilder<S> {\n return this.#append({ type: \"startAfter\", values });\n }\n\n endAt(...values: unknown[]): QueryBuilder<S> {\n return this.#append({ type: \"endAt\", values });\n }\n\n endBefore(...values: unknown[]): QueryBuilder<S> {\n return this.#append({ type: \"endBefore\", values });\n }\n\n async get(): Promise<Array<Doc<S>>> {\n const snapshots = await this.#ctx.driver.runQuery(\n this.#ctx.source,\n this.#constraints,\n );\n return this.#toDocs(snapshots);\n }\n\n list(): Promise<Array<Doc<S>>> {\n return this.get();\n }\n\n count(): Promise<number> {\n return this.#ctx.driver.count(this.#ctx.source, this.#constraints);\n }\n\n sum(field: NumericField<S>): Promise<number> {\n return this.#ctx.driver.sum(this.#ctx.source, this.#constraints, field);\n }\n\n average(field: NumericField<S>): Promise<number | null> {\n return this.#ctx.driver.average(this.#ctx.source, this.#constraints, field);\n }\n\n onSnapshot(observer: QuerySnapshotObserver<S>): Unsubscribe {\n const next = typeof observer === \"function\" ? observer : observer.next;\n const onError = typeof observer === \"function\" ? undefined : observer.error;\n return this.#ctx.driver.onSnapshotQuery(\n this.#ctx.source,\n this.#constraints,\n {\n next: (snapshots) => next(this.#toDocs(snapshots)),\n ...(onError && { error: onError }),\n },\n );\n }\n\n #toDocs(snapshots: readonly RawSnapshot[]): Array<Doc<S>> {\n const docs: Array<Doc<S>> = [];\n for (const snapshot of snapshots) {\n const result = readSnapshot(this.#ctx.def, snapshot);\n if (result !== null) {\n docs.push(result);\n }\n }\n return docs;\n }\n\n // Raw query with the coercing converter attached\n get ref(): unknown {\n return this.#ctx.driver.queryRef(\n this.#ctx.source,\n this.#constraints,\n makeConverter(this.#ctx.def, this.#ctx.driver.native),\n );\n }\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nimport { makeConverter, readSnapshot, toNativeData } from \"@/core/coerce\";\nimport {\n type BatchDriver,\n collectionLocation,\n docLocation,\n type Driver,\n type FieldRef,\n type TxDriver,\n type Unsubscribe,\n type WriteOptions,\n} from \"@/core/driver\";\nimport type { DocumentIdRef } from \"@/core/firestore\";\nimport {\n type NumericField,\n QueryBuilder,\n type QuerySnapshotObserver,\n type WhereField,\n type WhereValue,\n} from \"@/core/query\";\nimport type {\n ArrayElement,\n CollectionDef,\n Doc,\n InferOutput,\n MergeOptions,\n OrderByDirection,\n UpdateData,\n UpdatePaths,\n WhereFilterOp,\n WithFieldValue,\n} from \"@/core/types\";\n\nexport class CollectionHandle<S extends StandardSchemaV1> {\n readonly #driver: Driver;\n readonly #def: CollectionDef<S>;\n readonly #segments: readonly string[];\n\n constructor(\n driver: Driver,\n def: CollectionDef<S>,\n segments: readonly string[],\n ) {\n this.#driver = driver;\n this.#def = def;\n this.#segments = segments;\n }\n\n doc(id: string): DocumentHandle<S> {\n return new DocumentHandle(this.#driver, this.#def, [...this.#segments, id]);\n }\n\n get(id: string): Promise<Doc<S> | null> {\n return this.doc(id).get();\n }\n\n set(id: string, data: WithFieldValue<InferOutput<S>>): Promise<void>;\n set(\n id: string,\n data: UpdateData<InferOutput<S>>,\n options: MergeOptions<InferOutput<S>>,\n ): Promise<void>;\n set(id: string, data: unknown, options?: WriteOptions): Promise<void> {\n return this.doc(id).set(data as never, options as never);\n }\n\n update(id: string, data: UpdatePaths<InferOutput<S>>): Promise<void> {\n return this.doc(id).update(data);\n }\n\n async add(data: WithFieldValue<InferOutput<S>>): Promise<string> {\n const native = toNativeData(data, this.#driver.native);\n return this.#driver.addDoc(collectionLocation(this.#segments), native);\n }\n\n delete(id: string): Promise<void> {\n return this.doc(id).delete();\n }\n\n query(): QueryBuilder<S> {\n return new QueryBuilder({\n driver: this.#driver,\n def: this.#def,\n source: collectionLocation(this.#segments),\n });\n }\n\n where<K extends WhereField<S>>(\n field: K,\n op: \"in\" | \"not-in\",\n value: Array<WhereValue<S, K>>,\n ): QueryBuilder<S>;\n where<K extends WhereField<S>>(\n field: K,\n op: \"array-contains\",\n value: ArrayElement<WhereValue<S, K>>,\n ): QueryBuilder<S>;\n where<K extends WhereField<S>>(\n field: K,\n op: \"array-contains-any\",\n value: Array<ArrayElement<WhereValue<S, K>>>,\n ): QueryBuilder<S>;\n where<K extends WhereField<S>>(\n field: K,\n op: \"==\" | \"!=\" | \"<\" | \"<=\" | \">\" | \">=\",\n value: WhereValue<S, K>,\n ): QueryBuilder<S>;\n // Document id queries, id values are plain strings\n where(\n field: DocumentIdRef,\n op: \"in\" | \"not-in\",\n value: string[],\n ): QueryBuilder<S>;\n where(\n field: DocumentIdRef,\n op: \"==\" | \"!=\" | \"<\" | \"<=\" | \">\" | \">=\",\n value: string,\n ): QueryBuilder<S>;\n where(field: FieldRef, op: WhereFilterOp, value: unknown): QueryBuilder<S> {\n return this.query().where(field as never, op as never, value as never);\n }\n\n orderBy(field: WhereField<S>, direction?: OrderByDirection): QueryBuilder<S>;\n orderBy(field: DocumentIdRef, direction?: OrderByDirection): QueryBuilder<S>;\n orderBy(field: FieldRef, direction?: OrderByDirection): QueryBuilder<S> {\n return this.query().orderBy(field as never, direction);\n }\n\n limit(limit: number): QueryBuilder<S> {\n return this.query().limit(limit);\n }\n\n count(): Promise<number> {\n return this.query().count();\n }\n\n sum(field: NumericField<S>): Promise<number> {\n return this.query().sum(field);\n }\n\n average(field: NumericField<S>): Promise<number | null> {\n return this.query().average(field);\n }\n\n onSnapshot(observer: QuerySnapshotObserver<S>): Unsubscribe {\n return this.query().onSnapshot(observer);\n }\n\n // Raw ref with the coercing converter attached\n get ref(): unknown {\n return this.#driver.collectionRef(\n collectionLocation(this.#segments),\n makeConverter(this.#def, this.#driver.native),\n );\n }\n}\n\nexport class TxCollectionHandle<S extends StandardSchemaV1> {\n readonly #tx: TxDriver;\n readonly #driver: Driver;\n readonly #def: CollectionDef<S>;\n readonly #segments: readonly string[];\n\n constructor(\n tx: TxDriver,\n driver: Driver,\n def: CollectionDef<S>,\n segments: readonly string[],\n ) {\n this.#tx = tx;\n this.#driver = driver;\n this.#def = def;\n this.#segments = segments;\n }\n\n doc(id: string): TxDocumentHandle<S> {\n return new TxDocumentHandle(this.#tx, this.#driver, this.#def, [\n ...this.#segments,\n id,\n ]);\n }\n\n get(id: string): Promise<Doc<S> | null> {\n return this.doc(id).get();\n }\n\n // Buffer writes synchronously so a forgotten await still enqueues pre-commit\n set(id: string, data: WithFieldValue<InferOutput<S>>): void;\n set(\n id: string,\n data: UpdateData<InferOutput<S>>,\n options: MergeOptions<InferOutput<S>>,\n ): void;\n set(id: string, data: unknown, options?: WriteOptions): void {\n this.doc(id).set(data as never, options as never);\n }\n\n update(id: string, data: UpdatePaths<InferOutput<S>>): void {\n this.doc(id).update(data);\n }\n\n delete(id: string): void {\n this.doc(id).delete();\n }\n}\n\n// Write-only, so it carries no def, there is no read to coerce\nexport class BatchCollectionHandle<S extends StandardSchemaV1> {\n readonly #batch: BatchDriver;\n readonly #driver: Driver;\n readonly #segments: readonly string[];\n\n constructor(batch: BatchDriver, driver: Driver, segments: readonly string[]) {\n this.#batch = batch;\n this.#driver = driver;\n this.#segments = segments;\n }\n\n doc(id: string): BatchDocumentHandle<S> {\n return new BatchDocumentHandle<S>(this.#batch, this.#driver, [\n ...this.#segments,\n id,\n ]);\n }\n\n // Buffer writes synchronously so a forgotten await still enqueues pre-commit\n set(id: string, data: WithFieldValue<InferOutput<S>>): void;\n set(\n id: string,\n data: UpdateData<InferOutput<S>>,\n options: MergeOptions<InferOutput<S>>,\n ): void;\n set(id: string, data: unknown, options?: WriteOptions): void {\n this.doc(id).set(data as never, options as never);\n }\n\n update(id: string, data: UpdatePaths<InferOutput<S>>): void {\n this.doc(id).update(data);\n }\n\n delete(id: string): void {\n this.doc(id).delete();\n }\n}\n\nexport type DocSnapshotObserver<S extends StandardSchemaV1> =\n | ((doc: Doc<S> | null) => void)\n | {\n next: (doc: Doc<S> | null) => void;\n error?: (error: unknown) => void;\n };\n\nexport class DocumentHandle<S extends StandardSchemaV1> {\n readonly #driver: Driver;\n readonly #def: CollectionDef<S>;\n readonly #segments: readonly string[];\n\n constructor(\n driver: Driver,\n def: CollectionDef<S>,\n segments: readonly string[],\n ) {\n this.#driver = driver;\n this.#def = def;\n this.#segments = segments;\n }\n\n get id(): string {\n return this.#segments[this.#segments.length - 1]!;\n }\n\n collection<C extends StandardSchemaV1>(\n def: CollectionDef<C>,\n ): CollectionHandle<C> {\n return new CollectionHandle(this.#driver, def, [\n ...this.#segments,\n def.name,\n ]);\n }\n\n async get(): Promise<Doc<S> | null> {\n const snapshot = await this.#driver.getDoc(docLocation(this.#segments));\n return readSnapshot(this.#def, snapshot);\n }\n\n async exists(): Promise<boolean> {\n const snapshot = await this.#driver.getDoc(docLocation(this.#segments));\n return snapshot.exists;\n }\n\n set(data: WithFieldValue<InferOutput<S>>): Promise<void>;\n set(\n data: UpdateData<InferOutput<S>>,\n options: MergeOptions<InferOutput<S>>,\n ): Promise<void>;\n async set(data: unknown, options?: WriteOptions): Promise<void> {\n const native = toNativeData(data, this.#driver.native);\n await this.#driver.setDoc(docLocation(this.#segments), native, options);\n }\n\n async update(data: UpdatePaths<InferOutput<S>>): Promise<void> {\n const native = toNativeData(data, this.#driver.native);\n await this.#driver.updateDoc(docLocation(this.#segments), native);\n }\n\n delete(): Promise<void> {\n return this.#driver.deleteDoc(docLocation(this.#segments));\n }\n\n onSnapshot(observer: DocSnapshotObserver<S>): Unsubscribe {\n const next = typeof observer === \"function\" ? observer : observer.next;\n const onError = typeof observer === \"function\" ? undefined : observer.error;\n return this.#driver.onSnapshotDoc(docLocation(this.#segments), {\n next: (snapshot) => next(readSnapshot(this.#def, snapshot)),\n ...(onError && { error: onError }),\n });\n }\n\n // Raw ref with the coercing converter attached\n get ref(): unknown {\n return this.#driver.docRef(\n docLocation(this.#segments),\n makeConverter(this.#def, this.#driver.native),\n );\n }\n}\n\nexport class TxDocumentHandle<S extends StandardSchemaV1> {\n readonly #tx: TxDriver;\n readonly #driver: Driver;\n readonly #def: CollectionDef<S>;\n readonly #segments: readonly string[];\n\n constructor(\n tx: TxDriver,\n driver: Driver,\n def: CollectionDef<S>,\n segments: readonly string[],\n ) {\n this.#tx = tx;\n this.#driver = driver;\n this.#def = def;\n this.#segments = segments;\n }\n\n get id(): string {\n return this.#segments[this.#segments.length - 1]!;\n }\n\n collection<C extends StandardSchemaV1>(\n def: CollectionDef<C>,\n ): TxCollectionHandle<C> {\n return new TxCollectionHandle(this.#tx, this.#driver, def, [\n ...this.#segments,\n def.name,\n ]);\n }\n\n async get(): Promise<Doc<S> | null> {\n const snapshot = await this.#tx.get(docLocation(this.#segments));\n return readSnapshot(this.#def, snapshot);\n }\n\n // Buffer writes synchronously so a forgotten await still enqueues pre-commit\n set(data: WithFieldValue<InferOutput<S>>): void;\n set(\n data: UpdateData<InferOutput<S>>,\n options: MergeOptions<InferOutput<S>>,\n ): void;\n set(data: unknown, options?: WriteOptions): void {\n const native = toNativeData(data, this.#driver.native);\n this.#tx.set(docLocation(this.#segments), native, options);\n }\n\n update(data: UpdatePaths<InferOutput<S>>): void {\n const native = toNativeData(data, this.#driver.native);\n this.#tx.update(docLocation(this.#segments), native);\n }\n\n delete(): void {\n this.#tx.delete(docLocation(this.#segments));\n }\n}\n\n// Write-only, so it carries no def, there is no read to coerce\nexport class BatchDocumentHandle<S extends StandardSchemaV1> {\n readonly #batch: BatchDriver;\n readonly #driver: Driver;\n readonly #segments: readonly string[];\n\n constructor(batch: BatchDriver, driver: Driver, segments: readonly string[]) {\n this.#batch = batch;\n this.#driver = driver;\n this.#segments = segments;\n }\n\n get id(): string {\n return this.#segments[this.#segments.length - 1]!;\n }\n\n collection<C extends StandardSchemaV1>(\n def: CollectionDef<C>,\n ): BatchCollectionHandle<C> {\n return new BatchCollectionHandle<C>(this.#batch, this.#driver, [\n ...this.#segments,\n def.name,\n ]);\n }\n\n // Buffer writes synchronously so a forgotten await still enqueues pre-commit\n set(data: WithFieldValue<InferOutput<S>>): void;\n set(\n data: UpdateData<InferOutput<S>>,\n options: MergeOptions<InferOutput<S>>,\n ): void;\n set(data: unknown, options?: WriteOptions): void {\n const native = toNativeData(data, this.#driver.native);\n this.#batch.set(docLocation(this.#segments), native, options);\n }\n\n update(data: UpdatePaths<InferOutput<S>>): void {\n const native = toNativeData(data, this.#driver.native);\n this.#batch.update(docLocation(this.#segments), native);\n }\n\n delete(): void {\n this.#batch.delete(docLocation(this.#segments));\n }\n}\n","import type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nimport type {\n BatchDriver,\n Driver,\n TransactionOptions,\n TxDriver,\n} from \"@/core/driver\";\nimport {\n BatchCollectionHandle,\n CollectionHandle,\n TxCollectionHandle,\n} from \"@/core/handles\";\nimport { QueryBuilder } from \"@/core/query\";\nimport type { CollectionDef } from \"@/core/types\";\n\nexport class Transaction {\n readonly #tx: TxDriver;\n readonly #driver: Driver;\n\n constructor(tx: TxDriver, driver: Driver) {\n this.#tx = tx;\n this.#driver = driver;\n }\n\n collection<S extends StandardSchemaV1>(\n def: CollectionDef<S>,\n ): TxCollectionHandle<S> {\n return new TxCollectionHandle(this.#tx, this.#driver, def, [def.name]);\n }\n}\n\nexport class Batch {\n readonly #batch: BatchDriver;\n readonly #driver: Driver;\n\n constructor(batch: BatchDriver, driver: Driver) {\n this.#batch = batch;\n this.#driver = driver;\n }\n\n collection<S extends StandardSchemaV1>(\n def: CollectionDef<S>,\n ): BatchCollectionHandle<S> {\n return new BatchCollectionHandle<S>(this.#batch, this.#driver, [def.name]);\n }\n\n commit(): Promise<void> {\n return this.#batch.commit();\n }\n}\n\nexport class Database {\n readonly #driver: Driver;\n\n constructor(driver: Driver) {\n this.#driver = driver;\n }\n\n collection<S extends StandardSchemaV1>(\n def: CollectionDef<S>,\n ): CollectionHandle<S> {\n return new CollectionHandle(this.#driver, def, [def.name]);\n }\n\n // Cross-parent query over every collection sharing this id\n collectionGroup<S extends StandardSchemaV1>(\n def: CollectionDef<S>,\n ): QueryBuilder<S> {\n return new QueryBuilder({\n driver: this.#driver,\n def,\n source: { kind: \"collectionGroup\", collectionId: def.name },\n });\n }\n\n runTransaction<T>(\n fn: (tx: Transaction) => Promise<T>,\n options?: TransactionOptions,\n ): Promise<T> {\n return this.#driver.runTransaction(\n (tx) => fn(new Transaction(tx, this.#driver)),\n options,\n );\n }\n\n batch(): Batch {\n return new Batch(this.#driver.batch(), this.#driver);\n }\n}\n"]}