const BASE = process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:8000"; const PREFIX = "/api/v1"; if (typeof window !== "undefined") { console.log("[API] base URL:", `${BASE}${PREFIX}`); } // ── Token management ────────────────────────────────────────────────────────── export function getToken(): string | null { if (typeof window === "undefined") return null; return localStorage.getItem("bado_token"); } export function setTokens(access: string, refresh: string) { localStorage.setItem("bado_token", access); localStorage.setItem("bado_refresh", refresh); } export function clearTokens() { localStorage.removeItem("bado_token"); localStorage.removeItem("bado_refresh"); } // ── Error ───────────────────────────────────────────────────────────────────── export class ApiError extends Error { code: string; status: number; details?: unknown; constructor(code: string, message: string, status: number, details?: unknown) { super(message); this.code = code; this.status = status; this.details = details; } } // ── Paginated result shape ──────────────────────────────────────────────────── export interface PaginatedResult { data: T[]; meta: { total: number; page: number; per_page: number; pages: number }; } // ── Core request ────────────────────────────────────────────────────────────── async function request(path: string, init: RequestInit = {}): Promise { const token = getToken(); const method = (init.method ?? "GET").toUpperCase(); const headers: Record = { ...(init.headers as Record), }; if (method !== "GET" && method !== "DELETE" && !(init.body instanceof FormData)) { headers["Content-Type"] = "application/json"; } if (token) headers["Authorization"] = `Bearer ${token}`; const res = await fetch(`${BASE}${PREFIX}${path}`, { ...init, headers }); if (res.status === 204) return undefined as unknown as T; const body = await res.json(); if (body.success === false) { const err = body.error ?? {}; throw new ApiError( err.code ?? "UNKNOWN", err.message ?? "Une erreur est survenue", res.status, err.details ); } if ("meta" in body) { return { data: body.data, meta: body.meta } as T; } return body.data as T; } export const api = { get: (path: string) => request(path), post: (path: string, data?: unknown) => request(path, { method: "POST", body: data !== undefined ? JSON.stringify(data) : undefined, }), put: (path: string, data?: unknown) => request(path, { method: "PUT", body: JSON.stringify(data) }), patch: (path: string, data?: unknown) => request(path, { method: "PATCH", body: JSON.stringify(data) }), del: (path: string) => request(path, { method: "DELETE" }), upload: (path: string, formData: FormData) => request(path, { method: "POST", body: formData }), };