import { useEffect, useRef } from 'react'; import { refreshManager } from '@/lib/supertokens/refresh-manager'; import { logger } from '@/lib/supertokens'; import { ensureSuperTokensFrontend } from '@/lib/supertokens/client'; export function SessionMonitor() { const lastRefreshTimeRef = useRef(0); const REFRESH_COOLDOWN = 5 * 1000; useEffect(() => { if (typeof window === 'undefined') return; const handleVisibilityChange = async () => { if (document.visibilityState !== 'visible') return; const publicRoutes = ['/login', '/logout', '/refresh-session']; if (publicRoutes.some(route => window.location.pathname === route)) { return; } const now = Date.now(); const timeSinceLastRefresh = now - lastRefreshTimeRef.current; if (timeSinceLastRefresh < REFRESH_COOLDOWN) { logger.info(`Session monitor: skipping refresh (refreshed ${timeSinceLastRefresh}ms ago)`); return; } try { ensureSuperTokensFrontend(); const { doesSessionExist } = await import('supertokens-web-js/recipe/session'); const sessionExists = await doesSessionExist(); if (!sessionExists) { logger.info('Session monitor: no session exists, skipping refresh'); return; } logger.info('Session monitor: tab became visible, checking session freshness'); const refreshed = await refreshManager.refresh(); if (refreshed) { lastRefreshTimeRef.current = Date.now(); logger.info('Session monitor: session refreshed successfully'); } else { logger.warn('Session monitor: refresh returned false'); } } catch (error: any) { logger.error('Session monitor: error refreshing session', error?.message); } }; document.addEventListener('visibilitychange', handleVisibilityChange); return () => { document.removeEventListener('visibilitychange', handleVisibilityChange); }; }, []); return null; }