vinext 0.0.45 → 0.0.47

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 (311) hide show
  1. package/README.md +7 -5
  2. package/dist/build/prerender.d.ts +2 -1
  3. package/dist/build/prerender.js +80 -17
  4. package/dist/build/prerender.js.map +1 -1
  5. package/dist/build/report.d.ts +1 -1
  6. package/dist/build/route-classification-injector.d.ts +35 -0
  7. package/dist/build/route-classification-injector.js +61 -0
  8. package/dist/build/route-classification-injector.js.map +1 -0
  9. package/dist/build/route-classification-manifest.d.ts +1 -1
  10. package/dist/build/standalone.js +4 -3
  11. package/dist/build/standalone.js.map +1 -1
  12. package/dist/build/static-export.d.ts +1 -1
  13. package/dist/check.js +30 -18
  14. package/dist/check.js.map +1 -1
  15. package/dist/cli-args.d.ts +31 -0
  16. package/dist/cli-args.js +104 -0
  17. package/dist/cli-args.js.map +1 -0
  18. package/dist/cli.js +6 -19
  19. package/dist/cli.js.map +1 -1
  20. package/dist/cloudflare/kv-cache-handler.js +29 -9
  21. package/dist/cloudflare/kv-cache-handler.js.map +1 -1
  22. package/dist/config/config-matchers.js +1 -0
  23. package/dist/config/config-matchers.js.map +1 -1
  24. package/dist/config/next-config.d.ts +42 -4
  25. package/dist/config/next-config.js +27 -0
  26. package/dist/config/next-config.js.map +1 -1
  27. package/dist/deploy.js +18 -23
  28. package/dist/deploy.js.map +1 -1
  29. package/dist/entries/app-rsc-entry.d.ts +4 -3
  30. package/dist/entries/app-rsc-entry.js +435 -2317
  31. package/dist/entries/app-rsc-entry.js.map +1 -1
  32. package/dist/entries/app-rsc-manifest.d.ts +24 -0
  33. package/dist/entries/app-rsc-manifest.js +155 -0
  34. package/dist/entries/app-rsc-manifest.js.map +1 -0
  35. package/dist/entries/pages-server-entry.js +18 -105
  36. package/dist/entries/pages-server-entry.js.map +1 -1
  37. package/dist/index.js +82 -85
  38. package/dist/index.js.map +1 -1
  39. package/dist/plugins/fonts.js +54 -32
  40. package/dist/plugins/fonts.js.map +1 -1
  41. package/dist/plugins/rsc-client-shim-excludes.d.ts +6 -0
  42. package/dist/plugins/rsc-client-shim-excludes.js +28 -0
  43. package/dist/plugins/rsc-client-shim-excludes.js.map +1 -0
  44. package/dist/routing/app-route-graph.d.ts +109 -0
  45. package/dist/routing/app-route-graph.js +819 -0
  46. package/dist/routing/app-route-graph.js.map +1 -0
  47. package/dist/routing/app-router.d.ts +2 -79
  48. package/dist/routing/app-router.js +7 -621
  49. package/dist/routing/app-router.js.map +1 -1
  50. package/dist/routing/route-pattern.d.ts +9 -0
  51. package/dist/routing/route-pattern.js +90 -0
  52. package/dist/routing/route-pattern.js.map +1 -0
  53. package/dist/routing/route-trie.js +10 -11
  54. package/dist/routing/route-trie.js.map +1 -1
  55. package/dist/server/app-browser-entry.js +94 -232
  56. package/dist/server/app-browser-entry.js.map +1 -1
  57. package/dist/server/app-browser-error.d.ts +3 -4
  58. package/dist/server/app-browser-error.js +8 -4
  59. package/dist/server/app-browser-error.js.map +1 -1
  60. package/dist/server/app-browser-navigation-controller.d.ts +73 -0
  61. package/dist/server/app-browser-navigation-controller.js +282 -0
  62. package/dist/server/app-browser-navigation-controller.js.map +1 -0
  63. package/dist/server/app-browser-state.d.ts +1 -1
  64. package/dist/server/app-browser-state.js.map +1 -1
  65. package/dist/server/app-elements.js +1 -5
  66. package/dist/server/app-elements.js.map +1 -1
  67. package/dist/server/app-fallback-renderer.d.ts +57 -0
  68. package/dist/server/app-fallback-renderer.js +79 -0
  69. package/dist/server/app-fallback-renderer.js.map +1 -0
  70. package/dist/server/app-hook-warning-suppression.d.ts +7 -0
  71. package/dist/server/app-hook-warning-suppression.js +12 -0
  72. package/dist/server/app-hook-warning-suppression.js.map +1 -0
  73. package/dist/server/app-middleware.d.ts +32 -0
  74. package/dist/server/app-middleware.js +147 -0
  75. package/dist/server/app-middleware.js.map +1 -0
  76. package/dist/server/app-mounted-slots-header.d.ts +17 -0
  77. package/dist/server/app-mounted-slots-header.js +21 -0
  78. package/dist/server/app-mounted-slots-header.js.map +1 -0
  79. package/dist/server/app-page-boundary-render.d.ts +4 -2
  80. package/dist/server/app-page-boundary-render.js +50 -30
  81. package/dist/server/app-page-boundary-render.js.map +1 -1
  82. package/dist/server/app-page-boundary.d.ts +12 -1
  83. package/dist/server/app-page-boundary.js +27 -12
  84. package/dist/server/app-page-boundary.js.map +1 -1
  85. package/dist/server/app-page-cache.d.ts +22 -5
  86. package/dist/server/app-page-cache.js +90 -11
  87. package/dist/server/app-page-cache.js.map +1 -1
  88. package/dist/server/app-page-dispatch.d.ts +123 -0
  89. package/dist/server/app-page-dispatch.js +348 -0
  90. package/dist/server/app-page-dispatch.js.map +1 -0
  91. package/dist/server/app-page-element-builder.d.ts +61 -0
  92. package/dist/server/app-page-element-builder.js +139 -0
  93. package/dist/server/app-page-element-builder.js.map +1 -0
  94. package/dist/server/app-page-execution.d.ts +4 -3
  95. package/dist/server/app-page-execution.js +5 -8
  96. package/dist/server/app-page-execution.js.map +1 -1
  97. package/dist/server/app-page-head.d.ts +55 -0
  98. package/dist/server/app-page-head.js +196 -0
  99. package/dist/server/app-page-head.js.map +1 -0
  100. package/dist/server/app-page-method.d.ts +16 -0
  101. package/dist/server/app-page-method.js +30 -0
  102. package/dist/server/app-page-method.js.map +1 -0
  103. package/dist/server/app-page-params.d.ts +8 -0
  104. package/dist/server/app-page-params.js +28 -0
  105. package/dist/server/app-page-params.js.map +1 -0
  106. package/dist/server/app-page-render.d.ts +7 -2
  107. package/dist/server/app-page-render.js +131 -32
  108. package/dist/server/app-page-render.js.map +1 -1
  109. package/dist/server/app-page-request.d.ts +23 -8
  110. package/dist/server/app-page-request.js +51 -6
  111. package/dist/server/app-page-request.js.map +1 -1
  112. package/dist/server/app-page-response.d.ts +1 -0
  113. package/dist/server/app-page-response.js +3 -7
  114. package/dist/server/app-page-response.js.map +1 -1
  115. package/dist/server/app-page-route-wiring.d.ts +29 -5
  116. package/dist/server/app-page-route-wiring.js +30 -8
  117. package/dist/server/app-page-route-wiring.js.map +1 -1
  118. package/dist/server/app-page-stream.d.ts +10 -0
  119. package/dist/server/app-page-stream.js +5 -1
  120. package/dist/server/app-page-stream.js.map +1 -1
  121. package/dist/server/app-post-middleware-context.d.ts +16 -0
  122. package/dist/server/app-post-middleware-context.js +28 -0
  123. package/dist/server/app-post-middleware-context.js.map +1 -0
  124. package/dist/server/app-prerender-endpoints.d.ts +19 -0
  125. package/dist/server/app-prerender-endpoints.js +96 -0
  126. package/dist/server/app-prerender-endpoints.js.map +1 -0
  127. package/dist/server/app-prerender-static-params.d.ts +16 -0
  128. package/dist/server/app-prerender-static-params.js +14 -0
  129. package/dist/server/app-prerender-static-params.js.map +1 -0
  130. package/dist/server/app-request-context.d.ts +22 -0
  131. package/dist/server/app-request-context.js +30 -0
  132. package/dist/server/app-request-context.js.map +1 -0
  133. package/dist/server/app-route-handler-cache.d.ts +4 -0
  134. package/dist/server/app-route-handler-cache.js +11 -3
  135. package/dist/server/app-route-handler-cache.js.map +1 -1
  136. package/dist/server/app-route-handler-dispatch.d.ts +43 -0
  137. package/dist/server/app-route-handler-dispatch.js +149 -0
  138. package/dist/server/app-route-handler-dispatch.js.map +1 -0
  139. package/dist/server/app-route-handler-execution.d.ts +8 -3
  140. package/dist/server/app-route-handler-execution.js +25 -4
  141. package/dist/server/app-route-handler-execution.js.map +1 -1
  142. package/dist/server/app-route-handler-response.d.ts +6 -3
  143. package/dist/server/app-route-handler-response.js +52 -11
  144. package/dist/server/app-route-handler-response.js.map +1 -1
  145. package/dist/server/app-route-handler-runtime.d.ts +4 -1
  146. package/dist/server/app-route-handler-runtime.js +107 -1
  147. package/dist/server/app-route-handler-runtime.js.map +1 -1
  148. package/dist/server/app-router-entry.js.map +1 -1
  149. package/dist/server/app-rsc-error-handler.d.ts +21 -0
  150. package/dist/server/app-rsc-error-handler.js +30 -0
  151. package/dist/server/app-rsc-error-handler.js.map +1 -0
  152. package/dist/server/app-rsc-errors.d.ts +27 -0
  153. package/dist/server/app-rsc-errors.js +42 -0
  154. package/dist/server/app-rsc-errors.js.map +1 -0
  155. package/dist/server/app-rsc-handler.d.ts +117 -0
  156. package/dist/server/app-rsc-handler.js +260 -0
  157. package/dist/server/app-rsc-handler.js.map +1 -0
  158. package/dist/server/app-rsc-request-normalization.d.ts +40 -0
  159. package/dist/server/app-rsc-request-normalization.js +63 -0
  160. package/dist/server/app-rsc-request-normalization.js.map +1 -0
  161. package/dist/server/app-rsc-response-finalizer.d.ts +30 -0
  162. package/dist/server/app-rsc-response-finalizer.js +38 -0
  163. package/dist/server/app-rsc-response-finalizer.js.map +1 -0
  164. package/dist/server/app-rsc-route-matching.d.ts +40 -0
  165. package/dist/server/app-rsc-route-matching.js +66 -0
  166. package/dist/server/app-rsc-route-matching.js.map +1 -0
  167. package/dist/server/app-segment-config.d.ts +33 -0
  168. package/dist/server/app-segment-config.js +86 -0
  169. package/dist/server/app-segment-config.js.map +1 -0
  170. package/dist/server/app-server-action-execution.d.ts +88 -1
  171. package/dist/server/app-server-action-execution.js +257 -5
  172. package/dist/server/app-server-action-execution.js.map +1 -1
  173. package/dist/server/app-ssr-entry.d.ts +7 -0
  174. package/dist/server/app-ssr-entry.js +30 -9
  175. package/dist/server/app-ssr-entry.js.map +1 -1
  176. package/dist/server/app-ssr-stream.d.ts +4 -2
  177. package/dist/server/app-ssr-stream.js +29 -2
  178. package/dist/server/app-ssr-stream.js.map +1 -1
  179. package/dist/server/app-static-generation.d.ts +15 -0
  180. package/dist/server/app-static-generation.js +20 -0
  181. package/dist/server/app-static-generation.js.map +1 -0
  182. package/dist/server/cache-control.d.ts +24 -0
  183. package/dist/server/cache-control.js +33 -0
  184. package/dist/server/cache-control.js.map +1 -0
  185. package/dist/server/dev-error-overlay-store.d.ts +23 -0
  186. package/dist/server/dev-error-overlay-store.js +67 -0
  187. package/dist/server/dev-error-overlay-store.js.map +1 -0
  188. package/dist/server/dev-error-overlay.d.ts +15 -0
  189. package/dist/server/dev-error-overlay.js +548 -0
  190. package/dist/server/dev-error-overlay.js.map +1 -0
  191. package/dist/server/dev-route-files.d.ts +7 -0
  192. package/dist/server/dev-route-files.js +73 -0
  193. package/dist/server/dev-route-files.js.map +1 -0
  194. package/dist/server/dev-server.js +4 -0
  195. package/dist/server/dev-server.js.map +1 -1
  196. package/dist/server/file-based-metadata.d.ts +17 -0
  197. package/dist/server/file-based-metadata.js +356 -0
  198. package/dist/server/file-based-metadata.js.map +1 -0
  199. package/dist/server/implicit-tags.d.ts +6 -0
  200. package/dist/server/implicit-tags.js +42 -0
  201. package/dist/server/implicit-tags.js.map +1 -0
  202. package/dist/server/instrumentation-runtime.d.ts +44 -0
  203. package/dist/server/instrumentation-runtime.js +29 -0
  204. package/dist/server/instrumentation-runtime.js.map +1 -0
  205. package/dist/server/instrumentation.js.map +1 -1
  206. package/dist/server/isr-cache.d.ts +16 -3
  207. package/dist/server/isr-cache.js +56 -8
  208. package/dist/server/isr-cache.js.map +1 -1
  209. package/dist/server/metadata-route-build-data.d.ts +25 -0
  210. package/dist/server/metadata-route-build-data.js +150 -0
  211. package/dist/server/metadata-route-build-data.js.map +1 -0
  212. package/dist/server/metadata-route-response.d.ts +17 -0
  213. package/dist/server/metadata-route-response.js +187 -0
  214. package/dist/server/metadata-route-response.js.map +1 -0
  215. package/dist/server/metadata-routes.d.ts +42 -4
  216. package/dist/server/metadata-routes.js +127 -11
  217. package/dist/server/metadata-routes.js.map +1 -1
  218. package/dist/server/middleware-matcher.d.ts +15 -0
  219. package/dist/server/middleware-matcher.js +102 -0
  220. package/dist/server/middleware-matcher.js.map +1 -0
  221. package/dist/server/middleware-request-headers.js +2 -1
  222. package/dist/server/middleware-request-headers.js.map +1 -1
  223. package/dist/server/middleware-runtime.d.ts +39 -0
  224. package/dist/server/middleware-runtime.js +159 -0
  225. package/dist/server/middleware-runtime.js.map +1 -0
  226. package/dist/server/middleware.d.ts +4 -36
  227. package/dist/server/middleware.js +18 -228
  228. package/dist/server/middleware.js.map +1 -1
  229. package/dist/server/pages-page-data.d.ts +7 -2
  230. package/dist/server/pages-page-data.js +10 -5
  231. package/dist/server/pages-page-data.js.map +1 -1
  232. package/dist/server/pages-page-response.d.ts +2 -1
  233. package/dist/server/pages-page-response.js +5 -3
  234. package/dist/server/pages-page-response.js.map +1 -1
  235. package/dist/server/prerender-work-unit-setup.d.ts +7 -0
  236. package/dist/server/prerender-work-unit-setup.js +30 -0
  237. package/dist/server/prerender-work-unit-setup.js.map +1 -0
  238. package/dist/server/prod-server.js +10 -14
  239. package/dist/server/prod-server.js.map +1 -1
  240. package/dist/server/request-pipeline.d.ts +46 -5
  241. package/dist/server/request-pipeline.js +84 -5
  242. package/dist/server/request-pipeline.js.map +1 -1
  243. package/dist/server/rsc-stream-hints.d.ts +7 -0
  244. package/dist/server/rsc-stream-hints.js +38 -0
  245. package/dist/server/rsc-stream-hints.js.map +1 -0
  246. package/dist/server/seed-cache.js +19 -8
  247. package/dist/server/seed-cache.js.map +1 -1
  248. package/dist/server/server-action-not-found.d.ts +9 -0
  249. package/dist/server/server-action-not-found.js +40 -0
  250. package/dist/server/server-action-not-found.js.map +1 -0
  251. package/dist/shims/cache-runtime.js +28 -11
  252. package/dist/shims/cache-runtime.js.map +1 -1
  253. package/dist/shims/cache.d.ts +39 -4
  254. package/dist/shims/cache.js +93 -16
  255. package/dist/shims/cache.js.map +1 -1
  256. package/dist/shims/error-boundary.d.ts +66 -5
  257. package/dist/shims/error-boundary.js +106 -4
  258. package/dist/shims/error-boundary.js.map +1 -1
  259. package/dist/shims/fetch-cache.d.ts +4 -1
  260. package/dist/shims/fetch-cache.js +55 -13
  261. package/dist/shims/fetch-cache.js.map +1 -1
  262. package/dist/shims/font-google-base.d.ts +5 -4
  263. package/dist/shims/font-google-base.js +61 -13
  264. package/dist/shims/font-google-base.js.map +1 -1
  265. package/dist/shims/headers.d.ts +14 -2
  266. package/dist/shims/headers.js +127 -17
  267. package/dist/shims/headers.js.map +1 -1
  268. package/dist/shims/image.js +116 -10
  269. package/dist/shims/image.js.map +1 -1
  270. package/dist/shims/internal/make-hanging-promise.d.ts +16 -0
  271. package/dist/shims/internal/make-hanging-promise.js +46 -0
  272. package/dist/shims/internal/make-hanging-promise.js.map +1 -0
  273. package/dist/shims/internal/work-unit-async-storage.d.ts +26 -3
  274. package/dist/shims/internal/work-unit-async-storage.js +6 -3
  275. package/dist/shims/internal/work-unit-async-storage.js.map +1 -1
  276. package/dist/shims/metadata.d.ts +38 -26
  277. package/dist/shims/metadata.js +75 -45
  278. package/dist/shims/metadata.js.map +1 -1
  279. package/dist/shims/navigation.d.ts +10 -1
  280. package/dist/shims/navigation.js +18 -1
  281. package/dist/shims/navigation.js.map +1 -1
  282. package/dist/shims/navigation.react-server.d.ts +2 -2
  283. package/dist/shims/navigation.react-server.js +2 -2
  284. package/dist/shims/navigation.react-server.js.map +1 -1
  285. package/dist/shims/offline.d.ts +5 -0
  286. package/dist/shims/offline.js +17 -0
  287. package/dist/shims/offline.js.map +1 -0
  288. package/dist/shims/request-state-types.d.ts +3 -2
  289. package/dist/shims/root-params.d.ts +11 -0
  290. package/dist/shims/root-params.js +24 -0
  291. package/dist/shims/root-params.js.map +1 -0
  292. package/dist/shims/router.js +1 -1
  293. package/dist/shims/server.d.ts +3 -1
  294. package/dist/shims/server.js +83 -5
  295. package/dist/shims/server.js.map +1 -1
  296. package/dist/shims/thenable-params.d.ts +5 -0
  297. package/dist/shims/thenable-params.js +37 -0
  298. package/dist/shims/thenable-params.js.map +1 -0
  299. package/dist/shims/unified-request-context.d.ts +3 -2
  300. package/dist/shims/unified-request-context.js +3 -0
  301. package/dist/shims/unified-request-context.js.map +1 -1
  302. package/dist/shims/use-merged-ref.d.ts +7 -0
  303. package/dist/shims/use-merged-ref.js +40 -0
  304. package/dist/shims/use-merged-ref.js.map +1 -0
  305. package/dist/utils/cache-control-metadata.d.ts +6 -0
  306. package/dist/utils/cache-control-metadata.js +16 -0
  307. package/dist/utils/cache-control-metadata.js.map +1 -0
  308. package/package.json +6 -1
  309. package/dist/server/middleware-codegen.d.ts +0 -54
  310. package/dist/server/middleware-codegen.js +0 -414
  311. package/dist/server/middleware-codegen.js.map +0 -1
