UNPKG

unfire

Version:

⚡️ Utilities for Firebase 🔥 built with Composition API, Typescript and ❤️

357 lines (352 loc) 13 kB
var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/vue/index.ts var vue_exports = {}; __export(vue_exports, { createPathRef: () => createPathRef, deleteDoc: () => deleteDoc, toReactiveQueryOption: () => toReactiveQueryOption, upsertDoc: () => upsertDoc, useCollection: () => useCollection, useDoc: () => useDoc, useDocBiDirection: () => useDocBiDirection, whereFilterOps: () => whereFilterOps }); module.exports = __toCommonJS(vue_exports); // src/vue/vue-composables.ts var import_vue = require("vue"); var import_core = require("@vueuse/core"); // src/firebase/firestore.ts var import_unfire_init = require("@unfire-init"); var import_unfire_firestore_schema = require("@unfire-firestore-schema"); var import_unfire_init2 = require("@unfire-init"); var defaultWhereQueryBuilder = (...query2) => query2; var queryBuilder = ({ whereQueries, orderByQuery, limitBy }) => { return [ ...whereQueries ? whereQueries({ where: defaultWhereQueryBuilder }).map((query2) => (0, import_unfire_init.where)(...query2)) : [], ...orderByQuery ? [(0, import_unfire_init.orderBy)(orderByQuery.fieldPath, orderByQuery.directionStr)] : [], ...limitBy ? [(0, import_unfire_init.limit)(limitBy)] : [] ]; }; var getDocData = (docRef) => { const data = docRef.data(); if (data) { Object.defineProperty(data, "id", { value: docRef.id.toString(), writable: false }); } return data; }; var createCollection = (collectionPath, firestoreInstance) => { console.log("in createCollection"); return (0, import_unfire_init.collection)(firestoreInstance != null ? firestoreInstance : (0, import_unfire_init.getFirestore)(), collectionPath); }; var getCollectionDocRef = (collectionPath, docId, firestoreInstance) => (0, import_unfire_init.doc)(createCollection(collectionPath, firestoreInstance), docId); var upsertDoc = async (options) => { var _a; const { data, collectionPath, docId, docRef, setOption, validation = true, customSchema, onSuccess, onError } = options; const ref2 = docRef != null ? docRef : docId ? getCollectionDocRef(collectionPath, docId) : (0, import_unfire_init.doc)(createCollection(collectionPath)); try { if (validation) { const schema = customSchema != null ? customSchema : await (0, import_unfire_firestore_schema.ImportFirestoreSchemaByPath)(collectionPath); const schemaParseResult = schema == null ? void 0 : schema.safeParse(data); (schemaParseResult == null ? void 0 : schemaParseResult.success) ? await (0, import_unfire_init.setDoc)(ref2, schemaParseResult.data, setOption != null ? setOption : { merge: true }).then(() => { onSuccess == null ? void 0 : onSuccess(schemaParseResult.data); }) : onError == null ? void 0 : onError((_a = schemaParseResult == null ? void 0 : schemaParseResult.error) != null ? _a : new Error("No Schema Found")); } else { await (0, import_unfire_init.setDoc)(ref2, data, setOption != null ? setOption : { merge: true }).then(() => { onSuccess == null ? void 0 : onSuccess(data); }); } } catch (error) { onError == null ? void 0 : onError(error); } return ref2; }; var queryCollection = (options) => { const { collectionPath, onSnapshot, onError, queryOption, snapshotListenOptions = { includeMetadataChanges: false } } = options; try { const q = (0, import_unfire_init.query)(createCollection(collectionPath), ...queryOption ? queryBuilder(queryOption) : []); return { unsubscribe: (0, import_unfire_init.onSnapshot)(q, snapshotListenOptions, { next: (snapshot) => { onSnapshot({ snapshot, docsData: snapshot.docs.map(getDocData) }); }, error: onError }) }; } catch (error) { onError == null ? void 0 : onError(error); return { error }; } }; var queryDoc = (options) => { const { collectionPath, docId, docRef, onSnapshot, onError, snapshotListenOptions = { includeMetadataChanges: false } } = options; try { if (docRef) { return { unsubscribe: (0, import_unfire_init.onSnapshot)(docRef, snapshotListenOptions, { next: (snapshot) => { onSnapshot({ snapshot, docData: getDocData(snapshot) }); }, error: onError }) }; } else if (collectionPath && docId) { return { unsubscribe: (0, import_unfire_init.onSnapshot)(getCollectionDocRef(collectionPath, docId), snapshotListenOptions, { next: (snapshot) => { onSnapshot({ snapshot, docData: getDocData(snapshot) }); }, error: onError }) }; } else { const error = new Error('must provide "collectionPath" and "docId" or "docRef"'); onError == null ? void 0 : onError(error); return { error }; } } catch (error) { onError == null ? void 0 : onError(error); return { error }; } }; var deleteDoc = (options) => { const { collectionPath, docId, docRef, onError } = options; try { if (docRef) { return (0, import_unfire_init.deleteDoc)(docRef); } else if (collectionPath && docId) { return (0, import_unfire_init.deleteDoc)(getCollectionDocRef(collectionPath, docId)); } else { throw new Error('must provide "collectionPath" and "docId" or "docRef"'); } } catch (error) { onError == null ? void 0 : onError(error); } }; var whereFilterOps = ["==", "!=", ">", ">=", "<", "<=", "array-contains", "array-contains-any", "in", "not-in"]; // src/vue/vue-composables.ts var createPathRef = (path) => (0, import_vue.ref)(path); var toReactiveQueryOption = (queryOption) => (0, import_vue.reactive)(queryOption); var useCollection = (options) => { var _a; const { collectionPath: _collectionPath, resultsRef, queryOption, onError, snapshotListenOptions, optionsWatchDebounce = 20 } = options; console.log({ resultsRef }); const results = resultsRef != null ? resultsRef : (0, import_vue.ref)([]); const unsubscribe = (0, import_vue.ref)(); const collectionPath = (0, import_vue.ref)(_collectionPath); const _queryOption = (0, import_vue.ref)(); const initialWhereQueries = (_a = queryOption == null ? void 0 : queryOption.whereQueries) == null ? void 0 : _a.call(queryOption, { where: defaultWhereQueryBuilder }).map(([fieldPath, opStr, value]) => ({ fieldPath, opStr, value })); const whereQueries = (0, import_vue.ref)(initialWhereQueries != null ? initialWhereQueries : []); const orderByQuery = (0, import_vue.ref)(queryOption == null ? void 0 : queryOption.orderByQuery); const limitBy = (0, import_vue.ref)(queryOption == null ? void 0 : queryOption.limitBy); const stopQueryOptionWatch = (0, import_vue.watch)([whereQueries, orderByQuery, limitBy], ([queries, orderBy2, limit2]) => { _queryOption.value = { whereQueries: ({ where: where2 }) => queries.map(({ fieldPath, opStr, value }) => where2(fieldPath, opStr, value)), limitBy: limit2, orderByQuery: orderBy2 }; }, { immediate: true, deep: true }); const debounce = (0, import_vue.computed)(() => unsubscribe.value ? (0, import_vue.ref)(optionsWatchDebounce).value : 0); const watchStopHandle = (0, import_core.debouncedWatch)([collectionPath, _queryOption], ([collectionPath2, queryOption2]) => { var _a2; (_a2 = unsubscribe.value) == null ? void 0 : _a2.call(unsubscribe); unsubscribe.value = queryCollection({ collectionPath: collectionPath2, queryOption: queryOption2, onSnapshot: ({ docsData }) => { results.value = docsData; }, onError, snapshotListenOptions }).unsubscribe; }, { immediate: true, debounce, deep: true }); const stop = () => { var _a2; (_a2 = unsubscribe.value) == null ? void 0 : _a2.call(unsubscribe); watchStopHandle(); stopQueryOptionWatch(); }; (0, import_vue.onUnmounted)(() => { stop(); }); return { results, stop, whereQueries, orderByQuery, limitBy }; }; var useDoc = (options) => { const { collectionPath: _collectionPath, docId: _docId, onError, snapshotListenOptions, optionsWatchDebounce = 20 } = options; const result = (0, import_vue.ref)(); const unsubscribe = (0, import_vue.ref)(); const collectionPath = (0, import_vue.ref)(_collectionPath); const docId = (0, import_vue.ref)(_docId); const debounce = (0, import_vue.computed)(() => unsubscribe.value ? (0, import_vue.ref)(optionsWatchDebounce).value : 0); const watchStopHandle = (0, import_core.debouncedWatch)([collectionPath, docId], ([collectionPath2, docId2]) => { var _a; (_a = unsubscribe.value) == null ? void 0 : _a.call(unsubscribe); unsubscribe.value = queryDoc({ collectionPath: collectionPath2, docId: docId2, onSnapshot: ({ docData }) => { result.value = docData; }, onError, snapshotListenOptions }).unsubscribe; }, { immediate: true, debounce }); const stop = () => { var _a; watchStopHandle(); (_a = unsubscribe.value) == null ? void 0 : _a.call(unsubscribe); }; (0, import_vue.onUnmounted)(() => { stop(); }); return { result, stop }; }; var useDocBiDirection = (options) => { const { collectionPath: _collectionPath, docId: _docId, onError, onUpdateSuccess, snapshotListenOptions, refWatchUpdateDebounce = 200, optionsWatchDebounce = 20, updateValidation, updateCustomSchema } = options; const result = (0, import_vue.ref)(); const validationError = (0, import_vue.ref)(); const unsubscribe = (0, import_vue.ref)(); const collectionPath = (0, import_vue.ref)(_collectionPath); const docId = (0, import_vue.ref)(_docId); const resetValidationError = () => { validationError.value = void 0; }; const updateDoc = (data) => { return upsertDoc({ collectionPath: collectionPath.value, docId: docId.value, data, validation: (0, import_vue.isRef)(updateValidation) ? updateValidation.value : updateValidation, customSchema: updateCustomSchema, onSuccess: (data2) => { resetValidationError(); onUpdateSuccess == null ? void 0 : onUpdateSuccess(data2); }, onError: (e) => { onError == null ? void 0 : onError(e); if ("issues" in e) validationError.value = e; } }); }; const debounce = (0, import_vue.computed)(() => unsubscribe.value ? (0, import_vue.ref)(optionsWatchDebounce).value : 0); let shouldUpdateDoc = false; let localUpdated = false; const resultWatchStopHandle = (0, import_core.debouncedWatch)(result, async (newResult) => { if (newResult && shouldUpdateDoc) { localUpdated = true; await updateDoc(newResult); localUpdated = false; } }, { deep: true, debounce: refWatchUpdateDebounce }); const shouldUpdateDelay = (0, import_vue.computed)(() => (0, import_vue.ref)(refWatchUpdateDebounce).value + 100); const setShouldUpdateDoc = (0, import_core.useDebounceFn)(() => { shouldUpdateDoc = true; }, shouldUpdateDelay); const optionsWatchStopHandle = (0, import_core.debouncedWatch)([collectionPath, docId], ([collectionPath2, docId2]) => { var _a; (_a = unsubscribe.value) == null ? void 0 : _a.call(unsubscribe); unsubscribe.value = queryDoc({ collectionPath: collectionPath2, docId: docId2, onSnapshot: ({ docData }) => { if (!localUpdated) { shouldUpdateDoc = false; result.value = docData; setShouldUpdateDoc(); } }, onError, snapshotListenOptions }).unsubscribe; }, { immediate: true, debounce }); const stop = () => { var _a; resultWatchStopHandle(); optionsWatchStopHandle(); (_a = unsubscribe.value) == null ? void 0 : _a.call(unsubscribe); }; (0, import_vue.onUnmounted)(() => { stop(); }); return { result, validationError, updateDoc, resetValidationError, stop }; }; // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { createPathRef, deleteDoc, toReactiveQueryOption, upsertDoc, useCollection, useDoc, useDocBiDirection, whereFilterOps });