/** * Hook for validating the session on app mount. * * Calls the backend to confirm the session is still valid, rather than relying * solely on cached sessionStorage. Handles network errors gracefully by not * logging out — only explicit 401/403 responses trigger logout. */ import { useCallback, useEffect, useState } from "react"; import * as authApi from "../api/auth"; import { ApiError, isAuthError } from "../api/client"; export interface UseSessionValidationResult { /** `true` when the validation check is in flight. */ isLoading: boolean; /** An error if validation failed for a reason other than 401/403. */ error: Error | null; } /** * Validate the session on mount. * * This hook is called once during app initialization to confirm the session * is valid on the backend. It handles three cases: * * 1. **Valid session (200)** — `onSessionValid()` is called. * 2. **Invalid session (401/403)** — `onSessionExpired()` is called to log out. * 3. **Network error** — `onNetworkError()` is called. The user is not logged out * because the backend may be temporarily unreachable. * * @param onSessionValid - Callback when session is confirmed valid. * @param onSessionExpired - Callback when session is invalid (401/403). * @param onNetworkError - Callback when a network error occurs. * @returns An object with `isLoading` and `error` states. */ export function useSessionValidation( onSessionValid: () => void, onSessionExpired: () => void, onNetworkError?: (error: Error) => void, ): UseSessionValidationResult { const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); const validate = useCallback(async (): Promise => { setIsLoading(true); setError(null); try { await authApi.validateSession(); onSessionValid(); } catch (err) { if (err instanceof ApiError && isAuthError(err)) { // Explicit 401/403 — session is invalid or expired. onSessionExpired(); } else if (err instanceof Error) { // Network error or other issue — don't log out. setError(err); onNetworkError?.(err); } else { const unknownError = new Error("Unknown error during session validation"); setError(unknownError); onNetworkError?.(unknownError); } } finally { setIsLoading(false); } }, [onSessionValid, onSessionExpired, onNetworkError]); useEffect(() => { void validate(); }, [validate]); return { isLoading, error }; }