//#region src/utils/fetch.ts /** Status codes worth a second attempt: transient overload, throttling and gateway faults. */ const RETRY_STATUS_CODES = /* @__PURE__ */ new Set([ 408, 409, 425, 429, 500, 502, 503, 504 ]); /** * `GET` a JSON document, throwing on a non-2xx response. * * Errors carry `status` and `response` so `classifyNetworkError` can tell an HTTP * failure from a transport failure. Transport errors and the status codes above * are retried, since `fetch` itself will not. * * This module deliberately has no imports: it is loaded directly by * `scripts/generate-data.ts` under Node's type stripping, where extensionless * relative specifiers do not resolve. */ async function fetchJson(url, options = {}) { const attempts = (options.retry ?? 1) + 1; let lastError; for (let attempt = 0; attempt < attempts; attempt++) try { const response = await fetch(url, { headers: options.headers, signal: options.timeout ? AbortSignal.timeout(options.timeout) : void 0 }); if (response.ok) return await response.json(); lastError = Object.assign(/* @__PURE__ */ new Error(`Request to ${url} failed with ${response.status} ${response.statusText}`), { status: response.status, response }); if (!RETRY_STATUS_CODES.has(response.status)) break; } catch (error) { lastError = error; const name = error?.name; if (name === "TimeoutError" || name === "AbortError") break; } throw lastError; } //#endregion export { fetchJson as t };