export interface ApiFailure { error: string; code?: string; issues?: Array<{ path: unknown; message: string }>; } export class ApiClientError extends Error { constructor(public status: number, public code: string | undefined, message: string) { super(message); } } export async function apiFetch( input: string, init: RequestInit = {}, ): Promise { const headers = new Headers(init.headers); if (init.body && !headers.has("content-type") && !(init.body instanceof FormData)) { headers.set("content-type", "application/json"); } const res = await fetch(input, { ...init, headers }); const text = await res.text(); const data = text ? (JSON.parse(text) as unknown) : undefined; if (!res.ok) { const fail = (data ?? { error: res.statusText }) as ApiFailure; throw new ApiClientError(res.status, fail.code, fail.error); } return data as T; }