@timber-js/app 0.2.0-alpha.6 → 0.2.0-alpha.61

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 (406) hide show
  1. package/LICENSE +8 -0
  2. package/dist/_chunks/{als-registry-B7DbZ2hS.js → als-registry-Ba7URUIn.js} +1 -1
  3. package/dist/_chunks/als-registry-Ba7URUIn.js.map +1 -0
  4. package/dist/_chunks/chunk-DYhsFzuS.js +33 -0
  5. package/dist/_chunks/{debug-gwlJkDuf.js → debug-ECi_61pb.js} +2 -2
  6. package/dist/_chunks/debug-ECi_61pb.js.map +1 -0
  7. package/dist/_chunks/define-CT98cU9c.js +121 -0
  8. package/dist/_chunks/define-CT98cU9c.js.map +1 -0
  9. package/dist/_chunks/define-TK8C1M3x.js +279 -0
  10. package/dist/_chunks/define-TK8C1M3x.js.map +1 -0
  11. package/dist/_chunks/define-cookie-BWr_52kY.js +93 -0
  12. package/dist/_chunks/define-cookie-BWr_52kY.js.map +1 -0
  13. package/dist/_chunks/error-boundary-DpZJBCqh.js +211 -0
  14. package/dist/_chunks/error-boundary-DpZJBCqh.js.map +1 -0
  15. package/dist/_chunks/{format-DviM89f0.js → format-cX7wzEp2.js} +2 -2
  16. package/dist/_chunks/{format-DviM89f0.js.map → format-cX7wzEp2.js.map} +1 -1
  17. package/dist/_chunks/{interception-BOoWmLUA.js → interception-Cey5DCGr.js} +129 -77
  18. package/dist/_chunks/interception-Cey5DCGr.js.map +1 -0
  19. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → metadata-routes-BU684ls2.js} +1 -1
  20. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js.map → metadata-routes-BU684ls2.js.map} +1 -1
  21. package/dist/_chunks/{request-context-DIkVh_jG.js → request-context-rju2rbga.js} +97 -69
  22. package/dist/_chunks/request-context-rju2rbga.js.map +1 -0
  23. package/dist/_chunks/segment-context-CyaM1mrD.js +72 -0
  24. package/dist/_chunks/segment-context-CyaM1mrD.js.map +1 -0
  25. package/dist/_chunks/stale-reload-BSSym1MJ.js +64 -0
  26. package/dist/_chunks/stale-reload-BSSym1MJ.js.map +1 -0
  27. package/dist/_chunks/{tracing-Cwn7697K.js → tracing-VYETCQsg.js} +17 -3
  28. package/dist/_chunks/{tracing-Cwn7697K.js.map → tracing-VYETCQsg.js.map} +1 -1
  29. package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-wEXY2JQB.js} +1 -1
  30. package/dist/_chunks/use-query-states-wEXY2JQB.js.map +1 -0
  31. package/dist/_chunks/wrappers-BaG1bnM3.js +63 -0
  32. package/dist/_chunks/wrappers-BaG1bnM3.js.map +1 -0
  33. package/dist/adapters/compress-module.d.ts.map +1 -1
  34. package/dist/adapters/nitro.d.ts +17 -1
  35. package/dist/adapters/nitro.d.ts.map +1 -1
  36. package/dist/adapters/nitro.js +56 -13
  37. package/dist/adapters/nitro.js.map +1 -1
  38. package/dist/cache/fast-hash.d.ts +22 -0
  39. package/dist/cache/fast-hash.d.ts.map +1 -0
  40. package/dist/cache/index.d.ts +5 -2
  41. package/dist/cache/index.d.ts.map +1 -1
  42. package/dist/cache/index.js +90 -20
  43. package/dist/cache/index.js.map +1 -1
  44. package/dist/cache/register-cached-function.d.ts.map +1 -1
  45. package/dist/cache/singleflight.d.ts +18 -1
  46. package/dist/cache/singleflight.d.ts.map +1 -1
  47. package/dist/cache/timber-cache.d.ts +1 -1
  48. package/dist/cache/timber-cache.d.ts.map +1 -1
  49. package/dist/client/error-boundary.d.ts +10 -1
  50. package/dist/client/error-boundary.d.ts.map +1 -1
  51. package/dist/client/error-boundary.js +1 -125
  52. package/dist/client/error-reconstituter.d.ts +54 -0
  53. package/dist/client/error-reconstituter.d.ts.map +1 -0
  54. package/dist/client/form.d.ts +2 -2
  55. package/dist/client/form.d.ts.map +1 -1
  56. package/dist/client/index.d.ts +3 -2
  57. package/dist/client/index.d.ts.map +1 -1
  58. package/dist/client/index.js +433 -252
  59. package/dist/client/index.js.map +1 -1
  60. package/dist/client/link-pending-store.d.ts +78 -0
  61. package/dist/client/link-pending-store.d.ts.map +1 -0
  62. package/dist/client/link.d.ts +23 -9
  63. package/dist/client/link.d.ts.map +1 -1
  64. package/dist/client/navigation-context.d.ts +2 -2
  65. package/dist/client/navigation-context.d.ts.map +1 -1
  66. package/dist/client/router.d.ts +25 -3
  67. package/dist/client/router.d.ts.map +1 -1
  68. package/dist/client/rsc-fetch.d.ts +36 -2
  69. package/dist/client/rsc-fetch.d.ts.map +1 -1
  70. package/dist/client/segment-cache.d.ts +1 -1
  71. package/dist/client/segment-cache.d.ts.map +1 -1
  72. package/dist/client/segment-context.d.ts +1 -1
  73. package/dist/client/segment-context.d.ts.map +1 -1
  74. package/dist/client/segment-merger.d.ts.map +1 -1
  75. package/dist/client/segment-outlet.d.ts +63 -0
  76. package/dist/client/segment-outlet.d.ts.map +1 -0
  77. package/dist/client/stale-reload.d.ts +15 -0
  78. package/dist/client/stale-reload.d.ts.map +1 -1
  79. package/dist/client/top-loader.d.ts +1 -1
  80. package/dist/client/top-loader.d.ts.map +1 -1
  81. package/dist/client/transition-root.d.ts +1 -1
  82. package/dist/client/transition-root.d.ts.map +1 -1
  83. package/dist/client/use-params.d.ts +3 -3
  84. package/dist/client/use-params.d.ts.map +1 -1
  85. package/dist/client/use-query-states.d.ts +1 -1
  86. package/dist/client/use-query-states.d.ts.map +1 -1
  87. package/dist/codec.d.ts +21 -0
  88. package/dist/codec.d.ts.map +1 -0
  89. package/dist/cookies/define-cookie.d.ts +34 -13
  90. package/dist/cookies/define-cookie.d.ts.map +1 -1
  91. package/dist/cookies/index.js +1 -83
  92. package/dist/fonts/css.d.ts +1 -0
  93. package/dist/fonts/css.d.ts.map +1 -1
  94. package/dist/index.d.ts +127 -35
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js +665 -242
  97. package/dist/index.js.map +1 -1
  98. package/dist/params/define.d.ts +100 -0
  99. package/dist/params/define.d.ts.map +1 -0
  100. package/dist/params/index.d.ts +8 -0
  101. package/dist/params/index.d.ts.map +1 -0
  102. package/dist/params/index.js +4 -0
  103. package/dist/plugins/adapter-build.d.ts +1 -1
  104. package/dist/plugins/adapter-build.d.ts.map +1 -1
  105. package/dist/plugins/build-manifest.d.ts +2 -2
  106. package/dist/plugins/build-manifest.d.ts.map +1 -1
  107. package/dist/plugins/build-report.d.ts +3 -3
  108. package/dist/plugins/build-report.d.ts.map +1 -1
  109. package/dist/plugins/client-chunks.d.ts +32 -0
  110. package/dist/plugins/client-chunks.d.ts.map +1 -0
  111. package/dist/plugins/content.d.ts +1 -1
  112. package/dist/plugins/content.d.ts.map +1 -1
  113. package/dist/plugins/dev-browser-logs.d.ts +84 -0
  114. package/dist/plugins/dev-browser-logs.d.ts.map +1 -0
  115. package/dist/plugins/dev-error-overlay.d.ts +26 -1
  116. package/dist/plugins/dev-error-overlay.d.ts.map +1 -1
  117. package/dist/plugins/dev-logs.d.ts +1 -1
  118. package/dist/plugins/dev-logs.d.ts.map +1 -1
  119. package/dist/plugins/dev-server.d.ts +1 -1
  120. package/dist/plugins/dev-server.d.ts.map +1 -1
  121. package/dist/plugins/entries.d.ts +1 -1
  122. package/dist/plugins/entries.d.ts.map +1 -1
  123. package/dist/plugins/fonts.d.ts +9 -2
  124. package/dist/plugins/fonts.d.ts.map +1 -1
  125. package/dist/plugins/mdx.d.ts +1 -1
  126. package/dist/plugins/mdx.d.ts.map +1 -1
  127. package/dist/plugins/routing.d.ts +1 -1
  128. package/dist/plugins/routing.d.ts.map +1 -1
  129. package/dist/plugins/server-bundle.d.ts.map +1 -1
  130. package/dist/plugins/shims.d.ts +6 -5
  131. package/dist/plugins/shims.d.ts.map +1 -1
  132. package/dist/plugins/static-build.d.ts +1 -1
  133. package/dist/plugins/static-build.d.ts.map +1 -1
  134. package/dist/routing/codegen.d.ts +2 -2
  135. package/dist/routing/codegen.d.ts.map +1 -1
  136. package/dist/routing/index.js +1 -1
  137. package/dist/routing/scanner.d.ts.map +1 -1
  138. package/dist/routing/status-file-lint.d.ts +2 -1
  139. package/dist/routing/status-file-lint.d.ts.map +1 -1
  140. package/dist/routing/types.d.ts +16 -4
  141. package/dist/routing/types.d.ts.map +1 -1
  142. package/dist/rsc-runtime/rsc.d.ts +1 -1
  143. package/dist/rsc-runtime/rsc.d.ts.map +1 -1
  144. package/dist/rsc-runtime/ssr.d.ts +12 -0
  145. package/dist/rsc-runtime/ssr.d.ts.map +1 -1
  146. package/dist/search-params/codecs.d.ts +1 -1
  147. package/dist/search-params/define.d.ts +159 -0
  148. package/dist/search-params/define.d.ts.map +1 -0
  149. package/dist/search-params/index.d.ts +4 -5
  150. package/dist/search-params/index.d.ts.map +1 -1
  151. package/dist/search-params/index.js +4 -474
  152. package/dist/search-params/registry.d.ts +1 -1
  153. package/dist/search-params/wrappers.d.ts +53 -0
  154. package/dist/search-params/wrappers.d.ts.map +1 -0
  155. package/dist/server/access-gate.d.ts +4 -0
  156. package/dist/server/access-gate.d.ts.map +1 -1
  157. package/dist/server/action-client.d.ts.map +1 -1
  158. package/dist/server/action-encryption.d.ts +76 -0
  159. package/dist/server/action-encryption.d.ts.map +1 -0
  160. package/dist/server/action-handler.d.ts.map +1 -1
  161. package/dist/server/actions.d.ts +1 -1
  162. package/dist/server/actions.d.ts.map +1 -1
  163. package/dist/server/als-registry.d.ts +25 -4
  164. package/dist/server/als-registry.d.ts.map +1 -1
  165. package/dist/server/build-manifest.d.ts +2 -2
  166. package/dist/server/build-manifest.d.ts.map +1 -1
  167. package/dist/server/debug.d.ts +1 -1
  168. package/dist/server/default-logger.d.ts +22 -0
  169. package/dist/server/default-logger.d.ts.map +1 -0
  170. package/dist/server/deny-renderer.d.ts.map +1 -1
  171. package/dist/server/early-hints.d.ts +13 -5
  172. package/dist/server/early-hints.d.ts.map +1 -1
  173. package/dist/server/error-boundary-wrapper.d.ts +4 -0
  174. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  175. package/dist/server/fallback-error.d.ts +4 -3
  176. package/dist/server/fallback-error.d.ts.map +1 -1
  177. package/dist/server/flight-injection-state.d.ts +66 -0
  178. package/dist/server/flight-injection-state.d.ts.map +1 -0
  179. package/dist/server/flight-scripts.d.ts +42 -0
  180. package/dist/server/flight-scripts.d.ts.map +1 -0
  181. package/dist/server/flush.d.ts.map +1 -1
  182. package/dist/server/form-data.d.ts +29 -0
  183. package/dist/server/form-data.d.ts.map +1 -1
  184. package/dist/server/html-injectors.d.ts +51 -11
  185. package/dist/server/html-injectors.d.ts.map +1 -1
  186. package/dist/server/index.d.ts +4 -2
  187. package/dist/server/index.d.ts.map +1 -1
  188. package/dist/server/index.js +1977 -1648
  189. package/dist/server/index.js.map +1 -1
  190. package/dist/server/logger.d.ts +25 -7
  191. package/dist/server/logger.d.ts.map +1 -1
  192. package/dist/server/node-stream-transforms.d.ts +113 -0
  193. package/dist/server/node-stream-transforms.d.ts.map +1 -0
  194. package/dist/server/pipeline-interception.d.ts +1 -1
  195. package/dist/server/pipeline-interception.d.ts.map +1 -1
  196. package/dist/server/pipeline.d.ts +20 -6
  197. package/dist/server/pipeline.d.ts.map +1 -1
  198. package/dist/server/primitives.d.ts +30 -3
  199. package/dist/server/primitives.d.ts.map +1 -1
  200. package/dist/server/render-timeout.d.ts +51 -0
  201. package/dist/server/render-timeout.d.ts.map +1 -0
  202. package/dist/server/request-context.d.ts +65 -38
  203. package/dist/server/request-context.d.ts.map +1 -1
  204. package/dist/server/route-element-builder.d.ts +7 -0
  205. package/dist/server/route-element-builder.d.ts.map +1 -1
  206. package/dist/server/route-handler.d.ts.map +1 -1
  207. package/dist/server/route-matcher.d.ts +9 -2
  208. package/dist/server/route-matcher.d.ts.map +1 -1
  209. package/dist/server/rsc-entry/api-handler.d.ts +2 -2
  210. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  211. package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
  212. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  213. package/dist/server/rsc-entry/helpers.d.ts +48 -5
  214. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  215. package/dist/server/rsc-entry/index.d.ts +8 -3
  216. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  217. package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
  218. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  219. package/dist/server/rsc-entry/rsc-stream.d.ts +10 -1
  220. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  221. package/dist/server/rsc-entry/ssr-bridge.d.ts +1 -1
  222. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  223. package/dist/server/rsc-entry/ssr-renderer.d.ts +19 -4
  224. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  225. package/dist/server/slot-resolver.d.ts +1 -1
  226. package/dist/server/slot-resolver.d.ts.map +1 -1
  227. package/dist/server/ssr-entry.d.ts +22 -0
  228. package/dist/server/ssr-entry.d.ts.map +1 -1
  229. package/dist/server/ssr-render.d.ts +39 -21
  230. package/dist/server/ssr-render.d.ts.map +1 -1
  231. package/dist/server/ssr-wrappers.d.ts +50 -0
  232. package/dist/server/ssr-wrappers.d.ts.map +1 -0
  233. package/dist/server/status-code-resolver.d.ts +1 -1
  234. package/dist/server/status-code-resolver.d.ts.map +1 -1
  235. package/dist/server/stream-utils.d.ts +36 -0
  236. package/dist/server/stream-utils.d.ts.map +1 -0
  237. package/dist/server/tracing.d.ts +10 -0
  238. package/dist/server/tracing.d.ts.map +1 -1
  239. package/dist/server/tree-builder.d.ts +20 -13
  240. package/dist/server/tree-builder.d.ts.map +1 -1
  241. package/dist/server/types.d.ts +1 -3
  242. package/dist/server/types.d.ts.map +1 -1
  243. package/dist/server/version-skew.d.ts +61 -0
  244. package/dist/server/version-skew.d.ts.map +1 -0
  245. package/dist/server/waituntil-bridge.d.ts.map +1 -1
  246. package/dist/shared/merge-search-params.d.ts +22 -0
  247. package/dist/shared/merge-search-params.d.ts.map +1 -0
  248. package/dist/shims/font-google.d.ts +1 -1
  249. package/dist/shims/font-google.d.ts.map +1 -1
  250. package/dist/shims/navigation-client.d.ts +1 -1
  251. package/dist/shims/navigation-client.d.ts.map +1 -1
  252. package/dist/shims/navigation.d.ts +1 -1
  253. package/dist/shims/navigation.d.ts.map +1 -1
  254. package/dist/utils/state-machine.d.ts +80 -0
  255. package/dist/utils/state-machine.d.ts.map +1 -0
  256. package/package.json +17 -17
  257. package/src/adapters/compress-module.ts +24 -4
  258. package/src/adapters/nitro.ts +58 -9
  259. package/src/cache/fast-hash.ts +34 -0
  260. package/src/cache/index.ts +5 -2
  261. package/src/cache/register-cached-function.ts +7 -3
  262. package/src/cache/singleflight.ts +62 -4
  263. package/src/cache/timber-cache.ts +40 -29
  264. package/src/cli.ts +0 -0
  265. package/src/client/browser-entry.ts +151 -99
  266. package/src/client/error-boundary.tsx +18 -1
  267. package/src/client/error-reconstituter.tsx +65 -0
  268. package/src/client/form.tsx +2 -2
  269. package/src/client/index.ts +10 -1
  270. package/src/client/link-pending-store.ts +136 -0
  271. package/src/client/link.tsx +137 -22
  272. package/src/client/navigation-context.ts +6 -5
  273. package/src/client/router.ts +117 -60
  274. package/src/client/rsc-fetch.ts +90 -2
  275. package/src/client/segment-cache.ts +1 -1
  276. package/src/client/segment-context.ts +6 -1
  277. package/src/client/segment-merger.ts +2 -8
  278. package/src/client/segment-outlet.tsx +86 -0
  279. package/src/client/stale-reload.ts +73 -6
  280. package/src/client/top-loader.tsx +10 -9
  281. package/src/client/transition-root.tsx +20 -2
  282. package/src/client/use-params.ts +4 -4
  283. package/src/client/use-query-states.ts +2 -2
  284. package/src/codec.ts +21 -0
  285. package/src/cookies/define-cookie.ts +71 -20
  286. package/src/fonts/css.ts +2 -1
  287. package/src/index.ts +297 -85
  288. package/src/params/define.ts +327 -0
  289. package/src/params/index.ts +28 -0
  290. package/src/plugins/adapter-build.ts +8 -2
  291. package/src/plugins/build-manifest.ts +13 -2
  292. package/src/plugins/build-report.ts +3 -3
  293. package/src/plugins/cache-transform.ts +1 -1
  294. package/src/plugins/client-chunks.ts +65 -0
  295. package/src/plugins/content.ts +1 -1
  296. package/src/plugins/dev-browser-logs.ts +284 -0
  297. package/src/plugins/dev-error-overlay.ts +70 -1
  298. package/src/plugins/dev-logs.ts +1 -1
  299. package/src/plugins/dev-server.ts +41 -7
  300. package/src/plugins/entries.ts +6 -8
  301. package/src/plugins/fonts.ts +102 -55
  302. package/src/plugins/mdx.ts +1 -1
  303. package/src/plugins/routing.ts +57 -17
  304. package/src/plugins/server-action-exports.ts +1 -1
  305. package/src/plugins/server-bundle.ts +32 -1
  306. package/src/plugins/shims.ts +69 -31
  307. package/src/plugins/static-build.ts +10 -6
  308. package/src/routing/codegen.ts +109 -88
  309. package/src/routing/scanner.ts +86 -7
  310. package/src/routing/status-file-lint.ts +3 -2
  311. package/src/routing/types.ts +17 -4
  312. package/src/rsc-runtime/rsc.ts +2 -0
  313. package/src/rsc-runtime/ssr.ts +50 -0
  314. package/src/rsc-runtime/vendor-types.d.ts +7 -0
  315. package/src/search-params/codecs.ts +1 -1
  316. package/src/search-params/define.ts +518 -0
  317. package/src/search-params/index.ts +12 -18
  318. package/src/search-params/registry.ts +1 -1
  319. package/src/search-params/wrappers.ts +85 -0
  320. package/src/server/access-gate.tsx +40 -9
  321. package/src/server/action-client.ts +8 -2
  322. package/src/server/action-encryption.ts +144 -0
  323. package/src/server/action-handler.ts +20 -3
  324. package/src/server/actions.ts +1 -1
  325. package/src/server/als-registry.ts +25 -4
  326. package/src/server/build-manifest.ts +10 -4
  327. package/src/server/compress.ts +25 -7
  328. package/src/server/debug.ts +1 -1
  329. package/src/server/default-logger.ts +99 -0
  330. package/src/server/deny-renderer.ts +5 -3
  331. package/src/server/early-hints.ts +36 -15
  332. package/src/server/error-boundary-wrapper.ts +58 -15
  333. package/src/server/fallback-error.ts +29 -14
  334. package/src/server/flight-injection-state.ts +113 -0
  335. package/src/server/flight-scripts.ts +62 -0
  336. package/src/server/flush.ts +2 -1
  337. package/src/server/form-data.ts +76 -0
  338. package/src/server/html-injectors.ts +277 -117
  339. package/src/server/index.ts +9 -4
  340. package/src/server/logger.ts +44 -36
  341. package/src/server/node-stream-transforms.ts +509 -0
  342. package/src/server/pipeline-interception.ts +1 -1
  343. package/src/server/pipeline.ts +148 -41
  344. package/src/server/primitives.ts +47 -5
  345. package/src/server/render-timeout.ts +108 -0
  346. package/src/server/request-context.ts +125 -119
  347. package/src/server/route-element-builder.ts +107 -115
  348. package/src/server/route-handler.ts +2 -1
  349. package/src/server/route-matcher.ts +9 -2
  350. package/src/server/rsc-entry/api-handler.ts +8 -8
  351. package/src/server/rsc-entry/error-renderer.ts +286 -81
  352. package/src/server/rsc-entry/helpers.ts +134 -5
  353. package/src/server/rsc-entry/index.ts +177 -76
  354. package/src/server/rsc-entry/rsc-payload.ts +91 -18
  355. package/src/server/rsc-entry/rsc-stream.ts +74 -18
  356. package/src/server/rsc-entry/ssr-bridge.ts +2 -2
  357. package/src/server/rsc-entry/ssr-renderer.ts +152 -34
  358. package/src/server/slot-resolver.ts +231 -220
  359. package/src/server/ssr-entry.ts +211 -32
  360. package/src/server/ssr-render.ts +289 -67
  361. package/src/server/ssr-wrappers.tsx +139 -0
  362. package/src/server/status-code-resolver.ts +1 -1
  363. package/src/server/stream-utils.ts +213 -0
  364. package/src/server/tracing.ts +23 -0
  365. package/src/server/tree-builder.ts +92 -58
  366. package/src/server/types.ts +1 -3
  367. package/src/server/version-skew.ts +104 -0
  368. package/src/server/waituntil-bridge.ts +4 -1
  369. package/src/shared/merge-search-params.ts +55 -0
  370. package/src/shims/font-google.ts +1 -1
  371. package/src/shims/navigation-client.ts +1 -1
  372. package/src/shims/navigation.ts +2 -1
  373. package/src/utils/state-machine.ts +111 -0
  374. package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
  375. package/dist/_chunks/debug-gwlJkDuf.js.map +0 -1
  376. package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
  377. package/dist/_chunks/request-context-DIkVh_jG.js.map +0 -1
  378. package/dist/_chunks/ssr-data-MjmprTmO.js +0 -88
  379. package/dist/_chunks/ssr-data-MjmprTmO.js.map +0 -1
  380. package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
  381. package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
  382. package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
  383. package/dist/client/error-boundary.js.map +0 -1
  384. package/dist/client/link-status-provider.d.ts +0 -11
  385. package/dist/client/link-status-provider.d.ts.map +0 -1
  386. package/dist/cookies/index.js.map +0 -1
  387. package/dist/plugins/dynamic-transform.d.ts +0 -72
  388. package/dist/plugins/dynamic-transform.d.ts.map +0 -1
  389. package/dist/search-params/analyze.d.ts +0 -54
  390. package/dist/search-params/analyze.d.ts.map +0 -1
  391. package/dist/search-params/builtin-codecs.d.ts +0 -105
  392. package/dist/search-params/builtin-codecs.d.ts.map +0 -1
  393. package/dist/search-params/create.d.ts +0 -106
  394. package/dist/search-params/create.d.ts.map +0 -1
  395. package/dist/search-params/index.js.map +0 -1
  396. package/dist/server/prerender.d.ts +0 -77
  397. package/dist/server/prerender.d.ts.map +0 -1
  398. package/dist/server/response-cache.d.ts +0 -53
  399. package/dist/server/response-cache.d.ts.map +0 -1
  400. package/src/client/link-status-provider.tsx +0 -30
  401. package/src/plugins/dynamic-transform.ts +0 -161
  402. package/src/search-params/analyze.ts +0 -192
  403. package/src/search-params/builtin-codecs.ts +0 -228
  404. package/src/search-params/create.ts +0 -321
  405. package/src/server/prerender.ts +0 -139
  406. package/src/server/response-cache.ts +0 -277
