@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/LICENSE +21 -0
- package/README.md +118 -0
- package/dist/index.cjs +1096 -0
- package/dist/index.d.cts +605 -0
- package/dist/index.d.mts +605 -0
- package/dist/index.d.ts +605 -0
- package/dist/index.mjs +1060 -0
- package/package.json +85 -0
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 };
|