UNPKG

@tanstack/optimistic

Version:

Core optimistic updates library

177 lines (176 loc) 7.57 kB
import { Derived, Store } from '@tanstack/store'; import { SortedMap } from './SortedMap.cjs'; import { ChangeMessage, CollectionConfig, InsertConfig, OperationConfig, OptimisticChangeMessage, Transaction } from './types.cjs'; export declare const collectionsStore: Store<Map<string, Collection<any>>, (cb: Map<string, Collection<any>>) => Map<string, Collection<any>>>; /** * Preloads a collection with the given configuration * Returns a promise that resolves once the sync tool has done its first commit (initial sync is finished) * If the collection has already loaded, it resolves immediately * * This function is useful in route loaders or similar pre-rendering scenarios where you want * to ensure data is available before a route transition completes. It uses the same shared collection * instance that will be used by useCollection, ensuring data consistency. * * @example * ```typescript * // In a route loader * async function loader({ params }) { * await preloadCollection({ * id: `users-${params.userId}`, * sync: { ... }, * }); * * return null; * } * ``` * * @template T - The type of items in the collection * @param config - Configuration for the collection, including id and sync * @returns Promise that resolves when the initial sync is finished */ export declare function preloadCollection<T extends object = Record<string, unknown>>(config: CollectionConfig<T>): Promise<Collection<T>>; /** * Custom error class for schema validation errors */ export declare class SchemaValidationError extends Error { type: `insert` | `update`; issues: ReadonlyArray<{ message: string; path?: ReadonlyArray<string | number | symbol>; }>; constructor(type: `insert` | `update`, issues: ReadonlyArray<{ message: string; path?: ReadonlyArray<string | number | symbol>; }>, message?: string); } export declare class Collection<T extends object = Record<string, unknown>> { transactions: Store<SortedMap<string, Transaction>>; optimisticOperations: Derived<Array<OptimisticChangeMessage<T>>>; derivedState: Derived<Map<string, T>>; derivedArray: Derived<Array<T>>; derivedChanges: Derived<Array<ChangeMessage<T>>>; private syncedData; syncedMetadata: Store<Map<string, unknown>, (cb: Map<string, unknown>) => Map<string, unknown>>; private pendingSyncedTransactions; private syncedKeys; config: CollectionConfig<T>; private hasReceivedFirstCommit; objectKeyMap: WeakMap<object, string>; private onFirstCommitCallbacks; /** * Register a callback to be executed on the next commit * Useful for preloading collections * @param callback Function to call after the next commit */ onFirstCommit(callback: () => void): void; id: `${string}-${string}-${string}-${string}-${string}`; /** * Creates a new Collection instance * * @param config - Configuration object for the collection * @throws Error if sync config is missing */ constructor(config?: CollectionConfig<T>); /** * Attempts to commit pending synced transactions if there are no active transactions * This method processes operations from pending transactions and applies them to the synced data */ commitPendingTransactions: () => void; private ensureStandardSchema; private validateData; private generateKey; /** * Inserts one or more items into the collection * @param items - Single item or array of items to insert * @param config - Optional configuration including metadata and custom keys * @returns A Transaction object representing the insert operation(s) * @throws {SchemaValidationError} If the data fails schema validation * @example * // Insert a single item * insert({ text: "Buy groceries", completed: false }) * * // Insert multiple items * insert([ * { text: "Buy groceries", completed: false }, * { text: "Walk dog", completed: false } * ]) * * // Insert with custom key * insert({ text: "Buy groceries" }, { key: "grocery-task" }) */ insert: (data: T | Array<T>, config?: InsertConfig) => Transaction; /** * Updates one or more items in the collection using a callback function * @param items - Single item/key or array of items/keys to update * @param configOrCallback - Either update configuration or update callback * @param maybeCallback - Update callback if config was provided * @returns A Transaction object representing the update operation(s) * @throws {SchemaValidationError} If the updated data fails schema validation * @example * // Update a single item * update(todo, (draft) => { draft.completed = true }) * * // Update multiple items * update([todo1, todo2], (drafts) => { * drafts.forEach(draft => { draft.completed = true }) * }) * * // Update with metadata * update(todo, { metadata: { reason: "user update" } }, (draft) => { draft.text = "Updated text" }) */ update<TItem extends object = T>(item: TItem, configOrCallback: ((draft: TItem) => void) | OperationConfig, maybeCallback?: (draft: TItem) => void): Transaction; update<TItem extends object = T>(items: Array<TItem>, configOrCallback: ((draft: Array<TItem>) => void) | OperationConfig, maybeCallback?: (draft: Array<TItem>) => void): Transaction; /** * Deletes one or more items from the collection * @param items - Single item/key or array of items/keys to delete * @param config - Optional configuration including metadata * @returns A Transaction object representing the delete operation(s) * @example * // Delete a single item * delete(todo) * * // Delete multiple items * delete([todo1, todo2]) * * // Delete with metadata * delete(todo, { metadata: { reason: "completed" } }) */ delete: (items: Array<T | string> | T | string, config?: OperationConfig) => Transaction; /** * Gets the current state of the collection as a Map * * @returns A Map containing all items in the collection, with keys as identifiers */ get state(): Map<string, T>; /** * Gets the current state of the collection as a Map, but only resolves when data is available * Waits for the first sync commit to complete before resolving * * @returns Promise that resolves to a Map containing all items in the collection */ stateWhenReady(): Promise<Map<string, T>>; /** * Gets the current state of the collection as an Array * * @returns An Array containing all items in the collection */ get toArray(): T[]; /** * Gets the current state of the collection as an Array, but only resolves when data is available * Waits for the first sync commit to complete before resolving * * @returns Promise that resolves to an Array containing all items in the collection */ toArrayWhenReady(): Promise<Array<T>>; /** * Returns the current state of the collection as an array of changes * @returns An array of changes */ currentStateAsChanges(): Array<ChangeMessage<T>>; /** * Subscribe to changes in the collection * @param callback - A function that will be called with the changes in the collection * @returns A function that can be called to unsubscribe from the changes */ subscribeChanges(callback: (changes: Array<ChangeMessage<T>>) => void): () => void; }