import { QueryKey, UseMutationResult } from '@tanstack/react-query'; import { ApiError, RequestConfig, QueryParams } from '../types'; /** * Mutation variables structure */ export interface MutationVariables { /** Request body */ body?: TBody; /** Path parameters */ pathParams?: Record; /** Query parameters */ queryParams?: QueryParams; } /** * API mutation configuration */ export interface ApiMutationConfig { /** HTTP method */ method: 'POST' | 'PUT' | 'PATCH' | 'DELETE'; /** Request URL (can include :param placeholders) */ url: string; /** Additional request options */ requestOptions?: Partial; /** Query keys to invalidate on success */ invalidateQueries?: QueryKey[]; /** Query keys to refetch on success */ refetchQueries?: QueryKey[]; /** Query key for optimistic updates */ optimisticQueryKey?: QueryKey; /** Optimistic update function */ optimisticUpdate?: (oldData: unknown, variables: MutationVariables) => unknown; /** On mutate callback (for custom optimistic updates) */ onMutate?: (variables: MutationVariables) => Promise | TContext; /** On success callback */ onSuccess?: (data: TResponse, variables: MutationVariables, context: TContext | undefined) => void | Promise; /** On error callback */ onError?: (error: ApiError, variables: MutationVariables, context: TContext | undefined) => void | Promise; /** On settled callback */ onSettled?: (data: TResponse | undefined, error: ApiError | null, variables: MutationVariables, context: TContext | undefined) => void | Promise; /** Retry configuration */ retry?: number | boolean; /** Retry delay */ retryDelay?: number; } /** * Return type for useApiMutation */ export interface UseApiMutationResult extends Omit>, never> { /** Execute mutation with just body */ mutateWithBody: (body: TBody) => void; /** Execute mutation async with just body */ mutateAsyncWithBody: (body: TBody) => Promise; } /** * Hook for making typed API mutations * * @typeParam TResponse - Expected response data type * @typeParam TBody - Request body type * @typeParam TContext - Mutation context type (for optimistic updates) * @param config - Mutation configuration * @returns Mutation result with utilities * * @example * ```typescript * // Create mutation * const createUser = useApiMutation({ * method: 'POST', * url: '/users', * invalidateQueries: [['users', 'list']], * }); * * // Execute * createUser.mutate({ body: { name: 'John', email: 'john@example.com' } }); * * // Or with simplified API * createUser.mutateWithBody({ name: 'John', email: 'john@example.com' }); * * // Update mutation with path params * const updateUser = useApiMutation({ * method: 'PATCH', * url: '/users/:id', * invalidateQueries: [['users', 'list']], * }); * * updateUser.mutate({ * pathParams: { id: '123' }, * body: { name: 'Updated Name' }, * }); * * // Delete mutation * const deleteUser = useApiMutation({ * method: 'DELETE', * url: '/users/:id', * invalidateQueries: [['users', 'list']], * }); * * deleteUser.mutate({ pathParams: { id: '123' } }); * ``` */ export declare function useApiMutation(config: ApiMutationConfig): UseApiMutationResult; /** * Hook for POST mutations * * @example * ```typescript * const createUser = usePost('/users', { * invalidateQueries: [['users', 'list']], * }); * * createUser.mutateWithBody({ name: 'John' }); * ``` */ export declare function usePost(url: string, options?: Omit, 'method' | 'url'>): UseApiMutationResult; /** * Hook for PUT mutations * * @example * ```typescript * const updateUser = usePut('/users/:id', { * invalidateQueries: [['users', 'list']], * }); * * updateUser.mutate({ * pathParams: { id: '123' }, * body: { name: 'Updated' }, * }); * ``` */ export declare function usePut(url: string, options?: Omit, 'method' | 'url'>): UseApiMutationResult; /** * Hook for PATCH mutations * * @example * ```typescript * const patchUser = usePatch>('/users/:id'); * * patchUser.mutate({ * pathParams: { id: '123' }, * body: { status: 'active' }, * }); * ``` */ export declare function usePatch(url: string, options?: Omit, 'method' | 'url'>): UseApiMutationResult; /** * Hook for DELETE mutations * * @example * ```typescript * const deleteUser = useDelete('/users/:id', { * invalidateQueries: [['users', 'list']], * }); * * deleteUser.mutate({ pathParams: { id: '123' } }); * ``` */ export declare function useDelete(url: string, options?: Omit, 'method' | 'url'>): UseApiMutationResult; /** * Create optimistic update configuration for adding item to list * * @example * ```typescript * const createUser = usePost('/users', { * ...createOptimisticAdd(['users', 'list'], (body) => ({ * ...body, * id: 'temp-id', * createdAt: new Date().toISOString(), * })), * }); * ``` */ export declare function createOptimisticAdd(queryKey: QueryKey, createTempItem: (body: unknown) => TItem): Pick, 'optimisticQueryKey' | 'optimisticUpdate'>; /** * Create optimistic update configuration for updating item in list * * @example * ```typescript * const updateUser = usePatch>('/users/:id', { * ...createOptimisticUpdate(['users', 'list'], (item) => item.id), * }); * ``` */ export declare function createOptimisticUpdate>(queryKey: QueryKey, getItemId: (item: TItem) => string | number): Pick, { previousData: TItem[] | undefined; }>, 'optimisticQueryKey' | 'optimisticUpdate'>; /** * Create optimistic update configuration for removing item from list * * @example * ```typescript * const deleteUser = useDelete('/users/:id', { * ...createOptimisticRemove(['users', 'list'], (item) => item.id), * }); * ``` */ export declare function createOptimisticRemove(queryKey: QueryKey, getItemId: (item: TItem) => string | number): Pick, 'optimisticQueryKey' | 'optimisticUpdate'>; /** * Hook for executing multiple mutations in sequence * * @example * ```typescript * const batchUpdate = useBatchMutation( * '/users/:id', * 'PATCH' * ); * * await batchUpdate.mutateAsync([ * { pathParams: { id: '1' }, body: { status: 'active' } }, * { pathParams: { id: '2' }, body: { status: 'active' } }, * ]); * ``` */ export declare function useBatchMutation(url: string, method: 'POST' | 'PUT' | 'PATCH' | 'DELETE', options?: Omit, 'method' | 'url'>): { mutate: (variables: MutationVariables[]) => void; mutateAsync: (variables: MutationVariables[]) => Promise; isPending: boolean; isError: boolean; error: ApiError | null; data: TResponse[] | undefined; reset: () => void; };