@tanstack/vue-db
Version:
Vue integration for @tanstack/db
147 lines (144 loc) • 4.88 kB
JavaScript
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