let accessToken: string | null = null export function setToken(token: string | null) { accessToken = token } export function getToken() { return accessToken } async function handleResponse(res: Response): Promise { if (res.status === 204) return undefined as T if (!res.ok) { const text = await res.text().catch(() => '') throw new Error(`${res.status}: ${text || res.statusText}`) } return res.json() } async function request(url: string, options: RequestInit = {}): Promise { const headers = new Headers(options.headers) if (accessToken) headers.set('Authorization', `Bearer ${accessToken}`) if (options.body && typeof options.body === 'string') headers.set('Content-Type', 'application/json') let res = await fetch(url, { ...options, headers }) if (res.status === 401 && accessToken) { const refreshed = await refreshToken() if (refreshed) { headers.set('Authorization', `Bearer ${accessToken}`) res = await fetch(url, { ...options, headers }) } else { setToken(null) window.location.href = '/login' throw new Error('Session expired') } } return handleResponse(res) } async function refreshToken(): Promise { try { const res = await fetch('/api/admin/auth/refresh', { method: 'POST', credentials: 'include' }) if (!res.ok) return false const data = await res.json() setToken(data.token) return true } catch { return false } } export const api = { get: (url: string) => request(url), post: (url: string, body?: unknown) => request(url, { method: 'POST', body: body ? JSON.stringify(body) : undefined }), put: (url: string, body?: unknown) => request(url, { method: 'PUT', body: body ? JSON.stringify(body) : undefined }), patch: (url: string, body?: unknown) => request(url, { method: 'PATCH', body: body ? JSON.stringify(body) : undefined }), delete: (url: string) => request(url, { method: 'DELETE' }), upload: (url: string, formData: FormData) => request(url, { method: 'POST', body: formData }), }