@tanstack/solid-db 0.1.53 → 0.1.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/useLiveQuery.d.ts +11 -0
- package/dist/esm/useLiveQuery.js +26 -5
- package/dist/esm/useLiveQuery.js.map +1 -1
- package/package.json +20 -20
- package/src/index.ts +4 -4
- package/src/useLiveQuery.ts +75 -20
|
@@ -67,6 +67,17 @@ export declare function useLiveQuery<TContext extends Context>(queryFn: (q: Init
|
|
|
67
67
|
isError: Accessor<boolean>;
|
|
68
68
|
isCleanedUp: Accessor<boolean>;
|
|
69
69
|
};
|
|
70
|
+
export declare function useLiveQuery<TContext extends Context>(queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext> | undefined | null): {
|
|
71
|
+
state: ReactiveMap<string | number, GetResult<TContext>>;
|
|
72
|
+
data: Array<GetResult<TContext>>;
|
|
73
|
+
collection: Accessor<Collection<GetResult<TContext>, string | number, {}> | null>;
|
|
74
|
+
status: Accessor<CollectionStatus | `disabled`>;
|
|
75
|
+
isLoading: Accessor<boolean>;
|
|
76
|
+
isReady: Accessor<boolean>;
|
|
77
|
+
isIdle: Accessor<boolean>;
|
|
78
|
+
isError: Accessor<boolean>;
|
|
79
|
+
isCleanedUp: Accessor<boolean>;
|
|
80
|
+
};
|
|
70
81
|
/**
|
|
71
82
|
* Create a live query using configuration object
|
|
72
83
|
* @param config - Configuration object with query and options
|
package/dist/esm/useLiveQuery.js
CHANGED
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
import { createMemo, createSignal, createComputed, batch, createResource, onCleanup } from "solid-js";
|
|
2
2
|
import { ReactiveMap } from "@solid-primitives/map";
|
|
3
|
-
import { createLiveQueryCollection, CollectionImpl } from "@tanstack/db";
|
|
3
|
+
import { BaseQueryBuilder, createLiveQueryCollection, CollectionImpl } from "@tanstack/db";
|
|
4
4
|
import { createStore, reconcile } from "solid-js/store";
|
|
5
5
|
function useLiveQuery(configOrQueryOrCollection) {
|
|
6
6
|
const collection = createMemo(
|
|
7
7
|
() => {
|
|
8
8
|
if (configOrQueryOrCollection.length === 1) {
|
|
9
|
+
const queryBuilder = new BaseQueryBuilder();
|
|
10
|
+
const result = configOrQueryOrCollection(queryBuilder);
|
|
11
|
+
if (result === void 0 || result === null) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
9
14
|
return createLiveQueryCollection({
|
|
10
15
|
query: configOrQueryOrCollection,
|
|
11
16
|
startSync: true
|
|
12
17
|
});
|
|
13
18
|
}
|
|
14
19
|
const innerCollection = configOrQueryOrCollection();
|
|
20
|
+
if (innerCollection === void 0 || innerCollection === null) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
15
23
|
if (innerCollection instanceof CollectionImpl) {
|
|
16
24
|
innerCollection.startSyncImmediate();
|
|
17
25
|
return innerCollection;
|
|
@@ -28,9 +36,12 @@ function useLiveQuery(configOrQueryOrCollection) {
|
|
|
28
36
|
const [data, setData] = createStore([], {
|
|
29
37
|
name: `TanstackDBData`
|
|
30
38
|
});
|
|
31
|
-
const [status, setStatus] = createSignal(
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
const [status, setStatus] = createSignal(
|
|
40
|
+
collection() ? collection().status : `disabled`,
|
|
41
|
+
{
|
|
42
|
+
name: `TanstackDBStatus`
|
|
43
|
+
}
|
|
44
|
+
);
|
|
34
45
|
const syncDataFromCollection = (currentCollection) => {
|
|
35
46
|
setData(
|
|
36
47
|
(prev) => reconcile(Array.from(currentCollection.values()))(prev).filter(Boolean)
|
|
@@ -40,6 +51,16 @@ function useLiveQuery(configOrQueryOrCollection) {
|
|
|
40
51
|
createComputed(
|
|
41
52
|
() => {
|
|
42
53
|
const currentCollection = collection();
|
|
54
|
+
if (!currentCollection) {
|
|
55
|
+
setStatus(`disabled`);
|
|
56
|
+
state.clear();
|
|
57
|
+
setData([]);
|
|
58
|
+
if (currentUnsubscribe) {
|
|
59
|
+
currentUnsubscribe();
|
|
60
|
+
currentUnsubscribe = null;
|
|
61
|
+
}
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
43
64
|
setStatus(currentCollection.status);
|
|
44
65
|
state.clear();
|
|
45
66
|
for (const [key, value] of currentCollection.entries()) {
|
|
@@ -87,7 +108,7 @@ function useLiveQuery(configOrQueryOrCollection) {
|
|
|
87
108
|
collection,
|
|
88
109
|
status,
|
|
89
110
|
isLoading: () => status() === `loading`,
|
|
90
|
-
isReady: () => status() === `ready`,
|
|
111
|
+
isReady: () => status() === `ready` || status() === `disabled`,
|
|
91
112
|
isIdle: () => status() === `idle`,
|
|
92
113
|
isError: () => status() === `error`,
|
|
93
114
|
isCleanedUp: () => status() === `cleaned-up`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLiveQuery.js","sources":["../../src/useLiveQuery.ts"],"sourcesContent":["import {\n batch,\n createComputed,\n createMemo,\n createResource,\n createSignal,\n onCleanup,\n} from \"solid-js\"\nimport { ReactiveMap } from \"@solid-primitives/map\"\nimport { CollectionImpl, createLiveQueryCollection } from \"@tanstack/db\"\nimport { createStore, reconcile } from \"solid-js/store\"\nimport type { Accessor } from \"solid-js\"\nimport type {\n ChangeMessage,\n Collection,\n CollectionStatus,\n Context,\n GetResult,\n InitialQueryBuilder,\n LiveQueryCollectionConfig,\n QueryBuilder,\n} from \"@tanstack/db\"\n\n/**\n * Create a live query using a query function\n * @param queryFn - Query function that defines what data to fetch\n * @returns Object with reactive data, state, and status information\n * @example\n * // Basic query with object syntax\n * const todosQuery = useLiveQuery((q) =>\n * q.from({ todos: todosCollection })\n * .where(({ todos }) => eq(todos.completed, false))\n * .select(({ todos }) => ({ id: todos.id, text: todos.text }))\n * )\n *\n * @example\n * // With dependencies that trigger re-execution\n * const todosQuery = useLiveQuery(\n * (q) => q.from({ todos: todosCollection })\n * .where(({ todos }) => gt(todos.priority, minPriority())),\n * )\n *\n * @example\n * // Join pattern\n * const personIssues = useLiveQuery((q) =>\n * q.from({ issues: issueCollection })\n * .join({ persons: personCollection }, ({ issues, persons }) =>\n * eq(issues.userId, persons.id)\n * )\n * .select(({ issues, persons }) => ({\n * id: issues.id,\n * title: issues.title,\n * userName: persons.name\n * }))\n * )\n *\n * @example\n * // Handle loading and error states\n * const todosQuery = useLiveQuery((q) =>\n * q.from({ todos: todoCollection })\n * )\n *\n * return (\n * <Switch>\n * <Match when={todosQuery.isLoading()}>\n * <div>Loading...</div>\n * </Match>\n * <Match when={todosQuery.isError()}>\n * <div>Error: {todosQuery.status()}</div>\n * </Match>\n * <Match when={todosQuery.isReady()}>\n * <For each={todosQuery.data()}>\n * {(todo) => <li key={todo.id}>{todo.text}</li>}\n * </For>\n * </Match>\n * </Switch>\n * )\n */\n// Overload 1: Accept just the query function\nexport function useLiveQuery<TContext extends Context>(\n queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext>\n): {\n state: ReactiveMap<string | number, GetResult<TContext>>\n data: Array<GetResult<TContext>>\n collection: Accessor<Collection<GetResult<TContext>, string | number, {}>>\n status: Accessor<CollectionStatus>\n isLoading: Accessor<boolean>\n isReady: Accessor<boolean>\n isIdle: Accessor<boolean>\n isError: Accessor<boolean>\n isCleanedUp: Accessor<boolean>\n}\n\n/**\n * Create a live query using configuration object\n * @param config - Configuration object with query and options\n * @returns Object with reactive data, state, and status information\n * @example\n * // Basic config object usage\n * const todosQuery = useLiveQuery(() => ({\n * query: (q) => q.from({ todos: todosCollection }),\n * gcTime: 60000\n * }))\n *\n * @example\n * // With query builder and options\n * const queryBuilder = new Query()\n * .from({ persons: collection })\n * .where(({ persons }) => gt(persons.age, 30))\n * .select(({ persons }) => ({ id: persons.id, name: persons.name }))\n *\n * const personsQuery = useLiveQuery(() => ({ query: queryBuilder }))\n *\n * @example\n * // Handle all states uniformly\n * const itemsQuery = useLiveQuery(() => ({\n * query: (q) => q.from({ items: itemCollection })\n * }))\n *\n * return (\n * <Switch fallback={<div>{itemsQuery.data.length} items loaded</div>}>\n * <Match when={itemsQuery.isLoading()}>\n * <div>Loading...</div>\n * </Match>\n * <Match when={itemsQuery.isError()}>\n * <div>Something went wrong</div>\n * </Match>\n * <Match when={!itemsQuery.isReady()}>\n * <div>Preparing...</div>\n * </Match>\n * </Switch>\n * )\n */\n// Overload 2: Accept config object\nexport function useLiveQuery<TContext extends Context>(\n config: Accessor<LiveQueryCollectionConfig<TContext>>\n): {\n state: ReactiveMap<string | number, GetResult<TContext>>\n data: Array<GetResult<TContext>>\n collection: Accessor<Collection<GetResult<TContext>, string | number, {}>>\n status: Accessor<CollectionStatus>\n isLoading: Accessor<boolean>\n isReady: Accessor<boolean>\n isIdle: Accessor<boolean>\n isError: Accessor<boolean>\n isCleanedUp: Accessor<boolean>\n}\n\n/**\n * Subscribe to an existing live query collection\n * @param liveQueryCollection - Pre-created live query collection to subscribe to\n * @returns Object with reactive data, state, and status information\n * @example\n * // Using pre-created live query collection\n * const myLiveQuery = createLiveQueryCollection((q) =>\n * q.from({ todos: todosCollection }).where(({ todos }) => eq(todos.active, true))\n * )\n * const todosQuery = useLiveQuery(() => myLiveQuery)\n *\n * @example\n * // Access collection methods directly\n * const existingQuery = useLiveQuery(() => existingCollection)\n *\n * // Use collection for mutations\n * const handleToggle = (id) => {\n * existingQuery.collection().update(id, draft => { draft.completed = !draft.completed })\n * }\n *\n * @example\n * // Handle states consistently\n * const sharedQuery = useLiveQuery(() => sharedCollection)\n *\n * return (\n * <Switch fallback={<div><For each={sharedQuery.data()}>{(item) => <Item key={item.id} {...item} />}</For></div>}>\n * <Match when={sharedQuery.isLoading()}>\n * <div>Loading...</div>\n * </Match>\n * <Match when={sharedQuery.isError()}>\n * <div>Error loading data</div>\n * </Match>\n * </Switch>\n * )\n */\n// Overload 3: Accept pre-created live query collection\nexport function useLiveQuery<\n TResult extends object,\n TKey extends string | number,\n TUtils extends Record<string, any>,\n>(\n liveQueryCollection: Accessor<Collection<TResult, TKey, TUtils>>\n): {\n state: ReactiveMap<TKey, TResult>\n data: Array<TResult>\n collection: Accessor<Collection<TResult, TKey, TUtils>>\n status: Accessor<CollectionStatus>\n isLoading: Accessor<boolean>\n isReady: Accessor<boolean>\n isIdle: Accessor<boolean>\n isError: Accessor<boolean>\n isCleanedUp: Accessor<boolean>\n}\n\n// Implementation - use function overloads to infer the actual collection type\nexport function useLiveQuery(\n configOrQueryOrCollection: (queryFn?: any) => any\n) {\n const collection = createMemo(\n () => {\n if (configOrQueryOrCollection.length === 1) {\n return createLiveQueryCollection({\n query: configOrQueryOrCollection,\n startSync: true,\n })\n }\n\n const innerCollection = configOrQueryOrCollection()\n if (innerCollection instanceof CollectionImpl) {\n innerCollection.startSyncImmediate()\n return innerCollection as Collection\n }\n\n return createLiveQueryCollection({\n ...innerCollection,\n startSync: true,\n })\n },\n undefined,\n { name: `TanstackDBCollectionMemo` }\n )\n\n // Reactive state that gets updated granularly through change events\n const state = new ReactiveMap<string | number, any>()\n\n // Reactive data array that maintains sorted order\n const [data, setData] = createStore<Array<any>>([], {\n name: `TanstackDBData`,\n })\n\n // Track collection status reactively\n const [status, setStatus] = createSignal(collection().status, {\n name: `TanstackDBStatus`,\n })\n\n // Helper to sync data array from collection in correct order\n const syncDataFromCollection = (\n currentCollection: Collection<any, any, any>\n ) => {\n setData((prev) =>\n reconcile(Array.from(currentCollection.values()))(prev).filter(Boolean)\n )\n }\n\n // Track current unsubscribe function\n let currentUnsubscribe: (() => void) | null = null\n\n createComputed(\n () => {\n const currentCollection = collection()\n\n // Update status ref whenever the effect runs\n setStatus(currentCollection.status)\n\n // Initialize state with current collection data\n state.clear()\n for (const [key, value] of currentCollection.entries()) {\n state.set(key, value)\n }\n\n // Subscribe to collection changes with granular updates\n const subscription = currentCollection.subscribeChanges(\n (changes: Array<ChangeMessage<any>>) => {\n // Apply each change individually to the reactive state\n batch(() => {\n for (const change of changes) {\n switch (change.type) {\n case `insert`:\n case `update`:\n state.set(change.key, change.value)\n break\n case `delete`:\n state.delete(change.key)\n break\n }\n }\n })\n\n // Update the data array to maintain sorted order\n syncDataFromCollection(currentCollection)\n\n // Update status ref on every change\n setStatus(currentCollection.status)\n },\n {\n includeInitialState: true,\n }\n )\n\n currentUnsubscribe = subscription.unsubscribe.bind(subscription)\n\n // Preload collection data if not already started\n if (currentCollection.status === `idle`) {\n createResource(() => currentCollection.preload())\n }\n\n // Cleanup when computed is invalidated\n onCleanup(() => {\n if (currentUnsubscribe) {\n currentUnsubscribe()\n currentUnsubscribe = null\n }\n })\n },\n undefined,\n { name: `TanstackDBSyncComputed` }\n )\n\n return {\n state,\n data,\n collection,\n status,\n isLoading: () => status() === `loading`,\n isReady: () => status() === `ready`,\n isIdle: () => status() === `idle`,\n isError: () => status() === `error`,\n isCleanedUp: () => status() === `cleaned-up`,\n }\n}\n"],"names":[],"mappings":";;;;AA2MO,SAAS,aACd,2BACA;AACA,QAAM,aAAa;AAAA,IACjB,MAAM;AACJ,UAAI,0BAA0B,WAAW,GAAG;AAC1C,eAAO,0BAA0B;AAAA,UAC/B,OAAO;AAAA,UACP,WAAW;AAAA,QAAA,CACZ;AAAA,MACH;AAEA,YAAM,kBAAkB,0BAAA;AACxB,UAAI,2BAA2B,gBAAgB;AAC7C,wBAAgB,mBAAA;AAChB,eAAO;AAAA,MACT;AAEA,aAAO,0BAA0B;AAAA,QAC/B,GAAG;AAAA,QACH,WAAW;AAAA,MAAA,CACZ;AAAA,IACH;AAAA,IACA;AAAA,IACA,EAAE,MAAM,2BAAA;AAAA,EAA2B;AAIrC,QAAM,QAAQ,IAAI,YAAA;AAGlB,QAAM,CAAC,MAAM,OAAO,IAAI,YAAwB,CAAA,GAAI;AAAA,IAClD,MAAM;AAAA,EAAA,CACP;AAGD,QAAM,CAAC,QAAQ,SAAS,IAAI,aAAa,WAAA,EAAa,QAAQ;AAAA,IAC5D,MAAM;AAAA,EAAA,CACP;AAGD,QAAM,yBAAyB,CAC7B,sBACG;AACH;AAAA,MAAQ,CAAC,SACP,UAAU,MAAM,KAAK,kBAAkB,OAAA,CAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,OAAO;AAAA,IAAA;AAAA,EAE1E;AAGA,MAAI,qBAA0C;AAE9C;AAAA,IACE,MAAM;AACJ,YAAM,oBAAoB,WAAA;AAG1B,gBAAU,kBAAkB,MAAM;AAGlC,YAAM,MAAA;AACN,iBAAW,CAAC,KAAK,KAAK,KAAK,kBAAkB,WAAW;AACtD,cAAM,IAAI,KAAK,KAAK;AAAA,MACtB;AAGA,YAAM,eAAe,kBAAkB;AAAA,QACrC,CAAC,YAAuC;AAEtC,gBAAM,MAAM;AACV,uBAAW,UAAU,SAAS;AAC5B,sBAAQ,OAAO,MAAA;AAAA,gBACb,KAAK;AAAA,gBACL,KAAK;AACH,wBAAM,IAAI,OAAO,KAAK,OAAO,KAAK;AAClC;AAAA,gBACF,KAAK;AACH,wBAAM,OAAO,OAAO,GAAG;AACvB;AAAA,cAAA;AAAA,YAEN;AAAA,UACF,CAAC;AAGD,iCAAuB,iBAAiB;AAGxC,oBAAU,kBAAkB,MAAM;AAAA,QACpC;AAAA,QACA;AAAA,UACE,qBAAqB;AAAA,QAAA;AAAA,MACvB;AAGF,2BAAqB,aAAa,YAAY,KAAK,YAAY;AAG/D,UAAI,kBAAkB,WAAW,QAAQ;AACvC,uBAAe,MAAM,kBAAkB,SAAS;AAAA,MAClD;AAGA,gBAAU,MAAM;AACd,YAAI,oBAAoB;AACtB,6BAAA;AACA,+BAAqB;AAAA,QACvB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IACA;AAAA,IACA,EAAE,MAAM,yBAAA;AAAA,EAAyB;AAGnC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW,MAAM,aAAa;AAAA,IAC9B,SAAS,MAAM,aAAa;AAAA,IAC5B,QAAQ,MAAM,aAAa;AAAA,IAC3B,SAAS,MAAM,aAAa;AAAA,IAC5B,aAAa,MAAM,OAAA,MAAa;AAAA,EAAA;AAEpC;"}
|
|
1
|
+
{"version":3,"file":"useLiveQuery.js","sources":["../../src/useLiveQuery.ts"],"sourcesContent":["import {\n batch,\n createComputed,\n createMemo,\n createResource,\n createSignal,\n onCleanup,\n} from 'solid-js'\nimport { ReactiveMap } from '@solid-primitives/map'\nimport {\n BaseQueryBuilder,\n CollectionImpl,\n createLiveQueryCollection,\n} from '@tanstack/db'\nimport { createStore, reconcile } from 'solid-js/store'\nimport type { Accessor } from 'solid-js'\nimport type {\n ChangeMessage,\n Collection,\n CollectionStatus,\n Context,\n GetResult,\n InitialQueryBuilder,\n LiveQueryCollectionConfig,\n QueryBuilder,\n} from '@tanstack/db'\n\n/**\n * Create a live query using a query function\n * @param queryFn - Query function that defines what data to fetch\n * @returns Object with reactive data, state, and status information\n * @example\n * // Basic query with object syntax\n * const todosQuery = useLiveQuery((q) =>\n * q.from({ todos: todosCollection })\n * .where(({ todos }) => eq(todos.completed, false))\n * .select(({ todos }) => ({ id: todos.id, text: todos.text }))\n * )\n *\n * @example\n * // With dependencies that trigger re-execution\n * const todosQuery = useLiveQuery(\n * (q) => q.from({ todos: todosCollection })\n * .where(({ todos }) => gt(todos.priority, minPriority())),\n * )\n *\n * @example\n * // Join pattern\n * const personIssues = useLiveQuery((q) =>\n * q.from({ issues: issueCollection })\n * .join({ persons: personCollection }, ({ issues, persons }) =>\n * eq(issues.userId, persons.id)\n * )\n * .select(({ issues, persons }) => ({\n * id: issues.id,\n * title: issues.title,\n * userName: persons.name\n * }))\n * )\n *\n * @example\n * // Handle loading and error states\n * const todosQuery = useLiveQuery((q) =>\n * q.from({ todos: todoCollection })\n * )\n *\n * return (\n * <Switch>\n * <Match when={todosQuery.isLoading()}>\n * <div>Loading...</div>\n * </Match>\n * <Match when={todosQuery.isError()}>\n * <div>Error: {todosQuery.status()}</div>\n * </Match>\n * <Match when={todosQuery.isReady()}>\n * <For each={todosQuery.data()}>\n * {(todo) => <li key={todo.id}>{todo.text}</li>}\n * </For>\n * </Match>\n * </Switch>\n * )\n */\n// Overload 1: Accept query function that always returns QueryBuilder\nexport function useLiveQuery<TContext extends Context>(\n queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext>,\n): {\n state: ReactiveMap<string | number, GetResult<TContext>>\n data: Array<GetResult<TContext>>\n collection: Accessor<Collection<GetResult<TContext>, string | number, {}>>\n status: Accessor<CollectionStatus>\n isLoading: Accessor<boolean>\n isReady: Accessor<boolean>\n isIdle: Accessor<boolean>\n isError: Accessor<boolean>\n isCleanedUp: Accessor<boolean>\n}\n\n// Overload 1b: Accept query function that can return undefined/null\nexport function useLiveQuery<TContext extends Context>(\n queryFn: (\n q: InitialQueryBuilder,\n ) => QueryBuilder<TContext> | undefined | null,\n): {\n state: ReactiveMap<string | number, GetResult<TContext>>\n data: Array<GetResult<TContext>>\n collection: Accessor<Collection<\n GetResult<TContext>,\n string | number,\n {}\n > | null>\n status: Accessor<CollectionStatus | `disabled`>\n isLoading: Accessor<boolean>\n isReady: Accessor<boolean>\n isIdle: Accessor<boolean>\n isError: Accessor<boolean>\n isCleanedUp: Accessor<boolean>\n}\n\n/**\n * Create a live query using configuration object\n * @param config - Configuration object with query and options\n * @returns Object with reactive data, state, and status information\n * @example\n * // Basic config object usage\n * const todosQuery = useLiveQuery(() => ({\n * query: (q) => q.from({ todos: todosCollection }),\n * gcTime: 60000\n * }))\n *\n * @example\n * // With query builder and options\n * const queryBuilder = new Query()\n * .from({ persons: collection })\n * .where(({ persons }) => gt(persons.age, 30))\n * .select(({ persons }) => ({ id: persons.id, name: persons.name }))\n *\n * const personsQuery = useLiveQuery(() => ({ query: queryBuilder }))\n *\n * @example\n * // Handle all states uniformly\n * const itemsQuery = useLiveQuery(() => ({\n * query: (q) => q.from({ items: itemCollection })\n * }))\n *\n * return (\n * <Switch fallback={<div>{itemsQuery.data.length} items loaded</div>}>\n * <Match when={itemsQuery.isLoading()}>\n * <div>Loading...</div>\n * </Match>\n * <Match when={itemsQuery.isError()}>\n * <div>Something went wrong</div>\n * </Match>\n * <Match when={!itemsQuery.isReady()}>\n * <div>Preparing...</div>\n * </Match>\n * </Switch>\n * )\n */\n// Overload 2: Accept config object\nexport function useLiveQuery<TContext extends Context>(\n config: Accessor<LiveQueryCollectionConfig<TContext>>,\n): {\n state: ReactiveMap<string | number, GetResult<TContext>>\n data: Array<GetResult<TContext>>\n collection: Accessor<Collection<GetResult<TContext>, string | number, {}>>\n status: Accessor<CollectionStatus>\n isLoading: Accessor<boolean>\n isReady: Accessor<boolean>\n isIdle: Accessor<boolean>\n isError: Accessor<boolean>\n isCleanedUp: Accessor<boolean>\n}\n\n/**\n * Subscribe to an existing live query collection\n * @param liveQueryCollection - Pre-created live query collection to subscribe to\n * @returns Object with reactive data, state, and status information\n * @example\n * // Using pre-created live query collection\n * const myLiveQuery = createLiveQueryCollection((q) =>\n * q.from({ todos: todosCollection }).where(({ todos }) => eq(todos.active, true))\n * )\n * const todosQuery = useLiveQuery(() => myLiveQuery)\n *\n * @example\n * // Access collection methods directly\n * const existingQuery = useLiveQuery(() => existingCollection)\n *\n * // Use collection for mutations\n * const handleToggle = (id) => {\n * existingQuery.collection().update(id, draft => { draft.completed = !draft.completed })\n * }\n *\n * @example\n * // Handle states consistently\n * const sharedQuery = useLiveQuery(() => sharedCollection)\n *\n * return (\n * <Switch fallback={<div><For each={sharedQuery.data()}>{(item) => <Item key={item.id} {...item} />}</For></div>}>\n * <Match when={sharedQuery.isLoading()}>\n * <div>Loading...</div>\n * </Match>\n * <Match when={sharedQuery.isError()}>\n * <div>Error loading data</div>\n * </Match>\n * </Switch>\n * )\n */\n// Overload 3: Accept pre-created live query collection\nexport function useLiveQuery<\n TResult extends object,\n TKey extends string | number,\n TUtils extends Record<string, any>,\n>(\n liveQueryCollection: Accessor<Collection<TResult, TKey, TUtils>>,\n): {\n state: ReactiveMap<TKey, TResult>\n data: Array<TResult>\n collection: Accessor<Collection<TResult, TKey, TUtils>>\n status: Accessor<CollectionStatus>\n isLoading: Accessor<boolean>\n isReady: Accessor<boolean>\n isIdle: Accessor<boolean>\n isError: Accessor<boolean>\n isCleanedUp: Accessor<boolean>\n}\n\n// Implementation - use function overloads to infer the actual collection type\nexport function useLiveQuery(\n configOrQueryOrCollection: (queryFn?: any) => any,\n) {\n const collection = createMemo(\n () => {\n if (configOrQueryOrCollection.length === 1) {\n // This is a query function - check if it returns null/undefined\n const queryBuilder = new BaseQueryBuilder() as InitialQueryBuilder\n const result = configOrQueryOrCollection(queryBuilder)\n\n if (result === undefined || result === null) {\n // Disabled query - return null\n return null\n }\n\n return createLiveQueryCollection({\n query: configOrQueryOrCollection,\n startSync: true,\n })\n }\n\n const innerCollection = configOrQueryOrCollection()\n\n if (innerCollection === undefined || innerCollection === null) {\n // Disabled query - return null\n return null\n }\n\n if (innerCollection instanceof CollectionImpl) {\n innerCollection.startSyncImmediate()\n return innerCollection as Collection\n }\n\n return createLiveQueryCollection({\n ...innerCollection,\n startSync: true,\n })\n },\n undefined,\n { name: `TanstackDBCollectionMemo` },\n )\n\n // Reactive state that gets updated granularly through change events\n const state = new ReactiveMap<string | number, any>()\n\n // Reactive data array that maintains sorted order\n const [data, setData] = createStore<Array<any>>([], {\n name: `TanstackDBData`,\n })\n\n // Track collection status reactively\n const [status, setStatus] = createSignal(\n collection() ? collection()!.status : (`disabled` as const),\n {\n name: `TanstackDBStatus`,\n },\n )\n\n // Helper to sync data array from collection in correct order\n const syncDataFromCollection = (\n currentCollection: Collection<any, any, any>,\n ) => {\n setData((prev) =>\n reconcile(Array.from(currentCollection.values()))(prev).filter(Boolean),\n )\n }\n\n // Track current unsubscribe function\n let currentUnsubscribe: (() => void) | null = null\n\n createComputed(\n () => {\n const currentCollection = collection()\n\n // Handle null collection (disabled query)\n if (!currentCollection) {\n setStatus(`disabled` as const)\n state.clear()\n setData([])\n if (currentUnsubscribe) {\n currentUnsubscribe()\n currentUnsubscribe = null\n }\n return\n }\n\n // Update status ref whenever the effect runs\n setStatus(currentCollection.status)\n\n // Initialize state with current collection data\n state.clear()\n for (const [key, value] of currentCollection.entries()) {\n state.set(key, value)\n }\n\n // Subscribe to collection changes with granular updates\n const subscription = currentCollection.subscribeChanges(\n (changes: Array<ChangeMessage<any>>) => {\n // Apply each change individually to the reactive state\n batch(() => {\n for (const change of changes) {\n switch (change.type) {\n case `insert`:\n case `update`:\n state.set(change.key, change.value)\n break\n case `delete`:\n state.delete(change.key)\n break\n }\n }\n })\n\n // Update the data array to maintain sorted order\n syncDataFromCollection(currentCollection)\n\n // Update status ref on every change\n setStatus(currentCollection.status)\n },\n {\n includeInitialState: true,\n },\n )\n\n currentUnsubscribe = subscription.unsubscribe.bind(subscription)\n\n // Preload collection data if not already started\n if (currentCollection.status === `idle`) {\n createResource(() => currentCollection.preload())\n }\n\n // Cleanup when computed is invalidated\n onCleanup(() => {\n if (currentUnsubscribe) {\n currentUnsubscribe()\n currentUnsubscribe = null\n }\n })\n },\n undefined,\n { name: `TanstackDBSyncComputed` },\n )\n\n return {\n state,\n data,\n collection,\n status,\n isLoading: () => status() === `loading`,\n isReady: () => status() === `ready` || status() === `disabled`,\n isIdle: () => status() === `idle`,\n isError: () => status() === `error`,\n isCleanedUp: () => status() === `cleaned-up`,\n }\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/solid-db",
|
|
3
|
+
"version": "0.1.55",
|
|
3
4
|
"description": "Solid integration for @tanstack/db",
|
|
4
|
-
"version": "0.1.53",
|
|
5
5
|
"author": "Kyle Mathews",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
|
-
"url": "https://github.com/TanStack/db.git",
|
|
9
|
+
"url": "git+https://github.com/TanStack/db.git",
|
|
10
10
|
"directory": "packages/solid-db"
|
|
11
11
|
},
|
|
12
12
|
"homepage": "https://tanstack.com/db",
|
|
@@ -15,19 +15,10 @@
|
|
|
15
15
|
"solid",
|
|
16
16
|
"typescript"
|
|
17
17
|
],
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"devDependencies": {
|
|
23
|
-
"@electric-sql/client": "1.2.0",
|
|
24
|
-
"@solidjs/testing-library": "^0.8.10",
|
|
25
|
-
"@vitest/coverage-istanbul": "^3.2.4",
|
|
26
|
-
"jsdom": "^27.2.0",
|
|
27
|
-
"solid-js": "^1.9.10",
|
|
28
|
-
"vite-plugin-solid": "^2.11.10",
|
|
29
|
-
"vitest": "^3.2.4"
|
|
30
|
-
},
|
|
18
|
+
"type": "module",
|
|
19
|
+
"main": "dist/esm/index.js",
|
|
20
|
+
"module": "dist/esm/index.js",
|
|
21
|
+
"types": "dist/esm/index.d.ts",
|
|
31
22
|
"exports": {
|
|
32
23
|
".": {
|
|
33
24
|
"import": {
|
|
@@ -37,18 +28,27 @@
|
|
|
37
28
|
},
|
|
38
29
|
"./package.json": "./package.json"
|
|
39
30
|
},
|
|
31
|
+
"sideEffects": false,
|
|
40
32
|
"files": [
|
|
41
33
|
"dist",
|
|
42
34
|
"src"
|
|
43
35
|
],
|
|
44
|
-
"
|
|
45
|
-
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@solid-primitives/map": "^0.7.2",
|
|
38
|
+
"@tanstack/db": "0.5.12"
|
|
39
|
+
},
|
|
46
40
|
"peerDependencies": {
|
|
47
41
|
"solid-js": ">=1.9.0"
|
|
48
42
|
},
|
|
49
|
-
"
|
|
50
|
-
|
|
51
|
-
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@electric-sql/client": "1.2.0",
|
|
45
|
+
"@solidjs/testing-library": "^0.8.10",
|
|
46
|
+
"@vitest/coverage-istanbul": "^3.2.4",
|
|
47
|
+
"jsdom": "^27.2.0",
|
|
48
|
+
"solid-js": "^1.9.10",
|
|
49
|
+
"vite-plugin-solid": "^2.11.10",
|
|
50
|
+
"vitest": "^3.2.4"
|
|
51
|
+
},
|
|
52
52
|
"scripts": {
|
|
53
53
|
"build": "vite build",
|
|
54
54
|
"dev": "vite build --watch",
|
package/src/index.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// Re-export all public APIs
|
|
2
|
-
export * from
|
|
2
|
+
export * from './useLiveQuery'
|
|
3
3
|
|
|
4
4
|
// Re-export everything from @tanstack/db
|
|
5
|
-
export * from
|
|
5
|
+
export * from '@tanstack/db'
|
|
6
6
|
|
|
7
7
|
// Re-export some stuff explicitly to ensure the type & value is exported
|
|
8
|
-
export type { Collection } from
|
|
9
|
-
export { createTransaction } from
|
|
8
|
+
export type { Collection } from '@tanstack/db'
|
|
9
|
+
export { createTransaction } from '@tanstack/db'
|
package/src/useLiveQuery.ts
CHANGED
|
@@ -5,11 +5,15 @@ import {
|
|
|
5
5
|
createResource,
|
|
6
6
|
createSignal,
|
|
7
7
|
onCleanup,
|
|
8
|
-
} from
|
|
9
|
-
import { ReactiveMap } from
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
} from 'solid-js'
|
|
9
|
+
import { ReactiveMap } from '@solid-primitives/map'
|
|
10
|
+
import {
|
|
11
|
+
BaseQueryBuilder,
|
|
12
|
+
CollectionImpl,
|
|
13
|
+
createLiveQueryCollection,
|
|
14
|
+
} from '@tanstack/db'
|
|
15
|
+
import { createStore, reconcile } from 'solid-js/store'
|
|
16
|
+
import type { Accessor } from 'solid-js'
|
|
13
17
|
import type {
|
|
14
18
|
ChangeMessage,
|
|
15
19
|
Collection,
|
|
@@ -19,7 +23,7 @@ import type {
|
|
|
19
23
|
InitialQueryBuilder,
|
|
20
24
|
LiveQueryCollectionConfig,
|
|
21
25
|
QueryBuilder,
|
|
22
|
-
} from
|
|
26
|
+
} from '@tanstack/db'
|
|
23
27
|
|
|
24
28
|
/**
|
|
25
29
|
* Create a live query using a query function
|
|
@@ -76,9 +80,9 @@ import type {
|
|
|
76
80
|
* </Switch>
|
|
77
81
|
* )
|
|
78
82
|
*/
|
|
79
|
-
// Overload 1: Accept
|
|
83
|
+
// Overload 1: Accept query function that always returns QueryBuilder
|
|
80
84
|
export function useLiveQuery<TContext extends Context>(
|
|
81
|
-
queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext
|
|
85
|
+
queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext>,
|
|
82
86
|
): {
|
|
83
87
|
state: ReactiveMap<string | number, GetResult<TContext>>
|
|
84
88
|
data: Array<GetResult<TContext>>
|
|
@@ -91,6 +95,27 @@ export function useLiveQuery<TContext extends Context>(
|
|
|
91
95
|
isCleanedUp: Accessor<boolean>
|
|
92
96
|
}
|
|
93
97
|
|
|
98
|
+
// Overload 1b: Accept query function that can return undefined/null
|
|
99
|
+
export function useLiveQuery<TContext extends Context>(
|
|
100
|
+
queryFn: (
|
|
101
|
+
q: InitialQueryBuilder,
|
|
102
|
+
) => QueryBuilder<TContext> | undefined | null,
|
|
103
|
+
): {
|
|
104
|
+
state: ReactiveMap<string | number, GetResult<TContext>>
|
|
105
|
+
data: Array<GetResult<TContext>>
|
|
106
|
+
collection: Accessor<Collection<
|
|
107
|
+
GetResult<TContext>,
|
|
108
|
+
string | number,
|
|
109
|
+
{}
|
|
110
|
+
> | null>
|
|
111
|
+
status: Accessor<CollectionStatus | `disabled`>
|
|
112
|
+
isLoading: Accessor<boolean>
|
|
113
|
+
isReady: Accessor<boolean>
|
|
114
|
+
isIdle: Accessor<boolean>
|
|
115
|
+
isError: Accessor<boolean>
|
|
116
|
+
isCleanedUp: Accessor<boolean>
|
|
117
|
+
}
|
|
118
|
+
|
|
94
119
|
/**
|
|
95
120
|
* Create a live query using configuration object
|
|
96
121
|
* @param config - Configuration object with query and options
|
|
@@ -133,7 +158,7 @@ export function useLiveQuery<TContext extends Context>(
|
|
|
133
158
|
*/
|
|
134
159
|
// Overload 2: Accept config object
|
|
135
160
|
export function useLiveQuery<TContext extends Context>(
|
|
136
|
-
config: Accessor<LiveQueryCollectionConfig<TContext
|
|
161
|
+
config: Accessor<LiveQueryCollectionConfig<TContext>>,
|
|
137
162
|
): {
|
|
138
163
|
state: ReactiveMap<string | number, GetResult<TContext>>
|
|
139
164
|
data: Array<GetResult<TContext>>
|
|
@@ -187,7 +212,7 @@ export function useLiveQuery<
|
|
|
187
212
|
TKey extends string | number,
|
|
188
213
|
TUtils extends Record<string, any>,
|
|
189
214
|
>(
|
|
190
|
-
liveQueryCollection: Accessor<Collection<TResult, TKey, TUtils
|
|
215
|
+
liveQueryCollection: Accessor<Collection<TResult, TKey, TUtils>>,
|
|
191
216
|
): {
|
|
192
217
|
state: ReactiveMap<TKey, TResult>
|
|
193
218
|
data: Array<TResult>
|
|
@@ -202,11 +227,20 @@ export function useLiveQuery<
|
|
|
202
227
|
|
|
203
228
|
// Implementation - use function overloads to infer the actual collection type
|
|
204
229
|
export function useLiveQuery(
|
|
205
|
-
configOrQueryOrCollection: (queryFn?: any) => any
|
|
230
|
+
configOrQueryOrCollection: (queryFn?: any) => any,
|
|
206
231
|
) {
|
|
207
232
|
const collection = createMemo(
|
|
208
233
|
() => {
|
|
209
234
|
if (configOrQueryOrCollection.length === 1) {
|
|
235
|
+
// This is a query function - check if it returns null/undefined
|
|
236
|
+
const queryBuilder = new BaseQueryBuilder() as InitialQueryBuilder
|
|
237
|
+
const result = configOrQueryOrCollection(queryBuilder)
|
|
238
|
+
|
|
239
|
+
if (result === undefined || result === null) {
|
|
240
|
+
// Disabled query - return null
|
|
241
|
+
return null
|
|
242
|
+
}
|
|
243
|
+
|
|
210
244
|
return createLiveQueryCollection({
|
|
211
245
|
query: configOrQueryOrCollection,
|
|
212
246
|
startSync: true,
|
|
@@ -214,6 +248,12 @@ export function useLiveQuery(
|
|
|
214
248
|
}
|
|
215
249
|
|
|
216
250
|
const innerCollection = configOrQueryOrCollection()
|
|
251
|
+
|
|
252
|
+
if (innerCollection === undefined || innerCollection === null) {
|
|
253
|
+
// Disabled query - return null
|
|
254
|
+
return null
|
|
255
|
+
}
|
|
256
|
+
|
|
217
257
|
if (innerCollection instanceof CollectionImpl) {
|
|
218
258
|
innerCollection.startSyncImmediate()
|
|
219
259
|
return innerCollection as Collection
|
|
@@ -225,7 +265,7 @@ export function useLiveQuery(
|
|
|
225
265
|
})
|
|
226
266
|
},
|
|
227
267
|
undefined,
|
|
228
|
-
{ name: `TanstackDBCollectionMemo` }
|
|
268
|
+
{ name: `TanstackDBCollectionMemo` },
|
|
229
269
|
)
|
|
230
270
|
|
|
231
271
|
// Reactive state that gets updated granularly through change events
|
|
@@ -237,16 +277,19 @@ export function useLiveQuery(
|
|
|
237
277
|
})
|
|
238
278
|
|
|
239
279
|
// Track collection status reactively
|
|
240
|
-
const [status, setStatus] = createSignal(
|
|
241
|
-
|
|
242
|
-
|
|
280
|
+
const [status, setStatus] = createSignal(
|
|
281
|
+
collection() ? collection()!.status : (`disabled` as const),
|
|
282
|
+
{
|
|
283
|
+
name: `TanstackDBStatus`,
|
|
284
|
+
},
|
|
285
|
+
)
|
|
243
286
|
|
|
244
287
|
// Helper to sync data array from collection in correct order
|
|
245
288
|
const syncDataFromCollection = (
|
|
246
|
-
currentCollection: Collection<any, any, any
|
|
289
|
+
currentCollection: Collection<any, any, any>,
|
|
247
290
|
) => {
|
|
248
291
|
setData((prev) =>
|
|
249
|
-
reconcile(Array.from(currentCollection.values()))(prev).filter(Boolean)
|
|
292
|
+
reconcile(Array.from(currentCollection.values()))(prev).filter(Boolean),
|
|
250
293
|
)
|
|
251
294
|
}
|
|
252
295
|
|
|
@@ -257,6 +300,18 @@ export function useLiveQuery(
|
|
|
257
300
|
() => {
|
|
258
301
|
const currentCollection = collection()
|
|
259
302
|
|
|
303
|
+
// Handle null collection (disabled query)
|
|
304
|
+
if (!currentCollection) {
|
|
305
|
+
setStatus(`disabled` as const)
|
|
306
|
+
state.clear()
|
|
307
|
+
setData([])
|
|
308
|
+
if (currentUnsubscribe) {
|
|
309
|
+
currentUnsubscribe()
|
|
310
|
+
currentUnsubscribe = null
|
|
311
|
+
}
|
|
312
|
+
return
|
|
313
|
+
}
|
|
314
|
+
|
|
260
315
|
// Update status ref whenever the effect runs
|
|
261
316
|
setStatus(currentCollection.status)
|
|
262
317
|
|
|
@@ -292,7 +347,7 @@ export function useLiveQuery(
|
|
|
292
347
|
},
|
|
293
348
|
{
|
|
294
349
|
includeInitialState: true,
|
|
295
|
-
}
|
|
350
|
+
},
|
|
296
351
|
)
|
|
297
352
|
|
|
298
353
|
currentUnsubscribe = subscription.unsubscribe.bind(subscription)
|
|
@@ -311,7 +366,7 @@ export function useLiveQuery(
|
|
|
311
366
|
})
|
|
312
367
|
},
|
|
313
368
|
undefined,
|
|
314
|
-
{ name: `TanstackDBSyncComputed` }
|
|
369
|
+
{ name: `TanstackDBSyncComputed` },
|
|
315
370
|
)
|
|
316
371
|
|
|
317
372
|
return {
|
|
@@ -320,7 +375,7 @@ export function useLiveQuery(
|
|
|
320
375
|
collection,
|
|
321
376
|
status,
|
|
322
377
|
isLoading: () => status() === `loading`,
|
|
323
|
-
isReady: () => status() === `ready`,
|
|
378
|
+
isReady: () => status() === `ready` || status() === `disabled`,
|
|
324
379
|
isIdle: () => status() === `idle`,
|
|
325
380
|
isError: () => status() === `error`,
|
|
326
381
|
isCleanedUp: () => status() === `cleaned-up`,
|