@tanstack/solid-db
Version:
Solid integration for @tanstack/db
178 lines (177 loc) • 4.52 kB
JavaScript
import { createMemo, createSignal, createResource, batch, createEffect, onCleanup } from "solid-js";
import { ReactiveMap } from "@solid-primitives/map";
import { BaseQueryBuilder, createLiveQueryCollection, CollectionImpl } from "@tanstack/db";
import { createStore, reconcile } from "solid-js/store";
function useLiveQuery(configOrQueryOrCollection) {
const collection = createMemo(
() => {
if (configOrQueryOrCollection.length === 1) {
const queryBuilder = new BaseQueryBuilder();
const result = configOrQueryOrCollection(queryBuilder);
if (result === void 0 || result === null) {
return null;
}
return createLiveQueryCollection({
query: configOrQueryOrCollection,
startSync: true
});
}
const innerCollection = configOrQueryOrCollection();
if (innerCollection === void 0 || innerCollection === null) {
return null;
}
if (innerCollection instanceof CollectionImpl) {
innerCollection.startSyncImmediate();
return innerCollection;
}
return createLiveQueryCollection({
...innerCollection,
startSync: true
});
},
void 0,
{ name: `TanstackDBCollectionMemo` }
);
const state = new ReactiveMap();
const [data, setData] = createStore([], {
name: `TanstackDBData`
});
const [status, setStatus] = createSignal(
collection() ? collection().status : `disabled`,
{
name: `TanstackDBStatus`
}
);
const syncDataFromCollection = (currentCollection) => {
setData(
(prev) => reconcile(Array.from(currentCollection.values()))(prev).filter(Boolean)
);
};
const [getDataResource] = createResource(
() => ({ currentCollection: collection() }),
async ({ currentCollection }) => {
if (!currentCollection) {
return [];
}
setStatus(currentCollection.status);
try {
await currentCollection.toArrayWhenReady();
} catch (error) {
setStatus(`error`);
throw error;
}
batch(() => {
state.clear();
for (const [key, value] of currentCollection.entries()) {
state.set(key, value);
}
syncDataFromCollection(currentCollection);
setStatus(currentCollection.status);
});
return data;
},
{
name: `TanstackDBData`,
deferStream: false,
initialValue: data
}
);
createEffect(() => {
const currentCollection = collection();
if (!currentCollection) {
setStatus(`disabled`);
state.clear();
setData([]);
return;
}
const subscription = currentCollection.subscribeChanges(
(changes) => {
batch(() => {
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);
setStatus(currentCollection.status);
});
},
{
// Include initial state to ensure immediate population for pre-created collections
includeInitialState: true
}
);
onCleanup(() => {
subscription.unsubscribe();
});
});
function getData() {
const currentCollection = collection();
if (currentCollection) {
const config = currentCollection.config;
if (config.singleResult) {
getDataResource();
return data[0];
}
}
return getDataResource();
}
Object.defineProperties(getData, {
data: {
get() {
return getData();
}
},
status: {
get() {
return status();
}
},
collection: {
get() {
return collection();
}
},
state: {
get() {
return state;
}
},
isLoading: {
get() {
return status() === `loading`;
}
},
isReady: {
get() {
return status() === `ready` || status() === `disabled`;
}
},
isIdle: {
get() {
return status() === `idle`;
}
},
isError: {
get() {
return status() === `error`;
}
},
isCleanedUp: {
get() {
return status() === `cleaned-up`;
}
}
});
return getData;
}
export {
useLiveQuery
};
//# sourceMappingURL=useLiveQuery.js.map