vinext 0.0.30 → 0.0.31

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 (435) hide show
  1. package/README.md +12 -6
  2. package/dist/build/prerender.d.ts +188 -0
  3. package/dist/build/prerender.js +675 -0
  4. package/dist/build/prerender.js.map +1 -0
  5. package/dist/build/report.d.ts +45 -46
  6. package/dist/build/report.js +247 -276
  7. package/dist/build/report.js.map +1 -1
  8. package/dist/build/run-prerender.d.ts +62 -0
  9. package/dist/build/run-prerender.js +183 -0
  10. package/dist/build/run-prerender.js.map +1 -0
  11. package/dist/build/server-manifest.d.ts +19 -0
  12. package/dist/build/server-manifest.js +29 -0
  13. package/dist/build/server-manifest.js.map +1 -0
  14. package/dist/build/static-export.d.ts +51 -66
  15. package/dist/build/static-export.js +51 -545
  16. package/dist/build/static-export.js.map +1 -1
  17. package/dist/check.d.ts +26 -24
  18. package/dist/check.js +591 -571
  19. package/dist/check.js.map +1 -1
  20. package/dist/cli.d.ts +1 -15
  21. package/dist/cli.js +430 -491
  22. package/dist/cli.js.map +1 -1
  23. package/dist/client/entry.d.ts +1 -2
  24. package/dist/client/entry.js +49 -62
  25. package/dist/client/entry.js.map +1 -1
  26. package/dist/client/validate-module-path.d.ts +4 -1
  27. package/dist/client/validate-module-path.js +23 -28
  28. package/dist/client/validate-module-path.js.map +1 -1
  29. package/dist/client/vinext-next-data.d.ts +15 -20
  30. package/dist/client/vinext-next-data.js +0 -1
  31. package/dist/cloudflare/index.d.ts +3 -8
  32. package/dist/cloudflare/index.js +3 -8
  33. package/dist/cloudflare/kv-cache-handler.d.ts +95 -105
  34. package/dist/cloudflare/kv-cache-handler.js +354 -380
  35. package/dist/cloudflare/kv-cache-handler.js.map +1 -1
  36. package/dist/cloudflare/tpr.d.ts +36 -34
  37. package/dist/cloudflare/tpr.js +460 -603
  38. package/dist/cloudflare/tpr.js.map +1 -1
  39. package/dist/config/config-matchers.d.ts +31 -40
  40. package/dist/config/config-matchers.js +727 -936
  41. package/dist/config/config-matchers.js.map +1 -1
  42. package/dist/config/dotenv.d.ts +18 -11
  43. package/dist/config/dotenv.js +79 -84
  44. package/dist/config/dotenv.js.map +1 -1
  45. package/dist/config/next-config.d.ts +156 -146
  46. package/dist/config/next-config.js +374 -464
  47. package/dist/config/next-config.js.map +1 -1
  48. package/dist/deploy.d.ts +87 -96
  49. package/dist/deploy.js +490 -628
  50. package/dist/deploy.js.map +1 -1
  51. package/dist/entries/app-browser-entry.d.ts +4 -1
  52. package/dist/entries/app-browser-entry.js +12 -8
  53. package/dist/entries/app-browser-entry.js.map +1 -1
  54. package/dist/entries/app-rsc-entry.d.ts +33 -20
  55. package/dist/entries/app-rsc-entry.js +442 -211
  56. package/dist/entries/app-rsc-entry.js.map +1 -1
  57. package/dist/entries/app-ssr-entry.d.ts +9 -1
  58. package/dist/entries/app-ssr-entry.js +61 -28
  59. package/dist/entries/app-ssr-entry.js.map +1 -1
  60. package/dist/entries/pages-client-entry.d.ts +6 -2
  61. package/dist/entries/pages-client-entry.js +30 -33
  62. package/dist/entries/pages-client-entry.js.map +1 -1
  63. package/dist/entries/pages-entry-helpers.d.ts +5 -1
  64. package/dist/entries/pages-entry-helpers.js +17 -14
  65. package/dist/entries/pages-entry-helpers.js.map +1 -1
  66. package/dist/entries/pages-server-entry.d.ts +6 -2
  67. package/dist/entries/pages-server-entry.js +84 -113
  68. package/dist/entries/pages-server-entry.js.map +1 -1
  69. package/dist/index.d.ts +82 -62
  70. package/dist/index.js +2172 -3133
  71. package/dist/index.js.map +1 -1
  72. package/dist/init.d.ts +40 -37
  73. package/dist/init.js +201 -258
  74. package/dist/init.js.map +1 -1
  75. package/dist/plugins/async-hooks-stub.d.ts +7 -3
  76. package/dist/plugins/async-hooks-stub.js +39 -42
  77. package/dist/plugins/async-hooks-stub.js.map +1 -1
  78. package/dist/plugins/client-reference-dedup.d.ts +7 -3
  79. package/dist/plugins/client-reference-dedup.js +63 -88
  80. package/dist/plugins/client-reference-dedup.js.map +1 -1
  81. package/dist/routing/app-router.d.ts +100 -96
  82. package/dist/routing/app-router.js +560 -670
  83. package/dist/routing/app-router.js.map +1 -1
  84. package/dist/routing/file-matcher.d.ts +18 -15
  85. package/dist/routing/file-matcher.js +65 -65
  86. package/dist/routing/file-matcher.js.map +1 -1
  87. package/dist/routing/pages-router.d.ts +23 -24
  88. package/dist/routing/pages-router.js +147 -172
  89. package/dist/routing/pages-router.js.map +1 -1
  90. package/dist/routing/route-trie.d.ts +23 -20
  91. package/dist/routing/route-trie.js +131 -151
  92. package/dist/routing/route-trie.js.map +1 -1
  93. package/dist/routing/route-validation.d.ts +5 -2
  94. package/dist/routing/route-validation.js +98 -130
  95. package/dist/routing/route-validation.js.map +1 -1
  96. package/dist/routing/utils.d.ts +10 -7
  97. package/dist/routing/utils.js +75 -111
  98. package/dist/routing/utils.js.map +1 -1
  99. package/dist/server/api-handler.d.ts +8 -13
  100. package/dist/server/api-handler.js +161 -193
  101. package/dist/server/api-handler.js.map +1 -1
  102. package/dist/server/app-router-entry.d.ts +6 -16
  103. package/dist/server/app-router-entry.js +26 -54
  104. package/dist/server/app-router-entry.js.map +1 -1
  105. package/dist/server/dev-module-runner.d.ts +11 -64
  106. package/dist/server/dev-module-runner.js +89 -101
  107. package/dist/server/dev-module-runner.js.map +1 -1
  108. package/dist/server/dev-origin-check.d.ts +12 -10
  109. package/dist/server/dev-origin-check.js +98 -108
  110. package/dist/server/dev-origin-check.js.map +1 -1
  111. package/dist/server/dev-server.d.ts +17 -14
  112. package/dist/server/dev-server.js +542 -869
  113. package/dist/server/dev-server.js.map +1 -1
  114. package/dist/server/html.d.ts +4 -1
  115. package/dist/server/html.js +25 -26
  116. package/dist/server/html.js.map +1 -1
  117. package/dist/server/image-optimization.d.ts +31 -28
  118. package/dist/server/image-optimization.js +181 -210
  119. package/dist/server/image-optimization.js.map +1 -1
  120. package/dist/server/instrumentation.d.ts +25 -22
  121. package/dist/server/instrumentation.js +110 -122
  122. package/dist/server/instrumentation.js.map +1 -1
  123. package/dist/server/isr-cache.d.ts +16 -26
  124. package/dist/server/isr-cache.js +106 -128
  125. package/dist/server/isr-cache.js.map +1 -1
  126. package/dist/server/metadata-routes.d.ts +85 -88
  127. package/dist/server/metadata-routes.js +270 -317
  128. package/dist/server/metadata-routes.js.map +1 -1
  129. package/dist/server/middleware-codegen.d.ts +7 -4
  130. package/dist/server/middleware-codegen.js +61 -61
  131. package/dist/server/middleware-codegen.js.map +1 -1
  132. package/dist/server/middleware-request-headers.d.ts +8 -6
  133. package/dist/server/middleware-request-headers.js +47 -65
  134. package/dist/server/middleware-request-headers.js.map +1 -1
  135. package/dist/server/middleware.d.ts +31 -47
  136. package/dist/server/middleware.js +273 -404
  137. package/dist/server/middleware.js.map +1 -1
  138. package/dist/server/normalize-path.d.ts +4 -1
  139. package/dist/server/normalize-path.js +33 -47
  140. package/dist/server/normalize-path.js.map +1 -1
  141. package/dist/server/pages-i18n.d.ts +38 -30
  142. package/dist/server/pages-i18n.js +112 -139
  143. package/dist/server/pages-i18n.js.map +1 -1
  144. package/dist/server/prod-server.d.ts +19 -31
  145. package/dist/server/prod-server.js +714 -945
  146. package/dist/server/prod-server.js.map +1 -1
  147. package/dist/server/request-log.d.ts +18 -12
  148. package/dist/server/request-log.js +45 -52
  149. package/dist/server/request-log.js.map +1 -1
  150. package/dist/server/request-pipeline.d.ts +9 -17
  151. package/dist/server/request-pipeline.js +133 -184
  152. package/dist/server/request-pipeline.js.map +1 -1
  153. package/dist/server/worker-utils.d.ts +4 -1
  154. package/dist/server/worker-utils.js +31 -37
  155. package/dist/server/worker-utils.js.map +1 -1
  156. package/dist/shims/amp.d.ts +5 -2
  157. package/dist/shims/amp.js +19 -15
  158. package/dist/shims/amp.js.map +1 -1
  159. package/dist/shims/app.d.ts +8 -10
  160. package/dist/shims/app.js +0 -1
  161. package/dist/shims/cache-runtime.d.ts +20 -45
  162. package/dist/shims/cache-runtime.js +271 -422
  163. package/dist/shims/cache-runtime.js.map +1 -1
  164. package/dist/shims/cache.d.ts +130 -121
  165. package/dist/shims/cache.js +339 -427
  166. package/dist/shims/cache.js.map +1 -1
  167. package/dist/shims/client-only.d.ts +1 -18
  168. package/dist/shims/client-only.js +0 -17
  169. package/dist/shims/compat-router.d.ts +4 -1
  170. package/dist/shims/compat-router.js +23 -19
  171. package/dist/shims/compat-router.js.map +1 -1
  172. package/dist/shims/config.d.ts +7 -5
  173. package/dist/shims/config.js +16 -23
  174. package/dist/shims/config.js.map +1 -1
  175. package/dist/shims/constants.d.ts +119 -118
  176. package/dist/shims/constants.js +159 -164
  177. package/dist/shims/constants.js.map +1 -1
  178. package/dist/shims/document.d.ts +20 -16
  179. package/dist/shims/document.js +41 -22
  180. package/dist/shims/document.js.map +1 -1
  181. package/dist/shims/dynamic.d.ts +13 -22
  182. package/dist/shims/dynamic.js +122 -136
  183. package/dist/shims/dynamic.js.map +1 -1
  184. package/dist/shims/error-boundary.d.ts +22 -15
  185. package/dist/shims/error-boundary.js +81 -79
  186. package/dist/shims/error-boundary.js.map +1 -1
  187. package/dist/shims/error.d.ts +11 -12
  188. package/dist/shims/error.js +35 -39
  189. package/dist/shims/error.js.map +1 -1
  190. package/dist/shims/fetch-cache.d.ts +16 -14
  191. package/dist/shims/fetch-cache.js +437 -645
  192. package/dist/shims/fetch-cache.js.map +1 -1
  193. package/dist/shims/font-google-base.d.ts +28 -26
  194. package/dist/shims/font-google-base.js +238 -325
  195. package/dist/shims/font-google-base.js.map +1 -1
  196. package/dist/shims/font-google.d.ts +3 -3
  197. package/dist/shims/font-google.generated.d.ts +1928 -1924
  198. package/dist/shims/font-google.generated.js +1928 -2133
  199. package/dist/shims/font-google.generated.js.map +1 -1
  200. package/dist/shims/font-google.js +3 -3
  201. package/dist/shims/font-local.d.ts +28 -26
  202. package/dist/shims/font-local.js +204 -260
  203. package/dist/shims/font-local.js.map +1 -1
  204. package/dist/shims/form.d.ts +13 -27
  205. package/dist/shims/form.js +128 -180
  206. package/dist/shims/form.js.map +1 -1
  207. package/dist/shims/head-state.d.ts +8 -13
  208. package/dist/shims/head-state.js +25 -42
  209. package/dist/shims/head-state.js.map +1 -1
  210. package/dist/shims/head.d.ts +16 -20
  211. package/dist/shims/head.js +172 -250
  212. package/dist/shims/head.js.map +1 -1
  213. package/dist/shims/headers.d.ts +84 -78
  214. package/dist/shims/headers.js +447 -575
  215. package/dist/shims/headers.js.map +1 -1
  216. package/dist/shims/i18n-context.d.ts +16 -20
  217. package/dist/shims/i18n-context.js +35 -48
  218. package/dist/shims/i18n-context.js.map +1 -1
  219. package/dist/shims/i18n-state.d.ts +8 -14
  220. package/dist/shims/i18n-state.js +34 -42
  221. package/dist/shims/i18n-state.js.map +1 -1
  222. package/dist/shims/image-config.d.ts +11 -8
  223. package/dist/shims/image-config.js +50 -83
  224. package/dist/shims/image-config.js.map +1 -1
  225. package/dist/shims/image.d.ts +37 -46
  226. package/dist/shims/image.js +283 -308
  227. package/dist/shims/image.js.map +1 -1
  228. package/dist/shims/internal/api-utils.d.ts +7 -4
  229. package/dist/shims/internal/api-utils.js +0 -6
  230. package/dist/shims/internal/app-router-context.d.ts +22 -17
  231. package/dist/shims/internal/app-router-context.js +17 -13
  232. package/dist/shims/internal/app-router-context.js.map +1 -1
  233. package/dist/shims/internal/cookies.d.ts +2 -9
  234. package/dist/shims/internal/cookies.js +2 -9
  235. package/dist/shims/internal/parse-cookie-header.d.ts +4 -1
  236. package/dist/shims/internal/parse-cookie-header.js +29 -29
  237. package/dist/shims/internal/parse-cookie-header.js.map +1 -1
  238. package/dist/shims/internal/router-context.d.ts +6 -1
  239. package/dist/shims/internal/router-context.js +11 -7
  240. package/dist/shims/internal/router-context.js.map +1 -1
  241. package/dist/shims/internal/utils.d.ts +40 -37
  242. package/dist/shims/internal/utils.js +24 -30
  243. package/dist/shims/internal/utils.js.map +1 -1
  244. package/dist/shims/internal/work-unit-async-storage.d.ts +6 -10
  245. package/dist/shims/internal/work-unit-async-storage.js +14 -11
  246. package/dist/shims/internal/work-unit-async-storage.js.map +1 -1
  247. package/dist/shims/layout-segment-context.d.ts +11 -14
  248. package/dist/shims/layout-segment-context.js +24 -23
  249. package/dist/shims/layout-segment-context.js.map +1 -1
  250. package/dist/shims/legacy-image.d.ts +39 -46
  251. package/dist/shims/legacy-image.js +47 -42
  252. package/dist/shims/legacy-image.js.map +1 -1
  253. package/dist/shims/link.d.ts +32 -36
  254. package/dist/shims/link.js +255 -391
  255. package/dist/shims/link.js.map +1 -1
  256. package/dist/shims/metadata.d.ts +210 -202
  257. package/dist/shims/metadata.js +545 -546
  258. package/dist/shims/metadata.js.map +1 -1
  259. package/dist/shims/navigation-state.d.ts +10 -18
  260. package/dist/shims/navigation-state.js +66 -74
  261. package/dist/shims/navigation-state.js.map +1 -1
  262. package/dist/shims/navigation.d.ts +59 -63
  263. package/dist/shims/navigation.js +505 -704
  264. package/dist/shims/navigation.js.map +1 -1
  265. package/dist/shims/og.d.ts +2 -20
  266. package/dist/shims/og.js +2 -19
  267. package/dist/shims/readonly-url-search-params.d.ts +8 -5
  268. package/dist/shims/readonly-url-search-params.js +26 -22
  269. package/dist/shims/readonly-url-search-params.js.map +1 -1
  270. package/dist/shims/request-context.d.ts +8 -5
  271. package/dist/shims/request-context.js +50 -60
  272. package/dist/shims/request-context.js.map +1 -1
  273. package/dist/shims/request-state-types.d.ts +11 -11
  274. package/dist/shims/request-state-types.js +0 -1
  275. package/dist/shims/router-state.d.ts +13 -10
  276. package/dist/shims/router-state.js +34 -43
  277. package/dist/shims/router-state.js.map +1 -1
  278. package/dist/shims/router.d.ts +81 -85
  279. package/dist/shims/router.js +506 -628
  280. package/dist/shims/router.js.map +1 -1
  281. package/dist/shims/script.d.ts +39 -48
  282. package/dist/shims/script.js +107 -160
  283. package/dist/shims/script.js.map +1 -1
  284. package/dist/shims/server-only.d.ts +1 -19
  285. package/dist/shims/server-only.js +0 -18
  286. package/dist/shims/server.d.ts +175 -164
  287. package/dist/shims/server.js +462 -478
  288. package/dist/shims/server.js.map +1 -1
  289. package/dist/shims/unified-request-context.d.ts +20 -20
  290. package/dist/shims/unified-request-context.js +81 -99
  291. package/dist/shims/unified-request-context.js.map +1 -1
  292. package/dist/shims/url-safety.d.ts +4 -1
  293. package/dist/shims/url-safety.js +15 -11
  294. package/dist/shims/url-safety.js.map +1 -1
  295. package/dist/shims/url-utils.d.ts +8 -5
  296. package/dist/shims/url-utils.js +62 -93
  297. package/dist/shims/url-utils.js.map +1 -1
  298. package/dist/shims/web-vitals.d.ts +10 -8
  299. package/dist/shims/web-vitals.js +9 -15
  300. package/dist/shims/web-vitals.js.map +1 -1
  301. package/dist/utils/base-path.d.ts +5 -2
  302. package/dist/utils/base-path.js +21 -19
  303. package/dist/utils/base-path.js.map +1 -1
  304. package/dist/utils/domain-locale.d.ts +17 -9
  305. package/dist/utils/domain-locale.js +36 -56
  306. package/dist/utils/domain-locale.js.map +1 -1
  307. package/dist/utils/hash.d.ts +4 -1
  308. package/dist/utils/hash.js +19 -17
  309. package/dist/utils/hash.js.map +1 -1
  310. package/dist/utils/manifest-paths.d.ts +6 -3
  311. package/dist/utils/manifest-paths.js +15 -16
  312. package/dist/utils/manifest-paths.js.map +1 -1
  313. package/dist/utils/project.d.ts +13 -11
  314. package/dist/utils/project.js +169 -216
  315. package/dist/utils/project.js.map +1 -1
  316. package/dist/utils/query.d.ts +8 -6
  317. package/dist/utils/query.js +57 -67
  318. package/dist/utils/query.js.map +1 -1
  319. package/package.json +10 -9
  320. package/dist/build/report.d.ts.map +0 -1
  321. package/dist/build/static-export.d.ts.map +0 -1
  322. package/dist/check.d.ts.map +0 -1
  323. package/dist/cli.d.ts.map +0 -1
  324. package/dist/client/entry.d.ts.map +0 -1
  325. package/dist/client/validate-module-path.d.ts.map +0 -1
  326. package/dist/client/vinext-next-data.d.ts.map +0 -1
  327. package/dist/client/vinext-next-data.js.map +0 -1
  328. package/dist/cloudflare/index.d.ts.map +0 -1
  329. package/dist/cloudflare/index.js.map +0 -1
  330. package/dist/cloudflare/kv-cache-handler.d.ts.map +0 -1
  331. package/dist/cloudflare/tpr.d.ts.map +0 -1
  332. package/dist/config/config-matchers.d.ts.map +0 -1
  333. package/dist/config/dotenv.d.ts.map +0 -1
  334. package/dist/config/next-config.d.ts.map +0 -1
  335. package/dist/deploy.d.ts.map +0 -1
  336. package/dist/entries/app-browser-entry.d.ts.map +0 -1
  337. package/dist/entries/app-rsc-entry.d.ts.map +0 -1
  338. package/dist/entries/app-ssr-entry.d.ts.map +0 -1
  339. package/dist/entries/pages-client-entry.d.ts.map +0 -1
  340. package/dist/entries/pages-entry-helpers.d.ts.map +0 -1
  341. package/dist/entries/pages-server-entry.d.ts.map +0 -1
  342. package/dist/index.d.ts.map +0 -1
  343. package/dist/init.d.ts.map +0 -1
  344. package/dist/plugins/async-hooks-stub.d.ts.map +0 -1
  345. package/dist/plugins/client-reference-dedup.d.ts.map +0 -1
  346. package/dist/routing/app-router.d.ts.map +0 -1
  347. package/dist/routing/file-matcher.d.ts.map +0 -1
  348. package/dist/routing/pages-router.d.ts.map +0 -1
  349. package/dist/routing/route-trie.d.ts.map +0 -1
  350. package/dist/routing/route-validation.d.ts.map +0 -1
  351. package/dist/routing/utils.d.ts.map +0 -1
  352. package/dist/server/api-handler.d.ts.map +0 -1
  353. package/dist/server/app-router-entry.d.ts.map +0 -1
  354. package/dist/server/dev-module-runner.d.ts.map +0 -1
  355. package/dist/server/dev-origin-check.d.ts.map +0 -1
  356. package/dist/server/dev-server.d.ts.map +0 -1
  357. package/dist/server/html.d.ts.map +0 -1
  358. package/dist/server/image-optimization.d.ts.map +0 -1
  359. package/dist/server/instrumentation.d.ts.map +0 -1
  360. package/dist/server/isr-cache.d.ts.map +0 -1
  361. package/dist/server/metadata-routes.d.ts.map +0 -1
  362. package/dist/server/middleware-codegen.d.ts.map +0 -1
  363. package/dist/server/middleware-request-headers.d.ts.map +0 -1
  364. package/dist/server/middleware.d.ts.map +0 -1
  365. package/dist/server/normalize-path.d.ts.map +0 -1
  366. package/dist/server/pages-i18n.d.ts.map +0 -1
  367. package/dist/server/prod-server.d.ts.map +0 -1
  368. package/dist/server/request-log.d.ts.map +0 -1
  369. package/dist/server/request-pipeline.d.ts.map +0 -1
  370. package/dist/server/worker-utils.d.ts.map +0 -1
  371. package/dist/shims/amp.d.ts.map +0 -1
  372. package/dist/shims/app.d.ts.map +0 -1
  373. package/dist/shims/app.js.map +0 -1
  374. package/dist/shims/cache-runtime.d.ts.map +0 -1
  375. package/dist/shims/cache.d.ts.map +0 -1
  376. package/dist/shims/client-only.d.ts.map +0 -1
  377. package/dist/shims/client-only.js.map +0 -1
  378. package/dist/shims/compat-router.d.ts.map +0 -1
  379. package/dist/shims/config.d.ts.map +0 -1
  380. package/dist/shims/constants.d.ts.map +0 -1
  381. package/dist/shims/document.d.ts.map +0 -1
  382. package/dist/shims/dynamic.d.ts.map +0 -1
  383. package/dist/shims/error-boundary.d.ts.map +0 -1
  384. package/dist/shims/error.d.ts.map +0 -1
  385. package/dist/shims/fetch-cache.d.ts.map +0 -1
  386. package/dist/shims/font-google-base.d.ts.map +0 -1
  387. package/dist/shims/font-google.d.ts.map +0 -1
  388. package/dist/shims/font-google.generated.d.ts.map +0 -1
  389. package/dist/shims/font-google.js.map +0 -1
  390. package/dist/shims/font-local.d.ts.map +0 -1
  391. package/dist/shims/form.d.ts.map +0 -1
  392. package/dist/shims/head-state.d.ts.map +0 -1
  393. package/dist/shims/head.d.ts.map +0 -1
  394. package/dist/shims/headers.d.ts.map +0 -1
  395. package/dist/shims/i18n-context.d.ts.map +0 -1
  396. package/dist/shims/i18n-state.d.ts.map +0 -1
  397. package/dist/shims/image-config.d.ts.map +0 -1
  398. package/dist/shims/image.d.ts.map +0 -1
  399. package/dist/shims/internal/api-utils.d.ts.map +0 -1
  400. package/dist/shims/internal/api-utils.js.map +0 -1
  401. package/dist/shims/internal/app-router-context.d.ts.map +0 -1
  402. package/dist/shims/internal/cookies.d.ts.map +0 -1
  403. package/dist/shims/internal/cookies.js.map +0 -1
  404. package/dist/shims/internal/parse-cookie-header.d.ts.map +0 -1
  405. package/dist/shims/internal/router-context.d.ts.map +0 -1
  406. package/dist/shims/internal/utils.d.ts.map +0 -1
  407. package/dist/shims/internal/work-unit-async-storage.d.ts.map +0 -1
  408. package/dist/shims/layout-segment-context.d.ts.map +0 -1
  409. package/dist/shims/legacy-image.d.ts.map +0 -1
  410. package/dist/shims/link.d.ts.map +0 -1
  411. package/dist/shims/metadata.d.ts.map +0 -1
  412. package/dist/shims/navigation-state.d.ts.map +0 -1
  413. package/dist/shims/navigation.d.ts.map +0 -1
  414. package/dist/shims/og.d.ts.map +0 -1
  415. package/dist/shims/og.js.map +0 -1
  416. package/dist/shims/readonly-url-search-params.d.ts.map +0 -1
  417. package/dist/shims/request-context.d.ts.map +0 -1
  418. package/dist/shims/request-state-types.d.ts.map +0 -1
  419. package/dist/shims/request-state-types.js.map +0 -1
  420. package/dist/shims/router-state.d.ts.map +0 -1
  421. package/dist/shims/router.d.ts.map +0 -1
  422. package/dist/shims/script.d.ts.map +0 -1
  423. package/dist/shims/server-only.d.ts.map +0 -1
  424. package/dist/shims/server-only.js.map +0 -1
  425. package/dist/shims/server.d.ts.map +0 -1
  426. package/dist/shims/unified-request-context.d.ts.map +0 -1
  427. package/dist/shims/url-safety.d.ts.map +0 -1
  428. package/dist/shims/url-utils.d.ts.map +0 -1
  429. package/dist/shims/web-vitals.d.ts.map +0 -1
  430. package/dist/utils/base-path.d.ts.map +0 -1
  431. package/dist/utils/domain-locale.d.ts.map +0 -1
  432. package/dist/utils/hash.d.ts.map +0 -1
  433. package/dist/utils/manifest-paths.d.ts.map +0 -1
  434. package/dist/utils/project.d.ts.map +0 -1
  435. package/dist/utils/query.d.ts.map +0 -1
