@ponceca/firestore-sdk 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.
Files changed (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +692 -0
  3. package/dist/app.d.mts +51 -0
  4. package/dist/app.d.ts +51 -0
  5. package/dist/app.js +16 -0
  6. package/dist/app.js.map +1 -0
  7. package/dist/app.mjs +16 -0
  8. package/dist/app.mjs.map +1 -0
  9. package/dist/auth/index.d.mts +43 -0
  10. package/dist/auth/index.d.ts +43 -0
  11. package/dist/auth/index.js +18 -0
  12. package/dist/auth/index.js.map +1 -0
  13. package/dist/auth/index.mjs +18 -0
  14. package/dist/auth/index.mjs.map +1 -0
  15. package/dist/chunk-2RQUHE2K.js +719 -0
  16. package/dist/chunk-2RQUHE2K.js.map +1 -0
  17. package/dist/chunk-4CV4JOE5.js +27 -0
  18. package/dist/chunk-4CV4JOE5.js.map +1 -0
  19. package/dist/chunk-57XXMSJA.js +65 -0
  20. package/dist/chunk-57XXMSJA.js.map +1 -0
  21. package/dist/chunk-6J3LNKUQ.js +213 -0
  22. package/dist/chunk-6J3LNKUQ.js.map +1 -0
  23. package/dist/chunk-BXV7KTHB.js +645 -0
  24. package/dist/chunk-BXV7KTHB.js.map +1 -0
  25. package/dist/chunk-C3PCJJX4.mjs +645 -0
  26. package/dist/chunk-C3PCJJX4.mjs.map +1 -0
  27. package/dist/chunk-C6SKWUQV.mjs +213 -0
  28. package/dist/chunk-C6SKWUQV.mjs.map +1 -0
  29. package/dist/chunk-DXPQJR5D.mjs +2469 -0
  30. package/dist/chunk-DXPQJR5D.mjs.map +1 -0
  31. package/dist/chunk-MRVKMKSO.mjs +65 -0
  32. package/dist/chunk-MRVKMKSO.mjs.map +1 -0
  33. package/dist/chunk-NFEGQTCC.mjs +27 -0
  34. package/dist/chunk-NFEGQTCC.mjs.map +1 -0
  35. package/dist/chunk-RSBBZLDE.js +128 -0
  36. package/dist/chunk-RSBBZLDE.js.map +1 -0
  37. package/dist/chunk-RZWTSZSJ.js +2469 -0
  38. package/dist/chunk-RZWTSZSJ.js.map +1 -0
  39. package/dist/chunk-SZKHE2TQ.mjs +719 -0
  40. package/dist/chunk-SZKHE2TQ.mjs.map +1 -0
  41. package/dist/chunk-ZJ4A4Y2T.mjs +128 -0
  42. package/dist/chunk-ZJ4A4Y2T.mjs.map +1 -0
  43. package/dist/firestore/index.d.mts +1476 -0
  44. package/dist/firestore/index.d.ts +1476 -0
  45. package/dist/firestore/index.js +156 -0
  46. package/dist/firestore/index.js.map +1 -0
  47. package/dist/firestore/index.mjs +156 -0
  48. package/dist/firestore/index.mjs.map +1 -0
  49. package/dist/http-A2S5CWEV.js +10 -0
  50. package/dist/http-A2S5CWEV.js.map +1 -0
  51. package/dist/http-SZFONH6Z.mjs +10 -0
  52. package/dist/http-SZFONH6Z.mjs.map +1 -0
  53. package/dist/index.d.mts +4 -0
  54. package/dist/index.d.ts +4 -0
  55. package/dist/index.js +171 -0
  56. package/dist/index.js.map +1 -0
  57. package/dist/index.mjs +171 -0
  58. package/dist/index.mjs.map +1 -0
  59. package/dist/indexeddb-mutation-queue-5EB7C2D5.js +192 -0
  60. package/dist/indexeddb-mutation-queue-5EB7C2D5.js.map +1 -0
  61. package/dist/indexeddb-mutation-queue-M2MAH4E4.mjs +192 -0
  62. package/dist/indexeddb-mutation-queue-M2MAH4E4.mjs.map +1 -0
  63. package/dist/indexeddb-store-D23ZY3PR.mjs +162 -0
  64. package/dist/indexeddb-store-D23ZY3PR.mjs.map +1 -0
  65. package/dist/indexeddb-store-DNWBZUQE.js +162 -0
  66. package/dist/indexeddb-store-DNWBZUQE.js.map +1 -0
  67. package/dist/snapshot-MCQVLVHL.js +22 -0
  68. package/dist/snapshot-MCQVLVHL.js.map +1 -0
  69. package/dist/snapshot-ZWZFIFZD.mjs +22 -0
  70. package/dist/snapshot-ZWZFIFZD.mjs.map +1 -0
  71. package/dist/types-meoR-Ecp.d.mts +269 -0
  72. package/dist/types-meoR-Ecp.d.ts +269 -0
  73. package/package.json +78 -0
@@ -0,0 +1,2469 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
2
+
3
+ var _chunk2RQUHE2Kjs = require('./chunk-2RQUHE2K.js');
4
+
5
+
6
+ var _chunk6J3LNKUQjs = require('./chunk-6J3LNKUQ.js');
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+ var _chunkBXV7KTHBjs = require('./chunk-BXV7KTHB.js');
15
+
16
+ // src/firestore/reference.ts
17
+ var DocumentReferenceImpl = class {
18
+ constructor(firestore, path, parent) {
19
+ this.type = "document";
20
+ this.firestore = firestore;
21
+ this.path = path;
22
+ this.id = path.split("/").pop() || "";
23
+ this.parent = parent;
24
+ }
25
+ };
26
+ var CollectionReferenceImpl = class {
27
+ constructor(firestore, path, parent = null) {
28
+ this.type = "collection";
29
+ this.firestore = firestore;
30
+ this.path = path;
31
+ this.id = path.split("/").pop() || "";
32
+ this.parent = parent;
33
+ }
34
+ };
35
+ function normalizePath(path) {
36
+ return path.replace(/\/+/g, "/").replace(/^\//, "").replace(/\/$/, "");
37
+ }
38
+ function validatePath(path, expectedType) {
39
+ const segments = path.split("/").filter((s) => s.length > 0);
40
+ if (segments.length === 0) {
41
+ throw new Error(`Invalid ${expectedType} path: path cannot be empty`);
42
+ }
43
+ for (const segment of segments) {
44
+ if (segment.startsWith(".")) {
45
+ throw new Error(`Invalid path segment: "${segment}" - segments cannot start with a dot`);
46
+ }
47
+ if (segment.includes("..")) {
48
+ throw new Error(`Invalid path segment: "${segment}" - segments cannot contain double dots`);
49
+ }
50
+ }
51
+ const isEven = segments.length % 2 === 0;
52
+ if (expectedType === "document" && !isEven) {
53
+ throw new Error(`Invalid document path: "${path}" - document paths must have an even number of segments`);
54
+ }
55
+ if (expectedType === "collection" && isEven) {
56
+ throw new Error(`Invalid collection path: "${path}" - collection paths must have an odd number of segments`);
57
+ }
58
+ }
59
+ function doc(firestoreOrRef, ...pathSegments) {
60
+ let firestore;
61
+ let fullPath;
62
+ if ("type" in firestoreOrRef && firestoreOrRef.type === "collection") {
63
+ const collRef = firestoreOrRef;
64
+ firestore = collRef.firestore;
65
+ if (pathSegments.length === 0) {
66
+ fullPath = `${collRef.path}/${generateId()}`;
67
+ } else {
68
+ fullPath = `${collRef.path}/${pathSegments.join("/")}`;
69
+ }
70
+ } else {
71
+ firestore = firestoreOrRef;
72
+ fullPath = pathSegments.join("/");
73
+ }
74
+ fullPath = normalizePath(fullPath);
75
+ validatePath(fullPath, "document");
76
+ const segments = fullPath.split("/");
77
+ const parentPath = segments.slice(0, -1).join("/");
78
+ const parentRef = new CollectionReferenceImpl(firestore, parentPath);
79
+ return new DocumentReferenceImpl(firestore, fullPath, parentRef);
80
+ }
81
+ function collection(firestoreOrRef, ...pathSegments) {
82
+ let firestore;
83
+ let fullPath;
84
+ let parentDoc = null;
85
+ if ("type" in firestoreOrRef && firestoreOrRef.type === "document") {
86
+ const docRef = firestoreOrRef;
87
+ firestore = docRef.firestore;
88
+ fullPath = `${docRef.path}/${pathSegments.join("/")}`;
89
+ parentDoc = docRef;
90
+ } else {
91
+ firestore = firestoreOrRef;
92
+ fullPath = pathSegments.join("/");
93
+ }
94
+ fullPath = normalizePath(fullPath);
95
+ validatePath(fullPath, "collection");
96
+ if (!parentDoc) {
97
+ const segments = fullPath.split("/").filter(Boolean);
98
+ if (segments.length >= 3) {
99
+ const parentPath = segments.slice(0, -1).join("/");
100
+ const parentCollectionPath = segments.slice(0, -2).join("/");
101
+ const parentCollection = new CollectionReferenceImpl(
102
+ firestore,
103
+ parentCollectionPath
104
+ );
105
+ parentDoc = new DocumentReferenceImpl(
106
+ firestore,
107
+ parentPath,
108
+ parentCollection
109
+ );
110
+ }
111
+ }
112
+ return new CollectionReferenceImpl(firestore, fullPath, parentDoc);
113
+ }
114
+ function generateId() {
115
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
116
+ let result = "";
117
+ for (let i = 0; i < 20; i++) {
118
+ result += chars.charAt(Math.floor(Math.random() * chars.length));
119
+ }
120
+ return result;
121
+ }
122
+
123
+ // src/firestore/local-write-tracker.ts
124
+ var documentListeners = /* @__PURE__ */ new Map();
125
+ function registerLocalWriteListener(path, listener) {
126
+ let listeners = documentListeners.get(path);
127
+ if (!listeners) {
128
+ listeners = /* @__PURE__ */ new Set();
129
+ documentListeners.set(path, listeners);
130
+ }
131
+ listeners.add(listener);
132
+ return () => {
133
+ const current = documentListeners.get(path);
134
+ if (!current) return;
135
+ current.delete(listener);
136
+ if (current.size === 0) {
137
+ documentListeners.delete(path);
138
+ }
139
+ };
140
+ }
141
+ function notifyLocalWrite(path) {
142
+ const listeners = documentListeners.get(path);
143
+ if (!listeners) return;
144
+ listeners.forEach((listener) => listener());
145
+ }
146
+
147
+ // src/firestore/utilities.ts
148
+ function withConverter(reference, converter) {
149
+ const refWithConverter = Object.create(Object.getPrototypeOf(reference));
150
+ Object.assign(refWithConverter, reference);
151
+ refWithConverter.converter = converter;
152
+ return refWithConverter;
153
+ }
154
+ function refEqual(left, right) {
155
+ if (left === right) return true;
156
+ return left.firestore === right.firestore && left.path === right.path && left.type === right.type;
157
+ }
158
+ function queryEqual(left, right) {
159
+ if (left === right) return true;
160
+ if (left.firestore !== right.firestore) return false;
161
+ if (left.path !== right.path) return false;
162
+ if (left.type !== right.type) return false;
163
+ const leftConstraints = left.constraints || [];
164
+ const rightConstraints = right.constraints || [];
165
+ if (leftConstraints.length !== rightConstraints.length) return false;
166
+ return JSON.stringify(leftConstraints) === JSON.stringify(rightConstraints);
167
+ }
168
+ function snapshotEqual(left, right) {
169
+ if (left === right) return true;
170
+ const leftIsDoc = "ref" in left;
171
+ const rightIsDoc = "ref" in right;
172
+ if (leftIsDoc !== rightIsDoc) return false;
173
+ if (leftIsDoc && rightIsDoc) {
174
+ const l = left;
175
+ const r = right;
176
+ if (!refEqual(l.ref, r.ref)) return false;
177
+ if (l.exists() !== r.exists()) return false;
178
+ return JSON.stringify(l.data()) === JSON.stringify(r.data());
179
+ } else {
180
+ const l = left;
181
+ const r = right;
182
+ if (l.size !== r.size) return false;
183
+ for (let i = 0; i < l.docs.length; i++) {
184
+ if (!snapshotEqual(l.docs[i], r.docs[i])) {
185
+ return false;
186
+ }
187
+ }
188
+ return true;
189
+ }
190
+ }
191
+ function onSnapshotsInSync(firestore, onSync) {
192
+ let timeoutId = null;
193
+ let isActive = true;
194
+ const scheduleSync = () => {
195
+ if (!isActive) return;
196
+ if (timeoutId) {
197
+ clearTimeout(timeoutId);
198
+ }
199
+ timeoutId = setTimeout(() => {
200
+ if (isActive) {
201
+ onSync();
202
+ }
203
+ }, 50);
204
+ };
205
+ const firestoreInternal = firestore;
206
+ if (!firestoreInternal._syncCallbacks) {
207
+ firestoreInternal._syncCallbacks = /* @__PURE__ */ new Set();
208
+ }
209
+ firestoreInternal._syncCallbacks.add(scheduleSync);
210
+ scheduleSync();
211
+ return () => {
212
+ isActive = false;
213
+ if (timeoutId) {
214
+ clearTimeout(timeoutId);
215
+ }
216
+ _optionalChain([firestoreInternal, 'access', _ => _._syncCallbacks, 'optionalAccess', _2 => _2.delete, 'call', _3 => _3(scheduleSync)]);
217
+ };
218
+ }
219
+ function asQueryDocumentSnapshot(snapshot) {
220
+ if (!snapshot.exists()) {
221
+ return null;
222
+ }
223
+ return {
224
+ ...snapshot,
225
+ exists: () => true,
226
+ data: () => snapshot.data()
227
+ };
228
+ }
229
+ function applyConverterToDocumentSnapshot(snapshot, converter) {
230
+ if (!converter || !snapshot.exists()) {
231
+ return snapshot;
232
+ }
233
+ const querySnap = asQueryDocumentSnapshot(snapshot);
234
+ if (!querySnap) {
235
+ return snapshot;
236
+ }
237
+ const converted = converter.fromFirestore(querySnap);
238
+ return Object.assign(Object.create(Object.getPrototypeOf(snapshot)), snapshot, {
239
+ data: () => converted
240
+ });
241
+ }
242
+ function applyConverterToQuerySnapshot(snapshot, converter) {
243
+ if (!converter) {
244
+ return snapshot;
245
+ }
246
+ const convertedDocs = snapshot.docs.map(
247
+ (doc2) => applyConverterToDocumentSnapshot(doc2, converter)
248
+ );
249
+ const convertedChanges = snapshot.docChanges().map((change) => ({
250
+ ...change,
251
+ doc: applyConverterToDocumentSnapshot(
252
+ change.doc,
253
+ converter
254
+ )
255
+ }));
256
+ return Object.assign(Object.create(Object.getPrototypeOf(snapshot)), snapshot, {
257
+ docs: convertedDocs,
258
+ docChanges: () => convertedChanges
259
+ });
260
+ }
261
+
262
+ // src/firestore/crud.ts
263
+ async function getDoc(reference) {
264
+ if (!reference || !reference.path) {
265
+ throw new Error("getDoc requires a valid DocumentReference");
266
+ }
267
+ const pm = _chunk2RQUHE2Kjs.getPersistenceManager.call(void 0, reference.firestore);
268
+ if (!pm) {
269
+ return getDocDirect(reference);
270
+ }
271
+ if (pm.isOnline) {
272
+ try {
273
+ const snapshot = await getDocDirect(reference);
274
+ await pm.cacheDocument(reference.path, _nullishCoalesce(snapshot.data(), () => ( null)), snapshot.exists(), snapshot._updateTime);
275
+ const hasPending = await pm.hasPendingWrites(reference.path);
276
+ if (hasPending) {
277
+ return createSnapshotWithMetadata(reference, snapshot, { hasPendingWrites: true });
278
+ }
279
+ return snapshot;
280
+ } catch (error) {
281
+ const code = _optionalChain([error, 'optionalAccess', _4 => _4.code]);
282
+ if (code === "unavailable" || code === "deadline-exceeded") {
283
+ return getDocFromLocalCache(reference, pm);
284
+ }
285
+ throw error;
286
+ }
287
+ }
288
+ return getDocFromLocalCache(reference, pm);
289
+ }
290
+ async function getDocDirect(reference) {
291
+ const client = _chunk6J3LNKUQjs.getHttpClient.call(void 0, reference.firestore);
292
+ try {
293
+ const doc2 = await client.get(
294
+ `/documents/${reference.path}`
295
+ );
296
+ const snapshot = _chunkBXV7KTHBjs.createDocumentSnapshot.call(void 0, reference, doc2);
297
+ return applyConverterToDocumentSnapshot(snapshot, getConverter(reference));
298
+ } catch (error) {
299
+ if (error.code === "not-found") {
300
+ const snapshot = _chunkBXV7KTHBjs.createDocumentSnapshot.call(void 0, reference, null);
301
+ return applyConverterToDocumentSnapshot(snapshot, getConverter(reference));
302
+ }
303
+ throw error;
304
+ }
305
+ }
306
+ async function getDocFromLocalCache(reference, pm) {
307
+ const cached = await pm.getCachedDocument(reference.path);
308
+ if (cached) {
309
+ return new (0, _chunkBXV7KTHBjs.DocumentSnapshotImpl)(
310
+ reference,
311
+ cached.exists ? cached.data : void 0,
312
+ cached.exists,
313
+ { fromCache: true, hasPendingWrites: await pm.hasPendingWrites(reference.path) },
314
+ cached.updateTime
315
+ );
316
+ }
317
+ return new (0, _chunkBXV7KTHBjs.DocumentSnapshotImpl)(
318
+ reference,
319
+ void 0,
320
+ false,
321
+ { fromCache: true, hasPendingWrites: false }
322
+ );
323
+ }
324
+ async function getDocFromCache(reference) {
325
+ if (!reference || !reference.path) {
326
+ throw new Error("getDocFromCache requires a valid DocumentReference");
327
+ }
328
+ const pm = _chunk2RQUHE2Kjs.getPersistenceManager.call(void 0, reference.firestore);
329
+ if (!pm) {
330
+ throw createFirestoreError(
331
+ "failed-precondition",
332
+ "Failed to get document from cache. Persistence is not enabled."
333
+ );
334
+ }
335
+ const cached = await pm.getCachedDocument(reference.path);
336
+ if (!cached) {
337
+ throw createFirestoreError(
338
+ "unavailable",
339
+ "Failed to get document from cache. Document is not cached."
340
+ );
341
+ }
342
+ return await getDocFromLocalCache(reference, pm);
343
+ }
344
+ function createSnapshotWithMetadata(reference, source, metadata) {
345
+ return new (0, _chunkBXV7KTHBjs.DocumentSnapshotImpl)(
346
+ reference,
347
+ source.data(),
348
+ source.exists(),
349
+ {
350
+ fromCache: _nullishCoalesce(metadata.fromCache, () => ( source.metadata.fromCache)),
351
+ hasPendingWrites: _nullishCoalesce(metadata.hasPendingWrites, () => ( source.metadata.hasPendingWrites))
352
+ },
353
+ source._updateTime
354
+ );
355
+ }
356
+ async function setDoc(reference, data, options) {
357
+ if (!reference || !reference.path) {
358
+ throw new Error("setDoc requires a valid DocumentReference");
359
+ }
360
+ if (!data || typeof data !== "object") {
361
+ throw new Error("setDoc requires a valid data object");
362
+ }
363
+ const dataToWrite = applyConverterToData(reference, data);
364
+ assertValidTypes(dataToWrite);
365
+ const client = _chunk6J3LNKUQjs.getHttpClient.call(void 0, reference.firestore);
366
+ assertDocumentDepth(dataToWrite);
367
+ const fields = _chunkBXV7KTHBjs.toFirestoreFields.call(void 0, dataToWrite);
368
+ assertDocumentSize(fields);
369
+ notifyLocalWrite(reference.path);
370
+ const pm = _chunk2RQUHE2Kjs.getPersistenceManager.call(void 0, reference.firestore);
371
+ if (pm) {
372
+ await pm.addLocalWrite("set", reference.path, dataToWrite, options);
373
+ }
374
+ const body = {
375
+ fields
376
+ };
377
+ const sendToServer = async () => {
378
+ if (_optionalChain([options, 'optionalAccess', _5 => _5.merge]) || _optionalChain([options, 'optionalAccess', _6 => _6.mergeFields])) {
379
+ const fieldPaths = options.mergeFields || Object.keys(dataToWrite);
380
+ body.updateMask = { fieldPaths };
381
+ await client.patch(`/documents/${reference.path}`, body);
382
+ } else {
383
+ const parentPath = reference.path.split("/").slice(0, -1).join("/");
384
+ const documentId2 = reference.id;
385
+ await client.post(`/documents/${parentPath}?documentId=${documentId2}`, { fields });
386
+ }
387
+ };
388
+ if (pm && !pm.isOnline) {
389
+ return;
390
+ }
391
+ try {
392
+ await sendToServer();
393
+ if (pm) {
394
+ const mutations = await pm.mutations.getForPath(reference.path);
395
+ if (mutations.length > 0) {
396
+ await pm.completeMutation(mutations[mutations.length - 1].id);
397
+ }
398
+ }
399
+ } catch (error) {
400
+ if (pm) {
401
+ const code = _optionalChain([error, 'optionalAccess', _7 => _7.code]);
402
+ if (code === "unavailable" || code === "deadline-exceeded") {
403
+ return;
404
+ }
405
+ }
406
+ throw error;
407
+ }
408
+ }
409
+ async function getDocFromServer(reference) {
410
+ const snapshot = await getDocDirect(reference);
411
+ const pm = _chunk2RQUHE2Kjs.getPersistenceManager.call(void 0, reference.firestore);
412
+ if (pm) {
413
+ await pm.cacheDocument(reference.path, _nullishCoalesce(snapshot.data(), () => ( null)), snapshot.exists(), snapshot._updateTime);
414
+ }
415
+ return snapshot;
416
+ }
417
+ async function updateDoc(reference, dataOrField, ...moreFieldsAndValues) {
418
+ if (!reference || !reference.path) {
419
+ throw new Error("updateDoc requires a valid DocumentReference");
420
+ }
421
+ let data;
422
+ if (typeof dataOrField === "string") {
423
+ if (moreFieldsAndValues.length === 0 || moreFieldsAndValues.length % 2 === 0) {
424
+ throw createFirestoreError(
425
+ "invalid-argument",
426
+ "updateDoc with field/value pairs requires an even number of field/value arguments"
427
+ );
428
+ }
429
+ const obj = { [dataOrField]: moreFieldsAndValues[0] };
430
+ for (let i = 1; i < moreFieldsAndValues.length; i += 2) {
431
+ const field = moreFieldsAndValues[i];
432
+ if (typeof field !== "string") {
433
+ throw createFirestoreError(
434
+ "invalid-argument",
435
+ "Field paths must be strings in updateDoc"
436
+ );
437
+ }
438
+ obj[field] = moreFieldsAndValues[i + 1];
439
+ }
440
+ data = obj;
441
+ } else {
442
+ data = dataOrField;
443
+ }
444
+ if (!data || typeof data !== "object") {
445
+ throw new Error("updateDoc requires a valid data object");
446
+ }
447
+ const dataToWrite = applyConverterToData(reference, data);
448
+ assertValidTypes(dataToWrite);
449
+ const client = _chunk6J3LNKUQjs.getHttpClient.call(void 0, reference.firestore);
450
+ assertDocumentDepth(dataToWrite);
451
+ const fields = _chunkBXV7KTHBjs.toFirestoreFields.call(void 0, dataToWrite);
452
+ assertDocumentSize(fields);
453
+ notifyLocalWrite(reference.path);
454
+ const pm = _chunk2RQUHE2Kjs.getPersistenceManager.call(void 0, reference.firestore);
455
+ if (pm) {
456
+ await pm.addLocalWrite("update", reference.path, dataToWrite);
457
+ }
458
+ const fieldPaths = extractFieldPaths(dataToWrite);
459
+ const sendToServer = async () => {
460
+ await client.patch(`/documents/${reference.path}`, {
461
+ fields,
462
+ updateMask: { fieldPaths }
463
+ });
464
+ };
465
+ if (pm && !pm.isOnline) {
466
+ return;
467
+ }
468
+ try {
469
+ await sendToServer();
470
+ if (pm) {
471
+ const mutations = await pm.mutations.getForPath(reference.path);
472
+ if (mutations.length > 0) {
473
+ await pm.completeMutation(mutations[mutations.length - 1].id);
474
+ }
475
+ }
476
+ } catch (error) {
477
+ if (pm) {
478
+ const code = _optionalChain([error, 'optionalAccess', _8 => _8.code]);
479
+ if (code === "unavailable" || code === "deadline-exceeded") {
480
+ return;
481
+ }
482
+ }
483
+ throw error;
484
+ }
485
+ }
486
+ function extractFieldPaths(data, prefix = "") {
487
+ const paths = [];
488
+ for (const [key, value] of Object.entries(data)) {
489
+ if (value === void 0) {
490
+ continue;
491
+ }
492
+ const fullPath = prefix ? `${prefix}.${key}` : key;
493
+ if (key.includes(".")) {
494
+ paths.push(key);
495
+ } else if (isFieldValueForExtract(value)) {
496
+ paths.push(fullPath);
497
+ } else if (value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date)) {
498
+ paths.push(...extractFieldPaths(value, fullPath));
499
+ } else {
500
+ paths.push(fullPath);
501
+ }
502
+ }
503
+ return paths;
504
+ }
505
+ var MAX_DOCUMENT_SIZE_BYTES = 1024 * 1024;
506
+ var MAX_DOCUMENT_DEPTH = 20;
507
+ function createFirestoreError(code, message) {
508
+ const error = new Error(message);
509
+ error.code = code;
510
+ return error;
511
+ }
512
+ function assertDocumentSize(fields) {
513
+ const json = JSON.stringify({ fields });
514
+ const size = typeof TextEncoder !== "undefined" ? new TextEncoder().encode(json).length : json.length;
515
+ if (size > MAX_DOCUMENT_SIZE_BYTES) {
516
+ throw createFirestoreError("invalid-argument", "Document size exceeds 1 MiB");
517
+ }
518
+ }
519
+ function assertDocumentDepth(fields) {
520
+ if (getDepth(fields, 0) > MAX_DOCUMENT_DEPTH) {
521
+ throw createFirestoreError("invalid-argument", "Document exceeds maximum depth");
522
+ }
523
+ }
524
+ function assertValidTypes(data, path = "") {
525
+ if (data === void 0) {
526
+ return;
527
+ }
528
+ if (typeof data === "function") {
529
+ throw createFirestoreError(
530
+ "invalid-argument",
531
+ `Function setDoc() called with invalid data. Unsupported field value: a function${path ? ` (found in field ${path})` : ""}`
532
+ );
533
+ }
534
+ if (typeof data === "symbol") {
535
+ throw createFirestoreError(
536
+ "invalid-argument",
537
+ `Function setDoc() called with invalid data. Unsupported field value: a symbol${path ? ` (found in field ${path})` : ""}`
538
+ );
539
+ }
540
+ if (data === null) {
541
+ return;
542
+ }
543
+ if (Array.isArray(data)) {
544
+ for (let i = 0; i < data.length; i++) {
545
+ assertValidTypes(data[i], `${path}[${i}]`);
546
+ }
547
+ return;
548
+ }
549
+ if (typeof data === "object") {
550
+ if ("_type" in data && typeof data._type === "string") {
551
+ return;
552
+ }
553
+ for (const [key, value] of Object.entries(data)) {
554
+ const fieldPath = path ? `${path}.${key}` : key;
555
+ assertValidTypes(value, fieldPath);
556
+ }
557
+ }
558
+ }
559
+ function getDepth(value, current) {
560
+ if (value === null || value === void 0) {
561
+ return current;
562
+ }
563
+ if (Array.isArray(value)) {
564
+ let maxDepth = current;
565
+ for (const item of value) {
566
+ const depth = getDepth(item, current);
567
+ if (depth > maxDepth) {
568
+ maxDepth = depth;
569
+ }
570
+ }
571
+ return maxDepth;
572
+ }
573
+ if (typeof value === "object") {
574
+ let maxDepth = current + 1;
575
+ for (const item of Object.values(value)) {
576
+ const depth = getDepth(item, current + 1);
577
+ if (depth > maxDepth) {
578
+ maxDepth = depth;
579
+ }
580
+ }
581
+ return maxDepth;
582
+ }
583
+ return current;
584
+ }
585
+ function isFieldValueForExtract(value) {
586
+ return value !== null && typeof value === "object" && "_type" in value && typeof value._type === "string";
587
+ }
588
+ async function deleteDoc(reference) {
589
+ if (!reference || !reference.path) {
590
+ throw new Error("deleteDoc requires a valid DocumentReference");
591
+ }
592
+ const client = _chunk6J3LNKUQjs.getHttpClient.call(void 0, reference.firestore);
593
+ notifyLocalWrite(reference.path);
594
+ const pm = _chunk2RQUHE2Kjs.getPersistenceManager.call(void 0, reference.firestore);
595
+ if (pm) {
596
+ await pm.addLocalWrite("delete", reference.path, null);
597
+ }
598
+ if (pm && !pm.isOnline) {
599
+ return;
600
+ }
601
+ try {
602
+ await client.delete(`/documents/${reference.path}`);
603
+ if (pm) {
604
+ const mutations = await pm.mutations.getForPath(reference.path);
605
+ if (mutations.length > 0) {
606
+ await pm.completeMutation(mutations[mutations.length - 1].id);
607
+ }
608
+ }
609
+ } catch (error) {
610
+ if (pm) {
611
+ const code = _optionalChain([error, 'optionalAccess', _9 => _9.code]);
612
+ if (code === "unavailable" || code === "deadline-exceeded") {
613
+ return;
614
+ }
615
+ }
616
+ throw error;
617
+ }
618
+ }
619
+ async function addDoc(reference, data) {
620
+ if (!reference || !reference.path) {
621
+ throw new Error("addDoc requires a valid CollectionReference");
622
+ }
623
+ if (!data || typeof data !== "object") {
624
+ throw new Error("addDoc requires a valid data object");
625
+ }
626
+ const newId = generateId();
627
+ const docRef = doc(reference, newId);
628
+ const converter = getConverter(reference);
629
+ if (converter) {
630
+ docRef.converter = converter;
631
+ }
632
+ await setDoc(docRef, data);
633
+ return docRef;
634
+ }
635
+ function getConverter(reference) {
636
+ return reference.converter;
637
+ }
638
+ function applyConverterToData(reference, data) {
639
+ const converter = getConverter(reference);
640
+ return converter ? converter.toFirestore(data) : data;
641
+ }
642
+
643
+ // src/firestore/query.ts
644
+ var QueryImpl = class {
645
+ constructor(firestore, path, constraints = []) {
646
+ this.firestore = firestore;
647
+ this.path = path;
648
+ this.constraints = constraints;
649
+ this.type = "query";
650
+ }
651
+ };
652
+ function query(reference, ...constraints) {
653
+ const existingConstraints = "constraints" in reference ? reference.constraints : [];
654
+ const allConstraints = [...existingConstraints, ...constraints];
655
+ validateQueryConflicts(allConstraints);
656
+ const newQuery = new QueryImpl(
657
+ reference.firestore,
658
+ reference.path,
659
+ allConstraints
660
+ );
661
+ const converter = reference.converter;
662
+ if (converter) {
663
+ newQuery.converter = converter;
664
+ }
665
+ return newQuery;
666
+ }
667
+ function validateQueryConflicts(constraints) {
668
+ const whereConstraints = constraints.filter((c) => c.type === "where");
669
+ let hasIn = false;
670
+ let hasNotIn = false;
671
+ let hasNotEqual = false;
672
+ let arrayContainsCount = 0;
673
+ for (const w of whereConstraints) {
674
+ if (w.op === "in") hasIn = true;
675
+ if (w.op === "not-in") hasNotIn = true;
676
+ if (w.op === "!=") hasNotEqual = true;
677
+ if (w.op === "array-contains") arrayContainsCount++;
678
+ }
679
+ if (hasIn && hasNotIn) {
680
+ throw new Error(`Invalid Query. You cannot use 'in' and 'not-in' filters in the same query.`);
681
+ }
682
+ if (hasNotEqual && hasNotIn) {
683
+ throw new Error(`Invalid Query. You cannot use '!=' and 'not-in' filters in the same query.`);
684
+ }
685
+ if (arrayContainsCount > 1) {
686
+ throw new Error(`Invalid Query. You cannot use more than one 'array-contains' filter in a single query.`);
687
+ }
688
+ }
689
+ var VALID_OPS = /* @__PURE__ */ new Set([
690
+ "<",
691
+ "<=",
692
+ "==",
693
+ "!=",
694
+ ">=",
695
+ ">",
696
+ "array-contains",
697
+ "array-contains-any",
698
+ "in",
699
+ "not-in"
700
+ ]);
701
+ var ARRAY_LIMIT_OPS = /* @__PURE__ */ new Set(["in", "not-in", "array-contains-any"]);
702
+ function where(field, op, value) {
703
+ if (!VALID_OPS.has(op)) {
704
+ throw new Error(`Invalid operator '${op}' passed to where(). Valid operators are: <, <=, ==, !=, >=, >, array-contains, array-contains-any, in, not-in.`);
705
+ }
706
+ if (value === void 0) {
707
+ throw new Error(`Function Query.where() requires a valid third argument, but it was undefined.`);
708
+ }
709
+ if (typeof value === "function") {
710
+ throw new Error(`Function Query.where() requires a valid third argument, but it was a function.`);
711
+ }
712
+ if (typeof value === "symbol") {
713
+ throw new Error(`Function Query.where() requires a valid third argument, but it was a symbol.`);
714
+ }
715
+ if (ARRAY_LIMIT_OPS.has(op)) {
716
+ if (!Array.isArray(value)) {
717
+ throw new Error(`Invalid argument: in/not-in/array-contains-any requires an array value.`);
718
+ }
719
+ if (value.length > 30) {
720
+ throw new Error(`Invalid Query. '${op}' filters support a maximum of 30 elements in the value array.`);
721
+ }
722
+ }
723
+ return {
724
+ type: "where",
725
+ field,
726
+ op,
727
+ value
728
+ };
729
+ }
730
+ function orderBy(field, direction = "asc") {
731
+ return {
732
+ type: "orderBy",
733
+ field,
734
+ direction
735
+ };
736
+ }
737
+ function limit(n) {
738
+ if (n <= 0) {
739
+ throw new Error(`Function limit() requires a positive number, but it was: ${n}`);
740
+ }
741
+ return {
742
+ type: "limit",
743
+ limit: n
744
+ };
745
+ }
746
+ function limitToLast(n) {
747
+ if (n <= 0) {
748
+ throw new Error(`Function limitToLast() requires a positive number, but it was: ${n}`);
749
+ }
750
+ return {
751
+ type: "limitToLast",
752
+ limit: n
753
+ };
754
+ }
755
+ function startAt(...values) {
756
+ return {
757
+ type: "startAt",
758
+ values,
759
+ inclusive: true
760
+ };
761
+ }
762
+ function startAfter(...values) {
763
+ return {
764
+ type: "startAfter",
765
+ values,
766
+ inclusive: false
767
+ };
768
+ }
769
+ function endAt(...values) {
770
+ return {
771
+ type: "endAt",
772
+ values,
773
+ inclusive: true
774
+ };
775
+ }
776
+ function endBefore(...values) {
777
+ return {
778
+ type: "endBefore",
779
+ values,
780
+ inclusive: false
781
+ };
782
+ }
783
+ async function getDocs(queryRef) {
784
+ const pm = _chunk2RQUHE2Kjs.getPersistenceManager.call(void 0, queryRef.firestore);
785
+ if (!pm) {
786
+ return getDocsDirect(queryRef);
787
+ }
788
+ if (pm.isOnline) {
789
+ try {
790
+ const snapshot = await getDocsDirect(queryRef);
791
+ for (const doc2 of snapshot.docs) {
792
+ await pm.cacheDocument(doc2.ref.path, _nullishCoalesce(doc2.data(), () => ( null)), doc2.exists(), doc2._updateTime);
793
+ }
794
+ const queryKey = buildQueryCacheKey(queryRef);
795
+ await pm.cacheQuery(queryKey, snapshot.docs.map((d) => d.ref.path));
796
+ return snapshot;
797
+ } catch (error) {
798
+ const code = _optionalChain([error, 'optionalAccess', _10 => _10.code]);
799
+ if (code === "unavailable" || code === "deadline-exceeded") {
800
+ return getDocsFromLocalCache(queryRef, pm);
801
+ }
802
+ throw error;
803
+ }
804
+ }
805
+ return getDocsFromLocalCache(queryRef, pm);
806
+ }
807
+ async function getDocsDirect(queryRef) {
808
+ const client = _chunk6J3LNKUQjs.getHttpClient.call(void 0, queryRef.firestore);
809
+ const constraints = "constraints" in queryRef ? queryRef.constraints : [];
810
+ const flexibleQueries = Boolean(_optionalChain([queryRef, 'access', _11 => _11.firestore, 'access', _12 => _12._config, 'optionalAccess', _13 => _13.allowFlexibleQueries]));
811
+ validateQueryConstraints(constraints, { allowFlexibleQueries: flexibleQueries });
812
+ const isCollectionGroupQuery = queryRef.type === "collectionGroup";
813
+ const structuredQuery = buildStructuredQuery(queryRef.path, constraints, isCollectionGroupQuery);
814
+ const response = await client.post(
815
+ "/documents:runQuery",
816
+ { structuredQuery }
817
+ );
818
+ const documents = response.filter((r) => r.document).map((r) => r.document);
819
+ const queryForSnapshot = "constraints" in queryRef ? queryRef : new QueryImpl(queryRef.firestore, queryRef.path, []);
820
+ const snapshot = _chunkBXV7KTHBjs.createQuerySnapshot.call(void 0, queryForSnapshot, documents);
821
+ const converter = queryRef.converter;
822
+ return applyConverterToQuerySnapshot(snapshot, converter);
823
+ }
824
+ async function getDocsFromLocalCache(queryRef, pm) {
825
+ const queryForSnapshot = "constraints" in queryRef ? queryRef : new QueryImpl(queryRef.firestore, queryRef.path, []);
826
+ const queryKey = buildQueryCacheKey(queryRef);
827
+ const cachedPaths = await pm.getCachedQuery(queryKey);
828
+ if (cachedPaths) {
829
+ const docs2 = [];
830
+ for (const path of cachedPaths) {
831
+ const cached = await pm.getCachedDocument(path);
832
+ if (!cached || !cached.exists) continue;
833
+ const segments = path.split("/");
834
+ const ref = {
835
+ type: "document",
836
+ path,
837
+ id: segments[segments.length - 1],
838
+ firestore: queryRef.firestore,
839
+ parent: {
840
+ type: "collection",
841
+ path: segments.slice(0, -1).join("/"),
842
+ id: segments[segments.length - 2] || "",
843
+ firestore: queryRef.firestore,
844
+ parent: null
845
+ }
846
+ };
847
+ docs2.push(new (0, _chunkBXV7KTHBjs.DocumentSnapshotImpl)(
848
+ ref,
849
+ cached.data,
850
+ true,
851
+ { fromCache: true, hasPendingWrites: await pm.hasPendingWrites(path) }
852
+ ));
853
+ }
854
+ return new (0, _chunkBXV7KTHBjs.QuerySnapshotImpl)(queryForSnapshot, docs2, [], { fromCache: true });
855
+ }
856
+ const collectionDocs = await pm.getCachedCollection(queryRef.path);
857
+ const docs = [];
858
+ for (const cached of collectionDocs) {
859
+ const segments = cached.path.split("/");
860
+ const ref = {
861
+ type: "document",
862
+ path: cached.path,
863
+ id: segments[segments.length - 1],
864
+ firestore: queryRef.firestore,
865
+ parent: {
866
+ type: "collection",
867
+ path: segments.slice(0, -1).join("/"),
868
+ id: segments[segments.length - 2] || "",
869
+ firestore: queryRef.firestore,
870
+ parent: null
871
+ }
872
+ };
873
+ docs.push(new (0, _chunkBXV7KTHBjs.DocumentSnapshotImpl)(
874
+ ref,
875
+ cached.data,
876
+ true,
877
+ { fromCache: true, hasPendingWrites: await pm.hasPendingWrites(cached.path) }
878
+ ));
879
+ }
880
+ return new (0, _chunkBXV7KTHBjs.QuerySnapshotImpl)(queryForSnapshot, docs, [], { fromCache: true });
881
+ }
882
+ async function getDocsFromCache(queryRef) {
883
+ const pm = _chunk2RQUHE2Kjs.getPersistenceManager.call(void 0, queryRef.firestore);
884
+ if (!pm) {
885
+ throw createFirestoreError2(
886
+ "failed-precondition",
887
+ "Failed to get documents from cache. Persistence is not enabled."
888
+ );
889
+ }
890
+ return getDocsFromLocalCache(queryRef, pm);
891
+ }
892
+ function buildQueryCacheKey(queryRef) {
893
+ const constraints = "constraints" in queryRef ? queryRef.constraints : [];
894
+ return `${queryRef.path}:${JSON.stringify(constraints)}`;
895
+ }
896
+ async function getDocsFromServer(queryRef) {
897
+ const snapshot = await getDocsDirect(queryRef);
898
+ const pm = _chunk2RQUHE2Kjs.getPersistenceManager.call(void 0, queryRef.firestore);
899
+ if (pm) {
900
+ for (const doc2 of snapshot.docs) {
901
+ await pm.cacheDocument(doc2.ref.path, _nullishCoalesce(doc2.data(), () => ( null)), doc2.exists(), doc2._updateTime);
902
+ }
903
+ }
904
+ return snapshot;
905
+ }
906
+ var INEQUALITY_OPS = /* @__PURE__ */ new Set(["<", "<=", ">", ">=", "!=", "not-in"]);
907
+ var ARRAY_VALUE_OPS = /* @__PURE__ */ new Set(["in", "not-in", "array-contains-any"]);
908
+ function createFirestoreError2(code, message) {
909
+ const error = new Error(message);
910
+ error.code = code;
911
+ return error;
912
+ }
913
+ function validateQueryConstraints(constraints, options) {
914
+ const whereConstraints = collectWhereConstraints(constraints);
915
+ const orderByConstraints = constraints.filter((c) => c.type === "orderBy");
916
+ const allowFlexibleQueries = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _14 => _14.allowFlexibleQueries]), () => ( false));
917
+ const inequalityFields = /* @__PURE__ */ new Set();
918
+ for (const w of whereConstraints) {
919
+ if (ARRAY_VALUE_OPS.has(w.op)) {
920
+ validateArrayOperator(w);
921
+ }
922
+ if (INEQUALITY_OPS.has(w.op)) {
923
+ inequalityFields.add(w.field);
924
+ }
925
+ }
926
+ if (inequalityFields.size > 1) {
927
+ throw createFirestoreError2(
928
+ "invalid-argument",
929
+ "Firestore requires inequality filters on a single field"
930
+ );
931
+ }
932
+ if (!allowFlexibleQueries && inequalityFields.size === 1 && orderByConstraints.length > 0) {
933
+ const inequalityField = [...inequalityFields][0];
934
+ const firstOrderBy = orderByConstraints[0];
935
+ if (firstOrderBy.field !== inequalityField) {
936
+ throw createFirestoreError2(
937
+ "invalid-argument",
938
+ `Firestore requires an orderBy on '${inequalityField}' to appear first`
939
+ );
940
+ }
941
+ }
942
+ }
943
+ function validateArrayOperator(where2) {
944
+ if (!Array.isArray(where2.value)) {
945
+ throw createFirestoreError2(
946
+ "invalid-argument",
947
+ `Operator '${where2.op}' requires an array value`
948
+ );
949
+ }
950
+ if (where2.value.length === 0 || where2.value.length > 10) {
951
+ throw createFirestoreError2(
952
+ "invalid-argument",
953
+ `Operator '${where2.op}' requires a non-empty array with at most 10 elements`
954
+ );
955
+ }
956
+ }
957
+ function collectWhereConstraints(constraints) {
958
+ const result = [];
959
+ for (const constraint of constraints) {
960
+ if (constraint.type === "where") {
961
+ result.push(constraint);
962
+ } else if (constraint.type === "and" || constraint.type === "or") {
963
+ const composite = constraint;
964
+ result.push(...collectWhereConstraints(composite.constraints));
965
+ }
966
+ }
967
+ return result;
968
+ }
969
+ function buildStructuredQuery(collectionPath, constraints, isCollectionGroup2 = false) {
970
+ const query2 = {
971
+ from: [{
972
+ collectionId: getCollectionSelectorPath(collectionPath, isCollectionGroup2),
973
+ allDescendants: isCollectionGroup2
974
+ }]
975
+ };
976
+ const wheres = [];
977
+ const compositeFilters = [];
978
+ const orderBys = [];
979
+ let limitValue;
980
+ let limitToLastValue;
981
+ let offsetValue;
982
+ let startCursor;
983
+ let endCursor;
984
+ for (const constraint of constraints) {
985
+ switch (constraint.type) {
986
+ case "where":
987
+ wheres.push(constraint);
988
+ break;
989
+ case "and":
990
+ case "or":
991
+ compositeFilters.push(constraint);
992
+ break;
993
+ case "orderBy":
994
+ orderBys.push(constraint);
995
+ break;
996
+ case "limit":
997
+ limitValue = constraint.limit;
998
+ break;
999
+ case "limitToLast":
1000
+ limitToLastValue = constraint.limit;
1001
+ break;
1002
+ case "offset":
1003
+ offsetValue = constraint.count;
1004
+ break;
1005
+ case "startAt":
1006
+ case "startAfter": {
1007
+ const c = constraint;
1008
+ const cursorValues = extractCursorValues(c.values, orderBys);
1009
+ startCursor = {
1010
+ values: cursorValues.map((v) => _chunkBXV7KTHBjs.toFirestoreValue.call(void 0, v)),
1011
+ before: c.inclusive
1012
+ };
1013
+ break;
1014
+ }
1015
+ case "endAt":
1016
+ case "endBefore": {
1017
+ const c = constraint;
1018
+ const cursorValues = extractCursorValues(c.values, orderBys);
1019
+ endCursor = {
1020
+ values: cursorValues.map((v) => _chunkBXV7KTHBjs.toFirestoreValue.call(void 0, v)),
1021
+ before: !c.inclusive
1022
+ };
1023
+ break;
1024
+ }
1025
+ }
1026
+ }
1027
+ const allFilters = [];
1028
+ for (const w of wheres) {
1029
+ const filter = buildWhereFilter(w);
1030
+ if (filter) {
1031
+ allFilters.push(filter);
1032
+ }
1033
+ }
1034
+ for (const cf of compositeFilters) {
1035
+ allFilters.push(buildCompositeFilterQuery(cf));
1036
+ }
1037
+ if (allFilters.length === 1) {
1038
+ query2.where = allFilters[0];
1039
+ } else if (allFilters.length > 1) {
1040
+ query2.where = {
1041
+ compositeFilter: {
1042
+ op: "AND",
1043
+ filters: allFilters
1044
+ }
1045
+ };
1046
+ }
1047
+ if (orderBys.length > 0) {
1048
+ query2.orderBy = orderBys.map((ob) => ({
1049
+ field: { fieldPath: ob.field },
1050
+ direction: ob.direction === "desc" ? "DESCENDING" : "ASCENDING"
1051
+ }));
1052
+ }
1053
+ if (limitValue !== void 0) {
1054
+ query2.limit = limitValue;
1055
+ }
1056
+ if (limitToLastValue !== void 0) {
1057
+ query2.limitToLast = limitToLastValue;
1058
+ }
1059
+ if (offsetValue !== void 0) {
1060
+ query2.offset = offsetValue;
1061
+ }
1062
+ if (startCursor) {
1063
+ query2.startAt = startCursor;
1064
+ }
1065
+ if (endCursor) {
1066
+ query2.endAt = endCursor;
1067
+ }
1068
+ return query2;
1069
+ }
1070
+ function buildWhereFilter(where2) {
1071
+ const fieldPath = where2.field;
1072
+ const value = _chunkBXV7KTHBjs.toFirestoreValue.call(void 0, where2.value);
1073
+ const opMap = {
1074
+ "<": "LESS_THAN",
1075
+ "<=": "LESS_THAN_OR_EQUAL",
1076
+ "==": "EQUAL",
1077
+ "!=": "NOT_EQUAL",
1078
+ ">": "GREATER_THAN",
1079
+ ">=": "GREATER_THAN_OR_EQUAL",
1080
+ "array-contains": "ARRAY_CONTAINS",
1081
+ "array-contains-any": "ARRAY_CONTAINS_ANY",
1082
+ "in": "IN",
1083
+ "not-in": "NOT_IN"
1084
+ };
1085
+ if (where2.op === "array-contains-any" || where2.op === "in" || where2.op === "not-in") {
1086
+ return {
1087
+ fieldFilter: {
1088
+ field: { fieldPath },
1089
+ op: opMap[where2.op],
1090
+ value
1091
+ }
1092
+ };
1093
+ }
1094
+ return {
1095
+ fieldFilter: {
1096
+ field: { fieldPath },
1097
+ op: opMap[where2.op],
1098
+ value
1099
+ }
1100
+ };
1101
+ }
1102
+ function buildCompositeFilterQuery(constraint) {
1103
+ const op = constraint.type === "and" ? "AND" : "OR";
1104
+ const filters = constraint.constraints.map((c) => {
1105
+ if (c.type === "and" || c.type === "or") {
1106
+ return buildCompositeFilterQuery(c);
1107
+ }
1108
+ return buildWhereFilter(c);
1109
+ });
1110
+ return {
1111
+ compositeFilter: {
1112
+ op,
1113
+ filters
1114
+ }
1115
+ };
1116
+ }
1117
+ function getCollectionId(path) {
1118
+ const parts = path.split("/");
1119
+ return parts[parts.length - 1];
1120
+ }
1121
+ function getCollectionSelectorPath(path, isCollectionGroup2) {
1122
+ if (isCollectionGroup2) {
1123
+ return getCollectionId(path);
1124
+ }
1125
+ return path;
1126
+ }
1127
+ function extractCursorValues(values, orderBys) {
1128
+ if (values.length === 0) return values;
1129
+ const first = values[0];
1130
+ if (isDocumentSnapshot(first)) {
1131
+ const snapshot = first;
1132
+ const data = snapshot.data();
1133
+ if (!data) {
1134
+ return values;
1135
+ }
1136
+ if (orderBys.length > 0) {
1137
+ return orderBys.map((ob) => {
1138
+ if (ob.field === "__name__") {
1139
+ return snapshot.id;
1140
+ }
1141
+ return getNestedValue(data, ob.field);
1142
+ });
1143
+ }
1144
+ return [snapshot.id];
1145
+ }
1146
+ return values;
1147
+ }
1148
+ function isDocumentSnapshot(value) {
1149
+ if (!value || typeof value !== "object") return false;
1150
+ const obj = value;
1151
+ return typeof obj.exists === "function" && typeof obj.data === "function" && typeof obj.id === "string";
1152
+ }
1153
+ function getNestedValue(obj, path) {
1154
+ const parts = path.split(".");
1155
+ let current = obj;
1156
+ for (const part of parts) {
1157
+ if (current === null || current === void 0) return void 0;
1158
+ if (typeof current !== "object") return void 0;
1159
+ current = current[part];
1160
+ }
1161
+ return current;
1162
+ }
1163
+
1164
+ // src/transport/websocket.ts
1165
+ function getWebSocketConstructor() {
1166
+ if (typeof globalThis.WebSocket !== "undefined") {
1167
+ return globalThis.WebSocket;
1168
+ }
1169
+ return null;
1170
+ }
1171
+ function normalizeWebSocketHost(rawHost, ssl) {
1172
+ const trimmed = rawHost.trim().replace(/\/+$/, "");
1173
+ if (trimmed.startsWith("ws://") || trimmed.startsWith("wss://")) {
1174
+ return trimmed;
1175
+ }
1176
+ if (trimmed.startsWith("http://")) {
1177
+ return `ws://${trimmed.slice("http://".length)}`;
1178
+ }
1179
+ if (trimmed.startsWith("https://")) {
1180
+ return `wss://${trimmed.slice("https://".length)}`;
1181
+ }
1182
+ const protocol = ssl ? "wss" : "ws";
1183
+ return `${protocol}://${trimmed}`;
1184
+ }
1185
+ var WebSocketClient = class {
1186
+ constructor(firestore) {
1187
+ this.socket = null;
1188
+ this.state = "disconnected";
1189
+ this.reconnectAttempts = 0;
1190
+ this.maxReconnectAttempts = 5;
1191
+ this.reconnectDelay = 1e3;
1192
+ this.authToken = null;
1193
+ this.syncTimer = null;
1194
+ // Suscripciones activas
1195
+ this.subscriptions = /* @__PURE__ */ new Map();
1196
+ // ID para suscripciones
1197
+ this.subscriptionIdCounter = 0;
1198
+ this.firestore = firestore;
1199
+ const host = normalizeWebSocketHost(firestore._config.host, firestore._config.ssl);
1200
+ this.url = `${host}/v1/projects/${firestore._projectId}/databases/${firestore._databaseId}/documents:listen`;
1201
+ }
1202
+ /**
1203
+ * Establece el token de autenticación
1204
+ */
1205
+ setAuthToken(token) {
1206
+ this.authToken = token;
1207
+ if (this.socket && this.state === "connected") {
1208
+ this.reconnect();
1209
+ }
1210
+ }
1211
+ /**
1212
+ * Conecta al WebSocket
1213
+ */
1214
+ async connect() {
1215
+ if (this.state === "connecting" || this.state === "connected") {
1216
+ return;
1217
+ }
1218
+ this.state = "connecting";
1219
+ return new Promise((resolve, reject) => {
1220
+ try {
1221
+ const WS = getWebSocketConstructor();
1222
+ if (!WS) {
1223
+ this.state = "error";
1224
+ reject(new Error("WebSocket not available in this environment"));
1225
+ return;
1226
+ }
1227
+ this.socket = new WS(this.url);
1228
+ this.socket.onopen = () => {
1229
+ this.state = "connected";
1230
+ this.reconnectAttempts = 0;
1231
+ this.sendAuth();
1232
+ this.resubscribeAll();
1233
+ resolve();
1234
+ };
1235
+ this.socket.onclose = () => {
1236
+ this.state = "disconnected";
1237
+ this.handleDisconnect();
1238
+ };
1239
+ this.socket.onerror = () => {
1240
+ this.state = "error";
1241
+ reject(new Error("WebSocket connection failed"));
1242
+ };
1243
+ this.socket.onmessage = (event) => {
1244
+ this.handleMessage(event.data);
1245
+ };
1246
+ } catch (error) {
1247
+ this.state = "error";
1248
+ reject(error);
1249
+ }
1250
+ });
1251
+ }
1252
+ /**
1253
+ * Maneja desconexión e intenta reconectar
1254
+ */
1255
+ handleDisconnect() {
1256
+ if (this.reconnectAttempts < this.maxReconnectAttempts && this.subscriptions.size > 0) {
1257
+ this.reconnectAttempts++;
1258
+ const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
1259
+ setTimeout(() => this.connect(), delay);
1260
+ }
1261
+ }
1262
+ /**
1263
+ * Reconecta forzadamente
1264
+ */
1265
+ reconnect() {
1266
+ _optionalChain([this, 'access', _15 => _15.socket, 'optionalAccess', _16 => _16.close, 'call', _17 => _17()]);
1267
+ this.state = "disconnected";
1268
+ this.connect();
1269
+ }
1270
+ /**
1271
+ * Envía el token de autenticación como mensaje (no en URL)
1272
+ */
1273
+ sendAuth() {
1274
+ if (this.socket && this.state === "connected" && this.authToken) {
1275
+ this.socket.send(JSON.stringify({ type: "auth", token: this.authToken }));
1276
+ }
1277
+ }
1278
+ /**
1279
+ * Re-suscribe a todas las suscripciones activas
1280
+ */
1281
+ resubscribeAll() {
1282
+ for (const [id, sub] of this.subscriptions) {
1283
+ this.sendSubscribe(id, sub.path, sub.query, sub.includeMetadataChanges, sub.allDescendants);
1284
+ if (sub.resumeToken && sub.path) {
1285
+ this.sendResume(id, sub.resumeToken, sub.path);
1286
+ }
1287
+ }
1288
+ }
1289
+ /**
1290
+ * Envía mensaje de suscripción
1291
+ */
1292
+ sendSubscribe(id, path, query2, includeMetadataChanges, allDescendants) {
1293
+ if (this.socket && this.state === "connected") {
1294
+ const message = {
1295
+ type: "subscribe",
1296
+ id,
1297
+ path,
1298
+ query: query2,
1299
+ includeMetadataChanges,
1300
+ allDescendants
1301
+ };
1302
+ this.socket.send(JSON.stringify(message));
1303
+ }
1304
+ }
1305
+ /**
1306
+ * Envía mensaje de reanudación con resumeToken
1307
+ */
1308
+ sendResume(id, resumeToken, path) {
1309
+ if (this.socket && this.state === "connected") {
1310
+ const message = {
1311
+ type: "resume",
1312
+ id,
1313
+ resumeToken,
1314
+ path
1315
+ };
1316
+ this.socket.send(JSON.stringify(message));
1317
+ }
1318
+ }
1319
+ /**
1320
+ * Notifica onSnapshotsInSync con debounce
1321
+ */
1322
+ scheduleSnapshotsSync() {
1323
+ const firestoreInternal = this.firestore;
1324
+ if (!firestoreInternal._syncCallbacks || firestoreInternal._syncCallbacks.size === 0) {
1325
+ return;
1326
+ }
1327
+ if (this.syncTimer) {
1328
+ clearTimeout(this.syncTimer);
1329
+ }
1330
+ this.syncTimer = setTimeout(() => {
1331
+ _optionalChain([firestoreInternal, 'access', _18 => _18._syncCallbacks, 'optionalAccess', _19 => _19.forEach, 'call', _20 => _20((cb) => cb())]);
1332
+ }, 50);
1333
+ }
1334
+ /**
1335
+ * Envía mensaje de cancelación de suscripción
1336
+ */
1337
+ sendUnsubscribe(id) {
1338
+ if (this.socket && this.state === "connected") {
1339
+ const message = {
1340
+ type: "unsubscribe",
1341
+ id
1342
+ };
1343
+ this.socket.send(JSON.stringify(message));
1344
+ }
1345
+ }
1346
+ /**
1347
+ * Maneja mensajes entrantes
1348
+ */
1349
+ handleMessage(data) {
1350
+ try {
1351
+ const message = JSON.parse(data);
1352
+ switch (message.type) {
1353
+ case "document_change":
1354
+ case "query_change":
1355
+ case "metadata_change":
1356
+ case "missed_event": {
1357
+ const sub = this.subscriptions.get(message.id || "");
1358
+ if (sub) {
1359
+ if (message.resumeToken) {
1360
+ sub.resumeToken = message.resumeToken;
1361
+ }
1362
+ sub.callback(message);
1363
+ this.scheduleSnapshotsSync();
1364
+ }
1365
+ break;
1366
+ }
1367
+ case "snapshots_in_sync": {
1368
+ this.scheduleSnapshotsSync();
1369
+ break;
1370
+ }
1371
+ case "error": {
1372
+ const sub = this.subscriptions.get(message.id || "");
1373
+ if (_optionalChain([sub, 'optionalAccess', _21 => _21.errorCallback])) {
1374
+ sub.errorCallback(new Error(message.error || "Unknown error"));
1375
+ }
1376
+ break;
1377
+ }
1378
+ }
1379
+ } catch (e) {
1380
+ }
1381
+ }
1382
+ /**
1383
+ * Suscribe a cambios de un documento
1384
+ */
1385
+ async subscribeToDocument(path, callback, errorCallback, includeMetadataChanges) {
1386
+ if (this.state !== "connected") {
1387
+ await this.connect();
1388
+ }
1389
+ const id = `doc_${++this.subscriptionIdCounter}`;
1390
+ this.subscriptions.set(id, {
1391
+ path,
1392
+ callback,
1393
+ errorCallback,
1394
+ includeMetadataChanges
1395
+ });
1396
+ this.sendSubscribe(id, path, void 0, includeMetadataChanges);
1397
+ return () => {
1398
+ this.subscriptions.delete(id);
1399
+ this.sendUnsubscribe(id);
1400
+ if (this.subscriptions.size === 0) {
1401
+ _optionalChain([this, 'access', _22 => _22.socket, 'optionalAccess', _23 => _23.close, 'call', _24 => _24()]);
1402
+ this.state = "disconnected";
1403
+ }
1404
+ };
1405
+ }
1406
+ /**
1407
+ * Suscribe a cambios de una query
1408
+ */
1409
+ async subscribeToQuery(query2, callback, errorCallback, path, includeMetadataChanges, allDescendants) {
1410
+ if (this.state !== "connected") {
1411
+ await this.connect();
1412
+ }
1413
+ const id = `query_${++this.subscriptionIdCounter}`;
1414
+ this.subscriptions.set(id, {
1415
+ query: query2,
1416
+ callback,
1417
+ errorCallback,
1418
+ path,
1419
+ includeMetadataChanges,
1420
+ allDescendants
1421
+ });
1422
+ this.sendSubscribe(id, path, query2, includeMetadataChanges, allDescendants);
1423
+ return () => {
1424
+ this.subscriptions.delete(id);
1425
+ this.sendUnsubscribe(id);
1426
+ if (this.subscriptions.size === 0) {
1427
+ _optionalChain([this, 'access', _25 => _25.socket, 'optionalAccess', _26 => _26.close, 'call', _27 => _27()]);
1428
+ this.state = "disconnected";
1429
+ }
1430
+ };
1431
+ }
1432
+ /**
1433
+ * Cierra la conexión
1434
+ */
1435
+ close() {
1436
+ this.subscriptions.clear();
1437
+ _optionalChain([this, 'access', _28 => _28.socket, 'optionalAccess', _29 => _29.close, 'call', _30 => _30()]);
1438
+ this.state = "disconnected";
1439
+ }
1440
+ /**
1441
+ * Fuerza desconexión sin limpiar suscripciones (para pruebas de reconexión)
1442
+ */
1443
+ simulateDisconnect() {
1444
+ if (this.socket) {
1445
+ this.socket.close();
1446
+ }
1447
+ }
1448
+ };
1449
+ var clients = /* @__PURE__ */ new WeakMap();
1450
+ function getWebSocketClient(firestore) {
1451
+ let client = clients.get(firestore);
1452
+ if (!client) {
1453
+ client = new WebSocketClient(firestore);
1454
+ clients.set(firestore, client);
1455
+ }
1456
+ return client;
1457
+ }
1458
+
1459
+ // src/firestore/realtime.ts
1460
+ function onSnapshot(reference, onNextOrObserverOrOptions, onErrorOrObserver, onError) {
1461
+ let nextCallback;
1462
+ let errorCallback = onError;
1463
+ let options;
1464
+ let onNextOrObserver = onNextOrObserverOrOptions;
1465
+ const maybeOptions = onNextOrObserverOrOptions;
1466
+ if (maybeOptions && typeof maybeOptions === "object" && ("includeMetadataChanges" in maybeOptions || "source" in maybeOptions)) {
1467
+ options = maybeOptions;
1468
+ onNextOrObserver = onErrorOrObserver;
1469
+ errorCallback = onError;
1470
+ } else {
1471
+ errorCallback = onErrorOrObserver;
1472
+ }
1473
+ if (typeof onNextOrObserver === "function") {
1474
+ nextCallback = onNextOrObserver;
1475
+ } else {
1476
+ nextCallback = _optionalChain([onNextOrObserver, 'optionalAccess', _31 => _31.next]);
1477
+ errorCallback = _nullishCoalesce(_optionalChain([onNextOrObserver, 'optionalAccess', _32 => _32.error]), () => ( errorCallback));
1478
+ }
1479
+ const isDocument = reference.type === "document";
1480
+ if (isDocument) {
1481
+ return subscribeToDocument(
1482
+ reference,
1483
+ nextCallback,
1484
+ errorCallback,
1485
+ options
1486
+ );
1487
+ } else {
1488
+ return subscribeToQuery(
1489
+ reference,
1490
+ nextCallback,
1491
+ errorCallback,
1492
+ options
1493
+ );
1494
+ }
1495
+ }
1496
+ function subscribeToDocument(reference, onNext, onError, options) {
1497
+ let unsubscribed = false;
1498
+ let wsUnsubscribe = null;
1499
+ let localUnsubscribe = null;
1500
+ let lastSnapshot = null;
1501
+ const pm = _chunk2RQUHE2Kjs.getPersistenceManager.call(void 0, reference.firestore);
1502
+ if (pm) {
1503
+ pm.getCachedDocument(reference.path).then(async (cached) => {
1504
+ if (cached && !unsubscribed) {
1505
+ const cachedSnapshot = new (0, _chunkBXV7KTHBjs.DocumentSnapshotImpl)(
1506
+ reference,
1507
+ cached.exists ? cached.data : void 0,
1508
+ cached.exists,
1509
+ { fromCache: true, hasPendingWrites: await pm.hasPendingWrites(reference.path) }
1510
+ );
1511
+ lastSnapshot = cachedSnapshot;
1512
+ if (!unsubscribed && onNext) {
1513
+ onNext(cachedSnapshot);
1514
+ }
1515
+ }
1516
+ });
1517
+ }
1518
+ if (_optionalChain([options, 'optionalAccess', _33 => _33.source]) === "cache") {
1519
+ if (!lastSnapshot) {
1520
+ const hasPendingPromise = pm ? Promise.resolve(pm.hasPendingWrites(reference.path)) : Promise.resolve(false);
1521
+ hasPendingPromise.then((hasPending) => {
1522
+ if (unsubscribed || lastSnapshot) return;
1523
+ const emptyCachedSnapshot = new (0, _chunkBXV7KTHBjs.DocumentSnapshotImpl)(
1524
+ reference,
1525
+ void 0,
1526
+ false,
1527
+ {
1528
+ fromCache: true,
1529
+ hasPendingWrites: hasPending
1530
+ }
1531
+ );
1532
+ lastSnapshot = emptyCachedSnapshot;
1533
+ if (!unsubscribed && onNext) {
1534
+ onNext(emptyCachedSnapshot);
1535
+ }
1536
+ });
1537
+ }
1538
+ if (_optionalChain([options, 'optionalAccess', _34 => _34.includeMetadataChanges])) {
1539
+ localUnsubscribe = registerLocalWriteListener(reference.path, () => {
1540
+ if (unsubscribed || !onNext) return;
1541
+ const data = _optionalChain([lastSnapshot, 'optionalAccess', _35 => _35.data, 'call', _36 => _36()]);
1542
+ const pendingSnapshot = new (0, _chunkBXV7KTHBjs.DocumentSnapshotImpl)(
1543
+ reference,
1544
+ data,
1545
+ _nullishCoalesce(_optionalChain([lastSnapshot, 'optionalAccess', _37 => _37.exists, 'call', _38 => _38()]), () => ( false)),
1546
+ { fromCache: true, hasPendingWrites: true }
1547
+ );
1548
+ onNext(pendingSnapshot);
1549
+ });
1550
+ }
1551
+ return () => {
1552
+ unsubscribed = true;
1553
+ if (localUnsubscribe) {
1554
+ localUnsubscribe();
1555
+ }
1556
+ };
1557
+ }
1558
+ getDoc(reference).then(async (snapshot) => {
1559
+ if (!unsubscribed && onNext) {
1560
+ lastSnapshot = snapshot;
1561
+ if (pm) {
1562
+ await pm.cacheDocument(reference.path, _nullishCoalesce(snapshot.data(), () => ( null)), snapshot.exists(), snapshot._updateTime);
1563
+ }
1564
+ onNext(snapshot);
1565
+ }
1566
+ }).catch((error) => {
1567
+ if (!unsubscribed && onError) {
1568
+ onError(error);
1569
+ }
1570
+ });
1571
+ if (_optionalChain([options, 'optionalAccess', _39 => _39.includeMetadataChanges])) {
1572
+ localUnsubscribe = registerLocalWriteListener(reference.path, () => {
1573
+ if (unsubscribed || !onNext) return;
1574
+ const data = _optionalChain([lastSnapshot, 'optionalAccess', _40 => _40.data, 'call', _41 => _41()]);
1575
+ const pendingSnapshot = new (0, _chunkBXV7KTHBjs.DocumentSnapshotImpl)(
1576
+ reference,
1577
+ data,
1578
+ _nullishCoalesce(_optionalChain([lastSnapshot, 'optionalAccess', _42 => _42.exists, 'call', _43 => _43()]), () => ( false)),
1579
+ { fromCache: true, hasPendingWrites: true }
1580
+ );
1581
+ onNext(pendingSnapshot);
1582
+ });
1583
+ }
1584
+ try {
1585
+ const wsClient = getWebSocketClient(reference.firestore);
1586
+ wsClient.subscribeToDocument(
1587
+ reference.path,
1588
+ () => {
1589
+ if (!unsubscribed && onNext) {
1590
+ getDoc(reference).then(async (snapshot) => {
1591
+ if (!unsubscribed) {
1592
+ lastSnapshot = snapshot;
1593
+ if (pm) {
1594
+ await pm.cacheDocument(reference.path, _nullishCoalesce(snapshot.data(), () => ( null)), snapshot.exists(), snapshot._updateTime);
1595
+ }
1596
+ onNext(snapshot);
1597
+ }
1598
+ }).catch((error) => {
1599
+ if (!unsubscribed && onError) {
1600
+ onError(error);
1601
+ }
1602
+ });
1603
+ }
1604
+ },
1605
+ (error) => {
1606
+ if (!unsubscribed && onError) {
1607
+ onError(error);
1608
+ }
1609
+ },
1610
+ _optionalChain([options, 'optionalAccess', _44 => _44.includeMetadataChanges])
1611
+ ).then((unsub) => {
1612
+ wsUnsubscribe = unsub;
1613
+ if (unsubscribed) {
1614
+ unsub();
1615
+ }
1616
+ }).catch((error) => {
1617
+ if (!unsubscribed && onError) {
1618
+ onError(error);
1619
+ }
1620
+ });
1621
+ } catch (error) {
1622
+ if (!unsubscribed && onError) {
1623
+ onError(error);
1624
+ }
1625
+ }
1626
+ return () => {
1627
+ unsubscribed = true;
1628
+ if (wsUnsubscribe) {
1629
+ wsUnsubscribe();
1630
+ }
1631
+ if (localUnsubscribe) {
1632
+ localUnsubscribe();
1633
+ }
1634
+ };
1635
+ }
1636
+ function subscribeToQuery(queryRef, onNext, onError, options) {
1637
+ let unsubscribed = false;
1638
+ let previousSnapshot = null;
1639
+ let wsUnsubscribe = null;
1640
+ if (_optionalChain([options, 'optionalAccess', _45 => _45.source]) === "cache") {
1641
+ getDocsFromCache(queryRef).then((snapshot) => {
1642
+ if (!unsubscribed && onNext) {
1643
+ onNext(snapshot);
1644
+ }
1645
+ }).catch((error) => {
1646
+ if (!unsubscribed && onError) {
1647
+ onError(error);
1648
+ }
1649
+ });
1650
+ return () => {
1651
+ unsubscribed = true;
1652
+ };
1653
+ }
1654
+ const refresh = () => {
1655
+ getDocsWithPreviousState(queryRef, previousSnapshot).then((snapshot) => {
1656
+ if (!unsubscribed && onNext) {
1657
+ previousSnapshot = snapshot;
1658
+ onNext(snapshot);
1659
+ }
1660
+ }).catch((error) => {
1661
+ if (!unsubscribed && onError) {
1662
+ onError(error);
1663
+ }
1664
+ });
1665
+ };
1666
+ refresh();
1667
+ try {
1668
+ const wsClient = getWebSocketClient(queryRef.firestore);
1669
+ const constraints = "constraints" in queryRef ? queryRef.constraints : [];
1670
+ const isCollectionGroup2 = queryRef.type === "collectionGroup";
1671
+ wsClient.subscribeToQuery(
1672
+ constraints,
1673
+ () => {
1674
+ if (!unsubscribed) {
1675
+ refresh();
1676
+ }
1677
+ },
1678
+ (error) => {
1679
+ if (!unsubscribed && onError) {
1680
+ onError(error);
1681
+ }
1682
+ },
1683
+ queryRef.path,
1684
+ _optionalChain([options, 'optionalAccess', _46 => _46.includeMetadataChanges]),
1685
+ isCollectionGroup2
1686
+ // allDescendants para collectionGroup
1687
+ ).then((unsub) => {
1688
+ wsUnsubscribe = unsub;
1689
+ if (unsubscribed) {
1690
+ unsub();
1691
+ }
1692
+ }).catch((error) => {
1693
+ if (!unsubscribed && onError) {
1694
+ onError(error);
1695
+ }
1696
+ });
1697
+ } catch (error) {
1698
+ if (!unsubscribed && onError) {
1699
+ onError(error);
1700
+ }
1701
+ }
1702
+ return () => {
1703
+ unsubscribed = true;
1704
+ if (wsUnsubscribe) {
1705
+ wsUnsubscribe();
1706
+ }
1707
+ };
1708
+ }
1709
+ async function getDocsWithPreviousState(queryRef, previousSnapshot) {
1710
+ const { getHttpClient: getHttpClient2 } = await Promise.resolve().then(() => _interopRequireWildcard(require("./http-A2S5CWEV.js")));
1711
+ const { createQuerySnapshot: createQuerySnapshot2, toFirestoreValue: toFirestoreValue3 } = await Promise.resolve().then(() => _interopRequireWildcard(require("./snapshot-MCQVLVHL.js")));
1712
+ const client = getHttpClient2(queryRef.firestore);
1713
+ const constraints = "constraints" in queryRef ? queryRef.constraints : [];
1714
+ const isCollectionGroupQuery = queryRef.type === "collectionGroup";
1715
+ const structuredQuery = buildStructuredQueryForRealtime(queryRef.path, constraints, isCollectionGroupQuery, toFirestoreValue3);
1716
+ const response = await client.post(
1717
+ "/documents:runQuery",
1718
+ { structuredQuery }
1719
+ );
1720
+ const documents = response.filter((r) => r.document).map((r) => r.document);
1721
+ const previousDocs = previousSnapshot ? previousSnapshot.docs : [];
1722
+ return createQuerySnapshot2(queryRef, documents, previousDocs);
1723
+ }
1724
+ function buildStructuredQueryForRealtime(collectionPath, constraints, isCollectionGroup2, toFirestoreValue3) {
1725
+ const query2 = {
1726
+ from: [{
1727
+ collectionId: isCollectionGroup2 ? collectionPath.split("/").pop() || collectionPath : collectionPath,
1728
+ allDescendants: isCollectionGroup2
1729
+ }]
1730
+ };
1731
+ const allFilters = [];
1732
+ const orderBys = [];
1733
+ let startCursor;
1734
+ let endCursor;
1735
+ for (const raw of constraints) {
1736
+ if (raw.type === "where") {
1737
+ const w = raw;
1738
+ const filter = buildWhereFilterRealtime(w, toFirestoreValue3);
1739
+ if (filter) {
1740
+ allFilters.push(filter);
1741
+ }
1742
+ } else if (raw.type === "and" || raw.type === "or") {
1743
+ allFilters.push(buildCompositeFilterRealtime(raw, toFirestoreValue3));
1744
+ } else if (raw.type === "orderBy") {
1745
+ const o = raw;
1746
+ if (!query2.orderBy) query2.orderBy = [];
1747
+ query2.orderBy.push({
1748
+ field: { fieldPath: o.field },
1749
+ direction: o.direction === "desc" ? "DESCENDING" : "ASCENDING"
1750
+ });
1751
+ orderBys.push(o);
1752
+ } else if (raw.type === "limit") {
1753
+ query2.limit = raw.limit;
1754
+ } else if (raw.type === "limitToLast") {
1755
+ query2.limitToLast = raw.limit;
1756
+ } else if (raw.type === "startAt" || raw.type === "startAfter") {
1757
+ const c = raw;
1758
+ const cursorValues = extractCursorValuesRealtime(c.values, orderBys);
1759
+ startCursor = {
1760
+ values: cursorValues.map((v) => toFirestoreValue3(v)),
1761
+ before: c.inclusive
1762
+ };
1763
+ } else if (raw.type === "endAt" || raw.type === "endBefore") {
1764
+ const c = raw;
1765
+ const cursorValues = extractCursorValuesRealtime(c.values, orderBys);
1766
+ endCursor = {
1767
+ values: cursorValues.map((v) => toFirestoreValue3(v)),
1768
+ before: !c.inclusive
1769
+ };
1770
+ }
1771
+ }
1772
+ if (allFilters.length === 1) {
1773
+ query2.where = allFilters[0];
1774
+ } else if (allFilters.length > 1) {
1775
+ query2.where = {
1776
+ compositeFilter: {
1777
+ op: "AND",
1778
+ filters: allFilters
1779
+ }
1780
+ };
1781
+ }
1782
+ if (startCursor) {
1783
+ query2.startAt = startCursor;
1784
+ }
1785
+ if (endCursor) {
1786
+ query2.endAt = endCursor;
1787
+ }
1788
+ return query2;
1789
+ }
1790
+ function extractCursorValuesRealtime(values, orderBys) {
1791
+ if (!values || values.length === 0) return values;
1792
+ const first = values[0];
1793
+ if (first && typeof first.data === "function") {
1794
+ const data = first.data();
1795
+ if (!data) return values;
1796
+ if (orderBys.length > 0) {
1797
+ return orderBys.map((ob) => {
1798
+ if (ob.field === "__name__") {
1799
+ return _nullishCoalesce(first.id, () => ( ""));
1800
+ }
1801
+ return getNestedValue2(data, ob.field);
1802
+ });
1803
+ }
1804
+ }
1805
+ return values;
1806
+ }
1807
+ function getNestedValue2(obj, path) {
1808
+ const parts = path.split(".");
1809
+ let current = obj;
1810
+ for (const part of parts) {
1811
+ if (current === null || current === void 0) return void 0;
1812
+ if (typeof current !== "object") return void 0;
1813
+ current = current[part];
1814
+ }
1815
+ return current;
1816
+ }
1817
+ function buildWhereFilterRealtime(where2, toFirestoreValue3) {
1818
+ const opMap = {
1819
+ "<": "LESS_THAN",
1820
+ "<=": "LESS_THAN_OR_EQUAL",
1821
+ "==": "EQUAL",
1822
+ "!=": "NOT_EQUAL",
1823
+ ">": "GREATER_THAN",
1824
+ ">=": "GREATER_THAN_OR_EQUAL",
1825
+ "array-contains": "ARRAY_CONTAINS",
1826
+ "array-contains-any": "ARRAY_CONTAINS_ANY",
1827
+ "in": "IN",
1828
+ "not-in": "NOT_IN"
1829
+ };
1830
+ return {
1831
+ fieldFilter: {
1832
+ field: { fieldPath: where2.field },
1833
+ op: opMap[where2.op],
1834
+ value: toFirestoreValue3(where2.value)
1835
+ }
1836
+ };
1837
+ }
1838
+ function buildCompositeFilterRealtime(constraint, toFirestoreValue3) {
1839
+ const op = constraint.type === "and" ? "AND" : "OR";
1840
+ const constraints = constraint.constraints || [];
1841
+ const filters = constraints.map((c) => {
1842
+ const item = c;
1843
+ if (item.type === "and" || item.type === "or") {
1844
+ return buildCompositeFilterRealtime(item, toFirestoreValue3);
1845
+ }
1846
+ return buildWhereFilterRealtime(item, toFirestoreValue3);
1847
+ });
1848
+ return {
1849
+ compositeFilter: {
1850
+ op,
1851
+ filters
1852
+ }
1853
+ };
1854
+ }
1855
+
1856
+ // src/firestore/batch.ts
1857
+ var WriteBatchImpl = class {
1858
+ constructor(firestore) {
1859
+ this.firestore = firestore;
1860
+ this.operations = [];
1861
+ this.committed = false;
1862
+ }
1863
+ set(reference, data, options) {
1864
+ this.verifyNotCommitted();
1865
+ this.operations.push({
1866
+ type: "set",
1867
+ reference,
1868
+ data,
1869
+ options
1870
+ });
1871
+ return this;
1872
+ }
1873
+ update(reference, data) {
1874
+ this.verifyNotCommitted();
1875
+ this.operations.push({
1876
+ type: "update",
1877
+ reference,
1878
+ data
1879
+ });
1880
+ return this;
1881
+ }
1882
+ delete(reference) {
1883
+ this.verifyNotCommitted();
1884
+ this.operations.push({ type: "delete", reference });
1885
+ return this;
1886
+ }
1887
+ async commit() {
1888
+ this.verifyNotCommitted();
1889
+ this.committed = true;
1890
+ if (this.operations.length === 0) {
1891
+ return;
1892
+ }
1893
+ if (this.operations.length > 500) {
1894
+ throw createFirestoreError3("invalid-argument", "Batch write exceeds 500 operations");
1895
+ }
1896
+ const client = _chunk6J3LNKUQjs.getHttpClient.call(void 0, this.firestore);
1897
+ const writes = this.operations.map((op) => {
1898
+ switch (op.type) {
1899
+ case "set": {
1900
+ const fields = _chunkBXV7KTHBjs.toFirestoreFields.call(void 0, op.data);
1901
+ if (_optionalChain([op, 'access', _47 => _47.options, 'optionalAccess', _48 => _48.merge]) || _optionalChain([op, 'access', _49 => _49.options, 'optionalAccess', _50 => _50.mergeFields])) {
1902
+ const fieldPaths = op.options.mergeFields || Object.keys(op.data);
1903
+ return {
1904
+ update: {
1905
+ name: `projects/${this.firestore.app.options.projectId}/databases/(default)/documents/${op.reference.path}`,
1906
+ fields
1907
+ },
1908
+ updateMask: { fieldPaths }
1909
+ };
1910
+ }
1911
+ return {
1912
+ update: {
1913
+ name: `projects/${this.firestore.app.options.projectId}/databases/(default)/documents/${op.reference.path}`,
1914
+ fields
1915
+ }
1916
+ };
1917
+ }
1918
+ case "update": {
1919
+ const fields = _chunkBXV7KTHBjs.toFirestoreFields.call(void 0, op.data);
1920
+ const fieldPaths = Object.keys(op.data);
1921
+ return {
1922
+ update: {
1923
+ name: `projects/${this.firestore.app.options.projectId}/databases/(default)/documents/${op.reference.path}`,
1924
+ fields
1925
+ },
1926
+ updateMask: { fieldPaths }
1927
+ };
1928
+ }
1929
+ case "delete":
1930
+ return {
1931
+ delete: `projects/${this.firestore.app.options.projectId}/databases/(default)/documents/${op.reference.path}`
1932
+ };
1933
+ }
1934
+ });
1935
+ await client.post(":batchWrite", { writes });
1936
+ }
1937
+ verifyNotCommitted() {
1938
+ if (this.committed) {
1939
+ throw new Error("WriteBatch ya ha sido committed");
1940
+ }
1941
+ }
1942
+ };
1943
+ function writeBatch(firestore) {
1944
+ return new WriteBatchImpl(firestore);
1945
+ }
1946
+ var TransactionImpl = class {
1947
+ constructor(firestore, client) {
1948
+ this.firestore = firestore;
1949
+ this.client = client;
1950
+ this.reads = /* @__PURE__ */ new Map();
1951
+ this.operations = [];
1952
+ this.id = createTransactionId();
1953
+ this.readVersions = /* @__PURE__ */ new Map();
1954
+ this.preconditions = /* @__PURE__ */ new Map();
1955
+ }
1956
+ /**
1957
+ * Inicia la transacción
1958
+ */
1959
+ async begin() {
1960
+ const response = await this.client.post(
1961
+ ":beginTransaction",
1962
+ {}
1963
+ );
1964
+ this.transactionId = response.transaction;
1965
+ }
1966
+ async get(reference) {
1967
+ const cached = this.reads.get(reference.path);
1968
+ if (cached) {
1969
+ return cached;
1970
+ }
1971
+ const snapshot = await getDoc(reference);
1972
+ this.readVersions.set(reference.path, getDocumentVersion(reference.path));
1973
+ const snapImpl = snapshot;
1974
+ this.preconditions.set(reference.path, {
1975
+ exists: snapshot.exists(),
1976
+ updateTime: snapImpl._updateTime
1977
+ });
1978
+ this.reads.set(reference.path, snapshot);
1979
+ return snapshot;
1980
+ }
1981
+ set(reference, data, options) {
1982
+ this.operations.push({
1983
+ type: "set",
1984
+ reference,
1985
+ data,
1986
+ options
1987
+ });
1988
+ return this;
1989
+ }
1990
+ update(reference, data) {
1991
+ this.operations.push({
1992
+ type: "update",
1993
+ reference,
1994
+ data
1995
+ });
1996
+ return this;
1997
+ }
1998
+ delete(reference) {
1999
+ this.operations.push({ type: "delete", reference });
2000
+ return this;
2001
+ }
2002
+ /**
2003
+ * Ejecuta la transacción
2004
+ */
2005
+ async commit() {
2006
+ if (this.operations.length > 500) {
2007
+ throw createFirestoreError3("invalid-argument", "Transaction exceeds 500 operations");
2008
+ }
2009
+ if (this.operations.length > 0) {
2010
+ for (const [path, version] of this.readVersions.entries()) {
2011
+ if (getDocumentVersion(path) !== version) {
2012
+ throw createFirestoreError3("aborted", "Transaction read conflict");
2013
+ }
2014
+ }
2015
+ }
2016
+ const paths = this.operations.map((op) => op.reference.path);
2017
+ if (hasWriteConflict(this.id, paths)) {
2018
+ throw createFirestoreError3("aborted", "Transaction conflicted with another in-flight write");
2019
+ }
2020
+ acquireWriteLocks(this.id, paths);
2021
+ if (this.operations.length === 0) {
2022
+ if (this.transactionId) {
2023
+ await this.client.post(":rollback", {
2024
+ transaction: this.transactionId
2025
+ });
2026
+ }
2027
+ releaseWriteLocks(this.id);
2028
+ return;
2029
+ }
2030
+ const writes = this.operations.map((op) => {
2031
+ const baseName = `projects/${this.firestore.app.options.projectId}/databases/(default)/documents/${op.reference.path}`;
2032
+ switch (op.type) {
2033
+ case "set": {
2034
+ const fields = _chunkBXV7KTHBjs.toFirestoreFields.call(void 0, op.data);
2035
+ if (_optionalChain([op, 'access', _51 => _51.options, 'optionalAccess', _52 => _52.merge]) || _optionalChain([op, 'access', _53 => _53.options, 'optionalAccess', _54 => _54.mergeFields])) {
2036
+ const fieldPaths = op.options.mergeFields || Object.keys(op.data);
2037
+ return {
2038
+ update: { name: baseName, fields },
2039
+ updateMask: { fieldPaths },
2040
+ currentDocument: this.preconditions.get(op.reference.path)
2041
+ };
2042
+ }
2043
+ return {
2044
+ update: { name: baseName, fields },
2045
+ currentDocument: this.preconditions.get(op.reference.path)
2046
+ };
2047
+ }
2048
+ case "update": {
2049
+ const fields = _chunkBXV7KTHBjs.toFirestoreFields.call(void 0, op.data);
2050
+ const fieldPaths = Object.keys(op.data);
2051
+ return {
2052
+ update: { name: baseName, fields },
2053
+ updateMask: { fieldPaths },
2054
+ currentDocument: this.preconditions.get(op.reference.path)
2055
+ };
2056
+ }
2057
+ case "delete":
2058
+ return {
2059
+ delete: baseName,
2060
+ currentDocument: this.preconditions.get(op.reference.path)
2061
+ };
2062
+ }
2063
+ });
2064
+ try {
2065
+ await this.client.post(":commit", {
2066
+ transaction: this.transactionId,
2067
+ writes
2068
+ });
2069
+ bumpDocumentVersions(paths);
2070
+ } finally {
2071
+ releaseWriteLocks(this.id);
2072
+ }
2073
+ }
2074
+ /**
2075
+ * Rollback de la transacción
2076
+ */
2077
+ async rollback() {
2078
+ if (this.transactionId) {
2079
+ await this.client.post(":rollback", {
2080
+ transaction: this.transactionId
2081
+ });
2082
+ }
2083
+ releaseWriteLocks(this.id);
2084
+ }
2085
+ };
2086
+ async function runTransaction(firestore, updateFunction, options) {
2087
+ const maxAttempts = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _55 => _55.maxAttempts]), () => ( 5));
2088
+ const client = _chunk6J3LNKUQjs.getHttpClient.call(void 0, firestore);
2089
+ let lastError;
2090
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
2091
+ const transaction = new TransactionImpl(firestore, client);
2092
+ try {
2093
+ await transaction.begin();
2094
+ const result = await updateFunction(transaction);
2095
+ await transaction.commit();
2096
+ return result;
2097
+ } catch (error) {
2098
+ lastError = error;
2099
+ try {
2100
+ await transaction.rollback();
2101
+ } catch (e2) {
2102
+ }
2103
+ if (error.code === "aborted") {
2104
+ await new Promise(
2105
+ (resolve) => setTimeout(resolve, Math.pow(2, attempt) * 100)
2106
+ );
2107
+ continue;
2108
+ }
2109
+ throw error;
2110
+ }
2111
+ }
2112
+ throw lastError || new Error("Transaction failed after max attempts");
2113
+ }
2114
+ function createFirestoreError3(code, message) {
2115
+ const error = new Error(message);
2116
+ error.code = code;
2117
+ return error;
2118
+ }
2119
+ var writeLocks = /* @__PURE__ */ new Map();
2120
+ var documentVersions = /* @__PURE__ */ new Map();
2121
+ function createTransactionId() {
2122
+ return `tx_${Math.random().toString(36).slice(2)}_${Date.now()}`;
2123
+ }
2124
+ function hasWriteConflict(txId, paths) {
2125
+ return paths.some((path) => {
2126
+ const owner = writeLocks.get(path);
2127
+ return owner !== void 0 && owner !== txId;
2128
+ });
2129
+ }
2130
+ function getDocumentVersion(path) {
2131
+ return _nullishCoalesce(documentVersions.get(path), () => ( 0));
2132
+ }
2133
+ function bumpDocumentVersions(paths) {
2134
+ paths.forEach((path) => {
2135
+ const current = getDocumentVersion(path);
2136
+ documentVersions.set(path, current + 1);
2137
+ });
2138
+ }
2139
+ function acquireWriteLocks(txId, paths) {
2140
+ paths.forEach((path) => {
2141
+ writeLocks.set(path, txId);
2142
+ });
2143
+ }
2144
+ function releaseWriteLocks(txId) {
2145
+ for (const [path, owner] of writeLocks.entries()) {
2146
+ if (owner === txId) {
2147
+ writeLocks.delete(path);
2148
+ }
2149
+ }
2150
+ }
2151
+
2152
+ // src/firestore/advanced-query.ts
2153
+ function and(...constraints) {
2154
+ if (constraints.length === 0) {
2155
+ throw new Error("and() requires at least one constraint");
2156
+ }
2157
+ return {
2158
+ type: "and",
2159
+ constraints
2160
+ };
2161
+ }
2162
+ function or(...constraints) {
2163
+ if (constraints.length === 0) {
2164
+ throw new Error("or() requires at least one constraint");
2165
+ }
2166
+ return {
2167
+ type: "or",
2168
+ constraints
2169
+ };
2170
+ }
2171
+ var CollectionGroupImpl = class {
2172
+ constructor(firestore, collectionId, path, constraints = []) {
2173
+ this.firestore = firestore;
2174
+ this.collectionId = collectionId;
2175
+ this.path = path;
2176
+ this.constraints = constraints;
2177
+ this.type = "collectionGroup";
2178
+ }
2179
+ };
2180
+ function collectionGroup(firestore, collectionId) {
2181
+ if (!collectionId || typeof collectionId !== "string") {
2182
+ throw new Error("collectionGroup requires a valid collection ID");
2183
+ }
2184
+ if (collectionId.includes("/")) {
2185
+ throw new Error("collectionGroup ID cannot contain slashes");
2186
+ }
2187
+ return new CollectionGroupImpl(
2188
+ firestore,
2189
+ collectionId,
2190
+ collectionId,
2191
+ // path es solo el ID para collection groups
2192
+ []
2193
+ );
2194
+ }
2195
+ function isAndConstraint(constraint) {
2196
+ return constraint.type === "and";
2197
+ }
2198
+ function isOrConstraint(constraint) {
2199
+ return constraint.type === "or";
2200
+ }
2201
+ function isCompositeFilter(constraint) {
2202
+ return isAndConstraint(constraint) || isOrConstraint(constraint);
2203
+ }
2204
+ function isCollectionGroup(ref) {
2205
+ return ref.type === "collectionGroup";
2206
+ }
2207
+
2208
+ // src/firestore/aggregations.ts
2209
+ function count() {
2210
+ return {
2211
+ _aggregateType: "count"
2212
+ };
2213
+ }
2214
+ function sum(field) {
2215
+ return {
2216
+ _aggregateType: "sum",
2217
+ _field: field
2218
+ };
2219
+ }
2220
+ function average(field) {
2221
+ return {
2222
+ _aggregateType: "average",
2223
+ _field: field
2224
+ };
2225
+ }
2226
+ async function getCountFromServer(query2) {
2227
+ return getAggregateFromServer(query2, { count: count() });
2228
+ }
2229
+ async function getAggregateFromServer(query2, aggregateSpec) {
2230
+ const firestore = query2.firestore;
2231
+ const client = _chunk6J3LNKUQjs.getHttpClient.call(void 0, firestore);
2232
+ const structuredQuery = buildAggregateQuery(query2, aggregateSpec);
2233
+ const response = await client.post("/documents:runAggregationQuery", {
2234
+ structuredAggregationQuery: structuredQuery
2235
+ });
2236
+ let aggregateFields = {};
2237
+ if (Array.isArray(response)) {
2238
+ aggregateFields = _optionalChain([response, 'access', _56 => _56[0], 'optionalAccess', _57 => _57.result, 'optionalAccess', _58 => _58.aggregateFields]) || {};
2239
+ } else {
2240
+ aggregateFields = _optionalChain([response, 'optionalAccess', _59 => _59.result, 'optionalAccess', _60 => _60.aggregateFields]) || {};
2241
+ }
2242
+ const resultData = {};
2243
+ for (const [alias, spec] of Object.entries(aggregateSpec)) {
2244
+ const value = aggregateFields[alias];
2245
+ if (value) {
2246
+ if ("nullValue" in value) {
2247
+ resultData[alias] = null;
2248
+ } else if (value.integerValue !== void 0) {
2249
+ resultData[alias] = parseInt(value.integerValue, 10);
2250
+ } else if (value.doubleValue !== void 0) {
2251
+ resultData[alias] = value.doubleValue;
2252
+ } else {
2253
+ resultData[alias] = null;
2254
+ }
2255
+ } else {
2256
+ resultData[alias] = spec._aggregateType === "average" ? null : 0;
2257
+ }
2258
+ }
2259
+ return {
2260
+ data: () => resultData
2261
+ };
2262
+ }
2263
+ function buildAggregateQuery(query2, aggregateSpec) {
2264
+ const pathParts = query2.path.split("/");
2265
+ const collectionId = pathParts[pathParts.length - 1];
2266
+ const structuredQuery = {
2267
+ from: [{ collectionId }]
2268
+ };
2269
+ if ("constraints" in query2) {
2270
+ const constraints = query2.constraints || [];
2271
+ const wheres = constraints.filter((c) => c.type === "where");
2272
+ if (wheres.length > 0) {
2273
+ structuredQuery.where = buildWhereFromConstraints(wheres);
2274
+ }
2275
+ }
2276
+ const aggregations = Object.entries(aggregateSpec).map(([alias, spec]) => {
2277
+ const aggregation = { alias };
2278
+ switch (spec._aggregateType) {
2279
+ case "count":
2280
+ aggregation.count = {};
2281
+ break;
2282
+ case "sum":
2283
+ aggregation.sum = { field: { fieldPath: spec._field } };
2284
+ break;
2285
+ case "average":
2286
+ aggregation.average = { field: { fieldPath: spec._field } };
2287
+ break;
2288
+ }
2289
+ return aggregation;
2290
+ });
2291
+ return {
2292
+ structuredQuery,
2293
+ aggregations
2294
+ };
2295
+ }
2296
+ function buildWhereFromConstraints(constraints) {
2297
+ const filters = constraints.map((c) => {
2298
+ const constraint = c;
2299
+ return {
2300
+ fieldFilter: {
2301
+ field: { fieldPath: constraint.field },
2302
+ op: mapOperator(constraint.op),
2303
+ value: toFirestoreValue2(constraint.value)
2304
+ }
2305
+ };
2306
+ });
2307
+ if (filters.length === 1) {
2308
+ return filters[0];
2309
+ }
2310
+ return {
2311
+ compositeFilter: {
2312
+ op: "AND",
2313
+ filters
2314
+ }
2315
+ };
2316
+ }
2317
+ function mapOperator(op) {
2318
+ const opMap = {
2319
+ "<": "LESS_THAN",
2320
+ "<=": "LESS_THAN_OR_EQUAL",
2321
+ "==": "EQUAL",
2322
+ "!=": "NOT_EQUAL",
2323
+ ">": "GREATER_THAN",
2324
+ ">=": "GREATER_THAN_OR_EQUAL",
2325
+ "array-contains": "ARRAY_CONTAINS",
2326
+ "array-contains-any": "ARRAY_CONTAINS_ANY",
2327
+ "in": "IN",
2328
+ "not-in": "NOT_IN"
2329
+ };
2330
+ return opMap[op] || "EQUAL";
2331
+ }
2332
+ function toFirestoreValue2(value) {
2333
+ if (value === null) return { nullValue: null };
2334
+ if (typeof value === "boolean") return { booleanValue: value };
2335
+ if (typeof value === "number") {
2336
+ return Number.isInteger(value) ? { integerValue: String(value) } : { doubleValue: value };
2337
+ }
2338
+ if (typeof value === "string") return { stringValue: value };
2339
+ if (Array.isArray(value)) {
2340
+ return { arrayValue: { values: value.map(toFirestoreValue2) } };
2341
+ }
2342
+ if (typeof value === "object") {
2343
+ const fields = {};
2344
+ for (const [k, v] of Object.entries(value)) {
2345
+ fields[k] = toFirestoreValue2(v);
2346
+ }
2347
+ return { mapValue: { fields } };
2348
+ }
2349
+ return { stringValue: String(value) };
2350
+ }
2351
+
2352
+ // src/firestore/advanced-search.ts
2353
+ function whereSearch(field, value) {
2354
+ return {
2355
+ type: "where",
2356
+ field: `${field}_search`,
2357
+ op: "==",
2358
+ value
2359
+ };
2360
+ }
2361
+ function whereContains(field, value) {
2362
+ return {
2363
+ type: "where",
2364
+ field: `${field}_contains`,
2365
+ op: "==",
2366
+ value
2367
+ };
2368
+ }
2369
+ function whereFuzzy(field, value) {
2370
+ return {
2371
+ type: "where",
2372
+ field: `${field}_fuzzy`,
2373
+ op: "==",
2374
+ value
2375
+ // El threshold se maneja en el backend (default 0.3)
2376
+ };
2377
+ }
2378
+ function whereSimilar(field, value) {
2379
+ return {
2380
+ type: "where",
2381
+ field: `${field}_similar`,
2382
+ op: "==",
2383
+ value
2384
+ };
2385
+ }
2386
+ function orderByRelevance(direction = "desc") {
2387
+ return {
2388
+ type: "orderBy",
2389
+ field: "__relevance__",
2390
+ direction
2391
+ };
2392
+ }
2393
+ function offset(count2) {
2394
+ return {
2395
+ type: "offset",
2396
+ count: count2
2397
+ };
2398
+ }
2399
+ async function fastSearch(firestore, collectionPath, term, options = {}) {
2400
+ if (!collectionPath) {
2401
+ throw new Error("La colecci\xF3n es obligatoria.");
2402
+ }
2403
+ if (!term) {
2404
+ throw new Error("El t\xE9rmino es obligatorio.");
2405
+ }
2406
+ const params = new URLSearchParams({
2407
+ q: term,
2408
+ limit: String(_nullishCoalesce(options.limit, () => ( 50))),
2409
+ fuzzy: options.fuzzy ? "true" : "false"
2410
+ });
2411
+ if (options.field) {
2412
+ params.set("field", options.field);
2413
+ }
2414
+ const searchPath = `/search/${encodeURIComponent(collectionPath)}?${params.toString()}`;
2415
+ const client = _chunk6J3LNKUQjs.getHttpClient.call(void 0, firestore);
2416
+ return await client.get(searchPath);
2417
+ }
2418
+
2419
+
2420
+
2421
+
2422
+
2423
+
2424
+
2425
+
2426
+
2427
+
2428
+
2429
+
2430
+
2431
+
2432
+
2433
+
2434
+
2435
+
2436
+
2437
+
2438
+
2439
+
2440
+
2441
+
2442
+
2443
+
2444
+
2445
+
2446
+
2447
+
2448
+
2449
+
2450
+
2451
+
2452
+
2453
+
2454
+
2455
+
2456
+
2457
+
2458
+
2459
+
2460
+
2461
+
2462
+
2463
+
2464
+
2465
+
2466
+
2467
+
2468
+ exports.doc = doc; exports.collection = collection; exports.withConverter = withConverter; exports.refEqual = refEqual; exports.queryEqual = queryEqual; exports.snapshotEqual = snapshotEqual; exports.onSnapshotsInSync = onSnapshotsInSync; exports.getDoc = getDoc; exports.getDocFromCache = getDocFromCache; exports.setDoc = setDoc; exports.getDocFromServer = getDocFromServer; exports.updateDoc = updateDoc; exports.deleteDoc = deleteDoc; exports.addDoc = addDoc; exports.query = query; exports.where = where; exports.orderBy = orderBy; exports.limit = limit; exports.limitToLast = limitToLast; exports.startAt = startAt; exports.startAfter = startAfter; exports.endAt = endAt; exports.endBefore = endBefore; exports.getDocs = getDocs; exports.getDocsFromCache = getDocsFromCache; exports.getDocsFromServer = getDocsFromServer; exports.onSnapshot = onSnapshot; exports.writeBatch = writeBatch; exports.runTransaction = runTransaction; exports.and = and; exports.or = or; exports.collectionGroup = collectionGroup; exports.isAndConstraint = isAndConstraint; exports.isOrConstraint = isOrConstraint; exports.isCompositeFilter = isCompositeFilter; exports.isCollectionGroup = isCollectionGroup; exports.count = count; exports.sum = sum; exports.average = average; exports.getCountFromServer = getCountFromServer; exports.getAggregateFromServer = getAggregateFromServer; exports.whereSearch = whereSearch; exports.whereContains = whereContains; exports.whereFuzzy = whereFuzzy; exports.whereSimilar = whereSimilar; exports.orderByRelevance = orderByRelevance; exports.offset = offset; exports.fastSearch = fastSearch;
2469
+ //# sourceMappingURL=chunk-RZWTSZSJ.js.map