@timber-js/app 0.2.0-alpha.97 → 0.2.0-alpha.99

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 (372) hide show
  1. package/dist/_chunks/actions-CQ8Z8VGL.js +1061 -0
  2. package/dist/_chunks/actions-CQ8Z8VGL.js.map +1 -0
  3. package/dist/_chunks/build-output-helper-DXnW0qjz.js +61 -0
  4. package/dist/_chunks/build-output-helper-DXnW0qjz.js.map +1 -0
  5. package/dist/_chunks/{define-Itxvcd7F.js → define-B-Q_UMOD.js} +19 -23
  6. package/dist/_chunks/define-B-Q_UMOD.js.map +1 -0
  7. package/dist/_chunks/{define-C77ScO0m.js → define-CfBPoJb0.js} +24 -7
  8. package/dist/_chunks/define-CfBPoJb0.js.map +1 -0
  9. package/dist/_chunks/define-cookie-BjpIt4UC.js +194 -0
  10. package/dist/_chunks/define-cookie-BjpIt4UC.js.map +1 -0
  11. package/dist/_chunks/{format-CYBGxKtc.js → format-Bcn-Iv1x.js} +1 -1
  12. package/dist/_chunks/{format-CYBGxKtc.js.map → format-Bcn-Iv1x.js.map} +1 -1
  13. package/dist/_chunks/handler-store-B-lqaGyh.js +54 -0
  14. package/dist/_chunks/handler-store-B-lqaGyh.js.map +1 -0
  15. package/dist/_chunks/logger-0m8MsKdc.js +291 -0
  16. package/dist/_chunks/logger-0m8MsKdc.js.map +1 -0
  17. package/dist/_chunks/merge-search-params-BphMdht_.js +122 -0
  18. package/dist/_chunks/merge-search-params-BphMdht_.js.map +1 -0
  19. package/dist/_chunks/{metadata-routes-DS3eKNmf.js → metadata-routes-BU684ls2.js} +1 -1
  20. package/dist/_chunks/{metadata-routes-DS3eKNmf.js.map → metadata-routes-BU684ls2.js.map} +1 -1
  21. package/dist/_chunks/navigation-root-BCYczjml.js +96 -0
  22. package/dist/_chunks/navigation-root-BCYczjml.js.map +1 -0
  23. package/dist/_chunks/registry-I2ss-lvy.js +20 -0
  24. package/dist/_chunks/registry-I2ss-lvy.js.map +1 -0
  25. package/dist/_chunks/router-ref-h3-UaCQv.js +28 -0
  26. package/dist/_chunks/router-ref-h3-UaCQv.js.map +1 -0
  27. package/dist/_chunks/{schema-bridge-C3xl_vfb.js → schema-bridge-Cxu4l-7p.js} +1 -1
  28. package/dist/_chunks/{schema-bridge-C3xl_vfb.js.map → schema-bridge-Cxu4l-7p.js.map} +1 -1
  29. package/dist/_chunks/segment-classify-BjfuctV2.js +137 -0
  30. package/dist/_chunks/segment-classify-BjfuctV2.js.map +1 -0
  31. package/dist/_chunks/{segment-context-fHFLF1PE.js → segment-context-Dx_OizxD.js} +1 -1
  32. package/dist/_chunks/{segment-context-fHFLF1PE.js.map → segment-context-Dx_OizxD.js.map} +1 -1
  33. package/dist/_chunks/{router-ref-C8OCm7g7.js → ssr-data-B4CdH7rE.js} +2 -26
  34. package/dist/_chunks/ssr-data-B4CdH7rE.js.map +1 -0
  35. package/dist/_chunks/{stale-reload-BX5gL1r-.js → stale-reload-Bab885FO.js} +1 -1
  36. package/dist/_chunks/{stale-reload-BX5gL1r-.js.map → stale-reload-Bab885FO.js.map} +1 -1
  37. package/dist/_chunks/tracing-C8V-YGsP.js +329 -0
  38. package/dist/_chunks/tracing-C8V-YGsP.js.map +1 -0
  39. package/dist/_chunks/{use-query-states-BiV5GJgm.js → use-query-states-B2XTqxDR.js} +3 -19
  40. package/dist/_chunks/use-query-states-B2XTqxDR.js.map +1 -0
  41. package/dist/_chunks/{use-params-IOPu7E8t.js → use-segment-params-BkpKAQ7D.js} +9 -95
  42. package/dist/_chunks/use-segment-params-BkpKAQ7D.js.map +1 -0
  43. package/dist/_chunks/{interception-BbqMCVXa.js → walkers-Tg0Alwcg.js} +66 -87
  44. package/dist/_chunks/walkers-Tg0Alwcg.js.map +1 -0
  45. package/dist/_chunks/{dev-warnings-DpGRGoDi.js → warnings-Cg47l5sk.js} +3 -3
  46. package/dist/_chunks/warnings-Cg47l5sk.js.map +1 -0
  47. package/dist/adapters/build-output-helper.d.ts +28 -0
  48. package/dist/adapters/build-output-helper.d.ts.map +1 -0
  49. package/dist/adapters/cloudflare.d.ts.map +1 -1
  50. package/dist/adapters/cloudflare.js +8 -28
  51. package/dist/adapters/cloudflare.js.map +1 -1
  52. package/dist/adapters/nitro.d.ts.map +1 -1
  53. package/dist/adapters/nitro.js +63 -31
  54. package/dist/adapters/nitro.js.map +1 -1
  55. package/dist/adapters/shared.d.ts +16 -0
  56. package/dist/adapters/shared.d.ts.map +1 -0
  57. package/dist/cache/index.js +9 -2
  58. package/dist/cache/index.js.map +1 -1
  59. package/dist/cache/timber-cache.d.ts.map +1 -1
  60. package/dist/client/error-boundary.js +2 -1
  61. package/dist/client/error-boundary.js.map +1 -1
  62. package/dist/client/form.d.ts +10 -24
  63. package/dist/client/form.d.ts.map +1 -1
  64. package/dist/client/index.d.ts +1 -5
  65. package/dist/client/index.d.ts.map +1 -1
  66. package/dist/client/index.js +41 -91
  67. package/dist/client/index.js.map +1 -1
  68. package/dist/client/internal.d.ts +2 -1
  69. package/dist/client/internal.d.ts.map +1 -1
  70. package/dist/client/internal.js +81 -7
  71. package/dist/client/internal.js.map +1 -1
  72. package/dist/client/rsc-fetch.d.ts.map +1 -1
  73. package/dist/client/state.d.ts +1 -1
  74. package/dist/client/use-cookie.d.ts +8 -0
  75. package/dist/client/use-cookie.d.ts.map +1 -1
  76. package/dist/client/{use-params.d.ts → use-segment-params.d.ts} +1 -1
  77. package/dist/client/use-segment-params.d.ts.map +1 -0
  78. package/dist/codec.d.ts +1 -1
  79. package/dist/codec.d.ts.map +1 -1
  80. package/dist/codec.js +2 -2
  81. package/dist/config-types.d.ts +28 -0
  82. package/dist/config-types.d.ts.map +1 -1
  83. package/dist/cookies/define-cookie.d.ts +87 -35
  84. package/dist/cookies/define-cookie.d.ts.map +1 -1
  85. package/dist/cookies/index.d.ts +2 -1
  86. package/dist/cookies/index.d.ts.map +1 -1
  87. package/dist/cookies/index.js +48 -2
  88. package/dist/cookies/index.js.map +1 -0
  89. package/dist/cookies/json-cookie.d.ts +64 -0
  90. package/dist/cookies/json-cookie.d.ts.map +1 -0
  91. package/dist/cookies/validation.d.ts +46 -0
  92. package/dist/cookies/validation.d.ts.map +1 -0
  93. package/dist/{plugins/dev-404-page.d.ts → dev-tools/404-page.d.ts} +9 -19
  94. package/dist/dev-tools/404-page.d.ts.map +1 -0
  95. package/dist/{plugins/dev-browser-logs.d.ts → dev-tools/browser-logs.d.ts} +1 -1
  96. package/dist/dev-tools/browser-logs.d.ts.map +1 -0
  97. package/dist/{plugins/dev-error-page.d.ts → dev-tools/error-page.d.ts} +2 -2
  98. package/dist/dev-tools/error-page.d.ts.map +1 -0
  99. package/dist/{server/dev-holding-server.d.ts → dev-tools/holding-server.d.ts} +5 -3
  100. package/dist/dev-tools/holding-server.d.ts.map +1 -0
  101. package/dist/dev-tools/index.d.ts +31 -0
  102. package/dist/dev-tools/index.d.ts.map +1 -0
  103. package/dist/{server/dev-span-processor.d.ts → dev-tools/instrumentation.d.ts} +26 -6
  104. package/dist/dev-tools/instrumentation.d.ts.map +1 -0
  105. package/dist/{server/dev-logger.d.ts → dev-tools/logger.d.ts} +1 -1
  106. package/dist/dev-tools/logger.d.ts.map +1 -0
  107. package/dist/{plugins/dev-logs.d.ts → dev-tools/logs.d.ts} +1 -1
  108. package/dist/dev-tools/logs.d.ts.map +1 -0
  109. package/dist/{plugins/dev-error-overlay.d.ts → dev-tools/overlay.d.ts} +3 -12
  110. package/dist/dev-tools/overlay.d.ts.map +1 -0
  111. package/dist/dev-tools/stack-classifier.d.ts +34 -0
  112. package/dist/dev-tools/stack-classifier.d.ts.map +1 -0
  113. package/dist/{plugins/dev-terminal-error.d.ts → dev-tools/terminal.d.ts} +2 -2
  114. package/dist/dev-tools/terminal.d.ts.map +1 -0
  115. package/dist/{server/dev-warnings.d.ts → dev-tools/warnings.d.ts} +1 -1
  116. package/dist/dev-tools/warnings.d.ts.map +1 -0
  117. package/dist/index.d.ts +1 -0
  118. package/dist/index.d.ts.map +1 -1
  119. package/dist/index.js +285 -133
  120. package/dist/index.js.map +1 -1
  121. package/dist/plugin-context.d.ts +1 -1
  122. package/dist/plugin-context.d.ts.map +1 -1
  123. package/dist/plugins/adapter-build.d.ts.map +1 -1
  124. package/dist/plugins/build-report.d.ts +6 -4
  125. package/dist/plugins/build-report.d.ts.map +1 -1
  126. package/dist/routing/convention-lint.d.ts.map +1 -1
  127. package/dist/routing/index.d.ts +5 -3
  128. package/dist/routing/index.d.ts.map +1 -1
  129. package/dist/routing/index.js +3 -3
  130. package/dist/routing/scanner.d.ts +1 -10
  131. package/dist/routing/scanner.d.ts.map +1 -1
  132. package/dist/routing/segment-classify.d.ts +37 -8
  133. package/dist/routing/segment-classify.d.ts.map +1 -1
  134. package/dist/routing/status-file-lint.d.ts.map +1 -1
  135. package/dist/routing/types.d.ts +63 -23
  136. package/dist/routing/types.d.ts.map +1 -1
  137. package/dist/routing/walkers.d.ts +51 -0
  138. package/dist/routing/walkers.d.ts.map +1 -0
  139. package/dist/search-params/define.d.ts +25 -7
  140. package/dist/search-params/define.d.ts.map +1 -1
  141. package/dist/search-params/index.js +5 -3
  142. package/dist/search-params/index.js.map +1 -1
  143. package/dist/search-params/wrappers.d.ts +2 -2
  144. package/dist/search-params/wrappers.d.ts.map +1 -1
  145. package/dist/segment-params/define.d.ts +23 -6
  146. package/dist/segment-params/define.d.ts.map +1 -1
  147. package/dist/segment-params/index.js +1 -1
  148. package/dist/server/access-gate.d.ts +4 -3
  149. package/dist/server/access-gate.d.ts.map +1 -1
  150. package/dist/server/action-handler.d.ts +15 -6
  151. package/dist/server/action-handler.d.ts.map +1 -1
  152. package/dist/server/als-registry.d.ts +5 -5
  153. package/dist/server/als-registry.d.ts.map +1 -1
  154. package/dist/server/asset-headers.d.ts +1 -15
  155. package/dist/server/asset-headers.d.ts.map +1 -1
  156. package/dist/server/cookie-context.d.ts +170 -0
  157. package/dist/server/cookie-context.d.ts.map +1 -0
  158. package/dist/server/cookie-parsing.d.ts +51 -0
  159. package/dist/server/cookie-parsing.d.ts.map +1 -0
  160. package/dist/server/deny-boundary.d.ts +90 -0
  161. package/dist/server/deny-boundary.d.ts.map +1 -0
  162. package/dist/server/deny-renderer.d.ts.map +1 -1
  163. package/dist/server/early-hints-sender.d.ts.map +1 -1
  164. package/dist/server/html-injector-core.d.ts +212 -0
  165. package/dist/server/html-injector-core.d.ts.map +1 -0
  166. package/dist/server/html-injectors.d.ts +59 -59
  167. package/dist/server/html-injectors.d.ts.map +1 -1
  168. package/dist/server/index.d.ts +5 -4
  169. package/dist/server/index.d.ts.map +1 -1
  170. package/dist/server/index.js +4 -149
  171. package/dist/server/index.js.map +1 -1
  172. package/dist/server/internal.d.ts +6 -4
  173. package/dist/server/internal.d.ts.map +1 -1
  174. package/dist/server/internal.js +852 -852
  175. package/dist/server/internal.js.map +1 -1
  176. package/dist/server/logger.d.ts +14 -0
  177. package/dist/server/logger.d.ts.map +1 -1
  178. package/dist/server/middleware-runner.d.ts +17 -0
  179. package/dist/server/middleware-runner.d.ts.map +1 -1
  180. package/dist/server/node-stream-transforms.d.ts +46 -49
  181. package/dist/server/node-stream-transforms.d.ts.map +1 -1
  182. package/dist/server/param-coercion.d.ts +26 -0
  183. package/dist/server/param-coercion.d.ts.map +1 -0
  184. package/dist/server/pipeline-helpers.d.ts +95 -0
  185. package/dist/server/pipeline-helpers.d.ts.map +1 -0
  186. package/dist/server/pipeline-outcome.d.ts +49 -0
  187. package/dist/server/pipeline-outcome.d.ts.map +1 -0
  188. package/dist/server/pipeline-phases.d.ts +52 -0
  189. package/dist/server/pipeline-phases.d.ts.map +1 -0
  190. package/dist/server/pipeline.d.ts +51 -32
  191. package/dist/server/pipeline.d.ts.map +1 -1
  192. package/dist/server/port-resolution.d.ts +117 -0
  193. package/dist/server/port-resolution.d.ts.map +1 -0
  194. package/dist/server/request-context.d.ts +22 -159
  195. package/dist/server/request-context.d.ts.map +1 -1
  196. package/dist/server/route-element-builder.d.ts.map +1 -1
  197. package/dist/server/route-matcher.d.ts +20 -47
  198. package/dist/server/route-matcher.d.ts.map +1 -1
  199. package/dist/server/rsc-entry/action-middleware-runner.d.ts +66 -0
  200. package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -0
  201. package/dist/server/rsc-entry/helpers.d.ts +1 -1
  202. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  203. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  204. package/dist/server/rsc-entry/render-route.d.ts +50 -0
  205. package/dist/server/rsc-entry/render-route.d.ts.map +1 -0
  206. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +119 -0
  207. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -0
  208. package/dist/server/state-tree-diff.d.ts.map +1 -1
  209. package/dist/server/status-code-resolver.d.ts +16 -11
  210. package/dist/server/status-code-resolver.d.ts.map +1 -1
  211. package/dist/server/tracing.d.ts +1 -1
  212. package/dist/server/tracing.d.ts.map +1 -1
  213. package/dist/server/tree-builder.d.ts +45 -16
  214. package/dist/server/tree-builder.d.ts.map +1 -1
  215. package/dist/server/types.d.ts +48 -0
  216. package/dist/server/types.d.ts.map +1 -1
  217. package/dist/server/utils/escape-html.d.ts +14 -0
  218. package/dist/server/utils/escape-html.d.ts.map +1 -0
  219. package/dist/shims/headers.d.ts +2 -2
  220. package/dist/shims/headers.d.ts.map +1 -1
  221. package/dist/shims/navigation-client.d.ts +3 -1
  222. package/dist/shims/navigation-client.d.ts.map +1 -1
  223. package/dist/shims/navigation.d.ts +9 -4
  224. package/dist/shims/navigation.d.ts.map +1 -1
  225. package/dist/utils/directive-parser.d.ts +0 -45
  226. package/dist/utils/directive-parser.d.ts.map +1 -1
  227. package/package.json +1 -1
  228. package/src/adapters/build-output-helper.ts +77 -0
  229. package/src/adapters/cloudflare.ts +10 -50
  230. package/src/adapters/nitro.ts +66 -50
  231. package/src/adapters/shared.ts +40 -0
  232. package/src/cache/timber-cache.ts +3 -2
  233. package/src/client/form.tsx +17 -25
  234. package/src/client/index.ts +16 -9
  235. package/src/client/internal.ts +3 -2
  236. package/src/client/router.ts +1 -1
  237. package/src/client/rsc-fetch.ts +15 -0
  238. package/src/client/state.ts +2 -2
  239. package/src/client/use-cookie.ts +29 -0
  240. package/src/codec.ts +3 -7
  241. package/src/config-types.ts +28 -0
  242. package/src/cookies/define-cookie.ts +271 -78
  243. package/src/cookies/index.ts +11 -8
  244. package/src/cookies/json-cookie.ts +105 -0
  245. package/src/cookies/validation.ts +134 -0
  246. package/src/{plugins/dev-404-page.ts → dev-tools/404-page.ts} +17 -48
  247. package/src/{plugins/dev-error-page.ts → dev-tools/error-page.ts} +5 -32
  248. package/src/{server/dev-holding-server.ts → dev-tools/holding-server.ts} +4 -2
  249. package/src/dev-tools/index.ts +90 -0
  250. package/src/dev-tools/instrumentation.ts +176 -0
  251. package/src/{plugins/dev-logs.ts → dev-tools/logs.ts} +2 -2
  252. package/src/{plugins/dev-error-overlay.ts → dev-tools/overlay.ts} +5 -23
  253. package/src/dev-tools/stack-classifier.ts +75 -0
  254. package/src/{plugins/dev-terminal-error.ts → dev-tools/terminal.ts} +4 -38
  255. package/src/{server/dev-warnings.ts → dev-tools/warnings.ts} +1 -1
  256. package/src/index.ts +95 -34
  257. package/src/plugin-context.ts +1 -1
  258. package/src/plugins/adapter-build.ts +3 -1
  259. package/src/plugins/build-report.ts +13 -22
  260. package/src/plugins/dev-server.ts +3 -3
  261. package/src/plugins/routing.ts +14 -12
  262. package/src/plugins/shims.ts +1 -1
  263. package/src/plugins/static-build.ts +1 -1
  264. package/src/routing/codegen.ts +1 -1
  265. package/src/routing/convention-lint.ts +9 -8
  266. package/src/routing/index.ts +5 -3
  267. package/src/routing/interception.ts +1 -1
  268. package/src/routing/scanner.ts +22 -95
  269. package/src/routing/segment-classify.ts +107 -8
  270. package/src/routing/status-file-lint.ts +7 -5
  271. package/src/routing/types.ts +63 -23
  272. package/src/routing/walkers.ts +90 -0
  273. package/src/search-params/define.ts +71 -15
  274. package/src/search-params/wrappers.ts +9 -2
  275. package/src/segment-params/define.ts +66 -13
  276. package/src/server/access-gate.tsx +9 -8
  277. package/src/server/action-handler.ts +34 -38
  278. package/src/server/als-registry.ts +5 -5
  279. package/src/server/asset-headers.ts +8 -34
  280. package/src/server/cookie-context.ts +468 -0
  281. package/src/server/cookie-parsing.ts +135 -0
  282. package/src/server/{deny-page-resolver.ts → deny-boundary.ts} +78 -14
  283. package/src/server/deny-renderer.ts +7 -12
  284. package/src/server/early-hints-sender.ts +3 -2
  285. package/src/server/fallback-error.ts +2 -2
  286. package/src/server/html-injector-core.ts +403 -0
  287. package/src/server/html-injectors.ts +158 -297
  288. package/src/server/index.ts +13 -14
  289. package/src/server/internal.ts +10 -3
  290. package/src/server/logger.ts +23 -0
  291. package/src/server/middleware-runner.ts +44 -0
  292. package/src/server/node-stream-transforms.ts +108 -248
  293. package/src/server/param-coercion.ts +76 -0
  294. package/src/server/pipeline-helpers.ts +204 -0
  295. package/src/server/pipeline-outcome.ts +167 -0
  296. package/src/server/pipeline-phases.ts +409 -0
  297. package/src/server/pipeline.ts +70 -540
  298. package/src/server/port-resolution.ts +215 -0
  299. package/src/server/request-context.ts +46 -451
  300. package/src/server/route-element-builder.ts +8 -4
  301. package/src/server/route-matcher.ts +28 -60
  302. package/src/server/rsc-entry/action-middleware-runner.ts +167 -0
  303. package/src/server/rsc-entry/api-handler.ts +2 -2
  304. package/src/server/rsc-entry/error-renderer.ts +2 -2
  305. package/src/server/rsc-entry/helpers.ts +2 -7
  306. package/src/server/rsc-entry/index.ts +81 -366
  307. package/src/server/rsc-entry/render-route.ts +304 -0
  308. package/src/server/rsc-entry/rsc-payload.ts +1 -1
  309. package/src/server/rsc-entry/ssr-renderer.ts +2 -2
  310. package/src/server/rsc-entry/wrap-action-dispatch.ts +449 -0
  311. package/src/server/sitemap-generator.ts +1 -1
  312. package/src/server/slot-resolver.ts +1 -1
  313. package/src/server/ssr-entry.ts +1 -1
  314. package/src/server/state-tree-diff.ts +4 -1
  315. package/src/server/status-code-resolver.ts +112 -128
  316. package/src/server/tracing.ts +3 -3
  317. package/src/server/tree-builder.ts +134 -56
  318. package/src/server/types.ts +52 -0
  319. package/src/server/utils/escape-html.ts +20 -0
  320. package/src/shims/headers.ts +3 -3
  321. package/src/shims/navigation-client.ts +4 -3
  322. package/src/shims/navigation.ts +9 -7
  323. package/src/utils/directive-parser.ts +0 -392
  324. package/dist/_chunks/actions-DLnUaR65.js +0 -421
  325. package/dist/_chunks/actions-DLnUaR65.js.map +0 -1
  326. package/dist/_chunks/als-registry-HS0LGUl2.js +0 -41
  327. package/dist/_chunks/als-registry-HS0LGUl2.js.map +0 -1
  328. package/dist/_chunks/debug-ECi_61pb.js +0 -108
  329. package/dist/_chunks/debug-ECi_61pb.js.map +0 -1
  330. package/dist/_chunks/define-C77ScO0m.js.map +0 -1
  331. package/dist/_chunks/define-Itxvcd7F.js.map +0 -1
  332. package/dist/_chunks/define-cookie-BowvzoP0.js +0 -94
  333. package/dist/_chunks/define-cookie-BowvzoP0.js.map +0 -1
  334. package/dist/_chunks/dev-warnings-DpGRGoDi.js.map +0 -1
  335. package/dist/_chunks/interception-BbqMCVXa.js.map +0 -1
  336. package/dist/_chunks/merge-search-params-Cm_KIWDX.js +0 -41
  337. package/dist/_chunks/merge-search-params-Cm_KIWDX.js.map +0 -1
  338. package/dist/_chunks/request-context-CK5tZqIP.js +0 -478
  339. package/dist/_chunks/request-context-CK5tZqIP.js.map +0 -1
  340. package/dist/_chunks/router-ref-C8OCm7g7.js.map +0 -1
  341. package/dist/_chunks/segment-classify-BDNn6EzD.js +0 -65
  342. package/dist/_chunks/segment-classify-BDNn6EzD.js.map +0 -1
  343. package/dist/_chunks/tracing-CCYbKn5n.js +0 -238
  344. package/dist/_chunks/tracing-CCYbKn5n.js.map +0 -1
  345. package/dist/_chunks/use-params-IOPu7E8t.js.map +0 -1
  346. package/dist/_chunks/use-query-states-BiV5GJgm.js.map +0 -1
  347. package/dist/client/use-params.d.ts.map +0 -1
  348. package/dist/plugins/dev-404-page.d.ts.map +0 -1
  349. package/dist/plugins/dev-browser-logs.d.ts.map +0 -1
  350. package/dist/plugins/dev-error-overlay.d.ts.map +0 -1
  351. package/dist/plugins/dev-error-page.d.ts.map +0 -1
  352. package/dist/plugins/dev-logs.d.ts.map +0 -1
  353. package/dist/plugins/dev-terminal-error.d.ts.map +0 -1
  354. package/dist/server/deny-page-resolver.d.ts +0 -52
  355. package/dist/server/deny-page-resolver.d.ts.map +0 -1
  356. package/dist/server/dev-fetch-instrumentation.d.ts +0 -22
  357. package/dist/server/dev-fetch-instrumentation.d.ts.map +0 -1
  358. package/dist/server/dev-holding-server.d.ts.map +0 -1
  359. package/dist/server/dev-logger.d.ts.map +0 -1
  360. package/dist/server/dev-span-processor.d.ts.map +0 -1
  361. package/dist/server/dev-warnings.d.ts.map +0 -1
  362. package/dist/server/manifest-status-resolver.d.ts +0 -58
  363. package/dist/server/manifest-status-resolver.d.ts.map +0 -1
  364. package/dist/server/page-deny-boundary.d.ts +0 -31
  365. package/dist/server/page-deny-boundary.d.ts.map +0 -1
  366. package/src/server/dev-fetch-instrumentation.ts +0 -96
  367. package/src/server/dev-span-processor.ts +0 -78
  368. package/src/server/manifest-status-resolver.ts +0 -215
  369. package/src/server/page-deny-boundary.tsx +0 -56
  370. /package/src/client/{use-params.ts → use-segment-params.ts} +0 -0
  371. /package/src/{plugins/dev-browser-logs.ts → dev-tools/browser-logs.ts} +0 -0
  372. /package/src/{server/dev-logger.ts → dev-tools/logger.ts} +0 -0
