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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (610) hide show
  1. package/dist/_chunks/actions-DLnUaR65.js +421 -0
  2. package/dist/_chunks/actions-DLnUaR65.js.map +1 -0
  3. package/dist/_chunks/{als-registry-B7DbZ2hS.js → als-registry-HS0LGUl2.js} +1 -1
  4. package/dist/_chunks/als-registry-HS0LGUl2.js.map +1 -0
  5. package/dist/_chunks/chunk-BYIpzuS7.js +39 -0
  6. package/dist/_chunks/{debug-gwlJkDuf.js → debug-ECi_61pb.js} +2 -2
  7. package/dist/_chunks/debug-ECi_61pb.js.map +1 -0
  8. package/dist/_chunks/define-C77ScO0m.js +106 -0
  9. package/dist/_chunks/define-C77ScO0m.js.map +1 -0
  10. package/dist/_chunks/define-Itxvcd7F.js +199 -0
  11. package/dist/_chunks/define-Itxvcd7F.js.map +1 -0
  12. package/dist/_chunks/define-cookie-BowvzoP0.js +94 -0
  13. package/dist/_chunks/define-cookie-BowvzoP0.js.map +1 -0
  14. package/dist/_chunks/{format-DviM89f0.js → dev-warnings-DpGRGoDi.js} +5 -44
  15. package/dist/_chunks/dev-warnings-DpGRGoDi.js.map +1 -0
  16. package/dist/_chunks/format-CYBGxKtc.js +14 -0
  17. package/dist/_chunks/format-CYBGxKtc.js.map +1 -0
  18. package/dist/_chunks/{interception-BOoWmLUA.js → interception-DRlhJWbu.js} +219 -97
  19. package/dist/_chunks/interception-DRlhJWbu.js.map +1 -0
  20. package/dist/_chunks/merge-search-params-Cm_KIWDX.js +41 -0
  21. package/dist/_chunks/merge-search-params-Cm_KIWDX.js.map +1 -0
  22. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → metadata-routes-DS3eKNmf.js} +1 -1
  23. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js.map → metadata-routes-DS3eKNmf.js.map} +1 -1
  24. package/dist/_chunks/request-context-CK5tZqIP.js +478 -0
  25. package/dist/_chunks/request-context-CK5tZqIP.js.map +1 -0
  26. package/dist/_chunks/schema-bridge-C3xl_vfb.js +86 -0
  27. package/dist/_chunks/schema-bridge-C3xl_vfb.js.map +1 -0
  28. package/dist/_chunks/segment-classify-BDNn6EzD.js +65 -0
  29. package/dist/_chunks/segment-classify-BDNn6EzD.js.map +1 -0
  30. package/dist/_chunks/segment-context-fHFLF1PE.js +34 -0
  31. package/dist/_chunks/segment-context-fHFLF1PE.js.map +1 -0
  32. package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-DzuI0bIV.js} +1 -1
  33. package/dist/_chunks/{ssr-data-MjmprTmO.js.map → ssr-data-DzuI0bIV.js.map} +1 -1
  34. package/dist/_chunks/stale-reload-BX5gL1r-.js +64 -0
  35. package/dist/_chunks/stale-reload-BX5gL1r-.js.map +1 -0
  36. package/dist/_chunks/{tracing-CemImE6h.js → tracing-CCYbKn5n.js} +60 -9
  37. package/dist/_chunks/tracing-CCYbKn5n.js.map +1 -0
  38. package/dist/_chunks/use-params-Br9YSUFV.js +295 -0
  39. package/dist/_chunks/use-params-Br9YSUFV.js.map +1 -0
  40. package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-BiV5GJgm.js} +7 -4
  41. package/dist/_chunks/use-query-states-BiV5GJgm.js.map +1 -0
  42. package/dist/adapters/cloudflare-dev.d.ts +109 -0
  43. package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
  44. package/dist/adapters/cloudflare-dev.js +73 -0
  45. package/dist/adapters/cloudflare-dev.js.map +1 -0
  46. package/dist/adapters/cloudflare-kv-cache.d.ts +64 -0
  47. package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
  48. package/dist/adapters/cloudflare-kv-cache.js +95 -0
  49. package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
  50. package/dist/adapters/cloudflare.d.ts +148 -12
  51. package/dist/adapters/cloudflare.d.ts.map +1 -1
  52. package/dist/adapters/cloudflare.js +135 -11
  53. package/dist/adapters/cloudflare.js.map +1 -1
  54. package/dist/adapters/compress-module.d.ts.map +1 -1
  55. package/dist/adapters/nitro.d.ts +17 -1
  56. package/dist/adapters/nitro.d.ts.map +1 -1
  57. package/dist/adapters/nitro.js +56 -13
  58. package/dist/adapters/nitro.js.map +1 -1
  59. package/dist/cache/cache-api.d.ts +24 -0
  60. package/dist/cache/cache-api.d.ts.map +1 -0
  61. package/dist/cache/handler-store.d.ts +31 -0
  62. package/dist/cache/handler-store.d.ts.map +1 -0
  63. package/dist/cache/index.d.ts +23 -7
  64. package/dist/cache/index.d.ts.map +1 -1
  65. package/dist/cache/index.js +142 -80
  66. package/dist/cache/index.js.map +1 -1
  67. package/dist/cache/singleflight.d.ts +18 -1
  68. package/dist/cache/singleflight.d.ts.map +1 -1
  69. package/dist/cache/sizeof.d.ts +22 -0
  70. package/dist/cache/sizeof.d.ts.map +1 -0
  71. package/dist/cache/timber-cache.d.ts +1 -1
  72. package/dist/cache/timber-cache.d.ts.map +1 -1
  73. package/dist/cli.d.ts +6 -1
  74. package/dist/cli.d.ts.map +1 -1
  75. package/dist/cli.js +8 -3
  76. package/dist/cli.js.map +1 -1
  77. package/dist/client/browser-dev.d.ts +27 -1
  78. package/dist/client/browser-dev.d.ts.map +1 -1
  79. package/dist/client/browser-entry/action-dispatch.d.ts +17 -0
  80. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -0
  81. package/dist/client/browser-entry/hmr.d.ts +21 -0
  82. package/dist/client/browser-entry/hmr.d.ts.map +1 -0
  83. package/dist/client/browser-entry/hydrate.d.ts +46 -0
  84. package/dist/client/browser-entry/hydrate.d.ts.map +1 -0
  85. package/dist/client/browser-entry/index.d.ts +30 -0
  86. package/dist/client/browser-entry/index.d.ts.map +1 -0
  87. package/dist/client/browser-entry/post-hydration.d.ts +26 -0
  88. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
  89. package/dist/client/browser-entry/router-init.d.ts +23 -0
  90. package/dist/client/browser-entry/router-init.d.ts.map +1 -0
  91. package/dist/client/browser-entry/rsc-stream.d.ts +24 -0
  92. package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -0
  93. package/dist/client/browser-entry/scroll.d.ts +19 -0
  94. package/dist/client/browser-entry/scroll.d.ts.map +1 -0
  95. package/dist/client/error-boundary.d.ts +12 -5
  96. package/dist/client/error-boundary.d.ts.map +1 -1
  97. package/dist/client/error-boundary.js +10 -4
  98. package/dist/client/error-boundary.js.map +1 -1
  99. package/dist/client/error-reconstituter.d.ts +54 -0
  100. package/dist/client/error-reconstituter.d.ts.map +1 -0
  101. package/dist/client/form.d.ts +6 -3
  102. package/dist/client/form.d.ts.map +1 -1
  103. package/dist/client/history.d.ts +19 -4
  104. package/dist/client/history.d.ts.map +1 -1
  105. package/dist/client/index.d.ts +9 -21
  106. package/dist/client/index.d.ts.map +1 -1
  107. package/dist/client/index.js +229 -1018
  108. package/dist/client/index.js.map +1 -1
  109. package/dist/client/internal.d.ts +18 -0
  110. package/dist/client/internal.d.ts.map +1 -0
  111. package/dist/client/internal.js +890 -0
  112. package/dist/client/internal.js.map +1 -0
  113. package/dist/client/link-pending-store.d.ts +63 -0
  114. package/dist/client/link-pending-store.d.ts.map +1 -0
  115. package/dist/client/link.d.ts +62 -55
  116. package/dist/client/link.d.ts.map +1 -1
  117. package/dist/client/nav-link-store.d.ts +36 -0
  118. package/dist/client/nav-link-store.d.ts.map +1 -0
  119. package/dist/client/navigation-api-types.d.ts +90 -0
  120. package/dist/client/navigation-api-types.d.ts.map +1 -0
  121. package/dist/client/navigation-api.d.ts +115 -0
  122. package/dist/client/navigation-api.d.ts.map +1 -0
  123. package/dist/client/navigation-context.d.ts +13 -2
  124. package/dist/client/navigation-context.d.ts.map +1 -1
  125. package/dist/client/{transition-root.d.ts → navigation-root.d.ts} +42 -8
  126. package/dist/client/navigation-root.d.ts.map +1 -0
  127. package/dist/client/nuqs-adapter.d.ts.map +1 -1
  128. package/dist/client/router-ref.d.ts +1 -1
  129. package/dist/client/router.d.ts +70 -4
  130. package/dist/client/router.d.ts.map +1 -1
  131. package/dist/client/rsc-fetch.d.ts +38 -3
  132. package/dist/client/rsc-fetch.d.ts.map +1 -1
  133. package/dist/client/segment-cache.d.ts +1 -1
  134. package/dist/client/segment-cache.d.ts.map +1 -1
  135. package/dist/client/segment-outlet.d.ts +63 -0
  136. package/dist/client/segment-outlet.d.ts.map +1 -0
  137. package/dist/client/ssr-data.d.ts +13 -4
  138. package/dist/client/ssr-data.d.ts.map +1 -1
  139. package/dist/client/stale-reload.d.ts +15 -0
  140. package/dist/client/stale-reload.d.ts.map +1 -1
  141. package/dist/client/top-loader.d.ts +5 -5
  142. package/dist/client/top-loader.d.ts.map +1 -1
  143. package/dist/client/use-link-status.d.ts +5 -5
  144. package/dist/client/use-link-status.d.ts.map +1 -1
  145. package/dist/client/use-params.d.ts +6 -4
  146. package/dist/client/use-params.d.ts.map +1 -1
  147. package/dist/client/{use-navigation-pending.d.ts → use-pending-navigation.d.ts} +4 -4
  148. package/dist/client/use-pending-navigation.d.ts.map +1 -0
  149. package/dist/client/use-query-states.d.ts +1 -1
  150. package/dist/client/use-query-states.d.ts.map +1 -1
  151. package/dist/client/use-router.d.ts +1 -1
  152. package/dist/codec.d.ts +33 -0
  153. package/dist/codec.d.ts.map +1 -0
  154. package/dist/codec.js +2 -0
  155. package/dist/config-types.d.ts +266 -0
  156. package/dist/config-types.d.ts.map +1 -0
  157. package/dist/config-validation.d.ts +51 -0
  158. package/dist/config-validation.d.ts.map +1 -0
  159. package/dist/content/index.d.ts +1 -10
  160. package/dist/content/index.d.ts.map +1 -1
  161. package/dist/content/index.js +0 -2
  162. package/dist/cookies/define-cookie.d.ts +35 -14
  163. package/dist/cookies/define-cookie.d.ts.map +1 -1
  164. package/dist/cookies/index.js +1 -83
  165. package/dist/fonts/bundle.d.ts +48 -0
  166. package/dist/fonts/bundle.d.ts.map +1 -0
  167. package/dist/fonts/css.d.ts +1 -0
  168. package/dist/fonts/css.d.ts.map +1 -1
  169. package/dist/fonts/dev-middleware.d.ts +22 -0
  170. package/dist/fonts/dev-middleware.d.ts.map +1 -0
  171. package/dist/fonts/pipeline.d.ts +138 -0
  172. package/dist/fonts/pipeline.d.ts.map +1 -0
  173. package/dist/fonts/transform.d.ts +72 -0
  174. package/dist/fonts/transform.d.ts.map +1 -0
  175. package/dist/fonts/types.d.ts +45 -1
  176. package/dist/fonts/types.d.ts.map +1 -1
  177. package/dist/fonts/virtual-modules.d.ts +59 -0
  178. package/dist/fonts/virtual-modules.d.ts.map +1 -0
  179. package/dist/index.d.ts +45 -190
  180. package/dist/index.d.ts.map +1 -1
  181. package/dist/index.js +4294 -2453
  182. package/dist/index.js.map +1 -1
  183. package/dist/plugin-context.d.ts +107 -0
  184. package/dist/plugin-context.d.ts.map +1 -0
  185. package/dist/plugins/adapter-build.d.ts +1 -1
  186. package/dist/plugins/adapter-build.d.ts.map +1 -1
  187. package/dist/plugins/build-manifest.d.ts +2 -2
  188. package/dist/plugins/build-manifest.d.ts.map +1 -1
  189. package/dist/plugins/build-report.d.ts +3 -3
  190. package/dist/plugins/build-report.d.ts.map +1 -1
  191. package/dist/plugins/client-chunks.d.ts +32 -0
  192. package/dist/plugins/client-chunks.d.ts.map +1 -0
  193. package/dist/plugins/content.d.ts +1 -1
  194. package/dist/plugins/content.d.ts.map +1 -1
  195. package/dist/plugins/dev-404-page.d.ts +56 -0
  196. package/dist/plugins/dev-404-page.d.ts.map +1 -0
  197. package/dist/plugins/dev-browser-logs.d.ts +84 -0
  198. package/dist/plugins/dev-browser-logs.d.ts.map +1 -0
  199. package/dist/plugins/dev-error-overlay.d.ts +49 -9
  200. package/dist/plugins/dev-error-overlay.d.ts.map +1 -1
  201. package/dist/plugins/dev-error-page.d.ts +58 -0
  202. package/dist/plugins/dev-error-page.d.ts.map +1 -0
  203. package/dist/plugins/dev-logs.d.ts +1 -1
  204. package/dist/plugins/dev-logs.d.ts.map +1 -1
  205. package/dist/plugins/dev-server.d.ts +1 -1
  206. package/dist/plugins/dev-server.d.ts.map +1 -1
  207. package/dist/plugins/dev-terminal-error.d.ts +28 -0
  208. package/dist/plugins/dev-terminal-error.d.ts.map +1 -0
  209. package/dist/plugins/entries.d.ts +1 -1
  210. package/dist/plugins/entries.d.ts.map +1 -1
  211. package/dist/plugins/fonts.d.ts +17 -73
  212. package/dist/plugins/fonts.d.ts.map +1 -1
  213. package/dist/plugins/mdx.d.ts +1 -1
  214. package/dist/plugins/mdx.d.ts.map +1 -1
  215. package/dist/plugins/routing.d.ts +1 -1
  216. package/dist/plugins/routing.d.ts.map +1 -1
  217. package/dist/plugins/server-bundle.d.ts.map +1 -1
  218. package/dist/plugins/shims.d.ts +6 -5
  219. package/dist/plugins/shims.d.ts.map +1 -1
  220. package/dist/plugins/static-build.d.ts +4 -4
  221. package/dist/plugins/static-build.d.ts.map +1 -1
  222. package/dist/routing/codegen.d.ts +2 -2
  223. package/dist/routing/codegen.d.ts.map +1 -1
  224. package/dist/routing/convention-lint.d.ts +41 -0
  225. package/dist/routing/convention-lint.d.ts.map +1 -0
  226. package/dist/routing/index.d.ts +2 -0
  227. package/dist/routing/index.d.ts.map +1 -1
  228. package/dist/routing/index.js +3 -2
  229. package/dist/routing/scanner.d.ts.map +1 -1
  230. package/dist/routing/segment-classify.d.ts +46 -0
  231. package/dist/routing/segment-classify.d.ts.map +1 -0
  232. package/dist/routing/status-file-lint.d.ts +2 -1
  233. package/dist/routing/status-file-lint.d.ts.map +1 -1
  234. package/dist/routing/types.d.ts +16 -4
  235. package/dist/routing/types.d.ts.map +1 -1
  236. package/dist/rsc-runtime/rsc.d.ts +1 -1
  237. package/dist/rsc-runtime/rsc.d.ts.map +1 -1
  238. package/dist/rsc-runtime/ssr.d.ts +12 -0
  239. package/dist/rsc-runtime/ssr.d.ts.map +1 -1
  240. package/dist/schema-bridge.d.ts +76 -0
  241. package/dist/schema-bridge.d.ts.map +1 -0
  242. package/dist/search-params/define.d.ts +139 -0
  243. package/dist/search-params/define.d.ts.map +1 -0
  244. package/dist/search-params/index.d.ts +4 -7
  245. package/dist/search-params/index.d.ts.map +1 -1
  246. package/dist/search-params/index.js +32 -441
  247. package/dist/search-params/index.js.map +1 -1
  248. package/dist/search-params/registry.d.ts +2 -2
  249. package/dist/search-params/registry.d.ts.map +1 -1
  250. package/dist/search-params/wrappers.d.ts +53 -0
  251. package/dist/search-params/wrappers.d.ts.map +1 -0
  252. package/dist/segment-params/define.d.ts +78 -0
  253. package/dist/segment-params/define.d.ts.map +1 -0
  254. package/dist/segment-params/index.d.ts +3 -0
  255. package/dist/segment-params/index.d.ts.map +1 -0
  256. package/dist/segment-params/index.js +2 -0
  257. package/dist/server/access-gate.d.ts +4 -0
  258. package/dist/server/access-gate.d.ts.map +1 -1
  259. package/dist/server/action-client.d.ts +41 -6
  260. package/dist/server/action-client.d.ts.map +1 -1
  261. package/dist/server/action-encryption.d.ts +76 -0
  262. package/dist/server/action-encryption.d.ts.map +1 -0
  263. package/dist/server/action-handler.d.ts +7 -0
  264. package/dist/server/action-handler.d.ts.map +1 -1
  265. package/dist/server/actions.d.ts +3 -6
  266. package/dist/server/actions.d.ts.map +1 -1
  267. package/dist/server/als-registry.d.ts +32 -4
  268. package/dist/server/als-registry.d.ts.map +1 -1
  269. package/dist/server/build-manifest.d.ts +2 -2
  270. package/dist/server/build-manifest.d.ts.map +1 -1
  271. package/dist/server/debug.d.ts +1 -1
  272. package/dist/server/default-logger.d.ts +22 -0
  273. package/dist/server/default-logger.d.ts.map +1 -0
  274. package/dist/server/deny-page-resolver.d.ts +52 -0
  275. package/dist/server/deny-page-resolver.d.ts.map +1 -0
  276. package/dist/server/deny-renderer.d.ts.map +1 -1
  277. package/dist/server/dev-holding-server.d.ts +52 -0
  278. package/dist/server/dev-holding-server.d.ts.map +1 -0
  279. package/dist/server/dev-source-map.d.ts +22 -0
  280. package/dist/server/dev-source-map.d.ts.map +1 -0
  281. package/dist/server/dev-warnings.d.ts +1 -21
  282. package/dist/server/dev-warnings.d.ts.map +1 -1
  283. package/dist/server/early-hints.d.ts +13 -5
  284. package/dist/server/early-hints.d.ts.map +1 -1
  285. package/dist/server/error-boundary-wrapper.d.ts +7 -1
  286. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  287. package/dist/server/fallback-error.d.ts +12 -7
  288. package/dist/server/fallback-error.d.ts.map +1 -1
  289. package/dist/server/flight-injection-state.d.ts +66 -0
  290. package/dist/server/flight-injection-state.d.ts.map +1 -0
  291. package/dist/server/flight-scripts.d.ts +42 -0
  292. package/dist/server/flight-scripts.d.ts.map +1 -0
  293. package/dist/server/flush.d.ts.map +1 -1
  294. package/dist/server/form-data.d.ts +29 -0
  295. package/dist/server/form-data.d.ts.map +1 -1
  296. package/dist/server/html-injectors.d.ts +51 -11
  297. package/dist/server/html-injectors.d.ts.map +1 -1
  298. package/dist/server/index.d.ts +5 -43
  299. package/dist/server/index.d.ts.map +1 -1
  300. package/dist/server/index.js +195 -2800
  301. package/dist/server/index.js.map +1 -1
  302. package/dist/server/internal.d.ts +46 -0
  303. package/dist/server/internal.d.ts.map +1 -0
  304. package/dist/server/internal.js +2900 -0
  305. package/dist/server/internal.js.map +1 -0
  306. package/dist/server/logger.d.ts +25 -7
  307. package/dist/server/logger.d.ts.map +1 -1
  308. package/dist/server/middleware-runner.d.ts +19 -4
  309. package/dist/server/middleware-runner.d.ts.map +1 -1
  310. package/dist/server/node-stream-transforms.d.ts +113 -0
  311. package/dist/server/node-stream-transforms.d.ts.map +1 -0
  312. package/dist/server/page-deny-boundary.d.ts +31 -0
  313. package/dist/server/page-deny-boundary.d.ts.map +1 -0
  314. package/dist/server/pipeline-interception.d.ts +1 -1
  315. package/dist/server/pipeline-interception.d.ts.map +1 -1
  316. package/dist/server/pipeline-metadata.d.ts +6 -0
  317. package/dist/server/pipeline-metadata.d.ts.map +1 -1
  318. package/dist/server/pipeline.d.ts +52 -10
  319. package/dist/server/pipeline.d.ts.map +1 -1
  320. package/dist/server/primitives.d.ts +69 -18
  321. package/dist/server/primitives.d.ts.map +1 -1
  322. package/dist/server/render-timeout.d.ts +51 -0
  323. package/dist/server/render-timeout.d.ts.map +1 -0
  324. package/dist/server/request-context.d.ts +112 -43
  325. package/dist/server/request-context.d.ts.map +1 -1
  326. package/dist/server/route-element-builder.d.ts +27 -1
  327. package/dist/server/route-element-builder.d.ts.map +1 -1
  328. package/dist/server/route-handler.d.ts.map +1 -1
  329. package/dist/server/route-matcher.d.ts +16 -2
  330. package/dist/server/route-matcher.d.ts.map +1 -1
  331. package/dist/server/rsc-entry/api-handler.d.ts +2 -2
  332. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  333. package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
  334. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  335. package/dist/server/rsc-entry/helpers.d.ts +48 -5
  336. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  337. package/dist/server/rsc-entry/index.d.ts +20 -3
  338. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  339. package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
  340. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  341. package/dist/server/rsc-entry/rsc-stream.d.ts +14 -1
  342. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  343. package/dist/server/rsc-entry/ssr-bridge.d.ts +1 -1
  344. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  345. package/dist/server/rsc-entry/ssr-renderer.d.ts +19 -4
  346. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  347. package/dist/server/safe-load.d.ts +46 -0
  348. package/dist/server/safe-load.d.ts.map +1 -0
  349. package/dist/server/sensitive-fields.d.ts +74 -0
  350. package/dist/server/sensitive-fields.d.ts.map +1 -0
  351. package/dist/server/sitemap-generator.d.ts +129 -0
  352. package/dist/server/sitemap-generator.d.ts.map +1 -0
  353. package/dist/server/sitemap-handler.d.ts +22 -0
  354. package/dist/server/sitemap-handler.d.ts.map +1 -0
  355. package/dist/server/slot-resolver.d.ts +1 -1
  356. package/dist/server/slot-resolver.d.ts.map +1 -1
  357. package/dist/server/ssr-entry.d.ts +23 -0
  358. package/dist/server/ssr-entry.d.ts.map +1 -1
  359. package/dist/server/ssr-render.d.ts +39 -21
  360. package/dist/server/ssr-render.d.ts.map +1 -1
  361. package/dist/server/ssr-wrappers.d.ts +50 -0
  362. package/dist/server/ssr-wrappers.d.ts.map +1 -0
  363. package/dist/server/status-code-resolver.d.ts +1 -1
  364. package/dist/server/status-code-resolver.d.ts.map +1 -1
  365. package/dist/server/stream-utils.d.ts +36 -0
  366. package/dist/server/stream-utils.d.ts.map +1 -0
  367. package/dist/server/tracing.d.ts +4 -4
  368. package/dist/server/tracing.d.ts.map +1 -1
  369. package/dist/server/tree-builder.d.ts +22 -19
  370. package/dist/server/tree-builder.d.ts.map +1 -1
  371. package/dist/server/types.d.ts +1 -4
  372. package/dist/server/types.d.ts.map +1 -1
  373. package/dist/server/version-skew.d.ts +61 -0
  374. package/dist/server/version-skew.d.ts.map +1 -0
  375. package/dist/shared/merge-search-params.d.ts +22 -0
  376. package/dist/shared/merge-search-params.d.ts.map +1 -0
  377. package/dist/shims/font-google.d.ts +1 -1
  378. package/dist/shims/font-google.d.ts.map +1 -1
  379. package/dist/shims/font-google.js +42 -0
  380. package/dist/shims/font-google.js.map +1 -0
  381. package/dist/shims/font-local.d.ts +26 -0
  382. package/dist/shims/font-local.d.ts.map +1 -0
  383. package/dist/shims/font-local.js +20 -0
  384. package/dist/shims/font-local.js.map +1 -0
  385. package/dist/shims/headers.d.ts +2 -1
  386. package/dist/shims/headers.d.ts.map +1 -1
  387. package/dist/shims/navigation-client.d.ts +1 -1
  388. package/dist/shims/navigation-client.d.ts.map +1 -1
  389. package/dist/shims/navigation.d.ts +3 -2
  390. package/dist/shims/navigation.d.ts.map +1 -1
  391. package/dist/utils/directive-parser.d.ts +5 -2
  392. package/dist/utils/directive-parser.d.ts.map +1 -1
  393. package/dist/utils/state-machine.d.ts +80 -0
  394. package/dist/utils/state-machine.d.ts.map +1 -0
  395. package/package.json +51 -16
  396. package/src/adapters/cloudflare-dev.ts +177 -0
  397. package/src/adapters/cloudflare-kv-cache.ts +142 -0
  398. package/src/adapters/cloudflare.ts +342 -28
  399. package/src/adapters/compress-module.ts +24 -4
  400. package/src/adapters/nitro.ts +52 -8
  401. package/src/adapters/wrangler.d.ts +7 -0
  402. package/src/cache/cache-api.ts +38 -0
  403. package/src/cache/handler-store.ts +68 -0
  404. package/src/cache/index.ts +81 -18
  405. package/src/cache/singleflight.ts +62 -4
  406. package/src/cache/sizeof.ts +31 -0
  407. package/src/cache/timber-cache.ts +24 -20
  408. package/src/cli.ts +16 -6
  409. package/src/client/browser-dev.ts +128 -1
  410. package/src/client/browser-entry/action-dispatch.ts +116 -0
  411. package/src/client/browser-entry/hmr.ts +81 -0
  412. package/src/client/browser-entry/hydrate.ts +145 -0
  413. package/src/client/browser-entry/index.ts +143 -0
  414. package/src/client/browser-entry/post-hydration.ts +119 -0
  415. package/src/client/browser-entry/router-init.ts +193 -0
  416. package/src/client/browser-entry/rsc-stream.ts +157 -0
  417. package/src/client/browser-entry/scroll.ts +27 -0
  418. package/src/client/error-boundary.tsx +48 -16
  419. package/src/client/error-reconstituter.tsx +65 -0
  420. package/src/client/form.tsx +14 -7
  421. package/src/client/history.ts +26 -4
  422. package/src/client/index.ts +65 -38
  423. package/src/client/internal.ts +57 -0
  424. package/src/client/link-pending-store.ts +111 -0
  425. package/src/client/link.tsx +342 -113
  426. package/src/client/nav-link-store.ts +47 -0
  427. package/src/client/navigation-api-types.ts +112 -0
  428. package/src/client/navigation-api.ts +332 -0
  429. package/src/client/navigation-context.ts +31 -6
  430. package/src/client/navigation-root.tsx +342 -0
  431. package/src/client/nuqs-adapter.tsx +16 -3
  432. package/src/client/router-ref.ts +1 -1
  433. package/src/client/router.ts +299 -72
  434. package/src/client/rsc-fetch.ts +97 -8
  435. package/src/client/segment-cache.ts +1 -1
  436. package/src/client/segment-outlet.tsx +86 -0
  437. package/src/client/ssr-data.ts +13 -5
  438. package/src/client/stale-reload.ts +72 -3
  439. package/src/client/top-loader.tsx +18 -6
  440. package/src/client/use-link-status.ts +7 -7
  441. package/src/client/use-params.ts +7 -5
  442. package/src/client/{use-navigation-pending.ts → use-pending-navigation.ts} +6 -6
  443. package/src/client/use-query-states.ts +9 -3
  444. package/src/client/use-router.ts +1 -1
  445. package/src/codec.ts +49 -0
  446. package/src/config-types.ts +264 -0
  447. package/src/config-validation.ts +303 -0
  448. package/src/content/index.ts +5 -13
  449. package/src/cookies/define-cookie.ts +78 -25
  450. package/src/cookies/index.ts +8 -0
  451. package/src/fonts/bundle.ts +142 -0
  452. package/src/fonts/css.ts +2 -1
  453. package/src/fonts/dev-middleware.ts +74 -0
  454. package/src/fonts/pipeline.ts +275 -0
  455. package/src/fonts/transform.ts +353 -0
  456. package/src/fonts/types.ts +50 -1
  457. package/src/fonts/virtual-modules.ts +159 -0
  458. package/src/index.ts +314 -355
  459. package/src/plugin-context.ts +240 -0
  460. package/src/plugins/adapter-build.ts +9 -3
  461. package/src/plugins/build-manifest.ts +13 -2
  462. package/src/plugins/build-report.ts +3 -3
  463. package/src/plugins/client-chunks.ts +65 -0
  464. package/src/plugins/content.ts +1 -1
  465. package/src/plugins/dev-404-page.ts +418 -0
  466. package/src/plugins/dev-browser-logs.ts +288 -0
  467. package/src/plugins/dev-error-overlay.ts +286 -42
  468. package/src/plugins/dev-error-page.ts +536 -0
  469. package/src/plugins/dev-logs.ts +1 -1
  470. package/src/plugins/dev-server.ts +146 -19
  471. package/src/plugins/dev-terminal-error.ts +217 -0
  472. package/src/plugins/entries.ts +111 -10
  473. package/src/plugins/fonts.ts +133 -638
  474. package/src/plugins/mdx.ts +1 -1
  475. package/src/plugins/routing.ts +213 -31
  476. package/src/plugins/server-action-exports.ts +1 -1
  477. package/src/plugins/server-bundle.ts +32 -1
  478. package/src/plugins/shims.ts +136 -35
  479. package/src/plugins/static-build.ts +17 -11
  480. package/src/routing/codegen.ts +273 -105
  481. package/src/routing/convention-lint.ts +356 -0
  482. package/src/routing/index.ts +2 -0
  483. package/src/routing/scanner.ts +93 -23
  484. package/src/routing/segment-classify.ts +89 -0
  485. package/src/routing/status-file-lint.ts +3 -2
  486. package/src/routing/types.ts +17 -4
  487. package/src/rsc-runtime/rsc.ts +2 -0
  488. package/src/rsc-runtime/ssr.ts +50 -0
  489. package/src/rsc-runtime/vendor-types.d.ts +7 -0
  490. package/src/{search-params/codecs.ts → schema-bridge.ts} +57 -20
  491. package/src/search-params/define.ts +482 -0
  492. package/src/search-params/index.ts +14 -20
  493. package/src/search-params/registry.ts +2 -2
  494. package/src/search-params/wrappers.ts +85 -0
  495. package/src/segment-params/define.ts +279 -0
  496. package/src/segment-params/index.ts +9 -0
  497. package/src/server/access-gate.tsx +70 -29
  498. package/src/server/action-client.ts +88 -15
  499. package/src/server/action-encryption.ts +144 -0
  500. package/src/server/action-handler.ts +53 -6
  501. package/src/server/actions.ts +10 -9
  502. package/src/server/als-registry.ts +34 -6
  503. package/src/server/build-manifest.ts +10 -4
  504. package/src/server/compress.ts +25 -7
  505. package/src/server/debug.ts +1 -1
  506. package/src/server/default-logger.ts +99 -0
  507. package/src/server/deny-page-resolver.ts +154 -0
  508. package/src/server/deny-renderer.ts +24 -38
  509. package/src/server/dev-holding-server.ts +185 -0
  510. package/src/server/dev-source-map.ts +31 -0
  511. package/src/server/dev-warnings.ts +4 -49
  512. package/src/server/early-hints.ts +36 -15
  513. package/src/server/error-boundary-wrapper.ts +74 -22
  514. package/src/server/fallback-error.ts +74 -102
  515. package/src/server/flight-injection-state.ts +113 -0
  516. package/src/server/flight-scripts.ts +62 -0
  517. package/src/server/flush.ts +2 -1
  518. package/src/server/form-data.ts +76 -0
  519. package/src/server/html-injectors.ts +280 -120
  520. package/src/server/index.ts +25 -177
  521. package/src/server/internal.ts +169 -0
  522. package/src/server/logger.ts +44 -36
  523. package/src/server/middleware-runner.ts +31 -4
  524. package/src/server/node-stream-transforms.ts +509 -0
  525. package/src/server/page-deny-boundary.tsx +56 -0
  526. package/src/server/pipeline-interception.ts +17 -16
  527. package/src/server/pipeline-metadata.ts +13 -0
  528. package/src/server/pipeline.ts +261 -66
  529. package/src/server/primitives.ts +111 -28
  530. package/src/server/render-timeout.ts +108 -0
  531. package/src/server/request-context.ts +293 -132
  532. package/src/server/route-element-builder.ts +283 -191
  533. package/src/server/route-handler.ts +24 -4
  534. package/src/server/route-matcher.ts +31 -20
  535. package/src/server/rsc-entry/api-handler.ts +15 -16
  536. package/src/server/rsc-entry/error-renderer.ts +305 -89
  537. package/src/server/rsc-entry/helpers.ts +134 -5
  538. package/src/server/rsc-entry/index.ts +304 -111
  539. package/src/server/rsc-entry/rsc-payload.ts +65 -18
  540. package/src/server/rsc-entry/rsc-stream.ts +81 -13
  541. package/src/server/rsc-entry/ssr-bridge.ts +14 -5
  542. package/src/server/rsc-entry/ssr-renderer.ts +171 -38
  543. package/src/server/safe-load.ts +60 -0
  544. package/src/server/sensitive-fields.ts +230 -0
  545. package/src/server/sitemap-generator.ts +338 -0
  546. package/src/server/sitemap-handler.ts +126 -0
  547. package/src/server/slot-resolver.ts +244 -229
  548. package/src/server/ssr-entry.ts +215 -32
  549. package/src/server/ssr-render.ts +289 -67
  550. package/src/server/ssr-wrappers.tsx +139 -0
  551. package/src/server/status-code-resolver.ts +1 -1
  552. package/src/server/stream-utils.ts +213 -0
  553. package/src/server/tracing.ts +20 -9
  554. package/src/server/tree-builder.ts +92 -58
  555. package/src/server/types.ts +3 -6
  556. package/src/server/version-skew.ts +104 -0
  557. package/src/shared/merge-search-params.ts +55 -0
  558. package/src/shims/font-google.ts +1 -1
  559. package/src/shims/font-local.ts +34 -0
  560. package/src/shims/headers.ts +5 -1
  561. package/src/shims/navigation-client.ts +1 -1
  562. package/src/shims/navigation.ts +7 -2
  563. package/src/utils/directive-parser.ts +5 -2
  564. package/src/utils/state-machine.ts +111 -0
  565. package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
  566. package/dist/_chunks/debug-gwlJkDuf.js.map +0 -1
  567. package/dist/_chunks/format-DviM89f0.js.map +0 -1
  568. package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
  569. package/dist/_chunks/request-context-DIkVh_jG.js +0 -330
  570. package/dist/_chunks/request-context-DIkVh_jG.js.map +0 -1
  571. package/dist/_chunks/tracing-CemImE6h.js.map +0 -1
  572. package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
  573. package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
  574. package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
  575. package/dist/cache/register-cached-function.d.ts +0 -17
  576. package/dist/cache/register-cached-function.d.ts.map +0 -1
  577. package/dist/client/browser-entry.d.ts +0 -21
  578. package/dist/client/browser-entry.d.ts.map +0 -1
  579. package/dist/client/link-status-provider.d.ts +0 -11
  580. package/dist/client/link-status-provider.d.ts.map +0 -1
  581. package/dist/client/transition-root.d.ts.map +0 -1
  582. package/dist/client/use-navigation-pending.d.ts.map +0 -1
  583. package/dist/cookies/index.js.map +0 -1
  584. package/dist/plugins/cache-transform.d.ts +0 -36
  585. package/dist/plugins/cache-transform.d.ts.map +0 -1
  586. package/dist/plugins/dynamic-transform.d.ts +0 -72
  587. package/dist/plugins/dynamic-transform.d.ts.map +0 -1
  588. package/dist/search-params/analyze.d.ts +0 -54
  589. package/dist/search-params/analyze.d.ts.map +0 -1
  590. package/dist/search-params/builtin-codecs.d.ts +0 -105
  591. package/dist/search-params/builtin-codecs.d.ts.map +0 -1
  592. package/dist/search-params/codecs.d.ts +0 -53
  593. package/dist/search-params/codecs.d.ts.map +0 -1
  594. package/dist/search-params/create.d.ts +0 -106
  595. package/dist/search-params/create.d.ts.map +0 -1
  596. package/dist/server/prerender.d.ts +0 -77
  597. package/dist/server/prerender.d.ts.map +0 -1
  598. package/dist/server/response-cache.d.ts +0 -54
  599. package/dist/server/response-cache.d.ts.map +0 -1
  600. package/src/cache/register-cached-function.ts +0 -103
  601. package/src/client/browser-entry.ts +0 -678
  602. package/src/client/link-status-provider.tsx +0 -30
  603. package/src/client/transition-root.tsx +0 -166
  604. package/src/plugins/cache-transform.ts +0 -199
  605. package/src/plugins/dynamic-transform.ts +0 -161
  606. package/src/search-params/analyze.ts +0 -192
  607. package/src/search-params/builtin-codecs.ts +0 -228
  608. package/src/search-params/create.ts +0 -321
  609. package/src/server/prerender.ts +0 -139
  610. package/src/server/response-cache.ts +0 -410