@@ -1,9 +1,10 @@
1
1
  "use client";
2
- import { a as _setCurrentParams, c as cachedSearchParams, i as _setCachedSearch, l as currentParams, n as getSsrData, o as _setGlobalRouter, r as setSsrData, s as cachedSearch, t as clearSsrData, u as globalRouter } from "../_chunks/ssr-data-MjmprTmO.js";
3
- import { n as useQueryStates, t as bindUseQueryStates } from "../_chunks/use-query-states-D5KaffOK.js";
4
- import { t as useCookie } from "../_chunks/use-cookie-DX-l1_5E.js";
5
- import { TimberErrorBoundary } from "./error-boundary.js";
6
- import React, { cloneElement, createContext, createElement, isValidElement, useActionState as useActionState$1, useContext, useMemo, useSyncExternalStore, useTransition } from "react";
2
+ import { n as __exportAll } from "../_chunks/chunk-DYhsFzuS.js";
3
+ import { n as useQueryStates, t as bindUseQueryStates } from "../_chunks/use-query-states-wEXY2JQB.js";
4
+ import { n as useSegmentContext, r as mergePreservedSearchParams, t as SegmentProvider } from "../_chunks/segment-context-CyaM1mrD.js";
5
+ import { a as _setCachedSearch, c as cachedSearch, d as globalRouter, i as setSsrData, l as cachedSearchParams, n as clearSsrData, o as _setCurrentParams, r as getSsrData, s as _setGlobalRouter, t as TimberErrorBoundary, u as currentParams } from "../_chunks/error-boundary-DpZJBCqh.js";
6
+ import { t as _registerUseCookieModule } from "../_chunks/define-cookie-BWr_52kY.js";
7
+ import React, { cloneElement, createContext, createElement, isValidElement, useActionState as useActionState$1, useContext, useEffect, useRef, useState, useSyncExternalStore, useTransition } from "react";
7
8
  import { jsx } from "react/jsx-runtime";
