vinext 0.1.1 → 0.1.2

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 (147) hide show
  1. package/README.md +2 -5
  2. package/dist/build/client-build-config.d.ts +7 -1
  3. package/dist/build/client-build-config.js +9 -1
  4. package/dist/check.js +4 -3
  5. package/dist/client/navigation-runtime.d.ts +3 -2
  6. package/dist/client/window-next.d.ts +6 -4
  7. package/dist/config/config-matchers.d.ts +11 -4
  8. package/dist/config/config-matchers.js +15 -2
  9. package/dist/config/next-config.d.ts +13 -0
  10. package/dist/config/next-config.js +2 -0
  11. package/dist/deploy.js +9 -2
  12. package/dist/entries/app-rsc-entry.js +7 -1
  13. package/dist/entries/pages-client-entry.js +1 -1
  14. package/dist/entries/pages-server-entry.js +7 -6
  15. package/dist/index.d.ts +0 -2
  16. package/dist/index.js +86 -78
  17. package/dist/plugins/dynamic-preload-metadata.d.ts +13 -0
  18. package/dist/plugins/dynamic-preload-metadata.js +415 -0
  19. package/dist/plugins/og-assets.js +2 -2
  20. package/dist/plugins/optimize-imports.d.ts +8 -4
  21. package/dist/plugins/optimize-imports.js +16 -12
  22. package/dist/plugins/sass.d.ts +53 -24
  23. package/dist/plugins/sass.js +249 -1
  24. package/dist/plugins/wasm-module-import.d.ts +15 -0
  25. package/dist/plugins/wasm-module-import.js +50 -0
  26. package/dist/routing/app-route-graph.d.ts +23 -1
  27. package/dist/routing/app-route-graph.js +47 -8
  28. package/dist/routing/file-matcher.js +1 -1
  29. package/dist/server/app-browser-entry.js +108 -213
  30. package/dist/server/app-browser-error.d.ts +4 -1
  31. package/dist/server/app-browser-error.js +7 -1
  32. package/dist/server/app-browser-history-controller.d.ts +104 -0
  33. package/dist/server/app-browser-history-controller.js +210 -0
  34. package/dist/server/app-browser-navigation-controller.d.ts +3 -2
  35. package/dist/server/app-browser-navigation-controller.js +10 -7
  36. package/dist/server/app-browser-rsc-redirect.d.ts +11 -2
  37. package/dist/server/app-browser-rsc-redirect.js +30 -8
  38. package/dist/server/app-browser-state.js +4 -7
  39. package/dist/server/app-browser-visible-commit.js +1 -1
  40. package/dist/server/app-fallback-renderer.d.ts +2 -1
  41. package/dist/server/app-fallback-renderer.js +3 -1
  42. package/dist/server/app-middleware.js +1 -0
  43. package/dist/server/app-optimistic-routing.js +22 -1
  44. package/dist/server/app-page-boundary-render.d.ts +2 -1
  45. package/dist/server/app-page-boundary-render.js +4 -2
  46. package/dist/server/app-page-cache.js +9 -7
  47. package/dist/server/app-page-dispatch.d.ts +8 -0
  48. package/dist/server/app-page-dispatch.js +18 -5
  49. package/dist/server/app-page-element-builder.d.ts +22 -2
  50. package/dist/server/app-page-element-builder.js +37 -8
  51. package/dist/server/app-page-execution.d.ts +1 -1
  52. package/dist/server/app-page-execution.js +32 -17
  53. package/dist/server/app-page-render.d.ts +1 -1
  54. package/dist/server/app-page-render.js +7 -14
  55. package/dist/server/app-page-request.d.ts +1 -0
  56. package/dist/server/app-page-request.js +3 -2
  57. package/dist/server/app-page-response.js +1 -1
  58. package/dist/server/app-page-route-wiring.d.ts +3 -1
  59. package/dist/server/app-page-route-wiring.js +8 -7
  60. package/dist/server/app-page-stream.d.ts +1 -6
  61. package/dist/server/app-page-stream.js +1 -4
  62. package/dist/server/app-route-handler-response.js +11 -10
  63. package/dist/server/app-route-handler-runtime.js +12 -1
  64. package/dist/server/app-rsc-handler.js +1 -1
  65. package/dist/server/app-rsc-response-finalizer.js +1 -1
  66. package/dist/server/app-server-action-execution.d.ts +11 -0
  67. package/dist/server/app-server-action-execution.js +5 -2
  68. package/dist/server/app-ssr-entry.js +2 -2
  69. package/dist/server/app-ssr-stream.js +9 -1
  70. package/dist/server/dev-lockfile.js +2 -1
  71. package/dist/server/dev-server.js +43 -12
  72. package/dist/server/headers.d.ts +8 -1
  73. package/dist/server/headers.js +8 -1
  74. package/dist/server/instrumentation-runtime.d.ts +6 -0
  75. package/dist/server/instrumentation-runtime.js +8 -0
  76. package/dist/server/isr-decision.d.ts +79 -0
  77. package/dist/server/isr-decision.js +70 -0
  78. package/dist/server/metadata-route-response.js +5 -3
  79. package/dist/server/middleware-runtime.d.ts +13 -0
  80. package/dist/server/middleware-runtime.js +11 -7
  81. package/dist/server/middleware.js +1 -0
  82. package/dist/server/navigation-planner.d.ts +62 -1
  83. package/dist/server/navigation-planner.js +188 -0
  84. package/dist/server/navigation-trace.d.ts +11 -1
  85. package/dist/server/navigation-trace.js +11 -1
  86. package/dist/server/normalize-path.d.ts +0 -8
  87. package/dist/server/normalize-path.js +3 -1
  88. package/dist/server/otel-tracer-extension.d.ts +45 -0
  89. package/dist/server/otel-tracer-extension.js +89 -0
  90. package/dist/server/pages-api-route.d.ts +14 -3
  91. package/dist/server/pages-api-route.js +6 -1
  92. package/dist/server/pages-asset-tags.d.ts +15 -4
  93. package/dist/server/pages-asset-tags.js +18 -12
  94. package/dist/server/pages-data-route.js +5 -1
  95. package/dist/server/pages-node-compat.d.ts +3 -11
  96. package/dist/server/pages-node-compat.js +174 -121
  97. package/dist/server/pages-page-data.d.ts +28 -0
  98. package/dist/server/pages-page-data.js +61 -17
  99. package/dist/server/pages-page-handler.d.ts +1 -0
  100. package/dist/server/pages-page-handler.js +22 -6
  101. package/dist/server/pages-page-response.d.ts +45 -1
  102. package/dist/server/pages-page-response.js +66 -5
  103. package/dist/server/pages-readiness.d.ts +1 -1
  104. package/dist/server/pages-request-pipeline.d.ts +15 -1
  105. package/dist/server/pages-request-pipeline.js +23 -2
  106. package/dist/server/prod-server.d.ts +39 -1
  107. package/dist/server/prod-server.js +98 -34
  108. package/dist/shims/cache-runtime.js +9 -2
  109. package/dist/shims/dynamic-preload-chunks.d.ts +8 -0
  110. package/dist/shims/dynamic-preload-chunks.js +77 -0
  111. package/dist/shims/dynamic.d.ts +4 -0
  112. package/dist/shims/dynamic.js +4 -2
  113. package/dist/shims/error-boundary.d.ts +4 -4
  114. package/dist/shims/error.js +37 -11
  115. package/dist/shims/fetch-cache.d.ts +9 -1
  116. package/dist/shims/fetch-cache.js +11 -1
  117. package/dist/shims/head.js +6 -1
  118. package/dist/shims/headers.d.ts +16 -2
  119. package/dist/shims/headers.js +37 -1
  120. package/dist/shims/image-config.js +7 -1
  121. package/dist/shims/internal/app-route-detection.d.ts +6 -3
  122. package/dist/shims/internal/app-route-detection.js +10 -6
  123. package/dist/shims/internal/app-router-context.d.ts +5 -0
  124. package/dist/shims/metadata.d.ts +6 -2
  125. package/dist/shims/metadata.js +32 -14
  126. package/dist/shims/navigation.d.ts +7 -16
  127. package/dist/shims/navigation.js +33 -16
  128. package/dist/shims/router.js +28 -1
  129. package/dist/shims/script-nonce-context.d.ts +1 -1
  130. package/dist/shims/script-nonce-context.js +11 -3
  131. package/dist/shims/server.d.ts +17 -1
  132. package/dist/shims/server.js +31 -6
  133. package/dist/shims/slot.js +1 -1
  134. package/dist/shims/unified-request-context.js +1 -0
  135. package/dist/typegen.js +1 -0
  136. package/dist/utils/client-build-manifest.js +15 -5
  137. package/dist/utils/client-runtime-metadata.d.ts +45 -0
  138. package/dist/utils/client-runtime-metadata.js +63 -0
  139. package/dist/utils/hash.d.ts +17 -1
  140. package/dist/utils/hash.js +36 -1
  141. package/dist/utils/lazy-chunks.d.ts +27 -1
  142. package/dist/utils/lazy-chunks.js +65 -1
  143. package/dist/utils/manifest-paths.d.ts +20 -2
  144. package/dist/utils/manifest-paths.js +38 -3
  145. package/dist/utils/path.d.ts +2 -1
  146. package/dist/utils/path.js +5 -1
  147. package/package.json +2 -2
