// Small fetch wrapper: non-2xx responses become HttpErrors carrying the // status code so callers can branch on 401s; 2xx responses are parsed as JSON. export class HttpError extends Error { readonly status: number; constructor(what: string, status: number, body: string) { super(`${what} failed: ${status}: ${body}`); this.status = status; } } export async function fetchJson( what: string, url: string | URL, init?: RequestInit, ): Promise { const resp = await fetch(url, { ...init, signal: init?.signal ?? AbortSignal.timeout(30_000), }); if (!resp.ok) throw new HttpError(what, resp.status, await resp.text()); return resp.json() as Promise; }