@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
@@ -5,6 +5,17 @@
5
5
  * independently of the Vite RSC plugin runtime (which provides
6
6
  * createFromReadableStream for decoding RSC streams).
7
7
  *
8
+ * Uses a platform-adaptive rendering strategy:
9
+ * - **Node.js / Bun**: `renderToPipeableStream` — React pipes HTML chunks
10
+ * through Node.js native streams (C++ implementation). Each chunk flows
11
+ * through libuv buffers with zero Promise overhead.
12
+ * - **Cloudflare Workers / Edge**: `renderToReadableStream` — React outputs
13
+ * to Web Streams which are V8-native C++ built-ins on these platforms.
14
+ *
15
+ * The detection is automatic at runtime. Both paths produce a Web
16
+ * `ReadableStream<Uint8Array>` so downstream transforms (injectHead,
17
+ * injectRscPayload, compression) work identically regardless of platform.
18
+ *
8
19
  * Design docs: 02-rendering-pipeline.md §"Single-Pass Rendering",
9
20
  * 18-build-system.md §"Entry Files"
10
21
  */
@@ -12,7 +23,25 @@
12
23
  import type { ReactNode } from 'react';
13
24
  import { renderToReadableStream } from 'react-dom/server';
14
25
 
15
- import { formatSsrError } from './error-formatter.js';
26
+ import { createRenderTimeout, RenderTimeoutError } from './render-timeout.js';
27
+ import { logRenderError, logStreamingError } from './logger.js';
28
+
29
+ /**
30
+ * React's production error sanitization message. When NODE_ENV=production,
31
+ * React replaces all error messages with this string in renderToReadableStream
32
+ * and renderToPipeableStream. The original error was already logged by the
33
+ * RSC onError handler — logging the sanitized version in SSR is duplicate noise.
34
+ */
35
+ const REACT_PROD_ERROR_PREFIX = 'An error occurred in the Server Components render';
36
+
37
+ /**
38
+ * Returns true if the error is React's sanitized production error.
39
+ * These are duplicates of errors already logged by the RSC onError handler
40
+ * with the full original message — logging them again in SSR adds noise.
41
+ */
42
+ function isReactSanitizedError(error: unknown): boolean {
43
+ return error instanceof Error && error.message.startsWith(REACT_PROD_ERROR_PREFIX);
44
+ }
16
45
 
