@timber-js/app 0.2.0-alpha.7 → 0.2.0-alpha.71

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 (500) hide show
  1. package/LICENSE +8 -0
  2. package/dist/_chunks/{als-registry-B7DbZ2hS.js → als-registry-BJARkOcu.js} +1 -1
  3. package/dist/_chunks/als-registry-BJARkOcu.js.map +1 -0
  4. package/dist/_chunks/chunk-DYhsFzuS.js +33 -0
  5. package/dist/_chunks/{debug-gwlJkDuf.js → debug-ECi_61pb.js} +2 -2
  6. package/dist/_chunks/debug-ECi_61pb.js.map +1 -0
  7. package/dist/_chunks/define-CGuYoRHU.js +199 -0
  8. package/dist/_chunks/define-CGuYoRHU.js.map +1 -0
  9. package/dist/_chunks/define-Dz1bqwaS.js +106 -0
  10. package/dist/_chunks/define-Dz1bqwaS.js.map +1 -0
  11. package/dist/_chunks/define-cookie-B5mewxwM.js +93 -0
  12. package/dist/_chunks/define-cookie-B5mewxwM.js.map +1 -0
  13. package/dist/_chunks/error-boundary-D9hzsveV.js +216 -0
  14. package/dist/_chunks/error-boundary-D9hzsveV.js.map +1 -0
  15. package/dist/_chunks/{format-DviM89f0.js → format-Rn922VH2.js} +3 -20
  16. package/dist/_chunks/format-Rn922VH2.js.map +1 -0
  17. package/dist/_chunks/{tracing-Cwn7697K.js → handler-store-BVePM7hp.js} +68 -3
  18. package/dist/_chunks/handler-store-BVePM7hp.js.map +1 -0
  19. package/dist/_chunks/{interception-BOoWmLUA.js → interception-CEdHHviP.js} +171 -97
  20. package/dist/_chunks/interception-CEdHHviP.js.map +1 -0
  21. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → metadata-routes-DS3eKNmf.js} +1 -1
  22. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js.map → metadata-routes-DS3eKNmf.js.map} +1 -1
  23. package/dist/_chunks/{request-context-DIkVh_jG.js → request-context-CywiO4jV.js} +181 -69
  24. package/dist/_chunks/request-context-CywiO4jV.js.map +1 -0
  25. package/dist/_chunks/schema-bridge-C4SwjCQD.js +86 -0
  26. package/dist/_chunks/schema-bridge-C4SwjCQD.js.map +1 -0
  27. package/dist/_chunks/segment-classify-BDNn6EzD.js +65 -0
  28. package/dist/_chunks/segment-classify-BDNn6EzD.js.map +1 -0
  29. package/dist/_chunks/segment-context-hzuJ048X.js +72 -0
  30. package/dist/_chunks/segment-context-hzuJ048X.js.map +1 -0
  31. package/dist/_chunks/stale-reload-BLUC_Pl_.js +64 -0
  32. package/dist/_chunks/stale-reload-BLUC_Pl_.js.map +1 -0
  33. package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-DAhgj8Gx.js} +1 -1
  34. package/dist/_chunks/use-query-states-DAhgj8Gx.js.map +1 -0
  35. package/dist/_chunks/wrappers-LZbghvn0.js +63 -0
  36. package/dist/_chunks/wrappers-LZbghvn0.js.map +1 -0
  37. package/dist/adapters/cloudflare-dev.d.ts +109 -0
  38. package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
  39. package/dist/adapters/cloudflare-dev.js +73 -0
  40. package/dist/adapters/cloudflare-dev.js.map +1 -0
  41. package/dist/adapters/cloudflare.d.ts +148 -12
  42. package/dist/adapters/cloudflare.d.ts.map +1 -1
  43. package/dist/adapters/cloudflare.js +135 -11
  44. package/dist/adapters/cloudflare.js.map +1 -1
  45. package/dist/adapters/compress-module.d.ts.map +1 -1
  46. package/dist/adapters/nitro.d.ts +17 -1
  47. package/dist/adapters/nitro.d.ts.map +1 -1
  48. package/dist/adapters/nitro.js +56 -13
  49. package/dist/adapters/nitro.js.map +1 -1
  50. package/dist/cache/cache-api.d.ts +24 -0
  51. package/dist/cache/cache-api.d.ts.map +1 -0
  52. package/dist/cache/fast-hash.d.ts +22 -0
  53. package/dist/cache/fast-hash.d.ts.map +1 -0
  54. package/dist/cache/handler-store.d.ts +31 -0
  55. package/dist/cache/handler-store.d.ts.map +1 -0
  56. package/dist/cache/index.d.ts +7 -5
  57. package/dist/cache/index.d.ts.map +1 -1
  58. package/dist/cache/index.js +111 -73
  59. package/dist/cache/index.js.map +1 -1
  60. package/dist/cache/singleflight.d.ts +18 -1
  61. package/dist/cache/singleflight.d.ts.map +1 -1
  62. package/dist/cache/timber-cache.d.ts +1 -1
  63. package/dist/cache/timber-cache.d.ts.map +1 -1
  64. package/dist/client/error-boundary.d.ts +12 -5
  65. package/dist/client/error-boundary.d.ts.map +1 -1
  66. package/dist/client/error-boundary.js +1 -125
  67. package/dist/client/error-reconstituter.d.ts +54 -0
  68. package/dist/client/error-reconstituter.d.ts.map +1 -0
  69. package/dist/client/form.d.ts +2 -2
  70. package/dist/client/form.d.ts.map +1 -1
  71. package/dist/client/history.d.ts +19 -4
  72. package/dist/client/history.d.ts.map +1 -1
  73. package/dist/client/index.d.ts +6 -5
  74. package/dist/client/index.d.ts.map +1 -1
  75. package/dist/client/index.js +537 -166
  76. package/dist/client/index.js.map +1 -1
  77. package/dist/client/link-pending-store.d.ts +78 -0
  78. package/dist/client/link-pending-store.d.ts.map +1 -0
  79. package/dist/client/link.d.ts +90 -32
  80. package/dist/client/link.d.ts.map +1 -1
  81. package/dist/client/nav-link-store.d.ts +36 -0
  82. package/dist/client/nav-link-store.d.ts.map +1 -0
  83. package/dist/client/navigation-api-types.d.ts +90 -0
  84. package/dist/client/navigation-api-types.d.ts.map +1 -0
  85. package/dist/client/navigation-api.d.ts +115 -0
  86. package/dist/client/navigation-api.d.ts.map +1 -0
  87. package/dist/client/navigation-context.d.ts +13 -2
  88. package/dist/client/navigation-context.d.ts.map +1 -1
  89. package/dist/client/{transition-root.d.ts → navigation-root.d.ts} +42 -8
  90. package/dist/client/navigation-root.d.ts.map +1 -0
  91. package/dist/client/nuqs-adapter.d.ts.map +1 -1
  92. package/dist/client/router.d.ts +70 -4
  93. package/dist/client/router.d.ts.map +1 -1
  94. package/dist/client/rsc-fetch.d.ts +38 -3
  95. package/dist/client/rsc-fetch.d.ts.map +1 -1
  96. package/dist/client/segment-cache.d.ts +1 -1
  97. package/dist/client/segment-cache.d.ts.map +1 -1
  98. package/dist/client/segment-context.d.ts +1 -1
  99. package/dist/client/segment-context.d.ts.map +1 -1
  100. package/dist/client/segment-merger.d.ts.map +1 -1
  101. package/dist/client/segment-outlet.d.ts +63 -0
  102. package/dist/client/segment-outlet.d.ts.map +1 -0
  103. package/dist/client/ssr-data.d.ts +13 -4
  104. package/dist/client/ssr-data.d.ts.map +1 -1
  105. package/dist/client/stale-reload.d.ts +15 -0
  106. package/dist/client/stale-reload.d.ts.map +1 -1
  107. package/dist/client/top-loader.d.ts +3 -3
  108. package/dist/client/top-loader.d.ts.map +1 -1
  109. package/dist/client/use-params.d.ts +6 -4
  110. package/dist/client/use-params.d.ts.map +1 -1
  111. package/dist/client/use-query-states.d.ts +1 -1
  112. package/dist/client/use-query-states.d.ts.map +1 -1
  113. package/dist/codec.d.ts +23 -0
  114. package/dist/codec.d.ts.map +1 -0
  115. package/dist/codec.js +2 -0
  116. package/dist/cookies/define-cookie.d.ts +35 -14
  117. package/dist/cookies/define-cookie.d.ts.map +1 -1
  118. package/dist/cookies/index.d.ts +2 -0
  119. package/dist/cookies/index.d.ts.map +1 -1
  120. package/dist/cookies/index.js +3 -84
  121. package/dist/fonts/css.d.ts +1 -0
  122. package/dist/fonts/css.d.ts.map +1 -1
  123. package/dist/index.d.ts +154 -38
  124. package/dist/index.d.ts.map +1 -1
  125. package/dist/index.js +12092 -11916
  126. package/dist/index.js.map +1 -1
  127. package/dist/plugins/adapter-build.d.ts +1 -1
  128. package/dist/plugins/adapter-build.d.ts.map +1 -1
  129. package/dist/plugins/build-manifest.d.ts +2 -2
  130. package/dist/plugins/build-manifest.d.ts.map +1 -1
  131. package/dist/plugins/build-report.d.ts +3 -3
  132. package/dist/plugins/build-report.d.ts.map +1 -1
  133. package/dist/plugins/client-chunks.d.ts +32 -0
  134. package/dist/plugins/client-chunks.d.ts.map +1 -0
  135. package/dist/plugins/content.d.ts +1 -1
  136. package/dist/plugins/content.d.ts.map +1 -1
  137. package/dist/plugins/dev-browser-logs.d.ts +84 -0
  138. package/dist/plugins/dev-browser-logs.d.ts.map +1 -0
  139. package/dist/plugins/dev-error-overlay.d.ts +26 -1
  140. package/dist/plugins/dev-error-overlay.d.ts.map +1 -1
  141. package/dist/plugins/dev-logs.d.ts +1 -1
  142. package/dist/plugins/dev-logs.d.ts.map +1 -1
  143. package/dist/plugins/dev-server.d.ts +1 -1
  144. package/dist/plugins/dev-server.d.ts.map +1 -1
  145. package/dist/plugins/entries.d.ts +1 -1
  146. package/dist/plugins/entries.d.ts.map +1 -1
  147. package/dist/plugins/fonts.d.ts +19 -5
  148. package/dist/plugins/fonts.d.ts.map +1 -1
  149. package/dist/plugins/mdx.d.ts +1 -1
  150. package/dist/plugins/mdx.d.ts.map +1 -1
  151. package/dist/plugins/routing.d.ts +1 -1
  152. package/dist/plugins/routing.d.ts.map +1 -1
  153. package/dist/plugins/server-bundle.d.ts.map +1 -1
  154. package/dist/plugins/shims.d.ts +6 -5
  155. package/dist/plugins/shims.d.ts.map +1 -1
  156. package/dist/plugins/static-build.d.ts +1 -1
  157. package/dist/plugins/static-build.d.ts.map +1 -1
  158. package/dist/routing/codegen.d.ts +2 -2
  159. package/dist/routing/codegen.d.ts.map +1 -1
  160. package/dist/routing/index.d.ts +2 -0
  161. package/dist/routing/index.d.ts.map +1 -1
  162. package/dist/routing/index.js +3 -2
  163. package/dist/routing/scanner.d.ts.map +1 -1
  164. package/dist/routing/segment-classify.d.ts +46 -0
  165. package/dist/routing/segment-classify.d.ts.map +1 -0
  166. package/dist/routing/status-file-lint.d.ts +2 -1
  167. package/dist/routing/status-file-lint.d.ts.map +1 -1
  168. package/dist/routing/types.d.ts +16 -4
  169. package/dist/routing/types.d.ts.map +1 -1
  170. package/dist/rsc-runtime/rsc.d.ts +1 -1
  171. package/dist/rsc-runtime/rsc.d.ts.map +1 -1
  172. package/dist/rsc-runtime/ssr.d.ts +12 -0
  173. package/dist/rsc-runtime/ssr.d.ts.map +1 -1
  174. package/dist/schema-bridge.d.ts +76 -0
  175. package/dist/schema-bridge.d.ts.map +1 -0
  176. package/dist/search-params/define.d.ts +139 -0
  177. package/dist/search-params/define.d.ts.map +1 -0
  178. package/dist/search-params/index.d.ts +4 -6
  179. package/dist/search-params/index.d.ts.map +1 -1
  180. package/dist/search-params/index.js +4 -474
  181. package/dist/search-params/registry.d.ts +1 -1
  182. package/dist/search-params/wrappers.d.ts +53 -0
  183. package/dist/search-params/wrappers.d.ts.map +1 -0
  184. package/dist/segment-params/define.d.ts +78 -0
  185. package/dist/segment-params/define.d.ts.map +1 -0
  186. package/dist/segment-params/index.d.ts +7 -0
  187. package/dist/segment-params/index.d.ts.map +1 -0
  188. package/dist/segment-params/index.js +4 -0
  189. package/dist/server/access-gate.d.ts +4 -0
  190. package/dist/server/access-gate.d.ts.map +1 -1
  191. package/dist/server/action-client.d.ts +12 -1
  192. package/dist/server/action-client.d.ts.map +1 -1
  193. package/dist/server/action-encryption.d.ts +76 -0
  194. package/dist/server/action-encryption.d.ts.map +1 -0
  195. package/dist/server/action-handler.d.ts.map +1 -1
  196. package/dist/server/actions.d.ts +3 -6
  197. package/dist/server/actions.d.ts.map +1 -1
  198. package/dist/server/als-registry.d.ts +32 -4
  199. package/dist/server/als-registry.d.ts.map +1 -1
  200. package/dist/server/build-manifest.d.ts +2 -2
  201. package/dist/server/build-manifest.d.ts.map +1 -1
  202. package/dist/server/debug.d.ts +1 -1
  203. package/dist/server/default-logger.d.ts +22 -0
  204. package/dist/server/default-logger.d.ts.map +1 -0
  205. package/dist/server/deny-page-resolver.d.ts +52 -0
  206. package/dist/server/deny-page-resolver.d.ts.map +1 -0
  207. package/dist/server/deny-renderer.d.ts.map +1 -1
  208. package/dist/server/dev-warnings.d.ts +0 -14
  209. package/dist/server/dev-warnings.d.ts.map +1 -1
  210. package/dist/server/early-hints.d.ts +13 -5
  211. package/dist/server/early-hints.d.ts.map +1 -1
  212. package/dist/server/error-boundary-wrapper.d.ts +7 -1
  213. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  214. package/dist/server/fallback-error.d.ts +4 -3
  215. package/dist/server/fallback-error.d.ts.map +1 -1
  216. package/dist/server/flight-injection-state.d.ts +66 -0
  217. package/dist/server/flight-injection-state.d.ts.map +1 -0
  218. package/dist/server/flight-scripts.d.ts +42 -0
  219. package/dist/server/flight-scripts.d.ts.map +1 -0
  220. package/dist/server/flush.d.ts.map +1 -1
  221. package/dist/server/form-data.d.ts +29 -0
  222. package/dist/server/form-data.d.ts.map +1 -1
  223. package/dist/server/html-injectors.d.ts +51 -11
  224. package/dist/server/html-injectors.d.ts.map +1 -1
  225. package/dist/server/index.d.ts +5 -3
  226. package/dist/server/index.d.ts.map +1 -1
  227. package/dist/server/index.js +2176 -1663
  228. package/dist/server/index.js.map +1 -1
  229. package/dist/server/logger.d.ts +25 -7
  230. package/dist/server/logger.d.ts.map +1 -1
  231. package/dist/server/middleware-runner.d.ts +19 -4
  232. package/dist/server/middleware-runner.d.ts.map +1 -1
  233. package/dist/server/node-stream-transforms.d.ts +113 -0
  234. package/dist/server/node-stream-transforms.d.ts.map +1 -0
  235. package/dist/server/page-deny-boundary.d.ts +31 -0
  236. package/dist/server/page-deny-boundary.d.ts.map +1 -0
  237. package/dist/server/pipeline-interception.d.ts +1 -1
  238. package/dist/server/pipeline-interception.d.ts.map +1 -1
  239. package/dist/server/pipeline-metadata.d.ts +6 -0
  240. package/dist/server/pipeline-metadata.d.ts.map +1 -1
  241. package/dist/server/pipeline.d.ts +32 -10
  242. package/dist/server/pipeline.d.ts.map +1 -1
  243. package/dist/server/primitives.d.ts +30 -3
  244. package/dist/server/primitives.d.ts.map +1 -1
  245. package/dist/server/render-timeout.d.ts +51 -0
  246. package/dist/server/render-timeout.d.ts.map +1 -0
  247. package/dist/server/request-context.d.ts +76 -37
  248. package/dist/server/request-context.d.ts.map +1 -1
  249. package/dist/server/route-element-builder.d.ts +27 -1
  250. package/dist/server/route-element-builder.d.ts.map +1 -1
  251. package/dist/server/route-handler.d.ts.map +1 -1
  252. package/dist/server/route-matcher.d.ts +9 -2
  253. package/dist/server/route-matcher.d.ts.map +1 -1
  254. package/dist/server/rsc-entry/api-handler.d.ts +2 -2
  255. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  256. package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
  257. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  258. package/dist/server/rsc-entry/helpers.d.ts +48 -5
  259. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  260. package/dist/server/rsc-entry/index.d.ts +8 -3
  261. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  262. package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
  263. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  264. package/dist/server/rsc-entry/rsc-stream.d.ts +10 -1
  265. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  266. package/dist/server/rsc-entry/ssr-bridge.d.ts +1 -1
  267. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  268. package/dist/server/rsc-entry/ssr-renderer.d.ts +19 -4
  269. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  270. package/dist/server/safe-load.d.ts +46 -0
  271. package/dist/server/safe-load.d.ts.map +1 -0
  272. package/dist/server/sitemap-generator.d.ts +129 -0
  273. package/dist/server/sitemap-generator.d.ts.map +1 -0
  274. package/dist/server/sitemap-handler.d.ts +22 -0
  275. package/dist/server/sitemap-handler.d.ts.map +1 -0
  276. package/dist/server/slot-resolver.d.ts +1 -1
  277. package/dist/server/slot-resolver.d.ts.map +1 -1
  278. package/dist/server/ssr-entry.d.ts +22 -0
  279. package/dist/server/ssr-entry.d.ts.map +1 -1
  280. package/dist/server/ssr-render.d.ts +39 -21
  281. package/dist/server/ssr-render.d.ts.map +1 -1
  282. package/dist/server/ssr-wrappers.d.ts +50 -0
  283. package/dist/server/ssr-wrappers.d.ts.map +1 -0
  284. package/dist/server/status-code-resolver.d.ts +1 -1
  285. package/dist/server/status-code-resolver.d.ts.map +1 -1
  286. package/dist/server/stream-utils.d.ts +36 -0
  287. package/dist/server/stream-utils.d.ts.map +1 -0
  288. package/dist/server/tracing.d.ts +10 -0
  289. package/dist/server/tracing.d.ts.map +1 -1
  290. package/dist/server/tree-builder.d.ts +22 -19
  291. package/dist/server/tree-builder.d.ts.map +1 -1
  292. package/dist/server/types.d.ts +1 -4
  293. package/dist/server/types.d.ts.map +1 -1
  294. package/dist/server/version-skew.d.ts +61 -0
  295. package/dist/server/version-skew.d.ts.map +1 -0
  296. package/dist/server/waituntil-bridge.d.ts.map +1 -1
  297. package/dist/shared/merge-search-params.d.ts +22 -0
  298. package/dist/shared/merge-search-params.d.ts.map +1 -0
  299. package/dist/shims/font-google.d.ts +1 -1
  300. package/dist/shims/font-google.d.ts.map +1 -1
  301. package/dist/shims/font-google.js +42 -0
  302. package/dist/shims/font-google.js.map +1 -0
  303. package/dist/shims/font-local.d.ts +26 -0
  304. package/dist/shims/font-local.d.ts.map +1 -0
  305. package/dist/shims/font-local.js +20 -0
  306. package/dist/shims/font-local.js.map +1 -0
  307. package/dist/shims/navigation-client.d.ts +1 -1
  308. package/dist/shims/navigation-client.d.ts.map +1 -1
  309. package/dist/shims/navigation.d.ts +1 -1
  310. package/dist/shims/navigation.d.ts.map +1 -1
  311. package/dist/utils/directive-parser.d.ts +5 -2
  312. package/dist/utils/directive-parser.d.ts.map +1 -1
  313. package/dist/utils/state-machine.d.ts +80 -0
  314. package/dist/utils/state-machine.d.ts.map +1 -0
  315. package/package.json +37 -17
  316. package/src/adapters/cloudflare-dev.ts +177 -0
  317. package/src/adapters/cloudflare.ts +342 -28
  318. package/src/adapters/compress-module.ts +24 -4
  319. package/src/adapters/nitro.ts +58 -9
  320. package/src/adapters/wrangler.d.ts +7 -0
  321. package/src/cache/cache-api.ts +38 -0
  322. package/src/cache/fast-hash.ts +34 -0
  323. package/src/cache/handler-store.ts +68 -0
  324. package/src/cache/index.ts +9 -5
  325. package/src/cache/singleflight.ts +62 -4
  326. package/src/cache/timber-cache.ts +40 -29
  327. package/src/cli.ts +0 -0
  328. package/src/client/browser-entry.ts +314 -142
  329. package/src/client/error-boundary.tsx +48 -16
  330. package/src/client/error-reconstituter.tsx +65 -0
  331. package/src/client/form.tsx +2 -2
  332. package/src/client/history.ts +26 -4
  333. package/src/client/index.ts +13 -4
  334. package/src/client/link-pending-store.ts +136 -0
  335. package/src/client/link.tsx +346 -105
  336. package/src/client/nav-link-store.ts +47 -0
  337. package/src/client/navigation-api-types.ts +112 -0
  338. package/src/client/navigation-api.ts +332 -0
  339. package/src/client/navigation-context.ts +27 -6
  340. package/src/client/navigation-root.tsx +346 -0
  341. package/src/client/nuqs-adapter.tsx +16 -3
  342. package/src/client/router.ts +302 -77
  343. package/src/client/rsc-fetch.ts +93 -5
  344. package/src/client/segment-cache.ts +1 -1
  345. package/src/client/segment-context.ts +6 -1
  346. package/src/client/segment-merger.ts +2 -8
  347. package/src/client/segment-outlet.tsx +86 -0
  348. package/src/client/ssr-data.ts +13 -5
  349. package/src/client/stale-reload.ts +73 -6
  350. package/src/client/top-loader.tsx +22 -13
  351. package/src/client/use-navigation-pending.ts +1 -1
  352. package/src/client/use-params.ts +7 -5
  353. package/src/client/use-query-states.ts +2 -2
  354. package/src/codec.ts +34 -0
  355. package/src/cookies/define-cookie.ts +72 -21
  356. package/src/cookies/index.ts +7 -0
  357. package/src/fonts/css.ts +2 -1
  358. package/src/index.ts +328 -92
  359. package/src/plugins/adapter-build.ts +8 -2
  360. package/src/plugins/build-manifest.ts +13 -2
  361. package/src/plugins/build-report.ts +3 -3
  362. package/src/plugins/client-chunks.ts +65 -0
  363. package/src/plugins/content.ts +1 -1
  364. package/src/plugins/dev-browser-logs.ts +288 -0
  365. package/src/plugins/dev-error-overlay.ts +70 -1
  366. package/src/plugins/dev-logs.ts +1 -1
  367. package/src/plugins/dev-server.ts +55 -9
  368. package/src/plugins/entries.ts +70 -9
  369. package/src/plugins/fonts.ts +167 -61
  370. package/src/plugins/mdx.ts +1 -1
  371. package/src/plugins/routing.ts +57 -17
  372. package/src/plugins/server-action-exports.ts +1 -1
  373. package/src/plugins/server-bundle.ts +32 -1
  374. package/src/plugins/shims.ts +76 -33
  375. package/src/plugins/static-build.ts +10 -6
  376. package/src/routing/codegen.ts +165 -105
  377. package/src/routing/index.ts +2 -0
  378. package/src/routing/scanner.ts +93 -23
  379. package/src/routing/segment-classify.ts +89 -0
  380. package/src/routing/status-file-lint.ts +3 -2
  381. package/src/routing/types.ts +17 -4
  382. package/src/rsc-runtime/rsc.ts +2 -0
  383. package/src/rsc-runtime/ssr.ts +50 -0
  384. package/src/rsc-runtime/vendor-types.d.ts +7 -0
  385. package/src/{search-params/codecs.ts → schema-bridge.ts} +57 -20
  386. package/src/search-params/define.ts +482 -0
  387. package/src/search-params/index.ts +13 -19
  388. package/src/search-params/registry.ts +1 -1
  389. package/src/search-params/wrappers.ts +85 -0
  390. package/src/segment-params/define.ts +279 -0
  391. package/src/segment-params/index.ts +28 -0
  392. package/src/server/access-gate.tsx +70 -29
  393. package/src/server/action-client.ts +28 -3
  394. package/src/server/action-encryption.ts +144 -0
  395. package/src/server/action-handler.ts +20 -3
  396. package/src/server/actions.ts +10 -9
  397. package/src/server/als-registry.ts +32 -4
  398. package/src/server/build-manifest.ts +10 -4
  399. package/src/server/compress.ts +25 -7
  400. package/src/server/debug.ts +1 -1
  401. package/src/server/default-logger.ts +99 -0
  402. package/src/server/deny-page-resolver.ts +154 -0
  403. package/src/server/deny-renderer.ts +24 -38
  404. package/src/server/dev-warnings.ts +2 -28
  405. package/src/server/early-hints.ts +36 -15
  406. package/src/server/error-boundary-wrapper.ts +74 -22
  407. package/src/server/fallback-error.ts +31 -15
  408. package/src/server/flight-injection-state.ts +113 -0
  409. package/src/server/flight-scripts.ts +62 -0
  410. package/src/server/flush.ts +2 -1
  411. package/src/server/form-data.ts +76 -0
  412. package/src/server/html-injectors.ts +277 -117
  413. package/src/server/index.ts +9 -5
  414. package/src/server/logger.ts +44 -36
  415. package/src/server/middleware-runner.ts +31 -4
  416. package/src/server/node-stream-transforms.ts +509 -0
  417. package/src/server/page-deny-boundary.tsx +56 -0
  418. package/src/server/pipeline-interception.ts +17 -16
  419. package/src/server/pipeline-metadata.ts +13 -0
  420. package/src/server/pipeline.ts +195 -51
  421. package/src/server/primitives.ts +47 -5
  422. package/src/server/render-timeout.ts +108 -0
  423. package/src/server/request-context.ts +240 -117
  424. package/src/server/route-element-builder.ts +284 -197
  425. package/src/server/route-handler.ts +24 -4
  426. package/src/server/route-matcher.ts +24 -20
  427. package/src/server/rsc-entry/api-handler.ts +15 -16
  428. package/src/server/rsc-entry/error-renderer.ts +300 -89
  429. package/src/server/rsc-entry/helpers.ts +134 -5
  430. package/src/server/rsc-entry/index.ts +202 -113
  431. package/src/server/rsc-entry/rsc-payload.ts +100 -21
  432. package/src/server/rsc-entry/rsc-stream.ts +74 -18
  433. package/src/server/rsc-entry/ssr-bridge.ts +14 -5
  434. package/src/server/rsc-entry/ssr-renderer.ts +173 -40
  435. package/src/server/safe-load.ts +60 -0
  436. package/src/server/sitemap-generator.ts +338 -0
  437. package/src/server/sitemap-handler.ts +126 -0
  438. package/src/server/slot-resolver.ts +243 -228
  439. package/src/server/ssr-entry.ts +211 -32
  440. package/src/server/ssr-render.ts +289 -67
  441. package/src/server/ssr-wrappers.tsx +139 -0
  442. package/src/server/status-code-resolver.ts +1 -1
  443. package/src/server/stream-utils.ts +213 -0
  444. package/src/server/tracing.ts +37 -3
  445. package/src/server/tree-builder.ts +92 -58
  446. package/src/server/types.ts +3 -6
  447. package/src/server/version-skew.ts +104 -0
  448. package/src/server/waituntil-bridge.ts +4 -1
  449. package/src/shared/merge-search-params.ts +55 -0
  450. package/src/shims/font-google.ts +1 -1
  451. package/src/shims/font-local.ts +34 -0
  452. package/src/shims/navigation-client.ts +1 -1
  453. package/src/shims/navigation.ts +2 -1
  454. package/src/utils/directive-parser.ts +5 -2
  455. package/src/utils/state-machine.ts +111 -0
  456. package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
  457. package/dist/_chunks/debug-gwlJkDuf.js.map +0 -1
  458. package/dist/_chunks/format-DviM89f0.js.map +0 -1
  459. package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
  460. package/dist/_chunks/request-context-DIkVh_jG.js.map +0 -1
  461. package/dist/_chunks/ssr-data-MjmprTmO.js +0 -88
  462. package/dist/_chunks/ssr-data-MjmprTmO.js.map +0 -1
  463. package/dist/_chunks/tracing-Cwn7697K.js.map +0 -1
  464. package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
  465. package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
  466. package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
  467. package/dist/cache/register-cached-function.d.ts +0 -17
  468. package/dist/cache/register-cached-function.d.ts.map +0 -1
  469. package/dist/client/error-boundary.js.map +0 -1
  470. package/dist/client/link-status-provider.d.ts +0 -11
  471. package/dist/client/link-status-provider.d.ts.map +0 -1
  472. package/dist/client/transition-root.d.ts.map +0 -1
  473. package/dist/cookies/index.js.map +0 -1
  474. package/dist/plugins/cache-transform.d.ts +0 -36
  475. package/dist/plugins/cache-transform.d.ts.map +0 -1
  476. package/dist/plugins/dynamic-transform.d.ts +0 -72
  477. package/dist/plugins/dynamic-transform.d.ts.map +0 -1
  478. package/dist/search-params/analyze.d.ts +0 -54
  479. package/dist/search-params/analyze.d.ts.map +0 -1
  480. package/dist/search-params/builtin-codecs.d.ts +0 -105
  481. package/dist/search-params/builtin-codecs.d.ts.map +0 -1
  482. package/dist/search-params/codecs.d.ts +0 -53
  483. package/dist/search-params/codecs.d.ts.map +0 -1
  484. package/dist/search-params/create.d.ts +0 -106
  485. package/dist/search-params/create.d.ts.map +0 -1
  486. package/dist/search-params/index.js.map +0 -1
  487. package/dist/server/prerender.d.ts +0 -77
  488. package/dist/server/prerender.d.ts.map +0 -1
  489. package/dist/server/response-cache.d.ts +0 -53
  490. package/dist/server/response-cache.d.ts.map +0 -1
  491. package/src/cache/register-cached-function.ts +0 -99
  492. package/src/client/link-status-provider.tsx +0 -30
  493. package/src/client/transition-root.tsx +0 -160
  494. package/src/plugins/cache-transform.ts +0 -199
  495. package/src/plugins/dynamic-transform.ts +0 -161
  496. package/src/search-params/analyze.ts +0 -192
  497. package/src/search-params/builtin-codecs.ts +0 -228
  498. package/src/search-params/create.ts +0 -321
  499. package/src/server/prerender.ts +0 -139
  500. package/src/server/response-cache.ts +0 -277
