@timber-js/app 0.2.0-alpha.208 → 0.2.0-alpha.209

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 (520) hide show
  1. package/dist/_chunks/{primitives-DLAnvsrk.js → actions-BerlqoXA.js} +640 -410
  2. package/dist/_chunks/actions-BerlqoXA.js.map +1 -0
  3. package/dist/_chunks/{als-registry-C6kcfprT.js → als-registry-DaxkVjt5.js} +6 -2
  4. package/dist/_chunks/als-registry-DaxkVjt5.js.map +1 -0
  5. package/dist/_chunks/{build-manifest-DTmSGLRz.js → build-manifest-DWppEdLB.js} +2 -51
  6. package/dist/_chunks/build-manifest-DWppEdLB.js.map +1 -0
  7. package/dist/_chunks/{build-output-helper-9dqCv1pZ.js → build-output-helper-RV_BRcF1.js} +50 -53
  8. package/dist/_chunks/build-output-helper-RV_BRcF1.js.map +1 -0
  9. package/dist/_chunks/{cache-api-CUD9Ezaq.js → cache-api-CR23J_NC.js} +64 -32
  10. package/dist/_chunks/cache-api-CR23J_NC.js.map +1 -0
  11. package/dist/_chunks/{chains-B4bgOl2g.js → chains-CpFg56UB.js} +2 -2
  12. package/dist/_chunks/{chains-B4bgOl2g.js.map → chains-CpFg56UB.js.map} +1 -1
  13. package/dist/_chunks/{cli-check-G8o30ldg.js → cli-check-C6Ev6wBO.js} +11 -52
  14. package/dist/_chunks/cli-check-C6Ev6wBO.js.map +1 -0
  15. package/dist/_chunks/cli-context-By7k2xVo.js +70 -0
  16. package/dist/_chunks/cli-context-By7k2xVo.js.map +1 -0
  17. package/dist/_chunks/{cli-schema-sync--LZKs8Zn.js → cli-schema-sync-CbT2AUUI.js} +3 -3
  18. package/dist/_chunks/{cli-schema-sync--LZKs8Zn.js.map → cli-schema-sync-CbT2AUUI.js.map} +1 -1
  19. package/dist/_chunks/{cloudflare-BFb__LYG.js → cloudflare-Byxl8FWP.js} +96 -53
  20. package/dist/_chunks/{cloudflare-BFb__LYG.js.map → cloudflare-Byxl8FWP.js.map} +1 -1
  21. package/dist/_chunks/{convention-lint-5KzoMg_A.js → convention-lint-jKTwKwPe.js} +21 -6
  22. package/dist/_chunks/convention-lint-jKTwKwPe.js.map +1 -0
  23. package/dist/_chunks/{dev-server-BzBxgYAV.js → dev-server-C4WZdB7L.js} +15 -167
  24. package/dist/_chunks/dev-server-C4WZdB7L.js.map +1 -0
  25. package/dist/_chunks/{error-boundary-BrHmG-2X.js → error-boundary-tA7kVfs4.js} +84 -104
  26. package/dist/_chunks/error-boundary-tA7kVfs4.js.map +1 -0
  27. package/dist/_chunks/{fs-identity-D7vb6GdI.js → fs-identity-BRKuL215.js} +3 -4
  28. package/dist/_chunks/fs-identity-BRKuL215.js.map +1 -0
  29. package/dist/_chunks/{graph-cache-CP4GEmf9.js → graph-cache-CYiUS2aS.js} +4 -5
  30. package/dist/_chunks/graph-cache-CYiUS2aS.js.map +1 -0
  31. package/dist/_chunks/{json-lossy-check-ClNvBM_3.js → json-lossy-check-ip0Qi0MT.js} +6 -3
  32. package/dist/_chunks/json-lossy-check-ip0Qi0MT.js.map +1 -0
  33. package/dist/_chunks/{live-graph-Bm5WTvcr.js → live-graph-Dv-JJCZw.js} +3 -3
  34. package/dist/_chunks/{live-graph-Bm5WTvcr.js.map → live-graph-Dv-JJCZw.js.map} +1 -1
  35. package/dist/_chunks/{logger-k2DQ4EUf.js → logger-DiDt5ppH.js} +192 -51
  36. package/dist/_chunks/logger-DiDt5ppH.js.map +1 -0
  37. package/dist/_chunks/{navigation-root-mHSK9psY.js → navigation-root-BQfo1-kG.js} +2 -2
  38. package/dist/_chunks/{navigation-root-mHSK9psY.js.map → navigation-root-BQfo1-kG.js.map} +1 -1
  39. package/dist/_chunks/{plugin-context-8idfR3UZ.js → plugin-context-BPBPc3lL.js} +28 -4
  40. package/dist/_chunks/plugin-context-BPBPc3lL.js.map +1 -0
  41. package/dist/_chunks/{poison-scan-DG5eI2_z.js → poison-scan-CpeT6_OJ.js} +2 -2
  42. package/dist/_chunks/{poison-scan-DG5eI2_z.js.map → poison-scan-CpeT6_OJ.js.map} +1 -1
  43. package/dist/_chunks/render-timeout-DOf_BBcO.js +46 -0
  44. package/dist/_chunks/render-timeout-DOf_BBcO.js.map +1 -0
  45. package/dist/_chunks/{rsc-payload-path-B_LBodc2.js → rsc-payload-path-dffcs4jp.js} +9 -3
  46. package/dist/_chunks/{rsc-payload-path-B_LBodc2.js.map → rsc-payload-path-dffcs4jp.js.map} +1 -1
  47. package/dist/_chunks/{scanner-BQ5sPIJ7.js → scanner-Bw0oq1HB.js} +2 -2
  48. package/dist/_chunks/{scanner-BQ5sPIJ7.js.map → scanner-Bw0oq1HB.js.map} +1 -1
  49. package/dist/_chunks/{navigation-context-D0TU0Jog.js → segment-context-xtPUGfdq.js} +36 -34
  50. package/dist/_chunks/segment-context-xtPUGfdq.js.map +1 -0
  51. package/dist/_chunks/{singleflight-2lUWfcAk.js → singleflight-BeVMMKi0.js} +4 -3
  52. package/dist/_chunks/{singleflight-2lUWfcAk.js.map → singleflight-BeVMMKi0.js.map} +1 -1
  53. package/dist/_chunks/{sizeof-lXffQ1Vr.js → sizeof-UwzwB1uM.js} +3 -2
  54. package/dist/_chunks/sizeof-UwzwB1uM.js.map +1 -0
  55. package/dist/_chunks/ssr-data-nA3I70_n.js +49 -0
  56. package/dist/_chunks/ssr-data-nA3I70_n.js.map +1 -0
  57. package/dist/_chunks/{state-FippDgxN.js → state-BhNGPsdi.js} +6 -8
  58. package/dist/_chunks/state-BhNGPsdi.js.map +1 -0
  59. package/dist/_chunks/{status-page-marker-CNbpUOPB.js → status-page-marker-gaihi0KZ.js} +53 -20
  60. package/dist/_chunks/status-page-marker-gaihi0KZ.js.map +1 -0
  61. package/dist/_chunks/{walkers-CN2N_bA-.js → walkers-BXExhzzk.js} +2 -2
  62. package/dist/_chunks/{walkers-CN2N_bA-.js.map → walkers-BXExhzzk.js.map} +1 -1
  63. package/dist/_chunks/write-file-atomic-D1qWqHb4.js +32 -0
  64. package/dist/_chunks/write-file-atomic-D1qWqHb4.js.map +1 -0
  65. package/dist/adapters/build-output-helper.d.ts +7 -7
  66. package/dist/adapters/build-output-helper.d.ts.map +1 -1
  67. package/dist/adapters/canonicalize-module.d.ts +8 -0
  68. package/dist/adapters/canonicalize-module.d.ts.map +1 -0
  69. package/dist/adapters/cloudflare-dev.js +1 -1
  70. package/dist/adapters/cloudflare-kv-cache.js +2 -2
  71. package/dist/adapters/cloudflare.d.ts +30 -8
  72. package/dist/adapters/cloudflare.d.ts.map +1 -1
  73. package/dist/adapters/cloudflare.js +2 -2
  74. package/dist/adapters/compress-module.d.ts +8 -0
  75. package/dist/adapters/compress-module.d.ts.map +1 -1
  76. package/dist/adapters/fs-identity.d.ts +2 -3
  77. package/dist/adapters/fs-identity.d.ts.map +1 -1
  78. package/dist/adapters/nitro-presets.d.ts +0 -6
  79. package/dist/adapters/nitro-presets.d.ts.map +1 -1
  80. package/dist/adapters/nitro-preview.d.ts +43 -11
  81. package/dist/adapters/nitro-preview.d.ts.map +1 -1
  82. package/dist/adapters/nitro.d.ts +1 -13
  83. package/dist/adapters/nitro.d.ts.map +1 -1
  84. package/dist/adapters/nitro.js +291 -176
  85. package/dist/adapters/nitro.js.map +1 -1
  86. package/dist/adapters/shared.d.ts +7 -2
  87. package/dist/adapters/shared.d.ts.map +1 -1
  88. package/dist/adapters/types.d.ts +105 -21
  89. package/dist/adapters/types.d.ts.map +1 -1
  90. package/dist/adapters/types.js +0 -0
  91. package/dist/analyze/crawl-entry.js +3 -3
  92. package/dist/analyze/graph-cache.d.ts.map +1 -1
  93. package/dist/analyze/graph-command.js +4 -4
  94. package/dist/cache/index.js +2 -2
  95. package/dist/cache/json-lossy-check.d.ts.map +1 -1
  96. package/dist/cache/singleflight.d.ts.map +1 -1
  97. package/dist/cache/sizeof.d.ts.map +1 -1
  98. package/dist/cache/stores/memory.js +1 -1
  99. package/dist/cache/tag-aware-handler.d.ts.map +1 -1
  100. package/dist/cdn/workers-cache-purge.js +1 -1
  101. package/dist/cli-check.d.ts +7 -37
  102. package/dist/cli-check.d.ts.map +1 -1
  103. package/dist/cli-context.d.ts +54 -0
  104. package/dist/cli-context.d.ts.map +1 -0
  105. package/dist/cli.d.ts +9 -9
  106. package/dist/cli.d.ts.map +1 -1
  107. package/dist/cli.js +20 -24
  108. package/dist/cli.js.map +1 -1
  109. package/dist/client/browser-dev.d.ts +1 -1
  110. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -1
  111. package/dist/client/browser-entry/hydrate.d.ts +19 -29
  112. package/dist/client/browser-entry/hydrate.d.ts.map +1 -1
  113. package/dist/client/browser-entry/index.d.ts +7 -7
  114. package/dist/client/browser-entry/post-hydration.d.ts +6 -9
  115. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -1
  116. package/dist/client/browser-entry/router-init.d.ts +6 -11
  117. package/dist/client/browser-entry/router-init.d.ts.map +1 -1
  118. package/dist/client/error-boundary.d.ts +4 -3
  119. package/dist/client/error-boundary.d.ts.map +1 -1
  120. package/dist/client/error-boundary.js +1 -1
  121. package/dist/client/error-reconstituter.d.ts +3 -9
  122. package/dist/client/error-reconstituter.d.ts.map +1 -1
  123. package/dist/client/history.d.ts +12 -11
  124. package/dist/client/history.d.ts.map +1 -1
  125. package/dist/client/index.d.ts +0 -1
  126. package/dist/client/index.d.ts.map +1 -1
  127. package/dist/client/index.js +5 -6
  128. package/dist/client/index.js.map +1 -1
  129. package/dist/client/internal.d.ts +3 -3
  130. package/dist/client/internal.d.ts.map +1 -1
  131. package/dist/client/internal.js +68 -104
  132. package/dist/client/internal.js.map +1 -1
  133. package/dist/client/navigation-commit.d.ts +16 -7
  134. package/dist/client/navigation-commit.d.ts.map +1 -1
  135. package/dist/client/navigation-context.d.ts +3 -5
  136. package/dist/client/navigation-context.d.ts.map +1 -1
  137. package/dist/client/react-root.d.ts +3 -2
  138. package/dist/client/react-root.d.ts.map +1 -1
  139. package/dist/client/router-pipeline.d.ts +1 -6
  140. package/dist/client/router-pipeline.d.ts.map +1 -1
  141. package/dist/client/router-types.d.ts +45 -39
  142. package/dist/client/router-types.d.ts.map +1 -1
  143. package/dist/client/router-url.d.ts +24 -0
  144. package/dist/client/router-url.d.ts.map +1 -0
  145. package/dist/client/router.d.ts.map +1 -1
  146. package/dist/client/rsc-fetch.d.ts +8 -4
  147. package/dist/client/rsc-fetch.d.ts.map +1 -1
  148. package/dist/client/ssr-data.d.ts +18 -64
  149. package/dist/client/ssr-data.d.ts.map +1 -1
  150. package/dist/client/state.d.ts +2 -5
  151. package/dist/client/state.d.ts.map +1 -1
  152. package/dist/client/use-pathname.d.ts +1 -1
  153. package/dist/config-types.d.ts +2 -1
  154. package/dist/config-types.d.ts.map +1 -1
  155. package/dist/config-validation.d.ts.map +1 -1
  156. package/dist/cookies/index.js +1 -1
  157. package/dist/dev-tools/dev-page-shell.d.ts +17 -0
  158. package/dist/dev-tools/dev-page-shell.d.ts.map +1 -1
  159. package/dist/dev-tools/index.d.ts +1 -1
  160. package/dist/dev-tools/index.d.ts.map +1 -1
  161. package/dist/dev-tools/instrumentation.d.ts +17 -2
  162. package/dist/dev-tools/instrumentation.d.ts.map +1 -1
  163. package/dist/dev-tools/overlay.d.ts +6 -27
  164. package/dist/dev-tools/overlay.d.ts.map +1 -1
  165. package/dist/index.d.ts.map +1 -1
  166. package/dist/index.js +531 -373
  167. package/dist/index.js.map +1 -1
  168. package/dist/plugin-context.d.ts +26 -40
  169. package/dist/plugin-context.d.ts.map +1 -1
  170. package/dist/plugins/build-manifest.d.ts.map +1 -1
  171. package/dist/plugins/build-report.d.ts +15 -2
  172. package/dist/plugins/build-report.d.ts.map +1 -1
  173. package/dist/plugins/dev-server.d.ts.map +1 -1
  174. package/dist/plugins/entries.d.ts.map +1 -1
  175. package/dist/plugins/fonts.d.ts +19 -1
  176. package/dist/plugins/fonts.d.ts.map +1 -1
  177. package/dist/plugins/post-build.d.ts +110 -0
  178. package/dist/plugins/post-build.d.ts.map +1 -0
  179. package/dist/plugins/prebuilt-capture.d.ts +11 -4
  180. package/dist/plugins/prebuilt-capture.d.ts.map +1 -1
  181. package/dist/plugins/prebuilt.d.ts +17 -1
  182. package/dist/plugins/prebuilt.d.ts.map +1 -1
  183. package/dist/plugins/prerender-sugar.d.ts.map +1 -1
  184. package/dist/plugins/rsc-assets-manifest.d.ts +33 -0
  185. package/dist/plugins/rsc-assets-manifest.d.ts.map +1 -0
  186. package/dist/plugins/shims.d.ts.map +1 -1
  187. package/dist/plugins/static-build.d.ts +32 -9
  188. package/dist/plugins/static-build.d.ts.map +1 -1
  189. package/dist/routing/codegen-write.d.ts +0 -9
  190. package/dist/routing/codegen-write.d.ts.map +1 -1
  191. package/dist/routing/index.js +2 -2
  192. package/dist/routing/segment-codegen.d.ts.map +1 -1
  193. package/dist/server/access-gate.d.ts.map +1 -1
  194. package/dist/server/action-handler.d.ts +5 -4
  195. package/dist/server/action-handler.d.ts.map +1 -1
  196. package/dist/server/actions.d.ts +46 -7
  197. package/dist/server/actions.d.ts.map +1 -1
  198. package/dist/server/als-registry.d.ts +58 -5
  199. package/dist/server/als-registry.d.ts.map +1 -1
  200. package/dist/server/children-interception.d.ts.map +1 -1
  201. package/dist/server/cookie-context.d.ts +2 -23
  202. package/dist/server/cookie-context.d.ts.map +1 -1
  203. package/dist/server/csp-nonce.d.ts +0 -9
  204. package/dist/server/csp-nonce.d.ts.map +1 -1
  205. package/dist/server/csrf.d.ts +27 -4
  206. package/dist/server/csrf.d.ts.map +1 -1
  207. package/dist/server/debug.d.ts +0 -1
  208. package/dist/server/debug.d.ts.map +1 -1
  209. package/dist/server/default-logger.d.ts +2 -1
  210. package/dist/server/default-logger.d.ts.map +1 -1
  211. package/dist/server/deny-boundary.d.ts +12 -6
  212. package/dist/server/deny-boundary.d.ts.map +1 -1
  213. package/dist/server/deny-renderer.d.ts +2 -2
  214. package/dist/server/deny-renderer.d.ts.map +1 -1
  215. package/dist/server/error-boundary-wrapper.d.ts +7 -3
  216. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  217. package/dist/server/fallback-error.d.ts +9 -2
  218. package/dist/server/fallback-error.d.ts.map +1 -1
  219. package/dist/server/head-response.d.ts +4 -4
  220. package/dist/server/html-injectors.d.ts.map +1 -1
  221. package/dist/server/index.d.ts +0 -1
  222. package/dist/server/index.d.ts.map +1 -1
  223. package/dist/server/index.js +3 -4
  224. package/dist/server/index.js.map +1 -1
  225. package/dist/server/instrumentation.d.ts +10 -3
  226. package/dist/server/instrumentation.d.ts.map +1 -1
  227. package/dist/server/internal.d.ts +1 -4
  228. package/dist/server/internal.d.ts.map +1 -1
  229. package/dist/server/internal.js +961 -581
  230. package/dist/server/internal.js.map +1 -1
  231. package/dist/server/json-status-response.d.ts +34 -0
  232. package/dist/server/json-status-response.d.ts.map +1 -0
  233. package/dist/server/logger.d.ts +26 -0
  234. package/dist/server/logger.d.ts.map +1 -1
  235. package/dist/server/param-coercion.d.ts +11 -6
  236. package/dist/server/param-coercion.d.ts.map +1 -1
  237. package/dist/server/pipeline-helpers.d.ts +95 -7
  238. package/dist/server/pipeline-helpers.d.ts.map +1 -1
  239. package/dist/server/pipeline-interception.d.ts +11 -0
  240. package/dist/server/pipeline-interception.d.ts.map +1 -1
  241. package/dist/server/pipeline-outcome.d.ts +11 -1
  242. package/dist/server/pipeline-outcome.d.ts.map +1 -1
  243. package/dist/server/pipeline-phases.d.ts +2 -2
  244. package/dist/server/pipeline-phases.d.ts.map +1 -1
  245. package/dist/server/pipeline.d.ts +23 -35
  246. package/dist/server/pipeline.d.ts.map +1 -1
  247. package/dist/server/prebuilt/capture-render.d.ts +25 -0
  248. package/dist/server/prebuilt/capture-render.d.ts.map +1 -0
  249. package/dist/server/prebuilt/capture-routes.d.ts +37 -0
  250. package/dist/server/prebuilt/capture-routes.d.ts.map +1 -0
  251. package/dist/server/prebuilt/capture-state.d.ts +79 -35
  252. package/dist/server/prebuilt/capture-state.d.ts.map +1 -1
  253. package/dist/server/prebuilt/lifetime.d.ts +38 -0
  254. package/dist/server/prebuilt/lifetime.d.ts.map +1 -0
  255. package/dist/server/prebuilt/slots.d.ts +7 -0
  256. package/dist/server/prebuilt/slots.d.ts.map +1 -1
  257. package/dist/server/prebuilt/synthetic-store.d.ts.map +1 -1
  258. package/dist/server/prebuilt-builder.d.ts.map +1 -1
  259. package/dist/server/prebuilt-runtime.d.ts.map +1 -1
  260. package/dist/server/primitives.d.ts +6 -81
  261. package/dist/server/primitives.d.ts.map +1 -1
  262. package/dist/server/react-cache-bridge.d.ts +59 -0
  263. package/dist/server/react-cache-bridge.d.ts.map +1 -0
  264. package/dist/server/react-cache-scope.d.ts +49 -0
  265. package/dist/server/react-cache-scope.d.ts.map +1 -0
  266. package/dist/server/render-timeout.d.ts +15 -0
  267. package/dist/server/render-timeout.d.ts.map +1 -1
  268. package/dist/server/render-utils.d.ts +9 -0
  269. package/dist/server/render-utils.d.ts.map +1 -1
  270. package/dist/server/request-context.d.ts +26 -5
  271. package/dist/server/request-context.d.ts.map +1 -1
  272. package/dist/server/route-element-builder.d.ts.map +1 -1
  273. package/dist/server/route-handler.d.ts.map +1 -1
  274. package/dist/server/route-matcher.d.ts +7 -0
  275. package/dist/server/route-matcher.d.ts.map +1 -1
  276. package/dist/server/rsc-entry/action-middleware-runner.d.ts +22 -22
  277. package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -1
  278. package/dist/server/rsc-entry/api-handler.d.ts +7 -0
  279. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  280. package/dist/server/rsc-entry/deny-fallback.d.ts +32 -6
  281. package/dist/server/rsc-entry/deny-fallback.d.ts.map +1 -1
  282. package/dist/server/rsc-entry/error-renderer.d.ts +11 -18
  283. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  284. package/dist/server/rsc-entry/helpers.d.ts +0 -1
  285. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  286. package/dist/server/rsc-entry/index.d.ts +5 -15
  287. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  288. package/dist/server/rsc-entry/render-route.d.ts +5 -6
  289. package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
  290. package/dist/server/rsc-entry/render-signals.d.ts +65 -0
  291. package/dist/server/rsc-entry/render-signals.d.ts.map +1 -0
  292. package/dist/server/rsc-entry/revalidate-renderer.d.ts +6 -16
  293. package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -1
  294. package/dist/server/rsc-entry/rsc-payload.d.ts +7 -3
  295. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  296. package/dist/server/rsc-entry/rsc-stream.d.ts +8 -53
  297. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  298. package/dist/server/rsc-entry/ssr-bridge.d.ts +2 -2
  299. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  300. package/dist/server/rsc-entry/ssr-renderer.d.ts +9 -4
  301. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  302. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +1 -1
  303. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -1
  304. package/dist/server/signal-identity.d.ts +43 -0
  305. package/dist/server/signal-identity.d.ts.map +1 -0
  306. package/dist/server/slot-resolver.d.ts +4 -3
  307. package/dist/server/slot-resolver.d.ts.map +1 -1
  308. package/dist/server/slot-subtree-contain.d.ts.map +1 -1
  309. package/dist/server/ssr-bridge-types.d.ts +91 -53
  310. package/dist/server/ssr-bridge-types.d.ts.map +1 -1
  311. package/dist/server/ssr-entry.d.ts +8 -5
  312. package/dist/server/ssr-entry.d.ts.map +1 -1
  313. package/dist/server/ssr-render.d.ts +26 -40
  314. package/dist/server/ssr-render.d.ts.map +1 -1
  315. package/dist/server/ssr-wrappers.d.ts +1 -1
  316. package/dist/server/static-generator.d.ts.map +1 -1
  317. package/dist/server/stream-utils.d.ts +12 -0
  318. package/dist/server/stream-utils.d.ts.map +1 -1
  319. package/dist/server/tracing.d.ts +12 -16
  320. package/dist/server/tracing.d.ts.map +1 -1
  321. package/dist/server/types.d.ts +1 -1
  322. package/dist/server/version-skew.d.ts +3 -3
  323. package/dist/shared/csrf-reject.d.ts +16 -0
  324. package/dist/shared/csrf-reject.d.ts.map +1 -0
  325. package/dist/shared/error-digest.d.ts +28 -0
  326. package/dist/shared/error-digest.d.ts.map +1 -0
  327. package/dist/shared/payload-root.d.ts +11 -10
  328. package/dist/shared/payload-root.d.ts.map +1 -1
  329. package/dist/shared/rsc-payload-path.d.ts +6 -0
  330. package/dist/shared/rsc-payload-path.d.ts.map +1 -1
  331. package/dist/utils/write-file-atomic.d.ts +17 -0
  332. package/dist/utils/write-file-atomic.d.ts.map +1 -0
  333. package/docs/api/30-api-server.mdx +17 -14
  334. package/docs/api/32-api-cache.mdx +51 -23
  335. package/docs/api/34-api-config.mdx +34 -6
  336. package/docs/api/36-cli.mdx +11 -1
  337. package/docs/learn/03-fetching-data.mdx +17 -1
  338. package/docs/learn/04-access-control.mdx +1 -1
  339. package/docs/learn/10-caching.mdx +29 -11
  340. package/docs/learn/11-middleware.mdx +8 -2
  341. package/docs/learn/12-error-handling.mdx +6 -1
  342. package/package.json +5 -1
  343. package/src/adapters/build-output-helper.ts +55 -53
  344. package/src/adapters/canonicalize-module.ts +29 -0
  345. package/src/adapters/cloudflare.ts +105 -63
  346. package/src/adapters/compress-module.ts +16 -5
  347. package/src/adapters/fs-identity.ts +2 -3
  348. package/src/adapters/nitro-presets.ts +0 -15
  349. package/src/adapters/nitro-preview.ts +272 -136
  350. package/src/adapters/nitro.ts +119 -82
  351. package/src/adapters/shared.ts +23 -14
  352. package/src/adapters/types.ts +110 -21
  353. package/src/analyze/graph-cache.ts +3 -4
  354. package/src/cache/json-lossy-check.ts +3 -9
  355. package/src/cache/singleflight.ts +5 -2
  356. package/src/cache/sizeof.ts +3 -1
  357. package/src/cache/tag-aware-handler.ts +43 -26
  358. package/src/cli-check.ts +8 -98
  359. package/src/cli-context.ts +119 -0
  360. package/src/cli.ts +19 -28
  361. package/src/client/browser-dev.ts +1 -1
  362. package/src/client/browser-entry/action-dispatch.ts +26 -4
  363. package/src/client/browser-entry/hydrate.ts +53 -58
  364. package/src/client/browser-entry/index.ts +16 -27
  365. package/src/client/browser-entry/post-hydration.ts +6 -40
  366. package/src/client/browser-entry/router-init.ts +66 -84
  367. package/src/client/error-boundary.tsx +9 -41
  368. package/src/client/error-reconstituter.tsx +10 -5
  369. package/src/client/history.ts +18 -21
  370. package/src/client/index.ts +0 -1
  371. package/src/client/internal.ts +2 -7
  372. package/src/client/navigation-commit.ts +35 -18
  373. package/src/client/navigation-context.ts +3 -39
  374. package/src/client/react-root.ts +3 -2
  375. package/src/client/router-pipeline.ts +65 -128
  376. package/src/client/router-types.ts +46 -44
  377. package/src/client/router-url.ts +32 -0
  378. package/src/client/router.ts +43 -22
  379. package/src/client/rsc-fetch.ts +117 -155
  380. package/src/client/ssr-data.ts +19 -80
  381. package/src/client/state.ts +2 -9
  382. package/src/client/use-pathname.ts +1 -1
  383. package/src/config-types.ts +2 -1
  384. package/src/config-validation.ts +2 -1
  385. package/src/dev-tools/dev-page-shell.ts +18 -0
  386. package/src/dev-tools/index.ts +0 -2
  387. package/src/dev-tools/instrumentation.ts +50 -2
  388. package/src/dev-tools/overlay.ts +8 -238
  389. package/src/index.ts +24 -14
  390. package/src/plugin-context.ts +39 -40
  391. package/src/plugins/build-manifest.ts +4 -11
  392. package/src/plugins/build-report.ts +70 -70
  393. package/src/plugins/dev-server.ts +24 -44
  394. package/src/plugins/entries.ts +2 -1
  395. package/src/plugins/fonts.ts +35 -7
  396. package/src/plugins/post-build.ts +327 -0
  397. package/src/plugins/prebuilt-capture.ts +28 -32
  398. package/src/plugins/prebuilt.ts +54 -39
  399. package/src/plugins/prerender-sugar.ts +0 -4
  400. package/src/plugins/{adapter-build.ts → rsc-assets-manifest.ts} +20 -109
  401. package/src/plugins/shims.ts +1 -0
  402. package/src/plugins/static-build.ts +42 -74
  403. package/src/routing/codegen-write.ts +25 -3
  404. package/src/routing/segment-codegen.ts +3 -2
  405. package/src/rsc-runtime/vendor-types.d.ts +8 -0
  406. package/src/server/access-gate.tsx +2 -1
  407. package/src/server/action-client.ts +1 -1
  408. package/src/server/action-handler.ts +253 -110
  409. package/src/server/actions.ts +73 -25
  410. package/src/server/als-registry.ts +73 -5
  411. package/src/server/chain-url-parts.ts +1 -1
  412. package/src/server/children-interception.ts +2 -1
  413. package/src/server/cookie-context.ts +18 -48
  414. package/src/server/csp-nonce.ts +0 -12
  415. package/src/server/csrf.ts +140 -8
  416. package/src/server/debug.ts +0 -1
  417. package/src/server/default-logger.ts +2 -1
  418. package/src/server/deny-boundary.ts +25 -13
  419. package/src/server/deny-renderer.ts +30 -97
  420. package/src/server/error-boundary-wrapper.ts +7 -3
  421. package/src/server/fallback-error.ts +26 -11
  422. package/src/server/flight-scripts.ts +1 -1
  423. package/src/server/head-response.ts +4 -4
  424. package/src/server/html-injector-core.ts +2 -2
  425. package/src/server/html-injectors.ts +2 -4
  426. package/src/server/index.ts +0 -4
  427. package/src/server/instrumentation.ts +10 -3
  428. package/src/server/internal.ts +1 -6
  429. package/src/server/json-status-response.ts +105 -0
  430. package/src/server/logger.ts +39 -3
  431. package/src/server/param-coercion.ts +15 -12
  432. package/src/server/pipeline-helpers.ts +257 -12
  433. package/src/server/pipeline-interception.ts +133 -0
  434. package/src/server/pipeline-outcome.ts +103 -31
  435. package/src/server/pipeline-phases.ts +127 -237
  436. package/src/server/pipeline.ts +204 -207
  437. package/src/server/prebuilt/capture-render.ts +118 -0
  438. package/src/server/prebuilt/capture-routes.ts +104 -0
  439. package/src/server/prebuilt/capture-state.ts +155 -48
  440. package/src/server/prebuilt/lifetime.ts +151 -0
  441. package/src/server/prebuilt/slots.ts +14 -2
  442. package/src/server/prebuilt/synthetic-store.ts +3 -0
  443. package/src/server/prebuilt-builder.ts +30 -320
  444. package/src/server/prebuilt-runtime.ts +125 -129
  445. package/src/server/primitives.ts +8 -168
  446. package/src/server/react-cache-bridge.ts +124 -0
  447. package/src/server/react-cache-scope.ts +104 -0
  448. package/src/server/render-timeout.ts +20 -0
  449. package/src/server/render-utils.ts +11 -1
  450. package/src/server/request-context.ts +36 -9
  451. package/src/server/route-element-builder.ts +11 -6
  452. package/src/server/route-handler.ts +36 -23
  453. package/src/server/route-matcher.ts +15 -1
  454. package/src/server/rsc-entry/action-middleware-runner.ts +79 -123
  455. package/src/server/rsc-entry/api-handler.ts +27 -103
  456. package/src/server/rsc-entry/deny-fallback.ts +93 -26
  457. package/src/server/rsc-entry/error-renderer.ts +39 -91
  458. package/src/server/rsc-entry/helpers.ts +2 -4
  459. package/src/server/rsc-entry/index.ts +64 -58
  460. package/src/server/rsc-entry/render-route.ts +15 -80
  461. package/src/server/rsc-entry/render-signals.ts +108 -0
  462. package/src/server/rsc-entry/revalidate-renderer.ts +56 -57
  463. package/src/server/rsc-entry/rsc-payload.ts +28 -61
  464. package/src/server/rsc-entry/rsc-stream.ts +113 -213
  465. package/src/server/rsc-entry/ssr-bridge.ts +2 -2
  466. package/src/server/rsc-entry/ssr-renderer.ts +182 -263
  467. package/src/server/rsc-entry/wrap-action-dispatch.ts +12 -14
  468. package/src/server/signal-identity.ts +112 -0
  469. package/src/server/slot-resolver.ts +18 -18
  470. package/src/server/slot-subtree-contain.ts +2 -1
  471. package/src/server/ssr-bridge-types.ts +92 -56
  472. package/src/server/ssr-entry.ts +87 -111
  473. package/src/server/ssr-render.ts +55 -64
  474. package/src/server/ssr-wrappers.tsx +2 -2
  475. package/src/server/static-generator.ts +7 -42
  476. package/src/server/static-not-found.ts +3 -3
  477. package/src/server/stream-utils.ts +51 -0
  478. package/src/server/tracing.ts +58 -75
  479. package/src/server/types.ts +1 -1
  480. package/src/server/version-skew.ts +5 -5
  481. package/src/shared/csrf-reject.ts +15 -0
  482. package/src/shared/error-digest.ts +46 -0
  483. package/src/shared/payload-root.ts +11 -10
  484. package/src/shared/rsc-payload-path.ts +8 -1
  485. package/src/utils/write-file-atomic.ts +32 -0
  486. package/dist/_chunks/actions-jNrXdzgs.js +0 -346
  487. package/dist/_chunks/actions-jNrXdzgs.js.map +0 -1
  488. package/dist/_chunks/als-registry-C6kcfprT.js.map +0 -1
  489. package/dist/_chunks/build-manifest-DTmSGLRz.js.map +0 -1
  490. package/dist/_chunks/build-output-helper-9dqCv1pZ.js.map +0 -1
  491. package/dist/_chunks/cache-api-CUD9Ezaq.js.map +0 -1
  492. package/dist/_chunks/cli-check-G8o30ldg.js.map +0 -1
  493. package/dist/_chunks/convention-lint-5KzoMg_A.js.map +0 -1
  494. package/dist/_chunks/dev-server-BzBxgYAV.js.map +0 -1
  495. package/dist/_chunks/error-boundary-BrHmG-2X.js.map +0 -1
  496. package/dist/_chunks/fs-identity-D7vb6GdI.js.map +0 -1
  497. package/dist/_chunks/graph-cache-CP4GEmf9.js.map +0 -1
  498. package/dist/_chunks/json-lossy-check-ClNvBM_3.js.map +0 -1
  499. package/dist/_chunks/logger-k2DQ4EUf.js.map +0 -1
  500. package/dist/_chunks/navigation-context-D0TU0Jog.js.map +0 -1
  501. package/dist/_chunks/plugin-context-8idfR3UZ.js.map +0 -1
  502. package/dist/_chunks/primitives-DLAnvsrk.js.map +0 -1
  503. package/dist/_chunks/segment-context-D9_89u34.js +0 -34
  504. package/dist/_chunks/segment-context-D9_89u34.js.map +0 -1
  505. package/dist/_chunks/sizeof-lXffQ1Vr.js.map +0 -1
  506. package/dist/_chunks/ssr-data-D6T6Y3ef.js +0 -60
  507. package/dist/_chunks/ssr-data-D6T6Y3ef.js.map +0 -1
  508. package/dist/_chunks/state-FippDgxN.js.map +0 -1
  509. package/dist/_chunks/status-page-marker-CNbpUOPB.js.map +0 -1
  510. package/dist/client/types.d.ts +0 -14
  511. package/dist/client/types.d.ts.map +0 -1
  512. package/dist/plugins/adapter-build.d.ts +0 -38
  513. package/dist/plugins/adapter-build.d.ts.map +0 -1
  514. package/dist/server/asset-headers.d.ts +0 -32
  515. package/dist/server/asset-headers.d.ts.map +0 -1
  516. package/dist/server/dev-source-map.d.ts +0 -22
  517. package/dist/server/dev-source-map.d.ts.map +0 -1
  518. package/src/client/types.ts +0 -21
  519. package/src/server/asset-headers.ts +0 -59
  520. package/src/server/dev-source-map.ts +0 -31
