@timber-js/app 0.2.0-alpha.8 → 0.2.0-alpha.81

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 (571) hide show
  1. package/LICENSE +8 -0
  2. package/dist/_chunks/actions-Dg-ANYHb.js +421 -0
  3. package/dist/_chunks/actions-Dg-ANYHb.js.map +1 -0
  4. package/dist/_chunks/{als-registry-B7DbZ2hS.js → als-registry-HS0LGUl2.js} +1 -1
  5. package/dist/_chunks/als-registry-HS0LGUl2.js.map +1 -0
  6. package/dist/_chunks/chunk-DYhsFzuS.js +33 -0
  7. package/dist/_chunks/{debug-gwlJkDuf.js → debug-ECi_61pb.js} +2 -2
  8. package/dist/_chunks/debug-ECi_61pb.js.map +1 -0
  9. package/dist/_chunks/define-C77ScO0m.js +106 -0
  10. package/dist/_chunks/define-C77ScO0m.js.map +1 -0
  11. package/dist/_chunks/define-CZqDwhSu.js +199 -0
  12. package/dist/_chunks/define-CZqDwhSu.js.map +1 -0
  13. package/dist/_chunks/define-cookie-C2IkoFGN.js +94 -0
  14. package/dist/_chunks/define-cookie-C2IkoFGN.js.map +1 -0
  15. package/dist/_chunks/{format-DviM89f0.js → dev-warnings-DpGRGoDi.js} +5 -44
  16. package/dist/_chunks/dev-warnings-DpGRGoDi.js.map +1 -0
  17. package/dist/_chunks/format-CYBGxKtc.js +14 -0
  18. package/dist/_chunks/format-CYBGxKtc.js.map +1 -0
  19. package/dist/_chunks/{interception-BOoWmLUA.js → interception-Dpn_UfAD.js} +171 -97
  20. package/dist/_chunks/interception-Dpn_UfAD.js.map +1 -0
  21. package/dist/_chunks/merge-search-params-Cm_KIWDX.js +41 -0
  22. package/dist/_chunks/merge-search-params-Cm_KIWDX.js.map +1 -0
  23. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → metadata-routes-DS3eKNmf.js} +1 -1
  24. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js.map → metadata-routes-DS3eKNmf.js.map} +1 -1
  25. package/dist/_chunks/request-context-qMsWgy9C.js +478 -0
  26. package/dist/_chunks/request-context-qMsWgy9C.js.map +1 -0
  27. package/dist/_chunks/schema-bridge-C3xl_vfb.js +86 -0
  28. package/dist/_chunks/schema-bridge-C3xl_vfb.js.map +1 -0
  29. package/dist/_chunks/segment-classify-BDNn6EzD.js +65 -0
  30. package/dist/_chunks/segment-classify-BDNn6EzD.js.map +1 -0
  31. package/dist/_chunks/segment-context-fHFLF1PE.js +34 -0
  32. package/dist/_chunks/segment-context-fHFLF1PE.js.map +1 -0
  33. package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-DzuI0bIV.js} +1 -1
  34. package/dist/_chunks/{ssr-data-MjmprTmO.js.map → ssr-data-DzuI0bIV.js.map} +1 -1
  35. package/dist/_chunks/stale-reload-BX5gL1r-.js +64 -0
  36. package/dist/_chunks/stale-reload-BX5gL1r-.js.map +1 -0
  37. package/dist/_chunks/{tracing-CemImE6h.js → tracing-CCYbKn5n.js} +60 -9
  38. package/dist/_chunks/tracing-CCYbKn5n.js.map +1 -0
  39. package/dist/_chunks/use-params-Br9YSUFV.js +295 -0
  40. package/dist/_chunks/use-params-Br9YSUFV.js.map +1 -0
  41. package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-Lo_s_pw2.js} +4 -4
  42. package/dist/_chunks/use-query-states-Lo_s_pw2.js.map +1 -0
  43. package/dist/adapters/cloudflare-dev.d.ts +109 -0
  44. package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
  45. package/dist/adapters/cloudflare-dev.js +73 -0
  46. package/dist/adapters/cloudflare-dev.js.map +1 -0
  47. package/dist/adapters/cloudflare-kv-cache.d.ts +64 -0
  48. package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
  49. package/dist/adapters/cloudflare-kv-cache.js +95 -0
  50. package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
  51. package/dist/adapters/cloudflare.d.ts +148 -12
  52. package/dist/adapters/cloudflare.d.ts.map +1 -1
  53. package/dist/adapters/cloudflare.js +135 -11
  54. package/dist/adapters/cloudflare.js.map +1 -1
  55. package/dist/adapters/compress-module.d.ts.map +1 -1
  56. package/dist/adapters/nitro.d.ts +17 -1
  57. package/dist/adapters/nitro.d.ts.map +1 -1
  58. package/dist/adapters/nitro.js +56 -13
  59. package/dist/adapters/nitro.js.map +1 -1
  60. package/dist/cache/cache-api.d.ts +24 -0
  61. package/dist/cache/cache-api.d.ts.map +1 -0
  62. package/dist/cache/handler-store.d.ts +31 -0
  63. package/dist/cache/handler-store.d.ts.map +1 -0
  64. package/dist/cache/index.d.ts +23 -7
  65. package/dist/cache/index.d.ts.map +1 -1
  66. package/dist/cache/index.js +142 -80
  67. package/dist/cache/index.js.map +1 -1
  68. package/dist/cache/singleflight.d.ts +18 -1
  69. package/dist/cache/singleflight.d.ts.map +1 -1
  70. package/dist/cache/sizeof.d.ts +22 -0
  71. package/dist/cache/sizeof.d.ts.map +1 -0
  72. package/dist/cache/timber-cache.d.ts +1 -1
  73. package/dist/cache/timber-cache.d.ts.map +1 -1
  74. package/dist/cli.d.ts +6 -1
  75. package/dist/cli.d.ts.map +1 -1
  76. package/dist/cli.js +8 -3
  77. package/dist/cli.js.map +1 -1
  78. package/dist/client/browser-dev.d.ts +27 -1
  79. package/dist/client/browser-dev.d.ts.map +1 -1
  80. package/dist/client/browser-entry/action-dispatch.d.ts +17 -0
  81. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -0
  82. package/dist/client/browser-entry/hmr.d.ts +21 -0
  83. package/dist/client/browser-entry/hmr.d.ts.map +1 -0
  84. package/dist/client/browser-entry/hydrate.d.ts +46 -0
  85. package/dist/client/browser-entry/hydrate.d.ts.map +1 -0
  86. package/dist/client/browser-entry/index.d.ts +30 -0
  87. package/dist/client/browser-entry/index.d.ts.map +1 -0
  88. package/dist/client/browser-entry/post-hydration.d.ts +26 -0
  89. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
  90. package/dist/client/browser-entry/router-init.d.ts +23 -0
  91. package/dist/client/browser-entry/router-init.d.ts.map +1 -0
  92. package/dist/client/browser-entry/rsc-stream.d.ts +24 -0
  93. package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -0
  94. package/dist/client/browser-entry/scroll.d.ts +19 -0
  95. package/dist/client/browser-entry/scroll.d.ts.map +1 -0
  96. package/dist/client/error-boundary.d.ts +12 -5
  97. package/dist/client/error-boundary.d.ts.map +1 -1
  98. package/dist/client/error-boundary.js +10 -4
  99. package/dist/client/error-boundary.js.map +1 -1
  100. package/dist/client/error-reconstituter.d.ts +54 -0
  101. package/dist/client/error-reconstituter.d.ts.map +1 -0
  102. package/dist/client/form.d.ts +3 -3
  103. package/dist/client/form.d.ts.map +1 -1
  104. package/dist/client/history.d.ts +19 -4
  105. package/dist/client/history.d.ts.map +1 -1
  106. package/dist/client/index.d.ts +7 -21
  107. package/dist/client/index.d.ts.map +1 -1
  108. package/dist/client/index.js +210 -1017
  109. package/dist/client/index.js.map +1 -1
  110. package/dist/client/internal.d.ts +18 -0
  111. package/dist/client/internal.d.ts.map +1 -0
  112. package/dist/client/internal.js +890 -0
  113. package/dist/client/internal.js.map +1 -0
  114. package/dist/client/link-pending-store.d.ts +63 -0
  115. package/dist/client/link-pending-store.d.ts.map +1 -0
  116. package/dist/client/link.d.ts +90 -32
  117. package/dist/client/link.d.ts.map +1 -1
  118. package/dist/client/nav-link-store.d.ts +36 -0
  119. package/dist/client/nav-link-store.d.ts.map +1 -0
  120. package/dist/client/navigation-api-types.d.ts +90 -0
  121. package/dist/client/navigation-api-types.d.ts.map +1 -0
  122. package/dist/client/navigation-api.d.ts +115 -0
  123. package/dist/client/navigation-api.d.ts.map +1 -0
  124. package/dist/client/navigation-context.d.ts +13 -2
  125. package/dist/client/navigation-context.d.ts.map +1 -1
  126. package/dist/client/{transition-root.d.ts → navigation-root.d.ts} +42 -8
  127. package/dist/client/navigation-root.d.ts.map +1 -0
  128. package/dist/client/nuqs-adapter.d.ts.map +1 -1
  129. package/dist/client/router-ref.d.ts +1 -1
  130. package/dist/client/router.d.ts +70 -4
  131. package/dist/client/router.d.ts.map +1 -1
  132. package/dist/client/rsc-fetch.d.ts +38 -3
  133. package/dist/client/rsc-fetch.d.ts.map +1 -1
  134. package/dist/client/segment-cache.d.ts +1 -1
  135. package/dist/client/segment-cache.d.ts.map +1 -1
  136. package/dist/client/segment-outlet.d.ts +63 -0
  137. package/dist/client/segment-outlet.d.ts.map +1 -0
  138. package/dist/client/ssr-data.d.ts +13 -4
  139. package/dist/client/ssr-data.d.ts.map +1 -1
  140. package/dist/client/stale-reload.d.ts +15 -0
  141. package/dist/client/stale-reload.d.ts.map +1 -1
  142. package/dist/client/top-loader.d.ts +5 -5
  143. package/dist/client/top-loader.d.ts.map +1 -1
  144. package/dist/client/use-link-status.d.ts +5 -5
  145. package/dist/client/use-link-status.d.ts.map +1 -1
  146. package/dist/client/use-params.d.ts +6 -4
  147. package/dist/client/use-params.d.ts.map +1 -1
  148. package/dist/client/{use-navigation-pending.d.ts → use-pending-navigation.d.ts} +4 -4
  149. package/dist/client/use-pending-navigation.d.ts.map +1 -0
  150. package/dist/client/use-query-states.d.ts +1 -1
  151. package/dist/client/use-query-states.d.ts.map +1 -1
  152. package/dist/client/use-router.d.ts +1 -1
  153. package/dist/codec.d.ts +33 -0
  154. package/dist/codec.d.ts.map +1 -0
  155. package/dist/codec.js +2 -0
  156. package/dist/config-types.d.ts +227 -0
  157. package/dist/config-types.d.ts.map +1 -0
  158. package/dist/content/index.d.ts +1 -10
  159. package/dist/content/index.d.ts.map +1 -1
  160. package/dist/content/index.js +0 -2
  161. package/dist/cookies/define-cookie.d.ts +35 -14
  162. package/dist/cookies/define-cookie.d.ts.map +1 -1
  163. package/dist/cookies/index.js +1 -83
  164. package/dist/fonts/css.d.ts +1 -0
  165. package/dist/fonts/css.d.ts.map +1 -1
  166. package/dist/index.d.ts +45 -192
  167. package/dist/index.d.ts.map +1 -1
  168. package/dist/index.js +12357 -11925
  169. package/dist/index.js.map +1 -1
  170. package/dist/plugin-context.d.ts +107 -0
  171. package/dist/plugin-context.d.ts.map +1 -0
  172. package/dist/plugins/adapter-build.d.ts +1 -1
  173. package/dist/plugins/adapter-build.d.ts.map +1 -1
  174. package/dist/plugins/build-manifest.d.ts +2 -2
  175. package/dist/plugins/build-manifest.d.ts.map +1 -1
  176. package/dist/plugins/build-report.d.ts +3 -3
  177. package/dist/plugins/build-report.d.ts.map +1 -1
  178. package/dist/plugins/client-chunks.d.ts +32 -0
  179. package/dist/plugins/client-chunks.d.ts.map +1 -0
  180. package/dist/plugins/content.d.ts +1 -1
  181. package/dist/plugins/content.d.ts.map +1 -1
  182. package/dist/plugins/dev-browser-logs.d.ts +84 -0
  183. package/dist/plugins/dev-browser-logs.d.ts.map +1 -0
  184. package/dist/plugins/dev-error-overlay.d.ts +26 -1
  185. package/dist/plugins/dev-error-overlay.d.ts.map +1 -1
  186. package/dist/plugins/dev-logs.d.ts +1 -1
  187. package/dist/plugins/dev-logs.d.ts.map +1 -1
  188. package/dist/plugins/dev-server.d.ts +1 -1
  189. package/dist/plugins/dev-server.d.ts.map +1 -1
  190. package/dist/plugins/entries.d.ts +1 -1
  191. package/dist/plugins/entries.d.ts.map +1 -1
  192. package/dist/plugins/fonts.d.ts +19 -5
  193. package/dist/plugins/fonts.d.ts.map +1 -1
  194. package/dist/plugins/mdx.d.ts +1 -1
  195. package/dist/plugins/mdx.d.ts.map +1 -1
  196. package/dist/plugins/routing.d.ts +1 -1
  197. package/dist/plugins/routing.d.ts.map +1 -1
  198. package/dist/plugins/server-bundle.d.ts.map +1 -1
  199. package/dist/plugins/shims.d.ts +6 -5
  200. package/dist/plugins/shims.d.ts.map +1 -1
  201. package/dist/plugins/static-build.d.ts +4 -4
  202. package/dist/plugins/static-build.d.ts.map +1 -1
  203. package/dist/routing/codegen.d.ts +2 -2
  204. package/dist/routing/codegen.d.ts.map +1 -1
  205. package/dist/routing/index.d.ts +2 -0
  206. package/dist/routing/index.d.ts.map +1 -1
  207. package/dist/routing/index.js +3 -2
  208. package/dist/routing/scanner.d.ts.map +1 -1
  209. package/dist/routing/segment-classify.d.ts +46 -0
  210. package/dist/routing/segment-classify.d.ts.map +1 -0
  211. package/dist/routing/status-file-lint.d.ts +2 -1
  212. package/dist/routing/status-file-lint.d.ts.map +1 -1
  213. package/dist/routing/types.d.ts +16 -4
  214. package/dist/routing/types.d.ts.map +1 -1
  215. package/dist/rsc-runtime/rsc.d.ts +1 -1
  216. package/dist/rsc-runtime/rsc.d.ts.map +1 -1
  217. package/dist/rsc-runtime/ssr.d.ts +12 -0
  218. package/dist/rsc-runtime/ssr.d.ts.map +1 -1
  219. package/dist/schema-bridge.d.ts +76 -0
  220. package/dist/schema-bridge.d.ts.map +1 -0
  221. package/dist/search-params/define.d.ts +139 -0
  222. package/dist/search-params/define.d.ts.map +1 -0
  223. package/dist/search-params/index.d.ts +4 -7
  224. package/dist/search-params/index.d.ts.map +1 -1
  225. package/dist/search-params/index.js +32 -441
  226. package/dist/search-params/index.js.map +1 -1
  227. package/dist/search-params/registry.d.ts +2 -2
  228. package/dist/search-params/registry.d.ts.map +1 -1
  229. package/dist/search-params/wrappers.d.ts +53 -0
  230. package/dist/search-params/wrappers.d.ts.map +1 -0
  231. package/dist/segment-params/define.d.ts +78 -0
  232. package/dist/segment-params/define.d.ts.map +1 -0
  233. package/dist/segment-params/index.d.ts +3 -0
  234. package/dist/segment-params/index.d.ts.map +1 -0
  235. package/dist/segment-params/index.js +2 -0
  236. package/dist/server/access-gate.d.ts +4 -0
  237. package/dist/server/access-gate.d.ts.map +1 -1
  238. package/dist/server/action-client.d.ts +25 -6
  239. package/dist/server/action-client.d.ts.map +1 -1
  240. package/dist/server/action-encryption.d.ts +76 -0
  241. package/dist/server/action-encryption.d.ts.map +1 -0
  242. package/dist/server/action-handler.d.ts.map +1 -1
  243. package/dist/server/actions.d.ts +3 -6
  244. package/dist/server/actions.d.ts.map +1 -1
  245. package/dist/server/als-registry.d.ts +32 -4
  246. package/dist/server/als-registry.d.ts.map +1 -1
  247. package/dist/server/build-manifest.d.ts +2 -2
  248. package/dist/server/build-manifest.d.ts.map +1 -1
  249. package/dist/server/debug.d.ts +1 -1
  250. package/dist/server/default-logger.d.ts +22 -0
  251. package/dist/server/default-logger.d.ts.map +1 -0
  252. package/dist/server/deny-page-resolver.d.ts +52 -0
  253. package/dist/server/deny-page-resolver.d.ts.map +1 -0
  254. package/dist/server/deny-renderer.d.ts.map +1 -1
  255. package/dist/server/dev-holding-server.d.ts +52 -0
  256. package/dist/server/dev-holding-server.d.ts.map +1 -0
  257. package/dist/server/dev-warnings.d.ts +1 -21
  258. package/dist/server/dev-warnings.d.ts.map +1 -1
  259. package/dist/server/early-hints.d.ts +13 -5
  260. package/dist/server/early-hints.d.ts.map +1 -1
  261. package/dist/server/error-boundary-wrapper.d.ts +7 -1
  262. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  263. package/dist/server/fallback-error.d.ts +4 -3
  264. package/dist/server/fallback-error.d.ts.map +1 -1
  265. package/dist/server/flight-injection-state.d.ts +66 -0
  266. package/dist/server/flight-injection-state.d.ts.map +1 -0
  267. package/dist/server/flight-scripts.d.ts +42 -0
  268. package/dist/server/flight-scripts.d.ts.map +1 -0
  269. package/dist/server/flush.d.ts.map +1 -1
  270. package/dist/server/form-data.d.ts +29 -0
  271. package/dist/server/form-data.d.ts.map +1 -1
  272. package/dist/server/html-injectors.d.ts +51 -11
  273. package/dist/server/html-injectors.d.ts.map +1 -1
  274. package/dist/server/index.d.ts +5 -43
  275. package/dist/server/index.d.ts.map +1 -1
  276. package/dist/server/index.js +37 -2798
  277. package/dist/server/index.js.map +1 -1
  278. package/dist/server/internal.d.ts +46 -0
  279. package/dist/server/internal.d.ts.map +1 -0
  280. package/dist/server/internal.js +2883 -0
  281. package/dist/server/internal.js.map +1 -0
  282. package/dist/server/logger.d.ts +25 -7
  283. package/dist/server/logger.d.ts.map +1 -1
  284. package/dist/server/middleware-runner.d.ts +19 -4
  285. package/dist/server/middleware-runner.d.ts.map +1 -1
  286. package/dist/server/node-stream-transforms.d.ts +113 -0
  287. package/dist/server/node-stream-transforms.d.ts.map +1 -0
  288. package/dist/server/page-deny-boundary.d.ts +31 -0
  289. package/dist/server/page-deny-boundary.d.ts.map +1 -0
  290. package/dist/server/pipeline-interception.d.ts +1 -1
  291. package/dist/server/pipeline-interception.d.ts.map +1 -1
  292. package/dist/server/pipeline-metadata.d.ts +6 -0
  293. package/dist/server/pipeline-metadata.d.ts.map +1 -1
  294. package/dist/server/pipeline.d.ts +42 -10
  295. package/dist/server/pipeline.d.ts.map +1 -1
  296. package/dist/server/primitives.d.ts +69 -18
  297. package/dist/server/primitives.d.ts.map +1 -1
  298. package/dist/server/render-timeout.d.ts +51 -0
  299. package/dist/server/render-timeout.d.ts.map +1 -0
  300. package/dist/server/request-context.d.ts +112 -43
  301. package/dist/server/request-context.d.ts.map +1 -1
  302. package/dist/server/route-element-builder.d.ts +27 -1
  303. package/dist/server/route-element-builder.d.ts.map +1 -1
  304. package/dist/server/route-handler.d.ts.map +1 -1
  305. package/dist/server/route-matcher.d.ts +9 -2
  306. package/dist/server/route-matcher.d.ts.map +1 -1
  307. package/dist/server/rsc-entry/api-handler.d.ts +2 -2
  308. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  309. package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
  310. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  311. package/dist/server/rsc-entry/helpers.d.ts +48 -5
  312. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  313. package/dist/server/rsc-entry/index.d.ts +8 -3
  314. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  315. package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
  316. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  317. package/dist/server/rsc-entry/rsc-stream.d.ts +4 -1
  318. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  319. package/dist/server/rsc-entry/ssr-bridge.d.ts +1 -1
  320. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  321. package/dist/server/rsc-entry/ssr-renderer.d.ts +19 -4
  322. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  323. package/dist/server/safe-load.d.ts +46 -0
  324. package/dist/server/safe-load.d.ts.map +1 -0
  325. package/dist/server/sitemap-generator.d.ts +129 -0
  326. package/dist/server/sitemap-generator.d.ts.map +1 -0
  327. package/dist/server/sitemap-handler.d.ts +22 -0
  328. package/dist/server/sitemap-handler.d.ts.map +1 -0
  329. package/dist/server/slot-resolver.d.ts +1 -1
  330. package/dist/server/slot-resolver.d.ts.map +1 -1
  331. package/dist/server/ssr-entry.d.ts +22 -0
  332. package/dist/server/ssr-entry.d.ts.map +1 -1
  333. package/dist/server/ssr-render.d.ts +39 -21
  334. package/dist/server/ssr-render.d.ts.map +1 -1
  335. package/dist/server/ssr-wrappers.d.ts +50 -0
  336. package/dist/server/ssr-wrappers.d.ts.map +1 -0
  337. package/dist/server/status-code-resolver.d.ts +1 -1
  338. package/dist/server/status-code-resolver.d.ts.map +1 -1
  339. package/dist/server/stream-utils.d.ts +36 -0
  340. package/dist/server/stream-utils.d.ts.map +1 -0
  341. package/dist/server/tracing.d.ts +4 -4
  342. package/dist/server/tracing.d.ts.map +1 -1
  343. package/dist/server/tree-builder.d.ts +22 -19
  344. package/dist/server/tree-builder.d.ts.map +1 -1
  345. package/dist/server/types.d.ts +1 -4
  346. package/dist/server/types.d.ts.map +1 -1
  347. package/dist/server/version-skew.d.ts +61 -0
  348. package/dist/server/version-skew.d.ts.map +1 -0
  349. package/dist/shared/merge-search-params.d.ts +22 -0
  350. package/dist/shared/merge-search-params.d.ts.map +1 -0
  351. package/dist/shims/font-google.d.ts +1 -1
  352. package/dist/shims/font-google.d.ts.map +1 -1
  353. package/dist/shims/font-google.js +42 -0
  354. package/dist/shims/font-google.js.map +1 -0
  355. package/dist/shims/font-local.d.ts +26 -0
  356. package/dist/shims/font-local.d.ts.map +1 -0
  357. package/dist/shims/font-local.js +20 -0
  358. package/dist/shims/font-local.js.map +1 -0
  359. package/dist/shims/headers.d.ts +2 -1
  360. package/dist/shims/headers.d.ts.map +1 -1
  361. package/dist/shims/navigation-client.d.ts +1 -1
  362. package/dist/shims/navigation-client.d.ts.map +1 -1
  363. package/dist/shims/navigation.d.ts +3 -2
  364. package/dist/shims/navigation.d.ts.map +1 -1
  365. package/dist/utils/directive-parser.d.ts +5 -2
  366. package/dist/utils/directive-parser.d.ts.map +1 -1
  367. package/dist/utils/state-machine.d.ts +80 -0
  368. package/dist/utils/state-machine.d.ts.map +1 -0
  369. package/package.json +56 -22
  370. package/src/adapters/cloudflare-dev.ts +177 -0
  371. package/src/adapters/cloudflare-kv-cache.ts +142 -0
  372. package/src/adapters/cloudflare.ts +342 -28
  373. package/src/adapters/compress-module.ts +24 -4
  374. package/src/adapters/nitro.ts +52 -8
  375. package/src/adapters/wrangler.d.ts +7 -0
  376. package/src/cache/cache-api.ts +38 -0
  377. package/src/cache/handler-store.ts +68 -0
  378. package/src/cache/index.ts +81 -18
  379. package/src/cache/singleflight.ts +62 -4
  380. package/src/cache/sizeof.ts +31 -0
  381. package/src/cache/timber-cache.ts +24 -20
  382. package/src/cli.ts +16 -6
  383. package/src/client/browser-dev.ts +128 -1
  384. package/src/client/browser-entry/action-dispatch.ts +116 -0
  385. package/src/client/browser-entry/hmr.ts +81 -0
  386. package/src/client/browser-entry/hydrate.ts +145 -0
  387. package/src/client/browser-entry/index.ts +138 -0
  388. package/src/client/browser-entry/post-hydration.ts +119 -0
  389. package/src/client/browser-entry/router-init.ts +193 -0
  390. package/src/client/browser-entry/rsc-stream.ts +157 -0
  391. package/src/client/browser-entry/scroll.ts +27 -0
  392. package/src/client/error-boundary.tsx +48 -16
  393. package/src/client/error-reconstituter.tsx +65 -0
  394. package/src/client/form.tsx +9 -7
  395. package/src/client/history.ts +26 -4
  396. package/src/client/index.ts +19 -38
  397. package/src/client/internal.ts +57 -0
  398. package/src/client/link-pending-store.ts +111 -0
  399. package/src/client/link.tsx +329 -97
  400. package/src/client/nav-link-store.ts +47 -0
  401. package/src/client/navigation-api-types.ts +112 -0
  402. package/src/client/navigation-api.ts +332 -0
  403. package/src/client/navigation-context.ts +31 -6
  404. package/src/client/navigation-root.tsx +342 -0
  405. package/src/client/nuqs-adapter.tsx +16 -3
  406. package/src/client/router-ref.ts +1 -1
  407. package/src/client/router.ts +299 -72
  408. package/src/client/rsc-fetch.ts +97 -8
  409. package/src/client/segment-cache.ts +1 -1
  410. package/src/client/segment-outlet.tsx +86 -0
  411. package/src/client/ssr-data.ts +13 -5
  412. package/src/client/stale-reload.ts +72 -3
  413. package/src/client/top-loader.tsx +16 -8
  414. package/src/client/use-link-status.ts +7 -7
  415. package/src/client/use-params.ts +7 -5
  416. package/src/client/{use-navigation-pending.ts → use-pending-navigation.ts} +6 -6
  417. package/src/client/use-query-states.ts +3 -3
  418. package/src/client/use-router.ts +1 -1
  419. package/src/codec.ts +49 -0
  420. package/src/config-types.ts +225 -0
  421. package/src/content/index.ts +5 -13
  422. package/src/cookies/define-cookie.ts +78 -25
  423. package/src/cookies/index.ts +8 -0
  424. package/src/fonts/css.ts +2 -1
  425. package/src/index.ts +295 -354
  426. package/src/plugin-context.ts +240 -0
  427. package/src/plugins/adapter-build.ts +9 -3
  428. package/src/plugins/build-manifest.ts +13 -2
  429. package/src/plugins/build-report.ts +3 -3
  430. package/src/plugins/client-chunks.ts +65 -0
  431. package/src/plugins/content.ts +1 -1
  432. package/src/plugins/dev-browser-logs.ts +288 -0
  433. package/src/plugins/dev-error-overlay.ts +70 -1
  434. package/src/plugins/dev-logs.ts +1 -1
  435. package/src/plugins/dev-server.ts +70 -9
  436. package/src/plugins/entries.ts +71 -10
  437. package/src/plugins/fonts.ts +168 -61
  438. package/src/plugins/mdx.ts +1 -1
  439. package/src/plugins/routing.ts +57 -17
  440. package/src/plugins/server-action-exports.ts +1 -1
  441. package/src/plugins/server-bundle.ts +32 -1
  442. package/src/plugins/shims.ts +135 -35
  443. package/src/plugins/static-build.ts +17 -11
  444. package/src/routing/codegen.ts +165 -105
  445. package/src/routing/index.ts +2 -0
  446. package/src/routing/scanner.ts +93 -23
  447. package/src/routing/segment-classify.ts +89 -0
  448. package/src/routing/status-file-lint.ts +3 -2
  449. package/src/routing/types.ts +17 -4
  450. package/src/rsc-runtime/rsc.ts +2 -0
  451. package/src/rsc-runtime/ssr.ts +50 -0
  452. package/src/rsc-runtime/vendor-types.d.ts +7 -0
  453. package/src/{search-params/codecs.ts → schema-bridge.ts} +57 -20
  454. package/src/search-params/define.ts +482 -0
  455. package/src/search-params/index.ts +14 -20
  456. package/src/search-params/registry.ts +2 -2
  457. package/src/search-params/wrappers.ts +85 -0
  458. package/src/segment-params/define.ts +279 -0
  459. package/src/segment-params/index.ts +9 -0
  460. package/src/server/access-gate.tsx +70 -29
  461. package/src/server/action-client.ts +46 -11
  462. package/src/server/action-encryption.ts +144 -0
  463. package/src/server/action-handler.ts +21 -4
  464. package/src/server/actions.ts +10 -9
  465. package/src/server/als-registry.ts +34 -6
  466. package/src/server/build-manifest.ts +10 -4
  467. package/src/server/compress.ts +25 -7
  468. package/src/server/debug.ts +1 -1
  469. package/src/server/default-logger.ts +99 -0
  470. package/src/server/deny-page-resolver.ts +154 -0
  471. package/src/server/deny-renderer.ts +24 -38
  472. package/src/server/dev-holding-server.ts +185 -0
  473. package/src/server/dev-warnings.ts +4 -49
  474. package/src/server/early-hints.ts +36 -15
  475. package/src/server/error-boundary-wrapper.ts +74 -22
  476. package/src/server/fallback-error.ts +31 -15
  477. package/src/server/flight-injection-state.ts +113 -0
  478. package/src/server/flight-scripts.ts +62 -0
  479. package/src/server/flush.ts +2 -1
  480. package/src/server/form-data.ts +76 -0
  481. package/src/server/html-injectors.ts +280 -120
  482. package/src/server/index.ts +25 -177
  483. package/src/server/internal.ts +169 -0
  484. package/src/server/logger.ts +44 -36
  485. package/src/server/middleware-runner.ts +31 -4
  486. package/src/server/node-stream-transforms.ts +509 -0
  487. package/src/server/page-deny-boundary.tsx +56 -0
  488. package/src/server/pipeline-interception.ts +17 -16
  489. package/src/server/pipeline-metadata.ts +13 -0
  490. package/src/server/pipeline.ts +227 -62
  491. package/src/server/primitives.ts +111 -28
  492. package/src/server/render-timeout.ts +108 -0
  493. package/src/server/request-context.ts +293 -132
  494. package/src/server/route-element-builder.ts +283 -191
  495. package/src/server/route-handler.ts +24 -4
  496. package/src/server/route-matcher.ts +24 -20
  497. package/src/server/rsc-entry/api-handler.ts +15 -16
  498. package/src/server/rsc-entry/error-renderer.ts +300 -89
  499. package/src/server/rsc-entry/helpers.ts +134 -5
  500. package/src/server/rsc-entry/index.ts +200 -112
  501. package/src/server/rsc-entry/rsc-payload.ts +65 -18
  502. package/src/server/rsc-entry/rsc-stream.ts +65 -13
  503. package/src/server/rsc-entry/ssr-bridge.ts +14 -5
  504. package/src/server/rsc-entry/ssr-renderer.ts +168 -38
  505. package/src/server/safe-load.ts +60 -0
  506. package/src/server/sitemap-generator.ts +338 -0
  507. package/src/server/sitemap-handler.ts +126 -0
  508. package/src/server/slot-resolver.ts +244 -229
  509. package/src/server/ssr-entry.ts +211 -32
  510. package/src/server/ssr-render.ts +289 -67
  511. package/src/server/ssr-wrappers.tsx +139 -0
  512. package/src/server/status-code-resolver.ts +1 -1
  513. package/src/server/stream-utils.ts +213 -0
  514. package/src/server/tracing.ts +20 -9
  515. package/src/server/tree-builder.ts +92 -58
  516. package/src/server/types.ts +3 -6
  517. package/src/server/version-skew.ts +104 -0
  518. package/src/shared/merge-search-params.ts +55 -0
  519. package/src/shims/font-google.ts +1 -1
  520. package/src/shims/font-local.ts +34 -0
  521. package/src/shims/headers.ts +5 -1
  522. package/src/shims/navigation-client.ts +1 -1
  523. package/src/shims/navigation.ts +7 -2
  524. package/src/utils/directive-parser.ts +5 -2
  525. package/src/utils/state-machine.ts +111 -0
  526. package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
  527. package/dist/_chunks/debug-gwlJkDuf.js.map +0 -1
  528. package/dist/_chunks/format-DviM89f0.js.map +0 -1
  529. package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
  530. package/dist/_chunks/request-context-DIkVh_jG.js +0 -330
  531. package/dist/_chunks/request-context-DIkVh_jG.js.map +0 -1
  532. package/dist/_chunks/tracing-CemImE6h.js.map +0 -1
  533. package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
  534. package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
  535. package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
  536. package/dist/cache/register-cached-function.d.ts +0 -17
  537. package/dist/cache/register-cached-function.d.ts.map +0 -1
  538. package/dist/client/browser-entry.d.ts +0 -21
  539. package/dist/client/browser-entry.d.ts.map +0 -1
  540. package/dist/client/link-status-provider.d.ts +0 -11
  541. package/dist/client/link-status-provider.d.ts.map +0 -1
  542. package/dist/client/transition-root.d.ts.map +0 -1
  543. package/dist/client/use-navigation-pending.d.ts.map +0 -1
  544. package/dist/cookies/index.js.map +0 -1
  545. package/dist/plugins/cache-transform.d.ts +0 -36
  546. package/dist/plugins/cache-transform.d.ts.map +0 -1
  547. package/dist/plugins/dynamic-transform.d.ts +0 -72
  548. package/dist/plugins/dynamic-transform.d.ts.map +0 -1
  549. package/dist/search-params/analyze.d.ts +0 -54
  550. package/dist/search-params/analyze.d.ts.map +0 -1
  551. package/dist/search-params/builtin-codecs.d.ts +0 -105
  552. package/dist/search-params/builtin-codecs.d.ts.map +0 -1
  553. package/dist/search-params/codecs.d.ts +0 -53
  554. package/dist/search-params/codecs.d.ts.map +0 -1
  555. package/dist/search-params/create.d.ts +0 -106
  556. package/dist/search-params/create.d.ts.map +0 -1
  557. package/dist/server/prerender.d.ts +0 -77
  558. package/dist/server/prerender.d.ts.map +0 -1
  559. package/dist/server/response-cache.d.ts +0 -54
  560. package/dist/server/response-cache.d.ts.map +0 -1
  561. package/src/cache/register-cached-function.ts +0 -103
  562. package/src/client/browser-entry.ts +0 -678
  563. package/src/client/link-status-provider.tsx +0 -30
  564. package/src/client/transition-root.tsx +0 -166
  565. package/src/plugins/cache-transform.ts +0 -199
  566. package/src/plugins/dynamic-transform.ts +0 -161
  567. package/src/search-params/analyze.ts +0 -192
  568. package/src/search-params/builtin-codecs.ts +0 -228
  569. package/src/search-params/create.ts +0 -321
  570. package/src/server/prerender.ts +0 -139
  571. package/src/server/response-cache.ts +0 -410
