const apiBaseUrl = import.meta.env.VITE_API_BASE_URL ?? '' export class ApiError extends Error { readonly status: number readonly details: unknown constructor(message: string, status: number, details: unknown) { super(message) this.name = 'ApiError' this.status = status this.details = details } } export async function getJson(path: string): Promise { return requestJson(path, { method: 'GET', }) } export async function sendJson(path: string, method: 'POST' | 'PUT', body?: unknown): Promise { return requestJson(path, { method, headers: { 'Content-Type': 'application/json', }, body: body === undefined ? undefined : JSON.stringify(body), }) } async function requestJson(path: string, init: RequestInit): Promise { const response = await fetch(`${apiBaseUrl}${path}`, { ...init, headers: { Accept: 'application/json', ...init.headers, }, }) const payload = await readResponsePayload(response) if (!response.ok) { throw new ApiError(`Request failed with status ${response.status}`, response.status, payload) } return payload as T } async function readResponsePayload(response: Response): Promise { const contentType = response.headers.get('content-type') ?? '' if (!contentType.includes('application/json')) { return response.text() } return response.json() }