@@ -1,748 +1,638 @@
1
- /**
2
- * App Router file-system routing.
3
- *
4
- * Scans the app/ directory following Next.js App Router conventions:
5
- * - app/page.tsx -> /
6
- * - app/about/page.tsx -> /about
7
- * - app/blog/[slug]/page.tsx -> /blog/:slug
8
- * - app/[...catchAll]/page.tsx -> /:catchAll+
9
- * - app/route.ts -> / (API route)
10
- * - app/(group)/page.tsx -> / (route groups are transparent)
11
- * - Layouts: app/layout.tsx wraps all children
12
- * - Loading: app/loading.tsx -> Suspense fallback
13
- * - Error: app/error.tsx -> ErrorBoundary
14
- * - Not Found: app/not-found.tsx
15
- */
16
- import path from "node:path";
17
- import fs from "node:fs";
18
1
  import { compareRoutes, decodeRouteSegment, normalizePathnameForRouteMatch } from "./utils.js";
19
- import { createValidFileMatcher, scanWithExtensions, } from "./file-matcher.js";
2
+ import { createValidFileMatcher, scanWithExtensions } from "./file-matcher.js";
20
3
  import { validateRoutePatterns } from "./route-validation.js";
21
4
  import { buildRouteTrie, trieMatch } from "./route-trie.js";
