@tanstack/db-collections
Version:
A collection for (aspirationally) every way of loading your data
175 lines (174 loc) • 7.18 kB
text/typescript
import { QueryClient, QueryFunctionContext, QueryKey, QueryObserverOptions } from '@tanstack/query-core';
import { CollectionConfig, DeleteMutationFn, InsertMutationFn, UpdateMutationFn, UtilsRecord } from '@tanstack/db';
export interface QueryCollectionConfig<TItem extends object, TError = unknown, TQueryKey extends QueryKey = QueryKey> {
queryKey: TQueryKey;
queryFn: (context: QueryFunctionContext<TQueryKey>) => Promise<Array<TItem>>;
queryClient: QueryClient;
enabled?: boolean;
refetchInterval?: QueryObserverOptions<Array<TItem>, TError, Array<TItem>, Array<TItem>, TQueryKey>[`refetchInterval`];
retry?: QueryObserverOptions<Array<TItem>, TError, Array<TItem>, Array<TItem>, TQueryKey>[`retry`];
retryDelay?: QueryObserverOptions<Array<TItem>, TError, Array<TItem>, Array<TItem>, TQueryKey>[`retryDelay`];
staleTime?: QueryObserverOptions<Array<TItem>, TError, Array<TItem>, Array<TItem>, TQueryKey>[`staleTime`];
id?: string;
getKey: CollectionConfig<TItem>[`getKey`];
schema?: CollectionConfig<TItem>[`schema`];
sync?: CollectionConfig<TItem>[`sync`];
startSync?: CollectionConfig<TItem>[`startSync`];
/**
* Optional asynchronous handler function called before an insert operation
* @param params Object containing transaction and collection information
* @returns Promise resolving to void or { refetch?: boolean } to control refetching
* @example
* // Basic query collection insert handler
* onInsert: async ({ transaction }) => {
* const newItem = transaction.mutations[0].modified
* await api.createTodo(newItem)
* // Automatically refetches query after insert
* }
*
* @example
* // Insert handler with refetch control
* onInsert: async ({ transaction }) => {
* const newItem = transaction.mutations[0].modified
* await api.createTodo(newItem)
* return { refetch: false } // Skip automatic refetch
* }
*
* @example
* // Insert handler with multiple items
* onInsert: async ({ transaction }) => {
* const items = transaction.mutations.map(m => m.modified)
* await api.createTodos(items)
* // Will refetch query to get updated data
* }
*
* @example
* // Insert handler with error handling
* onInsert: async ({ transaction }) => {
* try {
* const newItem = transaction.mutations[0].modified
* await api.createTodo(newItem)
* } catch (error) {
* console.error('Insert failed:', error)
* throw error // Transaction will rollback optimistic changes
* }
* }
*/
onInsert?: InsertMutationFn<TItem>;
/**
* Optional asynchronous handler function called before an update operation
* @param params Object containing transaction and collection information
* @returns Promise resolving to void or { refetch?: boolean } to control refetching
* @example
* // Basic query collection update handler
* onUpdate: async ({ transaction }) => {
* const mutation = transaction.mutations[0]
* await api.updateTodo(mutation.original.id, mutation.changes)
* // Automatically refetches query after update
* }
*
* @example
* // Update handler with multiple items
* onUpdate: async ({ transaction }) => {
* const updates = transaction.mutations.map(m => ({
* id: m.key,
* changes: m.changes
* }))
* await api.updateTodos(updates)
* // Will refetch query to get updated data
* }
*
* @example
* // Update handler with manual refetch
* onUpdate: async ({ transaction, collection }) => {
* const mutation = transaction.mutations[0]
* await api.updateTodo(mutation.original.id, mutation.changes)
*
* // Manually trigger refetch
* await collection.utils.refetch()
*
* return { refetch: false } // Skip automatic refetch
* }
*
* @example
* // Update handler with related collection refetch
* onUpdate: async ({ transaction, collection }) => {
* const mutation = transaction.mutations[0]
* await api.updateTodo(mutation.original.id, mutation.changes)
*
* // Refetch related collections when this item changes
* await Promise.all([
* collection.utils.refetch(), // Refetch this collection
* usersCollection.utils.refetch(), // Refetch users
* tagsCollection.utils.refetch() // Refetch tags
* ])
*
* return { refetch: false } // Skip automatic refetch since we handled it manually
* }
*/
onUpdate?: UpdateMutationFn<TItem>;
/**
* Optional asynchronous handler function called before a delete operation
* @param params Object containing transaction and collection information
* @returns Promise resolving to void or { refetch?: boolean } to control refetching
* @example
* // Basic query collection delete handler
* onDelete: async ({ transaction }) => {
* const mutation = transaction.mutations[0]
* await api.deleteTodo(mutation.original.id)
* // Automatically refetches query after delete
* }
*
* @example
* // Delete handler with refetch control
* onDelete: async ({ transaction }) => {
* const mutation = transaction.mutations[0]
* await api.deleteTodo(mutation.original.id)
* return { refetch: false } // Skip automatic refetch
* }
*
* @example
* // Delete handler with multiple items
* onDelete: async ({ transaction }) => {
* const keysToDelete = transaction.mutations.map(m => m.key)
* await api.deleteTodos(keysToDelete)
* // Will refetch query to get updated data
* }
*
* @example
* // Delete handler with related collection refetch
* onDelete: async ({ transaction, collection }) => {
* const mutation = transaction.mutations[0]
* await api.deleteTodo(mutation.original.id)
*
* // Refetch related collections when this item is deleted
* await Promise.all([
* collection.utils.refetch(), // Refetch this collection
* usersCollection.utils.refetch(), // Refetch users
* projectsCollection.utils.refetch() // Refetch projects
* ])
*
* return { refetch: false } // Skip automatic refetch since we handled it manually
* }
*/
onDelete?: DeleteMutationFn<TItem>;
}
/**
* Type for the refetch utility function
*/
export type RefetchFn = () => Promise<void>;
/**
* Query collection utilities type
*/
export interface QueryCollectionUtils extends UtilsRecord {
refetch: RefetchFn;
}
/**
* Creates query collection options for use with a standard Collection
*
* @param config - Configuration options for the Query collection
* @returns Collection options with utilities
*/
export declare function queryCollectionOptions<TItem extends object, TError = unknown, TQueryKey extends QueryKey = QueryKey>(config: QueryCollectionConfig<TItem, TError, TQueryKey>): CollectionConfig<TItem> & {
utils: QueryCollectionUtils;
};