vinext 1.0.0-beta.2 → 1.0.0-beta.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.
Files changed (126) hide show
  1. package/README.md +6 -9
  2. package/dist/build/client-build-config.js +7 -1
  3. package/dist/check.js +4 -0
  4. package/dist/config/config-matchers.js +4 -1
  5. package/dist/config/next-config.d.ts +12 -3
  6. package/dist/config/next-config.js +4 -0
  7. package/dist/entries/app-browser-entry.d.ts +4 -10
  8. package/dist/entries/app-browser-entry.js +20 -4
  9. package/dist/entries/app-rsc-entry.js +3 -0
  10. package/dist/entries/app-rsc-manifest.js +19 -0
  11. package/dist/entries/pages-client-entry.js +0 -1
  12. package/dist/entries/pages-server-entry.js +10 -3
  13. package/dist/index.js +112 -43
  14. package/dist/init-cloudflare.d.ts +3 -1
  15. package/dist/init-cloudflare.js +59 -5
  16. package/dist/plugins/extensionless-dynamic-import.js +23 -18
  17. package/dist/plugins/ignore-dynamic-requests.js +3 -1
  18. package/dist/plugins/import-meta-url.js +17 -6
  19. package/dist/plugins/require-context.js +20 -15
  20. package/dist/plugins/transform-cache.d.ts +19 -0
  21. package/dist/plugins/transform-cache.js +36 -0
  22. package/dist/routing/app-route-graph.d.ts +14 -6
  23. package/dist/routing/app-route-graph.js +106 -16
  24. package/dist/server/api-handler.d.ts +2 -0
  25. package/dist/server/api-handler.js +3 -3
  26. package/dist/server/app-browser-entry.js +103 -31
  27. package/dist/server/app-browser-navigation-controller.d.ts +23 -21
  28. package/dist/server/app-browser-navigation-controller.js +1 -1
  29. package/dist/server/app-page-cache-finalizer.js +1 -1
  30. package/dist/server/app-page-cache.d.ts +1 -1
  31. package/dist/server/app-page-cache.js +16 -2
  32. package/dist/server/app-page-dispatch.d.ts +8 -0
  33. package/dist/server/app-page-dispatch.js +31 -6
  34. package/dist/server/app-page-element-builder.d.ts +2 -0
  35. package/dist/server/app-page-element-builder.js +33 -7
  36. package/dist/server/app-page-head.d.ts +3 -3
  37. package/dist/server/app-page-head.js +58 -13
  38. package/dist/server/app-page-http-access-fallback-metadata.d.ts +2 -2
  39. package/dist/server/app-page-http-access-fallback-metadata.js +9 -1
  40. package/dist/server/app-page-probe.d.ts +4 -0
  41. package/dist/server/app-page-probe.js +6 -2
  42. package/dist/server/app-page-request.d.ts +3 -0
  43. package/dist/server/app-page-request.js +1 -1
  44. package/dist/server/app-page-response.js +1 -1
  45. package/dist/server/app-page-route-wiring.d.ts +7 -0
  46. package/dist/server/app-page-route-wiring.js +211 -49
  47. package/dist/server/app-pages-bridge.d.ts +1 -1
  48. package/dist/server/app-pages-bridge.js +2 -1
  49. package/dist/server/app-route-handler-cache.js +4 -0
  50. package/dist/server/app-route-handler-dispatch.js +9 -3
  51. package/dist/server/app-route-handler-response.js +1 -1
  52. package/dist/server/app-route-module-loader.d.ts +6 -0
  53. package/dist/server/app-route-module-loader.js +3 -0
  54. package/dist/server/app-router-entry.js +6 -3
  55. package/dist/server/app-rsc-errors.js +10 -0
  56. package/dist/server/app-rsc-handler.js +21 -9
  57. package/dist/server/app-rsc-route-matching.d.ts +9 -0
  58. package/dist/server/app-rsc-route-matching.js +6 -0
  59. package/dist/server/app-ssr-entry.js +4 -4
  60. package/dist/server/cache-control.d.ts +2 -2
  61. package/dist/server/cache-control.js +2 -1
  62. package/dist/server/dev-server.d.ts +3 -1
  63. package/dist/server/dev-server.js +145 -312
  64. package/dist/server/headers.d.ts +2 -2
  65. package/dist/server/headers.js +4 -3
  66. package/dist/server/isr-cache.d.ts +10 -33
  67. package/dist/server/isr-cache.js +33 -43
  68. package/dist/server/isr-decision.d.ts +2 -2
  69. package/dist/server/pages-api-route.d.ts +2 -0
  70. package/dist/server/pages-api-route.js +4 -1
  71. package/dist/server/pages-dev-hydration.js +0 -1
  72. package/dist/server/pages-get-initial-props.d.ts +1 -1
  73. package/dist/server/pages-get-initial-props.js +1 -4
  74. package/dist/server/pages-i18n.js +64 -16
  75. package/dist/server/pages-node-compat.d.ts +2 -0
  76. package/dist/server/pages-node-compat.js +7 -3
  77. package/dist/server/pages-page-data.d.ts +61 -9
  78. package/dist/server/pages-page-data.js +334 -74
  79. package/dist/server/pages-page-handler.d.ts +5 -1
  80. package/dist/server/pages-page-handler.js +115 -19
  81. package/dist/server/pages-page-response.d.ts +5 -3
  82. package/dist/server/pages-page-response.js +23 -26
  83. package/dist/server/pages-request-pipeline.d.ts +7 -0
  84. package/dist/server/pages-request-pipeline.js +5 -1
  85. package/dist/server/pages-revalidate.d.ts +1 -1
  86. package/dist/server/pages-revalidate.js +54 -8
  87. package/dist/server/pages-router-entry.d.ts +1 -0
  88. package/dist/server/pages-router-entry.js +10 -4
  89. package/dist/server/prod-server.d.ts +2 -1
  90. package/dist/server/prod-server.js +37 -13
  91. package/dist/server/revalidation-host.d.ts +11 -0
  92. package/dist/server/revalidation-host.js +19 -0
  93. package/dist/server/worker-revalidation-context.d.ts +13 -0
  94. package/dist/server/worker-revalidation-context.js +29 -0
  95. package/dist/shims/cache-handler.d.ts +1 -1
  96. package/dist/shims/cache-handler.js +10 -7
  97. package/dist/shims/cache-runtime.d.ts +6 -0
  98. package/dist/shims/cache-runtime.js +4 -1
  99. package/dist/shims/cache.js +1 -1
  100. package/dist/shims/error.js +1 -1
  101. package/dist/shims/fetch-cache.js +1 -1
  102. package/dist/shims/font-google-base.js +17 -8
  103. package/dist/shims/font-local.js +41 -10
  104. package/dist/shims/headers.d.ts +10 -13
  105. package/dist/shims/headers.js +85 -36
  106. package/dist/shims/internal/cookie-serialize.d.ts +10 -9
  107. package/dist/shims/internal/cookie-serialize.js +9 -8
  108. package/dist/shims/internal/interpolate-as.d.ts +15 -1
  109. package/dist/shims/internal/interpolate-as.js +27 -2
  110. package/dist/shims/link.js +18 -6
  111. package/dist/shims/metadata.d.ts +7 -17
  112. package/dist/shims/metadata.js +74 -24
  113. package/dist/shims/navigation.js +1 -1
  114. package/dist/shims/request-context.d.ts +4 -1
  115. package/dist/shims/router.js +18 -7
  116. package/dist/shims/script.js +1 -1
  117. package/dist/shims/server.d.ts +7 -6
  118. package/dist/shims/server.js +156 -57
  119. package/dist/shims/unified-request-context.d.ts +21 -2
  120. package/dist/shims/unified-request-context.js +82 -1
  121. package/dist/utils/cache-control-metadata.d.ts +2 -1
  122. package/dist/utils/cache-control-metadata.js +5 -1
  123. package/dist/utils/html-limited-bots.js +1 -1
  124. package/dist/utils/protocol-headers.d.ts +7 -1
  125. package/dist/utils/protocol-headers.js +7 -1
  126. package/package.json +1 -1
