@netlify/plugin-nextjs 5.10.1 → 5.10.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2023 Netlify <team@netlify.com>
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -8,7 +8,7 @@ import "./chunk-OEQOKJGE.js";
8
8
 
9
9
  // package.json
10
10
  var name = "@netlify/plugin-nextjs";
11
- var version = "5.10.1";
11
+ var version = "5.10.3";
12
12
  var description = "Run Next.js seamlessly on Netlify";
13
13
  var main = "./dist/index.js";
14
14
  var type = "module";
@@ -56,15 +56,15 @@ var bugs = {
56
56
  };
57
57
  var homepage = "https://opennext.js.org/netlify";
58
58
  var devDependencies = {
59
- "@fastly/http-compute-js": "1.1.4",
60
- "@netlify/blobs": "^8.1.0",
61
- "@netlify/build": "^29.55.4",
62
- "@netlify/edge-bundler": "^12.2.3",
63
- "@netlify/edge-functions": "^2.11.0",
59
+ "@fastly/http-compute-js": "1.1.5",
60
+ "@netlify/blobs": "^8.1.2",
61
+ "@netlify/build": "^30.1.1",
62
+ "@netlify/edge-bundler": "^12.4.0",
63
+ "@netlify/edge-functions": "^2.11.1",
64
64
  "@netlify/eslint-config-node": "^7.0.1",
65
- "@netlify/functions": "^3.0.0",
66
- "@netlify/serverless-functions-api": "^1.30.1",
67
- "@netlify/zip-it-and-ship-it": "^9.41.0",
65
+ "@netlify/functions": "^3.0.4",
66
+ "@netlify/serverless-functions-api": "^1.36.0",
67
+ "@netlify/zip-it-and-ship-it": "^10.0.4",
68
68
  "@opentelemetry/api": "^1.8.0",
69
69
  "@opentelemetry/exporter-trace-otlp-http": "^0.51.0",
70
70
  "@opentelemetry/resources": "^1.24.0",
@@ -84,10 +84,11 @@ var devDependencies = {
84
84
  "fs-monkey": "^1.0.6",
85
85
  "get-port": "^7.1.0",
86
86
  "lambda-local": "^2.2.0",
87
+ "lru-cache": "^10.4.3",
87
88
  memfs: "^4.9.2",
88
89
  "mock-require": "^3.0.3",
89
90
  msw: "^2.0.7",
90
- "netlify-cli": "^17.37.1",
91
+ "netlify-cli": "^19.1.5",
91
92
  next: "^15.0.0-canary.28",
92
93
  os: "^0.1.2",
93
94
  outdent: "^0.8.0",
@@ -11,6 +11,7 @@ import { existsSync } from "node:fs";
11
11
  import { readFile } from "node:fs/promises";
12
12
  import { join, resolve } from "node:path";
13
13
  import { PLUGIN_DIR, RUN_CONFIG } from "./constants.js";
14
+ import { setInMemoryCacheMaxSizeFromNextConfig } from "./storage/storage.cjs";
14
15
  var getRunConfig = async () => {
15
16
  return JSON.parse(await readFile(resolve(PLUGIN_DIR, RUN_CONFIG), "utf-8"));
16
17
  };
@@ -21,12 +22,13 @@ var setRunConfig = (config) => {
21
22
  }
22
23
  config.experimental = {
23
24
  ...config.experimental,
24
- // @ts-expect-error incrementalCacheHandlerPath was removed from config type
25
- // but we still need to set it for older Next.js versions
25
+ // Before Next.js 14.1.0 path to the cache handler was in experimental section, see NextConfigForMultipleVersions type
26
26
  incrementalCacheHandlerPath: cacheHandler
27
27
  };
28
28
  config.cacheHandler = cacheHandler;
29
- config.cacheMaxMemorySize = 0;
29
+ setInMemoryCacheMaxSizeFromNextConfig(
30
+ config.cacheMaxMemorySize ?? config.experimental?.isrMemoryCacheSize
31
+ );
30
32
  process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(config);
31
33
  };
32
34
  export {
@@ -102,7 +102,7 @@ var init_builder = __esm({
102
102
  }
103
103
  });
104
104
 
105
- // node_modules/@netlify/functions/dist/chunk-SURWFFYE.mjs
105
+ // node_modules/@netlify/functions/dist/chunk-EZL2F32K.mjs
106
106
  var import_process = require("process");
107
107
  var purgeCache;
108
108
  var init_purge_cache = __esm({
@@ -113,28 +113,37 @@ var init_purge_cache = __esm({
113
113
  "`fetch` is not available. Please ensure you're using Node.js version 18.0.0 or above. Refer to https://ntl.fyi/functions-runtime for more information."
114
114
  );
115
115
  }
116
+ const { siteID } = options;
117
+ const { siteSlug } = options;
118
+ const { domain } = options;
119
+ if (siteID && siteSlug || siteID && domain || siteSlug && domain) {
120
+ throw new Error('Can only pass one of either "siteID", "siteSlug", or "domain"');
121
+ }
116
122
  const payload = {
117
- cache_tags: options.tags,
118
- deploy_alias: options.deployAlias
123
+ cache_tags: options.tags
119
124
  };
125
+ if ("deployAlias" in options) {
126
+ payload.deploy_alias = options.deployAlias;
127
+ } else if (!import_process.env.NETLIFY_LOCAL) {
128
+ payload.deploy_alias = import_process.env.NETLIFY_BRANCH;
129
+ }
120
130
  const token = import_process.env.NETLIFY_PURGE_API_TOKEN || options.token;
121
131
  if (import_process.env.NETLIFY_LOCAL && !token) {
122
132
  const scope = options.tags?.length ? ` for tags ${options.tags?.join(", ")}` : "";
123
133
  console.log(`Skipping purgeCache${scope} in local development.`);
124
134
  return;
125
135
  }
126
- if ("siteSlug" in options) {
127
- payload.site_slug = options.siteSlug;
128
- } else if ("domain" in options) {
129
- payload.domain = options.domain;
136
+ if (siteSlug) {
137
+ payload.site_slug = siteSlug;
138
+ } else if (domain) {
139
+ payload.domain = domain;
130
140
  } else {
131
- const siteID = options.siteID || import_process.env.SITE_ID;
132
- if (!siteID) {
141
+ payload.site_id = siteID || import_process.env.SITE_ID;
142
+ if (!payload.site_id) {
133
143
  throw new Error(
134
144
  "The Netlify site ID was not found in the execution environment. Please supply it manually using the `siteID` property."
135
145
  );
136
146
  }
137
- payload.site_id = siteID;
138
147
  }
139
148
  if (!token) {
140
149
  throw new Error(
@@ -155,7 +164,18 @@ var init_purge_cache = __esm({
155
164
  body: JSON.stringify(payload)
156
165
  });
157
166
  if (!response.ok) {
158
- throw new Error(`Cache purge API call returned an unexpected status code: ${response.status}`);
167
+ let text;
168
+ try {
169
+ text = await response.text();
170
+ } catch {
171
+ }
172
+ if (text) {
173
+ throw new Error(`Cache purge API call was unsuccessful.
174
+ Status: ${response.status}
175
+ Body: ${text}`);
176
+ }
177
+ throw new Error(`Cache purge API call was unsuccessful.
178
+ Status: ${response.status}`);
159
179
  }
160
180
  };
161
181
  }
@@ -175,29 +195,23 @@ var import_constants = require("next/dist/lib/constants.js");
175
195
 
176
196
  // package.json
177
197
  var name = "@netlify/plugin-nextjs";
178
- var version = "5.10.1";
198
+ var version = "5.10.3";
179
199
 
180
200
  // src/run/handlers/cache.cts
181
201
  var import_cache_types = require("../../shared/cache-types.cjs");
182
- var import_regional_blob_store = require("../regional-blob-store.cjs");
202
+ var import_storage = require("../storage/storage.cjs");
183
203
  var import_request_context = require("./request-context.cjs");
184
204
  var import_tracer = require("./tracer.cjs");
185
205
  var purgeCacheUserAgent = `${name}@${version}`;
186
206
  var NetlifyCacheHandler = class {
187
207
  options;
188
208
  revalidatedTags;
189
- blobStore;
209
+ cacheStore;
190
210
  tracer = (0, import_tracer.getTracer)();
191
- tagManifestsFetchedFromBlobStoreInCurrentRequest;
192
211
  constructor(options) {
193
212
  this.options = options;
194
213
  this.revalidatedTags = options.revalidatedTags;
195
- this.blobStore = (0, import_regional_blob_store.getRegionalBlobStore)({ consistency: "strong" });
196
- this.tagManifestsFetchedFromBlobStoreInCurrentRequest = {};
197
- }
198
- async encodeBlobKey(key) {
199
- const { encodeBlobKey } = await import("../../shared/blobkey.js");
200
- return await encodeBlobKey(key);
214
+ this.cacheStore = (0, import_storage.getMemoizedKeyValueStoreBackedByRegionalBlobStore)({ consistency: "strong" });
201
215
  }
202
216
  getTTL(blob) {
203
217
  if (blob.value?.kind === "FETCH" || blob.value?.kind === "ROUTE" || blob.value?.kind === "APP_ROUTE" || blob.value?.kind === "PAGE" || blob.value?.kind === "PAGES" || blob.value?.kind === "APP_PAGE") {
@@ -218,26 +232,17 @@ var NetlifyCacheHandler = class {
218
232
  }
219
233
  const requestContext = (0, import_request_context.getRequestContext)();
220
234
  if (!requestContext) {
221
- getCacheKeySpan.recordException(
222
- new Error("CacheHandler was called without a request context")
223
- );
224
- getCacheKeySpan.setAttributes({
225
- severity: "alert",
226
- warning: true
227
- });
235
+ (0, import_tracer.recordWarning)(new Error("CacheHandler was called without a request context"), getCacheKeySpan);
228
236
  return;
229
237
  }
230
238
  if (requestContext.responseCacheKey && requestContext.responseCacheKey !== key) {
231
239
  requestContext.responseCacheGetLastModified = void 0;
232
- getCacheKeySpan.recordException(
240
+ (0, import_tracer.recordWarning)(
233
241
  new Error(
234
242
  `Multiple response cache keys used in single request: ["${requestContext.responseCacheKey}, "${key}"]`
235
- )
243
+ ),
244
+ getCacheKeySpan
236
245
  );
237
- getCacheKeySpan.setAttributes({
238
- severity: "alert",
239
- warning: true
240
- });
241
246
  return;
242
247
  }
243
248
  requestContext.responseCacheKey = key;
@@ -254,9 +259,6 @@ var NetlifyCacheHandler = class {
254
259
  return restOfRouteValue;
255
260
  }
256
261
  captureCacheTags(cacheValue, key) {
257
- if (!cacheValue) {
258
- return;
259
- }
260
262
  const requestContext = (0, import_request_context.getRequestContext)();
261
263
  if (!requestContext) {
262
264
  return;
@@ -264,6 +266,11 @@ var NetlifyCacheHandler = class {
264
266
  if (requestContext.responseCacheTags) {
265
267
  return;
266
268
  }
269
+ if (!cacheValue) {
270
+ const cacheTags = [`_N_T_${key === "/index" ? "/" : encodeURI(key)}`];
271
+ requestContext.responseCacheTags = cacheTags;
272
+ return;
273
+ }
267
274
  if (cacheValue.kind === "PAGE" || cacheValue.kind === "PAGES" || cacheValue.kind === "APP_PAGE" || cacheValue.kind === "ROUTE" || cacheValue.kind === "APP_ROUTE") {
268
275
  if (cacheValue.headers?.[import_constants.NEXT_CACHE_TAGS_HEADER]) {
269
276
  const cacheTags = cacheValue.headers[import_constants.NEXT_CACHE_TAGS_HEADER].split(/,|%2c/gi);
@@ -313,25 +320,18 @@ var NetlifyCacheHandler = class {
313
320
  }
314
321
  async get(...args) {
315
322
  return this.tracer.withActiveSpan("get cache key", async (span) => {
316
- const [key, ctx = {}] = args;
323
+ const [key, context = {}] = args;
317
324
  (0, import_request_context.getLogger)().debug(`[NetlifyCacheHandler.get]: ${key}`);
318
- const blobKey = await this.encodeBlobKey(key);
319
- span.setAttributes({ key, blobKey });
320
- const blob = await this.tracer.withActiveSpan("blobStore.get", async (blobGetSpan) => {
321
- blobGetSpan.setAttributes({ key, blobKey });
322
- return await this.blobStore.get(blobKey, {
323
- type: "json"
324
- });
325
- });
325
+ span.setAttributes({ key });
326
+ const blob = await this.cacheStore.get(key, "blobStore.get");
326
327
  if (!blob) {
327
- span.addEvent("Cache miss", { key, blobKey });
328
+ span.addEvent("Cache miss", { key });
328
329
  return null;
329
330
  }
330
331
  const ttl = this.getTTL(blob);
331
332
  if ((0, import_request_context.getRequestContext)()?.isBackgroundRevalidation && typeof ttl === "number" && ttl < 0) {
332
333
  span.addEvent("Discarding stale entry due to SWR background revalidation request", {
333
334
  key,
334
- blobKey,
335
335
  ttl
336
336
  });
337
337
  (0, import_request_context.getLogger)().withFields({
@@ -342,18 +342,25 @@ var NetlifyCacheHandler = class {
342
342
  );
343
343
  return null;
344
344
  }
345
- const staleByTags = await this.checkCacheEntryStaleByTags(blob, ctx.tags, ctx.softTags);
345
+ const staleByTags = await this.checkCacheEntryStaleByTags(
346
+ blob,
347
+ context.tags,
348
+ context.softTags
349
+ );
346
350
  if (staleByTags) {
347
- span.addEvent("Stale", { staleByTags, key, blobKey, ttl });
351
+ span.addEvent("Stale", { staleByTags, key, ttl });
348
352
  return null;
349
353
  }
350
354
  this.captureResponseCacheLastModified(blob, key, span);
351
- this.captureCacheTags(blob.value, key);
355
+ const isDataRequest = Boolean(context.fetchUrl);
356
+ if (!isDataRequest) {
357
+ this.captureCacheTags(blob.value, key);
358
+ }
352
359
  switch (blob.value?.kind) {
353
360
  case "FETCH":
354
361
  span.addEvent("FETCH", {
355
362
  lastModified: blob.lastModified,
356
- revalidate: ctx.revalidate,
363
+ revalidate: context.revalidate,
357
364
  ttl
358
365
  });
359
366
  return {
@@ -441,17 +448,16 @@ var NetlifyCacheHandler = class {
441
448
  async set(...args) {
442
449
  return this.tracer.withActiveSpan("set cache key", async (span) => {
443
450
  const [key, data, context] = args;
444
- const blobKey = await this.encodeBlobKey(key);
445
451
  const lastModified = Date.now();
446
- span.setAttributes({ key, lastModified, blobKey });
452
+ span.setAttributes({ key, lastModified });
447
453
  (0, import_request_context.getLogger)().debug(`[NetlifyCacheHandler.set]: ${key}`);
448
454
  const value = this.transformToStorableObject(data, context);
449
- this.captureCacheTags(value, key);
450
- await this.blobStore.setJSON(blobKey, {
451
- lastModified,
452
- value
453
- });
454
- if (data?.kind === "PAGE" || data?.kind === "PAGES") {
455
+ const isDataReq = Boolean(context.fetchUrl);
456
+ if (!isDataReq) {
457
+ this.captureCacheTags(value, key);
458
+ }
459
+ await this.cacheStore.set(key, { lastModified, value }, "blobStore.set");
460
+ if (!data && !isDataReq || data?.kind === "PAGE" || data?.kind === "PAGES") {
455
461
  const requestContext = (0, import_request_context.getRequestContext)();
456
462
  if (requestContext?.didPagesRouterOnDemandRevalidate) {
457
463
  const tag = `_N_T_${key === "/index" ? "/" : encodeURI(key)}`;
@@ -491,7 +497,7 @@ var NetlifyCacheHandler = class {
491
497
  await Promise.all(
492
498
  tags.map(async (tag) => {
493
499
  try {
494
- await this.blobStore.setJSON(await this.encodeBlobKey(tag), data);
500
+ await this.cacheStore.set(tag, data, "tagManifest.set");
495
501
  } catch (error) {
496
502
  (0, import_request_context.getLogger)().withError(error).log(`Failed to update tag manifest for ${tag}`);
497
503
  }
@@ -502,7 +508,6 @@ var NetlifyCacheHandler = class {
502
508
  });
503
509
  }
504
510
  resetRequestCache() {
505
- this.tagManifestsFetchedFromBlobStoreInCurrentRequest = {};
506
511
  }
507
512
  /**
508
513
  * Checks if a cache entry is stale through on demand revalidated tags
@@ -526,19 +531,16 @@ var NetlifyCacheHandler = class {
526
531
  return new Promise((resolve, reject) => {
527
532
  const tagManifestPromises = [];
528
533
  for (const tag of cacheTags) {
529
- let tagManifestPromise = this.tagManifestsFetchedFromBlobStoreInCurrentRequest[tag];
530
- if (!tagManifestPromise) {
531
- tagManifestPromise = this.encodeBlobKey(tag).then((blobKey) => {
532
- return this.tracer.withActiveSpan(`get tag manifest`, async (span) => {
533
- span.setAttributes({ tag, blobKey });
534
- return this.blobStore.get(blobKey, { type: "json" });
535
- });
536
- });
537
- this.tagManifestsFetchedFromBlobStoreInCurrentRequest[tag] = tagManifestPromise;
538
- }
534
+ const tagManifestPromise = this.cacheStore.get(
535
+ tag,
536
+ "tagManifest.get"
537
+ );
539
538
  tagManifestPromises.push(
540
539
  tagManifestPromise.then((tagManifest) => {
541
- const isStale = tagManifest?.revalidatedAt >= (cacheEntry.lastModified || Date.now());
540
+ if (!tagManifest) {
541
+ return false;
542
+ }
543
+ const isStale = tagManifest.revalidatedAt >= (cacheEntry.lastModified || Date.now());
542
544
  if (isStale) {
543
545
  resolve(true);
544
546
  return true;
@@ -121,6 +121,14 @@ var init_internal = __esm({
121
121
  init_internal();
122
122
 
123
123
  // src/run/handlers/request-context.cts
124
+ var REQUEST_CONTEXT_GLOBAL_KEY = Symbol.for("nf-request-context-async-local-storage");
125
+ var REQUEST_COUNTER_KEY = Symbol.for("nf-request-counter");
126
+ var extendedGlobalThis = globalThis;
127
+ function getFallbackRequestID() {
128
+ const requestNumber = extendedGlobalThis[REQUEST_COUNTER_KEY] ?? 0;
129
+ extendedGlobalThis[REQUEST_COUNTER_KEY] = requestNumber + 1;
130
+ return `#${requestNumber}`;
131
+ }
124
132
  function createRequestContext(request, context) {
125
133
  const backgroundWorkPromises = [];
126
134
  const isDebugRequest = request?.headers.has("x-nf-debug-logging") || request?.headers.has("x-next-debug-logging");
@@ -142,16 +150,15 @@ function createRequestContext(request, context) {
142
150
  get backgroundWorkPromise() {
143
151
  return Promise.allSettled(backgroundWorkPromises);
144
152
  },
145
- logger
153
+ logger,
154
+ requestID: request?.headers.get("x-nf-request-id") ?? getFallbackRequestID()
146
155
  };
147
156
  }
148
- var REQUEST_CONTEXT_GLOBAL_KEY = Symbol.for("nf-request-context-async-local-storage");
149
157
  var requestContextAsyncLocalStorage;
150
158
  function getRequestContextAsyncLocalStorage() {
151
159
  if (requestContextAsyncLocalStorage) {
152
160
  return requestContextAsyncLocalStorage;
153
161
  }
154
- const extendedGlobalThis = globalThis;
155
162
  if (extendedGlobalThis[REQUEST_CONTEXT_GLOBAL_KEY]) {
156
163
  return extendedGlobalThis[REQUEST_CONTEXT_GLOBAL_KEY];
157
164
  }
@@ -3098,8 +3098,8 @@ import {
3098
3098
  setCacheTagsHeaders,
3099
3099
  setVaryHeaders
3100
3100
  } from "../headers.js";
3101
- import { setFetchBeforeNextPatchedIt } from "../regional-blob-store.cjs";
3102
3101
  import { nextResponseProxy } from "../revalidate.js";
3102
+ import { setFetchBeforeNextPatchedIt } from "../storage/storage.cjs";
3103
3103
  import { getLogger } from "./request-context.cjs";
3104
3104
  import { getTracer } from "./tracer.cjs";
3105
3105
  import { setupWaitUntil } from "./wait-until.cjs";
@@ -3174,11 +3174,10 @@ var server_default = async (request, _context, topLevelSpan, requestContext) =>
3174
3174
  headers: response.headers,
3175
3175
  request,
3176
3176
  span,
3177
- tracer,
3178
3177
  requestContext
3179
3178
  });
3180
3179
  }
3181
- setCacheControlHeaders(response, request, requestContext, nextConfig);
3180
+ setCacheControlHeaders(response, request, requestContext);
3182
3181
  setCacheTagsHeaders(response.headers, requestContext);
3183
3182
  setVaryHeaders(response.headers, request, nextConfig);
3184
3183
  setCacheStatusHeader(response.headers, nextCache);
@@ -20,7 +20,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/run/handlers/tracer.cts
21
21
  var tracer_exports = {};
22
22
  __export(tracer_exports, {
23
- getTracer: () => getTracer
23
+ getTracer: () => getTracer,
24
+ recordWarning: () => recordWarning
24
25
  });
25
26
  module.exports = __toCommonJS(tracer_exports);
26
27
 
@@ -897,7 +898,19 @@ function getTracer() {
897
898
  }
898
899
  return tracer;
899
900
  }
901
+ function recordWarning(warning, span) {
902
+ const spanToRecordWarningOn = span ?? trace.getActiveSpan();
903
+ if (!spanToRecordWarningOn) {
904
+ return;
905
+ }
906
+ spanToRecordWarningOn.recordException(warning);
907
+ spanToRecordWarningOn.setAttributes({
908
+ severity: "alert",
909
+ warning: true
910
+ });
911
+ }
900
912
  // Annotate the CommonJS export names for ESM import in node:
901
913
  0 && (module.exports = {
902
- getTracer
914
+ getTracer,
915
+ recordWarning
903
916
  });
@@ -68866,7 +68866,7 @@ var import_semantic_conventions = __toESM(require_src(), 1);
68866
68866
  import { getLogger } from "./request-context.cjs";
68867
68867
  var {
68868
68868
  default: { version, name }
68869
- } = await import("../../esm-chunks/package-UN6EVEHD.js");
68869
+ } = await import("../../esm-chunks/package-AKXSA3EX.js");
68870
68870
  var sdk = new import_sdk_node.NodeSDK({
68871
68871
  resource: new import_resources.Resource({
68872
68872
  [import_semantic_conventions.SEMRESATTRS_SERVICE_NAME]: name,
@@ -7,9 +7,8 @@
7
7
  import "../esm-chunks/chunk-OEQOKJGE.js";
8
8
 
9
9
  // src/run/headers.ts
10
- import { encodeBlobKey } from "../shared/blobkey.js";
11
- import { getLogger } from "./handlers/request-context.cjs";
12
- import { getRegionalBlobStore } from "./regional-blob-store.cjs";
10
+ import { recordWarning } from "./handlers/tracer.cjs";
11
+ import { getMemoizedKeyValueStoreBackedByRegionalBlobStore } from "./storage/storage.cjs";
13
12
  var ALL_VARIATIONS = Symbol.for("ALL_VARIATIONS");
14
13
  var NetlifyVaryKeys = /* @__PURE__ */ new Set(["header", "language", "cookie", "query", "country"]);
15
14
  var isNetlifyVaryKey = (key) => NetlifyVaryKeys.has(key);
@@ -88,7 +87,6 @@ var adjustDateHeader = async ({
88
87
  headers,
89
88
  request,
90
89
  span,
91
- tracer,
92
90
  requestContext
93
91
  }) => {
94
92
  const key = new URL(request.url).pathname;
@@ -96,38 +94,24 @@ var adjustDateHeader = async ({
96
94
  if (requestContext.responseCacheGetLastModified) {
97
95
  lastModified = requestContext.responseCacheGetLastModified;
98
96
  } else {
99
- span.recordException(
100
- new Error("lastModified not found in requestContext, falling back to trying blobs")
97
+ recordWarning(
98
+ new Error("lastModified not found in requestContext, falling back to trying blobs"),
99
+ span
101
100
  );
102
- span.setAttributes({
103
- severity: "alert",
104
- warning: true
105
- });
106
- const blobStore = getRegionalBlobStore({ consistency: "strong" });
107
- const blobKey = await encodeBlobKey(key);
108
- lastModified = await tracer.withActiveSpan(
109
- "get cache to calculate date header",
110
- async (getBlobForDateSpan) => {
111
- getBlobForDateSpan.setAttributes({
112
- key,
113
- blobKey
114
- });
115
- const blob = await blobStore.get(blobKey, { type: "json" }) ?? {};
116
- getBlobForDateSpan.addEvent(blob ? "Cache hit" : "Cache miss");
117
- return blob.lastModified;
118
- }
101
+ const cacheStore = getMemoizedKeyValueStoreBackedByRegionalBlobStore({ consistency: "strong" });
102
+ const cacheEntry = await cacheStore.get(
103
+ key,
104
+ "get cache to calculate date header"
119
105
  );
106
+ lastModified = cacheEntry?.lastModified;
120
107
  }
121
108
  if (!lastModified) {
122
- span.recordException(
109
+ recordWarning(
123
110
  new Error(
124
111
  "lastModified not found in either requestContext or blobs, date header for cached response is not set"
125
- )
112
+ ),
113
+ span
126
114
  );
127
- span.setAttributes({
128
- severity: "alert",
129
- warning: true
130
- });
131
115
  return;
132
116
  }
133
117
  const lastModifiedDate = new Date(lastModified);
@@ -141,15 +125,11 @@ function setCacheControlFromRequestContext(headers, revalidate) {
141
125
  );
142
126
  headers.set("netlify-cdn-cache-control", cdnCacheControl);
143
127
  }
144
- var setCacheControlHeaders = ({ headers, status }, request, requestContext, nextConfig) => {
128
+ var setCacheControlHeaders = ({ headers, status }, request, requestContext) => {
145
129
  if (typeof requestContext.routeHandlerRevalidate !== "undefined" && ["GET", "HEAD"].includes(request.method) && !headers.has("cdn-cache-control") && !headers.has("netlify-cdn-cache-control")) {
146
130
  setCacheControlFromRequestContext(headers, requestContext.routeHandlerRevalidate);
147
131
  return;
148
132
  }
149
- if (status === 308 && request.url.endsWith("/") !== nextConfig.trailingSlash) {
150
- getLogger().withFields({ trailingSlash: nextConfig.trailingSlash, location: headers.get("location") }).log("NetlifyHeadersHandler.trailingSlashRedirect");
151
- }
152
- const cacheControl = headers.get("cache-control");
153
133
  if (status === 404) {
154
134
  if (request.url.endsWith(".php")) {
155
135
  headers.set("cache-control", "public, max-age=0, must-revalidate");
@@ -161,6 +141,7 @@ var setCacheControlHeaders = ({ headers, status }, request, requestContext, next
161
141
  return;
162
142
  }
163
143
  }
144
+ const cacheControl = headers.get("cache-control");
164
145
  if (cacheControl !== null && ["GET", "HEAD"].includes(request.method) && !headers.has("cdn-cache-control") && !headers.has("netlify-cdn-cache-control")) {
165
146
  const browserCacheControl = omitHeaderValues(cacheControl, [
166
147
  "s-maxage",
@@ -179,13 +160,16 @@ var setCacheControlHeaders = ({ headers, status }, request, requestContext, next
179
160
  headers.set("netlify-cdn-cache-control", cdnCacheControl);
180
161
  return;
181
162
  }
182
- if (cacheControl === null && ["GET", "HEAD"].includes(request.method) && !headers.has("cdn-cache-control") && !headers.has("netlify-cdn-cache-control") && requestContext.usedFsReadForNonFallback) {
163
+ if (cacheControl === null && ["GET", "HEAD"].includes(request.method) && !headers.has("cdn-cache-control") && !headers.has("netlify-cdn-cache-control") && requestContext.usedFsReadForNonFallback && !requestContext.didPagesRouterOnDemandRevalidate) {
183
164
  headers.set("cache-control", "public, max-age=0, must-revalidate");
184
165
  headers.set("netlify-cdn-cache-control", `max-age=31536000, durable`);
185
166
  }
186
167
  };
187
168
  var setCacheTagsHeaders = (headers, requestContext) => {
188
- if (requestContext.responseCacheTags && (headers.has("cache-control") || headers.has("netlify-cdn-cache-control"))) {
169
+ if (!headers.has("cache-control") && !headers.has("netlify-cdn-cache-control")) {
170
+ return;
171
+ }
172
+ if (requestContext.responseCacheTags) {
189
173
  headers.set("netlify-cache-tag", requestContext.responseCacheTags.join(","));
190
174
  }
191
175
  };
package/dist/run/next.cjs CHANGED
@@ -493,7 +493,7 @@ var import_path = require("path");
493
493
  var import_fs_monkey = __toESM(require_lib());
494
494
  var import_request_context = require("./handlers/request-context.cjs");
495
495
  var import_tracer = require("./handlers/tracer.cjs");
496
- var import_regional_blob_store = require("./regional-blob-store.cjs");
496
+ var import_storage = require("./storage/storage.cjs");
497
497
  process.env.NODE_ENV = "production";
498
498
  var { getRequestHandlers } = require("next/dist/server/lib/start-server.js");
499
499
  var ResponseCache = require("next/dist/server/response-cache/index.js").default;
@@ -543,18 +543,15 @@ async function getMockedRequestHandler(...args) {
543
543
  const tracer = (0, import_tracer.getTracer)();
544
544
  return tracer.withActiveSpan("mocked request handler", async () => {
545
545
  const ofs = { ...import_promises.default };
546
- const { encodeBlobKey } = await import("../shared/blobkey.js");
547
546
  async function readFileFallbackBlobStore(...fsargs) {
548
547
  const [path, options] = fsargs;
549
548
  try {
550
549
  return await ofs.readFile(path, options);
551
550
  } catch (error) {
552
551
  if (typeof path === "string" && path.endsWith(".html")) {
553
- const store = (0, import_regional_blob_store.getRegionalBlobStore)();
552
+ const cacheStore = (0, import_storage.getMemoizedKeyValueStoreBackedByRegionalBlobStore)();
554
553
  const relPath = (0, import_path.relative)((0, import_path.resolve)(".next/server/pages"), path);
555
- const file = await store.get(await encodeBlobKey(relPath), {
556
- type: "json"
557
- });
554
+ const file = await cacheStore.get(relPath, "staticHtml.get");
558
555
  if (file !== null) {
559
556
  if (!file.isFallback) {
560
557
  const requestContext = (0, import_request_context.getRequestContext)();
@@ -11,8 +11,8 @@ import { isPromise } from "node:util/types";
11
11
  function isRevalidateMethod(key, nextResponseField) {
12
12
  return key === "revalidate" && typeof nextResponseField === "function";
13
13
  }
14
- var nextResponseProxy = (res, requestContext) => {
15
- return new Proxy(res, {
14
+ var nextResponseProxy = (response, requestContext) => {
15
+ return new Proxy(response, {
16
16
  get(target, key) {
17
17
  const originalValue = Reflect.get(target, key);
18
18
  if (isRevalidateMethod(key, originalValue)) {