@relking-elements/vue-firebase 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.
package/dist/index.cjs ADDED
@@ -0,0 +1,1096 @@
1
+ 'use strict';
2
+
3
+ const app = require('firebase/app');
4
+ const vue = require('vue');
5
+ const database = require('firebase/database');
6
+ const firestore = require('firebase/firestore');
7
+ const auth = require('firebase/auth');
8
+ const appCheck = require('firebase/app-check');
9
+ const storage = require('firebase/storage');
10
+
11
+ const _FirebaseAppInjectionKey = Symbol("firebaseApp");
12
+ function useFirebaseApp(name) {
13
+ return vue.getCurrentInstance() && vue.inject(
14
+ _FirebaseAppInjectionKey,
15
+ // avoid the inject not found warning
16
+ null
17
+ ) || app.getApp(name);
18
+ }
19
+
20
+ const noop = () => {
21
+ };
22
+ const isClient = typeof window !== "undefined";
23
+ function walkGet(obj, path) {
24
+ return path.split(".").reduce((target, key) => target && target[key], obj);
25
+ }
26
+ function walkSet(obj, path, value) {
27
+ const keys = ("" + path).split(".");
28
+ const key = keys.pop();
29
+ const target = keys.reduce(
30
+ (target2, key2) => (
31
+ // @ts-expect-error: FIXME: maybe
32
+ target2 && target2[key2]
33
+ ),
34
+ obj
35
+ );
36
+ if (target == null)
37
+ return;
38
+ return Array.isArray(target) ? target.splice(Number(key), 1, value) : (
39
+ // @ts-expect-error: FIXME: maybe
40
+ target[key] = //
41
+ value
42
+ );
43
+ }
44
+ function isObject(o) {
45
+ return !!o && typeof o === "object";
46
+ }
47
+ const ObjectPrototype = Object.prototype;
48
+ function isPOJO(obj) {
49
+ return isObject(obj) && Object.getPrototypeOf(obj) === ObjectPrototype;
50
+ }
51
+ function isDocumentRef(o) {
52
+ return isObject(o) && o.type === "document";
53
+ }
54
+ function callOnceWithArg(fn, argFn) {
55
+ let called;
56
+ return () => {
57
+ if (!called) {
58
+ called = true;
59
+ return fn(argFn());
60
+ }
61
+ };
62
+ }
63
+ function checkWrittenTarget(data, fnName) {
64
+ if (Object.getOwnPropertyDescriptor(data, "data")?.get?.() === data) {
65
+ console.warn(`[VueFire] the passed "options.target" is already the returned value of "${fnName}". If you want to subscribe to a different data source, pass a reactive variable to "${fnName}" instead:
66
+ https://vuefire.vuejs.org/guide/realtime-data.html#declarative-realtime-data
67
+ This will FAIL in production.`);
68
+ return true;
69
+ }
70
+ return false;
71
+ }
72
+
73
+ function createRecordFromDatabaseSnapshot(snapshot) {
74
+ if (!snapshot.exists())
75
+ return null;
76
+ const value = snapshot.val();
77
+ return isObject(value) ? Object.defineProperty(value, "id", {
78
+ // allow destructuring without interfering without using the `id` property
79
+ value: snapshot.key
80
+ }) : {
81
+ // if the value is a primitive we can just return a regular object, it's easier to debug
82
+ // @ts-expect-error: $value doesn't exist
83
+ $value: value,
84
+ id: snapshot.key
85
+ };
86
+ }
87
+ function indexForKey(array, key) {
88
+ for (let i = 0; i < array.length; i++) {
89
+ if (array[i].id === key)
90
+ return i;
91
+ }
92
+ return -1;
93
+ }
94
+
95
+ const DEFAULT_OPTIONS$1 = {
96
+ reset: false,
97
+ serialize: createRecordFromDatabaseSnapshot,
98
+ wait: true
99
+ };
100
+ function bindAsObject(target, document, resolve, reject, extraOptions) {
101
+ const options = Object.assign({}, DEFAULT_OPTIONS$1, extraOptions);
102
+ let unsubscribe = noop;
103
+ function onValueCallback(snapshot) {
104
+ const value = options.serialize(snapshot);
105
+ target.value = value;
106
+ resolve(value);
107
+ }
108
+ if (options.once) {
109
+ database.get(document).then(onValueCallback).catch(reject);
110
+ } else {
111
+ unsubscribe = database.onValue(document, onValueCallback, reject);
112
+ }
113
+ return (reset) => {
114
+ unsubscribe();
115
+ if (reset) {
116
+ const value = typeof reset === "function" ? reset() : null;
117
+ target.value = value;
118
+ }
119
+ };
120
+ }
121
+ function bindAsArray(target, collection, resolve, reject, extraOptions) {
122
+ const options = Object.assign({}, DEFAULT_OPTIONS$1, extraOptions);
123
+ let arrayRef = options.wait ? [] : target;
124
+ if (!options.wait) {
125
+ target.value = [];
126
+ }
127
+ let removeChildAddedListener = noop;
128
+ let removeChildChangedListener = noop;
129
+ let removeChildRemovedListener = noop;
130
+ let removeChildMovedListener = noop;
131
+ let removeValueListener = noop;
132
+ if (options.once) {
133
+ database.get(collection).then((data) => {
134
+ const array = [];
135
+ data.forEach((snapshot) => {
136
+ array.push(options.serialize(snapshot));
137
+ });
138
+ resolve(target.value = array);
139
+ }).catch(reject);
140
+ } else {
141
+ removeChildAddedListener = database.onChildAdded(
142
+ collection,
143
+ (snapshot, prevKey) => {
144
+ const array = vue.toValue(arrayRef);
145
+ const index = prevKey ? indexForKey(array, prevKey) + 1 : 0;
146
+ array.splice(index, 0, options.serialize(snapshot));
147
+ },
148
+ reject
149
+ );
150
+ removeChildRemovedListener = database.onChildRemoved(
151
+ collection,
152
+ (snapshot) => {
153
+ const array = vue.toValue(arrayRef);
154
+ array.splice(indexForKey(array, snapshot.key), 1);
155
+ },
156
+ reject
157
+ );
158
+ removeChildChangedListener = database.onChildChanged(
159
+ collection,
160
+ (snapshot) => {
161
+ const array = vue.toValue(arrayRef);
162
+ array.splice(
163
+ indexForKey(array, snapshot.key),
164
+ 1,
165
+ // cannot be null because it exists
166
+ options.serialize(snapshot)
167
+ );
168
+ },
169
+ reject
170
+ );
171
+ removeChildMovedListener = database.onChildMoved(
172
+ collection,
173
+ (snapshot, prevKey) => {
174
+ const array = vue.toValue(arrayRef);
175
+ const index = indexForKey(array, snapshot.key);
176
+ const oldRecord = array.splice(index, 1)[0];
177
+ const newIndex = prevKey ? indexForKey(array, prevKey) + 1 : 0;
178
+ array.splice(newIndex, 0, oldRecord);
179
+ },
180
+ reject
181
+ );
182
+ removeValueListener = database.onValue(
183
+ collection,
184
+ () => {
185
+ const array = vue.toValue(arrayRef);
186
+ if (options.wait) {
187
+ target.value = array;
188
+ arrayRef = target;
189
+ }
190
+ resolve(array);
191
+ removeValueListener();
192
+ },
193
+ reject
194
+ );
195
+ }
196
+ return (reset) => {
197
+ removeValueListener();
198
+ removeChildAddedListener();
199
+ removeChildRemovedListener();
200
+ removeChildChangedListener();
201
+ removeChildMovedListener();
202
+ if (reset) {
203
+ const value = typeof reset === "function" ? reset() : [];
204
+ target.value = value;
205
+ }
206
+ };
207
+ }
208
+
209
+ function _useDatabaseRef(reference, localOptions = {}, isList = false) {
210
+ let unbind = noop;
211
+ const options = Object.assign({}, DEFAULT_OPTIONS$1, localOptions);
212
+ const data = options.target || vue.ref();
213
+ if (process.env.NODE_ENV !== "production") {
214
+ if (options.target && checkWrittenTarget(data, "useDatabaseObject()/useDatabaseList()")) {
215
+ return data;
216
+ }
217
+ }
218
+ let shouldStartAsPending = true;
219
+ const error = vue.ref();
220
+ const pending = vue.ref(false);
221
+ const promise = vue.shallowRef();
222
+ const hasCurrentScope = vue.getCurrentScope();
223
+ function bindDatabaseRef() {
224
+ const referenceValue = vue.toValue(reference);
225
+ const newPromise = new Promise((resolve, reject) => {
226
+ unbind(options.reset);
227
+ if (!referenceValue) {
228
+ unbind = noop;
229
+ return resolve(null);
230
+ }
231
+ pending.value = shouldStartAsPending;
232
+ shouldStartAsPending = true;
233
+ if (Array.isArray(data.value)) {
234
+ unbind = bindAsArray(
235
+ data,
236
+ referenceValue,
237
+ resolve,
238
+ reject,
239
+ options
240
+ );
241
+ } else {
242
+ unbind = bindAsObject(data, referenceValue, resolve, reject, options);
243
+ }
244
+ }).catch((reason) => {
245
+ if (promise.value === newPromise) {
246
+ error.value = reason;
247
+ }
248
+ throw reason;
249
+ }).finally(() => {
250
+ if (promise.value === newPromise) {
251
+ pending.value = false;
252
+ }
253
+ });
254
+ promise.value = newPromise;
255
+ }
256
+ let stopWatcher = noop;
257
+ if (vue.isRef(reference) || typeof reference === "function") {
258
+ stopWatcher = vue.watch(reference, bindDatabaseRef);
259
+ }
260
+ bindDatabaseRef();
261
+ if (hasCurrentScope) {
262
+ vue.onScopeDispose(stop);
263
+ }
264
+ function stop(reset = options.reset) {
265
+ stopWatcher();
266
+ unbind(reset);
267
+ }
268
+ return Object.defineProperties(data, {
269
+ data: { get: () => data },
270
+ error: { get: () => error },
271
+ pending: { get: () => pending },
272
+ promise: { get: () => promise },
273
+ stop: { get: () => stop }
274
+ });
275
+ }
276
+
277
+ function useDatabaseList(reference, options) {
278
+ const data = vue.ref([]);
279
+ return _useDatabaseRef(
280
+ reference,
281
+ {
282
+ target: data,
283
+ ...options
284
+ },
285
+ true
286
+ );
287
+ }
288
+ const useList = useDatabaseList;
289
+ function useDatabaseObject(reference, options) {
290
+ const data = vue.ref();
291
+ return _useDatabaseRef(reference, {
292
+ target: data,
293
+ ...options
294
+ });
295
+ }
296
+ const useObject = useDatabaseObject;
297
+ function useDatabase(name, databaseUrl) {
298
+ const app = useFirebaseApp(name);
299
+ return databaseUrl ? database.getDatabase(app, databaseUrl) : database.getDatabase(app);
300
+ }
301
+
302
+ const firestoreDefaultConverter = {
303
+ toFirestore(data) {
304
+ return data;
305
+ },
306
+ fromFirestore(snapshot, options) {
307
+ return snapshot.exists() ? Object.defineProperties(snapshot.data(options), {
308
+ id: { value: snapshot.id }
309
+ // TODO: check if worth adding or should be through an option
310
+ // It could also be an example in the docs about converters
311
+ // $meta: {
312
+ // value: snapshot.metadata,
313
+ // },
314
+ // $ref: { get: () => snapshot.ref },
315
+ }) : null;
316
+ }
317
+ };
318
+ function extractRefs(doc, oldDoc, subs, options) {
319
+ if (!isPOJO(doc))
320
+ return [doc, {}];
321
+ const dataAndRefs = [
322
+ {},
323
+ {}
324
+ ];
325
+ const subsByPath = Object.keys(subs).reduce(
326
+ (resultSubs, subKey) => {
327
+ const sub = subs[subKey];
328
+ resultSubs[sub.path] = sub.data();
329
+ return resultSubs;
330
+ },
331
+ {}
332
+ );
333
+ function recursiveExtract(doc2, oldDoc2, path, result) {
334
+ oldDoc2 = oldDoc2 || {};
335
+ const [data, refs] = result;
336
+ Object.getOwnPropertyNames(doc2).forEach((propertyName) => {
337
+ const descriptor = Object.getOwnPropertyDescriptor(doc2, propertyName);
338
+ if (descriptor && !descriptor.enumerable) {
339
+ Object.defineProperty(data, propertyName, descriptor);
340
+ }
341
+ });
342
+ for (const key in doc2) {
343
+ const ref = doc2[key];
344
+ if (
345
+ // primitives
346
+ ref == null || // TODO: check and remove
347
+ // Firestore < 4.13
348
+ ref instanceof Date || ref instanceof firestore.Timestamp || ref instanceof firestore.GeoPoint
349
+ ) {
350
+ data[key] = ref;
351
+ } else if (isDocumentRef(ref)) {
352
+ const refSubKey = path + key;
353
+ data[key] = // if the ref was already bound, keep the same object
354
+ // otherwise set the path as a string so it can be bound later
355
+ // https://github.com/vuejs/vuefire/issues/831
356
+ // https://github.com/vuejs/vuefire/pull/1223
357
+ refSubKey in subs ? oldDoc2[key] : ref.path;
358
+ refs[refSubKey] = ref.converter ? ref : ref.withConverter(
359
+ options.converter
360
+ );
361
+ } else if (Array.isArray(ref)) {
362
+ data[key] = Array(ref.length);
363
+ for (let i = 0; i < ref.length; i++) {
364
+ const newRef = ref[i];
365
+ if (newRef && newRef.path in subsByPath)
366
+ data[key][i] = subsByPath[newRef.path];
367
+ }
368
+ recursiveExtract(ref, oldDoc2[key] || data[key], path + key + ".", [
369
+ data[key],
370
+ refs
371
+ ]);
372
+ } else if (isObject(ref)) {
373
+ data[key] = {};
374
+ recursiveExtract(ref, oldDoc2[key], path + key + ".", [data[key], refs]);
375
+ } else {
376
+ data[key] = ref;
377
+ }
378
+ }
379
+ }
380
+ recursiveExtract(doc, oldDoc, "", dataAndRefs);
381
+ return dataAndRefs;
382
+ }
383
+
384
+ const DEFAULT_OPTIONS = {
385
+ reset: false,
386
+ wait: true,
387
+ maxRefDepth: 2,
388
+ converter: firestoreDefaultConverter,
389
+ snapshotOptions: { serverTimestamps: "estimate" }
390
+ };
391
+ function unsubscribeAll(subs) {
392
+ for (const sub in subs) {
393
+ subs[sub].unsub();
394
+ }
395
+ }
396
+ function updateDataFromDocumentSnapshot(options, target, path, snapshot, subs, ops, depth, resolve, reject) {
397
+ const [data, refs] = extractRefs(
398
+ // Pass snapshot options
399
+ // @ts-expect-error: FIXME: use better types
400
+ snapshot.data(options.snapshotOptions),
401
+ walkGet(target, path),
402
+ subs,
403
+ options
404
+ );
405
+ ops.set(target, path, data);
406
+ subscribeToRefs(
407
+ options,
408
+ target,
409
+ path,
410
+ subs,
411
+ refs,
412
+ ops,
413
+ depth,
414
+ resolve,
415
+ reject
416
+ );
417
+ }
418
+ function subscribeToDocument({
419
+ ref: ref2,
420
+ target,
421
+ path,
422
+ depth,
423
+ resolve,
424
+ reject,
425
+ ops
426
+ }, options) {
427
+ const subs = /* @__PURE__ */ Object.create(null);
428
+ let unbind = noop;
429
+ if (options.once) {
430
+ firestore.getDoc(ref2).then((snapshot) => {
431
+ if (snapshot.exists()) {
432
+ updateDataFromDocumentSnapshot(
433
+ options,
434
+ target,
435
+ path,
436
+ snapshot,
437
+ subs,
438
+ ops,
439
+ depth,
440
+ resolve,
441
+ reject
442
+ );
443
+ } else {
444
+ ops.set(target, path, null);
445
+ resolve();
446
+ }
447
+ }).catch(reject);
448
+ } else {
449
+ unbind = firestore.onSnapshot(
450
+ ref2,
451
+ (snapshot) => {
452
+ if (snapshot.exists()) {
453
+ updateDataFromDocumentSnapshot(
454
+ options,
455
+ target,
456
+ path,
457
+ snapshot,
458
+ subs,
459
+ ops,
460
+ depth,
461
+ resolve,
462
+ reject
463
+ );
464
+ } else {
465
+ ops.set(target, path, null);
466
+ resolve();
467
+ }
468
+ },
469
+ reject
470
+ );
471
+ }
472
+ return () => {
473
+ unbind();
474
+ unsubscribeAll(subs);
475
+ };
476
+ }
477
+ function subscribeToRefs(options, target, path, subs, refs, ops, depth, resolve, reject) {
478
+ const refKeys = Object.keys(refs);
479
+ const missingKeys = Object.keys(subs).filter(
480
+ (refKey) => refKeys.indexOf(refKey) < 0
481
+ );
482
+ missingKeys.forEach((refKey) => {
483
+ subs[refKey].unsub();
484
+ delete subs[refKey];
485
+ });
486
+ if (!refKeys.length || ++depth > options.maxRefDepth)
487
+ return resolve(path);
488
+ let resolvedCount = 0;
489
+ const totalToResolve = refKeys.length;
490
+ const validResolves = /* @__PURE__ */ Object.create(null);
491
+ function deepResolve(key) {
492
+ if (key in validResolves) {
493
+ if (++resolvedCount >= totalToResolve)
494
+ resolve(path);
495
+ }
496
+ }
497
+ refKeys.forEach((refKey) => {
498
+ const sub = subs[refKey];
499
+ const ref2 = refs[refKey];
500
+ const docPath = `${path}.${refKey}`;
501
+ validResolves[docPath] = true;
502
+ if (sub) {
503
+ if (sub.path !== ref2.path)
504
+ sub.unsub();
505
+ else
506
+ return;
507
+ }
508
+ subs[refKey] = {
509
+ data: () => walkGet(target, docPath),
510
+ unsub: subscribeToDocument(
511
+ {
512
+ ref: ref2,
513
+ target,
514
+ path: docPath,
515
+ depth,
516
+ ops,
517
+ resolve: deepResolve.bind(null, docPath),
518
+ reject
519
+ },
520
+ options
521
+ ),
522
+ path: ref2.path
523
+ };
524
+ });
525
+ }
526
+ function bindCollection(target, collection, ops, resolve, reject, extraOptions) {
527
+ const options = Object.assign({}, DEFAULT_OPTIONS, extraOptions);
528
+ const { snapshotListenOptions, snapshotOptions, wait, once } = options;
529
+ const key = "value";
530
+ let arrayRef = vue.ref(wait ? [] : target.value);
531
+ if (!wait)
532
+ ops.set(target, key, []);
533
+ const originalResolve = resolve;
534
+ let isResolved;
535
+ let stopOnSnapshot = noop;
536
+ const arraySubs = [];
537
+ const change = {
538
+ added: ({ newIndex, doc }) => {
539
+ arraySubs.splice(newIndex, 0, /* @__PURE__ */ Object.create(null));
540
+ const subs = arraySubs[newIndex];
541
+ const [data, refs] = extractRefs(
542
+ // @ts-expect-error: FIXME: wrong cast, needs better types
543
+ doc.data(snapshotOptions),
544
+ void 0,
545
+ subs,
546
+ options
547
+ );
548
+ ops.add(vue.toValue(arrayRef), newIndex, data);
549
+ subscribeToRefs(
550
+ options,
551
+ arrayRef,
552
+ `${key}.${newIndex}`,
553
+ subs,
554
+ refs,
555
+ ops,
556
+ 0,
557
+ resolve.bind(null, doc),
558
+ reject
559
+ );
560
+ },
561
+ modified: ({ oldIndex, newIndex, doc }) => {
562
+ const array = vue.toValue(arrayRef);
563
+ const subs = arraySubs[oldIndex];
564
+ const oldData = array[oldIndex];
565
+ const [data, refs] = extractRefs(
566
+ // @ts-expect-error: FIXME: Better types
567
+ doc.data(snapshotOptions),
568
+ oldData,
569
+ subs,
570
+ options
571
+ );
572
+ arraySubs.splice(newIndex, 0, subs);
573
+ ops.remove(array, oldIndex);
574
+ ops.add(array, newIndex, data);
575
+ subscribeToRefs(
576
+ options,
577
+ arrayRef,
578
+ `${key}.${newIndex}`,
579
+ subs,
580
+ refs,
581
+ ops,
582
+ 0,
583
+ resolve,
584
+ reject
585
+ );
586
+ },
587
+ removed: ({ oldIndex }) => {
588
+ const array = vue.toValue(arrayRef);
589
+ ops.remove(array, oldIndex);
590
+ unsubscribeAll(arraySubs.splice(oldIndex, 1)[0]);
591
+ }
592
+ };
593
+ function onSnapshotCallback(snapshot) {
594
+ const docChanges = snapshot.docChanges(snapshotListenOptions);
595
+ if (!isResolved && docChanges.length) {
596
+ isResolved = true;
597
+ let count = 0;
598
+ const expectedItems = docChanges.length;
599
+ const validDocs = /* @__PURE__ */ Object.create(null);
600
+ for (let i = 0; i < expectedItems; i++) {
601
+ validDocs[docChanges[i].doc.id] = true;
602
+ }
603
+ resolve = (data) => {
604
+ if (data && data.id in validDocs) {
605
+ if (++count >= expectedItems) {
606
+ if (wait) {
607
+ ops.set(target, key, vue.toValue(arrayRef));
608
+ arrayRef = target;
609
+ }
610
+ originalResolve(vue.toValue(arrayRef));
611
+ resolve = noop;
612
+ }
613
+ }
614
+ };
615
+ }
616
+ docChanges.forEach((c) => {
617
+ change[c.type](c);
618
+ });
619
+ if (!docChanges.length) {
620
+ if (wait) {
621
+ ops.set(target, key, vue.toValue(arrayRef));
622
+ arrayRef = target;
623
+ }
624
+ resolve(vue.toValue(arrayRef));
625
+ }
626
+ }
627
+ if (once) {
628
+ firestore.getDocs(collection).then(onSnapshotCallback).catch(reject);
629
+ } else {
630
+ stopOnSnapshot = firestore.onSnapshot(collection, onSnapshotCallback, reject);
631
+ }
632
+ return (reset) => {
633
+ stopOnSnapshot();
634
+ if (reset) {
635
+ const value = typeof reset === "function" ? reset() : [];
636
+ ops.set(target, key, value);
637
+ }
638
+ arraySubs.forEach(unsubscribeAll);
639
+ };
640
+ }
641
+ function bindDocument(target, document, ops, resolve, reject, extraOptions) {
642
+ const options = Object.assign({}, DEFAULT_OPTIONS, extraOptions);
643
+ const key = "value";
644
+ const subs = /* @__PURE__ */ Object.create(null);
645
+ resolve = callOnceWithArg(resolve, () => walkGet(target, key));
646
+ let stopOnSnapshot = noop;
647
+ function onSnapshotCallback(snapshot) {
648
+ if (snapshot.exists()) {
649
+ updateDataFromDocumentSnapshot(
650
+ options,
651
+ target,
652
+ key,
653
+ snapshot,
654
+ subs,
655
+ ops,
656
+ 0,
657
+ resolve,
658
+ reject
659
+ );
660
+ } else {
661
+ ops.set(target, key, null);
662
+ resolve(null);
663
+ }
664
+ }
665
+ if (options.once) {
666
+ firestore.getDoc(document).then(onSnapshotCallback).catch(reject);
667
+ } else {
668
+ stopOnSnapshot = firestore.onSnapshot(document, onSnapshotCallback, reject);
669
+ }
670
+ return (reset) => {
671
+ stopOnSnapshot();
672
+ if (reset) {
673
+ const value = typeof reset === "function" ? reset() : null;
674
+ ops.set(target, key, value);
675
+ }
676
+ unsubscribeAll(subs);
677
+ };
678
+ }
679
+
680
+ function _useFirestoreRef(docOrCollectionRef, localOptions) {
681
+ let unbind = noop;
682
+ const options = Object.assign({}, DEFAULT_OPTIONS, localOptions);
683
+ const data = options.target || vue.ref();
684
+ if (process.env.NODE_ENV !== "production") {
685
+ if (options.target && checkWrittenTarget(data, "useDocument()/useCollection()")) {
686
+ return data;
687
+ }
688
+ }
689
+ let shouldStartAsPending = true;
690
+ const pending = vue.ref(false);
691
+ const error = vue.ref();
692
+ const promise = vue.shallowRef();
693
+ const hasCurrentScope = vue.getCurrentScope();
694
+ function bindFirestoreRef() {
695
+ let docRefValue = vue.toValue(docOrCollectionRef);
696
+ const newPromise = new Promise((resolve, reject) => {
697
+ unbind(options.reset);
698
+ if (!docRefValue) {
699
+ unbind = noop;
700
+ return resolve(null);
701
+ }
702
+ pending.value = shouldStartAsPending;
703
+ shouldStartAsPending = true;
704
+ if (!docRefValue.converter) {
705
+ docRefValue = docRefValue.withConverter(
706
+ // @ts-expect-error: seems like a ts error
707
+ options.converter
708
+ );
709
+ }
710
+ unbind = (isDocumentRef(docRefValue) ? bindDocument : bindCollection)(
711
+ // @ts-expect-error: cannot type with the ternary
712
+ data,
713
+ docRefValue,
714
+ ops,
715
+ resolve,
716
+ reject,
717
+ options
718
+ );
719
+ }).catch((reason) => {
720
+ if (promise.value === newPromise) {
721
+ error.value = reason;
722
+ }
723
+ return Promise.reject(reason);
724
+ }).finally(() => {
725
+ if (promise.value === newPromise) {
726
+ pending.value = false;
727
+ }
728
+ });
729
+ promise.value = newPromise;
730
+ }
731
+ let stopWatcher = noop;
732
+ if (vue.isRef(docOrCollectionRef) || typeof docOrCollectionRef === "function") {
733
+ stopWatcher = vue.watch(docOrCollectionRef, bindFirestoreRef);
734
+ }
735
+ bindFirestoreRef();
736
+ if (hasCurrentScope) {
737
+ vue.onScopeDispose(stop);
738
+ }
739
+ function stop(reset = options.reset) {
740
+ stopWatcher();
741
+ unbind(reset);
742
+ }
743
+ return Object.defineProperties(data, {
744
+ error: { get: () => error },
745
+ data: { get: () => data },
746
+ pending: { get: () => pending },
747
+ promise: { get: () => promise },
748
+ stop: { get: () => stop }
749
+ });
750
+ }
751
+ const ops = {
752
+ set: (target, key, value) => walkSet(target, key, value),
753
+ add: (array, index, data) => array.splice(index, 0, data),
754
+ remove: (array, index) => array.splice(index, 1)
755
+ };
756
+
757
+ function useCollection(collectionRef, options) {
758
+ return _useFirestoreRef(collectionRef, {
759
+ target: vue.ref([]),
760
+ ...options
761
+ });
762
+ }
763
+ function useDocument(documentRef, options) {
764
+ return _useFirestoreRef(documentRef, options);
765
+ }
766
+ function useFirestore(name, databaseId) {
767
+ const app = useFirebaseApp(name);
768
+ return databaseId ? firestore.getFirestore(app, databaseId) : firestore.getFirestore(app);
769
+ }
770
+
771
+ const scopeMap = /* @__PURE__ */ new WeakMap();
772
+ function getGlobalScope(firebaseApp, app) {
773
+ if (!scopeMap.has(firebaseApp)) {
774
+ const scope = vue.effectScope(true);
775
+ scopeMap.set(firebaseApp, scope);
776
+ const { unmount } = app;
777
+ app.unmount = () => {
778
+ unmount.call(app);
779
+ scope.stop();
780
+ scopeMap.delete(firebaseApp);
781
+ };
782
+ }
783
+ return scopeMap.get(firebaseApp);
784
+ }
785
+
786
+ const authUserMap = /* @__PURE__ */ new WeakMap();
787
+ function useCurrentUser(name) {
788
+ if (process.env.NODE_ENV !== "production" && !authUserMap.has(useFirebaseApp(name))) {
789
+ throw new Error(
790
+ `[VueFire] useCurrentUser() called before the VueFireAuth module was added to the VueFire plugin. This will fail in production.`
791
+ );
792
+ }
793
+ return authUserMap.get(useFirebaseApp(name));
794
+ }
795
+ function useIsCurrentUserLoaded(name) {
796
+ const currentUser = useCurrentUser(name);
797
+ return vue.computed(() => currentUser.value !== void 0);
798
+ }
799
+ function updateCurrentUserProfile(profile) {
800
+ return getCurrentUser().then((user) => {
801
+ if (user) {
802
+ return auth.updateProfile(user, profile).then(() => user.reload());
803
+ }
804
+ });
805
+ }
806
+ const initialUserMap = /* @__PURE__ */ new WeakMap();
807
+ function _getCurrentUserState(name) {
808
+ const firebaseApp = useFirebaseApp(name);
809
+ if (!initialUserMap.has(firebaseApp)) {
810
+ let resolve;
811
+ const promise = new Promise((_resolve) => {
812
+ resolve = _resolve;
813
+ });
814
+ const userState = [
815
+ promise,
816
+ (user) => {
817
+ initialUserMap.set(firebaseApp, user);
818
+ resolve(user.value);
819
+ }
820
+ ];
821
+ initialUserMap.set(firebaseApp, userState);
822
+ }
823
+ return initialUserMap.get(firebaseApp);
824
+ }
825
+ function getCurrentUser(name) {
826
+ const userOrPromise = _getCurrentUserState(name);
827
+ return Array.isArray(userOrPromise) ? userOrPromise[0] : Promise.resolve(userOrPromise.value);
828
+ }
829
+ function setupOnAuthStateChanged(user, auth$1) {
830
+ auth.onIdTokenChanged(auth$1, (userData) => {
831
+ const userOrPromise = _getCurrentUserState();
832
+ user.value = userData;
833
+ if (Array.isArray(userOrPromise)) {
834
+ userOrPromise[1](user);
835
+ }
836
+ });
837
+ }
838
+
839
+ function VueFireAuth() {
840
+ return VueFireAuthWithDependencies({
841
+ dependencies: {
842
+ popupRedirectResolver: auth.browserPopupRedirectResolver,
843
+ persistence: [
844
+ auth.indexedDBLocalPersistence,
845
+ auth.browserLocalPersistence,
846
+ auth.browserSessionPersistence
847
+ ]
848
+ }
849
+ });
850
+ }
851
+ const _VueFireAuthKey = Symbol("VueFireAuth");
852
+ function VueFireAuthOptionsFromAuth({
853
+ auth
854
+ }) {
855
+ return (firebaseApp, app) => {
856
+ const [user, _auth] = _VueFireAuthInit(
857
+ firebaseApp,
858
+ app,
859
+ void 0,
860
+ auth
861
+ );
862
+ setupOnAuthStateChanged(user, _auth);
863
+ };
864
+ }
865
+ function VueFireAuthWithDependencies({
866
+ dependencies
867
+ }) {
868
+ return (firebaseApp, app) => {
869
+ const [user, auth] = _VueFireAuthInit(
870
+ firebaseApp,
871
+ app,
872
+ dependencies
873
+ );
874
+ setupOnAuthStateChanged(user, auth);
875
+ };
876
+ }
877
+ function _VueFireAuthInit(firebaseApp, app, dependencies, auth$1 = auth.initializeAuth(firebaseApp, dependencies)) {
878
+ const user = getGlobalScope(firebaseApp, app).run(
879
+ () => vue.ref(void 0)
880
+ );
881
+ authUserMap.set(firebaseApp, user);
882
+ app.provide(_VueFireAuthKey, auth$1);
883
+ return [user, auth$1];
884
+ }
885
+ function useFirebaseAuth(name) {
886
+ if (process.env.NODE_ENV !== "production" && name != null) {
887
+ console.warn(
888
+ `[VueFire] useFirebaseAuth() no longer accepts a name parameter to enable tree shaking. If you have multiple applications, you must use "getAuth(firebaseApp)" or "getAuth(useFirebaseApp(name))" instead.`
889
+ );
890
+ }
891
+ return isClient ? vue.inject(_VueFireAuthKey) : null;
892
+ }
893
+
894
+ const AppCheckTokenInjectSymbol = Symbol("app-check-token");
895
+ function useAppCheckToken() {
896
+ return vue.inject(AppCheckTokenInjectSymbol);
897
+ }
898
+ function VueFireAppCheck(options) {
899
+ return (firebaseApp, app) => {
900
+ if (!isClient)
901
+ return;
902
+ const token = getGlobalScope(firebaseApp, app).run(() => vue.ref());
903
+ app.provide(AppCheckTokenInjectSymbol, token);
904
+ if (options.debug) {
905
+ self.FIREBASE_APPCHECK_DEBUG_TOKEN = options.debug;
906
+ }
907
+ const appCheck$1 = appCheck.initializeAppCheck(firebaseApp, options);
908
+ appCheck.onTokenChanged(appCheck$1, (newToken) => {
909
+ token.value = newToken.token;
910
+ });
911
+ AppCheckMap.set(firebaseApp, appCheck$1);
912
+ };
913
+ }
914
+ const AppCheckMap = /* @__PURE__ */ new WeakMap();
915
+ function useAppCheck(name) {
916
+ return AppCheckMap.get(useFirebaseApp(name));
917
+ }
918
+
919
+ function useFirebaseStorage(name) {
920
+ return storage.getStorage(useFirebaseApp(name));
921
+ }
922
+ function useStorageFileUrl(storageRef) {
923
+ const url = vue.ref();
924
+ const promise = vue.shallowRef(Promise.resolve(null));
925
+ function refresh() {
926
+ const storageSource = vue.toValue(storageRef);
927
+ if (storageSource) {
928
+ promise.value = storage.getDownloadURL(storageSource).then((downloadUrl) => url.value = downloadUrl).catch(() => null);
929
+ } else {
930
+ promise.value = Promise.resolve(url.value = null);
931
+ }
932
+ return promise.value;
933
+ }
934
+ refresh();
935
+ if (vue.isRef(storageRef) || typeof storageRef === "function") {
936
+ vue.watch(storageRef, refresh);
937
+ }
938
+ return { url, refresh, promise };
939
+ }
940
+ function useStorageFileMetadata(storageRef) {
941
+ const metadata = vue.shallowRef();
942
+ const promise = vue.shallowRef(
943
+ Promise.resolve(null)
944
+ );
945
+ function refresh() {
946
+ const storageSource = vue.toValue(storageRef);
947
+ if (storageSource) {
948
+ promise.value = storage.getMetadata(storageSource).then((data) => metadata.value = data).catch(() => null);
949
+ } else {
950
+ promise.value = Promise.resolve(metadata.value = null);
951
+ }
952
+ return promise.value;
953
+ }
954
+ function update(newMetadata) {
955
+ const storageSource = vue.toValue(storageRef);
956
+ if (storageSource) {
957
+ promise.value = storage.updateMetadata(storageSource, newMetadata).then(
958
+ (newData) => {
959
+ return metadata.value = newData;
960
+ }
961
+ );
962
+ } else if (process.env.NODE_ENV !== "production") {
963
+ console.warn('[VueFire]: "update()" called with no storage source.');
964
+ }
965
+ return promise.value;
966
+ }
967
+ refresh();
968
+ if (vue.isRef(storageRef)) {
969
+ vue.watch(storageRef, refresh);
970
+ }
971
+ return { metadata, update, refresh, promise };
972
+ }
973
+ function useStorageFile(storageRef) {
974
+ const { url, refresh: refreshUrl } = useStorageFileUrl(storageRef);
975
+ const {
976
+ metadata,
977
+ update: updateMetadata2,
978
+ refresh: refreshMetadata
979
+ } = useStorageFileMetadata(storageRef);
980
+ const uploadTask = vue.shallowRef();
981
+ const snapshot = vue.shallowRef();
982
+ const uploadError = vue.shallowRef();
983
+ const uploadProgress = vue.computed(() => {
984
+ const snap = vue.toValue(snapshot);
985
+ return snap ? snap.bytesTransferred / snap.totalBytes : null;
986
+ });
987
+ let unsub = noop;
988
+ function upload(newData, newMetadata) {
989
+ const storageSource = vue.toValue(storageRef);
990
+ const currentTask = vue.toValue(uploadTask);
991
+ if (currentTask) {
992
+ currentTask.cancel();
993
+ }
994
+ uploadError.value = null;
995
+ snapshot.value = null;
996
+ uploadTask.value = null;
997
+ url.value = null;
998
+ metadata.value = null;
999
+ unsub();
1000
+ if (storageSource) {
1001
+ const newTask = storage.uploadBytesResumable(storageSource, newData, newMetadata);
1002
+ uploadTask.value = newTask;
1003
+ snapshot.value = newTask.snapshot;
1004
+ unsub = newTask.on("state_changed", (newSnapshot) => {
1005
+ snapshot.value = newSnapshot;
1006
+ });
1007
+ return newTask.then((finalSnapshot) => {
1008
+ metadata.value = finalSnapshot.metadata;
1009
+ refreshUrl();
1010
+ }).catch((err) => {
1011
+ uploadError.value = err;
1012
+ return Promise.reject(err);
1013
+ }).finally(() => {
1014
+ unsub();
1015
+ uploadTask.value = null;
1016
+ });
1017
+ }
1018
+ }
1019
+ function refresh() {
1020
+ return Promise.all([refreshUrl(), refreshMetadata()]);
1021
+ }
1022
+ if (vue.isRef(storageRef) || typeof storageRef === "function") {
1023
+ vue.watch(storageRef, (storageSource) => {
1024
+ if (!storageSource) {
1025
+ if (uploadTask.value) {
1026
+ unsub();
1027
+ uploadTask.value.cancel();
1028
+ }
1029
+ uploadTask.value = null;
1030
+ snapshot.value = null;
1031
+ }
1032
+ refresh();
1033
+ });
1034
+ }
1035
+ if (vue.getCurrentScope()) {
1036
+ vue.onScopeDispose(unsub);
1037
+ }
1038
+ return {
1039
+ url,
1040
+ metadata,
1041
+ snapshot,
1042
+ uploadTask,
1043
+ uploadError,
1044
+ uploadProgress,
1045
+ upload,
1046
+ updateMetadata: updateMetadata2,
1047
+ refresh
1048
+ };
1049
+ }
1050
+ const useStorage = useFirebaseStorage;
1051
+ const useStorageUrl = useStorageFileUrl;
1052
+ const useStorageMetadata = useStorageFileMetadata;
1053
+ const useStorageObject = useStorageFile;
1054
+
1055
+ function VueFire(app, { firebaseApp, modules = [] }) {
1056
+ app.provide(_FirebaseAppInjectionKey, firebaseApp);
1057
+ for (const firebaseModule of modules) {
1058
+ firebaseModule(firebaseApp, app);
1059
+ }
1060
+ }
1061
+
1062
+ exports.VueFire = VueFire;
1063
+ exports.VueFireAppCheck = VueFireAppCheck;
1064
+ exports.VueFireAuth = VueFireAuth;
1065
+ exports.VueFireAuthOptionsFromAuth = VueFireAuthOptionsFromAuth;
1066
+ exports.VueFireAuthWithDependencies = VueFireAuthWithDependencies;
1067
+ exports._VueFireAuthInit = _VueFireAuthInit;
1068
+ exports._VueFireAuthKey = _VueFireAuthKey;
1069
+ exports.databaseDefaultSerializer = createRecordFromDatabaseSnapshot;
1070
+ exports.firestoreDefaultConverter = firestoreDefaultConverter;
1071
+ exports.getCurrentUser = getCurrentUser;
1072
+ exports.globalDatabaseOptions = DEFAULT_OPTIONS$1;
1073
+ exports.globalFirestoreOptions = DEFAULT_OPTIONS;
1074
+ exports.updateCurrentUserProfile = updateCurrentUserProfile;
1075
+ exports.useAppCheck = useAppCheck;
1076
+ exports.useAppCheckToken = useAppCheckToken;
1077
+ exports.useCollection = useCollection;
1078
+ exports.useCurrentUser = useCurrentUser;
1079
+ exports.useDatabase = useDatabase;
1080
+ exports.useDatabaseList = useDatabaseList;
1081
+ exports.useDatabaseObject = useDatabaseObject;
1082
+ exports.useDocument = useDocument;
1083
+ exports.useFirebaseApp = useFirebaseApp;
1084
+ exports.useFirebaseAuth = useFirebaseAuth;
1085
+ exports.useFirebaseStorage = useFirebaseStorage;
1086
+ exports.useFirestore = useFirestore;
1087
+ exports.useIsCurrentUserLoaded = useIsCurrentUserLoaded;
1088
+ exports.useList = useList;
1089
+ exports.useObject = useObject;
1090
+ exports.useStorage = useStorage;
1091
+ exports.useStorageFile = useStorageFile;
1092
+ exports.useStorageFileMetadata = useStorageFileMetadata;
1093
+ exports.useStorageFileUrl = useStorageFileUrl;
1094
+ exports.useStorageMetadata = useStorageMetadata;
1095
+ exports.useStorageObject = useStorageObject;
1096
+ exports.useStorageUrl = useStorageUrl;