// session.ts — 会话存储 // access token:仅内存(防 XSS 持久化窃取);refresh token:localStorage(header token 方案)。 // 取舍:doc/05 §2 给「HttpOnly+Secure cookie 或 header token」两选;纯静态导出无服务端 // 设置 cookie 的能力,故取 header token + localStorage,并配合静默续期与登出失效收敛风险。 import type { Session } from './types'; const REFRESH_KEY = 'pg_uc_refresh'; let accessToken: string | null = null; let accessExpiresAt = 0; export function getAccessToken(): string | null { return accessToken; } export function accessValid(skewMs = 15_000): boolean { return !!accessToken && Date.now() < accessExpiresAt - skewMs; } export function getRefreshToken(): string | null { if (typeof window === 'undefined') return null; try { return window.localStorage.getItem(REFRESH_KEY); } catch { return null; } } export function setSession(s: Session): void { accessToken = s.accessToken; accessExpiresAt = s.accessExpiresAt; if (typeof window !== 'undefined') { try { window.localStorage.setItem(REFRESH_KEY, s.refreshToken); } catch { /* ignore quota / privacy mode */ } } } export function clearSession(): void { accessToken = null; accessExpiresAt = 0; if (typeof window !== 'undefined') { try { window.localStorage.removeItem(REFRESH_KEY); } catch { /* ignore */ } } } export function hasRefresh(): boolean { return !!getRefreshToken(); }