@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
@@ -0,0 +1,193 @@
1
+ /**
2
+ * Router Initialization — creates the timber router with all dependencies.
3
+ *
4
+ * Wires up RouterDeps (fetch, history, scroll, RSC decoding, render
5
+ * callbacks) and optionally sets up Navigation API integration.
6
+ *
7
+ * See design/19-client-navigation.md §"Navigation API Integration"
8
+ */
9
+
10
+ import { createElement } from 'react';
11
+ import { createFromFetch } from '../../rsc-runtime/browser.js';
12
+ import { createRouter, setGlobalRouter } from '#client-internal';
13
+ import type { RouterDeps, RouterInstance } from '#client-internal';
14
+ import type { NavigationState } from '#client-internal';
15
+ import { applyHeadElements } from '../head.js';
16
+ import { TimberNuqsAdapter } from '../nuqs-adapter.js';
17
+ import { NavigationProvider } from '../navigation-context.js';
18
+ import { transitionRender, navigateTransition } from '../navigation-root.js';
19
+ import { isStaleClientReference, triggerStaleReload } from '../stale-reload.js';
20
+ import {
21
+ hasNavigationApi,
22
+ setupNavigationApi,
23
+ type NavigationApiController,
24
+ } from '../navigation-api.js';
25
+ import { getScrollY } from './scroll.js';
26
+
27
+ export interface RouterInitResult {
28
+ router: RouterInstance;
29
+ navApiController: NavigationApiController | null;
30
+ }
31
+
32
+ /**
33
+ * Create and register the global timber router.
34
+ *
35
+ * Must be called before hydrateRoot so `useRouter()` works during
36
+ * the initial render (methods lazily resolve the router at invocation,
37
+ * not render time, but initRouter must still run first).
38
+ */
39
+ export function createTimberRouter(): RouterInitResult {
40
+ // Feature-detect Navigation API. When available, the navigate event
41
+ // replaces popstate for back/forward and catches external navigations.
42
+ // See design/19-client-navigation.md §"Navigation API Integration"
43
+ const useNavApi = hasNavigationApi();
44
+
45
+ const deps: RouterDeps = {
46
+ fetch: (url, init) => window.fetch(url, init),
47
+ pushState: (data, unused, url) => window.history.pushState(data, unused, url),
48
+ replaceState: (data, unused, url) => window.history.replaceState(data, unused, url),
49
+ navigationApiActive: useNavApi,
50
+ scrollTo: (x, y) => {
51
+ // Scroll the document viewport.
52
+ window.scrollTo(x, y);
53
+ document.documentElement.scrollTop = y;
54
+ document.body.scrollTop = y;
55
+ // Scroll any element explicitly marked as a scroll container.
56
+ // With segment tree merging, shared layouts (sidebars, nav bars)
57
+ // are reconciled in place via cloneElement — React preserves their
58
+ // DOM and scroll state naturally. We no longer auto-detect overflow
59
+ // containers, which previously found the wrong element (e.g.,
60
+ // scrolling a sidebar instead of the main content area).
61
+ // Use `data-timber-scroll-restoration` to opt in specific containers.
62
+ for (const el of document.querySelectorAll('[data-timber-scroll-restoration]')) {
63
+ (el as HTMLElement).scrollTop = y;
64
+ }
65
+ },
66
+ getCurrentUrl: () => window.location.pathname + window.location.search,
67
+ getScrollY,
68
+
69
+ // Decode RSC Flight stream using createFromFetch.
70
+ // createFromFetch takes a Promise<Response> and progressively
71
+ // parses the RSC stream as chunks arrive.
72
+ //
73
+ // Wrapped with stale client reference detection: if the server
74
+ // has been redeployed with new bundles, the RSC payload may
75
+ // reference module IDs that don't exist in the old client bundle.
76
+ // We catch "Could not find the module" errors and trigger a full
77
+ // page reload so the browser fetches the new bundle.
78
+ decodeRsc: async (fetchPromise: Promise<Response>) => {
79
+ try {
80
+ // Wait for the full RSC stream to arrive before decoding.
81
+ // createFromFetch resolves on the first Flight chunk (the shell),
82
+ // but we need the transition to stay pending for the full response
83
+ // so useOptimistic (per-link pending) persists during slow navigations.
84
+ // Buffer the complete response, then decode from the buffered stream.
85
+ const response = await fetchPromise;
86
+ const body = await response.arrayBuffer();
87
+ const buffered = new Response(body, {
88
+ headers: response.headers,
89
+ status: response.status,
90
+ });
91
+ return await createFromFetch(Promise.resolve(buffered));
92
+ } catch (error) {
93
+ if (isStaleClientReference(error)) {
94
+ triggerStaleReload();
95
+ return new Promise(() => {});
96
+ }
97
+ throw error;
98
+ }
99
+ },
100
+
101
+ // Render decoded RSC tree via NavigationRoot's state-based mechanism.
102
+ // Used for non-navigation renders (popstate cached replay, applyRevalidation).
103
+ // Wraps with NavigationProvider + TimberNuqsAdapter.
104
+ //
105
+ // For navigation renders (navigate, refresh, popstate-with-fetch),
106
+ // navigateTransition is used instead — it wraps the entire navigation
107
+ // in a React transition with useOptimistic for the pending URL.
108
+ //
109
+ // navState is passed explicitly by the router — no temporal coupling
110
+ // with getNavigationState().
111
+ renderRoot: (element: unknown, navState: NavigationState) => {
112
+ const withNav = createElement(
113
+ NavigationProvider,
114
+ { value: navState },
115
+ element as React.ReactNode
116
+ );
117
+ const wrapped = createElement(TimberNuqsAdapter, null, withNav);
118
+ transitionRender(wrapped);
119
+ },
120
+
121
+ // Run a navigation inside a React transition with optimistic pending URL.
122
+ // The entire fetch + state update runs inside startTransition. useOptimistic
123
+ // shows the pending URL immediately and reverts to null when the transition
124
+ // commits (atomic with the new tree + params).
125
+ //
126
+ // The perform callback receives a wrapPayload function that wraps the
127
+ // decoded RSC payload with NavigationProvider + NuqsAdapter. navState
128
+ // is passed explicitly by the router — no getNavigationState() needed.
129
+ navigateTransition: (pendingUrl: string, perform) => {
130
+ return navigateTransition(pendingUrl, async () => {
131
+ const payload = await perform((rawPayload: unknown, navState: NavigationState) => {
132
+ const withNav = createElement(
133
+ NavigationProvider,
134
+ { value: navState },
135
+ rawPayload as React.ReactNode
136
+ );
137
+ return createElement(TimberNuqsAdapter, null, withNav);
138
+ });
139
+ return payload as React.ReactNode;
140
+ });
141
+ },
142
+
143
+ // Schedule a callback after the next paint so scroll operations
144
+ // happen after React commits the new content to the DOM.
145
+ // Double-rAF ensures the browser has painted the new frame.
146
+ afterPaint: (callback: () => void) => {
147
+ requestAnimationFrame(() => {
148
+ requestAnimationFrame(callback);
149
+ });
150
+ },
151
+
152
+ // Apply resolved head elements (title, meta tags) to the DOM after
153
+ // SPA navigation. See design/16-metadata.md.
154
+ applyHead: applyHeadElements,
155
+ };
156
+
157
+ const router = createRouter(deps);
158
+ setGlobalRouter(router);
159
+
160
+ // Set up Navigation API integration after router is created.
161
+ // The navigate event listener delegates to router.navigate and
162
+ // router.handlePopState for external navigations and traversals.
163
+ let navApiController: NavigationApiController | null = null;
164
+ if (useNavApi) {
165
+ navApiController = setupNavigationApi({
166
+ onExternalNavigate: async (url, { replace, signal, scroll }) => {
167
+ // Navigation intercepted by the Navigation API. Covers both
168
+ // Link <a> clicks (user-initiated) and external navigations.
169
+ // The Navigation API handles the URL update via intercept(),
170
+ // so pass _skipHistory to avoid double pushState.
171
+ await router.navigate(url, {
172
+ replace,
173
+ scroll,
174
+ _signal: signal,
175
+ _skipHistory: true,
176
+ });
177
+ },
178
+ onTraverse: async (url, scrollY, signal) => {
179
+ // Back/forward — delegate to the router's popstate handler.
180
+ await router.handlePopState(url, scrollY, signal);
181
+ },
182
+ });
183
+
184
+ // Wire the router-navigating flag into RouterDeps.
185
+ // This must be done after setupNavigationApi returns the controller.
186
+ deps.setRouterNavigating = (v) => navApiController!.setRouterNavigating(v);
187
+ deps.saveNavigationEntryScroll = (y) => navApiController!.saveScrollPosition(y);
188
+ deps.completeRouterNavigation = () => navApiController!.completeRouterNavigation();
189
+ deps.navigationNavigate = (url, replace) => navApiController!.navigate(url, replace);
190
+ }
191
+
192
+ return { router, navApiController };
193
+ }
@@ -0,0 +1,157 @@
1
+ /**
2
+ * RSC Stream Bootstrap — decodes the server-inlined RSC payload.
3
+ *
4
+ * The RSC payload is embedded in the HTML as progressive inline script
5
+ * tags that call `self.__timber_f.push([type, data])` as RSC chunks arrive.
6
+ * Typed tuples: [0] = bootstrap signal, [1, string] = Flight data chunk.
7
+ *
8
+ * This module sets up a ReadableStream fed by those push() calls so
9
+ * `createFromReadableStream` can decode the Flight protocol progressively.
10
+ *
11
+ * See design/18-build-system.md §"Entry Files"
12
+ */
13
+
14
+ import { createFromReadableStream } from '../../rsc-runtime/browser.js';
15
+ import { isPageUnloading } from '../unload-guard.js';
16
+
17
+ type FlightSegment = [isBootstrap: 0] | [isData: 1, data: string];
18
+
19
+ export interface RscStreamResult {
20
+ /** The decoded RSC element (thenable/lazy — resolved by React during render) */
21
+ element: unknown;
22
+ }
23
+
24
+ /**
25
+ * Create the RSC payload stream from server-inlined `__timber_f` chunks.
26
+ *
27
+ * Returns null if no RSC payload was inlined (e.g., JS-only client).
28
+ * When a payload exists, returns the decoded element for hydration.
29
+ */
30
+ export function createRscPayloadStream(): RscStreamResult | null {
31
+ // __timber_f is initialized in <head> via flightInitScript() (see
32
+ // flight-scripts.ts). If it doesn't exist, skip Flight decoding
33
+ // entirely and fall through to the createRoot branch.
34
+ // Do NOT defensively create it here: that would cause
35
+ // createFromReadableStream to be called on an empty stream, producing
36
+ // a "Connection closed" error on hydration. See TIM-552.
37
+ const timberChunks = (self as unknown as Record<string, FlightSegment[] | undefined>).__timber_f;
38
+ if (!timberChunks) return null;
39
+
40
+ const encoder = new TextEncoder();
41
+
42
+ // Buffer to hold string data until the stream writer is ready.
43
+ // Scripts that execute before hydration starts push data here.
44
+ let dataBuffer: string[] | undefined = [];
45
+ let streamWriter: ReadableStreamDefaultController<Uint8Array> | null = null;
46
+ let streamFlushed = false;
47
+
48
+ /** Process a typed tuple from __timber_f. */
49
+ function handleSegment(seg: FlightSegment): void {
50
+ if (seg[0] === 0) {
51
+ // Bootstrap signal — initialize buffer (already done above)
52
+ if (!dataBuffer) dataBuffer = [];
53
+ } else if (seg[0] === 1) {
54
+ // Flight data chunk
55
+ if (streamWriter) {
56
+ streamWriter.enqueue(encoder.encode(seg[1]));
57
+ } else if (dataBuffer) {
58
+ dataBuffer.push(seg[1]);
59
+ }
60
+ }
61
+ }
62
+
63
+ // Process any chunks that arrived before this script executed.
64
+ for (const seg of timberChunks) {
65
+ handleSegment(seg);
66
+ }
67
+ // Clear the array to release memory.
68
+ timberChunks.length = 0;
69
+
70
+ // Patch push() so subsequent script tags feed data in real time.
71
+ (timberChunks as unknown as { push: (seg: FlightSegment) => void }).push = handleSegment;
72
+
73
+ const rscPayload = new ReadableStream<Uint8Array>({
74
+ start(controller) {
75
+ streamWriter = controller;
76
+ // Flush buffered data into the stream.
77
+ if (dataBuffer) {
78
+ for (const data of dataBuffer) {
79
+ controller.enqueue(encoder.encode(data));
80
+ }
81
+ dataBuffer = undefined;
82
+ }
83
+ // If DOM already loaded (non-streaming or fast page), close now.
84
+ if (streamFlushed) {
85
+ controller.close();
86
+ }
87
+ },
88
+ });
89
+
90
+ // Close the stream when the document finishes loading.
91
+ // DOMContentLoaded fires after the HTML parser has processed all
92
+ // inline scripts (including streamed Suspense replacements and
93
+ // RSC data), so all push() calls have completed by this point.
94
+ //
95
+ // If the page is unloading (user refreshed or navigated away),
96
+ // do NOT close the stream. When the connection drops mid-stream,
97
+ // DOMContentLoaded fires because the parser finishes. Closing an
98
+ // incomplete RSC stream causes React's Flight client to throw
99
+ // "Connection closed." — a jarring error on a page being replaced.
100
+ // Leaving the stream open is harmless: the page is being torn down.
101
+ function onDOMContentLoaded(): void {
102
+ if (isPageUnloading()) return;
103
+
104
+ // In dev mode, do NOT close the stream. React's RSC renderer
105
+ // includes debug owner/stack references ($1, $14, etc.) in the
106
+ // Flight payload that point to rows delivered through the debug
107
+ // channel, not the main Flight stream. The browser Flight client
108
+ // tracks these as pending chunks. Closing the stream with
109
+ // unresolved chunks triggers reportGlobalError("Connection closed")
110
+ // which kills the entire React tree.
111
+ //
112
+ // Leaving the stream open is harmless: React has already received
113
+ // all data rows and can hydrate fully. The pending debug chunks
114
+ // just remain unresolved (they're only used for React DevTools
115
+ // component stacks, not rendering).
116
+ //
117
+ // In production, debug rows are not emitted, so closing is safe.
118
+ if (process.env.NODE_ENV === 'development') {
119
+ // Mark as flushed so no more data is buffered, but don't close.
120
+ streamFlushed = true;
121
+ dataBuffer = undefined;
122
+ return;
123
+ }
124
+
125
+ if (streamWriter && !streamFlushed) {
126
+ streamWriter.close();
127
+ streamFlushed = true;
128
+ dataBuffer = undefined;
129
+ }
130
+ streamFlushed = true;
131
+ }
132
+
133
+ if (document.readyState === 'loading') {
134
+ document.addEventListener('DOMContentLoaded', onDOMContentLoaded, false);
135
+ } else {
136
+ // DOM already parsed. All inline RSC <script> tags have already
137
+ // executed and pushed their data into the buffer. The buffer was
138
+ // flushed into the stream during start() above.
139
+ //
140
+ // Close via queueMicrotask rather than setTimeout. setTimeout
141
+ // defers to the next macrotask, which can race with React's
142
+ // Flight client read loop — if React finishes reading all queued
143
+ // chunks and issues a reader.read() that pends, the stream is
144
+ // NOT closed yet (setTimeout hasn't fired), so React sees an
145
+ // open stream and waits. Then setTimeout fires and closes it.
146
+ // This works in theory but some React Flight builds interpret
147
+ // a mid-read close as "Connection closed" rather than clean EOF.
148
+ // queueMicrotask fires at the end of the current microtask
149
+ // checkpoint — after start() and createFromReadableStream
150
+ // initialization but before any macrotask, giving React a
151
+ // consistent close signal. See TIM-524.
152
+ queueMicrotask(onDOMContentLoaded);
153
+ }
154
+
155
+ const element = createFromReadableStream(rscPayload);
156
+ return { element };
157
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Scroll position helpers for the browser entry.
3
+ *
4
+ * Reads scroll position from the document viewport or explicitly marked
5
+ * `data-timber-scroll-restoration` containers.
6
+ *
7
+ * See design/19-client-navigation.md §"Overflow Scroll Containers".
8
+ */
9
+
10
+ /**
11
+ * Read the current scroll position.
12
+ *
13
+ * Checks window scroll first, then explicit `data-timber-scroll-restoration`
14
+ * containers. With segment tree merging, shared layouts are reconciled in
15
+ * place via `cloneElement` — React preserves their DOM and scroll state
16
+ * naturally. We don't need to auto-detect overflow containers; only
17
+ * explicitly marked containers are tracked.
18
+ */
19
+ export function getScrollY(): number {
20
+ if (window.scrollY || document.documentElement.scrollTop || document.body.scrollTop) {
21
+ return window.scrollY || document.documentElement.scrollTop || document.body.scrollTop;
22
+ }
23
+ for (const el of document.querySelectorAll('[data-timber-scroll-restoration]')) {
24
+ if ((el as HTMLElement).scrollTop > 0) return (el as HTMLElement).scrollTop;
25
+ }
26
+ return 0;
27
+ }
@@ -65,17 +65,24 @@ type ParsedDigest = DenyDigest | RenderErrorDigest | RedirectDigest;
65
65
 
66
66
  export interface TimberErrorBoundaryProps {
67
67
  /** The component to render when an error is caught. */
68
- fallbackComponent: (...args: unknown[]) => ReactNode;
68
+ fallbackComponent?: (...args: unknown[]) => ReactNode;
69
+ /**
70
+ * Pre-rendered fallback element. Used for MDX status files which are server
71
+ * components and cannot be passed as function props across the RSC→client
72
+ * boundary. When set, rendered directly instead of calling fallbackComponent.
73
+ *
74
+ * See design/10-error-handling.md §"Status-Code File Variants" — MDX status
75
+ * files are server components by default (zero client JS).
76
+ */
77
+ fallbackElement?: ReactNode;
69
78
  /**
70
79
  * Status code filter. If set, only catches errors matching this status.
71
80
  * 400 = any 4xx, 500 = any 5xx, specific number = exact match.
72
81
  */
73
82
  status?: number;
74
83
  /**
75
- * When true, catching a DenySignal sets _denyHandledByBoundary on the
76
- * nav context to prevent page-level deny promotion. Only slot catch-all
77
- * boundaries should set this — segment boundaries (403.tsx, 4xx.tsx,
78
- * error.tsx) must NOT, otherwise normal page denies get swallowed.
84
+ * When true, this boundary wraps a parallel slot. Slot denials are
85
+ * graceful degradation they must NOT change the HTTP status code.
79
86
  */
80
87
  isSlotBoundary?: boolean;
81
88
  children: ReactNode;
@@ -148,20 +155,45 @@ export class TimberErrorBoundary extends Component<
148
155
  }
149
156
  }