@@ -18,7 +18,6 @@
18
18
  * this in try/catch.
19
19
  */
20
20
 
21
- import { getCookiesForSsr, getSetCookieHeaders } from '../cookie-context.ts';
22
21
  import {
23
22
  applyRequestHeaderOverlay,
24
23
  runWithRequestContext,
@@ -26,149 +25,106 @@ import {
26
25
  setSegmentParams,
27
26
  } from '../request-context.ts';
28
27
  import { runMiddlewareChain } from '../middleware-runner.ts';
29
- import { isDenySignal, isRedirectSignal, DenySignal, RedirectSignal } from '../primitives.ts';
30
- import { ParamCoercionError } from '../param-coercion.ts';
28
+ import { DenySignal, RedirectSignal } from '../primitives.ts';
29
+ import { isDenySignal, isRedirectSignal } from '../signal-identity.ts';
31
30
  import type { RouteMatch } from '../pipeline.ts';
32
31
  import type { MiddlewareContext } from '../types.ts';
33
32
  import { requestCspNonce } from '../csp-nonce.ts';
34
-
35
- /** Coerce a matched route's segment params via its `params.ts` codecs. */
36
- export type CoerceSegmentParamsFn = (match: RouteMatch) => Promise<void>;
33
+ import type { ReactCacheScope } from '../react-cache-scope.ts';
37
34
 
38
35
  /**
39
- * Outcome of running middleware on an action request, surfaced from the
40
- * inner `runWithRequestContext` scope so the outer dispatcher can convert
41
- * it to a Response (short-circuit) or continue to the action handler.
36
+ * Outcome of running a route's middleware chain, surfaced from the inner
37
+ * `runWithRequestContext` scope as a value. Its one consumer is the
38
+ * revalidation renderer, which turns every variant but `continue` into
39
+ * a thrown signal or a dropped revalidation.
42
40
  *
43
- * Each variant carries the post-middleware Set-Cookie snapshot so the
44
- * outer scope can apply cookies to whichever Response it ultimately
45
- * returns. The middleware ALS scope ends before the action ALS scope
46
- * begins, so cookie state must be threaded explicitly across the boundary
47
- * via `seedRequestCookies` (cookie reads) and `setCookieHeaders` (cookie
48
- * writes).
41
+ * Only `continue` carries state out of the scope: the request-header
42
+ * overlay, which the renderer applies to the action's scope so the
43
+ * revalidated tree sees middleware-injected headers. Cookies the chain sets
44
+ * stay in the inner scope and are discarded with it; see the renderer's
45
+ * docstring for why.
49
46
  */
50
47
  export type MiddlewareOutcome =
51
- | {
52
- kind: 'continue';
53
- overlay: Headers;
54
- cookies: Map<string, string>;
55
- setCookieHeaders: string[];
56
- }
57
- | {
58
- kind: 'short-circuit';
59
- response: Response;
60
- setCookieHeaders: string[];
61
- }
62
- | {
63
- kind: 'redirect';
64
- signal: RedirectSignal;
65
- setCookieHeaders: string[];
66
- }
67
- | {
68
- kind: 'deny';
69
- signal: DenySignal;
70
- match: RouteMatch;
71
- setCookieHeaders: string[];
72
- }
73
- | {
74
- kind: 'param-coercion-error';
75
- }
76
- | {
77
- kind: 'error';
78
- error: unknown;
79
- };
48
+ | { kind: 'continue'; overlay: Headers }
49
+ | { kind: 'short-circuit'; response: Response }
50
+ | { kind: 'redirect'; signal: RedirectSignal }
51
+ | { kind: 'deny'; signal: DenySignal }
52
+ | { kind: 'error'; error: unknown };
53
+
54
+ /** The inner request scope's inputs, besides the request itself. */
55
+ export interface MiddlewareScope {
56
+ /** The `React.cache` scope the revalidated tree will render in. */
57
+ reactCacheScope: ReactCacheScope;
58
+ /** The action's post-mutation cookies, as the inner scope's cookies. */
59
+ cookies?: Map<string, string>;
60
+ }
80
61
 
81
62
  /**
82
63
  * Run the matched route's middleware chain inside a fresh request-context
83
- * scope, captured as a `MiddlewareOutcome` value the outer dispatcher can
84
- * translate to a Response or use as the seed for the action handler.
64
+ * scope, captured as a `MiddlewareOutcome` value.
65
+ *
66
+ * `match` must already carry coerced segment params: coercion runs before
67
+ * middleware, in the caller, as it does in the page pipeline.
85
68
  */
86
69
  export async function runMiddlewareForAction(
87
70
  req: Request,
88
71
  match: RouteMatch,
89
- coerceSegmentParams: CoerceSegmentParamsFn
72
+ { reactCacheScope, cookies }: MiddlewareScope
90
73
  ): Promise<MiddlewareOutcome> {
91
- return runWithRequestContext(req, async (): Promise<MiddlewareOutcome> => {
92
- // ─── Coerce segment params (mirrors page pipeline) ──────────────
93
- try {
94
- await coerceSegmentParams(match);
95
- } catch (err) {
96
- if (err instanceof ParamCoercionError) {
97
- return { kind: 'param-coercion-error' };
98
- }
99
- return { kind: 'error', error: err };
100
- }
101
- setSegmentParams(match.segmentParams);
74
+ return runWithRequestContext(
75
+ req,
76
+ async (): Promise<MiddlewareOutcome> => {
77
+ setSegmentParams(match.segmentParams);
102
78
 
103
- // ─── Build the middleware context ───────────────────────────────
104
- const responseHeaders = new Headers();
105
- const requestHeaderOverlay = new Headers();
106
- const ctx: MiddlewareContext = {
107
- req,
108
- requestHeaders: requestHeaderOverlay,
109
- headers: responseHeaders,
110
- segmentParams: match.segmentParams,
111
- // 103 Early Hints are a page-render concern — server actions are
112
- // RPC and never produce HTML, so there is nothing to hint about.
113
- // Provide a no-op so user middleware can call `ctx.earlyHints()`
114
- // unconditionally without branching on request kind.
115
- earlyHints: () => {},
116
- // Same reasoning: an action response carries no inline scripts, so a
117
- // nonce has nothing to stamp. Still a real value so middleware that
118
- // builds its CSP header unconditionally keeps working.
119
- get nonce() {
120
- return requestCspNonce();
121
- },
122
- };
79
+ // ─── Build the middleware context ───────────────────────────────
80
+ const responseHeaders = new Headers();
81
+ const requestHeaderOverlay = new Headers();
82
+ const ctx: MiddlewareContext = {
83
+ req,
84
+ requestHeaders: requestHeaderOverlay,
85
+ headers: responseHeaders,
86
+ segmentParams: match.segmentParams,
87
+ // 103 Early Hints are a page-render concern — server actions are
88
+ // RPC and never produce HTML, so there is nothing to hint about.
89
+ // Provide a no-op so user middleware can call `ctx.earlyHints()`
90
+ // unconditionally without branching on request kind.
91
+ earlyHints: () => {},
92
+ // Same reasoning: an action response carries no inline scripts, so a
93
+ // nonce has nothing to stamp. Still a real value so middleware that
94
+ // builds its CSP header unconditionally keeps working.
95
+ get nonce() {
96
+ return requestCspNonce();
97
+ },
98
+ };
123
99
 
124
- // ─── Run the chain ──────────────────────────────────────────────
125
- setMutableCookieContext(true);
126
- try {
127
- let middlewareResponse: Response | undefined;
100
+ // ─── Run the chain ──────────────────────────────────────────────
101
+ setMutableCookieContext(true);
128
102
  try {
129
- middlewareResponse = await runMiddlewareChain(match.middlewareChain, ctx);
130
- } catch (err) {
131
- if (isRedirectSignal(err)) {
132
- return {
133
- kind: 'redirect',
134
- signal: err,
135
- setCookieHeaders: getSetCookieHeaders(),
136
- };
103
+ let middlewareResponse: Response | undefined;
104
+ try {
105
+ middlewareResponse = await runMiddlewareChain(match.middlewareChain, ctx);
106
+ } catch (err) {
107
+ if (isRedirectSignal(err)) return { kind: 'redirect', signal: err };
108
+ if (isDenySignal(err)) return { kind: 'deny', signal: err };
109
+ return { kind: 'error', error: err };
137
110
  }
138
- if (isDenySignal(err)) {
139
- return {
140
- kind: 'deny',
141
- signal: err,
142
- match,
143
- setCookieHeaders: getSetCookieHeaders(),
144
- };
145
- }
146
- return { kind: 'error', error: err };
147
- }
148
111
 
149
- if (middlewareResponse) {
150
- return {
151
- kind: 'short-circuit',
152
- response: middlewareResponse,
153
- setCookieHeaders: getSetCookieHeaders(),
154
- };
155
- }
112
+ if (middlewareResponse) {
113
+ return { kind: 'short-circuit', response: middlewareResponse };
114
+ }
156
115
 
157
- // Middleware passed — apply the request-header overlay to the
158
- // current scope so any code that might still read it within
159
- // this scope sees the merged view. The overlay is also captured
160
- // in the outcome so the caller can re-apply it inside the
161
- // action's request-context scope (which is a separate ALS run).
162
- applyRequestHeaderOverlay(requestHeaderOverlay);
116
+ // Middleware passed — apply the request-header overlay to the
117
+ // current scope so any code that might still read it within
118
+ // this scope sees the merged view. The overlay is also captured
119
+ // in the outcome so the caller can re-apply it inside the
120
+ // action's request-context scope (which is a separate ALS run).
121
+ applyRequestHeaderOverlay(requestHeaderOverlay);
163
122
 
164
- return {
165
- kind: 'continue',
166
- overlay: requestHeaderOverlay,
167
- cookies: getCookiesForSsr(),
168
- setCookieHeaders: getSetCookieHeaders(),
169
- };
170
- } finally {
171
- setMutableCookieContext(false);
172
- }
173
- });
123
+ return { kind: 'continue', overlay: requestHeaderOverlay };
124
+ } finally {
125
+ setMutableCookieContext(false);
126
+ }
127
+ },
128
+ { reactCacheScope, cookies }
129
+ );
174
130
  }
@@ -4,15 +4,20 @@
4
4
  * Runs access.ts standalone for all segments in the chain (no React render
5
5
  * pass, no AccessGate component). Then dispatches to the route handler.
6
6
  * See design/04-authorization.md §"Auth in API Routes".
7
+ *
8
+ * Nothing thrown here is answered here. A `deny()` or `redirect()` from
9
+ * `access.ts` or a method handler, and every other error, propagates to the
10
+ * pipeline: its deny fallback answers a route.ts match in the JSON status
11
+ * format, its redirect builder sends the 3xx, and its error outcome answers
12
+ * errors in the same JSON format. There is one translator for each, not one
13
+ * per route type (TIM-1537, TIM-1533).
7
14
  */
8
15
 
9
16
  import { withSpan, setSpanAttribute } from '../tracing.ts';
10
17
  import type { ManifestSegmentNode } from '../route-matcher.ts';
11
18
  import { loadModule } from '../safe-load.ts';
12
- import { isDenySignal, isRedirectSignal, DenySignal, RedirectSignal } from '../primitives.ts';
19
+ import { isDenySignal, isRedirectSignal } from '../signal-identity.ts';
13
20
  import { handleRouteRequest } from '../route-handler.ts';
14
- import { stripHeadBody } from '../head-response.ts';
15
- import { isDebug } from '../debug.ts';
16
21
  import type { RouteModule } from '../route-handler.ts';
17
22
  import type { RouteContext } from '../types.ts';
18
23
 
@@ -40,33 +45,27 @@ export async function handleApiRoute(
40
45
  const accessMod = await loadModule(segment.access);
41
46
  const accessFn = accessMod.default as (() => unknown) | undefined;
42
47
  if (accessFn) {
43
- try {
44
- await withSpan(
45
- 'timber.access',
46
- { 'timber.segment': segment.segmentName ?? 'unknown' },
47
- async () => {
48
- try {
49
- await accessFn();
50
- await setSpanAttribute('timber.result', 'pass');
51
- } catch (error) {
52
- if (isDenySignal(error)) {
53
- await setSpanAttribute('timber.result', 'deny');
54
- await setSpanAttribute('timber.deny_status', error.status);
55
- if (error.sourceFile) {
56
- await setSpanAttribute('timber.deny_file', error.sourceFile);
57
- }
58
- } else if (isRedirectSignal(error)) {
59
- await setSpanAttribute('timber.result', 'redirect');
48
+ await withSpan(
49
+ 'timber.access',
50
+ { 'timber.segment': segment.segmentName ?? 'unknown' },
51
+ async () => {
52
+ try {
53
+ await accessFn();
54
+ await setSpanAttribute('timber.result', 'pass');
55
+ } catch (error) {
56
+ if (isDenySignal(error)) {
57
+ await setSpanAttribute('timber.result', 'deny');
58
+ await setSpanAttribute('timber.deny_status', error.status);
59
+ if (error.sourceFile) {
60
+ await setSpanAttribute('timber.deny_file', error.sourceFile);
60
61
  }
61
- throw error;
62
+ } else if (isRedirectSignal(error)) {
63
+ await setSpanAttribute('timber.result', 'redirect');
62
64
  }
65
+ throw error;
63
66
  }
64
- );
65
- } catch (error) {
66
- const signalResponse = await translateApiSignal(error, req, segments, responseHeaders);
67
- if (signalResponse) return signalResponse;
68
- throw error;
69
- }
67
+ }
68
+ );
70
69
  }
71
70
  }
72
71
  }
@@ -77,80 +76,5 @@ export async function handleApiRoute(
77
76
  // the request-context ALS that the pipeline already populated.
78
77
  const routeMod = await loadModule<RouteModule>(leaf.route!);
79
78
  const ctx: RouteContext = { req, headers: responseHeaders };
80
- try {
81
- return await handleRouteRequest(routeMod, ctx);
82
- } catch (error) {
83
- const signalResponse = await translateApiSignal(error, req, segments, responseHeaders);
84
- if (signalResponse) return signalResponse;
85
- throw error;
86
- }
87
- }
88
-
89
- /**
90
- * Translate a control-flow signal thrown from access.ts or a route.ts
91
- * method handler into the proper API response: DenySignal → JSON status-file
92
- * chain via `renderApiDeny`, RedirectSignal → bare 3xx with Location header.
93
- *
94
- * For HEAD requests, strip the deny body to preserve HEAD semantics — signals
95
- * bypass the HEAD path in `handleRouteRequest`, so this exit needs its own
96
- * call. Shares `stripHeadBody` with that path and with the pipeline exit; the
97
- * pipeline applying it again downstream is a no-op (TIM-1324).
98
- *
99
- * Returns `null` for non-signal errors so the caller knows to rethrow.
100
- */
101
- async function translateApiSignal(
102
- error: unknown,
103
- req: Request,
104
- segments: ManifestSegmentNode[],
105
- responseHeaders: Headers
106
- ): Promise<Response | null> {
107
- if (isDenySignal(error)) {
108
- return stripHeadBody(await renderApiDeny(error, segments, responseHeaders), req.method);
109
- }
110
- if (isRedirectSignal(error)) {
111
- responseHeaders.set('Location', error.location);
112
- return new Response(null, { status: error.status, headers: responseHeaders });
113
- }
114
- return null;
115
- }
116
-
117
- /**
118
- * Render a deny response for an API route (route.ts).
119
- *
120
- * Tries JSON status file chain first. Falls back to bare JSON response.
121
- * Never renders a component — API consumers get structured JSON, not HTML.
122
- * See design/10-error-handling.md §"Format Selection for deny()"
123
- */
124
- async function renderApiDeny(
125
- deny: DenySignal,
126
- segments: ManifestSegmentNode[],
127
- responseHeaders: Headers
128
- ): Promise<Response> {
129
- const { resolveStatusFile } = await import('../status-code-resolver.ts');
130
-
131
- const resolution = resolveStatusFile(deny.status, segments, 'json');
132
- if (resolution) {
133
- if (isDebug() && deny.data !== undefined) {
134
- console.warn(
135
- `[timber] deny(${deny.status}, data) resolved to ${resolution.file.filePath}, ` +
136
- `which is a static JSON file. The data argument is dropped — JSON status files ` +
137
- `are returned verbatim with no interpolation. If you need the data in the ` +
138
- `response, use a route handler (route.ts) that returns Response.json() directly.`
139
- );
140
- }
141
- const mod = await loadModule(resolution.file);
142
- const jsonContent = mod.default ?? mod;
143
- responseHeaders.set('content-type', 'application/json; charset=utf-8');
144
- return new Response(JSON.stringify(jsonContent), {
145
- status: deny.status,
146
- headers: responseHeaders,
147
- });
148
- }
149
-
150
- // No JSON status file — bare JSON fallback
151
- responseHeaders.set('content-type', 'application/json; charset=utf-8');
152
- return new Response(JSON.stringify({ error: true, status: deny.status }), {
153
- status: deny.status,
154
- headers: responseHeaders,
155
- });
79
+ return handleRouteRequest(routeMod, ctx);
156
80
  }
@@ -1,22 +1,29 @@
1
1
  /**
2
2
  * Deny fallback renderer — renders the deny page (403.tsx, 404.tsx, etc.)
3
- * for DenySignals that escape from middleware or the render phase.
3
+ * for DenySignals that escape from proxy, middleware, or the render phase,
4
+ * and the 404 page for a URL no route matches.
5
+ *
6
+ * This is the one module that assembles deny pages. Renderers report a
7
+ * captured deny by rethrowing it; the pipeline's outcome translator calls
8
+ * this. See design/49-explicit-subsystem-boundaries.md §"C".
4
9
  *
5
10
  * Extracted from index.ts (TIM-968) as a pure move. The factory captures
6
11
  * the root segment and client bootstrap config once at handler creation;
7
- * the returned function is wired into `PipelineConfig.renderDenyFallback`
8
- * and reused by the action-dispatch wrapper.
12
+ * the returned function is wired into `PipelineConfig.renderDenyFallback`.
9
13
  *
10
14
  * Design docs: 04-authorization.md, 10-error-handling.md
11
15
  */
12
16
 
13
- import type { LayoutEntry } from '../deny-renderer.ts';
17
+ import { getFirstDeniedSegmentIndex } from '../deny-boundary.ts';
18
+ import type { DefaultPageRenderer, LayoutEntry } from '../deny-renderer.ts';
14
19
  import { renderDenyPage, renderDenyPageAsRsc } from '../deny-renderer.ts';
15
20
  import type { ClientBootstrapConfig } from '../html-injectors.ts';
16
- import { logRenderError } from '../logger.ts';
17
- import type { PipelineConfig, RouteMatch } from '../pipeline.ts';
18
- import type { ManifestSegmentNode } from '../route-matcher.ts';
19
- import { loadModule } from '../safe-load.ts';
21
+ import { renderJsonStatusResponse } from '../json-status-response.ts';
22
+ import { loadFallbackModule } from '../pipeline-helpers.ts';
23
+ import type { RouteMatch } from '../pipeline.ts';
24
+ import type { DenySignal } from '../primitives.ts';
25
+ import { isApiRouteChain, type ManifestSegmentNode } from '../route-matcher.ts';
26
+ import { rscErrorEnvelope } from '../rsc-error-envelope.ts';
20
27
  import { isRscRequest } from '../../shared/rsc-media-type.ts';
21
28
  import { callSsr } from './ssr-bridge.ts';
22
29
 
@@ -29,30 +36,73 @@ import { callSsr } from './ssr-bridge.ts';
29
36
  * route's `401.json` are picked up. Fall back to the root chain when no
30
37
  * match is available (e.g. proxy-stage deny before route matching).
31
38
  * See TIM-822, design/04-authorization.md, design/10-error-handling.md.
39
+ *
40
+ * The page is clamped to the denied segment exactly as the renderer clamps a
41
+ * captured deny: the index an AccessGate or layout recorded in request ALS
42
+ * bounds the status-file walk and the layout shell, so a thrown deny never
43
+ * selects a status file below the denial or runs the denied segment's
44
+ * layout. It is read here, at call time, rather than passed by the pipeline:
45
+ * the store is RSC-owned and the pipeline does not know it exists.
46
+ *
47
+ * The index is a position in the matched chain, so it is applied only when
48
+ * there is one. A proxy-phase deny arrives with no match (root-only chain),
49
+ * and one thrown after `await next()` shares the request store with the
50
+ * render it replaced — that render's denied index describes a different
51
+ * deny and must not clamp this one. A middleware-phase deny runs before
52
+ * render, so no index has been recorded. See TIM-1525, design/49-explicit-subsystem-boundaries.md §P0.
32
53
  */
33
54
  export function createDenyFallbackRenderer(options: {
34
55
  rootSegment: ManifestSegmentNode;
35
56
  clientBootstrap: ClientBootstrapConfig;
36
- }): NonNullable<PipelineConfig['renderDenyFallback']> {
57
+ }): DenyFallbackRenderer {
37
58
  const { rootSegment, clientBootstrap } = options;
38
- return async (deny, req, responseHeaders, matchedRoute) => {
59
+ return async (deny, req, responseHeaders, matchedRoute, defaultPage) => {
39
60
  const chain: ManifestSegmentNode[] = matchedRoute ? matchedRoute.segments : [rootSegment];
61
+
62
+ // A route.ts match answers in JSON whatever the Accept header says —
63
+ // before the RSC dispatch below, and without loading layouts it would
64
+ // never render. No AccessGate runs on an API route, so there is no
65
+ // denied-segment index to clamp to. See design/10-error-handling.md
66
+ // §"Format Selection for deny()".
67
+ //
68
+ // Asked of the match, not of `chain`: with no match the chain is the
69
+ // root alone, and an `app/route.ts` puts `route` on the root node. An
70
+ // unmatched URL or a proxy-phase deny is not a request to that route.
71
+ if (matchedRoute && isApiRouteChain(matchedRoute.segments)) {
72
+ return renderJsonStatusResponse(
73
+ req,
74
+ deny.status,
75
+ chain,
76
+ responseHeaders,
77
+ undefined,
78
+ deny.data
79
+ );
80
+ }
81
+
82
+ // A skipped segment whose access just flipped to deny marks the signal
83
+ // for hard-navigate: rendering a deny page here would execute the denied
84
+ // segment's protected layout and place it inside cached client chrome
85
+ // (TIM-1074). The envelope makes the client hard-navigate for a clean
86
+ // full render with correct deny page placement. See TIM-1363.
87
+ if (deny._hardNavigate && isRscRequest(req)) {
88
+ return rscErrorEnvelope(deny.status, responseHeaders);
89
+ }
90
+
91
+ // A layout that fails to import or evaluate is reported, and the page is
92
+ // wrapped in the layouts above it: a partial chain is acceptable, a deny
93
+ // page taken down by its layout is not. Nothing below the failure is
94
+ // wrapped, so a deeper layout never renders without its parent.
40
95
  const layoutComponents: LayoutEntry[] = [];
41
- try {
42
- for (const segment of chain) {
43
- if (!segment.layout) continue;
44
- const mod = await loadModule(segment.layout);
45
- if (mod.default) {
46
- layoutComponents.push({
47
- component: mod.default as (...args: unknown[]) => unknown,
48
- segment,
49
- });
50
- }
96
+ for (const segment of chain) {
97
+ if (!segment.layout) continue;
98
+ const mod = await loadFallbackModule(segment.layout, req, chain);
99
+ if (!mod) break;
100
+ if (mod.default) {
101
+ layoutComponents.push({
102
+ component: mod.default as (...args: unknown[]) => unknown,
103
+ segment,
104
+ });
51
105
  }
52
- } catch (layoutError) {
53
- // Layout failed to load — proceed without it. Partial layout chains
54
- // are acceptable; the deny renderer wraps in whatever loaded.
55
- logRenderError({ method: req.method, path: new URL(req.url).pathname, error: layoutError });
56
106
  }
57
107
  // Reuse the matched route's params/middleware metadata when present so
58
108
  // downstream rendering sees the real route shape. Otherwise synthesise
@@ -60,6 +110,7 @@ export function createDenyFallbackRenderer(options: {
60
110
  const match: RouteMatch = matchedRoute ?? {
61
111
  segments: chain,
62
112
  segmentParams: {},
113
+ rawSegmentParams: {},
63
114
  middlewareChain: [],
64
115
  };
65
116
  // For client navigation (Accept: text/x-component), the timber router
@@ -67,8 +118,9 @@ export function createDenyFallbackRenderer(options: {
67
118
  // decoder breaks navigation, so dispatch to the RSC renderer when the
68
119
  // request is an RSC payload request — mirroring the normal render path.
69
120
  // See design/19-client-navigation.md §"RSC Payload Handling" and TIM-823.
121
+ const deniedIndex = matchedRoute ? getFirstDeniedSegmentIndex() : Infinity;
70
122
  if (isRscRequest(req)) {
71
- return renderDenyPageAsRsc(deny, chain, layoutComponents, req, responseHeaders);
123
+ return renderDenyPageAsRsc(deny, chain, layoutComponents, req, responseHeaders, deniedIndex);
72
124
  }
73
125
  return renderDenyPage(
74
126
  deny,
@@ -78,7 +130,22 @@ export function createDenyFallbackRenderer(options: {
78
130
  match,
79
131
  responseHeaders,
80
132
  clientBootstrap,
81
- callSsr
133
+ callSsr,
134
+ defaultPage,
135
+ deniedIndex
82
136
  );
83
137
  };
84
138
  }
139
+
140
+ /**
141
+ * The deny fallback. `defaultPage` replaces the framework default status
142
+ * page when no status file answers — the dev 404 route listing for an
143
+ * unmatched URL.
144
+ */
145
+ export type DenyFallbackRenderer = (
146
+ deny: DenySignal,
147
+ req: Request,
148
+ responseHeaders: Headers,
149
+ matchedRoute?: RouteMatch,
150
+ defaultPage?: DefaultPageRenderer
151
+ ) => Promise<Response>;