8
9
  //#region src/client/use-link-status.ts
9
10
  /**
@@ -40,165 +41,6 @@ function useLinkStatus() {
40
41
  return useContext(LinkStatusContext);
41
42
  }
42
43
  //#endregion
43
- //#region src/client/navigation-context.ts
44
- /**
45
- * NavigationContext — React context for navigation state.
46
- *
47
- * Holds the current route params and pathname, updated atomically
48
- * with the RSC tree on each navigation. This replaces the previous
49
- * useSyncExternalStore approach for useParams() and usePathname(),
50
- * which suffered from a timing gap: the new tree could commit before
51
- * the external store re-renders fired, causing a frame where both
52
- * old and new active states were visible simultaneously.
53
- *
54
- * By wrapping the RSC payload element in NavigationProvider inside
55
- * renderRoot(), the context value and the element tree are passed to
56
- * reactRoot.render() in the same call — atomic by construction.
57
- * All consumers (useParams, usePathname) see the new values in the
58
- * same render pass as the new tree.
59
- *
60
- * During SSR, no NavigationProvider is mounted. Hooks fall back to
61
- * the ALS-backed getSsrData() for per-request isolation.
62
- *
63
- * IMPORTANT: createContext and useContext are NOT available in the RSC
64
- * environment (React Server Components use a stripped-down React).
65
- * The context is lazily initialized on first access, and all functions
66
- * that depend on these APIs are safe to call from any environment —
67
- * they return null or no-op when the APIs aren't available.
68
- *
69
- * SINGLETON GUARANTEE: All shared mutable state uses globalThis via
70
- * Symbol.for keys. The RSC client bundler can duplicate this module
71
- * across chunks (browser-entry graph + client-reference graph). With
72
- * ESM output, each chunk gets its own module scope — module-level
73
- * variables would create separate singleton instances per chunk.
74
- * globalThis guarantees a single instance regardless of duplication.
75
- *
76
- * This workaround will be removed when Rolldown ships `format: 'app'`
77
- * (module registry format that deduplicates like webpack/Turbopack).
78
- * See design/27-chunking-strategy.md.
79
- *
80
- * See design/19-client-navigation.md §"NavigationContext"
81
- */
82
- /**
83
- * The context is created lazily to avoid calling createContext at module
84
- * level. In the RSC environment, React.createContext doesn't exist —
85
- * calling it at import time would crash the server.
86
- *
87
- * Context instances are stored on globalThis (NOT in module-level
88
- * variables) because the ESM bundler can duplicate this module across
89
- * chunks. Module-level variables would create separate instances per
90
- * chunk — the provider in TransitionRoot (index chunk) would use
91
- * context A while the consumer in LinkStatusProvider (shared chunk)
92
- * reads from context B. globalThis guarantees a single instance.
93
- *
94
- * See design/27-chunking-strategy.md §"Singleton Safety"
95
- */
96
- var NAV_CTX_KEY = Symbol.for("__timber_nav_ctx");
97
- var PENDING_CTX_KEY = Symbol.for("__timber_pending_nav_ctx");
98
- function getOrCreateContext() {
99
- const existing = globalThis[NAV_CTX_KEY];
100
- if (existing !== void 0) return existing;
101
- if (typeof React.createContext === "function") {
102
- const ctx = React.createContext(null);
103
- globalThis[NAV_CTX_KEY] = ctx;
104
- return ctx;
105
- }
106
- }
107
- /**
108
- * Read the navigation context. Returns null during SSR (no provider)
109
- * or in the RSC environment (no context available).
110
- * Internal — used by useParams() and usePathname().
111
- */
112
- function useNavigationContext() {
113
- const ctx = getOrCreateContext();
114
- if (!ctx) return null;
115
- if (typeof React.useContext !== "function") return null;
116
- return React.useContext(ctx);
117
- }
118
- /**
119
- * Wraps children with NavigationContext.Provider.
120
- *
121
- * Used in browser-entry.ts renderRoot to wrap the RSC payload element
122
- * so that navigation state updates atomically with the tree render.
123
- */
124
- function NavigationProvider({ value, children }) {
125
- const ctx = getOrCreateContext();
126
- if (!ctx) return children;
127
- return createElement(ctx.Provider, { value }, children);
128
- }
129
- /**
130
- * Navigation state communicated between the router and renderRoot.
131
- *
132
- * The router calls setNavigationState() before renderRoot(). The
133
- * renderRoot callback reads via getNavigationState() to create the
134
- * NavigationProvider with the correct params/pathname.
135
- *
136
- * This is NOT used by hooks directly — hooks read from React context.
137
- *
138
- * Stored on globalThis (like the context instances above) because the
139
- * router lives in one chunk while renderRoot lives in another. Module-
140
- * level variables would be separate per chunk.
141
- */
142
- var NAV_STATE_KEY = Symbol.for("__timber_nav_state");
143
- function _getNavStateStore() {
144
- const g = globalThis;
145
- if (!g[NAV_STATE_KEY]) g[NAV_STATE_KEY] = { current: {
146
- params: {},
147
- pathname: "/"
148
- } };
149
- return g[NAV_STATE_KEY];
150
- }
151
- function setNavigationState(state) {
152
- _getNavStateStore().current = state;
153
- }
154
- function getNavigationState() {
155
- return _getNavStateStore().current;
156
- }
157
- /**
158
- * Separate context for the in-flight navigation URL. Provided by
159
- * TransitionRoot (urgent useState), consumed by LinkStatusProvider
160
- * and useNavigationPending.
161
- *
162
- * Uses globalThis via Symbol.for for the same reason as NavigationContext
163
- * above — the bundler may duplicate this module across chunks, and module-
164
- * level variables would create separate context instances.
165
- */
166
- function getOrCreatePendingContext() {
167
- const existing = globalThis[PENDING_CTX_KEY];
168
- if (existing !== void 0) return existing;
169
- if (typeof React.createContext === "function") {
170
- const ctx = React.createContext(null);
171
- globalThis[PENDING_CTX_KEY] = ctx;
172
- return ctx;
173
- }
174
- }
175
- /**
176
- * Read the pending navigation URL from context.
177
- * Returns null during SSR (no provider) or in the RSC environment.
178
- */
179
- function usePendingNavigationUrl() {
180
- const ctx = getOrCreatePendingContext();
181
- if (!ctx) return null;
182
- if (typeof React.useContext !== "function") return null;
183
- return React.useContext(ctx);
184
- }
185
- //#endregion
186
- //#region src/client/link-status-provider.tsx
187
- var NOT_PENDING = { pending: false };
188
- var IS_PENDING = { pending: true };
189
- /**
190
- * Client component that reads the pending URL from PendingNavigationContext
191
- * and provides a scoped LinkStatusContext to children. Renders no extra DOM —
192
- * just a context provider around children.
193
- */
194
- function LinkStatusProvider({ href, children }) {
195
- const status = usePendingNavigationUrl() === href ? IS_PENDING : NOT_PENDING;
196
- return /* @__PURE__ */ jsx(LinkStatusContext.Provider, {
197
- value: status,
198
- children
199
- });
200
- }
201
- //#endregion
202
44
  //#region src/client/router-ref.ts
