import { authFetchOrThrow, getApiBase } from "./auth"; export type ApiTransport = (input: RequestInfo | URL, init?: RequestInit) => Promise; export class ApiClientError extends Error { readonly status: number; constructor(status: number, message: string) { super(message); this.name = "ApiClientError"; this.status = status; } } const errorMessage = (payload: unknown, fallback: string) => { if (!payload || typeof payload !== "object") return fallback; const record = payload as Record; for (const key of ["detail", "error", "message"]) { const value = record[key]; if (typeof value === "string" && value.trim()) return value.trim(); } return fallback; }; export const apiUrl = (path: string) => { const normalizedPath = path.startsWith("/") ? path : `/${path}`; return `${getApiBase()}${normalizedPath}`; }; export async function requestJson( path: string, init?: RequestInit, transport: ApiTransport = authFetchOrThrow, ): Promise { const response = await transport(apiUrl(path), init); if (response.status === 204) return undefined as T; const text = await response.text(); let payload: unknown = null; if (text) { try { payload = JSON.parse(text); } catch { payload = text; } } if (!response.ok) { throw new ApiClientError(response.status, errorMessage(payload, text || `Request failed: ${response.status}`)); } return payload as T; }