17
46
  /**
18
47
  * Inline script that injects <meta name="robots" content="noindex"> into <head>.
@@ -28,60 +57,277 @@ import { formatSsrError } from './error-formatter.js';
28
57
  const NOINDEX_SCRIPT =
29
58
  '<script>document.head.appendChild(Object.assign(document.createElement("meta"),{name:"robots",content:"noindex"}))</script>';
30
59
 
60
+ // ─── Platform Detection ──────────────────────────────────────────────────────
61
+ //
62
+ // Detect whether we're running on a platform with native Node.js streams.
63
+ // On Node.js/Bun, `node:stream` is backed by C++ (libuv). On Cloudflare
64
+ // Workers, `node:stream` via nodejs_compat is a JS polyfill — Web Streams
65
+ // are the faster path there (V8-native C++ built-ins).
66
+ //
67
+ // We detect once at module load to avoid per-request overhead.
68
+ // The check: process.versions.node exists AND we can import node:stream.
69
+ // Cloudflare Workers with nodejs_compat may polyfill process.versions but
70
+ // the streams won't be native. The Readable.toWeb check confirms native support.
71
+
72
+ let _useNodeStreams = false;
73
+ let _PassThrough: typeof import('node:stream').PassThrough | null = null;
74
+ let _ReadableToWeb: ((readable: import('node:stream').Readable) => ReadableStream) | null = null;
75
+ let _renderToPipeableStream: typeof import('react-dom/server').renderToPipeableStream | null = null;
76
+
77
+ try {
78
+ // Dynamic imports to avoid bundling node:stream and the Node.js-specific
79
+ // react-dom/server entry for CF Workers builds.
80
+ // On Node.js/Bun this resolves to native C++ streams.
81
+ // On CF Workers this either fails or returns a JS polyfill.
82
+ const nodeStream = await import('node:stream');
83
+ if (
84
+ typeof nodeStream.PassThrough === 'function' &&
85
+ typeof nodeStream.Readable.toWeb === 'function' &&
86
+ // Real Node.js — not a polyfill. Polyfills typically don't set
87
+ // process.release.name to 'node'.
88
+ typeof process !== 'undefined' &&
89
+ process.release?.name === 'node'
90
+ ) {
91
+ // Dynamically import renderToPipeableStream from the Node.js-specific
92
+ // entry point. The SSR bundle resolves react-dom/server to the edge/browser
93
+ // export (which lacks renderToPipeableStream), so we import the .node file
94
+ // directly. This is safe because we're inside a process.release.name === 'node'
95
+ // guard — this code only runs on real Node.js.
96
+ const reactDomServer = await import('react-dom/server.node');
97
+ if (typeof reactDomServer.renderToPipeableStream === 'function') {
98
+ _useNodeStreams = true;
99
+ _PassThrough = nodeStream.PassThrough;
100
+ _ReadableToWeb = nodeStream.Readable.toWeb as (
101
+ readable: import('node:stream').Readable
102
+ ) => ReadableStream;
103
+ _renderToPipeableStream = reactDomServer.renderToPipeableStream;
104
+ }
105
+ }
106
+ } catch {
107
+ // node:stream or renderToPipeableStream not available — use Web Streams path
108
+ }
109
+
31
110
  /**
32
111
  * Render a React element tree to a ReadableStream of HTML.
33
112
  *
34
- * Uses renderToReadableStream (NOT renderToString) for streaming SSR.
113
+ * Automatically selects the optimal rendering path for the platform:
114
+ * - Node.js/Bun: `renderToPipeableStream` → Node.js native streams → `Readable.toWeb()`
115
+ * - CF Workers/Edge: `renderToReadableStream` → native Web Streams
116
+ *
35
117
  * The returned stream begins yielding after onShellReady — everything
36
118
  * outside <Suspense> boundaries is in the shell.
37
119
  *
38
- * With progressive streaming, the RSC stream is piped directly to SSR
39
- * without buffering. If deny() was called outside a Suspense boundary,
40
- * the RSC stream encodes an error in the shell — renderToReadableStream
41
- * rejects, and the RSC entry catches this to render a deny page with
42
- * the correct HTTP status code. If deny() was inside Suspense, the shell
43
- * succeeds (200 committed) and the error streams as an error boundary.
44
- *
45
120
  * @param element - The React element tree decoded from the RSC stream
46
121
  * @param options - Optional configuration
47
- * @param options.bootstrapScriptContent - Inline JS injected by React as a
48
- * non-deferred `<script>` in the shell HTML. Executes immediately during
49
- * parsing — even while Suspense boundaries are still streaming. Used to
50
- * kick off module loading via dynamic `import()` so hydration can start
51
- * before the HTML stream closes.
52
122
  * @returns A ReadableStream of HTML bytes with hydration markers
53
123
  */
