vinext 0.1.4 → 0.1.6

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 (176) hide show
  1. package/README.md +2 -2
  2. package/dist/build/css-url-assets.d.ts +1 -1
  3. package/dist/build/css-url-assets.js +9 -7
  4. package/dist/build/google-fonts/find-font-files-in-css.d.ts +16 -0
  5. package/dist/build/google-fonts/find-font-files-in-css.js +28 -0
  6. package/dist/build/prerender.js +2 -1
  7. package/dist/build/report.d.ts +1 -2
  8. package/dist/build/report.js +2 -11
  9. package/dist/build/run-prerender.js +1 -1
  10. package/dist/cache/cache-adapters-virtual.js +1 -1
  11. package/dist/check.js +3 -3
  12. package/dist/client/pages-router-link-navigation.d.ts +10 -0
  13. package/dist/client/pages-router-link-navigation.js +3 -3
  14. package/dist/cloudflare/src/cache/kv-data-adapter.runtime.d.ts +1 -1
  15. package/dist/deploy.js +3 -3
  16. package/dist/entries/app-rsc-entry.js +25 -20
  17. package/dist/entries/app-rsc-manifest.js +76 -46
  18. package/dist/entries/pages-server-entry.js +3 -1
  19. package/dist/index.js +254 -198
  20. package/dist/init.d.ts +5 -4
  21. package/dist/init.js +27 -8
  22. package/dist/plugins/css-data-url.js +30 -26
  23. package/dist/plugins/extensionless-dynamic-import.js +27 -24
  24. package/dist/plugins/fonts.js +3 -1
  25. package/dist/plugins/import-meta-url.js +21 -15
  26. package/dist/plugins/instrumentation-client.js +1 -1
  27. package/dist/plugins/middleware-export-validation.d.ts +5 -0
  28. package/dist/plugins/middleware-export-validation.js +36 -0
  29. package/dist/plugins/middleware-server-only.js +7 -6
  30. package/dist/plugins/og-asset-ownership.d.ts +27 -0
  31. package/dist/plugins/og-asset-ownership.js +285 -0
  32. package/dist/plugins/og-assets.js +66 -46
  33. package/dist/plugins/optimize-imports.js +9 -3
  34. package/dist/plugins/remove-console.d.ts +7 -1
  35. package/dist/plugins/remove-console.js +4 -1
  36. package/dist/plugins/require-context.js +21 -20
  37. package/dist/plugins/strip-server-exports.d.ts +7 -1
  38. package/dist/plugins/strip-server-exports.js +4 -1
  39. package/dist/server/accept-encoding.d.ts +29 -0
  40. package/dist/server/accept-encoding.js +95 -0
  41. package/dist/server/app-bfcache-identity.d.ts +26 -0
  42. package/dist/server/app-bfcache-identity.js +127 -0
  43. package/dist/server/app-browser-entry.js +17 -11
  44. package/dist/server/app-browser-rsc-redirect.d.ts +2 -1
  45. package/dist/server/app-browser-rsc-redirect.js +8 -1
  46. package/dist/server/app-browser-state.d.ts +2 -21
  47. package/dist/server/app-browser-state.js +4 -128
  48. package/dist/server/app-browser-stream.js +1 -1
  49. package/dist/server/app-browser-visible-commit.js +3 -2
  50. package/dist/server/app-fallback-renderer.d.ts +1 -1
  51. package/dist/server/app-layout-param-observation.d.ts +1 -1
  52. package/dist/server/app-layout-param-observation.js +1 -1
  53. package/dist/server/app-middleware.d.ts +1 -0
  54. package/dist/server/app-middleware.js +3 -1
  55. package/dist/server/app-page-boundary-render.d.ts +1 -1
  56. package/dist/server/app-page-boundary.js +1 -1
  57. package/dist/server/app-page-cache-finalizer.d.ts +62 -0
  58. package/dist/server/app-page-cache-finalizer.js +122 -0
  59. package/dist/server/app-page-cache-render.d.ts +2 -2
  60. package/dist/server/app-page-cache-render.js +1 -1
  61. package/dist/server/app-page-cache.d.ts +2 -53
  62. package/dist/server/app-page-cache.js +5 -131
  63. package/dist/server/app-page-dispatch.d.ts +4 -4
  64. package/dist/server/app-page-dispatch.js +10 -8
  65. package/dist/server/app-page-head.js +2 -2
  66. package/dist/server/app-page-probe.js +3 -2
  67. package/dist/server/app-page-render-observation.js +2 -2
  68. package/dist/server/app-page-render.d.ts +3 -3
  69. package/dist/server/app-page-render.js +3 -2
  70. package/dist/server/app-page-request.d.ts +7 -0
  71. package/dist/server/app-page-request.js +19 -1
  72. package/dist/server/app-page-stream.d.ts +2 -9
  73. package/dist/server/app-page-stream.js +1 -35
  74. package/dist/server/app-prerender-endpoints.d.ts +3 -3
  75. package/dist/server/app-prerender-endpoints.js +3 -4
  76. package/dist/server/app-request-context.d.ts +1 -2
  77. package/dist/server/app-request-context.js +2 -1
  78. package/dist/server/app-route-handler-dispatch.js +3 -2
  79. package/dist/server/app-route-handler-execution.d.ts +1 -1
  80. package/dist/server/app-route-handler-execution.js +1 -1
  81. package/dist/server/app-route-handler-response.d.ts +1 -1
  82. package/dist/server/app-route-module-loader.d.ts +62 -14
  83. package/dist/server/app-route-module-loader.js +61 -10
  84. package/dist/server/app-router-entry.js +2 -1
  85. package/dist/server/app-rsc-handler.d.ts +7 -6
  86. package/dist/server/app-rsc-handler.js +51 -40
  87. package/dist/server/app-rsc-response-finalizer.js +1 -1
  88. package/dist/server/app-rsc-route-matching.d.ts +9 -0
  89. package/dist/server/app-rsc-route-matching.js +13 -0
  90. package/dist/server/app-server-action-execution.d.ts +1 -1
  91. package/dist/server/app-server-action-execution.js +5 -4
  92. package/dist/server/app-ssr-entry.d.ts +1 -1
  93. package/dist/server/app-ssr-entry.js +9 -7
  94. package/dist/server/app-ssr-router-instance.d.ts +6 -0
  95. package/dist/server/app-ssr-router-instance.js +24 -0
  96. package/dist/server/app-ssr-stream.js +1 -1
  97. package/dist/server/artifact-compatibility.js +1 -1
  98. package/dist/server/client-reuse-manifest.js +1 -1
  99. package/dist/server/defer-until-stream-consumed.d.ts +7 -0
  100. package/dist/server/defer-until-stream-consumed.js +34 -0
  101. package/dist/server/dev-server.js +1 -1
  102. package/dist/server/headers.d.ts +5 -1
  103. package/dist/server/headers.js +5 -1
  104. package/dist/server/instrumentation.js +1 -1
  105. package/dist/server/isr-cache.d.ts +1 -1
  106. package/dist/server/isr-cache.js +1 -1
  107. package/dist/server/isr-decision.d.ts +1 -1
  108. package/dist/server/metadata-route-response.d.ts +3 -3
  109. package/dist/server/middleware-matcher.js +8 -6
  110. package/dist/server/middleware-runtime.d.ts +2 -1
  111. package/dist/server/middleware-runtime.js +21 -10
  112. package/dist/server/middleware.d.ts +2 -2
  113. package/dist/server/middleware.js +26 -11
  114. package/dist/server/open-redirect.d.ts +12 -0
  115. package/dist/server/open-redirect.js +21 -0
  116. package/dist/server/pages-page-data.d.ts +1 -1
  117. package/dist/server/pages-page-response.d.ts +1 -1
  118. package/dist/server/pages-page-response.js +2 -2
  119. package/dist/server/pages-request-pipeline.d.ts +3 -1
  120. package/dist/server/pages-request-pipeline.js +4 -2
  121. package/dist/server/prod-server.d.ts +1 -1
  122. package/dist/server/prod-server.js +87 -73
  123. package/dist/server/request-pipeline.d.ts +1 -24
  124. package/dist/server/request-pipeline.js +1 -33
  125. package/dist/server/seed-cache.d.ts +1 -1
  126. package/dist/shims/cache-handler.d.ts +106 -0
  127. package/dist/shims/cache-handler.js +176 -0
  128. package/dist/shims/cache-request-state.d.ts +47 -0
  129. package/dist/shims/cache-request-state.js +126 -0
  130. package/dist/shims/cache-runtime.d.ts +2 -2
  131. package/dist/shims/cache-runtime.js +3 -14
  132. package/dist/shims/cache.d.ts +3 -231
  133. package/dist/shims/cache.js +17 -383
  134. package/dist/shims/cdn-cache.d.ts +1 -1
  135. package/dist/shims/cdn-cache.js +1 -1
  136. package/dist/shims/error-boundary-navigation.d.ts +7 -0
  137. package/dist/shims/error-boundary-navigation.js +44 -0
  138. package/dist/shims/error-boundary.js +10 -8
  139. package/dist/shims/error.js +2 -1
  140. package/dist/shims/fetch-cache.js +1 -1
  141. package/dist/shims/font-google-base.d.ts +1 -0
  142. package/dist/shims/font-google-base.js +6 -21
  143. package/dist/shims/form.js +1 -1
  144. package/dist/shims/image.js +67 -9
  145. package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -0
  146. package/dist/shims/internal/app-page-props-cache-key.js +16 -0
  147. package/dist/shims/internal/interpolate-as.d.ts +25 -0
  148. package/dist/shims/internal/interpolate-as.js +196 -0
  149. package/dist/shims/internal/navigation-untracked.js +2 -1
  150. package/dist/shims/layout-segment-context.d.ts +1 -1
  151. package/dist/shims/layout-segment-context.js +2 -1
  152. package/dist/shims/link.js +26 -3
  153. package/dist/shims/navigation-context-state.d.ts +40 -0
  154. package/dist/shims/navigation-context-state.js +116 -0
  155. package/dist/shims/navigation-errors.d.ts +55 -0
  156. package/dist/shims/navigation-errors.js +110 -0
  157. package/dist/shims/navigation-server.d.ts +3 -0
  158. package/dist/shims/navigation-server.js +3 -0
  159. package/dist/shims/navigation-state.d.ts +1 -2
  160. package/dist/shims/navigation-state.js +2 -1
  161. package/dist/shims/navigation.d.ts +3 -291
  162. package/dist/shims/navigation.js +13 -444
  163. package/dist/shims/navigation.react-server.d.ts +2 -2
  164. package/dist/shims/navigation.react-server.js +4 -2
  165. package/dist/shims/request-state-types.d.ts +3 -3
  166. package/dist/shims/router.d.ts +1 -3
  167. package/dist/shims/router.js +62 -18
  168. package/dist/shims/script.js +1 -1
  169. package/dist/shims/slot.js +3 -1
  170. package/dist/shims/unified-request-context.d.ts +2 -2
  171. package/dist/typegen.js +2 -10
  172. package/dist/utils/project.d.ts +7 -1
  173. package/dist/utils/project.js +16 -2
  174. package/dist/utils/virtual-module.d.ts +5 -0
  175. package/dist/utils/virtual-module.js +0 -0
  176. package/package.json +7 -3
