@netlify/plugin-nextjs 5.0.0-beta.8 → 5.0.0-rc.0

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.
Files changed (40) hide show
  1. package/README.md +23 -0
  2. package/dist/build/cache.js +1 -1
  3. package/dist/build/content/prerendered.js +2 -1
  4. package/dist/build/content/server.js +2 -1
  5. package/dist/build/content/static.js +1 -1
  6. package/dist/build/functions/edge.js +2 -3
  7. package/dist/build/functions/server.js +4 -4
  8. package/dist/build/image-cdn.js +3 -1
  9. package/dist/build/plugin-context.js +1 -2
  10. package/dist/build/templates/handler-monorepo.tmpl.js +33 -30
  11. package/dist/build/templates/handler.tmpl.js +31 -25
  12. package/dist/esm-chunks/{chunk-YMFYCTRI.js → chunk-4J4A5OE2.js} +23 -3
  13. package/dist/esm-chunks/{chunk-XFDUV7DP.js → chunk-67EWAGDQ.js} +29 -20
  14. package/dist/esm-chunks/chunk-72ZI2IVI.js +36 -0
  15. package/dist/esm-chunks/{chunk-WSPFUAK4.js → chunk-FTCARYDZ.js} +6 -6
  16. package/dist/esm-chunks/{chunk-XIP2W57K.js → chunk-NL5YH5N6.js} +5 -4
  17. package/dist/esm-chunks/{chunk-IZ2AVCVF.js → chunk-PGQNT7XM.js} +52 -24
  18. package/dist/esm-chunks/chunk-RL4K4CVH.js +27 -0
  19. package/dist/esm-chunks/{chunk-N23TUUXK.js → chunk-UTCWWUFW.js} +68 -29
  20. package/dist/esm-chunks/{chunk-ETPYUOBQ.js → chunk-UX4JCTAE.js} +5 -5
  21. package/dist/esm-chunks/{chunk-K233JI4O.js → chunk-UYKENJEU.js} +4 -2
  22. package/dist/esm-chunks/{chunk-ZWFKLYLH.js → chunk-WQIG4U66.js} +5 -4
  23. package/dist/esm-chunks/chunk-XXBTIYSL.js +7199 -0
  24. package/dist/esm-chunks/{package-2CI3IXK3.js → package-5SG7C3OT.js} +13 -8
  25. package/dist/index.js +13 -14
  26. package/dist/run/config.js +2 -2
  27. package/dist/run/constants.js +5 -3
  28. package/dist/run/handlers/cache.cjs +165 -79
  29. package/dist/run/handlers/request-context.cjs +56 -0
  30. package/dist/run/handlers/server.js +34 -20
  31. package/dist/run/handlers/tracing.js +1 -1
  32. package/dist/run/headers.js +3 -3
  33. package/dist/run/next.cjs +6 -1
  34. package/dist/run/revalidate.js +1 -1
  35. package/edge-runtime/lib/response.ts +25 -21
  36. package/edge-runtime/lib/util.ts +6 -1
  37. package/package.json +1 -1
  38. package/dist/esm-chunks/chunk-EPSI5TTB.js +0 -28
  39. package/dist/esm-chunks/chunk-WT2HN3M6.js +0 -255
  40. package/dist/esm-chunks/chunk-XA2CZH5Y.js +0 -32
@@ -8,7 +8,7 @@ import "./chunk-5JVNISGM.js";
8
8
 
9
9
  // package.json
10
10
  var name = "@netlify/plugin-nextjs";
11
- var version = "5.0.0-beta.8";
11
+ var version = "5.0.0-rc.0";
12
12
  var description = "Run Next.js seamlessly on Netlify";
13
13
  var main = "./dist/index.js";
14
14
  var type = "module";
@@ -26,9 +26,10 @@ var scripts = {
26
26
  pretest: "node tests/prepare.mjs",
27
27
  build: "node ./tools/build.js",
28
28
  "build:watch": "node ./tools/build.js --watch",
29
- lint: "eslint --cache --format=codeframe --max-warnings=0 src/**/*.ts",
29
+ lint: "eslint --cache --format=codeframe --max-warnings=0 --ext .ts,.cts,.js src",
30
30
  test: "vitest",
31
31
  "test:ci": "vitest run --reporter=default --retry=3",
32
+ typecheck: "tsc --noEmit",
32
33
  e2e: "playwright test",
33
34
  "e2e:ci": "playwright test"
34
35
  };