@@ -0,0 +1,279 @@
1
+ /**
2
+ * defineSegmentParams — factory for typed route param coercion.
3
+ *
4
+ * Creates a ParamsDefinition that coerces raw string params from the
5
+ * URL into typed values. Used by exporting from params.ts (segment-level)
6
+ * convention file.
7
+ *
8
+ * Reuses the shared Codec<T> protocol with Standard Schema auto-detection,
9
+ * same pattern as defineSearchParams. Runtime constraints are stricter:
10
+ * - serialize must return string (not null — path segments can't be omitted)
11
+ * - parse throwing → 404 (invalid param value)
12
+ *
13
+ * Design doc: design/07a-route-params-triage.md
14
+ */
15
+
16
+ import type { Codec } from '../codec.js';
17
+ import {
18
+ type StandardSchemaV1,
19
+ validateSync,
20
+ isStandardSchema,
21
+ isCodec,
22
+ } from '../schema-bridge.js';
23
+
24
+ // ---------------------------------------------------------------------------
25
+ // Server-only ALS reference for .get()
26
+ // ---------------------------------------------------------------------------
27
+
28
+ // Same pattern as search-params: eagerly registered at server startup
29
+ // to avoid dynamic imports that lose ALS context. See TIM-523.
30
+ let _getSegmentParamsFn: (() => Promise<Record<string, string | string[]>>) | undefined;
31
+
32
+ /**
33
+ * Register the getSegmentParams function. Called once at module load time
34
+ * from request-context.ts to avoid dynamic import at call time.
35
+ * @internal
36
+ */
37
+ export function _setGetSegmentParamsFn(fn: () => Promise<Record<string, string | string[]>>): void {
38
+ _getSegmentParamsFn = fn;
39
+ }
40
+
41
+ function getSegmentParamsFromAls(): Promise<Record<string, string | string[]>> {
42
+ if (!_getSegmentParamsFn) {
43
+ throw new Error(
44
+ '[timber] segmentParams.get() is only available on the server. ' +
45
+ 'Use useSegmentParams() on the client.'
46
+ );
47
+ }
48
+ return _getSegmentParamsFn();
49
+ }
50
+
51
+ // ---------------------------------------------------------------------------
52
+ // Types
53
+ // ---------------------------------------------------------------------------
54
+
55
+ /** Infer the output type from a Codec or StandardSchemaV1. */
56
+ export type InferParamField<V> =
57
+ V extends Codec<infer T> ? T : V extends StandardSchemaV1<infer T> ? T : never;
58
+
59
+ /** Acceptable field value for defineParams: a Codec or a Standard Schema. */
60
+ export type ParamField<T = unknown> = Codec<T> | StandardSchemaV1<T>;
61
+
62
+ export type { StandardSchemaV1 };
63
+
64
+ /**
65
+ * A typed route params definition.
66
+ *
67
+ * Returned by defineParams(). Provides parse (string → typed) and
68
+ * serialize (typed → string) for each declared param.
69
+ */
70
+ export interface ParamsDefinition<T extends Record<string, unknown>> {
71
+ /** Parse raw string params into typed values. Throws on invalid values. */
72
+ parse(raw: Record<string, string | string[]>): T;
73
+
74
+ /** Serialize typed values back to strings for URL construction. */
75
+ serialize(values: T): Record<string, string>;
76
+
77
+ /**
78
+ * Get typed segment params from the current request context (ALS).
79
+ *
80
+ * Server-only. Reads getSegmentParams() from ALS and coerces through
81
+ * this definition's codecs, returning fully typed params.
82
+ *
83
+ * ```ts
84
+ * // app/products/[id]/params.ts
85
+ * export const segmentParams = defineSegmentParams({ id: z.coerce.number() })
86
+ *
87
+ * // app/products/[id]/page.tsx
88
+ * import { segmentParams } from './params'
89
+ * export default async function Page() {
90
+ * const { id } = await segmentParams.get() // id: number
91
+ * }
92
+ * ```
93
+ */
94
+ get(): Promise<T>;
95
+
96
+ /** Read-only codec map. */
97
+ codecs: { [K in keyof T]: Codec<T[K]> };
98
+ }
99
+
100
+ // ---------------------------------------------------------------------------
101
+ // Internal helpers
102
+ // ---------------------------------------------------------------------------
103
+
104
+ /**
105
+ * Wrap a Standard Schema into a Codec for route params.
106
+ *
107
+ * Unlike fromSchema for search params:
108
+ * - Parse throws on failure (no fallback to default)
109
+ * - Serialize returns string (not null)
110
+ */
111
+ function fromParamSchema<T>(fieldName: string, schema: StandardSchemaV1<T>): Codec<T> {
112
+ return {
113
+ parse(value: string | string[] | undefined): T {
114
+ // Route params are always strings (single segment) or string[] (catch-all)
115
+ const input = Array.isArray(value) ? value : value;
116
+
117
+ const result = validateSync(schema, input);
118
+ if (!result.issues) {
119
+ return result.value;
120
+ }
121
+
122
+ // For route params, parse failure means the param is invalid → throw
123
+ const messages = result.issues.map((i) => i.message).join(', ');
124
+ throw new Error(`[timber] Param '${fieldName}' coercion failed: ${messages}`);
125
+ },
126
+
127
+ serialize(value: T): string | null {
128
+ if (value === null || value === undefined) {
129
+ return null;
130
+ }
131
+ // Catch-all segments produce arrays — join with '/' for path reconstruction
132
+ if (Array.isArray(value)) {
133
+ return value.join('/');
134
+ }
135
+ return String(value);
136
+ },
137
+ };
138
+ }
139
+
140
+ /**
141
+ * Resolve a field value to a Codec. Auto-detects Standard Schema objects.
142
+ */
143
+ function resolveField(fieldName: string, value: ParamField): Codec<unknown> {
144
+ if (isCodec(value)) {
145
+ return value;
146
+ }
147
+
148
+ if (isStandardSchema(value)) {
149
+ return fromParamSchema(fieldName, value);
150
+ }
151
+
152
+ throw new Error(
153
+ `[timber] defineSegmentParams: field '${fieldName}' is not a valid codec or Standard Schema. ` +
154
+ `Expected an object with { parse, serialize } methods, or a Standard Schema object ` +
155
+ `(Zod, Valibot, ArkType).`
156
+ );
157
+ }
158
+
159
+ /**
160
+ * Validate that no codec's serialize returns null.
161
+ * Route params are structural — they must produce a valid path segment.
162
+ */
163
+ function validateSerialize(codecMap: Record<string, Codec<unknown>>): void {
164
+ for (const [key, codec] of Object.entries(codecMap)) {
165
+ // Test serialize with a sample parsed value to check for null
166
+ // We can't exhaustively test, but we can check that serialize(parse("test"))
167
+ // doesn't return null for a basic input.
168
+ try {
169
+ const testValue = codec.parse('test');
170
+ const serialized = codec.serialize(testValue);
171
+ if (serialized === null) {
172
+ throw new Error(
173
+ `[timber] defineSegmentParams: field '${key}' codec.serialize() returned null.\n` +
174
+ ` Route params are path segments — they cannot be omitted.\n` +
175
+ ` Ensure serialize() always returns a string.`
176
+ );
177
+ }
178
+ } catch (e) {
179
+ // parse('test') may throw for strict codecs (e.g., number-only).
180
+ // That's fine — it means the codec validates. We only care about
181
+ // serialize returning null, which we can't test without a valid value.
182
+ if (e instanceof Error && e.message.includes('returned null')) {
183
+ throw e;
184
+ }
185
+ }
186
+ }
187
+ }
188
+
189
+ // ---------------------------------------------------------------------------
190
+ // Factory
191
+ // ---------------------------------------------------------------------------
192
+
193
+ /**
194
+ * Create a ParamsDefinition from a map of codecs and/or Standard Schema objects.
195
+ *
196
+ * ```ts
197
+ * // app/products/[id]/layout.tsx
198
+ * import { defineSegmentParams } from '@timber-js/app/segment-params'
199
+ * import { z } from 'zod/v4'
200
+ *
201
+ * export const segmentParams = defineSegmentParams({
202
+ * id: z.coerce.number().int().positive(),
203
+ * })
204
+ * ```
205
+ */
206
+ export function defineSegmentParams<C extends Record<string, ParamField>>(
207
+ codecs: C
208
+ ): ParamsDefinition<{ [K in keyof C]: InferParamField<C[K]> }> {
209
+ type T = { [K in keyof C]: InferParamField<C[K]> };
210
+
211
+ const resolvedCodecs: Record<string, Codec<unknown>> = {};
212
+
213
+ for (const [key, value] of Object.entries(codecs)) {
214
+ resolvedCodecs[key] = resolveField(key, value as ParamField);
215
+ }
216
+
217
+ // Validate that serialize doesn't return null
218
+ validateSerialize(resolvedCodecs);
219
+
220
+ // ---- parse ----
221
+ function parse(raw: Record<string, string | string[]>): T {
222
+ const result: Record<string, unknown> = {};
223
+
224
+ for (const [key, codec] of Object.entries(resolvedCodecs)) {
225
+ const rawValue = raw[key];
226
+ // Route params are always present (the route matched)
227
+ result[key] = codec.parse(rawValue);
228
+ }
229
+
230
+ return result as T;
231
+ }
232
+
233
+ // ---- serialize ----
234
+ function serialize(values: T): Record<string, string> {
235
+ const result: Record<string, string> = {};
236
+
237
+ for (const [key, codec] of Object.entries(resolvedCodecs)) {
238
+ const serialized = codec.serialize(values[key as keyof T] as unknown);
239
+ if (serialized === null) {
240
+ throw new Error(
241
+ `[timber] params.serialize: field '${key}' serialized to null. ` +
242
+ `Route params must produce a valid path segment.`
243
+ );
244
+ }
245
+ result[key] = serialized;
246
+ }
247
+
248
+ return result;
249
+ }
250
+
251
+ // ---- get ----
252
+ // ALS-backed: reads segment params from the current request context.
253
+ // Server-only — throws on client.
254
+ //
255
+ // The pipeline already coerces params via coerceSegmentParams() which
256
+ // calls parse() and stores typed values in ALS via setSegmentParams().
257
+ // We return those directly instead of re-parsing, because codecs may
258
+ // not be idempotent (e.g., a codec that only accepts raw strings would
259
+ // throw if given an already-parsed value). See TIM-574.
260
+ async function get(): Promise<T> {
261
+ if (typeof window !== 'undefined') {
262
+ throw new Error(
263
+ '[timber] segmentParams.get() is server-only. ' + 'Use useSegmentParams() on the client.'
264
+ );
265
+ }
266
+ const params = await getSegmentParamsFromAls();
267
+ // params are already coerced by the pipeline — return as-is.
268
+ return params as unknown as T;
269
+ }
270
+
271
+ const definition: ParamsDefinition<T> = {
272
+ parse,
273
+ serialize,
274
+ get,
275
+ codecs: resolvedCodecs as { [K in keyof T]: Codec<T[K]> },
276
+ };
277
+
278
+ return definition;
279
+ }
@@ -0,0 +1,9 @@
1
+ // @timber-js/app/segment-params — Typed route param coercion
2
+ //
3
+ // This is the import path for defineSegmentParams and related types.
4
+ // For search params, import from @timber-js/app/search-params instead.
5
+ //
6
+ // See design/07-routing.md §"params.ts Convention File"
7
+
8
+ export type { ParamsDefinition, InferParamField, ParamField } from './define.js';
9
+ export { defineSegmentParams } from './define.js';
@@ -17,6 +17,8 @@ import { DenySignal, RedirectSignal } from './primitives.js';
17
17
  import type { AccessGateProps, SlotAccessGateProps, ReactElement } from './tree-builder.js';
