@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
@@ -6,14 +6,12 @@
6
6
 
7
7
  import type { ManifestSegmentNode } from '../route-matcher.js';
8
8
  import { swallow } from '../logger.js';
9
- import { computeSegmentKeys } from '../state-tree-diff.js';
9
+ import { computeSegmentKeys, computeSegmentTreePaths } from '../../routing/segment-keys.js';
10
+ import type { SegmentInfo } from '../../shared/segment-info.js';
10
11
  import type { SlotSkipEntry } from '../slot-resolver.js';
11
12
  import { isClientReference } from '../route-element-builder.js';
12
13
  import { isStaticRequestDependent } from '../request-dep.js';
13
14
 
14
- /** RSC content type for client navigation payload requests. */
15
- export const RSC_CONTENT_TYPE = 'text/x-component';
16
-
17
15
  /**
18
16
  * Create a debug channel sink that discards all debug data.
19
17
  *
@@ -180,16 +178,6 @@ export function parseDebugRows(text: string): DebugComponentEntry[] {
180
178
  *
181
179
  * See design/07-routing.md §"Server Diffing Rules".
182
180
  */
183
- interface SegmentInfoEntry {
184
- path: string;
185
- segmentId?: string;
186
- isRequestDependent: boolean;
187
- slot?: boolean;
188
- parentSegment?: string;
189
- denied?: boolean;
190
- skipped?: boolean;
191
- }
192
-
193
181
  export function buildSegmentInfo(
194
182
  segments: ManifestSegmentNode[],
195
183
  layoutComponents: Array<{
@@ -197,17 +185,34 @@ export function buildSegmentInfo(
197
185
  segment: ManifestSegmentNode;
198
186
  }>,
199
187
  slotSkipInfo?: SlotSkipEntry[],
200
- skippedSegmentKeys?: string[]
201
- ): SegmentInfoEntry[] {
188
+ skippedSegmentKeys?: string[],
189
+ firstDeniedIndex = Infinity
190
+ ): SegmentInfo[] {
202
191
  const layoutBySegment = new Map(
203
192
  layoutComponents.map(({ component, segment }) => [segment, component])
204
193
  );
205
194
 
206
195
  const segmentKeys = computeSegmentKeys(segments);
196
+ // The scope identity interception compares against. Emitted for every
197
+ // layout-bearing segment, which is exactly the set that can own a scope:
198
+ // slots are only resolved for segments whose layout renders
199
+ // (`route-element-builder.ts`), so a segment with no layout can never hold
200
+ // an intercepting slot. See TIM-1282.
201
+ const treePaths = computeSegmentTreePaths(segments);
207
202
  const skippedSet = skippedSegmentKeys ? new Set(skippedSegmentKeys) : null;
208
- const result: SegmentInfoEntry[] = [];
203
+ const result: SegmentInfo[] = [];
209
204
 
205
+ // Deepest segment that actually mounted, exclusive.
206
+ //
210
207
  for (let i = 0; i < segments.length; i++) {
208
+ // A denied segment's AccessGate renders the deny page in place of the
209
+ // layout, so this segment and everything below it never mounted. Their
210
+ // layouts were still loaded — `layoutComponents` holds every module the
211
+ // chain pulled in, not every component that rendered — so without this
212
+ // the client is told it has a tree it does not, and `treePaths` reports a
213
+ // slot owner whose slot was never resolved (TIM-1282).
214
+ if (i >= firstDeniedIndex) break;
215
+
211
216
  const segment = segments[i];
212
217
  const component = layoutBySegment.get(segment);
213
218
 
@@ -225,8 +230,9 @@ export function buildSegmentInfo(
225
230
  isRequestDependent = true;
226
231
  }
227
232
 
228
- const entry: SegmentInfoEntry = {
233
+ const entry: SegmentInfo = {
229
234
  path: segment.urlPath,
235
+ treePath: treePaths[i],
230
236
  isRequestDependent,
231
237
  };
232
238
  if (segmentId !== segment.urlPath) {
@@ -237,7 +243,7 @@ export function buildSegmentInfo(
237
243
 
238
244
  if (slotSkipInfo) {
239
245
  for (const slot of slotSkipInfo) {
240
- const entry: SegmentInfoEntry = {
246
+ const entry: SegmentInfo = {
241
247
  path: slot.slotKey,
242
248
  isRequestDependent: slot.isRequestDependent,
243
249
  slot: true,
@@ -252,15 +258,6 @@ export function buildSegmentInfo(
252
258
  return result;
253
259
  }
254
260
 
255
- /**
256
- * Check if a request is asking for an RSC payload (client navigation)
257
- * rather than full HTML. Client-side navigation sends Accept: text/x-component.
258
- */
259
- export function isRscPayloadRequest(req: Request): boolean {
260
- const accept = req.headers.get('Accept') ?? '';
261
- return accept.includes(RSC_CONTENT_TYPE);
262
- }
263
-
264
261
  // Re-export consolidated helpers from their single source of truth.
265
262
  // Callers within rsc-entry/ import from this file; the implementations
266
263
  // live in pipeline-helpers.ts (buildRedirectResponse) and render-utils.ts
@@ -270,3 +267,11 @@ export { isAbortError } from '../render-utils.js';
270
267
 
271
268
  // escapeHtml is now imported from server/utils/escape-html.ts
272
269
  export { escapeHtml } from '../utils/escape-html.js';
270
+
271
+ // Params no longer travel beside the payload. The payload root is the
272
+ // outermost node of every tree the server sends (`server/publish-params.ts`),
273
+ // so the record arrives as props React Flight serializes — which is what
274
+ // makes a `Date`- or `bigint`-valued codec result survive the trip, where
275
+ // `JSON.stringify` flattened it or threw. The response headers, the inline
276
+ // bootstrap scripts, and the two build-time manifest fields that used to
277
+ // carry it are all gone. See TIM-1294, design/41-global-params.md.
@@ -25,11 +25,6 @@
25
25
 
26
26
  // @ts-expect-error — virtual module provided by timber-routing plugin
27
27
  import routeManifest from 'virtual:timber-route-manifest';
28
- // TIM-830: Populate the search-params registry eagerly so <Link> can
29
- // serialize flat `Partial<T>` values synchronously in RSC renders.
30
- // The module has side effects only — no exports consumed here.
31
- // @ts-expect-error — virtual module provided by timber-routing plugin
32
- import 'virtual:timber-search-params-registry';
33
28
  // @ts-expect-error — virtual module provided by timber-entries plugin
34
29
  import config from 'virtual:timber-config';
35
30
  // @ts-expect-error — virtual module provided by timber-build-manifest plugin
@@ -54,6 +49,7 @@ import type { InterceptionContext, PipelineConfig, RouteMatch } from '../pipelin
54
49
  import { createPipeline } from '../pipeline.js';
55
50
  import { coerceSegmentParams, setGlobalSchemaCodecs } from '../param-coercion.js';
56
51
  import { createMetadataRouteMatcher, createRouteMatcher } from '../route-matcher.js';
52
+ import { createInterceptedRouteMatcher } from '../children-interception.js';
57
53
  import { initDevTracing } from '../tracing.js';
58
54
  import { createRevalidateRendererFactory } from './revalidate-renderer.js';
59
55
 
@@ -307,38 +303,45 @@ async function createRequestHandler(manifest: typeof routeManifest, runtimeConfi
307
303
  );
308
304
  },
309
305
  renderNoMatch: async (req: Request, responseHeaders: Headers) => {
310
- const response = await renderNoMatchPage(
311
- req,
312
- manifest.root,
313
- responseHeaders,
314
- clientBootstrap
315
- );
316
-
317
- // In dev mode, if the pipeline returned a bare 404 (no body — meaning
318
- // no user-defined 404.tsx was found), replace it with a helpful dev
319
- // page that lists available routes and suggests similar paths.
320
- // Only for GET requests that accept HTML — HEAD/API/RSC clients
321
- // should receive the bare 404 without an HTML body (TIM-793).
306
+ // In dev mode, when the app authored no 404 page, substitute a helpful
307
+ // page listing available routes and suggesting similar paths in place
308
+ // of the framework default. Only for GET requests that accept HTML —
309
+ // HEAD/API/RSC clients must not receive an HTML body (TIM-793).
310
+ //
311
+ // This is passed *into* the chain rather than applied to its result:
312
+ // the old version detected "no user-defined 404.tsx" by testing the
313
+ // response for an empty body, which stopped being true once the chain
314
+ // grew a real terminal (TIM-1258).
322
315
  const acceptsHtml = (req.headers.get('accept') ?? '').includes('text/html');
323
- if (isDev && !response.body && req.method === 'GET' && acceptsHtml) {
324
- const { generateDev404Page, collectRoutes } = await import('../../dev-tools/404-page.js');
325
- const routes = collectRoutes(manifest.root);
326
- const pathname = new URL(req.url).pathname;
327
- // devHmrOptions is set by the dev server after this module is
328
- // imported (read at request time, not closure-capture time).
329
- const html = generateDev404Page(pathname, routes, pipelineConfig.devHmrOptions);
330
- return new Response(html, {
331
- status: 404,
332
- headers: {
333
- ...Object.fromEntries(responseHeaders.entries()),
334
- 'content-type': 'text/html; charset=utf-8',
335
- },
336
- });
337
- }
316
+ const wantsDev404 = isDev && req.method === 'GET' && acceptsHtml;
317
+
318
+ // The dev page is loaded up front: the chain's terminal is synchronous,
319
+ // and dev-tools must stay out of the production bundle (dynamic import).
320
+ const devPage = wantsDev404
321
+ ? await import('../../dev-tools/404-page.js').catch(() => null)
322
+ : null;
323
+
324
+ const defaultPage = devPage
325
+ ? (_status: number, headers: Headers) => {
326
+ const routes = devPage.collectRoutes(manifest.root);
327
+ const pathname = new URL(req.url).pathname;
328
+ // devHmrOptions is set by the dev server after this module is
329
+ // imported (read at request time, not closure-capture time).
330
+ const html = devPage.generateDev404Page(pathname, routes, pipelineConfig.devHmrOptions);
331
+ return new Response(html, {
332
+ status: 404,
333
+ headers: {
334
+ ...Object.fromEntries(headers.entries()),
335
+ 'content-type': 'text/html; charset=utf-8',
336
+ },
337
+ });
338
+ }
339
+ : undefined;
338
340
 
339
- return response;
341
+ return renderNoMatchPage(req, manifest.root, responseHeaders, clientBootstrap, defaultPage);
340
342
  },
341
343
  interceptionRewrites: manifest.interceptionRewrites,
344
+ matchInterceptedRoute: createInterceptedRouteMatcher(manifest.root),
342
345
  // Slow request threshold from timber.config.ts. Default 3000ms, 0 to disable.
343
346
  // See design/17-logging.md §"slowRequestMs"
344
347
  slowRequestMs: (runtimeConfig as Record<string, unknown>).slowRequestMs as number | undefined,
@@ -41,9 +41,11 @@ import { recordTiming } from '../server-timing.js';
41
41
  import { requestContextAls } from '../als-registry.js';
42
42
  import { parseClientStateTree } from '../state-tree-diff.js';
43
43
 
44
+ import { getFirstDeniedSegmentIndex } from '../deny-boundary.js';
44
45
  import { handleApiRoute } from './api-handler.js';
45
46
  import { renderErrorPage, renderNoMatchPage } from './error-renderer.js';
46
- import { buildRedirectResponse, createDebugChannelSink, isRscPayloadRequest } from './helpers.js';
47
+ import { buildRedirectResponse, createDebugChannelSink } from './helpers.js';
48
+ import { isRscRequest } from '../../shared/rsc-media-type.js';
47
49
  import { buildRscPayloadResponse } from './rsc-payload.js';
48
50
  import { renderRscStream } from './rsc-stream.js';
49
51
  import { renderSsrResponse } from './ssr-renderer.js';
@@ -97,7 +99,7 @@ export async function renderRoute(
97
99
  // Only used for RSC requests — HTML requests always get a full render.
98
100
  // See design/19-client-navigation.md §"X-Timber-State-Tree Header"
99
101
  const clientStateTree =
100
- deps.clientSegmentCache && isRscPayloadRequest(req) ? parseClientStateTree(req) : null;
102
+ deps.clientSegmentCache && isRscRequest(req) ? parseClientStateTree(req) : null;
101
103
 
102
104
  // Build the React element tree — runs access checks eagerly to gate
103
105
  // metadata resolution (TIM-1027), then loads modules and resolves
@@ -140,7 +142,7 @@ export async function renderRoute(
140
142
  });
141
143
 
142
144
  const {
143
- element,
145
+ payload,
144
146
  layoutComponents,
145
147
  deferSuspenseFor,
146
148
  skippedSegments,
@@ -199,7 +201,7 @@ export async function renderRoute(
199
201
 
200
202
  // Render to RSC Flight stream with signal tracking.
201
203
  const _rscStart = performance.now();
202
- const { rscStream, signals, getDebugComponents } = renderRscStream(element, req);
204
+ const { rscStream, signals, getDebugComponents } = renderRscStream(payload, req);
203
205
  if (shellSettled) signals.shellSettled = shellSettled;
204
206
 
205
207
  // Store the debug components getter in ALS so onPipelineError can
@@ -224,14 +226,15 @@ export async function renderRoute(
224
226
  // Synchronous deny — deny() in a non-async component throws during
225
227
  // renderToReadableStream creation, caught in the try/catch above.
226
228
  if (signals.denySignal) {
227
- if (isRscPayloadRequest(req)) {
229
+ if (isRscRequest(req)) {
228
230
  return renderDenyPageAsRsc(
229
231
  signals.denySignal,
230
232
  segments,
231
233
  layoutComponents as LayoutEntry[],
232
234
  req,
233
235
  responseHeaders,
234
- createDebugChannelSink
236
+ createDebugChannelSink,
237
+ getFirstDeniedSegmentIndex()
235
238
  );
236
239
  }
237
240
  return renderDenyPage(
@@ -243,13 +246,18 @@ export async function renderRoute(
243
246
  responseHeaders,
244
247
  clientBootstrap,
245
248
  createDebugChannelSink,
246
- callSsr
249
+ callSsr,
250
+ undefined,
251
+ getFirstDeniedSegmentIndex()
247
252
  );
248
253
  }
249
254
 
250
255
  // Synchronous render error — renderToReadableStream threw before
251
256
  // creating the stream. Render the error page with correct 5xx status.
252
257
  // (Async render errors are tracked in onError and handled after SSR.)
258
+ // An RSC payload request gets the hard-navigate envelope rather than an
259
+ // error page — `renderErrorPage` owns that branch, so every one of its call
260
+ // sites is covered rather than this one alone (TIM-1322).
253
261
  if (signals.renderError && !rscStream) {
254
262
  return renderErrorPage(
255
263
  signals.renderError.error,
@@ -260,21 +268,21 @@ export async function renderRoute(
260
268
  match,
261
269
  responseHeaders,
262
270
  clientBootstrap,
263
- globalError
271
+ globalError,
272
+ getFirstDeniedSegmentIndex()
264
273
  );
265
274
  }
266
275
 
267
276
  // For RSC payload requests (client navigation), return the RSC Flight
268
277
  // stream directly — skip SSR HTML rendering entirely.
269
278
  // See design/19-client-navigation.md §"RSC Payload Handling"
270
- if (isRscPayloadRequest(req)) {
279
+ if (isRscRequest(req)) {
271
280
  return buildRscPayloadResponse(
272
281
  req,
273
282
  rscStream!,
274
283
  signals,
275
284
  segments,
276
285
  layoutComponents,
277
- match,
278
286
  responseHeaders,
279
287
  skippedSegments,
280
288
  slotSkipInfo
@@ -40,6 +40,7 @@ import { buildRouteElement } from '../route-element-builder.js';
40
40
  import type { RevalidateRenderer, RevalidationResult } from '../actions.js';
41
41
 
42
42
  import { runMiddlewareForAction, type CoerceSegmentParamsFn } from './action-middleware-runner.js';
43
+ import { RSC_CONTENT_TYPE } from '../../shared/rsc-media-type.js';
43
44
 
44
45
  /**
45
46
  * Sentinel thrown when revalidation cannot proceed because middleware
@@ -214,7 +215,7 @@ export function createRevalidateRendererFactory(
214
215
  revalidateUrl.pathname = validation.pathname;
215
216
  revalidateUrl.search = validation.search;
216
217
  const revalidateHeaders = new Headers(req.headers);
217
- revalidateHeaders.set('Accept', 'text/x-component');
218
+ revalidateHeaders.set('Accept', RSC_CONTENT_TYPE);
218
219
  // Snapshot the action's post-mutation cookie map (deletions
219
220
  // included) and serialize it into a `Cookie:` header value the
220
221
  // target middleware can read off `ctx.req.headers.get('cookie')`.
@@ -342,7 +343,7 @@ export function createRevalidateRendererFactory(
342
343
  deps.buildManifest.metadataRouteHashes
343
344
  );
344
345
  return {
345
- element: routeResult.element,
346
+ payload: routeResult.payload,
346
347
  };
347
348
  };
348
349
  };
@@ -10,21 +10,27 @@
10
10
 
11
11
  import type { LayoutEntry } from '../deny-renderer.js';
12
12
  import { renderDenyPageAsRsc } from '../deny-renderer.js';
13
- import type { RouteMatch } from '../pipeline.js';
14
13
  import type { RedirectSignal } from '../primitives.js';
15
14
  import type { LayoutComponentEntry } from '../route-element-builder.js';
16
15
  import type { ManifestSegmentNode } from '../route-matcher.js';
17
16
  import type { SlotSkipEntry } from '../slot-resolver.js';
18
17
 
19
- import {
20
- buildRedirectResponse,
21
- buildSegmentInfo,
22
- createDebugChannelSink,
23
- RSC_CONTENT_TYPE,
24
- } from './helpers.js';
18
+ import { buildRedirectResponse, buildSegmentInfo, createDebugChannelSink } from './helpers.js';
19
+ import { RSC_CONTENT_TYPE } from '../../shared/rsc-media-type.js';
20
+
21
+ import { rscErrorEnvelope } from '../../shared/rsc-error-envelope.js';
25
22
 
26
23
  import type { RenderSignals } from './rsc-stream.js';
27
24
 
25
+ /**
26
+ * Ceiling on waiting for a first chunk that is already in flight, used only
27
+ * when an addressed deny won the race against it. Matches the 50ms ceiling
28
+ * documented for the race itself: long enough that the error row — which is
29
+ * what the render just produced — arrives, short enough that a stalled stream
30
+ * cannot hold the response open.
31
+ */
32
+ const FIRST_CHUNK_CEILING_MS = 50;
33
+
28
34
  /**
29
35
  * Build an RSC payload Response for a client-side navigation request.
30
36
  *
@@ -40,7 +46,6 @@ export async function buildRscPayloadResponse(
40
46
  signals: RenderSignals,
41
47
  segments: ManifestSegmentNode[],
42
48
  layoutComponents: LayoutComponentEntry[],
43
- match: RouteMatch,
44
49
  responseHeaders: Headers,
45
50
  skippedSegments?: string[],
46
51
  slotSkipInfo?: SlotSkipEntry[]
@@ -70,10 +75,18 @@ export async function buildRscPayloadResponse(
70
75
  | { type: 'data'; chunk: ReadableStreamReadResult<Uint8Array> }
71
76
  | { type: 'signal' };
72
77
 
78
+ // Retained rather than inlined into the race below. When a signal wins, the
79
+ // usual answer is to cancel — but an ADDRESSED deny is one whose error row
80
+ // the client's boundary is going to render, so that payload has to survive
81
+ // (TIM-1356). Taking delivery of the read already in flight is not the
82
+ // "bare read() after a signal won" the async rules forbid; issuing a second
83
+ // one would be. It still gets a ceiling below.
84
+ const pendingRead = reader.read();
85
+
73
86
  let first: RaceResult;
74
87
  try {
75
88
  first = await Promise.race([
76
- reader.read().then((chunk) => ({ type: 'data' as const, chunk })),
89
+ pendingRead.then((chunk) => ({ type: 'data' as const, chunk })),
77
90
  signalDetected.then(() => ({ type: 'signal' as const })),
78
91
  ]);
79
92
  } catch (_readError) {
@@ -82,12 +95,7 @@ export async function buildRscPayloadResponse(
82
95
  // SSR-rendered error page. See design/10-error-handling.md.
83
96
  reader.cancel().catch(() => {});
84
97
  signals.onSignal = undefined;
85
- responseHeaders.set('X-Timber-Error', '1');
86
- responseHeaders.set('content-type', 'application/json; charset=utf-8');
87
- return new Response(JSON.stringify({ error: true, status: 500 }), {
88
- status: 500,
89
- headers: responseHeaders,
90
- });
98
+ return rscErrorEnvelope(500, responseHeaders);
91
99
  }
92
100
 
93
101
  // If data arrived first, still check signals — they may have fired
@@ -124,15 +132,42 @@ export async function buildRscPayloadResponse(
124
132
  reader.cancel().catch(() => {});
125
133
  return buildRedirectResponse(trackedRedirect, req, responseHeaders);
126
134
  }
127
- if (signals.denySignal) {
135
+ // An addressed deny needs no fallback: the payload already carries its error
136
+ // row, aimed at the boundary the client has mounted at that segment, which
137
+ // renders it. Cancelling would throw a finished render away and re-run the
138
+ // whole route — the exact cost TIM-666 removed. The status still lands,
139
+ // because the catch site called setDenyStatus() before re-throwing (read
140
+ // below via getDenyStatus).
141
+ //
142
+ // The question is asked of `unplacedDeny`, not of `denySignal.ownerKey`,
143
+ // because one render can produce both kinds and `denySignal` holds only one
144
+ // of them. A deny nothing could place has no boundary that may claim it, so
145
+ // its row would otherwise stream to a client with nothing to render it —
146
+ // and it needs the fallback whether or not some other deny was addressed
147
+ // first. See TIM-1356.
148
+ if (signals.unplacedDeny) {
128
149
  reader.cancel().catch(() => {});
150
+
151
+ // A skipped segment whose access just flipped to deny marks the signal
152
+ // for hard-navigate: rendering a deny page here would execute the denied
153
+ // segment's protected layout and place it inside cached client chrome
154
+ // (TIM-1074). Return rscErrorEnvelope so the client hard-navigates for
155
+ // a clean full render with correct deny page placement. See TIM-1363.
156
+ if (signals.unplacedDeny._hardNavigate) {
157
+ return rscErrorEnvelope(signals.unplacedDeny.status, responseHeaders);
158
+ }
159
+
160
+ // Read the denied segment index from ALS — set by AccessGate during
161
+ // render. See TIM-1358, TIM-1365.
162
+ const { getFirstDeniedSegmentIndex: getDeniedIdx } = await import('../deny-boundary.js');
129
163
  return renderDenyPageAsRsc(
130
- signals.denySignal,
164
+ signals.unplacedDeny,
131
165
  segments,
132
166
  layoutComponents as LayoutEntry[],
133
167
  req,
134
168
  responseHeaders,
135
- createDebugChannelSink
169
+ createDebugChannelSink,
170
+ getDeniedIdx()
136
171
  );
137
172
  }
138
173
 
@@ -143,15 +178,7 @@ export async function buildRscPayloadResponse(
143
178
  // §"Error Page Rendering for Client Navigation".
144
179
  if (signals.renderError) {
145
180
  reader.cancel().catch(() => {});
146
- responseHeaders.set('X-Timber-Error', '1');
147
- responseHeaders.set('content-type', 'application/json; charset=utf-8');
148
- return new Response(
149
- JSON.stringify({
150
- error: true,
151
- status: signals.renderError.status,
152
- }),
153
- { status: signals.renderError.status, headers: responseHeaders }
154
- );
181
+ return rscErrorEnvelope(signals.renderError.status, responseHeaders);
155
182
  }
156
183
 
157
184
  // Extract the first chunk from the race result.
@@ -162,6 +189,41 @@ export async function buildRscPayloadResponse(
162
189
  let firstRead: ReadableStreamReadResult<Uint8Array>;
163
190
  if (first.type === 'data') {
164
191
  firstRead = first.chunk;
192
+ } else if (signals.denySignal?.ownerKey) {
193
+ // An addressed deny won the race before its own error row surfaced.
194
+ // Cancelling here would hand the client a 4xx payload with nothing in it
195
+ // — no row for the owning boundary to render, so the navigation shows
196
+ // nothing at all. Take delivery of the read already in flight instead,
197
+ // under a ceiling so a stalled stream still cannot hang the response.
198
+ const TIMED_OUT = Symbol('first-chunk-timeout');
199
+ const raced = await Promise.race([
200
+ pendingRead,
201
+ new Promise<typeof TIMED_OUT>((resolve) =>
202
+ setTimeout(() => resolve(TIMED_OUT), FIRST_CHUNK_CEILING_MS)
203
+ ),
204
+ ]);
205
+
206
+ // Missing the ceiling must not be reported as a finished stream. Under
207
+ // event-loop contention or slow serialization the row is late rather than
208
+ // absent, and fabricating `done: true` here would produce the very empty
209
+ // 4xx this branch exists to prevent.
210
+ //
211
+ // Nor can it fall to `renderDenyPageAsRsc`. That renderer re-resolves from
212
+ // the FULL leaf chain and wraps whatever it finds, ignoring `ownerKey` —
213
+ // so an `/admin` denial addressed to a root `4xx.tsx` would come back as
214
+ // `/admin/secret/403.tsx` with the denied layouts executed, which is the
215
+ // TIM-1074 leak TIM-1358 still owns. A deny this path already placed
216
+ // correctly must not be handed to it.
217
+ //
218
+ // So: hard-navigate. The document request renders the same deny through
219
+ // the boundary at its owner, with the placement intact. A full page load
220
+ // is a real cost, on a path that needs a status page and a stalled stream
221
+ // to reach at all.
222
+ if (raced === TIMED_OUT) {
223
+ reader.cancel().catch(() => {});
224
+ return rscErrorEnvelope(signals.denySignal.status, responseHeaders);
225
+ }
226
+ firstRead = raced;
165
227
  } else {
166
228
  await reader.cancel();
167
229
  firstRead = { done: true, value: undefined };
@@ -200,7 +262,30 @@ export async function buildRscPayloadResponse(
200
262
  // for state tree diffing on subsequent navigations. Request-dependency
201
263
  // is determined by static module-graph analysis (not runtime taint).
202
264
  // See design/19-client-navigation.md §"X-Timber-State-Tree Header"
203
- const segmentInfo = buildSegmentInfo(segments, layoutComponents, slotSkipInfo, skippedSegments);
265
+ // Read the deny state before describing the tree — what mounted depends on it.
266
+ // Both values are recorded in ALS during render by AccessGate's catch path.
267
+ const { getDenyStatus, getFirstDeniedSegmentIndex } = await import('../deny-boundary.js');
268
+ const denyStatus = getDenyStatus();
269
+ const resolvedDenyIndex = getFirstDeniedSegmentIndex();
270
+
271
+ // Emitted in full even when a deny rendered, because this header answers two
272
+ // questions and they diverge here. The client picks its merge point out of
273
+ // this list (`buildSegmentUpdates`), and a partial payload with no merge
274
+ // point is never inserted at all — the URL commits over the stale previous
275
+ // UI. So it has to keep describing the chain the payload was BUILT against.
276
+ //
277
+ // What it must not also do on a deny is seed the segment cache, since the
278
+ // deny page replaced a subtree and part of that chain never mounted. That
279
+ // half is handled at the commit site from the response status, where the
280
+ // merge point has already been chosen. See `client/router-pipeline.ts` and
281
+ // TIM-1356.
282
+ const segmentInfo = buildSegmentInfo(
283
+ segments,
284
+ layoutComponents,
285
+ slotSkipInfo,
286
+ skippedSegments,
287
+ resolvedDenyIndex
288
+ );
204
289
  responseHeaders.set('X-Timber-Segments', JSON.stringify(segmentInfo));
205
290
 
206
291
  // Send skipped segments so the client can merge the partial RSC payload
@@ -209,18 +294,6 @@ export async function buildRscPayloadResponse(
209
294
  responseHeaders.set('X-Timber-Skipped-Segments', JSON.stringify(skippedSegments));
210
295
  }
211
296
 
212
- // Send route params so the client can populate useSegmentParams() after
213
- // SPA navigation. Without this, useSegmentParams() returns {}.
214
- if (Object.keys(match.segmentParams).length > 0) {
215
- responseHeaders.set('X-Timber-Params', JSON.stringify(match.segmentParams));
216
- }
217
-
218
- // Check if a DenySignal was caught in-tree by AccessGate or
219
- // PageDenyBoundary. The deny page is in the Flight stream as a normal
220
- // element — use the deny status for the HTTP response. See TIM-666.
221
- const { getDenyStatus } = await import('../deny-boundary.js');
222
- const denyStatus = getDenyStatus();
223
-
224
297
  return new Response(patchedStream, {
225
298
  status: denyStatus ?? 200,
226
299
  headers: responseHeaders,
@@ -11,6 +11,7 @@
11
11
  */
12
12
 
13
13
  import { renderToReadableStream } from '../../rsc-runtime/rsc.js';
14
+ import type { RscPayloadRoot } from '../../shared/payload-root.js';
14
15
 
15
16
  import { randomUUID } from 'node:crypto';
16
17
 
@@ -39,6 +40,18 @@ import { isDevMode } from '../debug.js';
39
40
  */
40
41
  export interface RenderSignals {
41
42
  denySignal: DenySignal | null;
43
+ /**
44
+ * The first deny that no in-tree catch site could place — no `ownerKey`, so
45
+ * no boundary may claim its error row and only the re-render fallback can
46
+ * produce a page for it.
47
+ *
48
+ * Tracked apart from `denySignal` because one render can produce both. A
49
+ * deep page can hoist a 404 to a boundary that will render it while an
50
+ * outer layout separately throws a 403 nothing matches; whichever lands in
51
+ * `denySignal` first, the unplaced one still needs the fallback, and
52
+ * deciding from `denySignal.ownerKey` alone would strand it. See TIM-1356.
53
+ */
54
+ unplacedDeny: DenySignal | null;
42
55
  redirectSignal: RedirectSignal | null;
43
56
  renderError: { error: unknown; status: number } | null;
44
57
  /**
@@ -74,7 +87,7 @@ export interface RscStreamResult {
74
87
  }
75
88
 
76
89
  /**
77
- * Render a React element tree to an RSC Flight stream.
90
+ * Render a payload root (tree plus its params) to an RSC Flight stream.
78
91
  *
79
92
  * The stream serializes server components as rendered output and client
80
93
  * components ("use client") as serialized references with module ID + export name.
@@ -84,9 +97,10 @@ export interface RscStreamResult {
84
97
  * fires onError during stream consumption. Signals are captured in the
85
98
  * returned `signals` object for the caller to handle.
86
99
  */
87
- export function renderRscStream(element: React.ReactElement, req: Request): RscStreamResult {
100
+ export function renderRscStream(payload: RscPayloadRoot, req: Request): RscStreamResult {
88
101
  const signals: RenderSignals = {
89
102
  denySignal: null,
103
+ unplacedDeny: null,
90
104
  redirectSignal: null,
91
105
  renderError: null,
92
106
  lastUnhandledError: null,
@@ -100,7 +114,7 @@ export function renderRscStream(element: React.ReactElement, req: Request): RscS
100
114
 
101
115
  try {
102
116
  rscStream = renderToReadableStream(
103
- element,
117
+ payload,
104
118
  {
105
119
  signal: req.signal,
106
120
  onError(error: unknown) {
@@ -109,9 +123,18 @@ export function renderRscStream(element: React.ReactElement, req: Request): RscS
109
123
  if (isAbortError(error) || req.signal?.aborted) return;
110
124
  if (error instanceof DenySignal) {
111
125
  signals.denySignal = error;
126
+ if (!error.ownerKey) signals.unplacedDeny ??= error;
112
127
  signals.onSignal?.();
113
- // Return structured digest for client-side error boundaries
114
- return JSON.stringify({ type: 'deny', status: error.status, data: error.data });
128
+ // Return structured digest for client-side error boundaries.
129
+ // `ownerKey` is set when an in-tree catch site hoisted the deny
130
+ // to the segment owning the matched file — it addresses the
131
+ // boundary that may render it. See TIM-1356.
132
+ return JSON.stringify({
133
+ type: 'deny',
134
+ status: error.status,
135
+ data: error.data,
136
+ ownerKey: error.ownerKey,
137
+ });
115
138
  }
116
139
  if (error instanceof RedirectSignal) {
117
140
  signals.redirectSignal = error;
@@ -217,6 +240,7 @@ export function renderRscStream(element: React.ReactElement, req: Request): RscS
217
240
  } catch (error) {
218
241
  if (error instanceof DenySignal) {
219
242
  signals.denySignal = error;
243
+ if (!error.ownerKey) signals.unplacedDeny ??= error;
220
244
  } else if (error instanceof RedirectSignal) {
221
245
  signals.redirectSignal = error;
222
246
  } else {