150
157
 
151
- // Report DenySignal handling to prevent page-level promotion but only
152
- // for slot boundaries. Segment boundaries (403.tsx, 4xx.tsx, error.tsx)
153
- // must NOT set this flag, otherwise normal page/hold-window denies get
154
- // swallowed as 200 with boundary HTML instead of the intended 4xx.
155
- // Runs here in render() (not getDerivedStateFromError) so the status
156
- // filter has already been applied — non-matching boundaries re-threw above.
157
- // See LOCAL-298.
158
- if (parsed?.type === 'deny' && this.props.isSlotBoundary) {
159
- const ssrData = getSsrData();
160
- if (ssrData?._navContext) {
161
- ssrData._navContext._denyHandledByBoundary = true;
158
+ // Report DenySignal handling so the pipeline skips the redundant
159
+ // renderDenyPage() re-render but ONLY when this boundary can fully
160
+ // handle the deny in-tree:
161
+ //
162
+ // TSX boundaries (fallbackComponent) can receive runtime props
163
+ // (status, dangerouslyPassData) dynamically in render()
164
+ // MDX boundaries (fallbackElement) — pre-rendered at tree-build time,
165
+ // cannot receive runtime deny props. Must fall through to re-render.
166
+ //
167
+ // For qualifying segment boundaries: also set the HTTP status code from
168
+ // the DenySignal so the Response has the correct 4xx status. This runs
169
+ // synchronously during Fizz rendering, BEFORE onShellReady.
170
+ //
171
+ // For slot boundaries: set _denyHandledByBoundary but do NOT change
172
+ // statusCode — slot denials are graceful degradation.
173
+ //
174
+ // See TIM-664, LOCAL-298.
175
+ if (parsed?.type === 'deny') {
176
+ const canHandleInTree = this.props.fallbackElement == null;
177
+
178
+ if (canHandleInTree || this.props.isSlotBoundary) {
179
+ const ssrData = getSsrData();
180
+ if (ssrData?._navContext) {
181
+ ssrData._navContext._denyHandledByBoundary = true;
182
+ if (!this.props.isSlotBoundary) {
183
+ ssrData._navContext.statusCode = parsed.status;
184
+ }
185
+ }
162
186
  }
163
187
  }
164
188
 
189
+ // Pre-rendered fallback element (MDX status files) — render directly.
190
+ // MDX components are server components that cannot be passed as function
191
+ // props across the RSC→client boundary. Instead, they are pre-rendered
192
+ // as elements in the RSC environment and passed here as fallbackElement.
193
+ if (this.props.fallbackElement != null) {
194
+ return this.props.fallbackElement;
195
+ }
196
+
165
197
  // Render the fallback component with the right props shape.
166
198
  if (parsed?.type === 'deny') {
167
199
  return createElement(this.props.fallbackComponent as never, {
@@ -0,0 +1,65 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * Reconstitutes a SerializableError into a real Error instance before
5
+ * passing to the user's error component.
6
+ *
7
+ * TSX error pages are 'use client' components that receive { error: Error, digest, reset }.
8
+ * Error objects are not RSC-serializable (React Flight throws "Only plain objects
9
+ * can be passed to Client Components"). This wrapper receives the error as a plain
10
+ * SerializableError object, reconstitutes a real Error instance, and passes it
11
+ * to the user's error component — ensuring error instanceof Error works correctly.
12
+ *
13
+ * See design/spike-TIM-565-unify-error-pages.md §"Edge Case B"
14
+ * See design/10-error-handling.md §"RSC → SSR for Error Pages via SerializableError"
15
+ */
16
+
17
+ import { createElement, type ReactNode, type ComponentType } from 'react';
18
+
19
+ /**
20
+ * Plain-object representation of an Error that can cross the RSC → client boundary.
21
+ * Stack is only included in dev mode (gated by isDevMode() on the server).
22
+ */
23
+ export interface SerializableError {
24
+ message: string;
25
+ name: string;
26
+ stack?: string;
27
+ }
28
+
29
+ /**
30
+ * Props for the ErrorReconstituter wrapper component.
31
+ * All props are RSC-serializable:
32
+ * - error: plain object (SerializableError)
33
+ * - digest: plain JSON or null
34
+ * - reset: undefined (only meaningful on client after boundary catch)
35
+ * - component: client module reference (RSC Flight serializes as opaque ref)
36
+ */
37
+ interface ErrorReconstituterProps {
38
+ error: SerializableError;
39
+ digest: { code: string; data: unknown } | null;
40
+ reset: undefined;
41
+ component: ComponentType<{
42
+ error: Error;
43
+ digest: { code: string; data: unknown } | null;
44
+ reset: (() => void) | undefined;
45
+ }>;
46
+ }
47
+
48
+ /**
49
+ * Reconstitute a SerializableError into a real Error instance and render
50
+ * the user's error component with the proper props.
51
+ */
52
+ export function ErrorReconstituter({
53
+ error: serialized,
54
+ digest,
55
+ reset,
56
+ component,
57
+ }: ErrorReconstituterProps): ReactNode {
58
+ // Reconstitute a real Error so instanceof checks work in user code
59
+ const error = Object.assign(new Error(serialized.message), {
60
+ name: serialized.name,
61
+ ...(serialized.stack != null ? { stack: serialized.stack } : {}),
62
+ });
63
+
64
+ return createElement(component, { error, digest, reset });
65
+ }
@@ -12,8 +12,8 @@
12
12
  */
13
13
 
14
14
  import { useActionState as reactUseActionState, useTransition } from 'react';
15
- import type { ActionResult, ValidationErrors } from '#/server/action-client';
16
- import type { FormFlashData } from '#/server/form-flash';
15
+ import type { ActionFn, ActionResult, InputHint, ValidationErrors } from '../server/action-client';
16
+ import type { FormFlashData } from '../server/form-flash';
17
17
 
18
18
  // ─── Types ───────────────────────────────────────────────────────────────
19
19
 
@@ -90,15 +90,22 @@ export function useActionState<TData>(
90
90
  * </button>
91
91
  * ```
92
92
  */
93
- export function useFormAction<TData>(
94
- action: (input: unknown) => Promise<ActionResult<TData>>
95
- ): [(input?: unknown) => Promise<ActionResult<TData>>, boolean] {
93
+ export function useFormAction<TData = unknown, TInput = unknown>(
94
+ action: ActionFn<TData, TInput> | ((input: TInput) => Promise<ActionResult<TData>>)
95
+ ): [
96
+ (
97
+ ...args: undefined extends TInput ? [input?: InputHint<TInput>] : [input: InputHint<TInput>]
98
+ ) => Promise<ActionResult<TData>>,
99
+ boolean,
100
+ ] {
96
101
  const [isPending, startTransition] = useTransition();
97
102
 
98
- const execute = (input?: unknown): Promise<ActionResult<TData>> => {
103
+ const execute = (input?: InputHint<TInput>): Promise<ActionResult<TData>> => {
99
104
  return new Promise((resolve) => {
100
105
  startTransition(async () => {
101
- const result = await action(input);
106
+ const result = await (action as (input: InputHint<TInput>) => Promise<ActionResult<TData>>)(
107
+ input as InputHint<TInput>
108
+ );
102
109
  resolve(result);
103
110
  });
104
111
  });
@@ -23,20 +23,42 @@ export interface HistoryEntry {
23
23
  * On forward navigation, the new page's payload is pushed onto the stack.
24
24
  * On popstate, the cached payload is replayed instantly.
25
25
  *
26
- * Scroll positions are stored in history.state (browser History API),
27
- * not in this stack see design/19-client-navigation.md §Scroll Restoration.
26
+ * Supports two keying modes:
27
+ * - **URL-keyed** (default): entries keyed by pathname + search.
28
+ * Used with the History API fallback.
29
+ * - **Entry-key + URL**: when the Navigation API is available,
30
+ * entries can also be stored by Navigation entry key for
31
+ * disambiguation of duplicate URLs in the history stack.
32
+ * Falls back to URL lookup when entry key is not found.
33
+ *
34
+ * Scroll positions are stored in history.state or Navigation API entry
35
+ * state, not in this stack — see design/19-client-navigation.md §Scroll Restoration.
28
36
  *
29
37
  * Entries persist for the session duration (no expiry) and are cleared
30
38
  * when the tab is closed — matching browser back-button behavior.
31
39
  */
32
40
  export class HistoryStack {
33
41
  private entries = new Map<string, HistoryEntry>();
42
+ /** Entries keyed by Navigation API entry key for duplicate URL disambiguation. */
43
+ private entryKeyMap = new Map<string, HistoryEntry>();
34
44
 
35
- push(url: string, entry: HistoryEntry): void {
45
+ push(url: string, entry: HistoryEntry, entryKey?: string): void {
36
46
  this.entries.set(url, entry);
47
+ if (entryKey) {
48
+ this.entryKeyMap.set(entryKey, entry);
49
+ }
37
50
  }
38
51
 
39
- get(url: string): HistoryEntry | undefined {
52
+ /**
53
+ * Get an entry. When an entry key is provided (Navigation API),
54
+ * tries the entry-key map first for accurate disambiguation of
55
+ * duplicate URLs, then falls back to URL lookup.
56
+ */
57
+ get(url: string, entryKey?: string): HistoryEntry | undefined {
58
+ if (entryKey) {
59
+ const byKey = this.entryKeyMap.get(entryKey);
60
+ if (byKey) return byKey;
61
+ }
40
62
  return this.entries.get(url);
41
63
  }
42
64