// 클라이언트 API wrapper. JWT 는 localStorage 에 보관. const TOKEN_KEY = 'jm_token'; export function getToken(): string | null { if (typeof window === 'undefined') return null; return localStorage.getItem(TOKEN_KEY); } export function setToken(t: string) { localStorage.setItem(TOKEN_KEY, t); } export function clearToken() { localStorage.removeItem(TOKEN_KEY); } async function request(path: string, opts: RequestInit = {}): Promise { const token = getToken(); const headers: Record = { 'Content-Type': 'application/json', ...(opts.headers as any), }; if (token) headers['Authorization'] = `Bearer ${token}`; const res = await fetch(path, { ...opts, headers }); if (res.status === 401) { clearToken(); if (typeof window !== 'undefined' && window.location.pathname !== '/login') { window.location.href = '/login'; } throw new Error('unauthorized'); } if (!res.ok) { const text = await res.text(); let msg = text; try { const j = JSON.parse(text); const d = j.detail; if (typeof d === 'string') msg = d; else if (Array.isArray(d)) msg = d.map((e: any) => e?.msg || e?.detail || JSON.stringify(e)).join(', '); else if (d && typeof d === 'object') msg = d.msg || JSON.stringify(d); else msg = text; } catch {} if (typeof msg !== 'string') msg = String(msg); throw new Error(msg || `${res.status}`); } if (res.status === 204) return undefined as any; return res.json(); } export const api = { get: (p: string) => request(p), post: (p: string, body: any) => request(p, { method: 'POST', body: JSON.stringify(body) }), put: (p: string, body: any) => request(p, { method: 'PUT', body: JSON.stringify(body) }), delete: (p: string) => request(p, { method: 'DELETE' }), };