import { QueryClient, QueryKey, useMutation, UseMutationOptions, MutationFunction } from '@tanstack/react-query'; /** * Snapshot of query data for rollback */ export interface QuerySnapshot { /** Query key */ queryKey: QueryKey; /** Snapshotted data */ data: T | undefined; /** Snapshot timestamp */ timestamp: number; /** Data version/etag if available */ version?: string; } /** * Optimistic mutation context */ export interface OptimisticContext { /** Query snapshots for rollback */ snapshots: QuerySnapshot[]; /** The optimistic data applied */ optimisticData?: T; /** Rollback function */ rollbackFn: () => void; /** Mutation ID */ mutationId: string; /** Start timestamp */ startTime: number; } /** * Conflict resolution strategy */ export type ConflictStrategy = 'server-wins' | 'client-wins' | 'merge' | 'manual'; /** * Conflict resolution context */ export interface ConflictContext { /** Server response data */ serverData: T; /** Client optimistic data */ clientData: T | undefined; /** Original data before mutation */ originalData: T | undefined; /** Query key */ queryKey: QueryKey; } /** * Optimistic update configuration */ export interface OptimisticUpdateConfig { /** Query keys to update optimistically */ queryKeys: QueryKey[] | ((variables: TVariables) => QueryKey[]); /** Generate optimistic data from variables */ getOptimisticData: (variables: TVariables, currentData: TData | undefined) => TData; /** Handle successful mutation */ onSuccess?: (data: TData, variables: TVariables, context: OptimisticContext) => void; /** Handle mutation error with rollback */ onError?: (error: Error, variables: TVariables, context: OptimisticContext) => void; /** Custom rollback logic */ customRollback?: (snapshots: QuerySnapshot[], queryClient: QueryClient) => void; /** Conflict resolution strategy */ conflictStrategy?: ConflictStrategy; /** Custom merge function for 'merge' strategy */ mergeFn?: (context: ConflictContext) => TData; /** Manual conflict resolution handler */ onConflict?: (context: ConflictContext) => TData | Promise; /** Enable offline optimistic updates */ offlineSupport?: boolean; /** Retry failed mutations when back online */ retryOnReconnect?: boolean; /** Custom context generator */ getContext?: TContext; } /** * Create optimistic mutation hook with advanced features */ export declare function useOptimisticMutation(mutationFn: MutationFunction, config: OptimisticUpdateConfig, options?: Omit>, 'mutationFn' | 'onMutate' | 'onError' | 'onSuccess' | 'onSettled'>): ReturnType>>; /** * List item with required ID */ export interface ListItem { id: string; } /** * List response structure */ export interface ListResponse { items: T[]; total?: number; } /** * Create optimistic update helpers for list operations */ export declare function createListOptimisticUpdates>(): { addItem: (list: TList | undefined, newItem: TItem, position?: 'start' | 'end') => TList; updateItem: (list: TList | undefined, id: string, updates: Partial) => TList; removeItem: (list: TList | undefined, id: string) => TList; reorderItems: (list: TList | undefined, fromIndex: number, toIndex: number) => TList; moveItem: (list: TList | undefined, id: string, toIndex: number) => TList; replaceList: (list: TList | undefined, newItems: TItem[]) => TList; findItem: (list: TList | undefined, id: string) => TItem | undefined; hasItem: (list: TList | undefined, id: string) => boolean; }; /** * Queued mutation entry */ export interface QueuedMutation { id: string; mutationFn: () => Promise; rollbackFn: () => void; variables: TVariables; timestamp: number; retries: number; maxRetries: number; status: 'pending' | 'processing' | 'failed'; } /** * Mutation queue configuration */ export interface MutationQueueConfig { /** Maximum retry attempts */ maxRetries?: number; /** Retry delay (ms) */ retryDelay?: number; /** Persist queue to storage */ persist?: boolean; /** Storage key for persistence */ storageKey?: string; /** Callback when mutation succeeds */ onSuccess?: (mutation: QueuedMutation) => void; /** Callback when mutation fails permanently */ onFailure?: (mutation: QueuedMutation, error: Error) => void; /** Callback when queue status changes */ onStatusChange?: (status: QueueStatus) => void; } /** * Queue status */ export interface QueueStatus { pending: number; processing: boolean; online: boolean; failed: number; lastSync?: number; } /** * Optimistic mutation queue for offline support */ export declare class OptimisticMutationQueue { private queue; private processing; private config; private readonly onlineHandler?; constructor(config?: MutationQueueConfig); /** * Add mutation to queue */ add(mutationFn: () => Promise, rollbackFn: () => void, variables: TVariables): string; /** * Remove mutation from queue */ remove(id: string): boolean; /** * Process queued mutations */ process(): Promise; /** * Rollback all pending mutations */ rollbackAll(): void; /** * Get queue status */ getStatus(): QueueStatus; /** * Get all queued mutations */ getQueue(): QueuedMutation[]; /** * Clean up */ destroy(): void; /** * Persist queue to storage */ private persist; /** * Load queue from storage */ private loadFromStorage; /** * Notify status change */ private notifyStatusChange; } export interface MutationQueueStatus { pending: number; processing: boolean; failed: number; } /** * Hook to use the optimistic mutation queue */ export declare function useMutationQueue(config?: MutationQueueConfig): { add: (mutationFn: () => Promise, rollbackFn: () => void, variables: TVariables) => string; remove: (id: string) => boolean; process: () => Promise; rollbackAll: () => void; getStatus: () => MutationQueueStatus; }; /** * Create a deep clone of data for snapshotting * * @remarks * This function handles primitive types, arrays, Date, Map, Set, and plain objects. * The type assertions are safe because we preserve the structure of the input. */ export declare function deepClone(data: T): T; /** * Merge two objects deeply */ export declare function deepMerge>(target: T, source: Partial): T; /** * Global optimistic mutation queue */ export declare const globalMutationQueue: OptimisticMutationQueue;