@timber-js/app 0.2.0-alpha.9 → 0.2.0-alpha.90

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 (610) hide show
  1. package/dist/_chunks/actions-DLnUaR65.js +421 -0
  2. package/dist/_chunks/actions-DLnUaR65.js.map +1 -0
  3. package/dist/_chunks/{als-registry-B7DbZ2hS.js → als-registry-HS0LGUl2.js} +1 -1
  4. package/dist/_chunks/als-registry-HS0LGUl2.js.map +1 -0
  5. package/dist/_chunks/chunk-BYIpzuS7.js +39 -0
  6. package/dist/_chunks/{debug-gwlJkDuf.js → debug-ECi_61pb.js} +2 -2
  7. package/dist/_chunks/debug-ECi_61pb.js.map +1 -0
  8. package/dist/_chunks/define-C77ScO0m.js +106 -0
  9. package/dist/_chunks/define-C77ScO0m.js.map +1 -0
  10. package/dist/_chunks/define-Itxvcd7F.js +199 -0
  11. package/dist/_chunks/define-Itxvcd7F.js.map +1 -0
  12. package/dist/_chunks/define-cookie-BowvzoP0.js +94 -0
  13. package/dist/_chunks/define-cookie-BowvzoP0.js.map +1 -0
  14. package/dist/_chunks/{format-DviM89f0.js → dev-warnings-DpGRGoDi.js} +5 -44
  15. package/dist/_chunks/dev-warnings-DpGRGoDi.js.map +1 -0
  16. package/dist/_chunks/format-CYBGxKtc.js +14 -0
  17. package/dist/_chunks/format-CYBGxKtc.js.map +1 -0
  18. package/dist/_chunks/{interception-BOoWmLUA.js → interception-DRlhJWbu.js} +219 -97
  19. package/dist/_chunks/interception-DRlhJWbu.js.map +1 -0
  20. package/dist/_chunks/merge-search-params-Cm_KIWDX.js +41 -0
  21. package/dist/_chunks/merge-search-params-Cm_KIWDX.js.map +1 -0
  22. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → metadata-routes-DS3eKNmf.js} +1 -1
  23. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js.map → metadata-routes-DS3eKNmf.js.map} +1 -1
  24. package/dist/_chunks/request-context-CK5tZqIP.js +478 -0
  25. package/dist/_chunks/request-context-CK5tZqIP.js.map +1 -0
  26. package/dist/_chunks/schema-bridge-C3xl_vfb.js +86 -0
  27. package/dist/_chunks/schema-bridge-C3xl_vfb.js.map +1 -0
  28. package/dist/_chunks/segment-classify-BDNn6EzD.js +65 -0
  29. package/dist/_chunks/segment-classify-BDNn6EzD.js.map +1 -0
  30. package/dist/_chunks/segment-context-fHFLF1PE.js +34 -0
  31. package/dist/_chunks/segment-context-fHFLF1PE.js.map +1 -0
  32. package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-DzuI0bIV.js} +1 -1
  33. package/dist/_chunks/{ssr-data-MjmprTmO.js.map → ssr-data-DzuI0bIV.js.map} +1 -1
  34. package/dist/_chunks/stale-reload-BX5gL1r-.js +64 -0
  35. package/dist/_chunks/stale-reload-BX5gL1r-.js.map +1 -0
  36. package/dist/_chunks/{tracing-CemImE6h.js → tracing-CCYbKn5n.js} +60 -9
  37. package/dist/_chunks/tracing-CCYbKn5n.js.map +1 -0
  38. package/dist/_chunks/use-params-Br9YSUFV.js +295 -0
  39. package/dist/_chunks/use-params-Br9YSUFV.js.map +1 -0
  40. package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-BiV5GJgm.js} +7 -4
  41. package/dist/_chunks/use-query-states-BiV5GJgm.js.map +1 -0
  42. package/dist/adapters/cloudflare-dev.d.ts +109 -0
  43. package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
  44. package/dist/adapters/cloudflare-dev.js +73 -0
  45. package/dist/adapters/cloudflare-dev.js.map +1 -0
  46. package/dist/adapters/cloudflare-kv-cache.d.ts +64 -0
  47. package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
  48. package/dist/adapters/cloudflare-kv-cache.js +95 -0
  49. package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
  50. package/dist/adapters/cloudflare.d.ts +148 -12
  51. package/dist/adapters/cloudflare.d.ts.map +1 -1
  52. package/dist/adapters/cloudflare.js +135 -11
  53. package/dist/adapters/cloudflare.js.map +1 -1
  54. package/dist/adapters/compress-module.d.ts.map +1 -1
  55. package/dist/adapters/nitro.d.ts +17 -1
  56. package/dist/adapters/nitro.d.ts.map +1 -1
  57. package/dist/adapters/nitro.js +56 -13
  58. package/dist/adapters/nitro.js.map +1 -1
  59. package/dist/cache/cache-api.d.ts +24 -0
  60. package/dist/cache/cache-api.d.ts.map +1 -0
  61. package/dist/cache/handler-store.d.ts +31 -0
  62. package/dist/cache/handler-store.d.ts.map +1 -0
  63. package/dist/cache/index.d.ts +23 -7
  64. package/dist/cache/index.d.ts.map +1 -1
  65. package/dist/cache/index.js +142 -80
  66. package/dist/cache/index.js.map +1 -1
  67. package/dist/cache/singleflight.d.ts +18 -1
  68. package/dist/cache/singleflight.d.ts.map +1 -1
  69. package/dist/cache/sizeof.d.ts +22 -0
  70. package/dist/cache/sizeof.d.ts.map +1 -0
  71. package/dist/cache/timber-cache.d.ts +1 -1
  72. package/dist/cache/timber-cache.d.ts.map +1 -1
  73. package/dist/cli.d.ts +6 -1
  74. package/dist/cli.d.ts.map +1 -1
  75. package/dist/cli.js +8 -3
  76. package/dist/cli.js.map +1 -1
  77. package/dist/client/browser-dev.d.ts +27 -1
  78. package/dist/client/browser-dev.d.ts.map +1 -1
  79. package/dist/client/browser-entry/action-dispatch.d.ts +17 -0
  80. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -0
  81. package/dist/client/browser-entry/hmr.d.ts +21 -0
  82. package/dist/client/browser-entry/hmr.d.ts.map +1 -0
  83. package/dist/client/browser-entry/hydrate.d.ts +46 -0
  84. package/dist/client/browser-entry/hydrate.d.ts.map +1 -0
  85. package/dist/client/browser-entry/index.d.ts +30 -0
  86. package/dist/client/browser-entry/index.d.ts.map +1 -0
  87. package/dist/client/browser-entry/post-hydration.d.ts +26 -0
  88. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
  89. package/dist/client/browser-entry/router-init.d.ts +23 -0
  90. package/dist/client/browser-entry/router-init.d.ts.map +1 -0
  91. package/dist/client/browser-entry/rsc-stream.d.ts +24 -0
  92. package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -0
  93. package/dist/client/browser-entry/scroll.d.ts +19 -0
  94. package/dist/client/browser-entry/scroll.d.ts.map +1 -0
  95. package/dist/client/error-boundary.d.ts +12 -5
  96. package/dist/client/error-boundary.d.ts.map +1 -1
  97. package/dist/client/error-boundary.js +10 -4
  98. package/dist/client/error-boundary.js.map +1 -1
  99. package/dist/client/error-reconstituter.d.ts +54 -0
  100. package/dist/client/error-reconstituter.d.ts.map +1 -0
  101. package/dist/client/form.d.ts +6 -3
  102. package/dist/client/form.d.ts.map +1 -1
  103. package/dist/client/history.d.ts +19 -4
  104. package/dist/client/history.d.ts.map +1 -1
  105. package/dist/client/index.d.ts +9 -21
  106. package/dist/client/index.d.ts.map +1 -1
  107. package/dist/client/index.js +229 -1018
  108. package/dist/client/index.js.map +1 -1
  109. package/dist/client/internal.d.ts +18 -0
  110. package/dist/client/internal.d.ts.map +1 -0
  111. package/dist/client/internal.js +890 -0
  112. package/dist/client/internal.js.map +1 -0
  113. package/dist/client/link-pending-store.d.ts +63 -0
  114. package/dist/client/link-pending-store.d.ts.map +1 -0
  115. package/dist/client/link.d.ts +62 -55
  116. package/dist/client/link.d.ts.map +1 -1
  117. package/dist/client/nav-link-store.d.ts +36 -0
  118. package/dist/client/nav-link-store.d.ts.map +1 -0
  119. package/dist/client/navigation-api-types.d.ts +90 -0
  120. package/dist/client/navigation-api-types.d.ts.map +1 -0
  121. package/dist/client/navigation-api.d.ts +115 -0
  122. package/dist/client/navigation-api.d.ts.map +1 -0
  123. package/dist/client/navigation-context.d.ts +13 -2
  124. package/dist/client/navigation-context.d.ts.map +1 -1
  125. package/dist/client/{transition-root.d.ts → navigation-root.d.ts} +42 -8
  126. package/dist/client/navigation-root.d.ts.map +1 -0
  127. package/dist/client/nuqs-adapter.d.ts.map +1 -1
  128. package/dist/client/router-ref.d.ts +1 -1
  129. package/dist/client/router.d.ts +70 -4
  130. package/dist/client/router.d.ts.map +1 -1
  131. package/dist/client/rsc-fetch.d.ts +38 -3
  132. package/dist/client/rsc-fetch.d.ts.map +1 -1
  133. package/dist/client/segment-cache.d.ts +1 -1
  134. package/dist/client/segment-cache.d.ts.map +1 -1
  135. package/dist/client/segment-outlet.d.ts +63 -0
  136. package/dist/client/segment-outlet.d.ts.map +1 -0
  137. package/dist/client/ssr-data.d.ts +13 -4
  138. package/dist/client/ssr-data.d.ts.map +1 -1
  139. package/dist/client/stale-reload.d.ts +15 -0
  140. package/dist/client/stale-reload.d.ts.map +1 -1
  141. package/dist/client/top-loader.d.ts +5 -5
  142. package/dist/client/top-loader.d.ts.map +1 -1
  143. package/dist/client/use-link-status.d.ts +5 -5
  144. package/dist/client/use-link-status.d.ts.map +1 -1
  145. package/dist/client/use-params.d.ts +6 -4
  146. package/dist/client/use-params.d.ts.map +1 -1
  147. package/dist/client/{use-navigation-pending.d.ts → use-pending-navigation.d.ts} +4 -4
  148. package/dist/client/use-pending-navigation.d.ts.map +1 -0
  149. package/dist/client/use-query-states.d.ts +1 -1
  150. package/dist/client/use-query-states.d.ts.map +1 -1
  151. package/dist/client/use-router.d.ts +1 -1
  152. package/dist/codec.d.ts +33 -0
  153. package/dist/codec.d.ts.map +1 -0
  154. package/dist/codec.js +2 -0
  155. package/dist/config-types.d.ts +266 -0
  156. package/dist/config-types.d.ts.map +1 -0
  157. package/dist/config-validation.d.ts +51 -0
  158. package/dist/config-validation.d.ts.map +1 -0
  159. package/dist/content/index.d.ts +1 -10
  160. package/dist/content/index.d.ts.map +1 -1
  161. package/dist/content/index.js +0 -2
  162. package/dist/cookies/define-cookie.d.ts +35 -14
  163. package/dist/cookies/define-cookie.d.ts.map +1 -1
  164. package/dist/cookies/index.js +1 -83
  165. package/dist/fonts/bundle.d.ts +48 -0
  166. package/dist/fonts/bundle.d.ts.map +1 -0
  167. package/dist/fonts/css.d.ts +1 -0
  168. package/dist/fonts/css.d.ts.map +1 -1
  169. package/dist/fonts/dev-middleware.d.ts +22 -0
  170. package/dist/fonts/dev-middleware.d.ts.map +1 -0
  171. package/dist/fonts/pipeline.d.ts +138 -0
  172. package/dist/fonts/pipeline.d.ts.map +1 -0
  173. package/dist/fonts/transform.d.ts +72 -0
  174. package/dist/fonts/transform.d.ts.map +1 -0
  175. package/dist/fonts/types.d.ts +45 -1
  176. package/dist/fonts/types.d.ts.map +1 -1
  177. package/dist/fonts/virtual-modules.d.ts +59 -0
  178. package/dist/fonts/virtual-modules.d.ts.map +1 -0
  179. package/dist/index.d.ts +45 -190
  180. package/dist/index.d.ts.map +1 -1
  181. package/dist/index.js +4294 -2453
  182. package/dist/index.js.map +1 -1
  183. package/dist/plugin-context.d.ts +107 -0
  184. package/dist/plugin-context.d.ts.map +1 -0
  185. package/dist/plugins/adapter-build.d.ts +1 -1
  186. package/dist/plugins/adapter-build.d.ts.map +1 -1
  187. package/dist/plugins/build-manifest.d.ts +2 -2
  188. package/dist/plugins/build-manifest.d.ts.map +1 -1
  189. package/dist/plugins/build-report.d.ts +3 -3
  190. package/dist/plugins/build-report.d.ts.map +1 -1
  191. package/dist/plugins/client-chunks.d.ts +32 -0
  192. package/dist/plugins/client-chunks.d.ts.map +1 -0
  193. package/dist/plugins/content.d.ts +1 -1
  194. package/dist/plugins/content.d.ts.map +1 -1
  195. package/dist/plugins/dev-404-page.d.ts +56 -0
  196. package/dist/plugins/dev-404-page.d.ts.map +1 -0
  197. package/dist/plugins/dev-browser-logs.d.ts +84 -0
  198. package/dist/plugins/dev-browser-logs.d.ts.map +1 -0
  199. package/dist/plugins/dev-error-overlay.d.ts +49 -9
  200. package/dist/plugins/dev-error-overlay.d.ts.map +1 -1
  201. package/dist/plugins/dev-error-page.d.ts +58 -0
  202. package/dist/plugins/dev-error-page.d.ts.map +1 -0
  203. package/dist/plugins/dev-logs.d.ts +1 -1
  204. package/dist/plugins/dev-logs.d.ts.map +1 -1
  205. package/dist/plugins/dev-server.d.ts +1 -1
  206. package/dist/plugins/dev-server.d.ts.map +1 -1
  207. package/dist/plugins/dev-terminal-error.d.ts +28 -0
  208. package/dist/plugins/dev-terminal-error.d.ts.map +1 -0
  209. package/dist/plugins/entries.d.ts +1 -1
  210. package/dist/plugins/entries.d.ts.map +1 -1
  211. package/dist/plugins/fonts.d.ts +17 -73
  212. package/dist/plugins/fonts.d.ts.map +1 -1
  213. package/dist/plugins/mdx.d.ts +1 -1
  214. package/dist/plugins/mdx.d.ts.map +1 -1
  215. package/dist/plugins/routing.d.ts +1 -1
  216. package/dist/plugins/routing.d.ts.map +1 -1
  217. package/dist/plugins/server-bundle.d.ts.map +1 -1
  218. package/dist/plugins/shims.d.ts +6 -5
  219. package/dist/plugins/shims.d.ts.map +1 -1
  220. package/dist/plugins/static-build.d.ts +4 -4
  221. package/dist/plugins/static-build.d.ts.map +1 -1
  222. package/dist/routing/codegen.d.ts +2 -2
  223. package/dist/routing/codegen.d.ts.map +1 -1
  224. package/dist/routing/convention-lint.d.ts +41 -0
  225. package/dist/routing/convention-lint.d.ts.map +1 -0
  226. package/dist/routing/index.d.ts +2 -0
  227. package/dist/routing/index.d.ts.map +1 -1
  228. package/dist/routing/index.js +3 -2
  229. package/dist/routing/scanner.d.ts.map +1 -1
  230. package/dist/routing/segment-classify.d.ts +46 -0
  231. package/dist/routing/segment-classify.d.ts.map +1 -0
  232. package/dist/routing/status-file-lint.d.ts +2 -1
  233. package/dist/routing/status-file-lint.d.ts.map +1 -1
  234. package/dist/routing/types.d.ts +16 -4
  235. package/dist/routing/types.d.ts.map +1 -1
  236. package/dist/rsc-runtime/rsc.d.ts +1 -1
  237. package/dist/rsc-runtime/rsc.d.ts.map +1 -1
  238. package/dist/rsc-runtime/ssr.d.ts +12 -0
  239. package/dist/rsc-runtime/ssr.d.ts.map +1 -1
  240. package/dist/schema-bridge.d.ts +76 -0
  241. package/dist/schema-bridge.d.ts.map +1 -0
  242. package/dist/search-params/define.d.ts +139 -0
  243. package/dist/search-params/define.d.ts.map +1 -0
  244. package/dist/search-params/index.d.ts +4 -7
  245. package/dist/search-params/index.d.ts.map +1 -1
  246. package/dist/search-params/index.js +32 -441
  247. package/dist/search-params/index.js.map +1 -1
  248. package/dist/search-params/registry.d.ts +2 -2
  249. package/dist/search-params/registry.d.ts.map +1 -1
  250. package/dist/search-params/wrappers.d.ts +53 -0
  251. package/dist/search-params/wrappers.d.ts.map +1 -0
  252. package/dist/segment-params/define.d.ts +78 -0
  253. package/dist/segment-params/define.d.ts.map +1 -0
  254. package/dist/segment-params/index.d.ts +3 -0
  255. package/dist/segment-params/index.d.ts.map +1 -0
  256. package/dist/segment-params/index.js +2 -0
  257. package/dist/server/access-gate.d.ts +4 -0
  258. package/dist/server/access-gate.d.ts.map +1 -1
  259. package/dist/server/action-client.d.ts +41 -6
  260. package/dist/server/action-client.d.ts.map +1 -1
  261. package/dist/server/action-encryption.d.ts +76 -0
  262. package/dist/server/action-encryption.d.ts.map +1 -0
  263. package/dist/server/action-handler.d.ts +7 -0
  264. package/dist/server/action-handler.d.ts.map +1 -1
  265. package/dist/server/actions.d.ts +3 -6
  266. package/dist/server/actions.d.ts.map +1 -1
  267. package/dist/server/als-registry.d.ts +32 -4
  268. package/dist/server/als-registry.d.ts.map +1 -1
  269. package/dist/server/build-manifest.d.ts +2 -2
  270. package/dist/server/build-manifest.d.ts.map +1 -1
  271. package/dist/server/debug.d.ts +1 -1
  272. package/dist/server/default-logger.d.ts +22 -0
  273. package/dist/server/default-logger.d.ts.map +1 -0
  274. package/dist/server/deny-page-resolver.d.ts +52 -0
  275. package/dist/server/deny-page-resolver.d.ts.map +1 -0
  276. package/dist/server/deny-renderer.d.ts.map +1 -1
  277. package/dist/server/dev-holding-server.d.ts +52 -0
  278. package/dist/server/dev-holding-server.d.ts.map +1 -0
  279. package/dist/server/dev-source-map.d.ts +22 -0
  280. package/dist/server/dev-source-map.d.ts.map +1 -0
  281. package/dist/server/dev-warnings.d.ts +1 -21
  282. package/dist/server/dev-warnings.d.ts.map +1 -1
  283. package/dist/server/early-hints.d.ts +13 -5
  284. package/dist/server/early-hints.d.ts.map +1 -1
  285. package/dist/server/error-boundary-wrapper.d.ts +7 -1
  286. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  287. package/dist/server/fallback-error.d.ts +12 -7
  288. package/dist/server/fallback-error.d.ts.map +1 -1
  289. package/dist/server/flight-injection-state.d.ts +66 -0
  290. package/dist/server/flight-injection-state.d.ts.map +1 -0
  291. package/dist/server/flight-scripts.d.ts +42 -0
  292. package/dist/server/flight-scripts.d.ts.map +1 -0
  293. package/dist/server/flush.d.ts.map +1 -1
  294. package/dist/server/form-data.d.ts +29 -0
  295. package/dist/server/form-data.d.ts.map +1 -1
  296. package/dist/server/html-injectors.d.ts +51 -11
  297. package/dist/server/html-injectors.d.ts.map +1 -1
  298. package/dist/server/index.d.ts +5 -43
  299. package/dist/server/index.d.ts.map +1 -1
  300. package/dist/server/index.js +195 -2800
  301. package/dist/server/index.js.map +1 -1
  302. package/dist/server/internal.d.ts +46 -0
  303. package/dist/server/internal.d.ts.map +1 -0
  304. package/dist/server/internal.js +2900 -0
  305. package/dist/server/internal.js.map +1 -0
  306. package/dist/server/logger.d.ts +25 -7
  307. package/dist/server/logger.d.ts.map +1 -1
  308. package/dist/server/middleware-runner.d.ts +19 -4
  309. package/dist/server/middleware-runner.d.ts.map +1 -1
  310. package/dist/server/node-stream-transforms.d.ts +113 -0
  311. package/dist/server/node-stream-transforms.d.ts.map +1 -0
  312. package/dist/server/page-deny-boundary.d.ts +31 -0
  313. package/dist/server/page-deny-boundary.d.ts.map +1 -0
  314. package/dist/server/pipeline-interception.d.ts +1 -1
  315. package/dist/server/pipeline-interception.d.ts.map +1 -1
  316. package/dist/server/pipeline-metadata.d.ts +6 -0
  317. package/dist/server/pipeline-metadata.d.ts.map +1 -1
  318. package/dist/server/pipeline.d.ts +52 -10
  319. package/dist/server/pipeline.d.ts.map +1 -1
  320. package/dist/server/primitives.d.ts +69 -18
  321. package/dist/server/primitives.d.ts.map +1 -1
  322. package/dist/server/render-timeout.d.ts +51 -0
  323. package/dist/server/render-timeout.d.ts.map +1 -0
  324. package/dist/server/request-context.d.ts +112 -43
  325. package/dist/server/request-context.d.ts.map +1 -1
  326. package/dist/server/route-element-builder.d.ts +27 -1
  327. package/dist/server/route-element-builder.d.ts.map +1 -1
  328. package/dist/server/route-handler.d.ts.map +1 -1
  329. package/dist/server/route-matcher.d.ts +16 -2
  330. package/dist/server/route-matcher.d.ts.map +1 -1
  331. package/dist/server/rsc-entry/api-handler.d.ts +2 -2
  332. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  333. package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
  334. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  335. package/dist/server/rsc-entry/helpers.d.ts +48 -5
  336. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  337. package/dist/server/rsc-entry/index.d.ts +20 -3
  338. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  339. package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
  340. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  341. package/dist/server/rsc-entry/rsc-stream.d.ts +14 -1
  342. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  343. package/dist/server/rsc-entry/ssr-bridge.d.ts +1 -1
  344. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  345. package/dist/server/rsc-entry/ssr-renderer.d.ts +19 -4
  346. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  347. package/dist/server/safe-load.d.ts +46 -0
  348. package/dist/server/safe-load.d.ts.map +1 -0
  349. package/dist/server/sensitive-fields.d.ts +74 -0
  350. package/dist/server/sensitive-fields.d.ts.map +1 -0
  351. package/dist/server/sitemap-generator.d.ts +129 -0
  352. package/dist/server/sitemap-generator.d.ts.map +1 -0
  353. package/dist/server/sitemap-handler.d.ts +22 -0
  354. package/dist/server/sitemap-handler.d.ts.map +1 -0
  355. package/dist/server/slot-resolver.d.ts +1 -1
  356. package/dist/server/slot-resolver.d.ts.map +1 -1
  357. package/dist/server/ssr-entry.d.ts +23 -0
  358. package/dist/server/ssr-entry.d.ts.map +1 -1
  359. package/dist/server/ssr-render.d.ts +39 -21
  360. package/dist/server/ssr-render.d.ts.map +1 -1
  361. package/dist/server/ssr-wrappers.d.ts +50 -0
  362. package/dist/server/ssr-wrappers.d.ts.map +1 -0
  363. package/dist/server/status-code-resolver.d.ts +1 -1
  364. package/dist/server/status-code-resolver.d.ts.map +1 -1
  365. package/dist/server/stream-utils.d.ts +36 -0
  366. package/dist/server/stream-utils.d.ts.map +1 -0
  367. package/dist/server/tracing.d.ts +4 -4
  368. package/dist/server/tracing.d.ts.map +1 -1
  369. package/dist/server/tree-builder.d.ts +22 -19
  370. package/dist/server/tree-builder.d.ts.map +1 -1
  371. package/dist/server/types.d.ts +1 -4
  372. package/dist/server/types.d.ts.map +1 -1
  373. package/dist/server/version-skew.d.ts +61 -0
  374. package/dist/server/version-skew.d.ts.map +1 -0
  375. package/dist/shared/merge-search-params.d.ts +22 -0
  376. package/dist/shared/merge-search-params.d.ts.map +1 -0
  377. package/dist/shims/font-google.d.ts +1 -1
  378. package/dist/shims/font-google.d.ts.map +1 -1
  379. package/dist/shims/font-google.js +42 -0
  380. package/dist/shims/font-google.js.map +1 -0
  381. package/dist/shims/font-local.d.ts +26 -0
  382. package/dist/shims/font-local.d.ts.map +1 -0
  383. package/dist/shims/font-local.js +20 -0
  384. package/dist/shims/font-local.js.map +1 -0
  385. package/dist/shims/headers.d.ts +2 -1
  386. package/dist/shims/headers.d.ts.map +1 -1
  387. package/dist/shims/navigation-client.d.ts +1 -1
  388. package/dist/shims/navigation-client.d.ts.map +1 -1
  389. package/dist/shims/navigation.d.ts +3 -2
  390. package/dist/shims/navigation.d.ts.map +1 -1
  391. package/dist/utils/directive-parser.d.ts +5 -2
  392. package/dist/utils/directive-parser.d.ts.map +1 -1
  393. package/dist/utils/state-machine.d.ts +80 -0
  394. package/dist/utils/state-machine.d.ts.map +1 -0
  395. package/package.json +51 -16
  396. package/src/adapters/cloudflare-dev.ts +177 -0
  397. package/src/adapters/cloudflare-kv-cache.ts +142 -0
  398. package/src/adapters/cloudflare.ts +342 -28
  399. package/src/adapters/compress-module.ts +24 -4
  400. package/src/adapters/nitro.ts +52 -8
  401. package/src/adapters/wrangler.d.ts +7 -0
  402. package/src/cache/cache-api.ts +38 -0
  403. package/src/cache/handler-store.ts +68 -0
  404. package/src/cache/index.ts +81 -18
  405. package/src/cache/singleflight.ts +62 -4
  406. package/src/cache/sizeof.ts +31 -0
  407. package/src/cache/timber-cache.ts +24 -20
  408. package/src/cli.ts +16 -6
  409. package/src/client/browser-dev.ts +128 -1
  410. package/src/client/browser-entry/action-dispatch.ts +116 -0
  411. package/src/client/browser-entry/hmr.ts +81 -0
  412. package/src/client/browser-entry/hydrate.ts +145 -0
  413. package/src/client/browser-entry/index.ts +143 -0
  414. package/src/client/browser-entry/post-hydration.ts +119 -0
  415. package/src/client/browser-entry/router-init.ts +193 -0
  416. package/src/client/browser-entry/rsc-stream.ts +157 -0
  417. package/src/client/browser-entry/scroll.ts +27 -0
  418. package/src/client/error-boundary.tsx +48 -16
  419. package/src/client/error-reconstituter.tsx +65 -0
  420. package/src/client/form.tsx +14 -7
  421. package/src/client/history.ts +26 -4
  422. package/src/client/index.ts +65 -38
  423. package/src/client/internal.ts +57 -0
  424. package/src/client/link-pending-store.ts +111 -0
  425. package/src/client/link.tsx +342 -113
  426. package/src/client/nav-link-store.ts +47 -0
  427. package/src/client/navigation-api-types.ts +112 -0
  428. package/src/client/navigation-api.ts +332 -0
  429. package/src/client/navigation-context.ts +31 -6
  430. package/src/client/navigation-root.tsx +342 -0
  431. package/src/client/nuqs-adapter.tsx +16 -3
  432. package/src/client/router-ref.ts +1 -1
  433. package/src/client/router.ts +299 -72
  434. package/src/client/rsc-fetch.ts +97 -8
  435. package/src/client/segment-cache.ts +1 -1
  436. package/src/client/segment-outlet.tsx +86 -0
  437. package/src/client/ssr-data.ts +13 -5
  438. package/src/client/stale-reload.ts +72 -3
  439. package/src/client/top-loader.tsx +18 -6
  440. package/src/client/use-link-status.ts +7 -7
  441. package/src/client/use-params.ts +7 -5
  442. package/src/client/{use-navigation-pending.ts → use-pending-navigation.ts} +6 -6
  443. package/src/client/use-query-states.ts +9 -3
  444. package/src/client/use-router.ts +1 -1
  445. package/src/codec.ts +49 -0
  446. package/src/config-types.ts +264 -0
  447. package/src/config-validation.ts +303 -0
  448. package/src/content/index.ts +5 -13
  449. package/src/cookies/define-cookie.ts +78 -25
  450. package/src/cookies/index.ts +8 -0
  451. package/src/fonts/bundle.ts +142 -0
  452. package/src/fonts/css.ts +2 -1
  453. package/src/fonts/dev-middleware.ts +74 -0
  454. package/src/fonts/pipeline.ts +275 -0
  455. package/src/fonts/transform.ts +353 -0
  456. package/src/fonts/types.ts +50 -1
  457. package/src/fonts/virtual-modules.ts +159 -0
  458. package/src/index.ts +314 -355
  459. package/src/plugin-context.ts +240 -0
  460. package/src/plugins/adapter-build.ts +9 -3
  461. package/src/plugins/build-manifest.ts +13 -2
  462. package/src/plugins/build-report.ts +3 -3
  463. package/src/plugins/client-chunks.ts +65 -0
  464. package/src/plugins/content.ts +1 -1
  465. package/src/plugins/dev-404-page.ts +418 -0
  466. package/src/plugins/dev-browser-logs.ts +288 -0
  467. package/src/plugins/dev-error-overlay.ts +286 -42
  468. package/src/plugins/dev-error-page.ts +536 -0
  469. package/src/plugins/dev-logs.ts +1 -1
  470. package/src/plugins/dev-server.ts +146 -19
  471. package/src/plugins/dev-terminal-error.ts +217 -0
  472. package/src/plugins/entries.ts +111 -10
  473. package/src/plugins/fonts.ts +133 -638
  474. package/src/plugins/mdx.ts +1 -1
  475. package/src/plugins/routing.ts +213 -31
  476. package/src/plugins/server-action-exports.ts +1 -1
  477. package/src/plugins/server-bundle.ts +32 -1
  478. package/src/plugins/shims.ts +136 -35
  479. package/src/plugins/static-build.ts +17 -11
  480. package/src/routing/codegen.ts +273 -105
  481. package/src/routing/convention-lint.ts +356 -0
  482. package/src/routing/index.ts +2 -0
  483. package/src/routing/scanner.ts +93 -23
  484. package/src/routing/segment-classify.ts +89 -0
  485. package/src/routing/status-file-lint.ts +3 -2
  486. package/src/routing/types.ts +17 -4
  487. package/src/rsc-runtime/rsc.ts +2 -0
  488. package/src/rsc-runtime/ssr.ts +50 -0
  489. package/src/rsc-runtime/vendor-types.d.ts +7 -0
  490. package/src/{search-params/codecs.ts → schema-bridge.ts} +57 -20
  491. package/src/search-params/define.ts +482 -0
  492. package/src/search-params/index.ts +14 -20
  493. package/src/search-params/registry.ts +2 -2
  494. package/src/search-params/wrappers.ts +85 -0
  495. package/src/segment-params/define.ts +279 -0
  496. package/src/segment-params/index.ts +9 -0
  497. package/src/server/access-gate.tsx +70 -29
  498. package/src/server/action-client.ts +88 -15
  499. package/src/server/action-encryption.ts +144 -0
  500. package/src/server/action-handler.ts +53 -6
  501. package/src/server/actions.ts +10 -9
  502. package/src/server/als-registry.ts +34 -6
  503. package/src/server/build-manifest.ts +10 -4
  504. package/src/server/compress.ts +25 -7
  505. package/src/server/debug.ts +1 -1
  506. package/src/server/default-logger.ts +99 -0
  507. package/src/server/deny-page-resolver.ts +154 -0
  508. package/src/server/deny-renderer.ts +24 -38
  509. package/src/server/dev-holding-server.ts +185 -0
  510. package/src/server/dev-source-map.ts +31 -0
  511. package/src/server/dev-warnings.ts +4 -49
  512. package/src/server/early-hints.ts +36 -15
  513. package/src/server/error-boundary-wrapper.ts +74 -22
  514. package/src/server/fallback-error.ts +74 -102
  515. package/src/server/flight-injection-state.ts +113 -0
  516. package/src/server/flight-scripts.ts +62 -0
  517. package/src/server/flush.ts +2 -1
  518. package/src/server/form-data.ts +76 -0
  519. package/src/server/html-injectors.ts +280 -120
  520. package/src/server/index.ts +25 -177
  521. package/src/server/internal.ts +169 -0
  522. package/src/server/logger.ts +44 -36
  523. package/src/server/middleware-runner.ts +31 -4
  524. package/src/server/node-stream-transforms.ts +509 -0
  525. package/src/server/page-deny-boundary.tsx +56 -0
  526. package/src/server/pipeline-interception.ts +17 -16
  527. package/src/server/pipeline-metadata.ts +13 -0
  528. package/src/server/pipeline.ts +261 -66
  529. package/src/server/primitives.ts +111 -28
  530. package/src/server/render-timeout.ts +108 -0
  531. package/src/server/request-context.ts +293 -132
  532. package/src/server/route-element-builder.ts +283 -191
  533. package/src/server/route-handler.ts +24 -4
  534. package/src/server/route-matcher.ts +31 -20
  535. package/src/server/rsc-entry/api-handler.ts +15 -16
  536. package/src/server/rsc-entry/error-renderer.ts +305 -89
  537. package/src/server/rsc-entry/helpers.ts +134 -5
  538. package/src/server/rsc-entry/index.ts +304 -111
  539. package/src/server/rsc-entry/rsc-payload.ts +65 -18
  540. package/src/server/rsc-entry/rsc-stream.ts +81 -13
  541. package/src/server/rsc-entry/ssr-bridge.ts +14 -5
  542. package/src/server/rsc-entry/ssr-renderer.ts +171 -38
  543. package/src/server/safe-load.ts +60 -0
  544. package/src/server/sensitive-fields.ts +230 -0
  545. package/src/server/sitemap-generator.ts +338 -0
  546. package/src/server/sitemap-handler.ts +126 -0
  547. package/src/server/slot-resolver.ts +244 -229
  548. package/src/server/ssr-entry.ts +215 -32
  549. package/src/server/ssr-render.ts +289 -67
  550. package/src/server/ssr-wrappers.tsx +139 -0
  551. package/src/server/status-code-resolver.ts +1 -1
  552. package/src/server/stream-utils.ts +213 -0
  553. package/src/server/tracing.ts +20 -9
  554. package/src/server/tree-builder.ts +92 -58
  555. package/src/server/types.ts +3 -6
  556. package/src/server/version-skew.ts +104 -0
  557. package/src/shared/merge-search-params.ts +55 -0
  558. package/src/shims/font-google.ts +1 -1
  559. package/src/shims/font-local.ts +34 -0
  560. package/src/shims/headers.ts +5 -1
  561. package/src/shims/navigation-client.ts +1 -1
  562. package/src/shims/navigation.ts +7 -2
  563. package/src/utils/directive-parser.ts +5 -2
  564. package/src/utils/state-machine.ts +111 -0
  565. package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
  566. package/dist/_chunks/debug-gwlJkDuf.js.map +0 -1
  567. package/dist/_chunks/format-DviM89f0.js.map +0 -1
  568. package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
  569. package/dist/_chunks/request-context-DIkVh_jG.js +0 -330
  570. package/dist/_chunks/request-context-DIkVh_jG.js.map +0 -1
  571. package/dist/_chunks/tracing-CemImE6h.js.map +0 -1
  572. package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
  573. package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
  574. package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
  575. package/dist/cache/register-cached-function.d.ts +0 -17
  576. package/dist/cache/register-cached-function.d.ts.map +0 -1
  577. package/dist/client/browser-entry.d.ts +0 -21
  578. package/dist/client/browser-entry.d.ts.map +0 -1
  579. package/dist/client/link-status-provider.d.ts +0 -11
  580. package/dist/client/link-status-provider.d.ts.map +0 -1
  581. package/dist/client/transition-root.d.ts.map +0 -1
  582. package/dist/client/use-navigation-pending.d.ts.map +0 -1
  583. package/dist/cookies/index.js.map +0 -1
  584. package/dist/plugins/cache-transform.d.ts +0 -36
  585. package/dist/plugins/cache-transform.d.ts.map +0 -1
  586. package/dist/plugins/dynamic-transform.d.ts +0 -72
  587. package/dist/plugins/dynamic-transform.d.ts.map +0 -1
  588. package/dist/search-params/analyze.d.ts +0 -54
  589. package/dist/search-params/analyze.d.ts.map +0 -1
  590. package/dist/search-params/builtin-codecs.d.ts +0 -105
  591. package/dist/search-params/builtin-codecs.d.ts.map +0 -1
  592. package/dist/search-params/codecs.d.ts +0 -53
  593. package/dist/search-params/codecs.d.ts.map +0 -1
  594. package/dist/search-params/create.d.ts +0 -106
  595. package/dist/search-params/create.d.ts.map +0 -1
  596. package/dist/server/prerender.d.ts +0 -77
  597. package/dist/server/prerender.d.ts.map +0 -1
  598. package/dist/server/response-cache.d.ts +0 -54
  599. package/dist/server/response-cache.d.ts.map +0 -1
  600. package/src/cache/register-cached-function.ts +0 -103
  601. package/src/client/browser-entry.ts +0 -678
  602. package/src/client/link-status-provider.tsx +0 -30
  603. package/src/client/transition-root.tsx +0 -166
  604. package/src/plugins/cache-transform.ts +0 -199
  605. package/src/plugins/dynamic-transform.ts +0 -161
  606. package/src/search-params/analyze.ts +0 -192
  607. package/src/search-params/builtin-codecs.ts +0 -228
  608. package/src/search-params/create.ts +0 -321
  609. package/src/server/prerender.ts +0 -139
  610. package/src/server/response-cache.ts +0 -410
