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

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 (619) 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-ErnB33JX.js} +301 -133
  19. package/dist/_chunks/interception-ErnB33JX.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-shared.d.ts +38 -0
  223. package/dist/routing/codegen-shared.d.ts.map +1 -0
  224. package/dist/routing/codegen-types.d.ts +36 -0
  225. package/dist/routing/codegen-types.d.ts.map +1 -0
  226. package/dist/routing/codegen.d.ts +2 -2
  227. package/dist/routing/codegen.d.ts.map +1 -1
  228. package/dist/routing/convention-lint.d.ts +41 -0
  229. package/dist/routing/convention-lint.d.ts.map +1 -0
  230. package/dist/routing/index.d.ts +2 -0
  231. package/dist/routing/index.d.ts.map +1 -1
  232. package/dist/routing/index.js +3 -2
  233. package/dist/routing/link-codegen.d.ts +90 -0
  234. package/dist/routing/link-codegen.d.ts.map +1 -0
  235. package/dist/routing/scanner.d.ts.map +1 -1
  236. package/dist/routing/segment-classify.d.ts +46 -0
  237. package/dist/routing/segment-classify.d.ts.map +1 -0
  238. package/dist/routing/status-file-lint.d.ts +2 -1
  239. package/dist/routing/status-file-lint.d.ts.map +1 -1
  240. package/dist/routing/types.d.ts +16 -4
  241. package/dist/routing/types.d.ts.map +1 -1
  242. package/dist/rsc-runtime/rsc.d.ts +1 -1
  243. package/dist/rsc-runtime/rsc.d.ts.map +1 -1
  244. package/dist/rsc-runtime/ssr.d.ts +12 -0
  245. package/dist/rsc-runtime/ssr.d.ts.map +1 -1
  246. package/dist/schema-bridge.d.ts +76 -0
  247. package/dist/schema-bridge.d.ts.map +1 -0
  248. package/dist/search-params/define.d.ts +139 -0
  249. package/dist/search-params/define.d.ts.map +1 -0
  250. package/dist/search-params/index.d.ts +4 -7
  251. package/dist/search-params/index.d.ts.map +1 -1
  252. package/dist/search-params/index.js +32 -441
  253. package/dist/search-params/index.js.map +1 -1
  254. package/dist/search-params/registry.d.ts +2 -2
  255. package/dist/search-params/registry.d.ts.map +1 -1
  256. package/dist/search-params/wrappers.d.ts +53 -0
  257. package/dist/search-params/wrappers.d.ts.map +1 -0
  258. package/dist/segment-params/define.d.ts +78 -0
  259. package/dist/segment-params/define.d.ts.map +1 -0
  260. package/dist/segment-params/index.d.ts +3 -0
  261. package/dist/segment-params/index.d.ts.map +1 -0
  262. package/dist/segment-params/index.js +2 -0
  263. package/dist/server/access-gate.d.ts +4 -0
  264. package/dist/server/access-gate.d.ts.map +1 -1
  265. package/dist/server/action-client.d.ts +41 -6
  266. package/dist/server/action-client.d.ts.map +1 -1
  267. package/dist/server/action-encryption.d.ts +76 -0
  268. package/dist/server/action-encryption.d.ts.map +1 -0
  269. package/dist/server/action-handler.d.ts +7 -0
  270. package/dist/server/action-handler.d.ts.map +1 -1
  271. package/dist/server/actions.d.ts +3 -6
  272. package/dist/server/actions.d.ts.map +1 -1
  273. package/dist/server/als-registry.d.ts +32 -4
  274. package/dist/server/als-registry.d.ts.map +1 -1
  275. package/dist/server/build-manifest.d.ts +2 -2
  276. package/dist/server/build-manifest.d.ts.map +1 -1
  277. package/dist/server/debug.d.ts +1 -1
  278. package/dist/server/default-logger.d.ts +22 -0
  279. package/dist/server/default-logger.d.ts.map +1 -0
  280. package/dist/server/deny-page-resolver.d.ts +52 -0
  281. package/dist/server/deny-page-resolver.d.ts.map +1 -0
  282. package/dist/server/deny-renderer.d.ts.map +1 -1
  283. package/dist/server/dev-holding-server.d.ts +52 -0
  284. package/dist/server/dev-holding-server.d.ts.map +1 -0
  285. package/dist/server/dev-source-map.d.ts +22 -0
  286. package/dist/server/dev-source-map.d.ts.map +1 -0
  287. package/dist/server/dev-warnings.d.ts +1 -21
  288. package/dist/server/dev-warnings.d.ts.map +1 -1
  289. package/dist/server/early-hints.d.ts +13 -5
  290. package/dist/server/early-hints.d.ts.map +1 -1
  291. package/dist/server/error-boundary-wrapper.d.ts +7 -1
  292. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  293. package/dist/server/fallback-error.d.ts +12 -7
  294. package/dist/server/fallback-error.d.ts.map +1 -1
  295. package/dist/server/flight-injection-state.d.ts +66 -0
  296. package/dist/server/flight-injection-state.d.ts.map +1 -0
  297. package/dist/server/flight-scripts.d.ts +42 -0
  298. package/dist/server/flight-scripts.d.ts.map +1 -0
  299. package/dist/server/flush.d.ts.map +1 -1
  300. package/dist/server/form-data.d.ts +29 -0
  301. package/dist/server/form-data.d.ts.map +1 -1
  302. package/dist/server/html-injectors.d.ts +51 -11
  303. package/dist/server/html-injectors.d.ts.map +1 -1
  304. package/dist/server/index.d.ts +5 -43
  305. package/dist/server/index.d.ts.map +1 -1
  306. package/dist/server/index.js +195 -2800
  307. package/dist/server/index.js.map +1 -1
  308. package/dist/server/internal.d.ts +46 -0
  309. package/dist/server/internal.d.ts.map +1 -0
  310. package/dist/server/internal.js +2900 -0
  311. package/dist/server/internal.js.map +1 -0
  312. package/dist/server/logger.d.ts +25 -7
  313. package/dist/server/logger.d.ts.map +1 -1
  314. package/dist/server/middleware-runner.d.ts +19 -4
  315. package/dist/server/middleware-runner.d.ts.map +1 -1
  316. package/dist/server/node-stream-transforms.d.ts +113 -0
  317. package/dist/server/node-stream-transforms.d.ts.map +1 -0
  318. package/dist/server/page-deny-boundary.d.ts +31 -0
  319. package/dist/server/page-deny-boundary.d.ts.map +1 -0
  320. package/dist/server/pipeline-interception.d.ts +1 -1
  321. package/dist/server/pipeline-interception.d.ts.map +1 -1
  322. package/dist/server/pipeline-metadata.d.ts +6 -0
  323. package/dist/server/pipeline-metadata.d.ts.map +1 -1
  324. package/dist/server/pipeline.d.ts +52 -10
  325. package/dist/server/pipeline.d.ts.map +1 -1
  326. package/dist/server/primitives.d.ts +69 -18
  327. package/dist/server/primitives.d.ts.map +1 -1
  328. package/dist/server/render-timeout.d.ts +51 -0
  329. package/dist/server/render-timeout.d.ts.map +1 -0
  330. package/dist/server/request-context.d.ts +112 -43
  331. package/dist/server/request-context.d.ts.map +1 -1
  332. package/dist/server/route-element-builder.d.ts +27 -1
  333. package/dist/server/route-element-builder.d.ts.map +1 -1
  334. package/dist/server/route-handler.d.ts.map +1 -1
  335. package/dist/server/route-matcher.d.ts +16 -2
  336. package/dist/server/route-matcher.d.ts.map +1 -1
  337. package/dist/server/rsc-entry/api-handler.d.ts +2 -2
  338. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  339. package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
  340. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  341. package/dist/server/rsc-entry/helpers.d.ts +48 -5
  342. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  343. package/dist/server/rsc-entry/index.d.ts +20 -3
  344. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  345. package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
  346. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  347. package/dist/server/rsc-entry/rsc-stream.d.ts +14 -1
  348. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  349. package/dist/server/rsc-entry/ssr-bridge.d.ts +1 -1
  350. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  351. package/dist/server/rsc-entry/ssr-renderer.d.ts +19 -4
  352. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  353. package/dist/server/safe-load.d.ts +46 -0
  354. package/dist/server/safe-load.d.ts.map +1 -0
  355. package/dist/server/sensitive-fields.d.ts +74 -0
  356. package/dist/server/sensitive-fields.d.ts.map +1 -0
  357. package/dist/server/sitemap-generator.d.ts +129 -0
  358. package/dist/server/sitemap-generator.d.ts.map +1 -0
  359. package/dist/server/sitemap-handler.d.ts +22 -0
  360. package/dist/server/sitemap-handler.d.ts.map +1 -0
  361. package/dist/server/slot-resolver.d.ts +1 -1
  362. package/dist/server/slot-resolver.d.ts.map +1 -1
  363. package/dist/server/ssr-entry.d.ts +23 -0
  364. package/dist/server/ssr-entry.d.ts.map +1 -1
  365. package/dist/server/ssr-render.d.ts +39 -21
  366. package/dist/server/ssr-render.d.ts.map +1 -1
  367. package/dist/server/ssr-wrappers.d.ts +50 -0
  368. package/dist/server/ssr-wrappers.d.ts.map +1 -0
  369. package/dist/server/status-code-resolver.d.ts +1 -1
  370. package/dist/server/status-code-resolver.d.ts.map +1 -1
  371. package/dist/server/stream-utils.d.ts +36 -0
  372. package/dist/server/stream-utils.d.ts.map +1 -0
  373. package/dist/server/tracing.d.ts +4 -4
  374. package/dist/server/tracing.d.ts.map +1 -1
  375. package/dist/server/tree-builder.d.ts +22 -19
  376. package/dist/server/tree-builder.d.ts.map +1 -1
  377. package/dist/server/types.d.ts +1 -4
  378. package/dist/server/types.d.ts.map +1 -1
  379. package/dist/server/version-skew.d.ts +61 -0
  380. package/dist/server/version-skew.d.ts.map +1 -0
  381. package/dist/shared/merge-search-params.d.ts +22 -0
  382. package/dist/shared/merge-search-params.d.ts.map +1 -0
  383. package/dist/shims/font-google.d.ts +1 -1
  384. package/dist/shims/font-google.d.ts.map +1 -1
  385. package/dist/shims/font-google.js +42 -0
  386. package/dist/shims/font-google.js.map +1 -0
  387. package/dist/shims/font-local.d.ts +26 -0
  388. package/dist/shims/font-local.d.ts.map +1 -0
  389. package/dist/shims/font-local.js +20 -0
  390. package/dist/shims/font-local.js.map +1 -0
  391. package/dist/shims/headers.d.ts +2 -1
  392. package/dist/shims/headers.d.ts.map +1 -1
  393. package/dist/shims/navigation-client.d.ts +1 -1
  394. package/dist/shims/navigation-client.d.ts.map +1 -1
  395. package/dist/shims/navigation.d.ts +3 -2
  396. package/dist/shims/navigation.d.ts.map +1 -1
  397. package/dist/utils/directive-parser.d.ts +5 -2
  398. package/dist/utils/directive-parser.d.ts.map +1 -1
  399. package/dist/utils/state-machine.d.ts +80 -0
  400. package/dist/utils/state-machine.d.ts.map +1 -0
  401. package/package.json +51 -16
  402. package/src/adapters/cloudflare-dev.ts +177 -0
  403. package/src/adapters/cloudflare-kv-cache.ts +142 -0
  404. package/src/adapters/cloudflare.ts +342 -28
  405. package/src/adapters/compress-module.ts +24 -4
  406. package/src/adapters/nitro.ts +52 -8
  407. package/src/adapters/wrangler.d.ts +7 -0
  408. package/src/cache/cache-api.ts +38 -0
  409. package/src/cache/handler-store.ts +68 -0
  410. package/src/cache/index.ts +81 -18
  411. package/src/cache/singleflight.ts +62 -4
  412. package/src/cache/sizeof.ts +31 -0
  413. package/src/cache/timber-cache.ts +24 -20
  414. package/src/cli.ts +16 -6
  415. package/src/client/browser-dev.ts +128 -1
  416. package/src/client/browser-entry/action-dispatch.ts +116 -0
  417. package/src/client/browser-entry/hmr.ts +81 -0
  418. package/src/client/browser-entry/hydrate.ts +145 -0
  419. package/src/client/browser-entry/index.ts +143 -0
  420. package/src/client/browser-entry/post-hydration.ts +119 -0
  421. package/src/client/browser-entry/router-init.ts +193 -0
  422. package/src/client/browser-entry/rsc-stream.ts +157 -0
  423. package/src/client/browser-entry/scroll.ts +27 -0
  424. package/src/client/error-boundary.tsx +48 -16
  425. package/src/client/error-reconstituter.tsx +65 -0
  426. package/src/client/form.tsx +14 -7
  427. package/src/client/history.ts +26 -4
  428. package/src/client/index.ts +65 -38
  429. package/src/client/internal.ts +57 -0
  430. package/src/client/link-pending-store.ts +111 -0
  431. package/src/client/link.tsx +342 -113
  432. package/src/client/nav-link-store.ts +47 -0
  433. package/src/client/navigation-api-types.ts +112 -0
  434. package/src/client/navigation-api.ts +332 -0
  435. package/src/client/navigation-context.ts +31 -6
  436. package/src/client/navigation-root.tsx +342 -0
  437. package/src/client/nuqs-adapter.tsx +16 -3
  438. package/src/client/router-ref.ts +1 -1
  439. package/src/client/router.ts +299 -72
  440. package/src/client/rsc-fetch.ts +97 -8
  441. package/src/client/segment-cache.ts +1 -1
  442. package/src/client/segment-outlet.tsx +86 -0
  443. package/src/client/ssr-data.ts +13 -5
  444. package/src/client/stale-reload.ts +72 -3
  445. package/src/client/top-loader.tsx +18 -6
  446. package/src/client/use-link-status.ts +7 -7
  447. package/src/client/use-params.ts +7 -5
  448. package/src/client/{use-navigation-pending.ts → use-pending-navigation.ts} +6 -6
  449. package/src/client/use-query-states.ts +9 -3
  450. package/src/client/use-router.ts +1 -1
  451. package/src/codec.ts +49 -0
  452. package/src/config-types.ts +264 -0
  453. package/src/config-validation.ts +303 -0
  454. package/src/content/index.ts +5 -13
  455. package/src/cookies/define-cookie.ts +78 -25
  456. package/src/cookies/index.ts +8 -0
  457. package/src/fonts/bundle.ts +142 -0
  458. package/src/fonts/css.ts +2 -1
  459. package/src/fonts/dev-middleware.ts +74 -0
  460. package/src/fonts/pipeline.ts +275 -0
  461. package/src/fonts/transform.ts +353 -0
  462. package/src/fonts/types.ts +50 -1
  463. package/src/fonts/virtual-modules.ts +159 -0
  464. package/src/index.ts +314 -355
  465. package/src/plugin-context.ts +240 -0
  466. package/src/plugins/adapter-build.ts +9 -3
  467. package/src/plugins/build-manifest.ts +13 -2
  468. package/src/plugins/build-report.ts +3 -3
  469. package/src/plugins/client-chunks.ts +65 -0
  470. package/src/plugins/content.ts +1 -1
  471. package/src/plugins/dev-404-page.ts +418 -0
  472. package/src/plugins/dev-browser-logs.ts +288 -0
  473. package/src/plugins/dev-error-overlay.ts +286 -42
  474. package/src/plugins/dev-error-page.ts +536 -0
  475. package/src/plugins/dev-logs.ts +1 -1
  476. package/src/plugins/dev-server.ts +146 -19
  477. package/src/plugins/dev-terminal-error.ts +217 -0
  478. package/src/plugins/entries.ts +111 -10
  479. package/src/plugins/fonts.ts +133 -638
  480. package/src/plugins/mdx.ts +1 -1
  481. package/src/plugins/routing.ts +213 -31
  482. package/src/plugins/server-action-exports.ts +1 -1
  483. package/src/plugins/server-bundle.ts +32 -1
  484. package/src/plugins/shims.ts +136 -35
  485. package/src/plugins/static-build.ts +17 -11
  486. package/src/routing/codegen-shared.ts +74 -0
  487. package/src/routing/codegen-types.ts +37 -0
  488. package/src/routing/codegen.ts +112 -173
  489. package/src/routing/convention-lint.ts +356 -0
  490. package/src/routing/index.ts +2 -0
  491. package/src/routing/link-codegen.ts +262 -0
  492. package/src/routing/scanner.ts +93 -23
  493. package/src/routing/segment-classify.ts +89 -0
  494. package/src/routing/status-file-lint.ts +3 -2
  495. package/src/routing/types.ts +17 -4
  496. package/src/rsc-runtime/rsc.ts +2 -0
  497. package/src/rsc-runtime/ssr.ts +50 -0
  498. package/src/rsc-runtime/vendor-types.d.ts +7 -0
  499. package/src/{search-params/codecs.ts → schema-bridge.ts} +57 -20
  500. package/src/search-params/define.ts +482 -0
  501. package/src/search-params/index.ts +14 -20
  502. package/src/search-params/registry.ts +2 -2
  503. package/src/search-params/wrappers.ts +85 -0
  504. package/src/segment-params/define.ts +279 -0
  505. package/src/segment-params/index.ts +9 -0
  506. package/src/server/access-gate.tsx +70 -29
  507. package/src/server/action-client.ts +88 -15
  508. package/src/server/action-encryption.ts +144 -0
  509. package/src/server/action-handler.ts +53 -6
  510. package/src/server/actions.ts +10 -9
  511. package/src/server/als-registry.ts +34 -6
  512. package/src/server/build-manifest.ts +10 -4
  513. package/src/server/compress.ts +25 -7
  514. package/src/server/debug.ts +1 -1
  515. package/src/server/default-logger.ts +99 -0
  516. package/src/server/deny-page-resolver.ts +154 -0
  517. package/src/server/deny-renderer.ts +24 -38
  518. package/src/server/dev-holding-server.ts +185 -0
  519. package/src/server/dev-source-map.ts +31 -0
  520. package/src/server/dev-warnings.ts +4 -49
  521. package/src/server/early-hints.ts +36 -15
  522. package/src/server/error-boundary-wrapper.ts +74 -22
  523. package/src/server/fallback-error.ts +74 -102
  524. package/src/server/flight-injection-state.ts +113 -0
  525. package/src/server/flight-scripts.ts +62 -0
  526. package/src/server/flush.ts +2 -1
  527. package/src/server/form-data.ts +76 -0
  528. package/src/server/html-injectors.ts +280 -120
  529. package/src/server/index.ts +25 -177
  530. package/src/server/internal.ts +169 -0
  531. package/src/server/logger.ts +44 -36
  532. package/src/server/middleware-runner.ts +31 -4
  533. package/src/server/node-stream-transforms.ts +509 -0
  534. package/src/server/page-deny-boundary.tsx +56 -0
  535. package/src/server/pipeline-interception.ts +17 -16
  536. package/src/server/pipeline-metadata.ts +13 -0
  537. package/src/server/pipeline.ts +261 -66
  538. package/src/server/primitives.ts +111 -28
  539. package/src/server/render-timeout.ts +108 -0
  540. package/src/server/request-context.ts +293 -132
  541. package/src/server/route-element-builder.ts +283 -191
  542. package/src/server/route-handler.ts +24 -4
  543. package/src/server/route-matcher.ts +31 -20
  544. package/src/server/rsc-entry/api-handler.ts +15 -16
  545. package/src/server/rsc-entry/error-renderer.ts +305 -89
  546. package/src/server/rsc-entry/helpers.ts +134 -5
  547. package/src/server/rsc-entry/index.ts +304 -111
  548. package/src/server/rsc-entry/rsc-payload.ts +65 -18
  549. package/src/server/rsc-entry/rsc-stream.ts +81 -13
  550. package/src/server/rsc-entry/ssr-bridge.ts +14 -5
  551. package/src/server/rsc-entry/ssr-renderer.ts +171 -38
  552. package/src/server/safe-load.ts +60 -0
  553. package/src/server/sensitive-fields.ts +230 -0
  554. package/src/server/sitemap-generator.ts +338 -0
  555. package/src/server/sitemap-handler.ts +126 -0
  556. package/src/server/slot-resolver.ts +244 -229
  557. package/src/server/ssr-entry.ts +215 -32
  558. package/src/server/ssr-render.ts +289 -67
  559. package/src/server/ssr-wrappers.tsx +139 -0
  560. package/src/server/status-code-resolver.ts +1 -1
  561. package/src/server/stream-utils.ts +213 -0
  562. package/src/server/tracing.ts +20 -9
  563. package/src/server/tree-builder.ts +92 -58
  564. package/src/server/types.ts +3 -6
  565. package/src/server/version-skew.ts +104 -0
  566. package/src/shared/merge-search-params.ts +55 -0
  567. package/src/shims/font-google.ts +1 -1
  568. package/src/shims/font-local.ts +34 -0
  569. package/src/shims/headers.ts +5 -1
  570. package/src/shims/navigation-client.ts +1 -1
  571. package/src/shims/navigation.ts +7 -2
  572. package/src/utils/directive-parser.ts +5 -2
  573. package/src/utils/state-machine.ts +111 -0
  574. package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
  575. package/dist/_chunks/debug-gwlJkDuf.js.map +0 -1
  576. package/dist/_chunks/format-DviM89f0.js.map +0 -1
  577. package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
  578. package/dist/_chunks/request-context-DIkVh_jG.js +0 -330
  579. package/dist/_chunks/request-context-DIkVh_jG.js.map +0 -1
  580. package/dist/_chunks/tracing-CemImE6h.js.map +0 -1
  581. package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
  582. package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
  583. package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
  584. package/dist/cache/register-cached-function.d.ts +0 -17
  585. package/dist/cache/register-cached-function.d.ts.map +0 -1
  586. package/dist/client/browser-entry.d.ts +0 -21
  587. package/dist/client/browser-entry.d.ts.map +0 -1
  588. package/dist/client/link-status-provider.d.ts +0 -11
  589. package/dist/client/link-status-provider.d.ts.map +0 -1
  590. package/dist/client/transition-root.d.ts.map +0 -1
  591. package/dist/client/use-navigation-pending.d.ts.map +0 -1
  592. package/dist/cookies/index.js.map +0 -1
  593. package/dist/plugins/cache-transform.d.ts +0 -36
  594. package/dist/plugins/cache-transform.d.ts.map +0 -1
  595. package/dist/plugins/dynamic-transform.d.ts +0 -72
  596. package/dist/plugins/dynamic-transform.d.ts.map +0 -1
  597. package/dist/search-params/analyze.d.ts +0 -54
  598. package/dist/search-params/analyze.d.ts.map +0 -1
  599. package/dist/search-params/builtin-codecs.d.ts +0 -105
  600. package/dist/search-params/builtin-codecs.d.ts.map +0 -1
  601. package/dist/search-params/codecs.d.ts +0 -53
  602. package/dist/search-params/codecs.d.ts.map +0 -1
  603. package/dist/search-params/create.d.ts +0 -106
  604. package/dist/search-params/create.d.ts.map +0 -1
  605. package/dist/server/prerender.d.ts +0 -77
  606. package/dist/server/prerender.d.ts.map +0 -1
  607. package/dist/server/response-cache.d.ts +0 -54
  608. package/dist/server/response-cache.d.ts.map +0 -1
  609. package/src/cache/register-cached-function.ts +0 -103
  610. package/src/client/browser-entry.ts +0 -678
  611. package/src/client/link-status-provider.tsx +0 -30
  612. package/src/client/transition-root.tsx +0 -166
  613. package/src/plugins/cache-transform.ts +0 -199
  614. package/src/plugins/dynamic-transform.ts +0 -161
  615. package/src/search-params/analyze.ts +0 -192
  616. package/src/search-params/builtin-codecs.ts +0 -228
  617. package/src/search-params/create.ts +0 -321
  618. package/src/server/prerender.ts +0 -139
  619. package/src/server/response-cache.ts +0 -410