@@ -50,21 +51,22 @@ var homepage = "https://github.com/netlify/next-runtime-minimal#readme";
50
51
  var devDependencies = {
51
52
  "@fastly/http-compute-js": "1.1.4",
52
53
  "@netlify/blobs": "^6.5.0",
53
- "@netlify/build": "^29.33.5",
54
+ "@netlify/build": "^29.36.1",
54
55
  "@netlify/edge-bundler": "^11.2.2",
55
- "@netlify/edge-functions": "^2.3.0",
56
+ "@netlify/edge-functions": "^2.3.1",
56
57
  "@netlify/eslint-config-node": "^7.0.1",
57
58
  "@netlify/functions": "^2.5.1",
58
59
  "@netlify/serverless-functions-api": "^1.10.1",
59
- "@netlify/zip-it-and-ship-it": "^9.29.1",
60
+ "@netlify/zip-it-and-ship-it": "^9.29.2",
60
61
  "@opentelemetry/api": "^1.7.0",
61
- "@opentelemetry/sdk-node": "^0.48.0",
62
62
  "@opentelemetry/exporter-trace-otlp-http": "^0.48.0",
63
63
  "@opentelemetry/resources": "^1.21.0",
64
- "@opentelemetry/semantic-conventions": "^1.21.0",
64
+ "@opentelemetry/sdk-node": "^0.48.0",
65
65
  "@opentelemetry/sdk-trace-node": "^1.21.0",
66
+ "@opentelemetry/semantic-conventions": "^1.21.0",
66
67
  "@playwright/test": "^1.40.0",
67
68
  "@types/node": "^20.9.2",
69
+ "@types/picomatch": "^2.3.3",
68
70
  "@types/uuid": "^9.0.6",
69
71
  "@vercel/nft": "^0.26.0",
70
72
  cheerio: "^1.0.0-rc.12",
@@ -76,15 +78,18 @@ var devDependencies = {
76
78
  "get-port": "^7.0.0",
77
79
  "lambda-local": "^2.1.2",
78
80
  memfs: "^4.6.0",
81
+ "mock-require": "^3.0.3",
79
82
  msw: "^2.0.7",
80
83
  next: "^14.0.4",
81
84
  os: "^0.1.2",
82
85
  outdent: "^0.8.0",
83
86
  "p-limit": "^4.0.0",
87
+ picomatch: "^3.0.1",
88
+ "regexp-tree": "^0.1.27",
84
89
  typescript: "^5.1.6",
85
90
  unionfs: "^4.5.1",
86
91
  uuid: "^9.0.1",
87
- vitest: "^0.34.6"
92
+ vitest: "^1.2.2"
88
93
  };
89
94
  var clean_package = {
90
95
  indent: 2,
package/dist/index.js CHANGED
@@ -5,34 +5,34 @@
5
5
  })();
6
6
 
7
7
  import {
8
- createServerHandler
9
- } from "./esm-chunks/chunk-WSPFUAK4.js";
10
- import {
11
- copyFetchContent,
12
8
  copyPrerenderedContent
13
- } from "./esm-chunks/chunk-XFDUV7DP.js";
14
- import "./esm-chunks/chunk-YMFYCTRI.js";
9
+ } from "./esm-chunks/chunk-67EWAGDQ.js";
15
10
  import {
16
11
  copyStaticAssets,
17
12
  copyStaticContent,
18
13
  publishStaticDir,
19
14
  unpublishStaticDir
20
- } from "./esm-chunks/chunk-ZWFKLYLH.js";
15
+ } from "./esm-chunks/chunk-WQIG4U66.js";
21
16
  import {
22
17
  createEdgeHandlers
23
- } from "./esm-chunks/chunk-ETPYUOBQ.js";
18
+ } from "./esm-chunks/chunk-UX4JCTAE.js";
24
19
  import {
25
- PluginContext
26
- } from "./esm-chunks/chunk-IZ2AVCVF.js";
20
+ createServerHandler
21
+ } from "./esm-chunks/chunk-FTCARYDZ.js";
22
+ import "./esm-chunks/chunk-4J4A5OE2.js";
27
23
  import "./esm-chunks/chunk-VZNKO4OO.js";
