@timber-js/app 0.2.0-alpha.207 → 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 (526) 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-BndF-3Td.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-DwQBrLBz.js → status-page-marker-gaihi0KZ.js} +140 -28
  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 +20 -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 +95 -108
  132. package/dist/client/internal.js.map +1 -1
  133. package/dist/client/navigation-commit.d.ts +20 -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 +3 -8
  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/segment-cache.d.ts +44 -4
  149. package/dist/client/segment-cache.d.ts.map +1 -1
  150. package/dist/client/ssr-data.d.ts +18 -64
  151. package/dist/client/ssr-data.d.ts.map +1 -1
  152. package/dist/client/state.d.ts +2 -5
  153. package/dist/client/state.d.ts.map +1 -1
  154. package/dist/client/use-pathname.d.ts +1 -1
  155. package/dist/config-types.d.ts +2 -1
  156. package/dist/config-types.d.ts.map +1 -1
  157. package/dist/config-validation.d.ts.map +1 -1
  158. package/dist/cookies/index.js +1 -1
  159. package/dist/dev-tools/dev-page-shell.d.ts +17 -0
  160. package/dist/dev-tools/dev-page-shell.d.ts.map +1 -1
  161. package/dist/dev-tools/index.d.ts +1 -1
  162. package/dist/dev-tools/index.d.ts.map +1 -1
  163. package/dist/dev-tools/instrumentation.d.ts +17 -2
  164. package/dist/dev-tools/instrumentation.d.ts.map +1 -1
  165. package/dist/dev-tools/overlay.d.ts +6 -27
  166. package/dist/dev-tools/overlay.d.ts.map +1 -1
  167. package/dist/index.d.ts.map +1 -1
  168. package/dist/index.js +632 -373
  169. package/dist/index.js.map +1 -1
  170. package/dist/plugin-context.d.ts +26 -40
  171. package/dist/plugin-context.d.ts.map +1 -1
  172. package/dist/plugins/build-manifest.d.ts.map +1 -1
  173. package/dist/plugins/build-report.d.ts +15 -2
  174. package/dist/plugins/build-report.d.ts.map +1 -1
  175. package/dist/plugins/dev-server.d.ts.map +1 -1
  176. package/dist/plugins/entries.d.ts.map +1 -1
  177. package/dist/plugins/fonts.d.ts +19 -1
  178. package/dist/plugins/fonts.d.ts.map +1 -1
  179. package/dist/plugins/post-build.d.ts +110 -0
  180. package/dist/plugins/post-build.d.ts.map +1 -0
  181. package/dist/plugins/prebuilt-capture.d.ts +11 -4
  182. package/dist/plugins/prebuilt-capture.d.ts.map +1 -1
  183. package/dist/plugins/prebuilt.d.ts +17 -1
  184. package/dist/plugins/prebuilt.d.ts.map +1 -1
  185. package/dist/plugins/prerender-sugar.d.ts.map +1 -1
  186. package/dist/plugins/react-resolve.d.ts +49 -0
  187. package/dist/plugins/react-resolve.d.ts.map +1 -0
  188. package/dist/plugins/rsc-assets-manifest.d.ts +33 -0
  189. package/dist/plugins/rsc-assets-manifest.d.ts.map +1 -0
  190. package/dist/plugins/shims.d.ts.map +1 -1
  191. package/dist/plugins/static-build.d.ts +32 -9
  192. package/dist/plugins/static-build.d.ts.map +1 -1
  193. package/dist/routing/codegen-write.d.ts +0 -9
  194. package/dist/routing/codegen-write.d.ts.map +1 -1
  195. package/dist/routing/index.js +2 -2
  196. package/dist/routing/segment-codegen.d.ts.map +1 -1
  197. package/dist/server/access-gate.d.ts.map +1 -1
  198. package/dist/server/action-handler.d.ts +5 -4
  199. package/dist/server/action-handler.d.ts.map +1 -1
  200. package/dist/server/actions.d.ts +46 -7
  201. package/dist/server/actions.d.ts.map +1 -1
  202. package/dist/server/als-registry.d.ts +58 -5
  203. package/dist/server/als-registry.d.ts.map +1 -1
  204. package/dist/server/children-interception.d.ts.map +1 -1
  205. package/dist/server/cookie-context.d.ts +2 -23
  206. package/dist/server/cookie-context.d.ts.map +1 -1
  207. package/dist/server/csp-nonce.d.ts +0 -9
  208. package/dist/server/csp-nonce.d.ts.map +1 -1
  209. package/dist/server/csrf.d.ts +27 -4
  210. package/dist/server/csrf.d.ts.map +1 -1
  211. package/dist/server/debug.d.ts +0 -1
  212. package/dist/server/debug.d.ts.map +1 -1
  213. package/dist/server/default-logger.d.ts +2 -1
  214. package/dist/server/default-logger.d.ts.map +1 -1
  215. package/dist/server/deny-boundary.d.ts +12 -6
  216. package/dist/server/deny-boundary.d.ts.map +1 -1
  217. package/dist/server/deny-renderer.d.ts +2 -2
  218. package/dist/server/deny-renderer.d.ts.map +1 -1
  219. package/dist/server/error-boundary-wrapper.d.ts +7 -3
  220. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  221. package/dist/server/fallback-error.d.ts +9 -2
  222. package/dist/server/fallback-error.d.ts.map +1 -1
  223. package/dist/server/head-response.d.ts +4 -4
  224. package/dist/server/html-injectors.d.ts.map +1 -1
  225. package/dist/server/index.d.ts +0 -1
  226. package/dist/server/index.d.ts.map +1 -1
  227. package/dist/server/index.js +3 -4
  228. package/dist/server/index.js.map +1 -1
  229. package/dist/server/instrumentation.d.ts +10 -3
  230. package/dist/server/instrumentation.d.ts.map +1 -1
  231. package/dist/server/internal.d.ts +1 -4
  232. package/dist/server/internal.d.ts.map +1 -1
  233. package/dist/server/internal.js +961 -581
  234. package/dist/server/internal.js.map +1 -1
  235. package/dist/server/json-status-response.d.ts +34 -0
  236. package/dist/server/json-status-response.d.ts.map +1 -0
  237. package/dist/server/logger.d.ts +26 -0
  238. package/dist/server/logger.d.ts.map +1 -1
  239. package/dist/server/param-coercion.d.ts +11 -6
  240. package/dist/server/param-coercion.d.ts.map +1 -1
  241. package/dist/server/pipeline-helpers.d.ts +95 -7
  242. package/dist/server/pipeline-helpers.d.ts.map +1 -1
  243. package/dist/server/pipeline-interception.d.ts +11 -0
  244. package/dist/server/pipeline-interception.d.ts.map +1 -1
  245. package/dist/server/pipeline-outcome.d.ts +11 -1
  246. package/dist/server/pipeline-outcome.d.ts.map +1 -1
  247. package/dist/server/pipeline-phases.d.ts +2 -2
  248. package/dist/server/pipeline-phases.d.ts.map +1 -1
  249. package/dist/server/pipeline.d.ts +23 -35
  250. package/dist/server/pipeline.d.ts.map +1 -1
  251. package/dist/server/prebuilt/capture-render.d.ts +25 -0
  252. package/dist/server/prebuilt/capture-render.d.ts.map +1 -0
  253. package/dist/server/prebuilt/capture-routes.d.ts +37 -0
  254. package/dist/server/prebuilt/capture-routes.d.ts.map +1 -0
  255. package/dist/server/prebuilt/capture-state.d.ts +79 -35
  256. package/dist/server/prebuilt/capture-state.d.ts.map +1 -1
  257. package/dist/server/prebuilt/lifetime.d.ts +38 -0
  258. package/dist/server/prebuilt/lifetime.d.ts.map +1 -0
  259. package/dist/server/prebuilt/slots.d.ts +7 -0
  260. package/dist/server/prebuilt/slots.d.ts.map +1 -1
  261. package/dist/server/prebuilt/synthetic-store.d.ts.map +1 -1
  262. package/dist/server/prebuilt-builder.d.ts.map +1 -1
  263. package/dist/server/prebuilt-runtime.d.ts.map +1 -1
  264. package/dist/server/primitives.d.ts +6 -81
  265. package/dist/server/primitives.d.ts.map +1 -1
  266. package/dist/server/react-cache-bridge.d.ts +59 -0
  267. package/dist/server/react-cache-bridge.d.ts.map +1 -0
  268. package/dist/server/react-cache-scope.d.ts +49 -0
  269. package/dist/server/react-cache-scope.d.ts.map +1 -0
  270. package/dist/server/render-timeout.d.ts +15 -0
  271. package/dist/server/render-timeout.d.ts.map +1 -1
  272. package/dist/server/render-utils.d.ts +9 -0
  273. package/dist/server/render-utils.d.ts.map +1 -1
  274. package/dist/server/request-context.d.ts +26 -5
  275. package/dist/server/request-context.d.ts.map +1 -1
  276. package/dist/server/route-element-builder.d.ts.map +1 -1
  277. package/dist/server/route-handler.d.ts.map +1 -1
  278. package/dist/server/route-matcher.d.ts +7 -0
  279. package/dist/server/route-matcher.d.ts.map +1 -1
  280. package/dist/server/rsc-entry/action-middleware-runner.d.ts +22 -22
  281. package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -1
  282. package/dist/server/rsc-entry/api-handler.d.ts +7 -0
  283. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  284. package/dist/server/rsc-entry/deny-fallback.d.ts +32 -6
  285. package/dist/server/rsc-entry/deny-fallback.d.ts.map +1 -1
  286. package/dist/server/rsc-entry/error-renderer.d.ts +11 -18
  287. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  288. package/dist/server/rsc-entry/helpers.d.ts +0 -1
  289. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  290. package/dist/server/rsc-entry/index.d.ts +5 -15
  291. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  292. package/dist/server/rsc-entry/render-route.d.ts +5 -6
  293. package/dist/server/rsc-entry/render-route.d.ts.map +1 -1
  294. package/dist/server/rsc-entry/render-signals.d.ts +65 -0
  295. package/dist/server/rsc-entry/render-signals.d.ts.map +1 -0
  296. package/dist/server/rsc-entry/revalidate-renderer.d.ts +6 -16
  297. package/dist/server/rsc-entry/revalidate-renderer.d.ts.map +1 -1
  298. package/dist/server/rsc-entry/rsc-payload.d.ts +7 -3
  299. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  300. package/dist/server/rsc-entry/rsc-stream.d.ts +8 -53
  301. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  302. package/dist/server/rsc-entry/ssr-bridge.d.ts +2 -2
  303. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  304. package/dist/server/rsc-entry/ssr-renderer.d.ts +9 -4
  305. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  306. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +1 -1
  307. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -1
  308. package/dist/server/signal-identity.d.ts +43 -0
  309. package/dist/server/signal-identity.d.ts.map +1 -0
  310. package/dist/server/slot-resolver.d.ts +4 -3
  311. package/dist/server/slot-resolver.d.ts.map +1 -1
  312. package/dist/server/slot-subtree-contain.d.ts.map +1 -1
  313. package/dist/server/ssr-bridge-types.d.ts +91 -53
  314. package/dist/server/ssr-bridge-types.d.ts.map +1 -1
  315. package/dist/server/ssr-entry.d.ts +8 -5
  316. package/dist/server/ssr-entry.d.ts.map +1 -1
  317. package/dist/server/ssr-render.d.ts +26 -40
  318. package/dist/server/ssr-render.d.ts.map +1 -1
  319. package/dist/server/ssr-wrappers.d.ts +1 -1
  320. package/dist/server/static-generator.d.ts.map +1 -1
  321. package/dist/server/stream-utils.d.ts +12 -0
  322. package/dist/server/stream-utils.d.ts.map +1 -1
  323. package/dist/server/tracing.d.ts +12 -16
  324. package/dist/server/tracing.d.ts.map +1 -1
  325. package/dist/server/types.d.ts +1 -1
  326. package/dist/server/version-skew.d.ts +3 -3
  327. package/dist/shared/csrf-reject.d.ts +16 -0
  328. package/dist/shared/csrf-reject.d.ts.map +1 -0
  329. package/dist/shared/error-digest.d.ts +28 -0
  330. package/dist/shared/error-digest.d.ts.map +1 -0
  331. package/dist/shared/payload-root.d.ts +11 -10
  332. package/dist/shared/payload-root.d.ts.map +1 -1
  333. package/dist/shared/rsc-payload-path.d.ts +6 -0
  334. package/dist/shared/rsc-payload-path.d.ts.map +1 -1
  335. package/dist/utils/write-file-atomic.d.ts +17 -0
  336. package/dist/utils/write-file-atomic.d.ts.map +1 -0
  337. package/docs/api/30-api-server.mdx +17 -14
  338. package/docs/api/32-api-cache.mdx +51 -23
  339. package/docs/api/34-api-config.mdx +34 -6
  340. package/docs/api/36-cli.mdx +11 -1
  341. package/docs/learn/03-fetching-data.mdx +17 -1
  342. package/docs/learn/04-access-control.mdx +1 -1
  343. package/docs/learn/10-caching.mdx +29 -11
  344. package/docs/learn/11-middleware.mdx +8 -2
  345. package/docs/learn/12-error-handling.mdx +6 -1
  346. package/package.json +7 -3
  347. package/src/adapters/build-output-helper.ts +55 -53
  348. package/src/adapters/canonicalize-module.ts +29 -0
  349. package/src/adapters/cloudflare.ts +105 -63
  350. package/src/adapters/compress-module.ts +16 -5
  351. package/src/adapters/fs-identity.ts +2 -3
  352. package/src/adapters/nitro-presets.ts +0 -15
  353. package/src/adapters/nitro-preview.ts +272 -136
  354. package/src/adapters/nitro.ts +119 -82
  355. package/src/adapters/shared.ts +23 -14
  356. package/src/adapters/types.ts +110 -21
  357. package/src/analyze/graph-cache.ts +3 -4
  358. package/src/cache/json-lossy-check.ts +3 -9
  359. package/src/cache/singleflight.ts +5 -2
  360. package/src/cache/sizeof.ts +3 -1
  361. package/src/cache/tag-aware-handler.ts +43 -26
  362. package/src/cli-check.ts +8 -98
  363. package/src/cli-context.ts +119 -0
  364. package/src/cli.ts +19 -28
  365. package/src/client/browser-dev.ts +1 -1
  366. package/src/client/browser-entry/action-dispatch.ts +26 -4
  367. package/src/client/browser-entry/hydrate.ts +53 -58
  368. package/src/client/browser-entry/index.ts +16 -27
  369. package/src/client/browser-entry/post-hydration.ts +6 -40
  370. package/src/client/browser-entry/router-init.ts +66 -84
  371. package/src/client/error-boundary.tsx +9 -41
  372. package/src/client/error-reconstituter.tsx +10 -5
  373. package/src/client/history.ts +35 -21
  374. package/src/client/index.ts +0 -1
  375. package/src/client/internal.ts +2 -7
  376. package/src/client/navigation-commit.ts +41 -18
  377. package/src/client/navigation-context.ts +3 -39
  378. package/src/client/react-root.ts +3 -2
  379. package/src/client/router-pipeline.ts +96 -132
  380. package/src/client/router-types.ts +46 -44
  381. package/src/client/router-url.ts +32 -0
  382. package/src/client/router.ts +62 -21
  383. package/src/client/rsc-fetch.ts +117 -155
  384. package/src/client/segment-cache.ts +110 -11
  385. package/src/client/ssr-data.ts +19 -80
  386. package/src/client/state.ts +2 -9
  387. package/src/client/use-pathname.ts +1 -1
  388. package/src/config-types.ts +2 -1
  389. package/src/config-validation.ts +2 -1
  390. package/src/dev-tools/dev-page-shell.ts +18 -0
  391. package/src/dev-tools/index.ts +0 -2
  392. package/src/dev-tools/instrumentation.ts +50 -2
  393. package/src/dev-tools/overlay.ts +8 -238
  394. package/src/index.ts +26 -14
  395. package/src/plugin-context.ts +39 -40
  396. package/src/plugins/build-manifest.ts +4 -11
  397. package/src/plugins/build-report.ts +70 -70
  398. package/src/plugins/dev-server.ts +24 -44
  399. package/src/plugins/entries.ts +2 -1
  400. package/src/plugins/fonts.ts +35 -7
  401. package/src/plugins/post-build.ts +327 -0
  402. package/src/plugins/prebuilt-capture.ts +28 -32
  403. package/src/plugins/prebuilt.ts +54 -39
  404. package/src/plugins/prerender-sugar.ts +0 -4
  405. package/src/plugins/react-resolve.ts +149 -0
  406. package/src/plugins/{adapter-build.ts → rsc-assets-manifest.ts} +20 -109
  407. package/src/plugins/shims.ts +1 -0
  408. package/src/plugins/static-build.ts +42 -74
  409. package/src/routing/codegen-write.ts +25 -3
  410. package/src/routing/segment-codegen.ts +3 -2
  411. package/src/rsc-runtime/vendor-types.d.ts +8 -0
  412. package/src/server/access-gate.tsx +2 -1
  413. package/src/server/action-client.ts +1 -1
  414. package/src/server/action-handler.ts +253 -110
  415. package/src/server/actions.ts +73 -25
  416. package/src/server/als-registry.ts +73 -5
  417. package/src/server/chain-url-parts.ts +1 -1
  418. package/src/server/children-interception.ts +2 -1
  419. package/src/server/cookie-context.ts +18 -48
  420. package/src/server/csp-nonce.ts +0 -12
  421. package/src/server/csrf.ts +140 -8
  422. package/src/server/debug.ts +0 -1
  423. package/src/server/default-logger.ts +2 -1
  424. package/src/server/deny-boundary.ts +25 -13
  425. package/src/server/deny-renderer.ts +30 -97
  426. package/src/server/error-boundary-wrapper.ts +7 -3
  427. package/src/server/fallback-error.ts +26 -11
  428. package/src/server/flight-scripts.ts +1 -1
  429. package/src/server/head-response.ts +4 -4
  430. package/src/server/html-injector-core.ts +2 -2
  431. package/src/server/html-injectors.ts +2 -4
  432. package/src/server/index.ts +0 -4
  433. package/src/server/instrumentation.ts +10 -3
  434. package/src/server/internal.ts +1 -6
  435. package/src/server/json-status-response.ts +105 -0
  436. package/src/server/logger.ts +39 -3
  437. package/src/server/param-coercion.ts +15 -12
  438. package/src/server/pipeline-helpers.ts +257 -12
  439. package/src/server/pipeline-interception.ts +133 -0
  440. package/src/server/pipeline-outcome.ts +103 -31
  441. package/src/server/pipeline-phases.ts +127 -237
  442. package/src/server/pipeline.ts +204 -207
  443. package/src/server/prebuilt/capture-render.ts +118 -0
  444. package/src/server/prebuilt/capture-routes.ts +104 -0
  445. package/src/server/prebuilt/capture-state.ts +155 -48
  446. package/src/server/prebuilt/lifetime.ts +151 -0
  447. package/src/server/prebuilt/slots.ts +14 -2
  448. package/src/server/prebuilt/synthetic-store.ts +3 -0
  449. package/src/server/prebuilt-builder.ts +30 -320
  450. package/src/server/prebuilt-runtime.ts +125 -129
  451. package/src/server/primitives.ts +8 -168
  452. package/src/server/react-cache-bridge.ts +124 -0
  453. package/src/server/react-cache-scope.ts +104 -0
  454. package/src/server/render-timeout.ts +20 -0
  455. package/src/server/render-utils.ts +11 -1
  456. package/src/server/request-context.ts +36 -9
  457. package/src/server/route-element-builder.ts +11 -6
  458. package/src/server/route-handler.ts +36 -23
  459. package/src/server/route-matcher.ts +15 -1
  460. package/src/server/rsc-entry/action-middleware-runner.ts +79 -123
  461. package/src/server/rsc-entry/api-handler.ts +27 -103
  462. package/src/server/rsc-entry/deny-fallback.ts +93 -26
  463. package/src/server/rsc-entry/error-renderer.ts +39 -91
  464. package/src/server/rsc-entry/helpers.ts +2 -4
  465. package/src/server/rsc-entry/index.ts +64 -58
  466. package/src/server/rsc-entry/render-route.ts +15 -80
  467. package/src/server/rsc-entry/render-signals.ts +108 -0
  468. package/src/server/rsc-entry/revalidate-renderer.ts +56 -57
  469. package/src/server/rsc-entry/rsc-payload.ts +28 -61
  470. package/src/server/rsc-entry/rsc-stream.ts +113 -213
  471. package/src/server/rsc-entry/ssr-bridge.ts +2 -2
  472. package/src/server/rsc-entry/ssr-renderer.ts +182 -263
  473. package/src/server/rsc-entry/wrap-action-dispatch.ts +12 -14
  474. package/src/server/signal-identity.ts +112 -0
  475. package/src/server/slot-resolver.ts +18 -18
  476. package/src/server/slot-subtree-contain.ts +2 -1
  477. package/src/server/ssr-bridge-types.ts +92 -56
  478. package/src/server/ssr-entry.ts +87 -111
  479. package/src/server/ssr-render.ts +55 -64
  480. package/src/server/ssr-wrappers.tsx +2 -2
  481. package/src/server/static-generator.ts +7 -42
  482. package/src/server/static-not-found.ts +3 -3
  483. package/src/server/stream-utils.ts +51 -0
  484. package/src/server/tracing.ts +58 -75
  485. package/src/server/types.ts +1 -1
  486. package/src/server/version-skew.ts +5 -5
  487. package/src/shared/csrf-reject.ts +15 -0
  488. package/src/shared/error-digest.ts +46 -0
  489. package/src/shared/payload-root.ts +11 -10
  490. package/src/shared/rsc-payload-path.ts +8 -1
  491. package/src/utils/write-file-atomic.ts +32 -0
  492. package/dist/_chunks/actions-jNrXdzgs.js +0 -346
  493. package/dist/_chunks/actions-jNrXdzgs.js.map +0 -1
  494. package/dist/_chunks/als-registry-C6kcfprT.js.map +0 -1
  495. package/dist/_chunks/build-manifest-DTmSGLRz.js.map +0 -1
  496. package/dist/_chunks/build-output-helper-9dqCv1pZ.js.map +0 -1
  497. package/dist/_chunks/cache-api-CUD9Ezaq.js.map +0 -1
  498. package/dist/_chunks/cli-check-G8o30ldg.js.map +0 -1
  499. package/dist/_chunks/convention-lint-5KzoMg_A.js.map +0 -1
  500. package/dist/_chunks/dev-server-BzBxgYAV.js.map +0 -1
  501. package/dist/_chunks/error-boundary-BndF-3Td.js.map +0 -1
  502. package/dist/_chunks/fs-identity-D7vb6GdI.js.map +0 -1
  503. package/dist/_chunks/graph-cache-CP4GEmf9.js.map +0 -1
  504. package/dist/_chunks/json-lossy-check-ClNvBM_3.js.map +0 -1
  505. package/dist/_chunks/logger-k2DQ4EUf.js.map +0 -1
  506. package/dist/_chunks/navigation-context-D0TU0Jog.js.map +0 -1
  507. package/dist/_chunks/plugin-context-8idfR3UZ.js.map +0 -1
  508. package/dist/_chunks/primitives-DLAnvsrk.js.map +0 -1
  509. package/dist/_chunks/segment-context-D9_89u34.js +0 -34
  510. package/dist/_chunks/segment-context-D9_89u34.js.map +0 -1
  511. package/dist/_chunks/sizeof-lXffQ1Vr.js.map +0 -1
  512. package/dist/_chunks/ssr-data-D6T6Y3ef.js +0 -60
  513. package/dist/_chunks/ssr-data-D6T6Y3ef.js.map +0 -1
  514. package/dist/_chunks/state-FippDgxN.js.map +0 -1
  515. package/dist/_chunks/status-page-marker-DwQBrLBz.js.map +0 -1
  516. package/dist/client/types.d.ts +0 -14
  517. package/dist/client/types.d.ts.map +0 -1
  518. package/dist/plugins/adapter-build.d.ts +0 -38
  519. package/dist/plugins/adapter-build.d.ts.map +0 -1
  520. package/dist/server/asset-headers.d.ts +0 -32
  521. package/dist/server/asset-headers.d.ts.map +0 -1
  522. package/dist/server/dev-source-map.d.ts +0 -22
  523. package/dist/server/dev-source-map.d.ts.map +0 -1
  524. package/src/client/types.ts +0 -21
  525. package/src/server/asset-headers.ts +0 -59
  526. package/src/server/dev-source-map.ts +0 -31