package/src/index.ts CHANGED
@@ -1,10 +1,8 @@
1
1
  import type { Plugin, PluginOption } from 'vite';
2
2
  import { existsSync } from 'node:fs';
3
- import { join } from 'node:path';
4
- import { pathToFileURL } from 'node:url';
3
+ import { join, resolve } from 'node:path';
5
4
  import { createRequire } from 'node:module';
6
- import react from '@vitejs/plugin-react';
7
- import { cacheTransformPlugin } from './plugins/cache-transform';
5
+ import react, { reactCompilerPreset } from '@vitejs/plugin-react';
8
6
  import { timberContent } from './plugins/content';
9
7
  import { timberDevServer } from './plugins/dev-server';
10
8
  import { timberEntries } from './plugins/entries';
@@ -13,12 +11,13 @@ import { timberRouting } from './plugins/routing';
13
11
  import { timberShims } from './plugins/shims';
14
12
  import { timberFonts } from './plugins/fonts';
15
13
  import { timberStaticBuild } from './plugins/static-build';
16
- import { timberDynamicTransform } from './plugins/dynamic-transform';
17
14
  import { timberServerActionExports } from './plugins/server-action-exports';
18
15
  import { timberBuildManifest } from './plugins/build-manifest';
19
16
  import { timberDevLogs } from './plugins/dev-logs';
