@timber-js/app 0.2.0-alpha.185 → 0.2.0-alpha.187

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 (570) hide show
  1. package/dist/_chunks/{actions-O_LsyCE4.js → actions-35jnMdeJ.js} +4 -3
  2. package/dist/_chunks/{actions-O_LsyCE4.js.map → actions-35jnMdeJ.js.map} +1 -1
  3. package/dist/_chunks/als-registry-C6kcfprT.js +41 -0
  4. package/dist/_chunks/als-registry-C6kcfprT.js.map +1 -0
  5. package/dist/_chunks/als-slots-BEEIPKYm.js +26 -0
  6. package/dist/_chunks/als-slots-BEEIPKYm.js.map +1 -0
  7. package/dist/_chunks/base-path-DaQrzbez.js +80 -0
  8. package/dist/_chunks/base-path-DaQrzbez.js.map +1 -0
  9. package/dist/_chunks/build-manifest-DWppEdLB.js +86 -0
  10. package/dist/_chunks/build-manifest-DWppEdLB.js.map +1 -0
  11. package/dist/_chunks/build-output-helper-C3DrfzZR.js +369 -0
  12. package/dist/_chunks/build-output-helper-C3DrfzZR.js.map +1 -0
  13. package/dist/_chunks/{cache-api-B-lhk9p4.js → cache-api-DjNrIWRR.js} +8 -14
  14. package/dist/_chunks/cache-api-DjNrIWRR.js.map +1 -0
  15. package/dist/_chunks/cli-check-CpmN7Nh-.js +256 -0
  16. package/dist/_chunks/cli-check-CpmN7Nh-.js.map +1 -0
  17. package/dist/_chunks/cli-schema-sync-CGMp_Psg.js +298 -0
  18. package/dist/_chunks/cli-schema-sync-CGMp_Psg.js.map +1 -0
  19. package/dist/_chunks/{cloudflare-CnT5Lr7U.js → cloudflare-CGP6BZKO.js} +92 -14
  20. package/dist/_chunks/{cloudflare-CnT5Lr7U.js.map → cloudflare-CGP6BZKO.js.map} +1 -1
  21. package/dist/_chunks/convention-lint-kXsgc_-7.js +784 -0
  22. package/dist/_chunks/convention-lint-kXsgc_-7.js.map +1 -0
  23. package/dist/_chunks/error-boundary-D-ODYX41.js +353 -0
  24. package/dist/_chunks/error-boundary-D-ODYX41.js.map +1 -0
  25. package/dist/_chunks/{fast-hash-D6hIVt1Y.js → fast-hash-C-tVYrLb.js} +6 -1
  26. package/dist/_chunks/fast-hash-C-tVYrLb.js.map +1 -0
  27. package/dist/_chunks/file-cache-DmX7OqZP.js +454 -0
  28. package/dist/_chunks/file-cache-DmX7OqZP.js.map +1 -0
  29. package/dist/_chunks/fs-identity-D7vb6GdI.js +208 -0
  30. package/dist/_chunks/fs-identity-D7vb6GdI.js.map +1 -0
  31. package/dist/_chunks/{logger-AWfuX-KJ.js → logger-D8xJZXIN.js} +34 -51
  32. package/dist/_chunks/logger-D8xJZXIN.js.map +1 -0
  33. package/dist/_chunks/mdx-file-C005ay-P.js +25 -0
  34. package/dist/_chunks/mdx-file-C005ay-P.js.map +1 -0
  35. package/dist/_chunks/{plugin-context---kTF5v8.js → plugin-context-rCinWLiE.js} +8 -2
  36. package/dist/_chunks/plugin-context-rCinWLiE.js.map +1 -0
  37. package/dist/_chunks/purge-store-Byr8XOjU.js +14 -0
  38. package/dist/_chunks/purge-store-Byr8XOjU.js.map +1 -0
  39. package/dist/_chunks/{resolve-schema-Dz3fcFUo.js → resolve-schema-5ma5pp1b.js} +2 -2
  40. package/dist/_chunks/{resolve-schema-Dz3fcFUo.js.map → resolve-schema-5ma5pp1b.js.map} +1 -1
  41. package/dist/_chunks/{router-ref-CtmF-aPv.js → router-ref-DuYuV_0Q.js} +2 -2
  42. package/dist/_chunks/router-ref-DuYuV_0Q.js.map +1 -0
  43. package/dist/_chunks/rsc-cache-key-DD0fl_-s.js +243 -0
  44. package/dist/_chunks/rsc-cache-key-DD0fl_-s.js.map +1 -0
  45. package/dist/_chunks/rsc-error-envelope-tT5PJs4q.js +40 -0
  46. package/dist/_chunks/rsc-error-envelope-tT5PJs4q.js.map +1 -0
  47. package/dist/_chunks/rsc-media-type-DRqE_lD_.js +46 -0
  48. package/dist/_chunks/rsc-media-type-DRqE_lD_.js.map +1 -0
  49. package/dist/_chunks/rsc-payload-path-B_LBodc2.js +48 -0
  50. package/dist/_chunks/rsc-payload-path-B_LBodc2.js.map +1 -0
  51. package/dist/_chunks/scanner-C8b0Gcw3.js +1564 -0
  52. package/dist/_chunks/scanner-C8b0Gcw3.js.map +1 -0
  53. package/dist/_chunks/schema-bridge-Cc2Gngu1.js +199 -0
  54. package/dist/_chunks/schema-bridge-Cc2Gngu1.js.map +1 -0
  55. package/dist/_chunks/{segment-classify-Byy425ng.js → segment-classify-C539Pa2O.js} +23 -2
  56. package/dist/_chunks/segment-classify-C539Pa2O.js.map +1 -0
  57. package/dist/_chunks/segment-context-CjOlyB8Y.js +97 -0
  58. package/dist/_chunks/segment-context-CjOlyB8Y.js.map +1 -0
  59. package/dist/_chunks/{canonicalize-DQHyFClh.js → segment-keys-BawYuNFO.js} +61 -2
  60. package/dist/_chunks/segment-keys-BawYuNFO.js.map +1 -0
  61. package/dist/_chunks/slot-params-BCTmZkQB.js +76 -0
  62. package/dist/_chunks/slot-params-BCTmZkQB.js.map +1 -0
  63. package/dist/_chunks/{ssr-data-BOWsq18U.js → ssr-data-14MXm7Pj.js} +17 -2
  64. package/dist/_chunks/ssr-data-14MXm7Pj.js.map +1 -0
  65. package/dist/_chunks/{use-query-states-DFvWd-EA.js → use-query-states-BbU5Ge1V.js} +74 -26
  66. package/dist/_chunks/use-query-states-BbU5Ge1V.js.map +1 -0
  67. package/dist/_chunks/use-segment-params-C4r4BD9T.js +398 -0
  68. package/dist/_chunks/use-segment-params-C4r4BD9T.js.map +1 -0
  69. package/dist/_chunks/walkers-RzN6AFjr.js +141 -0
  70. package/dist/_chunks/walkers-RzN6AFjr.js.map +1 -0
  71. package/dist/adapters/build-output-helper.d.ts +37 -0
  72. package/dist/adapters/build-output-helper.d.ts.map +1 -1
  73. package/dist/adapters/cloudflare-dev.js +1 -1
  74. package/dist/adapters/cloudflare-kv-cache.js +1 -1
  75. package/dist/adapters/cloudflare.d.ts.map +1 -1
  76. package/dist/adapters/cloudflare.js +1 -1
  77. package/dist/adapters/compress-module.d.ts +12 -0
  78. package/dist/adapters/compress-module.d.ts.map +1 -1
  79. package/dist/adapters/fs-identity.d.ts +64 -0
  80. package/dist/adapters/fs-identity.d.ts.map +1 -0
  81. package/dist/adapters/nitro.d.ts.map +1 -1
  82. package/dist/adapters/nitro.js +56 -5
  83. package/dist/adapters/nitro.js.map +1 -1
  84. package/dist/adapters/shared.d.ts +57 -1
  85. package/dist/adapters/shared.d.ts.map +1 -1
  86. package/dist/adapters/types.d.ts +13 -1
  87. package/dist/adapters/types.d.ts.map +1 -1
  88. package/dist/cache/fast-hash.d.ts +5 -0
  89. package/dist/cache/fast-hash.d.ts.map +1 -1
  90. package/dist/cache/index.js +1 -1
  91. package/dist/cdn/cloudflare-purge.js +30 -0
  92. package/dist/cdn/cloudflare-purge.js.map +1 -0
  93. package/dist/cdn/fastly-purge.js +33 -0
  94. package/dist/cdn/fastly-purge.js.map +1 -0
  95. package/dist/cdn/index.js +94 -0
  96. package/dist/cdn/index.js.map +1 -0
  97. package/dist/cdn/workers-cache-purge.js +35 -0
  98. package/dist/cdn/workers-cache-purge.js.map +1 -0
  99. package/dist/cli-check.d.ts +153 -0
  100. package/dist/cli-check.d.ts.map +1 -0
  101. package/dist/cli.d.ts +34 -8
  102. package/dist/cli.d.ts.map +1 -1
  103. package/dist/cli.js +46 -21
  104. package/dist/cli.js.map +1 -1
  105. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -1
  106. package/dist/client/browser-entry/hydrate.d.ts +20 -9
  107. package/dist/client/browser-entry/hydrate.d.ts.map +1 -1
  108. package/dist/client/browser-entry/index.d.ts +1 -1
  109. package/dist/client/browser-entry/index.d.ts.map +1 -1
  110. package/dist/client/browser-entry/post-hydration.d.ts +4 -1
  111. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -1
  112. package/dist/client/browser-entry/router-init.d.ts +3 -0
  113. package/dist/client/browser-entry/router-init.d.ts.map +1 -1
  114. package/dist/client/browser-entry/rsc-stream.d.ts +8 -0
  115. package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -1
  116. package/dist/client/error-boundary.d.ts +7 -0
  117. package/dist/client/error-boundary.d.ts.map +1 -1
  118. package/dist/client/error-boundary.js +1 -162
  119. package/dist/client/history.d.ts +13 -6
  120. package/dist/client/history.d.ts.map +1 -1
  121. package/dist/client/index.d.ts +1 -0
  122. package/dist/client/index.d.ts.map +1 -1
  123. package/dist/client/index.js +42 -41
  124. package/dist/client/index.js.map +1 -1
  125. package/dist/client/internal.d.ts +4 -3
  126. package/dist/client/internal.d.ts.map +1 -1
  127. package/dist/client/internal.js +877 -311
  128. package/dist/client/internal.js.map +1 -1
  129. package/dist/client/link.d.ts +1 -7
  130. package/dist/client/link.d.ts.map +1 -1
  131. package/dist/client/navigation-api.d.ts +2 -2
  132. package/dist/client/navigation-commit.d.ts +87 -0
  133. package/dist/client/navigation-commit.d.ts.map +1 -0
  134. package/dist/client/navigation-context.d.ts +37 -20
  135. package/dist/client/navigation-context.d.ts.map +1 -1
  136. package/dist/client/navigation-root.d.ts +63 -23
  137. package/dist/client/navigation-root.d.ts.map +1 -1
  138. package/dist/client/params-context.d.ts +81 -0
  139. package/dist/client/params-context.d.ts.map +1 -0
  140. package/dist/client/router-effects.d.ts +129 -0
  141. package/dist/client/router-effects.d.ts.map +1 -0
  142. package/dist/client/router-lifecycle.d.ts +55 -0
  143. package/dist/client/router-lifecycle.d.ts.map +1 -0
  144. package/dist/client/router-pipeline.d.ts +84 -0
  145. package/dist/client/router-pipeline.d.ts.map +1 -0
  146. package/dist/client/router-ref.d.ts +1 -1
  147. package/dist/client/router-ref.d.ts.map +1 -1
  148. package/dist/client/router-skew.d.ts +21 -0
  149. package/dist/client/router-skew.d.ts.map +1 -0
  150. package/dist/client/router-types.d.ts +207 -0
  151. package/dist/client/router-types.d.ts.map +1 -0
  152. package/dist/client/router.d.ts +1 -182
  153. package/dist/client/router.d.ts.map +1 -1
  154. package/dist/client/rsc-fetch.d.ts +47 -26
  155. package/dist/client/rsc-fetch.d.ts.map +1 -1
  156. package/dist/client/segment-cache.d.ts +87 -34
  157. package/dist/client/segment-cache.d.ts.map +1 -1
  158. package/dist/client/ssr-data.d.ts +6 -0
  159. package/dist/client/ssr-data.d.ts.map +1 -1
  160. package/dist/client/stale-client.d.ts +69 -0
  161. package/dist/client/stale-client.d.ts.map +1 -0
  162. package/dist/client/state.d.ts +10 -1
  163. package/dist/client/state.d.ts.map +1 -1
  164. package/dist/client/top-loader.d.ts +2 -1
  165. package/dist/client/top-loader.d.ts.map +1 -1
  166. package/dist/client/unload-guard.d.ts +5 -0
  167. package/dist/client/unload-guard.d.ts.map +1 -1
  168. package/dist/client/use-cookie.d.ts.map +1 -1
  169. package/dist/client/use-query-states.d.ts +9 -3
  170. package/dist/client/use-query-states.d.ts.map +1 -1
  171. package/dist/client/use-router.d.ts +1 -1
  172. package/dist/client/use-segment-params.d.ts +18 -8
  173. package/dist/client/use-segment-params.d.ts.map +1 -1
  174. package/dist/codec.js +1 -1
  175. package/dist/cookies/define-cookie.d.ts.map +1 -1
  176. package/dist/cookies/index.js +5 -5
  177. package/dist/cookies/index.js.map +1 -1
  178. package/dist/index.d.ts +4 -1
  179. package/dist/index.d.ts.map +1 -1
  180. package/dist/index.js +1009 -759
  181. package/dist/index.js.map +1 -1
  182. package/dist/params/index.js +1 -1
  183. package/dist/plugin-context.d.ts +46 -0
  184. package/dist/plugin-context.d.ts.map +1 -1
  185. package/dist/plugins/adapter-build.d.ts.map +1 -1
  186. package/dist/plugins/build-manifest.d.ts +1 -1
  187. package/dist/plugins/build-manifest.d.ts.map +1 -1
  188. package/dist/plugins/entries.d.ts.map +1 -1
  189. package/dist/plugins/fonts.d.ts.map +1 -1
  190. package/dist/plugins/request-dep/analysis.d.ts +106 -0
  191. package/dist/plugins/request-dep/analysis.d.ts.map +1 -0
  192. package/dist/plugins/request-dep/index.d.ts +75 -0
  193. package/dist/plugins/request-dep/index.d.ts.map +1 -0
  194. package/dist/plugins/request-dep/origin.d.ts +61 -0
  195. package/dist/plugins/request-dep/origin.d.ts.map +1 -0
  196. package/dist/plugins/routing.d.ts.map +1 -1
  197. package/dist/plugins/shims.d.ts.map +1 -1
  198. package/dist/plugins/static-build.d.ts +160 -8
  199. package/dist/plugins/static-build.d.ts.map +1 -1
  200. package/dist/routing/codegen-shared.d.ts +3 -44
  201. package/dist/routing/codegen-shared.d.ts.map +1 -1
  202. package/dist/routing/codegen-types.d.ts +28 -31
  203. package/dist/routing/codegen-types.d.ts.map +1 -1
  204. package/dist/routing/codegen-write.d.ts +51 -0
  205. package/dist/routing/codegen-write.d.ts.map +1 -0
  206. package/dist/routing/codegen.d.ts.map +1 -1
  207. package/dist/routing/collision-probe.d.ts +104 -0
  208. package/dist/routing/collision-probe.d.ts.map +1 -0
  209. package/dist/routing/collision-spaces.d.ts +26 -0
  210. package/dist/routing/collision-spaces.d.ts.map +1 -0
  211. package/dist/routing/convention-lint.d.ts +18 -4
  212. package/dist/routing/convention-lint.d.ts.map +1 -1
  213. package/dist/routing/export-detect.d.ts +16 -0
  214. package/dist/routing/export-detect.d.ts.map +1 -1
  215. package/dist/routing/index.js +4 -3
  216. package/dist/routing/interception.d.ts +235 -6
  217. package/dist/routing/interception.d.ts.map +1 -1
  218. package/dist/routing/link-codegen.d.ts +19 -4
  219. package/dist/routing/link-codegen.d.ts.map +1 -1
  220. package/dist/routing/manifest-codegen.d.ts +1 -7
  221. package/dist/routing/manifest-codegen.d.ts.map +1 -1
  222. package/dist/routing/scanner.d.ts.map +1 -1
  223. package/dist/routing/segment-classify.d.ts +33 -0
  224. package/dist/routing/segment-classify.d.ts.map +1 -1
  225. package/dist/routing/segment-keys.d.ts +95 -0
  226. package/dist/routing/segment-keys.d.ts.map +1 -0
  227. package/dist/routing/slot-placement.d.ts +48 -0
  228. package/dist/routing/slot-placement.d.ts.map +1 -0
  229. package/dist/routing/types.d.ts +0 -6
  230. package/dist/routing/types.d.ts.map +1 -1
  231. package/dist/routing/walkers.d.ts +6 -0
  232. package/dist/routing/walkers.d.ts.map +1 -1
  233. package/dist/schema-bridge.d.ts +60 -9
  234. package/dist/schema-bridge.d.ts.map +1 -1
  235. package/dist/search-params/define.d.ts +62 -14
  236. package/dist/search-params/define.d.ts.map +1 -1
  237. package/dist/search-params/index.d.ts +0 -1
  238. package/dist/search-params/index.d.ts.map +1 -1
  239. package/dist/search-params/index.js +221 -10
  240. package/dist/search-params/index.js.map +1 -1
  241. package/dist/search-params/parse-total.d.ts +70 -0
  242. package/dist/search-params/parse-total.d.ts.map +1 -0
  243. package/dist/search-params/wrappers.d.ts +26 -3
  244. package/dist/search-params/wrappers.d.ts.map +1 -1
  245. package/dist/server/access-gate.d.ts +19 -8
  246. package/dist/server/access-gate.d.ts.map +1 -1
  247. package/dist/server/action-handler.d.ts.map +1 -1
  248. package/dist/server/actions.d.ts +6 -3
  249. package/dist/server/actions.d.ts.map +1 -1
  250. package/dist/server/als-registry.d.ts +18 -1
  251. package/dist/server/als-registry.d.ts.map +1 -1
  252. package/dist/server/build-manifest.d.ts +13 -1
  253. package/dist/server/build-manifest.d.ts.map +1 -1
  254. package/dist/server/chain-url-parts.d.ts +82 -0
  255. package/dist/server/chain-url-parts.d.ts.map +1 -0
  256. package/dist/server/children-interception.d.ts +49 -0
  257. package/dist/server/children-interception.d.ts.map +1 -0
  258. package/dist/server/compress.d.ts.map +1 -1
  259. package/dist/server/default-status-page.d.ts +45 -0
  260. package/dist/server/default-status-page.d.ts.map +1 -0
  261. package/dist/server/deny-boundary.d.ts +148 -15
  262. package/dist/server/deny-boundary.d.ts.map +1 -1
  263. package/dist/server/deny-renderer.d.ts +15 -4
  264. package/dist/server/deny-renderer.d.ts.map +1 -1
  265. package/dist/server/error-boundary-wrapper.d.ts +85 -15
  266. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  267. package/dist/server/head-response.d.ts +35 -0
  268. package/dist/server/head-response.d.ts.map +1 -0
  269. package/dist/server/index.d.ts +0 -1
  270. package/dist/server/index.d.ts.map +1 -1
  271. package/dist/server/index.js +3 -2
  272. package/dist/server/index.js.map +1 -1
  273. package/dist/server/internal.d.ts +3 -1
  274. package/dist/server/internal.d.ts.map +1 -1
  275. package/dist/server/internal.js +712 -418
  276. package/dist/server/internal.js.map +1 -1
  277. package/dist/server/metadata-collector.d.ts +52 -0
  278. package/dist/server/metadata-collector.d.ts.map +1 -0
  279. package/dist/server/param-coercion.d.ts +22 -6
  280. package/dist/server/param-coercion.d.ts.map +1 -1
  281. package/dist/server/pipeline-helpers.d.ts +0 -18
  282. package/dist/server/pipeline-helpers.d.ts.map +1 -1
  283. package/dist/server/pipeline-interception.d.ts +59 -9
  284. package/dist/server/pipeline-interception.d.ts.map +1 -1
  285. package/dist/server/pipeline-outcome.d.ts.map +1 -1
  286. package/dist/server/pipeline-phases.d.ts.map +1 -1
  287. package/dist/server/pipeline.d.ts +11 -0
  288. package/dist/server/pipeline.d.ts.map +1 -1
  289. package/dist/server/primitives.d.ts +23 -0
  290. package/dist/server/primitives.d.ts.map +1 -1
  291. package/dist/server/publish-params.d.ts +33 -0
  292. package/dist/server/publish-params.d.ts.map +1 -0
  293. package/dist/server/request-context.d.ts +48 -0
  294. package/dist/server/request-context.d.ts.map +1 -1
  295. package/dist/server/route-element-builder.d.ts +22 -3
  296. package/dist/server/route-element-builder.d.ts.map +1 -1
  297. package/dist/server/route-handler.d.ts.map +1 -1
  298. package/dist/server/route-matcher.d.ts +13 -0
  299. package/dist/server/route-matcher.d.ts.map +1 -1
  300. package/dist/server/rsc-cache-key-guard.d.ts +78 -0
  301. package/dist/server/rsc-cache-key-guard.d.ts.map +1 -0
  302. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  303. package/dist/server/rsc-entry/deny-fallback.d.ts.map +1 -1
  304. package/dist/server/rsc-entry/error-renderer.d.ts +15 -3
  305. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  306. package/dist/server/rsc-entry/helpers.d.ts +2 -17
  307. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  308. package/dist/server/rsc-entry/index.d.ts +0 -1
  309. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  310. package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
  311. package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -1
  312. package/dist/server/rsc-entry/rsc-payload.d.ts +1 -2
  313. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  314. package/dist/server/rsc-entry/rsc-stream.d.ts +15 -2
  315. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  316. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  317. package/dist/server/skippable-prefix.d.ts +23 -0
  318. package/dist/server/skippable-prefix.d.ts.map +1 -0
  319. package/dist/server/slot-interception.d.ts +80 -0
  320. package/dist/server/slot-interception.d.ts.map +1 -0
  321. package/dist/server/slot-resolver.d.ts +70 -8
  322. package/dist/server/slot-resolver.d.ts.map +1 -1
  323. package/dist/server/ssr-bridge-types.d.ts +17 -0
  324. package/dist/server/ssr-bridge-types.d.ts.map +1 -1
  325. package/dist/server/ssr-entry.d.ts +0 -1
  326. package/dist/server/ssr-entry.d.ts.map +1 -1
  327. package/dist/server/ssr-wrappers.d.ts +24 -13
  328. package/dist/server/ssr-wrappers.d.ts.map +1 -1
  329. package/dist/server/state-tree-diff.d.ts +6 -27
  330. package/dist/server/state-tree-diff.d.ts.map +1 -1
  331. package/dist/server/static-generator.d.ts +6 -0
  332. package/dist/server/static-generator.d.ts.map +1 -1
  333. package/dist/server/static-not-found.d.ts +52 -0
  334. package/dist/server/static-not-found.d.ts.map +1 -0
  335. package/dist/server/status-code-resolver.d.ts +8 -1
  336. package/dist/server/status-code-resolver.d.ts.map +1 -1
  337. package/dist/server/tree-builder.d.ts +28 -36
  338. package/dist/server/tree-builder.d.ts.map +1 -1
  339. package/dist/server/types.d.ts +12 -7
  340. package/dist/server/types.d.ts.map +1 -1
  341. package/dist/server/utils/element-type.d.ts +40 -0
  342. package/dist/server/utils/element-type.d.ts.map +1 -0
  343. package/dist/shared/als-slots.d.ts +41 -0
  344. package/dist/shared/als-slots.d.ts.map +1 -0
  345. package/dist/shared/base-path.d.ts +56 -0
  346. package/dist/shared/base-path.d.ts.map +1 -0
  347. package/dist/shared/param-value.d.ts +80 -0
  348. package/dist/shared/param-value.d.ts.map +1 -0
  349. package/dist/shared/payload-root.d.ts +108 -0
  350. package/dist/shared/payload-root.d.ts.map +1 -0
  351. package/dist/shared/rsc-cache-key.d.ts +163 -0
  352. package/dist/shared/rsc-cache-key.d.ts.map +1 -0
  353. package/dist/shared/rsc-error-envelope.d.ts +25 -0
  354. package/dist/shared/rsc-error-envelope.d.ts.map +1 -0
  355. package/dist/shared/rsc-manifest.d.ts +28 -0
  356. package/dist/shared/rsc-manifest.d.ts.map +1 -0
  357. package/dist/shared/rsc-media-type.d.ts +40 -0
  358. package/dist/shared/rsc-media-type.d.ts.map +1 -0
  359. package/dist/shared/rsc-payload-path.d.ts +42 -0
  360. package/dist/shared/rsc-payload-path.d.ts.map +1 -0
  361. package/dist/shared/segment-info.d.ts +59 -0
  362. package/dist/shared/segment-info.d.ts.map +1 -0
  363. package/dist/shared/slot-params.d.ts +51 -0
  364. package/dist/shared/slot-params.d.ts.map +1 -0
  365. package/dist/shared/static-platform-files.d.ts +71 -0
  366. package/dist/shared/static-platform-files.d.ts.map +1 -0
  367. package/docs/api/30-api-server.mdx +1 -1
  368. package/docs/api/31-api-client.mdx +4 -2
  369. package/docs/api/33-api-search-params.mdx +38 -16
  370. package/docs/api/35-api-typescript.mdx +3 -3
  371. package/docs/api/36-cli.mdx +34 -7
  372. package/docs/learn/00-introduction.mdx +1 -1
  373. package/docs/learn/02-pages-and-layouts.mdx +2 -2
  374. package/docs/learn/05-typed-params.mdx +8 -8
  375. package/docs/learn/07-typed-routes.mdx +12 -7
  376. package/docs/learn/11-error-handling.mdx +18 -0
  377. package/docs/learn/12-client-navigation.mdx +2 -2
  378. package/docs/learn/14-deploying.mdx +23 -0
  379. package/docs/more/01-advanced-routing.mdx +173 -3
  380. package/docs/more/03-coming-from-nextjs.mdx +2 -2
  381. package/docs/more/04-metadata-and-fonts.mdx +1 -1
  382. package/docs/more/50-ai-agent-instructions.mdx +6 -4
  383. package/package.json +9 -6
  384. package/src/adapters/build-output-helper.ts +116 -3
  385. package/src/adapters/cloudflare.ts +90 -12
  386. package/src/adapters/compress-module.ts +79 -1
  387. package/src/adapters/fs-identity.ts +156 -0
  388. package/src/adapters/nitro.ts +6 -6
  389. package/src/adapters/shared.ts +196 -21
  390. package/src/adapters/types.ts +13 -1
  391. package/src/cache/fast-hash.ts +5 -0
  392. package/src/cli-check.ts +458 -0
  393. package/src/cli.ts +59 -24
  394. package/src/client/browser-entry/action-dispatch.ts +11 -5
  395. package/src/client/browser-entry/hydrate.ts +40 -29
  396. package/src/client/browser-entry/index.ts +15 -6
  397. package/src/client/browser-entry/post-hydration.ts +10 -9
  398. package/src/client/browser-entry/router-init.ts +104 -48
  399. package/src/client/browser-entry/rsc-stream.ts +11 -2
  400. package/src/client/error-boundary.tsx +85 -16
  401. package/src/client/history.ts +13 -6
  402. package/src/client/index.ts +14 -3
  403. package/src/client/internal.ts +4 -3
  404. package/src/client/link.tsx +120 -72
  405. package/src/client/navigation-api.ts +3 -3
  406. package/src/client/navigation-commit.ts +197 -0
  407. package/src/client/navigation-context.ts +40 -67
  408. package/src/client/navigation-root.tsx +326 -101
  409. package/src/client/params-context.ts +192 -0
  410. package/src/client/router-effects.ts +231 -0
  411. package/src/client/router-lifecycle.ts +288 -0
  412. package/src/client/router-pipeline.ts +393 -0
  413. package/src/client/router-ref.ts +1 -1
  414. package/src/client/router-skew.ts +30 -0
  415. package/src/client/router-types.ts +230 -0
  416. package/src/client/router.ts +243 -707
  417. package/src/client/rsc-fetch.ts +183 -106
  418. package/src/client/segment-cache.ts +129 -44
  419. package/src/client/ssr-data.ts +6 -0
  420. package/src/client/stale-client.ts +191 -0
  421. package/src/client/state.ts +14 -1
  422. package/src/client/top-loader.tsx +2 -1
  423. package/src/client/unload-guard.ts +34 -2
  424. package/src/client/use-cookie.ts +9 -2
  425. package/src/client/use-query-states.ts +102 -39
  426. package/src/client/use-router.ts +1 -1
  427. package/src/client/use-segment-params.ts +41 -18
  428. package/src/cookies/define-cookie.ts +6 -1
  429. package/src/index.ts +25 -4
  430. package/src/plugin-context.ts +58 -0
  431. package/src/plugins/adapter-build.ts +4 -0
  432. package/src/plugins/build-manifest.ts +34 -13
  433. package/src/plugins/entries.ts +4 -0
  434. package/src/plugins/fonts.ts +11 -8
  435. package/src/plugins/request-dep/analysis.ts +447 -0
  436. package/src/plugins/request-dep/index.ts +376 -0
  437. package/src/plugins/request-dep/origin.ts +310 -0
  438. package/src/plugins/routing.ts +97 -102
  439. package/src/plugins/shims.ts +0 -1
  440. package/src/plugins/static-build.ts +391 -95
  441. package/src/routing/codegen-shared.ts +3 -79
  442. package/src/routing/codegen-types.ts +28 -31
  443. package/src/routing/codegen-write.ts +139 -0
  444. package/src/routing/codegen.ts +86 -172
  445. package/src/routing/collision-probe.ts +438 -0
  446. package/src/routing/collision-spaces.ts +281 -0
  447. package/src/routing/convention-lint.ts +139 -40
  448. package/src/routing/export-detect.ts +151 -7
  449. package/src/routing/interception.ts +896 -50
  450. package/src/routing/link-codegen.ts +32 -65
  451. package/src/routing/manifest-codegen.ts +6 -62
  452. package/src/routing/scanner.ts +117 -92
  453. package/src/routing/segment-classify.ts +57 -0
  454. package/src/routing/segment-keys.ts +146 -0
  455. package/src/routing/slot-placement.ts +97 -0
  456. package/src/routing/types.ts +0 -6
  457. package/src/routing/walkers.ts +8 -0
  458. package/src/schema-bridge.ts +180 -58
  459. package/src/search-params/define.ts +108 -66
  460. package/src/search-params/index.ts +0 -1
  461. package/src/search-params/parse-total.ts +78 -0
  462. package/src/search-params/wrappers.ts +60 -11
  463. package/src/server/access-gate.tsx +60 -40
  464. package/src/server/action-handler.ts +4 -5
  465. package/src/server/actions.ts +6 -3
  466. package/src/server/als-registry.ts +18 -1
  467. package/src/server/build-manifest.ts +14 -1
  468. package/src/server/chain-url-parts.ts +163 -0
  469. package/src/server/children-interception.ts +115 -0
  470. package/src/server/compress.ts +9 -1
  471. package/src/server/default-status-page.ts +127 -0
  472. package/src/server/deny-boundary.ts +269 -41
  473. package/src/server/deny-renderer.ts +111 -39
  474. package/src/server/error-boundary-wrapper.ts +166 -79
  475. package/src/server/head-response.ts +54 -0
  476. package/src/server/index.ts +1 -3
  477. package/src/server/internal.ts +2 -2
  478. package/src/server/metadata-collector.ts +115 -0
  479. package/src/server/param-coercion.ts +51 -69
  480. package/src/server/pipeline-helpers.ts +2 -47
  481. package/src/server/pipeline-interception.ts +81 -32
  482. package/src/server/pipeline-outcome.ts +4 -5
  483. package/src/server/pipeline-phases.ts +77 -25
  484. package/src/server/pipeline.ts +57 -10
  485. package/src/server/prebuilt-runtime.ts +4 -4
  486. package/src/server/primitives.ts +25 -0
  487. package/src/server/publish-params.ts +42 -0
  488. package/src/server/request-context.ts +97 -18
  489. package/src/server/route-element-builder.ts +241 -253
  490. package/src/server/route-handler.ts +8 -8
  491. package/src/server/route-matcher.ts +21 -9
  492. package/src/server/rsc-cache-key-guard.ts +164 -0
  493. package/src/server/rsc-entry/api-handler.ts +6 -8
  494. package/src/server/rsc-entry/deny-fallback.ts +3 -2
  495. package/src/server/rsc-entry/error-renderer.ts +94 -35
  496. package/src/server/rsc-entry/helpers.ts +33 -28
  497. package/src/server/rsc-entry/index.ts +36 -33
  498. package/src/server/rsc-entry/render-route.ts +18 -10
  499. package/src/server/rsc-entry/revalidate-renderer.ts +3 -2
  500. package/src/server/rsc-entry/rsc-payload.ts +113 -40
  501. package/src/server/rsc-entry/rsc-stream.ts +29 -5
  502. package/src/server/rsc-entry/ssr-renderer.ts +38 -22
  503. package/src/server/skippable-prefix.ts +92 -0
  504. package/src/server/slot-interception.ts +168 -0
  505. package/src/server/slot-resolver.ts +263 -158
  506. package/src/server/ssr-bridge-types.ts +18 -0
  507. package/src/server/ssr-entry.ts +20 -10
  508. package/src/server/ssr-wrappers.tsx +33 -32
  509. package/src/server/state-tree-diff.ts +14 -55
  510. package/src/server/static-generator.ts +68 -29
  511. package/src/server/static-not-found.ts +134 -0
  512. package/src/server/status-code-resolver.ts +28 -11
  513. package/src/server/tree-builder.ts +35 -218
  514. package/src/server/types.ts +12 -7
  515. package/src/server/utils/element-type.ts +72 -0
  516. package/src/shared/als-slots.ts +72 -0
  517. package/src/shared/base-path.ts +80 -0
  518. package/src/shared/param-value.ts +244 -0
  519. package/src/shared/payload-root.ts +151 -0
  520. package/src/shared/rsc-cache-key.ts +269 -0
  521. package/src/shared/rsc-error-envelope.ts +31 -0
  522. package/src/shared/rsc-manifest.ts +29 -0
  523. package/src/shared/rsc-media-type.ts +43 -0
  524. package/src/shared/rsc-payload-path.ts +45 -0
  525. package/src/shared/segment-info.ts +60 -0
  526. package/src/shared/slot-params.ts +111 -0
  527. package/src/shared/static-platform-files.ts +75 -0
  528. package/dist/_chunks/build-output-helper-DOGYFb_X.js +0 -196
  529. package/dist/_chunks/build-output-helper-DOGYFb_X.js.map +0 -1
  530. package/dist/_chunks/cache-api-B-lhk9p4.js.map +0 -1
  531. package/dist/_chunks/canonicalize-DQHyFClh.js.map +0 -1
  532. package/dist/_chunks/cli-schema-sync-BTWEKJXo.js +0 -668
  533. package/dist/_chunks/cli-schema-sync-BTWEKJXo.js.map +0 -1
  534. package/dist/_chunks/define-COtkxMRT.js +0 -191
  535. package/dist/_chunks/define-COtkxMRT.js.map +0 -1
  536. package/dist/_chunks/define-c4au4I9R.js +0 -82
  537. package/dist/_chunks/define-c4au4I9R.js.map +0 -1
  538. package/dist/_chunks/fast-hash-D6hIVt1Y.js.map +0 -1
  539. package/dist/_chunks/logger-AWfuX-KJ.js.map +0 -1
  540. package/dist/_chunks/navigation-root-bUDZLw74.js +0 -124
  541. package/dist/_chunks/navigation-root-bUDZLw74.js.map +0 -1
  542. package/dist/_chunks/plugin-context---kTF5v8.js.map +0 -1
  543. package/dist/_chunks/registry-DbJPKoBp.js +0 -20
  544. package/dist/_chunks/registry-DbJPKoBp.js.map +0 -1
  545. package/dist/_chunks/router-ref-CtmF-aPv.js.map +0 -1
  546. package/dist/_chunks/schema-bridge-DT_Tn0Xf.js +0 -119
  547. package/dist/_chunks/schema-bridge-DT_Tn0Xf.js.map +0 -1
  548. package/dist/_chunks/segment-classify-Byy425ng.js.map +0 -1
  549. package/dist/_chunks/segment-context-ZDnXDkbz.js +0 -34
  550. package/dist/_chunks/segment-context-ZDnXDkbz.js.map +0 -1
  551. package/dist/_chunks/ssr-data-BOWsq18U.js.map +0 -1
  552. package/dist/_chunks/use-query-states-DFvWd-EA.js.map +0 -1
  553. package/dist/_chunks/use-segment-params-D1CzlgBo.js +0 -151
  554. package/dist/_chunks/use-segment-params-D1CzlgBo.js.map +0 -1
  555. package/dist/_chunks/walkers-_6zKFlch.js +0 -1002
  556. package/dist/_chunks/walkers-_6zKFlch.js.map +0 -1
  557. package/dist/client/error-boundary.js.map +0 -1
  558. package/dist/plugins/request-dep.d.ts +0 -32
  559. package/dist/plugins/request-dep.d.ts.map +0 -1
  560. package/dist/search-params/registry.d.ts +0 -20
  561. package/dist/search-params/registry.d.ts.map +0 -1
  562. package/dist/segment-params/define.d.ts +0 -89
  563. package/dist/segment-params/define.d.ts.map +0 -1
  564. package/dist/segment-params/index.d.ts +0 -3
  565. package/dist/segment-params/index.d.ts.map +0 -1
  566. package/dist/segment-params/index.js +0 -2
  567. package/src/plugins/request-dep.ts +0 -499
  568. package/src/search-params/registry.ts +0 -31
  569. package/src/segment-params/define.ts +0 -249
  570. package/src/segment-params/index.ts +0 -9
