vinext 1.0.0-beta.0 → 1.0.0-beta.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 (305) hide show
  1. package/README.md +21 -2
  2. package/dist/build/assets-ignore.js +1 -1
  3. package/dist/build/clean-output.js +1 -1
  4. package/dist/build/client-build-config.js +7 -4
  5. package/dist/build/css-url-assets.js +3 -3
  6. package/dist/build/google-fonts/fallback-metrics.js +1 -1
  7. package/dist/build/google-fonts/font-metadata.js +1 -1
  8. package/dist/build/inject-pregenerated-paths.js +1 -1
  9. package/dist/build/inline-css.js +2 -5
  10. package/dist/build/module-dependency-cache.d.ts +4 -0
  11. package/dist/build/module-dependency-cache.js +13 -0
  12. package/dist/build/next-client-runtime-manifests.js +1 -1
  13. package/dist/build/pages-client-assets-module.js +1 -1
  14. package/dist/build/precompress.js +7 -7
  15. package/dist/build/prerender-paths.d.ts +2 -2
  16. package/dist/build/prerender-paths.js +10 -15
  17. package/dist/build/prerender-server-pool.js +2 -2
  18. package/dist/build/prerender.js +1 -1
  19. package/dist/build/preview-credentials.d.ts +11 -0
  20. package/dist/build/preview-credentials.js +19 -0
  21. package/dist/build/report.d.ts +8 -4
  22. package/dist/build/report.js +14 -6
  23. package/dist/build/run-prerender.d.ts +2 -11
  24. package/dist/build/run-prerender.js +2 -10
  25. package/dist/build/server-manifest.js +1 -1
  26. package/dist/build/ssr-manifest.d.ts +4 -0
  27. package/dist/build/ssr-manifest.js +10 -6
  28. package/dist/build/standalone.js +37 -37
  29. package/dist/cache/cache-adapters-virtual.d.ts +1 -17
  30. package/dist/cache/cache-adapters-virtual.js +20 -11
  31. package/dist/check.d.ts +0 -16
  32. package/dist/check.js +27 -36
  33. package/dist/cli.js +61 -55
  34. package/dist/client/instrumentation-client-inject.js +1 -1
  35. package/dist/client/pages-router-link-navigation.js +1 -1
  36. package/dist/config/config-matchers.d.ts +13 -37
  37. package/dist/config/config-matchers.js +33 -123
  38. package/dist/config/dotenv.js +1 -1
  39. package/dist/config/next-config.d.ts +7 -3
  40. package/dist/config/next-config.js +84 -15
  41. package/dist/config/prerender.d.ts +2 -2
  42. package/dist/config/prerender.js +7 -15
  43. package/dist/config/request-context.d.ts +14 -0
  44. package/dist/config/request-context.js +26 -0
  45. package/dist/config/server-external-packages.js +1 -1
  46. package/dist/config/tsconfig-paths.js +2 -2
  47. package/dist/{node_modules/.pnpm/am-i-vibing@0.5.0/node_modules → deps/.pnpm/am-i-vibing@0.5.0/deps}/am-i-vibing/dist/detector-1yx2Hoe0.js +2 -2
  48. package/dist/deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js +50 -0
  49. package/dist/entries/app-rsc-entry.js +39 -14
  50. package/dist/entries/app-rsc-manifest.js +21 -4
  51. package/dist/entries/pages-client-entry.js +6 -5
  52. package/dist/entries/pages-server-entry.js +18 -28
  53. package/dist/entries/runtime-entry-module.js +2 -2
  54. package/dist/index.js +314 -230
  55. package/dist/init-cloudflare.js +1 -1
  56. package/dist/init-platform.js +1 -1
  57. package/dist/init.d.ts +6 -4
  58. package/dist/init.js +25 -27
  59. package/dist/plugins/ast-utils.js +1 -1
  60. package/dist/plugins/dynamic-preload-metadata.js +7 -7
  61. package/dist/plugins/extensionless-dynamic-import.js +1 -1
  62. package/dist/plugins/fonts.js +3 -3
  63. package/dist/plugins/ignore-dynamic-requests.js +13 -8
  64. package/dist/plugins/import-meta-url.js +16 -17
  65. package/dist/plugins/middleware-export-validation.js +1 -1
  66. package/dist/plugins/middleware-server-only.js +2 -2
  67. package/dist/plugins/og-asset-ownership.js +7 -6
  68. package/dist/plugins/og-assets.js +5 -6
  69. package/dist/plugins/optimize-imports.js +12 -13
  70. package/dist/plugins/postcss.js +1 -1
  71. package/dist/plugins/remove-console.js +1 -1
  72. package/dist/plugins/require-context.js +1 -1
  73. package/dist/plugins/sass.js +2 -2
  74. package/dist/plugins/server-externals-manifest.js +1 -1
  75. package/dist/plugins/strip-server-exports.js +1 -1
  76. package/dist/plugins/styled-jsx.js +3 -2
  77. package/dist/plugins/typeof-window.js +1 -1
  78. package/dist/routing/app-route-graph.d.ts +16 -15
  79. package/dist/routing/app-route-graph.js +86 -88
  80. package/dist/routing/app-router.d.ts +0 -5
  81. package/dist/routing/app-router.js +12 -11
  82. package/dist/routing/file-matcher.d.ts +13 -28
  83. package/dist/routing/file-matcher.js +31 -44
  84. package/dist/routing/pages-router.js +26 -32
  85. package/dist/routing/route-matching.d.ts +14 -1
  86. package/dist/routing/route-matching.js +13 -1
  87. package/dist/routing/route-pattern.d.ts +2 -1
  88. package/dist/routing/route-pattern.js +7 -4
  89. package/dist/routing/route-trie.d.ts +5 -1
  90. package/dist/routing/route-trie.js +5 -2
  91. package/dist/server/api-handler.js +41 -33
  92. package/dist/server/app-browser-entry.js +18 -11
  93. package/dist/server/app-browser-history-controller.d.ts +1 -1
  94. package/dist/server/app-browser-history-controller.js +3 -3
  95. package/dist/server/app-browser-navigation-controller.js +4 -2
  96. package/dist/server/app-browser-server-action-client.js +1 -1
  97. package/dist/server/app-elements-wire.d.ts +2 -1
  98. package/dist/server/app-fallback-renderer.d.ts +11 -0
  99. package/dist/server/app-fallback-renderer.js +16 -2
  100. package/dist/server/app-middleware.js +2 -1
  101. package/dist/server/app-page-boundary-render.d.ts +26 -2
  102. package/dist/server/app-page-boundary-render.js +190 -55
  103. package/dist/server/app-page-cache-finalizer.d.ts +1 -1
  104. package/dist/server/app-page-cache.d.ts +1 -1
  105. package/dist/server/app-page-dispatch.d.ts +12 -2
  106. package/dist/server/app-page-dispatch.js +37 -51
  107. package/dist/server/app-page-element-builder.d.ts +8 -2
  108. package/dist/server/app-page-element-builder.js +112 -27
  109. package/dist/server/app-page-execution.d.ts +3 -1
  110. package/dist/server/app-page-execution.js +31 -39
  111. package/dist/server/app-page-head.d.ts +54 -2
  112. package/dist/server/app-page-head.js +164 -78
  113. package/dist/server/app-page-http-access-fallback-metadata.d.ts +29 -0
  114. package/dist/server/app-page-http-access-fallback-metadata.js +106 -0
  115. package/dist/server/app-page-render.d.ts +2 -2
  116. package/dist/server/app-page-render.js +1 -1
  117. package/dist/server/app-page-request.d.ts +12 -0
  118. package/dist/server/app-page-request.js +134 -14
  119. package/dist/server/app-page-route-wiring.d.ts +9 -0
  120. package/dist/server/app-page-route-wiring.js +44 -4
  121. package/dist/server/app-post-middleware-context.d.ts +1 -1
  122. package/dist/server/app-post-middleware-context.js +1 -1
  123. package/dist/server/app-route-handler-dispatch.js +31 -17
  124. package/dist/server/app-route-handler-execution.d.ts +6 -1
  125. package/dist/server/app-route-handler-execution.js +41 -15
  126. package/dist/server/app-route-handler-policy.d.ts +2 -0
  127. package/dist/server/app-route-handler-policy.js +3 -3
  128. package/dist/server/app-route-module-loader.d.ts +3 -1
  129. package/dist/server/app-route-module-loader.js +1 -0
  130. package/dist/server/app-route-tree-prefetch.js +1 -1
  131. package/dist/server/app-rsc-cache-busting.d.ts +1 -1
  132. package/dist/server/app-rsc-cache-busting.js +1 -1
  133. package/dist/server/app-rsc-errors.d.ts +1 -1
  134. package/dist/server/app-rsc-errors.js +12 -2
  135. package/dist/server/app-rsc-handler.d.ts +10 -5
  136. package/dist/server/app-rsc-handler.js +51 -23
  137. package/dist/server/app-rsc-redirect-flight.d.ts +66 -0
  138. package/dist/server/app-rsc-redirect-flight.js +71 -0
  139. package/dist/server/app-rsc-request-normalization.d.ts +3 -2
  140. package/dist/server/app-rsc-request-normalization.js +8 -2
  141. package/dist/server/app-rsc-response-finalizer.d.ts +2 -2
  142. package/dist/server/app-rsc-response-finalizer.js +5 -11
  143. package/dist/server/app-rsc-route-matching.d.ts +20 -0
  144. package/dist/server/app-rsc-route-matching.js +87 -11
  145. package/dist/server/app-segment-config.js +15 -5
  146. package/dist/server/app-server-action-execution.d.ts +3 -1
  147. package/dist/server/app-server-action-execution.js +8 -6
  148. package/dist/server/app-ssr-entry.js +4 -1
  149. package/dist/server/app-ssr-stream.d.ts +2 -7
  150. package/dist/server/app-ssr-stream.js +5 -10
  151. package/dist/server/cache-proof.js +1 -1
  152. package/dist/server/config-headers.d.ts +24 -0
  153. package/dist/server/config-headers.js +52 -0
  154. package/dist/server/default-global-error-module.d.ts +3 -1
  155. package/dist/server/default-not-found-module.d.ts +3 -1
  156. package/dist/server/dev-initial-server-error.d.ts +1 -1
  157. package/dist/server/dev-lockfile.js +2 -3
  158. package/dist/server/dev-route-files.js +1 -1
  159. package/dist/server/dev-server.js +281 -173
  160. package/dist/server/dev-stack-sourcemap.js +4 -3
  161. package/dist/server/headers.d.ts +3 -1
  162. package/dist/server/headers.js +3 -1
  163. package/dist/server/image-optimization.js +2 -2
  164. package/dist/server/implicit-tags.js +2 -1
  165. package/dist/server/instrumentation.js +2 -2
  166. package/dist/server/isr-cache.d.ts +1 -1
  167. package/dist/server/isr-cache.js +1 -1
  168. package/dist/server/metadata-routes.js +4 -4
  169. package/dist/server/middleware-matcher-pattern.d.ts +22 -0
  170. package/dist/server/middleware-matcher-pattern.js +219 -0
  171. package/dist/server/middleware-matcher.d.ts +2 -7
  172. package/dist/server/middleware-matcher.js +13 -60
  173. package/dist/server/middleware-path-to-regexp.d.ts +14 -0
  174. package/dist/server/middleware-path-to-regexp.js +228 -0
  175. package/dist/server/middleware-response-headers.js +1 -1
  176. package/dist/server/middleware-runtime.js +5 -4
  177. package/dist/server/middleware.d.ts +2 -1
  178. package/dist/server/middleware.js +3 -2
  179. package/dist/server/navigation-planner.d.ts +2 -0
  180. package/dist/server/navigation-planner.js +8 -2
  181. package/dist/server/next-error-digest.d.ts +9 -24
  182. package/dist/server/next-error-digest.js +23 -15
  183. package/dist/server/operation-token.js +1 -1
  184. package/dist/server/pages-body-parser-config.js +2 -1
  185. package/dist/server/pages-data-route.d.ts +11 -1
  186. package/dist/server/pages-data-route.js +16 -1
  187. package/dist/server/pages-dev-hydration.d.ts +14 -0
  188. package/dist/server/pages-dev-hydration.js +83 -0
  189. package/dist/server/pages-dev-module-url.js +2 -2
  190. package/dist/server/pages-get-initial-props.d.ts +15 -2
  191. package/dist/server/pages-get-initial-props.js +16 -6
  192. package/dist/server/pages-node-compat.d.ts +13 -6
  193. package/dist/server/pages-node-compat.js +44 -45
  194. package/dist/server/pages-page-data.d.ts +4 -2
  195. package/dist/server/pages-page-data.js +20 -10
  196. package/dist/server/pages-page-handler.d.ts +4 -2
  197. package/dist/server/pages-page-handler.js +74 -43
  198. package/dist/server/pages-page-response.d.ts +2 -2
  199. package/dist/server/pages-page-response.js +1 -1
  200. package/dist/server/pages-preview.d.ts +26 -0
  201. package/dist/server/pages-preview.js +165 -0
  202. package/dist/server/pages-readiness.d.ts +5 -4
  203. package/dist/server/pages-readiness.js +4 -2
  204. package/dist/server/pages-request-pipeline.d.ts +1 -0
  205. package/dist/server/pages-request-pipeline.js +25 -11
  206. package/dist/server/pages-router-entry.js +6 -0
  207. package/dist/server/prerender-route-params.js +2 -2
  208. package/dist/server/prod-server.d.ts +1 -4
  209. package/dist/server/prod-server.js +44 -30
  210. package/dist/server/request-pipeline.d.ts +15 -29
  211. package/dist/server/request-pipeline.js +25 -60
  212. package/dist/server/rsc-stream-hints.js +122 -18
  213. package/dist/server/seed-cache.js +1 -1
  214. package/dist/server/socket-error-backstop.js +1 -1
  215. package/dist/server/static-file-cache.js +7 -8
  216. package/dist/server/worker-utils.js +1 -1
  217. package/dist/shims/app.d.ts +1 -1
  218. package/dist/shims/cache-request-state.d.ts +27 -1
  219. package/dist/shims/cache-request-state.js +60 -1
  220. package/dist/shims/cache-runtime.d.ts +12 -1
  221. package/dist/shims/cache-runtime.js +22 -7
  222. package/dist/shims/cache.d.ts +5 -5
  223. package/dist/shims/cache.js +28 -11
  224. package/dist/shims/constants.js +1 -1
  225. package/dist/shims/document.d.ts +42 -83
  226. package/dist/shims/document.js +62 -53
  227. package/dist/shims/dynamic.d.ts +5 -25
  228. package/dist/shims/dynamic.js +29 -8
  229. package/dist/shims/error-boundary.d.ts +4 -4
  230. package/dist/shims/error.d.ts +22 -6
  231. package/dist/shims/error.js +53 -15
  232. package/dist/shims/fetch-cache.js +13 -4
  233. package/dist/shims/font-google-base.d.ts +11 -4
  234. package/dist/shims/font-local.d.ts +10 -3
  235. package/dist/shims/font-utils.js +1 -1
  236. package/dist/shims/form.d.ts +1 -1
  237. package/dist/shims/head.d.ts +13 -2
  238. package/dist/shims/head.js +6 -6
  239. package/dist/shims/headers.d.ts +28 -31
  240. package/dist/shims/headers.js +115 -53
  241. package/dist/shims/image.d.ts +27 -37
  242. package/dist/shims/image.js +21 -14
  243. package/dist/shims/internal/cookie-serialize.d.ts +3 -1
  244. package/dist/shims/internal/cookie-serialize.js +3 -1
  245. package/dist/shims/internal/hybrid-client-route-owner.js +3 -1
  246. package/dist/shims/internal/pages-data-fetch-dedup.js +5 -3
  247. package/dist/shims/internal/utils.d.ts +3 -3
  248. package/dist/shims/layout-segment-context.d.ts +1 -1
  249. package/dist/shims/legacy-image.d.ts +3 -37
  250. package/dist/shims/legacy-image.js +6 -16
  251. package/dist/shims/link.d.ts +16 -21
  252. package/dist/shims/link.js +25 -13
  253. package/dist/shims/navigation-context-state.d.ts +1 -1
  254. package/dist/shims/navigation-errors.d.ts +2 -1
  255. package/dist/shims/navigation-errors.js +9 -13
  256. package/dist/shims/navigation.d.ts +8 -4
  257. package/dist/shims/navigation.js +29 -18
  258. package/dist/shims/next-shims-augmentations.d.ts +1 -0
  259. package/dist/shims/next-shims-public.d.ts +1 -0
  260. package/dist/shims/public-shim-map.json.js +103 -0
  261. package/dist/shims/readonly-url-search-params.d.ts +3 -3
  262. package/dist/shims/readonly-url-search-params.js +3 -3
  263. package/dist/shims/request-state-types.d.ts +1 -1
  264. package/dist/shims/router-state.d.ts +1 -0
  265. package/dist/shims/router.d.ts +57 -22
  266. package/dist/shims/router.js +178 -46
  267. package/dist/shims/script.d.ts +6 -10
  268. package/dist/shims/script.js +7 -4
  269. package/dist/shims/server.d.ts +45 -22
  270. package/dist/shims/server.js +46 -7
  271. package/dist/shims/slot.d.ts +1 -1
  272. package/dist/shims/thenable-params.js +1 -1
  273. package/dist/shims/unified-request-context.d.ts +1 -1
  274. package/dist/shims/unified-request-context.js +2 -0
  275. package/dist/shims/url-safety.d.ts +1 -1
  276. package/dist/shims/url-safety.js +2 -2
  277. package/dist/typegen.d.ts +8 -2
  278. package/dist/typegen.js +84 -25
  279. package/dist/utils/client-build-manifest.js +2 -2
  280. package/dist/utils/client-entry-manifest.js +1 -1
  281. package/dist/utils/client-runtime-metadata.js +1 -1
  282. package/dist/utils/commonjs-loader.js +3 -3
  283. package/dist/utils/domain-locale.d.ts +2 -2
  284. package/dist/utils/external-url.d.ts +5 -0
  285. package/dist/utils/external-url.js +7 -0
  286. package/dist/utils/mdx-scan.js +1 -1
  287. package/dist/utils/path.d.ts +1 -13
  288. package/dist/utils/path.js +1 -15
  289. package/dist/utils/plugin-options.d.ts +4 -0
  290. package/dist/utils/plugin-options.js +8 -0
  291. package/dist/utils/project.d.ts +0 -6
  292. package/dist/utils/project.js +2 -8
  293. package/dist/utils/public-routes.js +2 -2
  294. package/dist/utils/react-version.js +1 -1
  295. package/dist/utils/redirect-digest.d.ts +9 -0
  296. package/dist/utils/redirect-digest.js +25 -0
  297. package/dist/utils/regex-safety.d.ts +8 -0
  298. package/dist/utils/regex-safety.js +737 -0
  299. package/dist/utils/vinext-root.js +1 -1
  300. package/dist/utils/vite-version.d.ts +5 -2
  301. package/dist/utils/vite-version.js +43 -17
  302. package/package.json +16 -4
  303. /package/dist/build/google-fonts/{fallback-metrics-data.js → fallback-metrics-data.json.js} +0 -0
  304. /package/dist/build/google-fonts/{font-data.js → font-data.json.js} +0 -0
  305. /package/dist/{node_modules/.pnpm/process-ancestry@0.1.0/node_modules → deps/.pnpm/process-ancestry@0.1.0/deps}/process-ancestry/dist/index.js +0 -0
