var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import _debug from "debug"; import { serializeHeaders, unserializeHeaders } from "./headers.js"; const debug = _debug("fetch-mock-cache:core"); const origFetch = fetch; /** * Creates a new caching fetch implementation. Generally not used directly, * instead use the same named function provided by the various run-time entry * points. */ export default function createCachingMock({ Store, fetch, runtime, }) { if (!Store) throw new Error("No `Store` option was provided, but is required. See docs."); if (!fetch) fetch = origFetch; // Init with options if passed as [ Store, { /* ... */ } ] const store = Array.isArray(Store) ? new Store[0](Object.assign(Object.assign({}, Store[1]), { runtime })) : new Store({ runtime }); const fetchCache = Object.assign(function cachingMockImplementation(urlOrRequest, requestInit) { return __awaiter(this, void 0, void 0, function* () { var _a, _b; if (!urlOrRequest) throw new Error("urlOrRequest is undefined"); // TODO, main options? merge? const options = Array.isArray(fetchCache._options) ? fetchCache._options.shift() : fetchCache._options; const fetchRequest = typeof urlOrRequest === "string" || urlOrRequest instanceof URL ? new Request(urlOrRequest, requestInit) : urlOrRequest; const url = fetchRequest.url; const clonedRequest = fetchRequest.clone(); const cacheContentRequest = { url, method: fetchRequest.method, }; if (Array.from(fetchRequest.headers.keys()).length > 0) { // Not really necessary as set-cookie never appears in the REQUEST headers. cacheContentRequest.headers = serializeHeaders(fetchRequest.headers); } if (clonedRequest.body) { const bodyText = yield clonedRequest.text(); if ((_a = clonedRequest.headers .get("Content-Type")) === null || _a === void 0 ? void 0 : _a.startsWith("application/json")) cacheContentRequest.bodyJson = JSON.parse(bodyText); else cacheContentRequest.bodyText = bodyText; } const existingContent = yield store.fetchContent(cacheContentRequest, options); if (existingContent) { debug("Using cached copy of %o", url); const bodyText = existingContent.response.bodyJson ? JSON.stringify(existingContent.response.bodyJson) : existingContent.response.bodyText; existingContent.response.headers["X-FMC-Cache"] = "HIT"; return new Response(bodyText, { status: existingContent.response.status, statusText: existingContent.response.statusText, headers: unserializeHeaders(existingContent.response.headers), }); } debug("Fetching and caching %o", url); const p = fetch(url, requestInit); const response = yield p; const newContent = { request: cacheContentRequest, response: { ok: response.ok, status: response.status, statusText: response.statusText, headers: serializeHeaders(response.headers), }, }; const bodyText = yield response.text(); if ((_b = response.headers.get("Content-Type")) === null || _b === void 0 ? void 0 : _b.startsWith("application/json")) newContent.response.bodyJson = JSON.parse(bodyText); else newContent.response.bodyText = bodyText; yield store.storeContent(newContent, options); const headers = new Headers(response.headers); headers.set("X-FMC-Cache", "MISS"); return new Response(bodyText, { status: response.status, statusText: response.statusText, headers, }); }); }, { runtime, _store: store, _options: [], // TODO _once(options) { if (!Array.isArray(this._options)) this._options = []; this._options.push(options); }, }); // store.setFetchCache(fetchCache); return fetchCache; }