54
124
  export async function renderSsrStream(
55
125
  element: ReactNode,
56
- options?: { bootstrapScriptContent?: string; deferSuspenseFor?: number; signal?: AbortSignal }
126
+ options?: {
127
+ bootstrapScriptContent?: string;
128
+ deferSuspenseFor?: number;
129
+ signal?: AbortSignal;
130
+ renderTimeoutMs?: number;
131
+ }
57
132
  ): Promise<ReadableStream<Uint8Array>> {
133
+ return renderViaReadableStream(element, options);
134
+ }
135
+
136
+ /** Whether the current platform uses native Node.js streams for SSR. */
137
+ export const useNodeStreams = _useNodeStreams;
138
+
139
+ // ─── Node.js Path: renderToPipeableStream ────────────────────────────────────
140
+ //
141
+ // Uses React's Node.js-native API. HTML chunks flow through C++ stream
142
+ // buffers with zero Promise allocations per chunk. Returns a Node.js
143
+ // Readable — the caller (ssr-entry.ts) pipes through Node.js Transform
144
+ // streams for injectHead/injectRscPayload before converting to Web
145
+ // ReadableStream at the Response boundary.
146
+
147
+ /**
148
+ * Render via renderToPipeableStream, returning a Node.js Readable.
149
+ *
150
+ * The entire HTML rendering + post-processing pipeline stays in native
151
+ * Node.js streams (C++ backed). Only converted to Web ReadableStream
152
+ * at the very end for the Response body.
153
+ */
154
+ export async function renderSsrNodeStream(
155
+ element: ReactNode,
156
+ options?: {
157
+ bootstrapScriptContent?: string;
158
+ deferSuspenseFor?: number;
159
+ signal?: AbortSignal;
160
+ renderTimeoutMs?: number;
161
+ }
162
+ ): Promise<import('node:stream').Readable> {
58
163
  const signal = options?.signal;
59
- const stream = await renderToReadableStream(element, {
60
- bootstrapScriptContent: options?.bootstrapScriptContent || undefined,
61
- signal,
62
- onError(error: unknown) {
63
- // Suppress logging for connection aborts — the user refreshed or
64
- // navigated away, not an application error.
65
- if (isAbortError(error) || signal?.aborted) return;
66
- console.error('[timber] SSR render error:', formatSsrError(error));
67
- },
164
+ const deferMs = options?.deferSuspenseFor;
165
+ const timeoutMs = options?.renderTimeoutMs;
166
+
167
+ return new Promise<import('node:stream').Readable>((resolve, reject) => {
168
+ const passthrough = new _PassThrough!();
169
+
170
+ let allReadyResolve: (() => void) | null = null;
171
+ let allReadyReject: ((reason?: unknown) => void) | null = null;
172
+ const allReady = new Promise<void>((resolve, reject) => {
173
+ allReadyResolve = resolve;
174
+ allReadyReject = reject;
175
+ });
176
+ allReady.catch(() => {});
177
+
178
+ const { pipe, abort } = _renderToPipeableStream!(element, {
179
+ bootstrapScriptContent: options?.bootstrapScriptContent || undefined,
180
+
181
+ onShellReady() {
182
+ if (deferMs && deferMs > 0) {
183
+ Promise.race([allReady, new Promise<void>((r) => setTimeout(r, deferMs))]).then(() => {
184
+ pipe(passthrough);
185
+ resolve(passthrough);
186
+ });
187
+ } else {
188
+ pipe(passthrough);
189
+ resolve(passthrough);
190
+ }
191
+ },
192
+
193
+ onAllReady() {
194
+ allReadyResolve?.();
195
+ },
196
+
197
+ onShellError(error: unknown) {
198
+ // Reject allReady so the render timeout is cancelled.
199
+ // Without this, a pre-shell failure leaves the timer
200
+ // running for the full timeout window.
201
+ allReadyReject?.(error);
202
+ reject(error);
203
+ },
204
+
205
+ onError(error: unknown) {
206
+ if (isAbortError(error) || signal?.aborted) return;
207
+ // Skip React's sanitized production errors — the original was
208
+ // already logged by the RSC onError with full details.
209
+ if (isReactSanitizedError(error)) return;
210
+ logRenderError({ method: '', path: '', error });
211
+ },
212
+ });
213
+
214
+ // Wire abort to both request signal AND render timeout.
215
+ // If the client stays connected but a downstream fetch hangs,
216
+ // the timeout ensures abort() is eventually called.
217
+ if (signal) {
218
+ if (signal.aborted) {
219
+ abort();
220
+ } else {
221
+ signal.addEventListener('abort', () => abort(), { once: true });
222
+ }
223
+ }
224
+
225
+ if (timeoutMs && timeoutMs > 0) {
226
+ const renderTimeout = createRenderTimeout(timeoutMs, signal);
227
+ renderTimeout.signal.addEventListener(
228
+ 'abort',
229
+ () => {
230
+ logRenderError({
231
+ method: '',
232
+ path: '',
233
+ error: new Error(
234
+ `SSR render timed out after ${timeoutMs}ms — aborting. ` +
235
+ 'A Suspense component or downstream fetch may be hanging.'
236
+ ),
237
+ });
238
+ abort(renderTimeout.signal.reason);
239
+ },
240
+ { once: true }
241
+ );
242
+ // Cancel the timeout when the render completes OR on pre-shell
243
+ // failure. Without the catch branch, onShellError → reject()
244
+ // would leave the timer running for the full timeout window.
245
+ allReady.then(
246
+ () => renderTimeout.cancel(),
247
+ () => renderTimeout.cancel()
248
+ );
249
+ }
68
250
  });
251
+ }
252
+
253
+ /** Convert a Node.js Readable to a Web ReadableStream (zero-copy bridge). */
254
+ export function nodeReadableToWeb(
255
+ readable: import('node:stream').Readable
256
+ ): ReadableStream<Uint8Array> {
257
+ return _ReadableToWeb!(readable) as ReadableStream<Uint8Array>;
258
+ }
259
+
260
+ // ─── Web Streams Path: renderToReadableStream ────────────────────────────────
261
+ //
262
+ // Uses React's Web Streams API. On Cloudflare Workers, ReadableStream is a
263
+ // V8-native C++ built-in, making this the fastest path for that platform.
264
+ // On Node.js, Web Streams are a JS reimplementation — slower, but this path
265
+ // is only used as a fallback when Node.js native streams aren't available.
266
+
267
+ async function renderViaReadableStream(
268
+ element: ReactNode,
269
+ options?: {
270
+ bootstrapScriptContent?: string;
271
+ deferSuspenseFor?: number;
272
+ signal?: AbortSignal;
273
+ renderTimeoutMs?: number;
274
+ }
275
+ ): Promise<ReadableStream<Uint8Array>> {
276
+ const signal = options?.signal;
277
+ const timeoutMs = options?.renderTimeoutMs;
278
+
279
+ // If a render timeout is configured, create a combined signal that
280
+ // fires on either request abort OR timeout — whichever comes first.
281
+ let renderTimeout: import('./render-timeout.js').RenderTimeout | null = null;
282
+ let effectiveSignal = signal;
283
+ if (timeoutMs && timeoutMs > 0) {
284
+ renderTimeout = createRenderTimeout(timeoutMs, signal);
285
+ effectiveSignal = renderTimeout.signal;
286
+ }
287
+
288
+ let stream: Awaited<ReturnType<typeof renderToReadableStream>>;
289
+ try {
290
+ stream = await renderToReadableStream(element, {
291
+ bootstrapScriptContent: options?.bootstrapScriptContent || undefined,
292
+ signal: effectiveSignal,
293
+ onError(error: unknown) {
294
+ if (isAbortError(error) || effectiveSignal?.aborted) return;
295
+ if (error instanceof RenderTimeoutError) {
296
+ logRenderError({
297
+ method: '',
298
+ path: '',
299
+ error: new Error(
300
+ `SSR render timed out after ${timeoutMs}ms — aborting. ` +
301
+ 'A Suspense component or downstream fetch may be hanging.'
302
+ ),
303
+ });
304
+ return;
305
+ }
306
+ // Skip React's sanitized production errors — the original was
307
+ // already logged by the RSC onError with full details.
308
+ if (isReactSanitizedError(error)) return;
309
+ logRenderError({ method: '', path: '', error });
310
+ },
311
+ });
312
+ } catch (error) {
313
+ // Pre-shell failure (e.g. RSC stream error). Cancel the render
314
+ // timeout so it doesn't leak a timer + abort callback for the
315
+ // full timeout window. Under repeated pre-shell failures this
316
+ // would accumulate unnecessary timers.
317
+ renderTimeout?.cancel();
318
+ throw error;
319
+ }
69
320
 
70
321
  // Prevent unhandled promise rejection from streaming-phase errors.
71
- // React DOM Server exposes `allReady` — a promise that resolves when
72
- // ALL content (including Suspense boundaries) has been rendered. If a
73
- // streaming-phase error occurs (e.g. React boundary flush failure),
74
- // `allReady` rejects independently of the stream. Without this catch,
75
- // the rejection becomes an unhandled promise rejection that crashes
76
- // the Node.js process.
77
322
  stream.allReady.catch(() => {});
78
323
 
324
+ // Cancel the render timeout once allReady resolves (render completed).
325
+ if (renderTimeout) {
326
+ stream.allReady.then(() => renderTimeout!.cancel()).catch(() => renderTimeout!.cancel());
327
+ }
328
+
79
329
  // deferSuspenseFor hold: delay the first read so React can resolve
80
330
  // fast-completing Suspense boundaries before we read the shell HTML.
81
- // renderToReadableStream generates HTML lazily on pull — if we wait
82
- // before reading, React resolves pending boundaries and inlines their
83
- // content instead of serializing fallbacks. Race allReady against
84
- // deferSuspenseFor so we don't wait longer than necessary.
85
331
  // See design/05-streaming.md §"deferSuspenseFor"
86
332
  const deferMs = options?.deferSuspenseFor;
87
333
  if (deferMs && deferMs > 0) {
@@ -91,30 +337,19 @@ export async function renderSsrStream(
91
337
  ]);
92
338
  }
93
339
 
94
- // renderToReadableStream resolves after onShellReady by default.
95
- // The stream is ready to read — the shell (everything outside
96
- // Suspense boundaries) is available. Suspense content streams
97
- // into the open connection as it resolves.
98
- //
99
- // Wrap the stream in an error-resilient transform. With progressive
100
- // streaming, errors inside Suspense boundaries (e.g. deny() or throws
101
- // in async components) cause React's stream to error during the flush
102
- // phase. The onError callback logs the error, but the stream error
103
- // would become an unhandled promise rejection and crash the process.
104
- // The transform catches these post-shell streaming errors and closes
105
- // the stream cleanly — the shell (with correct status code) has
106
- // already been sent.
107
340
  return wrapStreamWithErrorHandling(stream, signal);
108
341
  }
109
342
 
343
+ // ─── Shared Utilities ────────────────────────────────────────────────────────
344
+
110
345
  /**
111
346
  * Wrap an HTML stream with error handling for the streaming phase.
112
347
  *
113
348
  * During progressive RSC→SSR streaming, errors in Suspense boundaries
114
349
  * (e.g. deny() inside Suspense, throws in async components) cause
115
- * React DOM's renderToReadableStream to error after the shell has been
116
- * flushed. Without this wrapper, the stream error becomes an unhandled
117
- * promise rejection that crashes the process.
350
+ * React DOM's stream to error after the shell has been flushed. Without
351
+ * this wrapper, the stream error becomes an unhandled promise rejection
352
+ * that crashes the process.
118
353
  *
119
354
  * The wrapper catches streaming-phase errors, logs them, and closes
120
355
  * the output stream cleanly. The shell (headers, status code, content
@@ -138,18 +373,11 @@ export function wrapStreamWithErrorHandling(
138
373
  }
139
374
  controller.enqueue(value);
140
375
  } catch (error) {
141
- // Connection abort (user refreshed or navigated away) — close
142
- // silently without logging. This is not an application error.
143
376
  if (isAbortError(error) || signal?.aborted) {
144
377
  controller.close();
145
378
  return;
146
379
  }
147
- // Streaming-phase error (e.g. React boundary flush failure,
148
- // deny() or throw inside Suspense after flush).
149
- // The shell has already been sent with status 200. Inject a
150
- // noindex meta tag so search engines don't index this error page,
151
- // then close cleanly. See design/05-streaming.md.
152
- console.error('[timber] SSR streaming error (post-shell):', formatSsrError(error));
380
+ logStreamingError({ error });
153
381
  controller.enqueue(encoder.encode(NOINDEX_SCRIPT));
154
382
  controller.close();
155
383
  }
@@ -162,10 +390,6 @@ export function wrapStreamWithErrorHandling(
162
390
 
163
391
  /**
164
392
  * Check if an error is an abort error (connection closed by client).
165
- *
166
- * When the browser aborts a request (page refresh, navigation away),
167
- * the AbortSignal fires and React/streams throw an AbortError. This
168
- * is not an application error — suppress it from error boundaries and logs.
169
393
  */
170
394
  function isAbortError(error: unknown): boolean {
171
395
  if (error instanceof DOMException && error.name === 'AbortError') return true;
@@ -177,12 +401,10 @@ function isAbortError(error: unknown): boolean {
177
401
  * Build a Response from the SSR HTML stream with the correct
178
402
  * status code and headers from the navigation context.
179
403
  *
180
- * Sets content-type to text/html if not already set by middleware.
404
+ * React 19.3+ automatically emits `<!DOCTYPE html>` when the root
405
+ * element is `<html>`, so no framework-level doctype prepending is needed.
181
406
  *
182
- * @param htmlStream - The HTML stream from renderSsrStream
183
- * @param statusCode - The committed HTTP status code from RSC
184
- * @param responseHeaders - Response headers from middleware/proxy
185
- * @returns A Response ready to send to the client
407
+ * Sets content-type to text/html if not already set by middleware.
186
408
  */
187
409
  export function buildSsrResponse(
188
410
  htmlStream: ReadableStream<Uint8Array>,
@@ -0,0 +1,139 @@
1
+ /**
2
+ * SSR wrapper components that match the client-side component tree depth.
3
+ *
4
+ * During hydration, React's useId() generates deterministic IDs based on
5
+ * the component's position in the fiber tree. If the SSR tree has fewer
6
+ * wrapper components than the client hydration tree, every useId() call
7
+ * produces different IDs — causing hydration mismatches in libraries like
8
+ * Radix UI that rely on useId() internally.
9
+ *
10
+ * The client tree (browser-entry.ts) wraps the RSC element with:
11
+ * NavigationRoot → PendingNavigationProvider → Fragment(TopLoader, ...) →
12
+ * TimberNuqsAdapter → NuqsAdapterProvider → NavigationProvider → element
13
+ *
14
+ * The SSR tree must produce the same component boundaries. These wrappers
15
+ * are no-op components that render children directly but exist as fiber
16
+ * nodes to match the client's tree depth.
17
+ *
18
+ * Related issues: facebook/react#24669, radix-ui/primitives#3700
19
+ * See design/02-rendering-pipeline.md §"RSC → SSR → Client Hydration"
20
+ */
21
+
22
+ import { createElement, Fragment, type ReactNode } from 'react';
23
+ import { withNuqsSsrAdapter } from './nuqs-ssr-provider.js';
24
+
25
+ /**
26
+ * SSR equivalent of NavigationRoot.
27
+ *
28
+ * On the client, NavigationRoot uses useState and standalone startTransition, rendering:
29
+ * PendingNavigationProvider(Fragment(TopLoader, element))
30
+ *
31
+ * This SSR version matches the component boundary depth without client
32
+ * hooks. It renders SsrPendingProvider → Fragment(SsrTopLoader, children).
33
+ */
34
+ function SsrNavigationRoot({
35
+ children,
36
+ hasTopLoader,
37
+ }: {
38
+ children: ReactNode;
39
+ hasTopLoader: boolean;
40
+ }): ReactNode {
41
+ if (hasTopLoader) {
42
+ return createElement(
43
+ SsrPendingProvider,
44
+ null,
45
+ createElement(Fragment, null, createElement(SsrTopLoader, null), children)
46
+ );
47
+ }
48
+ return createElement(SsrPendingProvider, null, children);
49
+ }
50
+
51
+ /**
52
+ * SSR equivalent of PendingNavigationProvider.
53
+ * Matches the context.Provider component boundary on the client.
54
+ */
55
+ function SsrPendingProvider({ children }: { children: ReactNode }): ReactNode {
56
+ return children as ReactNode;
57
+ }
58
+
59
+ /**
60
+ * SSR equivalent of TopLoader.
61
+ * Exists as a fiber node to match the client tree depth; renders nothing.
62
+ */
63
+ function SsrTopLoader(): ReactNode {
64
+ return null;
65
+ }
66
+
67
+ /**
68
+ * SSR equivalent of NavigationProvider.
69
+ * Matches the context.Provider component boundary on the client.
70
+ */
71
+ function SsrNavigationProvider({ children }: { children: ReactNode }): ReactNode {
72
+ return children as ReactNode;
73
+ }
74
+
75
+ /**
76
+ * SSR equivalent of TimberNuqsAdapter component boundary.
77
+ * The actual NuqsAdapterProvider (from createAdapterProvider) is added
78
+ * inside this wrapper via withNuqsSsrAdapter, matching the client's
79
+ * TimberNuqsAdapter → NuqsAdapterProvider nesting.
80
+ */
81
+ function SsrNuqsWrapper({
82
+ searchParams,
83
+ children,
84
+ }: {
85
+ searchParams: Record<string, string>;
86
+ children: ReactNode;
87
+ }): ReactNode {
88
+ // withNuqsSsrAdapter creates a NuqsAdapterProvider (from createAdapterProvider),
89
+ // which is the same component factory used by TimberNuqsAdapter on the client.
90
+ // Both produce the same internal component boundary depth.
91
+ return withNuqsSsrAdapter(searchParams, children);
92
+ }
93
+
94
+ /**
95
+ * Wrap the SSR element tree with the same component boundaries as the
96
+ * client hydration tree. This ensures useId() generates matching IDs
97
+ * on both sides.
98
+ *
99
+ * Client tree (browser-entry.ts):
100
+ * NavigationRoot
101
+ * → PendingNavigationProvider
102
+ * → Fragment(TopLoader, element)
103
+ * → TimberNuqsAdapter
104
+ * → NuqsAdapterProvider (from createAdapterProvider)
105
+ * → NavigationProvider
106
+ * → [RSC element]
107
+ *
108
+ * SSR tree (this function):
109
+ * SsrNavigationRoot
110
+ * → SsrPendingProvider
111
+ * → Fragment(SsrTopLoader, element)
112
+ * → SsrNuqsWrapper
113
+ * → NuqsAdapterProvider (from withNuqsSsrAdapter → createAdapterProvider)
114
+ * → SsrNavigationProvider
115
+ * → [RSC element]
116
+ *
117
+ * @param element - The decoded RSC element
118
+ * @param searchParams - Request search params for nuqs SSR adapter
119
+ * @param hasTopLoader - Whether the top loader is enabled (must match client config)
120
+ */
121
+ export function wrapSsrElement(
122
+ element: ReactNode,
123
+ searchParams: Record<string, string>,
124
+ hasTopLoader: boolean
125
+ ): ReactNode {
126
+ // Build inside-out to match the client's createElement chain:
127
+ // NavigationProvider(TimberNuqsAdapter(element))
128
+ // → passed as initial to NavigationRoot
129
+ // → NavigationRoot renders PendingNavigationProvider(Fragment(TopLoader, initial))
130
+
131
+ // 1. Innermost: NavigationProvider equivalent
132
+ const withNav = createElement(SsrNavigationProvider, null, element);
133
+
134
+ // 2. TimberNuqsAdapter equivalent (wraps withNuqsSsrAdapter for the actual nuqs provider)
135
+ const withNuqs = createElement(SsrNuqsWrapper, { searchParams, children: withNav });
136
+
137
+ // 3. Outermost: NavigationRoot equivalent (PendingNavigationProvider + TopLoader)
138
+ return createElement(SsrNavigationRoot, { hasTopLoader, children: withNuqs });
139
+ }
@@ -27,7 +27,7 @@
27
27
  * Then framework default (returns null)
28
28
  */
29
29
 
30
- import type { SegmentNode, RouteFile } from '#/routing/types.js';
30
+ import type { SegmentNode, RouteFile } from '../routing/types.js';
31
31
 
32
32
  // ─── Types ───────────────────────────────────────────────────────────────────
33
33