@@ -31,6 +31,7 @@ type AppRscInterceptForMatching = {
31
31
  sourceMatchPattern?: string;
32
32
  sourcePageSegments?: readonly string[];
33
33
  interceptLayouts: readonly unknown[];
34
+ __loadInterceptLayouts?: readonly (() => Promise<unknown>)[] | null;
34
35
  page: unknown;
35
36
  __pageLoader?: (() => Promise<unknown>) | null;
36
37
  params: readonly string[];
@@ -45,6 +46,7 @@ type AppRscSiblingInterceptForMatching = {
45
46
  sourcePageSegments?: readonly string[];
46
47
  slotId: string | null;
47
48
  interceptLayouts: readonly unknown[];
49
+ __loadInterceptLayouts?: readonly (() => Promise<unknown>)[] | null;
48
50
  page: unknown;
49
51
  __pageLoader?: (() => Promise<unknown>) | null;
50
52
  params: readonly string[];
@@ -58,6 +60,11 @@ type AppRscRouteForMatching = {
58
60
  type AppRscInterceptMatch = AppRscInterceptLookupEntry & {
59
61
  matchedParams: AppRscRouteParams;
60
62
  };
63
+ type AppRscInterceptLoadState = {
64
+ page: unknown;
65
+ pageLoading: Promise<unknown> | null;
66
+ interceptLayoutsLoading: Promise<readonly unknown[]> | null;
67
+ };
61
68
  type AppRscInterceptLookupEntry = {
62
69
  sourceRouteIndex: number;
63
70
  slotKey: string;
@@ -67,8 +74,10 @@ type AppRscInterceptLookupEntry = {
67
74
  sourceMatchPatternParts: string[] | null;
68
75
  sourcePageSegments: readonly string[] | null;
69
76
  interceptLayouts: readonly unknown[];
77
+ __loadInterceptLayouts?: readonly (() => Promise<unknown>)[] | null;
70
78
  page: unknown;
71
79
  __pageLoader?: (() => Promise<unknown>) | null;
80
+ __loadState: AppRscInterceptLoadState;
72
81
  params: readonly string[];
73
82
  slotId: string | null;
74
83
  };
@@ -39,6 +39,7 @@ function createAppRscRouteMatcher(routes) {
39
39
  const sourceParams = matchedSourceParams ?? createRouteParams();
40
40
  return {
41
41
  ...entry,
42
+ page: entry.__loadState.page,
42
43
  sourceRouteIndex: concreteSourceRouteIndex,
43
44
  matchedParams: mergeMatchedParams(sourceParams, params)
44
45
  };
@@ -84,8 +85,14 @@ function createInterceptLookup(routes) {
84
85
  sourceMatchPatternParts,
85
86
  sourcePageSegments: intercept.sourcePageSegments ?? null,
86
87
  interceptLayouts: intercept.interceptLayouts,
88
+ __loadInterceptLayouts: intercept.__loadInterceptLayouts,
87
89
  page: intercept.page,
88
90
  __pageLoader: intercept.__pageLoader,
91
+ __loadState: {
92
+ page: intercept.page,
93
+ pageLoading: null,
94
+ interceptLayoutsLoading: null
95
+ },
89
96
  params: intercept.params
90
97
  });
91
98
  }
@@ -103,8 +110,14 @@ function createInterceptLookup(routes) {
103
110
  sourceMatchPatternParts,
104
111
  sourcePageSegments: intercept.sourcePageSegments ?? null,
105
112
  interceptLayouts: intercept.interceptLayouts,
113
+ __loadInterceptLayouts: intercept.__loadInterceptLayouts,
106
114
  page: intercept.page,
107
115
  __pageLoader: intercept.__pageLoader,
116
+ __loadState: {
117
+ page: intercept.page,
118
+ pageLoading: null,
119
+ interceptLayoutsLoading: null
120
+ },
108
121
  params: intercept.params
109
122
  });
110
123
  }
@@ -1,4 +1,4 @@
1
- import { ActionRevalidationKind } from "../shims/cache.js";
1
+ import { ActionRevalidationKind } from "../shims/cache-request-state.js";
2
2
  import { AppRscRenderMode } from "./app-rsc-render-mode.js";
3
3
  import { FetchCacheMode } from "../shims/fetch-cache.js";
4
4
  import { HeadersAccessPhase } from "../shims/headers.js";
@@ -4,17 +4,18 @@ import { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS
4
4
  import { isExternalUrl } from "../config/config-matchers.js";
5
5
  import { internalServerErrorResponse, payloadTooLargeResponse } from "./http-error-responses.js";
6
6
  import { validateCsrfOrigin, validateServerActionPayload } from "./request-pipeline.js";
7
- import { headersContextFromRequest, setHeadersContext } from "../shims/headers.js";
8
- import { getAndClearActionRevalidationKind } from "../shims/cache.js";
9
7
  import { APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI } from "./app-rsc-render-mode.js";
8
+ import { headersContextFromRequest, setHeadersContext } from "../shims/headers.js";
9
+ import { getAndClearActionRevalidationKind } from "../shims/cache-request-state.js";
10
10
  import { setCurrentFetchCacheMode, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault } from "../shims/fetch-cache.js";
11
- import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
12
11
  import { readStreamAsTextWithLimit } from "../utils/text-stream.js";
12
+ import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
13
13
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
14
14
  import { applyEdgeRuntimeHeader } from "./app-page-response.js";
15
15
  import { getNextErrorDigest, parseNextHttpErrorDigest, parseNextRedirectDigest } from "./next-error-digest.js";
16
16
  import { createServerActionNotFoundResponse, getServerActionNotFoundMessage, isServerActionNotFoundError } from "./server-action-not-found.js";
17
- import { deferUntilStreamConsumed } from "./app-page-stream.js";
17
+ import { deferUntilStreamConsumed } from "./defer-until-stream-consumed.js";
18
+ import "./app-page-stream.js";
18
19
  import { buildAppPageTags } from "./implicit-tags.js";
19
20
  import { resolveAppPageNavigationParams } from "./app-page-element-builder.js";
20
21
  import { resolveAppPageActionRerenderTarget } from "./app-page-request.js";
@@ -1,4 +1,4 @@
1
- import { NavigationContext } from "../shims/navigation.js";
1
+ import { NavigationContext } from "../shims/navigation-context-state.js";
2
2
  import { RootParams } from "../shims/root-params.js";
3
3
  import { AppSsrRenderResult } from "./app-page-stream.js";
4
4
  import { ReactFormState } from "react-dom/client";
@@ -1,12 +1,13 @@
1
1
  import "./server-globals.js";
2
2
  import { notFoundResponse } from "./http-error-responses.js";
3
- import { isOpenRedirectShaped } from "./request-pipeline.js";
4
- import { isPprFallbackShellAbortError } from "../shims/ppr-fallback-shell.js";
3
+ import { isOpenRedirectShaped } from "./open-redirect.js";
5
4
  import { AppElementsWire } from "./app-elements-wire.js";
6
5
  import "./app-elements.js";
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, appRouterInstance, clearServerInsertedHTML, getBfcacheIdMapContext, renderServerInsertedHTML, setNavigationContext, useServerInsertedHTML } from "../shims/navigation.js";
9
+ import { ServerInsertedHTMLContext, clearServerInsertedHTML, getBfcacheIdMapContext, registerServerInsertedHTMLCallback, renderServerInsertedHTML, setNavigationContext } from "../shims/navigation-context-state.js";
10
+ import "../shims/navigation-server.js";
10
11
  import { runWithNavigationContext } from "../shims/navigation-state.js";
11
12
  import { withScriptNonce } from "../shims/script-nonce-context.js";
12
13
  import { createInlineScriptTag, createNonceAttribute, escapeHtmlAttr, safeJsonStringify } from "./html.js";
@@ -17,12 +18,13 @@ import { createSsrErrorMetaRenderer } from "./app-ssr-error-meta.js";
17
18
  import { createNavigationRuntimeRscMetadataScript, createRscEmbedTransform, createTickBufferedTransform } from "./app-ssr-stream.js";
18
19
  import { BeforeInteractiveContext } from "../shims/before-interactive-context.js";
19
20
  import { runWithRootParamsScope } from "../shims/root-params.js";
20
- import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap } from "./app-browser-state.js";
21
+ import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap } from "./app-bfcache-identity.js";
21
22
  import { RSC_FORM_STATE_GLOBAL } from "./app-browser-hydration.js";
