UNPKG

@prismicio/client

Version:

The official JavaScript + TypeScript client library for Prismic

74 lines (72 loc) 2.93 kB
import { pLimit } from "./pLimit.js"; //#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 blob = await response.blob(); const memoized = { ok: response.ok, status: response.status, headers: response.headers, url: response.url, text: async () => blob.text(), json: async () => JSON.parse(await blob.text()), blob: async () => blob, 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 === null || init === void 0 ? void 0 : init.body) { var _url$hostname; job = (THROTTLED_RUNNERS[_url$hostname = url.hostname] || (THROTTLED_RUNNERS[_url$hostname] = pLimit({ interval: DEFAULT_RETRY_AFTER })))(() => fetchFn(stringURL, init)); } else { var _DEDUPLICATED_JOBS$st; const existingJob = (_DEDUPLICATED_JOBS$st = DEDUPLICATED_JOBS[stringURL]) === null || _DEDUPLICATED_JOBS$st === void 0 ? void 0 : _DEDUPLICATED_JOBS$st.get(init === null || init === void 0 ? void 0 : init.signal); if (existingJob) job = existingJob; else { job = fetchFn(stringURL, init).then(memoizeResponse).finally(() => { var _DEDUPLICATED_JOBS$st2, _DEDUPLICATED_JOBS$st3; (_DEDUPLICATED_JOBS$st2 = DEDUPLICATED_JOBS[stringURL]) === null || _DEDUPLICATED_JOBS$st2 === void 0 || _DEDUPLICATED_JOBS$st2.delete(init === null || init === void 0 ? void 0 : init.signal); if (((_DEDUPLICATED_JOBS$st3 = DEDUPLICATED_JOBS[stringURL]) === null || _DEDUPLICATED_JOBS$st3 === void 0 ? void 0 : _DEDUPLICATED_JOBS$st3.size) === 0) delete DEDUPLICATED_JOBS[stringURL]; }); (DEDUPLICATED_JOBS[stringURL] || (DEDUPLICATED_JOBS[stringURL] = /* @__PURE__ */ new Map())).set(init === null || init === void 0 ? void 0 : 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 export { request }; //# sourceMappingURL=request.js.map