22
- // Cache for app routes
5
+ import fs from "node:fs";
6
+ import path from "node:path";
7
+ //#region src/routing/app-router.ts
8
+ /**
9
+ * App Router file-system routing.
10
+ *
11
+ * Scans the app/ directory following Next.js App Router conventions:
12
+ * - app/page.tsx -> /
13
+ * - app/about/page.tsx -> /about
14
+ * - app/blog/[slug]/page.tsx -> /blog/:slug
15
+ * - app/[...catchAll]/page.tsx -> /:catchAll+
16
+ * - app/route.ts -> / (API route)
17
+ * - app/(group)/page.tsx -> / (route groups are transparent)
18
+ * - Layouts: app/layout.tsx wraps all children
19
+ * - Loading: app/loading.tsx -> Suspense fallback
20
+ * - Error: app/error.tsx -> ErrorBoundary
21
+ * - Not Found: app/not-found.tsx
22
+ */
23
23
  let cachedRoutes = null;
24
24
  let cachedAppDir = null;
25
25
  let cachedPageExtensionsKey = null;
26
- export function invalidateAppRouteCache() {
27
- cachedRoutes = null;
28
- cachedAppDir = null;
29
- cachedPageExtensionsKey = null;
26
+ function invalidateAppRouteCache() {
27
+ cachedRoutes = null;
28
+ cachedAppDir = null;
29
+ cachedPageExtensionsKey = null;
30
30
  }
31
31
  /**
32
- * Scan the app/ directory and return a list of routes.
33
- */
34
- export async function appRouter(appDir, pageExtensions, matcher) {
35
- matcher ??= createValidFileMatcher(pageExtensions);
36
- const pageExtensionsKey = JSON.stringify(matcher.extensions);
37
- if (cachedRoutes && cachedAppDir === appDir && cachedPageExtensionsKey === pageExtensionsKey) {
38
- return cachedRoutes;
39
- }
40
- // Find all page.tsx and route.ts files, excluding @slot directories
41
- // (slot pages are not standalone routes — they're rendered as props of their parent layout)
42
- // and _private folders (Next.js convention for colocated non-route files).
43
- const routes = [];
44
- const excludeDir = (name) => name.startsWith("@") || name.startsWith("_");
45
- // Process page files in a single pass
46
- // Use function form of exclude for Node < 22.14 compatibility (string arrays require >= 22.14)
47
- for await (const file of scanWithExtensions("**/page", appDir, matcher.extensions, excludeDir)) {
48
- const route = fileToAppRoute(file, appDir, "page", matcher);
49
- if (route)
50
- routes.push(route);
51
- }
52
- // Process route handler files (API routes) in a single pass
53
- for await (const file of scanWithExtensions("**/route", appDir, matcher.extensions, excludeDir)) {
54
- const route = fileToAppRoute(file, appDir, "route", matcher);
55
- if (route)
56
- routes.push(route);
57
- }
58
- // Discover sub-routes created by nested pages within parallel slots.
59
- // In Next.js, pages nested inside @slot directories create additional URL routes.
60
- // For example, @audience/demographics/page.tsx at app/parallel-routes/ creates
61
- // a route at /parallel-routes/demographics.
62
- const slotSubRoutes = discoverSlotSubRoutes(routes, appDir, matcher);
63
- routes.push(...slotSubRoutes);
64
- validateRoutePatterns(routes.map((route) => route.pattern));
65
- validateRoutePatterns(routes.flatMap((route) => route.parallelSlots.flatMap((slot) => slot.interceptingRoutes.map((intercept) => intercept.targetPattern))));
66
- // Sort: static routes first, then dynamic, then catch-all
67
- routes.sort(compareRoutes);
68
- cachedRoutes = routes;
69
- cachedAppDir = appDir;
70
- cachedPageExtensionsKey = pageExtensionsKey;
71
- return routes;
32
+ * Scan the app/ directory and return a list of routes.
33
+ */
34
+ async function appRouter(appDir, pageExtensions, matcher) {
35
+ matcher ??= createValidFileMatcher(pageExtensions);
36
+ const pageExtensionsKey = JSON.stringify(matcher.extensions);
37
+ if (cachedRoutes && cachedAppDir === appDir && cachedPageExtensionsKey === pageExtensionsKey) return cachedRoutes;
38
+ const routes = [];
39
+ const excludeDir = (name) => name.startsWith("@") || name.startsWith("_");
40
+ for await (const file of scanWithExtensions("**/page", appDir, matcher.extensions, excludeDir)) {
41
+ const route = fileToAppRoute(file, appDir, "page", matcher);
42
+ if (route) routes.push(route);
43
+ }
44
+ for await (const file of scanWithExtensions("**/route", appDir, matcher.extensions, excludeDir)) {
45
+ const route = fileToAppRoute(file, appDir, "route", matcher);
46
+ if (route) routes.push(route);
47
+ }
48
+ const slotSubRoutes = discoverSlotSubRoutes(routes, appDir, matcher);
49
+ routes.push(...slotSubRoutes);
50
+ validateRoutePatterns(routes.map((route) => route.pattern));
51
+ validateRoutePatterns(routes.flatMap((route) => route.parallelSlots.flatMap((slot) => slot.interceptingRoutes.map((intercept) => intercept.targetPattern))));
52
+ routes.sort(compareRoutes);
53
+ cachedRoutes = routes;
54
+ cachedAppDir = appDir;
55
+ cachedPageExtensionsKey = pageExtensionsKey;
56
+ return routes;
72
57
  }
73
58
  /**
74
- * Discover sub-routes created by nested pages within parallel slots.
75
- *
76
- * In Next.js, pages nested inside @slot directories create additional URL routes.
77
- * For example, given:
78
- * app/parallel-routes/@audience/demographics/page.tsx
79
- * This creates a route at /parallel-routes/demographics where:
80
- * - children slot → parent's default.tsx
81
- * - @audience slot → @audience/demographics/page.tsx (matched)
82
- * - other slots → their default.tsx (fallback)
83
- */
59
+ * Discover sub-routes created by nested pages within parallel slots.
60
+ *
61
+ * In Next.js, pages nested inside @slot directories create additional URL routes.
62
+ * For example, given:
63
+ * app/parallel-routes/@audience/demographics/page.tsx
64
+ * This creates a route at /parallel-routes/demographics where:
65
+ * - children slot → parent's default.tsx
66
+ * - @audience slot → @audience/demographics/page.tsx (matched)
67
+ * - other slots → their default.tsx (fallback)
68
+ */
84
69
  function discoverSlotSubRoutes(routes, _appDir, matcher) {
85
- const syntheticRoutes = [];
86
- // O(1) lookup for existing routes by pattern — avoids O(n) routes.find() per sub-path per parent.
87
- // Updated as new synthetic routes are pushed so that later parents can see earlier synthetic entries.
88
- const routesByPattern = new Map(routes.map((r) => [r.pattern, r]));
89
- const slotKey = (slotName, ownerDir) => `${slotName}\u0000${ownerDir}`;
90
- const applySlotSubPages = (route, slotPages) => {
91
- route.parallelSlots = route.parallelSlots.map((slot) => ({
92
- ...slot,
93
- pagePath: slotPages.get(slotKey(slot.name, slot.ownerDir)) ?? slot.pagePath,
94
- }));
95
- };
96
- for (const parentRoute of routes) {
97
- if (parentRoute.parallelSlots.length === 0)
98
- continue;
99
- if (!parentRoute.pagePath)
100
- continue;
101
- const parentPageDir = path.dirname(parentRoute.pagePath);
102
- // Collect sub-paths from all slots.
103
- // Map: normalized visible sub-path -> slot pages, raw filesystem segments (for routeSegments),
104
- // and the pre-computed convertedSubRoute (to avoid a redundant re-conversion in the merge loop).
105
- const subPathMap = new Map();
106
- for (const slot of parentRoute.parallelSlots) {
107
- const slotDir = path.join(parentPageDir, `@${slot.name}`);
108
- if (!fs.existsSync(slotDir))
109
- 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)
115
- continue;
116
- const { urlSegments } = convertedSubRoute;
117
- const normalizedSubPath = urlSegments.join("/");
118
- let subPathEntry = subPathMap.get(normalizedSubPath);
119
- if (!subPathEntry) {
120
- subPathEntry = {
121
- rawSegments: subSegments,
122
- converted: convertedSubRoute,
123
- slotPages: new Map(),
124
- };
125
- subPathMap.set(normalizedSubPath, subPathEntry);
126
- }
127
- const slotId = slotKey(slot.name, slot.ownerDir);
128
- const existingSlotPage = subPathEntry.slotPages.get(slotId);
129
- if (existingSlotPage) {
130
- const pattern = joinRoutePattern(parentRoute.pattern, normalizedSubPath);
131
- throw new Error(`You cannot have two routes that resolve to the same path ("${pattern}").`);
132
- }
133
- subPathEntry.slotPages.set(slotId, pagePath);
134
- }
135
- }
136
- if (subPathMap.size === 0)
137
- continue;
138
- // Find the default.tsx for the children slot at the parent directory
139
- const childrenDefault = findFile(parentPageDir, "default", matcher);
140
- if (!childrenDefault)
141
- continue;
142
- for (const { rawSegments, converted: convertedSubRoute, slotPages } of subPathMap.values()) {
143
- const { urlSegments: urlParts, params: subParams, isDynamic: subIsDynamic, } = convertedSubRoute;
144
- const subUrlPath = urlParts.join("/");
145
- const pattern = joinRoutePattern(parentRoute.pattern, subUrlPath);
146
- const existingRoute = routesByPattern.get(pattern);
147
- if (existingRoute) {
148
- if (existingRoute.routePath && !existingRoute.pagePath) {
149
- throw new Error(`You cannot have two routes that resolve to the same path ("${pattern}").`);
150
- }
151
- applySlotSubPages(existingRoute, slotPages);
152
- continue;
153
- }
154
- // Build parallel slots for this sub-route: matching slots get the sub-page,
155
- // non-matching slots get null pagePath (rendering falls back to defaultPath)
156
- const subSlots = parentRoute.parallelSlots.map((slot) => ({
157
- ...slot,
158
- pagePath: slotPages.get(slotKey(slot.name, slot.ownerDir)) || null,
159
- }));
160
- const newRoute = {
161
- pattern,
162
- pagePath: childrenDefault, // children slot uses parent's default.tsx as page
163
- routePath: null,
164
- layouts: parentRoute.layouts,
165
- templates: parentRoute.templates,
166
- parallelSlots: subSlots,
167
- loadingPath: parentRoute.loadingPath,
168
- errorPath: parentRoute.errorPath,
169
- layoutErrorPaths: parentRoute.layoutErrorPaths,
170
- notFoundPath: parentRoute.notFoundPath,
171
- notFoundPaths: parentRoute.notFoundPaths,
172
- forbiddenPath: parentRoute.forbiddenPath,
173
- unauthorizedPath: parentRoute.unauthorizedPath,
174
- routeSegments: [...parentRoute.routeSegments, ...rawSegments],
175
- layoutTreePositions: parentRoute.layoutTreePositions,
176
- isDynamic: parentRoute.isDynamic || subIsDynamic,
177
- params: [...parentRoute.params, ...subParams],
178
- patternParts: [...parentRoute.patternParts, ...urlParts],
179
- };
180
- syntheticRoutes.push(newRoute);
181
- routesByPattern.set(pattern, newRoute);
182
- }
183
- }
184
- return syntheticRoutes;
70
+ const syntheticRoutes = [];
71
+ const routesByPattern = new Map(routes.map((r) => [r.pattern, r]));
72
+ const slotKey = (slotName, ownerDir) => `${slotName}\u0000${ownerDir}`;
73
+ const applySlotSubPages = (route, slotPages) => {
74
+ route.parallelSlots = route.parallelSlots.map((slot) => ({
75
+ ...slot,
76
+ pagePath: slotPages.get(slotKey(slot.name, slot.ownerDir)) ?? slot.pagePath
77
+ }));
78
+ };
79
+ for (const parentRoute of routes) {
80
+ if (parentRoute.parallelSlots.length === 0) continue;
81
+ if (!parentRoute.pagePath) continue;
82
+ const parentPageDir = path.dirname(parentRoute.pagePath);
83
+ const subPathMap = /* @__PURE__ */ new Map();
84
+ for (const slot of parentRoute.parallelSlots) {
85
+ const slotDir = path.join(parentPageDir, `@${slot.name}`);
86
+ if (!fs.existsSync(slotDir)) continue;
87
+ const subPages = findSlotSubPages(slotDir, matcher);
88
+ for (const { relativePath, pagePath } of subPages) {
89
+ const subSegments = relativePath.split(path.sep);
90
+ const convertedSubRoute = convertSegmentsToRouteParts(subSegments);
91
+ if (!convertedSubRoute) continue;
92
+ const { urlSegments } = convertedSubRoute;
93
+ const normalizedSubPath = urlSegments.join("/");
94
+ let subPathEntry = subPathMap.get(normalizedSubPath);
95
+ if (!subPathEntry) {
96
+ subPathEntry = {
97
+ rawSegments: subSegments,
98
+ converted: convertedSubRoute,
99
+ slotPages: /* @__PURE__ */ new Map()
100
+ };
101
+ subPathMap.set(normalizedSubPath, subPathEntry);
102
+ }
103
+ const slotId = slotKey(slot.name, slot.ownerDir);
104
+ if (subPathEntry.slotPages.get(slotId)) {
105
+ const pattern = joinRoutePattern(parentRoute.pattern, normalizedSubPath);
106
+ throw new Error(`You cannot have two routes that resolve to the same path ("${pattern}").`);
107
+ }
108
+ subPathEntry.slotPages.set(slotId, pagePath);
109
+ }
110
+ }
111
+ if (subPathMap.size === 0) continue;
112
+ const childrenDefault = findFile(parentPageDir, "default", matcher);
113
+ if (!childrenDefault) continue;
114
+ for (const { rawSegments, converted: convertedSubRoute, slotPages } of subPathMap.values()) {
115
+ const { urlSegments: urlParts, params: subParams, isDynamic: subIsDynamic } = convertedSubRoute;
116
+ const subUrlPath = urlParts.join("/");
117
+ const pattern = joinRoutePattern(parentRoute.pattern, subUrlPath);
118
+ const existingRoute = routesByPattern.get(pattern);
119
+ if (existingRoute) {
120
+ if (existingRoute.routePath && !existingRoute.pagePath) throw new Error(`You cannot have two routes that resolve to the same path ("${pattern}").`);
121
+ applySlotSubPages(existingRoute, slotPages);
122
+ continue;
123
+ }
124
+ const subSlots = parentRoute.parallelSlots.map((slot) => ({
125
+ ...slot,
126
+ pagePath: slotPages.get(slotKey(slot.name, slot.ownerDir)) || null
127
+ }));
128
+ const newRoute = {
129
+ pattern,
130
+ pagePath: childrenDefault,
131
+ routePath: null,
132
+ layouts: parentRoute.layouts,
133
+ templates: parentRoute.templates,
134
+ parallelSlots: subSlots,
135
+ loadingPath: parentRoute.loadingPath,
136
+ errorPath: parentRoute.errorPath,
137
+ layoutErrorPaths: parentRoute.layoutErrorPaths,
138
+ notFoundPath: parentRoute.notFoundPath,
139
+ notFoundPaths: parentRoute.notFoundPaths,
140
+ forbiddenPath: parentRoute.forbiddenPath,
141
+ unauthorizedPath: parentRoute.unauthorizedPath,
142
+ routeSegments: [...parentRoute.routeSegments, ...rawSegments],
143
+ layoutTreePositions: parentRoute.layoutTreePositions,
144
+ isDynamic: parentRoute.isDynamic || subIsDynamic,
145
+ params: [...parentRoute.params, ...subParams],
146
+ patternParts: [...parentRoute.patternParts, ...urlParts]
147
+ };
148
+ syntheticRoutes.push(newRoute);
149
+ routesByPattern.set(pattern, newRoute);
150
+ }
151
+ }
152
+ return syntheticRoutes;
185
153
  }