203
45
  /**
204
46
  * Set the global router instance. Called once during bootstrap.
@@ -223,8 +65,62 @@ function getRouterOrNull() {
223
65
  return globalRouter;
224
66
  }
225
67
  //#endregion
68
+ //#region src/client/link-pending-store.ts
69
+ var LINK_PENDING_KEY = Symbol.for("__timber_link_pending");
70
+ /** Status object indicating link is pending — shared reference */
71
+ var PENDING_LINK_STATUS = { pending: true };
72
+ /** Status object indicating link is idle — shared reference */
73
+ var IDLE_LINK_STATUS = { pending: false };
74
+ function getStore() {
75
+ const g = globalThis;
76
+ if (!g[LINK_PENDING_KEY]) g[LINK_PENDING_KEY] = {
77
+ current: null,
78
+ navId: 0
79
+ };
80
+ return g[LINK_PENDING_KEY];
81
+ }
82
+ /**
83
+ * Register the link instance that initiated the current navigation.
84
+ *
85
+ * Called from <Link>'s click handler before router.navigate().
86
+ * - Resets the previous pending link to IDLE (urgent update, immediate)
87
+ * - Does NOT set the new link to PENDING here — the Link's click handler
88
+ * calls setLinkStatus(PENDING) directly for the eager show
89
+ * - Increments the navId counter for stale-clear protection
90
+ *
91
+ * Pass `null` to clear (e.g., for programmatic navigations).
92
+ */
93
+ function setLinkForCurrentNavigation(link) {
94
+ const store = getStore();
95
+ const prev = store.current;
96
+ if (prev && prev !== link) prev.setLinkStatus(IDLE_LINK_STATUS);
97
+ store.current = link;
98
+ store.navId++;
99
+ }
100
+ /**
101
+ * Unmount a link instance from navigation tracking. Called when a Link
102
+ * component unmounts while it is the current navigation link. Prevents
103
+ * calling setState on an unmounted component.
104
+ */
105
+ function unmountLinkForCurrentNavigation(link) {
106
+ const store = getStore();
107
+ if (store.current === link) store.current = null;
108
+ }
109
+ //#endregion
226
110
  //#region src/client/link.tsx