22
23
  import { createClientReferencePreloader } from "./app-client-reference-preloader.js";
23
- import { deferUntilStreamConsumed } from "./app-page-stream.js";
24
+ import { deferUntilStreamConsumed } from "./defer-until-stream-consumed.js";
24
25
  import { renderBeforeInteractiveInlineScripts } from "./before-interactive-head.js";
25
26
  import { createInitialDevServerErrorScript } from "./dev-initial-server-error.js";
27
+ import { ssrAppRouterInstance } from "./app-ssr-router-instance.js";
26
28
  import { Fragment, createElement, use } from "react";
27
29
  import { renderToReadableStream, renderToStaticMarkup } from "react-dom/server.edge";
28
30
  import { createFromReadableStream } from "@vitejs/plugin-rsc/ssr";
@@ -192,8 +194,8 @@ async function handleSsr(rscStream, navContext, fontData, options) {
192
194
  return BfcacheIdMapContext ? createElement(BfcacheIdMapContext.Provider, { value: createInitialBfcacheIdMap(elements) }, stateKeyTree) : stateKeyTree;
193
195
  }
194
196
  const flightRootElement = createElement(VinextFlightRoot);
195
- const root = AppRouterContext ? createElement(AppRouterContext.Provider, { value: appRouterInstance }, flightRootElement) : flightRootElement;
196
- const ssrTree = ServerInsertedHTMLContext ? createElement(ServerInsertedHTMLContext.Provider, { value: useServerInsertedHTML }, root) : root;
197
+ const root = AppRouterContext ? createElement(AppRouterContext.Provider, { value: ssrAppRouterInstance }, flightRootElement) : flightRootElement;
198
+ const ssrTree = ServerInsertedHTMLContext ? createElement(ServerInsertedHTMLContext.Provider, { value: registerServerInsertedHTMLCallback }, root) : root;
197
199
  const beforeInteractiveInlineScripts = [];
