UNPKG

@tanstack/vue-db

Version:

Vue integration for @tanstack/db

147 lines (144 loc) 4.88 kB
import { computed, toValue, reactive, ref, watchEffect, getCurrentInstance, onUnmounted } from "vue"; import { isCollection, createLiveQueryCollection, isSingleResultCollection, createLiveQueryObserver } from "@tanstack/db"; function useLiveQuery(configOrQueryOrCollection, deps = []) { const collection = computed(() => { let unwrappedParam = configOrQueryOrCollection; if (typeof configOrQueryOrCollection !== `function`) { try { const potentiallyUnwrapped = toValue(configOrQueryOrCollection); if (potentiallyUnwrapped !== configOrQueryOrCollection) { unwrappedParam = potentiallyUnwrapped; } } catch { unwrappedParam = configOrQueryOrCollection; } } const inputIsCollection = isCollection(unwrappedParam); if (inputIsCollection) { const syncMode = unwrappedParam.config?.syncMode; if (syncMode === `on-demand`) { console.warn( `[useLiveQuery] Warning: Passing a collection with syncMode "on-demand" directly to useLiveQuery will not load any data. In on-demand mode, data is only loaded when queries with predicates request it. Instead, use a query builder function: const { data } = useLiveQuery((q) => q.from({ c: myCollection }).select(({ c }) => c)) Or switch to syncMode "eager" if you want all data to sync automatically.` ); } if (unwrappedParam.status === `idle`) { unwrappedParam.startSyncImmediate(); } return unwrappedParam; } deps.forEach((dep) => toValue(dep)); if (typeof unwrappedParam === `function`) { const wrappedQuery = (q) => { const result = unwrappedParam(q); if (result === void 0 || result === null) { throw new Error(`__DISABLED_QUERY__`); } return result; }; try { return createLiveQueryCollection({ query: wrappedQuery, startSync: true }); } catch (error) { if (error instanceof Error && error.message === `__DISABLED_QUERY__`) { return null; } throw error; } } else { return createLiveQueryCollection({ ...unwrappedParam, startSync: true }); } }); const state = reactive(/* @__PURE__ */ new Map()); const internalData = reactive([]); const data = computed(() => { const currentCollection = collection.value; if (!currentCollection) { return internalData; } return isSingleResultCollection(currentCollection) ? internalData[0] : internalData; }); const status = ref( collection.value ? collection.value.status : `disabled` ); const syncDataFromCollection = (currentCollection) => { internalData.length = 0; internalData.push(...Array.from(currentCollection.values())); }; let currentObserver = null; const syncFromObserver = (observer, currentCollection) => { status.value = observer.getSnapshot().status; syncDataFromCollection(currentCollection); }; watchEffect((onInvalidate) => { const currentCollection = collection.value; currentObserver?.dispose(); currentObserver = null; if (!currentCollection) { status.value = `disabled`; state.clear(); internalData.length = 0; return; } const observer = createLiveQueryObserver(currentCollection); currentObserver = observer; state.clear(); const unsubscribe = observer.subscribe( (changes) => { if (changes) { for (const change of changes) { switch (change.type) { case `insert`: case `update`: state.set(change.key, change.value); break; case `delete`: state.delete(change.key); break; } } } else { state.clear(); for (const [key, value] of observer.getSnapshot().state ?? []) { state.set(key, value); } } syncFromObserver(observer, currentCollection); } ); syncFromObserver(observer, currentCollection); onInvalidate(() => { unsubscribe(); observer.dispose(); currentObserver = null; }); }); const instance = getCurrentInstance(); if (instance) { onUnmounted(() => currentObserver?.dispose()); } return { state: computed(() => state), data, collection: computed(() => collection.value), status: computed(() => status.value), isLoading: computed(() => status.value === `loading`), isReady: computed( () => status.value === `ready` || status.value === `disabled` ), isIdle: computed(() => status.value === `idle`), isError: computed(() => status.value === `error`), isCleanedUp: computed(() => status.value === `cleaned-up`) }; } export { useLiveQuery }; //# sourceMappingURL=useLiveQuery.js.map