@@ -18,10 +18,45 @@
18
18
  // - params and fully-resolved string href are mutually exclusive
19
19
  // - searchParams and inline query string are mutually exclusive
20
20
 
21
- import type { AnchorHTMLAttributes, ReactNode, MouseEvent as ReactMouseEvent } from 'react';
22
- import type { SearchParamsDefinition } from '#/search-params/create.js';
23
- import { LinkStatusProvider } from './link-status-provider.js';
21
+ import {
22
+ useOptimistic,
23
+ useEffect,
24
+ useRef,
25
+ type AnchorHTMLAttributes,
26
+ type JSX,
27
+ type ReactNode,
28
+ type MouseEvent as ReactMouseEvent,
29
+ } from 'react';
30
+ import type { SearchParamsDefinition } from '../search-params/define.js';
31
+ import { classifyUrlSegment, type UrlSegment } from '../routing/segment-classify.js';
32
+ import { LinkStatusContext } from './use-link-status.js';
24
33
  import { getRouterOrNull } from './router-ref.js';
34
+ import { getSsrData } from './ssr-data.js';
35
+ import { mergePreservedSearchParams } from '../shared/merge-search-params.js';
36
+ import {
37
+ setLinkForCurrentNavigation,
38
+ unmountLinkForCurrentNavigation,
39
+ LINK_IDLE,
40
+ type LinkPendingInstance,
41
+ } from './link-pending-store.js';
42
+ import { setNavLinkMetadata } from './nav-link-store.js';
43
+ import { hasNavigationApi } from './navigation-api.js';
44
+
45
+ // ─── Current Search Params ────────────────────────────────────────
46
+
47
+ /**
48
+ * Read the current URL's search string without requiring a React hook.
49
+ * On the client, reads window.location.search. During SSR, reads from
50
+ * the request context (getSsrData). Returns empty string if unavailable.
51
+ */
52
+ function getCurrentSearch(): string {
53
+ if (typeof window !== 'undefined') return window.location.search;
54
+ const data = getSsrData();
55
+ if (!data) return '';
56
+ const sp = new URLSearchParams(data.searchParams);
57
+ const str = sp.toString();
58
+ return str ? `?${str}` : '';
59
+ }
25
60
 
