// Single API client: one place for fetch, JSON, and the error envelope. const BASE = "/api/v1"; async function request(path, options = {}) { const response = await fetch(BASE + path, { headers: { "Content-Type": "application/json" }, ...options, }); let body = null; try { body = await response.json(); } catch (_) { body = null; } if (!response.ok) { const envelope = body && body.error ? body.error : {}; const error = new Error(envelope.message || response.statusText); error.status = response.status; error.code = envelope.code || "error"; throw error; } return body; } export const api = { listAssets: (params = {}) => request("/inventory/assets?" + new URLSearchParams(params).toString()), listClusters: (params = {}) => request("/duplicates/clusters?" + new URLSearchParams(params).toString()), getCluster: (id) => request(`/duplicates/clusters/${encodeURIComponent(id)}`), decide: (id, payload) => request(`/duplicates/clusters/${encodeURIComponent(id)}/decision`, { method: "POST", body: JSON.stringify(payload), }), thumbnailUrl: (assetId, size = 512) => `${BASE}/assets/${encodeURIComponent(assetId)}/thumbnail?size=${size}`, };