28
- import "./esm-chunks/chunk-TYCYFZ22.js";
29
24
  import {
30
25
  restoreBuildCache,
31
26
  saveBuildCache
32
- } from "./esm-chunks/chunk-XA2CZH5Y.js";
27
+ } from "./esm-chunks/chunk-72ZI2IVI.js";
33
28
  import {
34
29
  setImageConfig
35
- } from "./esm-chunks/chunk-EPSI5TTB.js";
30
+ } from "./esm-chunks/chunk-XXBTIYSL.js";
31
+ import {
32
+ PluginContext
33
+ } from "./esm-chunks/chunk-PGQNT7XM.js";
34
+ import "./esm-chunks/chunk-UYKENJEU.js";
35
+ import "./esm-chunks/chunk-TYCYFZ22.js";
36
36
  import "./esm-chunks/chunk-5JVNISGM.js";
37
37
 
38
38
  // src/index.ts
@@ -58,7 +58,6 @@ var onBuild = async (options) => {
58
58
  copyStaticAssets(ctx),
59
59
  copyStaticContent(ctx),
60
60
  copyPrerenderedContent(ctx),
61
- copyFetchContent(ctx),
62
61
  createServerHandler(ctx),
63
62
  createEdgeHandlers(ctx)
64
63
  ]);
@@ -8,8 +8,8 @@ import {
8
8
  getRunConfig,
9
9
  getTagsManifest,
10
10
  setRunConfig
11
- } from "../esm-chunks/chunk-XIP2W57K.js";
12
- import "../esm-chunks/chunk-K233JI4O.js";
11
+ } from "../esm-chunks/chunk-NL5YH5N6.js";
12
+ import "../esm-chunks/chunk-UYKENJEU.js";
13
13
  import "../esm-chunks/chunk-5JVNISGM.js";
14
14
  export {
15
15
  getRunConfig,
@@ -6,10 +6,12 @@
6
6
 
7
7
  import {
8
8
  MODULE_DIR,
9
- PLUGIN_DIR
10
- } from "../esm-chunks/chunk-K233JI4O.js";
9
+ PLUGIN_DIR,
10
+ RUN_CONFIG
11
+ } from "../esm-chunks/chunk-UYKENJEU.js";
11
12
  import "../esm-chunks/chunk-5JVNISGM.js";
12
13
  export {
13
14
  MODULE_DIR,
14
- PLUGIN_DIR
15
+ PLUGIN_DIR,
16
+ RUN_CONFIG
15
17
  };
@@ -1347,12 +1347,12 @@ var require_status = __commonJS({
1347
1347
  "use strict";
1348
1348
  Object.defineProperty(exports2, "__esModule", { value: true });
1349
1349
  exports2.SpanStatusCode = void 0;
1350
- var SpanStatusCode;
1351
- (function(SpanStatusCode2) {
1352
- SpanStatusCode2[SpanStatusCode2["UNSET"] = 0] = "UNSET";
1353
- SpanStatusCode2[SpanStatusCode2["OK"] = 1] = "OK";
1354
- SpanStatusCode2[SpanStatusCode2["ERROR"] = 2] = "ERROR";
1355
- })(SpanStatusCode = exports2.SpanStatusCode || (exports2.SpanStatusCode = {}));
1350
+ var SpanStatusCode2;
1351
+ (function(SpanStatusCode3) {
1352
+ SpanStatusCode3[SpanStatusCode3["UNSET"] = 0] = "UNSET";
1353
+ SpanStatusCode3[SpanStatusCode3["OK"] = 1] = "OK";
1354
+ SpanStatusCode3[SpanStatusCode3["ERROR"] = 2] = "ERROR";
1355
+ })(SpanStatusCode2 = exports2.SpanStatusCode || (exports2.SpanStatusCode = {}));
1356
1356
  }
1357
1357
  });
1358
1358
 
@@ -2431,81 +2431,115 @@ var pipeline = (0, import_util.promisify)(import_stream.default.pipeline);
2431
2431
  var import_functions = __toESM(require_main());
2432
2432
  var import_api = __toESM(require_src());
2433
2433
  var import_constants = require("next/dist/lib/constants.js");
2434
+ var import_request_context = require("./request-context.cjs");
2434
2435
  var fetchBeforeNextPatchedIt = globalThis.fetch;