26
61
  // ─── Types ───────────────────────────────────────────────────────
27
62
 
@@ -42,6 +77,20 @@ interface LinkBaseProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'h
42
77
  * Set to false for tabbed interfaces where content changes within a fixed layout.
43
78
  */
44
79
  scroll?: boolean;
80
+ /**
81
+ * Preserve search params from the current URL across navigation.
82
+ *
83
+ * - `true` — preserve ALL current search params (target params take precedence)
84
+ * - `string[]` — preserve only the named params (e.g. `['private', 'token']`)
85
+ *
86
+ * Useful for route-group gating where a search param (e.g. `?private=access`)
87
+ * must persist across internal navigations. The target href's own search params
88
+ * always take precedence over preserved ones.
89
+ *
90
+ * During SSR, reads search params from the request context. On the client,
91
+ * reads from the current URL and updates reactively when the URL changes.
92
+ */
93
+ preserveSearchParams?: true | string[];
45
94
  /**
46
95
  * Called before client-side navigation commits. Call `e.preventDefault()`
47
96
  * to cancel the default navigation — the caller is then responsible for
@@ -54,48 +103,107 @@ interface LinkBaseProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'h
54
103
  children?: ReactNode;
55
104
  }
56
105
 
106
+ // ─── Typed Link Props ────────────────────────────────────────────
107
+
108
+ /**
109
+ * Widen server-side string params to string | number for Link convenience.
110
+ * Exported for use by codegen-generated overloads.
111
+ */
112
+ export type LinkSegmentParams<T> = {
113
+ [K in keyof T]: [string] extends [T[K]] ? string | number : T[K];
114
+ };
115
+
116
+ // ─── External Href Types ─────────────────────────────────────────
117
+
118
+ /**
119
+ * Href types accepted by the catch-all (non-route) call signature.
120
+ *
121
+ * - External protocols: https://, http://, mailto:, tel:, ftp://
122
+ * - Hash-only and query-only links: #section, ?param=value
123
+ * - Computed `string` variables (non-literal)
124
+ *
125
+ * Internal path literals like "/typo-route" do NOT match — they must
126
+ * be a known route (from codegen) or stored in a `string` variable.
127
+ * This catches wrong hrefs at the type level. See TIM-624.
128
+ */
129
+ type ExternalHref =
130
+ | `http://${string}`
131
+ | `https://${string}`
132
+ | `mailto:${string}`
133
+ | `tel:${string}`
134
+ | `ftp://${string}`
135
+ | `//${string}`
136
+ | `#${string}`
137
+ | `?${string}`;
138
+
139
+ /**
140
+ * Callable interface for the Link component.
141
+ *
142
+ * Two kinds of call signatures:
143
+ * 1. Per-route (added by codegen via interface merging): DIRECT types
144
+ * for segmentParams — preserves TypeScript excess property checking.
145
+ * 2. Catch-all (below): accepts external hrefs and computed `string`
146
+ * variables. Does NOT accept internal path literals — those must
147
+ * match a known route from the codegen.
148
+ *
149
+ * See TIM-624.
150
+ */
151
+ export interface LinkFunction {
152
+ // External links (literal protocol hrefs)
153
+ (
154
+ props: LinkBaseProps & {
155
+ href: ExternalHref;
156
+ segmentParams?: never;
157
+ searchParams?: {
158
+ definition: SearchParamsDefinition<Record<string, unknown>>;
159
+ values: Record<string, unknown>;
160
+ };
161
+ }
162
+ ): JSX.Element;
163
+ // Computed/variable href (non-literal string) — e.g. href={myVar}
164
+ // `string extends H` is true only when H is the wide `string` type,
165
+ // not a specific literal. Template literal hrefs like `/blog/${slug}`
166
+ // are handled by resolved-pattern signatures in the codegen.
167
+ <H extends string>(
168
+ props: string extends H
169
+ ? LinkBaseProps & {
170
+ href: H;
171
+ segmentParams?: Record<string, string | number | string[]>;
172
+ searchParams?: {
173
+ definition: SearchParamsDefinition<Record<string, unknown>>;
174
+ values: Record<string, unknown>;
175
+ };
176
+ }
177
+ : never
178
+ ): JSX.Element;
179
+ }
180
+
57
181
  /**
58
- * Link with a fully-resolved string href.
59
- * When using a string href with params already interpolated,
60
- * the params prop is not available.
182
+ * Runtime-only loose props used internally by the Link implementation.
183
+ * Not exposed to callers the public API uses LinkFunction.
61
184
  */
