@timber-js/app 0.2.0-alpha.18 → 0.2.0-alpha.181

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 (1026) hide show
  1. package/LICENSE +8 -0
  2. package/agent-skill.md +344 -0
  3. package/dist/_chunks/actions-O_LsyCE4.js +317 -0
  4. package/dist/_chunks/actions-O_LsyCE4.js.map +1 -0
  5. package/dist/_chunks/build-output-helper-DF5uScqS.js +158 -0
  6. package/dist/_chunks/build-output-helper-DF5uScqS.js.map +1 -0
  7. package/dist/_chunks/cache-api-B-lhk9p4.js +1202 -0
  8. package/dist/_chunks/cache-api-B-lhk9p4.js.map +1 -0
  9. package/dist/_chunks/canonicalize-DQHyFClh.js +248 -0
  10. package/dist/_chunks/canonicalize-DQHyFClh.js.map +1 -0
  11. package/dist/_chunks/cli-schema-sync-D3naS3eH.js +688 -0
  12. package/dist/_chunks/cli-schema-sync-D3naS3eH.js.map +1 -0
  13. package/dist/_chunks/cloudflare-AHoWYTYr.js +1188 -0
  14. package/dist/_chunks/cloudflare-AHoWYTYr.js.map +1 -0
  15. package/dist/_chunks/codec-registry-oOUxugz3.js +21 -0
  16. package/dist/_chunks/codec-registry-oOUxugz3.js.map +1 -0
  17. package/dist/_chunks/define-COtkxMRT.js +191 -0
  18. package/dist/_chunks/define-COtkxMRT.js.map +1 -0
  19. package/dist/_chunks/define-c4au4I9R.js +82 -0
  20. package/dist/_chunks/define-c4au4I9R.js.map +1 -0
  21. package/dist/_chunks/dist-BA3u1z3W.js +423 -0
  22. package/dist/_chunks/dist-BA3u1z3W.js.map +1 -0
  23. package/dist/_chunks/fast-hash-D6hIVt1Y.js +36 -0
  24. package/dist/_chunks/fast-hash-D6hIVt1Y.js.map +1 -0
  25. package/dist/_chunks/format-CfwjgPz9.js +14 -0
  26. package/dist/_chunks/format-CfwjgPz9.js.map +1 -0
  27. package/dist/_chunks/href-validation-CMc5JRls.js +141 -0
  28. package/dist/_chunks/href-validation-CMc5JRls.js.map +1 -0
  29. package/dist/_chunks/json-lossy-check-ClNvBM_3.js +63 -0
  30. package/dist/_chunks/json-lossy-check-ClNvBM_3.js.map +1 -0
  31. package/dist/_chunks/logger-AWfuX-KJ.js +1468 -0
  32. package/dist/_chunks/logger-AWfuX-KJ.js.map +1 -0
  33. package/dist/_chunks/navigation-root-bUDZLw74.js +124 -0
  34. package/dist/_chunks/navigation-root-bUDZLw74.js.map +1 -0
  35. package/dist/_chunks/plugin-context---kTF5v8.js +315 -0
  36. package/dist/_chunks/plugin-context---kTF5v8.js.map +1 -0
  37. package/dist/_chunks/registry-DbJPKoBp.js +20 -0
  38. package/dist/_chunks/registry-DbJPKoBp.js.map +1 -0
  39. package/dist/_chunks/resolve-schema-Dz3fcFUo.js +50 -0
  40. package/dist/_chunks/resolve-schema-Dz3fcFUo.js.map +1 -0
  41. package/dist/_chunks/router-ref-CtmF-aPv.js +28 -0
  42. package/dist/_chunks/router-ref-CtmF-aPv.js.map +1 -0
  43. package/dist/_chunks/schema-bridge-DT_Tn0Xf.js +119 -0
  44. package/dist/_chunks/schema-bridge-DT_Tn0Xf.js.map +1 -0
  45. package/dist/_chunks/segment-classify-Byy425ng.js +176 -0
  46. package/dist/_chunks/segment-classify-Byy425ng.js.map +1 -0
  47. package/dist/_chunks/segment-context-ZDnXDkbz.js +34 -0
  48. package/dist/_chunks/segment-context-ZDnXDkbz.js.map +1 -0
  49. package/dist/_chunks/sizeof-lXffQ1Vr.js +35 -0
  50. package/dist/_chunks/sizeof-lXffQ1Vr.js.map +1 -0
  51. package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-BOWsq18U.js} +1 -1
  52. package/dist/_chunks/ssr-data-BOWsq18U.js.map +1 -0
  53. package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-DFvWd-EA.js} +71 -26
  54. package/dist/_chunks/use-query-states-DFvWd-EA.js.map +1 -0
  55. package/dist/_chunks/use-segment-params-D1CzlgBo.js +151 -0
  56. package/dist/_chunks/use-segment-params-D1CzlgBo.js.map +1 -0
  57. package/dist/_chunks/walkers-BtTlKviE.js +1002 -0
  58. package/dist/_chunks/walkers-BtTlKviE.js.map +1 -0
  59. package/dist/adapters/build-output-helper.d.ts +29 -0
  60. package/dist/adapters/build-output-helper.d.ts.map +1 -0
  61. package/dist/adapters/cloudflare-dev.d.ts +109 -0
  62. package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
  63. package/dist/adapters/cloudflare-dev.js +73 -0
  64. package/dist/adapters/cloudflare-dev.js.map +1 -0
  65. package/dist/adapters/cloudflare-kv-cache.d.ts +65 -0
  66. package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
  67. package/dist/adapters/cloudflare-kv-cache.js +124 -0
  68. package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
  69. package/dist/adapters/cloudflare.d.ts +189 -21
  70. package/dist/adapters/cloudflare.d.ts.map +1 -1
  71. package/dist/adapters/cloudflare.js +2 -188
  72. package/dist/adapters/compress-module.d.ts +5 -4
  73. package/dist/adapters/compress-module.d.ts.map +1 -1
  74. package/dist/adapters/nitro.d.ts +41 -3
  75. package/dist/adapters/nitro.d.ts.map +1 -1
  76. package/dist/adapters/nitro.js +224 -172
  77. package/dist/adapters/nitro.js.map +1 -1
  78. package/dist/adapters/shared.d.ts +6 -0
  79. package/dist/adapters/shared.d.ts.map +1 -0
  80. package/dist/adapters/types.d.ts +2 -6
  81. package/dist/adapters/types.d.ts.map +1 -1
  82. package/dist/cache/cache-api.d.ts +48 -0
  83. package/dist/cache/cache-api.d.ts.map +1 -0
  84. package/dist/cache/handler-store.d.ts +33 -0
  85. package/dist/cache/handler-store.d.ts.map +1 -0
  86. package/dist/cache/index.d.ts +31 -8
  87. package/dist/cache/index.d.ts.map +1 -1
  88. package/dist/cache/index.js +3 -326
  89. package/dist/cache/invalidation-epoch.d.ts +43 -0
  90. package/dist/cache/invalidation-epoch.d.ts.map +1 -0
  91. package/dist/cache/json-lossy-check.d.ts +11 -0
  92. package/dist/cache/json-lossy-check.d.ts.map +1 -0
  93. package/dist/cache/redis-handler.d.ts +140 -8
  94. package/dist/cache/redis-handler.d.ts.map +1 -1
  95. package/dist/cache/singleflight.d.ts +19 -2
  96. package/dist/cache/singleflight.d.ts.map +1 -1
  97. package/dist/cache/sizeof.d.ts +22 -0
  98. package/dist/cache/sizeof.d.ts.map +1 -0
  99. package/dist/cache/stable-stringify.d.ts +9 -0
  100. package/dist/cache/stable-stringify.d.ts.map +1 -1
  101. package/dist/cache/store.d.ts +53 -0
  102. package/dist/cache/store.d.ts.map +1 -0
  103. package/dist/cache/stores/cloudflare-kv.d.ts +38 -0
  104. package/dist/cache/stores/cloudflare-kv.d.ts.map +1 -0
  105. package/dist/cache/stores/cloudflare-kv.js +29 -0
  106. package/dist/cache/stores/cloudflare-kv.js.map +1 -0
  107. package/dist/cache/stores/memory.d.ts +42 -0
  108. package/dist/cache/stores/memory.d.ts.map +1 -0
  109. package/dist/cache/stores/memory.js +90 -0
  110. package/dist/cache/stores/memory.js.map +1 -0
  111. package/dist/cache/stores/redis.d.ts +69 -0
  112. package/dist/cache/stores/redis.d.ts.map +1 -0
  113. package/dist/cache/stores/redis.js +35 -0
  114. package/dist/cache/stores/redis.js.map +1 -0
  115. package/dist/cache/stores/vercel.d.ts +36 -0
  116. package/dist/cache/stores/vercel.d.ts.map +1 -0
  117. package/dist/cache/stores/vercel.js +33 -0
  118. package/dist/cache/stores/vercel.js.map +1 -0
  119. package/dist/cache/tag-aware-handler.d.ts +52 -0
  120. package/dist/cache/tag-aware-handler.d.ts.map +1 -0
  121. package/dist/cache/timber-cache.d.ts +20 -10
  122. package/dist/cache/timber-cache.d.ts.map +1 -1
  123. package/dist/cdn/cloudflare-purge.d.ts +23 -0
  124. package/dist/cdn/cloudflare-purge.d.ts.map +1 -0
  125. package/dist/cdn/fastly-purge.d.ts +25 -0
  126. package/dist/cdn/fastly-purge.d.ts.map +1 -0
  127. package/dist/cdn/headers.d.ts +97 -0
  128. package/dist/cdn/headers.d.ts.map +1 -0
  129. package/dist/cdn/index.d.ts +5 -0
  130. package/dist/cdn/index.d.ts.map +1 -0
  131. package/dist/cdn/purge-store.d.ts +23 -0
  132. package/dist/cdn/purge-store.d.ts.map +1 -0
  133. package/dist/cdn/workers-cache-purge.d.ts +16 -0
  134. package/dist/cdn/workers-cache-purge.d.ts.map +1 -0
  135. package/dist/cli-schema-sync.d.ts +59 -0
  136. package/dist/cli-schema-sync.d.ts.map +1 -0
  137. package/dist/cli.d.ts +35 -2
  138. package/dist/cli.d.ts.map +1 -1
  139. package/dist/cli.js +113 -34
  140. package/dist/cli.js.map +1 -1
  141. package/dist/client/browser-dev.d.ts +37 -1
  142. package/dist/client/browser-dev.d.ts.map +1 -1
  143. package/dist/client/browser-entry/action-dispatch.d.ts +17 -0
  144. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -0
  145. package/dist/client/browser-entry/hmr.d.ts +21 -0
  146. package/dist/client/browser-entry/hmr.d.ts.map +1 -0
  147. package/dist/client/browser-entry/hydrate.d.ts +46 -0
  148. package/dist/client/browser-entry/hydrate.d.ts.map +1 -0
  149. package/dist/client/browser-entry/index.d.ts +29 -0
  150. package/dist/client/browser-entry/index.d.ts.map +1 -0
  151. package/dist/client/browser-entry/post-hydration.d.ts +26 -0
  152. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
  153. package/dist/client/browser-entry/router-init.d.ts +27 -0
  154. package/dist/client/browser-entry/router-init.d.ts.map +1 -0
  155. package/dist/client/browser-entry/rsc-stream.d.ts +24 -0
  156. package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -0
  157. package/dist/client/browser-entry/scroll.d.ts +28 -0
  158. package/dist/client/browser-entry/scroll.d.ts.map +1 -0
  159. package/dist/client/error-boundary.d.ts +12 -5
  160. package/dist/client/error-boundary.d.ts.map +1 -1
  161. package/dist/client/error-boundary.js +47 -10
  162. package/dist/client/error-boundary.js.map +1 -1
  163. package/dist/client/error-reconstituter.d.ts +61 -0
  164. package/dist/client/error-reconstituter.d.ts.map +1 -0
  165. package/dist/client/form.d.ts +16 -27
  166. package/dist/client/form.d.ts.map +1 -1
  167. package/dist/client/history.d.ts +21 -6
  168. package/dist/client/history.d.ts.map +1 -1
  169. package/dist/client/index.d.ts +10 -24
  170. package/dist/client/index.d.ts.map +1 -1
  171. package/dist/client/index.js +185 -1134
  172. package/dist/client/index.js.map +1 -1
  173. package/dist/client/internal.d.ts +19 -0
  174. package/dist/client/internal.d.ts.map +1 -0
  175. package/dist/client/internal.js +938 -0
  176. package/dist/client/internal.js.map +1 -0
  177. package/dist/client/link.d.ts +69 -60
  178. package/dist/client/link.d.ts.map +1 -1
  179. package/dist/client/navigation-api.d.ts +121 -0
  180. package/dist/client/navigation-api.d.ts.map +1 -0
  181. package/dist/client/navigation-context.d.ts +3 -2
  182. package/dist/client/navigation-context.d.ts.map +1 -1
  183. package/dist/client/navigation-root.d.ts +119 -0
  184. package/dist/client/navigation-root.d.ts.map +1 -0
  185. package/dist/client/nuqs-adapter.d.ts +1 -1
  186. package/dist/client/nuqs-adapter.d.ts.map +1 -1
  187. package/dist/client/router-ref.d.ts +1 -1
  188. package/dist/client/router.d.ts +99 -14
  189. package/dist/client/router.d.ts.map +1 -1
  190. package/dist/client/rsc-fetch.d.ts +62 -15
  191. package/dist/client/rsc-fetch.d.ts.map +1 -1
  192. package/dist/client/segment-cache.d.ts +30 -7
  193. package/dist/client/segment-cache.d.ts.map +1 -1
  194. package/dist/client/segment-outlet.d.ts +57 -0
  195. package/dist/client/segment-outlet.d.ts.map +1 -0
  196. package/dist/client/segment-update-context.d.ts +21 -0
  197. package/dist/client/segment-update-context.d.ts.map +1 -0
  198. package/dist/client/shallow-url.d.ts +10 -0
  199. package/dist/client/shallow-url.d.ts.map +1 -0
  200. package/dist/client/slot-context.d.ts +31 -0
  201. package/dist/client/slot-context.d.ts.map +1 -0
  202. package/dist/client/slot-outlet.d.ts +16 -0
  203. package/dist/client/slot-outlet.d.ts.map +1 -0
  204. package/dist/client/slot-provider.d.ts +25 -0
  205. package/dist/client/slot-provider.d.ts.map +1 -0
  206. package/dist/client/ssr-data.d.ts +13 -4
  207. package/dist/client/ssr-data.d.ts.map +1 -1
  208. package/dist/client/state.d.ts +1 -1
  209. package/dist/client/top-loader.d.ts +5 -5
  210. package/dist/client/top-loader.d.ts.map +1 -1
  211. package/dist/client/use-cookie.d.ts +12 -0
  212. package/dist/client/use-cookie.d.ts.map +1 -1
  213. package/dist/client/use-link-status.d.ts +5 -5
  214. package/dist/client/use-link-status.d.ts.map +1 -1
  215. package/dist/client/use-pathname.d.ts.map +1 -1
  216. package/dist/client/use-pending-navigation.d.ts +23 -0
  217. package/dist/client/use-pending-navigation.d.ts.map +1 -0
  218. package/dist/client/use-query-states.d.ts +1 -1
  219. package/dist/client/use-query-states.d.ts.map +1 -1
  220. package/dist/client/use-router.d.ts +1 -1
  221. package/dist/client/use-router.d.ts.map +1 -1
  222. package/dist/client/use-search-params.d.ts +12 -5
  223. package/dist/client/use-search-params.d.ts.map +1 -1
  224. package/dist/client/{use-params.d.ts → use-segment-params.d.ts} +8 -6
  225. package/dist/client/use-segment-params.d.ts.map +1 -0
  226. package/dist/codec.d.ts +69 -0
  227. package/dist/codec.d.ts.map +1 -0
  228. package/dist/codec.js +76 -0
  229. package/dist/codec.js.map +1 -0
  230. package/dist/config-types.d.ts +284 -0
  231. package/dist/config-types.d.ts.map +1 -0
  232. package/dist/config-validation.d.ts +51 -0
  233. package/dist/config-validation.d.ts.map +1 -0
  234. package/dist/content/index.d.ts +1 -10
  235. package/dist/content/index.d.ts.map +1 -1
  236. package/dist/content/index.js +0 -2
  237. package/dist/cookies/define-cookie.d.ts +58 -25
  238. package/dist/cookies/define-cookie.d.ts.map +1 -1
  239. package/dist/cookies/index.d.ts +2 -1
  240. package/dist/cookies/index.d.ts.map +1 -1
  241. package/dist/cookies/index.js +257 -36
  242. package/dist/cookies/index.js.map +1 -1
  243. package/dist/cookies/json-cookie.d.ts +64 -0
  244. package/dist/cookies/json-cookie.d.ts.map +1 -0
  245. package/dist/cookies/validation.d.ts +34 -0
  246. package/dist/cookies/validation.d.ts.map +1 -0
  247. package/dist/dev-tools/404-page.d.ts +50 -0
  248. package/dist/dev-tools/404-page.d.ts.map +1 -0
  249. package/dist/dev-tools/browser-logs.d.ts +40 -0
  250. package/dist/dev-tools/browser-logs.d.ts.map +1 -0
  251. package/dist/dev-tools/dev-page-shell.d.ts +78 -0
  252. package/dist/dev-tools/dev-page-shell.d.ts.map +1 -0
  253. package/dist/dev-tools/error-page.d.ts +32 -0
  254. package/dist/dev-tools/error-page.d.ts.map +1 -0
  255. package/dist/dev-tools/holding-server.d.ts +54 -0
  256. package/dist/dev-tools/holding-server.d.ts.map +1 -0
  257. package/dist/dev-tools/hydration-overlay.d.ts +11 -0
  258. package/dist/dev-tools/hydration-overlay.d.ts.map +1 -0
  259. package/dist/dev-tools/index.d.ts +31 -0
  260. package/dist/dev-tools/index.d.ts.map +1 -0
  261. package/dist/dev-tools/instrumentation.d.ts +59 -0
  262. package/dist/dev-tools/instrumentation.d.ts.map +1 -0
  263. package/dist/{server/dev-logger.d.ts → dev-tools/logger.d.ts} +1 -1
  264. package/dist/dev-tools/logger.d.ts.map +1 -0
  265. package/dist/{plugins/dev-logs.d.ts → dev-tools/logs.d.ts} +17 -3
  266. package/dist/dev-tools/logs.d.ts.map +1 -0
  267. package/dist/dev-tools/overlay.d.ts +91 -0
  268. package/dist/dev-tools/overlay.d.ts.map +1 -0
  269. package/dist/dev-tools/stack-classifier.d.ts +34 -0
  270. package/dist/dev-tools/stack-classifier.d.ts.map +1 -0
  271. package/dist/dev-tools/terminal.d.ts +28 -0
  272. package/dist/dev-tools/terminal.d.ts.map +1 -0
  273. package/dist/fonts/ast-walk.d.ts +68 -0
  274. package/dist/fonts/ast-walk.d.ts.map +1 -0
  275. package/dist/fonts/ast.d.ts +110 -6
  276. package/dist/fonts/ast.d.ts.map +1 -1
  277. package/dist/fonts/bundle.d.ts +50 -0
  278. package/dist/fonts/bundle.d.ts.map +1 -0
  279. package/dist/fonts/dev-middleware.d.ts +22 -0
  280. package/dist/fonts/dev-middleware.d.ts.map +1 -0
  281. package/dist/fonts/fallbacks.d.ts +0 -7
  282. package/dist/fonts/fallbacks.d.ts.map +1 -1
  283. package/dist/fonts/google.d.ts +4 -2
  284. package/dist/fonts/google.d.ts.map +1 -1
  285. package/dist/fonts/local.d.ts +4 -4
  286. package/dist/fonts/local.d.ts.map +1 -1
  287. package/dist/fonts/paths.d.ts +43 -0
  288. package/dist/fonts/paths.d.ts.map +1 -0
  289. package/dist/fonts/pipeline.d.ts +177 -0
  290. package/dist/fonts/pipeline.d.ts.map +1 -0
  291. package/dist/fonts/transform.d.ts +82 -0
  292. package/dist/fonts/transform.d.ts.map +1 -0
  293. package/dist/fonts/types.d.ts +47 -1
  294. package/dist/fonts/types.d.ts.map +1 -1
  295. package/dist/fonts/virtual-modules.d.ts +77 -0
  296. package/dist/fonts/virtual-modules.d.ts.map +1 -0
  297. package/dist/index.d.ts +46 -180
  298. package/dist/index.d.ts.map +1 -1
  299. package/dist/index.js +9243 -14093
  300. package/dist/index.js.map +1 -1
  301. package/dist/params/codec-registry.d.ts +26 -0
  302. package/dist/params/codec-registry.d.ts.map +1 -0
  303. package/dist/params/define-schema.d.ts +81 -0
  304. package/dist/params/define-schema.d.ts.map +1 -0
  305. package/dist/params/index.d.ts +5 -0
  306. package/dist/params/index.d.ts.map +1 -0
  307. package/dist/params/index.js +34 -0
  308. package/dist/params/index.js.map +1 -0
  309. package/dist/params/resolve-schema.d.ts +34 -0
  310. package/dist/params/resolve-schema.d.ts.map +1 -0
  311. package/dist/plugin-context.d.ts +217 -0
  312. package/dist/plugin-context.d.ts.map +1 -0
  313. package/dist/plugins/adapter-build.d.ts +21 -1
  314. package/dist/plugins/adapter-build.d.ts.map +1 -1
  315. package/dist/plugins/build-manifest.d.ts +7 -3
  316. package/dist/plugins/build-manifest.d.ts.map +1 -1
  317. package/dist/plugins/build-report.d.ts +43 -7
  318. package/dist/plugins/build-report.d.ts.map +1 -1
  319. package/dist/plugins/cache.d.ts +64 -0
  320. package/dist/plugins/cache.d.ts.map +1 -0
  321. package/dist/plugins/callsite-ast.d.ts +117 -0
  322. package/dist/plugins/callsite-ast.d.ts.map +1 -0
  323. package/dist/plugins/callsite-jsx.d.ts +35 -0
  324. package/dist/plugins/callsite-jsx.d.ts.map +1 -0
  325. package/dist/plugins/chunks.d.ts +11 -4
  326. package/dist/plugins/chunks.d.ts.map +1 -1
  327. package/dist/plugins/client-chunks.d.ts +40 -0
  328. package/dist/plugins/client-chunks.d.ts.map +1 -0
  329. package/dist/plugins/cloudflare-wasm.d.ts +21 -0
  330. package/dist/plugins/cloudflare-wasm.d.ts.map +1 -0
  331. package/dist/plugins/content.d.ts +1 -1
  332. package/dist/plugins/content.d.ts.map +1 -1
  333. package/dist/plugins/dev-server.d.ts +17 -1
  334. package/dist/plugins/dev-server.d.ts.map +1 -1
  335. package/dist/plugins/entries.d.ts +28 -4
  336. package/dist/plugins/entries.d.ts.map +1 -1
  337. package/dist/plugins/fonts.d.ts +16 -73
  338. package/dist/plugins/fonts.d.ts.map +1 -1
  339. package/dist/plugins/mdx.d.ts +1 -1
  340. package/dist/plugins/mdx.d.ts.map +1 -1
  341. package/dist/plugins/prebuilt-capture.d.ts +60 -0
  342. package/dist/plugins/prebuilt-capture.d.ts.map +1 -0
  343. package/dist/plugins/prebuilt-options-analysis.d.ts +40 -0
  344. package/dist/plugins/prebuilt-options-analysis.d.ts.map +1 -0
  345. package/dist/plugins/prebuilt.d.ts +82 -0
  346. package/dist/plugins/prebuilt.d.ts.map +1 -0
  347. package/dist/plugins/prerender-sugar.d.ts +42 -0
  348. package/dist/plugins/prerender-sugar.d.ts.map +1 -0
  349. package/dist/plugins/request-dep.d.ts +21 -0
  350. package/dist/plugins/request-dep.d.ts.map +1 -0
  351. package/dist/plugins/routing.d.ts +1 -1
  352. package/dist/plugins/routing.d.ts.map +1 -1
  353. package/dist/plugins/server-bundle.d.ts.map +1 -1
  354. package/dist/plugins/shims.d.ts +29 -5
  355. package/dist/plugins/shims.d.ts.map +1 -1
  356. package/dist/plugins/static-build.d.ts +5 -26
  357. package/dist/plugins/static-build.d.ts.map +1 -1
  358. package/dist/routing/codegen-shared.d.ts +67 -0
  359. package/dist/routing/codegen-shared.d.ts.map +1 -0
  360. package/dist/routing/codegen-types.d.ts +64 -0
  361. package/dist/routing/codegen-types.d.ts.map +1 -0
  362. package/dist/routing/codegen.d.ts +7 -2
  363. package/dist/routing/codegen.d.ts.map +1 -1
  364. package/dist/routing/convention-lint.d.ts +41 -0
  365. package/dist/routing/convention-lint.d.ts.map +1 -0
  366. package/dist/routing/export-detect.d.ts +56 -0
  367. package/dist/routing/export-detect.d.ts.map +1 -0
  368. package/dist/routing/file-cache.d.ts +8 -0
  369. package/dist/routing/file-cache.d.ts.map +1 -0
  370. package/dist/routing/index.d.ts +7 -1
  371. package/dist/routing/index.d.ts.map +1 -1
  372. package/dist/routing/index.js +4 -2
  373. package/dist/routing/interception.d.ts +0 -5
  374. package/dist/routing/interception.d.ts.map +1 -1
  375. package/dist/routing/link-codegen.d.ts +90 -0
  376. package/dist/routing/link-codegen.d.ts.map +1 -0
  377. package/dist/routing/manifest-codegen.d.ts +32 -0
  378. package/dist/routing/manifest-codegen.d.ts.map +1 -0
  379. package/dist/routing/scanner.d.ts +1 -10
  380. package/dist/routing/scanner.d.ts.map +1 -1
  381. package/dist/routing/schema-validation.d.ts +35 -0
  382. package/dist/routing/schema-validation.d.ts.map +1 -0
  383. package/dist/routing/segment-classify.d.ts +81 -0
  384. package/dist/routing/segment-classify.d.ts.map +1 -0
  385. package/dist/routing/segment-codegen.d.ts +38 -0
  386. package/dist/routing/segment-codegen.d.ts.map +1 -0
  387. package/dist/routing/types.d.ts +81 -25
  388. package/dist/routing/types.d.ts.map +1 -1
  389. package/dist/routing/walkers.d.ts +51 -0
  390. package/dist/routing/walkers.d.ts.map +1 -0
  391. package/dist/rsc-runtime/rsc.d.ts +1 -1
  392. package/dist/rsc-runtime/rsc.d.ts.map +1 -1
  393. package/dist/rsc-runtime/ssr.d.ts +12 -0
  394. package/dist/rsc-runtime/ssr.d.ts.map +1 -1
  395. package/dist/schema-bridge.d.ts +91 -0
  396. package/dist/schema-bridge.d.ts.map +1 -0
  397. package/dist/search-params/define.d.ts +188 -0
  398. package/dist/search-params/define.d.ts.map +1 -0
  399. package/dist/search-params/index.d.ts +4 -7
  400. package/dist/search-params/index.d.ts.map +1 -1
  401. package/dist/search-params/index.js +34 -441
  402. package/dist/search-params/index.js.map +1 -1
  403. package/dist/search-params/registry.d.ts +2 -2
  404. package/dist/search-params/registry.d.ts.map +1 -1
  405. package/dist/search-params/wrappers.d.ts +53 -0
  406. package/dist/search-params/wrappers.d.ts.map +1 -0
  407. package/dist/segment-params/define.d.ts +89 -0
  408. package/dist/segment-params/define.d.ts.map +1 -0
  409. package/dist/segment-params/index.d.ts +3 -0
  410. package/dist/segment-params/index.d.ts.map +1 -0
  411. package/dist/segment-params/index.js +2 -0
  412. package/dist/server/access-gate.d.ts +8 -3
  413. package/dist/server/access-gate.d.ts.map +1 -1
  414. package/dist/server/action-client.d.ts +42 -7
  415. package/dist/server/action-client.d.ts.map +1 -1
  416. package/dist/server/action-encryption.d.ts +76 -0
  417. package/dist/server/action-encryption.d.ts.map +1 -0
  418. package/dist/server/action-handler.d.ts +35 -1
  419. package/dist/server/action-handler.d.ts.map +1 -1
  420. package/dist/server/actions.d.ts +6 -30
  421. package/dist/server/actions.d.ts.map +1 -1
  422. package/dist/server/als-registry.d.ts +93 -11
  423. package/dist/server/als-registry.d.ts.map +1 -1
  424. package/dist/server/asset-headers.d.ts +8 -18
  425. package/dist/server/asset-headers.d.ts.map +1 -1
  426. package/dist/server/body-limits.d.ts.map +1 -1
  427. package/dist/server/build-manifest.d.ts +12 -29
  428. package/dist/server/build-manifest.d.ts.map +1 -1
  429. package/dist/server/canonicalize.d.ts +10 -0
  430. package/dist/server/canonicalize.d.ts.map +1 -1
  431. package/dist/server/coalesce-tick.d.ts +40 -0
  432. package/dist/server/coalesce-tick.d.ts.map +1 -0
  433. package/dist/server/cookie-context.d.ts +170 -0
  434. package/dist/server/cookie-context.d.ts.map +1 -0
  435. package/dist/server/cookie-parsing.d.ts +65 -0
  436. package/dist/server/cookie-parsing.d.ts.map +1 -0
  437. package/dist/server/csrf.d.ts +3 -2
  438. package/dist/server/csrf.d.ts.map +1 -1
  439. package/dist/server/default-logger.d.ts +22 -0
  440. package/dist/server/default-logger.d.ts.map +1 -0
  441. package/dist/server/deny-boundary.d.ts +117 -0
  442. package/dist/server/deny-boundary.d.ts.map +1 -0
  443. package/dist/server/deny-renderer.d.ts +2 -2
  444. package/dist/server/deny-renderer.d.ts.map +1 -1
  445. package/dist/server/dev-source-map.d.ts +22 -0
  446. package/dist/server/dev-source-map.d.ts.map +1 -0
  447. package/dist/server/early-hints-sender.d.ts.map +1 -1
  448. package/dist/server/early-hints.d.ts +13 -11
  449. package/dist/server/early-hints.d.ts.map +1 -1
  450. package/dist/server/error-boundary-wrapper.d.ts +7 -1
  451. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  452. package/dist/server/fallback-error.d.ts +12 -7
  453. package/dist/server/fallback-error.d.ts.map +1 -1
  454. package/dist/server/flight-injection-state.d.ts +66 -0
  455. package/dist/server/flight-injection-state.d.ts.map +1 -0
  456. package/dist/server/flight-scripts.d.ts +42 -0
  457. package/dist/server/flight-scripts.d.ts.map +1 -0
  458. package/dist/server/form-data.d.ts +41 -0
  459. package/dist/server/form-data.d.ts.map +1 -1
  460. package/dist/server/html-injector-core.d.ts +242 -0
  461. package/dist/server/html-injector-core.d.ts.map +1 -0
  462. package/dist/server/html-injectors.d.ts +82 -41
  463. package/dist/server/html-injectors.d.ts.map +1 -1
  464. package/dist/server/index.d.ts +11 -47
  465. package/dist/server/index.d.ts.map +1 -1
  466. package/dist/server/index.js +182 -2906
  467. package/dist/server/index.js.map +1 -1
  468. package/dist/server/internal.d.ts +49 -0
  469. package/dist/server/internal.d.ts.map +1 -0
  470. package/dist/server/internal.js +3892 -0
  471. package/dist/server/internal.js.map +1 -0
  472. package/dist/server/logger.d.ts +39 -7
  473. package/dist/server/logger.d.ts.map +1 -1
  474. package/dist/server/metadata-routes.d.ts +60 -11
  475. package/dist/server/metadata-routes.d.ts.map +1 -1
  476. package/dist/server/metadata.d.ts +8 -0
  477. package/dist/server/metadata.d.ts.map +1 -1
  478. package/dist/server/middleware-runner.d.ts +19 -4
  479. package/dist/server/middleware-runner.d.ts.map +1 -1
  480. package/dist/server/node-stream-transforms.d.ts +119 -0
  481. package/dist/server/node-stream-transforms.d.ts.map +1 -0
  482. package/dist/server/param-coercion.d.ts +54 -0
  483. package/dist/server/param-coercion.d.ts.map +1 -0
  484. package/dist/server/pipeline-helpers.d.ts +95 -0
  485. package/dist/server/pipeline-helpers.d.ts.map +1 -0
  486. package/dist/server/pipeline-interception.d.ts +1 -1
  487. package/dist/server/pipeline-interception.d.ts.map +1 -1
  488. package/dist/server/pipeline-metadata.d.ts +6 -0
  489. package/dist/server/pipeline-metadata.d.ts.map +1 -1
  490. package/dist/server/pipeline-outcome.d.ts +49 -0
  491. package/dist/server/pipeline-outcome.d.ts.map +1 -0
  492. package/dist/server/pipeline-phases.d.ts +59 -0
  493. package/dist/server/pipeline-phases.d.ts.map +1 -0
  494. package/dist/server/pipeline.d.ts +140 -19
  495. package/dist/server/pipeline.d.ts.map +1 -1
  496. package/dist/server/port-resolution.d.ts +117 -0
  497. package/dist/server/port-resolution.d.ts.map +1 -0
  498. package/dist/server/prebuilt/cache-key.d.ts +62 -0
  499. package/dist/server/prebuilt/cache-key.d.ts.map +1 -0
  500. package/dist/server/prebuilt/capture-state.d.ts +57 -0
  501. package/dist/server/prebuilt/capture-state.d.ts.map +1 -0
  502. package/dist/server/prebuilt/key-discipline.d.ts +23 -0
  503. package/dist/server/prebuilt/key-discipline.d.ts.map +1 -0
  504. package/dist/server/prebuilt/manifest-tag-index.d.ts +27 -0
  505. package/dist/server/prebuilt/manifest-tag-index.d.ts.map +1 -0
  506. package/dist/server/prebuilt/overlay.d.ts +100 -0
  507. package/dist/server/prebuilt/overlay.d.ts.map +1 -0
  508. package/dist/server/prebuilt/payload-source.d.ts +78 -0
  509. package/dist/server/prebuilt/payload-source.d.ts.map +1 -0
  510. package/dist/server/prebuilt/slots.d.ts +99 -0
  511. package/dist/server/prebuilt/slots.d.ts.map +1 -0
  512. package/dist/server/prebuilt/synthetic-store.d.ts +66 -0
  513. package/dist/server/prebuilt/synthetic-store.d.ts.map +1 -0
  514. package/dist/server/prebuilt-builder.d.ts +120 -0
  515. package/dist/server/prebuilt-builder.d.ts.map +1 -0
  516. package/dist/server/prebuilt-runtime.d.ts +111 -0
  517. package/dist/server/prebuilt-runtime.d.ts.map +1 -0
  518. package/dist/server/primitives.d.ts +88 -43
  519. package/dist/server/primitives.d.ts.map +1 -1
  520. package/dist/server/render-timeout.d.ts +51 -0
  521. package/dist/server/render-timeout.d.ts.map +1 -0
  522. package/dist/server/render-utils.d.ts +25 -0
  523. package/dist/server/render-utils.d.ts.map +1 -0
  524. package/dist/server/request-context.d.ts +62 -107
  525. package/dist/server/request-context.d.ts.map +1 -1
  526. package/dist/server/request-dep.d.ts +15 -0
  527. package/dist/server/request-dep.d.ts.map +1 -0
  528. package/dist/server/route-element-builder.d.ts +53 -25
  529. package/dist/server/route-element-builder.d.ts.map +1 -1
  530. package/dist/server/route-handler.d.ts.map +1 -1
  531. package/dist/server/route-matcher.d.ts +25 -36
  532. package/dist/server/route-matcher.d.ts.map +1 -1
  533. package/dist/server/rsc-entry/action-middleware-runner.d.ts +66 -0
  534. package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -0
  535. package/dist/server/rsc-entry/api-handler.d.ts +12 -3
  536. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  537. package/dist/server/rsc-entry/deny-fallback.d.ts +29 -0
  538. package/dist/server/rsc-entry/deny-fallback.d.ts.map +1 -0
  539. package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
  540. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  541. package/dist/server/rsc-entry/helpers.d.ts +69 -37
  542. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  543. package/dist/server/rsc-entry/index.d.ts +28 -6
  544. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  545. package/dist/server/rsc-entry/render-route.d.ts +51 -0
  546. package/dist/server/rsc-entry/render-route.d.ts.map +1 -0
  547. package/dist/server/rsc-entry/revalidate-renderer.d.ts +108 -0
  548. package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -0
  549. package/dist/server/rsc-entry/rsc-payload.d.ts +6 -6
  550. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  551. package/dist/server/rsc-entry/rsc-stream.d.ts +25 -1
  552. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  553. package/dist/server/rsc-entry/ssr-bridge.d.ts +5 -1
  554. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  555. package/dist/server/rsc-entry/ssr-renderer.d.ts +36 -4
  556. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  557. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +89 -0
  558. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -0
  559. package/dist/server/safe-load.d.ts +46 -0
  560. package/dist/server/safe-load.d.ts.map +1 -0
  561. package/dist/server/sensitive-fields.d.ts +74 -0
  562. package/dist/server/sensitive-fields.d.ts.map +1 -0
  563. package/dist/server/sitemap-generator.d.ts +129 -0
  564. package/dist/server/sitemap-generator.d.ts.map +1 -0
  565. package/dist/server/sitemap-handler.d.ts +22 -0
  566. package/dist/server/sitemap-handler.d.ts.map +1 -0
  567. package/dist/server/slot-resolver.d.ts +66 -5
  568. package/dist/server/slot-resolver.d.ts.map +1 -1
  569. package/dist/server/ssr-bridge-types.d.ts +121 -0
  570. package/dist/server/ssr-bridge-types.d.ts.map +1 -0
  571. package/dist/server/ssr-entry.d.ts +2 -43
  572. package/dist/server/ssr-entry.d.ts.map +1 -1
  573. package/dist/server/ssr-render.d.ts +64 -21
  574. package/dist/server/ssr-render.d.ts.map +1 -1
  575. package/dist/server/ssr-wrappers.d.ts +50 -0
  576. package/dist/server/ssr-wrappers.d.ts.map +1 -0
  577. package/dist/server/state-tree-diff.d.ts +72 -9
  578. package/dist/server/state-tree-diff.d.ts.map +1 -1
  579. package/dist/server/status-code-resolver.d.ts +22 -11
  580. package/dist/server/status-code-resolver.d.ts.map +1 -1
  581. package/dist/server/stream-utils.d.ts +47 -0
  582. package/dist/server/stream-utils.d.ts.map +1 -0
  583. package/dist/server/tracing.d.ts +44 -9
  584. package/dist/server/tracing.d.ts.map +1 -1
  585. package/dist/server/tree-builder.d.ts +69 -30
  586. package/dist/server/tree-builder.d.ts.map +1 -1
  587. package/dist/server/tree-match.d.ts +49 -0
  588. package/dist/server/tree-match.d.ts.map +1 -0
  589. package/dist/server/types.d.ts +71 -6
  590. package/dist/server/types.d.ts.map +1 -1
  591. package/dist/server/utils/escape-html.d.ts +14 -0
  592. package/dist/server/utils/escape-html.d.ts.map +1 -0
  593. package/dist/server/utils/mdx-file.d.ts +15 -0
  594. package/dist/server/utils/mdx-file.d.ts.map +1 -0
  595. package/dist/server/version-skew.d.ts +61 -0
  596. package/dist/server/version-skew.d.ts.map +1 -0
  597. package/dist/server/workers-cache-bridge.d.ts +26 -0
  598. package/dist/server/workers-cache-bridge.d.ts.map +1 -0
  599. package/dist/shared/href-validation.d.ts +49 -0
  600. package/dist/shared/href-validation.d.ts.map +1 -0
  601. package/dist/shared/merge-search-params.d.ts +22 -0
  602. package/dist/shared/merge-search-params.d.ts.map +1 -0
  603. package/dist/shared/redirect-type.d.ts +17 -0
  604. package/dist/shared/redirect-type.d.ts.map +1 -0
  605. package/dist/shims/font-google.d.ts +1 -1
  606. package/dist/shims/font-google.d.ts.map +1 -1
  607. package/dist/shims/font-google.js +42 -0
  608. package/dist/shims/font-google.js.map +1 -0
  609. package/dist/shims/font-local.d.ts +26 -0
  610. package/dist/shims/font-local.d.ts.map +1 -0
  611. package/dist/shims/font-local.js +20 -0
  612. package/dist/shims/font-local.js.map +1 -0
  613. package/dist/shims/headers.d.ts +53 -1
  614. package/dist/shims/headers.d.ts.map +1 -1
  615. package/dist/shims/image.d.ts +120 -120
  616. package/dist/shims/image.d.ts.map +1 -1
  617. package/dist/shims/navigation-client.d.ts +35 -11
  618. package/dist/shims/navigation-client.d.ts.map +1 -1
  619. package/dist/shims/navigation.d.ts +11 -5
  620. package/dist/shims/navigation.d.ts.map +1 -1
  621. package/dist/utils/state-machine.d.ts +80 -0
  622. package/dist/utils/state-machine.d.ts.map +1 -0
  623. package/docs/api/30-api-server.mdx +233 -0
  624. package/docs/api/31-api-client.mdx +161 -0
  625. package/docs/api/32-api-cache.mdx +311 -0
  626. package/docs/api/33-api-search-params.mdx +154 -0
  627. package/docs/api/34-api-config.mdx +325 -0
  628. package/docs/api/35-api-typescript.mdx +170 -0
  629. package/docs/api/36-cli.mdx +143 -0
  630. package/docs/learn/00-introduction.mdx +109 -0
  631. package/docs/learn/01-quick-start.mdx +94 -0
  632. package/docs/learn/02-pages-and-layouts.mdx +147 -0
  633. package/docs/learn/03-fetching-data.mdx +211 -0
  634. package/docs/learn/03b-access-control.mdx +130 -0
  635. package/docs/learn/04-loading-states.mdx +67 -0
  636. package/docs/learn/04b-the-flush-point.mdx +115 -0
  637. package/docs/learn/05-typed-params.mdx +275 -0
  638. package/docs/learn/06-forms-and-actions.mdx +146 -0
  639. package/docs/learn/07-typed-routes.mdx +127 -0
  640. package/docs/learn/08-streaming.mdx +146 -0
  641. package/docs/learn/09-caching.mdx +252 -0
  642. package/docs/learn/10-middleware.mdx +157 -0
  643. package/docs/learn/11-error-handling.mdx +156 -0
  644. package/docs/learn/12-client-navigation.mdx +176 -0
  645. package/docs/learn/13-configuration.mdx +162 -0
  646. package/docs/learn/14-deploying.mdx +264 -0
  647. package/docs/more/01-advanced-routing.mdx +173 -0
  648. package/docs/more/02-advanced-forms.mdx +137 -0
  649. package/docs/more/03-coming-from-nextjs.mdx +186 -0
  650. package/docs/more/04-metadata-and-fonts.mdx +193 -0
  651. package/docs/more/04b-mdx.mdx +209 -0
  652. package/docs/more/05-content-collections.mdx +90 -0
  653. package/docs/more/06-instrumentation.mdx +214 -0
  654. package/docs/more/07-security.mdx +129 -0
  655. package/docs/more/08-developer-experience.mdx +134 -0
  656. package/docs/more/40-why-timber.mdx +50 -0
  657. package/docs/more/41-timber-vs-nextjs.mdx +81 -0
  658. package/docs/more/42-timber-vs-others.mdx +68 -0
  659. package/docs/more/50-ai-agent-instructions.mdx +169 -0
  660. package/llms.txt +55 -0
  661. package/package.json +105 -26
  662. package/src/adapters/build-output-helper.ts +199 -0
  663. package/src/adapters/cloudflare-dev.ts +177 -0
  664. package/src/adapters/cloudflare-kv-cache.ts +204 -0
  665. package/src/adapters/cloudflare.ts +620 -129
  666. package/src/adapters/compress-module.ts +27 -92
  667. package/src/adapters/nitro.ts +266 -122
  668. package/src/adapters/raw-imports.d.ts +5 -0
  669. package/src/adapters/shared.ts +68 -0
  670. package/src/adapters/types.ts +2 -7
  671. package/src/adapters/wrangler.d.ts +7 -0
  672. package/src/cache/cache-api.ts +107 -0
  673. package/src/cache/handler-store.ts +76 -0
  674. package/src/cache/index.ts +114 -21
  675. package/src/cache/invalidation-epoch.ts +93 -0
  676. package/src/cache/json-lossy-check.ts +75 -0
  677. package/src/cache/redis-handler.ts +197 -19
  678. package/src/cache/singleflight.ts +64 -6
  679. package/src/cache/sizeof.ts +33 -0
  680. package/src/cache/stable-stringify.ts +65 -2
  681. package/src/cache/store.ts +71 -0
  682. package/src/cache/stores/cloudflare-kv.ts +52 -0
  683. package/src/cache/stores/memory.ts +125 -0
  684. package/src/cache/stores/redis.ts +97 -0
  685. package/src/cache/stores/vercel.ts +59 -0
  686. package/src/cache/tag-aware-handler.ts +237 -0
  687. package/src/cache/timber-cache.ts +161 -36
  688. package/src/cdn/cloudflare-purge.ts +50 -0
  689. package/src/cdn/fastly-purge.ts +63 -0
  690. package/src/cdn/headers.ts +153 -0
  691. package/src/cdn/index.ts +17 -0
  692. package/src/cdn/purge-store.ts +34 -0
  693. package/src/cdn/workers-cache-purge.ts +30 -0
  694. package/src/cli-schema-sync.ts +401 -0
  695. package/src/cli.ts +167 -34
  696. package/src/client/browser-dev.ts +156 -1
  697. package/src/client/browser-entry/action-dispatch.ts +124 -0
  698. package/src/client/browser-entry/hmr.ts +70 -0
  699. package/src/client/browser-entry/hydrate.ts +187 -0
  700. package/src/client/browser-entry/index.ts +113 -0
  701. package/src/client/browser-entry/post-hydration.ts +110 -0
  702. package/src/client/browser-entry/router-init.ts +286 -0
  703. package/src/client/browser-entry/rsc-stream.ts +157 -0
  704. package/src/client/browser-entry/scroll.ts +50 -0
  705. package/src/client/error-boundary.tsx +127 -22
  706. package/src/client/error-reconstituter.tsx +79 -0
  707. package/src/client/form.tsx +31 -32
  708. package/src/client/history.ts +21 -6
  709. package/src/client/index.ts +67 -45
  710. package/src/client/internal.ts +58 -0
  711. package/src/client/link.tsx +349 -150
  712. package/src/client/navigation-api.ts +345 -0
  713. package/src/client/navigation-context.ts +15 -7
  714. package/src/client/navigation-root.tsx +355 -0
  715. package/src/client/nuqs-adapter.tsx +16 -3
  716. package/src/client/router-ref.ts +1 -1
  717. package/src/client/router.ts +589 -215
  718. package/src/client/rsc-fetch.ts +251 -34
  719. package/src/client/segment-cache.ts +105 -17
  720. package/src/client/segment-outlet.tsx +141 -0
  721. package/src/client/segment-update-context.ts +42 -0
  722. package/src/client/shallow-url.ts +22 -0
  723. package/src/client/slot-context.ts +50 -0
  724. package/src/client/slot-outlet.tsx +22 -0
  725. package/src/client/slot-provider.tsx +32 -0
  726. package/src/client/ssr-data.ts +13 -5
  727. package/src/client/state.ts +2 -2
  728. package/src/client/top-loader.tsx +11 -9
  729. package/src/client/use-cookie.ts +60 -15
  730. package/src/client/use-link-status.ts +7 -7
  731. package/src/client/use-pathname.ts +1 -0
  732. package/src/client/use-pending-navigation.ts +40 -0
  733. package/src/client/use-query-states.ts +108 -10
  734. package/src/client/use-router.ts +4 -1
  735. package/src/client/use-search-params.ts +31 -44
  736. package/src/client/{use-params.ts → use-segment-params.ts} +9 -6
  737. package/src/codec.ts +149 -0
  738. package/src/config-types.ts +282 -0
  739. package/src/config-validation.ts +330 -0
  740. package/src/content/index.ts +5 -13
  741. package/src/cookies/define-cookie.ts +217 -53
  742. package/src/cookies/index.ts +12 -1
  743. package/src/cookies/json-cookie.ts +105 -0
  744. package/src/cookies/validation.ts +192 -0
  745. package/src/dev-tools/404-page.ts +286 -0
  746. package/src/dev-tools/browser-logs.ts +55 -0
  747. package/src/dev-tools/dev-page-shell.ts +260 -0
  748. package/src/dev-tools/error-page.ts +331 -0
  749. package/src/dev-tools/holding-server.ts +187 -0
  750. package/src/dev-tools/hydration-overlay.ts +158 -0
  751. package/src/dev-tools/index.ts +83 -0
  752. package/src/dev-tools/instrumentation.ts +213 -0
  753. package/src/{server/dev-logger.ts → dev-tools/logger.ts} +33 -51
  754. package/src/{plugins/dev-logs.ts → dev-tools/logs.ts} +122 -26
  755. package/src/dev-tools/overlay.ts +469 -0
  756. package/src/dev-tools/stack-classifier.ts +75 -0
  757. package/src/dev-tools/terminal.ts +182 -0
  758. package/src/fonts/ast-walk.ts +235 -0
  759. package/src/fonts/ast.ts +477 -126
  760. package/src/fonts/bundle.ts +138 -0
  761. package/src/fonts/dev-middleware.ts +85 -0
  762. package/src/fonts/fallbacks.ts +0 -23
  763. package/src/fonts/google.ts +100 -18
  764. package/src/fonts/local.ts +9 -8
  765. package/src/fonts/paths.ts +58 -0
  766. package/src/fonts/pipeline.ts +348 -0
  767. package/src/fonts/transform.ts +311 -0
  768. package/src/fonts/types.ts +52 -1
  769. package/src/fonts/virtual-modules.ts +179 -0
  770. package/src/index.ts +446 -352
  771. package/src/params/codec-registry.ts +34 -0
  772. package/src/params/define-schema.ts +115 -0
  773. package/src/params/index.ts +17 -0
  774. package/src/params/resolve-schema.ts +84 -0
  775. package/src/plugin-context.ts +432 -0
  776. package/src/plugins/adapter-build.ts +220 -7
  777. package/src/plugins/build-manifest.ts +177 -23
  778. package/src/plugins/build-report.ts +253 -35
  779. package/src/plugins/cache.ts +243 -0
  780. package/src/plugins/callsite-ast.ts +472 -0
  781. package/src/plugins/callsite-jsx.ts +243 -0
  782. package/src/plugins/chunks.ts +74 -5
  783. package/src/plugins/client-chunks.ts +185 -0
  784. package/src/plugins/cloudflare-wasm.ts +141 -0
  785. package/src/plugins/content.ts +1 -1
  786. package/src/plugins/dev-server.ts +284 -94
  787. package/src/plugins/entries.ts +134 -16
  788. package/src/plugins/fonts.ts +225 -660
  789. package/src/plugins/mdx.ts +47 -10
  790. package/src/plugins/prebuilt-capture.ts +217 -0
  791. package/src/plugins/prebuilt-options-analysis.ts +175 -0
  792. package/src/plugins/prebuilt.ts +655 -0
  793. package/src/plugins/prerender-sugar.ts +328 -0
  794. package/src/plugins/request-dep.ts +458 -0
  795. package/src/plugins/routing.ts +237 -241
  796. package/src/plugins/server-bundle.ts +89 -12
  797. package/src/plugins/shims.ts +241 -64
  798. package/src/plugins/static-build.ts +15 -90
  799. package/src/routing/codegen-shared.ts +115 -0
  800. package/src/routing/codegen-types.ts +65 -0
  801. package/src/routing/codegen.ts +372 -178
  802. package/src/routing/convention-lint.ts +394 -0
  803. package/src/routing/export-detect.ts +304 -0
  804. package/src/routing/file-cache.ts +23 -0
  805. package/src/routing/index.ts +10 -1
  806. package/src/routing/interception.ts +3 -22
  807. package/src/routing/link-codegen.ts +313 -0
  808. package/src/routing/manifest-codegen.ts +287 -0
  809. package/src/routing/scanner.ts +338 -189
  810. package/src/routing/schema-validation.ts +155 -0
  811. package/src/routing/segment-classify.ts +223 -0
  812. package/src/routing/segment-codegen.ts +98 -0
  813. package/src/routing/types.ts +82 -25
  814. package/src/routing/walkers.ts +90 -0
  815. package/src/rsc-runtime/rsc.ts +9 -0
  816. package/src/rsc-runtime/ssr.ts +50 -0
  817. package/src/rsc-runtime/vendor-types.d.ts +7 -0
  818. package/src/schema-bridge.ts +253 -0
  819. package/src/search-params/define.ts +576 -0
  820. package/src/search-params/index.ts +14 -20
  821. package/src/search-params/registry.ts +2 -2
  822. package/src/search-params/wrappers.ts +101 -0
  823. package/src/segment-params/define.ts +249 -0
  824. package/src/segment-params/index.ts +9 -0
  825. package/src/server/access-gate.tsx +111 -34
  826. package/src/server/action-client.ts +120 -29
  827. package/src/server/action-encryption.ts +144 -0
  828. package/src/server/action-handler.ts +123 -33
  829. package/src/server/actions.ts +48 -54
  830. package/src/server/als-registry.ts +137 -20
  831. package/src/server/asset-headers.ts +15 -37
  832. package/src/server/body-limits.ts +10 -2
  833. package/src/server/build-manifest.ts +19 -56
  834. package/src/server/canonicalize.ts +6 -3
  835. package/src/server/coalesce-tick.ts +75 -0
  836. package/src/server/compress.ts +34 -7
  837. package/src/server/cookie-context.ts +484 -0
  838. package/src/server/cookie-parsing.ts +163 -0
  839. package/src/server/csrf.ts +39 -6
  840. package/src/server/default-logger.ts +99 -0
  841. package/src/server/deny-boundary.ts +314 -0
  842. package/src/server/deny-renderer.ts +85 -77
  843. package/src/server/dev-source-map.ts +31 -0
  844. package/src/server/early-hints-sender.ts +3 -2
  845. package/src/server/early-hints.ts +37 -27
  846. package/src/server/error-boundary-wrapper.ts +61 -22
  847. package/src/server/fallback-error.ts +79 -102
  848. package/src/server/flight-injection-state.ts +113 -0
  849. package/src/server/flight-scripts.ts +62 -0
  850. package/src/server/form-data.ts +124 -12
  851. package/src/server/html-injector-core.ts +495 -0
  852. package/src/server/html-injectors.ts +271 -254
  853. package/src/server/index.ts +31 -185
  854. package/src/server/internal.ts +181 -0
  855. package/src/server/logger.ts +72 -36
  856. package/src/server/metadata-routes.ts +205 -24
  857. package/src/server/metadata.ts +21 -0
  858. package/src/server/middleware-runner.ts +31 -4
  859. package/src/server/node-stream-transforms.ts +336 -0
  860. package/src/server/param-coercion.ts +207 -0
  861. package/src/server/pipeline-helpers.ts +204 -0
  862. package/src/server/pipeline-interception.ts +45 -18
  863. package/src/server/pipeline-metadata.ts +14 -0
  864. package/src/server/pipeline-outcome.ts +197 -0
  865. package/src/server/pipeline-phases.ts +545 -0
  866. package/src/server/pipeline.ts +274 -382
  867. package/src/server/port-resolution.ts +215 -0
  868. package/src/server/prebuilt/cache-key.ts +298 -0
  869. package/src/server/prebuilt/capture-state.ts +89 -0
  870. package/src/server/prebuilt/key-discipline.ts +53 -0
  871. package/src/server/prebuilt/manifest-tag-index.ts +46 -0
  872. package/src/server/prebuilt/overlay.ts +256 -0
  873. package/src/server/prebuilt/payload-source.ts +201 -0
  874. package/src/server/prebuilt/slots.ts +190 -0
  875. package/src/server/prebuilt/synthetic-store.ts +121 -0
  876. package/src/server/prebuilt-builder.ts +809 -0
  877. package/src/server/prebuilt-runtime.ts +815 -0
  878. package/src/server/primitives.ts +160 -83
  879. package/src/server/render-timeout.ts +108 -0
  880. package/src/server/render-utils.ts +31 -0
  881. package/src/server/request-context.ts +170 -337
  882. package/src/server/request-dep.ts +37 -0
  883. package/src/server/route-element-builder.ts +699 -295
  884. package/src/server/route-handler.ts +31 -4
  885. package/src/server/route-matcher.ts +158 -277
  886. package/src/server/rsc-entry/action-middleware-runner.ts +167 -0
  887. package/src/server/rsc-entry/api-handler.ts +69 -32
  888. package/src/server/rsc-entry/deny-fallback.ts +92 -0
  889. package/src/server/rsc-entry/error-renderer.ts +306 -89
  890. package/src/server/rsc-entry/helpers.ts +210 -85
  891. package/src/server/rsc-entry/index.ts +332 -332
  892. package/src/server/rsc-entry/render-route.ts +300 -0
  893. package/src/server/rsc-entry/revalidate-renderer.ts +349 -0
  894. package/src/server/rsc-entry/rsc-payload.ts +102 -42
  895. package/src/server/rsc-entry/rsc-stream.ts +93 -13
  896. package/src/server/rsc-entry/ssr-bridge.ts +18 -5
  897. package/src/server/rsc-entry/ssr-renderer.ts +275 -43
  898. package/src/server/rsc-entry/wrap-action-dispatch.ts +186 -0
  899. package/src/server/safe-load.ts +60 -0
  900. package/src/server/sensitive-fields.ts +230 -0
  901. package/src/server/server-only-guard-noop.js +3 -0
  902. package/src/server/sitemap-generator.ts +345 -0
  903. package/src/server/sitemap-handler.ts +157 -0
  904. package/src/server/slot-resolver.ts +574 -250
  905. package/src/server/ssr-bridge-types.ts +124 -0
  906. package/src/server/ssr-entry.ts +206 -86
  907. package/src/server/ssr-render.ts +345 -86
  908. package/src/server/ssr-wrappers.tsx +141 -0
  909. package/src/server/state-tree-diff.ts +177 -30
  910. package/src/server/status-code-resolver.ts +115 -130
  911. package/src/server/stream-utils.ts +288 -0
  912. package/src/server/tracing.ts +126 -14
  913. package/src/server/tree-builder.ts +214 -90
  914. package/src/server/tree-match.ts +262 -0
  915. package/src/server/types.ts +78 -9
  916. package/src/server/utils/escape-html.ts +20 -0
  917. package/src/server/utils/mdx-file.ts +22 -0
  918. package/src/server/version-skew.ts +104 -0
  919. package/src/server/workers-cache-bridge.ts +33 -0
  920. package/src/shared/href-validation.ts +159 -0
  921. package/src/shared/merge-search-params.ts +55 -0
  922. package/src/shared/redirect-type.ts +17 -0
  923. package/src/shims/font-google.ts +1 -1
  924. package/src/shims/font-local.ts +34 -0
  925. package/src/shims/headers.ts +122 -1
  926. package/src/shims/navigation-client.ts +51 -29
  927. package/src/shims/navigation.ts +14 -7
  928. package/src/utils/state-machine.ts +111 -0
  929. package/dist/_chunks/als-registry-B7DbZ2hS.js +0 -41
  930. package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
  931. package/dist/_chunks/debug-B3Gypr3D.js +0 -108
  932. package/dist/_chunks/debug-B3Gypr3D.js.map +0 -1
  933. package/dist/_chunks/format-RyoGQL74.js +0 -164
  934. package/dist/_chunks/format-RyoGQL74.js.map +0 -1
  935. package/dist/_chunks/interception-BOoWmLUA.js +0 -676
  936. package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
  937. package/dist/_chunks/metadata-routes-Cjmvi3rQ.js +0 -153
  938. package/dist/_chunks/metadata-routes-Cjmvi3rQ.js.map +0 -1
  939. package/dist/_chunks/request-context-BQUC8PHn.js +0 -330
  940. package/dist/_chunks/request-context-BQUC8PHn.js.map +0 -1
  941. package/dist/_chunks/ssr-data-MjmprTmO.js.map +0 -1
  942. package/dist/_chunks/tracing-CemImE6h.js +0 -187
  943. package/dist/_chunks/tracing-CemImE6h.js.map +0 -1
  944. package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
  945. package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
  946. package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
  947. package/dist/adapters/cloudflare.js.map +0 -1
  948. package/dist/cache/index.js.map +0 -1
  949. package/dist/cache/register-cached-function.d.ts +0 -17
  950. package/dist/cache/register-cached-function.d.ts.map +0 -1
  951. package/dist/client/browser-entry.d.ts +0 -21
  952. package/dist/client/browser-entry.d.ts.map +0 -1
  953. package/dist/client/head.d.ts +0 -16
  954. package/dist/client/head.d.ts.map +0 -1
  955. package/dist/client/link-status-provider.d.ts +0 -11
  956. package/dist/client/link-status-provider.d.ts.map +0 -1
  957. package/dist/client/segment-merger.d.ts +0 -119
  958. package/dist/client/segment-merger.d.ts.map +0 -1
  959. package/dist/client/stale-reload.d.ts +0 -44
  960. package/dist/client/stale-reload.d.ts.map +0 -1
  961. package/dist/client/transition-root.d.ts +0 -74
  962. package/dist/client/transition-root.d.ts.map +0 -1
  963. package/dist/client/use-navigation-pending.d.ts +0 -26
  964. package/dist/client/use-navigation-pending.d.ts.map +0 -1
  965. package/dist/client/use-params.d.ts.map +0 -1
  966. package/dist/plugins/cache-transform.d.ts +0 -36
  967. package/dist/plugins/cache-transform.d.ts.map +0 -1
  968. package/dist/plugins/dev-error-overlay.d.ts +0 -60
  969. package/dist/plugins/dev-error-overlay.d.ts.map +0 -1
  970. package/dist/plugins/dev-logs.d.ts.map +0 -1
  971. package/dist/plugins/dynamic-transform.d.ts +0 -72
  972. package/dist/plugins/dynamic-transform.d.ts.map +0 -1
  973. package/dist/plugins/server-action-exports.d.ts +0 -26
  974. package/dist/plugins/server-action-exports.d.ts.map +0 -1
  975. package/dist/routing/status-file-lint.d.ts +0 -33
  976. package/dist/routing/status-file-lint.d.ts.map +0 -1
  977. package/dist/search-params/analyze.d.ts +0 -54
  978. package/dist/search-params/analyze.d.ts.map +0 -1
  979. package/dist/search-params/builtin-codecs.d.ts +0 -105
  980. package/dist/search-params/builtin-codecs.d.ts.map +0 -1
  981. package/dist/search-params/codecs.d.ts +0 -53
  982. package/dist/search-params/codecs.d.ts.map +0 -1
  983. package/dist/search-params/create.d.ts +0 -106
  984. package/dist/search-params/create.d.ts.map +0 -1
  985. package/dist/server/client-module-map.d.ts +0 -47
  986. package/dist/server/client-module-map.d.ts.map +0 -1
  987. package/dist/server/dev-fetch-instrumentation.d.ts +0 -22
  988. package/dist/server/dev-fetch-instrumentation.d.ts.map +0 -1
  989. package/dist/server/dev-logger.d.ts.map +0 -1
  990. package/dist/server/dev-span-processor.d.ts +0 -29
  991. package/dist/server/dev-span-processor.d.ts.map +0 -1
  992. package/dist/server/dev-warnings.d.ts +0 -129
  993. package/dist/server/dev-warnings.d.ts.map +0 -1
  994. package/dist/server/flush.d.ts +0 -74
  995. package/dist/server/flush.d.ts.map +0 -1
  996. package/dist/server/manifest-status-resolver.d.ts +0 -58
  997. package/dist/server/manifest-status-resolver.d.ts.map +0 -1
  998. package/dist/server/prerender.d.ts +0 -77
  999. package/dist/server/prerender.d.ts.map +0 -1
  1000. package/dist/utils/directive-parser.d.ts +0 -70
  1001. package/dist/utils/directive-parser.d.ts.map +0 -1
  1002. package/src/cache/register-cached-function.ts +0 -103
  1003. package/src/client/browser-entry.ts +0 -678
  1004. package/src/client/head.ts +0 -61
  1005. package/src/client/link-status-provider.tsx +0 -30
  1006. package/src/client/segment-merger.ts +0 -339
  1007. package/src/client/stale-reload.ts +0 -87
  1008. package/src/client/transition-root.tsx +0 -166
  1009. package/src/client/use-navigation-pending.ts +0 -38
  1010. package/src/plugins/cache-transform.ts +0 -199
  1011. package/src/plugins/dev-error-overlay.ts +0 -230
  1012. package/src/plugins/dynamic-transform.ts +0 -161
  1013. package/src/plugins/server-action-exports.ts +0 -220
  1014. package/src/routing/status-file-lint.ts +0 -112
  1015. package/src/search-params/analyze.ts +0 -192
  1016. package/src/search-params/builtin-codecs.ts +0 -228
  1017. package/src/search-params/codecs.ts +0 -153
  1018. package/src/search-params/create.ts +0 -321
  1019. package/src/server/client-module-map.ts +0 -58
  1020. package/src/server/dev-fetch-instrumentation.ts +0 -96
  1021. package/src/server/dev-span-processor.ts +0 -78
  1022. package/src/server/dev-warnings.ts +0 -283
  1023. package/src/server/flush.ts +0 -182
  1024. package/src/server/manifest-status-resolver.ts +0 -215
  1025. package/src/server/prerender.ts +0 -139
  1026. package/src/utils/directive-parser.ts +0 -529