@@ -9,12 +9,12 @@
9
9
  * 16-metadata.md §"Head Elements"
10
10
  */
11
11
 
12
- import type { LayoutEntry } from '#/server/deny-renderer.js';
13
- import { renderDenyPageAsRsc } from '#/server/deny-renderer.js';
14
- import type { RouteMatch } from '#/server/pipeline.js';
15
- import type { RedirectSignal } from '#/server/primitives.js';
16
- import type { HeadElement, LayoutComponentEntry } from '#/server/route-element-builder.js';
17
- import type { ManifestSegmentNode } from '#/server/route-matcher.js';
12
+ import type { LayoutEntry } from '../deny-renderer.js';
13
+ import { renderDenyPageAsRsc } from '../deny-renderer.js';
14
+ import type { RouteMatch } from '../pipeline.js';
15
+ import type { RedirectSignal } from '../primitives.js';
16
+ import type { HeadElement, LayoutComponentEntry } from '../route-element-builder.js';
17
+ import type { ManifestSegmentNode } from '../route-matcher.js';
18
18
 
19
19
  import {
20
20
  buildRedirectResponse,
@@ -69,10 +69,25 @@ export async function buildRscPayloadResponse(
69
69
  | { type: 'data'; chunk: ReadableStreamReadResult<Uint8Array> }
70
70
  | { type: 'signal' };
71
71
 
72
- const first: RaceResult = await Promise.race([
73
- reader.read().then((chunk) => ({ type: 'data' as const, chunk })),
74
- signalDetected.then(() => ({ type: 'signal' as const })),
75
- ]);
72
+ let first: RaceResult;
73
+ try {
74
+ first = await Promise.race([
75
+ reader.read().then((chunk) => ({ type: 'data' as const, chunk })),
76
+ signalDetected.then(() => ({ type: 'signal' as const })),
77
+ ]);
78
+ } catch (_readError) {
79
+ // RSC stream failed on first read — unhandled error in the page component.
80
+ // Return an error response so the client can hard-navigate for the
81
+ // SSR-rendered error page. See design/10-error-handling.md.
82
+ reader.cancel().catch(() => {});
83
+ signals.onSignal = undefined;
84
+ responseHeaders.set('X-Timber-Error', '1');
85
+ responseHeaders.set('content-type', 'application/json; charset=utf-8');
86
+ return new Response(JSON.stringify({ error: true, status: 500 }), {
87
+ status: 500,
88
+ headers: responseHeaders,
89
+ });
90
+ }
76
91
 
77
92
  // If data arrived first, still check signals — they may have fired
78
93
  // concurrently. Also do a final ceiling timeout check for edge cases
@@ -102,10 +117,36 @@ export async function buildRscPayloadResponse(
102
117
  );
103
118
  }
104
119
 
120
+ // Check for unhandled errors (RenderError or plain Error).
121
+ // These aren't redirect/deny signals but the RSC stream will be broken.
122
+ // Return an error response so the client can hard-navigate for the
123
+ // SSR-rendered error page. See design/10-error-handling.md
124
+ // §"Error Page Rendering for Client Navigation".
125
+ if (signals.renderError) {
126
+ reader.cancel().catch(() => {});
127
+ responseHeaders.set('X-Timber-Error', '1');
128
+ responseHeaders.set('content-type', 'application/json; charset=utf-8');
129
+ return new Response(
130
+ JSON.stringify({
131
+ error: true,
132
+ status: signals.renderError.status,
133
+ }),
134
+ { status: signals.renderError.status, headers: responseHeaders }
135
+ );
136
+ }
137
+
105
138
  // Extract the first chunk from the race result.
106
- // If the signal won the race, read the first chunk now (the stream
107
- // was already cancelled above, but we need a firstRead shape below).
108
- const firstRead = first.type === 'data' ? first.chunk : await reader.read();
139
+ // If the signal won the race but neither redirect nor deny was detected
140
+ // (edge case), cancel the reader immediately rather than issuing a bare
141
+ // read() that could hang forever if the RSC stream has stalled.
142
+ // See TIM-519.
143
+ let firstRead: ReadableStreamReadResult<Uint8Array>;
144
+ if (first.type === 'data') {
145
+ firstRead = first.chunk;
146
+ } else {
147
+ await reader.cancel();
148
+ firstRead = { done: true, value: undefined };
149
+ }
109
150
 
110
151
  // Reconstruct the stream: prepend the buffered first chunk,
111
152
  // then continue piping from the original reader.
@@ -155,14 +196,20 @@ export async function buildRscPayloadResponse(
155
196
  responseHeaders.set('X-Timber-Skipped-Segments', JSON.stringify(skippedSegments));
156
197
  }
157
198
 
158
- // Send route params so the client can populate useParams() after
159
- // SPA navigation. Without this, useParams() returns {}.
160
- if (Object.keys(match.params).length > 0) {
161
- responseHeaders.set('X-Timber-Params', JSON.stringify(match.params));
199
+ // Send route params so the client can populate useSegmentParams() after
200
+ // SPA navigation. Without this, useSegmentParams() returns {}.
201
+ if (Object.keys(match.segmentParams).length > 0) {
202
+ responseHeaders.set('X-Timber-Params', JSON.stringify(match.segmentParams));
162
203
  }
163
204
 
205
+ // Check if a DenySignal was caught in-tree by AccessGate or
206
+ // PageDenyBoundary. The deny page is in the Flight stream as a normal
207
+ // element — use the deny status for the HTTP response. See TIM-666.
208
+ const { getDenyStatus } = await import('../deny-page-resolver.js');
209
+ const denyStatus = getDenyStatus();
210
+
164
211
  return new Response(patchedStream, {
165
- status: 200,
212
+ status: denyStatus ?? 200,
166
213
  headers: responseHeaders,
167
214
  });
168
215
  }
@@ -10,14 +10,22 @@
10
10
  * 13-security.md §"Errors don't leak"
11
11
  */
12
12
 
13
- import { renderToReadableStream } from '#/rsc-runtime/rsc.js';
13
+ import { renderToReadableStream } from '../../rsc-runtime/rsc.js';
14
14
 
15
- import { logRenderError } from '#/server/logger.js';
16
- import { DenySignal, RedirectSignal, RenderError } from '#/server/primitives.js';
17
- import { checkAndWarnRscPropError } from '#/server/rsc-prop-warnings.js';
15
+ import { randomUUID } from 'node:crypto';
18
16
 
19
- import { createDebugChannelSink, isAbortError } from './helpers.js';
20
- import { isDebug } from '#/server/debug.js';
17
+ import { logRenderError } from '../logger.js';
18
+ import { DenySignal, RedirectSignal, RenderError } from '../primitives.js';
19
+ import { checkAndWarnRscPropError } from '../rsc-prop-warnings.js';
20
+
21
+ import {
22
+ createDebugChannelSink,
23
+ createDebugChannelCollector,
24
+ isAbortError,
25
+ type DebugComponentEntry,
26
+ } from './helpers.js';
27
+ import { isDebug } from '../debug.js';
28
+ import { isDevMode } from '../debug.js';
21
29
 
22
30
  /**
23
31
  * Mutable signal state captured during RSC rendering.
@@ -33,6 +41,16 @@ export interface RenderSignals {
33
41
  denySignal: DenySignal | null;
34
42
  redirectSignal: RedirectSignal | null;
35
43
  renderError: { error: unknown; status: number } | null;
44
+ /**
45
+ * The last unhandled error seen by RSC onError that isn't a signal.
46
+ * Used as a fallback when SSR fails (SsrStreamError) but no structured
47
+ * signal was captured — provides the original error for the error page
48
+ * instead of relying on SsrStreamError.cause extraction.
49
+ *
50
+ * NOT used for page-level error detection (that would break Suspense
51
+ * error isolation). Only consumed when SSR actually fails.
52
+ */
53
+ lastUnhandledError: unknown | null;
36
54
  /** Callback fired when a redirect or deny signal is captured in onError. */
37
55
  onSignal?: () => void;
38
56
  }
