"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); 0 && (module.exports = { validateTags: null, addImplicitTags: null, patchFetch: null }); function _export(target, all) { for(var name in all)Object.defineProperty(target, name, { enumerable: true, get: all[name] }); } _export(exports, { validateTags: function() { return validateTags; }, addImplicitTags: function() { return addImplicitTags; }, patchFetch: function() { return patchFetch; } }); const _constants = require("./trace/constants"); const _tracer = require("./trace/tracer"); const _constants1 = require("../../lib/constants"); const _log = /*#__PURE__*/ _interop_require_wildcard(require("../../build/output/log")); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interop_require_wildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for(var key in obj){ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } const isEdgeRuntime = process.env.NEXT_RUNTIME === "edge"; function validateTags(tags, description) { const validTags = []; const invalidTags = []; for (const tag of tags){ if (typeof tag !== "string") { invalidTags.push({ tag, reason: "invalid type, must be a string" }); } else if (tag.length > _constants1.NEXT_CACHE_TAG_MAX_LENGTH) { invalidTags.push({ tag, reason: `exceeded max length of ${_constants1.NEXT_CACHE_TAG_MAX_LENGTH}` }); } else { validTags.push(tag); } } if (invalidTags.length > 0) { console.warn(`Warning: invalid tags passed to ${description}: `); for (const { tag, reason } of invalidTags){ console.log(`tag: "${tag}" ${reason}`); } } return validTags; } const getDerivedTags = (pathname)=>{ const derivedTags = [ `/layout` ]; // we automatically add the current path segments as tags // for revalidatePath handling if (pathname.startsWith("/")) { const pathnameParts = pathname.split("/"); for(let i = 1; i < pathnameParts.length + 1; i++){ let curPathname = pathnameParts.slice(0, i).join("/"); if (curPathname) { // all derived tags other than the page are layout tags if (!curPathname.endsWith("/page") && !curPathname.endsWith("/route")) { curPathname = `${curPathname}${!curPathname.endsWith("/") ? "/" : ""}layout`; } derivedTags.push(curPathname); } } } return derivedTags; }; function addImplicitTags(staticGenerationStore) { const newTags = []; if (!staticGenerationStore) { return newTags; } const { pagePath, urlPathname } = staticGenerationStore; if (!Array.isArray(staticGenerationStore.tags)) { staticGenerationStore.tags = []; } if (pagePath) { const derivedTags = getDerivedTags(pagePath); for (let tag of derivedTags){ var _staticGenerationStore_tags; tag = `${_constants1.NEXT_CACHE_IMPLICIT_TAG_ID}${tag}`; if (!((_staticGenerationStore_tags = staticGenerationStore.tags) == null ? void 0 : _staticGenerationStore_tags.includes(tag))) { staticGenerationStore.tags.push(tag); } newTags.push(tag); } } if (urlPathname) { var _staticGenerationStore_tags1; const tag = `${_constants1.NEXT_CACHE_IMPLICIT_TAG_ID}${urlPathname}`; if (!((_staticGenerationStore_tags1 = staticGenerationStore.tags) == null ? void 0 : _staticGenerationStore_tags1.includes(tag))) { staticGenerationStore.tags.push(tag); } newTags.push(tag); } return newTags; } function trackFetchMetric(staticGenerationStore, ctx) { if (!staticGenerationStore) return; if (!staticGenerationStore.fetchMetrics) { staticGenerationStore.fetchMetrics = []; } const dedupeFields = [ "url", "status", "method" ]; // don't add metric if one already exists for the fetch if (staticGenerationStore.fetchMetrics.some((metric)=>{ return dedupeFields.every((field)=>metric[field] === ctx[field]); })) { return; } staticGenerationStore.fetchMetrics.push({ url: ctx.url, cacheStatus: ctx.cacheStatus, cacheReason: ctx.cacheReason, status: ctx.status, method: ctx.method, start: ctx.start, end: Date.now(), idx: staticGenerationStore.nextFetchId || 0 }); } function patchFetch({ serverHooks, staticGenerationAsyncStorage }) { if (!globalThis._nextOriginalFetch) { globalThis._nextOriginalFetch = globalThis.fetch; } if (globalThis.fetch.__nextPatched) return; const { DynamicServerError } = serverHooks; const originFetch = globalThis._nextOriginalFetch; globalThis.fetch = async (input, init)=>{ var _init_method, _this; let url; try { url = new URL(input instanceof Request ? input.url : input); url.username = ""; url.password = ""; } catch { // Error caused by malformed URL should be handled by native fetch url = undefined; } const fetchUrl = (url == null ? void 0 : url.href) ?? ""; const fetchStart = Date.now(); const method = (init == null ? void 0 : (_init_method = init.method) == null ? void 0 : _init_method.toUpperCase()) || "GET"; // Do create a new span trace for internal fetches in the // non-verbose mode. const isInternal = ((_this = init == null ? void 0 : init.next) == null ? void 0 : _this.internal) === true; return await (0, _tracer.getTracer)().trace(isInternal ? _constants.NextNodeServerSpan.internalFetch : _constants.AppRenderSpan.fetch, { kind: _tracer.SpanKind.CLIENT, spanName: [ "fetch", method, fetchUrl ].filter(Boolean).join(" "), attributes: { "http.url": fetchUrl, "http.method": method, "net.peer.name": url == null ? void 0 : url.hostname, "net.peer.port": (url == null ? void 0 : url.port) || undefined } }, async ()=>{ var _getRequestMeta; const staticGenerationStore = staticGenerationAsyncStorage.getStore() || (fetch.__nextGetStaticStore == null ? void 0 : fetch.__nextGetStaticStore.call(fetch)); const isRequestInput = input && typeof input === "object" && typeof input.method === "string"; const getRequestMeta = (field)=>{ let value = isRequestInput ? input[field] : null; return value || (init == null ? void 0 : init[field]); }; // If the staticGenerationStore is not available, we can't do any // special treatment of fetch, therefore fallback to the original // fetch implementation. if (!staticGenerationStore || isInternal || staticGenerationStore.isDraftMode) { return originFetch(input, init); } let revalidate = undefined; const getNextField = (field)=>{ var _init_next, _init_next1, _input_next; return typeof (init == null ? void 0 : (_init_next = init.next) == null ? void 0 : _init_next[field]) !== "undefined" ? init == null ? void 0 : (_init_next1 = init.next) == null ? void 0 : _init_next1[field] : isRequestInput ? (_input_next = input.next) == null ? void 0 : _input_next[field] : undefined; }; // RequestInit doesn't keep extra fields e.g. next so it's // only available if init is used separate let curRevalidate = getNextField("revalidate"); const tags = validateTags(getNextField("tags") || [], `fetch ${input.toString()}`); if (Array.isArray(tags)) { if (!staticGenerationStore.tags) { staticGenerationStore.tags = []; } for (const tag of tags){ if (!staticGenerationStore.tags.includes(tag)) { staticGenerationStore.tags.push(tag); } } } const implicitTags = addImplicitTags(staticGenerationStore); const isOnlyCache = staticGenerationStore.fetchCache === "only-cache"; const isForceCache = staticGenerationStore.fetchCache === "force-cache"; const isDefaultCache = staticGenerationStore.fetchCache === "default-cache"; const isDefaultNoStore = staticGenerationStore.fetchCache === "default-no-store"; const isOnlyNoStore = staticGenerationStore.fetchCache === "only-no-store"; const isForceNoStore = staticGenerationStore.fetchCache === "force-no-store"; let _cache = getRequestMeta("cache"); let cacheReason = ""; if (typeof _cache === "string" && typeof curRevalidate !== "undefined") { _log.warn(`fetch for ${fetchUrl} on ${staticGenerationStore.urlPathname} specified "cache: ${_cache}" and "revalidate: ${curRevalidate}", only one should be specified.`); _cache = undefined; } if (_cache === "force-cache") { curRevalidate = false; } if ([ "no-cache", "no-store" ].includes(_cache || "")) { curRevalidate = 0; cacheReason = `cache: ${_cache}`; } if (typeof curRevalidate === "number" || curRevalidate === false) { revalidate = curRevalidate; } const _headers = getRequestMeta("headers"); const initHeaders = typeof (_headers == null ? void 0 : _headers.get) === "function" ? _headers : new Headers(_headers || {}); const hasUnCacheableHeader = initHeaders.get("authorization") || initHeaders.get("cookie"); const isUnCacheableMethod = ![ "get", "head" ].includes(((_getRequestMeta = getRequestMeta("method")) == null ? void 0 : _getRequestMeta.toLowerCase()) || "get"); // if there are authorized headers or a POST method and // dynamic data usage was present above the tree we bail // e.g. if cookies() is used before an authed/POST fetch const autoNoCache = (hasUnCacheableHeader || isUnCacheableMethod) && staticGenerationStore.revalidate === 0; if (isForceNoStore) { revalidate = 0; cacheReason = "fetchCache = force-no-store"; } if (isOnlyNoStore) { if (_cache === "force-cache" || revalidate === 0) { throw new Error(`cache: 'force-cache' used on fetch for ${fetchUrl} with 'export const fetchCache = 'only-no-store'`); } revalidate = 0; cacheReason = "fetchCache = only-no-store"; } if (isOnlyCache && _cache === "no-store") { throw new Error(`cache: 'no-store' used on fetch for ${fetchUrl} with 'export const fetchCache = 'only-cache'`); } if (isForceCache && (typeof curRevalidate === "undefined" || curRevalidate === 0)) { cacheReason = "fetchCache = force-cache"; revalidate = false; } if (typeof revalidate === "undefined") { if (isDefaultCache) { revalidate = false; cacheReason = "fetchCache = default-cache"; } else if (autoNoCache) { revalidate = 0; cacheReason = "auto no cache"; } else if (isDefaultNoStore) { revalidate = 0; cacheReason = "fetchCache = default-no-store"; } else { cacheReason = "auto cache"; revalidate = typeof staticGenerationStore.revalidate === "boolean" || typeof staticGenerationStore.revalidate === "undefined" ? false : staticGenerationStore.revalidate; } } else if (!cacheReason) { cacheReason = `revalidate: ${revalidate}`; } if (// we don't consider autoNoCache to switch to dynamic during // revalidate although if it occurs during build we do !autoNoCache && (typeof staticGenerationStore.revalidate === "undefined" || typeof revalidate === "number" && (staticGenerationStore.revalidate === false || typeof staticGenerationStore.revalidate === "number" && revalidate < staticGenerationStore.revalidate))) { staticGenerationStore.revalidate = revalidate; } const isCacheableRevalidate = typeof revalidate === "number" && revalidate > 0 || revalidate === false; let cacheKey; if (staticGenerationStore.incrementalCache && isCacheableRevalidate) { try { cacheKey = await staticGenerationStore.incrementalCache.fetchCacheKey(fetchUrl, isRequestInput ? input : init); } catch (err) { console.error(`Failed to generate cache key for`, input); } } const fetchIdx = staticGenerationStore.nextFetchId ?? 1; staticGenerationStore.nextFetchId = fetchIdx + 1; const normalizedRevalidate = typeof revalidate !== "number" ? _constants1.CACHE_ONE_YEAR : revalidate; const doOriginalFetch = async (isStale, cacheReasonOverride)=>{ const requestInputFields = [ "cache", "credentials", "headers", "integrity", "keepalive", "method", "mode", "redirect", "referrer", "referrerPolicy", "window", "duplex", // don't pass through signal when revalidating ...isStale ? [] : [ "signal" ] ]; if (isRequestInput) { const reqInput = input; const reqOptions = { body: reqInput._ogBody || reqInput.body }; for (const field of requestInputFields){ // @ts-expect-error custom fields reqOptions[field] = reqInput[field]; } input = new Request(reqInput.url, reqOptions); } else if (init) { const initialInit = init; init = { body: init._ogBody || init.body }; for (const field of requestInputFields){ // @ts-expect-error custom fields init[field] = initialInit[field]; } } // add metadata to init without editing the original const clonedInit = { ...init, next: { ...init == null ? void 0 : init.next, fetchType: "origin", fetchIdx } }; return originFetch(input, clonedInit).then(async (res)=>{ if (!isStale) { trackFetchMetric(staticGenerationStore, { start: fetchStart, url: fetchUrl, cacheReason: cacheReasonOverride || cacheReason, cacheStatus: revalidate === 0 || cacheReasonOverride ? "skip" : "miss", status: res.status, method: clonedInit.method || "GET" }); } if (res.status === 200 && staticGenerationStore.incrementalCache && cacheKey && isCacheableRevalidate) { const bodyBuffer = Buffer.from(await res.arrayBuffer()); try { await staticGenerationStore.incrementalCache.set(cacheKey, { kind: "FETCH", data: { headers: Object.fromEntries(res.headers.entries()), body: bodyBuffer.toString("base64"), status: res.status, url: res.url }, revalidate: normalizedRevalidate }, { fetchCache: true, revalidate, fetchUrl, fetchIdx, tags }); } catch (err) { console.warn(`Failed to set fetch cache`, input, err); } const response = new Response(bodyBuffer, { headers: new Headers(res.headers), status: res.status }); Object.defineProperty(response, "url", { value: res.url }); return response; } return res; }); }; let handleUnlock = ()=>Promise.resolve(); let cacheReasonOverride; if (cacheKey && staticGenerationStore.incrementalCache) { handleUnlock = await staticGenerationStore.incrementalCache.lock(cacheKey); const entry = staticGenerationStore.isOnDemandRevalidate ? null : await staticGenerationStore.incrementalCache.get(cacheKey, { fetchCache: true, revalidate, fetchUrl, fetchIdx, tags, softTags: implicitTags }); if (entry) { await handleUnlock(); } else { // in dev, incremental cache response will be null in case the browser adds `cache-control: no-cache` in the request headers cacheReasonOverride = "cache-control: no-cache (hard refresh)"; } if ((entry == null ? void 0 : entry.value) && entry.value.kind === "FETCH") { // when stale and is revalidating we wait for fresh data // so the revalidated entry has the updated data if (!(staticGenerationStore.isRevalidate && entry.isStale)) { if (entry.isStale) { if (!staticGenerationStore.pendingRevalidates) { staticGenerationStore.pendingRevalidates = []; } staticGenerationStore.pendingRevalidates.push(doOriginalFetch(true).catch(console.error)); } const resData = entry.value.data; let decodedBody; if (process.env.NEXT_RUNTIME === "edge") { const { decode } = require("../../shared/lib/base64-arraybuffer"); decodedBody = decode(resData.body); } else { decodedBody = Buffer.from(resData.body, "base64").subarray(); } trackFetchMetric(staticGenerationStore, { start: fetchStart, url: fetchUrl, cacheReason, cacheStatus: "hit", status: resData.status || 200, method: (init == null ? void 0 : init.method) || "GET" }); const response = new Response(decodedBody, { headers: resData.headers, status: resData.status }); Object.defineProperty(response, "url", { value: entry.value.data.url }); return response; } } } if (staticGenerationStore.isStaticGeneration) { if (init && typeof init === "object") { const cache = init.cache; // Delete `cache` property as Cloudflare Workers will throw an error if (isEdgeRuntime) { delete init.cache; } if (cache === "no-store") { staticGenerationStore.revalidate = 0; const dynamicUsageReason = `no-store fetch ${input}${staticGenerationStore.urlPathname ? ` ${staticGenerationStore.urlPathname}` : ""}`; const err = new DynamicServerError(dynamicUsageReason); staticGenerationStore.dynamicUsageErr = err; staticGenerationStore.dynamicUsageStack = err.stack; staticGenerationStore.dynamicUsageDescription = dynamicUsageReason; } const hasNextConfig = "next" in init; const next = init.next || {}; if (typeof next.revalidate === "number" && (typeof staticGenerationStore.revalidate === "undefined" || typeof staticGenerationStore.revalidate === "number" && next.revalidate < staticGenerationStore.revalidate)) { const forceDynamic = staticGenerationStore.forceDynamic; if (!forceDynamic || next.revalidate !== 0) { staticGenerationStore.revalidate = next.revalidate; } if (!forceDynamic && next.revalidate === 0) { const dynamicUsageReason = `revalidate: ${next.revalidate} fetch ${input}${staticGenerationStore.urlPathname ? ` ${staticGenerationStore.urlPathname}` : ""}`; const err = new DynamicServerError(dynamicUsageReason); staticGenerationStore.dynamicUsageErr = err; staticGenerationStore.dynamicUsageStack = err.stack; staticGenerationStore.dynamicUsageDescription = dynamicUsageReason; } } if (hasNextConfig) delete init.next; } } return doOriginalFetch(false, cacheReasonOverride).finally(handleUnlock); }); }; globalThis.fetch.__nextGetStaticStore = ()=>{ return staticGenerationAsyncStorage; }; globalThis.fetch.__nextPatched = true; } //# sourceMappingURL=patch-fetch.js.map