@@ -18,21 +18,11 @@ import type {
18
18
  ScannerConfig,
19
19
  InterceptionMarker,
20
20
  } from './types.js';
21
- import { DEFAULT_PAGE_EXTENSIONS, INTERCEPTION_MARKERS } from './types.js';
22
- import { classifyMetadataRoute, isDynamicMetadataExtension } from '#/server/metadata-routes.js';
23
-
24
- /**
25
- * Pattern matching encoded path delimiters that must be rejected during route discovery.
26
- * %2F / %2f (forward slash) and %5C / %5c (backslash) can cause route collisions
27
- * when decoded. See design/13-security.md §"Encoded separators rejected".
28
- */
29
- const ENCODED_SEPARATOR_PATTERN = /%(?:2[fF]|5[cC])/;
30
-
31
- /**
32
- * Pattern matching encoded null bytes (%00) that must be rejected.
33
- * See design/13-security.md §"Null bytes rejected".
34
- */
35
- const ENCODED_NULL_PATTERN = /%00/;
21
+ import { classifySegment } from './segment-classify.js';
22
+ import { DEFAULT_PAGE_EXTENSIONS } from './types.js';
23
+ import { classifyMetadataRoute, isDynamicMetadataExtension } from '../server/metadata-routes.js';
24
+ import { swallow } from '../server/logger.js';
25
+ import { ENCODED_SEPARATOR_RE, NULL_BYTE_RE } from '../server/canonicalize.js';
36
26
 