@@ -40,6 +58,8 @@ export interface RenderSignals {
40
58
  export interface RscStreamResult {
41
59
  rscStream: ReadableStream<Uint8Array> | undefined;
42
60
  signals: RenderSignals;
61
+ /** Dev-only: server component debug info from the Flight debug channel. */
62
+ getDebugComponents?: () => DebugComponentEntry[];
43
63
  }
44
64
 
45
65
  /**
@@ -58,10 +78,15 @@ export function renderRscStream(element: React.ReactElement, req: Request): RscS
58
78
  denySignal: null,
59
79
  redirectSignal: null,
60
80
  renderError: null,
81
+ lastUnhandledError: null,
61
82
  };
62
83
 
63
84
  let rscStream: ReadableStream<Uint8Array> | undefined;
64
85
 
86
+ // In dev mode, collect debug channel data for the error overlay.
87
+ // In production, use the discard sink (no overhead).
88
+ const debugChannel = isDevMode() ? createDebugChannelCollector() : createDebugChannelSink();
89
+
65
90
  try {
66
91
  rscStream = renderToReadableStream(
67
92
  element,
@@ -126,13 +151,47 @@ export function renderRscStream(element: React.ReactElement, req: Request): RscS
126
151
  checkAndWarnRscPropError(error, new URL(req.url).pathname);
127
152
  }
128
153
 
129
- // Track unhandled errors for pre-flush handling (500 status)
130
- if (!signals.renderError) {
131
- signals.renderError = { error, status: 500 };
132
- }
133
- logRenderError({ method: req.method, path: new URL(req.url).pathname, error });
154
+ // Log the error but do NOT track it as a page-level render error.
155
+ // If this error is inside a <Suspense> boundary, React will emit
156
+ // an error row in the Flight stream and the Suspense fallback will
157
+ // render on the client. Tracking it as signals.renderError would
158
+ // cause the pipeline to treat the entire page as a 500, even though
159
+ // the shell rendered successfully. See TIM-524.
160
+ //
161
+ // Only track as renderError if no Suspense boundary contains it —
162
+ // React will call onShellError for truly unrecoverable errors.
163
+
164
+ // Track the last unhandled error so the pipeline can use it
165
+ // if SSR fails (SsrStreamError). This is NOT used for page-level
166
+ // error detection — only as a fallback when SSR actually fails.
167
+ signals.lastUnhandledError = error;
168
+
169
+ // Return a digest so React emits a per-row error in the Flight
170
+ // stream instead of leaving the lazy reference unresolved.
171
+ //
172
+ // SECURITY: Never include error.message in the digest — it may
173
+ // contain SQL queries, filesystem paths, secret fragments, or
174
+ // internal IDs. Use a generic message with a correlation ID so
175
+ // the error can be matched to server logs.
176
+ // See design/13-security.md §"Errors don't leak".
177
+ const errorId = randomUUID();
178
+ logRenderError({
179
+ method: req.method,
180
+ path: new URL(req.url).pathname,
181
+ error,
182
+ errorId,
183
+ });
184
+ return JSON.stringify({
185
+ type: 'error',
186
+ message: isDevMode()
187
+ ? error instanceof Error
188
+ ? error.message
189
+ : String(error)
190
+ : 'An unexpected error occurred.',
191
+ errorId,
192
+ });
134
193
  },
135
- debugChannel: createDebugChannelSink(),
194
+ debugChannel,
136
195
  },
137
196
  {
138
197
  onClientReference(info: { id: string; name: string; deps: unknown }) {
@@ -160,5 +219,14 @@ export function renderRscStream(element: React.ReactElement, req: Request): RscS
160
219
  }
161
220
  }
162
221
 
163
- return { rscStream, signals };
222
+ return {
223
+ rscStream,
224
+ signals,
225
+ // Expose the debug channel collector's getComponents in dev mode.
226
+ // The caller can retrieve component tree info when handling errors.
227
+ getDebugComponents:
228
+ 'getComponents' in debugChannel
229
+ ? (debugChannel as { getComponents: () => DebugComponentEntry[] }).getComponents
230
+ : undefined,
231
+ };
164
232
  }
@@ -4,15 +4,24 @@
4
4
 
5
5
  /// <reference types="@vitejs/plugin-rsc/types" />
6
6
 
7
- import type { NavContext } from '#/server/ssr-entry.js';
7
+ import type { NavContext } from '../ssr-entry.js';
8
8
 
9
9
  export async function callSsr(
10
10
  rscStream: ReadableStream<Uint8Array>,
11
11
  navContext: NavContext
12
12
  ): Promise<Response> {
13
- const ssrEntry = await import.meta.viteRsc.import<typeof import('#/server/ssr-entry.js')>(
14
- '../ssr-entry.js',
15
- { environment: 'ssr' }
16
- );
13
+ let ssrEntry: typeof import('../ssr-entry.js');
14
+ try {
15
+ ssrEntry = await import.meta.viteRsc.import<typeof import('../ssr-entry.js')>(
16
+ '../ssr-entry.js',
17
+ { environment: 'ssr' }
18
+ );
19
+ } catch (error) {
20
+ const original = error instanceof Error ? error.message : String(error);
21
+ throw new Error(
22
+ `[timber] Failed to load SSR entry from RSC environment.\n ${original}\n This usually means a module evaluation error in the SSR bundle.`,
23
+ { cause: error }
24
+ );
25
+ }
17
26
  return ssrEntry.handleSsr(rscStream, navContext);
18
27
  }
@@ -12,25 +12,49 @@
12
12
  * 05-streaming.md §"deferSuspenseFor and the Hold Window"
13
13
  */
14
14
 
15
- import type { ClientBootstrapConfig } from '#/server/html-injectors.js';
16
- import type { LayoutEntry } from '#/server/deny-renderer.js';
17
- import { renderDenyPage } from '#/server/deny-renderer.js';
18
- import type { RouteMatch } from '#/server/pipeline.js';
19
- import { SsrStreamError } from '#/server/primitives.js';
20
- import type { LayoutComponentEntry } from '#/server/route-element-builder.js';
21
- import type { ManifestSegmentNode } from '#/server/route-matcher.js';
22
- import type { NavContext } from '#/server/ssr-entry.js';
15
+ import type { ClientBootstrapConfig } from '../html-injectors.js';
16
+ import { flightInitScript } from '../flight-scripts.js';
17
+ import type { LayoutEntry } from '../deny-renderer.js';
18
+ import { renderDenyPage } from '../deny-renderer.js';
19
+ import type { RouteMatch } from '../pipeline.js';
20
+ import { SsrStreamError } from '../primitives.js';
21
+ import type { LayoutComponentEntry } from '../route-element-builder.js';
22
+ import type { ManifestSegmentNode } from '../route-matcher.js';
23
+ import type { NavContext } from '../ssr-entry.js';
23
24
 
24
25
  import {
25
26
  buildRedirectResponse,
26
27
  buildSegmentInfo,
27
28
  createDebugChannelSink,
28
29
  isAbortError,
29
- parseCookiesFromHeader,
30
30
  } from './helpers.js';
31
- import { renderErrorPage } from './error-renderer.js';
31
+ import { getCookiesForSsr } from '../request-context.js';
32
+ import { getDenyStatus } from '../deny-page-resolver.js';
33
+ import { renderErrorPage, type GlobalErrorFile } from './error-renderer.js';
32
34
  import { callSsr } from './ssr-bridge.js';
33
35
  import type { RenderSignals } from './rsc-stream.js';
36
+ import { recordTiming } from '../server-timing.js';
37
+ import { teeWithErrorPropagation } from '../stream-utils.js';
38
+
39
+ /**
40
+ * Maximum number of queueMicrotask yields during signal promotion.
41
+ * The known rejection chain depth for a withSpan-wrapped component is 3+
42
+ * microtasks. We use 5 to tolerate additional async wrappers or React
43
+ * Flight internals adding extra microtask hops. Do not increase beyond 8 —
44
+ * a deeper chain indicates a structural problem.
45
+ */
46
+ const SIGNAL_PROMOTION_MAX_YIELDS = 5;
47
+
48
+ /**
49
+ * Test-only observable: records how many microtask yields were consumed
50
+ * during the last signal promotion check. Import this in tests to assert
51
+ * the actual rejection chain depth and detect regressions if wrappers
52
+ * add more async hops.
53
+ *
54
+ * Only populated when the object is imported and exists — production
55
+ * bundles that don't import it pay zero cost (the typeof check is free).
56
+ */
57
+ export const __test_only_signalPromotionDepth: { value: number } = { value: 0 };
34
58
 
35
59
  interface SsrRenderOptions {
36
60
  req: Request;
@@ -44,6 +68,8 @@ interface SsrRenderOptions {
44
68
  clientJsDisabled: boolean;
45
69
  headHtml: string;
46
70
  deferSuspenseFor: number;
71
+ /** Tier 2 global-error.tsx file, if present in app/. */
72
+ globalError?: GlobalErrorFile;
47
73
  }
48
74
 
49
75
  /**
@@ -77,11 +103,26 @@ export async function renderSsrResponse(opts: SsrRenderOptions): Promise<Respons
77
103
  clientJsDisabled,
78
104
  headHtml,
79
105
  deferSuspenseFor,
106
+ globalError,
80
107
  } = opts;
81
108
 
82
109
  // Tee the RSC stream — one copy goes to SSR for HTML rendering,
83
110
  // the other is inlined in the HTML for client-side hydration.
84
- const [ssrStream, inlineStream] = rscStream.tee();
111
+ // Uses teeWithErrorPropagation to ensure errors on either branch
112
+ // cancel the other (preventing hung responses) and to monitor
113
+ // buffer divergence between SSR and inline consumers.
114
+ //
115
+ // When client JS is disabled, skip the tee — the inline stream would
116
+ // never be consumed, causing monotonic buffer divergence that eventually
117
+ // triggers the 5MB guard and cancels the SSR stream.
118
+ let ssrStream: ReadableStream<Uint8Array>;
119
+ let inlineStream: ReadableStream<Uint8Array> | undefined;
120
+ if (clientJsDisabled) {
121
+ ssrStream = rscStream;
122
+ inlineStream = undefined;
123
+ } else {
124
+ [ssrStream, inlineStream] = teeWithErrorPropagation(rscStream);
125
+ }
85
126
 
86
127
  // Embed segment metadata in HTML for initial hydration.
87
128
  // The client reads this to populate its segment cache before the
@@ -91,26 +132,33 @@ export async function renderSsrResponse(opts: SsrRenderOptions): Promise<Respons
91
132
  ? ''
92
133
  : `<script>self.__timber_segments=${JSON.stringify(buildSegmentInfo(segments, layoutComponents))}</script>`;
93
134
 
94
- // Embed route params in HTML so useParams() works on initial hydration.
95
- // Without this, useParams() returns {} until the first client navigation.
135
+ // Embed route params in HTML so useSegmentParams() works on initial hydration.
136
+ // Without this, useSegmentParams() returns {} until the first client navigation.
96
137
  const paramsScript =
97
- clientJsDisabled || Object.keys(match.params).length === 0
138
+ clientJsDisabled || Object.keys(match.segmentParams).length === 0
98
139
  ? ''
99
- : `<script>self.__timber_params=${JSON.stringify(match.params)}</script>`;
140
+ : `<script>self.__timber_params=${JSON.stringify(match.segmentParams)}</script>`;
100
141
 
101
142
  const navContext: NavContext = {
102
143
  pathname: new URL(req.url).pathname,
103
- params: match.params,
144
+ params: match.segmentParams,
104
145
  searchParams: Object.fromEntries(new URL(req.url).searchParams),
105
146
  statusCode: 200,
106
147
  responseHeaders,
107
- headHtml: headHtml + clientBootstrap.preloadLinks + segmentScript + paramsScript,
148
+ headHtml:
149
+ headHtml +
150
+ clientBootstrap.preloadLinks +
151
+ segmentScript +
152
+ paramsScript +
153
+ // Initialize __timber_f in <head> so it exists before any streaming
154
+ // chunk scripts arrive in <body>. See flight-scripts.ts, LOCAL-415.
155
+ (clientJsDisabled ? '' : flightInitScript()),
108
156
  bootstrapScriptContent: clientBootstrap.bootstrapScriptContent,
109
157
  // Skip RSC inline stream when client JS is disabled — no client to hydrate.
110
158
  rscStream: clientJsDisabled ? undefined : inlineStream,
111
159
  deferSuspenseFor: deferSuspenseFor > 0 ? deferSuspenseFor : undefined,
112
160
  signal: req.signal,
113
- cookies: parseCookiesFromHeader(req.headers.get('cookie') ?? ''),
161
+ cookies: getCookiesForSsr(),
114
162
  };
115
163
 
116
164
  // Helper: check if render-phase signals were captured and return the
@@ -118,14 +166,19 @@ export async function renderSsrResponse(opts: SsrRenderOptions): Promise<Respons
118
166
  // promotion from Suspense) and failed SSR (signal outside Suspense).
119
167
  //
120
168
  // When `skipHandledDeny` is true (SSR success path), skip DenySignal
121
- // promotion if the denial was already handled by a TimberErrorBoundary
122
- // (e.g., slot error boundary). The boundary sets navContext._denyHandledByBoundary
123
- // during SSR rendering. See LOCAL-298.
169
+ // re-render if the denial was already handled by a TimberErrorBoundary.
170
+ // The boundary renders the deny page as its fallback AND sets the correct
171
+ // HTTP status code on navContext — no redundant renderDenyPage() needed.
172
+ // See TIM-664, LOCAL-298.
124
173
  function checkCapturedSignals(skipHandledDeny = false): Response | Promise<Response> | null {
125
174
  if (signals.redirectSignal) {
126
175
  return buildRedirectResponse(req, signals.redirectSignal, responseHeaders);
127
176
  }
128
177
  if (signals.denySignal && !(skipHandledDeny && navContext._denyHandledByBoundary)) {
178
+ // Deny was not handled by an in-tree error boundary.
179
+ // Fall back to renderDenyPage (separate React.cache scope).
180
+ // For single-render behavior, add a 'use client' status-code file
181
+ // (e.g., 4xx.tsx) — the error boundary handles it in-tree.
129
182
  return renderDenyPage(
130
183
  signals.denySignal,
131
184
  segments,
@@ -147,7 +200,8 @@ export async function renderSsrResponse(opts: SsrRenderOptions): Promise<Respons
147
200
  req,
148
201
  match,
149
202
  responseHeaders,
150
- clientBootstrap
203
+ clientBootstrap,
204
+ globalError
151
205
  );
152
206
  }
153
207
  return null;
@@ -156,18 +210,51 @@ export async function renderSsrResponse(opts: SsrRenderOptions): Promise<Respons
156
210
  try {
157
211
  const ssrResponse = await callSsr(ssrStream, navContext);
158
212
 
213
+ // Record SSR sub-phase timings for Server-Timing header (detailed mode).
214
+ // These are populated by handleSsr() in the SSR environment and passed
215
+ // back via navContext._ssrTimings across the RSC→SSR boundary.
216
+ if (navContext._ssrTimings) {
217
+ const t = navContext._ssrTimings;
218
+ recordTiming({ name: 'ssr-decode', dur: t.decodeMs, desc: 'RSC Flight decode' });
219
+ recordTiming({ name: 'ssr-shell', dur: t.shellMs, desc: 'Fizz onShellReady' });
220
+ recordTiming({ name: 'ssr-pipeline', dur: t.pipelineMs, desc: 'stream transforms' });
221
+ recordTiming({
222
+ name: 'ssr-total',
223
+ dur: t.totalMs,
224
+ desc: t.nodeStreams ? 'SSR (Node streams)' : 'SSR (Web Streams)',
225
+ });
226
+ }
227
+
159
228
  // Signal promotion: check if any signals were captured during rendering
160
- // inside Suspense boundaries. If no signals are present yet, yield one
161
- // microtask so async component rejections propagate to the RSC onError
162
- // callback before we commit the response.
229
+ // inside Suspense boundaries. If no signals are present yet, yield
230
+ // multiple microtasks so async component rejections propagate through
231
+ // the full rejection chain to the RSC onError callback before we
232
+ // commit the response.
233
+ //
234
+ // The known rejection chain depth for a withSpan-wrapped page:
235
+ // 1. PageComponent throws DenySignal/RedirectSignal
236
+ // 2. withSpan catches and re-throws (microtask 1)
237
+ // 3. TracedPage promise rejects (microtask 2)
238
+ // 4. React Flight rejection handler → onError (microtask 3+)
239
+ //
240
+ // A single queueMicrotask only advances the queue by one step, which
241
+ // is insufficient for chains deeper than 1. We retry up to
242
+ // SIGNAL_PROMOTION_MAX_YIELDS (5) times, exiting early as soon as a
243
+ // signal is detected. This tolerates future wrappers adding depth
244
+ // without requiring code changes.
163
245
  //
164
246
  // When signals are already captured (onSignal already fired), skip the
165
247
  // yield entirely — react immediately. Uses queueMicrotask instead of
166
- // setTimeout(0) for the fallback to avoid yielding to the full event
167
- // loop (timers phase).
248
+ // setTimeout(0) to avoid yielding to the full event loop (timers phase).
168
249
  // See design/05-streaming.md §"deferSuspenseFor and the Hold Window"
169
250
  if (!signals.redirectSignal && !signals.denySignal && !signals.renderError) {
170
- await new Promise<void>((r) => queueMicrotask(r));
251
+ let yieldsConsumed = 0;
252
+ for (let i = 0; i < SIGNAL_PROMOTION_MAX_YIELDS; i++) {
253
+ await new Promise<void>((r) => queueMicrotask(r));
254
+ yieldsConsumed++;
255
+ if (signals.redirectSignal || signals.denySignal || signals.renderError) break;
256
+ }
257
+ __test_only_signalPromotionDepth.value = yieldsConsumed;
171
258
  }
172
259
 
173
260
  const promoted = checkCapturedSignals(/* skipHandledDeny */ true);
@@ -175,6 +262,19 @@ export async function renderSsrResponse(opts: SsrRenderOptions): Promise<Respons
175
262
  ssrResponse.body?.cancel();
176
263
  return promoted;
177
264
  }