@@ -1,9 +1,7 @@
1
- import { compareRoutes, decodeRouteSegment, normalizePathnameForRouteMatch } from "./utils.js";
2
- import { createValidFileMatcher, scanWithExtensions } from "./file-matcher.js";
3
- import { validateRoutePatterns } from "./route-validation.js";
1
+ import { normalizePathnameForRouteMatch } from "./utils.js";
2
+ import { createValidFileMatcher } from "./file-matcher.js";
4
3
  import { buildRouteTrie, trieMatch } from "./route-trie.js";
5
- import fs from "node:fs";
6
- import path from "node:path";
4
+ import { buildAppRouteGraph, computeRootParamNames } from "./app-route-graph.js";
7
5
  //#region src/routing/app-router.ts
8
6
  /**
9
7
  * App Router file-system routing.
@@ -28,13 +26,6 @@ function invalidateAppRouteCache() {
28
26
  cachedAppDir = null;
29
27
  cachedPageExtensionsKey = null;
30
28
  }
31
- function hasParallelSlotDirectory(dir) {
32
- try {
33
- return fs.readdirSync(dir, { withFileTypes: true }).some((entry) => entry.isDirectory() && entry.name.startsWith("@"));
34
- } catch {
35
- return false;
36
- }
37
- }
38
29
  /**
39
30
  * Scan the app/ directory and return a list of routes.
40
31
  */