2435
2436
  var NetlifyCacheHandler = class {
2436
2437
  options;
2437
2438
  revalidatedTags;
2438
2439
  blobStore;
2439
2440
  tracer = import_api.trace.getTracer("Netlify Cache Handler");
2441
+ tagManifestsFetchedFromBlobStoreInCurrentRequest;
2440
2442
  constructor(options) {
2441
2443
  this.options = options;
2442
2444
  this.revalidatedTags = options.revalidatedTags;
2443
- this.blobStore = getDeployStore({ fetch: fetchBeforeNextPatchedIt });
2445
+ this.blobStore = getDeployStore({ fetch: fetchBeforeNextPatchedIt, consistency: "strong" });
2446
+ this.tagManifestsFetchedFromBlobStoreInCurrentRequest = {};
2444
2447
  }
2445
2448
  async encodeBlobKey(key) {
2446
2449
  const { encodeBlobKey: encodeBlobKey2 } = await Promise.resolve().then(() => (init_blobkey(), blobkey_exports));
2447
2450
  return await encodeBlobKey2(key);
2448
2451
  }
2452
+ captureResponseCacheLastModified(cacheValue, key, getCacheKeySpan) {
2453
+ if (cacheValue.value?.kind === "FETCH") {
2454
+ return;
2455
+ }
2456
+ const requestContext = (0, import_request_context.getRequestContext)();
2457
+ if (!requestContext) {
2458
+ getCacheKeySpan.recordException(
2459
+ new Error("CacheHandler was called without a request context")
2460
+ );
2461
+ getCacheKeySpan.setAttributes({
2462
+ severity: "alert",
2463
+ warning: true
2464
+ });
2465
+ return;
2466
+ }
2467
+ if (requestContext.responseCacheKey && requestContext.responseCacheKey !== key) {
2468
+ requestContext.responseCacheGetLastModified = void 0;
2469
+ getCacheKeySpan.recordException(
2470
+ new Error(
2471
+ `Multiple response cache keys used in single request: ["${requestContext.responseCacheKey}, "${key}"]`
2472
+ )
2473
+ );
2474
+ getCacheKeySpan.setAttributes({
2475
+ severity: "alert",
2476
+ warning: true
2477
+ });
2478
+ return;
2479
+ }
2480
+ requestContext.responseCacheKey = key;
2481
+ if (cacheValue.lastModified) {
2482
+ requestContext.responseCacheGetLastModified = cacheValue.lastModified;
2483
+ }
2484
+ }
2449
2485
  async get(...args) {
2450
2486
  return this.tracer.startActiveSpan("get cache key", async (span) => {
2451
- const [key, ctx = {}] = args;
2452
- console.debug(`[NetlifyCacheHandler.get]: ${key}`);
2453
- const blobKey = await this.encodeBlobKey(key);
2454
- span.setAttributes({ key, blobKey });
2455
- const blob = await this.blobStore.get(blobKey, {
2456
- type: "json"
2457
- });
2458
- if (!blob) {
2459
- span.addEvent("Cache miss", { key, blobKey });
2460
- span.end();
2487
+ try {
2488
+ const [key, ctx = {}] = args;
2489
+ console.debug(`[NetlifyCacheHandler.get]: ${key}`);
2490
+ const blobKey = await this.encodeBlobKey(key);
2491
+ span.setAttributes({ key, blobKey });
2492
+ const blob = await this.blobStore.get(blobKey, {
2493
+ type: "json"
2494
+ });
2495
+ if (!blob) {
2496
+ span.addEvent("Cache miss", { key, blobKey });
2497
+ return null;
2498
+ }
2499
+ const staleByTags = await this.checkCacheEntryStaleByTags(blob, ctx.tags, ctx.softTags);
2500
+ if (staleByTags) {
2501
+ span.addEvent("Stale", { staleByTags });
2502
+ return null;
2503
+ }
2504
+ this.captureResponseCacheLastModified(blob, key, span);
2505
+ switch (blob.value?.kind) {
2506
+ case "FETCH":
2507
+ span.addEvent("FETCH", { lastModified: blob.lastModified, revalidate: ctx.revalidate });
2508
+ return {
2509
+ lastModified: blob.lastModified,
2510
+ value: blob.value
2511
+ };
2512
+ case "ROUTE":
2513
+ span.addEvent("ROUTE", { lastModified: blob.lastModified, status: blob.value.status });
2514
+ return {
2515
+ lastModified: blob.lastModified,
2516
+ value: {
2517
+ ...blob.value,
2518
+ body: import_node_buffer2.Buffer.from(blob.value.body, "base64")
2519
+ }
2520
+ };
2521
+ case "PAGE":
2522
+ span.addEvent("PAGE", { lastModified: blob.lastModified });
2523
+ return {
2524
+ lastModified: blob.lastModified,
2525
+ value: blob.value
2526
+ };
2527
+ default:
2528
+ span.recordException(new Error(`Unknown cache entry kind: ${blob.value?.kind}`));
2529
+ }
2461
2530
  return null;
2462
- }
2463
- const staleByTags = await this.checkCacheEntryStaleByTags(blob, ctx.softTags);
2464
- if (staleByTags) {
2465
- span.addEvent("Stale", { staleByTags });
2531
+ } catch (error) {
2532
+ if (error instanceof Error) {
2533
+ span.recordException(error);
2534
+ }
2535
+ span.setStatus({
2536
+ code: import_api.SpanStatusCode.ERROR,
2537
+ message: error instanceof Error ? error.message : String(error)
2538
+ });
2539
+ throw error;
2540
+ } finally {
2466
2541
  span.end();
2467
- return null;
2468
2542
  }
2469
- switch (blob.value.kind) {
2470
- case "FETCH":
2471
- span.addEvent("FETCH", { lastModified: blob.lastModified, revalidate: ctx.revalidate });
2472
- span.end();
2473
- return {
2474
- lastModified: blob.lastModified,
2475
- value: {
2476
- kind: blob.value.kind,
2477
- data: blob.value.data,
2478
- revalidate: blob.value.revalidate
2479
- }
2480
- };
2481
- case "ROUTE":
2482
- span.addEvent("ROUTE", {
2483
- lastModified: blob.lastModified,
2484
- kind: blob.value.kind,
2485
- status: blob.value.status
2486
- });
2487
- span.end();
2488
- return {
2489
- lastModified: blob.lastModified,
2490
- value: {
2491
- body: import_node_buffer2.Buffer.from(blob.value.body, "base64"),
2492
- kind: blob.value.kind,
2493
- status: blob.value.status,
2494
- headers: blob.value.headers
2495
- }
2496
- };
2497
- case "PAGE":
2498
- span.addEvent("PAGE", { lastModified: blob.lastModified });
2499
- span.end();
2500
- return {
2501
- lastModified: blob.lastModified,
2502
- value: blob.value
2503
- };
2504
- default:
2505
- span.recordException(new Error(`Unknown cache entry kind: ${blob.value.kind}`));
2506
- }
2507
- span.end();
2508
- return null;
2509
2543
  });
2510
2544
  }
2511
2545
  async set(...args) {
@@ -2522,6 +2556,16 @@ var NetlifyCacheHandler = class {
2522
2556
  lastModified,
2523
2557
  value: data
2524
2558
  });
2559
+ if (data?.kind === "PAGE") {
2560
+ const requestContext = (0, import_request_context.getRequestContext)();
2561
+ if (requestContext?.didPagesRouterOnDemandRevalidate) {
2562
+ const tag = `_N_T_${key === "/index" ? "/" : key}`;
2563
+ console.debug("Purging CDN cache for:", [tag]);
2564
+ (0, import_functions.purgeCache)({ tags: [tag] }).catch((error) => {
2565
+ console.error(`[NetlifyCacheHandler]: Purging the cache for tag ${tag} failed`, error);
2566
+ });
2567
+ }
2568
+ }
2525
2569
  span.end();
2526
2570
  });
