import { useMutation, UseMutationOptions } from "@tanstack/react-query"; import { ServerResult } from "../types"; import toast from '@/lib/sonner' import { logger } from '@/lib/supertokens' let sessionRefreshRedirect: Promise | null = null; export function useServerMutation( options: Omit, 'mutationFn'> & { mutationFn: (variables: TVariables) => Promise>; successMessage?: string; showErrorToast?: boolean; showSuccessToast?: boolean; } ) { const { mutationFn, successMessage, showErrorToast = true, showSuccessToast = true, onSuccess, onError, ...mutationOptions } = options; return useMutation({ ...mutationOptions, mutationFn: async (variables: TVariables) => { try { const result = await mutationFn(variables); if (!result.success) { if (showErrorToast) { toast.error(result.error.userMessage); } throw new Error(result.error.userMessage); } return result.data; } catch (error: any) { if (error?.response?.status === 401) { try { const errorData = typeof error.response.data === 'string' ? JSON.parse(error.response.data) : error.response.data; if (errorData?.error === "SESSION_REFRESH_REQUIRED") { logger.warn("Mutation detected SESSION_REFRESH_REQUIRED"); if (!sessionRefreshRedirect) { const currentUrl = window.location.pathname + window.location.search; logger.info("Mutation initiating refresh redirect to:", currentUrl); sessionRefreshRedirect = new Promise((resolve) => { setTimeout(() => { window.location.href = `/refresh-session?redirect=${encodeURIComponent(currentUrl)}`; resolve(); }, 100); }); sessionRefreshRedirect.finally(() => { setTimeout(() => { sessionRefreshRedirect = null; }, 1000); }); } else { logger.info("Mutation: refresh redirect already in progress, waiting..."); await sessionRefreshRedirect; } throw new Error("SESSION_REFRESH_REQUIRED"); } } catch (parseError) {} } throw error; } }, onSuccess: (data, variables, onMutateResult, context) => { if (showSuccessToast && successMessage) { toast.success(successMessage); } onSuccess?.(data, variables, onMutateResult, context); }, onError: (error, variables, onMutateResult, context) => { onError?.(error, variables, onMutateResult, context); } }); }