{"version":3,"file":"useLiveQuery.cjs","sources":["../../src/useLiveQuery.ts"],"sourcesContent":["import { useRef, useSyncExternalStore } from 'react'\nimport {\n  BaseQueryBuilder,\n  CollectionImpl,\n  createLiveQueryCollection,\n} from '@tanstack/db'\nimport type {\n  Collection,\n  CollectionConfigSingleRowOption,\n  CollectionStatus,\n  Context,\n  GetResult,\n  InferResultType,\n  InitialQueryBuilder,\n  LiveQueryCollectionConfig,\n  NonSingleResult,\n  QueryBuilder,\n  SingleResult,\n} from '@tanstack/db'\n\nconst DEFAULT_GC_TIME_MS = 1 // Live queries created by useLiveQuery are cleaned up immediately (0 disables GC)\n\nexport type UseLiveQueryStatus = CollectionStatus | `disabled`\n\n/**\n * Create a live query using a query function\n * @param queryFn - Query function that defines what data to fetch\n * @param deps - Array of dependencies that trigger query re-execution when changed\n * @returns Object with reactive data, state, and status information\n * @example\n * // Basic query with object syntax\n * const { data, isLoading } = 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 * // Single result query\n * const { data } = useLiveQuery(\n *   (q) => q.from({ todos: todosCollection })\n *          .where(({ todos }) => eq(todos.id, 1))\n *          .findOne()\n * )\n *\n * @example\n * // With dependencies that trigger re-execution\n * const { data, state } = useLiveQuery(\n *   (q) => q.from({ todos: todosCollection })\n *          .where(({ todos }) => gt(todos.priority, minPriority)),\n *   [minPriority] // Re-run when minPriority changes\n * )\n *\n * @example\n * // Join pattern\n * const { data } = 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 { data, isLoading, isError, status } = useLiveQuery((q) =>\n *   q.from({ todos: todoCollection })\n * )\n *\n * if (isLoading) return <div>Loading...</div>\n * if (isError) return <div>Error: {status}</div>\n *\n * return (\n *   <ul>\n *     {data.map(todo => <li key={todo.id}>{todo.text}</li>)}\n *   </ul>\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  deps?: Array<unknown>,\n): {\n  state: Map<string | number, GetResult<TContext>>\n  data: InferResultType<TContext>\n  collection: Collection<GetResult<TContext>, string | number, {}>\n  status: CollectionStatus // Can't be disabled if always returns QueryBuilder\n  isLoading: boolean\n  isReady: boolean\n  isIdle: boolean\n  isError: boolean\n  isCleanedUp: boolean\n  isEnabled: true // Always true if always returns QueryBuilder\n}\n\n// Overload 2: 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  deps?: Array<unknown>,\n): {\n  state: Map<string | number, GetResult<TContext>> | undefined\n  data: InferResultType<TContext> | undefined\n  collection: Collection<GetResult<TContext>, string | number, {}> | undefined\n  status: UseLiveQueryStatus\n  isLoading: boolean\n  isReady: boolean\n  isIdle: boolean\n  isError: boolean\n  isCleanedUp: boolean\n  isEnabled: boolean\n}\n\n// Overload 3: Accept query function that can return LiveQueryCollectionConfig\nexport function useLiveQuery<TContext extends Context>(\n  queryFn: (\n    q: InitialQueryBuilder,\n  ) => LiveQueryCollectionConfig<TContext> | undefined | null,\n  deps?: Array<unknown>,\n): {\n  state: Map<string | number, GetResult<TContext>> | undefined\n  data: InferResultType<TContext> | undefined\n  collection: Collection<GetResult<TContext>, string | number, {}> | undefined\n  status: UseLiveQueryStatus\n  isLoading: boolean\n  isReady: boolean\n  isIdle: boolean\n  isError: boolean\n  isCleanedUp: boolean\n  isEnabled: boolean\n}\n\n// Overload 4: Accept query function that can return Collection\nexport function useLiveQuery<\n  TResult extends object,\n  TKey extends string | number,\n  TUtils extends Record<string, any>,\n>(\n  queryFn: (\n    q: InitialQueryBuilder,\n  ) => Collection<TResult, TKey, TUtils> | undefined | null,\n  deps?: Array<unknown>,\n): {\n  state: Map<TKey, TResult> | undefined\n  data: Array<TResult> | undefined\n  collection: Collection<TResult, TKey, TUtils> | undefined\n  status: UseLiveQueryStatus\n  isLoading: boolean\n  isReady: boolean\n  isIdle: boolean\n  isError: boolean\n  isCleanedUp: boolean\n  isEnabled: boolean\n}\n\n// Overload 5: Accept query function that can return all types\nexport function useLiveQuery<\n  TContext extends Context,\n  TResult extends object,\n  TKey extends string | number,\n  TUtils extends Record<string, any>,\n>(\n  queryFn: (\n    q: InitialQueryBuilder,\n  ) =>\n    | QueryBuilder<TContext>\n    | LiveQueryCollectionConfig<TContext>\n    | Collection<TResult, TKey, TUtils>\n    | undefined\n    | null,\n  deps?: Array<unknown>,\n): {\n  state:\n    | Map<string | number, GetResult<TContext>>\n    | Map<TKey, TResult>\n    | undefined\n  data: InferResultType<TContext> | Array<TResult> | undefined\n  collection:\n    | Collection<GetResult<TContext>, string | number, {}>\n    | Collection<TResult, TKey, TUtils>\n    | undefined\n  status: UseLiveQueryStatus\n  isLoading: boolean\n  isReady: boolean\n  isIdle: boolean\n  isError: boolean\n  isCleanedUp: boolean\n  isEnabled: boolean\n}\n\n/**\n * Create a live query using configuration object\n * @param config - Configuration object with query and options\n * @param deps - Array of dependencies that trigger query re-execution when changed\n * @returns Object with reactive data, state, and status information\n * @example\n * // Basic config object usage\n * const { data, status } = 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 { data, isReady } = useLiveQuery({ query: queryBuilder })\n *\n * @example\n * // Handle all states uniformly\n * const { data, isLoading, isReady, isError } = useLiveQuery({\n *   query: (q) => q.from({ items: itemCollection })\n * })\n *\n * if (isLoading) return <div>Loading...</div>\n * if (isError) return <div>Something went wrong</div>\n * if (!isReady) return <div>Preparing...</div>\n *\n * return <div>{data.length} items loaded</div>\n */\n// Overload 6: Accept config object\nexport function useLiveQuery<TContext extends Context>(\n  config: LiveQueryCollectionConfig<TContext>,\n  deps?: Array<unknown>,\n): {\n  state: Map<string | number, GetResult<TContext>>\n  data: InferResultType<TContext>\n  collection: Collection<GetResult<TContext>, string | number, {}>\n  status: CollectionStatus // Can't be disabled for config objects\n  isLoading: boolean\n  isReady: boolean\n  isIdle: boolean\n  isError: boolean\n  isCleanedUp: boolean\n  isEnabled: true // Always true for config objects\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 { data, collection } = useLiveQuery(myLiveQuery)\n *\n * @example\n * // Access collection methods directly\n * const { data, collection, isReady } = useLiveQuery(existingCollection)\n *\n * // Use collection for mutations\n * const handleToggle = (id) => {\n *   collection.update(id, draft => { draft.completed = !draft.completed })\n * }\n *\n * @example\n * // Handle states consistently\n * const { data, isLoading, isError } = useLiveQuery(sharedCollection)\n *\n * if (isLoading) return <div>Loading...</div>\n * if (isError) return <div>Error loading data</div>\n *\n * return <div>{data.map(item => <Item key={item.id} {...item} />)}</div>\n */\n// Overload 7: 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: Collection<TResult, TKey, TUtils> & NonSingleResult,\n): {\n  state: Map<TKey, TResult>\n  data: Array<TResult>\n  collection: Collection<TResult, TKey, TUtils>\n  status: CollectionStatus // Can't be disabled for pre-created live query collections\n  isLoading: boolean\n  isReady: boolean\n  isIdle: boolean\n  isError: boolean\n  isCleanedUp: boolean\n  isEnabled: true // Always true for pre-created live query collections\n}\n\n// Overload 8: Accept pre-created live query collection with singleResult: true\nexport function useLiveQuery<\n  TResult extends object,\n  TKey extends string | number,\n  TUtils extends Record<string, any>,\n>(\n  liveQueryCollection: Collection<TResult, TKey, TUtils> & SingleResult,\n): {\n  state: Map<TKey, TResult>\n  data: TResult | undefined\n  collection: Collection<TResult, TKey, TUtils> & SingleResult\n  status: CollectionStatus // Can't be disabled for pre-created live query collections\n  isLoading: boolean\n  isReady: boolean\n  isIdle: boolean\n  isError: boolean\n  isCleanedUp: boolean\n  isEnabled: true // Always true for pre-created live query collections\n}\n\n// Implementation - use function overloads to infer the actual collection type\nexport function useLiveQuery(\n  configOrQueryOrCollection: any,\n  deps: Array<unknown> = [],\n) {\n  // Check if it's already a collection by checking for specific collection methods\n  const isCollection =\n    configOrQueryOrCollection &&\n    typeof configOrQueryOrCollection === `object` &&\n    typeof configOrQueryOrCollection.subscribeChanges === `function` &&\n    typeof configOrQueryOrCollection.startSyncImmediate === `function` &&\n    typeof configOrQueryOrCollection.id === `string`\n\n  // Use refs to cache collection and track dependencies\n  const collectionRef = useRef<Collection<object, string | number, {}> | null>(\n    null,\n  )\n  const depsRef = useRef<Array<unknown> | null>(null)\n  const configRef = useRef<unknown>(null)\n\n  // Use refs to track version and memoized snapshot\n  const versionRef = useRef(0)\n  const snapshotRef = useRef<{\n    collection: Collection<object, string | number, {}> | null\n    version: number\n  } | null>(null)\n\n  // Check if we need to create/recreate the collection\n  const needsNewCollection =\n    !collectionRef.current ||\n    (isCollection && configRef.current !== configOrQueryOrCollection) ||\n    (!isCollection &&\n      (depsRef.current === null ||\n        depsRef.current.length !== deps.length ||\n        depsRef.current.some((dep, i) => dep !== deps[i])))\n\n  if (needsNewCollection) {\n    if (isCollection) {\n      // Warn when passing a collection directly with on-demand sync mode\n      // In on-demand mode, data is only loaded when queries with predicates request it\n      // Passing the collection directly doesn't provide any predicates, so no data loads\n      const syncMode = (\n        configOrQueryOrCollection as { config?: { syncMode?: string } }\n      ).config?.syncMode\n      if (syncMode === `on-demand`) {\n        console.warn(\n          `[useLiveQuery] Warning: Passing a collection with syncMode \"on-demand\" directly to useLiveQuery ` +\n            `will not load any data. In on-demand mode, data is only loaded when queries with predicates request it.\\n\\n` +\n            `Instead, use a query builder function:\\n` +\n            `  const { data } = useLiveQuery((q) => q.from({ c: myCollection }).select(({ c }) => c))\\n\\n` +\n            `Or switch to syncMode \"eager\" if you want all data to sync automatically.`,\n        )\n      }\n      // It's already a collection, ensure sync is started for React hooks\n      configOrQueryOrCollection.startSyncImmediate()\n      collectionRef.current = configOrQueryOrCollection\n      configRef.current = configOrQueryOrCollection\n    } else {\n      // Handle different callback return types\n      if (typeof configOrQueryOrCollection === `function`) {\n        // Call the function with a query builder to see what it returns\n        const queryBuilder = new BaseQueryBuilder() as InitialQueryBuilder\n        const result = configOrQueryOrCollection(queryBuilder)\n\n        if (result === undefined || result === null) {\n          // Callback returned undefined/null - disabled query\n          collectionRef.current = null\n        } else if (result instanceof CollectionImpl) {\n          // Callback returned a Collection instance - use it directly\n          result.startSyncImmediate()\n          collectionRef.current = result\n        } else if (result instanceof BaseQueryBuilder) {\n          // Callback returned QueryBuilder - create live query collection using the original callback\n          // (not the result, since the result might be from a different query builder instance)\n          collectionRef.current = createLiveQueryCollection({\n            query: configOrQueryOrCollection,\n            startSync: true,\n            gcTime: DEFAULT_GC_TIME_MS,\n          })\n        } else if (result && typeof result === `object`) {\n          // Assume it's a LiveQueryCollectionConfig\n          collectionRef.current = createLiveQueryCollection({\n            startSync: true,\n            gcTime: DEFAULT_GC_TIME_MS,\n            ...result,\n          })\n        } else {\n          // Unexpected return type\n          throw new Error(\n            `useLiveQuery callback must return a QueryBuilder, LiveQueryCollectionConfig, Collection, undefined, or null. Got: ${typeof result}`,\n          )\n        }\n        depsRef.current = [...deps]\n      } else {\n        // Original logic for config objects\n        collectionRef.current = createLiveQueryCollection({\n          startSync: true,\n          gcTime: DEFAULT_GC_TIME_MS,\n          ...configOrQueryOrCollection,\n        })\n        depsRef.current = [...deps]\n      }\n    }\n  }\n\n  // Reset refs when collection changes\n  if (needsNewCollection) {\n    versionRef.current = 0\n    snapshotRef.current = null\n  }\n\n  // Create stable subscribe function using ref\n  const subscribeRef = useRef<\n    ((onStoreChange: () => void) => () => void) | null\n  >(null)\n  if (!subscribeRef.current || needsNewCollection) {\n    subscribeRef.current = (onStoreChange: () => void) => {\n      // If no collection, return a no-op unsubscribe function\n      if (!collectionRef.current) {\n        return () => {}\n      }\n\n      const subscription = collectionRef.current.subscribeChanges(() => {\n        // Bump version on any change; getSnapshot will rebuild next time\n        versionRef.current += 1\n        onStoreChange()\n      })\n      // Collection may be ready and will not receive initial `subscribeChanges()`\n      if (collectionRef.current.status === `ready`) {\n        versionRef.current += 1\n        onStoreChange()\n      }\n      return () => {\n        subscription.unsubscribe()\n      }\n    }\n  }\n\n  // Create stable getSnapshot function using ref\n  const getSnapshotRef = useRef<\n    | (() => {\n        collection: Collection<object, string | number, {}> | null\n        version: number\n      })\n    | null\n  >(null)\n  if (!getSnapshotRef.current || needsNewCollection) {\n    getSnapshotRef.current = () => {\n      const currentVersion = versionRef.current\n      const currentCollection = collectionRef.current\n\n      // Recreate snapshot object only if version/collection changed\n      if (\n        !snapshotRef.current ||\n        snapshotRef.current.version !== currentVersion ||\n        snapshotRef.current.collection !== currentCollection\n      ) {\n        snapshotRef.current = {\n          collection: currentCollection,\n          version: currentVersion,\n        }\n      }\n\n      return snapshotRef.current\n    }\n  }\n\n  // Use useSyncExternalStore to subscribe to collection changes\n  const snapshot = useSyncExternalStore(\n    subscribeRef.current,\n    getSnapshotRef.current,\n  )\n\n  // Track last snapshot (from useSyncExternalStore) and the returned value separately\n  const returnedSnapshotRef = useRef<{\n    collection: Collection<object, string | number, {}> | null\n    version: number\n  } | null>(null)\n  // Keep implementation return loose to satisfy overload signatures\n  const returnedRef = useRef<any>(null)\n\n  // Rebuild returned object only when the snapshot changes (version or collection identity)\n  if (\n    !returnedSnapshotRef.current ||\n    returnedSnapshotRef.current.version !== snapshot.version ||\n    returnedSnapshotRef.current.collection !== snapshot.collection\n  ) {\n    // Handle null collection case (when callback returns undefined/null)\n    if (!snapshot.collection) {\n      returnedRef.current = {\n        state: undefined,\n        data: undefined,\n        collection: undefined,\n        status: `disabled`,\n        isLoading: false,\n        isReady: true,\n        isIdle: false,\n        isError: false,\n        isCleanedUp: false,\n        isEnabled: false,\n      }\n    } else {\n      // Capture a stable view of entries for this snapshot to avoid tearing\n      const entries = Array.from(snapshot.collection.entries())\n      const config: CollectionConfigSingleRowOption<any, any, any> =\n        snapshot.collection.config\n      const singleResult = config.singleResult\n      let stateCache: Map<string | number, unknown> | null = null\n      let dataCache: Array<unknown> | null = null\n\n      returnedRef.current = {\n        get state() {\n          if (!stateCache) {\n            stateCache = new Map(entries)\n          }\n          return stateCache\n        },\n        get data() {\n          if (!dataCache) {\n            dataCache = entries.map(([, value]) => value)\n          }\n          return singleResult ? dataCache[0] : dataCache\n        },\n        collection: snapshot.collection,\n        status: snapshot.collection.status,\n        isLoading: snapshot.collection.status === `loading`,\n        isReady: snapshot.collection.status === `ready`,\n        isIdle: snapshot.collection.status === `idle`,\n        isError: snapshot.collection.status === `error`,\n        isCleanedUp: snapshot.collection.status === `cleaned-up`,\n        isEnabled: true,\n      }\n    }\n\n    // Remember the snapshot that produced this returned value\n    returnedSnapshotRef.current = snapshot\n  }\n\n  return returnedRef.current!\n}\n"],"names":["useRef","BaseQueryBuilder","CollectionImpl","createLiveQueryCollection","useSyncExternalStore"],"mappings":"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"}