@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
@@ -23,7 +23,7 @@ export interface FetchResult {
23
23
  headElements: HeadElement[] | null;
24
24
  /** Segment metadata from X-Timber-Segments header for populating the segment cache. */
25
25
  segmentInfo: SegmentInfo[] | null;
26
- /** Route params from X-Timber-Params header for populating useParams(). */
26
+ /** Route params from X-Timber-Params header for populating useSegmentParams(). */
27
27
  params: Record<string, string | string[]> | null;
28
28
  /** Segment paths that were skipped by the server (for client-side merging). */
29
29
  skippedSegments: string[] | null;
@@ -58,6 +58,43 @@ function appendRscParam(url: string): string {
58
58
  return `${url}${separator}_rsc=${generateCacheBustId()}`;
59
59
  }
60
60
 
61
+ // ─── Deployment ID ───────────────────────────────────────────────
62
+
63
+ /**
64
+ * The client's deployment ID, set at bootstrap from the runtime config.
65
+ * Sent with every RSC/action request for version skew detection.
66
+ * Null in dev mode. See TIM-446.
67
+ */
68
+ let clientDeploymentId: string | null = null;
69
+
70
+ /** Set the client deployment ID. Called once at bootstrap. */
71
+ export function setClientDeploymentId(id: string | null): void {
72
+ clientDeploymentId = id;
73
+ }
74
+
75
+ /** Get the client deployment ID. */
76
+ export function getClientDeploymentId(): string | null {
77
+ return clientDeploymentId;
78
+ }
79
+
80
+ // ─── Reload Signal ───────────────────────────────────────────────
81
+
82
+ /** Header name used by the server to signal a version skew reload. */
83
+ export const RELOAD_HEADER = 'X-Timber-Reload';
84
+
85
+ /** Header name for the client's deployment ID. */
86
+ export const DEPLOYMENT_ID_HEADER = 'X-Timber-Deployment-Id';
87
+
88
+ /**
89
+ * Check if a response signals a version skew reload.
90
+ * Triggers a full page reload if the server indicates the client is stale.
91
+ */
92
+ export function checkReloadSignal(response: Response): boolean {
93
+ return response.headers.get(RELOAD_HEADER) === '1';
94
+ }
95
+
96
+ // ─── Header Builder ──────────────────────────────────────────────
97
+
61
98
  export function buildRscHeaders(
62
99
  stateTree: { segments: string[] } | undefined,
63
100
  currentUrl?: string
@@ -75,6 +112,13 @@ export function buildRscHeaders(
75
112
  if (currentUrl) {
76
113
  headers['X-Timber-URL'] = currentUrl;
77
114
  }
115
+ // Send deployment ID for version skew detection (TIM-446).
116
+ // The server compares this against the current build's ID.
117
+ // On mismatch, the server signals a reload instead of returning
118
+ // an RSC payload with mismatched module references.
119
+ if (clientDeploymentId) {
120
+ headers[DEPLOYMENT_ID_HEADER] = clientDeploymentId;
121
+ }
78
122
  return headers;
79
123
  }
80
124
 
@@ -135,7 +179,7 @@ export function extractSkippedSegments(response: Response): string[] | null {
135
179
  * Extract route params from the X-Timber-Params response header.
136
180
  * Returns null if the header is missing or malformed.
137
181
  *
138
- * Used to populate useParams() after client-side navigation.
182
+ * Used to populate useSegmentParams() after client-side navigation.
139
183
  */
140
184
  export function extractParams(response: Response): Record<string, string | string[]> | null {
141
185
  const header = response.headers.get('X-Timber-Params');
@@ -161,6 +205,36 @@ export class RedirectError extends Error {
161
205
  }
162
206
  }
163
207
 
208
+ /**
209
+ * Thrown when the server signals a version skew (X-Timber-Reload header).
210
+ * Caught in navigate() to trigger a full page reload via triggerStaleReload().
211
+ * See TIM-446.
212
+ */
213
+ export class VersionSkewError extends Error {
214
+ constructor() {
215
+ super('Version skew detected — server has been redeployed');
216
+ }
217
+ }
218
+
219
+ /**
220
+ * Thrown when the server returns an error for an RSC payload request.
221
+ * The server sends X-Timber-Error header and a JSON body instead of a
222
+ * broken RSC stream for any RenderError (4xx or 5xx). Caught in
223
+ * navigate() to trigger a hard navigation so the server can render
224
+ * the error page as HTML.
225
+ *
226
+ * See design/10-error-handling.md §"Error Page Rendering for Client Navigation"
227
+ */
228
+ export class ServerErrorResponse extends Error {
229
+ readonly status: number;
230
+ readonly url: string;
231
+ constructor(status: number, url: string) {
232
+ super(`Server error ${status} during navigation to ${url}`);
233
+ this.status = status;
234
+ this.url = url;
235
+ }
236
+ }
237
+
164
238
  // ─── Fetch ───────────────────────────────────────────────────────
165
239
 
166
240
  /**
@@ -175,7 +249,8 @@ export async function fetchRscPayload(
175
249
  url: string,
176
250
  deps: RouterDeps,
177
251
  stateTree?: { segments: string[] },
178
- currentUrl?: string
252
+ currentUrl?: string,
253
+ signal?: AbortSignal
179
254
  ): Promise<FetchResult> {
180
255
  const rscUrl = appendRscParam(url);
181
256
  const headers = buildRscHeaders(stateTree, currentUrl);
@@ -186,12 +261,18 @@ export async function fetchRscPayload(
186
261
  //
187
262
  // Intercept the response to read X-Timber-Head before createFromFetch
188
263
  // consumes the body. Reading headers does NOT consume the body stream.
189
- const fetchPromise = deps.fetch(rscUrl, { headers, redirect: 'manual' });
264
+ const fetchPromise = deps.fetch(rscUrl, { headers, redirect: 'manual', signal });
190
265
  let headElements: HeadElement[] | null = null;
191
266
  let segmentInfo: SegmentInfo[] | null = null;
192
267
  let params: Record<string, string | string[]> | null = null;
193
268
  let skippedSegments: string[] | null = null;
194
269
  const wrappedPromise = fetchPromise.then((response) => {
270
+ // Version skew detection (TIM-446): if the server signals a reload,
271
+ // throw VersionSkewError so the caller (router navigate) can trigger
272
+ // a full page reload via triggerStaleReload().
273
+ if (checkReloadSignal(response)) {
274
+ throw new VersionSkewError();
275
+ }
195
276
  // Detect server-side redirects. The server returns 204 + X-Timber-Redirect
196
277
  // for RSC payload requests instead of a raw 302, because fetch with
197
278
  // redirect: "manual" turns 302s into opaque redirects (status 0, null body)
@@ -202,21 +283,29 @@ export async function fetchRscPayload(
202
283
  if (redirectLocation) {
203
284
  throw new RedirectError(redirectLocation);
204
285
  }
286
+ // Detect server error responses. The server returns X-Timber-Error header
287
+ // with a JSON body instead of a broken RSC stream for any RenderError
288
+ // (4xx or 5xx). Hard-navigate so the server renders the error page as HTML.
289
+ // See design/10-error-handling.md §"Error Page Rendering for Client Navigation"
290
+ if (response.headers.get('X-Timber-Error') === '1') {
291
+ throw new ServerErrorResponse(response.status, url);
292
+ }
205
293
  headElements = extractHeadElements(response);
206
294
  segmentInfo = extractSegmentInfo(response);
207
295
  params = extractParams(response);
208
296
  skippedSegments = extractSkippedSegments(response);
209
297
  return response;
210
298
  });
211
- // Await so headElements/segmentInfo/params are populated before we return.
212
- // Also await the decoded payload — createFromFetch returns a thenable
213
- // that resolves to the React element tree.
299
+ // Await headers so headElements/segmentInfo/params are populated.
214
300
  await wrappedPromise;
301
+ // Await the decoded payload — createFromFetch returns a thenable
302
+ // that resolves to the React element tree once the Flight stream
303
+ // has enough data to produce the shell.
215
304
  const payload = await deps.decodeRsc(wrappedPromise);
216
305
  return { payload, headElements, segmentInfo, params, skippedSegments };
217
306
  }
218
307
  // Test/fallback path: return raw text
219
- const response = await deps.fetch(rscUrl, { headers, redirect: 'manual' });
308
+ const response = await deps.fetch(rscUrl, { headers, redirect: 'manual', signal });
220
309
  // Check for redirect in test path too
221
310
  if (response.status >= 300 && response.status < 400) {
222
311
  const location = response.headers.get('Location');
@@ -11,7 +11,7 @@ export interface PrefetchResult {
11
11
  headElements: HeadElement[] | null;
12
12
  /** Segment metadata from X-Timber-Segments header for populating the segment cache. */
13
13
  segmentInfo?: SegmentInfo[] | null;
14
- /** Route params from X-Timber-Params header for populating useParams(). */
14
+ /** Route params from X-Timber-Params header for populating useSegmentParams(). */
15
15
  params?: Record<string, string | string[]> | null;
16
16
  /** Segment paths skipped by the server (for client-side merging). */
17
17
  skippedSegments?: string[] | null;
@@ -0,0 +1,86 @@
1
+ /**
2
+ * SegmentOutlet — client component boundary at each layout segment.
3
+ *
4
+ * Replaces the post-hoc tree walking in segment-merger.ts with an explicit
5
+ * client component at each segment boundary. Each outlet:
6
+ *
7
+ * 1. Knows its own segment path (prop from the server)
8
+ * 2. Caches its children in a ref across navigations
9
+ * 3. When `keepCurrent` is true (partial navigation, this segment skipped),
10
+ * returns the previously cached children — layout state is preserved
11
+ * 4. When `keepCurrent` is false (full navigation or this segment changed),
12
+ * stores and renders the new children
13
+ *
14
+ * This eliminates the need for client-side element tree walking, which
15
+ * breaks on real RSC trees due to opaque client component lazy refs,
16
+ * Suspense thenables, and AccessGate wrappers.
17
+ *
18
+ * Architecture is similar to Next.js's `<LayoutRouter>` client component —
19
+ * each layout boundary is an explicit client component that manages its
20
+ * own subtree. See design/19-client-navigation.md.
21
+ *
22
+ * Security: This is a performance optimization only. The server always
23
+ * runs all access.ts files regardless of segment skipping. A fabricated
24
+ * keepCurrent prop can only cause stale layouts — never auth bypass.
25
+ * See design/13-security.md §"State tree manipulation".
26
+ */
27
+
28
+ 'use client';
29
+
30
+ import { useRef, type ReactNode } from 'react';
31
+
32
+ export interface SegmentOutletProps {
33
+ /**
34
+ * Unique identifier for this segment. For normal segments this is the
35
+ * urlPath (e.g., "/", "/dashboard"). For route groups this includes the
36
+ * group name (e.g., "/(marketing)") to distinguish siblings that share
37
+ * the same urlPath. Must match the segmentId used in state-tree-diff.ts.
38
+ */
39
+ segmentPath: string;
40
+
41
+ /**
42
+ * When true, the outlet returns its previously cached children instead
43
+ * of rendering the new children prop. Set by the server when this
44
+ * segment was skipped (the client already has the layout mounted).
45
+ *
46
+ * On the first render (SSR/hydration), this is always false — there's
47
+ * no cached content yet. On subsequent partial navigations, the server
48
+ * sets this to true for segments it skipped rendering.
49
+ */
50
+ keepCurrent?: boolean;
51
+
52
+ /** The segment's React subtree (layout + inner content). */
53
+ children: ReactNode;
54
+ }
55
+
56
+ /**
57
+ * Client component boundary at each layout segment in the element tree.
58
+ *
59
+ * On full navigation: receives new children, stores them, renders them.
60
+ * On partial navigation (keepCurrent=true): ignores children prop,
61
+ * returns previously stored content — React reconciles the same elements,
62
+ * preserving all client component state in the layout subtree.
63
+ *
64
+ * React preserves the ref across `reactRoot.render()` calls because:
65
+ * - SegmentOutlet has a stable type (client component module reference)
66
+ * - It appears at the same tree position on every navigation
67
+ * - React reconciles same-type, same-position → instance preserved
68
+ */
69
+ export function SegmentOutlet({
70
+ segmentPath: _segmentPath,
71
+ keepCurrent = false,
72
+ children,
73
+ }: SegmentOutletProps) {
74
+ // Store content in a ref to avoid triggering re-renders on cache updates.
75
+ // The ref persists across reactRoot.render() calls because React reconciles
76
+ // the same component type at the same tree position.
77
+ const contentRef = useRef<ReactNode>(null);
78
+
79
+ if (!keepCurrent) {
80
+ // Full render or this segment was re-rendered — store and render new content
81
+ contentRef.current = children;
82
+ }
83
+ // else: keepCurrent=true — return previously cached content
84
+
85
+ return contentRef.current;
86
+ }
@@ -41,12 +41,20 @@ export interface SsrData {
41
41
  /** The request's route params (e.g. { id: '123' }) */
42
42
  params: Record<string, string | string[]>;
43
43
  /**
44
- * Mutable reference to NavContext for error boundary → RSC communication.
45
- * When TimberErrorBoundary catches a DenySignal, it sets
46
- * `_navContext._denyHandledByBoundary = true` to prevent the RSC entry
47
- * from promoting the denial to page-level. See LOCAL-298.
44
+ * Mutable reference to NavContext for error boundary → pipeline communication.
45
+ *
46
+ * When TimberErrorBoundary catches a DenySignal during SSR, it:
47
+ * 1. Sets `statusCode` to the deny status (e.g., 403) — so the HTTP
48
+ * Response has the correct status code without a re-render.
49
+ * 2. Sets `_denyHandledByBoundary = true` — so the pipeline skips
50
+ * the redundant renderDenyPage() re-render.
51
+ *
52
+ * This runs synchronously during Fizz rendering, BEFORE onShellReady,
53
+ * so the status code is committed before any bytes are sent.
54
+ *
55
+ * See TIM-664, design/04-authorization.md §"React.cache Scope in Deny/Error Re-renders"
48
56
  */
49
- _navContext?: { _denyHandledByBoundary?: boolean };
57
+ _navContext?: { statusCode?: number; _denyHandledByBoundary?: boolean };
50
58
  }
51
59
 
52
60
  // ─── ALS-Backed Provider ─────────────────────────────────────────
@@ -16,6 +16,16 @@
16
16
 
17
17
  const RELOAD_FLAG_KEY = '__timber_stale_reload';
18
18
 
19
+ /**
20
+ * In-memory fallback counter for environments where sessionStorage is
21
+ * unavailable (private browsing, storage full, extension interference).
22
+ * Incremented each time triggerStaleReload() falls into the catch path.
23
+ * If the counter exceeds 0 on a subsequent call, the reload is suppressed
24
+ * to prevent an infinite loop. Resets naturally on page load (module
25
+ * re-evaluates) and can be manually reset via clearStaleReloadFlag().
26
+ */
27
+ let memoryReloadCount = 0;
28
+
19
29
  /**
20
30
  * Check if an error is a stale client reference error from React's
21
31
  * Flight client. These errors have the message pattern:
@@ -32,6 +42,34 @@ export function isStaleClientReference(error: unknown): boolean {
32
42
  return msg.includes('Could not find the module') || msg.includes('client reference not found');
33
43
  }
34
44
 
45
+ /**
46
+ * Check if an error is a chunk load failure from a dynamic import.
47
+ *
48
+ * After a deployment, old chunk filenames no longer exist. When the client
49
+ * tries to dynamically import a chunk that's been replaced, the browser
50
+ * throws one of these errors:
51
+ *
52
+ * - Chromium: "Failed to fetch dynamically imported module: <url>"
53
+ * - Firefox: "error loading dynamically imported module: <url>"
54
+ * - Safari: "Importing a module script failed."
55
+ * - Vite/Rollup: "Unable to preload CSS for <url>"
56
+ *
57
+ * See TIM-446
58
+ */
59
+ export function isChunkLoadError(error: unknown): boolean {
60
+ if (!(error instanceof Error)) return false;
61
+ const msg = error.message.toLowerCase();
62
+ return (
63
+ msg.includes('failed to fetch dynamically imported module') ||
64
+ msg.includes('error loading dynamically imported module') ||
65
+ msg.includes('importing a module script failed') ||
66
+ msg.includes('unable to preload css') ||
67
+ // Webpack-style chunk load errors (unlikely in Vite but defensive)
68
+ msg.includes('loading chunk') ||
69
+ msg.includes('loading css chunk')
70
+ );
71
+ }
72
+
35
73
  /**
36
74
  * Trigger a full page reload to pick up new bundles.
37
75
  *
@@ -65,9 +103,33 @@ export function triggerStaleReload(): boolean {
65
103
  window.location.reload();
66
104
  return true;
67
105
  } catch {
68
- // sessionStorage may be unavailable (private browsing, storage full, etc.)
69
- // Fall back to reloading without loop protection
70
- console.warn('[timber] Stale client reference detected. Reloading page.');
106
+ // sessionStorage unavailable (private browsing, storage full, etc.)
107
+ // Use document.cookie as a reload-persistent fallback loop guard.
108
+ // Module-level memoryReloadCount resets on every reload, so it can't
109
+ // detect cross-reload loops. Cookies persist across reloads and are
110
+ // available even when sessionStorage is blocked (TIM-576).
111
+ const cookieFlag = document.cookie.includes(RELOAD_FLAG_KEY + '=1');
112
+ if (cookieFlag || memoryReloadCount > 0) {
113
+ console.warn(
114
+ '[timber] Stale client reference detected again after reload. ' +
115
+ 'Not reloading to prevent infinite loop. ' +
116
+ 'This may indicate a deployment issue — try a hard refresh.'
117
+ );
118
+ return false;
119
+ }
120
+
121
+ memoryReloadCount++;
122
+ // Set a short-lived cookie (60s) as the persistent loop guard.
123
+ // It auto-expires so it won't block future legitimate reloads.
124
+ try {
125
+ document.cookie = `${RELOAD_FLAG_KEY}=1; max-age=60; path=/; SameSite=Lax`;
126
+ } catch {
127
+ // Cookie API unavailable — proceed anyway, memoryReloadCount guards same-page loops
128
+ }
129
+ console.warn(
130
+ '[timber] Stale client reference detected — the server has been ' +
131
+ 'redeployed with new bundles. Reloading to pick up the new version.'
132
+ );
71
133
  window.location.reload();
72
134
  return true;
73
135
  }
@@ -79,9 +141,16 @@ export function triggerStaleReload(): boolean {
79
141
  * reference error should trigger a fresh reload attempt.
80
142
  */
81
143
  export function clearStaleReloadFlag(): void {
144
+ memoryReloadCount = 0;
82
145
  try {
83
146
  sessionStorage.removeItem(RELOAD_FLAG_KEY);
84
147
  } catch {
85
148
  // sessionStorage unavailable — nothing to clear
86
149
  }
150
+ // Also clear the cookie fallback
151
+ try {
152
+ document.cookie = `${RELOAD_FLAG_KEY}=; max-age=0; path=/; SameSite=Lax`;
153
+ } catch {
154
+ // Cookie API unavailable
155
+ }
87
156
  }
@@ -3,11 +3,11 @@
3
3
  *
4
4
  * Shows an animated progress bar at the top of the viewport while an RSC
5
5
  * navigation is in flight. Injected automatically by the framework into
6
- * TransitionRoot — users never render this component directly.
6
+ * NavigationRoot — users never render this component directly.
7
7
  *
8
8
  * Configuration is via timber.config.ts `topLoader` key. Enabled by default.
9
9
  * Users who want a fully custom progress indicator disable the built-in one
10
- * (`topLoader: { enabled: false }`) and use `useNavigationPending()` directly.
10
+ * (`topLoader: { enabled: false }`) and use `usePendingNavigation()` directly.
11
11
  *
12
12
  * Animation approach: pure CSS @keyframes. The bar crawls from 0% to ~90%
13
13
  * width over ~30s using ease-out timing. When navigation completes, the bar
@@ -21,7 +21,7 @@
21
21
  * stays invisible during the delay period. If navigation finishes before the
22
22
  * delay, the bar was never visible so the finish transition is also invisible.
23
23
  *
24
- * See design/19-client-navigation.md §"useNavigationPending()"
24
+ * See design/19-client-navigation.md §"usePendingNavigation()"
25
25
  * See LOCAL-336 for design decisions.
26
26
  */
27
27
 
@@ -39,7 +39,7 @@ export interface TopLoaderConfig {
39
39
  color?: string;
40
40
  /** Bar height in pixels. Default: 3. */
41
41
  height?: number;
42
- /** Show subtle glow/shadow effect. Default: true. */
42
+ /** Show subtle glow/shadow effect. Default: false. */
43
43
  shadow?: boolean;
44
44
  /** Delay in ms before showing the bar. Default: 0. */
45
45
  delay?: number;
@@ -51,7 +51,7 @@ export interface TopLoaderConfig {
51
51
 
52
52
  const DEFAULT_COLOR = '#2299DD';
53
53
  const DEFAULT_HEIGHT = 3;
54
- const DEFAULT_SHADOW = true;
54
+ const DEFAULT_SHADOW = false;
55
55
  const DEFAULT_DELAY = 0;
56
56
  const DEFAULT_Z_INDEX = 1600;
57
57
 
@@ -97,7 +97,7 @@ function ensureKeyframes(): void {
97
97
  // ─── Component ───────────────────────────────────────────────────
98
98
 
99
99
  /**
100
- * Internal top-loader component. Injected by TransitionRoot.
100
+ * Internal top-loader component. Injected by NavigationRoot.
101
101
  *
102
102
  * Reads pending navigation state from PendingNavigationContext.
103
103
  * Phase transitions are derived synchronously during render:
@@ -112,6 +112,18 @@ function ensureKeyframes(): void {
112
112
  */
113
113
  export function TopLoader({ config }: { config?: TopLoaderConfig }): React.ReactElement | null {
114
114
  const pendingUrl = usePendingNavigationUrl();
115
+ // Navigation is pending when the React-based pending URL is set.
116
+ // pendingUrl is set as an urgent update in navigateTransition() —
117
+ // React commits it before the next paint, so the TopLoader appears
118
+ // immediately when a real RSC navigation starts.
119
+ //
120
+ // We intentionally do NOT check hasNativeNavigationTransition() here.
121
+ // The Navigation API's transition is active for ALL intercepted
122
+ // navigations, including shallow URL updates (nuqs search param
123
+ // changes with shallow: true) and prevented navigations. Those
124
+ // briefly set navigation.transition via event.intercept() but do
125
+ // NOT trigger RSC fetches — showing the TopLoader would be incorrect.
126
+ // pendingUrl is the authoritative signal for "we're fetching RSC data."
115
127
  const isPending = pendingUrl !== null;
116
128
 
117
129
  const color = config?.color ?? DEFAULT_COLOR;
@@ -1,26 +1,26 @@
1
1
  'use client';
2
2
 
3
- // useLinkStatus — returns { pending: true } while the nearest parent <Link>'s
3
+ // useLinkStatus — returns { isPending: true } while the nearest parent <Link>'s
4
4
  // navigation is in flight. No arguments — scoped via React context.
5
5
  // See design/19-client-navigation.md §"useLinkStatus()"
6
6
 
7
7
  import { useContext, createContext } from 'react';
8
8
 
9
9
  export interface LinkStatus {
10
- pending: boolean;
10
+ isPending: boolean;
11
11
  }
12
12
 
13
13
  /**
14
14
  * React context provided by <Link>. Holds the pending status
15
15
  * for that specific link's navigation.
16
16
  */
17
- export const LinkStatusContext = createContext<LinkStatus>({ pending: false });
17
+ export const LinkStatusContext = createContext<LinkStatus>({ isPending: false });
18
18
 
19
19
  /**
20
- * Returns `{ pending: true }` while the nearest parent `<Link>` component's
20
+ * Returns `{ isPending: true }` while the nearest parent `<Link>` component's
21
21
  * navigation is in flight. Must be used inside a `<Link>` component's children.
22
22
  *
23
- * Unlike `useNavigationPending()` which is global, this hook is scoped to
23
+ * Unlike `usePendingNavigation()` which is global, this hook is scoped to
24
24
  * the nearest parent `<Link>` — only the link the user clicked shows pending.
25
25
  *
26
26
  * ```tsx
@@ -28,8 +28,8 @@ export const LinkStatusContext = createContext<LinkStatus>({ pending: false });
28
28
  * import { Link, useLinkStatus } from '@timber-js/app/client'
29
29
  *
30
30
  * function Hint() {
31
- * const { pending } = useLinkStatus()
32
- * return <span className={pending ? 'opacity-50' : ''} />
31
+ * const { isPending } = useLinkStatus()
32
+ * return <span className={isPending ? 'opacity-50' : ''} />
33
33
  * }
34
34
  *
35
35
  * export function NavLink({ href, children }) {
@@ -7,7 +7,7 @@
7
7
  *
8
8
  * Two layers of type narrowing work together:
9
9
  * 1. The generic overload here uses the Routes interface directly —
10
- * `useParams<R>()` returns `Routes[R]['params']`.
10
+ * `useParams<R>()` returns `Routes[R]['segmentParams']`.
11
11
  * 2. Build-time codegen generates per-route string-literal overloads
12
12
  * in the .d.ts file for IDE autocomplete (see routing/codegen.ts).
13
13
  *
@@ -30,7 +30,7 @@
30
30
  * Design doc: design/09-typescript.md §"Typed Routes"
31
31
  */
32
32
 
33
- import type { Routes } from '#/index.js';
33
+ import type { Routes } from '../index.js';
34
34
  import { getSsrData } from './ssr-data.js';
35
35
  import { currentParams, _setCurrentParams, paramsListeners } from './state.js';
36
36
  import { useNavigationContext } from './navigation-context.js';
@@ -119,9 +119,11 @@ export function notifyParamsListeners(): void {
119
119
  * exact params shape from the generated Routes interface.
120
120
  * @overload Fallback — returns the generic params record.
121
121
  */
122
- export function useParams<R extends keyof Routes>(route: R): Routes[R]['params'];
123
- export function useParams(route?: string): Record<string, string | string[]>;
124
- export function useParams(_route?: string): Record<string, string | string[]> {
122
+ export function useSegmentParams<R extends keyof Routes>(
123
+ route: R
124
+ ): Routes[R] extends { segmentParams: infer P } ? P : Record<string, string | string[]>;
125
+ export function useSegmentParams(route?: string): Record<string, string | string[]>;
126
+ export function useSegmentParams(_route?: string): Record<string, string | string[]> {
125
127
  // Try reading from NavigationContext (client-side, inside React tree).
126
128
  // During SSR, no NavigationProvider is mounted, so this returns null.
127
129
  // When called outside a React component, useContext throws — caught below.
@@ -1,7 +1,7 @@
1
- // useNavigationPending — returns true while an RSC navigation is in flight.
2
- // See design/19-client-navigation.md §"useNavigationPending()"
1
+ // usePendingNavigation — returns true while an RSC navigation is in flight.
2
+ // See design/19-client-navigation.md §"usePendingNavigation()"
3
3
  //
4
- // Reads from PendingNavigationContext (provided by TransitionRoot) so the
4
+ // Reads from PendingNavigationContext (provided by NavigationRoot) so the
5
5
  // pending state shows immediately (urgent update) and clears atomically
6
6
  // with the new tree (same startTransition commit).
7
7
 
@@ -19,10 +19,10 @@ import { usePendingNavigationUrl } from './navigation-context.js';
19
19
  *
20
20
  * ```tsx
21
21
  * 'use client'
22
- * import { useNavigationPending } from '@timber-js/app/client'
22
+ * import { usePendingNavigation } from '@timber-js/app/client'
23
23
  *
24
24
  * export function NavBar() {
25
- * const isPending = useNavigationPending()
25
+ * const isPending = usePendingNavigation()
26
26
  * return (
27
27
  * <nav className={isPending ? 'opacity-50' : ''}>
28
28
  * <Link href="/dashboard">Dashboard</Link>
@@ -31,7 +31,7 @@ import { usePendingNavigationUrl } from './navigation-context.js';
31
31
  * }
32
32
  * ```
33
33
  */
34
- export function useNavigationPending(): boolean {
34
+ export function usePendingNavigation(): boolean {
35
35
  const pendingUrl = usePendingNavigationUrl();
36
36
  // During SSR or outside PendingNavigationProvider, no navigation is pending
37
37
  return pendingUrl !== null;
@@ -17,8 +17,8 @@ import type {
17
17
  SearchParamsDefinition,
18
18
  SetParams,
19
19
  QueryStatesOptions,
20
- } from '#/search-params/create.js';
21
- import { getSearchParams } from '#/search-params/registry.js';
20
+ } from '../search-params/define.js';
21
+ import { getSearchParamsDefinition } from '../search-params/registry.js';
22
22
 
23
23
  // ─── Codec Bridge ─────────────────────────────────────────────────
24
24
 
@@ -79,7 +79,7 @@ export function useQueryStates<T extends Record<string, unknown>>(
79
79
  let codecs: { [K in keyof T]: SearchParamCodec<T[K]> };
80
80
  let resolvedUrlKeys = urlKeys;
81
81
  if (typeof codecsOrRoute === 'string') {
82
- const definition = getSearchParams(codecsOrRoute);
82
+ const definition = getSearchParamsDefinition(codecsOrRoute);
83
83
  if (!definition) {
84
84
  throw new Error(
85
85
  `useQueryStates('${codecsOrRoute}'): no search params registered for this route. ` +
@@ -95,8 +95,14 @@ export function useQueryStates<T extends Record<string, unknown>>(
95
95
 
96
96
  const bridged = bridgeCodecs(codecs);
97
97
 
98
+ // Forward hook-level options (shallow, scroll, history) to nuqs.
99
+ // These become the default for all setter calls from this hook instance.
100
+ // Per-call options in setParams(values, opts) override these defaults.
98
101
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
99
102
  const nuqsOptions: any = {};
103
+ if (_options?.shallow !== undefined) nuqsOptions.shallow = _options.shallow;
104
+ if (_options?.scroll !== undefined) nuqsOptions.scroll = _options.scroll;
105
+ if (_options?.history !== undefined) nuqsOptions.history = _options.history;
100
106
  if (resolvedUrlKeys && Object.keys(resolvedUrlKeys).length > 0) {
101
107
  nuqsOptions.urlKeys = resolvedUrlKeys;
102
108
  }
@@ -20,7 +20,7 @@
20
20
  *
21
21
  * For loading UI during navigation, use:
22
22
  * - useLinkStatus() — per-link pending indicator (inside <Link>)
23
- * - useNavigationPending() — global navigation pending state
23
+ * - usePendingNavigation() — global navigation pending state
24
24
  */
25
25
 
26
26
  import { getRouterOrNull } from './router-ref.js';