@@ -11,14 +11,14 @@
11
11
  'use client';
12
12
 
13
13
  import { useQueryStates as nuqsUseQueryStates } from 'nuqs';
14
- import type { SingleParser } from 'nuqs';
14
+ import type { MultiParser } from 'nuqs';
15
15
  import type {
16
16
  SearchParamCodec,
17
17
  SearchParamsDefinition,
18
18
  SetParams,
19
19
  QueryStatesOptions,
20
20
  } from '../search-params/define.js';
21
- import { getSearchParamsDefinition } from '../search-params/registry.js';
21
+ import { parseTotal } from '../search-params/parse-total.js';
22
22
 
23
23
  // ─── Codec Bridge ─────────────────────────────────────────────────
24
24
 
@@ -50,32 +50,80 @@ function unwrapNuqsValue(value: unknown): unknown {
50
50
  }
51
51
 
52
52
  /**
53
- * Bridge a timber SearchParamCodec to a nuqs-compatible SingleParser.
53
+ * Bridge a timber SearchParamCodec to a nuqs-compatible MultiParser.
54
54
  *
55
55
  * nuqs parsers: { parse(string) → T|null, serialize?(T) → string, eq?, defaultValue? }
56
56
  * timber codecs: { parse(string|string[]|undefined) → T, serialize(T) → string|null }
57
57
  *
58
- * The defaultValue is computed eagerly. Codecs are documented to return a
59
- * default rather than throw, but a throwing codec must not crash every
60
- * component that mounts the hook — treat its default as undefined and let
61
- * its error surface from server-side parse() instead.
58
+ * The defaultValue is computed eagerly, through `parseTotal` — the same
59
+ * entry point server-side `parse()` uses, so the hook and the server agree
60
+ * on what an absent param means (a bare nuqs parser answers `null`, not
61
+ * `undefined`; TIM-1350). Codecs are documented to return a default rather
62
+ * than throw, but a throwing codec must not crash every component that
63
+ * mounts the hook — treat its default as undefined and let its error
64
+ * surface from server-side parse() instead.
65
+ *
66
+ * A `null` absent-value is NOT registered as the nuqs default. nuqs
67
+ * already represents an absent key as `null`, so the hook reads the same
68
+ * value either way — but registering it makes `clearOnDefault` fire on
69
+ * `setParams({ q: null })` and delete the key before the bridged
70
+ * `serialize` runs. For a codec that encodes `null` as a real query value
71
+ * (`serialize(null) === 'none'`), that silently disagrees with
72
+ * `buildSearchParams({ q: null })`, which writes it. Same reasoning as
73
+ * `getDefaultSerialized` on the server: a codec with no value for an
74
+ * absent param has no default to register.
62
75
  */
