@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
@@ -11,7 +11,8 @@
11
11
  * [timber] INFO message method=GET path=/dashboard status=200 durationMs=43 trace_id=4bf92f35
12
12
  *
13
13
  * Behavior:
14
- * - Suppressed entirely in dev mode (dev logging handles all output)
14
+ * - `info` and `debug` suppressed in dev mode (dev logging handles them);
15
+ * `warn` and `error` are always written (TIM-555)
15
16
  * - `debug` suppressed unless TIMBER_DEBUG is set
16
17
  * - Replaced entirely when a custom logger is set via `setLogger()`
17
18
  *
@@ -39,8 +39,9 @@ import { ErrorReconstituter } from '../client/error-reconstituter.tsx';
39
39
  import type { SerializableError } from '../client/error-reconstituter.tsx';
40
40
  import { StatusPageMarker } from '../client/status-page-marker.tsx';
41
41
  import { requestContextAls } from './als-registry.ts';
42
- import { isDenySignal, DenySignal } from './primitives.ts';
43
- import { loadModule } from './safe-load.ts';
42
+ import { DenySignal } from './primitives.ts';
43
+ import { isDenySignal } from './signal-identity.ts';
44
+ import { loadFallbackModule } from './pipeline-helpers.ts';
44
45
  import type { ManifestLoader } from './safe-load.ts';
45
46
  import { withSpan } from './tracing.ts';
46
47
  import { isValidElementType, type LoadedComponent } from './utils/element-type.ts';
@@ -136,8 +137,12 @@ export type DenyPlacement =
136
137
  *
137
138
  * See TIM-1356.
138
139
  */
