import { API_URL } from "../config"; /** * Base API client that centralizes fetch configuration. * All requests include credentials and proper headers. */ export class ApiError extends Error { constructor( message: string, public status: number, public data?: unknown ) { super(message); this.name = "ApiError"; } } async function request(endpoint: string, options: RequestInit = {}): Promise { const url = `${API_URL}${endpoint}`; const headers: Record = { ...(options.headers as Record), }; if (options.body && typeof options.body === "string") { headers["Content-Type"] = "application/json"; } const res = await fetch(url, { ...options, headers, credentials: "include", }); if (!res.ok) { let data: unknown; try { data = await res.json(); } catch { // Response wasn't JSON } throw new ApiError(`Request failed: ${res.status}`, res.status, data); } return res.json(); } /** * Base API client methods. * Domain-specific APIs should use these internally. */ export const client = { get(endpoint: string): Promise { return request(endpoint); }, post(endpoint: string, body?: unknown): Promise { return request(endpoint, { method: "POST", body: body ? JSON.stringify(body) : undefined, }); }, put(endpoint: string, body?: unknown): Promise { return request(endpoint, { method: "PUT", body: body ? JSON.stringify(body) : undefined, }); }, };