18
18
  import { withSpan, setSpanAttribute } from './tracing.js';
19
19
  import { isDebug } from './debug.js';
20
+ import type { DenyPageEntry } from './deny-page-resolver.js';
21
+ import { renderMatchingDenyPage, setDenyStatus } from './deny-page-resolver.js';
20
22
 
21
23
  // ─── AccessGate ─────────────────────────────────────────────────────────────
22
24
 
@@ -35,24 +37,20 @@ import { isDebug } from './debug.js';
35
37
  * gets the same data by calling the same cached functions (React.cache dedup).
36
38
  */
37
39
  export function AccessGate(props: AccessGateProps): ReactElement | Promise<ReactElement> {
38
- const { accessFn, params, searchParams, segmentName, verdict, children } = props;
40
+ const { accessFn, segmentName, verdict, denyPages, children } = props;
39
41
 
40
42
  // Fast path: replay pre-computed verdict from the pre-render pass.
41
- // This is synchronous — Suspense boundaries cannot interfere with the
42
- // status code because the signal throws before any async work.
43
43
  if (verdict !== undefined) {
44
44
  if (verdict === 'pass') {
45
45
  return children;
46
46
  }
47
- // Throw the stored DenySignal or RedirectSignal synchronously.
48
- // React catches this as a render-phase throw — the flush controller
49
- // produces the correct HTTP status code.
50
47
  throw verdict;
51
48
  }
52
49
 
53
- // Fallback: call accessFn directly (used by tree-builder.ts which
54
- // doesn't run a pre-render pass, and for backward compat).
55
- return accessGateFallback(accessFn, params, searchParams, segmentName, children);
50
+ // Primary path: call accessFn directly during render.
51
+ // If denyPages is provided, catch DenySignal and render the deny page
52
+ // in-tree no throw reaches React Flight, no second render pass.
53
+ return accessGateFallback(accessFn, segmentName, denyPages, children);
56
54
  }