62
- export interface LinkPropsWithHref extends LinkBaseProps {
185
+ interface LinkRuntimeProps extends LinkBaseProps {
63
186
  href: string;
64
- params?: never;
65
- /**
66
- * Typed search params — serialized via the route's SearchParamsDefinition.
67
- * Mutually exclusive with an inline query string in href.
68
- */
187
+ segmentParams?: Record<string, string | number | string[]>;
69
188
  searchParams?: {
70
189
  definition: SearchParamsDefinition<Record<string, unknown>>;
71
190
  values: Record<string, unknown>;
72
191
  };
73
192
  }
74
193
 
75
- /**
76
- * Link with a route pattern + params for interpolation.
77
- * e.g. <Link href="/products/[id]" params={{ id: "123" }}>
78
- * <Link href="/products/[id]" params={{ id: 123 }}>
79
- */
80
- export interface LinkPropsWithParams extends LinkBaseProps {
81
- /** Route pattern with dynamic segments (e.g. "/products/[id]") */
194
+ // Legacy exports for backward compat (used by buildLinkProps, tests, etc.)
195
+ export type LinkPropsWithHref = LinkBaseProps & {
82
196
  href: string;
83
- /**
84
- * Dynamic segment values to interpolate into the href.
85
- * Single dynamic segments accept string | number (numbers are stringified).
86
- * Catch-all segments accept string[].
87
- */
88
- params: Record<string, string | number | string[]>;
89
- /**
90
- * Typed search params — serialized via the route's SearchParamsDefinition.
91
- */
197
+ segmentParams?: never;
92
198
  searchParams?: {
93
199
  definition: SearchParamsDefinition<Record<string, unknown>>;
94
200
  values: Record<string, unknown>;
95
201
  };
96
- }
97
-
98
- export type LinkProps = LinkPropsWithHref | LinkPropsWithParams;
202
+ };
203
+ export type LinkPropsWithParams = LinkRuntimeProps & {
204
+ segmentParams: Record<string, string | number | string[]>;
205
+ };
206
+ export type LinkProps = LinkRuntimeProps;
99
207
 
100
208
  // ─── Dangerous URL Scheme Detection ──────────────────────────────
101
209
 
@@ -141,57 +249,91 @@ export function isInternalHref(href: string): boolean {
141
249
  * - [...param] → catch-all (joined with /)
142
250
  * - [[...param]] → optional catch-all (omitted if undefined/empty)
143
251
  */
252
+ /**
253
+ * Parse a route pattern's path portion into classified segments.
254
+ * Exported for testing. Uses the shared character-based classifier.
255
+ */
256
+ export function parseSegments(pattern: string): UrlSegment[] {
257
+ return pattern.split('/').filter(Boolean).map(classifyUrlSegment);
258
+ }
259
+
260
+ /**
261
+ * Resolve a single classified segment into its string representation.
262
+ * Returns null for optional catch-all with no value (filtered out before join).
263
+ */
264
+ function resolveSegment(
265
+ seg: UrlSegment,
266
+ params: Record<string, string | number | string[]>,
267
+ pattern: string
268
+ ): string | null {
269
+ switch (seg.kind) {
270
+ case 'static':
271
+ return seg.value;
272
+
273
+ case 'optional-catch-all': {
274
+ const value = params[seg.name];
275
+ if (value === undefined || (Array.isArray(value) && value.length === 0)) {
276
+ return null;
277
+ }
278
+ const segments = Array.isArray(value) ? value : [value];
279
+ return segments.map(encodeURIComponent).join('/');
280
+ }
281
+
282
+ case 'catch-all': {
283
+ const value = params[seg.name];
284
+ if (value === undefined) {
285
+ throw new Error(
286
+ `<Link> missing required catch-all param "${seg.name}" for pattern "${pattern}".`
287
+ );
288
+ }
289
+ const segments = Array.isArray(value) ? value : [value];
290
+ if (segments.length === 0) {
291
+ throw new Error(
292
+ `<Link> catch-all param "${seg.name}" must have at least one segment for pattern "${pattern}".`
293
+ );
294
+ }
295
+ return segments.map(encodeURIComponent).join('/');
296
+ }
297
+
298
+ case 'dynamic': {
299
+ const value = params[seg.name];
300
+ if (value === undefined) {
301
+ throw new Error(`<Link> missing required param "${seg.name}" for pattern "${pattern}".`);
302
+ }
303
+ if (Array.isArray(value)) {
304
+ throw new Error(
305
+ `<Link> param "${seg.name}" expected a string but received an array for pattern "${pattern}".`
306
+ );
307
+ }
308
+ return encodeURIComponent(String(value));
309
+ }
310
+ }
311
+ }
312
+
313
+ /**
314
+ * Split a URL pattern into the path portion and any trailing ?query/#hash suffix.
315
+ * Uses URL parsing for correctness rather than manual index arithmetic.
316
+ */
317
+ function splitPatternSuffix(pattern: string): [path: string, suffix: string] {
318
+ if (!pattern.includes('?') && !pattern.includes('#')) {
319
+ return [pattern, ''];
320
+ }
321
+ const url = new URL(pattern, 'http://x');
322
+ const suffix = url.search + url.hash;
323
+ const path = pattern.slice(0, pattern.length - suffix.length);
324
+ return [path, suffix];
325
+ }
326
+
144
327
  export function interpolateParams(
145
328
  pattern: string,
146
329
  params: Record<string, string | number | string[]>
147
330
  ): string {
148
- return (
149
- pattern
150
- .replace(
151
- /\[\[\.\.\.(\w+)\]\]|\[\.\.\.(\w+)\]|\[(\w+)\]/g,
152
- (_match, optionalCatchAll, catchAll, single) => {
153
- if (optionalCatchAll) {
154
- const value = params[optionalCatchAll];
155
- if (value === undefined || (Array.isArray(value) && value.length === 0)) {
156
- return '';
157
- }
158
- const segments = Array.isArray(value) ? value : [value];
159
- return segments.map(encodeURIComponent).join('/');
160
- }
331
+ const [pathPart, suffix] = splitPatternSuffix(pattern);
161
332
 
162
- if (catchAll) {
163
- const value = params[catchAll];
164
- if (value === undefined) {
165
- throw new Error(
166
- `<Link> missing required catch-all param "${catchAll}" for pattern "${pattern}".`
167
- );
168
- }
169
- const segments = Array.isArray(value) ? value : [value];
170
- if (segments.length === 0) {
171
- throw new Error(
172
- `<Link> catch-all param "${catchAll}" must have at least one segment for pattern "${pattern}".`
173
- );
174
- }
175
- return segments.map(encodeURIComponent).join('/');
176
- }
177
-
178
- // single dynamic segment
179
- const value = params[single];
180
- if (value === undefined) {
181
- throw new Error(`<Link> missing required param "${single}" for pattern "${pattern}".`);
182
- }
183
- if (Array.isArray(value)) {
184
- throw new Error(
185
- `<Link> param "${single}" expected a string but received an array for pattern "${pattern}".`
186
- );
187
- }
188
- // Accept numbers — coerce to string for URL interpolation
189
- return encodeURIComponent(String(value));
190
- }
191
- )
192
- // Clean up trailing slash from empty optional catch-all
193
- .replace(/\/+$/, '') || '/'
194
- );
333
+ const resolved = parseSegments(pathPart)
334
+ .map((seg) => resolveSegment(seg, params, pattern))
335
+ .filter((s): s is string => s !== null);
336
+ return ('/' + resolved.join('/') || '/') + suffix;
195
337
  }
196
338
 
197
339
  // ─── Resolve Href ───────────────────────────────────────────────
@@ -302,23 +444,76 @@ function shouldInterceptClick(
302
444
  * navigation via the router. No global event delegation — each Link owns
303
445
  * its own click handling.
304
446
  *
305
- * Supports typed routes via codegen overloads. At runtime:
306
- * - `params` prop interpolates dynamic segments in the href pattern
447
+ * Supports typed routes via the Routes interface (populated by codegen).
448
+ * At runtime:
449
+ * - `segmentParams` prop interpolates dynamic segments in the href pattern
307
450
  * - `searchParams` prop serializes query parameters via a SearchParamsDefinition
451
+ *
452
+ * Typed via the LinkFunction callable interface. The base call signature
453
+ * forbids segmentParams; per-route signatures are added by codegen via
454
+ * interface merging. See TIM-624.
308
455
  */
309
- export function Link({
310
- href,
311
- prefetch,
312
- scroll,
313
- params,
314
- searchParams,
315
- onNavigate,
316
- onClick: userOnClick,
317
- onMouseEnter: userOnMouseEnter,
318
- children,
319
- ...rest
320
- }: LinkProps) {
321
- const { href: resolvedHref } = buildLinkProps({ href, params, searchParams });
456
+ // Cast to LinkFunction — the callable interface provides the public type,
457
+ // but the implementation destructures LinkRuntimeProps internally.
458
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
459
+ export const Link: LinkFunction = function LinkImpl(props: any) {
460
+ const {
461
+ href,
462
+ prefetch,
463
+ scroll,
464
+ segmentParams,
465
+ searchParams,
466
+ preserveSearchParams,
467
+ onNavigate,
468
+ onClick: userOnClick,
469
+ onMouseEnter: userOnMouseEnter,
470
+ children,
471
+ ...rest
472
+ } = props as LinkRuntimeProps;
473
+ const { href: baseHref } = buildLinkProps({ href, params: segmentParams, searchParams });
474
+
475
+ // ─── Per-link pending state (useOptimistic) ────────────────────────
476
+ // Each Link has its own pending state. Only the clicked link's
477
+ // setter is invoked during navigation — zero other links re-render.
478
+ //
479
+ // Link click stores the instance; NavigationRoot activates inside startTransition.
480
+ // useOptimistic auto-reverts to LINK_IDLE when the navigation
481
+ // startTransition — batched with the new tree commit.
482
+ //
483
+ // See design/19-client-navigation.md §"Per-Link Pending State"
484
+ const [linkStatus, setIsPending] = useOptimistic(LINK_IDLE);
485
+
486
+ // Build the link instance ref for the pending store.
487
+ // The ref is stable across renders — we update the setter on each
488
+ // render to keep it current.
489
+ const linkInstanceRef = useRef<LinkPendingInstance | null>(null);
490
+ if (!linkInstanceRef.current) {
491
+ linkInstanceRef.current = { setIsPending };
492
+ } else {
493
+ linkInstanceRef.current.setIsPending = setIsPending;
494
+ }
495
+
496
+ // Clean up if this link unmounts while it's the current navigation link.
497
+ // Prevents calling setOptimistic on an unmounted component.
498
+ useEffect(() => {
499
+ const instance = linkInstanceRef.current;
500
+ return () => {
501
+ if (instance) {
502
+ unmountLinkForCurrentNavigation(instance);
503
+ }
504
+ };
505
+ }, []);
506
+
507
+ // Preserve search params from the current URL when requested.
508
+ // useSearchParams() works during both SSR (reads from request context)
509
+ // and on the client (reads from window.location, reactive to URL changes).
510
+ // We read current search params directly to avoid unconditional hook calls.
511
+ // On the client, window.location.search is always current; during SSR,
512
+ // getSsrData() provides the request's search params.
513
+ const resolvedHref = preserveSearchParams
514
+ ? mergePreservedSearchParams(baseHref, getCurrentSearch(), preserveSearchParams)
515
+ : baseHref;
516
+
322
517
  const internal = isInternalHref(resolvedHref);
323
518
 
324
519
  // ─── Click handler ───────────────────────────────────────────
@@ -349,9 +544,42 @@ export function Link({
349
544
  const router = getRouterOrNull();
350
545
  if (!router) return; // SSR or pre-hydration — fall through to browser nav
351
546
 
352
- event.preventDefault();
353
547
  const shouldScroll = scroll !== false;
354
- void router.navigate(resolvedHref, { scroll: shouldScroll });
548
+
549
+ // Register this link in the pending store. The actual
550
+ // setIsPending(LINK_PENDING) call happens inside NavigationRoot's
551
+ // async startTransition via activateLinkPending().
552
+
553
+ setLinkForCurrentNavigation(linkInstanceRef.current);
554
+
555
+ // When Navigation API is active, let the <a> click propagate
556
+ // naturally — do NOT call preventDefault(). The navigate event
557
+ // handler intercepts it and runs the RSC pipeline. This is a
558
+ // user-initiated navigation, so Chrome shows the native loading
559
+ // indicator (tab spinner). Metadata (scroll, link instance) is
560
+ // passed via nav-link-store so the handler can configure the nav.
561
+ //
562
+ // Without Navigation API (fallback), preventDefault and drive
563
+ // navigation through the router as before.
564
+ if (hasNavigationApi()) {
565
+ setNavLinkMetadata({
566
+ scroll: shouldScroll,
567
+ linkInstance: linkInstanceRef.current,
568
+ });
569
+ // Don't preventDefault — let the <a> click fire the navigate event
570
+ return;
571
+ }
572
+
573
+ // History API fallback — prevent default and navigate via router
574
+ event.preventDefault();
575
+
576
+ // Re-merge preserved search params at click time to pick up any
577
+ // URL changes since render (e.g. from other navigations or pushState).
578
+ const navHref = preserveSearchParams
579
+ ? mergePreservedSearchParams(baseHref, getCurrentSearch(), preserveSearchParams)
580
+ : resolvedHref;
581
+
582
+ void router.navigate(navHref, { scroll: shouldScroll });
355
583
  }
356
584
  : userOnClick; // External links — just pass through user's onClick
357
585
 
@@ -362,14 +590,18 @@ export function Link({
362
590
  userOnMouseEnter?.(event);
363
591
  const router = getRouterOrNull();
364
592
  if (router) {
365
- router.prefetch(resolvedHref);
593
+ // Re-merge preserved search params at hover time for fresh prefetch URL
594
+ const prefetchHref = preserveSearchParams
595
+ ? mergePreservedSearchParams(baseHref, getCurrentSearch(), preserveSearchParams)
596
+ : resolvedHref;
597
+ router.prefetch(prefetchHref);
366
598
  }
367
599
  }
368
600
  : userOnMouseEnter;
369
601
 
370
602
  return (
371
603
  <a {...rest} href={resolvedHref} onClick={handleClick} onMouseEnter={handleMouseEnter}>
372
- <LinkStatusProvider href={resolvedHref}>{children}</LinkStatusProvider>
604
+ <LinkStatusContext.Provider value={linkStatus}>{children}</LinkStatusContext.Provider>
373
605
  </a>
374
606
  );
375
- }
607
+ };
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Navigation Link Store — passes per-link metadata from Link's onClick
3
+ * to the Navigation API's navigate event handler.
4
+ *
5
+ * When the Navigation API is active, Link does NOT call event.preventDefault()
6
+ * or router.navigate(). Instead it stores metadata (scroll option, link
7
+ * pending instance) here, and lets the <a> click propagate naturally.
8
+ * The navigate event handler reads this metadata to configure the RSC
9
+ * navigation with the correct options.
10
+ *
11
+ * This store is consumed once per navigation — after reading, the metadata
12
+ * is cleared. If no metadata is present (e.g., a plain <a> tag without
13
+ * our Link component), the navigate handler uses default options.
14
+ *
15
+ * See design/19-client-navigation.md §"Navigation API Integration"
16
+ */
17
+
18
+ import type { LinkPendingInstance } from './link-pending-store.js';
19
+
20
+ export interface NavLinkMetadata {
21
+ /** Whether to scroll to top after navigation. Default: true. */
22
+ scroll: boolean;
23
+ /** The Link's pending state instance for per-link status tracking. */
24
+ linkInstance: LinkPendingInstance | null;
25
+ }
26
+
27
+ let pendingMetadata: NavLinkMetadata | null = null;
28
+
29
+ /**
30
+ * Store metadata from Link's onClick for the next navigate event.
31
+ * Called synchronously in the click handler — the navigate event
32
+ * fires synchronously after onClick returns.
33
+ */
34
+ export function setNavLinkMetadata(metadata: NavLinkMetadata): void {
35
+ pendingMetadata = metadata;
36
+ }
37
+
38
+ /**
39
+ * Consume the stored metadata. Returns null if no Link onClick
40
+ * preceded this navigation (e.g., plain <a> tag, programmatic nav).
41
+ * Clears the store after reading.
42
+ */
43
+ export function consumeNavLinkMetadata(): NavLinkMetadata | null {
44
+ const metadata = pendingMetadata;
45
+ pendingMetadata = null;
46
+ return metadata;
47
+ }
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Ambient type declarations for the Navigation API.
3
+ *
4
+ * The Navigation API is not yet in TypeScript's standard lib. These types
5
+ * are used internally via type assertions — we never import Navigation API
6
+ * types unconditionally. Progressive enhancement only: the API is feature-
7
+ * detected at runtime.
8
+ *
9
+ * See https://developer.mozilla.org/en-US/docs/Web/API/Navigation_API
10
+ */
11
+
12
+ // ─── Navigation Entry ────────────────────────────────────────────
13
+
14
+ export interface NavigationHistoryEntry {
15
+ readonly key: string;
16
+ readonly id: string;
17
+ readonly url: string | null;
18
+ readonly index: number;
19
+ readonly sameDocument: boolean;
20
+ getState(): unknown;
21
+ addEventListener(type: string, listener: EventListener): void;
22
+ removeEventListener(type: string, listener: EventListener): void;
23
+ }
24
+
25
+ // ─── Navigation Destination ──────────────────────────────────────
26
+
27
+ export interface NavigationDestination {
28
+ readonly url: string;
29
+ readonly key: string | null;
30
+ readonly id: string | null;
31
+ readonly index: number;
32
+ readonly sameDocument: boolean;
33
+ getState(): unknown;
34
+ }
35
+
36
+ // ─── Navigate Event ──────────────────────────────────────────────
37
+
38
+ export interface NavigateEvent extends Event {
39
+ readonly navigationType: 'push' | 'replace' | 'reload' | 'traverse';
40
+ readonly destination: NavigationDestination;
41
+ readonly canIntercept: boolean;
42
+ readonly userInitiated: boolean;
43
+ readonly hashChange: boolean;
44
+ readonly signal: AbortSignal;
45
+ readonly formData: FormData | null;
46
+ readonly downloadRequest: string | null;
47
+ readonly info: unknown;
48
+ intercept(options?: NavigateInterceptOptions): void;
49
+ scroll(): void;
50
+ }
51
+
52
+ export interface NavigateInterceptOptions {
53
+ handler?: () => Promise<void>;
54
+ focusReset?: 'after-transition' | 'manual';
55
+ scroll?: 'after-transition' | 'manual';
56
+ }
57
+
58
+ // ─── Navigation Transition ───────────────────────────────────────
59
+
60
+ export interface NavigationTransition {
61
+ readonly navigationType: 'push' | 'replace' | 'reload' | 'traverse';
62
+ readonly from: NavigationHistoryEntry;
63
+ readonly finished: Promise<void>;
64
+ }
65
+
66
+ // ─── Navigation Result ───────────────────────────────────────────
67
+
68
+ export interface NavigationResult {
69
+ committed: Promise<NavigationHistoryEntry>;
70
+ finished: Promise<NavigationHistoryEntry>;
71
+ }
72
+
73
+ // ─── Navigation Interface ────────────────────────────────────────
74
+
75
+ export interface NavigationApi {
76
+ readonly currentEntry: NavigationHistoryEntry | null;
77
+ readonly transition: NavigationTransition | null;
78
+ readonly canGoBack: boolean;
79
+ readonly canGoForward: boolean;
80
+ entries(): NavigationHistoryEntry[];
81
+ navigate(url: string, options?: NavigationNavigateOptions): NavigationResult;
82
+ reload(options?: NavigationReloadOptions): NavigationResult;
83
+ traverseTo(key: string, options?: NavigationOptions): NavigationResult;
84
+ back(options?: NavigationOptions): NavigationResult;
85
+ forward(options?: NavigationOptions): NavigationResult;
86
+ updateCurrentEntry(options: NavigationUpdateCurrentEntryOptions): void;
87
+ addEventListener(type: 'navigate', listener: (event: NavigateEvent) => void): void;
88
+ addEventListener(type: 'navigatesuccess', listener: (event: Event) => void): void;
89
+ addEventListener(type: 'navigateerror', listener: (event: Event) => void): void;
90
+ addEventListener(type: 'currententrychange', listener: (event: Event) => void): void;
91
+ addEventListener(type: string, listener: EventListener): void;
92
+ removeEventListener(type: string, listener: EventListener): void;
93
+ }
94
+
95
+ export interface NavigationNavigateOptions {
96
+ state?: unknown;
97
+ history?: 'auto' | 'push' | 'replace';
98
+ info?: unknown;
99
+ }
100
+
101
+ export interface NavigationReloadOptions {
102
+ state?: unknown;
103
+ info?: unknown;
104
+ }
105
+
106
+ export interface NavigationOptions {
107
+ info?: unknown;
108
+ }
109
+
110
+ export interface NavigationUpdateCurrentEntryOptions {
111
+ state: unknown;
112
+ }