265
+
266
+ // Check if a DenySignal was caught in-tree by AccessGate or
267
+ // PageDenyBoundary. The deny page was rendered as a normal element
268
+ // (no error in the Flight stream), so SSR succeeded with status 200.
269
+ // Override the status code from the ALS-stored deny status. See TIM-666.
270
+ const denyStatus = getDenyStatus();
271
+ if (denyStatus) {
272
+ return new Response(ssrResponse.body, {
273
+ status: denyStatus,
274
+ headers: ssrResponse.headers,
275
+ });
276
+ }
277
+
178
278
  return ssrResponse;
179
279
  } catch (ssrError) {
180
280
  // Connection abort — the client disconnected (page refresh, navigation
@@ -185,19 +285,34 @@ export async function renderSsrResponse(opts: SsrRenderOptions): Promise<Respons
185
285
 
186
286
  // SsrStreamError: SSR's renderToReadableStream failed because the RSC
187
287
  // stream contained an uncontained error (e.g., slot without error boundary).
188
- // Render the deny/error page WITHOUT layout wrapping to avoid re-executing
189
- // server components (which call headers()/cookies() and fail in SSR's
190
- // separate ALS scope). See LOCAL-293.
191
- if (ssrError instanceof SsrStreamError) {
288
+ //
289
+ // Error pages now use SSR-only rendering (Fizz directly, no RSC Flight),
290
+ // which imports layouts in the SSR environment where ALS is active. This
291
+ // means we CAN include layouts — they'll call getHeaders()/getCookies() correctly.
292
+ //
293
+ // Deny pages still go through RSC → SSR (plain props), so they pass empty
294
+ // layouts to avoid re-executing server components in the RSC environment's
295
+ // stale ALS scope. See LOCAL-293.
296
+ // Name-based check: SsrStreamError is thrown in the SSR environment
297
+ // but caught in the RSC environment. Since RSC and SSR are separate
298
+ // Vite module graphs, `instanceof` fails (different class identities).
299
+ // Use error.name instead. See design/18-build-system.md §"Virtual Module
300
+ // Resolution Quirks".
301
+ const isSsrStreamError =
302
+ ssrError instanceof SsrStreamError ||
303
+ (ssrError instanceof Error && ssrError.name === 'SsrStreamError');
304
+ if (isSsrStreamError) {
192
305
  if (signals.redirectSignal) {
193
306
  return buildRedirectResponse(req, signals.redirectSignal, responseHeaders);
194
307
  }
195
308
  if (signals.denySignal) {
196
- // Render deny page without layouts pass empty layout list
309
+ // SSR failed (SsrStreamError) the deny was in the shell and
310
+ // the error boundary didn't catch it during Fizz rendering.
311
+ // Fall back to renderDenyPage (separate render). See TIM-664.
197
312
  return renderDenyPage(
198
313
  signals.denySignal,
199
314
  segments,
200
- [] as LayoutEntry[],
315
+ layoutComponents as LayoutEntry[],
201
316
  req,
202
317
  match,
203
318
  responseHeaders,
@@ -207,19 +322,37 @@ export async function renderSsrResponse(opts: SsrRenderOptions): Promise<Respons
207
322
  );
208
323
  }
209
324
  if (signals.renderError) {
325
+ // RenderError: TSX error pages use SSR-only path (layouts OK),
326
+ // MDX error pages use RSC path (plain props, no Error object).
210
327
  return renderErrorPage(
211
328
  signals.renderError.error,
212
329
  signals.renderError.status,
213
330
  segments,
214
- [] as LayoutEntry[],
331
+ layoutComponents as LayoutEntry[],
215
332
  req,
216
333
  match,
217
334
  responseHeaders,
218
- clientBootstrap
335
+ clientBootstrap,
336
+ globalError
219
337
  );
220
338
  }
221
- // No captured signal — return bare 500
222
- return new Response(null, { status: 500, headers: responseHeaders });
339
+ // No captured signal — unhandled error in the RSC stream.
340
+ // Use the lastUnhandledError from RSC onError if available (more
341
+ // reliable than extracting SsrStreamError.cause). Falls back to
342
+ // cause extraction for backward compatibility.
343
+ const originalError =
344
+ signals.lastUnhandledError ?? (ssrError as { cause?: unknown }).cause ?? ssrError;
345
+ return renderErrorPage(
346
+ originalError,
347
+ 500,
348
+ segments,
349
+ layoutComponents as LayoutEntry[],
350
+ req,
351
+ match,
352
+ responseHeaders,
353
+ clientBootstrap,
354
+ globalError
355
+ );
223
356
  }
224
357
 
225
358
  // SSR shell rendering failed — the error was outside Suspense.