/* Browser-side fetch helper for the JSON API. */ export class ApiError extends Error { constructor( public status: number, message: string, public details?: unknown ) { super(message); } } export async function api(url: string, init?: RequestInit & { json?: unknown }): Promise { const { json, ...rest } = init ?? {}; const res = await fetch(url, { ...rest, headers: json !== undefined ? { "content-type": "application/json", ...rest.headers } : rest.headers, body: json !== undefined ? JSON.stringify(json) : rest.body, }); const data = await res.json().catch(() => ({})); if (!res.ok) { const details = Array.isArray(data.details) ? `: ${data.details.join("; ")}` : ""; throw new ApiError(res.status, (data.error ?? res.statusText) + details, data.details); } return data as T; }