@@ -6,9 +6,19 @@ import type { SegmentInfo } from './segment-cache';
6
6
  import { HistoryStack } from './history';
7
7
  import type { HeadElement } from './head';
8
8
  import { setCurrentParams } from './use-params.js';
9
- import { setNavigationState } from './navigation-context.js';
9
+ import {
10
+ setNavigationState,
11
+ getNavigationState,
12
+ type NavigationState,
13
+ } from './navigation-context.js';
10
14
  import { SegmentElementCache, cacheSegmentElements, mergeSegmentTree } from './segment-merger.js';
11
- import { fetchRscPayload, RedirectError } from './rsc-fetch.js';
15
+ import {
16
+ fetchRscPayload,
17
+ RedirectError,
18
+ ServerErrorResponse,
19
+ VersionSkewError,
20
+ } from './rsc-fetch.js';
21
+ import { setHardNavigating } from './navigation-root.js';
12
22
  import type { FetchResult } from './rsc-fetch.js';
13
23
 
14
24
  // ─── Types ───────────────────────────────────────────────────────
@@ -18,6 +28,19 @@ export interface NavigationOptions {
18
28
  scroll?: boolean;
19
29
  /** Use replaceState instead of pushState (replaces current history entry) */
20
30
  replace?: boolean;
31
+ /**
32
+ * @internal AbortSignal from the Navigation API's NavigateEvent.
33
+ * When provided, the signal is linked to the router's per-navigation
34
+ * AbortController so in-flight RSC fetches are cancelled when a new
35
+ * navigation starts.
36
+ */
37
+ _signal?: AbortSignal;
38
+ /**
39
+ * @internal Skip pushState/replaceState — the Navigation API has already
40
+ * updated the URL via event.intercept(). Used for external navigations
41
+ * intercepted by the navigate event handler.
42
+ */
43
+ _skipHistory?: boolean;
21
44
  }