2527
2571
  }
@@ -2540,27 +2584,69 @@ var NetlifyCacheHandler = class {
2540
2584
  console.error(`[NetlifyCacheHandler]: Purging the cache for tag ${tag} failed`, error);
2541
2585
  });
2542
2586
  }
2587
+ resetRequestCache() {
2588
+ this.tagManifestsFetchedFromBlobStoreInCurrentRequest = {};
2589
+ }
2543
2590
  /**
2544
- * Checks if a page is stale through on demand revalidated tags
2591
+ * Checks if a cache entry is stale through on demand revalidated tags
2545
2592
  */
2546
- async checkCacheEntryStaleByTags(cacheEntry, softTags = []) {
2547
- const tags = "headers" in cacheEntry.value ? cacheEntry.value.headers?.[import_constants.NEXT_CACHE_TAGS_HEADER]?.split(",") || [] : [];
2548
- const cacheTags = [...tags, ...softTags];
2549
- const allManifests = await Promise.all(
2550
- cacheTags.map(async (tag) => {
2551
- const res = await this.blobStore.get(await this.encodeBlobKey(tag), { type: "json" }).then((value) => ({ [tag]: value })).catch(console.error);
2552
- return res || { [tag]: null };
2553
- })
2554
- );
2555
- const tagsManifest = Object.assign({}, ...allManifests);
2556
- const isStale = cacheTags.some((tag) => {
2557
- if (this.revalidatedTags?.includes(tag)) {
2558
- return true;
2593
+ async checkCacheEntryStaleByTags(cacheEntry, tags = [], softTags = []) {
2594
+ let cacheTags = [];
2595
+ if (cacheEntry.value?.kind === "FETCH") {
2596
+ cacheTags = [...tags, ...softTags];
2597
+ } else if (cacheEntry.value?.kind === "PAGE" || cacheEntry.value?.kind === "ROUTE") {
2598
+ cacheTags = cacheEntry.value.headers?.[import_constants.NEXT_CACHE_TAGS_HEADER]?.split(",") || [];
2599
+ } else {
2600
+ return false;
2601
+ }
2602
+ if (this.revalidatedTags && this.revalidatedTags.length !== 0) {
2603
+ for (const tag of this.revalidatedTags) {
2604
+ if (cacheTags.includes(tag)) {
2605
+ return true;
2606
+ }
2607
+ }
2608
+ }
2609
+ return new Promise((resolve, reject) => {
2610
+ const tagManifestPromises = [];
2611
+ for (const tag of cacheTags) {
2612
+ let tagManifestPromise = this.tagManifestsFetchedFromBlobStoreInCurrentRequest[tag];
2613
+ if (!tagManifestPromise) {
2614
+ tagManifestPromise = this.encodeBlobKey(tag).then((blobKey) => {
2615
+ return this.tracer.startActiveSpan(`get tag manifest`, async (span) => {
2616
+ span.setAttributes({ tag, blobKey });
2617
+ try {
2618
+ return await this.blobStore.get(blobKey, { type: "json" });
2619
+ } catch (error) {
2620
+ if (error instanceof Error) {
2621
+ span.recordException(error);
2622
+ }
2623
+ span.setStatus({
2624
+ code: import_api.SpanStatusCode.ERROR,
2625
+ message: error instanceof Error ? error.message : String(error)
2626
+ });
2627
+ throw error;
2628
+ } finally {
2629
+ span.end();
2630
+ }
2631
+ });
2632
+ });
2633
+ this.tagManifestsFetchedFromBlobStoreInCurrentRequest[tag] = tagManifestPromise;
2634
+ }
2635
+ tagManifestPromises.push(
2636
+ tagManifestPromise.then((tagManifest) => {
2637
+ const isStale = tagManifest?.revalidatedAt >= (cacheEntry.lastModified || Date.now());
2638
+ if (isStale) {
2639
+ resolve(true);
2640
+ return true;
2641
+ }
2642
+ return false;
2643
+ })
2644
+ );
2559
2645
  }
2560
- const { revalidatedAt } = tagsManifest[tag] || {};
2561
- return revalidatedAt && revalidatedAt >= (cacheEntry.lastModified || Date.now());
2646
+ Promise.all(tagManifestPromises).then((tagManifestAreStale) => {
2647
+ resolve(tagManifestAreStale.some((tagIsStale) => tagIsStale));
2648
+ }).catch(reject);
2562
2649
  });
2563
- return isStale;
2564
2650
  }
2565
2651
  };
2566
2652
  var cache_default = NetlifyCacheHandler;
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/run/handlers/request-context.cts
21
+ var request_context_exports = {};
22
+ __export(request_context_exports, {
23
+ createRequestContext: () => createRequestContext,
24
+ getRequestContext: () => getRequestContext,
25
+ runWithRequestContext: () => runWithRequestContext
26
+ });
27
+ module.exports = __toCommonJS(request_context_exports);
28
+ var import_node_async_hooks = require("node:async_hooks");
29
+ function createRequestContext() {
30
+ return {};
31
+ }
32
+ var REQUEST_CONTEXT_GLOBAL_KEY = Symbol.for("nf-request-context-async-local-storage");
33
+ var requestContextAsyncLocalStorage;
34
+ function getRequestContextAsyncLocalStorage() {
35
+ if (requestContextAsyncLocalStorage) {
36
+ return requestContextAsyncLocalStorage;
37
+ }
38
+ const extendedGlobalThis = globalThis;
39
+ if (extendedGlobalThis[REQUEST_CONTEXT_GLOBAL_KEY]) {
40
+ return extendedGlobalThis[REQUEST_CONTEXT_GLOBAL_KEY];
41
+ }
42
+ const storage = new import_node_async_hooks.AsyncLocalStorage();
43
+ requestContextAsyncLocalStorage = storage;
44
+ extendedGlobalThis[REQUEST_CONTEXT_GLOBAL_KEY] = storage;
45
+ return storage;
46
+ }
47
+ var getRequestContext = () => getRequestContextAsyncLocalStorage().getStore();
48
+ function runWithRequestContext(requestContext, fn) {
49
+ return getRequestContextAsyncLocalStorage().run(requestContext, fn);
50
+ }
51
+ // Annotate the CommonJS export names for ESM import in node:
52
+ 0 && (module.exports = {
53
+ createRequestContext,
54
+ getRequestContext,
55
+ runWithRequestContext
56
+ });
@@ -7,24 +7,24 @@
7
7
  import {
8
8
  require_src
9
9
  } from "../../esm-chunks/chunk-VDDK7MXY.js";
10
+ import {
11
+ import_internal
12
+ } from "../../esm-chunks/chunk-HYBEXB2Z.js";
10
13
  import {
11
14
  getTagsManifest
12
- } from "../../esm-chunks/chunk-XIP2W57K.js";
13
- import "../../esm-chunks/chunk-K233JI4O.js";
15
+ } from "../../esm-chunks/chunk-NL5YH5N6.js";
16
+ import "../../esm-chunks/chunk-UYKENJEU.js";
14
17
  import {
15
18
  adjustDateHeader,
16
- handleNextCacheHeader,
17
19
  setCacheControlHeaders,
20
+ setCacheStatusHeader,
18
21
  setCacheTagsHeaders,
19
22
  setVaryHeaders
20
- } from "../../esm-chunks/chunk-N23TUUXK.js";
23
+ } from "../../esm-chunks/chunk-UTCWWUFW.js";
21
24
  import "../../esm-chunks/chunk-TYCYFZ22.js";
22
25
  import {
23
26
  nextResponseProxy
24
- } from "../../esm-chunks/chunk-WT2HN3M6.js";
25
- import {
26
- import_internal
27
- } from "../../esm-chunks/chunk-HYBEXB2Z.js";
27
+ } from "../../esm-chunks/chunk-RL4K4CVH.js";
28
28
  import {
29
29
  __commonJS,
30
30
  __toESM
@@ -3261,6 +3261,7 @@ function toComputeResponse(res) {
3261
3261
 
3262
3262
  // src/run/handlers/server.ts
3263
3263
  var import_api = __toESM(require_src(), 1);
3264
+ import { createRequestContext, runWithRequestContext } from "./request-context.cjs";
3264
3265
  var nextHandler;
3265
3266
  var nextConfig;
3266
3267
  var tagsManifest;
@@ -3291,20 +3292,33 @@ var server_default = async (request) => {
3291
3292
  }
3292
3293
  return await tracer.startActiveSpan("generate response", async (span) => {
3293
3294
  const { req, res } = toReqRes(request);
3294
- const resProxy = nextResponseProxy(res);
3295
- delete req.headers["accept-encoding"];
3296
- const nextHandlerPromise = nextHandler(req, resProxy).catch((error) => {
3297
- import_internal.systemLogger.withError(error).error("next handler error");
3298
- console.error(error);
3299
- resProxy.statusCode = 500;
3300
- resProxy.end("Internal Server Error");
3301
- });
3295
+ const requestContext = createRequestContext();
3296
+ const resProxy = nextResponseProxy(res, requestContext);
3297
+ const nextHandlerPromise = runWithRequestContext(
3298
+ requestContext,
3299
+ () => nextHandler(req, resProxy).catch((error) => {
3300
+ import_internal.systemLogger.withError(error).error("next handler error");
3301
+ console.error(error);
3302
+ resProxy.statusCode = 500;
3303
+ span.recordException(error);
3304
+ span.setAttribute("http.status_code", 500);
3305
+ span.setStatus({
3306
+ code: import_api.SpanStatusCode.ERROR,
3307
+ message: error instanceof Error ? error.message : String(error)
3308
+ });
3309
+ span.end();
3310
+ resProxy.end("Internal Server Error");
3311
+ })
3312
+ );
3302
3313
  const response = await toComputeResponse(resProxy);
3303
- await adjustDateHeader(response.headers, request, span, tracer);
3304
- setCacheControlHeaders(response.headers, request);
3305
- setCacheTagsHeaders(response.headers, request, tagsManifest);
3314
+ if (requestContext.responseCacheKey) {
3315
+ span.setAttribute("responseCacheKey", requestContext.responseCacheKey);
3316
+ }
3317
+ await adjustDateHeader({ headers: response.headers, request, span, tracer, requestContext });
3318
+ setCacheControlHeaders(response.headers, request, requestContext);
3319
+ setCacheTagsHeaders(response.headers, request, tagsManifest, requestContext);
3306
3320
  setVaryHeaders(response.headers, request, nextConfig);
3307
- handleNextCacheHeader(response.headers);
3321
+ setCacheStatusHeader(response.headers);
3308
3322
  if (response.status > 300 && response.status < 400 || response.status >= 500) {
3309
3323
  const body = await response.text();
3310
3324
  span.end();
@@ -52794,7 +52794,7 @@ var import_semantic_conventions = __toESM(require_src2(), 1);
52794
52794
  var import_api = __toESM(require_src(), 1);
52795
52795
  var {
52796
52796
  default: { version, name }
52797
- } = await import("../../esm-chunks/package-2CI3IXK3.js");
52797
+ } = await import("../../esm-chunks/package-5SG7C3OT.js");
52798
52798
  var sdk = new import_sdk_node.NodeSDK({
52799
52799
  resource: new import_resources.Resource({
52800
52800
  [import_semantic_conventions.SemanticResourceAttributes.SERVICE_NAME]: name,
@@ -6,17 +6,17 @@
6
6
 
7
7
  import {
8
8
  adjustDateHeader,
9
- handleNextCacheHeader,
10
9
  setCacheControlHeaders,
10
+ setCacheStatusHeader,
11
11
  setCacheTagsHeaders,
12
12
  setVaryHeaders
13
- } from "../esm-chunks/chunk-N23TUUXK.js";
13
+ } from "../esm-chunks/chunk-UTCWWUFW.js";
14
14
  import "../esm-chunks/chunk-TYCYFZ22.js";
15
15
  import "../esm-chunks/chunk-5JVNISGM.js";
16
16
  export {
17
17
  adjustDateHeader,
18
- handleNextCacheHeader,
19
18
  setCacheControlHeaders,
19
+ setCacheStatusHeader,
20
20
  setCacheTagsHeaders,
21
21
  setVaryHeaders
22
22
  };
package/dist/run/next.cjs CHANGED
@@ -2734,11 +2734,11 @@ var pipeline = (0, import_util.promisify)(import_stream.default.pipeline);
2734
2734
  // src/run/next.cts
2735
2735
  var import_api = __toESM(require_src());
2736
2736
  var import_fs_monkey = __toESM(require_lib());
2737
+ var import_request_context = require("./handlers/request-context.cjs");
2737
2738
  var fetchBeforeNextPatchedIt = globalThis.fetch;
2738
2739
  async function getMockedRequestHandlers(...args) {
2739
2740
  const tracer = import_api.trace.getTracer("Next.js Runtime");
2740
2741
  return tracer.startActiveSpan("mocked request handler", async (span) => {
2741
- const store = getDeployStore({ fetch: fetchBeforeNextPatchedIt });
2742
2742
  const ofs = { ...import_promises.default };
2743
2743
  const { encodeBlobKey: encodeBlobKey2 } = await Promise.resolve().then(() => (init_blobkey(), blobkey_exports));
2744
2744
  async function readFileFallbackBlobStore(...fsargs) {
@@ -2747,9 +2747,14 @@ async function getMockedRequestHandlers(...args) {
2747
2747
  return await ofs.readFile(path, options);
2748
2748
  } catch (error) {
2749
2749
  if (typeof path === "string" && path.endsWith(".html")) {
2750
+ const store = getDeployStore({ fetch: fetchBeforeNextPatchedIt });
2750
2751
  const relPath = (0, import_path.relative)((0, import_path.resolve)(".next/server/pages"), path);
2751
2752
  const file = await store.get(await encodeBlobKey2(relPath));
2752
2753
  if (file !== null) {
2754
+ const requestContext = (0, import_request_context.getRequestContext)();
2755
+ if (requestContext) {
2756
+ requestContext.usedFsRead = true;
2757
+ }
2753
2758
  return file;
2754
2759
  }
2755
2760
  }
@@ -6,7 +6,7 @@
6
6
 
7
7
  import {
8
8
  nextResponseProxy
9
- } from "../esm-chunks/chunk-WT2HN3M6.js";
9
+ } from "../esm-chunks/chunk-RL4K4CVH.js";
10
10
  import "../esm-chunks/chunk-5JVNISGM.js";
11
11
  export {
12
12
  nextResponseProxy