227
111
  /**
112
+ * Read the current URL's search string without requiring a React hook.
113
+ * On the client, reads window.location.search. During SSR, reads from
114
+ * the request context (getSsrData). Returns empty string if unavailable.
115
+ */
116
+ function getCurrentSearch() {
117
+ if (typeof window !== "undefined") return window.location.search;
118
+ const data = getSsrData();
119
+ if (!data) return "";
120
+ const str = new URLSearchParams(data.searchParams).toString();
121
+ return str ? `?${str}` : "";
122
+ }
123
+ /**
228
124
  * Reject dangerous URL schemes that could execute script.
229
125
  * Security: design/13-security.md § Link scheme injection (test #9)
230
126
  */
@@ -324,15 +220,26 @@ function shouldInterceptClick(event, resolvedHref) {
324
220
  * its own click handling.
325
221
  *
326
222
  * Supports typed routes via codegen overloads. At runtime:
327
- * - `params` prop interpolates dynamic segments in the href pattern
223
+ * - `segmentParams` prop interpolates dynamic segments in the href pattern
328
224
  * - `searchParams` prop serializes query parameters via a SearchParamsDefinition
329
225
  */
330
- function Link({ href, prefetch, scroll, params, searchParams, onNavigate, onClick: userOnClick, onMouseEnter: userOnMouseEnter, children, ...rest }) {
331
- const { href: resolvedHref } = buildLinkProps({
226
+ function Link({ href, prefetch, scroll, segmentParams, searchParams, preserveSearchParams, onNavigate, onClick: userOnClick, onMouseEnter: userOnMouseEnter, children, ...rest }) {
227
+ const { href: baseHref } = buildLinkProps({
332
228
  href,
333
- params,
229
+ params: segmentParams,
334
230
  searchParams
335
231
  });
232
+ const [linkStatus, setLinkStatus] = useState(IDLE_LINK_STATUS);
233
+ const linkInstanceRef = useRef(null);
234
+ if (!linkInstanceRef.current) linkInstanceRef.current = { setLinkStatus };
235
+ else linkInstanceRef.current.setLinkStatus = setLinkStatus;
236
+ useEffect(() => {
237
+ const instance = linkInstanceRef.current;
238
+ return () => {
239
+ if (instance) unmountLinkForCurrentNavigation(instance);
240
+ };
241
+ }, []);
242
+ const resolvedHref = preserveSearchParams ? mergePreservedSearchParams(baseHref, getCurrentSearch(), preserveSearchParams) : baseHref;
336
243
  const internal = isInternalHref(resolvedHref);
337
244
  const handleClick = internal ? (event) => {
338
245
  userOnClick?.(event);
@@ -351,20 +258,26 @@ function Link({ href, prefetch, scroll, params, searchParams, onNavigate, onClic
351
258
  if (!router) return;
352
259
  event.preventDefault();
353
260
  const shouldScroll = scroll !== false;
354
- router.navigate(resolvedHref, { scroll: shouldScroll });
261
+ const navHref = preserveSearchParams ? mergePreservedSearchParams(baseHref, getCurrentSearch(), preserveSearchParams) : resolvedHref;
262
+ setLinkStatus(PENDING_LINK_STATUS);
263
+ setLinkForCurrentNavigation(linkInstanceRef.current);
264
+ router.navigate(navHref, { scroll: shouldScroll });
355
265
  } : userOnClick;
356
266
  const handleMouseEnter = internal && prefetch ? (event) => {
357
267
  userOnMouseEnter?.(event);
358
268
  const router = getRouterOrNull();
359
- if (router) router.prefetch(resolvedHref);
269
+ if (router) {
270
+ const prefetchHref = preserveSearchParams ? mergePreservedSearchParams(baseHref, getCurrentSearch(), preserveSearchParams) : resolvedHref;
271
+ router.prefetch(prefetchHref);
272
+ }
360
273
  } : userOnMouseEnter;
361
274
  return /* @__PURE__ */ jsx("a", {
362
275
  ...rest,
363
276
  href: resolvedHref,
364
277
  onClick: handleClick,
365
278
  onMouseEnter: handleMouseEnter,
366
- children: /* @__PURE__ */ jsx(LinkStatusProvider, {
367
- href: resolvedHref,
279
+ children: /* @__PURE__ */ jsx(LinkStatusContext.Provider, {
280
+ value: linkStatus,
368
281
  children
369
282
  })
370
283
  });
@@ -501,6 +414,150 @@ var HistoryStack = class {
501
414
  }
502
415
  };
503
416
  //#endregion
417
+ //#region src/client/navigation-context.ts
418
+ /**
419
+ * NavigationContext — React context for navigation state.
420
+ *
421
+ * Holds the current route params and pathname, updated atomically
422
+ * with the RSC tree on each navigation. This replaces the previous
423
+ * useSyncExternalStore approach for useSegmentParams() and usePathname(),
424
+ * which suffered from a timing gap: the new tree could commit before
425
+ * the external store re-renders fired, causing a frame where both
426
+ * old and new active states were visible simultaneously.
427
+ *
428
+ * By wrapping the RSC payload element in NavigationProvider inside
429
+ * renderRoot(), the context value and the element tree are passed to
430
+ * reactRoot.render() in the same call — atomic by construction.
431
+ * All consumers (useParams, usePathname) see the new values in the
432
+ * same render pass as the new tree.
433
+ *
434
+ * During SSR, no NavigationProvider is mounted. Hooks fall back to
435
+ * the ALS-backed getSsrData() for per-request isolation.
436
+ *
437
+ * IMPORTANT: createContext and useContext are NOT available in the RSC
438
+ * environment (React Server Components use a stripped-down React).
439
+ * The context is lazily initialized on first access, and all functions
440
+ * that depend on these APIs are safe to call from any environment —
441
+ * they return null or no-op when the APIs aren't available.
442
+ *
443
+ * SINGLETON GUARANTEE: All shared mutable state uses globalThis via
444
+ * Symbol.for keys. The RSC client bundler can duplicate this module
445
+ * across chunks (browser-entry graph + client-reference graph). With
446
+ * ESM output, each chunk gets its own module scope — module-level
447
+ * variables would create separate singleton instances per chunk.
448
+ * globalThis guarantees a single instance regardless of duplication.
449
+ *
450
+ * This workaround will be removed when Rolldown ships `format: 'app'`
451
+ * (module registry format that deduplicates like webpack/Turbopack).
452
+ * See design/27-chunking-strategy.md.
453
+ *
454
+ * See design/19-client-navigation.md §"NavigationContext"
455
+ */
456
+ /**
457
+ * The context is created lazily to avoid calling createContext at module
458
+ * level. In the RSC environment, React.createContext doesn't exist —
459
+ * calling it at import time would crash the server.
460
+ *
461
+ * Context instances are stored on globalThis (NOT in module-level
462
+ * variables) because the ESM bundler can duplicate this module across
463
+ * chunks. Module-level variables would create separate instances per
464
+ * chunk — the provider in TransitionRoot (index chunk) would use
465
+ * context A while the consumer in useNavigationPending (shared chunk)
466
+ * reads from context B. globalThis guarantees a single instance.
467
+ *
468
+ * See design/27-chunking-strategy.md §"Singleton Safety"
469
+ */
470
+ var NAV_CTX_KEY = Symbol.for("__timber_nav_ctx");
471
+ var PENDING_CTX_KEY = Symbol.for("__timber_pending_nav_ctx");
472
+ function getOrCreateContext() {
473
+ const existing = globalThis[NAV_CTX_KEY];
474
+ if (existing !== void 0) return existing;
475
+ if (typeof React.createContext === "function") {
476
+ const ctx = React.createContext(null);
477
+ globalThis[NAV_CTX_KEY] = ctx;
478
+ return ctx;
479
+ }
480
+ }
481
+ /**
482
+ * Read the navigation context. Returns null during SSR (no provider)
483
+ * or in the RSC environment (no context available).
484
+ * Internal — used by useSegmentParams() and usePathname().
485
+ */
486
+ function useNavigationContext() {
487
+ const ctx = getOrCreateContext();
488
+ if (!ctx) return null;
489
+ if (typeof React.useContext !== "function") return null;
490
+ return React.useContext(ctx);
491
+ }
492
+ /**
493
+ * Wraps children with NavigationContext.Provider.
494
+ *
495
+ * Used in browser-entry.ts renderRoot to wrap the RSC payload element
496
+ * so that navigation state updates atomically with the tree render.
497
+ */
498
+ function NavigationProvider({ value, children }) {
499
+ const ctx = getOrCreateContext();
500
+ if (!ctx) return children;
501
+ return createElement(ctx.Provider, { value }, children);
502
+ }
503
+ /**
504
+ * Navigation state communicated between the router and renderRoot.
505
+ *
506
+ * The router calls setNavigationState() before renderRoot(). The
507
+ * renderRoot callback reads via getNavigationState() to create the
508
+ * NavigationProvider with the correct params/pathname.
509
+ *
510
+ * This is NOT used by hooks directly — hooks read from React context.
511
+ *
512
+ * Stored on globalThis (like the context instances above) because the
513
+ * router lives in one chunk while renderRoot lives in another. Module-
514
+ * level variables would be separate per chunk.
515
+ */
516
+ var NAV_STATE_KEY = Symbol.for("__timber_nav_state");
517
+ function _getNavStateStore() {
518
+ const g = globalThis;
519
+ if (!g[NAV_STATE_KEY]) g[NAV_STATE_KEY] = { current: {
520
+ params: {},
521
+ pathname: "/"
522
+ } };
523
+ return g[NAV_STATE_KEY];
524
+ }
525
+ function setNavigationState(state) {
526
+ _getNavStateStore().current = state;
527
+ }
528
+ function getNavigationState() {
529
+ return _getNavStateStore().current;
530
+ }
531
+ /**
532
+ * Separate context for the in-flight navigation URL. Provided by
533
+ * TransitionRoot (urgent useState), consumed by useNavigationPending
534
+ * and TopLoader. Per-link pending state uses useOptimistic instead
535
+ * (see link-pending-store.ts).
536
+ *
537
+ * Uses globalThis via Symbol.for for the same reason as NavigationContext
538
+ * above — the bundler may duplicate this module across chunks, and module-
539
+ * level variables would create separate context instances.
540
+ */
541
+ function getOrCreatePendingContext() {
542
+ const existing = globalThis[PENDING_CTX_KEY];
543
+ if (existing !== void 0) return existing;
544
+ if (typeof React.createContext === "function") {
545
+ const ctx = React.createContext(null);
546
+ globalThis[PENDING_CTX_KEY] = ctx;
547
+ return ctx;
548
+ }
549
+ }
550
+ /**
551
+ * Read the pending navigation URL from context.
552
+ * Returns null during SSR (no provider) or in the RSC environment.
553
+ */
554
+ function usePendingNavigationUrl() {
555
+ const ctx = getOrCreatePendingContext();
556
+ if (!ctx) return null;
557
+ if (typeof React.useContext !== "function") return null;
558
+ return React.useContext(ctx);
559
+ }
560
+ //#endregion
504
561
  //#region src/client/use-params.ts
505
562
  /**
506
563
  * Set the current route params in the module-level store.
@@ -520,7 +577,7 @@ var HistoryStack = class {
520
577
  function setCurrentParams(params) {
521
578
  _setCurrentParams(params);
522
579
  }
523
- function useParams(_route) {
580
+ function useSegmentParams(_route) {
524
581
  try {
525
582
  const navContext = useNavigationContext();
526
583
  if (navContext !== null) return navContext.params;
@@ -759,10 +816,28 @@ function generateCacheBustId() {
759
816
  function appendRscParam(url) {
760
817
  return `${url}${url.includes("?") ? "&" : "?"}_rsc=${generateCacheBustId()}`;
761
818
  }
819
+ /**
820
+ * The client's deployment ID, set at bootstrap from the runtime config.
821
+ * Sent with every RSC/action request for version skew detection.
822
+ * Null in dev mode. See TIM-446.
823
+ */
824
+ var clientDeploymentId = null;
825
+ /** Header name used by the server to signal a version skew reload. */
826
+ var RELOAD_HEADER = "X-Timber-Reload";
827
+ /** Header name for the client's deployment ID. */
828
+ var DEPLOYMENT_ID_HEADER = "X-Timber-Deployment-Id";
829
+ /**
830
+ * Check if a response signals a version skew reload.
831
+ * Triggers a full page reload if the server indicates the client is stale.
832
+ */
833
+ function checkReloadSignal(response) {
834
+ return response.headers.get(RELOAD_HEADER) === "1";
835
+ }
762
836
  function buildRscHeaders(stateTree, currentUrl) {
763
837
  const headers = { Accept: RSC_CONTENT_TYPE };
764
838
  if (stateTree) headers["X-Timber-State-Tree"] = JSON.stringify(stateTree);
765
839
  if (currentUrl) headers["X-Timber-URL"] = currentUrl;
840
+ if (clientDeploymentId) headers[DEPLOYMENT_ID_HEADER] = clientDeploymentId;
766
841
  return headers;
767
842
  }
768
843
  /**
@@ -817,7 +892,7 @@ function extractSkippedSegments(response) {
817
892
  * Extract route params from the X-Timber-Params response header.
818
893
  * Returns null if the header is missing or malformed.
819
894
  *
820
- * Used to populate useParams() after client-side navigation.
895
+ * Used to populate useSegmentParams() after client-side navigation.
821
896
  */
822
897
  function extractParams(response) {
823
898
  const header = response.headers.get("X-Timber-Params");
@@ -840,6 +915,33 @@ var RedirectError = class extends Error {
840
915
  }
841
916
  };
842
917
  /**
918
+ * Thrown when the server signals a version skew (X-Timber-Reload header).
919
+ * Caught in navigate() to trigger a full page reload via triggerStaleReload().
920
+ * See TIM-446.
921
+ */
922
+ var VersionSkewError = class extends Error {
923
+ constructor() {
924
+ super("Version skew detected — server has been redeployed");
925
+ }
926
+ };
927
+ /**
928
+ * Thrown when the server returns a 5xx error for an RSC payload request.
929
+ * The server sends X-Timber-Error header and a JSON body instead of a
930
+ * broken RSC stream. Caught in navigate() to trigger a hard navigation
931
+ * so the server can render the error page as HTML.
932
+ *
933
+ * See design/10-error-handling.md §"Error Page Rendering for Client Navigation"
934
+ */
935
+ var ServerErrorResponse = class extends Error {
936
+ status;
937
+ url;
938
+ constructor(status, url) {
939
+ super(`Server error ${status} during navigation to ${url}`);
940
+ this.status = status;
941
+ this.url = url;
942
+ }
943
+ };
944
+ /**
843
945
  * Fetch an RSC payload from the server. If a decodeRsc function is provided,
844
946
  * the response is decoded into a React element tree via createFromFetch.
845
947
  * Otherwise, the raw response text is returned (test mode).
@@ -860,8 +962,10 @@ async function fetchRscPayload(url, deps, stateTree, currentUrl) {
860
962
  let params = null;
861
963
  let skippedSegments = null;
862
964
  const wrappedPromise = fetchPromise.then((response) => {
965
+ if (checkReloadSignal(response)) throw new VersionSkewError();
863
966
  const redirectLocation = response.headers.get("X-Timber-Redirect") || (response.status >= 300 && response.status < 400 ? response.headers.get("Location") : null);
864
967
  if (redirectLocation) throw new RedirectError(redirectLocation);
968
+ if (response.headers.get("X-Timber-Error") === "1" && response.status >= 500) throw new ServerErrorResponse(response.status, url);
865
969
  headElements = extractHeadElements(response);
866
970
  segmentInfo = extractSegmentInfo(response);
867
971
  params = extractParams(response);
@@ -904,23 +1008,20 @@ function isAbortError(error) {
904
1008
  if (error instanceof Error && error.name === "AbortError") return true;
905
1009
  return false;
906
1010
  }
907
- /**
908
- * Create a router instance. In production, called once at app hydration
909
- * with real browser APIs. In tests, called with mock dependencies.
910
- */
911
1011
  function createRouter(deps) {
912
1012
  const segmentCache = new SegmentCache();
913
1013
  const prefetchCache = new PrefetchCache();
914
1014
  const historyStack = new HistoryStack();
915
1015
  const segmentElementCache = new SegmentElementCache();
916
- let pending = false;
917
- let pendingUrl = null;
1016
+ let routerPhase = { phase: "idle" };
918
1017
  const pendingListeners = /* @__PURE__ */ new Set();
919
1018
  function setPending(value, url) {
920
- const newPendingUrl = value && url ? url : null;
921
- if (pending === value && pendingUrl === newPendingUrl) return;
922
- pending = value;
923
- pendingUrl = newPendingUrl;
1019
+ const next = value && url ? {
1020
+ phase: "navigating",
1021
+ targetUrl: url
1022
+ } : { phase: "idle" };
1023
+ if (routerPhase.phase === next.phase && (routerPhase.phase === "idle" || routerPhase.phase === "navigating" && next.phase === "navigating" && routerPhase.targetUrl === next.targetUrl)) return;
1024
+ routerPhase = next;
924
1025
  for (const listener of pendingListeners) listener(value);
925
1026
  }
926
1027
  /** Update the segment cache from server-provided segment metadata. */
@@ -930,8 +1031,8 @@ function createRouter(deps) {
930
1031
  if (tree) segmentCache.set("/", tree);
931
1032
  }
932
1033
  /** Render a decoded RSC payload into the DOM if a renderer is available. */
933
- function renderPayload(payload) {
934
- if (deps.renderRoot) deps.renderRoot(payload);
1034
+ function renderPayload(payload, navState) {
1035
+ if (deps.renderRoot) deps.renderRoot(payload, navState);
935
1036
  }
936
1037
  /**
937
1038
  * Merge a partial RSC payload with cached segment elements if segments
@@ -947,24 +1048,26 @@ function createRouter(deps) {
947
1048
  /**
948
1049
  * Update navigation state (params + pathname) for the next render.
949
1050
  *
950
- * Sets both the module-level fallback (for tests and SSR) and the
951
- * navigation context state (read by renderRoot to wrap the element
952
- * in NavigationProvider). The context update is atomic with the tree
953
- * render both are passed to reactRoot.render() in the same call.
1051
+ * Sets the module-level fallback (for tests and SSR) and the
1052
+ * globalThis bridge, then returns the NavigationState so callers
1053
+ * can pass it explicitly to renderRoot/wrapPayload eliminating
1054
+ * temporal coupling with getNavigationState().
954
1055
  */
955
1056
  function updateNavigationState(params, url) {
956
1057
  const resolvedParams = params ?? {};
957
1058
  setCurrentParams(resolvedParams);
958
- setNavigationState({
1059
+ const navState = {
959
1060
  params: resolvedParams,
960
1061
  pathname: url.startsWith("http") ? new URL(url).pathname : url.split("?")[0] || "/"
961
- });
1062
+ };
1063
+ setNavigationState(navState);
1064
+ return navState;
962
1065
  }
963
1066
  /**
964
1067
  * Render a payload via navigateTransition (production) or renderRoot (tests).
965
- * The perform callback should fetch data, update state, and return the payload.
966
- * In production, the entire callback runs inside a React transition with
967
- * useOptimistic for the pending URL. In tests, the payload is rendered directly.
1068
+ * The perform callback should fetch data, update state, and return the
1069
+ * FetchResult plus the NavigationState (so it can be passed explicitly
1070
+ * to wrapPayload/renderRoot without temporal coupling).
968
1071
  */
969
1072
  async function renderViaTransition(url, perform) {
970
1073
  if (deps.navigateTransition) {
@@ -978,7 +1081,7 @@ function createRouter(deps) {
978
1081
  headElements: result.headElements,
979
1082
  params: result.params
980
1083
  });
981
- return wrapPayload(merged);
1084
+ return wrapPayload(merged, result.navState);
982
1085
  });
983
1086
  return headElements;
984
1087
  }
@@ -989,7 +1092,7 @@ function createRouter(deps) {
989
1092
  headElements: result.headElements,
990
1093
  params: result.params
991
1094
  });
992
- renderPayload(merged);
1095
+ renderPayload(merged, result.navState);
993
1096
  return result.headElements;
994
1097
  }
995
1098
  /** Apply head elements (title, meta tags) to the DOM if available. */
@@ -1002,6 +1105,16 @@ function createRouter(deps) {
1002
1105
  else callback();
1003
1106
  }
1004
1107
  /**
1108
+ * Schedule scroll restoration after the next paint and fire the
1109
+ * scroll-restored event. Used by navigate, popstate, and refresh.
1110
+ */
1111
+ function restoreScrollAfterPaint(scrollY) {
1112
+ afterPaint(() => {
1113
+ deps.scrollTo(0, scrollY);
1114
+ window.dispatchEvent(new Event("timber:scroll-restored"));
1115
+ });
1116
+ }
1117
+ /**
1005
1118
  * Core navigation logic shared between the transition and fallback paths.
1006
1119
  * Fetches the RSC payload, updates all state, and returns the result.
1007
1120
  */
@@ -1028,8 +1141,11 @@ function createRouter(deps) {
1028
1141
  scrollY: 0
1029
1142
  }, "", url);
1030
1143
  updateSegmentCache(result.segmentInfo);
1031
- updateNavigationState(result.params, url);
1032
- return result;
1144
+ const navState = updateNavigationState(result.params, url);
1145
+ return {
1146
+ ...result,
1147
+ navState
1148
+ };
1033
1149
  }
1034
1150
  async function navigate(url, options = {}) {
1035
1151
  const scroll = options.scroll !== false;
@@ -1043,17 +1159,22 @@ function createRouter(deps) {
1043
1159
  try {
1044
1160
  applyHead(await renderViaTransition(url, () => performNavigationFetch(url, { replace })));
1045
1161
  window.dispatchEvent(new Event("timber:navigation-end"));
1046
- afterPaint(() => {
1047
- if (scroll) deps.scrollTo(0, 0);
1048
- else deps.scrollTo(0, currentScrollY);
1049
- window.dispatchEvent(new Event("timber:scroll-restored"));
1050
- });
1162
+ restoreScrollAfterPaint(scroll ? 0 : currentScrollY);
1051
1163
  } catch (error) {
1164
+ if (error instanceof VersionSkewError) {
1165
+ const { triggerStaleReload } = await import("../_chunks/stale-reload-BSSym1MJ.js");
1166
+ triggerStaleReload();
1167
+ return new Promise(() => {});
1168
+ }
1052
1169
  if (error instanceof RedirectError) {
1053
1170
  setPending(false);
1054
1171
  await navigate(error.redirectUrl, { replace: true });
1055
1172
  return;
1056
1173
  }
1174
+ if (error instanceof ServerErrorResponse) {
1175
+ window.location.href = error.url;
1176
+ return new Promise(() => {});
1177
+ }
1057
1178
  if (isAbortError(error)) return;
1058
1179
  throw error;
1059
1180
  } finally {
@@ -1067,8 +1188,11 @@ function createRouter(deps) {
1067
1188
  applyHead(await renderViaTransition(currentUrl, async () => {
1068
1189
  const result = await fetchRscPayload(currentUrl, deps);
1069
1190
  updateSegmentCache(result.segmentInfo);
1070
- updateNavigationState(result.params, currentUrl);
1071
- return result;
1191
+ const navState = updateNavigationState(result.params, currentUrl);
1192
+ return {
1193
+ ...result,
1194
+ navState
1195
+ };
1072
1196
  }));
1073
1197
  } finally {
1074
1198
  setPending(false);
@@ -1077,26 +1201,23 @@ function createRouter(deps) {
1077
1201
  async function handlePopState(url, scrollY = 0) {
1078
1202
  const entry = historyStack.get(url);
1079
1203
  if (entry && entry.payload !== null) {
1080
- updateNavigationState(entry.params, url);
1081
- renderPayload(entry.payload);
1204
+ const navState = updateNavigationState(entry.params, url);
1205
+ renderPayload(entry.payload, navState);
1082
1206
  applyHead(entry.headElements);
1083
- afterPaint(() => {
1084
- deps.scrollTo(0, scrollY);
1085
- window.dispatchEvent(new Event("timber:scroll-restored"));
1086
- });
1207
+ restoreScrollAfterPaint(scrollY);
1087
1208
  } else {
1088
1209
  setPending(true, url);
1089
1210
  try {
1090
1211
  applyHead(await renderViaTransition(url, async () => {
1091
1212
  const result = await fetchRscPayload(url, deps, segmentCache.serializeStateTree(segmentElementCache.getMergeablePaths()));
1092
1213
  updateSegmentCache(result.segmentInfo);
1093
- updateNavigationState(result.params, url);
1094
- return result;
1214
+ const navState = updateNavigationState(result.params, url);
1215
+ return {
1216
+ ...result,
1217
+ navState
1218
+ };
1095
1219
  }));
1096
- afterPaint(() => {
1097
- deps.scrollTo(0, scrollY);
1098
- window.dispatchEvent(new Event("timber:scroll-restored"));
1099
- });
1220
+ restoreScrollAfterPaint(scrollY);
1100
1221
  } finally {
1101
1222
  setPending(false);
1102
1223
  }
@@ -1117,8 +1238,8 @@ function createRouter(deps) {
1117
1238
  navigate,
1118
1239
  refresh,
1119
1240
  handlePopState,
1120
- isPending: () => pending,
1121
- getPendingUrl: () => pendingUrl,
1241
+ isPending: () => routerPhase.phase === "navigating",
1242
+ getPendingUrl: () => routerPhase.phase === "navigating" ? routerPhase.targetUrl : null,
1122
1243
  onPendingChange(listener) {
1123
1244
  pendingListeners.add(listener);
1124
1245
  return () => pendingListeners.delete(listener);
@@ -1131,7 +1252,7 @@ function createRouter(deps) {
1131
1252
  payload: merged,
1132
1253
  headElements
1133
1254
  });
1134
- renderPayload(merged);
1255
+ renderPayload(merged, getNavigationState());
1135
1256
  applyHead(headElements);
1136
1257
  },
1137
1258
  initSegmentCache: (segments) => updateSegmentCache(segments),
@@ -1354,36 +1475,6 @@ function useSearchParams() {
1354
1475
  return typeof window !== "undefined" ? getSearchParams() : getServerSearchParams();
1355
1476
  }
1356
1477
  //#endregion
1357
- //#region src/client/segment-context.ts
1358
- /**
1359
- * Segment Context — provides layout segment position for useSelectedLayoutSegment hooks.
1360
- *
1361
- * Each layout in the segment tree is wrapped with a SegmentProvider that stores
1362
- * the URL segments from root to the current layout level. The hooks read this
1363
- * context to determine which child segments are active below the calling layout.
1364
- *
1365
- * The context value is intentionally minimal: just the segment path array and
1366
- * parallel route keys. No internal cache details are exposed.
1367
- *
1368
- * Design docs: design/19-client-navigation.md, design/14-ecosystem.md
1369
- */
1370
- var SegmentContext = createContext(null);
1371
- /** Read the segment context. Returns null if no provider is above this component. */
1372
- function useSegmentContext() {
1373
- return useContext(SegmentContext);
1374
- }
1375
- /**
1376
- * Wraps each layout to provide segment position context.
1377
- * Injected by rsc-entry.ts during element tree construction.
1378
- */
1379
- function SegmentProvider({ segments, segmentId: _segmentId, parallelRouteKeys, children }) {
1380
- const value = useMemo(() => ({
1381
- segments,
1382
- parallelRouteKeys
1383
- }), [segments.join("/"), parallelRouteKeys.join(",")]);
1384
- return createElement(SegmentContext.Provider, { value }, children);
1385
- }
1386
- //#endregion
1387
1478
  //#region src/client/use-selected-layout-segment.ts
1388
1479
  /**
1389
1480
  * useSelectedLayoutSegment / useSelectedLayoutSegments — client-side hooks
@@ -1589,6 +1680,96 @@ function useFormErrors(result) {
1589
1680
  };
1590
1681
  }
1591
1682
  //#endregion
1592
- export { HistoryStack, Link, LinkStatusContext, NavigationProvider, PrefetchCache, SegmentCache, SegmentProvider, TimberErrorBoundary, bindUseQueryStates, buildLinkProps, clearSsrData, createRouter, getNavigationState, getRouter, getSsrData, interpolateParams, resolveHref, setCurrentParams, setGlobalRouter, setNavigationState, setSsrData, useActionState, useCookie, useFormAction, useFormErrors, useLinkStatus, useNavigationPending, useParams, usePathname, useQueryStates, useRouter, useSearchParams, useSegmentContext, useSelectedLayoutSegment, useSelectedLayoutSegments, validateLinkHref };
1683
+ //#region src/client/use-cookie.ts
1684
+ /**
1685
+ * useCookie — reactive client-side cookie hook.
1686
+ *
1687
+ * Uses useSyncExternalStore for SSR-safe, reactive cookie access.
1688
+ * All components reading the same cookie name re-render on change.
1689
+ * No cross-tab sync (intentional — see design/29-cookies.md).
1690
+ *
1691
+ * See design/29-cookies.md §"useCookie(name) Hook"
1692
+ */
1693
+ var use_cookie_exports = /* @__PURE__ */ __exportAll({ useCookie: () => useCookie });
1694
+ /** Per-name subscriber sets. */
1695
+ var listeners = /* @__PURE__ */ new Map();
1696
+ /** Parse a cookie name from document.cookie. */
1697
+ function getCookieValue(name) {
1698
+ if (typeof document === "undefined") return void 0;
1699
+ const match = document.cookie.match(new RegExp("(?:^|;\\s*)" + name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "\\s*=\\s*([^;]*)"));
1700
+ return match ? decodeURIComponent(match[1]) : void 0;
1701
+ }
1702
+ /** Serialize options into a cookie string suffix. */
1703
+ function serializeOptions(options) {
1704
+ if (!options) return "; Path=/; SameSite=Lax";
1705
+ const parts = [];
1706
+ parts.push(`Path=${options.path ?? "/"}`);
1707
+ if (options.domain) parts.push(`Domain=${options.domain}`);
1708
+ if (options.maxAge !== void 0) parts.push(`Max-Age=${options.maxAge}`);
1709
+ if (options.expires) parts.push(`Expires=${options.expires.toUTCString()}`);
1710
+ const sameSite = options.sameSite ?? "lax";
1711
+ parts.push(`SameSite=${sameSite.charAt(0).toUpperCase()}${sameSite.slice(1)}`);
1712
+ if (options.secure) parts.push("Secure");
1713
+ return "; " + parts.join("; ");
1714
+ }
1715
+ /** Notify all subscribers for a given cookie name. */
1716
+ function notify(name) {
1717
+ const subs = listeners.get(name);
1718
+ if (subs) for (const fn of subs) fn();
1719
+ }
1720
+ /**
1721
+ * Reactive hook for reading/writing a client-side cookie.
1722
+ *
1723
+ * Returns `[value, setCookie, deleteCookie]`:
1724
+ * - `value`: current cookie value (string | undefined)
1725
+ * - `setCookie`: sets the cookie and triggers re-renders
1726
+ * - `deleteCookie`: deletes the cookie and triggers re-renders
1727
+ *
1728
+ * @param name - Cookie name.
1729
+ * @param defaultOptions - Default options for setCookie calls.
1730
+ */
1731
+ function useCookie(name, defaultOptions) {
1732
+ const subscribe = (callback) => {
1733
+ let subs = listeners.get(name);
1734
+ if (!subs) {
1735
+ subs = /* @__PURE__ */ new Set();
1736
+ listeners.set(name, subs);
1737
+ }
1738
+ subs.add(callback);
1739
+ return () => {
1740
+ subs.delete(callback);
1741
+ if (subs.size === 0) listeners.delete(name);
1742
+ };
1743
+ };
1744
+ const getSnapshot = () => getCookieValue(name);
1745
+ const getServerSnapshot = () => getSsrData()?.cookies.get(name);
1746
+ const value = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
1747
+ const setCookie = (newValue, options) => {
1748
+ const merged = {
1749
+ ...defaultOptions,
1750
+ ...options
1751
+ };
1752
+ document.cookie = `${name}=${encodeURIComponent(newValue)}${serializeOptions(merged)}`;
1753
+ notify(name);
1754
+ };
1755
+ const deleteCookie = () => {
1756
+ const path = defaultOptions?.path ?? "/";
1757
+ const domain = defaultOptions?.domain;
1758
+ let cookieStr = `${name}=; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=${path}`;
1759
+ if (domain) cookieStr += `; Domain=${domain}`;
1760
+ document.cookie = cookieStr;
1761
+ notify(name);
1762
+ };
1763
+ return [
1764
+ value,
1765
+ setCookie,
1766
+ deleteCookie
1767
+ ];
1768
+ }
1769
+ //#endregion
1770
+ //#region src/client/index.ts
1771
+ _registerUseCookieModule(use_cookie_exports);
1772
+ //#endregion
1773
+ export { HistoryStack, Link, LinkStatusContext, NavigationProvider, PrefetchCache, SegmentCache, SegmentProvider, TimberErrorBoundary, bindUseQueryStates, buildLinkProps, clearSsrData, createRouter, getNavigationState, getRouter, getSsrData, interpolateParams, mergePreservedSearchParams, resolveHref, setCurrentParams, setGlobalRouter, setNavigationState, setSsrData, useActionState, useCookie, useFormAction, useFormErrors, useLinkStatus, useNavigationPending, usePathname, useQueryStates, useRouter, useSearchParams, useSegmentContext, useSegmentParams, useSelectedLayoutSegment, useSelectedLayoutSegments, validateLinkHref };
1593
1774
 
1594
1775
  //# sourceMappingURL=index.js.map