22
45
 
23
46
  /**
@@ -31,8 +54,12 @@ export type RscDecoder = (fetchPromise: Promise<Response>) => unknown;
31
54
  * Function that renders a decoded RSC element tree into the DOM.
32
55
  * In production: reactRoot.render(element).
33
56
  * In tests: a no-op or mock.
57
+ *
58
+ * Receives the current NavigationState explicitly — no temporal
59
+ * coupling with setNavigationState/getNavigationState. The renderer
60
+ * wraps the element in NavigationProvider with this state.
34
61
  */
35
- export type RootRenderer = (element: unknown) => void;
62
+ export type RootRenderer = (element: unknown, navState: NavigationState) => void;
36
63
 
37
64
  /**
38
65
  * Platform dependencies injected for testability. In production these
@@ -64,14 +91,54 @@ export interface RouterDeps {
64
91
  *
65
92
  * The `perform` callback receives a `wrapPayload` function to wrap the
66
93
  * decoded RSC payload with NavigationProvider + NuqsAdapter before
67
- * TransitionRoot sets it as the new element.
94
+ * NavigationRoot sets it as the new element. The `wrapPayload` function
95
+ * receives the NavigationState explicitly — no temporal coupling with
96
+ * getNavigationState().
68
97
  *
69
98
  * If not provided (tests), the router falls back to renderRoot.
70
99
  */
