import { attemptRefreshingSession } from 'supertokens-web-js/recipe/session'; import { logger } from './index'; class SessionRefreshManager { private refreshPromise: Promise | null = null; private redirectPromise: Promise | null = null; private lastRefreshTime: number = 0; private readonly MIN_REFRESH_INTERVAL = 1000; async refresh(): Promise { if (this.refreshPromise) { logger.info('RefreshManager: Reusing existing refresh promise'); return this.refreshPromise; } const timeSinceLastRefresh = Date.now() - this.lastRefreshTime; if (timeSinceLastRefresh < this.MIN_REFRESH_INTERVAL) { logger.info(`RefreshManager: Skipping refresh (last refresh ${timeSinceLastRefresh}ms ago)`); return true; } logger.info('RefreshManager: Starting new session refresh'); this.refreshPromise = attemptRefreshingSession() .then((result) => { logger.info('RefreshManager: Refresh completed successfully:', result); this.lastRefreshTime = Date.now(); return result; }) .catch((error) => { logger.error('RefreshManager: Refresh failed:', error); throw error; }) .finally(() => { setTimeout(() => { this.refreshPromise = null; }, 500); }); return this.refreshPromise; } async redirectToRefresh(currentPath: string): Promise { if (this.redirectPromise) { logger.info('RefreshManager: Redirect already in progress, waiting...'); return this.redirectPromise; } logger.info('RefreshManager: Initiating refresh redirect to:', currentPath); this.redirectPromise = new Promise((resolve) => { setTimeout(() => { window.location.href = `/refresh-session?redirect=${encodeURIComponent(currentPath)}`; resolve(); }, 100); }); this.redirectPromise.finally(() => { setTimeout(() => { this.redirectPromise = null; }, 1000); }); return this.redirectPromise; } reset(): void { logger.info('RefreshManager: Resetting state'); this.refreshPromise = null; this.redirectPromise = null; this.lastRefreshTime = 0; } getTimeSinceLastRefresh(): number { return Date.now() - this.lastRefreshTime; } } export const refreshManager = new SessionRefreshManager();