UNPKG

@tanstack/vue-db

Version:

Vue integration for @tanstack/db

162 lines (159 loc) 5.29 kB
import { computed, toValue, reactive, ref, watchEffect, nextTick, getCurrentInstance, onUnmounted } from "vue"; import { createLiveQueryCollection } 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 isCollection = unwrappedParam && typeof unwrappedParam === `object` && typeof unwrappedParam.subscribeChanges === `function` && typeof unwrappedParam.startSyncImmediate === `function` && typeof unwrappedParam.id === `string`; if (isCollection) { 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; } const config = currentCollection.config; return config.singleResult ? 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 currentUnsubscribe = null; watchEffect((onInvalidate) => { const currentCollection = collection.value; if (!currentCollection) { status.value = `disabled`; state.clear(); internalData.length = 0; if (currentUnsubscribe) { currentUnsubscribe(); currentUnsubscribe = null; } return; } status.value = currentCollection.status; if (currentUnsubscribe) { currentUnsubscribe(); } state.clear(); for (const [key, value] of currentCollection.entries()) { state.set(key, value); } syncDataFromCollection(currentCollection); currentCollection.onFirstReady(() => { nextTick(() => { status.value = currentCollection.status; }); }); const subscription = currentCollection.subscribeChanges( (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; } } syncDataFromCollection(currentCollection); status.value = currentCollection.status; }, { includeInitialState: true } ); currentUnsubscribe = subscription.unsubscribe.bind(subscription); if (currentCollection.status === `idle`) { currentCollection.preload().catch(console.error); } onInvalidate(() => { if (currentUnsubscribe) { currentUnsubscribe(); currentUnsubscribe = null; } }); }); const instance = getCurrentInstance(); if (instance) { onUnmounted(() => { if (currentUnsubscribe) { currentUnsubscribe(); } }); } 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