71
100
  navigateTransition?: (
72
101
  pendingUrl: string,
73
- perform: (wrapPayload: (payload: unknown) => unknown) => Promise<unknown>
102
+ perform: (
103
+ wrapPayload: (payload: unknown, navState: NavigationState) => unknown
104
+ ) => Promise<unknown>
74
105
  ) => Promise<void>;
106
+
107
+ /**
108
+ * Whether the Navigation API is active and handling traversals.
109
+ * When true, the popstate handler is a no-op — the Navigation API's
110
+ * navigate event covers back/forward button presses.
111
+ */
112
+ navigationApiActive?: boolean;
113
+
114
+ /**
115
+ * Called around pushState/replaceState to set a flag that prevents
116
+ * the Navigation API's navigate listener from double-handling
117
+ * router-initiated navigations.
118
+ */
119
+ setRouterNavigating?: (value: boolean) => void;
120
+
121
+ /**
122
+ * Save scroll position via the Navigation API's per-entry state.
123
+ * When provided, used instead of history.replaceState for scroll storage.
124
+ */
125
+ saveNavigationEntryScroll?: (scrollY: number) => void;
126
+
127
+ /**
128
+ * Signal that a router-initiated navigation has completed. Resolves the
129
+ * deferred promise that ties the browser's native loading state to the
130
+ * navigation lifecycle. Called in the finally block of navigate/refresh,
131
+ * aligned with when the TopLoader's pendingUrl clears.
132
+ */
133
+ completeRouterNavigation?: () => void;
134
+
135
+ /**
136
+ * Initiate a navigation via the Navigation API (`navigation.navigate()`).
137
+ * Fires the navigate event BEFORE committing the URL, allowing Chrome
138
+ * to show its native loading indicator. Falls back to pushState when
139
+ * unavailable.
140
+ */
141
+ navigationNavigate?: (url: string, replace: boolean) => void;
75
142
  }