57
55
 
58
56
  /**
@@ -61,28 +59,41 @@ export function AccessGate(props: AccessGateProps): ReactElement | Promise<React
61
59
  */
62
60
  async function accessGateFallback(
63
61
  accessFn: AccessGateProps['accessFn'],
64
- params: AccessGateProps['params'],
65
- searchParams: AccessGateProps['searchParams'],
66
62
  segmentName: AccessGateProps['segmentName'],
63
+ denyPages: DenyPageEntry[] | undefined,
67
64
  children: ReactElement
68
65
  ): Promise<ReactElement> {
69
- await withSpan('timber.access', { 'timber.segment': segmentName ?? 'unknown' }, async () => {
70
- try {
71
- await accessFn({ params, searchParams });
72
- await setSpanAttribute('timber.result', 'pass');
73
- } catch (error: unknown) {
74
- if (error instanceof DenySignal) {
75
- await setSpanAttribute('timber.result', 'deny');
76
- await setSpanAttribute('timber.deny_status', error.status);
77
- if (error.sourceFile) {
78
- await setSpanAttribute('timber.deny_file', error.sourceFile);
66
+ try {
67
+ await withSpan('timber.access', { 'timber.segment': segmentName ?? 'unknown' }, async () => {
68
+ try {
69
+ await accessFn();
70
+ await setSpanAttribute('timber.result', 'pass');
71
+ } catch (error: unknown) {
72
+ if (error instanceof DenySignal) {
73
+ await setSpanAttribute('timber.result', 'deny');
74
+ await setSpanAttribute('timber.deny_status', error.status);
75
+ if (error.sourceFile) {
76
+ await setSpanAttribute('timber.deny_file', error.sourceFile);
77
+ }
78
+ } else if (error instanceof RedirectSignal) {
79
+ await setSpanAttribute('timber.result', 'redirect');
79
80
  }
80
- } else if (error instanceof RedirectSignal) {
81
- await setSpanAttribute('timber.result', 'redirect');
81
+ throw error;
82
+ }
83
+ });
84
+ } catch (error: unknown) {
85
+ // Catch DenySignal and render the deny page in-tree.
86
+ // No throw reaches React Flight — clean stream, single render pass.
87
+ // RedirectSignal and other errors propagate normally.
88
+ if (error instanceof DenySignal && denyPages) {
89
+ const denyElement = renderMatchingDenyPage(denyPages, error.status, error.data);
90
+ if (denyElement) {
91
+ setDenyStatus(error.status);
92
+ return denyElement;
82
93
  }
83
- throw error;
84
94
  }
85
- });
95
+ throw error;
96
+ }
86
97
 
87
98
  return children;
88
99
  }
@@ -96,18 +107,27 @@ async function accessGateFallback(
96
107
  * The HTTP status code is unaffected — slot denial is a UI concern, not
97
108
  * a protocol concern. The parent layout and sibling slots still render.
98
109
  *
110
+ * DeniedComponent is passed instead of a pre-built element so that
111
+ * DenySignal.data can be forwarded as the dangerouslyPassData prop
112
+ * and the slot name can be passed as the slot prop. See TIM-488.
113
+ *
99
114
  * redirect() in slot access.ts is a dev-mode error — redirecting from a
100
115
  * slot doesn't make architectural sense.
101
116
  */
102
117
  export async function SlotAccessGate(props: SlotAccessGateProps): Promise<ReactElement> {
103
- const { accessFn, params, searchParams, deniedFallback, defaultFallback, children } = props;
118
+ const { accessFn, DeniedComponent, slotName, createElement, defaultFallback, children } = props;
104
119
 
105
120
  try {
106
- await accessFn({ params, searchParams });
121
+ await accessFn();
107
122
  } catch (error: unknown) {
108
123
  // DenySignal → graceful degradation (denied.tsx → default.tsx → null)
124
+ // Build the denied element dynamically so DenySignal.data is forwarded.
109
125
  if (error instanceof DenySignal) {
110
- return deniedFallback ?? defaultFallback ?? null;
126
+ return (
127
+ buildDeniedFallback(DeniedComponent, slotName, error.data, createElement) ??
128
+ defaultFallback ??
129
+ null
130
+ );
111
131
  }
112
132
 
113
133
  // RedirectSignal in slot access → dev-mode error.
@@ -123,7 +143,11 @@ export async function SlotAccessGate(props: SlotAccessGateProps): Promise<ReactE
123
143
  );
124
144
  }
125
145
  // In production, treat as a deny — render fallback rather than crash.
126
- return deniedFallback ?? defaultFallback ?? null;
146
+ return (
147
+ buildDeniedFallback(DeniedComponent, slotName, undefined, createElement) ??
148
+ defaultFallback ??
149
+ null
150
+ );
127
151
  }
128
152
 
129
153
  // Unhandled error — re-throw so error boundaries can catch it.
@@ -141,3 +165,20 @@ export async function SlotAccessGate(props: SlotAccessGateProps): Promise<ReactE
141
165
  // Access passed — render slot content.
142
166
  return children;
143
167
  }
168
+
169
+ /**
170
+ * Build the denied fallback element dynamically with DenySignal data.
171
+ * Returns null if no DeniedComponent is available.
172
+ */
173
+ function buildDeniedFallback(
174
+ DeniedComponent: SlotAccessGateProps['DeniedComponent'],
175
+ slotName: string,
176
+ data: unknown,
177
+ createElement: SlotAccessGateProps['createElement']
178
+ ): ReactElement | null {
179
+ if (!DeniedComponent) return null;
180
+ return createElement(DeniedComponent, {
181
+ slot: slotName,
182
+ dangerouslyPassData: data,
183
+ });
184
+ }
@@ -131,6 +131,13 @@ interface ActionClientConfig<TCtx> {
131
131
  middleware?: ActionMiddleware<TCtx> | ActionMiddleware<Record<string, unknown>>[];
132
132
  /** Max file size in bytes. Files exceeding this are rejected with validation errors. */
133
133
  fileSizeLimit?: number;
134
+ /**
135
+ * Override the sensitive-field deny-list for this action client.
136
+ * See `SensitiveFieldsOption` in `./sensitive-fields.ts`. Per-action config
137
+ * takes precedence over the global `forms.stripSensitiveFields` option in
138
+ * `timber.config.ts`. See design/08-forms-and-actions.md and TIM-816.
139
+ */
140
+ stripSensitiveFields?: SensitiveFieldsOption;
134
141
  }
135
142
 
136
143
  /** Intermediate builder returned by createActionClient(). */
@@ -138,22 +145,53 @@ export interface ActionBuilder<TCtx> {
138
145
  /** Declare the input schema. Validation errors are returned typed. */
139
146
  schema<TInput>(schema: ActionSchema<TInput>): ActionBuilderWithSchema<TCtx, TInput>;
140
147
  /** Define the action body without input validation. */
141
- action<TData>(fn: (ctx: ActionContext<TCtx, undefined>) => Promise<TData>): ActionFn<TData>;
148
+ action<TData>(
149
+ fn: (ctx: ActionContext<TCtx, undefined>) => Promise<TData>
150
+ ): ActionFn<TData, undefined>;
142
151
  }
143
152
 
144
153
  /** Builder after .schema() has been called. */
145
154
  export interface ActionBuilderWithSchema<TCtx, TInput> {
146
155
  /** Define the action body with validated input. */
147
- action<TData>(fn: (ctx: ActionContext<TCtx, TInput>) => Promise<TData>): ActionFn<TData>;
156
+ action<TData>(fn: (ctx: ActionContext<TCtx, TInput>) => Promise<TData>): ActionFn<TData, TInput>;
148
157
  }
149
158
 
150
159
  /**
151
- * The final action function. Callable two ways:
160
+ * The final action function. Callable three ways:
152
161
  * - Direct: action(input) → Promise<ActionResult<TData>>
153
162
  * - React useActionState: action(prevState, formData) → Promise<ActionResult<TData>>
163
+ * - React <form action={fn}>: action(formData) → void (return value ignored by React)
164
+ *
165
+ * The third overload exists purely for type compatibility with React's
166
+ * `<form action>` prop, which expects `(formData: FormData) => void`.
167
+ * At runtime the function still returns Promise<ActionResult>, but React
168
+ * discards it. This lets validated actions be passed directly to forms
169
+ * without casts.
170
+ */
171
+ /**
172
+ * Map schema output keys to `string | undefined` for form-facing APIs.
173
+ * HTML form values are always strings, and fields can be absent.
174
+ * Gives autocomplete for field names without lying about value types.
154
175
  */
155
- export type ActionFn<TData> = {
156
- (input?: unknown): Promise<ActionResult<TData>>;
176
+ export type InputHint<T> =
177
+ T extends Record<string, unknown> ? { [K in keyof T]: string | undefined } : T;
178
+
179
+ /**
180
+ * ActionFn — the callable returned by `createActionClient().action()`.
181
+ *
182
+ * Generic order: `<TData, TInput>` — TData first for backward compatibility.
183
+ * Previously ActionFn had a single `<TData>` generic, so existing code like
184
+ * `ActionFn<MyResult>` must still work with TData in the first position.
185
+ * See TIM-797.
186
+ */
187
+ export type ActionFn<TData = unknown, TInput = unknown> = {
188
+ /** <form action={fn}> compatibility — React discards the return value. */
189
+ (formData: FormData): void;
190
+ /** Direct call: action(input) — optional when TInput is undefined/unknown (no-schema actions). */
191
+ (
192
+ ...args: undefined extends TInput ? [input?: TInput] : [input: TInput]
193
+ ): Promise<ActionResult<TData>>;
194
+ /** React useActionState: action(prevState, formData) */
157
195
  (prevState: ActionResult<TData> | null, formData: FormData): Promise<ActionResult<TData>>;
158
196
  };
159
197
 
@@ -183,8 +221,15 @@ async function runActionMiddleware<TCtx>(
183
221
 
184
222
  // Re-export parseFormData for use throughout the framework
185
223
  import { parseFormData } from './form-data.js';
186
- import { formatSize } from '#/utils/format.js';
224
+ import { formatSize } from '../utils/format.js';
187
225
  import { isDebug, isDevMode } from './debug.js';
226
+ import { RedirectSignal, DenySignal } from './primitives.js';
227
+ import {
228
+ stripSensitiveFields,
229
+ resolveSensitivePredicate,
230
+ getGlobalSensitiveFieldsConfig,
231
+ type SensitiveFieldsOption,
232
+ } from './sensitive-fields.js';
188
233
 
189
234
  /**
190
235
  * Extract validation errors from a schema error.
@@ -286,7 +331,7 @@ export function createActionClient<TCtx = Record<string, never>>(
286
331
  function buildAction<TInput, TData>(
287
332
  schema: ActionSchema<TInput> | undefined,
288
333
  fn: (ctx: ActionContext<TCtx, TInput>) => Promise<TData>
289
- ): ActionFn<TData> {
334
+ ): ActionFn<TData, TInput> {
290
335
  async function actionHandler(...args: unknown[]): Promise<ActionResult<TData>> {
291
336
  try {
292
337
  // Run middleware
@@ -308,6 +353,25 @@ export function createActionClient<TCtx = Record<string, never>>(
308
353
  rawInput = args[0];
309
354
  }
310
355
 
356
+ // Resolve the sensitive-field stripping predicate once per invocation.
357
+ // Precedence: per-action (config.stripSensitiveFields) > global
358
+ // (forms.stripSensitiveFields from timber.config.ts) > built-in deny-list.
359
+ // See TIM-816.
360
+ const sensitivePredicate = resolveSensitivePredicate(
361
+ config.stripSensitiveFields,
362
+ getGlobalSensitiveFieldsConfig()
363
+ );
364
+
365
+ // Capture a "safe-to-echo" snapshot of the raw input once. Files are
366
+ // stripped (can't serialize, shouldn't echo back) and sensitive fields
367
+ // (passwords, tokens, CVV, etc.) are removed before they would land
368
+ // in the RSC payload → client form `defaultValue` → DOM.
369
+ const buildSubmittedValues = (): Record<string, unknown> | undefined => {
370
+ const withoutFiles = stripFiles(rawInput);
371
+ if (withoutFiles === undefined) return undefined;
372
+ return stripSensitiveFields(withoutFiles, sensitivePredicate);
373
+ };
374
+
311
375
  // Validate file sizes before schema validation.
312
376
  if (config.fileSizeLimit !== undefined && rawInput && typeof rawInput === 'object') {
313
377
  const fileSizeErrors = validateFileSizes(
@@ -315,14 +379,12 @@ export function createActionClient<TCtx = Record<string, never>>(
315
379
  config.fileSizeLimit
316
380
  );
317
381
  if (fileSizeErrors) {
318
- const submittedValues = stripFiles(rawInput);
319
- return { validationErrors: fileSizeErrors, submittedValues };
382
+ return { validationErrors: fileSizeErrors, submittedValues: buildSubmittedValues() };
320
383
  }
321
384
  }
322
385
 
323
386
  // Capture submitted values for repopulation on validation failure.
324
- // Exclude File objects (can't serialize, shouldn't echo back).
325
- const submittedValues = schema ? stripFiles(rawInput) : undefined;
387
+ const submittedValues = schema ? buildSubmittedValues() : undefined;
326
388
 
327
389
  // Validate with schema if provided
328
390
  let input: TInput;
@@ -366,22 +428,33 @@ export function createActionClient<TCtx = Record<string, never>>(
366
428
  const data = await fn({ ctx, input });
367
429
  return { data };
368
430
  } catch (error) {
431
+ // Re-throw redirect/deny signals — these are control flow, not errors.
432
+ // They must propagate to executeAction() which converts them to proper
433
+ // HTTP responses (302 redirect, 4xx deny). Catching them here would
434
+ // wrap them as INTERNAL_ERROR and break redirect()/redirectExternal()/deny().
435
+ if (error instanceof RedirectSignal || error instanceof DenySignal) {
436
+ throw error;
437
+ }
369
438
  return handleActionError(error);
370
439
  }
371
440
  }
372
441
 
373
- return actionHandler as ActionFn<TData>;
442
+ return actionHandler as ActionFn<TData, TInput>;
374
443
  }
375
444
 
376
445
  return {
377
446
  schema<TInput>(schema: ActionSchema<TInput>) {
378
447
  return {
379
- action<TData>(fn: (ctx: ActionContext<TCtx, TInput>) => Promise<TData>): ActionFn<TData> {
448
+ action<TData>(
449
+ fn: (ctx: ActionContext<TCtx, TInput>) => Promise<TData>
450
+ ): ActionFn<TData, TInput> {
380
451
  return buildAction(schema, fn);
381
452
  },
382
453
  };
383
454
  },
384
- action<TData>(fn: (ctx: ActionContext<TCtx, undefined>) => Promise<TData>): ActionFn<TData> {
455
+ action<TData>(
456
+ fn: (ctx: ActionContext<TCtx, undefined>) => Promise<TData>
457
+ ): ActionFn<TData, undefined> {
385
458
  return buildAction(undefined, fn as (ctx: ActionContext<TCtx, unknown>) => Promise<TData>);
386
459
  },
387
460
  };
@@ -410,7 +483,7 @@ export function createActionClient<TCtx = Record<string, never>>(
410
483
  export function validated<TInput, TData>(
411
484
  schema: ActionSchema<TInput>,
412
485
  handler: (input: TInput) => Promise<TData>
413
- ): ActionFn<TData> {
486
+ ): ActionFn<TData, TInput> {
414
487
  return createActionClient()
415
488
  .schema(schema)
416
489
  .action(async ({ input }) => handler(input));