@@ -23,18 +23,18 @@ import type { Codec } from '../codec.js';
23
23
  // dynamic `await import()` at call time because the async microtask from the
24
24
  // dynamic import loses AsyncLocalStorage context in React's RSC Flight renderer,
25
25
  // breaking getSearchParams() in parallel slot pages. See TIM-523.
26
- let _getSearchParamsFn: (() => Promise<URLSearchParams>) | undefined;
26
+ let _getSearchParamsFn: (() => URLSearchParams) | undefined;
27
27
 
28
28
  /**
29
29
  * Register the getSearchParams function. Called once at module load time
30
30
  * from request-context.ts to avoid dynamic import at call time.
31
31
  * @internal
32
32
  */
33
- export function _setGetSearchParamsFn(fn: () => Promise<URLSearchParams>): void {
33
+ export function _setGetSearchParamsFn(fn: () => URLSearchParams): void {
34
34
  _getSearchParamsFn = fn;
35
35
  }
36
36
 
37
- function getSearchParamsFromAls(): Promise<URLSearchParams> {
37
+ function getSearchParamsFromAls(): URLSearchParams {
38
38
  if (!_getSearchParamsFn) {
39
39
  throw new Error(
40
40
  '[timber] searchParams.get() is only available on the server. ' +
@@ -111,19 +111,18 @@ export interface SearchParamsDefinition<T extends Record<string, unknown>> {
111
111
  /**
112
112
  * Get typed search params from the current request context (ALS-backed).
113
113
  *
114
- * Server-only reads getSearchParams() from ALS and parses through codecs.
115
- * Throws on client. Eliminates the naming conflict between the definition
116
- * export and the server helper.
114
+ * Server-only, sync. Reads getSearchParams() from ALS and parses through codecs.
115
+ * Throws on client.
117
116
  *
118
117
  * ```tsx
119
118
  * // app/products/page.tsx
120
119
  * import { searchParams } from './params'
121
- * export default async function Page() {
122
- * const { page, category } = await searchParams.get()
120
+ * export default function Page() {
121
+ * const { page, category } = searchParams.get()
123
122
  * }
124
123
  * ```
125
124
  */
126
- get(): Promise<T>;
125
+ get(): T;
127
126
 
128
127
  /** Client hook — reads current URL params and returns typed values + setter. */
129
128
  useQueryStates(options?: QueryStatesOptions): [T, SetParams<T>];
@@ -271,11 +270,68 @@ function validateDefaults(codecMap: Record<string, SearchParamCodec<unknown>>):
271
270
  * })
272
271
  * ```
273
272
  */
273
+ /**
274
+ * Overload: accept a Standard Schema object schema (e.g., z.object({...})).
275
+ *
276
+ * The schema must have a `.shape` property whose values are themselves
277
+ * Standard Schema objects. Each shape property becomes a field codec
278
+ * via fromSchema().
279
+ *
280
+ * ```ts
281
+ * const searchParams = defineSearchParams(
282
+ * z.object({ page: z.coerce.number().default(1), q: z.string().optional() })
283
+ * )
284
+ * ```
285
+ */
286
+ export function defineSearchParams<T extends Record<string, unknown>>(
287
+ schema: StandardSchemaV1<T> & { shape: Record<string, StandardSchemaV1<unknown>> }
288
+ ): SearchParamsDefinition<T>;
289
+
290
+ /**
291
+ * Overload: accept a map of codecs and/or Standard Schema objects.
292
+ */
274
293
  export function defineSearchParams<C extends Record<string, SearchParamField>>(
275
294
  codecs: C
276
- ): SearchParamsDefinition<{ [K in keyof C]: InferField<C[K]> }> {
277
- type T = { [K in keyof C]: InferField<C[K]> };
295
+ ): SearchParamsDefinition<{ [K in keyof C]: InferField<C[K]> }>;
296
+
297
+ export function defineSearchParams(
298
+ codecsOrSchema:
299
+ | Record<string, SearchParamField>
300
+ | (StandardSchemaV1<unknown> & { shape: Record<string, StandardSchemaV1<unknown>> })
301
+ ): SearchParamsDefinition<Record<string, unknown>> {
302
+ // Detect Standard Schema object with .shape (e.g., z.object(...))
303
+ if (isStandardSchema(codecsOrSchema) && hasShape(codecsOrSchema)) {
304
+ const fieldCodecs: Record<string, SearchParamField> = {};
305
+ for (const [key, fieldSchema] of Object.entries(codecsOrSchema.shape)) {
306
+ if (isStandardSchema(fieldSchema)) {
307
+ fieldCodecs[key] = fieldSchema;
308
+ } else {
309
+ throw new Error(
310
+ `[timber] defineSearchParams: field '${key}' in schema.shape is not a Standard Schema. ` +
311
+ `All shape properties must be Standard Schema objects (Zod, Valibot, ArkType).`
312
+ );
313
+ }
314
+ }
315
+ return defineSearchParamsFromMap(fieldCodecs);
316
+ }
317
+
318
+ return defineSearchParamsFromMap(codecsOrSchema as Record<string, SearchParamField>);
319
+ }
320
+
321
+ /** Check if a schema has a .shape property with object-type values. */
322
+ function hasShape(schema: unknown): schema is { shape: Record<string, unknown> } {
323
+ return (
324
+ typeof schema === 'object' &&
325
+ schema !== null &&
326
+ 'shape' in schema &&
327
+ typeof (schema as { shape: unknown }).shape === 'object' &&
328
+ (schema as { shape: unknown }).shape !== null
329
+ );
330
+ }
278
331
 
332
+ function defineSearchParamsFromMap(
333
+ codecs: Record<string, SearchParamField>
334
+ ): SearchParamsDefinition<Record<string, unknown>> {
279
335
  const resolvedCodecs: Record<string, SearchParamCodec<unknown>> = {};
280
336
  const urlKeys: Record<string, string> = {};
281
337
 
@@ -290,7 +346,7 @@ export function defineSearchParams<C extends Record<string, SearchParamField>>(
290
346
  // Validate that all codecs handle absent params
291
347
  validateDefaults(resolvedCodecs);
292
348
 
293
- return buildDefinition<T>(resolvedCodecs as unknown as CodecMap<T>, urlKeys);
349
+ return buildDefinition(resolvedCodecs as unknown as CodecMap<Record<string, unknown>>, urlKeys);
294
350
  }
295
351
 
296
352
  // ---------------------------------------------------------------------------
@@ -453,15 +509,15 @@ function buildDefinition<T extends Record<string, unknown>>(
453
509
 
454
510
  // ---- get ----
455
511
  // ALS-backed: reads getSearchParams() from the current request context
456
- // and parses through codecs. Server-only — throws on client.
457
- async function get(): Promise<T> {
512
+ // and parses through codecs. Server-only, sync.
513
+ function get(): T {
458
514
  if (typeof window !== 'undefined') {
459
515
  throw new Error(
460
516
  '[timber] searchParams.get() is server-only. ' +
461
517
  'Use searchParams.useQueryStates() on the client.'
462
518
  );
463
519
  }
464
- const raw = await getSearchParamsFromAls();
520
+ const raw = getSearchParamsFromAls();
465
521
  return parseSync(raw);
466
522
  }
467
523
 
@@ -8,7 +8,8 @@
8
8
  * Design doc: design/23-search-params.md
9
9
  */
10
10
 
11
- import type { SearchParamCodec, SearchParamCodecWithUrlKey } from './define.js';
11
+ import type { SearchParamCodec, SearchParamCodecWithUrlKey, SearchParamField } from './define.js';
12
+ import { isCodec, isStandardSchema, fromSchema } from '../schema-bridge.js';
12
13
 
13
14
  // ---------------------------------------------------------------------------
14
15
  // withDefault
@@ -74,9 +75,15 @@ export function withDefault<T>(
74
75
  * ```
75
76
  */
76
77
  export function withUrlKey<T>(
77
- codec: SearchParamCodec<T>,
78
+ codecOrSchema: SearchParamField<T>,
78
79
  urlKey: string
79
80
  ): SearchParamCodecWithUrlKey<T> {
81
+ // Auto-detect Standard Schema (Zod, Valibot, ArkType) and wrap
82
+ const codec: SearchParamCodec<T> = isCodec(codecOrSchema)
83
+ ? codecOrSchema
84
+ : isStandardSchema(codecOrSchema)
85
+ ? fromSchema(codecOrSchema)
86
+ : (codecOrSchema as SearchParamCodec<T>);
80
87
  return {
81
88
  parse: codec.parse.bind(codec),
82
89
  serialize: codec.serialize.bind(codec),
@@ -27,22 +27,44 @@ import {
27
27
 
28
28
  // Same pattern as search-params: eagerly registered at server startup
29
29
  // to avoid dynamic imports that lose ALS context. See TIM-523.
30
- let _getSegmentParamsFn: (() => Promise<Record<string, string | string[]>>) | undefined;
30
+ let _getSegmentParamsFn: (() => Record<string, string | string[]>) | undefined;
31
+ let _useSegmentParamsHook: (() => Record<string, string | string[]>) | undefined;
32
+
33
+ /**
34
+ * Register the client useSegmentParams hook.
35
+ * Called by client entry at module load time to avoid require() at call time.
36
+ * @internal
37
+ */
38
+ export function _registerUseSegmentParams(hook: () => Record<string, string | string[]>): void {
39
+ _useSegmentParamsHook = hook;
40
+ }
41
+
42
+ // Self-register on the client when the barrel hasn't been imported yet.
43
+ // Handles the edge case where a client component imports only from params.ts
44
+ // without importing anything from @timber-js/app/client (which runs the
45
+ // registration). The dynamic import resolves before React hydration in Vite.
46
+ if (typeof window !== 'undefined' && !_useSegmentParamsHook) {
47
+ import('../client/use-segment-params.js').then((mod) => {
48
+ if (!_useSegmentParamsHook) {
49
+ _useSegmentParamsHook = mod.useSegmentParams;
50
+ }
51
+ });
52
+ }
31
53
 
32
54
  /**
33
55
  * Register the getSegmentParams function. Called once at module load time
34
56
  * from request-context.ts to avoid dynamic import at call time.
35
57
  * @internal
36
58
  */
37
- export function _setGetSegmentParamsFn(fn: () => Promise<Record<string, string | string[]>>): void {
59
+ export function _setGetSegmentParamsFn(fn: () => Record<string, string | string[]>): void {
38
60
  _getSegmentParamsFn = fn;
39
61
  }
40
62
 
41
- function getSegmentParamsFromAls(): Promise<Record<string, string | string[]>> {
63
+ function getSegmentParamsFromAls(): Record<string, string | string[]> {
42
64
  if (!_getSegmentParamsFn) {
43
65
  throw new Error(
44
66
  '[timber] segmentParams.get() is only available on the server. ' +
45
- 'Use useSegmentParams() on the client.'
67
+ 'Use segmentParams.useSegmentParams() on the client.'
46
68
  );
47
69
  }
48
70
  return _getSegmentParamsFn();
@@ -77,8 +99,7 @@ export interface ParamsDefinition<T extends Record<string, unknown>> {
77
99
  /**
78
100
  * Get typed segment params from the current request context (ALS).
79
101
  *
80
- * Server-only. Reads getSegmentParams() from ALS and coerces through
81
- * this definition's codecs, returning fully typed params.
102
+ * Server-only, sync.
82
103
  *
83
104
  * ```ts
84
105
  * // app/products/[id]/params.ts
@@ -86,12 +107,25 @@ export interface ParamsDefinition<T extends Record<string, unknown>> {
86
107
  *
87
108
  * // app/products/[id]/page.tsx
88
109
  * import { segmentParams } from './params'
89
- * export default async function Page() {
90
- * const { id } = await segmentParams.get() // id: number
110
+ * export default function Page() {
111
+ * const { id } = segmentParams.get() // id: number
112
+ * }
113
+ * ```
114
+ */
115
+ get(): T;
116
+
117
+ /**
118
+ * Client hook for accessing typed segment params reactively.
119
+ *
120
+ * ```tsx
121
+ * 'use client'
122
+ * import { segmentParams } from './params'
123
+ * export function ProductHeader() {
124
+ * const { id } = segmentParams.useSegmentParams()
91
125
  * }
92
126
  * ```
93
127
  */
94
- get(): Promise<T>;
128
+ useSegmentParams(): T;
95
129
 
96
130
  /** Read-only codec map. */
97
131
  codecs: { [K in keyof T]: Codec<T[K]> };
@@ -250,28 +284,47 @@ export function defineSegmentParams<C extends Record<string, ParamField>>(
250
284
 
251
285
  // ---- get ----
252
286
  // ALS-backed: reads segment params from the current request context.
253
- // Server-only — throws on client.
287
+ // Server-only, sync.
254
288
  //
255
289
  // The pipeline already coerces params via coerceSegmentParams() which
256
290
  // calls parse() and stores typed values in ALS via setSegmentParams().
257
291
  // We return those directly instead of re-parsing, because codecs may
258
292
  // not be idempotent (e.g., a codec that only accepts raw strings would
259
293
  // throw if given an already-parsed value). See TIM-574.
260
- async function get(): Promise<T> {
294
+ function get(): T {
261
295
  if (typeof window !== 'undefined') {
262
296
  throw new Error(
263
- '[timber] segmentParams.get() is server-only. ' + 'Use useSegmentParams() on the client.'
297
+ '[timber] segmentParams.get() is server-only. ' +
298
+ 'Use segmentParams.useSegmentParams() on the client.'
264
299
  );
265
300
  }
266
- const params = await getSegmentParamsFromAls();
301
+ const params = getSegmentParamsFromAls();
267
302
  // params are already coerced by the pipeline — return as-is.
268
303
  return params as unknown as T;
269
304
  }
270
305
 
306
+ // ---- useSegmentParams ----
307
+ // Client hook that reads typed params from the navigation context.
308
+ // Delegates to the existing useSegmentParams hook from use-segment-params.ts.
309
+ function useSegmentParams(): T {
310
+ if (!_useSegmentParamsHook) {
311
+ throw new Error(
312
+ '[timber] segmentParams.useSegmentParams() requires @timber-js/app/client to be loaded. ' +
313
+ 'This hook can only be used in client components.'
314
+ );
315
+ }
316
+ const raw = _useSegmentParamsHook();
317
+ // Params are already coerced by the server pipeline before being sent
318
+ // to the client — return as-is. Re-parsing would break non-idempotent
319
+ // codecs (e.g., z.coerce.number() on an already-parsed number). See TIM-574.
320
+ return raw as unknown as T;
321
+ }
322
+
271
323
  const definition: ParamsDefinition<T> = {
272
324
  parse,
273
325
  serialize,
274
326
  get,
327
+ useSegmentParams,
275
328
  codecs: resolvedCodecs as { [K in keyof T]: Codec<T[K]> },
276
329
  };
277
330
 
@@ -14,11 +14,12 @@
14
14
  */
15
15
 
16
16
  import { DenySignal, RedirectSignal } from './primitives.js';
17
- import type { AccessGateProps, SlotAccessGateProps, ReactElement } from './tree-builder.js';
17
+ import type { AccessGateProps, SlotAccessGateProps } 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
+ import type { DenyPageEntry } from './deny-boundary.js';
21
+ import { renderMatchingDenyPage, setDenyStatus } from './deny-boundary.js';
22
+ import type { ReactNode } from 'react';
22
23
 
23
24
  // ─── AccessGate ─────────────────────────────────────────────────────────────
24
25
 
@@ -36,7 +37,7 @@ import { renderMatchingDenyPage, setDenyStatus } from './deny-page-resolver.js';
36
37
  * access.ts is a pure gate — return values are discarded. The layout below
37
38
  * gets the same data by calling the same cached functions (React.cache dedup).
38
39
  */
39
- export function AccessGate(props: AccessGateProps): ReactElement | Promise<ReactElement> {
40
+ export function AccessGate(props: AccessGateProps): ReactNode | Promise<ReactNode> {
40
41
  const { accessFn, segmentName, verdict, denyPages, children } = props;
41
42
 
42
43
  // Fast path: replay pre-computed verdict from the pre-render pass.
@@ -61,8 +62,8 @@ async function accessGateFallback(
61
62
  accessFn: AccessGateProps['accessFn'],
62
63
  segmentName: AccessGateProps['segmentName'],
63
64
  denyPages: DenyPageEntry[] | undefined,
64
- children: ReactElement
65
- ): Promise<ReactElement> {
65
+ children: ReactNode
66
+ ): Promise<ReactNode> {
66
67
  try {
67
68
  await withSpan('timber.access', { 'timber.segment': segmentName ?? 'unknown' }, async () => {
68
69
  try {
@@ -114,7 +115,7 @@ async function accessGateFallback(
114
115
  * redirect() in slot access.ts is a dev-mode error — redirecting from a
115
116
  * slot doesn't make architectural sense.
116
117
  */
117
- export async function SlotAccessGate(props: SlotAccessGateProps): Promise<ReactElement> {
118
+ export async function SlotAccessGate(props: SlotAccessGateProps): Promise<ReactNode> {
118
119
  const { accessFn, DeniedComponent, slotName, createElement, defaultFallback, children } = props;
119
120
 
120
121
  try {
@@ -175,7 +176,7 @@ function buildDeniedFallback(
175
176
  slotName: string,
176
177
  data: unknown,
177
178
  createElement: SlotAccessGateProps['createElement']
178
- ): ReactElement | null {
179
+ ): ReactNode | null {
179
180
  if (!DeniedComponent) return null;
180
181
  return createElement(DeniedComponent, {
181
182
  slot: slotName,
@@ -22,12 +22,8 @@ import {
22
22
 
23
23
  import { validateCsrf, type CsrfConfig } from './csrf.js';
24
24
  import { executeAction, type RevalidateRenderer } from './actions.js';
25
- import {
26
- runWithRequestContext,
27
- setMutableCookieContext,
28
- getSetCookieHeaders,
29
- getCookiesForSsr,
30
- } from './request-context.js';
25
+ import { runWithRequestContext, setMutableCookieContext } from './request-context.js';
26
+ import { getSetCookieHeaders, getCookiesForSsr } from './cookie-context.js';
31
27
  import { handleActionError } from './action-client.js';
32
28
  import { enforceBodyLimits, enforceFieldLimit, type BodyLimitsConfig } from './body-limits.js';
33
29
  import { parseFormData } from './form-data.js';
@@ -72,6 +68,12 @@ const RSC_CONTENT_TYPE = 'text/x-component';
72
68
  * - With JS: POST with `x-rsc-action` header (client callServer dispatch)
73
69
  * - Without JS: POST with form data containing `$ACTION_REF` or `$ACTION_KEY`
74
70
  * (React's progressive enhancement hidden fields)
71
+ *
72
+ * **Important:** This function returns true for ANY POST with a form
73
+ * Content-Type, including non-action POSTs to route.ts API handlers.
74
+ * The caller (wrap-action-dispatch.ts) MUST check the matched route type
75
+ * before entering the action path — route.ts matches skip action detection
76
+ * entirely so their body is not pre-parsed. See TIM-870.
75
77
  */
76
78
  export function isActionRequest(req: Request): boolean {
77
79
  if (req.method !== 'POST') return false;
@@ -90,25 +92,6 @@ export function isActionRequest(req: Request): boolean {
90
92
 
91
93
  // ─── Handler ──────────────────────────────────────────────────────────────
92
94
 
93
- /**
94
- * Serialize a `Map<string, string>` of cookie name → value as a `Cookie:`
95
- * request header value. Format: `name1=value1; name2=value2`. Matches the
96
- * format `parseCookieHeader` in `request-context.ts` reads with, so the
97
- * rerender pipeline can parse it back into the same RYW state.
98
- *
99
- * Used to thread the post-action cookie state from the action's ALS scope
100
- * into the rerender pipeline's fresh ALS scope. Cookies marked for deletion
101
- * are already absent from `getCookiesForSsr()`'s map, so they naturally drop
102
- * out of the synthesized header. See TIM-837.
103
- */
104
- function serializeCookieMapAsHeader(cookies: Map<string, string>): string {
105
- const parts: string[] = [];
106
- for (const [name, value] of cookies) {
107
- parts.push(`${name}=${value}`);
108
- }
109
- return parts.join('; ');
110
- }
111
-
112
95
  /**
113
96
  * Signal from handleFormAction to re-render the page with flash data instead of redirecting.
114
97
  *
@@ -120,16 +103,19 @@ function serializeCookieMapAsHeader(cookies: Map<string, string>): string {
120
103
  * final HTML response. Without this, cookies set inside the action are
121
104
  * silently dropped from the response. See TIM-836 (LOCAL-740).
122
105
  *
123
- * - `cookieHeader`: the post-action read-your-own-writes view of the
124
- * cookie jar, serialized as a `Cookie:` request header. The rerender
125
- * pipeline uses this to clone the request before re-rendering, so the
126
- * page server components see the action's cookie writes immediately
127
- * instead of the stale pre-action state. See TIM-837.
106
+ * - `cookies`: the post-action read-your-own-writes view of the cookie
107
+ * jar, as the same `Map<string, string>` shape used by the request
108
+ * context's `parsedCookies`. The rerender dispatcher seeds this map
109
+ * directly into the rerender request context via `seedRequestCookies`,
110
+ * bypassing any string round-trip through a `Cookie:` header. The
111
+ * direct-Map seed eliminates the value-smuggling primitive that the
112
+ * previous `cookieHeader: string` shape carried — see
113
+ * ONGOING_SECURITY.md H-3 (TIM-868) and TIM-837.
128
114
  */
129
115
  export interface FormRerender {
130
116
  rerender: FormFlashData;
131
117
  setCookieHeaders: string[];
132
- cookieHeader: string;
118
+ cookies: Map<string, string>;
133
119
  }
134
120
 
135
121
  /**
@@ -158,6 +144,12 @@ export async function handleActionRequest(
158
144
  }
159
145
 
160
146
  // CSRF validation — reject cross-origin mutation requests.
147
+ //
148
+ // Defense-in-depth: the pipeline boundary in rsc-entry/index.ts already
149
+ // validates Origin on every unsafe-method request before dispatch reaches
150
+ // here, so this call is a no-op on the happy path. It is intentionally
151
+ // retained so that handleActionRequest remains safe to call from any
152
+ // future entry point that bypasses the wrapper. See LOCAL-773.
161
153
  const csrfResult = validateCsrf(req, config.csrf);
162
154
  if (!csrfResult.ok) {
163
155
  return new Response(null, { status: csrfResult.status });
@@ -202,9 +194,13 @@ export async function handleActionRequest(
202
194
  }
203
195
  } else if (result && 'rerender' in result) {
204
196
  result.setCookieHeaders = getSetCookieHeaders();
205
- // Snapshot the post-action RYW cookie state so the rerender pipeline
206
- // can re-parse it into a fresh ALS scope. See TIM-837.
207
- result.cookieHeader = serializeCookieMapAsHeader(getCookiesForSsr());
197
+ // Snapshot the post-action RYW cookie state as a Map so the rerender
198
+ // dispatcher can seed it directly into the rerender request context
199
+ // via `seedRequestCookies`, with no string round-trip. See TIM-837
200
+ // and ONGOING_SECURITY.md H-3 (TIM-868). `getCookiesForSsr` already
201
+ // returns a defensive copy, so the rerender scope cannot mutate the
202
+ // snapshot through this reference.
203
+ result.cookies = getCookiesForSsr();
208
204
  }
209
205
  return result;
210
206
  });
@@ -391,7 +387,7 @@ async function handleFormAction(
391
387
  },
392
388
  // Filled in by handleActionRequest before the ALS scope exits.
393
389
  setCookieHeaders: [],
394
- cookieHeader: '',
390
+ cookies: new Map(),
395
391
  };
396
392
  }
397
393
 
@@ -421,7 +417,7 @@ async function handleFormAction(
421
417
  );
422
418
  }
423
419
 
424
- // setCookieHeaders + cookieHeader are filled in by handleActionRequest
425
- // before the ALS scope exits.
426
- return { rerender: actionResult, setCookieHeaders: [], cookieHeader: '' };
420
+ // setCookieHeaders + cookies are filled in by handleActionRequest before
421
+ // the ALS scope exits.
422
+ return { rerender: actionResult, setCookieHeaders: [], cookies: new Map() };
427
423
  }
@@ -40,25 +40,25 @@ export interface RequestContextStore {
40
40
  /** Original (pre-overlay) frozen headers, kept for overlay merging. */
41
41
  originalHeaders: Headers;
42
42
  /**
43
- * Promise resolving to the raw URLSearchParams for the current request.
43
+ * Raw URLSearchParams for the current request.
44
44
  * To get typed parsed params, import a search params definition and
45
45
  * call `.parse(searchParams())`.
46
46
  */
47
- searchParamsPromise: Promise<URLSearchParams>;
47
+ searchParams: URLSearchParams;
48
48
  /**
49
49
  * Raw search string from the request URL (e.g. "?foo=bar&baz=1").
50
50
  * Available synchronously for use in `redirect()` with `preserveSearchParams`.
51
51
  */
52
52
  searchString: string;
53
53
  /**
54
- * Promise resolving to the coerced segment params for the current request.
54
+ * Coerced segment params for the current request.
55
55
  * Set by the pipeline after route matching and param coercion, before
56
56
  * middleware and rendering. Pages and layouts read params via
57
57
  * `getSegmentParams()` instead of receiving them as a prop.
58
58
  *
59
59
  * See design/07-routing.md §"params.ts — Convention File for Typed Params"
60
60
  */
61
- segmentParamsPromise?: Promise<Record<string, string | string[]>>;
61
+ segmentParams?: Record<string, string | string[]>;
62
62
  /** Outgoing Set-Cookie entries (name → serialized value + options). Last write wins. */
63
63
  cookieJar: Map<string, CookieEntry>;
64
64
  /** Whether the response has flushed (headers committed). */
@@ -84,7 +84,7 @@ export interface RequestContextStore {
84
84
  export interface CookieEntry {
85
85
  name: string;
86
86
  value: string;
87
- options: import('./request-context.js').CookieOptions;
87
+ options: import('./cookie-context.js').CookieOptions;
88
88
  }
89
89
 
90
90
  // ─── Tracing ──────────────────────────────────────────────────────────────
@@ -15,6 +15,14 @@
15
15
  * Design docs: 18-build-system.md, 06-caching.md
16
16
  */
17
17
 
18
+ import { IMMUTABLE_CACHE, STATIC_CACHE } from '../adapters/shared.js';
19
+
20
+ // Re-export cache constants and generateHeadersFile from the shared adapter
21
+ // module. The canonical definitions live in adapters/shared.ts because
22
+ // adapters are loaded by Node before Vite's resolver is available — they
23
+ // can only import from within their own directory.
24
+ export { IMMUTABLE_CACHE, STATIC_CACHE, generateHeadersFile } from '../adapters/shared.js';
25
+
18
26
  /**
19
27
  * Regex matching Vite-hashed asset filenames.
20
28
  *
@@ -30,18 +38,6 @@
30
38
  */
31
39
  const HASHED_ASSET_RE = /[-.][\da-f]{8,}\.\w+$/;
32
40
 
33
- /** One year in seconds (365 days). */
34
- const ONE_YEAR = 31_536_000;
35
-
36
- /** One hour in seconds. */
37
- const ONE_HOUR = 3_600;
38
-
39
- /** Cache-Control value for hashed (immutable) assets. */
40
- export const IMMUTABLE_CACHE = `public, max-age=${ONE_YEAR}, immutable`;
41
-
42
- /** Cache-Control value for unhashed static assets. */
43
- export const STATIC_CACHE = `public, max-age=${ONE_HOUR}, must-revalidate`;
44
-
45
41
  /**
46
42
  * Check if a URL path looks like a hashed asset.
47
43
  */
@@ -57,25 +53,3 @@ export function isHashedAsset(pathname: string): boolean {
57
53
  export function getAssetCacheControl(pathname: string): string {
58
54
  return isHashedAsset(pathname) ? IMMUTABLE_CACHE : STATIC_CACHE;
59
55
  }
60
-
61
- /**
62
- * Generate a `_headers` file for static asset cache control.
63
- *
64
- * The `_headers` file is a platform convention supported by Cloudflare Workers
65
- * Static Assets, Cloudflare Pages, and Netlify. It maps URL patterns to
66
- * HTTP response headers.
67
- *
68
- * Vite places all hashed chunks under `/assets/` — these get immutable caching.
69
- * Everything else (favicon.ico, robots.txt, etc.) gets a shorter cache.
70
- */
71
- export function generateHeadersFile(): string {
72
- return `# Auto-generated by @timber-js/app — static asset cache headers.
73
- # See design/25-production-deployments.md §"CDN / Edge Cache"
74
-
75
- /assets/*
76
- Cache-Control: ${IMMUTABLE_CACHE}
77
-
78
- /*
79
- Cache-Control: ${STATIC_CACHE}
80
- `;
81
- }