76
143
 
77
144
  export interface RouterInstance {
@@ -80,7 +147,7 @@ export interface RouterInstance {
80
147
  /** Full re-render of the current URL — no state tree sent */
81
148
  refresh(): Promise<void>;
82
149
  /** Handle a popstate event (back/forward button). scrollY is read from history.state. */
83
- handlePopState(url: string, scrollY?: number): Promise<void>;
150
+ handlePopState(url: string, scrollY?: number, externalSignal?: AbortSignal): Promise<void>;
84
151
  /** Whether a navigation is currently in flight */
85
152
  isPending(): boolean;
86
153
  /** The URL currently being navigated to, or null if idle */
@@ -130,24 +197,73 @@ function isAbortError(error: unknown): boolean {
130
197
  * Create a router instance. In production, called once at app hydration
131
198
  * with real browser APIs. In tests, called with mock dependencies.
132
199
  */
200
+ /**
201
+ * Router navigation phase — discriminated union replacing scattered
202
+ * `pending` + `pendingUrl` boolean flags.
203
+ *
204
+ * - `idle`: No navigation in flight. The committed params/pathname
205
+ * are current.
206
+ * - `navigating`: A fetch or render is in progress. `targetUrl` is
207
+ * the destination being navigated to.
208
+ */
209
+ export type RouterPhase = { phase: 'idle' } | { phase: 'navigating'; targetUrl: string };
210
+
133
211
  export function createRouter(deps: RouterDeps): RouterInstance {
134
212
  const segmentCache = new SegmentCache();
135
213
  const prefetchCache = new PrefetchCache();
136
214
  const historyStack = new HistoryStack();
137
215
  const segmentElementCache = new SegmentElementCache();
138
216
 
139
- let pending = false;
140
- let pendingUrl: string | null = null;
217
+ let routerPhase: RouterPhase = { phase: 'idle' };
141
218
  const pendingListeners = new Set<(pending: boolean) => void>();
142
219
 
220
+ // AbortController for the current in-flight navigation.
221
+ // When a new navigation starts, the previous controller is aborted,
222
+ // cancelling any in-progress RSC fetch. This provides automatic
223
+ // cancellation of stale fetches regardless of Navigation API support.
224
+ let currentNavAbort: AbortController | null = null;
225
+
226
+ /**
227
+ * Create a new AbortController for a navigation, aborting any
228
+ * previous in-flight navigation. Optionally links to an external
229
+ * signal (e.g., from the Navigation API's NavigateEvent.signal).
230
+ */
231
+ function createNavAbort(externalSignal?: AbortSignal): AbortController {
232
+ // Abort previous navigation's fetch
233
+ currentNavAbort?.abort();
234
+ const controller = new AbortController();
235
+ currentNavAbort = controller;
236
+
237
+ // If an external signal is provided (e.g., Navigation API),
238
+ // forward its abort to our controller.
239
+ if (externalSignal) {
240
+ if (externalSignal.aborted) {
241
+ controller.abort();
242
+ } else {
243
+ externalSignal.addEventListener('abort', () => controller.abort(), { once: true });
244
+ }
245
+ }
246
+
247
+ return controller;
248
+ }
249
+
143
250
  function setPending(value: boolean, url?: string): void {
144
- const newPendingUrl = value && url ? url : null;
145
- if (pending === value && pendingUrl === newPendingUrl) return;
146
- pending = value;
147
- pendingUrl = newPendingUrl;
251
+ const next: RouterPhase =
252
+ value && url ? { phase: 'navigating', targetUrl: url } : { phase: 'idle' };
253
+ // Skip no-op updates
254
+ if (
255
+ routerPhase.phase === next.phase &&
256
+ (routerPhase.phase === 'idle' ||
257
+ (routerPhase.phase === 'navigating' &&
258
+ next.phase === 'navigating' &&
259
+ routerPhase.targetUrl === next.targetUrl))
260
+ ) {
261
+ return;
262
+ }
263
+ routerPhase = next;
148
264
  // Notify external store listeners (non-React consumers).
149
265
  // React-facing pending state is handled by useOptimistic in
150
- // TransitionRoot via navigateTransition — not this function.
266
+ // NavigationRoot via navigateTransition — not this function.
151
267
  for (const listener of pendingListeners) {
152
268
  listener(value);
153
269
  }
@@ -163,9 +279,9 @@ export function createRouter(deps: RouterDeps): RouterInstance {
163
279
  }
164
280
 
165
281
  /** Render a decoded RSC payload into the DOM if a renderer is available. */
166
- function renderPayload(payload: unknown): void {
282
+ function renderPayload(payload: unknown, navState: NavigationState): void {
167
283
  if (deps.renderRoot) {
168
- deps.renderRoot(payload);
284
+ deps.renderRoot(payload, navState);
169
285
  }
170
286
  }
171
287
 
@@ -194,32 +310,34 @@ export function createRouter(deps: RouterDeps): RouterInstance {
194
310
  /**
195
311
  * Update navigation state (params + pathname) for the next render.
196
312
  *
197
- * Sets both the module-level fallback (for tests and SSR) and the
198
- * navigation context state (read by renderRoot to wrap the element
199
- * in NavigationProvider). The context update is atomic with the tree
200
- * render both are passed to reactRoot.render() in the same call.
313
+ * Sets the module-level fallback (for tests and SSR) and the
314
+ * globalThis bridge, then returns the NavigationState so callers
315
+ * can pass it explicitly to renderRoot/wrapPayload eliminating
316
+ * temporal coupling with getNavigationState().
201
317
  */
202
318
  function updateNavigationState(
203
319
  params: Record<string, string | string[]> | null | undefined,
204
320
  url: string
205
- ): void {
321
+ ): NavigationState {
206
322
  const resolvedParams = params ?? {};
207
323
  // Module-level fallback for tests (no NavigationProvider) and SSR
208
324
  setCurrentParams(resolvedParams);
209
- // Navigation contextread by renderRoot to wrap the RSC element
325
+ // globalThis bridgekept for backward compat
210
326
  const pathname = url.startsWith('http') ? new URL(url).pathname : url.split('?')[0] || '/';
211
- setNavigationState({ params: resolvedParams, pathname });
327
+ const navState: NavigationState = { params: resolvedParams, pathname };
328
+ setNavigationState(navState);
329
+ return navState;
212
330
  }
213
331
 
214
332
  /**
215
333
  * Render a payload via navigateTransition (production) or renderRoot (tests).
216
- * The perform callback should fetch data, update state, and return the payload.
217
- * In production, the entire callback runs inside a React transition with
218
- * useOptimistic for the pending URL. In tests, the payload is rendered directly.
334
+ * The perform callback should fetch data, update state, and return the
335
+ * FetchResult plus the NavigationState (so it can be passed explicitly
336
+ * to wrapPayload/renderRoot without temporal coupling).
219
337
  */
220
338
  async function renderViaTransition(
221
339
  url: string,
222
- perform: () => Promise<FetchResult>
340
+ perform: () => Promise<FetchResult & { navState: NavigationState }>
223
341
  ): Promise<HeadElement[] | null> {
224
342
  if (deps.navigateTransition) {
225
343
  let headElements: HeadElement[] | null = null;
@@ -235,7 +353,9 @@ export function createRouter(deps: RouterDeps): RouterInstance {
235
353
  headElements: result.headElements,
236
354
  params: result.params,
237
355
  });
238
- return wrapPayload(merged);
356
+ // Pass navState explicitly — wrapPayload wraps element in
357
+ // NavigationProvider with this state, no getNavigationState() needed.
358
+ return wrapPayload(merged, result.navState);
239
359
  });
240
360
  return headElements;
241
361
  }
@@ -249,7 +369,7 @@ export function createRouter(deps: RouterDeps): RouterInstance {
249
369
  headElements: result.headElements,
250
370
  params: result.params,
251
371
  });
252
- renderPayload(merged);
372
+ renderPayload(merged, result.navState);
253
373
  return result.headElements;
254
374
  }
255
375
 
@@ -269,14 +389,25 @@ export function createRouter(deps: RouterDeps): RouterInstance {
269
389
  }
270
390
  }
271
391
 
392
+ /**
393
+ * Schedule scroll restoration after the next paint and fire the
394
+ * scroll-restored event. Used by navigate, popstate, and refresh.
395
+ */
396
+ function restoreScrollAfterPaint(scrollY: number): void {
397
+ afterPaint(() => {
398
+ deps.scrollTo(0, scrollY);
399
+ window.dispatchEvent(new Event('timber:scroll-restored'));
400
+ });
401
+ }
402
+
272
403
  /**
273
404
  * Core navigation logic shared between the transition and fallback paths.
274
405
  * Fetches the RSC payload, updates all state, and returns the result.
275
406
  */
276
407
  async function performNavigationFetch(
277
408
  url: string,
278
- options: { replace: boolean }
279
- ): Promise<FetchResult> {
409
+ options: { replace: boolean; signal?: AbortSignal; skipHistory?: boolean }
410
+ ): Promise<FetchResult & { navState: NavigationState }> {
280
411
  // Check prefetch cache first. PrefetchResult has optional segmentInfo/params
281
412
  // fields — normalize to null for FetchResult compatibility.
282
413
  const prefetched = prefetchCache.consume(url);
@@ -298,14 +429,21 @@ export function createRouter(deps: RouterDeps): RouterInstance {
298
429
  const currentUrl = rawCurrentUrl.startsWith('http')
299
430
  ? new URL(rawCurrentUrl).pathname
300
431
  : new URL(rawCurrentUrl, 'http://localhost').pathname;
301
- result = await fetchRscPayload(url, deps, stateTree, currentUrl);
432
+ result = await fetchRscPayload(url, deps, stateTree, currentUrl, options.signal);
302
433
  }
303
434
 
304
- // Update the browser history — replace mode overwrites the current entry
305
- if (options.replace) {
306
- deps.replaceState({ timber: true, scrollY: 0 }, '', url);
307
- } else {
308
- deps.pushState({ timber: true, scrollY: 0 }, '', url);
435
+ // Update the browser history — skip when the Navigation API has already
436
+ // updated the URL via event.intercept() (external navigations).
437
+ if (!options.skipHistory) {
438
+ // Set the router-navigating flag so the Navigation API's navigate
439
+ // listener doesn't double-intercept this pushState/replaceState.
440
+ deps.setRouterNavigating?.(true);
441
+ if (options.replace) {
442
+ deps.replaceState({ timber: true, scrollY: 0 }, '', url);
443
+ } else {
444
+ deps.pushState({ timber: true, scrollY: 0 }, '', url);
445
+ }
446
+ deps.setRouterNavigating?.(false);
309
447
  }
310
448
 
311
449
  // NOTE: History push is deferred — the merged payload (after segment
@@ -316,29 +454,57 @@ export function createRouter(deps: RouterDeps): RouterInstance {
316
454
  // Update the segment cache with the new route's segment tree.
317
455
  updateSegmentCache(result.segmentInfo);
318
456
 
319
- // Update navigation state (params + pathname) before rendering.
320
- updateNavigationState(result.params, url);
457
+ // Update navigation state and capture it for explicit passing.
458
+ const navState = updateNavigationState(result.params, url);
321
459
 
322
- return result;
460
+ return { ...result, navState };
323
461
  }
324
462
 
325
463
  async function navigate(url: string, options: NavigationOptions = {}): Promise<void> {
326
464
  const scroll = options.scroll !== false;
327
465
  const replace = options.replace === true;
466
+ const externalSignal = options._signal as AbortSignal | undefined;
467
+ const skipHistory = options._skipHistory === true;
468
+
469
+ // Create an abort controller for this navigation. Links to the external
470
+ // signal (Navigation API's event.signal) when provided.
471
+ const navAbort = createNavAbort(externalSignal);
328
472
 
329
473
  // Capture the departing page's scroll position for scroll={false} preservation.
330
474
  const currentScrollY = deps.getScrollY();
331
475
 
332
- // Save the departing page's scroll position in history.state before
333
- // pushing a new entry. This ensures back/forward navigation can restore
334
- // the correct scroll position from the browser's per-entry state.
335
- deps.replaceState({ timber: true, scrollY: currentScrollY }, '', deps.getCurrentUrl());
476
+ // Save the departing page's scroll position use Navigation API entry
477
+ // state when available, otherwise fall back to history.state.
478
+ if (deps.saveNavigationEntryScroll) {
479
+ deps.saveNavigationEntryScroll(currentScrollY);
480
+ } else {
481
+ deps.replaceState({ timber: true, scrollY: currentScrollY }, '', deps.getCurrentUrl());
482
+ }
483
+
484
+ // When Navigation API is active, initiate the navigation via
485
+ // navigation.navigate() BEFORE the fetch. Unlike history.pushState()
486
+ // which commits the URL synchronously (so Chrome sees it as "done"),
487
+ // navigation.navigate() fires the navigate event before committing.
488
+ // Our handler intercepts with a deferred promise, and Chrome shows
489
+ // its native loading indicator until completeRouterNavigation()
490
+ // resolves it in the finally block (same time as TopLoader clears).
491
+ let effectiveSkipHistory = skipHistory;
492
+ if (!skipHistory && deps.navigationNavigate) {
493
+ deps.setRouterNavigating?.(true);
494
+ deps.navigationNavigate(url, replace);
495
+ deps.setRouterNavigating?.(false);
496
+ effectiveSkipHistory = true;
497
+ }
336
498
 
337
499
  setPending(true, url);
338
500
 
339
501
  try {
340
502
  const headElements = await renderViaTransition(url, () =>
341
- performNavigationFetch(url, { replace })
503
+ performNavigationFetch(url, {
504
+ replace,
505
+ signal: navAbort.signal,
506
+ skipHistory: effectiveSkipHistory,
507
+ })
342
508
  );
343
509
 
344
510
  // Update document.title and <meta> tags with the new page's metadata
@@ -350,51 +516,105 @@ export function createRouter(deps: RouterDeps): RouterInstance {
350
516
  // Scroll-to-top on forward navigation, or restore captured position
351
517
  // for scroll={false}. React's render() on the document root can reset
352
518
  // scroll during DOM reconciliation, so all scroll must be actively managed.
353
- afterPaint(() => {
354
- if (scroll) {
355
- deps.scrollTo(0, 0);
356
- } else {
357
- deps.scrollTo(0, currentScrollY);
358
- }
359
- window.dispatchEvent(new Event('timber:scroll-restored'));
360
- });
519
+ restoreScrollAfterPaint(scroll ? 0 : currentScrollY);
361
520
  } catch (error) {
521
+ // Version skew — server has been redeployed. Trigger full page reload
522
+ // so the browser fetches the new bundle. See TIM-446.
523
+ // Set hard-navigating flag to prevent Navigation API interception
524
+ // and React from rendering during page teardown. See TIM-626.
525
+ if (error instanceof VersionSkewError) {
526
+ setHardNavigating(true);
527
+ // Import triggerStaleReload dynamically to avoid circular deps
528
+ // and keep the reload logic centralized with its loop guard.
529
+ const { triggerStaleReload } = await import('./stale-reload.js');
530
+ triggerStaleReload();
531
+ // Return a never-resolving promise — page is reloading.
532
+ return new Promise(() => {}) as never;
533
+ }
362
534
  // Server-side redirect during RSC fetch → soft router navigation.
535
+ // The redirect navigate will push/replace its own URL.
363
536
  if (error instanceof RedirectError) {
364
537
  setPending(false);
538
+ deps.completeRouterNavigation?.();
365
539
  await navigate(error.redirectUrl, { replace: true });
366
540
  return;
367
541
  }
542
+ // Server 5xx error — hard-navigate so the server renders the
543
+ // error page as HTML. See design/10-error-handling.md
544
+ // §"Error Page Rendering for Client Navigation".
545
+ //
546
+ // Set hard-navigating flag BEFORE setting window.location.href:
547
+ // 1. Prevents Navigation API from intercepting → infinite loop
548
+ // 2. Causes NavigationRoot to throw unresolvedThenable → prevents
549
+ // React from rendering children during page teardown (avoids
550
+ // "Rendered more hooks" crashes). See TIM-626.
551
+ if (error instanceof ServerErrorResponse) {
552
+ setHardNavigating(true);
553
+ window.location.href = error.url;
554
+ return new Promise(() => {}) as never;
555
+ }
368
556
  // Abort errors are not application errors — swallow silently.
369
557
  if (isAbortError(error)) return;
370
558
  throw error;
371
559
  } finally {
560
+ // Clear the abort controller so we don't abort a completed navigation
561
+ // when the next one starts. In dev mode, the RSC body stream stays
562
+ // open after data arrives (React's Flight client waits for debug rows).
563
+ // Aborting a "completed" navigation kills the open stream reader →
564
+ // "BodyStreamBuffer was aborted". By clearing the controller here,
565
+ // createNavAbort() becomes a no-op for completed navigations.
566
+ if (currentNavAbort === navAbort) {
567
+ currentNavAbort = null;
568
+ }
372
569
  setPending(false);
570
+ // Resolve the Navigation API deferred — clears the browser's native
571
+ // loading state (tab spinner) at the same time as the TopLoader.
572
+ deps.completeRouterNavigation?.();
373
573
  }
374
574
  }
375
575
 
376
576
  async function refresh(): Promise<void> {
377
577
  const currentUrl = deps.getCurrentUrl();
578
+ const navAbort = createNavAbort();
378
579
 
379
580
  setPending(true, currentUrl);
380
581
 
381
582
  try {
382
583
  const headElements = await renderViaTransition(currentUrl, async () => {
383
584
  // No state tree sent — server renders the complete RSC payload
384
- const result = await fetchRscPayload(currentUrl, deps);
585
+ const result = await fetchRscPayload(
586
+ currentUrl,
587
+ deps,
588
+ undefined,
589
+ undefined,
590
+ navAbort.signal
591
+ );
385
592
  // History push handled by renderViaTransition (stores merged payload)
386
593
  updateSegmentCache(result.segmentInfo);
387
- updateNavigationState(result.params, currentUrl);
388
- return result;
594
+ const navState = updateNavigationState(result.params, currentUrl);
595
+ return { ...result, navState };
389
596
  });
390
597
 
391
598
  applyHead(headElements);
599
+ } catch (error) {
600
+ // Stale transition (superseded by a newer navigation) or aborted
601
+ // fetch — silently ignore. See TIM-629.
602
+ if (isAbortError(error)) return;
603
+ throw error;
392
604
  } finally {
605
+ if (currentNavAbort === navAbort) {
606
+ currentNavAbort = null;
607
+ }
393
608
  setPending(false);
609
+ deps.completeRouterNavigation?.();
394
610
  }
395
611
  }
396
612
 
397
- async function handlePopState(url: string, scrollY: number = 0): Promise<void> {
613
+ async function handlePopState(
614
+ url: string,
615
+ scrollY: number = 0,
616
+ externalSignal?: AbortSignal
617
+ ): Promise<void> {
398
618
  // Scroll position is read from history.state by the caller (browser-entry.ts)
399
619
  // and passed in. This is more reliable than tracking scroll per-URL in memory
400
620
  // because the browser maintains per-entry state even with duplicate URLs.
@@ -402,37 +622,40 @@ export function createRouter(deps: RouterDeps): RouterInstance {
402
622
 
403
623
  if (entry && entry.payload !== null) {
404
624
  // Replay cached payload — no server roundtrip
405
- updateNavigationState(entry.params, url);
406
- renderPayload(entry.payload);
625
+ const navState = updateNavigationState(entry.params, url);
626
+ renderPayload(entry.payload, navState);
407
627
  applyHead(entry.headElements);
408
- afterPaint(() => {
409
- deps.scrollTo(0, scrollY);
410
- window.dispatchEvent(new Event('timber:scroll-restored'));
411
- });
628
+ restoreScrollAfterPaint(scrollY);
412
629
  } else {
413
630
  // No cached payload — fetch from server.
414
631
  // This happens when navigating back to the initial SSR'd page
415
632
  // (its payload is null since it was rendered via SSR, not RSC fetch)
416
633
  // or when the entry doesn't exist at all.
634
+ const navAbort = createNavAbort(externalSignal);
417
635
  setPending(true, url);
418
636
  try {
419
637
  const headElements = await renderViaTransition(url, async () => {
420
638
  const stateTree = segmentCache.serializeStateTree(
421
639
  segmentElementCache.getMergeablePaths()
422
640
  );
423
- const result = await fetchRscPayload(url, deps, stateTree);
641
+ const result = await fetchRscPayload(url, deps, stateTree, undefined, navAbort.signal);
424
642
  updateSegmentCache(result.segmentInfo);
425
- updateNavigationState(result.params, url);
643
+ const navState = updateNavigationState(result.params, url);
426
644
  // History push handled by renderViaTransition (stores merged payload)
427
- return result;
645
+ return { ...result, navState };
428
646
  });
429
647
 
430
648
  applyHead(headElements);
431
- afterPaint(() => {
432
- deps.scrollTo(0, scrollY);
433
- window.dispatchEvent(new Event('timber:scroll-restored'));
434
- });
649
+ restoreScrollAfterPaint(scrollY);
650
+ } catch (error) {
651
+ // Stale transition (superseded by a newer navigation) or aborted
652
+ // fetch — silently ignore. See TIM-629.
653
+ if (isAbortError(error)) return;
654
+ throw error;
435
655
  } finally {
656
+ if (currentNavAbort === navAbort) {
657
+ currentNavAbort = null;
658
+ }
436
659
  setPending(false);
437
660
  }
438
661
  }
@@ -463,8 +686,8 @@ export function createRouter(deps: RouterDeps): RouterInstance {
463
686
  navigate,
464
687
  refresh,
465
688
  handlePopState,
466
- isPending: () => pending,
467
- getPendingUrl: () => pendingUrl,
689
+ isPending: () => routerPhase.phase === 'navigating',
690
+ getPendingUrl: () => (routerPhase.phase === 'navigating' ? routerPhase.targetUrl : null),
468
691
  onPendingChange(listener) {
469
692
  pendingListeners.add(listener);
470
693
  return () => pendingListeners.delete(listener);
@@ -481,7 +704,11 @@ export function createRouter(deps: RouterDeps): RouterInstance {
481
704
  payload: merged,
482
705
  headElements,
483
706
  });
484
- renderPayload(merged);
707
+ // Revalidation doesn't change params/pathname — preserve current state.
708
+ // DO NOT call updateNavigationState(null, ...) here: that normalizes
709
+ // params to {}, clearing dynamic route params on every action response.
710
+ const navState = getNavigationState();
711
+ renderPayload(merged, navState);
485
712
  applyHead(headElements);
486
713
  },
487
714
  initSegmentCache: (segments: SegmentInfo[]) => updateSegmentCache(segments),