@timber-js/app 0.2.0-alpha.185 → 0.2.0-alpha.187

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 (570) hide show
  1. package/dist/_chunks/{actions-O_LsyCE4.js → actions-35jnMdeJ.js} +4 -3
  2. package/dist/_chunks/{actions-O_LsyCE4.js.map → actions-35jnMdeJ.js.map} +1 -1
  3. package/dist/_chunks/als-registry-C6kcfprT.js +41 -0
  4. package/dist/_chunks/als-registry-C6kcfprT.js.map +1 -0
  5. package/dist/_chunks/als-slots-BEEIPKYm.js +26 -0
  6. package/dist/_chunks/als-slots-BEEIPKYm.js.map +1 -0
  7. package/dist/_chunks/base-path-DaQrzbez.js +80 -0
  8. package/dist/_chunks/base-path-DaQrzbez.js.map +1 -0
  9. package/dist/_chunks/build-manifest-DWppEdLB.js +86 -0
  10. package/dist/_chunks/build-manifest-DWppEdLB.js.map +1 -0
  11. package/dist/_chunks/build-output-helper-C3DrfzZR.js +369 -0
  12. package/dist/_chunks/build-output-helper-C3DrfzZR.js.map +1 -0
  13. package/dist/_chunks/{cache-api-B-lhk9p4.js → cache-api-DjNrIWRR.js} +8 -14
  14. package/dist/_chunks/cache-api-DjNrIWRR.js.map +1 -0
  15. package/dist/_chunks/cli-check-CpmN7Nh-.js +256 -0
  16. package/dist/_chunks/cli-check-CpmN7Nh-.js.map +1 -0
  17. package/dist/_chunks/cli-schema-sync-CGMp_Psg.js +298 -0
  18. package/dist/_chunks/cli-schema-sync-CGMp_Psg.js.map +1 -0
  19. package/dist/_chunks/{cloudflare-CnT5Lr7U.js → cloudflare-CGP6BZKO.js} +92 -14
  20. package/dist/_chunks/{cloudflare-CnT5Lr7U.js.map → cloudflare-CGP6BZKO.js.map} +1 -1
  21. package/dist/_chunks/convention-lint-kXsgc_-7.js +784 -0
  22. package/dist/_chunks/convention-lint-kXsgc_-7.js.map +1 -0
  23. package/dist/_chunks/error-boundary-D-ODYX41.js +353 -0
  24. package/dist/_chunks/error-boundary-D-ODYX41.js.map +1 -0
  25. package/dist/_chunks/{fast-hash-D6hIVt1Y.js → fast-hash-C-tVYrLb.js} +6 -1
  26. package/dist/_chunks/fast-hash-C-tVYrLb.js.map +1 -0
  27. package/dist/_chunks/file-cache-DmX7OqZP.js +454 -0
  28. package/dist/_chunks/file-cache-DmX7OqZP.js.map +1 -0
  29. package/dist/_chunks/fs-identity-D7vb6GdI.js +208 -0
  30. package/dist/_chunks/fs-identity-D7vb6GdI.js.map +1 -0
  31. package/dist/_chunks/{logger-AWfuX-KJ.js → logger-D8xJZXIN.js} +34 -51
  32. package/dist/_chunks/logger-D8xJZXIN.js.map +1 -0
  33. package/dist/_chunks/mdx-file-C005ay-P.js +25 -0
  34. package/dist/_chunks/mdx-file-C005ay-P.js.map +1 -0
  35. package/dist/_chunks/{plugin-context---kTF5v8.js → plugin-context-rCinWLiE.js} +8 -2
  36. package/dist/_chunks/plugin-context-rCinWLiE.js.map +1 -0
  37. package/dist/_chunks/purge-store-Byr8XOjU.js +14 -0
  38. package/dist/_chunks/purge-store-Byr8XOjU.js.map +1 -0
  39. package/dist/_chunks/{resolve-schema-Dz3fcFUo.js → resolve-schema-5ma5pp1b.js} +2 -2
  40. package/dist/_chunks/{resolve-schema-Dz3fcFUo.js.map → resolve-schema-5ma5pp1b.js.map} +1 -1
  41. package/dist/_chunks/{router-ref-CtmF-aPv.js → router-ref-DuYuV_0Q.js} +2 -2
  42. package/dist/_chunks/router-ref-DuYuV_0Q.js.map +1 -0
  43. package/dist/_chunks/rsc-cache-key-DD0fl_-s.js +243 -0
  44. package/dist/_chunks/rsc-cache-key-DD0fl_-s.js.map +1 -0
  45. package/dist/_chunks/rsc-error-envelope-tT5PJs4q.js +40 -0
  46. package/dist/_chunks/rsc-error-envelope-tT5PJs4q.js.map +1 -0
  47. package/dist/_chunks/rsc-media-type-DRqE_lD_.js +46 -0
  48. package/dist/_chunks/rsc-media-type-DRqE_lD_.js.map +1 -0
  49. package/dist/_chunks/rsc-payload-path-B_LBodc2.js +48 -0
  50. package/dist/_chunks/rsc-payload-path-B_LBodc2.js.map +1 -0
  51. package/dist/_chunks/scanner-C8b0Gcw3.js +1564 -0
  52. package/dist/_chunks/scanner-C8b0Gcw3.js.map +1 -0
  53. package/dist/_chunks/schema-bridge-Cc2Gngu1.js +199 -0
  54. package/dist/_chunks/schema-bridge-Cc2Gngu1.js.map +1 -0
  55. package/dist/_chunks/{segment-classify-Byy425ng.js → segment-classify-C539Pa2O.js} +23 -2
  56. package/dist/_chunks/segment-classify-C539Pa2O.js.map +1 -0
  57. package/dist/_chunks/segment-context-CjOlyB8Y.js +97 -0
  58. package/dist/_chunks/segment-context-CjOlyB8Y.js.map +1 -0
  59. package/dist/_chunks/{canonicalize-DQHyFClh.js → segment-keys-BawYuNFO.js} +61 -2
  60. package/dist/_chunks/segment-keys-BawYuNFO.js.map +1 -0
  61. package/dist/_chunks/slot-params-BCTmZkQB.js +76 -0
  62. package/dist/_chunks/slot-params-BCTmZkQB.js.map +1 -0
  63. package/dist/_chunks/{ssr-data-BOWsq18U.js → ssr-data-14MXm7Pj.js} +17 -2
  64. package/dist/_chunks/ssr-data-14MXm7Pj.js.map +1 -0
  65. package/dist/_chunks/{use-query-states-DFvWd-EA.js → use-query-states-BbU5Ge1V.js} +74 -26
  66. package/dist/_chunks/use-query-states-BbU5Ge1V.js.map +1 -0
  67. package/dist/_chunks/use-segment-params-C4r4BD9T.js +398 -0
  68. package/dist/_chunks/use-segment-params-C4r4BD9T.js.map +1 -0
  69. package/dist/_chunks/walkers-RzN6AFjr.js +141 -0
  70. package/dist/_chunks/walkers-RzN6AFjr.js.map +1 -0
  71. package/dist/adapters/build-output-helper.d.ts +37 -0
  72. package/dist/adapters/build-output-helper.d.ts.map +1 -1
  73. package/dist/adapters/cloudflare-dev.js +1 -1
  74. package/dist/adapters/cloudflare-kv-cache.js +1 -1
  75. package/dist/adapters/cloudflare.d.ts.map +1 -1
  76. package/dist/adapters/cloudflare.js +1 -1
  77. package/dist/adapters/compress-module.d.ts +12 -0
  78. package/dist/adapters/compress-module.d.ts.map +1 -1
  79. package/dist/adapters/fs-identity.d.ts +64 -0
  80. package/dist/adapters/fs-identity.d.ts.map +1 -0
  81. package/dist/adapters/nitro.d.ts.map +1 -1
  82. package/dist/adapters/nitro.js +56 -5
  83. package/dist/adapters/nitro.js.map +1 -1
  84. package/dist/adapters/shared.d.ts +57 -1
  85. package/dist/adapters/shared.d.ts.map +1 -1
  86. package/dist/adapters/types.d.ts +13 -1
  87. package/dist/adapters/types.d.ts.map +1 -1
  88. package/dist/cache/fast-hash.d.ts +5 -0
  89. package/dist/cache/fast-hash.d.ts.map +1 -1
  90. package/dist/cache/index.js +1 -1
  91. package/dist/cdn/cloudflare-purge.js +30 -0
  92. package/dist/cdn/cloudflare-purge.js.map +1 -0
  93. package/dist/cdn/fastly-purge.js +33 -0
  94. package/dist/cdn/fastly-purge.js.map +1 -0
  95. package/dist/cdn/index.js +94 -0
  96. package/dist/cdn/index.js.map +1 -0
  97. package/dist/cdn/workers-cache-purge.js +35 -0
  98. package/dist/cdn/workers-cache-purge.js.map +1 -0
  99. package/dist/cli-check.d.ts +153 -0
  100. package/dist/cli-check.d.ts.map +1 -0
  101. package/dist/cli.d.ts +34 -8
  102. package/dist/cli.d.ts.map +1 -1
  103. package/dist/cli.js +46 -21
  104. package/dist/cli.js.map +1 -1
  105. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -1
  106. package/dist/client/browser-entry/hydrate.d.ts +20 -9
  107. package/dist/client/browser-entry/hydrate.d.ts.map +1 -1
  108. package/dist/client/browser-entry/index.d.ts +1 -1
  109. package/dist/client/browser-entry/index.d.ts.map +1 -1
  110. package/dist/client/browser-entry/post-hydration.d.ts +4 -1
  111. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -1
  112. package/dist/client/browser-entry/router-init.d.ts +3 -0
  113. package/dist/client/browser-entry/router-init.d.ts.map +1 -1
  114. package/dist/client/browser-entry/rsc-stream.d.ts +8 -0
  115. package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -1
  116. package/dist/client/error-boundary.d.ts +7 -0
  117. package/dist/client/error-boundary.d.ts.map +1 -1
  118. package/dist/client/error-boundary.js +1 -162
  119. package/dist/client/history.d.ts +13 -6
  120. package/dist/client/history.d.ts.map +1 -1
  121. package/dist/client/index.d.ts +1 -0
  122. package/dist/client/index.d.ts.map +1 -1
  123. package/dist/client/index.js +42 -41
  124. package/dist/client/index.js.map +1 -1
  125. package/dist/client/internal.d.ts +4 -3
  126. package/dist/client/internal.d.ts.map +1 -1
  127. package/dist/client/internal.js +877 -311
  128. package/dist/client/internal.js.map +1 -1
  129. package/dist/client/link.d.ts +1 -7
  130. package/dist/client/link.d.ts.map +1 -1
  131. package/dist/client/navigation-api.d.ts +2 -2
  132. package/dist/client/navigation-commit.d.ts +87 -0
  133. package/dist/client/navigation-commit.d.ts.map +1 -0
  134. package/dist/client/navigation-context.d.ts +37 -20
  135. package/dist/client/navigation-context.d.ts.map +1 -1
  136. package/dist/client/navigation-root.d.ts +63 -23
  137. package/dist/client/navigation-root.d.ts.map +1 -1
  138. package/dist/client/params-context.d.ts +81 -0
  139. package/dist/client/params-context.d.ts.map +1 -0
  140. package/dist/client/router-effects.d.ts +129 -0
  141. package/dist/client/router-effects.d.ts.map +1 -0
  142. package/dist/client/router-lifecycle.d.ts +55 -0
  143. package/dist/client/router-lifecycle.d.ts.map +1 -0
  144. package/dist/client/router-pipeline.d.ts +84 -0
  145. package/dist/client/router-pipeline.d.ts.map +1 -0
  146. package/dist/client/router-ref.d.ts +1 -1
  147. package/dist/client/router-ref.d.ts.map +1 -1
  148. package/dist/client/router-skew.d.ts +21 -0
  149. package/dist/client/router-skew.d.ts.map +1 -0
  150. package/dist/client/router-types.d.ts +207 -0
  151. package/dist/client/router-types.d.ts.map +1 -0
  152. package/dist/client/router.d.ts +1 -182
  153. package/dist/client/router.d.ts.map +1 -1
  154. package/dist/client/rsc-fetch.d.ts +47 -26
  155. package/dist/client/rsc-fetch.d.ts.map +1 -1
  156. package/dist/client/segment-cache.d.ts +87 -34
  157. package/dist/client/segment-cache.d.ts.map +1 -1
  158. package/dist/client/ssr-data.d.ts +6 -0
  159. package/dist/client/ssr-data.d.ts.map +1 -1
  160. package/dist/client/stale-client.d.ts +69 -0
  161. package/dist/client/stale-client.d.ts.map +1 -0
  162. package/dist/client/state.d.ts +10 -1
  163. package/dist/client/state.d.ts.map +1 -1
  164. package/dist/client/top-loader.d.ts +2 -1
  165. package/dist/client/top-loader.d.ts.map +1 -1
  166. package/dist/client/unload-guard.d.ts +5 -0
  167. package/dist/client/unload-guard.d.ts.map +1 -1
  168. package/dist/client/use-cookie.d.ts.map +1 -1
  169. package/dist/client/use-query-states.d.ts +9 -3
  170. package/dist/client/use-query-states.d.ts.map +1 -1
  171. package/dist/client/use-router.d.ts +1 -1
  172. package/dist/client/use-segment-params.d.ts +18 -8
  173. package/dist/client/use-segment-params.d.ts.map +1 -1
  174. package/dist/codec.js +1 -1
  175. package/dist/cookies/define-cookie.d.ts.map +1 -1
  176. package/dist/cookies/index.js +5 -5
  177. package/dist/cookies/index.js.map +1 -1
  178. package/dist/index.d.ts +4 -1
  179. package/dist/index.d.ts.map +1 -1
  180. package/dist/index.js +1009 -759
  181. package/dist/index.js.map +1 -1
  182. package/dist/params/index.js +1 -1
  183. package/dist/plugin-context.d.ts +46 -0
  184. package/dist/plugin-context.d.ts.map +1 -1
  185. package/dist/plugins/adapter-build.d.ts.map +1 -1
  186. package/dist/plugins/build-manifest.d.ts +1 -1
  187. package/dist/plugins/build-manifest.d.ts.map +1 -1
  188. package/dist/plugins/entries.d.ts.map +1 -1
  189. package/dist/plugins/fonts.d.ts.map +1 -1
  190. package/dist/plugins/request-dep/analysis.d.ts +106 -0
  191. package/dist/plugins/request-dep/analysis.d.ts.map +1 -0
  192. package/dist/plugins/request-dep/index.d.ts +75 -0
  193. package/dist/plugins/request-dep/index.d.ts.map +1 -0
  194. package/dist/plugins/request-dep/origin.d.ts +61 -0
  195. package/dist/plugins/request-dep/origin.d.ts.map +1 -0
  196. package/dist/plugins/routing.d.ts.map +1 -1
  197. package/dist/plugins/shims.d.ts.map +1 -1
  198. package/dist/plugins/static-build.d.ts +160 -8
  199. package/dist/plugins/static-build.d.ts.map +1 -1
  200. package/dist/routing/codegen-shared.d.ts +3 -44
  201. package/dist/routing/codegen-shared.d.ts.map +1 -1
  202. package/dist/routing/codegen-types.d.ts +28 -31
  203. package/dist/routing/codegen-types.d.ts.map +1 -1
  204. package/dist/routing/codegen-write.d.ts +51 -0
  205. package/dist/routing/codegen-write.d.ts.map +1 -0
  206. package/dist/routing/codegen.d.ts.map +1 -1
  207. package/dist/routing/collision-probe.d.ts +104 -0
  208. package/dist/routing/collision-probe.d.ts.map +1 -0
  209. package/dist/routing/collision-spaces.d.ts +26 -0
  210. package/dist/routing/collision-spaces.d.ts.map +1 -0
  211. package/dist/routing/convention-lint.d.ts +18 -4
  212. package/dist/routing/convention-lint.d.ts.map +1 -1
  213. package/dist/routing/export-detect.d.ts +16 -0
  214. package/dist/routing/export-detect.d.ts.map +1 -1
  215. package/dist/routing/index.js +4 -3
  216. package/dist/routing/interception.d.ts +235 -6
  217. package/dist/routing/interception.d.ts.map +1 -1
  218. package/dist/routing/link-codegen.d.ts +19 -4
  219. package/dist/routing/link-codegen.d.ts.map +1 -1
  220. package/dist/routing/manifest-codegen.d.ts +1 -7
  221. package/dist/routing/manifest-codegen.d.ts.map +1 -1
  222. package/dist/routing/scanner.d.ts.map +1 -1
  223. package/dist/routing/segment-classify.d.ts +33 -0
  224. package/dist/routing/segment-classify.d.ts.map +1 -1
  225. package/dist/routing/segment-keys.d.ts +95 -0
  226. package/dist/routing/segment-keys.d.ts.map +1 -0
  227. package/dist/routing/slot-placement.d.ts +48 -0
  228. package/dist/routing/slot-placement.d.ts.map +1 -0
  229. package/dist/routing/types.d.ts +0 -6
  230. package/dist/routing/types.d.ts.map +1 -1
  231. package/dist/routing/walkers.d.ts +6 -0
  232. package/dist/routing/walkers.d.ts.map +1 -1
  233. package/dist/schema-bridge.d.ts +60 -9
  234. package/dist/schema-bridge.d.ts.map +1 -1
  235. package/dist/search-params/define.d.ts +62 -14
  236. package/dist/search-params/define.d.ts.map +1 -1
  237. package/dist/search-params/index.d.ts +0 -1
  238. package/dist/search-params/index.d.ts.map +1 -1
  239. package/dist/search-params/index.js +221 -10
  240. package/dist/search-params/index.js.map +1 -1
  241. package/dist/search-params/parse-total.d.ts +70 -0
  242. package/dist/search-params/parse-total.d.ts.map +1 -0
  243. package/dist/search-params/wrappers.d.ts +26 -3
  244. package/dist/search-params/wrappers.d.ts.map +1 -1
  245. package/dist/server/access-gate.d.ts +19 -8
  246. package/dist/server/access-gate.d.ts.map +1 -1
  247. package/dist/server/action-handler.d.ts.map +1 -1
  248. package/dist/server/actions.d.ts +6 -3
  249. package/dist/server/actions.d.ts.map +1 -1
  250. package/dist/server/als-registry.d.ts +18 -1
  251. package/dist/server/als-registry.d.ts.map +1 -1
  252. package/dist/server/build-manifest.d.ts +13 -1
  253. package/dist/server/build-manifest.d.ts.map +1 -1
  254. package/dist/server/chain-url-parts.d.ts +82 -0
  255. package/dist/server/chain-url-parts.d.ts.map +1 -0
  256. package/dist/server/children-interception.d.ts +49 -0
  257. package/dist/server/children-interception.d.ts.map +1 -0
  258. package/dist/server/compress.d.ts.map +1 -1
  259. package/dist/server/default-status-page.d.ts +45 -0
  260. package/dist/server/default-status-page.d.ts.map +1 -0
  261. package/dist/server/deny-boundary.d.ts +148 -15
  262. package/dist/server/deny-boundary.d.ts.map +1 -1
  263. package/dist/server/deny-renderer.d.ts +15 -4
  264. package/dist/server/deny-renderer.d.ts.map +1 -1
  265. package/dist/server/error-boundary-wrapper.d.ts +85 -15
  266. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  267. package/dist/server/head-response.d.ts +35 -0
  268. package/dist/server/head-response.d.ts.map +1 -0
  269. package/dist/server/index.d.ts +0 -1
  270. package/dist/server/index.d.ts.map +1 -1
  271. package/dist/server/index.js +3 -2
  272. package/dist/server/index.js.map +1 -1
  273. package/dist/server/internal.d.ts +3 -1
  274. package/dist/server/internal.d.ts.map +1 -1
  275. package/dist/server/internal.js +712 -418
  276. package/dist/server/internal.js.map +1 -1
  277. package/dist/server/metadata-collector.d.ts +52 -0
  278. package/dist/server/metadata-collector.d.ts.map +1 -0
  279. package/dist/server/param-coercion.d.ts +22 -6
  280. package/dist/server/param-coercion.d.ts.map +1 -1
  281. package/dist/server/pipeline-helpers.d.ts +0 -18
  282. package/dist/server/pipeline-helpers.d.ts.map +1 -1
  283. package/dist/server/pipeline-interception.d.ts +59 -9
  284. package/dist/server/pipeline-interception.d.ts.map +1 -1
  285. package/dist/server/pipeline-outcome.d.ts.map +1 -1
  286. package/dist/server/pipeline-phases.d.ts.map +1 -1
  287. package/dist/server/pipeline.d.ts +11 -0
  288. package/dist/server/pipeline.d.ts.map +1 -1
  289. package/dist/server/primitives.d.ts +23 -0
  290. package/dist/server/primitives.d.ts.map +1 -1
  291. package/dist/server/publish-params.d.ts +33 -0
  292. package/dist/server/publish-params.d.ts.map +1 -0
  293. package/dist/server/request-context.d.ts +48 -0
  294. package/dist/server/request-context.d.ts.map +1 -1
  295. package/dist/server/route-element-builder.d.ts +22 -3
  296. package/dist/server/route-element-builder.d.ts.map +1 -1
  297. package/dist/server/route-handler.d.ts.map +1 -1
  298. package/dist/server/route-matcher.d.ts +13 -0
  299. package/dist/server/route-matcher.d.ts.map +1 -1
  300. package/dist/server/rsc-cache-key-guard.d.ts +78 -0
  301. package/dist/server/rsc-cache-key-guard.d.ts.map +1 -0
  302. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  303. package/dist/server/rsc-entry/deny-fallback.d.ts.map +1 -1
  304. package/dist/server/rsc-entry/error-renderer.d.ts +15 -3
  305. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  306. package/dist/server/rsc-entry/helpers.d.ts +2 -17
  307. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  308. package/dist/server/rsc-entry/index.d.ts +0 -1
  309. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  310. package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
  311. package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -1
  312. package/dist/server/rsc-entry/rsc-payload.d.ts +1 -2
  313. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  314. package/dist/server/rsc-entry/rsc-stream.d.ts +15 -2
  315. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  316. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  317. package/dist/server/skippable-prefix.d.ts +23 -0
  318. package/dist/server/skippable-prefix.d.ts.map +1 -0
  319. package/dist/server/slot-interception.d.ts +80 -0
  320. package/dist/server/slot-interception.d.ts.map +1 -0
  321. package/dist/server/slot-resolver.d.ts +70 -8
  322. package/dist/server/slot-resolver.d.ts.map +1 -1
  323. package/dist/server/ssr-bridge-types.d.ts +17 -0
  324. package/dist/server/ssr-bridge-types.d.ts.map +1 -1
  325. package/dist/server/ssr-entry.d.ts +0 -1
  326. package/dist/server/ssr-entry.d.ts.map +1 -1
  327. package/dist/server/ssr-wrappers.d.ts +24 -13
  328. package/dist/server/ssr-wrappers.d.ts.map +1 -1
  329. package/dist/server/state-tree-diff.d.ts +6 -27
  330. package/dist/server/state-tree-diff.d.ts.map +1 -1
  331. package/dist/server/static-generator.d.ts +6 -0
  332. package/dist/server/static-generator.d.ts.map +1 -1
  333. package/dist/server/static-not-found.d.ts +52 -0
  334. package/dist/server/static-not-found.d.ts.map +1 -0
  335. package/dist/server/status-code-resolver.d.ts +8 -1
  336. package/dist/server/status-code-resolver.d.ts.map +1 -1
  337. package/dist/server/tree-builder.d.ts +28 -36
  338. package/dist/server/tree-builder.d.ts.map +1 -1
  339. package/dist/server/types.d.ts +12 -7
  340. package/dist/server/types.d.ts.map +1 -1
  341. package/dist/server/utils/element-type.d.ts +40 -0
  342. package/dist/server/utils/element-type.d.ts.map +1 -0
  343. package/dist/shared/als-slots.d.ts +41 -0
  344. package/dist/shared/als-slots.d.ts.map +1 -0
  345. package/dist/shared/base-path.d.ts +56 -0
  346. package/dist/shared/base-path.d.ts.map +1 -0
  347. package/dist/shared/param-value.d.ts +80 -0
  348. package/dist/shared/param-value.d.ts.map +1 -0
  349. package/dist/shared/payload-root.d.ts +108 -0
  350. package/dist/shared/payload-root.d.ts.map +1 -0
  351. package/dist/shared/rsc-cache-key.d.ts +163 -0
  352. package/dist/shared/rsc-cache-key.d.ts.map +1 -0
  353. package/dist/shared/rsc-error-envelope.d.ts +25 -0
  354. package/dist/shared/rsc-error-envelope.d.ts.map +1 -0
  355. package/dist/shared/rsc-manifest.d.ts +28 -0
  356. package/dist/shared/rsc-manifest.d.ts.map +1 -0
  357. package/dist/shared/rsc-media-type.d.ts +40 -0
  358. package/dist/shared/rsc-media-type.d.ts.map +1 -0
  359. package/dist/shared/rsc-payload-path.d.ts +42 -0
  360. package/dist/shared/rsc-payload-path.d.ts.map +1 -0
  361. package/dist/shared/segment-info.d.ts +59 -0
  362. package/dist/shared/segment-info.d.ts.map +1 -0
  363. package/dist/shared/slot-params.d.ts +51 -0
  364. package/dist/shared/slot-params.d.ts.map +1 -0
  365. package/dist/shared/static-platform-files.d.ts +71 -0
  366. package/dist/shared/static-platform-files.d.ts.map +1 -0
  367. package/docs/api/30-api-server.mdx +1 -1
  368. package/docs/api/31-api-client.mdx +4 -2
  369. package/docs/api/33-api-search-params.mdx +38 -16
  370. package/docs/api/35-api-typescript.mdx +3 -3
  371. package/docs/api/36-cli.mdx +34 -7
  372. package/docs/learn/00-introduction.mdx +1 -1
  373. package/docs/learn/02-pages-and-layouts.mdx +2 -2
  374. package/docs/learn/05-typed-params.mdx +8 -8
  375. package/docs/learn/07-typed-routes.mdx +12 -7
  376. package/docs/learn/11-error-handling.mdx +18 -0
  377. package/docs/learn/12-client-navigation.mdx +2 -2
  378. package/docs/learn/14-deploying.mdx +23 -0
  379. package/docs/more/01-advanced-routing.mdx +173 -3
  380. package/docs/more/03-coming-from-nextjs.mdx +2 -2
  381. package/docs/more/04-metadata-and-fonts.mdx +1 -1
  382. package/docs/more/50-ai-agent-instructions.mdx +6 -4
  383. package/package.json +9 -6
  384. package/src/adapters/build-output-helper.ts +116 -3
  385. package/src/adapters/cloudflare.ts +90 -12
  386. package/src/adapters/compress-module.ts +79 -1
  387. package/src/adapters/fs-identity.ts +156 -0
  388. package/src/adapters/nitro.ts +6 -6
  389. package/src/adapters/shared.ts +196 -21
  390. package/src/adapters/types.ts +13 -1
  391. package/src/cache/fast-hash.ts +5 -0
  392. package/src/cli-check.ts +458 -0
  393. package/src/cli.ts +59 -24
  394. package/src/client/browser-entry/action-dispatch.ts +11 -5
  395. package/src/client/browser-entry/hydrate.ts +40 -29
  396. package/src/client/browser-entry/index.ts +15 -6
  397. package/src/client/browser-entry/post-hydration.ts +10 -9
  398. package/src/client/browser-entry/router-init.ts +104 -48
  399. package/src/client/browser-entry/rsc-stream.ts +11 -2
  400. package/src/client/error-boundary.tsx +85 -16
  401. package/src/client/history.ts +13 -6
  402. package/src/client/index.ts +14 -3
  403. package/src/client/internal.ts +4 -3
  404. package/src/client/link.tsx +120 -72
  405. package/src/client/navigation-api.ts +3 -3
  406. package/src/client/navigation-commit.ts +197 -0
  407. package/src/client/navigation-context.ts +40 -67
  408. package/src/client/navigation-root.tsx +326 -101
  409. package/src/client/params-context.ts +192 -0
  410. package/src/client/router-effects.ts +231 -0
  411. package/src/client/router-lifecycle.ts +288 -0
  412. package/src/client/router-pipeline.ts +393 -0
  413. package/src/client/router-ref.ts +1 -1
  414. package/src/client/router-skew.ts +30 -0
  415. package/src/client/router-types.ts +230 -0
  416. package/src/client/router.ts +243 -707
  417. package/src/client/rsc-fetch.ts +183 -106
  418. package/src/client/segment-cache.ts +129 -44
  419. package/src/client/ssr-data.ts +6 -0
  420. package/src/client/stale-client.ts +191 -0
  421. package/src/client/state.ts +14 -1
  422. package/src/client/top-loader.tsx +2 -1
  423. package/src/client/unload-guard.ts +34 -2
  424. package/src/client/use-cookie.ts +9 -2
  425. package/src/client/use-query-states.ts +102 -39
  426. package/src/client/use-router.ts +1 -1
  427. package/src/client/use-segment-params.ts +41 -18
  428. package/src/cookies/define-cookie.ts +6 -1
  429. package/src/index.ts +25 -4
  430. package/src/plugin-context.ts +58 -0
  431. package/src/plugins/adapter-build.ts +4 -0
  432. package/src/plugins/build-manifest.ts +34 -13
  433. package/src/plugins/entries.ts +4 -0
  434. package/src/plugins/fonts.ts +11 -8
  435. package/src/plugins/request-dep/analysis.ts +447 -0
  436. package/src/plugins/request-dep/index.ts +376 -0
  437. package/src/plugins/request-dep/origin.ts +310 -0
  438. package/src/plugins/routing.ts +97 -102
  439. package/src/plugins/shims.ts +0 -1
  440. package/src/plugins/static-build.ts +391 -95
  441. package/src/routing/codegen-shared.ts +3 -79
  442. package/src/routing/codegen-types.ts +28 -31
  443. package/src/routing/codegen-write.ts +139 -0
  444. package/src/routing/codegen.ts +86 -172
  445. package/src/routing/collision-probe.ts +438 -0
  446. package/src/routing/collision-spaces.ts +281 -0
  447. package/src/routing/convention-lint.ts +139 -40
  448. package/src/routing/export-detect.ts +151 -7
  449. package/src/routing/interception.ts +896 -50
  450. package/src/routing/link-codegen.ts +32 -65
  451. package/src/routing/manifest-codegen.ts +6 -62
  452. package/src/routing/scanner.ts +117 -92
  453. package/src/routing/segment-classify.ts +57 -0
  454. package/src/routing/segment-keys.ts +146 -0
  455. package/src/routing/slot-placement.ts +97 -0
  456. package/src/routing/types.ts +0 -6
  457. package/src/routing/walkers.ts +8 -0
  458. package/src/schema-bridge.ts +180 -58
  459. package/src/search-params/define.ts +108 -66
  460. package/src/search-params/index.ts +0 -1
  461. package/src/search-params/parse-total.ts +78 -0
  462. package/src/search-params/wrappers.ts +60 -11
  463. package/src/server/access-gate.tsx +60 -40
  464. package/src/server/action-handler.ts +4 -5
  465. package/src/server/actions.ts +6 -3
  466. package/src/server/als-registry.ts +18 -1
  467. package/src/server/build-manifest.ts +14 -1
  468. package/src/server/chain-url-parts.ts +163 -0
  469. package/src/server/children-interception.ts +115 -0
  470. package/src/server/compress.ts +9 -1
  471. package/src/server/default-status-page.ts +127 -0
  472. package/src/server/deny-boundary.ts +269 -41
  473. package/src/server/deny-renderer.ts +111 -39
  474. package/src/server/error-boundary-wrapper.ts +166 -79
  475. package/src/server/head-response.ts +54 -0
  476. package/src/server/index.ts +1 -3
  477. package/src/server/internal.ts +2 -2
  478. package/src/server/metadata-collector.ts +115 -0
  479. package/src/server/param-coercion.ts +51 -69
  480. package/src/server/pipeline-helpers.ts +2 -47
  481. package/src/server/pipeline-interception.ts +81 -32
  482. package/src/server/pipeline-outcome.ts +4 -5
  483. package/src/server/pipeline-phases.ts +77 -25
  484. package/src/server/pipeline.ts +57 -10
  485. package/src/server/prebuilt-runtime.ts +4 -4
  486. package/src/server/primitives.ts +25 -0
  487. package/src/server/publish-params.ts +42 -0
  488. package/src/server/request-context.ts +97 -18
  489. package/src/server/route-element-builder.ts +241 -253
  490. package/src/server/route-handler.ts +8 -8
  491. package/src/server/route-matcher.ts +21 -9
  492. package/src/server/rsc-cache-key-guard.ts +164 -0
  493. package/src/server/rsc-entry/api-handler.ts +6 -8
  494. package/src/server/rsc-entry/deny-fallback.ts +3 -2
  495. package/src/server/rsc-entry/error-renderer.ts +94 -35
  496. package/src/server/rsc-entry/helpers.ts +33 -28
  497. package/src/server/rsc-entry/index.ts +36 -33
  498. package/src/server/rsc-entry/render-route.ts +18 -10
  499. package/src/server/rsc-entry/revalidate-renderer.ts +3 -2
  500. package/src/server/rsc-entry/rsc-payload.ts +113 -40
  501. package/src/server/rsc-entry/rsc-stream.ts +29 -5
  502. package/src/server/rsc-entry/ssr-renderer.ts +38 -22
  503. package/src/server/skippable-prefix.ts +92 -0
  504. package/src/server/slot-interception.ts +168 -0
  505. package/src/server/slot-resolver.ts +263 -158
  506. package/src/server/ssr-bridge-types.ts +18 -0
  507. package/src/server/ssr-entry.ts +20 -10
  508. package/src/server/ssr-wrappers.tsx +33 -32
  509. package/src/server/state-tree-diff.ts +14 -55
  510. package/src/server/static-generator.ts +68 -29
  511. package/src/server/static-not-found.ts +134 -0
  512. package/src/server/status-code-resolver.ts +28 -11
  513. package/src/server/tree-builder.ts +35 -218
  514. package/src/server/types.ts +12 -7
  515. package/src/server/utils/element-type.ts +72 -0
  516. package/src/shared/als-slots.ts +72 -0
  517. package/src/shared/base-path.ts +80 -0
  518. package/src/shared/param-value.ts +244 -0
  519. package/src/shared/payload-root.ts +151 -0
  520. package/src/shared/rsc-cache-key.ts +269 -0
  521. package/src/shared/rsc-error-envelope.ts +31 -0
  522. package/src/shared/rsc-manifest.ts +29 -0
  523. package/src/shared/rsc-media-type.ts +43 -0
  524. package/src/shared/rsc-payload-path.ts +45 -0
  525. package/src/shared/segment-info.ts +60 -0
  526. package/src/shared/slot-params.ts +111 -0
  527. package/src/shared/static-platform-files.ts +75 -0
  528. package/dist/_chunks/build-output-helper-DOGYFb_X.js +0 -196
  529. package/dist/_chunks/build-output-helper-DOGYFb_X.js.map +0 -1
  530. package/dist/_chunks/cache-api-B-lhk9p4.js.map +0 -1
  531. package/dist/_chunks/canonicalize-DQHyFClh.js.map +0 -1
  532. package/dist/_chunks/cli-schema-sync-BTWEKJXo.js +0 -668
  533. package/dist/_chunks/cli-schema-sync-BTWEKJXo.js.map +0 -1
  534. package/dist/_chunks/define-COtkxMRT.js +0 -191
  535. package/dist/_chunks/define-COtkxMRT.js.map +0 -1
  536. package/dist/_chunks/define-c4au4I9R.js +0 -82
  537. package/dist/_chunks/define-c4au4I9R.js.map +0 -1
  538. package/dist/_chunks/fast-hash-D6hIVt1Y.js.map +0 -1
  539. package/dist/_chunks/logger-AWfuX-KJ.js.map +0 -1
  540. package/dist/_chunks/navigation-root-bUDZLw74.js +0 -124
  541. package/dist/_chunks/navigation-root-bUDZLw74.js.map +0 -1
  542. package/dist/_chunks/plugin-context---kTF5v8.js.map +0 -1
  543. package/dist/_chunks/registry-DbJPKoBp.js +0 -20
  544. package/dist/_chunks/registry-DbJPKoBp.js.map +0 -1
  545. package/dist/_chunks/router-ref-CtmF-aPv.js.map +0 -1
  546. package/dist/_chunks/schema-bridge-DT_Tn0Xf.js +0 -119
  547. package/dist/_chunks/schema-bridge-DT_Tn0Xf.js.map +0 -1
  548. package/dist/_chunks/segment-classify-Byy425ng.js.map +0 -1
  549. package/dist/_chunks/segment-context-ZDnXDkbz.js +0 -34
  550. package/dist/_chunks/segment-context-ZDnXDkbz.js.map +0 -1
  551. package/dist/_chunks/ssr-data-BOWsq18U.js.map +0 -1
  552. package/dist/_chunks/use-query-states-DFvWd-EA.js.map +0 -1
  553. package/dist/_chunks/use-segment-params-D1CzlgBo.js +0 -151
  554. package/dist/_chunks/use-segment-params-D1CzlgBo.js.map +0 -1
  555. package/dist/_chunks/walkers-_6zKFlch.js +0 -1002
  556. package/dist/_chunks/walkers-_6zKFlch.js.map +0 -1
  557. package/dist/client/error-boundary.js.map +0 -1
  558. package/dist/plugins/request-dep.d.ts +0 -32
  559. package/dist/plugins/request-dep.d.ts.map +0 -1
  560. package/dist/search-params/registry.d.ts +0 -20
  561. package/dist/search-params/registry.d.ts.map +0 -1
  562. package/dist/segment-params/define.d.ts +0 -89
  563. package/dist/segment-params/define.d.ts.map +0 -1
  564. package/dist/segment-params/index.d.ts +0 -3
  565. package/dist/segment-params/index.d.ts.map +0 -1
  566. package/dist/segment-params/index.js +0 -2
  567. package/src/plugins/request-dep.ts +0 -499
  568. package/src/search-params/registry.ts +0 -31
  569. package/src/segment-params/define.ts +0 -249
  570. package/src/segment-params/index.ts +0 -9
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Segment key computation — the stable identity of a segment in the route tree.
3
+ *
4
+ * A segment key is the string that names a segment across the RSC/SSR/client
5
+ * boundary: it appears in the X-Timber-State-Tree header, the X-Timber-Segments
6
+ * header, SegmentOutlet props, the client segment cache, and (since TIM-1279)
7
+ * interception scoping.
8
+ *
9
+ * This module lives in `routing/` rather than `server/` because the keys are a
10
+ * property of the route tree itself — both the build-time scanner tree and the
11
+ * runtime manifest tree produce identical keys for the same directory, which is
12
+ * what lets a build-time value (an interception scope) be compared against a
13
+ * request-time matched chain.
14
+ *
15
+ * See design/19-client-navigation.md §"X-Timber-State-Tree Header"
16
+ */
17
+
18
+ /**
19
+ * Segment node shape expected by computeSegmentKeys.
20
+ *
21
+ * Structurally satisfied by both `SegmentNode` (build time) and
22
+ * `ManifestSegmentNode` (request time) — keys depend only on the
23
+ * URL path and the segment classification, never on file payloads.
24
+ */
25
+ export interface SegmentKeyInput {
26
+ urlPath: string;
27
+ segmentName?: string;
28
+ segmentType?: string;
29
+ }
30
+
31
+ /**
32
+ * Compute state-tree keys for a segment chain.
33
+ *
34
+ * Non-group segments use their urlPath as-is. Route groups accumulate
35
+ * ancestor group names to produce globally unique keys:
36
+ * app/(a)/(shared)/dashboard → keys: ['/', '/(a)', '/(a)/(shared)', '/dashboard']
37
+ *
38
+ * **An intercepting segment switches the chain to name accumulation for good.**
39
+ * A children-path interception (TIM-1280) puts an intercepting node and its
40
+ * descendants into the *main* rendered chain, and their `urlPath`s are not
41
+ * URLs: interception adds no URL depth, so `app/(browse)/(...)[artistSlug]/[year]`
42
+ * carries `/` and `/[year]`. Keyed by urlPath the intercepting node would
43
+ * collide with its own owner, and `[year]` with any top-level `[year]` route —
44
+ * so a client that had one mounted would reuse the wrong cached layout. The
45
+ * switch is sticky rather than per-node because the *descendants* are where
46
+ * the false URLs are; the intercepting node alone is not the problem.
47
+ *
48
+ * This is the single source of truth for segment keys — used by the
49
+ * element builder (skip decisions, SegmentOutlet props), segment info
50
+ * (X-Timber-Segments header), the client cache/state tree, and
51
+ * interception scoping (`routing/interception.ts`).
52
+ */
53
+ export function computeSegmentKeys(segments: SegmentKeyInput[]): string[] {
54
+ const keys: string[] = [];
55
+ let prevKey = '';
56
+ let insideIntercepting = false;
57
+
58
+ for (const segment of segments) {
59
+ if (segment.segmentType === 'intercepting') insideIntercepting = true;
60
+ if (segment.segmentType === 'group' || insideIntercepting) {
61
+ const base = prevKey === '/' ? '' : prevKey;
62
+ const key = `${base}/${segment.segmentName}`;
63
+ keys.push(key);
64
+ prevKey = key;
65
+ } else {
66
+ keys.push(segment.urlPath);
67
+ prevKey = segment.urlPath;
68
+ }
69
+ }
70
+
71
+ return keys;
72
+ }
73
+
74
+ /**
75
+ * Compute tree paths for a segment chain — the directory path of each segment
76
+ * with slots elided, e.g. `app/(browse)/feed` → `/(browse)/feed`.
77
+ *
78
+ * This is `computeSegmentKeys` with the group branch applied to *every*
79
+ * segment rather than only to groups. That one difference is the whole point:
80
+ * `computeSegmentKeys` resets to `urlPath` at each URL-visible segment, so
81
+ * `(browse)/feed` and `(landing)/feed` both key as `/feed`. Two directories
82
+ * that render different layouts must not share an identity.
83
+ *
84
+ * Used for interception scoping (`routing/interception.ts`), where the
85
+ * question is "does this route pass through *that* directory?" — not "does it
86
+ * render this URL?". Not interchangeable with `computeSegmentKeys`: the state
87
+ * tree is keyed by URL on purpose, because the client caches by URL.
88
+ */
89
+ export function computeSegmentTreePaths(segments: SegmentKeyInput[]): string[] {
90
+ const paths: string[] = [];
91
+ let prev = '';
92
+
93
+ for (const segment of segments) {
94
+ const name = segment.segmentName ?? '';
95
+ if (!name) {
96
+ // The app root — no directory name of its own.
97
+ paths.push('/');
98
+ prev = '/';
99
+ continue;
100
+ }
101
+ const base = prev === '/' ? '' : prev;
102
+ const path = `${base}/${name}`;
103
+ paths.push(path);
104
+ prev = path;
105
+ }
106
+
107
+ return paths;
108
+ }
109
+
110
+ /**
111
+ * The directory names a tree path is built from — `/` is none, `/feed/(a)` is
112
+ * `['feed', '(a)']`.
113
+ *
114
+ * The inverse of the walk above, and it lives beside it so the format is
115
+ * stated once: `findChainByTreePath` (`server/children-interception.ts`) walks
116
+ * these names back down the tree to the directory the path addresses, and
117
+ * `treePathDepth` counts them. Both are readings of the same string, and a
118
+ * reader that disagreed with the producer about what separates two names
119
+ * resolves an interception to the wrong node or to none.
120
+ */
121
+ export function treePathNames(treePath: string): string[] {
122
+ return treePath === '/' ? [] : treePath.slice(1).split('/');
123
+ }
124
+
125
+ /**
126
+ * How many directories a tree path names — `/` is 0, `/feed` is 1,
127
+ * `/feed/(a)` is 2.
128
+ *
129
+ * Two tree paths on a single rendered chain are strictly nested, so on that
130
+ * chain depth orders them totally — which is what makes it usable as "the
131
+ * deeper of these two directories" wherever a route passes through both
132
+ * (`routing/interception.ts`).
133
+ */
134
+ export function treePathDepth(treePath: string): number {
135
+ return treePathNames(treePath).length;
136
+ }
137
+
138
+ /**
139
+ * Compute a unique key for a parallel route slot.
140
+ * Format: `{parentSegmentId}/@{slotName}`, e.g. `/@sidebar` or `/dashboard/@modal`.
141
+ */
142
+ export function computeSlotKey(parentSegmentId: string, slotName: string): string {
143
+ const name = slotName.startsWith('@') ? slotName : `@${slotName}`;
144
+ const prefix = parentSegmentId === '/' ? '' : parentSegmentId;
145
+ return `${prefix}/${name}`;
146
+ }
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Parallel slot placement.
3
+ *
4
+ * One rule: a slot is resolved only for a segment on the **matched route
5
+ * chain**, and a slot's own subtree is never on that chain. So a slot declared
6
+ * anywhere inside another slot's subtree can never render, and is rejected at
7
+ * build time rather than left as a directory the author will keep editing.
8
+ *
9
+ * See design/07-routing.md §"Parallel Routes".
10
+ */
11
+
12
+ import type { SegmentNode } from './types.js';
13
+
14
+ /**
15
+ * Reject every parallel slot that no renderer reaches.
16
+ *
17
+ * **Where slots are resolved.** Two places read `segment.slots`, and both walk
18
+ * the main route chain: `route-element-builder.ts` (the RSC render) and
19
+ * `tree-builder.ts`. Neither is reachable from inside a slot. The slot's own
20
+ * subtree is rendered by `slot-resolver.ts`, which walks the slot's matched
21
+ * chain to apply that chain's layouts, error boundaries and access gates
22
+ * (`wrapWithIntermediateSegments`, `wrapWithLayout`) and never reads `.slots`
23
+ * on any of those nodes. So `app/feed/@modal/photo/@side/page.tsx` and
24
+ * everything below it is dead: the file is scanned, typed, code-split and
25
+ * shipped, and no request can render it.
26
+ *
27
+ * That is the TIM-1278 failure — a directory that silently never renders —
28
+ * and the reason it is a build error rather than a documented limit is that
29
+ * nothing at request time can report it. A slot that does not match renders
30
+ * `default.tsx` or `null`, which is exactly what a slot the resolver never
31
+ * looked at also produces, so the author sees the *designed* behaviour of a
32
+ * non-matching slot and has no signal to distinguish it from a slot that
33
+ * cannot match at all.
34
+ *
35
+ * **Interception is incidental.** TIM-1311 arrived as
36
+ * `feed/@modal/(.)photo/@side`, and the interception contributes nothing: the
37
+ * identical `feed/@modal/photo/@side` never renders either, for the same
38
+ * reason and with no marker anywhere. Rejecting only the intercepting spelling
39
+ * would have drawn a line the author cannot see from the directory names.
40
+ *
41
+ * The children-path interception shape is **not** affected and must not be:
42
+ * its intercepting node joins the main chain (`server/children-interception.ts`
43
+ * splices `[…owner ancestors, interceptingNode, …descendants]` into an ordinary
44
+ * `RouteMatch`), so `route-element-builder.ts` resolves slots on it and below
45
+ * it exactly as it does for any other chain segment. `(browse)/(...)photo/[id]/@side`
46
+ * renders; `feed/@modal/(.)photo/@side` does not. The discriminator is the slot
47
+ * boundary, which is what this walk tracks — not the marker.
48
+ */
49
+ export function validateSlotPlacement(root: SegmentNode): void {
50
+ walkForSlotPlacement(root, '', null);
51
+ }
52
+
53
+ /**
54
+ * `enclosingSlotPath` is the `app/`-relative path of the nearest slot at or
55
+ * above `node`, or null on the main chain. It is carried rather than recomputed
56
+ * so the error can name the slot that swallows the offender — "this is inside
57
+ * @modal" is the part of the diagnosis the author cannot see from the offending
58
+ * path alone.
59
+ */
60
+ function walkForSlotPlacement(
61
+ node: SegmentNode,
62
+ path: string,
63
+ enclosingSlotPath: string | null
64
+ ): void {
65
+ for (const [slotName, slotNode] of Object.entries(node.slots)) {
66
+ const slotPath = path ? `${path}/@${slotName}` : `@${slotName}`;
67
+ if (enclosingSlotPath !== null) {
68
+ throwNestedSlot(slotPath, enclosingSlotPath);
69
+ }
70
+ walkForSlotPlacement(slotNode, slotPath, slotPath);
71
+ }
72
+
73
+ for (const child of node.children) {
74
+ walkForSlotPlacement(
75
+ child,
76
+ path ? `${path}/${child.segmentName}` : child.segmentName,
77
+ enclosingSlotPath
78
+ );
79
+ }
80
+ }
81
+
82
+ function throwNestedSlot(slotPath: string, enclosingSlotPath: string): never {
83
+ throw new Error(
84
+ `Build error: parallel slot nested inside another parallel slot.\n` +
85
+ ` Directory: app/${slotPath}\n` +
86
+ ` Inside: app/${enclosingSlotPath}\n` +
87
+ `A parallel slot is resolved only for a segment on the matched route chain, and a ` +
88
+ `slot's own subtree is never on that chain — the slot resolver walks the slot's ` +
89
+ `matched chain to apply its layouts, error boundaries and access gates, and never ` +
90
+ `looks at slots declared inside it. So app/${slotPath} and everything below it can ` +
91
+ `never render, and no request-time signal can tell you: an unreachable slot ` +
92
+ `produces exactly what a slot that simply did not match produces.\n` +
93
+ `Declare the slot on a segment of the main route chain instead, or move its pages ` +
94
+ `into app/${enclosingSlotPath}'s own subtree.\n` +
95
+ `See design/07-routing.md §"Parallel Routes".`
96
+ );
97
+ }
@@ -96,12 +96,6 @@ export interface SegmentNode<TFile = RouteFile> {
96
96
  middleware?: TFile;
97
97
  access?: TFile;
98
98
  route?: TFile;
99
- /**
100
- * params.ts — isomorphic convention file exporting segmentParams and/or searchParams.
101
- * Discovered by the scanner like middleware.ts and access.ts.
102
- * See design/07-routing.md §"params.ts Convention File"
103
- */
104
- params?: TFile;
105
99
  error?: TFile;
106
100
  default?: TFile;
107
101
  /** Status-code files: 4xx.tsx, 5xx.tsx, {status}.tsx (component format) */
@@ -49,6 +49,12 @@ export interface CollectLeafRoutesOptions {
49
49
  * entries (the build report deduplicates by URL afterward).
50
50
  * - Parallel slots are skipped unless `includeSlots: true` (slots
51
51
  * share their parent's URL and are not addressable on their own).
52
+ * - Intercepting subtrees are skipped unconditionally. They render only
53
+ * on soft navigation and add no URL depth, so their computed `urlPath`s
54
+ * are not addresses — listing them would advertise routes (`/[year]`)
55
+ * that no request can reach. This matches every other consumer of the
56
+ * tree that produces URLs: the sitemap generator, the static generator,
57
+ * prerendering and the prebuilt-payload builder all skip them too.
52
58
  * - Result is sorted by `urlPath` for deterministic output.
53
59
  */
54
60
  export function collectLeafRoutes<TFile>(
@@ -68,6 +74,8 @@ function walk<TFile>(
68
74
  result: LeafRoute<TFile>[],
69
75
  includeSlots: boolean
70
76
  ): void {
77
+ if (node.segmentType === 'intercepting') return;
78
+
71
79
  const currentChain = [...chain, node];
72
80
  const path = node.urlPath || '/';
73
81
 
@@ -5,8 +5,17 @@
5
5
  * This module is the single source of truth for:
6
6
  * - StandardSchemaV1 interface (subset of the Standard Schema spec)
7
7
  * - validateSync() helper
8
- * - fromSchema() — bridge from Standard Schema to Codec<T>
9
- * - fromArraySchema() — bridge for array-valued codecs
8
+ * - fromSchema() — search-param bridge; scalar shape first, array second
9
+ * - fromArraySchema() — same loop, array shape first
10
+ * - fromCookieSchema() — scalar shape only; a cookie has no array shape
11
+ * - fromParamSchema() — route params; throws on failure (invalid param → 404)
12
+ *
13
+ * One parse loop, four candidate orders. Which shapes a bridge offers, and
14
+ * in what order, is the ONLY thing that differs — see §"Shape tolerance"
15
+ * below and in design/23-search-params.md. `serialize` is deliberately NOT
16
+ * shared: `null` means "omit the key" for a search param and "delete the
17
+ * cookie" for a cookie, so unifying it silently changed what
18
+ * `cookie.set([])` did (TIM-1352).
10
19
  *
11
20
  * These are re-exported from @timber-js/app/search-params, @timber-js/app/segment-params,
12
21
  * and @timber-js/app/cookies for convenience. The canonical import is
@@ -122,18 +131,21 @@ export function fromParamSchema<T>(fieldName: string, schema: StandardSchemaV1<T
122
131
  * @param fieldName - used in error messages
123
132
  * @param value - the codec or schema to resolve
124
133
  * @param mode - 'param' uses fromParamSchema (throws on parse failure),
125
- * 'search' uses fromSchema (falls back to default on failure)
134
+ * 'search' uses fromSchema (falls back to default on failure,
135
+ * tolerant of the repeated-key array shape),
136
+ * 'cookie' uses fromCookieSchema (same, minus the array shape,
137
+ * which a cookie value cannot have)
126
138
  */
127
139
  export function resolveCodecOrSchema(
128
140
  fieldName: string,
129
141
  value: unknown,
130
- mode: 'param' | 'search' = 'search'
142
+ mode: 'param' | 'search' | 'cookie' = 'search'
131
143
  ): Codec<unknown> {
132
144
  if (isCodec(value)) return value;
133
145
  if (isStandardSchema(value)) {
134
- return mode === 'param'
135
- ? fromParamSchema(fieldName, value)
136
- : (fromSchema(value) as Codec<unknown>);
146
+ if (mode === 'param') return fromParamSchema(fieldName, value);
147
+ if (mode === 'cookie') return fromCookieSchema(value) as Codec<unknown>;
148
+ return fromSchema(value) as Codec<unknown>;
137
149
  }
138
150
  throw new Error(
139
151
  `[timber] Field '${fieldName}' is not a valid codec or Standard Schema. ` +
@@ -146,51 +158,169 @@ export function resolveCodecOrSchema(
146
158
  // fromSchema — bridge from Standard Schema to Codec<T>
147
159
  // ---------------------------------------------------------------------------
148
160
 
161
+ // ---------------------------------------------------------------------------
162
+ // Shape tolerance — the shared parse loop for both bridges
163
+ //
164
+ // A URL value is `string | string[] | undefined`, but a schema is written
165
+ // against ONE of those: `z.string()` wants `'a'`, `z.array(z.string())`
166
+ // wants `['a']`. Nothing in Standard Schema says which — `~standard.types`
167
+ // exists at the type level only, and probing at runtime is not reliable
168
+ // (design/23-search-params.md §"Shape tolerance"). So a bridge tries BOTH
169
+ // shapes rather than committing to one and discarding the value when it
170
+ // guessed wrong.
171
+ //
172
+ // Each bridge only chooses WHICH candidates, and in what order. The first
173
+ // candidate is always the shape that bridge already passed, so nothing that
174
+ // parses today changes meaning; a later one is reached only where the old
175
+ // code fell through to the default. `fromCookieSchema` offers ONE candidate,
176
+ // because a cookie has no array shape at all.
177
+ // ---------------------------------------------------------------------------
178
+
179
+ /**
180
+ * The scalar shape, and only it. A value that cannot be repeated — a cookie —
181
+ * has no array shape to tolerate, so its bridge stays exactly where it was.
182
+ */
183
+ function scalarOnly(value: string | string[] | undefined): unknown[] {
184
+ return [Array.isArray(value) ? value[0] : value];
185
+ }
186
+
187
+ /** Candidate inputs for the scalar bridge: scalar first, array second. */
188
+ function scalarFirst(value: string | string[] | undefined): unknown[] {
189
+ if (value === undefined) return [undefined];
190
+ if (typeof value === 'string') return [value, [value]];
191
+ // Repeated keys: `value[0]` matches URLSearchParams.get().
192
+ //
193
+ // A raw `[]` carries no value at all. `value[0]` is `undefined`, which is
194
+ // the shape the scalar bridge has always passed for it, so `undefined`
195
+ // stays FIRST — an empty array must keep meaning "absent" and land on the
196
+ // schema's default. Only `defineSearchParams().parse({ tags: [] })`, the
197
+ // record form, can produce one: URLSearchParams never yields an empty list.
198
+ return value.length > 0 ? [value[0], value] : [undefined, value];
199
+ }
200
+
201
+ /** Candidate inputs for the array bridge: array first, scalar second. */
202
+ function arrayFirst(value: string | string[] | undefined): unknown[] {
203
+ if (value === undefined) return [undefined];
204
+ if (typeof value === 'string') return [[value], value];
205
+ // `[]` first here for the same reason, inverted: the array bridge has
206
+ // always passed the empty array straight through.
207
+ return value.length > 0 ? [value, value[0]] : [value, undefined];
208
+ }
209
+
210
+ /**
211
+ * Validate `value` against `schema` in each candidate shape, then fall back
212
+ * to the schema's default. Shared by every bridge — they differ only in
213
+ * which candidates they offer, and in what order.
214
+ */
215
+ function parseThroughSchema<T>(
216
+ schema: StandardSchemaV1<T>,
217
+ candidates: (value: string | string[] | undefined) => unknown[],
218
+ value: string | string[] | undefined
219
+ ): T {
220
+ const inputs = candidates(value);
221
+ for (let i = 0; i < inputs.length; i++) {
222
+ // A throw from the FIRST candidate propagates, unchanged: that is the
223
+ // shape the schema was written against, and a throw from it is the
224
+ // deliberate signal design/23 protects — an app schema may `redirect()`
225
+ // or `notFound()` on a value it refuses, and `validateSync` throws on
226
+ // an async schema.
227
+ //
228
+ // A throw from a LATER candidate is ours, not the app's. We invented
229
+ // that shape; the schema never agreed to receive it. A scalar-only
230
+ // hand-written validator doing `value.toUpperCase()`, or a schema that
231
+ // is async for the array shape only, would turn a field that used to
232
+ // fall back to its default into a render-phase 500. Treat it as "this
233
+ // shape does not fit" and keep going.
234
+ let result: StandardSchemaResult<T>;
235
+ try {
236
+ result = validateSync(schema, inputs[i]);
237
+ } catch (error) {
238
+ if (i === 0) throw error;
239
+ continue;
240
+ }
241
+ if (!result.issues) {
242
+ return result.value;
243
+ }
244
+ }
245
+
246
+ // No shape validated — try parsing undefined to get the default.
247
+ // Re-validate each time so factory defaults (e.g. .default(() => []))
248
+ // produce fresh values.
249
+ const defaultResult = validateSync(schema, undefined);
250
+ if (!defaultResult.issues) {
251
+ return defaultResult.value;
252
+ }
253
+
254
+ // No default available — the field is implicitly optional. Return
255
+ // undefined; defineSearchParams widens the field's inferred type to
256
+ // T | undefined via InferField so this doesn't lie.
257
+ // design/23-search-params.md §"Implicit Optionality"
258
+ return undefined as T;
259
+ }
260
+
149
261
  /**
150
262
  * Bridge a Standard Schema-compatible schema (Zod, Valibot, ArkType) to a
151
263
  * Codec<T>.
152
264
  *
153
- * Parse: coerces the raw string through the schema. On validation failure,
154
- * parses `undefined` to get the schema's default value (the schema should have
155
- * a `.default()` call). If that also fails, returns `undefined`.
265
+ * Parse: coerces the raw URL value through the schema, trying the scalar
266
+ * shape and then the array shape (see `scalarFirst`), so an array schema
267
+ * works bare: `z.array(z.string()).default([])` yields `[]` when absent,
268
+ * `['a']` for `?tags=a`, and `['a','b']` for `?tags=a&tags=b`. When no
269
+ * shape validates, parses `undefined` to get the schema's default (the
270
+ * schema should have a `.default()` call). If that also fails, returns
271
+ * `undefined`.
156
272
  *
157
- * Serialize: uses `String()` for primitives, `null` for null/undefined.
273
+ * Serialize: `String()` for primitives, `null` for null/undefined. Note
274
+ * that `String(['a','b'])` is `'a,b'` — the same string `fromArraySchema`
275
+ * writes — so a bare array schema round-trips exactly as design/09
276
+ * §"Array params" describes.
277
+ *
278
+ * This is the SEARCH-PARAM bridge. Cookies use `fromCookieSchema`; a
279
+ * cookie has no array shape (see below).
158
280
  *
159
281
  * ```ts
160
- * import { fromSchema } from '@timber-js/app/codec'
161
282
  * import { z } from 'zod/v4'
162
283
  *
163
284
  * const pageCodec = fromSchema(z.coerce.number().int().min(1).default(1))
285
+ * const tagsCodec = fromSchema(z.array(z.string()).default([]))
164
286
  * ```
165
287
  */
166
288
  export function fromSchema<T>(schema: StandardSchemaV1<T>): Codec<T> {
167
289
  return {
168
- parse(value: string | string[] | undefined): T {
169
- // For array inputs (duplicate query keys), use the first value.
170
- // Browsers and URLSearchParams.get() return the first occurrence.
171
- const input = Array.isArray(value) ? value[0] : value;
172
-
173
- // Try parsing the raw value
174
- const result = validateSync(schema, input);
175
- if (!result.issues) {
176
- return result.value;
177
- }
178
-
179
- // On failure, try parsing undefined to get the default.
180
- // Re-validate each time so factory defaults (e.g. .default(() => []))
181
- // produce fresh values.
182
- const defaultResult = validateSync(schema, undefined);
183
- if (!defaultResult.issues) {
184
- return defaultResult.value;
290
+ parse: (value: string | string[] | undefined): T =>
291
+ parseThroughSchema(schema, scalarFirst, value),
292
+ serialize(value: T): string | null {
293
+ if (value === null || value === undefined) {
294
+ return null;
185
295
  }
186
-
187
- // No default available — the field is implicitly optional. Return
188
- // undefined; defineSearchParams widens the field's inferred type to
189
- // T | undefined via InferField so this doesn't lie.
190
- // design/23-search-params.md §"Implicit Optionality"
191
- return undefined as T;
296
+ return String(value);
192
297
  },
298
+ };
299
+ }
193
300
 
301
+ // ---------------------------------------------------------------------------
302
+ // fromCookieSchema — bridge for cookie values
303
+ // ---------------------------------------------------------------------------
304
+
305
+ /**
306
+ * Bridge a Standard Schema for a COOKIE value.
307
+ *
308
+ * Identical to `fromSchema` minus the array shape, because a cookie cannot
309
+ * carry one: `Cookie:` headers and `document.cookie` yield a single string
310
+ * per name, and there is no repeated-key concept to be tolerant of. Sharing
311
+ * the search-param bridge here meant a cookie written by this very codec —
312
+ * `serialize(['a','b'])` → `a,b` — read back as the one-element array
313
+ * `['a,b']` instead of failing to its default: no repeated key in sight,
314
+ * just a delimiter reinterpreted as data.
315
+ *
316
+ * The `serialize` contract also differs by domain and must not be unified:
317
+ * for a search param `null` means "omit the key", for a cookie it means
318
+ * **delete the cookie** (design/29-cookies.md).
319
+ */
320
+ export function fromCookieSchema<T>(schema: StandardSchemaV1<T>): Codec<T> {
321
+ return {
322
+ parse: (value: string | string[] | undefined): T =>
323
+ parseThroughSchema(schema, scalarOnly, value),
194
324
  serialize(value: T): string | null {
195
325
  if (value === null || value === undefined) {
196
326
  return null;
@@ -214,32 +344,24 @@ export function fromSchema<T>(schema: StandardSchemaV1<T>): Codec<T> {
214
344
  *
215
345
  * const tagsCodec = fromArraySchema(z.array(z.string()).default([]))
216
346
  * ```
347
+ *
348
+ * Since TIM-1352 a bare array schema works through `fromSchema` too, so
349
+ * this is no longer required to make an array field parse. Two cases still
350
+ * want it, both listed in design/23 §"Shape tolerance":
351
+ *
352
+ * 1. A **permissive** schema meant as an array — one that accepts a string
353
+ * as readily as an array (`z.any()`, a hand-written coercing validator)
354
+ * — where scalar-first ordering would settle on the scalar shape.
355
+ * 2. An array schema wrapped in `.catch([])`, which swallows the failure
356
+ * that would otherwise trigger the array attempt.
357
+ *
358
+ * It also serializes an empty array to `null` (omitting the key) where
359
+ * `fromSchema` writes `''`.
217
360
  */
218
361
  export function fromArraySchema<T>(schema: StandardSchemaV1<T>): Codec<T> {
219
362
  return {
220
- parse(value: string | string[] | undefined): T {
221
- // Coerce single string to array for array schemas
222
- let input: unknown = value;
223
- if (typeof value === 'string') {
224
- input = [value];
225
- } else if (value === undefined) {
226
- input = undefined;
227
- }
228
-
229
- const result = validateSync(schema, input);
230
- if (!result.issues) {
231
- return result.value;
232
- }
233
-
234
- // On failure, try undefined for default
235
- const defaultResult = validateSync(schema, undefined);
236
- if (!defaultResult.issues) {
237
- return defaultResult.value;
238
- }
239
-
240
- return undefined as T;
241
- },
242
-
363
+ parse: (value: string | string[] | undefined): T =>
364
+ parseThroughSchema(schema, arrayFirst, value),
243
365
  serialize(value: T): string | null {
244
366
  if (value === null || value === undefined) {
245
367
  return null;