37
27
  /**
38
28
  * File convention names that use pageExtensions (can be .tsx, .ts, .jsx, .js, .mdx, etc.)
@@ -53,7 +43,7 @@ const LEGACY_STATUS_FILES: Record<string, number> = {
53
43
  /**
54
44
  * File convention names that are always .ts/.tsx (never .mdx etc.)
55
45
  */
56
- const FIXED_CONVENTIONS = new Set(['middleware', 'access', 'route', 'prerender', 'search-params']);
46
+ const FIXED_CONVENTIONS = new Set(['middleware', 'access', 'route', 'params']);
57
47
 
58
48
  /**
59
49
  * Status-code file patterns:
@@ -83,6 +73,14 @@ export function scanRoutes(appDir: string, config: ScannerConfig = {}): RouteTre
83
73
  tree.proxy = proxyFile;
84
74
  }
85
75
 
76
+ // Check for global-error.{tsx,ts,jsx,js} at app root.
77
+ // Tier 2 error page — renders standalone (no layouts) when no segment-level
78
+ // error file is found. See design/10-error-handling.md §"Tier 2".
79
+ const globalErrorFile = findPageExtFile(appDir, 'global-error', extSet);
80
+ if (globalErrorFile) {
81
+ tree.globalError = globalErrorFile;
82
+ }
83
+
86
84
  // Scan the root directory's files
87
85
  scanSegmentFiles(appDir, tree.root, extSet);
88
86
 
@@ -92,6 +90,18 @@ export function scanRoutes(appDir: string, config: ScannerConfig = {}): RouteTre
92
90
  // Validate: detect route group collisions (different groups producing pages at the same URL)
93
91
  validateRouteGroupCollisions(tree.root);
94
92
 
93
+ // Validate: detect duplicate param names in nested dynamic segments
94
+ // e.g., /[id]/items/[id] — same param name in ancestor and descendant
95
+ validateDuplicateParamNames(tree.root);
96
+
97
+ // Validate: detect same param name used with different bracket forms
98
+ // e.g., [id] in one route and [...id] in another
99
+ validateUniqueBracketForms(tree.root);
100
+
101
+ // Validate: detect affixed dynamic siblings with equal specificity
102
+ // e.g., a-[id] and [slug]-b both have prefix+suffix length = 2
103
+ validateAffixedSiblingConflicts(tree.root);
104
+
95
105
  return tree;
96
106
  }
97
107
 
@@ -104,106 +114,24 @@ function createSegmentNode(
104
114
  urlPath: string,
105
115
  paramName?: string,
106
116
  interceptionMarker?: InterceptionMarker,
107
- interceptedSegmentName?: string
117
+ interceptedSegmentName?: string,
118
+ paramPrefix?: string,
119
+ paramSuffix?: string
108
120
  ): SegmentNode {
109
121
  return {
110
122
  segmentName,
111
123
  segmentType,
112
124
  urlPath,
113
125
  paramName,
126
+ paramPrefix,
127
+ paramSuffix,
114
128
  interceptionMarker,
115
129
  interceptedSegmentName,
116
130
  children: [],
117
- slots: new Map(),
131
+ slots: {},
118
132
  };
119
133
  }
120
134
 
121
- /**
122
- * Classify a directory name into its segment type.
123
- */
124
- export function classifySegment(dirName: string): {
125
- type: SegmentType;
126
- paramName?: string;
127
- interceptionMarker?: InterceptionMarker;
128
- interceptedSegmentName?: string;
129
- } {
130
- // Private folder: _name (excluded from routing)
131
- if (dirName.startsWith('_')) {
132
- return { type: 'private' };
133
- }
134
-
135
- // Parallel route slot: @name
136
- if (dirName.startsWith('@')) {
137
- return { type: 'slot' };
138
- }
139
-
140
- // Intercepting routes: (.)name, (..)name, (...)name, (..)(..)name
141
- // Check before route groups since intercepting markers also start with (
142
- const interception = parseInterceptionMarker(dirName);
143
- if (interception) {
144
- return {
145
- type: 'intercepting',
146
- interceptionMarker: interception.marker,
147
- interceptedSegmentName: interception.segmentName,
148
- };
149
- }
150
-
151
- // Route group: (name)
152
- if (dirName.startsWith('(') && dirName.endsWith(')')) {
153
- return { type: 'group' };
154
- }
155
-
156
- // Optional catch-all: [[...name]]
157
- if (dirName.startsWith('[[...') && dirName.endsWith(']]')) {
158
- const paramName = dirName.slice(5, -2);
159
- return { type: 'optional-catch-all', paramName };
160
- }
161
-
162
- // Catch-all: [...name]
163
- if (dirName.startsWith('[...') && dirName.endsWith(']')) {
164
- const paramName = dirName.slice(4, -1);
165
- return { type: 'catch-all', paramName };
166
- }
167
-
168
- // Dynamic: [name]
169
- if (dirName.startsWith('[') && dirName.endsWith(']')) {
170
- const paramName = dirName.slice(1, -1);
171
- return { type: 'dynamic', paramName };
172
- }
173
-
174
- return { type: 'static' };
175
- }
176
-
177
- /**
178
- * Parse an interception marker from a directory name.
179
- *
180
- * Returns the marker and the remaining segment name, or null if not an
181
- * intercepting route. Markers are checked longest-first to avoid (..)
182
- * matching before (..)(..).
183
- *
184
- * Examples:
185
- * "(.)photo" → { marker: "(.)", segmentName: "photo" }
186
- * "(..)feed" → { marker: "(..)", segmentName: "feed" }
187
- * "(...)photos" → { marker: "(...)", segmentName: "photos" }
188
- * "(..)(..)admin" → { marker: "(..)(..)", segmentName: "admin" }
189
- * "(marketing)" → null (route group, not interception)
190
- */
191
- function parseInterceptionMarker(
192
- dirName: string
193
- ): { marker: InterceptionMarker; segmentName: string } | null {
194
- for (const marker of INTERCEPTION_MARKERS) {
195
- if (dirName.startsWith(marker)) {
196
- const rest = dirName.slice(marker.length);
197
- // Must have a segment name after the marker, and the rest must not
198
- // be empty or end with ) (which would be a route group like "(auth)")
199
- if (rest.length > 0 && !rest.endsWith(')')) {
200
- return { marker, segmentName: rest };
201
- }
202
- }
203
- }
204
- return null;
205
- }
206
-
207
135
  /**
208
136
  * Compute the URL path for a child segment given its parent's URL path.
209
137
  * Route groups, slots, and intercepting routes do NOT add URL depth.
@@ -225,7 +153,8 @@ function scanSegmentFiles(dirPath: string, node: SegmentNode, extSet: Set<string
225
153
  let entries: string[];
226
154
  try {
227
155
  entries = readdirSync(dirPath);
228
- } catch {
156
+ } catch (err) {
157
+ swallow(err, `scanSegmentFiles: unreadable directory ${dirPath}`, { level: 'warn' });
229
158
  return;
230
159
  }
231
160
 
@@ -244,47 +173,26 @@ function scanSegmentFiles(dirPath: string, node: SegmentNode, extSet: Set<string
244
173
 
245
174
  // Page-extension conventions (page, layout, error, default, denied)
246
175
  if (PAGE_EXT_CONVENTIONS.has(name) && extSet.has(ext)) {
247
- const file: RouteFile = { filePath: fullPath, extension: ext };
248
- switch (name) {
249
- case 'page':
250
- node.page = file;
251
- break;
252
- case 'layout':
253
- node.layout = file;
254
- break;
255
- case 'error':
256
- node.error = file;
257
- break;
258
- case 'default':
259
- node.default = file;
260
- break;
261
- case 'denied':
262
- node.denied = file;
263
- break;
176
+ const key = name as 'page' | 'layout' | 'error' | 'default' | 'denied';
177
+ const existing = node[key];
178
+ if (existing) {
179
+ throwDuplicateConvention(name, existing.filePath, fullPath);
264
180
  }
181
+ node[key] = { filePath: fullPath, extension: ext };
265
182
  continue;
266
183
  }
267
184
 
268
- // Fixed conventions (middleware, access, route) — always .ts or .tsx
269
- if (FIXED_CONVENTIONS.has(name) && /\.?[jt]sx?$/.test(ext)) {
270
- const file: RouteFile = { filePath: fullPath, extension: ext };
271
- switch (name) {
272
- case 'middleware':
273
- node.middleware = file;
274
- break;
275
- case 'access':
276
- node.access = file;
277
- break;
278
- case 'route':
279
- node.route = file;
280
- break;
281
- case 'prerender':
282
- node.prerender = file;
283
- break;
284
- case 'search-params':
285
- node.searchParams = file;
286
- break;
185
+ // Fixed conventions (middleware, access, route, params) — only
186
+ // .ts/.tsx/.js/.jsx, never pageExtensions like .mdx. The regex is
187
+ // anchored: mts/cts/mjs/cjs (and stray tail matches like `.foots`)
188
+ // are NOT recognized. See design/07-routing.md §"Page Extensions".
189
+ if (FIXED_CONVENTIONS.has(name) && /^[jt]sx?$/.test(ext)) {
190
+ const key = name as 'middleware' | 'access' | 'route' | 'params';
191
+ const existing = node[key];
192
+ if (existing) {
193
+ throwDuplicateConvention(name, existing.filePath, fullPath);
287
194
  }
195
+ node[key] = { filePath: fullPath, extension: ext };
288
196
  continue;
289
197
  }
290
198
 
@@ -292,50 +200,69 @@ function scanSegmentFiles(dirPath: string, node: SegmentNode, extSet: Set<string
292
200
  // Recognized regardless of pageExtensions — .json is a data format, not a page extension.
293
201
  if (STATUS_CODE_PATTERN.test(name) && ext === 'json') {
294
202
  if (!node.jsonStatusFiles) {
295
- node.jsonStatusFiles = new Map();
203
+ node.jsonStatusFiles = {};
296
204
  }
297
- node.jsonStatusFiles.set(name, { filePath: fullPath, extension: ext });
205
+ node.jsonStatusFiles[name] = { filePath: fullPath, extension: ext };
298
206
  continue;
299
207
  }
300
208
 
301
209
  // Status-code files (401.tsx, 4xx.tsx, 503.tsx, 5xx.tsx)
302
210
  if (STATUS_CODE_PATTERN.test(name) && extSet.has(ext)) {
303
211
  if (!node.statusFiles) {
304
- node.statusFiles = new Map();
212
+ node.statusFiles = {};
305
213
  }
306
- node.statusFiles.set(name, { filePath: fullPath, extension: ext });
214
+ const existing = node.statusFiles[name];
215
+ if (existing) {
216
+ throwDuplicateConvention(name, existing.filePath, fullPath);
217
+ }
218
+ node.statusFiles[name] = { filePath: fullPath, extension: ext };
307
219
  continue;
308
220
  }
309
221
 
310
222
  // Legacy compat files (not-found.tsx, forbidden.tsx, unauthorized.tsx)
311
223
  if (name in LEGACY_STATUS_FILES && extSet.has(ext)) {
312
224
  if (!node.legacyStatusFiles) {
313
- node.legacyStatusFiles = new Map();
225
+ node.legacyStatusFiles = {};
226
+ }
227
+ const existing = node.legacyStatusFiles[name];
228
+ if (existing) {
229
+ throwDuplicateConvention(name, existing.filePath, fullPath);
314
230
  }
315
- node.legacyStatusFiles.set(name, { filePath: fullPath, extension: ext });
231
+ node.legacyStatusFiles[name] = { filePath: fullPath, extension: ext };
316
232
  continue;
317
233
  }
318
234
 
319
235
  // Metadata route files (sitemap.ts, robots.ts, icon.tsx, opengraph-image.tsx, etc.)
320
236
  // Both static (.xml, .txt, .png, .ico, etc.) and dynamic (.ts, .tsx) files are recognized.
321
237
  // When both exist for the same base name, dynamic takes precedence.
238
+ // Two files of the SAME kind (static+static or dynamic+dynamic) are a
239
+ // build error — picking one by readdir order is platform-dependent.
322
240
  // See design/16-metadata.md §"Metadata Routes"
323
241
  const metaInfo = classifyMetadataRoute(entry);
324
242
  if (metaInfo) {
243
+ if (!metaInfo.nestable && node.segmentName !== '') {
244
+ throw new Error(
245
+ `Build error: '${name}' is a root-only metadata convention and must be in the app root directory.\n` +
246
+ ` File: ${fullPath}\n` +
247
+ ` Move this file to the app root (not a route group or nested segment).`
248
+ );
249
+ }
325
250
  if (!node.metadataRoutes) {
326
- node.metadataRoutes = new Map();
251
+ node.metadataRoutes = {};
327
252
  }
328
- const existing = node.metadataRoutes.get(name);
253
+ const existing = node.metadataRoutes[name];
329
254
  if (existing) {
330
- // Dynamic > static precedence: only overwrite if the new file is dynamic
331
- // or the existing file is static (dynamic always wins).
332
255
  const existingIsDynamic = isDynamicMetadataExtension(name, existing.extension);
333
256
  const newIsDynamic = isDynamicMetadataExtension(name, ext);
334
- if (newIsDynamic || !existingIsDynamic) {
335
- node.metadataRoutes.set(name, { filePath: fullPath, extension: ext });
257
+ if (existingIsDynamic === newIsDynamic) {
258
+ throwDuplicateConvention(name, existing.filePath, fullPath);
259
+ }
260
+ // Dynamic > static precedence: overwrite only when the new file is dynamic.
261
+ if (newIsDynamic) {
262
+ node.metadataRoutes[name] = { filePath: fullPath, extension: ext };
336
263
  }
337
264
  } else {
338
- node.metadataRoutes.set(name, { filePath: fullPath, extension: ext });
265
+ node.metadataRoutes[name] = { filePath: fullPath, extension: ext };
339
266
  }
340
267
  }
341
268
  }
@@ -351,6 +278,26 @@ function scanSegmentFiles(dirPath: string, node: SegmentNode, extSet: Set<string
351
278
  }
352
279
  }
353
280
 
281
+ /**
282
+ * Throw a build error for two files claiming the same convention slot in
283
+ * one segment (e.g. page.tsx + page.jsx). Which file readdir returns first
284
+ * is platform-dependent (APFS sorts entries, ext4 does not) — silently
285
+ * picking one would let macOS dev and Linux CI serve different
286
+ * implementations of the same route.
287
+ */
288
+ function throwDuplicateConvention(
289
+ convention: string,
290
+ firstPath: string,
291
+ secondPath: string
292
+ ): never {
293
+ throw new Error(
294
+ `Build error: duplicate '${convention}' files in the same route segment.\n` +
295
+ ` File 1: ${firstPath}\n` +
296
+ ` File 2: ${secondPath}\n` +
297
+ `Each segment may define '${convention}' at most once. Remove one of the files.`
298
+ );
299
+ }
300
+
354
301
  /**
355
302
  * Recursively scan child directories and build the segment tree.
356
303
  */