17
+ import { timberDevBrowserLogs } from './plugins/dev-browser-logs';
20
18
  import { timberReactProd } from './plugins/react-prod';
21
19
  import { timberChunks } from './plugins/chunks';
20
+ import { clientChunkGroup } from './plugins/client-chunks';
22
21
  import { timberServerBundle } from './plugins/server-bundle';
23
22
  import { timberAdapterBuild } from './plugins/adapter-build';
24
23
  import { timberBuildReport } from './plugins/build-report';
@@ -26,6 +25,7 @@ import type { RouteTree } from './routing/types';
26
25
  import type { BuildManifest } from './server/build-manifest';
27
26
  import type { StartupTimer } from './utils/startup-timer';
28
27
  import { createStartupTimer, createNoopTimer } from './utils/startup-timer';
28
+ import { resolveEncryptionKeyExpression, shouldEnableEncryption } from './server/action-encryption';
29
29
 
30
30
  /** Configuration for client-side JavaScript output. */
31
31
  export interface ClientJavascriptConfig {
@@ -90,23 +90,54 @@ export interface TimberUserConfig {
90
90
  * See design/17-logging.md §"slowRequestMs".
91
91
  */
92
92
  slowRequestMs?: number;
93
+ /**
94
+ * Render timeout in milliseconds. If an SSR render or RSC stream read
95
+ * does not complete within this duration, the render is aborted and
96
+ * the connection is closed. Protects against hung fetches and Suspense
97
+ * components that never resolve.
98
+ *
99
+ * Set to 0 to disable (not recommended in production).
100
+ * Default: 30000 (30 seconds).
101
+ *
102
+ * See design/02-rendering-pipeline.md §"Streaming Constraints".
103
+ */
104
+ renderTimeoutMs?: number;
105
+ /**
106
+ * Forward browser console output to the server terminal in dev mode.
107
+ *
108
+ * Sets the minimum log level to forward:
109
+ * - `'error'` — only `console.error`
110
+ * - `'warn'` — `console.error` + `console.warn` (default)
111
+ * - `'info'` — `console.error` + `console.warn` + `console.info`
112
+ * - `'none'` — disabled
113
+ *
114
+ * Does not intercept `console.log` or `console.debug` (too noisy).
115
+ * No effect in production builds.
116
+ *
117
+ * See TIM-513.
118
+ */
119
+ devBrowserLogs?: 'error' | 'warn' | 'info' | 'none';
93
120
  /** Dev-mode options. These have no effect in production builds. */
94
121
  dev?: {
95
122
  /** Threshold in ms to highlight slow phases in dev logging output. Default: 200. */
96
123
  slowPhaseMs?: number;
97
124
  };
98
125
  /**
99
- * Cookie signing configuration. See design/29-cookies.md §"Signed Cookies".
126
+ * Control Server-Timing header output.
100
127
  *
101
- * Provide `secret` for a single key, or `secrets` (array) for key rotation.
102
- * When `secrets` is used, index 0 is the signing key; all are tried for verification.
128
+ * - `'detailed'` per-phase breakdown (proxy, middleware, render). Useful
129
+ * for APM / network monitoring. Exposes phase names to clients.
130
+ * - `'total'` — single `total;dur=N` entry. Safe to expose, gives
131
+ * browser DevTools useful timing without internal details.
132
+ * - `false` — no Server-Timing header at all.
133
+ *
134
+ * Default: `'detailed'` in dev, `'total'` in production.
135
+ *
136
+ * This is separate from `debug` / `TIMBER_DEBUG` — it's an intentional
137
+ * decision to expose timing data to clients, not a side effect of debug
138
+ * logging.
103
139
  */
104
- cookies?: {
105
- /** Single signing secret. Shorthand for `secrets: [secret]`. */
106
- secret?: string;
107
- /** Array of signing secrets for key rotation. Index 0 signs; all verify. */
108
- secrets?: string[];
109
- };
140
+ serverTiming?: 'detailed' | 'total' | false;
110
141
  /**
111
142
  * Override the app directory location. By default, timber auto-detects
112
143
  * `app/` at the project root, falling back to `src/app/`.
@@ -132,6 +163,72 @@ export interface TimberUserConfig {
132
163
  *
133
164
  * See LOCAL-336 for design decisions.
134
165
  */
166
+ /**
167
+ * Server action bound args encryption configuration.
168
+ *
169
+ * The RSC plugin encrypts closure variables captured by 'use server' functions
170
+ * using AES-256-GCM so they are opaque and tamper-proof in the Flight payload.
171
+ * Encryption is always enabled in production.
172
+ *
173
+ * The encryption key is auto-generated at build time and embedded in the server bundle,
174
+ * so all instances running the same build share the same key automatically.
175
+ * For rolling/blue-green deployments where multiple builds coexist, set
176
+ * `TIMBER_ACTIONS_ENCRYPTION_KEY` env var to share a key across builds.
177
+ *
178
+ * See design/08-forms-and-actions.md §"Security"
179
+ */
180
+ actionEncryption?: {
181
+ /**
182
+ * Disable encryption in dev mode for easier debugging of bound args.
183
+ * Has no effect in production — encryption is always enabled.
184
+ * Default: false (encryption is on in dev too).
185
+ */
186
+ disableInDev?: boolean;
187
+ };
188
+ /**
189
+ * Enable the React Compiler (babel-plugin-react-compiler) for automatic
190
+ * memoization of components and hooks at build time.
191
+ *
192
+ * - `true` — enable with default options
193
+ * - `{ compilationMode, target }` — enable with custom options
194
+ * - `compilationMode: 'annotation'` — only compile files with `'use memo'`
195
+ * - `target: '18'` — target React 18 (uses react-compiler-runtime package)
196
+ * - `false` or omitted — disabled (default)
197
+ *
198
+ * Uses `@vitejs/plugin-react`'s built-in `reactCompilerPreset`, which:
199
+ * - Applies Babel only for the compiler pass (OXC handles JSX)
200
+ * - Automatically scopes to client environment only
201
+ * - Uses `react/compiler-runtime` built into React 19
202
+ *
203
+ * Requires `babel-plugin-react-compiler` as a peer dependency.
204
+ */
205
+ reactCompiler?: boolean | { compilationMode?: string; target?: string };
206
+ /**
207
+ * Auto-generate sitemap.xml from the route tree.
208
+ *
209
+ * When enabled, timber walks the file-system route tree and produces a sitemap
210
+ * for all discoverable pages. Dynamic routes with `generateStaticParams()` are
211
+ * enumerated. Routes protected by `access.ts` are excluded by default.
212
+ *
213
+ * If a user-authored `sitemap.ts` or `sitemap.xml` exists at the app root,
214
+ * auto-generation is disabled — the user takes full control.
215
+ *
216
+ * Supports automatic pagination (sitemap index) for sites with > 50,000 URLs.
217
+ *
218
+ * See design/16-metadata.md §"Auto-generated Sitemap"
219
+ */
220
+ sitemap?: {
221
+ /** Must be explicitly `true` to enable auto-generation. Default: false. */
222
+ enabled?: boolean;
223
+ /** Base URL for absolute URLs in the sitemap. Required when enabled. e.g., 'https://example.com' */
224
+ baseUrl?: string;
225
+ /** Default `<changefreq>` for all entries. Optional. */
226
+ defaultChangeFrequency?: string;
227
+ /** Default `<priority>` for all entries (0.0–1.0). Optional. */
228
+ defaultPriority?: number;
229
+ /** Include routes protected by `access.ts`. Default: false. */
230
+ includeProtected?: boolean;
231
+ };
135
232
  topLoader?: {
136
233
  /** Whether the top-loader is enabled. Default: true. */
137
234
  enabled?: boolean;
@@ -146,34 +243,6 @@ export interface TimberUserConfig {
146
243
  /** CSS z-index. Default: 1600. */
147
244
  zIndex?: number;
148
245
  };
149
- /**
150
- * Response-level caching and deduplication.
151
- *
152
- * When enabled, concurrent requests to the same URL share a single render
153
- * (singleflight), and recently rendered responses are reused from a short-TTL
154
- * LRU cache without re-executing the RSC-to-SSR pipeline.
155
- *
156
- * Set to `false` to disable entirely. Default: enabled with sensible defaults.
157
- *
158
- * See design/31-benchmarking.md for performance context.
159
- */
160
- responseCache?:
161
- | false
162
- | {
163
- /** Maximum number of entries in the LRU cache. Default: 150. */
164
- maxSize?: number;
165
- /** TTL for cached entries in milliseconds. Default: 5000 (5s). */
166
- ttlMs?: number;
167
- /**
168
- * When true (default), requests with Cookie or Authorization headers
169
- * bypass the cache entirely. This prevents sharing user-specific
170
- * responses across requests.
171
- *
172
- * Set to false to cache all responses regardless of auth state.
173
- * Only do this if your pages are truly public and don't vary by user.
174
- */
175
- publicOnly?: boolean;
176
- };
177
246
  }
178
247
 
179
248
  /**
@@ -221,10 +290,10 @@ export interface PluginContext {
221
290
  dev: boolean;
222
291
  /** CSS build manifest (populated by adapter after client build, null in dev) */
223
292
  buildManifest: BuildManifest | null;
293
+ /** Per-build deployment ID for version skew detection (null in dev) */
294
+ deploymentId: string | null;
224
295
  /** Startup timer for profiling cold start phases (active in dev, no-op in prod) */
225
296
  timer: StartupTimer;
226
- /** URL path to font CSS file, set by timber-fonts when fonts are registered */
227
- fontCssUrl?: string;
228
297
  }
229
298
 
230
299
  /**
@@ -258,7 +327,10 @@ export function resolveAppDir(root: string, configAppDir?: string): string {
258
327
 
259
328
  function createPluginContext(config?: TimberUserConfig, root?: string): PluginContext {
260
329
  const projectRoot = root ?? process.cwd();
261
- const resolvedConfig: TimberUserConfig = { output: 'server', ...config };
330
+ // Don't apply defaults here they would override file-based config
331
+ // during mergeFileConfig (inline spreads over file). Defaults are
332
+ // applied after merge in timber(). See TIM-451.
333
+ const resolvedConfig: TimberUserConfig = { ...config };
262
334
  // Timer starts as active — swapped to noop in configResolved for production builds
263
335
  return {
264
336
  config: resolvedConfig,
@@ -268,6 +340,7 @@ function createPluginContext(config?: TimberUserConfig, root?: string): PluginCo
268
340
  root: projectRoot,
269
341
  dev: false,
270
342
  buildManifest: null,
343
+ deploymentId: null,
271
344
  timer: createStartupTimer(),
272
345
  };
273
346
  }
@@ -275,14 +348,18 @@ function createPluginContext(config?: TimberUserConfig, root?: string): PluginCo
275
348
  /**
276
349
  * Load timber.config.ts (or .js, .mjs) from the project root.
277
350
  * Returns the config object or null if no config file is found.
351
+ *
352
+ * Uses require() which works for ESM modules on Node 22.12+.
353
+ * This keeps timber() synchronous — no async config loading needed.
278
354
  */
279
- async function loadTimberConfigFile(root: string): Promise<TimberUserConfig | null> {
355
+ export function loadTimberConfigFile(root: string): TimberUserConfig | null {
280
356
  const configNames = ['timber.config.ts', 'timber.config.js', 'timber.config.mjs'];
357
+ const req = createRequire(join(root, 'package.json'));
281
358
 
282
359
  for (const name of configNames) {
283
360
  const configPath = join(root, name);
284
361
  if (existsSync(configPath)) {
285
- const mod = await import(pathToFileURL(configPath).href);
362
+ const mod = req(configPath);
286
363
  return (mod.default ?? mod) as TimberUserConfig;
287
364
  }
288
365
  }
@@ -302,7 +379,6 @@ export function warnConfigConflicts(
302
379
  ): string[] {
303
380
  const conflicts: string[] = [];
304
381
  for (const key of Object.keys(fileConfig) as (keyof TimberUserConfig)[]) {
305
- if (key === 'output') continue;
306
382
  if (key in inline && inline[key] !== undefined) {
307
383
  conflicts.push(key);
308
384
  }
@@ -341,30 +417,181 @@ function mergeFileConfig(ctx: PluginContext, fileConfig: TimberUserConfig): void
341
417
  };
342
418
  }
343
419
 
344
- function timberCache(_ctx: PluginContext): Plugin {
345
- return cacheTransformPlugin();
420
+ /**
421
+ * Resolve the React Compiler plugin via @rolldown/plugin-babel.
422
+ *
423
+ * Uses the `reactCompilerPreset` from @vitejs/plugin-react, which:
424
+ * - Uses Babel ONLY for the compiler pass (OXC handles JSX)
425
+ * - Automatically scopes to client environment via applyToEnvironmentHook
426
+ * - Uses react/compiler-runtime built into React 19
427
+ *
428
+ * @rolldown/plugin-babel and babel-plugin-react-compiler are optional peer deps.
429
+ * If either is missing, require() fails with a clear error message.
430
+ */
431
+ function resolveReactCompilerPlugin(
432
+ config: true | { compilationMode?: string; target?: string },
433
+ req: NodeRequire
434
+ ): PluginOption {
435
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
436
+ let babel: any;
437
+ try {
438
+ babel = req('@rolldown/plugin-babel');
439
+ } catch {
440
+ throw new Error(
441
+ '[timber] reactCompiler requires @rolldown/plugin-babel. ' +
442
+ 'Install it: pnpm add -D @rolldown/plugin-babel babel-plugin-react-compiler'
443
+ );
444
+ }
445
+ const options = typeof config === 'object' ? config : {};
446
+ const babelPlugin = babel.default ?? babel;
447
+ return babelPlugin({
448
+ presets: [reactCompilerPreset(options as Parameters<typeof reactCompilerPreset>[0])],
449
+ }) as PluginOption;
450
+ }
451
+
452
+ /**
453
+ * Build the options object for @vitejs/plugin-rsc.
454
+ *
455
+ * Uses a getter for `enableActionEncryption` so the RSC plugin reads
456
+ * the value lazily — after ctx.dev is set in configResolved. This lets
457
+ * `actionEncryption.disableInDev` work correctly even though the RSC
458
+ * plugin is created before Vite resolves the command.
459
+ */
460
+ function createRscOptions(
461
+ ctx: PluginContext,
462
+ encryptionKeyExpr: string | undefined
463
+ ): Record<string, unknown> {
464
+ const options: Record<string, unknown> = {
465
+ serverHandler: false,
466
+ customClientEntry: true,
467
+ entries: {
468
+ rsc: 'virtual:timber-rsc-entry',
469
+ ssr: 'virtual:timber-ssr-entry',
470
+ client: 'virtual:timber-browser-entry',
471
+ },
472
+ // Group client references by layout boundary to balance route-scoped code
473
+ // splitting with HTTP request count. A constant group name ('client-refs')
474
+ // would collapse all routes into one chunk — any page downloads every
475
+ // client component. Per-serverChunk grouping creates many sub-500B files.
476
+ // Layout-boundary grouping is the middle ground: components under the same
477
+ // layout segment share a chunk. See design/27-chunking-strategy.md, TIM-440, TIM-499.
478
+ clientChunks: (meta: { id: string; normalizedId: string; serverChunk: string }) =>
479
+ clientChunkGroup(meta, ctx.appDir),
480
+ };
481
+
482
+ // Bound args encryption — AES-256-GCM authenticated encryption for
483
+ // closure variables in 'use server' functions. Always on in production,
484
+ // configurable in dev. See design/08-forms-and-actions.md §"Bound Args Encryption".
485
+ //
486
+ // Uses a getter so the RSC plugin reads the value lazily in its transform
487
+ // hooks, after ctx.dev is set in configResolved. This lets disableInDev
488
+ // work correctly — ctx.dev is false at construction time but true during
489
+ // dev server transforms.
490
+ Object.defineProperty(options, 'enableActionEncryption', {
491
+ get() {
492
+ return shouldEnableEncryption(ctx.dev, ctx.config.actionEncryption);
493
+ },
494
+ enumerable: true,
495
+ });
496
+
497
+ // When TIMBER_ACTIONS_ENCRYPTION_KEY is set, pass it as a runtime expression
498
+ // so the RSC plugin uses it instead of auto-generating a per-build key.
499
+ if (encryptionKeyExpr) {
500
+ options.defineEncryptionKey = encryptionKeyExpr;
501
+ }
502
+
503
+ return options;
346
504
  }
347
505
 
506
+ // NOTE: 'use cache' directive transform removed — future feature pending design doc.
507
+ // The timber.cache() API (createCache) remains available for explicit caching.
508
+ // See design/06-caching.md.
509
+
510
+ /**
511
+ * Create the timber Vite plugin array.
512
+ *
513
+ * Loads timber.config.ts and all dependencies synchronously before
514
+ * constructing the plugin array. This ensures ALL plugins — including
515
+ * the RSC plugin and React Compiler — see the fully merged config
516
+ * (inline + file-based). No async, no deferred config, no stale reads.
517
+ *
518
+ * Requires Node >= 22.12 for synchronous require() of ESM modules
519
+ * (@vitejs/plugin-rsc is ESM-only).
520
+ *
521
+ * Previous versions used async loading and deferred config merging,
522
+ * causing file-based config for reactCompiler, actionEncryption, and
523
+ * output mode to be silently ignored. See TIM-451.
524
+ */
348
525
  export function timber(config?: TimberUserConfig): PluginOption[] {
349
526
  const ctx = createPluginContext(config);
350
- // Sync ctx.root and ctx.appDir with Vite's resolved root, which may
351
- // differ from process.cwd() when --config points to a subdirectory.
352
- // Also loads timber.config.ts and merges it into ctx.config (inline config wins).
527
+
528
+ // Resolve dependencies from the consumer's project (process.cwd()),
529
+ // not from timber's own node_modules. This is critical for pnpm link:
530
+ // when linked, timber's node_modules has a separate vite instance, and
531
+ // the RSC plugin must use the same vite instance as the dev server.
532
+ const consumerRequire = createRequire(join(process.cwd(), 'package.json'));
533
+
534
+ // ── Step 1: Load @vitejs/plugin-rsc ─────────────────────────────────
535
+ // Synchronous require() works for ESM modules on Node 22.12+.
536
+ ctx.timer.start('rsc-plugin-import');
537
+ const rscMod = consumerRequire('@vitejs/plugin-rsc');
538
+ const vitePluginRsc = rscMod.default ?? rscMod;
539
+ ctx.timer.end('rsc-plugin-import');
540
+
541
+ // ── Step 2: Compute config-dependent options ────────────────────────
542
+ // encryptionKeyExpr is env-based and doesn't depend on file config.
543
+ const encryptionKeyExpr = resolveEncryptionKeyExpression();
544
+
545
+ // ── Step 3: Pre-load file config for plugin resolution ──────────────
546
+ // Load timber.config.ts eagerly from process.cwd() so we can resolve
547
+ // plugins (like React Compiler) and add them to the top-level array.
548
+ // Vite's config() hook return type is Omit<UserConfig, 'plugins'> —
549
+ // plugins returned from config() are silently ignored. See TIM-632.
550
+ //
551
+ // The config() hook still loads from the correct Vite root (which may
552
+ // differ from cwd in monorepo setups — see TIM-498), but only for
553
+ // non-plugin config merging.
554
+ const earlyFileConfig = loadTimberConfigFile(process.cwd());
555
+
556
+ // ── Step 4: Build rootSync plugin ───────────────────────────────────
557
+ // rootSync loads timber.config.ts from Vite's resolved root and merges
558
+ // it into ctx.config. Plugin resolution is handled eagerly above — the
559
+ // config() hook must NOT return a `plugins` field (Vite ignores it).
353
560
  const rootSync: Plugin = {
354
561
  name: 'timber-root-sync',
355
- async config(userConfig, { command }) {
356
- // Load timber.config.ts early before configResolved/buildStart — so
357
- // all plugins (including timber-mdx) see the merged config in their
358
- // buildStart hooks. The config hook runs once and supports async.
359
- const root = userConfig.root ?? process.cwd();
562
+ config(userConfig, { command }) {
563
+ // ── Load timber.config.ts from the correct root ───────────────
564
+ // Vite's `config` hook fires before `configResolved`. The user's
565
+ // `root` option (if set) tells us where the project lives.
566
+ // `resolve()` mirrors Vite's own root resolution logic.
567
+ const viteRoot = resolve(userConfig.root ?? process.cwd());
360
568
  ctx.timer.start('config-load');
361
- const fileConfig = await loadTimberConfigFile(root);
569
+ const fileConfig = loadTimberConfigFile(viteRoot);
362
570
  if (fileConfig) {
363
571
  mergeFileConfig(ctx, fileConfig);
364
572
  ctx.clientJavascript = resolveClientJavascript(ctx.config);
365
573
  }
574
+ // Apply defaults AFTER merge so file-based config isn't overridden
575
+ // by defaults that were baked into the inline config object.
576
+ ctx.config.output ??= 'server';
366
577
  ctx.timer.end('config-load');
367
578
 
579
+ // Warn if the Vite root differs from cwd and the re-loaded config
580
+ // has reactCompiler but the early cwd-based load missed it. In this
581
+ // edge case the user must move reactCompiler to inline config.
582
+ if (viteRoot !== process.cwd()) {
583
+ const hasCompilerInReloaded = !config?.reactCompiler && ctx.config.reactCompiler;
584
+ const hadCompilerInEarly = !config?.reactCompiler && earlyFileConfig?.reactCompiler;
585
+ if (hasCompilerInReloaded && !hadCompilerInEarly) {
586
+ console.warn(
587
+ '[timber] reactCompiler is set in timber.config.ts but could not be ' +
588
+ 'registered because the config file is in a non-cwd root directory. ' +
589
+ 'Move reactCompiler to the inline timber() config in vite.config.ts, or ' +
590
+ 'run vite from the project root directory.'
591
+ );
592
+ }
593
+ }
594
+
368
595
  // Force production JSX transform for builds.
369
596
  //
370
597
  // Vite determines dev vs prod JSX via `isProduction`, which checks
@@ -401,17 +628,28 @@ export function timber(config?: TimberUserConfig): PluginOption[] {
401
628
  }
402
629
  },
403
630
  };
631
+
632
+ // ── Step 5: Resolve optional plugins ────────────────────────────────
633
+ // React Compiler — resolved eagerly from either inline or file config.
634
+ // Vite's config() hook return type is Omit<UserConfig, 'plugins'>, so
635
+ // plugins MUST be in the top-level array — returning them from config()
636
+ // silently drops them. See TIM-632.
637
+ //
638
+ // Inline config takes precedence. File config (from the early cwd-based
639
+ // load) is used when inline config doesn't set reactCompiler.
640
+ const reactCompilerPlugins: PluginOption[] = [];
641
+ const effectiveReactCompiler = config?.reactCompiler ?? earlyFileConfig?.reactCompiler;
642
+ if (effectiveReactCompiler) {
643
+ reactCompilerPlugins.push(resolveReactCompilerPlugin(effectiveReactCompiler, consumerRequire));
644
+ }
645
+
646
+ // ── Step 6: Assemble plugin array ─────────────────────────────────────
404
647
  // @vitejs/plugin-rsc handles:
405
648
  // - RSC/SSR/client environment setup
406
649
  // - "use client" directive → client reference proxy transformation
407
650
  // - "use server" directive → server reference transformation
408
651
  // - Client reference tracking and module map generation
409
652
  //
410
- // Loaded via dynamic import() because @vitejs/plugin-rsc is ESM-only.
411
- // Vite's config loader uses esbuild to transpile to CJS, which breaks
412
- // static imports of ESM-only packages. The dynamic import() is preserved
413
- // by esbuild and runs natively in ESM at runtime.
414
- //
415
653
  // serverHandler: false — timber has its own dev server (timber-dev-server)
416
654
  // entries — tells the RSC plugin about timber's virtual entry modules so
417
655
  // it correctly wires up the browser entry (needed for React Fast Refresh
@@ -424,30 +662,6 @@ export function timber(config?: TimberUserConfig): PluginOption[] {
424
662
  // We do NOT set customBuildApp — the RSC plugin's orchestration is correct
425
663
  // and handles bundle ordering, asset manifest generation, and environment
426
664
  // imports manifest. See @vitejs/plugin-rsc's buildApp implementation.
427
- // Resolve @vitejs/plugin-rsc from the consumer's project (process.cwd()),
428
- // not from timber's own node_modules. This is critical for pnpm link:
429
- // when linked, timber's node_modules has a separate vite instance, and
430
- // the RSC plugin must use the same vite instance as the dev server.
431
- const consumerRequire = createRequire(join(process.cwd(), 'package.json'));
432
- const rscPluginPath = consumerRequire.resolve('@vitejs/plugin-rsc');
433
- ctx.timer.start('rsc-plugin-import');
434
- const rscPluginsPromise = import(pathToFileURL(rscPluginPath).href).then(
435
- ({ default: vitePluginRsc }) => {
436
- ctx.timer.end('rsc-plugin-import');
437
- return vitePluginRsc({
438
- serverHandler: false,
439
- customClientEntry: true,
440
- entries: {
441
- rsc: 'virtual:timber-rsc-entry',
442
- ssr: 'virtual:timber-ssr-entry',
443
- client: 'virtual:timber-browser-entry',
444
- },
445
- // No custom clientChunks — Rolldown handles natural code splitting.
446
- // See design/27-chunking-strategy.md and LOCAL-337.
447
- });
448
- }
449
- );
450
-
451
665
  return [
452
666
  rootSync,
453
667
  timberReactProd(),
@@ -456,15 +670,14 @@ export function timber(config?: TimberUserConfig): PluginOption[] {
456
670
  // following Vinext's convention — the RSC plugin's virtual browser entry
457
671
  // coordinates with plugin-react via __vite_plugin_react_preamble_installed__.
458
672
  react(),
673
+ ...reactCompilerPlugins,
459
674
  timberServerActionExports(),
460
- rscPluginsPromise,
675
+ vitePluginRsc(createRscOptions(ctx, encryptionKeyExpr)),
461
676
  timberShims(ctx),
462
677
  timberRouting(ctx),
463
678
  timberEntries(ctx),
464
679
  timberBuildManifest(ctx),
465
- timberCache(ctx),
466
680
  timberStaticBuild(ctx),
467
- timberDynamicTransform(ctx),
468
681
  timberFonts(ctx),
469
682
  timberMdx(ctx),
470
683
  timberContent(ctx),
@@ -473,6 +686,7 @@ export function timber(config?: TimberUserConfig): PluginOption[] {
473
686
  timberBuildReport(ctx), // Post-build: route table with bundle sizes
474
687
  timberAdapterBuild(ctx), // Post-build: invoke adapter.buildOutput()
475
688
  timberDevLogs(ctx), // Dev-only: forward server console.* to browser console
689
+ timberDevBrowserLogs(ctx), // Dev-only: forward browser console.* to server terminal
476
690
  timberDevServer(ctx), // Must be last — configureServer post-hook runs after all watchers
477
691
  ];
478
692
  }
@@ -481,7 +695,7 @@ export function timber(config?: TimberUserConfig): PluginOption[] {
481
695
  * Route map interface — augmented by the generated timber-routes.d.ts.
482
696
  *
483
697
  * Each key is a route path pattern. Values have:
484
- * params: shape of URL params (e.g. { id: string })
698
+ * segmentParams: shape of URL segment params (e.g. { id: string })
485
699
  * searchParams: parsed type from search-params.ts, or {} if none
486
700
  *
487
701
  * This interface is empty by default and populated via codegen.
@@ -490,4 +704,26 @@ export function timber(config?: TimberUserConfig): PluginOption[] {
490
704
  // eslint-disable-next-line @typescript-eslint/no-empty-object-type
491
705
  export interface Routes {}
492
706
 
707
+ /**
708
+ * Type-safe helper for timber.config.ts files.
709
+ *
710
+ * A pass-through identity function that provides autocomplete and
711
+ * type checking for timber configuration. No runtime validation —
712
+ * purely a DX convenience (same pattern as Vite's defineConfig).
713
+ *
714
+ * @example
715
+ * ```ts
716
+ * // timber.config.ts
717
+ * import { defineConfig } from '@timber-js/app';
718
+ *
719
+ * export default defineConfig({
720
+ * output: 'server',
721
+ * pageExtensions: ['tsx', 'ts', 'mdx'],
722
+ * });
723
+ * ```
724
+ */
725
+ export function defineConfig(config: TimberUserConfig): TimberUserConfig {
726
+ return config;
727
+ }
728
+
493
729
  export default timber;
@@ -16,8 +16,8 @@
16
16
  import type { Plugin } from 'vite';
17
17
  import { join } from 'node:path';
18
18
  import { readFile, writeFile } from 'node:fs/promises';
19
- import type { PluginContext } from '#/index.js';
20
- import type { TimberPlatformAdapter, TimberConfig } from '#/adapters/types.js';
19
+ import type { PluginContext } from '../index.js';
20
+ import type { TimberPlatformAdapter, TimberConfig } from '../adapters/types.js';
21
21
 
22
22
  export function timberAdapterBuild(ctx: PluginContext): Plugin {
23
23
  return {
@@ -50,6 +50,12 @@ export function timberAdapterBuild(ctx: PluginContext): Plugin {
50
50
  : ctx.buildManifest;
51
51
  const json = JSON.stringify(manifest);
52
52
  manifestInit = `globalThis.__TIMBER_BUILD_MANIFEST__ = ${json};\n`;
53
+
54
+ // Embed the deployment ID for version skew detection (TIM-446).
55
+ // The server reads this at startup via setDeploymentId().
56
+ if (ctx.deploymentId) {
57
+ manifestInit += `globalThis.__TIMBER_DEPLOYMENT_ID__ = ${JSON.stringify(ctx.deploymentId)};\n`;
58
+ }
53
59
  }
54
60
 
55
61
  // Strip JS from the RSC plugin's assets manifest when client JS
@@ -16,9 +16,10 @@
16
16
  * Design docs: 18-build-system.md §"Build Manifest", 02-rendering-pipeline.md §"Early Hints"
17
17
  */
18
18
 
19
+ import { randomUUID } from 'node:crypto';
19
20
  import type { Plugin, ResolvedConfig } from 'vite';
20
- import type { PluginContext } from '#/index.js';
21
- import type { BuildManifest } from '#/server/build-manifest.js';
21
+ import type { PluginContext } from '../index.js';
22
+ import type { BuildManifest } from '../server/build-manifest.js';
22
23
 
23
24
  // Rollup types used by generateBundle hook — imported from vite which re-exports them.
24
25
  // We define minimal interfaces here to avoid a direct 'rollup' dependency.
@@ -242,6 +243,16 @@ export function timberBuildManifest(ctx: PluginContext): Plugin {
242
243
  configResolved(config: ResolvedConfig) {
243
244
  resolvedBase = config.base;
244
245
  isDev = config.command === 'serve';
246
+
247
+ // Generate a per-build deployment ID early so virtual:timber-config
248
+ // can serialize it during the load hook (which runs before generateBundle).
249
+ // A random UUID is used instead of a content hash — determinism provides
250
+ // no real benefit here since you almost never redeploy identical code,
251
+ // and a random ID avoids the timing problem where the content hash was
252
+ // only available after generateBundle (TIM-452).
253
+ if (!isDev && !ctx.deploymentId) {
254
+ ctx.deploymentId = randomUUID().replace(/-/g, '').slice(0, 16);
255
+ }
245
256
  },
246
257
 
247
258
  resolveId(id: string) {
@@ -15,9 +15,9 @@
15
15
 
16
16
  import { gzipSync } from 'node:zlib';
17
17
  import type { Plugin, Logger } from 'vite';
18
- import type { PluginContext } from '#/index.js';
19
- import type { SegmentNode, RouteTree } from '#/routing/types.js';
20
- import { formatSize } from '#/utils/format.js';
18
+ import type { PluginContext } from '../index.js';
19
+ import type { SegmentNode, RouteTree } from '../routing/types.js';
20
+ import { formatSize } from '../utils/format.js';
21
21
 
22
22
  // ─── Public types ─────────────────────────────────────────────────────────
23
23