session fixes
This commit is contained in:
@@ -4,30 +4,34 @@ import Passwordless from "supertokens-web-js/recipe/passwordless";
|
||||
import { appInfo } from "./config";
|
||||
import { logger } from "./";
|
||||
|
||||
let refreshAttemptCount = 0;
|
||||
let refreshPromise: Promise<boolean> | null = null;
|
||||
|
||||
export const resetRefreshFlag = () => {
|
||||
refreshAttemptCount = 0;
|
||||
refreshPromise = null;
|
||||
};
|
||||
|
||||
const setupFetchInterceptor = () => {
|
||||
if (typeof window === 'undefined') return;
|
||||
export const getOrCreateRefreshPromise = (refreshFn: () => Promise<boolean>): Promise<boolean> => {
|
||||
if (refreshPromise) {
|
||||
logger.info("Reusing existing refresh promise");
|
||||
return refreshPromise;
|
||||
}
|
||||
|
||||
const originalFetch = window.fetch;
|
||||
//@ts-ignore
|
||||
window.fetch = async (resource: RequestInfo | URL, options?: RequestInit) => {
|
||||
const url = typeof resource === 'string' ? resource :
|
||||
resource instanceof URL ? resource.toString() : resource.url;
|
||||
logger.info("Creating new refresh promise");
|
||||
refreshPromise = refreshFn()
|
||||
.then((result) => {
|
||||
logger.info("Refresh completed successfully:", result);
|
||||
setTimeout(() => {
|
||||
refreshPromise = null;
|
||||
}, 500);
|
||||
return result;
|
||||
})
|
||||
.catch((error) => {
|
||||
logger.error("Refresh failed:", error);
|
||||
refreshPromise = null;
|
||||
throw error;
|
||||
});
|
||||
|
||||
if (url.includes('/api/auth/session/refresh')) {
|
||||
refreshAttemptCount++;
|
||||
if (refreshAttemptCount > 1) {
|
||||
throw new Error('Duplicate refresh attempt blocked');
|
||||
}
|
||||
}
|
||||
|
||||
return originalFetch.call(window, resource, options);
|
||||
};
|
||||
return refreshPromise;
|
||||
};
|
||||
|
||||
export const frontendConfig = () => {
|
||||
@@ -53,7 +57,6 @@ export function ensureSuperTokensFrontend() {
|
||||
if (typeof window === "undefined") return;
|
||||
|
||||
if (!initialized) {
|
||||
setupFetchInterceptor();
|
||||
SuperTokens.init(frontendConfig());
|
||||
initialized = true;
|
||||
logger.info("SuperTokens initialized");
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { useMutation, UseMutationOptions } from "@tanstack/react-query";
|
||||
import { ServerResult } from "../types";
|
||||
import toast from '@/lib/sonner'
|
||||
import { logger } from '@/lib/supertokens'
|
||||
|
||||
let isMutationRefreshingSession = false;
|
||||
|
||||
let sessionRefreshRedirect: Promise<void> | null = null;
|
||||
|
||||
export function useServerMutation<TData, TVariables = unknown>(
|
||||
options: Omit<UseMutationOptions<TData, Error, TVariables>, 'mutationFn'> & {
|
||||
@@ -39,24 +41,39 @@ export function useServerMutation<TData, TVariables = unknown>(
|
||||
} catch (error: any) {
|
||||
if (error?.response?.status === 401) {
|
||||
try {
|
||||
const errorData = typeof error.response.data === 'string'
|
||||
? JSON.parse(error.response.data)
|
||||
const errorData = typeof error.response.data === 'string'
|
||||
? JSON.parse(error.response.data)
|
||||
: error.response.data;
|
||||
|
||||
|
||||
if (errorData?.error === "SESSION_REFRESH_REQUIRED") {
|
||||
if (!isMutationRefreshingSession) {
|
||||
isMutationRefreshingSession = true;
|
||||
logger.warn("Mutation detected SESSION_REFRESH_REQUIRED");
|
||||
|
||||
if (!sessionRefreshRedirect) {
|
||||
const currentUrl = window.location.pathname + window.location.search;
|
||||
setTimeout(() => {
|
||||
isMutationRefreshingSession = false;
|
||||
}, 1000);
|
||||
window.location.href = `/refresh-session?redirect=${encodeURIComponent(currentUrl)}`;
|
||||
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;
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user