UNPKG

@tanstack/vue-db

Version:

Vue integration for @tanstack/db

173 lines (172 loc) 7.66 kB
import { Collection, CollectionStatus, Context, GetResult, InferResultType, InitialQueryBuilder, LiveQueryCollectionConfig, NonSingleResult, QueryBuilder, SingleResult } from '@tanstack/db'; import { ComputedRef, MaybeRefOrGetter } from 'vue'; /** * Return type for useLiveQuery hook * @property state - Reactive Map of query results (key → item) * @property data - Reactive array of query results in order, or single result for findOne queries * @property collection - The underlying query collection instance * @property status - Current query status * @property isLoading - True while initial query data is loading * @property isReady - True when query has received first data and is ready * @property isIdle - True when query hasn't started yet * @property isError - True when query encountered an error * @property isCleanedUp - True when query has been cleaned up */ export interface UseLiveQueryReturn<TContext extends Context> { state: ComputedRef<Map<string | number, GetResult<TContext>>>; data: ComputedRef<InferResultType<TContext>>; collection: ComputedRef<Collection<GetResult<TContext>, string | number, {}>>; status: ComputedRef<CollectionStatus>; isLoading: ComputedRef<boolean>; isReady: ComputedRef<boolean>; isIdle: ComputedRef<boolean>; isError: ComputedRef<boolean>; isCleanedUp: ComputedRef<boolean>; } export interface UseLiveQueryReturnWithCollection<T extends object, TKey extends string | number, TUtils extends Record<string, any>> { state: ComputedRef<Map<TKey, T>>; data: ComputedRef<Array<T>>; collection: ComputedRef<Collection<T, TKey, TUtils>>; status: ComputedRef<CollectionStatus>; isLoading: ComputedRef<boolean>; isReady: ComputedRef<boolean>; isIdle: ComputedRef<boolean>; isError: ComputedRef<boolean>; isCleanedUp: ComputedRef<boolean>; } export interface UseLiveQueryReturnWithSingleResultCollection<T extends object, TKey extends string | number, TUtils extends Record<string, any>> { state: ComputedRef<Map<TKey, T>>; data: ComputedRef<T | undefined>; collection: ComputedRef<Collection<T, TKey, TUtils> & SingleResult>; status: ComputedRef<CollectionStatus>; isLoading: ComputedRef<boolean>; isReady: ComputedRef<boolean>; isIdle: ComputedRef<boolean>; isError: ComputedRef<boolean>; isCleanedUp: ComputedRef<boolean>; } /** * Create a live query using a query function * @param queryFn - Query function that defines what data to fetch * @param deps - Array of reactive dependencies that trigger query re-execution when changed * @returns Reactive object with query data, state, and status information * @example * // Basic query with object syntax * const { data, isLoading } = useLiveQuery((q) => * q.from({ todos: todosCollection }) * .where(({ todos }) => eq(todos.completed, false)) * .select(({ todos }) => ({ id: todos.id, text: todos.text })) * ) * * @example * // With reactive dependencies * const minPriority = ref(5) * const { data, state } = useLiveQuery( * (q) => q.from({ todos: todosCollection }) * .where(({ todos }) => gt(todos.priority, minPriority.value)), * [minPriority] // Re-run when minPriority changes * ) * * @example * // Join pattern * const { data } = useLiveQuery((q) => * q.from({ issues: issueCollection }) * .join({ persons: personCollection }, ({ issues, persons }) => * eq(issues.userId, persons.id) * ) * .select(({ issues, persons }) => ({ * id: issues.id, * title: issues.title, * userName: persons.name * })) * ) * * @example * // Handle loading and error states in template * const { data, isLoading, isError, status } = useLiveQuery((q) => * q.from({ todos: todoCollection }) * ) * * // In template: * // <div v-if="isLoading">Loading...</div> * // <div v-else-if="isError">Error: {{ status }}</div> * // <ul v-else> * // <li v-for="todo in data" :key="todo.id">{{ todo.text }}</li> * // </ul> */ export declare function useLiveQuery<TContext extends Context>(queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext>, deps?: Array<MaybeRefOrGetter<unknown>>): UseLiveQueryReturn<TContext>; export declare function useLiveQuery<TContext extends Context>(queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext> | undefined | null, deps?: Array<MaybeRefOrGetter<unknown>>): UseLiveQueryReturn<TContext>; /** * Create a live query using configuration object * @param config - Configuration object with query and options * @param deps - Array of reactive dependencies that trigger query re-execution when changed * @returns Reactive object with query data, state, and status information * @example * // Basic config object usage * const { data, status } = useLiveQuery({ * query: (q) => q.from({ todos: todosCollection }), * gcTime: 60000 * }) * * @example * // With reactive dependencies * const filter = ref('active') * const { data, isReady } = useLiveQuery({ * query: (q) => q.from({ todos: todosCollection }) * .where(({ todos }) => eq(todos.status, filter.value)) * }, [filter]) * * @example * // Handle all states uniformly * const { data, isLoading, isReady, isError } = useLiveQuery({ * query: (q) => q.from({ items: itemCollection }) * }) * * // In template: * // <div v-if="isLoading">Loading...</div> * // <div v-else-if="isError">Something went wrong</div> * // <div v-else-if="!isReady">Preparing...</div> * // <div v-else>{{ data.length }} items loaded</div> */ export declare function useLiveQuery<TContext extends Context>(config: LiveQueryCollectionConfig<TContext>, deps?: Array<MaybeRefOrGetter<unknown>>): UseLiveQueryReturn<TContext>; /** * Subscribe to an existing query collection (can be reactive) * @param liveQueryCollection - Pre-created query collection to subscribe to (can be a ref) * @returns Reactive object with query data, state, and status information * @example * // Using pre-created query collection * const myLiveQuery = createLiveQueryCollection((q) => * q.from({ todos: todosCollection }).where(({ todos }) => eq(todos.active, true)) * ) * const { data, collection } = useLiveQuery(myLiveQuery) * * @example * // Reactive query collection reference * const selectedQuery = ref(todosQuery) * const { data, collection } = useLiveQuery(selectedQuery) * * // Switch queries reactively * selectedQuery.value = archiveQuery * * @example * // Access query collection methods directly * const { data, collection, isReady } = useLiveQuery(existingQuery) * * // Use underlying collection for mutations * const handleToggle = (id) => { * collection.value.update(id, draft => { draft.completed = !draft.completed }) * } * * @example * // Handle states consistently * const { data, isLoading, isError } = useLiveQuery(sharedQuery) * * // In template: * // <div v-if="isLoading">Loading...</div> * // <div v-else-if="isError">Error loading data</div> * // <div v-else> * // <Item v-for="item in data" :key="item.id" v-bind="item" /> * // </div> */ export declare function useLiveQuery<TResult extends object, TKey extends string | number, TUtils extends Record<string, any>>(liveQueryCollection: MaybeRefOrGetter<Collection<TResult, TKey, TUtils> & NonSingleResult>): UseLiveQueryReturnWithCollection<TResult, TKey, TUtils>; export declare function useLiveQuery<TResult extends object, TKey extends string | number, TUtils extends Record<string, any>>(liveQueryCollection: MaybeRefOrGetter<Collection<TResult, TKey, TUtils> & SingleResult>): UseLiveQueryReturnWithSingleResultCollection<TResult, TKey, TUtils>;