const GATEWAY_URL = process.env['NEXT_PUBLIC_GATEWAY_URL'] ?? 'http://localhost:14242'; export interface ApiRequestInit extends Omit { body?: unknown; } export interface ApiError { statusCode: number; message: string; } /** * Fetch wrapper for the Mosaic gateway API. * Sends credentials (cookies) and JSON body automatically. */ export async function api(path: string, init?: ApiRequestInit): Promise { const { body, headers: customHeaders, ...rest } = init ?? {}; const headers: Record = { Accept: 'application/json', ...(customHeaders as Record), }; if (body !== undefined) { headers['Content-Type'] = 'application/json'; } const res = await fetch(`${GATEWAY_URL}${path}`, { credentials: 'include', ...rest, headers, body: body !== undefined ? JSON.stringify(body) : undefined, }); if (!res.ok) { const errorBody = (await res.json().catch(() => ({ statusCode: res.status, message: res.statusText, }))) as ApiError; throw Object.assign(new Error(errorBody.message), { statusCode: errorBody.statusCode, }); } if (res.status === 204) return undefined as T; return (await res.json()) as T; }