198
200
  const registerBeforeInteractiveInlineScript = (script) => {
199
201
  beforeInteractiveInlineScripts.push(script);
@@ -0,0 +1,6 @@
1
+ import { AppRouterInstance } from "../shims/internal/app-router-context.js";
2
+
3
+ //#region src/server/app-ssr-router-instance.d.ts
4
+ declare const ssrAppRouterInstance: AppRouterInstance;
5
+ //#endregion
6
+ export { ssrAppRouterInstance };
@@ -0,0 +1,24 @@
1
+ import { assertSafeNavigationUrl } from "../shims/url-safety.js";
2
+ import "./app-bfcache-id.js";
3
+ //#region src/server/app-ssr-router-instance.ts
4
+ function validateNavigationHref(href) {
5
+ assertSafeNavigationUrl(href);
6
+ }
7
+ const ssrAppRouterInstance = {
8
+ bfcacheId: "0",
9
+ back() {},
10
+ forward() {},
11
+ refresh() {},
12
+ push(href, _options) {
13
+ validateNavigationHref(href);
14
+ },
15
+ replace(href, _options) {
16
+ validateNavigationHref(href);
17
+ },
18
+ prefetch(href) {
19
+ validateNavigationHref(href);
20
+ }
21
+ };
22
+ if (process.env.__NEXT_GESTURE_TRANSITION) ssrAppRouterInstance.experimental_gesturePush = validateNavigationHref;
23
+ //#endregion
24
+ export { ssrAppRouterInstance };
@@ -1,6 +1,6 @@
1
- import { NAVIGATION_RUNTIME_SYMBOL_DESCRIPTION } from "../client/navigation-runtime.js";
2
1
  import { createInlineScriptTag, escapeHtmlAttr, htmlTokenListContains, safeJsonStringify } from "./html.js";
3
2
  import { bytesToBase64, concatUint8Arrays } from "./app-rsc-embedded-chunks.js";
3
+ import { NAVIGATION_RUNTIME_SYMBOL_DESCRIPTION } from "../client/navigation-runtime.js";
4
4
  //#region src/server/app-ssr-stream.ts
5
5
  const NAVIGATION_RUNTIME_REFERENCE = `self[Symbol.for(${safeJsonStringify(NAVIGATION_RUNTIME_SYMBOL_DESCRIPTION)})]`;
6
6
  function navigationRuntimeRscBootstrapExpression() {
@@ -1,5 +1,5 @@
1
- import { fnv1a64 } from "../utils/hash.js";
2
1
  import { isUnknownRecord } from "../utils/record.js";
2
+ import { fnv1a64 } from "../utils/hash.js";
3
3
  //#region src/server/artifact-compatibility.ts
4
4
  const ARTIFACT_COMPATIBILITY_SCHEMA_VERSION = 1;
5
5
  const APP_ELEMENTS_SCHEMA_VERSION = 1;
@@ -1,5 +1,5 @@
1
- import { fnv1a64 } from "../utils/hash.js";
2
1
  import { isUnknownRecord } from "../utils/record.js";
2
+ import { fnv1a64 } from "../utils/hash.js";
3
3
  import { parseArtifactCompatibilityEnvelope } from "./artifact-compatibility.js";
4
4
  import { AppElementsWire } from "./app-elements-wire.js";
5
5
  import { isNonNegativeSafeInteger } from "../utils/number.js";
@@ -0,0 +1,7 @@
1
+ //#region src/server/defer-until-stream-consumed.d.ts
2
+ /**
3
+ * Defers cleanup until the downstream consumer drains or cancels the stream.
4
+ */
5
+ declare function deferUntilStreamConsumed(stream: ReadableStream<Uint8Array>, onFlush: () => void): ReadableStream<Uint8Array>;
6
+ //#endregion
7
+ export { deferUntilStreamConsumed };
@@ -0,0 +1,34 @@
1
+ //#region src/server/defer-until-stream-consumed.ts
2
+ /**
3
+ * Defers cleanup until the downstream consumer drains or cancels the stream.
4
+ */
5
+ function deferUntilStreamConsumed(stream, onFlush) {
6
+ let called = false;
7
+ const once = () => {
8
+ if (!called) {
9
+ called = true;
10
+ onFlush();
11
+ }
12
+ };
13
+ const cleanup = new TransformStream({ flush() {
14
+ once();
15
+ } });
16
+ const reader = stream.pipeThrough(cleanup).getReader();
17
+ return new ReadableStream({
18
+ pull(controller) {
19
+ return reader.read().then(({ done, value }) => {
20
+ if (done) controller.close();
21
+ else controller.enqueue(value);
22
+ }, (error) => {
23
+ once();
24
+ controller.error(error);
25
+ });
26
+ },
27
+ cancel(reason) {
28
+ once();
29
+ return reader.cancel(reason);
30
+ }
31
+ });
32
+ }
33
+ //#endregion
34
+ export { deferUntilStreamConsumed };
@@ -7,10 +7,10 @@ import { normalizeStaticPathname } from "../routing/route-pattern.js";
7
7
  import { importModule, reportRequestError } from "./instrumentation.js";
8
8
  import { buildCacheStateHeaders } from "./cache-headers.js";
9
9
  import { isUnknownRecord } from "../utils/record.js";
10
- import { _runWithCacheState } from "../shims/cache.js";
11
10
  import { NEVER_CACHE_CONTROL, NO_STORE_CACHE_CONTROL } from "./cache-control.js";
12
11
  import { buildMissIsrCacheControl, decideIsr } from "./isr-decision.js";
13
12
  import { PRERENDER_REVALIDATE_HEADER, buildPagesCacheValue, getRevalidateDuration, isOnDemandRevalidateRequest, isrCacheKey, isrGet, isrSet, setRevalidateDuration, triggerBackgroundRegeneration } from "./isr-cache.js";
13
+ import { _runWithCacheState } from "../shims/cache-request-state.js";
14
14
  import { ensureFetchPatch, runWithFetchCache } from "../shims/fetch-cache.js";
15
15
  import { runWithPrivateCache } from "../shims/cache-runtime.js";
16
16
  import { mergeRouteParamsIntoQuery, parseQueryString } from "../utils/query.js";
@@ -23,6 +23,10 @@ declare const VINEXT_TIMING_HEADER = "x-vinext-timing";
23
23
  declare const VINEXT_PRERENDER_SECRET_HEADER = "x-vinext-prerender-secret";
24
24
  /** URL-encoded JSON route params for build-time prerender renders. */
25
25
  declare const VINEXT_PRERENDER_ROUTE_PARAMS_HEADER = "x-vinext-prerender-route-params";
26
+ /** Internal endpoint used to evaluate App Router generateStaticParams exports. */
27
+ declare const VINEXT_PRERENDER_STATIC_PARAMS_PATH = "/__vinext/prerender/static-params";
28
+ /** Internal endpoint used to evaluate Pages Router getStaticPaths exports. */
29
+ declare const VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH = "/__vinext/prerender/pages-static-paths";
26
30
  /** TPR (Tailored Per-Request) revalidation interval in seconds. */
27
31
  declare const VINEXT_REVALIDATE_HEADER = "x-vinext-revalidate";
28
32
  /** Marker on cached ISR entries indicating RSC payload (value "1"). */
@@ -107,4 +111,4 @@ declare const INTERNAL_HEADERS: string[];
107
111
  /** Vinext-only internal headers stripped alongside Next.js protocol internals. */
108
112
  declare const VINEXT_INTERNAL_HEADERS: string[];
109
113
  //#endregion
110
- export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_OVERRIDE_HEADERS, MIDDLEWARE_REQUEST_HEADER_PREFIX, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
114
+ export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_OVERRIDE_HEADERS, MIDDLEWARE_REQUEST_HEADER_PREFIX, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
@@ -23,6 +23,10 @@ const VINEXT_TIMING_HEADER = "x-vinext-timing";
23
23
  const VINEXT_PRERENDER_SECRET_HEADER = "x-vinext-prerender-secret";
24
24
  /** URL-encoded JSON route params for build-time prerender renders. */
25
25
  const VINEXT_PRERENDER_ROUTE_PARAMS_HEADER = "x-vinext-prerender-route-params";
26
+ /** Internal endpoint used to evaluate App Router generateStaticParams exports. */
27
+ const VINEXT_PRERENDER_STATIC_PARAMS_PATH = "/__vinext/prerender/static-params";
28
+ /** Internal endpoint used to evaluate Pages Router getStaticPaths exports. */
29
+ const VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH = "/__vinext/prerender/pages-static-paths";
26
30
  /** TPR (Tailored Per-Request) revalidation interval in seconds. */
27
31
  const VINEXT_REVALIDATE_HEADER = "x-vinext-revalidate";
28
32
  /** Marker on cached ISR entries indicating RSC payload (value "1"). */
@@ -129,4 +133,4 @@ const INTERNAL_HEADERS = [
129
133
  /** Vinext-only internal headers stripped alongside Next.js protocol internals. */
130
134
  const VINEXT_INTERNAL_HEADERS = [VINEXT_PRERENDER_ROUTE_PARAMS_HEADER];
131
135
  //#endregion
132
- export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_OVERRIDE_HEADERS, MIDDLEWARE_REQUEST_HEADER_PREFIX, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
136
+ export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_OVERRIDE_HEADERS, MIDDLEWARE_REQUEST_HEADER_PREFIX, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
@@ -51,7 +51,7 @@ async function importModule(runner, id) {
51
51
  const INSTRUMENTATION_LOCATIONS = ["", "src/"];
52
52
  function findInstrumentationHookFile(root, basename, fileMatcher) {
53
53
  for (const dir of INSTRUMENTATION_LOCATIONS) for (const ext of fileMatcher.dottedExtensions) {
54
- const fullPath = path.join(root, dir, `${basename}${ext}`);
54
+ const fullPath = path.posix.join(root, dir, `${basename}${ext}`);
55
55
  if (fs.existsSync(fullPath)) return fullPath;
56
56
  }
57
57
  return null;
@@ -1,5 +1,5 @@
1
1
  import { RenderObservation } from "./cache-proof.js";
2
- import { CacheHandlerValue, CachedAppPageValue, CachedPagesValue, IncrementalCacheValue } from "../shims/cache.js";
2
+ import { CacheHandlerValue, CachedAppPageValue, CachedPagesValue, IncrementalCacheValue } from "../shims/cache-handler.js";
3
3
  import { OnRequestErrorContext } from "./instrumentation.js";
4
4
  import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
5
5
  import { AppRscRenderMode } from "./app-rsc-render-mode.js";
@@ -1,7 +1,7 @@
1
1
  import { getRequestExecutionContext } from "../shims/request-context.js";
2
2
  import { reportRequestError } from "./instrumentation.js";
3
- import { fnv1a64 } from "../utils/hash.js";
4
3
  import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
4
+ import { fnv1a64 } from "../utils/hash.js";
5
5
  import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
6
6
  import { APP_RSC_RENDER_MODE_NAVIGATION, getRscRenderModeCacheVariant } from "./app-rsc-render-mode.js";
7
7
  import { normalizeAppPageInterceptionProofPathname } from "./app-page-render-identity.js";
@@ -1,4 +1,4 @@
1
- import { CacheControlMetadata } from "../shims/cache.js";
1
+ import { CacheControlMetadata } from "../shims/cache-handler.js";
2
2
  import { NEVER_CACHE_CONTROL, NO_STORE_CACHE_CONTROL } from "./cache-control.js";
3
3
 
4
4
  //#region src/server/isr-decision.d.ts
@@ -2,15 +2,15 @@ import { MetadataFileRoute } from "./metadata-routes.js";
2
2
 
3
3
  //#region src/server/metadata-route-response.d.ts
4
4
  type AppPageParams = Record<string, string | string[]>;
5
- type MakeThenableParams = (params: AppPageParams) => unknown;
5
+ type MetadataRouteMakeThenableParams = (params: AppPageParams) => unknown;
6
6
  type MetadataRuntimeRoute = MetadataFileRoute & {
7
7
  fileDataBase64?: string;
8
8
  };
9
9
  type MetadataRouteRequestOptions = {
10
10
  metadataRoutes: readonly MetadataRuntimeRoute[];
11
11
  cleanPathname: string;
12
- makeThenableParams: MakeThenableParams;
12
+ makeThenableParams: MetadataRouteMakeThenableParams;
13
13
  };
14
14
  declare function handleMetadataRouteRequest(options: MetadataRouteRequestOptions): Promise<Response | null>;
15
15
  //#endregion
16
- export { handleMetadataRouteRequest };
16
+ export { MetadataRouteMakeThenableParams, MetadataRuntimeRoute, handleMetadataRouteRequest };
@@ -48,17 +48,19 @@ function stripLocalePrefix(pathname, i18nConfig) {
48
48
  const segments = pathname.split("/");
49
49
  const firstSegment = segments[1];
50
50
  if (!firstSegment || !i18nConfig.locales.includes(firstSegment)) return null;
51
- return removeTrailingSlash("/" + segments.slice(2).join("/"));
51
+ return "/" + segments.slice(2).join("/");
52
52
  }
53
53
  function matchPattern(pathname, pattern) {
54
- let cached = _mwPatternCache.get(pattern);
54
+ const normalizedPattern = /[\\():*+?]/.test(pattern) ? pattern : removeTrailingSlash(pattern);
55
+ let cached = _mwPatternCache.get(normalizedPattern);
55
56
  if (cached === void 0) {
56
- cached = compileMatcherPattern(pattern);
57
- _mwPatternCache.set(pattern, cached);
57
+ cached = compileMatcherPattern(normalizedPattern);
58
+ _mwPatternCache.set(normalizedPattern, cached);
58
59
  }
59
60
  if (cached === UNSAFE_MATCHER_PATTERN) return true;
60
- if (cached === null) return pathname === pattern;
61
- return cached.test(pathname);
61
+ if (cached === null) return removeTrailingSlash(pathname) === normalizedPattern;
62
+ if (cached.test(pathname)) return true;
63
+ return pathname.endsWith("/") && cached.test(removeTrailingSlash(pathname));
62
64
  }
63
65
  function extractConstraint(str, re) {
64
66
  if (str[re.lastIndex] !== "(") return null;
@@ -56,6 +56,7 @@ type ExecuteMiddlewareOptions = {
56
56
  type RunGeneratedMiddlewareOptions = ExecuteMiddlewareOptions & {
57
57
  ctx?: ExecutionContextLike;
58
58
  };
59
+ declare function createMiddlewareMissingExportError(filePath: string | undefined, isProxy: boolean): Error;
59
60
  declare function resolveMiddlewareModuleHandler(mod: MiddlewareModule, options: {
60
61
  filePath?: string;
61
62
  isProxy: boolean;
@@ -63,4 +64,4 @@ declare function resolveMiddlewareModuleHandler(mod: MiddlewareModule, options:
63
64
  declare function executeMiddleware(options: ExecuteMiddlewareOptions): Promise<MiddlewareResult>;
64
65
  declare function runGeneratedMiddleware(options: RunGeneratedMiddlewareOptions): Promise<MiddlewareResult>;
65
66
  //#endregion
66
- export { MiddlewareModule, MiddlewareResult, executeMiddleware, resolveMiddlewareModuleHandler, runGeneratedMiddleware };
67
+ export { MiddlewareModule, MiddlewareResult, createMiddlewareMissingExportError, executeMiddleware, resolveMiddlewareModuleHandler, runGeneratedMiddleware };
@@ -1,5 +1,5 @@
1
1
  import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
2
- import { addBasePathToPathname, hasBasePath, stripBasePath } from "../utils/base-path.js";
2
+ import { addBasePathToPathname, hasBasePath, removeTrailingSlash, stripBasePath } from "../utils/base-path.js";
3
3
  import "./server-globals.js";
4
4
  import { getRequestExecutionContext, runWithExecutionContext } from "../shims/request-context.js";
5
5
  import { MIDDLEWARE_REWRITE_HEADER } from "./headers.js";
@@ -9,6 +9,7 @@ import { normalizePath } from "./normalize-path.js";
9
9
  import { matchesMiddleware } from "./middleware-matcher.js";
10
10
  import { badRequestResponse, internalServerErrorResponse } from "./http-error-responses.js";
11
11
  import { processMiddlewareHeaders } from "./request-pipeline.js";
12
+ import path from "node:path";
12
13
  //#region src/server/middleware-runtime.ts
13
14
  function isMiddlewareHandler(value) {
14
15
  return typeof value === "function";
@@ -16,19 +17,29 @@ function isMiddlewareHandler(value) {
16
17
  function isMiddlewareConfigExport(value) {
17
18
  return !!value && typeof value === "object";
18
19
  }
19
- function middlewareFileLabel(isProxy) {
20
- return isProxy ? "Proxy" : "Middleware";
21
- }
22
20
  function middlewareExpectedExport(isProxy) {
23
21
  return isProxy ? "proxy" : "middleware";
24
22
  }
23
+ function middlewareDisplayPath(filePath) {
24
+ const fileName = path.basename(filePath);
25
+ return path.basename(path.dirname(filePath)) === "src" ? `./src/${fileName}` : `./${fileName}`;
26
+ }
27
+ function createMiddlewareMissingExportError(filePath, isProxy) {
28
+ const expectedExport = middlewareExpectedExport(isProxy);
29
+ const displayPath = filePath ? middlewareDisplayPath(filePath) : void 0;
30
+ const resolvedPath = displayPath ? ` "${displayPath}"` : "";
31
+ const migrationReason = isProxy ? "- You are migrating from `middleware` to `proxy`, but haven't updated the exported function.\n" : "";
32
+ return /* @__PURE__ */ new Error(`The file${resolvedPath} must export a function, either as a default export or as a named "${expectedExport}" export.\nThis function is what Next.js runs for every request handled by this ${isProxy ? "proxy (previously called middleware)" : "middleware"}.\n\nWhy this happens:\n` + migrationReason + `- The file exists but doesn't export a function.
33
+ - The export is not a function (e.g., an object or constant).
34
+ - There's a syntax error preventing the export from being recognized.
35
+
36
+ To fix it:
37
+ - Ensure this file has either a default or "${expectedExport}" function export.\n\nLearn more: https://nextjs.org/docs/messages/middleware-to-proxy`);
38
+ }
25
39
  function resolveMiddlewareModuleHandler(mod, options) {
26
40
  const handler = options.isProxy ? mod.proxy ?? mod.default : mod.middleware ?? mod.default;
27
41
  if (isMiddlewareHandler(handler)) return handler;
28
- const fileLabel = middlewareFileLabel(options.isProxy);
29
- const expectedExport = middlewareExpectedExport(options.isProxy);
30
- const fileSuffix = options.filePath ? ` "${options.filePath}"` : "";
31
- throw new Error(`The ${fileLabel} file${fileSuffix} must export a function named \`${expectedExport}\` or a \`default\` function.`);
42
+ throw createMiddlewareMissingExportError(options.filePath, options.isProxy);
32
43
  }
33
44
  function middlewareMatcher(mod) {
34
45
  const config = mod.config;
@@ -130,7 +141,7 @@ async function executeMiddleware(options) {
130
141
  const matchPathname = options.basePath ? stripBasePath(normalizedPathname, options.basePath) : normalizedPathname;
131
142
  if (!matchesMiddleware(matchPathname, middlewareMatcher(options.module), options.request, options.i18nConfig)) return { continue: true };
132
143
  const nextRequest = createNextRequest(options.request, normalizedPathname, options.i18nConfig, options.basePath, options.trailingSlash, hadBasePath);
133
- const fetchEvent = new NextFetchEvent({ page: matchPathname });
144
+ const fetchEvent = new NextFetchEvent({ page: removeTrailingSlash(matchPathname) });
134
145
  let response;
135
146
  try {
136
147
  response = await middlewareFn(nextRequest, fetchEvent);
@@ -226,4 +237,4 @@ async function runGeneratedMiddleware(options) {
226
237
  return options.ctx ? runWithExecutionContext(options.ctx, run) : run();
227
238
  }
228
239
  //#endregion
229
- export { executeMiddleware, resolveMiddlewareModuleHandler, runGeneratedMiddleware };
240
+ export { createMiddlewareMissingExportError, executeMiddleware, resolveMiddlewareModuleHandler, runGeneratedMiddleware };
@@ -28,7 +28,7 @@ declare function isProxyFile(filePath: string): boolean;
28
28
  */
29
29
  declare function resolveMiddlewareHandler(mod: MiddlewareModule, filePath: string): (request: NextRequest, event: NextFetchEvent) => Response | undefined | void | Promise<Response | undefined | void>;
30
30
  /**
31
- * Find the proxy or middleware file in the project root.
31
+ * Find the proxy or middleware file at the selected app/pages convention level.
32
32
  * Checks for proxy.ts (Next.js 16) first, then falls back to middleware.ts.
33
33
  * If middleware.ts is found, logs a deprecation warning.
34
34
  *
@@ -44,7 +44,7 @@ declare function resolveMiddlewareHandler(mod: MiddlewareModule, filePath: strin
44
44
  * @see https://github.com/vercel/next.js/blob/canary/packages/next/src/build/index.ts
45
45
  * (search for "MIDDLEWARE_FILENAME" + "file convention is deprecated")
46
46
  */
47
- declare function findMiddlewareFile(root: string, fileMatcher: ValidFileMatcher): string | null;
47
+ declare function findMiddlewareFile(root: string, fileMatcher: ValidFileMatcher, conventionDir?: string): string | null;
48
48
  /**
49
49
  * Load and execute middleware for a given request.
50
50
  *
@@ -13,7 +13,8 @@ import path from "node:path";
13
13
  * https://github.com/vercel/next.js/blob/canary/packages/next/src/build/templates/middleware.ts
14
14
  */
15
15
  function isProxyFile(filePath) {
16
- return path.basename(filePath).replace(/\.\w+$/, "") === "proxy";
16
+ const base = path.basename(filePath);
17
+ return base === "proxy" || base.startsWith("proxy.");
17
18
  }
18
19
  /**
19
20
  * Resolve the middleware/proxy handler function from a module's exports.
@@ -32,9 +33,8 @@ function resolveMiddlewareHandler(mod, filePath) {
32
33
  isProxy: isProxyFile(filePath)
33
34
  });
34
35
  }
35
- const MIDDLEWARE_LOCATIONS = ["", "src/"];
36
36
  /**
37
- * Find the proxy or middleware file in the project root.
37
+ * Find the proxy or middleware file at the selected app/pages convention level.
38
38
  * Checks for proxy.ts (Next.js 16) first, then falls back to middleware.ts.
39
39
  * If middleware.ts is found, logs a deprecation warning.
40
40
  *
@@ -50,18 +50,33 @@ const MIDDLEWARE_LOCATIONS = ["", "src/"];
50
50
  * @see https://github.com/vercel/next.js/blob/canary/packages/next/src/build/index.ts
51
51
  * (search for "MIDDLEWARE_FILENAME" + "file convention is deprecated")
52
52
  */
53
- function findMiddlewareFile(root, fileMatcher) {
54
- for (const dir of MIDDLEWARE_LOCATIONS) for (const ext of fileMatcher.dottedExtensions) {
55
- const fullPath = path.join(root, dir, `proxy${ext}`);
56
- if (fs.existsSync(fullPath)) return fullPath;
53
+ function findMiddlewareFile(root, fileMatcher, conventionDir = root) {
54
+ let proxyPath = null;
55
+ for (const ext of fileMatcher.dottedExtensions) {
56
+ const fullPath = path.join(conventionDir, `proxy${ext}`);
57
+ if (fs.existsSync(fullPath)) {
58
+ proxyPath = fullPath;
59
+ break;
60
+ }
57
61
  }
58
- for (const dir of MIDDLEWARE_LOCATIONS) for (const ext of fileMatcher.dottedExtensions) {
59
- const fullPath = path.join(root, dir, `middleware${ext}`);
62
+ let middlewarePath = null;
63
+ for (const ext of fileMatcher.dottedExtensions) {
64
+ const fullPath = path.join(conventionDir, `middleware${ext}`);
60
65
  if (fs.existsSync(fullPath)) {
61
- console.warn("The \"middleware\" file convention is deprecated. Please use \"proxy\" instead.\n\n To migrate automatically, run:\n npx @next/codemod@canary middleware-to-proxy .\n\n Learn more: https://nextjs.org/docs/messages/middleware-to-proxy");
62
- return fullPath;
66
+ middlewarePath = fullPath;
67
+ break;
63
68
  }
64
69
  }
70
+ if (proxyPath && middlewarePath) {
71
+ const relativeProxyPath = `./${path.relative(root, proxyPath)}`;
72
+ const relativeMiddlewarePath = `./${path.relative(root, middlewarePath)}`;
73
+ throw new Error(`Both middleware file "${relativeMiddlewarePath}" and proxy file "${relativeProxyPath}" are detected. Please use "${relativeProxyPath}" only. Learn more: https://nextjs.org/docs/messages/middleware-to-proxy`);
74
+ }
75
+ if (proxyPath) return proxyPath;
76
+ if (middlewarePath) {
77
+ console.warn("The \"middleware\" file convention is deprecated. Please use \"proxy\" instead.\n\n To migrate automatically, run:\n npx @next/codemod@canary middleware-to-proxy .\n\n Learn more: https://nextjs.org/docs/messages/middleware-to-proxy");
78
+ return middlewarePath;
79
+ }
65
80
  return null;
66
81
  }
67
82
  function isMiddlewareModule(value) {
@@ -0,0 +1,12 @@
1
+ //#region src/server/open-redirect.d.ts
2
+ /**
3
+ * Returns true if a request pathname looks like a protocol-relative open
4
+ * redirect, in either literal or percent-encoded form.
5
+ *
6
+ * A pathname is considered "open redirect shaped" when its first segment,
7
+ * after decoding backslashes and encoded delimiters, would cause a browser
8
+ * to resolve a `Location` containing the pathname as protocol-relative.
9
+ */
10
+ declare function isOpenRedirectShaped(rawPathname: string): boolean;
11
+ //#endregion
12
+ export { isOpenRedirectShaped };
@@ -0,0 +1,21 @@
1
+ //#region src/server/open-redirect.ts
2
+ /**
3
+ * Returns true if a request pathname looks like a protocol-relative open
4
+ * redirect, in either literal or percent-encoded form.
5
+ *
6
+ * A pathname is considered "open redirect shaped" when its first segment,
7
+ * after decoding backslashes and encoded delimiters, would cause a browser
8
+ * to resolve a `Location` containing the pathname as protocol-relative.
9
+ */
10
+ function isOpenRedirectShaped(rawPathname) {
11
+ if (!rawPathname.startsWith("/")) return false;
12
+ const afterSlash = rawPathname.slice(1);
13
+ if (afterSlash.startsWith("/") || afterSlash.startsWith("\\")) return true;
14
+ if (afterSlash.length >= 3 && afterSlash[0] === "%") {
15
+ const encoded = afterSlash.slice(0, 3).toLowerCase();
16
+ if (encoded === "%5c" || encoded === "%2f") return true;
17
+ }
18
+ return false;
19
+ }
20
+ //#endregion
21
+ export { isOpenRedirectShaped };
@@ -1,6 +1,6 @@
1
1
  import { Route } from "../routing/pages-router.js";
2
2
  import { VinextNextData } from "../client/vinext-next-data.js";
3
- import { CachedPagesValue } from "../shims/cache.js";
3
+ import { CachedPagesValue } from "../shims/cache-handler.js";
4
4
  import { ISRCacheEntry } from "./isr-cache.js";
5
5
  import { PagesGsspResponse, PagesI18nRenderContext, PagesNextDataExtras } from "./pages-page-response.js";
6
6
  import { ReactNode } from "react";
@@ -1,5 +1,5 @@
1
1
  import { VinextNextData } from "../client/vinext-next-data.js";
2
- import { CachedPagesValue } from "../shims/cache.js";
2
+ import { CachedPagesValue } from "../shims/cache-handler.js";
3
3
  import { RenderPageEnhancers } from "./pages-document-initial-props.js";
4
4
  import { ComponentType, ReactNode } from "react";
5
5