UNPKG

@prismicio/client

Version:

The official JavaScript + TypeScript client library for Prismic

63 lines (62 loc) 2.37 kB
const require_pLimit = require("./pLimit.cjs"); //#region src/lib/request.ts /** * The default number of milliseconds to wait before retrying a rate-limited `fetch()` request (429 * response code). The default value is only used if the response does not include a `retry-after` * header. */ const DEFAULT_RETRY_AFTER = 1500; /** A record of URLs mapped to throttled task runners. */ const THROTTLED_RUNNERS = {}; /** A record of URLs mapped to active deduplicated jobs. Jobs are keyed by their optional signal. */ const DEDUPLICATED_JOBS = {}; async function memoizeResponse(response) { const buffer = await response.arrayBuffer(); const memoized = { ok: response.ok, status: response.status, headers: response.headers, url: response.url, text: async () => new TextDecoder().decode(buffer), json: async () => JSON.parse(new TextDecoder().decode(buffer)), arrayBuffer: async () => buffer, blob: async () => new Blob([buffer]), clone: () => memoized }; return memoized; } /** * Makes an HTTP request with automatic retry for rate limits and request deduplication. * * @param url - The URL to request. * @param init - Fetch options. * @param fetchFn - The fetch function to use. * @returns The response from the fetch request. */ async function request(url, init, fetchFn) { const stringURL = url.toString(); let job; if (init?.body) job = (THROTTLED_RUNNERS[url.hostname] ||= require_pLimit.pLimit({ interval: DEFAULT_RETRY_AFTER }))(() => fetchFn(stringURL, init)); else { const existingJob = DEDUPLICATED_JOBS[stringURL]?.get(init?.signal); if (existingJob) job = existingJob; else { job = fetchFn(stringURL, init).then(memoizeResponse).finally(() => { DEDUPLICATED_JOBS[stringURL]?.delete(init?.signal); if (DEDUPLICATED_JOBS[stringURL]?.size === 0) delete DEDUPLICATED_JOBS[stringURL]; }); (DEDUPLICATED_JOBS[stringURL] ||= /* @__PURE__ */ new Map()).set(init?.signal, job); } } const response = await job; if (response.status === 429) { const retryAfter = Number(response.headers.get("retry-after")); const resolvedRetryAfter = Number.isNaN(retryAfter) ? DEFAULT_RETRY_AFTER : retryAfter * 1e3; await new Promise((resolve) => setTimeout(resolve, resolvedRetryAfter)); return request(url, init, fetchFn); } return response; } //#endregion exports.request = request; //# sourceMappingURL=request.cjs.map