/* * API communication module. Centralizes fetch calls so network details stay * out of rendering and state logic. All JSON traffic from the frontend goes * through `fetchJson()`, which prepends the versioned base path and unwraps * structured error responses into regular thrown errors. */ import { API_BASE } from './constants.js'; /* * Generic JSON fetcher. Prepends the API base path when the caller passes a * relative path, forwards headers, and parses the response body on success. * Non-2xx responses raise an `Error` whose message is the server's `message` * field when present, otherwise a generic status-code fallback. */ export async function fetchJson(path, options = {}) { const url = path.startsWith('http') ? path : `${API_BASE}${path}`; const requestOptions = { ...options, headers: { Accept: 'application/json', ...(options.headers || {}) } }; const response = await fetch(url, requestOptions); if (!response.ok) { let message = `Request failed for ${url}: ${response.status}`; try { const errorPayload = await response.json(); if (errorPayload?.message) { message = errorPayload.message; } } catch { /* Ignore JSON parse errors for non-JSON responses. */ } throw new Error(message); } return response.json(); }