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