@@ -26,7 +26,19 @@ const DATA_PREFIX = 'd:';
26
26
  const TAG_SET_PREFIX = 'ts:';
27
27
  const TAG_VERSION_PREFIX = 'tv:';
28
28
 
29
- type Strategy = 'native' | 'eager' | 'lazy';
29
+ /** A store whose optional capability methods are known to be present. */
30
+ type StoreWith<K extends keyof CacheStore> = CacheStore & Required<Pick<CacheStore, K>>;
31
+ type NativeStore = StoreWith<'setWithTags' | 'invalidateTag'>;
32
+ type EagerStore = StoreWith<'sadd' | 'smembers' | 'srem' | 'sdel'>;
33
+
34
+ /**
35
+ * The detected strategy carries the store narrowed to the capabilities that
36
+ * strategy relies on, so each branch calls those methods without assertions.
37
+ */
38
+ type Strategy =
39
+ | { kind: 'native'; store: NativeStore }
40
+ | { kind: 'eager'; store: EagerStore }
41
+ | { kind: 'lazy' };
30
42
 
31
43
  /** Stored entry format for eager strategy. */
32
44
  interface EagerEntry {
@@ -43,10 +55,18 @@ interface LazyEntry {
43
55
  tagVersions: Record<string, number>;
44
56
  }
45
57
 
58
+ function isNativeStore(store: CacheStore): store is NativeStore {
59
+ return !!(store.setWithTags && store.invalidateTag);
60
+ }
61
+
62
+ function isEagerStore(store: CacheStore): store is EagerStore {
63
+ return !!(store.sadd && store.smembers && store.srem && store.sdel);
64
+ }
65
+
46
66
  function detectStrategy(store: CacheStore): Strategy {
47
- if (store.setWithTags && store.invalidateTag) return 'native';
48
- if (store.sadd && store.smembers && store.srem && store.sdel) return 'eager';
49
- return 'lazy';
67
+ if (isNativeStore(store)) return { kind: 'native', store };
68
+ if (isEagerStore(store)) return { kind: 'eager', store };
69
+ return { kind: 'lazy' };
50
70
  }
51
71
 
52
72
  export class TagAwareCacheHandler implements CacheHandler {
@@ -85,7 +105,7 @@ export class TagAwareCacheHandler implements CacheHandler {
85
105
  const raw = await this.store.get(this.dataKey(key));
86
106
  if (raw === null) return null;
87
107
 
88
- if (this.strategy === 'native' || this.strategy === 'eager') {
108
+ if (this.strategy.kind !== 'lazy') {
89
109
  const entry = JSON.parse(raw) as EagerEntry;
90
110
  const stale = Date.now() > entry.expiresAt;
91
111
  return { value: entry.value, stale };
@@ -111,8 +131,9 @@ export class TagAwareCacheHandler implements CacheHandler {
111
131
  opts: { ttl: number; tags: string[]; generation?: number }
112
132
  ): Promise<void> {
113
133
  const physicalTtl = Math.max(opts.ttl * 2 + 60, 120);
134
+ const strategy = this.strategy;
114
135
 
115
- if (this.strategy === 'native') {
136
+ if (strategy.kind === 'native') {
116
137
  const entry: EagerEntry = {
117
138
  value,
118
139
  expiresAt: Date.now() + opts.ttl * 1000,
@@ -120,7 +141,7 @@ export class TagAwareCacheHandler implements CacheHandler {
120
141
  };
121
142
  const payload = JSON.stringify(entry);
122
143
  if (opts.tags.length > 0) {
123
- await this.store.setWithTags!(
144
+ await strategy.store.setWithTags(
124
145
  this.dataKey(key),
125
146
  payload,
126
147
  physicalTtl,
@@ -132,7 +153,7 @@ export class TagAwareCacheHandler implements CacheHandler {
132
153
  return;
133
154
  }
134
155
 
135
- if (this.strategy === 'eager') {
156
+ if (strategy.kind === 'eager') {
136
157
  const entry: EagerEntry = {
137
158
  value,
138
159
  expiresAt: Date.now() + opts.ttl * 1000,
@@ -141,7 +162,7 @@ export class TagAwareCacheHandler implements CacheHandler {
141
162
  await this.store.set(this.dataKey(key), JSON.stringify(entry), physicalTtl);
142
163
  if (opts.tags.length > 0) {
143
164
  await Promise.all(
144
- opts.tags.map((tag) => this.store.sadd!(this.tagSetKey(tag), [key], physicalTtl))
165
+ opts.tags.map((tag) => strategy.store.sadd(this.tagSetKey(tag), [key], physicalTtl))
145
166
  );
146
167
  }
147
168
  return;
@@ -159,27 +180,30 @@ export class TagAwareCacheHandler implements CacheHandler {
159
180
  }
160
181
 
161
182
  async invalidate(opts: { key?: string; tag?: string }): Promise<void> {
183
+ const strategy = this.strategy;
184
+
162
185
  if (opts.key) {
163
- if (this.strategy === 'eager') {
164
- const raw = await this.store.get(this.dataKey(opts.key));
186
+ const key = opts.key;
187
+ if (strategy.kind === 'eager') {
188
+ const raw = await this.store.get(this.dataKey(key));
165
189
  if (raw !== null) {
166
190
  const entry = JSON.parse(raw) as EagerEntry;
167
191
  if (entry.tags.length > 0) {
168
192
  await Promise.all(
169
- entry.tags.map((tag) => this.store.srem!(this.tagSetKey(tag), [opts.key!]))
193
+ entry.tags.map((tag) => strategy.store.srem(this.tagSetKey(tag), [key]))
170
194
  );
171
195
  }
172
196
  }
173
197
  }
174
- await this.store.del(this.dataKey(opts.key));
198
+ await this.store.del(this.dataKey(key));
175
199
  }
176
200
 
177
201
  if (opts.tag) {
178
202
  const tag = opts.tag;
179
- if (this.strategy === 'native') {
180
- await this.store.invalidateTag!(`${this.prefix}${tag}`);
181
- } else if (this.strategy === 'eager') {
182
- const members = await this.store.smembers!(this.tagSetKey(tag));
203
+ if (strategy.kind === 'native') {
204
+ await strategy.store.invalidateTag(`${this.prefix}${tag}`);
205
+ } else if (strategy.kind === 'eager') {
206
+ const members = await strategy.store.smembers(this.tagSetKey(tag));
183
207
  // Verify each member still carries the tag before deleting — the set
184
208
  // can contain stale memberships from overwritten entries or LRU eviction.
185
209
  // Remove only the snapshot members (via srem, not sdel) so concurrent
@@ -187,17 +211,10 @@ export class TagAwareCacheHandler implements CacheHandler {
187
211
  await Promise.all(
188
212
  members.map(async (k) => {
189
213
  const raw = await this.store.get(this.dataKey(k));
190
- if (raw === null) {
191
- await this.store.srem!(this.tagSetKey(tag), [k]);
192
- return;
193
- }
194
- const entry = JSON.parse(raw) as EagerEntry;
195
- if (entry.tags.includes(tag)) {
214
+ if (raw !== null && (JSON.parse(raw) as EagerEntry).tags.includes(tag)) {
196
215
  await this.store.del(this.dataKey(k));
197
- await this.store.srem!(this.tagSetKey(tag), [k]);
198
- } else {
199
- await this.store.srem!(this.tagSetKey(tag), [k]);
200
216
  }
217
+ await strategy.store.srem(this.tagSetKey(tag), [k]);
201
218
  })
202
219
  );
203
220
  } else {
package/src/cli-check.ts CHANGED
@@ -36,10 +36,7 @@ import { dirname, join, resolve } from 'node:path';
36
36
  import { scanRoutes } from './routing/scanner.ts';
37
37
  import { lintConventions, formatConventionWarnings } from './routing/convention-lint.ts';
38
38
  import { writeRouteCodegen, CODEGEN_OUTPUT, ENV_DTS_FILENAME } from './routing/codegen-write.ts';
39
- import { isTimberPluginApi } from './plugin-context.ts';
40
-
41
- /** The plugin that publishes timber's resolved context on its Vite `api`. */
42
- const TIMBER_ROOT_SYNC_PLUGIN = 'timber-root-sync';
39
+ import { resolveTimberContext, type ResolveViteConfig } from './cli-context.ts';
43
40
 
44
41
  /** The npm package that provides tsgo. Named in the missing-tool message. */
45
42
  const TSGO_PACKAGE = '@typescript/native-preview';
@@ -68,23 +65,6 @@ export type RunTsgo = (command: string, args: string[], cwd: string) => Promise<
68
65
  */
69
66
  export type ReadTsgoConfig = (command: string, args: string[], cwd: string) => Promise<string>;
70
67
 
71
- /**
72
- * Vite's own `resolveConfig`, narrowed to what this module passes and reads.
73
- *
74
- * The seam sits at `resolveConfig` rather than at "give me the plugins" so the
75
- * *arguments* are the thing under test: which config file, which command, and
76
- * which mode defaults. Those arguments have been wrong three separate times
77
- * (TIM-1332 rounds 4-6), and a double that answered "here are the plugins"
78
- * could not see any of it. The double returns what Vite returns — plugins with
79
- * an opaque `api` — so the lookup and narrowing under test stay the real ones.
80
- */
81
- export type ResolveViteConfig = (
82
- inlineConfig: { configFile: string | undefined },
83
- command: 'build',
84
- defaultMode: string,
85
- defaultNodeEnv: string
86
- ) => Promise<{ plugins: readonly PluginWithApi[] }>;
87
-
88
68
  /** @internal Dependency injection for testing. */
89
69
  export interface CheckDeps {
90
70
  /**
@@ -164,89 +144,19 @@ export interface RouteInputs {
164
144
  pageExtensions: string[] | undefined;
165
145
  }
166
146
 
167
- /** The subset of a resolved Vite plugin this module reads. */
168
- export interface PluginWithApi {
169
- name: string;
170
- api?: unknown;
171
- }
172
-
173
147
  /**
174
- * Ask Vite for the resolved config, which is what carries timber's context.
175
- *
176
- * `resolveConfig` runs the whole config pipeline — config file discovery,
177
- * `config` and `configResolved` hooks — so the context it produces is the one
178
- * `timber build` would use. Measured at ~300-400ms on a real app; the type pass
179
- * it precedes costs far more.
180
- */
181
- const defaultResolveViteConfig: ResolveViteConfig = async (
182
- inlineConfig,
183
- command,
184
- defaultMode,
185
- defaultNodeEnv
186
- ) => {
187
- const { resolveConfig } = await import('vite');
188
- return resolveConfig(inlineConfig, command, defaultMode, defaultNodeEnv);
189
- };
190
-
191
- /**
192
- * The mode defaults `timber build` resolves under.
193
- *
194
- * `resolveConfig`'s own defaults are `'development'` for both, but nothing
195
- * reaches it with those on a build: `createBuilder` goes through Vite's
196
- * internal `resolveConfigToBuild`, which calls
197
- * `resolveConfig(inlineConfig, 'build', 'production', 'production')`. A config
198
- * written as `defineConfig(({ mode }) => …)`, or one that loads `.env.production`,
199
- * therefore resolves to a *different* app under the two. Passing the defaults
200
- * explicitly is what makes "check validates what build builds" true rather than
201
- * true-by-coincidence for configs that ignore mode (TIM-1332, round 6).
202
- */
203
- const BUILD_MODE_DEFAULTS = ['production', 'production'] as const;
204
-
205
- /**
206
- * Resolve root, appDir and pageExtensions the way `timber build` resolves them.
207
- *
208
- * Reading `timber.config.ts` directly is **not** equivalent, which is the whole
209
- * reason this goes through Vite (TIM-1332, review round 3):
210
- *
211
- * - Config passed inline — `timber({ pageExtensions: [...] })` in
212
- * `vite.config.ts` — lives only in the plugin's closure. Nothing that
213
- * re-reads the config file can see it, so a scan built that way silently uses
214
- * default page extensions and writes a route map missing the app's pages.
215
- * `examples/next-playground-migration` is exactly this shape.
216
- * - `root` is Vite's resolved root, not the caller's cwd, and the two differ in
217
- * the monorepo layouts TIM-498 describes. `appDir` resolves against it.
218
- *
219
- * There is no fallback to a second, hand-rolled resolution. A project whose
220
- * Vite config does not produce the timber plugin cannot be built either, so a
221
- * check that quietly proceeded on a guessed tree would report a verdict about
222
- * an app that does not exist.
148
+ * Resolve root, appDir and pageExtensions the way `timber build` resolves them
149
+ * — through Vite, never by re-reading `timber.config.ts` (see `cli-context.ts`).
150
+ * Inline `timber({ pageExtensions: [...] })` is the case that bites: a scan
151
+ * that re-read the file would silently use default page extensions and write a
152
+ * route map missing the app's pages. `examples/next-playground-migration` is
153
+ * exactly this shape.
223
154
  */
224
155
  export async function resolveRouteInputs(
225
156
  options: RouteOptions = {},
226
157
  deps: CheckDeps = {}
227
158
  ): Promise<RouteInputs> {
228
- const resolveViteConfig = deps.resolveViteConfig ?? defaultResolveViteConfig;
229
- // `configFile: undefined` is Vite's own "discover it" value, so the default
230
- // path stays exactly what Vite does for `timber build` without `--config`.
231
- const { plugins } = await resolveViteConfig(
232
- { configFile: options.viteConfigFile },
233
- 'build',
234
- ...BUILD_MODE_DEFAULTS
235
- );
236
-
237
- const rootSync = plugins.find((plugin) => plugin.name === TIMBER_ROOT_SYNC_PLUGIN);
238
- if (!rootSync || !isTimberPluginApi(rootSync.api)) {
239
- throw new Error(
240
- `[timber] Could not read the resolved timber configuration from your Vite config.\n\n` +
241
- ` \`timber check\` resolves your project through Vite so it validates the same\n` +
242
- ` routes \`timber build\` builds — including config passed inline to timber().\n\n` +
243
- ` Check that vite.config.ts exists and lists the timber plugin:\n\n` +
244
- ` import { timber } from '@timber-js/app';\n` +
245
- ` export default { plugins: [timber()] };\n`
246
- );
247
- }
248
-
249
- const ctx = rootSync.api.getContext();
159
+ const ctx = await resolveTimberContext('check', options.viteConfigFile, deps.resolveViteConfig);
250
160
  return { root: ctx.root, appDir: ctx.appDir, pageExtensions: ctx.config.pageExtensions };
251
161
  }
252
162
 
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Resolve timber's configuration the way `timber build` resolves it, for CLI
3
+ * commands that run outside the build: `timber check` and `timber preview`.
4
+ *
5
+ * Reading `timber.config.ts` directly is **not** equivalent, which is the whole
6
+ * reason this goes through Vite (TIM-1332, review round 3; TIM-1531):
7
+ *
8
+ * - Config passed inline — `timber({ pageExtensions, adapter, output })` in
9
+ * `vite.config.ts` — lives only in the plugin's closure. Nothing that
10
+ * re-reads the config file can see it.
11
+ * - `root` is Vite's resolved root, not the caller's cwd, and the two differ in
12
+ * the monorepo layouts TIM-498 describes.
13
+ * - The build directory can come from Vite's `build.outDir`, which only a
14
+ * resolved Vite config knows.
15
+ * - `--config` names a Vite config file; only Vite can load it.
16
+ *
17
+ * There is no fallback to a second, hand-rolled resolution. A project whose
18
+ * Vite config does not produce the timber plugin cannot be built either, so a
19
+ * command that quietly proceeded on a guess would act on an app that does not
20
+ * exist.
21
+ *
22
+ * Design docs: 11-platform.md §CLI
23
+ */
24
+
25
+ import { isTimberPluginApi, type PluginContext } from './plugin-context.ts';
26
+
27
+ /** The plugin that publishes timber's resolved context on its Vite `api`. */
28
+ const TIMBER_ROOT_SYNC_PLUGIN = 'timber-root-sync';
29
+
30
+ /** The subset of a resolved Vite plugin this module reads. */
31
+ export interface PluginWithApi {
32
+ name: string;
33
+ api?: unknown;
34
+ }
35
+
36
+ /**
37
+ * Vite's own `resolveConfig`, narrowed to what this module passes and reads.
38
+ *
39
+ * The seam sits at `resolveConfig` rather than at "give me the plugins" so the
40
+ * *arguments* are the thing under test: which config file, which command, and
41
+ * which mode defaults. Those arguments have been wrong three separate times
42
+ * (TIM-1332 rounds 4-6), and a double that answered "here are the plugins"
43
+ * could not see any of it. The double returns what Vite returns — plugins with
44
+ * an opaque `api` — so the lookup and narrowing under test stay the real ones.
45
+ */
46
+ export type ResolveViteConfig = (
47
+ inlineConfig: { configFile: string | undefined },
48
+ command: 'build',
49
+ defaultMode: string,
50
+ defaultNodeEnv: string
51
+ ) => Promise<{ plugins: readonly PluginWithApi[] }>;
52
+
53
+ /**
54
+ * Ask Vite for the resolved config, which is what carries timber's context.
55
+ *
56
+ * `resolveConfig` runs the whole config pipeline — config file discovery,
57
+ * `config` and `configResolved` hooks — so the context it produces is the one
58
+ * `timber build` would use. Measured at ~300-400ms on a real app.
59
+ */
60
+ const defaultResolveViteConfig: ResolveViteConfig = async (
61
+ inlineConfig,
62
+ command,
63
+ defaultMode,
64
+ defaultNodeEnv
65
+ ) => {
66
+ const { resolveConfig } = await import('vite');
67
+ return resolveConfig(inlineConfig, command, defaultMode, defaultNodeEnv);
68
+ };
69
+
70
+ /**
71
+ * The mode defaults `timber build` resolves under.
72
+ *
73
+ * `resolveConfig`'s own defaults are `'development'` for both, but nothing
74
+ * reaches it with those on a build: `createBuilder` goes through Vite's
75
+ * internal `resolveConfigToBuild`, which calls
76
+ * `resolveConfig(inlineConfig, 'build', 'production', 'production')`. A config
77
+ * written as `defineConfig(({ mode }) => …)`, or one that loads `.env.production`,
78
+ * therefore resolves to a *different* app under the two. Passing the defaults
79
+ * explicitly is what makes "check validates what build builds" — and "preview
80
+ * serves what build wrote" — true rather than true-by-coincidence for configs
81
+ * that ignore mode (TIM-1332, round 6).
82
+ */
83
+ const BUILD_MODE_DEFAULTS = ['production', 'production'] as const;
84
+
85
+ /**
86
+ * Resolve the project through Vite and return timber's context as
87
+ * `timber build` would see it.
88
+ *
89
+ * @param command The CLI command asking, named in the error message.
90
+ * @param viteConfigFile `--config`. Undefined means Vite's own discovery, the
91
+ * same as `timber build` without the flag.
92
+ */
93
+ export async function resolveTimberContext(
94
+ command: string,
95
+ viteConfigFile: string | undefined,
96
+ resolveViteConfig: ResolveViteConfig = defaultResolveViteConfig
97
+ ): Promise<PluginContext> {
98
+ // `configFile: undefined` is Vite's own "discover it" value, so the default
99
+ // path stays exactly what Vite does for `timber build` without `--config`.
100
+ const { plugins } = await resolveViteConfig(
101
+ { configFile: viteConfigFile },
102
+ 'build',
103
+ ...BUILD_MODE_DEFAULTS
104
+ );
105
+
106
+ const rootSync = plugins.find((plugin) => plugin.name === TIMBER_ROOT_SYNC_PLUGIN);
107
+ if (!rootSync || !isTimberPluginApi(rootSync.api)) {
108
+ throw new Error(
109
+ `[timber] Could not read the resolved timber configuration from your Vite config.\n\n` +
110
+ ` \`timber ${command}\` resolves your project through Vite so it sees the same\n` +
111
+ ` configuration \`timber build\` uses — including config passed inline to timber().\n\n` +
112
+ ` Check that vite.config.ts exists and lists the timber plugin:\n\n` +
113
+ ` import { timber } from '@timber-js/app';\n` +
114
+ ` export default { plugins: [timber()] };\n`
115
+ );
116
+ }
117
+
118
+ return rootSync.api.getContext();
119
+ }
package/src/cli.ts CHANGED
@@ -15,6 +15,7 @@
15
15
  // Type-only — the implementation is imported dynamically inside runCheck so the
16
16
  // CLI's other commands never load the route scanner.
17
17
  import type { CheckDeps } from './cli-check.ts';
18
+ import type { ResolveViteConfig } from './cli-context.ts';
18
19
 
19
20
  export type { CheckDeps };
20
21
 
@@ -140,6 +141,7 @@ export interface ViteDeps {
140
141
  createServer?: typeof import('vite').createServer;
141
142
  createBuilder?: typeof import('vite').createBuilder;
142
143
  preview?: typeof import('vite').preview;
144
+ resolveViteConfig?: ResolveViteConfig;
143
145
  }
144
146
 
145
147
  /**
@@ -227,42 +229,31 @@ export async function runBuild(options: CommandOptions, _deps?: ViteDeps): Promi
227
229
  await builder.buildApp();
228
230
  }
229
231
 
230
- /**
231
- * Determine whether to use the adapter's preview or Vite's built-in preview.
232
- * Exported for testing — the actual runPreview function uses this internally.
233
- */
234
- export function resolvePreviewStrategy(
235
- adapter: import('./adapters/types.ts').TimberPlatformAdapter | undefined
236
- ): 'adapter' | 'vite' {
237
- if (adapter && typeof adapter.preview === 'function') {
238
- return 'adapter';
239
- }
240
- return 'vite';
241
- }
242
-
243
232
  /**
244
233
  * Serve the production build for local testing.
245
234
  * If the adapter provides a preview() method, it takes priority.
246
235
  * Otherwise falls back to Vite's built-in preview server.
247
236
  *
248
- * Uses the same loadTimberConfigFile loader as dev/build — one loader,
249
- * one set of module semantics. A config file that exists but fails to
250
- * load throws (naming the file) instead of silently degrading to plain
251
- * Vite preview. See TIM-1066.
237
+ * The project is resolved through Vite, as `timber check` resolves it
238
+ * (`cli-context.ts`), so the adapter, the output mode, and the build
239
+ * directory are the ones `timber build` used — including `--config`, inline
240
+ * `timber({ ... })` options, Vite's `root`, and `build.outDir`, none of which
241
+ * a re-read of `timber.config.ts` can see (TIM-1531). A config file that
242
+ * exists but fails to load throws (naming the file) instead of silently
243
+ * degrading to plain Vite preview (TIM-1066).
252
244
  */
253
245
  export async function runPreview(options: CommandOptions, _deps?: ViteDeps): Promise<void> {
254
- const { loadTimberConfigFile, resolveBuildDir } = await import('./plugin-context.ts');
246
+ const { resolveTimberContext } = await import('./cli-context.ts');
247
+ const { adapterConfig, contextAdapter } = await import('./plugin-context.ts');
255
248
 
256
- const root = process.cwd();
257
- const config = loadTimberConfigFile(root);
258
- const adapter = config?.adapter as
259
- | import('./adapters/types.ts').TimberPlatformAdapter
260
- | undefined;
261
-
262
- if (resolvePreviewStrategy(adapter) === 'adapter') {
263
- const buildDir = resolveBuildDir(root, config?.buildDir);
264
- const timberConfig = { output: (config?.output ?? 'server') as 'server' | 'static' };
265
- await adapter!.preview!(timberConfig, buildDir);
249
+ const ctx = await resolveTimberContext('preview', options.config, _deps?.resolveViteConfig);
250
+ const adapter = contextAdapter(ctx);
251
+
252
+ if (typeof adapter?.preview === 'function') {
253
+ await adapter.preview(adapterConfig(ctx), {
254
+ output: ctx.config.output ?? 'server',
255
+ outputDir: ctx.buildDir,
256
+ });
266
257
  return;
267
258
  }
268
259
 
@@ -312,7 +312,7 @@ export function setupClientErrorForwarding(hot: HotInterface): void {
312
312
  * they are expected during navigation and are handled by the error boundary
313
313
  * and router. Exported for tests.
314
314
  *
315
- * See also: isControlFlowSignal() in server/primitives.ts (server-side,
315
+ * See also: isControlFlowSignal() in server/signal-identity.ts (server-side,
316
316
  * handles both instanceof and digest detection).
317
317
  */
318
318
  export function isFrameworkSignalError(error: unknown): boolean {
@@ -22,11 +22,12 @@ import { setHardNavigating } from '../navigation-root.tsx';
22
22
  import { getClientDeploymentId, DEPLOYMENT_ID_HEADER, RELOAD_HEADER } from '../rsc-fetch.ts';
23
23
  import { markClientStale } from '../stale-client.ts';
24
24
  import { RSC_CONTENT_TYPE } from '../../shared/rsc-media-type.ts';
25
+ import { CSRF_REJECT_HEADER, CSRF_REJECT_VALUE } from '../../shared/csrf-reject.ts';
25
26
  import { createActionQueue } from './action-queue.ts';
26
27
 
27
28
  /**
28
29
  * Wait for a navigation or refresh to both settle (promise resolved) AND
29
- * commit (pushState / renderPayload's commit thunk ran). The queue must
30
+ * commit (pushState / the navigation's commit thunk ran). The queue must
30
31
  * not release the next action until the URL is correct in the address bar
31
32
  * — same rule `<Link>` uses for `isPending` (design/19 §Per-Link Pending
32
33
  * State). `onCommit` fires exactly once: on commit, supersession, or
@@ -93,6 +94,13 @@ export function setupServerActions(): void {
93
94
  markClientStale();
94
95
  throw new Error('Version skew detected — this client is out of date');
95
96
  }
97
+ // A CSRF 403 has a plain-text body; handing it to createFromFetch
98
+ // would surface as an opaque Flight decode error (TIM-1459).
99
+ if (res.headers.get(CSRF_REJECT_HEADER) === CSRF_REJECT_VALUE) {
100
+ throw new Error(
101
+ 'Server action rejected: CSRF origin check failed (403). ' + 'The server log says why.'
102
+ );
103
+ }
96
104
  hasRevalidation = res.headers.get('X-Timber-Revalidation') === '1';
97
105
  hasRedirect = res.headers.get('X-Timber-Redirect') != null;
98
106
  reval.paths = res.headers.get('X-Timber-Revalidation-Path');
@@ -170,7 +178,8 @@ export function setupServerActions(): void {
170
178
  .then(
171
179
  (applied) => {
172
180
  if (!applied) {
173
- router.evictStaleCaches();
181
+ // Synchronous eviction already ran at line 121 — only
182
+ // the refresh flag needs deferral (TIM-1518).
174
183
  queue.markNeedsRefresh();
175
184
  }
176
185
  },
@@ -184,8 +193,17 @@ export function setupServerActions(): void {
184
193
  }
185
194
 
186
195
  // revalidatePath was called but only for non-current paths —
187
- // caches were already invalidated above, no refresh needed.
196
+ // caches were already invalidated above, so no refresh is needed
197
+ // unless a navigation ran while this action was in flight. That
198
+ // navigation may have consumed a pre-mutation prefetch before the
199
+ // eviction above, or fetched before the mutation landed, and it is
200
+ // now on screen. The other branches catch this through
201
+ // applyActionResult's epoch check; this one must check itself
202
+ // (TIM-1483).
188
203
  if (reval.paths) {
204
+ if (router && epoch && !router.isEpochCurrent(epoch)) {
205
+ queue.markNeedsRefresh();
206
+ }
189
207
  return decoded;
190
208
  }
191
209
 
@@ -194,11 +212,15 @@ export function setupServerActions(): void {
194
212
  // the queue until the refresh commits so the next action captures a
195
213
  // current epoch (codex on #1125).
196
214
  if (router && epoch) {
215
+ // TIM-1518: Evict synchronously so a navigation that supersedes
216
+ // this action's refresh cannot consume a pre-mutation prefetch.
217
+ // The deferred eviction in .then() ran as a microtask — after the
218
+ // superseding navigation had already consumed a stale entry.
219
+ router.evictStaleCaches();
197
220
  hold(
198
221
  router.applyActionResult(epoch).then(
199
222
  (applied) => {
200
223
  if (!applied) {
201
- router.evictStaleCaches();
202
224
  queue.markNeedsRefresh();
203
225
  }
204
226
  },