@@ -1,3 +1,4 @@
1
+ import { toSlash } from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
1
2
  import { VINEXT_ORIGINAL_STACK_TRACE_ENDPOINT } from "../utils/dev-stack-sourcemap-endpoint.js";
2
3
  import { readFile } from "node:fs/promises";
3
4
  import { fileURLToPath, pathToFileURL } from "node:url";
@@ -184,7 +185,7 @@ function extractV8ParenMethodName(prefix) {
184
185
  }
185
186
  function normalizeProjectRoot(root) {
186
187
  if (!root) return void 0;
187
- return root.replaceAll("\\", "/").replace(/\/+$/, "") || (root.startsWith("/") ? "/" : void 0);
188
+ return toSlash(root).replace(/\/+$/, "") || (root.startsWith("/") ? "/" : void 0);
188
189
  }
189
190
  function stripTrailingSlash(value) {
190
191
  return value?.replace(/[\\/]+$/, "");
@@ -240,7 +241,7 @@ function isWindowsAbsolutePath(value) {
240
241
  return /^[A-Za-z]:[\\/]/.test(value);
241
242
  }
242
243
  function normalizeLocalPathForCompare(value) {
243
- const normalized = (stripTrailingSlash(value.replaceAll("\\", "/")) ?? "").replace(/\/+/g, "/");
244
+ const normalized = (stripTrailingSlash(toSlash(value)) ?? "").replace(/\/+/g, "/");
244
245
  return /^[A-Za-z]:\//.test(normalized) ? normalized.toLowerCase() : normalized;
245
246
  }
246
247
  function normalizeIgnoreListPath(value) {
@@ -255,7 +256,7 @@ function normalizeIgnoreListPath(value) {
255
256
  try {
256
257
  path = decodeURIComponent(path);
257
258
  } catch {}
258
- return path.replaceAll("\\", "/").toLowerCase();
259
+ return toSlash(path).toLowerCase();
259
260
  }
260
261
  function isExternalHttpFrame(file, requestHost) {
261
262
  if (!/^https?:\/\//i.test(file) || !requestHost) return false;
@@ -56,6 +56,8 @@ declare const VINEXT_CLIENT_REUSE_MANIFEST_HEADER = "X-Vinext-Client-Reuse-Manif
56
56
  * cheap way to detect the redirect ahead of stream decode.
57
57
  */
58
58
  declare const VINEXT_RSC_REDIRECT_HEADER = "X-Vinext-Rsc-Redirect";
59
+ /** History update mode encoded by a streamed RSC redirect. */
60
+ declare const VINEXT_RSC_REDIRECT_TYPE_HEADER = "X-Vinext-Rsc-Redirect-Type";
59
61
  /** Standard RSC header — value "1" indicates an RSC payload request. */
60
62
  declare const RSC_HEADER = "RSC";
61
63
  /** Server Action invocation header (vinext/vite-rsc protocol). */
@@ -105,4 +107,4 @@ declare const INTERNAL_HEADERS: string[];
105
107
  /** Vinext-only internal headers stripped alongside Next.js protocol internals. */
106
108
  declare const VINEXT_INTERNAL_HEADERS: string[];
107
109
  //#endregion
108
- 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_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, MIDDLEWARE_SKIP_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_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_CACHE_LIFE_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
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_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, MIDDLEWARE_SKIP_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_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_CACHE_LIFE_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_REDIRECT_TYPE_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
@@ -55,6 +55,8 @@ const VINEXT_CLIENT_REUSE_MANIFEST_HEADER = "X-Vinext-Client-Reuse-Manifest";
55
55
  * cheap way to detect the redirect ahead of stream decode.
56
56
  */
57
57
  const VINEXT_RSC_REDIRECT_HEADER = "X-Vinext-Rsc-Redirect";
58
+ /** History update mode encoded by a streamed RSC redirect. */
59
+ const VINEXT_RSC_REDIRECT_TYPE_HEADER = "X-Vinext-Rsc-Redirect-Type";
58
60
  /** Standard RSC header — value "1" indicates an RSC payload request. */
59
61
  const RSC_HEADER = "RSC";
60
62
  /** Server Action invocation header (vinext/vite-rsc protocol). */
@@ -128,4 +130,4 @@ const VINEXT_INTERNAL_HEADERS = [
128
130
  VINEXT_PRERENDER_CACHE_LIFE_HEADER
129
131
  ];
130
132
  //#endregion
131
- 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_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, MIDDLEWARE_SKIP_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_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_CACHE_LIFE_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
133
+ 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_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, MIDDLEWARE_SKIP_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_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_CACHE_LIFE_HEADER, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_REVALIDATE_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_REDIRECT_TYPE_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_STATIC_FILE_HEADER, VINEXT_TIMING_HEADER };
@@ -87,7 +87,7 @@ function resolveDevImageRedirect(requestUrl, allowedWidths = [...DEFAULT_DEVICE_
87
87
  * https://github.com/vercel/next.js/blob/canary/test/integration/image-optimizer/test/index.test.ts
88
88
  */
89
89
  function parseImageParams(url, allowedWidths = [...DEFAULT_DEVICE_SIZES, ...DEFAULT_IMAGE_SIZES], allowedQualities, options = {}) {
90
- const allowedParamNames = new Set([
90
+ const allowedParamNames = /* @__PURE__ */ new Set([
91
91
  "url",
92
92
  "w",
93
93
  "q",
@@ -150,7 +150,7 @@ const IMAGE_CONTENT_SECURITY_POLICY = "script-src 'none'; frame-src 'none'; sand
150
150
  * SVG is intentionally excluded — it can contain embedded JavaScript and is
151
151
  * essentially an XML document, not a safe raster image format.
152
152
  */
153
- const SAFE_IMAGE_CONTENT_TYPES = new Set([
153
+ const SAFE_IMAGE_CONTENT_TYPES = /* @__PURE__ */ new Set([
154
154
  "image/jpeg",
155
155
  "image/png",
156
156
  "image/gif",
@@ -33,7 +33,8 @@ function buildAppPageTags(cleanPathname, extraTags, routeSegments) {
33
33
  return buildPageCacheTags(cleanPathname, extraTags, [...routeSegments], "page");
34
34
  }
35
35
  function buildPageCacheTags(pathname, extraTags, routeSegments, leafKind) {
36
- const tags = [pathname, `${NEXT_CACHE_IMPLICIT_TAG_ID}${pathname.length > 1 && pathname.endsWith("/") ? pathname.slice(0, -1) : pathname}`];
36
+ const normalizedPathname = pathname.length > 1 && pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
37
+ const tags = [pathname, `${NEXT_CACHE_IMPLICIT_TAG_ID}${normalizedPathname}`];
37
38
  if (pathname === "/") appendUnique(tags, `${NEXT_CACHE_IMPLICIT_TAG_ID}/index`);
38
39
  if (pathname === "/index") appendUnique(tags, `${NEXT_CACHE_IMPLICIT_TAG_ID}/`);
39
40
  appendDerivedTags(tags, buildRouteCachePath(routeSegments, leafKind));
@@ -1,6 +1,6 @@
1
+ import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
1
2
  import { getRequestExecutionContext } from "../shims/request-context.js";
2
3
  import fs from "node:fs";
3
- import path from "node:path";
4
4
  //#region src/server/instrumentation.ts
5
5
  /**
6
6
  * instrumentation.ts support
@@ -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.posix.join(root, dir, `${basename}${ext}`);
54
+ const fullPath = path.join(root, dir, `${basename}${ext}`);
55
55
  if (fs.existsSync(fullPath)) return fullPath;
56
56
  }
57
57
  return null;
@@ -1,8 +1,8 @@
1
1
  import { OnRequestErrorContext } from "./instrumentation.js";
2
2
  import { RenderObservation } from "./cache-proof.js";
3
+ import { AppRscRenderMode } from "./app-rsc-render-mode.js";
3
4
  import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
4
5
  import { CacheHandlerValue, CachedAppPageValue, CachedPagesValue, IncrementalCacheValue } from "../shims/cache-handler.js";
5
- import { AppRscRenderMode } from "./app-rsc-render-mode.js";
6
6
 
7
7
  //#region src/server/isr-cache.d.ts
8
8
  /**
@@ -62,7 +62,7 @@ function getRevalidateSecret() {
62
62
  const baked = process.env.__VINEXT_REVALIDATE_SECRET;
63
63
  if (baked) return baked;
64
64
  if (devRevalidateSecret === void 0) {
65
- const bytes = new Uint8Array(32);
65
+ const bytes = /* @__PURE__ */ new Uint8Array(32);
66
66
  crypto.getRandomValues(bytes);
67
67
  devRevalidateSecret = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
68
68
  }
@@ -1,6 +1,6 @@
1
+ import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
1
2
  import { matchRoutePattern } from "../routing/route-pattern.js";
2
3
  import fs from "node:fs";
3
- import path from "node:path";
4
4
  //#region src/server/metadata-routes.ts
5
5
  /**
6
6
  * File-based metadata route handling.
@@ -292,7 +292,7 @@ function computeMetadataRouteSuffix(appDirPath, leafName) {
292
292
  };
293
293
  }
294
294
  function getMetadataRouteFilename(appDirPath, lastSegment) {
295
- const ext = path.posix.extname(lastSegment);
295
+ const ext = path.extname(lastSegment);
296
296
  const name = lastSegment.slice(0, -ext.length || void 0);
297
297
  const { suffix } = computeMetadataRouteSuffix(appDirPath, name);
298
298
  return `${name}${suffix ? `-${suffix}` : ""}${ext}`;
@@ -339,8 +339,8 @@ function metadataRouteSuffix(parentSegments, metaType) {
339
339
  }
340
340
  function withMetadataSuffix(urlPath, suffix) {
341
341
  if (!suffix) return urlPath;
342
- const parsed = path.posix.parse(urlPath);
343
- return path.posix.join(parsed.dir || "/", `${parsed.name}-${suffix}${parsed.ext}`);
342
+ const parsed = path.parse(urlPath);
343
+ return path.join(parsed.dir || "/", `${parsed.name}-${suffix}${parsed.ext}`);
344
344
  }
345
345
  function getMetadataServedUrl(metaType, config, ext, isDynamic, suffix, routeBaseName) {
346
346
  if (isDynamic && (metaType === "icon" || metaType === "apple-icon" || metaType === "opengraph-image" || metaType === "twitter-image")) return withMetadataSuffix(`/${routeBaseName}`, suffix);
@@ -0,0 +1,22 @@
1
+ import { HasCondition } from "../config/next-config.js";
2
+
3
+ //#region src/server/middleware-matcher-pattern.d.ts
4
+ type CompiledMiddlewareMatcherPattern = {
5
+ regexp: RegExp;
6
+ error?: never;
7
+ } | {
8
+ regexp?: never;
9
+ error: string;
10
+ kind: "invalid" | "unsafe";
11
+ };
12
+ type MiddlewareMatcherObject = {
13
+ source: string;
14
+ locale?: false;
15
+ has?: HasCondition[];
16
+ missing?: HasCondition[];
17
+ };
18
+ declare function isValidMiddlewareMatcherObjectConfig(value: unknown): value is MiddlewareMatcherObject;
19
+ declare function compileMiddlewareMatcherPattern(source: string): CompiledMiddlewareMatcherPattern;
20
+ declare function validateMiddlewareMatcherPatterns(value: unknown): void;
21
+ //#endregion
22
+ export { CompiledMiddlewareMatcherPattern, MiddlewareMatcherObject, compileMiddlewareMatcherPattern, isValidMiddlewareMatcherObjectConfig, validateMiddlewareMatcherPatterns };
@@ -0,0 +1,219 @@
1
+ import { analyzeRegexSafety, regexAtomsMayOverlap } from "../utils/regex-safety.js";
2
+ import { middlewarePathTokensToRegExp, normalizeMiddlewarePathTokens, parseMiddlewarePath } from "./middleware-path-to-regexp.js";
3
+ //#region src/server/middleware-matcher-pattern.ts
4
+ const MATCHER_OBJECT_KEYS = /* @__PURE__ */ new Set([
5
+ "source",
6
+ "locale",
7
+ "has",
8
+ "missing"
9
+ ]);
10
+ const CONDITION_TYPES_WITH_KEY = /* @__PURE__ */ new Set([
11
+ "header",
12
+ "query",
13
+ "cookie"
14
+ ]);
15
+ function invalidConditionReason(value) {
16
+ if (!value || typeof value !== "object" || Array.isArray(value)) return "has and missing entries must be objects";
17
+ const condition = value;
18
+ const type = condition.type;
19
+ if (typeof type === "string" && CONDITION_TYPES_WITH_KEY.has(type)) {
20
+ for (const key of Object.keys(condition)) if (key !== "type" && key !== "key" && key !== "value") return `condition contains unsupported field "${key}"`;
21
+ if (typeof condition.key !== "string") return `condition type "${type}" requires a string key`;
22
+ if (condition.value !== void 0 && typeof condition.value !== "string") return `condition type "${type}" requires value to be a string`;
23
+ return null;
24
+ }
25
+ if (type === "host") {
26
+ for (const key of Object.keys(condition)) if (key !== "type" && key !== "value") return `host condition contains unsupported field "${key}"`;
27
+ return typeof condition.value === "string" ? null : "host condition requires a string value";
28
+ }
29
+ return "condition type must be header, query, cookie, or host";
30
+ }
31
+ function invalidConditionsReason(value, field) {
32
+ if (value === void 0) return null;
33
+ if (!Array.isArray(value)) return `${field} must be an array`;
34
+ for (const condition of value) {
35
+ const reason = invalidConditionReason(condition);
36
+ if (reason) return `${field} ${reason}`;
37
+ }
38
+ return null;
39
+ }
40
+ function matcherObjectSource(value) {
41
+ if (!value || typeof value !== "object" || Array.isArray(value)) return { error: "matcher entries must be strings or objects" };
42
+ const matcher = value;
43
+ for (const key of Object.keys(matcher)) if (!MATCHER_OBJECT_KEYS.has(key)) return { error: `matcher object contains unsupported field "${key}"` };
44
+ if (typeof matcher.source !== "string") return { error: "matcher object requires a string source" };
45
+ if (matcher.locale !== void 0 && matcher.locale !== false) return { error: "matcher object locale must be false when provided" };
46
+ const invalidHas = invalidConditionsReason(matcher.has, "has");
47
+ if (invalidHas) return { error: invalidHas };
48
+ const invalidMissing = invalidConditionsReason(matcher.missing, "missing");
49
+ if (invalidMissing) return { error: invalidMissing };
50
+ return { source: matcher.source };
51
+ }
52
+ function isValidMiddlewareMatcherObjectConfig(value) {
53
+ return matcherObjectSource(value).error === void 0;
54
+ }
55
+ function patternMatches(pattern, value) {
56
+ try {
57
+ return new RegExp(`^(?:${pattern})$`).test(value);
58
+ } catch {
59
+ return false;
60
+ }
61
+ }
62
+ function atomsOverlap(left, right) {
63
+ return regexAtomsMayOverlap(left, right, true);
64
+ }
65
+ function groupCanMatchEmpty(group) {
66
+ if (/^\?(?:[=!]|<[=!])/.test(group)) return true;
67
+ return patternMatches(group.startsWith("?:") ? group.slice(2) : group, "");
68
+ }
69
+ function hasOverlappingSequentialRepetition(pattern) {
70
+ const repeatedAtDepth = [[]];
71
+ const groupStarts = [];
72
+ let depth = 0;
73
+ for (let index = 0; index < pattern.length; index++) {
74
+ const character = pattern[index];
75
+ if (character === "(") {
76
+ groupStarts.push(index);
77
+ depth++;
78
+ repeatedAtDepth[depth] = [];
79
+ if (pattern[index + 1] === "?") {
80
+ index++;
81
+ if (pattern[index + 1] === "<" && /[=!]/.test(pattern[index + 2] ?? "")) index += 2;
82
+ else if (/[=:!]/.test(pattern[index + 1] ?? "")) index++;
83
+ }
84
+ continue;
85
+ }
86
+ if (character === ")") {
87
+ const groupStart = groupStarts.pop();
88
+ repeatedAtDepth[depth] = [];
89
+ depth = Math.max(0, depth - 1);
90
+ if (groupStart !== void 0) {
91
+ const modifier = pattern[index + 1];
92
+ if (!(modifier === "*" || modifier === "?" || modifier === "{" && /^\{0(?:,\d*)?\}/.test(pattern.slice(index + 1))) && !groupCanMatchEmpty(pattern.slice(groupStart + 1, index))) repeatedAtDepth[depth] = [];
93
+ }
94
+ continue;
95
+ }
96
+ if (character === "|") {
97
+ repeatedAtDepth[depth] = [];
98
+ continue;
99
+ }
100
+ if (character === "^" || character === "$") continue;
101
+ if (character === "*" || character === "+" || character === "?" || character === "{") continue;
102
+ let atom = character;
103
+ if (character === "\\") {
104
+ if (index + 1 >= pattern.length) return true;
105
+ atom += pattern[++index];
106
+ } else if (character === "[") {
107
+ let classEnd = index + 1;
108
+ if (pattern[classEnd] === "^") classEnd++;
109
+ while (classEnd < pattern.length && pattern[classEnd] !== "]") {
110
+ if (pattern[classEnd] === "\\") classEnd++;
111
+ classEnd++;
112
+ }
113
+ if (classEnd >= pattern.length) return true;
114
+ atom = pattern.slice(index, classEnd + 1);
115
+ index = classEnd;
116
+ } else if (character === ".") atom = ".";
117
+ const quantifierStart = index + 1;
118
+ const quantifier = pattern[quantifierStart];
119
+ let unbounded = quantifier === "*" || quantifier === "+";
120
+ let canBeEmpty = quantifier === "*";
121
+ let quantifierEnd = quantifierStart;
122
+ if (quantifier === "{") {
123
+ const match = /^\{(\d+),\}/.exec(pattern.slice(quantifierStart));
124
+ if (match) {
125
+ unbounded = true;
126
+ canBeEmpty = Number(match[1]) === 0;
127
+ quantifierEnd += match[0].length - 1;
128
+ }
129
+ }
130
+ if (!unbounded) {
131
+ if (quantifier !== "?") repeatedAtDepth[depth] = [];
132
+ if (quantifier === "?") index = quantifierStart;
133
+ continue;
134
+ }
135
+ if (repeatedAtDepth[depth].some((previous) => atomsOverlap(previous, atom))) return true;
136
+ repeatedAtDepth[depth] = canBeEmpty ? [...repeatedAtDepth[depth], atom] : [atom];
137
+ index = quantifierEnd;
138
+ }
139
+ return false;
140
+ }
141
+ function unsafeTokenReason(token) {
142
+ const regexSafetyIssue = analyzeRegexSafety(token.pattern, { ignoreCase: true });
143
+ if (regexSafetyIssue) {
144
+ if (regexSafetyIssue === "analysis budget exceeded") return `parameter "${token.name}" exceeds the regex analysis budget`;
145
+ return `parameter "${token.name}" contains ${regexSafetyIssue}`;
146
+ }
147
+ if (hasOverlappingSequentialRepetition(token.pattern)) return `parameter "${token.name}" contains overlapping sequential repetition`;
148
+ if (token.modifier !== "*" && token.modifier !== "+") return null;
149
+ if (patternMatches(token.pattern, "") || patternMatches(token.pattern, "/")) return `repeated parameter "${token.name}" may match an empty value or path delimiter`;
150
+ return null;
151
+ }
152
+ function validateTokens(tokens) {
153
+ for (const token of tokens) {
154
+ if (typeof token === "string") continue;
155
+ const reason = unsafeTokenReason(token);
156
+ if (reason) return reason;
157
+ }
158
+ return null;
159
+ }
160
+ function compileMiddlewareMatcherPattern(source) {
161
+ if (!source.startsWith("/")) return {
162
+ kind: "invalid",
163
+ error: "source must start with /"
164
+ };
165
+ if (source.length > 4096) return {
166
+ kind: "invalid",
167
+ error: "source exceeds max built length of 4096"
168
+ };
169
+ let tokens;
170
+ try {
171
+ tokens = parseMiddlewarePath(source);
172
+ } catch (error) {
173
+ return {
174
+ kind: "invalid",
175
+ error: error instanceof Error ? error.message : "matcher could not be parsed"
176
+ };
177
+ }
178
+ const unsafeReason = validateTokens(tokens);
179
+ if (unsafeReason) return {
180
+ kind: "unsafe",
181
+ error: unsafeReason
182
+ };
183
+ try {
184
+ return { regexp: middlewarePathTokensToRegExp(tokens) };
185
+ } catch {
186
+ const normalizedTokens = normalizeMiddlewarePathTokens(tokens);
187
+ const normalizedUnsafeReason = validateTokens(normalizedTokens);
188
+ if (normalizedUnsafeReason) return {
189
+ kind: "unsafe",
190
+ error: normalizedUnsafeReason
191
+ };
192
+ try {
193
+ return { regexp: middlewarePathTokensToRegExp(normalizedTokens) };
194
+ } catch (error) {
195
+ return {
196
+ kind: "invalid",
197
+ error: error instanceof Error ? error.message : "matcher could not be compiled"
198
+ };
199
+ }
200
+ }
201
+ }
202
+ function validateMiddlewareMatcherPatterns(value) {
203
+ const sources = [];
204
+ if (typeof value === "string") sources.push(value);
205
+ else if (Array.isArray(value)) for (const matcher of value) if (typeof matcher === "string") sources.push(matcher);
206
+ else {
207
+ const result = matcherObjectSource(matcher);
208
+ if (result.error) throw new Error(`Invalid middleware matcher config: ${result.error}.`);
209
+ sources.push(result.source);
210
+ }
211
+ else throw new Error("Invalid middleware matcher config: matcher must be a string or an array of strings or objects.");
212
+ for (const source of sources) {
213
+ const result = compileMiddlewareMatcherPattern(source);
214
+ if (result.regexp) continue;
215
+ throw new Error(`Invalid middleware matcher "${source}": ${result.error}.`);
216
+ }
217
+ }
218
+ //#endregion
219
+ export { compileMiddlewareMatcherPattern, isValidMiddlewareMatcherObjectConfig, validateMiddlewareMatcherPatterns };
@@ -1,12 +1,7 @@
1
- import { HasCondition, NextI18nConfig } from "../config/next-config.js";
1
+ import { NextI18nConfig } from "../config/next-config.js";
2
+ import { MiddlewareMatcherObject } from "./middleware-matcher-pattern.js";
2
3
 
3
4
  //#region src/server/middleware-matcher.d.ts
4
- type MiddlewareMatcherObject = {
5
- source: string;
6
- locale?: false;
7
- has?: HasCondition[];
8
- missing?: HasCondition[];
9
- };
10
5
  type MatcherConfig = string | Array<string | MiddlewareMatcherObject>;
11
6
  declare function matchesMiddleware(pathname: string, matcher: MatcherConfig | undefined, request?: Request, i18nConfig?: NextI18nConfig | null): boolean;
12
7
  declare function matchPattern(pathname: string, pattern: string): boolean;
@@ -1,5 +1,7 @@
1
1
  import { removeTrailingSlash } from "../utils/base-path.js";
2
- import { checkHasConditions, isSafeRegex, requestContextFromRequest, safeRegExp } from "../config/config-matchers.js";
2
+ import { requestContextFromRequest } from "../config/request-context.js";
3
+ import { checkHasConditions } from "../config/config-matchers.js";
4
+ import { compileMiddlewareMatcherPattern, isValidMiddlewareMatcherObjectConfig } from "./middleware-matcher-pattern.js";
3
5
  //#region src/server/middleware-matcher.ts
4
6
  const EMPTY_MIDDLEWARE_REQUEST_CONTEXT = {
5
7
  headers: new Headers(),
@@ -12,30 +14,20 @@ const _mwPatternCache = /* @__PURE__ */ new Map();
12
14
  function matchesMiddleware(pathname, matcher, request, i18nConfig) {
13
15
  if (!matcher) return true;
14
16
  if (typeof matcher === "string") return matchMatcherPattern(pathname, matcher, i18nConfig);
15
- if (!Array.isArray(matcher)) return false;
17
+ if (!Array.isArray(matcher)) return true;
16
18
  const requestContext = request ? requestContextFromRequest(request) : EMPTY_MIDDLEWARE_REQUEST_CONTEXT;
17
19
  for (const m of matcher) {
18
20
  if (typeof m === "string") {
19
21
  if (matchMatcherPattern(pathname, m, i18nConfig)) return true;
20
22
  continue;
21
23
  }
22
- if (isValidMiddlewareMatcherObject(m)) {
23
- if (!matchObjectMatcher(pathname, m, i18nConfig)) continue;
24
- if (!checkHasConditions(m.has, m.missing, requestContext)) continue;
25
- return true;
26
- }
24
+ if (!isValidMiddlewareMatcherObjectConfig(m)) return true;
25
+ if (!matchObjectMatcher(pathname, m, i18nConfig)) continue;
26
+ if (!checkHasConditions(m.has, m.missing, requestContext)) continue;
27
+ return true;
27
28
  }
28
29
  return false;
29
30
  }
30
- function isValidMiddlewareMatcherObject(value) {
31
- if (!value || typeof value !== "object" || Array.isArray(value)) return false;
32
- if (!("source" in value) || typeof value.source !== "string") return false;
33
- for (const key of Object.keys(value)) if (key !== "source" && key !== "locale" && key !== "has" && key !== "missing") return false;
34
- if ("locale" in value && value.locale !== void 0 && value.locale !== false) return false;
35
- if ("has" in value && value.has !== void 0 && !Array.isArray(value.has)) return false;
36
- if ("missing" in value && value.missing !== void 0 && !Array.isArray(value.missing)) return false;
37
- return true;
38
- }
39
31
  function matchMatcherPattern(pathname, pattern, i18nConfig) {
40
32
  if (!i18nConfig) return matchPattern(pathname, pattern);
41
33
  return matchPattern(stripLocalePrefix(pathname, i18nConfig) ?? pathname, pattern);
@@ -58,54 +50,15 @@ function matchPattern(pathname, pattern) {
58
50
  _mwPatternCache.set(normalizedPattern, cached);
59
51
  }
60
52
  if (cached === UNSAFE_MATCHER_PATTERN) return true;
61
- if (cached === null) return removeTrailingSlash(pathname) === normalizedPattern;
62
53
  if (cached.test(pathname)) return true;
63
54
  return pathname.endsWith("/") && cached.test(removeTrailingSlash(pathname));
64
55
  }
65
- function extractConstraint(str, re) {
66
- if (str[re.lastIndex] !== "(") return null;
67
- const start = re.lastIndex + 1;
68
- let depth = 1;
69
- let i = start;
70
- while (i < str.length && depth > 0) {
71
- if (str[i] === "(") depth++;
72
- else if (str[i] === ")") depth--;
73
- i++;
74
- }
75
- if (depth !== 0) return null;
76
- re.lastIndex = i;
77
- return str.slice(start, i - 1);
78
- }
79
56
  function compileMatcherPattern(pattern) {
80
- const hasConstraints = /:[\w-]+[*+]?\(/.test(pattern);
81
- if (!hasConstraints && (pattern.includes("(") || pattern.includes("\\"))) return compileMatcherRegExp("^" + pattern + "$", pattern);
82
- let regexStr = "";
83
- const tokenRe = /\/:([\w-]+)\*|\/:([\w-]+)\+|:([\w-]+)|[.]|[^/:.]+|./g;
84
- let tok;
85
- while ((tok = tokenRe.exec(pattern)) !== null) if (tok[1] !== void 0) {
86
- const constraint = hasConstraints ? extractConstraint(pattern, tokenRe) : null;
87
- regexStr += constraint !== null ? `(?:/(${constraint}))?` : "(?:/.*)?";
88
- } else if (tok[2] !== void 0) {
89
- const constraint = hasConstraints ? extractConstraint(pattern, tokenRe) : null;
90
- regexStr += constraint !== null ? `(?:/(${constraint}))` : "(?:/.+)";
91
- } else if (tok[3] !== void 0) {
92
- const constraint = hasConstraints ? extractConstraint(pattern, tokenRe) : null;
93
- const isOptional = pattern[tokenRe.lastIndex] === "?";
94
- if (isOptional) tokenRe.lastIndex += 1;
95
- const group = constraint !== null ? `(${constraint})` : "([^/]+)";
96
- if (isOptional && regexStr.endsWith("/")) regexStr = regexStr.slice(0, -1) + `(?:/${group})?`;
97
- else if (isOptional) regexStr += `${group}?`;
98
- else regexStr += group;
99
- } else if (tok[0] === ".") regexStr += "\\.";
100
- else regexStr += tok[0];
101
- return compileMatcherRegExp("^" + regexStr + "$", pattern);
102
- }
103
- function compileMatcherRegExp(regexPattern, sourcePattern) {
104
- if (!isSafeRegex(regexPattern)) {
105
- console.warn(`[vinext] Rejecting potentially unsafe middleware matcher (ReDoS risk): ${sourcePattern}\n Middleware will run for all paths to avoid bypassing request guards.\n Simplify the matcher to avoid nested repetition.`);
106
- return UNSAFE_MATCHER_PATTERN;
107
- }
108
- return safeRegExp(regexPattern);
57
+ const result = compileMiddlewareMatcherPattern(pattern);
58
+ if (result.regexp) return result.regexp;
59
+ const problem = result.kind === "unsafe" ? "potentially unsafe" : "invalid";
60
+ console.warn(`[vinext] Rejecting ${problem} middleware matcher: ${pattern}\n ${result.error}.\n Middleware will run for all paths to avoid bypassing request guards.`);
61
+ return UNSAFE_MATCHER_PATTERN;
109
62
  }
110
63
  //#endregion
111
64
  export { matchPattern, matchesMiddleware };
@@ -0,0 +1,14 @@
1
+ //#region src/server/middleware-path-to-regexp.d.ts
2
+ type MiddlewarePathToken = string | MiddlewarePathKey;
3
+ type MiddlewarePathKey = {
4
+ name: string | number;
5
+ prefix: string;
6
+ suffix: string;
7
+ pattern: string;
8
+ modifier: string;
9
+ };
10
+ declare function parseMiddlewarePath(value: string): MiddlewarePathToken[];
11
+ declare function normalizeMiddlewarePathTokens(tokens: MiddlewarePathToken[]): MiddlewarePathToken[];
12
+ declare function middlewarePathTokensToRegExp(tokens: MiddlewarePathToken[]): RegExp;
13
+ //#endregion
14
+ export { MiddlewarePathKey, MiddlewarePathToken, middlewarePathTokensToRegExp, normalizeMiddlewarePathTokens, parseMiddlewarePath };