63
- function bridgeCodec<T>(codec: SearchParamCodec<T>): SingleParser<T> & { defaultValue: T } {
64
- let defaultValue: unknown;
76
+ function bridgeCodec<T>(codec: SearchParamCodec<T>): MultiParser<T> & { defaultValue: T } {
77
+ let absent: unknown;
65
78
  try {
66
- defaultValue = codec.parse(undefined);
79
+ absent = parseTotal(codec, undefined);
67
80
  } catch {
68
- defaultValue = undefined;
81
+ absent = undefined;
69
82
  }
70
- return {
71
- parse: (v: string) => wrapNuqsValue(codec.parse(v)),
83
+
84
+ const parser = {
85
+ // `multi`, so nuqs reads the key with `searchParams.getAll()` and hands
86
+ // us EVERY value. A single parser reads `.get()` — the first value only
87
+ // — which is not the domain a timber codec is defined over. The server
88
+ // parses `?tags=a&tags=b` as `['a','b']`; a single parser made the hook
89
+ // answer `['a']` for the same URL, under a declared `string[]` that
90
+ // admitted no such disagreement (TIM-1352). Scalar codecs are unaffected:
91
+ // they receive the array and take `value[0]`, exactly as they do on the
92
+ // server, so first-value-wins is preserved through the same code path
93
+ // rather than through nuqs's reader.
94
+ //
95
+ // nuqs never calls this with an empty array — `isAbsentFromUrl` treats
96
+ // `[]` as absent and answers `defaultValue` directly — which is what
97
+ // keeps the absent case agreeing with the server's `undefined`.
98
+ //
99
+ // Reading every value is only half of it: the values must arrive in the
100
+ // SAME SHAPE the server would have produced, or the divergence just
101
+ // moves. `normalizeRaw` (search-params/define.ts) collapses a
102
+ // single-valued key to a bare string and keeps an array only for a
103
+ // repeated one, so this mirrors that rule exactly. Handing a codec
104
+ // `['3']` where the server hands it `'3'` breaks every codec whose
105
+ // `parse` is written for the scalar case — which is most hand-written
106
+ // ones, contract or no contract.
107
+ type: 'multi' as const,
108
+ // Through parseTotal, not codec.parse. nuqs's own `.withDefault(d)`
109
+ // overrides ONLY `parseServerSide`, so `parseAsInteger.withDefault(1)`
110
+ // on `?page=abc` returned 1 from the server and null from the hook —
111
+ // a divergence the declared non-nullable `number` did not admit.
112
+ parse: (v: readonly string[]) =>
113
+ wrapNuqsValue(parseTotal(codec, v.length === 1 ? v[0] : [...v])),
72
114
  serialize: (v: unknown) => {
73
115
  const value = unwrapNuqsValue(v);
74
116
  // Delegate null to the codec — some codecs encode null as a real
75
117
  // query value. undefined has no encoding; nuqs requires a string.
76
- return value === undefined ? '' : (codec.serialize(value as T) ?? '');
118
+ //
119
+ // ONE element, always. A multi parser may return several — nuqs
120
+ // appends one key per entry — but `Codec.serialize` returns a single
121
+ // string by construction, so timber cannot emit repeated keys here
122
+ // any more than `buildSearchParams` can. Widening that protocol is
123
+ // TIM-1353. Wrapping the same string keeps the URL the hook writes
124
+ // byte-identical to the one `buildSearchParams` writes.
125
+ return [value === undefined ? '' : (codec.serialize(value as T) ?? '')];
77
126
  },
78
- defaultValue: wrapNuqsValue(defaultValue),
79
127
  eq: (a: unknown, b: unknown) => {
80
128
  if (a === b) return true;
81
129
  try {
@@ -86,7 +134,26 @@ function bridgeCodec<T>(codec: SearchParamCodec<T>): SingleParser<T> & { default
86
134
  return false;
87
135
  }
88
136
  },
89
- } as SingleParser<T> & { defaultValue: T };
137
+ } as MultiParser<T> & { defaultValue: T };
138
+
139
+ if (absent !== null) parser.defaultValue = wrapNuqsValue(absent) as T;
140
+ return parser;
141
+ }
142
+
143
+ /**
144
+ * Collect `withUrlKey` aliases off a codec map.
145
+ *
146
+ * `withUrlKey(codec, 'q')` returns a codec carrying `urlKey: 'q'`, so the map
147
+ * alone is enough to reconstruct the aliases — `defineSearchParams` builds its
148
+ * own `urlKeys` from exactly this property.
149
+ */
150
+ function deriveUrlKeys(codecs: Record<string, SearchParamCodec<unknown>>): Record<string, string> {
151
+ const result: Record<string, string> = {};
152
+ for (const key of Object.keys(codecs)) {
153
+ const alias = codecs[key]?.urlKey;
154
+ if (alias) result[key] = alias;
155
+ }
156
+ return result;
90
157
  }
91
158
 
92
159
  /**
@@ -95,12 +162,12 @@ function bridgeCodec<T>(codec: SearchParamCodec<T>): SingleParser<T> & { default
95
162
  function bridgeCodecs<T extends Record<string, unknown>>(codecs: {
96
163
  [K in keyof T]: SearchParamCodec<T[K]>;
97
164
  }) {
98
- const result: Record<string, SingleParser<unknown> & { defaultValue: unknown }> = {};
165
+ const result: Record<string, MultiParser<unknown> & { defaultValue: unknown }> = {};
99
166
  for (const key of Object.keys(codecs)) {
100
167
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
101
168
  result[key] = bridgeCodec(codecs[key as keyof T]) as any;
102
169
  }
103
- return result as { [K in keyof T]: SingleParser<T[K]> & { defaultValue: T[K] } };
170
+ return result as { [K in keyof T]: MultiParser<T[K]> & { defaultValue: T[K] } };
104
171
  }
105
172
 
106
173
  // ─── Hook ─────────────────────────────────────────────────────────
@@ -113,7 +180,7 @@ function bridgeCodecs<T extends Record<string, unknown>>(codecs: {
113
180
  *
114
181
  * Usage:
115
182
  * ```ts
116
- * // Via a SearchParamsDefinition
183
+ * // Via a SearchParamsDefinition imported from the route's params.ts
117
184
  * const [params, setParams] = definition.useQueryStates()
118
185
  *
119
186
  * // Standalone with inline codecs
@@ -121,30 +188,18 @@ function bridgeCodecs<T extends Record<string, unknown>>(codecs: {
121
188
  * page: fromSchema(z.coerce.number().int().min(1).default(1)),
122
189
  * })
123
190
  * ```
191
+ *
192
+ * There is deliberately no route-string form (`useQueryStates('/products')`).
193
+ * Importing the definition from `params.ts` is the documented way to reach
194
+ * another route's codecs — it needs no runtime registry lookup and so has no
195
+ * "not registered yet" failure mode. See design/23-search-params.md
196
+ * §"Client Access".
124
197
  */
125
198
  export function useQueryStates<T extends Record<string, unknown>>(
126
- codecsOrRoute: { [K in keyof T]: SearchParamCodec<T[K]> } | string,
199
+ codecs: { [K in keyof T]: SearchParamCodec<T[K]> },
127
200
  _options?: QueryStatesOptions,
128
201
  urlKeys?: Readonly<Record<string, string>>
129
202
  ): [T, SetParams<T>] {
130
- // Route-string overload: resolve codecs from the registry
131
- let codecs: { [K in keyof T]: SearchParamCodec<T[K]> };
132
- let resolvedUrlKeys = urlKeys;
133
- if (typeof codecsOrRoute === 'string') {
134
- const definition = getSearchParamsDefinition(codecsOrRoute);
135
- if (!definition) {
136
- throw new Error(
137
- `useQueryStates('${codecsOrRoute}'): no search params registered for this route. ` +
138
- `Either the route has no search-params.ts file, or it hasn't been loaded yet. ` +
139
- `For cross-route usage, import the definition explicitly.`
140
- );
141
- }
142
- codecs = definition.codecs as { [K in keyof T]: SearchParamCodec<T[K]> };
143
- resolvedUrlKeys = definition.urlKeys;
144
- } else {
145
- codecs = codecsOrRoute;
146
- }
147
-
148
203
  const bridged = bridgeCodecs(codecs);
149
204
 
150
205
  // Forward hook-level options (shallow, scroll, history) to nuqs.
@@ -155,7 +210,15 @@ export function useQueryStates<T extends Record<string, unknown>>(
155
210
  if (_options?.shallow !== undefined) nuqsOptions.shallow = _options.shallow;
156
211
  if (_options?.scroll !== undefined) nuqsOptions.scroll = _options.scroll;
157
212
  if (_options?.history !== undefined) nuqsOptions.history = _options.history;
158
- if (resolvedUrlKeys && Object.keys(resolvedUrlKeys).length > 0) {
213
+ // `withUrlKey` attaches the alias to the codec itself — that is the design's
214
+ // "URL keys travel with codecs" principle — so the aliases are derivable
215
+ // here and must be, for the inline codec-map form: nobody passes `urlKeys`
216
+ // on that path, and without this an aliased bundle silently read and wrote
217
+ // the property name instead of the alias. `bindUseQueryStates` still passes
218
+ // the definition's precomputed map, which wins on conflict; it is built from
219
+ // these same codecs, so the two agree by construction rather than by luck.
220
+ const resolvedUrlKeys = { ...deriveUrlKeys(codecs), ...urlKeys };
221
+ if (Object.keys(resolvedUrlKeys).length > 0) {
159
222
  nuqsOptions.urlKeys = resolvedUrlKeys;
160
223
  }
161
224
 
@@ -14,7 +14,7 @@
14
14
  * In timber, navigation calls reactRoot.render() which is a root-level
15
15
  * render — startTransition has no effect on root renders.
16
16
  *
17
- * Navigation state (params, pathname) is delivered atomically via
17
+ * Navigation state (pathname, search) is delivered atomically via
18
18
  * NavigationContext embedded in the element tree passed to
19
19
  * reactRoot.render(). See design/19-client-navigation.md §"NavigationContext".
20
20
  *
@@ -18,11 +18,11 @@
18
18
  * (populated by ssr-entry.ts) to ensure correct per-request isolation
19
19
  * across concurrent requests with streaming Suspense.
20
20
  *
21
- * Reactivity: On the client, useParams() reads from NavigationContext
22
- * which is updated atomically with the RSC tree render. This replaces
23
- * the previous useSyncExternalStore approach that suffered from a
24
- * timing gap between tree render and store notification — causing
25
- * preserved layout components to briefly show stale active state.
21
+ * Reactivity: On the client, useParams() reads from ParamsContext, published
22
+ * by the one provider the client renders above the merge point
23
+ * (`PayloadRoot`). Params update atomically with the tree because they travel
24
+ * on the same payload root — there is no separate channel that could be
25
+ * seeded a render early or late (TIM-1294, TIM-1297).
26
26
  *
27
27
  * All mutable state is delegated to client/state.ts for singleton guarantees.
28
28
  * See design/18-build-system.md §"Singleton State Registry"
@@ -32,8 +32,15 @@
32
32
 
33
33
  import type { Routes } from '../index.js';
34
34
  import { getSsrData } from './ssr-data.js';
35
- import { currentParams, _setCurrentParams, paramsListeners } from './state.js';
36
- import { useNavigationContext } from './navigation-context.js';
35
+ import {
36
+ currentParams,
37
+ currentSlotParams,
38
+ _setCurrentParams,
39
+ _setCurrentSlotParams,
40
+ paramsListeners,
41
+ } from './state.js';
42
+ import { resolveSegmentParams, type SlotParamsRecord } from '../shared/slot-params.js';
43
+ import { useParamsContext } from './params-context.js';
37
44
 
38
45
  // ---------------------------------------------------------------------------
39
46
  // Module-level subscribe/notify pattern — kept for backward compat and tests
@@ -81,6 +88,18 @@ export function setCurrentParams(params: Record<string, string | string[]>): voi
81
88
  _setCurrentParams(params);
82
89
  }
83
90
 
91
+ /**
92
+ * Set the per-slot params snapshot in the module-level store.
93
+ *
94
+ * Paired with `setCurrentParams`: the router calls both on every navigation,
95
+ * including with `null` when a response carries no slot params, so a slot's
96
+ * params from the *previous* route cannot be read on the next one. Fill and
97
+ * serve are paired; so are fill and clear. See TIM-1285.
98
+ */
99
+ export function setCurrentSlotParams(slotParams: SlotParamsRecord | null): void {
100
+ _setCurrentSlotParams(slotParams);
101
+ }
102
+
84
103
  /**
85
104
  * Notify all legacy subscribers that params have changed.
86
105
  *
@@ -105,9 +124,9 @@ export function notifyParamsListeners(): void {
105
124
  * The optional `_route` argument exists only for TypeScript narrowing —
106
125
  * it does not affect the runtime return value.
107
126
  *
108
- * On the client, reads from NavigationContext (provided by
109
- * NavigationProvider in renderRoot). This ensures params update
110
- * atomically with the RSC tree — no timing gap.
127
+ * On the client, reads from ParamsContext, published by `PayloadRoot` above
128
+ * everything the navigation renders. Params update atomically with the RSC
129
+ * tree — no timing gap.
111
130
  *
112
131
  * During SSR, reads from the ALS-backed SSR data context to ensure
113
132
  * per-request isolation across concurrent requests with streaming Suspense.
@@ -123,15 +142,17 @@ export function useSegmentParams<R extends keyof Routes>(
123
142
  segmentPath: R
124
143
  ): Routes[R] extends { segmentParams: infer P } ? P : Record<string, string | string[]>;
125
144
  export function useSegmentParams(segmentPath?: string): Record<string, string | string[]>;
126
- export function useSegmentParams(_segmentPath?: string): Record<string, string | string[]> {
127
- // Try reading from NavigationContext (client-side, inside React tree).
128
- // During SSR, no NavigationProvider is mounted, so this returns null.
129
- // When called outside a React component, useContext throws — caught below.
145
+ export function useSegmentParams(segmentPath?: string): Record<string, string | string[]> {
146
+ // Try the client-owned provider first. It sits above everything a navigation
147
+ // renders, so any component on the page — initial document, full navigation,
148
+ // or a layout the server skipped — has one above it. Absent during SSR,
149
+ // where the ALS path below is the answer. When called outside a React
150
+ // component, useContext throws — caught below.
130
151
  try {
131
152
  // eslint-disable-next-line react-hooks/rules-of-hooks -- conditional on environment, not render path
132
- const navContext = useNavigationContext();
133
- if (navContext !== null) {
134
- return navContext.params;
153
+ const paramsContext = useParamsContext();
154
+ if (paramsContext !== null) {
155
+ return resolveSegmentParams(paramsContext.params, paramsContext.slotParams, segmentPath);
135
156
  }
136
157
  } catch {
137
158
  // No React dispatcher available (called outside a component).
@@ -140,5 +161,7 @@ export function useSegmentParams(_segmentPath?: string): Record<string, string |
140
161
 
141
162
  // SSR path: read from ALS-backed SSR data context.
142
163
  // Falls back to module-level currentParams for tests.
143
- return getSsrData()?.params ?? currentParams;
164
+ const ssrData = getSsrData();
165
+ if (ssrData) return resolveSegmentParams(ssrData.params, ssrData.slotParams, segmentPath);
166
+ return resolveSegmentParams(currentParams, currentSlotParams, segmentPath);
144
167
  }
@@ -147,7 +147,12 @@ function deleteClientCookie(name: string, options?: ClientCookieOptions): void {
147
147
  // ─── Standard Schema Auto-Detection ───────────────────────────────────────
148
148
 
149
149
  function resolveCodec<T>(codecOrSchema: CookieCodec<T> | StandardSchemaV1<T>): CookieCodec<T> {
150
- return resolveCodecOrSchema('codec', codecOrSchema, 'search') as CookieCodec<T>;
150
+ // 'cookie', not 'search': a cookie carries one string per name, so the
151
+ // repeated-key array shape the search bridge tolerates does not exist
152
+ // here — and `serialize` returning `null` means DELETE for a cookie
153
+ // where it means "omit the key" for a search param. See
154
+ // schema-bridge.ts §fromCookieSchema.
155
+ return resolveCodecOrSchema('codec', codecOrSchema, 'cookie') as CookieCodec<T>;
151
156
  }
152
157
 
153
158
  // ─── Factory ──────────────────────────────────────────────────────────────
package/src/index.ts CHANGED
@@ -31,7 +31,7 @@ import { timberChunks } from './plugins/chunks';
31
31
  import { clientChunkGroup } from './plugins/client-chunks';
32
32
  import { timberServerBundle } from './plugins/server-bundle';
33
33
  import { timberCacheTransform } from './plugins/cache';
34
- import { timberRequestDep } from './plugins/request-dep';
34
+ import { timberRequestDep } from './plugins/request-dep/index.js';
35
35
  import { timberPrebuilt } from './plugins/prebuilt';
36
36
  import { timberPrerenderSugar } from './plugins/prerender-sugar';
37
37
  import { timberCloudflareWasm } from './plugins/cloudflare-wasm';
@@ -42,7 +42,7 @@ import { resolveEncryptionKeyExpression, shouldEnableEncryption } from './server
42
42
  import { createHoldingServer } from './dev-tools/holding-server.js';
43
43
  import { resolveStartPort, startDevServerPort } from './server/port-resolution.js';
44
44
  import type { TimberUserConfig } from './config-types.js';
45
- import type { PluginContext } from './plugin-context.js';
45
+ import type { PluginContext, TimberPluginApi } from './plugin-context.js';
46
46
  import {
47
47
  createPluginContext,
48
48
  loadTimberConfigFile,
@@ -69,7 +69,10 @@ export type { Metadata, MetadataRoute, MetadataHandler, MetadataResult } from '.
69
69
  *
70
70
  * Each key is a route path pattern. Values have:
71
71
  * segmentParams: shape of URL segment params (e.g. { id: string })
72
- * searchParams: parsed type from search-params.ts, or {} if none
72
+ *
73
+ * There is no `searchParams` member: since TIM-1343 the framework does not
74
+ * scan for search-param definitions, so it has nothing to type them with. A
75
+ * definition carries its own type to call sites through an ordinary import.
73
76
  *
74
77
  * This interface is empty by default and populated via codegen.
75
78
  * See design/09-typescript.md §"Typed Routes".
@@ -245,6 +248,21 @@ export function timber(config?: TimberUserConfig): PluginOption[] {
245
248
  // config() hook must NOT return a `plugins` field (Vite ignores it).
246
249
  const rootSync: Plugin = {
247
250
  name: 'timber-root-sync',
251
+
252
+ // The plugin context, published for out-of-band callers that need the
253
+ // *resolved* configuration rather than a second reading of the files it
254
+ // came from. `timber check` is the one today: it runs Vite's
255
+ // `resolveConfig()` and reads root, appDir, and pageExtensions from here,
256
+ // so it scans exactly the tree `timber build` builds — including config
257
+ // passed inline as `timber({ ... })`, which lives only in this closure and
258
+ // is invisible to anything that re-reads `timber.config.ts`. See
259
+ // `cli-check.ts` and design/11-platform.md §`timber check`.
260
+ //
261
+ // Valid from `configResolved` onward; `appDir` and `root` are unset before
262
+ // that, which is why the reader runs a full `resolveConfig()` rather than
263
+ // just loading the config file.
264
+ api: { getContext: () => ctx } satisfies TimberPluginApi,
265
+
248
266
  async config(userConfig, { command, isPreview }) {
249
267
  // ── Load timber.config.ts from the correct root ───────────────
250
268
  // Vite's `config` hook fires before `configResolved`. The user's
@@ -388,7 +406,6 @@ export function timber(config?: TimberUserConfig): PluginOption[] {
388
406
  '@timber-js/app/cookies',
389
407
  '@timber-js/app/cache',
390
408
  '@timber-js/app/search-params',
391
- '@timber-js/app/segment-params',
392
409
  '@timber-js/app/params',
393
410
  '@timber-js/app/codec',
394
411
  ];
@@ -464,6 +481,10 @@ export function timber(config?: TimberUserConfig): PluginOption[] {
464
481
  ctx.root = resolved.root;
465
482
  ctx.appDir = resolveAppDir(resolved.root, ctx.config.appDir);
466
483
  ctx.dev = resolved.command === 'serve';
484
+ // Vite's resolved base — the deployment path prefix. Captured once
485
+ // here so every sub-plugin that emits a URL (assets, fonts, RSC
486
+ // payloads) reads the same value. See TIM-1261.
487
+ ctx.base = resolved.base;
467
488
 
468
489
  // Register all timber config file candidates as Vite config file
469
490
  // dependencies so Vite's built-in restart-on-change handles them
@@ -73,6 +73,21 @@ export interface PluginContext {
73
73
  root: string;
74
74
  /** Whether the dev server is running (set by timber-root-sync in configResolved) */
75
75
  dev: boolean;
76
+ /**
77
+ * Vite's resolved `base` (set by timber-root-sync in configResolved).
78
+ * Always has a trailing slash; `'/'` unless the app is deployed under a
79
+ * sub-path. Every URL the framework emits — assets, fonts, RSC payloads —
80
+ * carries this prefix. This is the single copy: sub-plugins read it here
81
+ * rather than capturing `config.base` in their own configResolved.
82
+ *
83
+ * **Availability:** written by timber-root-sync, which has no `enforce`, so
84
+ * it is populated from `buildStart`/`load`/`generateBundle`/`configureServer`
85
+ * onward — but NOT during the `configResolved` of an `enforce: 'pre'`
86
+ * plugin, which Vite runs first. A pre plugin that needs the base inside
87
+ * its own `configResolved` must read `config.base` there (timber-fonts
88
+ * does). See TIM-1261.
89
+ */
90
+ base: string;
76
91
  /** CSS build manifest (populated by adapter after client build, null in dev) */
77
92
  buildManifest: BuildManifest | null;
78
93
  /** Per-build deployment ID for version skew detection (null in dev) */
@@ -98,6 +113,22 @@ export interface PluginContext {
98
113
  * populate per-route modulepreload entries from clientReferenceDeps.
99
114
  */
100
115
  routeClientRefKeys?: Map<string, Set<string>>;
116
+ /**
117
+ * Static request-dependency verdict per segment entry file, keyed by the
118
+ * absolute `filePath` the route scanner produced. Computed once by
119
+ * `timber-request-dep`'s RSC `buildEnd` and serialized into
120
+ * `buildManifest.requestDep` by `timber-build-manifest` (build only — dev
121
+ * answers the same question through the `Symbol.for('timber:request-dep')`
122
+ * bridge instead).
123
+ *
124
+ * `undefined` and `{}` are different states and the difference is the whole
125
+ * of TIM-1300: an empty object means the analysis ran and found no segments,
126
+ * `undefined` means it never ran, and the runtime cannot tell them apart —
127
+ * every key is absent either way, so every segment falls to the conservative
128
+ * `true` and nothing is ever skipped. The build fails loudly on `undefined`
129
+ * rather than shipping that silently.
130
+ */
131
+ requestDepMap?: Record<string, boolean>;
101
132
  /**
102
133
  * Maps absolute module IDs of client references in non-facade RSC
103
134
  * chunks to the absolute paths of their consuming facade modules.
@@ -217,6 +248,32 @@ export class ParseMemo {
217
248
 
218
249
  // ── App directory resolution ──────────────────────────────────────────────
219
250
 
251
+ // ── Plugin API (Vite `plugin.api`) ────────────────────────────────────────
252
+
253
+ /**
254
+ * What `timber-root-sync` publishes on its Vite `plugin.api`.
255
+ *
256
+ * The single supported way to read timber's *resolved* configuration from
257
+ * outside the plugin pipeline. Re-reading `timber.config.ts` is not equivalent:
258
+ * config passed inline as `timber({ ... })` in `vite.config.ts` exists only in
259
+ * the plugin's closure, and `root`/`appDir` are resolved against Vite's root
260
+ * rather than the caller's cwd.
261
+ */
262
+ export interface TimberPluginApi {
263
+ /** The live plugin context. Fully populated from `configResolved` onward. */
264
+ getContext(): PluginContext;
265
+ }
266
+
267
+ /** Narrow an unknown Vite `plugin.api` to timber's. */
268
+ export function isTimberPluginApi(api: unknown): api is TimberPluginApi {
269
+ return (
270
+ typeof api === 'object' &&
271
+ api !== null &&
272
+ 'getContext' in api &&
273
+ typeof api.getContext === 'function'
274
+ );
275
+ }
276
+
220
277
  /**
221
278
  * Resolve the app directory. Checks (in order):
222
279
  * 1. Explicit `configAppDir` from timber.config.ts
@@ -258,6 +315,7 @@ export function createPluginContext(config?: TimberUserConfig, root?: string): P
258
315
  appDir: join(projectRoot, 'app'),
259
316
  root: projectRoot,
260
317
  dev: false,
318
+ base: '/',
261
319
  buildManifest: null,
262
320
  deploymentId: null,
263
321
  timer: createStartupTimer(),
@@ -21,6 +21,7 @@ import type { PluginContext } from '../plugin-context.js';
21
21
  import type { TimberPlatformAdapter, TimberConfig } from '../adapters/types.js';
22
22
  import type { BuildManifest } from '../server/build-manifest.js';
23
23
  import { swallow } from '../server/logger.js';
24
+ import { normalizeBasePath } from '../shared/base-path.js';
24
25
 
25
26
  export function timberAdapterBuild(ctx: PluginContext): Plugin {
26
27
  return {
@@ -85,6 +86,9 @@ export function timberAdapterBuild(ctx: PluginContext): Plugin {
85
86
 
86
87
  const adapterConfig: TimberConfig = {
87
88
  root: ctx.root,
89
+ // Normalized once here, not in each adapter: the platform files
90
+ // adapters write address deployed-URL space (TIM-1274).
91
+ base: normalizeBasePath(ctx.base),
88
92
  output: ctx.config.output ?? 'server',
89
93
  clientJavascriptDisabled: ctx.clientJavascript.disabled,
90
94
  manifestInit,
@@ -20,7 +20,7 @@ import { randomUUID, createHash } from 'node:crypto';
20
20
  import { readFileSync } from 'node:fs';
21
21
  import type { Plugin, ResolvedConfig } from 'vite';
22
22
  import type { PluginContext } from '../plugin-context.js';
23
- import type { BuildManifest } from '../server/build-manifest.js';
23
+ import { EMPTY_BUILD_MANIFEST, type BuildManifest } from '../server/build-manifest.js';
24
24
  import type { SegmentNode, RouteFile } from '../routing/types.js';
25
25
  import { isDynamicMetadataExtension } from '../server/metadata-routes.js';
26
26
 
@@ -335,14 +335,12 @@ function walkModuleImports(
335
335
  * Hooks: configResolved, resolveId, load, generateBundle (client and RSC envs)
336
336
  */
337
337
  export function timberBuildManifest(ctx: PluginContext): Plugin {
338
- let resolvedBase = '/';
339
338
  let isDev = false;
340
339
 
341
340
  return {
342
341
  name: 'timber-build-manifest',
343
342
 
344
343
  configResolved(config: ResolvedConfig) {
345
- resolvedBase = config.base;
346
344
  isDev = config.command === 'serve';
347
345
 
348
346
  // Generate a per-build deployment ID early so virtual:timber-config
@@ -373,13 +371,18 @@ export function timberBuildManifest(ctx: PluginContext): Plugin {
373
371
  load(id: string) {
374
372
  if (id !== RESOLVED_VIRTUAL_ID) return null;
375
373
 
374
+ // Serialized, not restated: an empty manifest is described once, in
375
+ // server/build-manifest.ts. Both branches below emitted their own object
376
+ // literal and had already drifted apart — see EMPTY_BUILD_MANIFEST.
377
+ const empty = JSON.stringify(EMPTY_BUILD_MANIFEST);
378
+
376
379
  // In dev mode, return empty manifest — Vite HMR handles CSS.
377
380
  if (isDev) {
378
381
  return [
379
382
  '// Auto-generated build manifest — do not edit.',
380
383
  '// Dev mode: empty manifest (Vite HMR handles CSS/JS).',
381
384
  '',
382
- 'const manifest = { css: {}, js: {}, modulepreload: {}, fonts: {}, metadataRouteHashes: {} };',
385
+ `const manifest = ${empty};`,
383
386
  '',
384
387
  'export default manifest;',
385
388
  ].join('\n');
@@ -389,11 +392,17 @@ export function timberBuildManifest(ctx: PluginContext): Plugin {
389
392
  // The adapter writes a _timber-manifest-init.js that sets this global
390
393
  // before the RSC handler imports this module. ESM evaluation order
391
394
  // guarantees the global is set by the time this code runs.
395
+ //
396
+ // The literal is only reached when the global is unset — an app built
397
+ // with no adapter, which writes no init module. It is NOT the map the
398
+ // build computed; that lives in _timber-manifest-init.js (TIM-1300).
392
399
  return [
393
400
  '// Auto-generated build manifest — do not edit.',
394
401
  '// Production: reads manifest from globalThis (set by _timber-manifest-init.js).',
402
+ '// The object below is only the fallback for when that global is unset —',
403
+ '// the real manifest, including the requestDep map, is in that init module.',
395
404
  '',
396
- 'const manifest = globalThis.__TIMBER_BUILD_MANIFEST__ ?? { css: {}, js: {}, modulepreload: {}, fonts: {}, metadataRouteHashes: {}, requestDep: {} };',
405
+ `const manifest = globalThis.__TIMBER_BUILD_MANIFEST__ ?? ${empty};`,
397
406
  '',
398
407
  'export default manifest;',
399
408
  ].join('\n');
@@ -436,21 +445,33 @@ export function timberBuildManifest(ctx: PluginContext): Plugin {
436
445
  }
437
446
 
438
447
  if (envName === 'client') {
439
- ctx.buildManifest = buildManifestFromBundle(bundle, resolvedBase, ctx.root);
448
+ ctx.buildManifest = buildManifestFromBundle(bundle, ctx.base, ctx.root);
440
449
 
441
450
  // Compute cache-busting hashes for metadata route files
442
451
  if (ctx.routeTree) {
443
452
  ctx.buildManifest.metadataRouteHashes = computeMetadataRouteHashes(ctx.routeTree.root);
444
453
  }
445
454
 
446
- // Attach static request-dependency map from the request-dep plugin.
447
- // Computed in the RSC buildEnd hook and stored on ctx.
448
- const requestDepMap = (ctx as unknown as Record<string, unknown>).requestDepMap as
449
- | Record<string, boolean>
450
- | undefined;
451
- if (requestDepMap) {
452
- ctx.buildManifest.requestDep = requestDepMap;
455
+ // Attach the static request-dependency map from the request-dep
456
+ // plugin, computed in the RSC `buildEnd` hook. The RSC environment is
457
+ // built before the client one, so the field is populated by now.
458
+ //
459
+ // Absent means the RSC `buildEnd` never ran — a broken plugin pipeline,
460
+ // not an app without segments, which produces `{}`. Serializing that as
461
+ // an empty map is indistinguishable at runtime from an analysis that
462
+ // found nothing (`server/request-dep.ts` answers `true` for any absent
463
+ // key either way), so every segment and slot silently stops being a
464
+ // skip candidate and slot caching is off with nothing to show for it.
465
+ // Fail the build instead (TIM-1300).
466
+ if (ctx.requestDepMap === undefined) {
467
+ throw new Error(
468
+ '[timber] Build manifest: the request-dependency map was never computed. ' +
469
+ "The RSC environment's buildEnd hook did not run before the client build, " +
470
+ 'so no segment or slot could be skipped on client navigation. This is a ' +
471
+ 'plugin pipeline bug — timber-request-dep must run in the rsc environment.'
472
+ );
453
473
  }
474
+ ctx.buildManifest.requestDep = ctx.requestDepMap;
454
475
 
455
476
  // When client JavaScript is disabled, strip JS chunks from the bundle
456
477
  // so Rollup never writes them to disk. CSS assets are preserved —
@@ -136,6 +136,10 @@ function generateConfigModule(ctx: PluginContext): string {
136
136
  csrf: ctx.config.csrf ?? true,
137
137
  allowedOrigins: ctx.config.allowedOrigins,
138
138
  clientJavascript: ctx.clientJavascript,
139
+ // Vite's resolved `base` — the deployment path prefix. The client needs
140
+ // it to address pre-generated RSC payloads in static mode, which live
141
+ // below the base like every other emitted file (TIM-1261).
142
+ base: ctx.base,
139
143
  dev: ctx.dev ?? false,
140
144
  slowPhaseMs: ctx.config.dev?.slowPhaseMs ?? 200,
141
145
  slowRequestMs: ctx.config.slowRequestMs ?? 3000,