export class ApiError extends Error { readonly status: number; constructor(message: string, status: number) { super(message); this.name = "ApiError"; this.status = status; } } type RequestInitWithJson = RequestInit & { json?: unknown; }; async function request( input: string, init: RequestInitWithJson = {}, ): Promise { const headers = new Headers(init.headers); const body = init.json === undefined ? init.body : JSON.stringify(init.json, null, 2); if (init.json !== undefined) { headers.set("Content-Type", "application/json"); } const response = await fetch(input, { ...init, headers, body, }); if (!response.ok) { let message = `${response.status} ${response.statusText}`; try { const errorPayload = (await response.json()) as { error?: { message?: string }; }; message = errorPayload.error?.message ?? message; } catch { message = `${response.status} ${response.statusText}`; } throw new ApiError(message, response.status); } const contentType = response.headers.get("Content-Type") ?? ""; if (contentType.includes("application/yaml")) { return (await response.text()) as TResponse; } return (await response.json()) as TResponse; } export function getJson(input: string) { return request(input); } export function getText(input: string) { return request(input); } export function postJson(input: string, json?: unknown) { return request(input, { method: "POST", json, }); } export function postText(input: string, text: string) { return request(input, { method: "POST", headers: { "Content-Type": "application/yaml", }, body: text, }); }