91 lines
2.9 KiB
TypeScript
91 lines
2.9 KiB
TypeScript
import { useMutation, UseMutationOptions } from "@tanstack/react-query";
|
|
import { ServerResult } from "../types";
|
|
import toast from '@/lib/sonner'
|
|
import { logger } from '@/lib/supertokens'
|
|
|
|
|
|
let sessionRefreshRedirect: Promise<void> | null = null;
|
|
|
|
export function useServerMutation<TData, TVariables = unknown>(
|
|
options: Omit<UseMutationOptions<TData, Error, TVariables>, 'mutationFn'> & {
|
|
mutationFn: (variables: TVariables) => Promise<ServerResult<TData>>;
|
|
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<void>((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);
|
|
}
|
|
});
|
|
}
|