@@ -42,612 +33,11 @@ async function appRouter(appDir, pageExtensions, matcher) {
42
33
  matcher ??= createValidFileMatcher(pageExtensions);
43
34
  const pageExtensionsKey = JSON.stringify(matcher.extensions);
44
35
  if (cachedRoutes && cachedAppDir === appDir && cachedPageExtensionsKey === pageExtensionsKey) return cachedRoutes;
45
- const routes = [];
46
- const excludeDir = (name) => name.startsWith("@") || name.startsWith("_");
47
- for await (const file of scanWithExtensions("**/page", appDir, matcher.extensions, excludeDir)) {
48
- const route = fileToAppRoute(file, appDir, "page", matcher);
49
- if (route) routes.push(route);
50
- }
51
- for await (const file of scanWithExtensions("**/route", appDir, matcher.extensions, excludeDir)) {
52
- const route = fileToAppRoute(file, appDir, "route", matcher);
53
- if (route) routes.push(route);
54
- }
55
- const routePatterns = new Set(routes.map((route) => route.pattern));
56
- for await (const file of scanWithExtensions("**/layout", appDir, matcher.extensions, excludeDir)) {
57
- const dir = path.dirname(file);
58
- const routeDir = dir === "." ? appDir : path.join(appDir, dir);
59
- if (!hasParallelSlotDirectory(routeDir)) continue;
60
- if (discoverParallelSlots(routeDir, appDir, matcher).length === 0) continue;
61
- const route = directoryToAppRoute(dir, appDir, matcher, null, null);
62
- if (!route || routePatterns.has(route.pattern)) continue;
63
- routes.push(route);
64
- routePatterns.add(route.pattern);
65
- }
66
- const slotSubRoutes = discoverSlotSubRoutes(routes, appDir, matcher);
67
- routes.push(...slotSubRoutes);
68
- validateRoutePatterns(routes.map((route) => route.pattern));
69
- validateRoutePatterns([...new Set(routes.flatMap((route) => route.parallelSlots.flatMap((slot) => slot.interceptingRoutes.map((intercept) => intercept.targetPattern))))]);
70
- routes.sort(compareRoutes);
71
- cachedRoutes = routes;
36
+ const graph = await buildAppRouteGraph(appDir, matcher);
37
+ cachedRoutes = graph.routes;
72
38
  cachedAppDir = appDir;
73
39
  cachedPageExtensionsKey = pageExtensionsKey;
74
- return routes;
75
- }
76
- /**
77
- * Discover sub-routes created by nested pages within parallel slots.
78
- *
79
- * In Next.js, pages nested inside @slot directories create additional URL routes.
80
- * For example, given:
81
- * app/parallel-routes/@audience/demographics/page.tsx
82
- * This creates a route at /parallel-routes/demographics where:
83
- * - children slot → parent's default.tsx
84
- * - @audience slot → @audience/demographics/page.tsx (matched)
85
- * - other slots → their default.tsx (fallback)
86
- */
87
- function discoverSlotSubRoutes(routes, _appDir, matcher) {
88
- const syntheticRoutes = [];
89
- const routesByPattern = new Map(routes.map((r) => [r.pattern, r]));
90
- const applySlotSubPages = (route, slotPages, rawSegments) => {
91
- route.parallelSlots = route.parallelSlots.map((slot) => {
92
- const subPage = slotPages.get(slot.key);
93
- if (subPage !== void 0) return {
94
- ...slot,
95
- pagePath: subPage,
96
- routeSegments: rawSegments
97
- };
98
- return slot;
99
- });
100
- };
101
- for (const parentRoute of routes) {
102
- if (parentRoute.parallelSlots.length === 0) continue;
103
- if (!parentRoute.pagePath) continue;
104
- const parentPageDir = path.dirname(parentRoute.pagePath);
105
- const subPathMap = /* @__PURE__ */ new Map();
106
- for (const slot of parentRoute.parallelSlots) {
107
- if (path.dirname(slot.ownerDir) !== parentPageDir) continue;
108
- const slotDir = slot.ownerDir;
109
- if (!fs.existsSync(slotDir)) continue;
110
- const subPages = findSlotSubPages(slotDir, matcher);
111
- for (const { relativePath, pagePath } of subPages) {
112
- const subSegments = relativePath.split(path.sep);
113
- const convertedSubRoute = convertSegmentsToRouteParts(subSegments);
114
- if (!convertedSubRoute) continue;
115
- const { urlSegments } = convertedSubRoute;
116
- const normalizedSubPath = urlSegments.join("/");
117
- let subPathEntry = subPathMap.get(normalizedSubPath);
118
- if (!subPathEntry) {
119
- subPathEntry = {
120
- rawSegments: subSegments,
121
- converted: convertedSubRoute,
122
- slotPages: /* @__PURE__ */ new Map()
123
- };
124
- subPathMap.set(normalizedSubPath, subPathEntry);
125
- }
126
- if (subPathEntry.slotPages.get(slot.key)) {
127
- const pattern = joinRoutePattern(parentRoute.pattern, normalizedSubPath);
128
- throw new Error(`You cannot have two routes that resolve to the same path ("${pattern}").`);
129
- }
130
- subPathEntry.slotPages.set(slot.key, pagePath);
131
- }
132
- }
133
- if (subPathMap.size === 0) continue;
134
- const childrenDefault = findFile(parentPageDir, "default", matcher);
135
- if (!childrenDefault) continue;
136
- for (const { rawSegments, converted: convertedSubRoute, slotPages } of subPathMap.values()) {
137
- const { urlSegments: urlParts, params: subParams, isDynamic: subIsDynamic } = convertedSubRoute;
138
- const subUrlPath = urlParts.join("/");
139
- const pattern = joinRoutePattern(parentRoute.pattern, subUrlPath);
140
- const existingRoute = routesByPattern.get(pattern);
141
- if (existingRoute) {
142
- if (existingRoute.routePath && !existingRoute.pagePath) throw new Error(`You cannot have two routes that resolve to the same path ("${pattern}").`);
143
- applySlotSubPages(existingRoute, slotPages, rawSegments);
144
- continue;
145
- }
146
- const subSlots = parentRoute.parallelSlots.map((slot) => {
147
- const subPage = slotPages.get(slot.key);
148
- return {
149
- ...slot,
150
- pagePath: subPage || null,
151
- routeSegments: subPage ? rawSegments : null
152
- };
153
- });
154
- const newRoute = {
155
- pattern,
156
- pagePath: childrenDefault,
157
- routePath: null,
158
- layouts: parentRoute.layouts,
159
- templates: parentRoute.templates,
160
- parallelSlots: subSlots,
161
- loadingPath: parentRoute.loadingPath,
162
- errorPath: parentRoute.errorPath,
163
- layoutErrorPaths: parentRoute.layoutErrorPaths,
164
- notFoundPath: parentRoute.notFoundPath,
165
- notFoundPaths: parentRoute.notFoundPaths,
166
- forbiddenPath: parentRoute.forbiddenPath,
167
- unauthorizedPath: parentRoute.unauthorizedPath,
168
- routeSegments: [...parentRoute.routeSegments, ...rawSegments],
169
- templateTreePositions: parentRoute.templateTreePositions,
170
- layoutTreePositions: parentRoute.layoutTreePositions,
171
- isDynamic: parentRoute.isDynamic || subIsDynamic,
172
- params: [...parentRoute.params, ...subParams],
173
- patternParts: [...parentRoute.patternParts, ...urlParts]
174
- };
175
- syntheticRoutes.push(newRoute);
176
- routesByPattern.set(pattern, newRoute);
177
- }
178
- }
179
- return syntheticRoutes;
180
- }
181
- /**
182
- * Find all page files in subdirectories of a parallel slot directory.
183
- * Returns relative paths (from the slot dir) and absolute page paths.
184
- * Skips the root page.tsx (already handled as the slot's main page)
185
- * and intercepting route directories.
186
- */
187
- function findSlotSubPages(slotDir, matcher) {
188
- const results = [];
189
- function scan(dir) {
190
- if (!fs.existsSync(dir)) return;
191
- const entries = fs.readdirSync(dir, { withFileTypes: true });
192
- for (const entry of entries) {
193
- if (!entry.isDirectory()) continue;
194
- if (matchInterceptConvention(entry.name)) continue;
195
- if (entry.name.startsWith("_")) continue;
196
- const subDir = path.join(dir, entry.name);
197
- const page = findFile(subDir, "page", matcher);
198
- if (page) {
199
- const relativePath = path.relative(slotDir, subDir);
200
- results.push({
201
- relativePath,
202
- pagePath: page
203
- });
204
- }
205
- scan(subDir);
206
- }
207
- }
208
- scan(slotDir);
209
- return results;
210
- }
211
- /**
212
- * Convert a file path relative to app/ into an AppRoute.
213
- */
214
- function fileToAppRoute(file, appDir, type, matcher) {
215
- return directoryToAppRoute(path.dirname(file), appDir, matcher, type === "page" ? path.join(appDir, file) : null, type === "route" ? path.join(appDir, file) : null);
216
- }
217
- function directoryToAppRoute(dir, appDir, matcher, pagePath, routePath) {
218
- const segments = dir === "." ? [] : dir.split(path.sep);
219
- const params = [];
220
- let isDynamic = false;
221
- const convertedRoute = convertSegmentsToRouteParts(segments);
222
- if (!convertedRoute) return null;
223
- const { urlSegments, params: routeParams, isDynamic: routeIsDynamic } = convertedRoute;
224
- params.push(...routeParams);
225
- isDynamic = routeIsDynamic;
226
- const pattern = "/" + urlSegments.join("/");
227
- const layouts = discoverLayouts(segments, appDir, matcher);
228
- const templates = discoverTemplates(segments, appDir, matcher);
229
- const templateTreePositions = computeLayoutTreePositions(appDir, templates);
230
- const layoutTreePositions = computeLayoutTreePositions(appDir, layouts);
231
- const layoutErrorPaths = discoverLayoutAlignedErrors(segments, appDir, matcher);
232
- const routeDir = dir === "." ? appDir : path.join(appDir, dir);
233
- const loadingPath = findFile(routeDir, "loading", matcher);
234
- const errorPath = findFile(routeDir, "error", matcher);
235
- const notFoundPath = discoverBoundaryFile(segments, appDir, "not-found", matcher);
236
- const forbiddenPath = discoverBoundaryFile(segments, appDir, "forbidden", matcher);
237
- const unauthorizedPath = discoverBoundaryFile(segments, appDir, "unauthorized", matcher);
238
- const notFoundPaths = discoverBoundaryFilePerLayout(layouts, "not-found", matcher);
239
- const parallelSlots = discoverInheritedParallelSlots(segments, appDir, routeDir, matcher);
240
- return {
241
- pattern: pattern === "/" ? "/" : pattern,
242
- pagePath,
243
- routePath,
244
- layouts,
245
- templates,
246
- parallelSlots,
247
- loadingPath,
248
- errorPath,
249
- layoutErrorPaths,
250
- notFoundPath,
251
- notFoundPaths,
252
- forbiddenPath,
253
- unauthorizedPath,
254
- routeSegments: segments,
255
- templateTreePositions,
256
- layoutTreePositions,
257
- isDynamic,
258
- params,
259
- patternParts: urlSegments
260
- };
261
- }
262
- /**
263
- * Compute the tree position (directory depth from app root) for each layout.
264
- * Root layout = 0, a layout at app/blog/ = 1, app/blog/(group)/ = 2.
265
- * Counts ALL directory levels including route groups and parallel slots.
266
- */
267
- function computeLayoutTreePositions(appDir, layouts) {
268
- return layouts.map((layoutPath) => {
269
- const layoutDir = path.dirname(layoutPath);
270
- if (layoutDir === appDir) return 0;
271
- return path.relative(appDir, layoutDir).split(path.sep).length;
272
- });
273
- }
274
- /**
275
- * Discover all layout files from root to the given directory.
276
- * Each level of the directory tree may have a layout.tsx.
277
- */
278
- function discoverLayouts(segments, appDir, matcher) {
279
- const layouts = [];
280
- const rootLayout = findFile(appDir, "layout", matcher);
281
- if (rootLayout) layouts.push(rootLayout);
282
- let currentDir = appDir;
283
- for (const segment of segments) {
284
- currentDir = path.join(currentDir, segment);
285
- const layout = findFile(currentDir, "layout", matcher);
286
- if (layout) layouts.push(layout);
287
- }
288
- return layouts;
289
- }
290
- /**
291
- * Discover all template files from root to the given directory.
292
- * Each level of the directory tree may have a template.tsx.
293
- * Templates are like layouts but re-mount on navigation.
294
- */
295
- function discoverTemplates(segments, appDir, matcher) {
296
- const templates = [];
297
- const rootTemplate = findFile(appDir, "template", matcher);
298
- if (rootTemplate) templates.push(rootTemplate);
299
- let currentDir = appDir;
300
- for (const segment of segments) {
301
- currentDir = path.join(currentDir, segment);
302
- const template = findFile(currentDir, "template", matcher);
303
- if (template) templates.push(template);
304
- }
305
- return templates;
306
- }
307
- /**
308
- * Discover error.tsx files aligned with the layouts array.
309
- * Walks the same directory levels as discoverLayouts and, for each level
310
- * that contributes a layout entry, checks whether error.tsx also exists.
311
- * Returns an array of the same length as discoverLayouts() would return,
312
- * with the error path (or null) at each corresponding layout level.
313
- *
314
- * This enables interleaving ErrorBoundary components with layouts in the
315
- * rendering tree, matching Next.js behavior where each segment independently
316
- * wraps its children with an error boundary.
317
- */
318
- function discoverLayoutAlignedErrors(segments, appDir, matcher) {
319
- const errors = [];
320
- if (findFile(appDir, "layout", matcher)) errors.push(findFile(appDir, "error", matcher));
321
- let currentDir = appDir;
322
- for (const segment of segments) {
323
- currentDir = path.join(currentDir, segment);
324
- if (findFile(currentDir, "layout", matcher)) errors.push(findFile(currentDir, "error", matcher));
325
- }
326
- return errors;
327
- }
328
- /**
329
- * Discover the nearest boundary file (not-found, forbidden, unauthorized)
330
- * by walking from the route's directory up to the app root.
331
- * Returns the first (closest) file found, or null.
332
- */
333
- function discoverBoundaryFile(segments, appDir, fileName, matcher) {
334
- const dirs = [];
335
- let dir = appDir;
336
- dirs.push(dir);
337
- for (const segment of segments) {
338
- dir = path.join(dir, segment);
339
- dirs.push(dir);
340
- }
341
- for (let i = dirs.length - 1; i >= 0; i--) {
342
- const f = findFile(dirs[i], fileName, matcher);
343
- if (f) return f;
344
- }
345
- return null;
346
- }
347
- /**
348
- * Discover boundary files (not-found, forbidden, unauthorized) at each layout directory.
349
- * Returns an array aligned with the layouts array, where each entry is the boundary
350
- * file at that layout's directory, or null if none exists there.
351
- *
352
- * This is used for per-layout error boundaries. In Next.js, each layout level
353
- * has its own boundary that wraps the layout's children. When notFound() is thrown
354
- * from a layout, it propagates up to the parent layout's boundary.
355
- */
356
- function discoverBoundaryFilePerLayout(layouts, fileName, matcher) {
357
- return layouts.map((layoutPath) => {
358
- return findFile(path.dirname(layoutPath), fileName, matcher);
359
- });
360
- }
361
- /**
362
- * Discover parallel slots inherited from ancestor directories.
363
- *
364
- * In Next.js, parallel slots belong to the layout that defines them. When a
365
- * child route is rendered, its parent layout's slots must still be present.
366
- * If the child doesn't have matching content in a slot, the slot's default.tsx
367
- * is rendered instead.
368
- *
369
- * Walk from appDir through each segment to the route's directory. At each level
370
- * that has @slot dirs, collect them. Slots at the route's own directory level
371
- * use page.tsx; slots at ancestor levels use default.tsx only.
372
- */
373
- function discoverInheritedParallelSlots(segments, appDir, routeDir, matcher) {
374
- const slotMap = /* @__PURE__ */ new Map();
375
- let currentDir = appDir;
376
- const dirsToCheck = [];
377
- let layoutIdx = findFile(appDir, "layout", matcher) ? 0 : -1;
378
- dirsToCheck.push({
379
- dir: appDir,
380
- layoutIdx
381
- });
382
- for (const segment of segments) {
383
- currentDir = path.join(currentDir, segment);
384
- if (findFile(currentDir, "layout", matcher)) layoutIdx++;
385
- dirsToCheck.push({
386
- dir: currentDir,
387
- layoutIdx
388
- });
389
- }
390
- const routeHasLayout = layoutIdx >= 0;
391
- for (const { dir, layoutIdx: lvlLayoutIdx } of dirsToCheck) {
392
- if (lvlLayoutIdx < 0 && routeHasLayout) continue;
393
- const isOwnDir = dir === routeDir;
394
- const slotLayoutIdx = Math.max(lvlLayoutIdx, 0);
395
- const slotsAtLevel = discoverParallelSlots(dir, appDir, matcher);
396
- for (const slot of slotsAtLevel) if (isOwnDir) {
397
- slot.layoutIndex = slotLayoutIdx;
398
- slotMap.set(slot.key, slot);
399
- } else {
400
- const inheritedSlot = {
401
- ...slot,
402
- pagePath: null,
403
- layoutIndex: slotLayoutIdx,
404
- routeSegments: null
405
- };
406
- slotMap.set(slot.key, inheritedSlot);
407
- }
408
- }
409
- return Array.from(slotMap.values());
410
- }
411
- /**
412
- * Discover parallel route slots (@team, @analytics, etc.) in a directory.
413
- * Returns a ParallelSlot for each @-prefixed subdirectory that has a page or default component.
414
- */
415
- function discoverParallelSlots(dir, appDir, matcher) {
416
- if (!fs.existsSync(dir)) return [];
417
- const entries = fs.readdirSync(dir, { withFileTypes: true });
418
- const slots = [];
419
- for (const entry of entries) {
420
- if (!entry.isDirectory() || !entry.name.startsWith("@")) continue;
421
- const slotName = entry.name.slice(1);
422
- const slotDir = path.join(dir, entry.name);
423
- const pagePath = findFile(slotDir, "page", matcher);
424
- const defaultPath = findFile(slotDir, "default", matcher);
425
- const interceptingRoutes = discoverInterceptingRoutes(slotDir, dir, appDir, matcher);
426
- if (!pagePath && !defaultPath && interceptingRoutes.length === 0) continue;
427
- slots.push({
428
- key: `${slotName}@${path.relative(appDir, slotDir).replace(/\\/g, "/")}`,
429
- name: slotName,
430
- ownerDir: slotDir,
431
- pagePath,
432
- defaultPath,
433
- layoutPath: findFile(slotDir, "layout", matcher),
434
- loadingPath: findFile(slotDir, "loading", matcher),
435
- errorPath: findFile(slotDir, "error", matcher),
436
- interceptingRoutes,
437
- layoutIndex: -1,
438
- routeSegments: pagePath ? [] : null
439
- });
440
- }
441
- return slots;
442
- }
443
- /**
444
- * The interception convention prefix patterns.
445
- * (.) — same level, (..) — one level up, (..)(..)" — two levels up, (...) — root
446
- */
447
- const INTERCEPT_PATTERNS = [
448
- {
449
- prefix: "(...)",
450
- convention: "..."
451
- },
452
- {
453
- prefix: "(..)(..)",
454
- convention: "../.."
455
- },
456
- {
457
- prefix: "(..)",
458
- convention: ".."
459
- },
460
- {
461
- prefix: "(.)",
462
- convention: "."
463
- }
464
- ];
465
- /**
466
- * Discover intercepting routes inside a parallel slot directory.
467
- *
468
- * Intercepting routes use conventions like (.)photo, (..)feed, (...), etc.
469
- * They intercept navigation to another route and render within the slot instead.
470
- *
471
- * @param slotDir - The parallel slot directory (e.g. app/feed/@modal)
472
- * @param routeDir - The directory of the route that owns this slot (e.g. app/feed)
473
- * @param appDir - The root app directory
474
- */
475
- function discoverInterceptingRoutes(slotDir, routeDir, appDir, matcher) {
476
- if (!fs.existsSync(slotDir)) return [];
477
- const results = [];
478
- scanForInterceptingPages(slotDir, routeDir, appDir, results, matcher);
479
- return results;
480
- }
481
- /**
482
- * Recursively scan a directory tree for page.tsx files that are inside
483
- * intercepting route directories.
484
- */
485
- function scanForInterceptingPages(currentDir, routeDir, appDir, results, matcher) {
486
- if (!fs.existsSync(currentDir)) return;
487
- const entries = fs.readdirSync(currentDir, { withFileTypes: true });
488
- for (const entry of entries) {
489
- if (!entry.isDirectory()) continue;
490
- if (entry.name.startsWith("_")) continue;
491
- const interceptMatch = matchInterceptConvention(entry.name);
492
- if (interceptMatch) {
493
- const restOfName = entry.name.slice(interceptMatch.prefix.length);
494
- const interceptDir = path.join(currentDir, entry.name);
495
- collectInterceptingPages(interceptDir, interceptDir, interceptMatch.convention, restOfName, routeDir, appDir, results, matcher);
496
- } else scanForInterceptingPages(path.join(currentDir, entry.name), routeDir, appDir, results, matcher);
497
- }
498
- }
499
- /**
500
- * Match a directory name against interception convention prefixes.
501
- */
502
- function matchInterceptConvention(name) {
503
- for (const pattern of INTERCEPT_PATTERNS) if (name.startsWith(pattern.prefix)) return pattern;
504
- return null;
505
- }
506
- /**
507
- * Collect page.tsx files inside an intercepting route directory tree
508
- * and compute their target URL patterns.
509
- */
510
- function collectInterceptingPages(currentDir, interceptRoot, convention, interceptSegment, routeDir, appDir, results, matcher, parentLayoutPaths = []) {
511
- const currentLayoutPath = findFile(currentDir, "layout", matcher);
512
- const layoutPaths = currentLayoutPath ? [...parentLayoutPaths, currentLayoutPath] : parentLayoutPaths;
513
- const page = findFile(currentDir, "page", matcher);
514
- if (page) {
515
- const targetPattern = computeInterceptTarget(convention, interceptSegment, currentDir, interceptRoot, routeDir, appDir);
516
- if (targetPattern) results.push({
517
- convention,
518
- layoutPaths: [...layoutPaths],
519
- targetPattern: targetPattern.pattern,
520
- pagePath: page,
521
- params: targetPattern.params
522
- });
523
- }
524
- if (!fs.existsSync(currentDir)) return;
525
- const entries = fs.readdirSync(currentDir, { withFileTypes: true });
526
- for (const entry of entries) {
527
- if (!entry.isDirectory()) continue;
528
- if (entry.name.startsWith("_")) continue;
529
- collectInterceptingPages(path.join(currentDir, entry.name), interceptRoot, convention, interceptSegment, routeDir, appDir, results, matcher, layoutPaths);
530
- }
531
- }
532
- /**
533
- * Check whether a path segment is invisible in the URL (route groups, parallel slots, ".").
534
- *
535
- * Used by computeInterceptTarget, convertSegmentsToRouteParts, and
536
- * hasRemainingVisibleSegments — keep this the single source of truth.
537
- */
538
- function isInvisibleSegment(segment) {
539
- if (segment === ".") return true;
540
- if (segment.startsWith("(") && segment.endsWith(")")) return true;
541
- if (segment.startsWith("@")) return true;
542
- return false;
543
- }
544
- /**
545
- * Compute the target URL pattern for an intercepting route.
546
- *
547
- * Interception conventions (..), (..)(..)" climb by *visible route segments*
548
- * (not filesystem directories). Route groups like (marketing) and parallel
549
- * slots like @modal are invisible and must be skipped when counting levels.
550
- *
551
- * - (.) same level: resolve relative to routeDir
552
- * - (..) one level up: climb 1 visible segment
553
- * - (..)(..) two levels up: climb 2 visible segments
554
- * - (...) root: resolve from appDir
555
- */
556
- function computeInterceptTarget(convention, interceptSegment, currentDir, interceptRoot, routeDir, appDir) {
557
- const routeSegments = path.relative(appDir, routeDir).split(path.sep).filter(Boolean);
558
- let baseParts;
559
- switch (convention) {
560
- case ".":
561
- baseParts = routeSegments;
562
- break;
563
- case "..":
564
- case "../..": {
565
- const levelsToClimb = convention === ".." ? 1 : 2;
566
- let climbed = 0;
567
- let cutIndex = routeSegments.length;
568
- while (cutIndex > 0 && climbed < levelsToClimb) {
569
- cutIndex--;
570
- if (!isInvisibleSegment(routeSegments[cutIndex])) climbed++;
571
- }
572
- baseParts = routeSegments.slice(0, cutIndex);
573
- break;
574
- }
575
- case "...":
576
- baseParts = [];
577
- break;
578
- default: return null;
579
- }
580
- const nestedParts = path.relative(interceptRoot, currentDir).split(path.sep).filter(Boolean);
581
- const convertedTarget = convertSegmentsToRouteParts([
582
- ...baseParts,
583
- interceptSegment,
584
- ...nestedParts
585
- ]);
586
- if (!convertedTarget) return null;
587
- const { urlSegments, params } = convertedTarget;
588
- const pattern = "/" + urlSegments.join("/");
589
- return {
590
- pattern: pattern === "/" ? "/" : pattern,
591
- params
592
- };
593
- }
594
- /**
595
- * Find a file by name (without extension) in a directory.
596
- * Checks configured pageExtensions.
597
- */
598
- function findFile(dir, name, matcher) {
599
- for (const ext of matcher.dottedExtensions) {
600
- const filePath = path.join(dir, name + ext);
601
- if (fs.existsSync(filePath)) return filePath;
602
- }
603
- return null;
604
- }
605
- /**
606
- * Convert filesystem path segments to URL route parts, skipping invisible segments
607
- * (route groups, @slots, ".") and converting dynamic segment syntax to Express-style
608
- * patterns (e.g. "[id]" → ":id", "[...slug]" → ":slug+").
609
- */
610
- function convertSegmentsToRouteParts(segments) {
611
- const urlSegments = [];
612
- const params = [];
613
- let isDynamic = false;
614
- for (let i = 0; i < segments.length; i++) {
615
- const segment = segments[i];
616
- if (isInvisibleSegment(segment)) continue;
617
- const catchAllMatch = segment.match(/^\[\.\.\.([\w-]+)\]$/);
618
- if (catchAllMatch) {
619
- if (hasRemainingVisibleSegments(segments, i + 1)) return null;
620
- isDynamic = true;
621
- params.push(catchAllMatch[1]);
622
- urlSegments.push(`:${catchAllMatch[1]}+`);
623
- continue;
624
- }
625
- const optionalCatchAllMatch = segment.match(/^\[\[\.\.\.([\w-]+)\]\]$/);
626
- if (optionalCatchAllMatch) {
627
- if (hasRemainingVisibleSegments(segments, i + 1)) return null;
628
- isDynamic = true;
629
- params.push(optionalCatchAllMatch[1]);
630
- urlSegments.push(`:${optionalCatchAllMatch[1]}*`);
631
- continue;
632
- }
633
- const dynamicMatch = segment.match(/^\[([\w-]+)\]$/);
634
- if (dynamicMatch) {
635
- isDynamic = true;
636
- params.push(dynamicMatch[1]);
637
- urlSegments.push(`:${dynamicMatch[1]}`);
638
- continue;
639
- }
640
- urlSegments.push(decodeRouteSegment(segment));
641
- }
642
- return {
643
- urlSegments,
644
- params,
645
- isDynamic
646
- };
647
- }
648
- function hasRemainingVisibleSegments(segments, startIndex) {
649
- for (let i = startIndex; i < segments.length; i++) if (!isInvisibleSegment(segments[i])) return true;
650
- return false;
40
+ return graph.routes;
651
41
  }
652
42
  const appTrieCache = /* @__PURE__ */ new WeakMap();
653
43
  function getOrBuildAppTrie(routes) {
@@ -658,10 +48,6 @@ function getOrBuildAppTrie(routes) {
658
48
  }
659
49
  return trie;
660
50
  }
661
- function joinRoutePattern(basePattern, subPath) {
662
- if (!subPath) return basePattern;
663
- return basePattern === "/" ? `/${subPath}` : `${basePattern}/${subPath}`;
664
- }
665
51
  /**
666
52
  * Match a URL against App Router routes.
667
53
  */
@@ -673,6 +59,6 @@ function matchAppRoute(url, routes) {
673
59
  return trieMatch(getOrBuildAppTrie(routes), urlParts);
674
60
  }
675
61
  //#endregion
676
- export { appRouter, invalidateAppRouteCache, matchAppRoute };
62
+ export { appRouter, computeRootParamNames, invalidateAppRouteCache, matchAppRoute };
677
63
 
678
64
  //# sourceMappingURL=app-router.js.map