import { type QueryKey, useMutation, useQueryClient } from "@tanstack/react-query" import type { BetterFetchOption } from "better-auth/react" import { useContext } from "react" import type { AuthQueryOptions, NonThrowableResult, ThrowableResult } from "../.." import { AuthQueryContext } from "../../lib/auth-query-provider" import { useOnMutateError } from "./use-mutate-error" type AuthMutationFn = (params: TParams) => Promise export function useAuthMutation< // biome-ignore lint/suspicious/noExplicitAny: TAuthFn extends AuthMutationFn >({ queryKey, mutationFn, optimisticData, options }: { queryKey: QueryKey mutationFn: TAuthFn optimisticData?( params: Omit[0], "fetchOptions">, previousData: unknown ): unknown options?: Partial }) { type TParams = Parameters[0] const queryClient = useQueryClient() const context = useContext(AuthQueryContext) const { optimistic } = { ...context, ...options } const { onMutateError } = useOnMutateError() const mutation = useMutation({ mutationFn: ({ fetchOptions = { throw: true }, ...params }: TParams) => mutationFn({ fetchOptions, ...params }), onMutate: async (params: TParams) => { if (!optimistic || !optimisticData) return await queryClient.cancelQueries({ queryKey }) const previousData = queryClient.getQueryData(queryKey) if (!previousData) return queryClient.setQueryData(queryKey, () => optimisticData(params, previousData)) return { previousData } }, onError: (error, _, context) => onMutateError(error, queryKey, context), onSettled: () => queryClient.invalidateQueries({ queryKey }) }) const { mutate, isPending, error } = mutation async function mutateAsync( params: Omit & { fetchOptions?: { throw?: true } | undefined } ): Promise async function mutateAsync( params: Omit & { fetchOptions?: BetterFetchOption } ): Promise async function mutateAsync(params: TParams): Promise { return await mutation.mutateAsync(params) } return { ...mutation, mutate, mutateAsync, isPending, error } }