139
- async function loadChainComponent(file: ManifestLoader): Promise<LoadedComponent | null> {
140
- const mod = await loadModule(file).catch(() => null);
140
+ async function loadChainComponent(
141
+ file: ManifestLoader,
142
+ req: Request,
143
+ segments: ManifestSegmentNode[]
144
+ ): Promise<LoadedComponent | null> {
145
+ const mod = await loadFallbackModule(file, req, segments);
141
146
  return isValidElementType(mod?.default) ? mod.default : null;
142
147
  }
143
148
 
@@ -159,7 +164,8 @@ async function loadChainComponent(file: ManifestLoader): Promise<LoadedComponent
159
164
  export async function buildDenyPageChain(
160
165
  segments: ManifestSegmentNode[],
161
166
  startIndex: number,
162
- segmentKeys: string[]
167
+ segmentKeys: string[],
168
+ req: Request
163
169
  ): Promise<DenyPageEntry[]> {
164
170
  const chain: DenyPageEntry[] = [];
165
171
 
@@ -176,7 +182,7 @@ export async function buildDenyPageChain(
176
182
  if (key !== '4xx' && key !== '5xx') {
177
183
  const status = parseInt(key, 10);
178
184
  if (!isNaN(status)) {
179
- const component = await loadChainComponent(file);
185
+ const component = await loadChainComponent(file, req, segments);
180
186
  if (component) {
181
187
  chain.push({
182
188
  status,
@@ -193,7 +199,7 @@ export async function buildDenyPageChain(
193
199
  // Category catch-alls (4xx.tsx, 5xx.tsx)
194
200
  for (const [key, file] of Object.entries(segment.statusFiles)) {
195
201
  if (key === '4xx' || key === '5xx') {
196
- const component = await loadChainComponent(file);
202
+ const component = await loadChainComponent(file, req, segments);
197
203
  if (component) {
198
204
  const categoryStatus = key === '4xx' ? 400 : 500;
199
205
  chain.push({
@@ -214,7 +220,7 @@ export async function buildDenyPageChain(
214
220
  for (let i = startIndex; i >= 0; i--) {
215
221
  const segment = segments[i];
216
222
  if (segment.error) {
217
- const component = await loadChainComponent(segment.error);
223
+ const component = await loadChainComponent(segment.error, req, segments);
218
224
  if (component) {
219
225
  chain.push({
220
226
  status: null,
@@ -394,11 +400,17 @@ function renderDenyPage(
394
400
  * Otherwise it throws — annotated with `ownerKey` when an ancestor owns the
395
401
  * file, bare when nothing matched at all.
396
402
  *
397
- * `setDenyStatus` runs on the hoist path too, and must run *before* the
398
- * throw: on the document path the hoisted row fails the Fizz shell and the
399
- * re-render fallback serves the page, and the ALS status is what the
400
- * pipeline commits for it. The RSC payload path never reads it — a Flight
401
- * payload response is always 200 and the row itself carries the deny (TIM-1495).
403
+ * `setDenyStatus` runs on the hoist path too, *before* the throw, for one
404
+ * case. Normally Flight's `onError` captures the rethrown signal within the
405
+ * renderer's promotion cap, and the pipeline renders the deny page with
406
+ * `deny.status` — the recorded status goes unread. When the signal lands
407
+ * after the cap but within the detection window that follows, the renderer
408
+ * discards it (never promoted) and streams the document it already has;
409
+ * `getDenyStatus()`, read once as the renderer returns, gives that document
410
+ * the deny's 4xx instead of a 200. A deny later than that commits 200. Pinned by
411
+ * `tests/late-hoisted-deny-status.test.ts`. The RSC payload path never
412
+ * reads it — a Flight payload response is always 200 and the row itself
413
+ * carries the deny (TIM-1495).
402
414
  *
403
415
  * Either branch leaves part of the matched chain unmounted — hoisting sends
404
416
  * the render to a boundary that discards everything below it, and a layout
@@ -20,12 +20,11 @@ import { renderToReadableStream } from '../rsc-runtime/rsc.ts';
20
20
 
21
21
  import { DenySignal } from './primitives.ts';
22
22
  import { appVisibleSearch } from '../shared/rsc-cache-key.ts';
23
- import { getSlotParamsForClient } from './request-context.ts';
24
23
  import { withPublishedParams } from './publish-params.ts';
25
24
  import { renderDenyEntry, type DenyEntryShape } from './deny-boundary.ts';
26
25
  import { getCookiesForSsr } from './cookie-context.ts';
27
26
  import { logRenderError } from './logger.ts';
28
- import { loadModule } from './safe-load.ts';
27
+ import { loadFallbackModule, reportRenderError } from './pipeline-helpers.ts';
29
28
  import { isDebug } from './debug.ts';
30
29
  import { resolveMetadata, renderMetadataToElements } from './metadata.ts';
31
30
  import { headElementsToReact } from './metadata.ts';
@@ -33,8 +32,9 @@ import { resolveStatusFile } from './status-code-resolver.ts';
33
32
  import { defaultStatusPageResponse } from './default-status-page.ts';
34
33
  import { rscErrorEnvelope } from './rsc-error-envelope.ts';
35
34
  import type { ManifestSegmentNode } from './route-matcher.ts';
35
+ import { renderJsonStatusFile } from './json-status-response.ts';
36
36
  import type { RouteMatch } from './pipeline.ts';
37
- import type { NavContext } from './ssr-bridge-types.ts';
37
+ import type { NavContext, SsrRenderResult } from './ssr-bridge-types.ts';
38
38
  import { flightInitScript } from './flight-scripts.ts';
39
39
  import { getCspNonce } from './csp-nonce.ts';
40
40
  import type { ClientBootstrapConfig } from './html-injectors.ts';
@@ -52,15 +52,7 @@ export interface LayoutEntry {
52
52
  export type CallSsrFn = (
53
53
  rscStream: ReadableStream<Uint8Array>,
54
54
  navContext: NavContext
55
- ) => Promise<Response>;
56
-
57
- /**
58
- * Check if the leaf segment is an API route (has route.ts).
59
- */
60
- function isApiRoute(segments: ReadonlyArray<ManifestSegmentNode>): boolean {
61
- const leaf = segments[segments.length - 1];
62
- return !!leaf?.route;
63
- }
55
+ ) => Promise<SsrRenderResult>;
64
56
 
65
57
  /**
66
58
  * Build the deny page element for a resolved status file with the correct
@@ -121,19 +113,21 @@ export async function renderDenyPage(
121
113
  // (the gate-outside-layout rule from TIM-1074). See TIM-1358.
122
114
  const maxIndex = firstDeniedIndex < Infinity ? firstDeniedIndex : undefined;
123
115
 
124
- // API routes (route.ts) → JSON only, never render components
125
- if (isApiRoute(segments)) {
126
- const jsonResponse = await renderDenyPageJson(deny, segments, responseHeaders, maxIndex);
127
- if (jsonResponse) return jsonResponse;
128
- return bareJsonResponse(deny.status, responseHeaders);
129
- }
130
-
131
- // Page routes → component chain first, JSON fallback only if no component found.
116
+ // Page routes → component chain first, JSON fallback only if no component
117
+ // found. A route.ts chain never reaches here: the deny fallback answers it
118
+ // in JSON before choosing a page renderer.
132
119
  const resolution = resolveStatusFile(deny.status, segments, 'component', maxIndex);
133
120
 
134
121
  // No component status file — try JSON chain, then the framework default page.
135
122
  if (!resolution) {
136
- const jsonResponse = await renderDenyPageJson(deny, segments, responseHeaders, maxIndex);
123
+ const jsonResponse = await renderJsonStatusFile(
124
+ req,
125
+ deny.status,
126
+ segments,
127
+ responseHeaders,
128
+ maxIndex,
129
+ deny.data
130
+ );
137
131
  if (jsonResponse) return jsonResponse;
138
132
  return (
139
133
  defaultPage?.(deny.status, responseHeaders) ??
@@ -159,11 +153,18 @@ export async function renderDenyPage(
159
153
  // default — or whose module fails to import or evaluate — is not a usable
160
154
  // component match: continue down the documented chain (JSON, then framework
161
155
  // default) rather than returning an empty body or letting the loader's
162
- // rejection escape request handling. Mirrors buildDenyPageChain and the
163
- // error-file resolver, which both swallow the load failure.
164
- const mod = await loadModule(resolution.file).catch(() => null);
156
+ // rejection escape request handling. `loadFallbackModule` reports the load
157
+ // failure, as it does for every status and error page load.
158
+ const mod = await loadFallbackModule(resolution.file, req, segments);
165
159
  if (!mod?.default) {
166
- const jsonResponse = await renderDenyPageJson(deny, segments, responseHeaders, maxIndex);
160
+ const jsonResponse = await renderJsonStatusFile(
161
+ req,
162
+ deny.status,
163
+ segments,
164
+ responseHeaders,
165
+ maxIndex,
166
+ deny.data
167
+ );
167
168
  if (jsonResponse) return jsonResponse;
168
169
  return (
169
170
  defaultPage?.(deny.status, responseHeaders) ??
@@ -209,21 +210,17 @@ export async function renderDenyPage(
209
210
  const rscStream = renderToReadableStream(withPublishedParams(element), {
210
211
  signal: req.signal,
211
212
  onError(error: unknown) {
212
- logRenderError({ method: req.method, path: new URL(req.url).pathname, error });
213
+ reportRenderError(error, req, { segments });
213
214
  },
214
215
  });
215
216
 
216
217
  const [ssrStream, inlineStream] = teeWithErrorPropagation(rscStream);
217
218
 
218
- const slotParams = getSlotParamsForClient();
219
-
220
219
  const denyUrl = new URL(req.url);
221
220
  const nonce = getCspNonce();
222
221
  const navContext: NavContext = {
223
222
  pathname: denyUrl.pathname,
224
223
  search: appVisibleSearch(denyUrl).search,
225
- segmentParams: match.segmentParams,
226
- slotParams,
227
224
  statusCode: deny.status,
228
225
  responseHeaders,
229
226
  headHtml: flightInitScript(nonce),
@@ -241,7 +238,7 @@ export async function renderDenyPage(
241
238
  // own deny fallback catches this and can only produce an empty response,
242
239
  // and a crashing 404.tsx is exactly when the reader has nothing else to
243
240
  // go on (TIM-1258).
244
- return await callSsr(ssrStream, navContext);
241
+ return (await callSsr(ssrStream, navContext)).response;
245
242
  } catch (renderError) {
246
243
  logRenderError({ method: req.method, path: new URL(req.url).pathname, error: renderError });
247
244
  return defaultStatusPageResponse(deny.status, responseHeaders);
@@ -283,7 +280,7 @@ export async function renderDenyPageAsRsc(
283
280
  return denyHardNavigateResponse(deny.status, responseHeaders);
284
281
  }
285
282
 
286
- const mod = await loadModule(resolution.file).catch(() => null);
283
+ const mod = await loadFallbackModule(resolution.file, req, segments);
287
284
  if (!mod?.default) {
288
285
  return denyHardNavigateResponse(deny.status, responseHeaders);
289
286
  }
@@ -310,7 +307,7 @@ export async function renderDenyPageAsRsc(
310
307
  const rscStream = renderToReadableStream(withPublishedParams(element), {
311
308
  signal: req.signal,
312
309
  onError(error: unknown) {
313
- console.error('[timber] Error page RSC render error:', error);
310
+ reportRenderError(error, req);
314
311
  },
315
312
  });
316
313
 
@@ -325,68 +322,4 @@ export async function renderDenyPageAsRsc(
325
322
  });
326
323
  }
327
324
 
328
- // ─── JSON Rendering ─────────────────────────────────────────────────────────
329
-
330
- /**
331
- * Render a JSON status-code file for a DenySignal.
332
- *
333
- * JSON status files are returned verbatim with Content-Type: application/json.
334
- * No React rendering pipeline, no layout wrapping.
335
- *
336
- * Returns null if no JSON status file is found (caller should use bare JSON fallback).
337
- */
338
- async function renderDenyPageJson(
339
- deny: DenySignal,
340
- segments: ManifestSegmentNode[],
341
- responseHeaders: Headers,
342
- maxIndex?: number
343
- ): Promise<Response | null> {
344
- const resolution = resolveStatusFile(deny.status, segments, 'json', maxIndex);
345
-
346
- if (!resolution) {
347
- return null;
348
- }
349
-
350
- // JSON status files are loaded as modules that export the JSON content.
351
- // The manifest's load() imports the .json file, which Vite handles as a
352
- // default export of the parsed JSON object.
353
- // A .json status file that fails to load is not a usable match — return
354
- // null so the caller continues to the framework default rather than
355
- // rejecting out of the chain.
356
- // Dev warning: deny(status, { dangerouslyPassData }) carries data but JSON
357
- // status files are static bodies — the data is silently dropped. The same
358
- // deny() would deliver the data to a .tsx file's data prop. See
359
- // design/10-error-handling.md §"Status-Code File Variants".
360
- if (isDebug() && deny.data !== undefined) {
361
- console.warn(
362
- `[timber] deny(${deny.status}, data) resolved to ${resolution.file.filePath}, ` +
363
- `which is a static JSON file. The data argument is dropped — JSON status files ` +
364
- `are returned verbatim with no interpolation. If you need the data in the ` +
365
- `response, use a .tsx status file or a route handler (route.ts).`
366
- );
367
- }
368
-
369
- const mod = await loadModule(resolution.file).catch(() => null);
370
- if (!mod) return null;
371
- const jsonContent = mod.default ?? mod;
372
-
373
- responseHeaders.set('content-type', 'application/json; charset=utf-8');
374
- return new Response(JSON.stringify(jsonContent), {
375
- status: deny.status,
376
- headers: responseHeaders,
377
- });
378
- }
379
-
380
- /**
381
- * Return a bare JSON error response when no JSON status file exists.
382
- * This is the framework default for JSON format requests.
383
- */
384
- function bareJsonResponse(status: number, responseHeaders: Headers): Response {
385
- responseHeaders.set('content-type', 'application/json; charset=utf-8');
386
- return new Response(JSON.stringify({ error: true, status }), {
387
- status,
388
- headers: responseHeaders,
389
- });
390
- }
391
-
392
325
  // escapeHtml imported from server/utils/escape-html.ts
@@ -61,10 +61,14 @@ export interface ErrorBoundaryProps {
61
61
  children: ReactNode;
62
62
  }
63
63
 
64
- /** How to load a route file's module. Only `default` is read. */
64
+ /**
65
+ * How to load a route file's module. Only `default` is read. The server
66
+ * injects `loadFallbackModule`, which reports a failed load and returns
67
+ * `null`, so a broken status or error page is never skipped silently.
68
+ */
65
69
  type BoundaryModuleLoader<TFile> = (
66
70
  file: TFile
67
- ) => { default?: unknown } | Promise<{ default?: unknown }>;
71
+ ) => { default?: unknown } | null | Promise<{ default?: unknown } | null>;
68
72
 
69
73
  /** Everything the walk needs from its host environment. */
70
74
  export interface ErrorBoundaryWrapConfig<TFile, TElement> {
@@ -98,7 +102,7 @@ async function loadBoundaryComponent<TFile>(
98
102
  file: TFile,
99
103
  loadModule: BoundaryModuleLoader<TFile>
100
104
  ): Promise<LoadedComponent | null> {
101
- let mod: { default?: unknown };
105
+ let mod: { default?: unknown } | null;
102
106
  try {
103
107
  mod = await loadModule(file);
104
108
  } catch {
@@ -8,21 +8,26 @@
8
8
  * In production: attempts to render root error pages (500.tsx / 5xx.tsx /
9
9
  * error.tsx) via the normal RSC → SSR pipeline. Stack traces are never
10
10
  * exposed to the client (design/13-security.md principle 4).
11
+ *
12
+ * A route.ts match, in dev or production, gets the API route's JSON format
13
+ * instead: the `500.json` / `5xx.json` chain, then the bare
14
+ * `{"error": true, "status": 500}` body. That is the same format its denies
15
+ * use (design/10-error-handling.md §"JSON Error Pages").
11
16
  */
12
17
 
13
18
  import type { RouteMatch } from './pipeline.ts';
14
- import type { ManifestSegmentNode } from './route-matcher.ts';
19
+ import { isApiRouteChain, type ManifestSegmentNode } from './route-matcher.ts';
15
20
  import type { ClientBootstrapConfig } from './html-injectors.ts';
16
21
  import type { LayoutEntry } from './deny-renderer.ts';
17
22
  import type { GlobalErrorFile } from './rsc-entry/error-renderer.ts';
18
23
  import { swallow } from './logger.ts';
19
- import { logRenderError } from './logger.ts';
24
+ import { reportRenderError } from './pipeline-helpers.ts';
20
25
  import { loadModule } from './safe-load.ts';
21
- import { sourceMapError } from './dev-source-map.ts';
22
26
 
23
27
  /**
24
28
  * Render a fallback error page when the render pipeline throws.
25
29
  *
30
+ * For a route.ts match: the JSON status chain.
26
31
  * In dev: styled HTML with error details.
27
32
  * In prod: renders root error pages via renderErrorPage.
28
33
  */
@@ -30,6 +35,7 @@ export async function renderFallbackError(
30
35
  error: unknown,
31
36
  req: Request,
32
37
  responseHeaders: Headers,
38
+ match: RouteMatch | undefined,
33
39
  isDev: boolean,
34
40
  rootSegment: ManifestSegmentNode,
35
41
  clientBootstrap: ClientBootstrapConfig,
@@ -37,9 +43,13 @@ export async function renderFallbackError(
37
43
  projectRoot?: string,
38
44
  hmrOptions?: import('../dev-tools/dev-page-shell.ts').DevErrorHmrOptions
39
45
  ): Promise<Response> {
40
- // Source-map the error's stack trace in dev mode so the error page
41
- // shows original source positions. See TIM-811.
42
- sourceMapError(error);
46
+ // An API consumer never gets a page, including the dev error page. The dev
47
+ // overlay still shows the error; it is fed by onPipelineError, not by this
48
+ // response.
49
+ if (match && isApiRouteChain(match.segments)) {
50
+ const { renderJsonStatusResponse } = await import('./json-status-response.ts');
51
+ return renderJsonStatusResponse(req, 500, match.segments, responseHeaders);
52
+ }
43
53
 
44
54
  if (isDev) {
45
55
  return renderDevErrorPage(error, projectRoot, hmrOptions);
@@ -66,16 +76,21 @@ export async function renderFallbackError(
66
76
  // Layout failed to load — proceed without it. renderErrorPage will
67
77
  // attempt segment-level error pages (without layout wrapping) and
68
78
  // then fall through to global-error.tsx if those also fail.
69
- logRenderError({ method: req.method, path: new URL(req.url).pathname, error: layoutError });
79
+ reportRenderError(layoutError, req, { segments: match?.segments });
70
80
  }
71
- const match: RouteMatch = { segments, segmentParams: {}, middlewareChain: [] };
81
+ const rootMatch: RouteMatch = {
82
+ segments,
83
+ segmentParams: {},
84
+ rawSegmentParams: {},
85
+ middlewareChain: [],
86
+ };
72
87
  return renderErrorPage(
73
88
  error,
74
89
  500,
75
90
  segments,
76
91
  layoutComponents,
77
92
  req,
78
- match,
93
+ rootMatch,
79
94
  responseHeaders,
80
95
  clientBootstrap,
81
96
  globalError
@@ -102,8 +117,8 @@ export async function renderDevErrorPage(
102
117
 
103
118
  let html: string;
104
119
  try {
105
- // Dynamic import — keeps dev-error-page.ts and its transitive deps
106
- // (dev-error-overlay.ts, @jridgewell/trace-mapping) out of production bundles.
120
+ // Dynamic import — keeps dev-tools/error-page.ts and its transitive deps
121
+ // (dev-tools/overlay.ts, dev-tools/terminal.ts) out of production bundles.
107
122
  const { generateDevErrorPage } = await import('../dev-tools/error-page.ts');
108
123
  html = generateDevErrorPage(err, 'render', root, hmrOptions);
109
124
  // Inject Vite client script so the error overlay fires when HMR connects.
@@ -15,7 +15,7 @@
15
15
  * See design/02-rendering-pipeline.md, LOCAL-415
16
16
  */
17
17
 
18
- import { nonceAttr } from './csp-nonce.ts';
18
+ import { nonceAttr } from './render-utils.ts';
19
19
 
20
20
  // ─── JSON Escaping ────────────────────────────────────────────────────────
21
21
 
@@ -16,10 +16,10 @@
16
16
  *
17
17
  * The pipeline applies this at its single exit so every response shape is
18
18
  * covered — page render, API route, metadata route, deny page, error page,
19
- * proxy short-circuit. The two unit-level producers that are also reachable as
20
- * standalone functions (`handleRouteRequest`, `handleApiRoute`) call it too, so
21
- * each honours HEAD on its own; they share this implementation rather than
22
- * repeating it, and applying it twice is a no-op.
19
+ * proxy short-circuit. The unit-level producer that is also reachable as a
20
+ * standalone function (`handleRouteRequest`) calls it too, so it honours HEAD
21
+ * on its own; it shares this implementation rather than repeating it, and
22
+ * applying it twice is a no-op.
23
23
  */
24
24
 
25
25
  /**
@@ -33,7 +33,7 @@ import {
33
33
  type FlightInjectionState,
34
34
  type FlightInjectionEvent,
35
35
  } from './flight-injection-state.ts';
36
- import { withTimeout, RenderTimeoutError } from './render-timeout.ts';
36
+ import { withTimeout, RenderTimeoutError, resolveRenderTimeoutMs } from './render-timeout.ts';
37
37
 
38
38
  // ─── Encoders / Constants ────────────────────────────────────────────────────
39
39
 
@@ -384,7 +384,7 @@ export class FlightInjectorCore {
384
384
 
385
385
  constructor(rscStream: ReadableStream<Uint8Array>, options: FlightInjectorOptions = {}) {
386
386
  this.rscReader = rscStream.getReader();
387
- this.timeoutMs = (options.renderTimeoutMs ?? 30_000) || 120_000;
387
+ this.timeoutMs = resolveRenderTimeoutMs(options.renderTimeoutMs);
388
388
  this.errorSignal = options.errorSignal;
389
389
  this.nonce = options.nonce;
390
390
  this.machine = createMachine<FlightInjectionState, FlightInjectionEvent>({
@@ -31,7 +31,7 @@ import {
31
31
  suffixFlush,
32
32
  } from './html-injector-core.ts';
33
33
  import { flightChunkScript } from './flight-scripts.ts';
34
- import { withTimeout, RenderTimeoutError } from './render-timeout.ts';
34
+ import { withTimeout, RenderTimeoutError, resolveRenderTimeoutMs } from './render-timeout.ts';
35
35
  import { createTickCoalescer } from './coalesce-tick.ts';
36
36
 
37
37
  // ─── Buffered Transform ──────────────────────────────────────────────────────
@@ -207,9 +207,7 @@ export function createInlinedRscStream(
207
207
  ): ReadableStream<Uint8Array> {
208
208
  const rscReader = rscStream.getReader();
209
209
  const decoder = new TextDecoder('utf-8', { fatal: true });
210
- // When renderTimeoutMs is 0 ("disabled"), enforce a safety ceiling
211
- // so a stalled RSC stream can't hang the connection forever.
212
- const timeoutMs = (renderTimeoutMs ?? 30_000) || 120_000;
210
+ const timeoutMs = resolveRenderTimeoutMs(renderTimeoutMs);
213
211
 
214
212
  return new ReadableStream<Uint8Array>({
215
213
  async pull(controller) {
@@ -30,10 +30,6 @@ export {
30
30
  type DenyOptions,
31
31
  type RedirectOptions,
32
32
  } from './primitives.ts';
33
- // RenderError removed from public exports per TIM-724.
34
- // Use deny({ status: 500, data: ... }) instead. RenderError stays in
35
- // #server-internal for pipeline catch logic.
36
- export type { RenderErrorDigest } from './primitives.ts';
37
33
  // JsonSerializable moved to @timber-js/app/codec as the single canonical path.
38
34
  // Re-export removed per TIM-721.
39
35
 
@@ -29,11 +29,18 @@ export interface InstrumentationRequestInfo {
29
29
  }
30
30
 
31
31
  export interface InstrumentationErrorContext {
32
- /** Which pipeline phase the error occurred in. */
33
- phase: 'proxy' | 'handler' | 'render' | 'action' | 'route';
32
+ /**
33
+ * Which pipeline phase the error occurred in. `'setup'` is route setup
34
+ * between `proxy.ts` and `middleware.ts`: route matching and segment-param
35
+ * coercion (e.g. an `app/schema.ts` codec returning a value a param cannot
36
+ * hold). `'handler'` is `middleware.ts`; `'route'` is a `route.ts` handler
37
+ * or its `access.ts`, or a metadata route handler. design/17 §"Which errors
38
+ * reach it" lists every error that is reported, and those that are not.
39
+ */
40
+ phase: 'proxy' | 'setup' | 'handler' | 'render' | 'action' | 'route';
34
41
  /** The route pattern: '/dashboard/projects/[id]' */
35
42
  routePath: string;
36
- /** Type of route that was matched. */
43
+ /** Type of route that was matched. A metadata route reports as `'route'`. */
37
44
  routeType: 'page' | 'route' | 'action';
38
45
  /** Always set — OTEL trace ID or UUID fallback. */
39
46
  traceId: string;
@@ -27,8 +27,7 @@ export { getCookie, getSetCookieHeaders } from './cookie-context.ts';
27
27
  export { coerce } from './form-data.ts';
28
28
 
29
29
  // ── Signal classes (instanceof targets for pipeline catch logic) ──────────
30
- export { DenySignal, RedirectSignal, RenderError } from './primitives.ts';
31
- export type { RenderErrorDigest } from './primitives.ts';
30
+ export { DenySignal, RedirectSignal } from './primitives.ts';
32
31
 
33
32
  // ── Pipeline ─────────────────────────────────────────────────────────────
34
33
  export { createPipeline } from './pipeline.ts';
@@ -78,10 +77,6 @@ export type {
78
77
  SlotDeniedKind,
79
78
  } from './status-code-resolver.ts';
80
79
 
81
- // ── CSRF Protection ──────────────────────────────────────────────────────
82
- export { validateCsrf } from './csrf.ts';
83
- export type { CsrfConfig, CsrfResult } from './csrf.ts';
84
-
85
80
  // ── Body Limits ──────────────────────────────────────────────────────────
86
81
  export { parseBodySize, enforceBodyLimits, DEFAULT_LIMITS } from './body-limits.ts';
87
82
  export type { BodyLimitsConfig, BodyLimitResult, BodyKind } from './body-limits.ts';
@@ -0,0 +1,105 @@
1
+ /**
2
+ * JSON status responses — the status-code chain for API consumers.
3
+ *
4
+ * `{status}.json` → `{category}.json`, leaf → root, then the bare
5
+ * `{"error": true, "status": N}` body. No React, so the route.ts path and
6
+ * the pipeline's fallback renderer can use it without loading the RSC
7
+ * runtime.
8
+ *
9
+ * See design/10-error-handling.md §"JSON Error Pages".
10
+ */
11
+
12
+ import { isDebug } from './debug.ts';
13
+ import { loadFallbackModule } from './pipeline-helpers.ts';
14
+ import { resolveStatusFile } from './status-code-resolver.ts';
15
+ import type { ManifestSegmentNode } from './route-matcher.ts';
16
+
17
+ /**
18
+ * Render the JSON status chain for `status` — `{status}.json` →
19
+ * `{category}.json`, leaf → root — ending in the bare
20
+ * `{"error": true, "status": N}` body when no file resolves.
21
+ *
22
+ * This is the one API-route error format (design/10-error-handling.md
23
+ * §"Format Selection for deny()"). A deny from `access.ts` or a handler, and
24
+ * an error the pipeline answers for a route.ts match, all end here.
25
+ *
26
+ * `droppedData` is a deny()'s data. It is only read to warn that a static
27
+ * JSON file cannot carry it.
28
+ */
29
+ export async function renderJsonStatusResponse(
30
+ req: Request,
31
+ status: number,
32
+ segments: ManifestSegmentNode[],
33
+ responseHeaders: Headers,
34
+ maxIndex?: number,
35
+ droppedData?: unknown
36
+ ): Promise<Response> {
37
+ return (
38
+ (await renderJsonStatusFile(req, status, segments, responseHeaders, maxIndex, droppedData)) ??
39
+ bareJsonResponse(status, responseHeaders)
40
+ );
41
+ }
42
+
43
+ /**
44
+ * Render a JSON status-code file for `status`.
45
+ *
46
+ * JSON status files are returned verbatim with Content-Type: application/json.
47
+ * No React rendering pipeline, no layout wrapping.
48
+ *
49
+ * Returns null if no JSON status file is found (caller should use bare JSON fallback).
50
+ */
51
+ export async function renderJsonStatusFile(
52
+ req: Request,
53
+ status: number,
54
+ segments: ManifestSegmentNode[],
55
+ responseHeaders: Headers,
56
+ maxIndex?: number,
57
+ droppedData?: unknown
58
+ ): Promise<Response | null> {
59
+ const resolution = resolveStatusFile(status, segments, 'json', maxIndex);
60
+
61
+ if (!resolution) {
62
+ return null;
63
+ }
64
+
65
+ // JSON status files are loaded as modules that export the JSON content.
66
+ // The manifest's load() imports the .json file, which Vite handles as a
67
+ // default export of the parsed JSON object.
68
+ // A .json status file that fails to load (reported) is not a usable
69
+ // match — return null so the caller continues to the framework default
70
+ // rather than rejecting out of the chain.
71
+ // Dev warning: deny(status, { dangerouslyPassData }) carries data but JSON
72
+ // status files are static bodies — the data is silently dropped. The same
73
+ // deny() would deliver the data to a .tsx file's data prop. See
74
+ // design/10-error-handling.md §"Status-Code File Variants".
75
+ if (isDebug() && droppedData !== undefined) {
76
+ console.warn(
77
+ `[timber] deny(${status}, data) resolved to ${resolution.file.filePath}, ` +
78
+ `which is a static JSON file. The data argument is dropped — JSON status files ` +
79
+ `are returned verbatim with no interpolation. If you need the data in the ` +
80
+ `response, use a .tsx status file or a route handler (route.ts).`
81
+ );
82
+ }
83
+
84
+ const mod = await loadFallbackModule(resolution.file, req, segments);
85
+ if (!mod) return null;
86
+ const jsonContent = mod.default ?? mod;
87
+
88
+ responseHeaders.set('content-type', 'application/json; charset=utf-8');
89
+ return new Response(JSON.stringify(jsonContent), {
90
+ status,
91
+ headers: responseHeaders,
92
+ });
93
+ }
94
+
95
+ /**
96
+ * Return a bare JSON error response when no JSON status file exists.
97
+ * This is the framework default for JSON format requests.
98
+ */
99
+ function bareJsonResponse(status: number, responseHeaders: Headers): Response {
100
+ responseHeaders.set('content-type', 'application/json; charset=utf-8');
101
+ return new Response(JSON.stringify({ error: true, status }), {
102
+ status,
103
+ headers: responseHeaders,
104
+ });
105
+ }