@tanstack/vue-db
Version:
Vue integration for @tanstack/db
162 lines (159 loc) • 5.37 kB
JavaScript
;
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const vue = require("vue");
const db = require("@tanstack/db");
function useLiveQuery(configOrQueryOrCollection, deps = []) {
const collection = vue.computed(() => {
let unwrappedParam = configOrQueryOrCollection;
if (typeof configOrQueryOrCollection !== `function`) {
try {
const potentiallyUnwrapped = vue.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) => vue.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 db.createLiveQueryCollection({
query: wrappedQuery,
startSync: true
});
} catch (error) {
if (error instanceof Error && error.message === `__DISABLED_QUERY__`) {
return null;
}
throw error;
}
} else {
return db.createLiveQueryCollection({
...unwrappedParam,
startSync: true
});
}
});
const state = vue.reactive(/* @__PURE__ */ new Map());
const internalData = vue.reactive([]);
const data = vue.computed(() => {
const currentCollection = collection.value;
if (!currentCollection) {
return internalData;
}
const config = currentCollection.config;
return config.singleResult ? internalData[0] : internalData;
});
const status = vue.ref(
collection.value ? collection.value.status : `disabled`
);
const syncDataFromCollection = (currentCollection) => {
internalData.length = 0;
internalData.push(...Array.from(currentCollection.values()));
};
let currentUnsubscribe = null;
vue.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(() => {
vue.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 = vue.getCurrentInstance();
if (instance) {
vue.onUnmounted(() => {
if (currentUnsubscribe) {
currentUnsubscribe();
}
});
}
return {
state: vue.computed(() => state),
data,
collection: vue.computed(() => collection.value),
status: vue.computed(() => status.value),
isLoading: vue.computed(() => status.value === `loading`),
isReady: vue.computed(
() => status.value === `ready` || status.value === `disabled`
),
isIdle: vue.computed(() => status.value === `idle`),
isError: vue.computed(() => status.value === `error`),
isCleanedUp: vue.computed(() => status.value === `cleaned-up`)
};
}
exports.useLiveQuery = useLiveQuery;
//# sourceMappingURL=useLiveQuery.cjs.map