@@ -358,7 +305,8 @@ function scanChildren(dirPath: string, parentNode: SegmentNode, extSet: Set<stri
358
305
  let entries: string[];
359
306
  try {
360
307
  entries = readdirSync(dirPath);
361
- } catch {
308
+ } catch (err) {
309
+ swallow(err, `scanChildren: unreadable directory ${dirPath}`, { level: 'warn' });
362
310
  return;
363
311
  }
364
312
 
@@ -374,24 +322,31 @@ function scanChildren(dirPath: string, parentNode: SegmentNode, extSet: Set<stri
374
322
  // Reject directories with encoded path delimiters or null bytes.
375
323
  // These can cause route collisions when decoded at the URL boundary.
376
324
  // See design/13-security.md §"Encoded separators rejected" and §"Null bytes rejected".
377
- if (ENCODED_SEPARATOR_PATTERN.test(entry)) {
325
+ if (ENCODED_SEPARATOR_RE.test(entry)) {
378
326
  throw new Error(
379
- `Build error: directory name contains an encoded path delimiter (%%2F or %%5C).\n` +
327
+ `Build error: directory name contains an encoded path delimiter (%2F or %5C).\n` +
380
328
  ` Directory: ${fullPath}\n` +
381
329
  `Encoded separators in directory names cause route collisions when decoded. ` +
382
330
  `Rename the directory to remove the encoded delimiter.`
383
331
  );
384
332
  }
385
- if (ENCODED_NULL_PATTERN.test(entry)) {
333
+ if (NULL_BYTE_RE.test(entry)) {
386
334
  throw new Error(
387
- `Build error: directory name contains an encoded null byte (%%00).\n` +
335
+ `Build error: directory name contains an encoded null byte (%00).\n` +
388
336
  ` Directory: ${fullPath}\n` +
389
337
  `Encoded null bytes in directory names are not allowed. ` +
390
338
  `Rename the directory to remove the null byte encoding.`
391
339
  );
392
340
  }
393
341
 
394
- const { type, paramName, interceptionMarker, interceptedSegmentName } = classifySegment(entry);
342
+ const {
343
+ type,
344
+ paramName,
345
+ paramPrefix,
346
+ paramSuffix,
347
+ interceptionMarker,
348
+ interceptedSegmentName,
349
+ } = classifySegment(entry);
395
350
 
396
351
  // Skip private folders — underscore-prefixed dirs are excluded from routing
397
352
  if (type === 'private') continue;
@@ -403,7 +358,9 @@ function scanChildren(dirPath: string, parentNode: SegmentNode, extSet: Set<stri
403
358
  urlPath,
404
359
  paramName,
405
360
  interceptionMarker,
406
- interceptedSegmentName
361
+ interceptedSegmentName,
362
+ paramPrefix,
363
+ paramSuffix
407
364
  );
408
365
 
409
366
  // Scan this segment's files
@@ -412,10 +369,10 @@ function scanChildren(dirPath: string, parentNode: SegmentNode, extSet: Set<stri
412
369
  // Recurse into subdirectories
413
370
  scanChildren(fullPath, childNode, extSet);
414
371
 
415
- // Attach to parent: slots go into slots map, everything else is a child
372
+ // Attach to parent: slots go into slots record, everything else is a child
416
373
  if (type === 'slot') {
417
374
  const slotName = entry.slice(1); // remove @
418
- parentNode.slots.set(slotName, childNode);
375
+ parentNode.slots[slotName] = childNode;
419
376
  } else {
420
377
  parentNode.children.push(childNode);
421
378
  }
@@ -428,58 +385,228 @@ function scanChildren(dirPath: string, parentNode: SegmentNode, extSet: Set<stri
428
385
  * Two route groups like (auth)/login/page.tsx and (marketing)/login/page.tsx both claim
429
386
  * /login — the scanner must detect and reject this at build time.
430
387
  *
431
- * Parallel slots are excluded from collision detection — they intentionally coexist at
432
- * the same URL path as their parent (that's the whole point of parallel routes).
388
+ * Each parallel slot is validated as its OWN collision space: a slot's pages
389
+ * intentionally share URL paths with the parent tree (that's the point of
390
+ * parallel routes), but two route groups INSIDE one slot claiming the same
391
+ * URL — e.g. @side/(a)/x/page.tsx + @side/(b)/x/page.tsx — still collide.
433
392
  */
434
393
  function validateRouteGroupCollisions(root: SegmentNode): void {
435
394
  // Map from urlPath → { filePath, source } for the first page/route seen at that path
436
- const seen = new Map<string, { filePath: string; segmentPath: string }>();
437
- collectRoutableLeaves(root, seen, '', false);
395
+ collectRoutableLeaves(root, new Map(), '');
438
396
  }
439
397
 
440
398
  /**
441
399
  * Walk the segment tree and collect all routable leaves (page or route files),
442
- * throwing on collision. Slots are tracked in their own collision space since
443
- * they are parallel routes that intentionally share URL paths with their parent.
400
+ * throwing on collision. Each slot recurses with a FRESH collision map —
401
+ * slots are parallel routes that intentionally share URL paths with their
402
+ * parent tree, but collisions within a single slot are real errors.
444
403
  */
445
404
  function collectRoutableLeaves(
446
405
  node: SegmentNode,
447
406
  seen: Map<string, { filePath: string; segmentPath: string }>,
448
- segmentPath: string,
449
- insideSlot: boolean
407
+ segmentPath: string
450
408
  ): void {
409
+ // Intercepting routes are resolved by the slot resolver, not URL matching,
410
+ // and their computed urlPaths intentionally mirror other routes (e.g. two
411
+ // interceptors in one slot both produce /gallery/[id]). Skip them entirely.
412
+ if (node.segmentType === 'intercepting') return;
413
+
451
414
  const currentPath = segmentPath
452
415
  ? `${segmentPath}/${node.segmentName}`
453
416
  : node.segmentName || '(root)';
454
417
 
455
- // Only check collisions for non-slot pages — slots intentionally share URL paths
456
- if (!insideSlot) {
457
- const routableFile = node.page ?? node.route;
458
- if (routableFile) {
459
- const existing = seen.get(node.urlPath);
460
- if (existing) {
418
+ const routableFile = node.page ?? node.route;
419
+ if (routableFile) {
420
+ const existing = seen.get(node.urlPath);
421
+ if (existing) {
422
+ throw new Error(
423
+ `Build error: route collision — multiple route groups produce a page/route at the same URL path.\n` +
424
+ ` URL path: ${node.urlPath}\n` +
425
+ ` File 1: ${existing.filePath} (via ${existing.segmentPath})\n` +
426
+ ` File 2: ${routableFile.filePath} (via ${currentPath})\n` +
427
+ `Each URL path must map to exactly one page or route handler. ` +
428
+ `Rename or move one of the conflicting files.`
429
+ );
430
+ }
431
+ seen.set(node.urlPath, { filePath: routableFile.filePath, segmentPath: currentPath });
432
+ }
433
+
434
+ // Recurse into children
435
+ for (const child of node.children) {
436
+ collectRoutableLeaves(child, seen, currentPath);
437
+ }
438
+
439
+ // Recurse into slots — each slot gets a fresh map (its own collision space)
440
+ for (const slotNode of Object.values(node.slots)) {
441
+ collectRoutableLeaves(slotNode, new Map(), currentPath);
442
+ }
443
+ }
444
+
445
+ /**
446
+ * Validate that no route chain contains duplicate dynamic param names.
447
+ *
448
+ * Example violation:
449
+ * app/[id]/items/[id]/page.tsx — 'id' appears twice in the ancestor chain.
450
+ *
451
+ * Route groups are transparent — params accumulate through them.
452
+ * Slots are independent — duplicate detection does NOT cross slot boundaries.
453
+ *
454
+ * See design/07-routing.md §"Duplicate Param Name Detection"
455
+ */
456
+ function validateDuplicateParamNames(root: SegmentNode): void {
457
+ walkForDuplicateParams(root, new Map());
458
+ }
459
+
460
+ /**
461
+ * Recursively walk the segment tree, tracking seen param names → segment paths.
462
+ * Throws on the first duplicate found.
463
+ */
464
+ function walkForDuplicateParams(node: SegmentNode, seen: Map<string, string>): void {
465
+ // If this node introduces a param name, check for duplicates
466
+ if (node.paramName) {
467
+ const existing = seen.get(node.paramName);
468
+ if (existing) {
469
+ throw new Error(
470
+ `[timber] Duplicate param name '${node.paramName}' in route chain.\n` +
471
+ ` First defined at: ${existing}\n` +
472
+ ` Duplicate at: ${node.urlPath || '/'}\n` +
473
+ ` Rename one of the segments to avoid ambiguity.`
474
+ );
475
+ }
476
+ // Add to seen for descendants (use a new Map to avoid polluting siblings)
477
+ seen = new Map(seen);
478
+ seen.set(node.paramName, node.urlPath || '/');
479
+ }
480
+
481
+ // Recurse into children (they inherit the accumulated params)
482
+ for (const child of node.children) {
483
+ walkForDuplicateParams(child, seen);
484
+ }
485
+
486
+ // Slots are independent parallel routes — start fresh param tracking
487
+ // (a slot's params don't conflict with the main route's params)
488
+ for (const slotNode of Object.values(node.slots)) {
489
+ walkForDuplicateParams(slotNode, new Map(seen));
490
+ }
491
+ }
492
+
493
+ /**
494
+ * Validate that each param name uses a single bracket form across the entire route tree.
495
+ *
496
+ * Different bracket forms produce different types:
497
+ * [id] → string
498
+ * [...id] → string[]
499
+ * [[...id]] → string[] | undefined
500
+ *
501
+ * If the same param name appears with multiple forms, the no-argument
502
+ * getSegmentParams() / useSegmentParams() return type becomes ambiguous.
503
+ *
504
+ * Same name + same form across different routes is fine and expected.
505
+ */
506
+ function validateUniqueBracketForms(root: SegmentNode): void {
507
+ const forms = new Map<string, { segmentType: SegmentType; urlPath: string }>();
508
+ collectBracketForms(root, forms);
509
+ }
510
+
511
+ function collectBracketForms(
512
+ node: SegmentNode,
513
+ forms: Map<string, { segmentType: SegmentType; urlPath: string }>
514
+ ): void {
515
+ if (node.paramName && node.segmentType !== 'static' && node.segmentType !== 'group') {
516
+ const existing = forms.get(node.paramName);
517
+ if (existing && existing.segmentType !== node.segmentType) {
518
+ const bracketExamples: Record<string, string> = {
519
+ 'dynamic': `[${node.paramName}]`,
520
+ 'catch-all': `[...${node.paramName}]`,
521
+ 'optional-catch-all': `[[...${node.paramName}]]`,
522
+ };
523
+ throw new Error(
524
+ `[timber] Param name '${node.paramName}' uses multiple bracket forms.\n` +
525
+ ` ${bracketExamples[existing.segmentType] ?? existing.segmentType} at: ${existing.urlPath}\n` +
526
+ ` ${bracketExamples[node.segmentType] ?? node.segmentType} at: ${node.urlPath || '/'}\n` +
527
+ ` Each param name must use a single bracket form across all routes.\n` +
528
+ ` Rename one of the segments to fix this (e.g., [${node.paramName}] → [${node.paramName}Id]).`
529
+ );
530
+ }
531
+ if (!existing) {
532
+ forms.set(node.paramName, {
533
+ segmentType: node.segmentType,
534
+ urlPath: node.urlPath || '/',
535
+ });
536
+ }
537
+ }
538
+
539
+ for (const child of node.children) {
540
+ collectBracketForms(child, forms);
541
+ }
542
+ for (const slotNode of Object.values(node.slots)) {
543
+ collectBracketForms(slotNode, forms);
544
+ }
545
+ }
546
+
547
+ /**
548
+ * Validate that no sibling affixed dynamic segments have equal specificity.
549
+ *
550
+ * Among affixed siblings, longer combined prefix+suffix length wins. When two
551
+ * siblings tie (same total affix length), the router would fall back to
552
+ * filesystem scan order — which is platform-dependent. This is a build error.
553
+ *
554
+ * Route groups are URL-transparent, so affixed segments inside different groups
555
+ * at the same level still conflict with each other.
556
+ *
557
+ * See design/07-routing.md §"Priority"
558
+ */
559
+ function validateAffixedSiblingConflicts(node: SegmentNode): void {
560
+ const affixed = collectEffectiveAffixed(node);
561
+
562
+ if (affixed.length >= 2) {
563
+ const byLength = new Map<number, SegmentNode[]>();
564
+ for (const child of affixed) {
565
+ const len = (child.paramPrefix?.length ?? 0) + (child.paramSuffix?.length ?? 0);
566
+ const group = byLength.get(len);
567
+ if (group) {
568
+ group.push(child);
569
+ } else {
570
+ byLength.set(len, [child]);
571
+ }
572
+ }
573
+
574
+ for (const [, group] of byLength) {
575
+ if (group.length >= 2) {
461
576
  throw new Error(
462
- `Build error: route collision — multiple route groups produce a page/route at the same URL path.\n` +
463
- ` URL path: ${node.urlPath}\n` +
464
- ` File 1: ${existing.filePath} (via ${existing.segmentPath})\n` +
465
- ` File 2: ${routableFile.filePath} (via ${currentPath})\n` +
466
- `Each URL path must map to exactly one page or route handler. ` +
467
- `Rename or move one of the conflicting files.`
577
+ `Build error: ambiguous affixed dynamic siblings with equal specificity.\n` +
578
+ ` Parent: ${node.urlPath || '/'}\n` +
579
+ ` Segments: ${group.map((s) => s.segmentName).join(', ')}\n` +
580
+ ` Combined prefix+suffix length: ${(group[0]!.paramPrefix?.length ?? 0) + (group[0]!.paramSuffix?.length ?? 0)}\n` +
581
+ `The router cannot deterministically choose between these — filesystem scan order is platform-dependent.\n` +
582
+ `Rename one segment to give it a longer or shorter combined affix.`
468
583
  );
469
584
  }
470
- seen.set(node.urlPath, { filePath: routableFile.filePath, segmentPath: currentPath });
471
585
  }
472
586
  }
473
587
 
474
- // Recurse into children
475
588
  for (const child of node.children) {
476
- collectRoutableLeaves(child, seen, currentPath, insideSlot);
589
+ validateAffixedSiblingConflicts(child);
590
+ }
591
+ for (const slotNode of Object.values(node.slots)) {
592
+ validateAffixedSiblingConflicts(slotNode);
477
593
  }
594
+ }
478
595
 
479
- // Recurse into slots — each slot is its own parallel route space
480
- for (const [, slotNode] of node.slots) {
481
- collectRoutableLeaves(slotNode, seen, currentPath, true);
596
+ /**
597
+ * Collect affixed dynamic segments that are effective children of a node.
598
+ * Route groups are URL-transparent, so we look through them recursively.
599
+ */
600
+ function collectEffectiveAffixed(node: SegmentNode): SegmentNode[] {
601
+ const result: SegmentNode[] = [];
602
+ for (const child of node.children) {
603
+ if (child.segmentType === 'dynamic' && (child.paramPrefix || child.paramSuffix)) {
604
+ result.push(child);
605
+ } else if (child.segmentType === 'group') {
606
+ result.push(...collectEffectiveAffixed(child));
607
+ }
482
608
  }
609
+ return result;
483
610
  }
484
611
 
485
612
  /**
@@ -498,3 +625,25 @@ function findFixedFile(dirPath: string, name: string): RouteFile | undefined {
498
625
  }
499
626
  return undefined;
500
627
  }
628
+
629
+ /**
630
+ * Find a file using the configured page extensions (tsx, ts, jsx, js, mdx, etc.).
631
+ * Used for app-root conventions like global-error that aren't per-segment.
632
+ */
633
+ function findPageExtFile(
634
+ dirPath: string,
635
+ name: string,
636
+ extSet: Set<string>
637
+ ): RouteFile | undefined {
638
+ for (const ext of extSet) {
639
+ const fullPath = join(dirPath, `${name}.${ext}`);
640
+ try {
641
+ if (statSync(fullPath).isFile()) {
642
+ return { filePath: fullPath, extension: ext };
643
+ }
644
+ } catch {
645
+ // File doesn't exist
646
+ }
647
+ }
648
+ return undefined;
649
+ }