186
154
  /**
187
- * Find all page files in subdirectories of a parallel slot directory.
188
- * Returns relative paths (from the slot dir) and absolute page paths.
189
- * Skips the root page.tsx (already handled as the slot's main page)
190
- * and intercepting route directories.
191
- */
155
+ * Find all page files in subdirectories of a parallel slot directory.
156
+ * Returns relative paths (from the slot dir) and absolute page paths.
157
+ * Skips the root page.tsx (already handled as the slot's main page)
158
+ * and intercepting route directories.
159
+ */
192
160
  function findSlotSubPages(slotDir, matcher) {
193
- const results = [];
194
- function scan(dir) {
195
- if (!fs.existsSync(dir))
196
- return;
197
- const entries = fs.readdirSync(dir, { withFileTypes: true });
198
- for (const entry of entries) {
199
- if (!entry.isDirectory())
200
- continue;
201
- // Skip intercepting route directories
202
- if (matchInterceptConvention(entry.name))
203
- continue;
204
- // Skip private folders (prefixed with _)
205
- if (entry.name.startsWith("_"))
206
- continue;
207
- const subDir = path.join(dir, entry.name);
208
- const page = findFile(subDir, "page", matcher);
209
- if (page) {
210
- const relativePath = path.relative(slotDir, subDir);
211
- results.push({ relativePath, pagePath: page });
212
- }
213
- // Continue scanning deeper for nested sub-pages
214
- scan(subDir);
215
- }
216
- }
217
- scan(slotDir);
218
- return results;
161
+ const results = [];
162
+ function scan(dir) {
163
+ if (!fs.existsSync(dir)) return;
164
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
165
+ for (const entry of entries) {
166
+ if (!entry.isDirectory()) continue;
167
+ if (matchInterceptConvention(entry.name)) continue;
168
+ if (entry.name.startsWith("_")) continue;
169
+ const subDir = path.join(dir, entry.name);
170
+ const page = findFile(subDir, "page", matcher);
171
+ if (page) {
172
+ const relativePath = path.relative(slotDir, subDir);
173
+ results.push({
174
+ relativePath,
175
+ pagePath: page
176
+ });
177
+ }
178
+ scan(subDir);
179
+ }
180
+ }
181
+ scan(slotDir);
182
+ return results;
219
183
  }
220
184
  /**
221
- * Convert a file path relative to app/ into an AppRoute.
222
- */
185
+ * Convert a file path relative to app/ into an AppRoute.
186
+ */
223
187
  function fileToAppRoute(file, appDir, type, matcher) {
224
- // Remove the filename (page.tsx or route.ts)
225
- const dir = path.dirname(file);
226
- const segments = dir === "." ? [] : dir.split(path.sep);
227
- const params = [];
228
- let isDynamic = false;
229
- const convertedRoute = convertSegmentsToRouteParts(segments);
230
- if (!convertedRoute)
231
- return null;
232
- const { urlSegments, params: routeParams, isDynamic: routeIsDynamic } = convertedRoute;
233
- params.push(...routeParams);
234
- isDynamic = routeIsDynamic;
235
- const pattern = "/" + urlSegments.join("/");
236
- // Discover layouts and templates from root to leaf
237
- const layouts = discoverLayouts(segments, appDir, matcher);
238
- const templates = discoverTemplates(segments, appDir, matcher);
239
- // Compute the tree position (directory depth) for each layout.
240
- const layoutTreePositions = computeLayoutTreePositions(appDir, layouts);
241
- // Discover per-layout error boundaries (aligned with layouts array).
242
- // In Next.js, each segment independently wraps its children with an ErrorBoundary.
243
- // This array enables interleaving error boundaries with layouts in the rendering.
244
- const layoutErrorPaths = discoverLayoutAlignedErrors(segments, appDir, matcher);
245
- // Discover loading, error in the route's directory
246
- const routeDir = dir === "." ? appDir : path.join(appDir, dir);
247
- const loadingPath = findFile(routeDir, "loading", matcher);
248
- const errorPath = findFile(routeDir, "error", matcher);
249
- // Discover not-found/forbidden/unauthorized: walk from route directory up to root (nearest wins).
250
- const notFoundPath = discoverBoundaryFile(segments, appDir, "not-found", matcher);
251
- const forbiddenPath = discoverBoundaryFile(segments, appDir, "forbidden", matcher);
252
- const unauthorizedPath = discoverBoundaryFile(segments, appDir, "unauthorized", matcher);
253
- // Discover per-layout not-found files (one per layout directory).
254
- // These are used for per-layout NotFoundBoundary to match Next.js behavior where
255
- // notFound() thrown from a layout is caught by the parent layout's boundary.
256
- const notFoundPaths = discoverBoundaryFilePerLayout(layouts, "not-found", matcher);
257
- // Discover parallel slots (@team, @analytics, etc.).
258
- // Slots at the route's own directory use page.tsx; slots at ancestor directories
259
- // (inherited from parent layouts) use default.tsx as fallback.
260
- const parallelSlots = discoverInheritedParallelSlots(segments, appDir, routeDir, matcher);
261
- return {
262
- pattern: pattern === "/" ? "/" : pattern,
263
- pagePath: type === "page" ? path.join(appDir, file) : null,
264
- routePath: type === "route" ? path.join(appDir, file) : null,
265
- layouts,
266
- templates,
267
- parallelSlots,
268
- loadingPath,
269
- errorPath,
270
- layoutErrorPaths,
271
- notFoundPath,
272
- notFoundPaths,
273
- forbiddenPath,
274
- unauthorizedPath,
275
- routeSegments: segments,
276
- layoutTreePositions,
277
- isDynamic,
278
- params,
279
- patternParts: urlSegments,
280
- };
188
+ const dir = path.dirname(file);
189
+ const segments = dir === "." ? [] : dir.split(path.sep);
190
+ const params = [];
191
+ let isDynamic = false;
192
+ const convertedRoute = convertSegmentsToRouteParts(segments);
193
+ if (!convertedRoute) return null;
194
+ const { urlSegments, params: routeParams, isDynamic: routeIsDynamic } = convertedRoute;
195
+ params.push(...routeParams);
196
+ isDynamic = routeIsDynamic;
197
+ const pattern = "/" + urlSegments.join("/");
198
+ const layouts = discoverLayouts(segments, appDir, matcher);
199
+ const templates = discoverTemplates(segments, appDir, matcher);
200
+ const layoutTreePositions = computeLayoutTreePositions(appDir, layouts);
201
+ const layoutErrorPaths = discoverLayoutAlignedErrors(segments, appDir, matcher);
202
+ const routeDir = dir === "." ? appDir : path.join(appDir, dir);
203
+ const loadingPath = findFile(routeDir, "loading", matcher);
204
+ const errorPath = findFile(routeDir, "error", matcher);
205
+ const notFoundPath = discoverBoundaryFile(segments, appDir, "not-found", matcher);
206
+ const forbiddenPath = discoverBoundaryFile(segments, appDir, "forbidden", matcher);
207
+ const unauthorizedPath = discoverBoundaryFile(segments, appDir, "unauthorized", matcher);
208
+ const notFoundPaths = discoverBoundaryFilePerLayout(layouts, "not-found", matcher);
209
+ const parallelSlots = discoverInheritedParallelSlots(segments, appDir, routeDir, matcher);
210
+ return {
211
+ pattern: pattern === "/" ? "/" : pattern,
212
+ pagePath: type === "page" ? path.join(appDir, file) : null,
213
+ routePath: type === "route" ? path.join(appDir, file) : null,
214
+ layouts,
215
+ templates,
216
+ parallelSlots,
217
+ loadingPath,
218
+ errorPath,
219
+ layoutErrorPaths,
220
+ notFoundPath,
221
+ notFoundPaths,
222
+ forbiddenPath,
223
+ unauthorizedPath,
224
+ routeSegments: segments,
225
+ layoutTreePositions,
226
+ isDynamic,
227
+ params,
228
+ patternParts: urlSegments
229
+ };
281
230
  }
282
231
  /**
283
- * Compute the tree position (directory depth from app root) for each layout.
284
- * Root layout = 0, a layout at app/blog/ = 1, app/blog/(group)/ = 2.
285
- * Counts ALL directory levels including route groups and parallel slots.
286
- */
232
+ * Compute the tree position (directory depth from app root) for each layout.
233
+ * Root layout = 0, a layout at app/blog/ = 1, app/blog/(group)/ = 2.
234
+ * Counts ALL directory levels including route groups and parallel slots.
235
+ */
287
236
  function computeLayoutTreePositions(appDir, layouts) {
288
- return layouts.map((layoutPath) => {
289
- const layoutDir = path.dirname(layoutPath);
290
- if (layoutDir === appDir)
291
- return 0;
292
- const relative = path.relative(appDir, layoutDir);
293
- return relative.split(path.sep).length;
294
- });
237
+ return layouts.map((layoutPath) => {
238
+ const layoutDir = path.dirname(layoutPath);
239
+ if (layoutDir === appDir) return 0;
240
+ return path.relative(appDir, layoutDir).split(path.sep).length;
241
+ });
295
242
  }
296
243
  /**
297
- * Discover all layout files from root to the given directory.
298
- * Each level of the directory tree may have a layout.tsx.
299
- */
244
+ * Discover all layout files from root to the given directory.
245
+ * Each level of the directory tree may have a layout.tsx.
246
+ */
300
247
  function discoverLayouts(segments, appDir, matcher) {
301
- const layouts = [];
302
- // Check root layout
303
- const rootLayout = findFile(appDir, "layout", matcher);
304
- if (rootLayout)
305
- layouts.push(rootLayout);
306
- // Check each directory level
307
- let currentDir = appDir;
308
- for (const segment of segments) {
309
- currentDir = path.join(currentDir, segment);
310
- const layout = findFile(currentDir, "layout", matcher);
311
- if (layout)
312
- layouts.push(layout);
313
- }
314
- return layouts;
248
+ const layouts = [];
249
+ const rootLayout = findFile(appDir, "layout", matcher);
250
+ if (rootLayout) layouts.push(rootLayout);
251
+ let currentDir = appDir;
252
+ for (const segment of segments) {
253
+ currentDir = path.join(currentDir, segment);
254
+ const layout = findFile(currentDir, "layout", matcher);
255
+ if (layout) layouts.push(layout);
256
+ }
257
+ return layouts;
315
258
  }
316
259
  /**
317
- * Discover all template files from root to the given directory.
318
- * Each level of the directory tree may have a template.tsx.
319
- * Templates are like layouts but re-mount on navigation.
320
- */
260
+ * Discover all template files from root to the given directory.
261
+ * Each level of the directory tree may have a template.tsx.
262
+ * Templates are like layouts but re-mount on navigation.
263
+ */
321
264
  function discoverTemplates(segments, appDir, matcher) {
322
- const templates = [];
323
- // Check root template
324
- const rootTemplate = findFile(appDir, "template", matcher);
325
- if (rootTemplate)
326
- templates.push(rootTemplate);
327
- // Check each directory level
328
- let currentDir = appDir;
329
- for (const segment of segments) {
330
- currentDir = path.join(currentDir, segment);
331
- const template = findFile(currentDir, "template", matcher);
332
- if (template)
333
- templates.push(template);
334
- }
335
- return templates;
265
+ const templates = [];
266
+ const rootTemplate = findFile(appDir, "template", matcher);
267
+ if (rootTemplate) templates.push(rootTemplate);
268
+ let currentDir = appDir;
269
+ for (const segment of segments) {
270
+ currentDir = path.join(currentDir, segment);
271
+ const template = findFile(currentDir, "template", matcher);
272
+ if (template) templates.push(template);
273
+ }
274
+ return templates;
336
275
  }
337
276
  /**
338
- * Discover error.tsx files aligned with the layouts array.
339
- * Walks the same directory levels as discoverLayouts and, for each level
340
- * that contributes a layout entry, checks whether error.tsx also exists.
341
- * Returns an array of the same length as discoverLayouts() would return,
342
- * with the error path (or null) at each corresponding layout level.
343
- *
344
- * This enables interleaving ErrorBoundary components with layouts in the
345
- * rendering tree, matching Next.js behavior where each segment independently
346
- * wraps its children with an error boundary.
347
- */
277
+ * Discover error.tsx files aligned with the layouts array.
278
+ * Walks the same directory levels as discoverLayouts and, for each level
279
+ * that contributes a layout entry, checks whether error.tsx also exists.
280
+ * Returns an array of the same length as discoverLayouts() would return,
281
+ * with the error path (or null) at each corresponding layout level.
282
+ *
283
+ * This enables interleaving ErrorBoundary components with layouts in the
284
+ * rendering tree, matching Next.js behavior where each segment independently
285
+ * wraps its children with an error boundary.
286
+ */
348
287
  function discoverLayoutAlignedErrors(segments, appDir, matcher) {
349
- const errors = [];
350
- // Root level (only if root has a layout matching discoverLayouts logic)
351
- const rootLayout = findFile(appDir, "layout", matcher);
352
- if (rootLayout) {
353
- errors.push(findFile(appDir, "error", matcher));
354
- }
355
- // Check each directory level
356
- let currentDir = appDir;
357
- for (const segment of segments) {
358
- currentDir = path.join(currentDir, segment);
359
- const layout = findFile(currentDir, "layout", matcher);
360
- if (layout) {
361
- errors.push(findFile(currentDir, "error", matcher));
362
- }
363
- }
364
- return errors;
288
+ const errors = [];
289
+ if (findFile(appDir, "layout", matcher)) errors.push(findFile(appDir, "error", matcher));
290
+ let currentDir = appDir;
291
+ for (const segment of segments) {
292
+ currentDir = path.join(currentDir, segment);
293
+ if (findFile(currentDir, "layout", matcher)) errors.push(findFile(currentDir, "error", matcher));
294
+ }
295
+ return errors;
365
296
  }
366
297
  /**
367
- * Discover the nearest boundary file (not-found, forbidden, unauthorized)
368
- * by walking from the route's directory up to the app root.
369
- * Returns the first (closest) file found, or null.
370
- */
298
+ * Discover the nearest boundary file (not-found, forbidden, unauthorized)
299
+ * by walking from the route's directory up to the app root.
300
+ * Returns the first (closest) file found, or null.
301
+ */
371
302
  function discoverBoundaryFile(segments, appDir, fileName, matcher) {
372
- // Build all directory paths from leaf to root
373
- const dirs = [];
374
- let dir = appDir;
375
- dirs.push(dir);
376
- for (const segment of segments) {
377
- dir = path.join(dir, segment);
378
- dirs.push(dir);
379
- }
380
- // Walk from leaf (last) to root (first)
381
- for (let i = dirs.length - 1; i >= 0; i--) {
382
- const f = findFile(dirs[i], fileName, matcher);
383
- if (f)
384
- return f;
385
- }
386
- return null;
303
+ const dirs = [];
304
+ let dir = appDir;
305
+ dirs.push(dir);
306
+ for (const segment of segments) {
307
+ dir = path.join(dir, segment);
308
+ dirs.push(dir);
309
+ }
310
+ for (let i = dirs.length - 1; i >= 0; i--) {
311
+ const f = findFile(dirs[i], fileName, matcher);
312
+ if (f) return f;
313
+ }
314
+ return null;
387
315
  }
388
316
  /**
389
- * Discover boundary files (not-found, forbidden, unauthorized) at each layout directory.
390
- * Returns an array aligned with the layouts array, where each entry is the boundary
391
- * file at that layout's directory, or null if none exists there.
392
- *
393
- * This is used for per-layout error boundaries. In Next.js, each layout level
394
- * has its own boundary that wraps the layout's children. When notFound() is thrown
395
- * from a layout, it propagates up to the parent layout's boundary.
396
- */
317
+ * Discover boundary files (not-found, forbidden, unauthorized) at each layout directory.
318
+ * Returns an array aligned with the layouts array, where each entry is the boundary
319
+ * file at that layout's directory, or null if none exists there.
320
+ *
321
+ * This is used for per-layout error boundaries. In Next.js, each layout level
322
+ * has its own boundary that wraps the layout's children. When notFound() is thrown
323
+ * from a layout, it propagates up to the parent layout's boundary.
324
+ */
397
325
  function discoverBoundaryFilePerLayout(layouts, fileName, matcher) {
398
- return layouts.map((layoutPath) => {
399
- const layoutDir = path.dirname(layoutPath);
400
- return findFile(layoutDir, fileName, matcher);
401
- });
326
+ return layouts.map((layoutPath) => {
327
+ return findFile(path.dirname(layoutPath), fileName, matcher);
328
+ });
402
329
  }
403
330
  /**
404
- * Discover parallel slots inherited from ancestor directories.
405
- *
406
- * In Next.js, parallel slots belong to the layout that defines them. When a
407
- * child route is rendered, its parent layout's slots must still be present.
408
- * If the child doesn't have matching content in a slot, the slot's default.tsx
409
- * is rendered instead.
410
- *
411
- * Walk from appDir through each segment to the route's directory. At each level
412
- * that has @slot dirs, collect them. Slots at the route's own directory level
413
- * use page.tsx; slots at ancestor levels use default.tsx only.
414
- */
331
+ * Discover parallel slots inherited from ancestor directories.
332
+ *
333
+ * In Next.js, parallel slots belong to the layout that defines them. When a
334
+ * child route is rendered, its parent layout's slots must still be present.
335
+ * If the child doesn't have matching content in a slot, the slot's default.tsx
336
+ * is rendered instead.
337
+ *
338
+ * Walk from appDir through each segment to the route's directory. At each level
339
+ * that has @slot dirs, collect them. Slots at the route's own directory level
340
+ * use page.tsx; slots at ancestor levels use default.tsx only.
341
+ */
415
342
  function discoverInheritedParallelSlots(segments, appDir, routeDir, matcher) {
416
- const slotMap = new Map();
417
- // Walk from appDir through each segment, tracking layout indices.
418
- // layoutIndex tracks which position in the route's layouts[] array corresponds
419
- // to a given directory. Only directories with a layout.tsx file increment.
420
- let currentDir = appDir;
421
- const dirsToCheck = [];
422
- let layoutIdx = findFile(appDir, "layout", matcher) ? 0 : -1;
423
- dirsToCheck.push({ dir: appDir, layoutIdx: Math.max(layoutIdx, 0) });
424
- for (const segment of segments) {
425
- currentDir = path.join(currentDir, segment);
426
- if (findFile(currentDir, "layout", matcher)) {
427
- layoutIdx++;
428
- }
429
- dirsToCheck.push({ dir: currentDir, layoutIdx: Math.max(layoutIdx, 0) });
430
- }
431
- for (const { dir, layoutIdx: lvlLayoutIdx } of dirsToCheck) {
432
- const isOwnDir = dir === routeDir;
433
- const slotsAtLevel = discoverParallelSlots(dir, appDir, matcher);
434
- for (const slot of slotsAtLevel) {
435
- if (isOwnDir) {
436
- // At the route's own directory: use page.tsx (normal behavior)
437
- slot.layoutIndex = lvlLayoutIdx;
438
- slotMap.set(slot.name, slot);
439
- }
440
- else {
441
- // At an ancestor directory: use default.tsx as the page, not page.tsx
442
- // (the slot's page.tsx is for the parent route, not this child route)
443
- const inheritedSlot = {
444
- ...slot,
445
- pagePath: null, // Don't use ancestor's page.tsx
446
- layoutIndex: lvlLayoutIdx,
447
- // defaultPath, loadingPath, errorPath, interceptingRoutes remain
448
- };
449
- // Only inherit if we haven't seen this slot at a closer level
450
- if (!slotMap.has(slot.name)) {
451
- slotMap.set(slot.name, inheritedSlot);
452
- }
453
- }
454
- }
455
- }
456
- return Array.from(slotMap.values());
343
+ const slotMap = /* @__PURE__ */ new Map();
344
+ let currentDir = appDir;
345
+ const dirsToCheck = [];
346
+ let layoutIdx = findFile(appDir, "layout", matcher) ? 0 : -1;
347
+ dirsToCheck.push({
348
+ dir: appDir,
349
+ layoutIdx: Math.max(layoutIdx, 0)
350
+ });
351
+ for (const segment of segments) {
352
+ currentDir = path.join(currentDir, segment);
353
+ if (findFile(currentDir, "layout", matcher)) layoutIdx++;
354
+ dirsToCheck.push({
355
+ dir: currentDir,
356
+ layoutIdx: Math.max(layoutIdx, 0)
357
+ });
358
+ }
359
+ for (const { dir, layoutIdx: lvlLayoutIdx } of dirsToCheck) {
360
+ const isOwnDir = dir === routeDir;
361
+ const slotsAtLevel = discoverParallelSlots(dir, appDir, matcher);
362
+ for (const slot of slotsAtLevel) if (isOwnDir) {
363
+ slot.layoutIndex = lvlLayoutIdx;
364
+ slotMap.set(slot.name, slot);
365
+ } else {
366
+ const inheritedSlot = {
367
+ ...slot,
368
+ pagePath: null,
369
+ layoutIndex: lvlLayoutIdx
370
+ };
371
+ slotMap.set(slot.name, inheritedSlot);
372
+ }
373
+ }
374
+ return Array.from(slotMap.values());
457
375
  }
458
376
  /**
459
- * Discover parallel route slots (@team, @analytics, etc.) in a directory.
460
- * Returns a ParallelSlot for each @-prefixed subdirectory that has a page or default component.
461
- */
377
+ * Discover parallel route slots (@team, @analytics, etc.) in a directory.
378
+ * Returns a ParallelSlot for each @-prefixed subdirectory that has a page or default component.
379
+ */
462
380
  function discoverParallelSlots(dir, appDir, matcher) {
463
- if (!fs.existsSync(dir))
464
- return [];
465
- const entries = fs.readdirSync(dir, { withFileTypes: true });
466
- const slots = [];
467
- for (const entry of entries) {
468
- if (!entry.isDirectory() || !entry.name.startsWith("@"))
469
- continue;
470
- const slotName = entry.name.slice(1); // "@team" -> "team"
471
- const slotDir = path.join(dir, entry.name);
472
- const pagePath = findFile(slotDir, "page", matcher);
473
- const defaultPath = findFile(slotDir, "default", matcher);
474
- const interceptingRoutes = discoverInterceptingRoutes(slotDir, dir, appDir, matcher);
475
- // Only include slots that have at least a page, default, or intercepting route
476
- if (!pagePath && !defaultPath && interceptingRoutes.length === 0)
477
- continue;
478
- slots.push({
479
- name: slotName,
480
- ownerDir: slotDir,
481
- pagePath,
482
- defaultPath,
483
- layoutPath: findFile(slotDir, "layout", matcher),
484
- loadingPath: findFile(slotDir, "loading", matcher),
485
- errorPath: findFile(slotDir, "error", matcher),
486
- interceptingRoutes,
487
- layoutIndex: -1, // Will be set by discoverInheritedParallelSlots
488
- });
489
- }
490
- return slots;
381
+ if (!fs.existsSync(dir)) return [];
382
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
383
+ const slots = [];
384
+ for (const entry of entries) {
385
+ if (!entry.isDirectory() || !entry.name.startsWith("@")) continue;
386
+ const slotName = entry.name.slice(1);
387
+ const slotDir = path.join(dir, entry.name);
388
+ const pagePath = findFile(slotDir, "page", matcher);
389
+ const defaultPath = findFile(slotDir, "default", matcher);
390
+ const interceptingRoutes = discoverInterceptingRoutes(slotDir, dir, appDir, matcher);
391
+ if (!pagePath && !defaultPath && interceptingRoutes.length === 0) continue;
392
+ slots.push({
393
+ name: slotName,
394
+ ownerDir: slotDir,
395
+ pagePath,
396
+ defaultPath,
397
+ layoutPath: findFile(slotDir, "layout", matcher),
398
+ loadingPath: findFile(slotDir, "loading", matcher),
399
+ errorPath: findFile(slotDir, "error", matcher),
400
+ interceptingRoutes,
401
+ layoutIndex: -1
402
+ });
403
+ }
404
+ return slots;
491
405
  }
492
406
  /**
493
- * The interception convention prefix patterns.
494
- * (.) — same level, (..) — one level up, (..)(..)" — two levels up, (...) — root
495
- */
407
+ * The interception convention prefix patterns.
408
+ * (.) — same level, (..) — one level up, (..)(..)" — two levels up, (...) — root
409
+ */
496
410
  const INTERCEPT_PATTERNS = [
497
- { prefix: "(...)", convention: "..." },
498
- { prefix: "(..)(..)", convention: "../.." },
499
- { prefix: "(..)", convention: ".." },
500
- { prefix: "(.)", convention: "." },
411
+ {
412
+ prefix: "(...)",
413
+ convention: "..."
414
+ },
415
+ {
416
+ prefix: "(..)(..)",
417
+ convention: "../.."
418
+ },
419
+ {
420
+ prefix: "(..)",
421
+ convention: ".."
422
+ },
423
+ {
424
+ prefix: "(.)",
425
+ convention: "."
426
+ }
501
427
  ];
502
428
  /**
503
- * Discover intercepting routes inside a parallel slot directory.
504
- *
505
- * Intercepting routes use conventions like (.)photo, (..)feed, (...), etc.
506
- * They intercept navigation to another route and render within the slot instead.
507
- *
508
- * @param slotDir - The parallel slot directory (e.g. app/feed/@modal)
509
- * @param routeDir - The directory of the route that owns this slot (e.g. app/feed)
510
- * @param appDir - The root app directory
511
- */
429
+ * Discover intercepting routes inside a parallel slot directory.
430
+ *
431
+ * Intercepting routes use conventions like (.)photo, (..)feed, (...), etc.
432
+ * They intercept navigation to another route and render within the slot instead.
433
+ *
434
+ * @param slotDir - The parallel slot directory (e.g. app/feed/@modal)
435
+ * @param routeDir - The directory of the route that owns this slot (e.g. app/feed)
436
+ * @param appDir - The root app directory
437
+ */
512
438
  function discoverInterceptingRoutes(slotDir, routeDir, appDir, matcher) {
513
- if (!fs.existsSync(slotDir))
514
- return [];
515
- const results = [];
516
- // Recursively scan for page files inside intercepting directories
517
- scanForInterceptingPages(slotDir, routeDir, appDir, results, matcher);
518
- return results;
439
+ if (!fs.existsSync(slotDir)) return [];
440
+ const results = [];
441
+ scanForInterceptingPages(slotDir, routeDir, appDir, results, matcher);
442
+ return results;
519
443
  }
520
444
  /**
521
- * Recursively scan a directory tree for page.tsx files that are inside
522
- * intercepting route directories.
523
- */
445
+ * Recursively scan a directory tree for page.tsx files that are inside
446
+ * intercepting route directories.
447
+ */
524
448
  function scanForInterceptingPages(currentDir, routeDir, appDir, results, matcher) {
525
- if (!fs.existsSync(currentDir))
526
- return;
527
- const entries = fs.readdirSync(currentDir, { withFileTypes: true });
528
- for (const entry of entries) {
529
- if (!entry.isDirectory())
530
- continue;
531
- // Skip private folders (prefixed with _)
532
- if (entry.name.startsWith("_"))
533
- continue;
534
- // Check if this directory name starts with an interception convention
535
- const interceptMatch = matchInterceptConvention(entry.name);
536
- if (interceptMatch) {
537
- // This directory is the start of an intercepting route
538
- // e.g. "(.)photos" means intercept same-level "photos" route
539
- const restOfName = entry.name.slice(interceptMatch.prefix.length);
540
- const interceptDir = path.join(currentDir, entry.name);
541
- // Find page files within this intercepting directory tree
542
- collectInterceptingPages(interceptDir, interceptDir, interceptMatch.convention, restOfName, routeDir, appDir, results, matcher);
543
- }
544
- else {
545
- // Regular subdirectory — keep scanning for intercepting dirs
546
- scanForInterceptingPages(path.join(currentDir, entry.name), routeDir, appDir, results, matcher);
547
- }
548
- }
449
+ if (!fs.existsSync(currentDir)) return;
450
+ const entries = fs.readdirSync(currentDir, { withFileTypes: true });
451
+ for (const entry of entries) {
452
+ if (!entry.isDirectory()) continue;
453
+ if (entry.name.startsWith("_")) continue;
454
+ const interceptMatch = matchInterceptConvention(entry.name);
455
+ if (interceptMatch) {
456
+ const restOfName = entry.name.slice(interceptMatch.prefix.length);
457
+ const interceptDir = path.join(currentDir, entry.name);
458
+ collectInterceptingPages(interceptDir, interceptDir, interceptMatch.convention, restOfName, routeDir, appDir, results, matcher);
459
+ } else scanForInterceptingPages(path.join(currentDir, entry.name), routeDir, appDir, results, matcher);
460
+ }
549
461
  }
550
462
  /**
551
- * Match a directory name against interception convention prefixes.
552
- */
463
+ * Match a directory name against interception convention prefixes.
464
+ */
553
465
  function matchInterceptConvention(name) {
554
- for (const pattern of INTERCEPT_PATTERNS) {
555
- if (name.startsWith(pattern.prefix)) {
556
- return pattern;
557
- }
558
- }
559
- return null;
466
+ for (const pattern of INTERCEPT_PATTERNS) if (name.startsWith(pattern.prefix)) return pattern;
467
+ return null;
560
468
  }
561
469
  /**
562
- * Collect page.tsx files inside an intercepting route directory tree
563
- * and compute their target URL patterns.
564
- */
470
+ * Collect page.tsx files inside an intercepting route directory tree
471
+ * and compute their target URL patterns.
472
+ */
565
473
  function collectInterceptingPages(currentDir, interceptRoot, convention, interceptSegment, routeDir, appDir, results, matcher) {
566
- // Check for page.tsx in current directory
567
- const page = findFile(currentDir, "page", matcher);
568
- if (page) {
569
- const targetPattern = computeInterceptTarget(convention, interceptSegment, currentDir, interceptRoot, routeDir, appDir);
570
- if (targetPattern) {
571
- results.push({
572
- convention,
573
- targetPattern: targetPattern.pattern,
574
- pagePath: page,
575
- params: targetPattern.params,
576
- });
577
- }
578
- }
579
- // Recurse into subdirectories for nested intercepting routes
580
- if (!fs.existsSync(currentDir))
581
- return;
582
- const entries = fs.readdirSync(currentDir, { withFileTypes: true });
583
- for (const entry of entries) {
584
- if (!entry.isDirectory())
585
- continue;
586
- // Skip private folders (prefixed with _)
587
- if (entry.name.startsWith("_"))
588
- continue;
589
- collectInterceptingPages(path.join(currentDir, entry.name), interceptRoot, convention, interceptSegment, routeDir, appDir, results, matcher);
590
- }
474
+ const page = findFile(currentDir, "page", matcher);
475
+ if (page) {
476
+ const targetPattern = computeInterceptTarget(convention, interceptSegment, currentDir, interceptRoot, routeDir, appDir);
477
+ if (targetPattern) results.push({
478
+ convention,
479
+ targetPattern: targetPattern.pattern,
480
+ pagePath: page,
481
+ params: targetPattern.params
482
+ });
483
+ }
484
+ if (!fs.existsSync(currentDir)) return;
485
+ const entries = fs.readdirSync(currentDir, { withFileTypes: true });
486
+ for (const entry of entries) {
487
+ if (!entry.isDirectory()) continue;
488
+ if (entry.name.startsWith("_")) continue;
489
+ collectInterceptingPages(path.join(currentDir, entry.name), interceptRoot, convention, interceptSegment, routeDir, appDir, results, matcher);
490
+ }
591
491
  }
592
492
  /**
593
- * Check whether a path segment is invisible in the URL (route groups, parallel slots, ".").
594
- *
595
- * Used by computeInterceptTarget, convertSegmentsToRouteParts, and
596
- * hasRemainingVisibleSegments — keep this the single source of truth.
597
- */
493
+ * Check whether a path segment is invisible in the URL (route groups, parallel slots, ".").
494
+ *
495
+ * Used by computeInterceptTarget, convertSegmentsToRouteParts, and
496
+ * hasRemainingVisibleSegments — keep this the single source of truth.
497
+ */
598
498
  function isInvisibleSegment(segment) {
599
- if (segment === ".")
600
- return true;
601
- if (segment.startsWith("(") && segment.endsWith(")"))
602
- return true;
603
- if (segment.startsWith("@"))
604
- return true;
605
- return false;
499
+ if (segment === ".") return true;
500
+ if (segment.startsWith("(") && segment.endsWith(")")) return true;
501
+ if (segment.startsWith("@")) return true;
502
+ return false;
606
503
  }
607
504
  /**
608
- * Compute the target URL pattern for an intercepting route.
609
- *
610
- * Interception conventions (..), (..)(..)" climb by *visible route segments*
611
- * (not filesystem directories). Route groups like (marketing) and parallel
612
- * slots like @modal are invisible and must be skipped when counting levels.
613
- *
614
- * - (.) same level: resolve relative to routeDir
615
- * - (..) one level up: climb 1 visible segment
616
- * - (..)(..) two levels up: climb 2 visible segments
617
- * - (...) root: resolve from appDir
618
- */
505
+ * Compute the target URL pattern for an intercepting route.
506
+ *
507
+ * Interception conventions (..), (..)(..)" climb by *visible route segments*
508
+ * (not filesystem directories). Route groups like (marketing) and parallel
509
+ * slots like @modal are invisible and must be skipped when counting levels.
510
+ *
511
+ * - (.) same level: resolve relative to routeDir
512
+ * - (..) one level up: climb 1 visible segment
513
+ * - (..)(..) two levels up: climb 2 visible segments
514
+ * - (...) root: resolve from appDir
515
+ */
619
516
  function computeInterceptTarget(convention, interceptSegment, currentDir, interceptRoot, routeDir, appDir) {
620
- // Determine the base segments for target resolution.
621
- // We work on route segments (not filesystem paths) so that route groups
622
- // and parallel slots are properly skipped when climbing.
623
- const routeSegments = path.relative(appDir, routeDir).split(path.sep).filter(Boolean);
624
- let baseParts;
625
- switch (convention) {
626
- case ".":
627
- baseParts = routeSegments;
628
- break;
629
- case "..":
630
- case "../..": {
631
- const levelsToClimb = convention === ".." ? 1 : 2;
632
- let climbed = 0;
633
- let cutIndex = routeSegments.length;
634
- while (cutIndex > 0 && climbed < levelsToClimb) {
635
- cutIndex--;
636
- if (!isInvisibleSegment(routeSegments[cutIndex])) {
637
- climbed++;
638
- }
639
- }
640
- baseParts = routeSegments.slice(0, cutIndex);
641
- break;
642
- }
643
- case "...":
644
- baseParts = [];
645
- break;
646
- default:
647
- return null;
648
- }
649
- // Add the intercept segment and any nested path segments
650
- const nestedParts = path.relative(interceptRoot, currentDir).split(path.sep).filter(Boolean);
651
- const allSegments = [...baseParts, interceptSegment, ...nestedParts];
652
- const convertedTarget = convertSegmentsToRouteParts(allSegments);
653
- if (!convertedTarget)
654
- return null;
655
- const { urlSegments, params } = convertedTarget;
656
- const pattern = "/" + urlSegments.join("/");
657
- return { pattern: pattern === "/" ? "/" : pattern, params };
517
+ const routeSegments = path.relative(appDir, routeDir).split(path.sep).filter(Boolean);
518
+ let baseParts;
519
+ switch (convention) {
520
+ case ".":
521
+ baseParts = routeSegments;
522
+ break;
523
+ case "..":
524
+ case "../..": {
525
+ const levelsToClimb = convention === ".." ? 1 : 2;
526
+ let climbed = 0;
527
+ let cutIndex = routeSegments.length;
528
+ while (cutIndex > 0 && climbed < levelsToClimb) {
529
+ cutIndex--;
530
+ if (!isInvisibleSegment(routeSegments[cutIndex])) climbed++;
531
+ }
532
+ baseParts = routeSegments.slice(0, cutIndex);
533
+ break;
534
+ }
535
+ case "...":
536
+ baseParts = [];
537
+ break;
538
+ default: return null;
539
+ }
540
+ const nestedParts = path.relative(interceptRoot, currentDir).split(path.sep).filter(Boolean);
541
+ const convertedTarget = convertSegmentsToRouteParts([
542
+ ...baseParts,
543
+ interceptSegment,
544
+ ...nestedParts
545
+ ]);
546
+ if (!convertedTarget) return null;
547
+ const { urlSegments, params } = convertedTarget;
548
+ const pattern = "/" + urlSegments.join("/");
549
+ return {
550
+ pattern: pattern === "/" ? "/" : pattern,
551
+ params
552
+ };
658
553
  }
659
554
  /**
660
- * Find a file by name (without extension) in a directory.
661
- * Checks configured pageExtensions.
662
- */
555
+ * Find a file by name (without extension) in a directory.
556
+ * Checks configured pageExtensions.
557
+ */
663
558
  function findFile(dir, name, matcher) {
664
- for (const ext of matcher.dottedExtensions) {
665
- const filePath = path.join(dir, name + ext);
666
- if (fs.existsSync(filePath))
667
- return filePath;
668
- }
669
- return null;
559
+ for (const ext of matcher.dottedExtensions) {
560
+ const filePath = path.join(dir, name + ext);
561
+ if (fs.existsSync(filePath)) return filePath;
562
+ }
563
+ return null;
670
564
  }
671
565
  /**
672
- * Convert filesystem path segments to URL route parts, skipping invisible segments
673
- * (route groups, @slots, ".") and converting dynamic segment syntax to Express-style
674
- * patterns (e.g. "[id]" → ":id", "[...slug]" → ":slug+").
675
- */
566
+ * Convert filesystem path segments to URL route parts, skipping invisible segments
567
+ * (route groups, @slots, ".") and converting dynamic segment syntax to Express-style
568
+ * patterns (e.g. "[id]" → ":id", "[...slug]" → ":slug+").
569
+ */
676
570
  function convertSegmentsToRouteParts(segments) {
677
- const urlSegments = [];
678
- const params = [];
679
- let isDynamic = false;
680
- for (let i = 0; i < segments.length; i++) {
681
- const segment = segments[i];
682
- if (isInvisibleSegment(segment))
683
- continue;
684
- // Catch-all segments are only valid in terminal URL position.
685
- const catchAllMatch = segment.match(/^\[\.\.\.([\w-]+)\]$/);
686
- if (catchAllMatch) {
687
- if (hasRemainingVisibleSegments(segments, i + 1))
688
- return null;
689
- isDynamic = true;
690
- params.push(catchAllMatch[1]);
691
- urlSegments.push(`:${catchAllMatch[1]}+`);
692
- continue;
693
- }
694
- const optionalCatchAllMatch = segment.match(/^\[\[\.\.\.([\w-]+)\]\]$/);
695
- if (optionalCatchAllMatch) {
696
- if (hasRemainingVisibleSegments(segments, i + 1))
697
- return null;
698
- isDynamic = true;
699
- params.push(optionalCatchAllMatch[1]);
700
- urlSegments.push(`:${optionalCatchAllMatch[1]}*`);
701
- continue;
702
- }
703
- const dynamicMatch = segment.match(/^\[([\w-]+)\]$/);
704
- if (dynamicMatch) {
705
- isDynamic = true;
706
- params.push(dynamicMatch[1]);
707
- urlSegments.push(`:${dynamicMatch[1]}`);
708
- continue;
709
- }
710
- urlSegments.push(decodeRouteSegment(segment));
711
- }
712
- return { urlSegments, params, isDynamic };
571
+ const urlSegments = [];
572
+ const params = [];
573
+ let isDynamic = false;
574
+ for (let i = 0; i < segments.length; i++) {
575
+ const segment = segments[i];
576
+ if (isInvisibleSegment(segment)) continue;
577
+ const catchAllMatch = segment.match(/^\[\.\.\.([\w-]+)\]$/);
578
+ if (catchAllMatch) {
579
+ if (hasRemainingVisibleSegments(segments, i + 1)) return null;
580
+ isDynamic = true;
581
+ params.push(catchAllMatch[1]);
582
+ urlSegments.push(`:${catchAllMatch[1]}+`);
583
+ continue;
584
+ }
585
+ const optionalCatchAllMatch = segment.match(/^\[\[\.\.\.([\w-]+)\]\]$/);
586
+ if (optionalCatchAllMatch) {
587
+ if (hasRemainingVisibleSegments(segments, i + 1)) return null;
588
+ isDynamic = true;
589
+ params.push(optionalCatchAllMatch[1]);
590
+ urlSegments.push(`:${optionalCatchAllMatch[1]}*`);
591
+ continue;
592
+ }
593
+ const dynamicMatch = segment.match(/^\[([\w-]+)\]$/);
594
+ if (dynamicMatch) {
595
+ isDynamic = true;
596
+ params.push(dynamicMatch[1]);
597
+ urlSegments.push(`:${dynamicMatch[1]}`);
598
+ continue;
599
+ }
600
+ urlSegments.push(decodeRouteSegment(segment));
601
+ }
602
+ return {
603
+ urlSegments,
604
+ params,
605
+ isDynamic
606
+ };
713
607
  }
714
608
  function hasRemainingVisibleSegments(segments, startIndex) {
715
- for (let i = startIndex; i < segments.length; i++) {
716
- if (!isInvisibleSegment(segments[i]))
717
- return true;
718
- }
719
- return false;
609
+ for (let i = startIndex; i < segments.length; i++) if (!isInvisibleSegment(segments[i])) return true;
610
+ return false;
720
611
  }
721
- // Trie cache keyed by route array identity (same array = same trie)
722
- const appTrieCache = new WeakMap();
612
+ const appTrieCache = /* @__PURE__ */ new WeakMap();
723
613
  function getOrBuildAppTrie(routes) {
724
- let trie = appTrieCache.get(routes);
725
- if (!trie) {
726
- trie = buildRouteTrie(routes);
727
- appTrieCache.set(routes, trie);
728
- }
729
- return trie;
614
+ let trie = appTrieCache.get(routes);
615
+ if (!trie) {
616
+ trie = buildRouteTrie(routes);
617
+ appTrieCache.set(routes, trie);
618
+ }
619
+ return trie;
730
620
  }
731
621
  function joinRoutePattern(basePattern, subPath) {
732
- if (!subPath)
733
- return basePattern;
734
- return basePattern === "/" ? `/${subPath}` : `${basePattern}/${subPath}`;
622
+ if (!subPath) return basePattern;
623
+ return basePattern === "/" ? `/${subPath}` : `${basePattern}/${subPath}`;
735
624
  }
736
625
  /**
737
- * Match a URL against App Router routes.
738
- */
739
- export function matchAppRoute(url, routes) {
740
- const pathname = url.split("?")[0];
741
- let normalizedUrl = pathname === "/" ? "/" : pathname.replace(/\/$/, "");
742
- normalizedUrl = normalizePathnameForRouteMatch(normalizedUrl);
743
- // Split URL once, look up via trie
744
- const urlParts = normalizedUrl.split("/").filter(Boolean);
745
- const trie = getOrBuildAppTrie(routes);
746
- return trieMatch(trie, urlParts);
626
+ * Match a URL against App Router routes.
627
+ */
628
+ function matchAppRoute(url, routes) {
629
+ const pathname = url.split("?")[0];
630
+ let normalizedUrl = pathname === "/" ? "/" : pathname.replace(/\/$/, "");
631
+ normalizedUrl = normalizePathnameForRouteMatch(normalizedUrl);
632
+ const urlParts = normalizedUrl.split("/").filter(Boolean);
633
+ return trieMatch(getOrBuildAppTrie(routes), urlParts);
747
634
  }
635
+ //#endregion
636
+ export { appRouter, invalidateAppRouteCache, matchAppRoute };
637
+
748
638
  //# sourceMappingURL=app-router.js.map