@@ -1,10 +1,11 @@
1
1
  import { VINEXT_MOUNTED_SLOTS_HEADER } from "./headers.js";
2
2
  import { setCacheStateHeaders } from "./cache-headers.js";
3
3
  import { encodeCacheTag } from "../utils/encode-cache-tag.js";
4
+ import { applyCdnResponseHeaders } from "./cache-control.js";
5
+ import { decideIsr } from "./isr-decision.js";
4
6
  import { buildAppPageCacheValue } from "./isr-cache.js";
5
7
  import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
6
8
  import { readStreamAsText } from "../utils/text-stream.js";
7
- import { applyCdnResponseHeaders, buildCachedRevalidateCacheControl } from "./cache-control.js";
8
9
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
9
10
  import { applyEdgeRuntimeHeader } from "./app-page-response.js";
10
11
  import { hasCompleteNegativeRequestApiProof } from "./cache-proof.js";
@@ -52,9 +53,6 @@ function buildAppPageCacheTags(pathname, extraTags) {
52
53
  for (const tag of extraTags) if (!tags.includes(tag)) tags.push(tag);
53
54
  return tags.map(encodeCacheTag);
54
55
  }
55
- function buildAppPageCacheControl(cacheState, revalidateSeconds, expireSeconds) {
56
- return buildCachedRevalidateCacheControl(cacheState, revalidateSeconds, expireSeconds);
57
- }
58
56
  function buildAppPageCachedHeaders(options) {
59
57
  const headers = new Headers({
60
58
  "Content-Type": options.contentType,
@@ -87,9 +85,13 @@ function resolveAppPageCacheWritePolicy(options) {
87
85
  }
88
86
  function buildAppPageCachedResponse(cachedValue, options) {
89
87
  const status = options.middlewareStatus ?? (cachedValue.status || 200);
90
- const revalidateSeconds = options.cacheControl?.revalidate ?? options.revalidateSeconds;
91
- const expireSeconds = options.cacheControl === void 0 ? void 0 : options.cacheControl.expire ?? options.expireSeconds;
92
- const cacheControl = buildAppPageCacheControl(options.cacheState, revalidateSeconds, expireSeconds);
88
+ const { cacheControl } = decideIsr({
89
+ cacheState: options.cacheState,
90
+ kind: "app-page",
91
+ revalidateSeconds: options.revalidateSeconds,
92
+ expireSeconds: options.expireSeconds,
93
+ cacheControlMeta: options.cacheControl
94
+ });
93
95
  if (options.isRscRequest) {
94
96
  if (!cachedValue.rscData) return null;
95
97
  const rscHeaders = buildAppPageCachedHeaders({
@@ -51,6 +51,12 @@ type AppPageModule = {
51
51
  dynamic?: unknown;
52
52
  revalidate?: unknown;
53
53
  };
54
+ type AppPageDispatchSlot = {
55
+ default?: AppPageModule | null;
56
+ page?: AppPageModule | null;
57
+ slotPatternParts?: readonly string[] | null;
58
+ slotParamNames?: readonly string[] | null;
59
+ };
54
60
  type AppPageDispatchRoute = {
55
61
  __buildTimeClassifications?: LayoutClassificationOptions["buildTimeClassifications"];
56
62
  __buildTimeReasons?: LayoutClassificationOptions["buildTimeReasons"];
@@ -67,6 +73,7 @@ type AppPageDispatchRoute = {
67
73
  params: readonly string[];
68
74
  pattern: string;
69
75
  routeSegments: readonly string[];
76
+ slots?: Readonly<Record<string, AppPageDispatchSlot>>;
70
77
  unauthorized?: AppPageModule | null;
71
78
  unauthorizeds?: readonly (AppPageModule | null | undefined)[];
72
79
  };
@@ -87,6 +94,7 @@ type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
87
94
  buildPageElement: (route: TRoute, params: AppPageParams, opts: AppPageDispatchInterceptOptions | undefined, searchParams: URLSearchParams, layoutParamAccess?: AppLayoutParamAccessTracker) => Promise<AppPageElement>;
88
95
  clientReuseManifest?: ClientReuseManifestParseResult;
89
96
  cleanPathname: string;
97
+ displayPathname?: string;
90
98
  clearRequestContext: () => void;
91
99
  createRscOnErrorHandler: (pathname: string, routePath: string) => AppPageBoundaryOnError;
92
100
  debugClassification?: (layoutId: string, reason: ClassificationReason) => void;
@@ -18,9 +18,10 @@ import { resolveAppPageParentHttpAccessBoundary, resolveAppPageParentHttpAccessB
18
18
  import { isAppSsrRenderResult } from "./app-page-stream.js";
19
19
  import { createAppLayoutParamAccessTracker, isAppLayoutObservationUnsafeForStaticReuse } from "./app-layout-param-observation.js";
20
20
  import { resolveAppPageMethodResponse } from "./app-page-method.js";
21
+ import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
22
+ import { resolveAppPageNavigationParams } from "./app-page-element-builder.js";
21
23
  import { buildAppPageElement, resolveAppPageIntercept, resolveAppPageInterceptionRerenderTarget, validateAppPageDynamicParams } from "./app-page-request.js";
22
24
  import { renderAppPageLifecycle } from "./app-page-render.js";
23
- import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
24
25
  import { createStaticGenerationHeadersContext } from "./app-static-generation.js";
25
26
  import { buildPageCacheTags } from "./implicit-tags.js";
26
27
  import React from "react";
@@ -124,7 +125,7 @@ async function runAppPageRevalidationContext(options, renderFn) {
124
125
  ensureFetchPatch();
125
126
  setCurrentFetchSoftTags(buildAppPageTags(options.cleanPathname, [], options.routeSegments));
126
127
  options.setNavigationContext({
127
- pathname: options.cleanPathname,
128
+ pathname: options.displayPathname ?? options.cleanPathname,
128
129
  searchParams: new URLSearchParams(),
129
130
  params: options.params
130
131
  });
@@ -183,10 +184,11 @@ async function dispatchAppPageInner(options) {
183
184
  routeKind: "page",
184
185
  routePattern: route.pattern
185
186
  }));
187
+ const staticNavigationParams = resolveAppPageNavigationParams(route, options.params, options.cleanPathname, null);
186
188
  options.setNavigationContext({
187
- pathname: options.cleanPathname,
189
+ pathname: options.displayPathname ?? options.cleanPathname,
188
190
  searchParams: new URLSearchParams(),
189
- params: options.params
191
+ params: staticNavigationParams
190
192
  });
191
193
  }
192
194
  if (shouldReadAppPageCache({
@@ -233,9 +235,11 @@ async function dispatchAppPageInner(options) {
233
235
  return toInterceptOptions(options.interceptionContext, intercept);
234
236
  }
235
237
  });
238
+ revalidationTarget.navigationParams = resolveAppPageNavigationParams(revalidationTarget.route, revalidationTarget.navigationParams, options.cleanPathname, revalidationTarget.interceptOpts);
236
239
  await options.ensureRouteLoaded?.(revalidationTarget.route);
237
240
  return runAppPageRevalidationContext({
238
241
  cleanPathname: options.cleanPathname,
242
+ displayPathname: options.displayPathname,
239
243
  currentFetchCacheMode: options.resolveRouteFetchCacheMode?.(revalidationTarget.route) ?? (revalidationTarget.route === route ? options.fetchCache ?? null : null),
240
244
  draftModeSecret: options.draftModeSecret,
241
245
  dynamicConfig,
@@ -352,6 +356,9 @@ async function dispatchAppPageInner(options) {
352
356
  },
353
357
  isRscRequest: options.isRscRequest,
354
358
  layoutParamAccess,
359
+ resolveNavigationParams(sourceRoute, navigationParams, pathname, interceptOpts) {
360
+ return resolveAppPageNavigationParams(sourceRoute, navigationParams, pathname, interceptOpts);
361
+ },
355
362
  renderInterceptResponse(sourceRoute, interceptElement) {
356
363
  const interceptOnError = options.createRscOnErrorHandler(options.cleanPathname, sourceRoute.pattern);
357
364
  const interceptStream = options.renderToReadableStream(interceptElement, { onError: interceptOnError });
@@ -387,6 +394,12 @@ async function dispatchAppPageInner(options) {
387
394
  resolveSpecialError: resolveAppPageSpecialError
388
395
  });
389
396
  if (pageBuildResult.response) return pageBuildResult.response;
397
+ const navigationParams = resolveAppPageNavigationParams(route, options.params, options.cleanPathname, interceptResult.interceptOpts);
398
+ options.setNavigationContext({
399
+ pathname: options.displayPathname ?? options.cleanPathname,
400
+ searchParams: options.searchParams,
401
+ params: navigationParams
402
+ });
390
403
  const layoutClassifications = getEffectiveLayoutClassifications(route, options.debugClassification);
391
404
  return renderAppPageLifecycle({
392
405
  basePath: options.basePath,
@@ -442,6 +455,7 @@ async function dispatchAppPageInner(options) {
442
455
  layoutCount: route.layouts.length,
443
456
  loadSsrHandler: options.loadSsrHandler,
444
457
  middlewareContext: options.middlewareContext,
458
+ navigationParams,
445
459
  params: options.params,
446
460
  layoutParamAccess,
447
461
  rootParams: options.rootParams,
@@ -495,7 +509,6 @@ async function dispatchAppPageInner(options) {
495
509
  return renderPageSpecialError(options, specialError);
496
510
  },
497
511
  renderToReadableStream: options.renderToReadableStream,
498
- routeHasLocalBoundary: Boolean(route.error?.default || route.errors?.some((errorModule) => errorModule?.default)),
499
512
  routePattern: route.pattern,
500
513
  runWithSuppressedHookWarning(probe) {
501
514
  return options.runWithSuppressedHookWarning(probe);
@@ -49,9 +49,28 @@ type BuildPageElementsOptions<TModule extends AppPageModule = AppPageModule, TEr
49
49
  * Configured next.config `basePath`. Threaded through `resolveAppPageHead`
50
50
  * so file-based metadata route URLs emitted in <head> are prefixed.
51
51
  */
52
- basePath?: string; /** Serialized next.config `htmlLimitedBots` regexp source. */
52
+ basePath?: string; /** Configured next.config `trailingSlash`, threaded into canonical URL rendering. */
53
+ trailingSlash?: boolean; /** Serialized next.config `htmlLimitedBots` regexp source. */
53
54
  htmlLimitedBots?: string;
54
55
  };
56
+ type AppPageNavigationParamModule = {
57
+ default?: unknown;
58
+ };
59
+ type AppPageNavigationParamSlot = {
60
+ default?: AppPageNavigationParamModule | null;
61
+ page?: AppPageNavigationParamModule | null;
62
+ slotPatternParts?: readonly string[] | null;
63
+ slotParamNames?: readonly string[] | null;
64
+ };
65
+ type AppPageNavigationParamRoute = {
66
+ params?: readonly string[] | null;
67
+ slots?: Readonly<Record<string, AppPageNavigationParamSlot>> | null;
68
+ };
69
+ type AppPageNavigationParamInterceptOptions = {
70
+ interceptPage?: unknown;
71
+ interceptParams?: AppPageParams | null;
72
+ interceptSlotKey?: string | null;
73
+ };
55
74
  /**
56
75
  * Build the App Router element tree for a matched route.
57
76
  *
@@ -69,5 +88,6 @@ type BuildPageElementsOptions<TModule extends AppPageModule = AppPageModule, TEr
69
88
  * {@link https://github.com/vercel/next.js/blob/canary/packages/next/src/server/app-render/create-metadata.tsx|create-metadata.tsx}.
70
89
  */
71
90
  declare function buildPageElements<TModule extends AppPageModule = AppPageModule, TErrorModule extends AppPageErrorModule = AppPageErrorModule>(options: BuildPageElementsOptions<TModule, TErrorModule>): Promise<AppElements>;
91
+ declare function resolveAppPageNavigationParams(route: AppPageNavigationParamRoute, routeParams: AppPageParams, routePath: string, opts?: AppPageNavigationParamInterceptOptions | null): AppPageParams;
72
92
  //#endregion
73
- export { AppPageBuildRoute, type AppPageErrorModule, AppPageInterceptOptions, AppPagePageRequest, type AppPageRouteWiringRoute, BuildPageElementsOptions, buildPageElements };
93
+ export { AppPageBuildRoute, type AppPageErrorModule, AppPageInterceptOptions, AppPagePageRequest, type AppPageRouteWiringRoute, BuildPageElementsOptions, buildPageElements, resolveAppPageNavigationParams };
@@ -8,8 +8,8 @@ import { resolveActiveParallelRouteHeadInputs, resolveAppPageHead } from "./app-
8
8
  import { makeObservedAppPageSearchParamsThenable } from "./app-page-search-params-observation.js";
9
9
  import { buildAppPageElements, createAppPageTreePath } from "./app-page-route-wiring.js";
10
10
  import { DEFAULT_GLOBAL_ERROR_MODULE } from "./default-global-error-module.js";
11
- import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
12
11
  import "./app-rsc-route-matching.js";
12
+ import { shouldServeStreamingMetadata } from "./streaming-metadata.js";
13
13
  import { createElement } from "react";
14
14
  //#region src/server/app-page-element-builder.ts
15
15
  /**
@@ -118,7 +118,8 @@ async function buildPageElements(options) {
118
118
  route,
119
119
  searchParams: pageSearchParamsThenable,
120
120
  slotOverrides,
121
- renderMode
121
+ renderMode,
122
+ trailingSlash: options.trailingSlash
122
123
  });
123
124
  }
124
125
  /**
@@ -142,6 +143,18 @@ function buildSlotOverrides(route, routeParams, routePath, opts) {
142
143
  pageModule: opts.interceptPage,
143
144
  params: opts.interceptParams || routeParams
144
145
  };
146
+ const slotParamOverrides = resolveSlotParamOverrides(route, routePath);
147
+ for (const [slotKey, params] of Object.entries(slotParamOverrides ?? {})) {
148
+ const existing = overrides[slotKey];
149
+ overrides[slotKey] = existing ? {
150
+ ...existing,
151
+ params
152
+ } : { params };
153
+ }
154
+ return Object.keys(overrides).length > 0 ? overrides : null;
155
+ }
156
+ function resolveSlotParamOverrides(route, routePath) {
157
+ const overrides = {};
145
158
  const slots = route.slots;
146
159
  if (slots) {
147
160
  let urlParts = null;
@@ -154,19 +167,35 @@ function buildSlotOverrides(route, routeParams, routePath, opts) {
154
167
  if (urlParts === null) urlParts = routePath.split("/").filter(Boolean);
155
168
  const matched = matchRoutePattern(urlParts, patternParts);
156
169
  if (!matched) continue;
157
- const existing = overrides[slotKey];
158
- overrides[slotKey] = existing ? {
159
- ...existing,
160
- params: matched
161
- } : { params: matched };
170
+ overrides[slotKey] = matched;
162
171
  }
163
172
  }
164
173
  return Object.keys(overrides).length > 0 ? overrides : null;
165
174
  }
175
+ function mergeAppPageParams(target, source) {
176
+ for (const [key, value] of Object.entries(source)) target[key] = value;
177
+ }
178
+ function isDefaultExportModule(module) {
179
+ return typeof module === "object" && module !== null;
180
+ }
181
+ function hasDefaultExport(module) {
182
+ if (!isDefaultExportModule(module)) return false;
183
+ return module?.default !== null && module?.default !== void 0;
184
+ }
185
+ function resolveAppPageNavigationParams(route, routeParams, routePath, opts) {
186
+ const navigationParams = { ...routeParams };
187
+ const slotParamOverrides = resolveSlotParamOverrides(route, routePath);
188
+ for (const [slotKey, slot] of Object.entries(route.slots ?? {})) {
189
+ const isInterceptedSlot = opts?.interceptSlotKey === slotKey && opts.interceptSlotKey !== "__vinext_page_intercept" && hasDefaultExport(opts.interceptPage);
190
+ if (!isInterceptedSlot && !hasDefaultExport(slot.page) && !hasDefaultExport(slot.default)) continue;
191
+ mergeAppPageParams(navigationParams, isInterceptedSlot ? opts?.interceptParams ?? routeParams : slotParamOverrides?.[slotKey] ?? routeParams);
192
+ }
193
+ return navigationParams;
194
+ }
166
195
  function collectParamNameSet(params) {
167
196
  const set = /* @__PURE__ */ new Set();
168
197
  if (params) for (const name of params) set.add(name);
169
198
  return set;
170
199
  }
171
200
  //#endregion
172
- export { buildPageElements };
201
+ export { buildPageElements, resolveAppPageNavigationParams };
@@ -103,7 +103,7 @@ type LayoutClassificationOptions = {
103
103
  * unsafe even if the older dynamic scope did not report dynamic usage.
104
104
  */
105
105
  isLayoutObservationDynamic?: (layoutId: string) => boolean; /** Runs a function with isolated dynamic usage tracking per layout. */
106
- runWithIsolatedDynamicScope: <T>(fn: () => T) => Promise<{
106
+ runWithIsolatedDynamicScope: <T>(fn: () => T | Promise<T>) => Promise<{
107
107
  result: T;
108
108
  dynamicDetected: boolean;
109
109
  }>;
@@ -1,5 +1,6 @@
1
1
  import { addBasePathToPathname } from "../utils/base-path.js";
2
2
  import { VINEXT_RSC_REDIRECT_HEADER } from "./headers.js";
3
+ import { runWithConnectionProbe } from "../shims/headers.js";
3
4
  import { VINEXT_RSC_CONTENT_TYPE, applyRscCompatibilityIdHeader, createRscRedirectLocation } from "./app-rsc-cache-busting.js";
4
5
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
5
6
  import { applyEdgeRuntimeHeader } from "./app-page-response.js";
@@ -180,10 +181,15 @@ async function buildAppPageSpecialErrorResponse(options) {
180
181
  }
181
182
  if (options.renderFallbackPage) {
182
183
  const fallbackResponse = await options.renderFallbackPage(options.specialError.statusCode);
183
- if (fallbackResponse) return mergeAppPageSpecialErrorHeaders(fallbackResponse, options.middlewareContext);
184
+ if (fallbackResponse) return mergeAppPageSpecialErrorHeaders(options.specialError.fromMetadata === true && options.serveStreamingMetadata !== false ? new Response(fallbackResponse.body, {
185
+ headers: fallbackResponse.headers,
186
+ status: 200,
187
+ statusText: fallbackResponse.statusText
188
+ }) : fallbackResponse, options.middlewareContext);
184
189
  }
185
190
  options.clearRequestContext();
186
- return mergeAppPageSpecialErrorHeaders(new Response(getAppPageStatusText(options.specialError.statusCode), { status: options.specialError.statusCode }), options.middlewareContext);
191
+ const responseStatus = options.specialError.fromMetadata === true && options.serveStreamingMetadata !== false ? 200 : options.specialError.statusCode;
192
+ return mergeAppPageSpecialErrorHeaders(new Response(getAppPageStatusText(options.specialError.statusCode), { status: responseStatus }), options.middlewareContext);
187
193
  }
188
194
  /** See `LayoutFlags` type docblock in app-elements.ts for lifecycle. */
189
195
  async function probeAppPageLayouts(options) {
@@ -210,7 +216,10 @@ async function probeAppPageLayouts(options) {
210
216
  if (cls) {
211
217
  const layoutId = cls.getLayoutId(layoutIndex);
212
218
  try {
213
- const { dynamicDetected } = await cls.runWithIsolatedDynamicScope(() => options.probeLayoutAt(layoutIndex));
219
+ const { dynamicDetected } = await cls.runWithIsolatedDynamicScope(async () => {
220
+ const outcome = await runWithConnectionProbe(() => options.probeLayoutAt(layoutIndex));
221
+ return outcome.completed ? outcome.result : null;
222
+ });
214
223
  const observationDynamic = cls.isLayoutObservationDynamic?.(layoutId) === true;
215
224
  const layoutDynamic = dynamicDetected || observationDynamic;
216
225
  layoutFlags[layoutId] = layoutDynamic ? "d" : "s";
@@ -239,25 +248,31 @@ async function probeAppPageLayouts(options) {
239
248
  };
240
249
  }
241
250
  async function probeLayoutForErrors(options, layoutIndex) {
242
- try {
243
- const layoutResult = options.probeLayoutAt(layoutIndex);
244
- if (isPromiseLike(layoutResult)) await layoutResult;
245
- } catch (error) {
246
- return options.onLayoutError(error, layoutIndex);
247
- }
248
- return null;
249
- }
250
- async function probeAppPageComponent(options) {
251
- return options.runWithSuppressedHookWarning(async () => {
251
+ const outcome = await runWithConnectionProbe(async () => {
252
252
  try {
253
- const pageResult = options.probePage();
254
- if (isPromiseLike(pageResult)) if (options.awaitAsyncResult) await pageResult;
255
- else Promise.resolve(pageResult).catch(() => {});
253
+ const layoutResult = options.probeLayoutAt(layoutIndex);
254
+ if (isPromiseLike(layoutResult)) await layoutResult;
256
255
  } catch (error) {
257
- return options.onError(error);
256
+ return options.onLayoutError(error, layoutIndex);
258
257
  }
259
258
  return null;
260
259
  });
260
+ return outcome.completed ? outcome.result : null;
261
+ }
262
+ async function probeAppPageComponent(options) {
263
+ return options.runWithSuppressedHookWarning(async () => {
264
+ const outcome = await runWithConnectionProbe(async () => {
265
+ try {
266
+ const pageResult = options.probePage();
267
+ if (isPromiseLike(pageResult)) if (options.awaitAsyncResult) await pageResult;
268
+ else Promise.resolve(pageResult).catch(() => {});
269
+ } catch (error) {
270
+ return options.onError(error);
271
+ }
272
+ return null;
273
+ });
274
+ return outcome.completed ? outcome.result : null;
275
+ });
261
276
  }
262
277
  async function readAppPageBinaryStream(stream) {
263
278
  const reader = stream.getReader();
@@ -68,6 +68,7 @@ type RenderAppPageLifecycleOptions = {
68
68
  layoutCount: number;
69
69
  loadSsrHandler: () => Promise<AppPageSsrHandler>;
70
70
  middlewareContext: AppPageMiddlewareContext;
71
+ navigationParams: Record<string, unknown>;
71
72
  params: Record<string, unknown>;
72
73
  rootParams?: RootParams;
73
74
  peekRenderObservationState?: () => AppPageRenderObservationState;
@@ -82,7 +83,6 @@ type RenderAppPageLifecycleOptions = {
82
83
  renderToReadableStream: (element: ReactNode | AppOutgoingElements, options: {
83
84
  onError: AppPageBoundaryOnError;
84
85
  }) => ReadableStream<Uint8Array>;
85
- routeHasLocalBoundary: boolean;
86
86
  routePattern: string;
87
87
  runWithSuppressedHookWarning<T>(probe: () => Promise<T>): Promise<T>;
88
88
  scriptNonce?: string;
@@ -1,8 +1,8 @@
1
+ import { NO_STORE_CACHE_CONTROL } from "./cache-control.js";
1
2
  import { createArtifactCompatibilityEnvelope, createArtifactCompatibilityGraphVersion } from "./artifact-compatibility.js";
2
3
  import { AppElementsWire, isAppElementsRecord } from "./app-elements-wire.js";
3
4
  import "./app-elements.js";
4
5
  import { runWithFetchDedupe } from "../shims/fetch-cache.js";
5
- import { NO_STORE_CACHE_CONTROL } from "./cache-control.js";
6
6
  import { buildAppPageHtmlResponse, buildAppPageRscResponse, resolveAppPageHtmlResponsePolicy, resolveAppPageRscResponsePolicy } from "./app-page-response.js";
7
7
  import { buildAppPageFontLinkHeader, readAppPageBinaryStream, resolveAppPageSpecialError, teeAppPageRscStreamForCapture } from "./app-page-execution.js";
8
8
  import { probeAppPageBeforeRender } from "./app-page-probe.js";
@@ -10,7 +10,7 @@ import { DEFAULT_CACHE_VARIANT_BUDGET, buildCacheVariantWithRouteBudget, buildRe
10
10
  import { createAppPageHtmlOutputScope, createAppPageRenderObservation, createAppPageRscOutputScope, createEmptyAppPageRenderObservationState } from "./app-page-render-observation.js";
11
11
  import { finalizeAppPageHtmlCacheResponse, finalizeAppPageRscCacheResponse } from "./app-page-cache.js";
12
12
  import { createStaticLayoutClientReuseArtifactCompatibility, createStaticLayoutClientReusePayloadHash, createStaticLayoutClientReuseRouteId } from "./static-layout-client-reuse-proof.js";
13
- import { buildAppPageLinkHeader, createAppPageFontData, createAppPageRscErrorTracker, deferUntilStreamConsumed, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery, shouldRerenderAppPageWithGlobalError } from "./app-page-stream.js";
13
+ import { buildAppPageLinkHeader, createAppPageFontData, createAppPageRscErrorTracker, deferUntilStreamConsumed, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery } from "./app-page-stream.js";
14
14
  import { getStaticLayoutObservationSkipRejection } from "./app-layout-param-observation.js";
15
15
  import { hasDigest } from "./app-rsc-errors.js";
16
16
  import { createClientReuseSkipTransportPlan, crossCheckClientReuseManifestEntryWithCache } from "./skip-cache-proof.js";
@@ -293,7 +293,7 @@ async function renderAppPageLifecycle(options) {
293
293
  cleanPathname: options.cleanPathname,
294
294
  completeness: "partial",
295
295
  output: rscOutputScope,
296
- params: options.params,
296
+ params: options.navigationParams,
297
297
  state: options.peekRenderObservationState?.() ?? createEmptyAppPageRenderObservationState()
298
298
  });
299
299
  const skipDisposition = options.skipDisposition ?? createRenderLifecycleSkipDisposition({
@@ -349,7 +349,7 @@ async function renderAppPageLifecycle(options) {
349
349
  isEdgeRuntime: options.isEdgeRuntime,
350
350
  middlewareContext: options.middlewareContext,
351
351
  mountedSlotsHeader: options.mountedSlotsHeader,
352
- params: options.params,
352
+ params: options.navigationParams,
353
353
  policy: rscResponsePolicy,
354
354
  timing: buildResponseTiming({
355
355
  compileEnd,
@@ -371,7 +371,7 @@ async function renderAppPageLifecycle(options) {
371
371
  cleanPathname: options.cleanPathname,
372
372
  completeness: "complete",
373
373
  output: rscOutputScope,
374
- params: options.params,
374
+ params: options.navigationParams,
375
375
  state: input.state
376
376
  });
377
377
  },
@@ -448,13 +448,6 @@ async function renderAppPageLifecycle(options) {
448
448
  }
449
449
  }
450
450
  }
451
- if (shouldRerenderAppPageWithGlobalError({
452
- capturedError: rscErrorTracker.getCapturedError(),
453
- hasLocalBoundary: options.routeHasLocalBoundary
454
- })) {
455
- const cleanResponse = await options.renderErrorBoundaryResponse(rscErrorTracker.getCapturedError());
456
- if (cleanResponse) return cleanResponse;
457
- }
458
451
  if (options.isPrerender === true) {
459
452
  await settleCapturedRscRenderForCacheMetadata(htmlRender.capturedRscData);
460
453
  ({expireSeconds, revalidateSeconds} = applyRequestCacheLife({
@@ -516,7 +509,7 @@ async function renderAppPageLifecycle(options) {
516
509
  cleanPathname: options.cleanPathname,
517
510
  completeness: "complete",
518
511
  output: htmlOutputScope,
519
- params: options.params,
512
+ params: options.navigationParams,
520
513
  state: input.state
521
514
  });
522
515
  },
@@ -528,7 +521,7 @@ async function renderAppPageLifecycle(options) {
528
521
  cleanPathname: options.cleanPathname,
529
522
  completeness: "complete",
530
523
  output: rscOutputScope,
531
- params: options.params,
524
+ params: options.navigationParams,
532
525
  state: input.state
533
526
  });
534
527
  },
@@ -87,6 +87,7 @@ type ResolveAppPageInterceptOptions<TRoute, TPage, TInterceptOpts, TElement> = {
87
87
  getSourceRoute: (sourceRouteIndex: number) => Awaitable<TRoute | undefined>;
88
88
  isRscRequest: boolean;
89
89
  layoutParamAccess?: AppLayoutParamAccessTracker;
90
+ resolveNavigationParams: (route: TRoute, params: AppPageParams, pathname: string, interceptOpts: TInterceptOpts) => AppPageParams;
90
91
  renderInterceptResponse: (route: TRoute, element: TElement) => Promise<Response> | Response;
91
92
  searchParams: URLSearchParams;
92
93
  setNavigationContext: (context: {
@@ -155,13 +155,14 @@ async function resolveAppPageIntercept(options) {
155
155
  });
156
156
  if (interceptState.kind === "source-route") {
157
157
  const renderRoute = interceptState.sourceRoute;
158
+ const interceptOpts = options.toInterceptOpts(interceptState.intercept);
158
159
  const renderParams = pickRouteParams(interceptState.intercept.matchedParams, options.getRouteParamNames(interceptState.sourceRoute));
159
160
  options.setNavigationContext({
160
- params: interceptState.intercept.matchedParams,
161
+ params: options.resolveNavigationParams(renderRoute, interceptState.intercept.matchedParams, options.cleanPathname, interceptOpts),
161
162
  pathname: options.cleanPathname,
162
163
  searchParams: options.searchParams
163
164
  });
164
- const interceptElement = await options.buildPageElement(renderRoute, renderParams, options.toInterceptOpts(interceptState.intercept), options.searchParams, options.layoutParamAccess);
165
+ const interceptElement = await options.buildPageElement(renderRoute, renderParams, interceptOpts, options.searchParams, options.layoutParamAccess);
165
166
  return {
166
167
  interceptOpts: void 0,
167
168
  response: await options.renderInterceptResponse(renderRoute, interceptElement)
@@ -1,7 +1,7 @@
1
1
  import { VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_PARAMS_HEADER, VINEXT_TIMING_HEADER } from "./headers.js";
2
2
  import { setCacheStateHeaders } from "./cache-headers.js";
3
- import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
4
3
  import { NO_STORE_CACHE_CONTROL, STATIC_CACHE_CONTROL, buildRevalidateCacheControl } from "./cache-control.js";
4
+ import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
5
5
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
6
6
  //#region src/server/app-page-response.ts
7
7
  function applyTimingHeader(headers, timing) {
@@ -113,6 +113,7 @@ type BuildAppPageRouteElementOptions<TModule extends AppPageModule = AppPageModu
113
113
  resolvedMetadata: Metadata | null;
114
114
  resolvedMetadataPathname?: string;
115
115
  resolvedViewport: Viewport;
116
+ trailingSlash?: boolean;
116
117
  rootForbiddenModule?: TModule | null;
117
118
  rootNotFoundModule?: TModule | null;
118
119
  rootUnauthorizedModule?: TModule | null;
@@ -142,6 +143,7 @@ declare function createAppPageLayoutEntries<TModule extends AppPageModule, TErro
142
143
  forbiddens?: readonly (TModule | null | undefined)[] | null;
143
144
  unauthorizeds?: readonly (TModule | null | undefined)[] | null;
144
145
  }): AppPageLayoutEntry<TModule, TErrorModule>[];
146
+ declare function createAppPageRouteBodyMetadata(metadata: Metadata | null, pathname: string, metadataPlacement: "body" | "head", trailingSlash?: boolean): ReactNode;
145
147
  declare function buildAppPageElements<TModule extends AppPageModule, TErrorModule extends AppPageErrorModule>(options: BuildAppPageElementsOptions<TModule, TErrorModule>): AppElements;
146
148
  //#endregion
147
- export { AppPageErrorModule, AppPageModule, AppPageRouteWiringRoute, AppPageSlotOverride, buildAppPageElements, createAppPageLayoutEntries, createAppPageTreePath, probeAppPageLayoutWithTracking, resolveAppPageChildSegments };
149
+ export { AppPageErrorModule, AppPageModule, AppPageRouteWiringRoute, AppPageSlotOverride, buildAppPageElements, createAppPageLayoutEntries, createAppPageRouteBodyMetadata, createAppPageTreePath, probeAppPageLayoutWithTracking, resolveAppPageChildSegments };
@@ -139,21 +139,22 @@ function createAppPageSlotBindings(route, layoutEntries, resolveSlotOverride, op
139
139
  }
140
140
  return normalizeAppElementsSlotBindings(bindings, { layoutIds: layoutEntries.map((entry) => entry.id) });
141
141
  }
142
- function createAppPageRouteHead(metadata, viewport, pathname, metadataPlacement) {
142
+ function createAppPageRouteHead(metadata, viewport, pathname, metadataPlacement, trailingSlash) {
143
143
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [
144
144
  /* @__PURE__ */ jsx("meta", { charSet: "utf-8" }),
145
145
  metadata && metadataPlacement === "head" ? /* @__PURE__ */ jsx(MetadataHead, {
146
146
  metadata,
147
- pathname
147
+ pathname,
148
+ trailingSlash
148
149
  }) : null,
149
150
  /* @__PURE__ */ jsx(ViewportHead, { viewport })
150
151
  ] });
151
152
  }
152
- function createAppPageRouteBodyMetadata(metadata, pathname, metadataPlacement) {
153
+ function createAppPageRouteBodyMetadata(metadata, pathname, metadataPlacement, trailingSlash) {
153
154
  if (!metadata || metadataPlacement !== "body") return null;
154
155
  return /* @__PURE__ */ jsx("div", {
155
156
  hidden: true,
156
- dangerouslySetInnerHTML: { __html: renderMetadataToHtml(metadata, pathname) }
157
+ dangerouslySetInnerHTML: { __html: renderMetadataToHtml(metadata, pathname, { trailingSlash }) }
157
158
  });
158
159
  }
159
160
  function buildAppPageElements(options) {
@@ -431,12 +432,12 @@ function buildAppPageElements(options) {
431
432
  children: routeChildren
432
433
  });
433
434
  elements[routeId] = /* @__PURE__ */ jsxs(Fragment$1, { children: [
434
- createAppPageRouteHead(options.resolvedMetadata, options.resolvedViewport, options.resolvedMetadataPathname ?? options.routePath, metadataPlacement),
435
+ createAppPageRouteHead(options.resolvedMetadata, options.resolvedViewport, options.resolvedMetadataPathname ?? options.routePath, metadataPlacement, options.trailingSlash),
435
436
  routeChildren,
436
- createAppPageRouteBodyMetadata(options.resolvedMetadata, options.resolvedMetadataPathname ?? options.routePath, metadataPlacement)
437
+ createAppPageRouteBodyMetadata(options.resolvedMetadata, options.resolvedMetadataPathname ?? options.routePath, metadataPlacement, options.trailingSlash)
437
438
  ] });
438
439
  registerAppElementRenderDependencies(elements, renderDependenciesByElementId);
439
440
  return elements;
440
441
  }
441
442
  //#endregion
442
- export { buildAppPageElements, createAppPageLayoutEntries, createAppPageTreePath, probeAppPageLayoutWithTracking, resolveAppPageChildSegments };
443
+ export { buildAppPageElements, createAppPageLayoutEntries, createAppPageRouteBodyMetadata, createAppPageTreePath, probeAppPageLayoutWithTracking, resolveAppPageChildSegments };
@@ -129,10 +129,6 @@ type AppPageRscErrorTracker = {
129
129
  getCapturedSpecialError: () => unknown;
130
130
  onRenderError: (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown;
131
131
  };
132
- type ShouldRerenderAppPageWithGlobalErrorOptions = {
133
- capturedError: unknown;
134
- hasLocalBoundary: boolean;
135
- };
136
132
  declare function createAppPageFontData(options: CreateAppPageFontDataOptions): AppPageFontData;
137
133
  declare function renderAppPageHtmlStream(options: RenderAppPageHtmlStreamOptions): Promise<AppSsrRenderResult>;
138
134
  /**
@@ -146,6 +142,5 @@ declare function deferUntilStreamConsumed(stream: ReadableStream<Uint8Array>, on
146
142
  declare function renderAppPageHtmlResponse(options: RenderAppPageHtmlResponseOptions): Promise<Response>;
147
143
  declare function renderAppPageHtmlStreamWithRecovery<TSpecialError>(options: RenderAppPageHtmlStreamWithRecoveryOptions<TSpecialError>): Promise<AppPageHtmlStreamRecoveryResult>;
148
144
  declare function createAppPageRscErrorTracker(baseOnError: (error: unknown, requestInfo: unknown, errorContext: unknown) => unknown): AppPageRscErrorTracker;
149
- declare function shouldRerenderAppPageWithGlobalError(options: ShouldRerenderAppPageWithGlobalErrorOptions): boolean;
150
145
  //#endregion
151
- export { AppPageFontData, AppPageSsrHandler, AppSsrRenderResult, buildAppPageLinkHeader, createAppPageFontData, createAppPageRscErrorTracker, deferUntilStreamConsumed, isAppSsrRenderResult, renderAppPageHtmlResponse, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery, shouldRerenderAppPageWithGlobalError };
146
+ export { AppPageFontData, AppPageSsrHandler, AppSsrRenderResult, buildAppPageLinkHeader, createAppPageFontData, createAppPageRscErrorTracker, deferUntilStreamConsumed, isAppSsrRenderResult, renderAppPageHtmlResponse, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery };
@@ -166,8 +166,5 @@ function createAppPageRscErrorTracker(baseOnError) {
166
166
  }
167
167
  };
168
168
  }
169
- function shouldRerenderAppPageWithGlobalError(options) {
170
- return Boolean(options.capturedError) && !options.hasLocalBoundary;
171
- }
172
169
  //#endregion
173
- export { buildAppPageLinkHeader, createAppPageFontData, createAppPageRscErrorTracker, deferUntilStreamConsumed, isAppSsrRenderResult, renderAppPageHtmlResponse, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery, shouldRerenderAppPageWithGlobalError };
170
+ export { buildAppPageLinkHeader, createAppPageFontData, createAppPageRscErrorTracker, deferUntilStreamConsumed, isAppSsrRenderResult, renderAppPageHtmlResponse, renderAppPageHtmlStream, renderAppPageHtmlStreamWithRecovery };
@@ -1,7 +1,8 @@
1
1
  import "./headers.js";
2
2
  import { processMiddlewareHeaders } from "./request-pipeline.js";
3
3
  import { setCacheStateHeaders } from "./cache-headers.js";
4
- import { NEVER_CACHE_CONTROL, STATIC_CACHE_CONTROL, applyCdnResponseHeaders, buildCachedRevalidateCacheControl } from "./cache-control.js";
4
+ import { applyCdnResponseHeaders } from "./cache-control.js";
5
+ import { buildAppRouteMissIsrCacheControl, decideIsr } from "./isr-decision.js";
5
6
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
6
7
  import { getSetCookieName } from "./cookie-utils.js";
7
8
  //#region src/server/app-route-handler-response.ts
@@ -11,11 +12,6 @@ function hasMiddlewareHeader(headers) {
11
12
  for (const key of headers.keys()) if (key.startsWith("x-middleware-")) return true;
12
13
  return false;
13
14
  }
14
- function buildRouteHandlerCacheControl(cacheState, revalidateSeconds, expireSeconds) {
15
- if (revalidateSeconds === 0) return NEVER_CACHE_CONTROL;
16
- if (revalidateSeconds === Infinity) return STATIC_CACHE_CONTROL;
17
- return buildCachedRevalidateCacheControl(cacheState, revalidateSeconds, expireSeconds);
18
- }
19
15
  function applyRouteHandlerMiddlewareContext(response, middlewareContext) {
20
16
  if (!middlewareContext.headers && middlewareContext.status == null) return response;
21
17
  const responseHeaders = new Headers(response.headers);
@@ -35,9 +31,14 @@ function buildRouteHandlerCachedResponse(cachedValue, options) {
35
31
  for (const [key, value] of Object.entries(cachedValue.headers)) if (Array.isArray(value)) for (const entry of value) headers.append(key, entry);
36
32
  else headers.set(key, value);
37
33
  setCacheStateHeaders(headers, options.cacheState);
38
- const revalidateSeconds = options.cacheControl?.revalidate ?? options.revalidateSeconds;
39
- const expireSeconds = options.cacheControl === void 0 ? void 0 : options.cacheControl.expire ?? options.expireSeconds;
40
- applyCdnResponseHeaders(headers, { cacheControl: buildRouteHandlerCacheControl(options.cacheState, revalidateSeconds, expireSeconds) });
34
+ const { cacheControl } = decideIsr({
35
+ cacheState: options.cacheState,
36
+ kind: "app-route",
37
+ revalidateSeconds: options.revalidateSeconds,
38
+ expireSeconds: options.expireSeconds,
39
+ cacheControlMeta: options.cacheControl
40
+ });
41
+ applyCdnResponseHeaders(headers, { cacheControl });
41
42
  return new Response(options.isHead ? null : cachedValue.body, {
42
43
  status: cachedValue.status,
43
44
  headers
@@ -45,7 +46,7 @@ function buildRouteHandlerCachedResponse(cachedValue, options) {
45
46
  }
46
47
  function applyRouteHandlerRevalidateHeader(response, revalidateSeconds, expireSeconds, tags) {
47
48
  applyCdnResponseHeaders(response.headers, {
48
- cacheControl: buildRouteHandlerCacheControl("HIT", revalidateSeconds, expireSeconds),
49
+ cacheControl: buildAppRouteMissIsrCacheControl(revalidateSeconds, expireSeconds),
49
50
  tags
50
51
  });
51
52
  }