@@ -1,12 +1,13 @@
1
- import { createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
1
+ import { closeAfterResponse, closeAfterResponseWithBody, createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
2
2
  import { addBasePathToPathname, hasBasePath, stripBasePath } from "../utils/base-path.js";
3
3
  import { getRequestExecutionContext } from "../shims/request-context.js";
4
- import { VINEXT_MW_CTX_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER } from "../utils/protocol-headers.js";
4
+ import { VINEXT_MW_CTX_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER, VINEXT_REVALIDATE_HOST_HEADER } from "../utils/protocol-headers.js";
5
5
  import { ACTION_REVALIDATED_HEADER } from "./headers.js";
6
6
  import { requestContextFromRequest } from "../config/request-context.js";
7
7
  import { isExternalUrl } from "../utils/external-url.js";
8
8
  import { notFoundResponse } from "./http-error-responses.js";
9
9
  import { cloneRequestWithHeaders, cloneRequestWithUrl, filterInternalHeaders, normalizeTrailingSlash, resolvePublicFileRoute } from "./request-pipeline.js";
10
+ import { isOnDemandRevalidateRequest } from "./isr-cache.js";
10
11
  import { headersContextFromRequest } from "../shims/headers.js";
11
12
  import { ensureFetchPatch, setCurrentFetchSoftTags } from "../shims/fetch-cache.js";
12
13
  import { mergeRewriteQuery } from "../utils/query.js";
@@ -190,8 +191,9 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
190
191
  };
191
192
  let didMiddlewareRewrite = false;
192
193
  let didMiddlewareRewritePathname = false;
193
- if (options.runMiddleware) {
194
- const middlewareResult = await options.runMiddleware({
194
+ const runMiddleware = isOnDemandRevalidateRequest(request.headers.get("x-prerender-revalidate")) ? void 0 : options.runMiddleware;
195
+ if (runMiddleware) {
196
+ const middlewareResult = await runMiddleware({
195
197
  cleanPathname,
196
198
  context: middlewareContext,
197
199
  hadBasePath,
@@ -480,7 +482,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
480
482
  }
481
483
  if (pagesDataRequest) {
482
484
  options.clearRequestContext();
483
- if (options.runMiddleware && (middlewareContext.status === null || middlewareContext.status === 200 || middlewareContext.status === 404)) {
485
+ if (runMiddleware && (middlewareContext.status === null || middlewareContext.status === 200 || middlewareContext.status === 404)) {
484
486
  const response = buildNextDataNotFoundResponse();
485
487
  const headers = new Headers(response.headers);
486
488
  headers.set("x-nextjs-matched-path", matchPathname(canonicalPathname));
@@ -632,9 +634,11 @@ function createAppRscHandler(options) {
632
634
  const pagesDataNormalization = options.renderPagesFallback && pagesDataCandidate ? normalizePagesDataRequest(pagesDataCandidate, options.buildId, "", typeof options.runMiddleware === "function" && options.trailingSlash) : null;
633
635
  if (pagesDataNormalization?.notFoundResponse) return pagesDataNormalization.notFoundResponse;
634
636
  const isPagesDataRequest = pagesDataNormalization?.isDataReq === true;
637
+ const executionContext = isExecutionContextLike(ctx) ? ctx : getRequestExecutionContext() ?? null;
635
638
  const prerenderRouteParamsPayload = readTrustedPrerenderRouteParams(rawRequest);
636
639
  const isTrustedSpeculativePrerender = process.env.VINEXT_PRERENDER === "1" && rawRequest.headers.get("x-vinext-prerender-secret") !== null && rawRequest.headers.get("x-vinext-prerender-speculative") === "1";
637
- const filteredHeaders = filterInternalHeaders(rawRequest.headers);
640
+ const filteredHeaders = executionContext?.isInternalPagesRevalidation ? new Headers(rawRequest.headers) : filterInternalHeaders(rawRequest.headers);
641
+ filteredHeaders.delete(VINEXT_REVALIDATE_HOST_HEADER);
638
642
  if (mwCtx !== null) filteredHeaders.set(VINEXT_MW_CTX_HEADER, mwCtx);
639
643
  const prerenderRouteParamsHeader = serializePrerenderRouteParamsHeader(prerenderRouteParamsPayload);
640
644
  if (prerenderRouteParamsHeader !== null) filteredHeaders.set(VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, prerenderRouteParamsHeader);
@@ -647,12 +651,12 @@ function createAppRscHandler(options) {
647
651
  }
648
652
  const request = cloneRequestWithHeaders(appRequest, filteredHeaders);
649
653
  const pagesDataRequest = pagesDataNormalization?.isDataReq ? cloneRequestWithHeaders(pagesDataCandidate, filteredHeaders) : null;
650
- const executionContext = isExecutionContextLike(ctx) ? ctx : getRequestExecutionContext() ?? null;
651
- return runWithRequestContext(createRequestContext({
654
+ const requestContext = createRequestContext({
652
655
  headersContext: headersContextFromRequest(request, { draftModeSecret: options.draftModeSecret }),
653
656
  executionContext,
654
657
  unstableCacheRevalidation: "background"
655
- }), () => runWithPrerenderWorkUnit(async () => {
658
+ });
659
+ const responsePromise = runWithRequestContext(requestContext, () => runWithPrerenderWorkUnit(async () => {
656
660
  ensureFetchPatch();
657
661
  const preMiddlewareRequestContext = requestContextFromRequest(request);
658
662
  let response;
@@ -669,6 +673,14 @@ function createAppRscHandler(options) {
669
673
  requestContext: preMiddlewareRequestContext
670
674
  });
671
675
  }, { route: () => new URL(request.url).pathname }));
676
+ let response;
677
+ try {
678
+ response = await responsePromise;
679
+ } catch (error) {
680
+ await closeAfterResponse(requestContext);
681
+ throw error;
682
+ }
683
+ return closeAfterResponseWithBody(response, requestContext);
672
684
  };
673
685
  }
674
686
  //#endregion
@@ -33,8 +33,11 @@ type AppRscInterceptForMatching = {
33
33
  interceptLayouts: readonly unknown[];
34
34
  interceptLayoutSegments?: readonly (readonly string[])[];
35
35
  interceptBranchSegments?: readonly string[];
36
+ interceptLoadings?: readonly unknown[];
37
+ interceptLoadingTreePositions?: readonly number[];
36
38
  interceptNotFoundBranchSegments?: readonly string[];
37
39
  __loadInterceptLayouts?: readonly (() => Promise<unknown>)[] | null;
40
+ __loadInterceptLoadings?: readonly (() => Promise<unknown>)[] | null;
38
41
  page: unknown;
39
42
  __pageLoader?: (() => Promise<unknown>) | null;
40
43
  notFound?: unknown;
@@ -54,8 +57,11 @@ type AppRscSiblingInterceptForMatching = {
54
57
  interceptLayouts: readonly unknown[];
55
58
  interceptLayoutSegments?: readonly (readonly string[])[];
56
59
  interceptBranchSegments?: readonly string[];
60
+ interceptLoadings?: readonly unknown[];
61
+ interceptLoadingTreePositions?: readonly number[];
57
62
  interceptNotFoundBranchSegments?: readonly string[];
58
63
  __loadInterceptLayouts?: readonly (() => Promise<unknown>)[] | null;
64
+ __loadInterceptLoadings?: readonly (() => Promise<unknown>)[] | null;
59
65
  page: unknown;
60
66
  __pageLoader?: (() => Promise<unknown>) | null;
61
67
  notFound?: unknown;
@@ -93,8 +99,11 @@ type AppRscInterceptLookupEntry = {
93
99
  interceptLayouts: readonly unknown[];
94
100
  interceptLayoutSegments?: readonly (readonly string[])[];
95
101
  interceptBranchSegments?: readonly string[];
102
+ interceptLoadings?: readonly unknown[];
103
+ interceptLoadingTreePositions?: readonly number[];
96
104
  interceptNotFoundBranchSegments?: readonly string[];
97
105
  __loadInterceptLayouts?: readonly (() => Promise<unknown>)[] | null;
106
+ __loadInterceptLoadings?: readonly (() => Promise<unknown>)[] | null;
98
107
  page: unknown;
99
108
  __pageLoader?: (() => Promise<unknown>) | null;
100
109
  notFound: unknown;
@@ -170,8 +170,11 @@ function createInterceptLookup(routes) {
170
170
  interceptLayouts: intercept.interceptLayouts,
171
171
  interceptLayoutSegments: intercept.interceptLayoutSegments,
172
172
  interceptBranchSegments: intercept.interceptBranchSegments,
173
+ interceptLoadings: intercept.interceptLoadings,
174
+ interceptLoadingTreePositions: intercept.interceptLoadingTreePositions,
173
175
  interceptNotFoundBranchSegments: intercept.interceptNotFoundBranchSegments,
174
176
  __loadInterceptLayouts: intercept.__loadInterceptLayouts,
177
+ __loadInterceptLoadings: intercept.__loadInterceptLoadings,
175
178
  page: intercept.page,
176
179
  __pageLoader: intercept.__pageLoader,
177
180
  notFound: intercept.notFound,
@@ -203,8 +206,11 @@ function createInterceptLookup(routes) {
203
206
  interceptLayouts: intercept.interceptLayouts,
204
207
  interceptLayoutSegments: intercept.interceptLayoutSegments,
205
208
  interceptBranchSegments: intercept.interceptBranchSegments,
209
+ interceptLoadings: intercept.interceptLoadings,
210
+ interceptLoadingTreePositions: intercept.interceptLoadingTreePositions,
206
211
  interceptNotFoundBranchSegments: intercept.interceptNotFoundBranchSegments,
207
212
  __loadInterceptLayouts: intercept.__loadInterceptLayouts,
213
+ __loadInterceptLoadings: intercept.__loadInterceptLoadings,
208
214
  page: intercept.page,
209
215
  __pageLoader: intercept.__pageLoader,
210
216
  notFound: intercept.notFound,
@@ -6,13 +6,12 @@ import "./app-elements.js";
6
6
  import { isPprFallbackShellAbortError } from "../shims/ppr-fallback-shell.js";
7
7
  import { AppRouterContext } from "../shims/internal/app-router-context.js";
8
8
  import { appendAssetDeploymentIdQuery } from "../utils/deployment-id.js";
9
- import { ServerInsertedHTMLContext, clearServerInsertedHTML, getBfcacheIdMapContext, registerServerInsertedHTMLCallback, renderServerInsertedHTML, setNavigationContext } from "../shims/navigation-context-state.js";
10
- import "../shims/navigation-server.js";
11
- import { runWithNavigationContext } from "../shims/navigation-state.js";
12
9
  import { withScriptNonce } from "../shims/script-nonce-context.js";
13
10
  import { createInlineScriptTag, createNonceAttribute, escapeHtmlAttr, safeJsonStringify } from "./html.js";
14
11
  import { getClientTraceMetadataHTML } from "./client-trace-metadata.js";
15
12
  import { setPagesClientAssets } from "./pages-client-assets.js";
13
+ import { ServerInsertedHTMLContext, clearServerInsertedHTML, getBfcacheIdMapContext, registerServerInsertedHTMLCallback, renderServerInsertedHTML, setNavigationContext } from "../shims/navigation-context-state.js";
14
+ import "../shims/navigation-server.js";
16
15
  import DefaultGlobalError from "../shims/default-global-error.js";
17
16
  import { BfcacheStateKeyMapContext, ElementsContext, Slot } from "../shims/slot.js";
18
17
  import { createSsrErrorMetaRenderer } from "./app-ssr-error-meta.js";
@@ -22,6 +21,7 @@ import { RSC_FORM_STATE_GLOBAL } from "./app-browser-hydration.js";
22
21
  import { createClientReferencePreloader } from "./app-client-reference-preloader.js";
23
22
  import { deferUntilStreamConsumed } from "./defer-until-stream-consumed.js";
24
23
  import { runWithRootParamsScope } from "../shims/root-params.js";
24
+ import { runWithNavigationContext } from "../shims/navigation-state.js";
25
25
  import { BeforeInteractiveContext } from "../shims/before-interactive-context.js";
26
26
  import { renderBeforeInteractiveInlineScripts } from "./before-interactive-head.js";
27
27
  import { createInitialDevServerErrorScript } from "./dev-initial-server-error.js";
@@ -123,7 +123,7 @@ function renderFontHtml(fontData, nonce, options = {}) {
123
123
  const nonceAttr = createNonceAttribute(nonce);
124
124
  const includeStyles = options.includeStyles ?? true;
125
125
  for (const url of fontData.links ?? []) fontHTML += `<link rel="stylesheet"${nonceAttr} href="${escapeHtmlAttr(appendAssetDeploymentIdQuery(url))}" />\n`;
126
- for (const preload of fontData.preloads ?? []) fontHTML += `<link rel="preload"${nonceAttr} href="${escapeHtmlAttr(appendAssetDeploymentIdQuery(preload.href))}" as="font" type="${escapeHtmlAttr(preload.type)}" crossorigin />\n`;
126
+ for (const preload of fontData.preloads ?? []) fontHTML += `<link rel="preload"${nonceAttr} href="${escapeHtmlAttr(preload.href)}" as="font" type="${escapeHtmlAttr(preload.type)}" crossorigin />\n`;
127
127
  if (includeStyles && fontData.styles && fontData.styles.length > 0) fontHTML += `<style data-vinext-fonts${nonceAttr}>${fontData.styles.join("\n")}</style>\n`;
128
128
  return fontHTML;
129
129
  }
@@ -26,7 +26,7 @@ declare function applyCdnResponseHeaders(headers: Headers, input: CdnCacheableHe
26
26
  * Next.js source:
27
27
  * https://github.com/vercel/next.js/blob/canary/packages/next/src/server/lib/cache-control.ts
28
28
  */
29
- declare function buildRevalidateCacheControl(revalidateSeconds: number, expireSeconds?: number): string;
29
+ declare function buildRevalidateCacheControl(revalidateSeconds: number | false, expireSeconds?: number): string;
30
30
  /**
31
31
  * Builds Cache-Control for ISR cache reads. HIT responses and STALE responses
32
32
  * with stored expire metadata use the same route policy because Next.js derives
@@ -34,6 +34,6 @@ declare function buildRevalidateCacheControl(revalidateSeconds: number, expireSe
34
34
  * STALE entries without expire metadata keep vinext's legacy `s-maxage=0`
35
35
  * fallback so older cache entries are not treated as newly fresh downstream.
36
36
  */
37
- declare function buildCachedRevalidateCacheControl(cacheState: "HIT" | "STALE", revalidateSeconds: number, expireSeconds?: number): string;
37
+ declare function buildCachedRevalidateCacheControl(cacheState: "HIT" | "STALE", revalidateSeconds: number | false, expireSeconds?: number): string;
38
38
  //#endregion
39
39
  export { BROWSER_REVALIDATE_CACHE_CONTROL, NEVER_CACHE_CONTROL, NO_STORE_CACHE_CONTROL, STATIC_CACHE_CONTROL, applyCdnResponseHeaders, buildCachedRevalidateCacheControl, buildRevalidateCacheControl, shouldUseNextDeployCacheControl };
@@ -48,6 +48,7 @@ function applyCdnResponseHeaders(headers, input) {
48
48
  * https://github.com/vercel/next.js/blob/canary/packages/next/src/server/lib/cache-control.ts
49
49
  */
50
50
  function buildRevalidateCacheControl(revalidateSeconds, expireSeconds) {
51
+ if (revalidateSeconds === false) return STATIC_CACHE_CONTROL;
51
52
  if (expireSeconds === void 0) return `s-maxage=${revalidateSeconds}, stale-while-revalidate`;
52
53
  if (revalidateSeconds >= expireSeconds) return `s-maxage=${revalidateSeconds}`;
53
54
  return `s-maxage=${revalidateSeconds}, stale-while-revalidate=${expireSeconds - revalidateSeconds}`;
@@ -60,7 +61,7 @@ function buildRevalidateCacheControl(revalidateSeconds, expireSeconds) {
60
61
  * fallback so older cache entries are not treated as newly fresh downstream.
61
62
  */
62
63
  function buildCachedRevalidateCacheControl(cacheState, revalidateSeconds, expireSeconds) {
63
- if (revalidateSeconds === Infinity) return STATIC_CACHE_CONTROL;
64
+ if (revalidateSeconds === false || revalidateSeconds === Infinity) return STATIC_CACHE_CONTROL;
64
65
  if (cacheState === "STALE" && expireSeconds === void 0) return STALE_REVALIDATE_CACHE_CONTROL;
65
66
  return buildRevalidateCacheControl(revalidateSeconds, expireSeconds);
66
67
  }
@@ -53,7 +53,9 @@ clientTraceMetadata?: readonly string[], htmlLimitedBots?: string,
53
53
  * `nextConfig?.reactStrictMode === true`.
54
54
  */
55
55
 
56
- reactStrictMode?: boolean): (req: IncomingMessage, res: ServerResponse, url: string, /** Status code override propagated from middleware rewrite status. */
56
+ reactStrictMode?: boolean, /** Next.js `expireTime`, used when formatting terminal GSP responses. */
57
+
58
+ expireTime?: number): (req: IncomingMessage, res: ServerResponse, url: string, /** Status code override — propagated from middleware rewrite status. */
57
59
 
58
60
  statusCode?: number,
59
61
  /**