@timber-js/app 0.2.0-alpha.8 → 0.2.0-alpha.81

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 (571) hide show
  1. package/LICENSE +8 -0
  2. package/dist/_chunks/actions-Dg-ANYHb.js +421 -0
  3. package/dist/_chunks/actions-Dg-ANYHb.js.map +1 -0
  4. package/dist/_chunks/{als-registry-B7DbZ2hS.js → als-registry-HS0LGUl2.js} +1 -1
  5. package/dist/_chunks/als-registry-HS0LGUl2.js.map +1 -0
  6. package/dist/_chunks/chunk-DYhsFzuS.js +33 -0
  7. package/dist/_chunks/{debug-gwlJkDuf.js → debug-ECi_61pb.js} +2 -2
  8. package/dist/_chunks/debug-ECi_61pb.js.map +1 -0
  9. package/dist/_chunks/define-C77ScO0m.js +106 -0
  10. package/dist/_chunks/define-C77ScO0m.js.map +1 -0
  11. package/dist/_chunks/define-CZqDwhSu.js +199 -0
  12. package/dist/_chunks/define-CZqDwhSu.js.map +1 -0
  13. package/dist/_chunks/define-cookie-C2IkoFGN.js +94 -0
  14. package/dist/_chunks/define-cookie-C2IkoFGN.js.map +1 -0
  15. package/dist/_chunks/{format-DviM89f0.js → dev-warnings-DpGRGoDi.js} +5 -44
  16. package/dist/_chunks/dev-warnings-DpGRGoDi.js.map +1 -0
  17. package/dist/_chunks/format-CYBGxKtc.js +14 -0
  18. package/dist/_chunks/format-CYBGxKtc.js.map +1 -0
  19. package/dist/_chunks/{interception-BOoWmLUA.js → interception-Dpn_UfAD.js} +171 -97
  20. package/dist/_chunks/interception-Dpn_UfAD.js.map +1 -0
  21. package/dist/_chunks/merge-search-params-Cm_KIWDX.js +41 -0
  22. package/dist/_chunks/merge-search-params-Cm_KIWDX.js.map +1 -0
  23. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js → metadata-routes-DS3eKNmf.js} +1 -1
  24. package/dist/_chunks/{metadata-routes-Cjmvi3rQ.js.map → metadata-routes-DS3eKNmf.js.map} +1 -1
  25. package/dist/_chunks/request-context-qMsWgy9C.js +478 -0
  26. package/dist/_chunks/request-context-qMsWgy9C.js.map +1 -0
  27. package/dist/_chunks/schema-bridge-C3xl_vfb.js +86 -0
  28. package/dist/_chunks/schema-bridge-C3xl_vfb.js.map +1 -0
  29. package/dist/_chunks/segment-classify-BDNn6EzD.js +65 -0
  30. package/dist/_chunks/segment-classify-BDNn6EzD.js.map +1 -0
  31. package/dist/_chunks/segment-context-fHFLF1PE.js +34 -0
  32. package/dist/_chunks/segment-context-fHFLF1PE.js.map +1 -0
  33. package/dist/_chunks/{ssr-data-MjmprTmO.js → ssr-data-DzuI0bIV.js} +1 -1
  34. package/dist/_chunks/{ssr-data-MjmprTmO.js.map → ssr-data-DzuI0bIV.js.map} +1 -1
  35. package/dist/_chunks/stale-reload-BX5gL1r-.js +64 -0
  36. package/dist/_chunks/stale-reload-BX5gL1r-.js.map +1 -0
  37. package/dist/_chunks/{tracing-CemImE6h.js → tracing-CCYbKn5n.js} +60 -9
  38. package/dist/_chunks/tracing-CCYbKn5n.js.map +1 -0
  39. package/dist/_chunks/use-params-Br9YSUFV.js +295 -0
  40. package/dist/_chunks/use-params-Br9YSUFV.js.map +1 -0
  41. package/dist/_chunks/{use-query-states-D5KaffOK.js → use-query-states-Lo_s_pw2.js} +4 -4
  42. package/dist/_chunks/use-query-states-Lo_s_pw2.js.map +1 -0
  43. package/dist/adapters/cloudflare-dev.d.ts +109 -0
  44. package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
  45. package/dist/adapters/cloudflare-dev.js +73 -0
  46. package/dist/adapters/cloudflare-dev.js.map +1 -0
  47. package/dist/adapters/cloudflare-kv-cache.d.ts +64 -0
  48. package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
  49. package/dist/adapters/cloudflare-kv-cache.js +95 -0
  50. package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
  51. package/dist/adapters/cloudflare.d.ts +148 -12
  52. package/dist/adapters/cloudflare.d.ts.map +1 -1
  53. package/dist/adapters/cloudflare.js +135 -11
  54. package/dist/adapters/cloudflare.js.map +1 -1
  55. package/dist/adapters/compress-module.d.ts.map +1 -1
  56. package/dist/adapters/nitro.d.ts +17 -1
  57. package/dist/adapters/nitro.d.ts.map +1 -1
  58. package/dist/adapters/nitro.js +56 -13
  59. package/dist/adapters/nitro.js.map +1 -1
  60. package/dist/cache/cache-api.d.ts +24 -0
  61. package/dist/cache/cache-api.d.ts.map +1 -0
  62. package/dist/cache/handler-store.d.ts +31 -0
  63. package/dist/cache/handler-store.d.ts.map +1 -0
  64. package/dist/cache/index.d.ts +23 -7
  65. package/dist/cache/index.d.ts.map +1 -1
  66. package/dist/cache/index.js +142 -80
  67. package/dist/cache/index.js.map +1 -1
  68. package/dist/cache/singleflight.d.ts +18 -1
  69. package/dist/cache/singleflight.d.ts.map +1 -1
  70. package/dist/cache/sizeof.d.ts +22 -0
  71. package/dist/cache/sizeof.d.ts.map +1 -0
  72. package/dist/cache/timber-cache.d.ts +1 -1
  73. package/dist/cache/timber-cache.d.ts.map +1 -1
  74. package/dist/cli.d.ts +6 -1
  75. package/dist/cli.d.ts.map +1 -1
  76. package/dist/cli.js +8 -3
  77. package/dist/cli.js.map +1 -1
  78. package/dist/client/browser-dev.d.ts +27 -1
  79. package/dist/client/browser-dev.d.ts.map +1 -1
  80. package/dist/client/browser-entry/action-dispatch.d.ts +17 -0
  81. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -0
  82. package/dist/client/browser-entry/hmr.d.ts +21 -0
  83. package/dist/client/browser-entry/hmr.d.ts.map +1 -0
  84. package/dist/client/browser-entry/hydrate.d.ts +46 -0
  85. package/dist/client/browser-entry/hydrate.d.ts.map +1 -0
  86. package/dist/client/browser-entry/index.d.ts +30 -0
  87. package/dist/client/browser-entry/index.d.ts.map +1 -0
  88. package/dist/client/browser-entry/post-hydration.d.ts +26 -0
  89. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
  90. package/dist/client/browser-entry/router-init.d.ts +23 -0
  91. package/dist/client/browser-entry/router-init.d.ts.map +1 -0
  92. package/dist/client/browser-entry/rsc-stream.d.ts +24 -0
  93. package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -0
  94. package/dist/client/browser-entry/scroll.d.ts +19 -0
  95. package/dist/client/browser-entry/scroll.d.ts.map +1 -0
  96. package/dist/client/error-boundary.d.ts +12 -5
  97. package/dist/client/error-boundary.d.ts.map +1 -1
  98. package/dist/client/error-boundary.js +10 -4
  99. package/dist/client/error-boundary.js.map +1 -1
  100. package/dist/client/error-reconstituter.d.ts +54 -0
  101. package/dist/client/error-reconstituter.d.ts.map +1 -0
  102. package/dist/client/form.d.ts +3 -3
  103. package/dist/client/form.d.ts.map +1 -1
  104. package/dist/client/history.d.ts +19 -4
  105. package/dist/client/history.d.ts.map +1 -1
  106. package/dist/client/index.d.ts +7 -21
  107. package/dist/client/index.d.ts.map +1 -1
  108. package/dist/client/index.js +210 -1017
  109. package/dist/client/index.js.map +1 -1
  110. package/dist/client/internal.d.ts +18 -0
  111. package/dist/client/internal.d.ts.map +1 -0
  112. package/dist/client/internal.js +890 -0
  113. package/dist/client/internal.js.map +1 -0
  114. package/dist/client/link-pending-store.d.ts +63 -0
  115. package/dist/client/link-pending-store.d.ts.map +1 -0
  116. package/dist/client/link.d.ts +90 -32
  117. package/dist/client/link.d.ts.map +1 -1
  118. package/dist/client/nav-link-store.d.ts +36 -0
  119. package/dist/client/nav-link-store.d.ts.map +1 -0
  120. package/dist/client/navigation-api-types.d.ts +90 -0
  121. package/dist/client/navigation-api-types.d.ts.map +1 -0
  122. package/dist/client/navigation-api.d.ts +115 -0
  123. package/dist/client/navigation-api.d.ts.map +1 -0
  124. package/dist/client/navigation-context.d.ts +13 -2
  125. package/dist/client/navigation-context.d.ts.map +1 -1
  126. package/dist/client/{transition-root.d.ts → navigation-root.d.ts} +42 -8
  127. package/dist/client/navigation-root.d.ts.map +1 -0
  128. package/dist/client/nuqs-adapter.d.ts.map +1 -1
  129. package/dist/client/router-ref.d.ts +1 -1
  130. package/dist/client/router.d.ts +70 -4
  131. package/dist/client/router.d.ts.map +1 -1
  132. package/dist/client/rsc-fetch.d.ts +38 -3
  133. package/dist/client/rsc-fetch.d.ts.map +1 -1
  134. package/dist/client/segment-cache.d.ts +1 -1
  135. package/dist/client/segment-cache.d.ts.map +1 -1
  136. package/dist/client/segment-outlet.d.ts +63 -0
  137. package/dist/client/segment-outlet.d.ts.map +1 -0
  138. package/dist/client/ssr-data.d.ts +13 -4
  139. package/dist/client/ssr-data.d.ts.map +1 -1
  140. package/dist/client/stale-reload.d.ts +15 -0
  141. package/dist/client/stale-reload.d.ts.map +1 -1
  142. package/dist/client/top-loader.d.ts +5 -5
  143. package/dist/client/top-loader.d.ts.map +1 -1
  144. package/dist/client/use-link-status.d.ts +5 -5
  145. package/dist/client/use-link-status.d.ts.map +1 -1
  146. package/dist/client/use-params.d.ts +6 -4
  147. package/dist/client/use-params.d.ts.map +1 -1
  148. package/dist/client/{use-navigation-pending.d.ts → use-pending-navigation.d.ts} +4 -4
  149. package/dist/client/use-pending-navigation.d.ts.map +1 -0
  150. package/dist/client/use-query-states.d.ts +1 -1
  151. package/dist/client/use-query-states.d.ts.map +1 -1
  152. package/dist/client/use-router.d.ts +1 -1
  153. package/dist/codec.d.ts +33 -0
  154. package/dist/codec.d.ts.map +1 -0
  155. package/dist/codec.js +2 -0
  156. package/dist/config-types.d.ts +227 -0
  157. package/dist/config-types.d.ts.map +1 -0
  158. package/dist/content/index.d.ts +1 -10
  159. package/dist/content/index.d.ts.map +1 -1
  160. package/dist/content/index.js +0 -2
  161. package/dist/cookies/define-cookie.d.ts +35 -14
  162. package/dist/cookies/define-cookie.d.ts.map +1 -1
  163. package/dist/cookies/index.js +1 -83
  164. package/dist/fonts/css.d.ts +1 -0
  165. package/dist/fonts/css.d.ts.map +1 -1
  166. package/dist/index.d.ts +45 -192
  167. package/dist/index.d.ts.map +1 -1
  168. package/dist/index.js +12357 -11925
  169. package/dist/index.js.map +1 -1
  170. package/dist/plugin-context.d.ts +107 -0
  171. package/dist/plugin-context.d.ts.map +1 -0
  172. package/dist/plugins/adapter-build.d.ts +1 -1
  173. package/dist/plugins/adapter-build.d.ts.map +1 -1
  174. package/dist/plugins/build-manifest.d.ts +2 -2
  175. package/dist/plugins/build-manifest.d.ts.map +1 -1
  176. package/dist/plugins/build-report.d.ts +3 -3
  177. package/dist/plugins/build-report.d.ts.map +1 -1
  178. package/dist/plugins/client-chunks.d.ts +32 -0
  179. package/dist/plugins/client-chunks.d.ts.map +1 -0
  180. package/dist/plugins/content.d.ts +1 -1
  181. package/dist/plugins/content.d.ts.map +1 -1
  182. package/dist/plugins/dev-browser-logs.d.ts +84 -0
  183. package/dist/plugins/dev-browser-logs.d.ts.map +1 -0
  184. package/dist/plugins/dev-error-overlay.d.ts +26 -1
  185. package/dist/plugins/dev-error-overlay.d.ts.map +1 -1
  186. package/dist/plugins/dev-logs.d.ts +1 -1
  187. package/dist/plugins/dev-logs.d.ts.map +1 -1
  188. package/dist/plugins/dev-server.d.ts +1 -1
  189. package/dist/plugins/dev-server.d.ts.map +1 -1
  190. package/dist/plugins/entries.d.ts +1 -1
  191. package/dist/plugins/entries.d.ts.map +1 -1
  192. package/dist/plugins/fonts.d.ts +19 -5
  193. package/dist/plugins/fonts.d.ts.map +1 -1
  194. package/dist/plugins/mdx.d.ts +1 -1
  195. package/dist/plugins/mdx.d.ts.map +1 -1
  196. package/dist/plugins/routing.d.ts +1 -1
  197. package/dist/plugins/routing.d.ts.map +1 -1
  198. package/dist/plugins/server-bundle.d.ts.map +1 -1
  199. package/dist/plugins/shims.d.ts +6 -5
  200. package/dist/plugins/shims.d.ts.map +1 -1
  201. package/dist/plugins/static-build.d.ts +4 -4
  202. package/dist/plugins/static-build.d.ts.map +1 -1
  203. package/dist/routing/codegen.d.ts +2 -2
  204. package/dist/routing/codegen.d.ts.map +1 -1
  205. package/dist/routing/index.d.ts +2 -0
  206. package/dist/routing/index.d.ts.map +1 -1
  207. package/dist/routing/index.js +3 -2
  208. package/dist/routing/scanner.d.ts.map +1 -1
  209. package/dist/routing/segment-classify.d.ts +46 -0
  210. package/dist/routing/segment-classify.d.ts.map +1 -0
  211. package/dist/routing/status-file-lint.d.ts +2 -1
  212. package/dist/routing/status-file-lint.d.ts.map +1 -1
  213. package/dist/routing/types.d.ts +16 -4
  214. package/dist/routing/types.d.ts.map +1 -1
  215. package/dist/rsc-runtime/rsc.d.ts +1 -1
  216. package/dist/rsc-runtime/rsc.d.ts.map +1 -1
  217. package/dist/rsc-runtime/ssr.d.ts +12 -0
  218. package/dist/rsc-runtime/ssr.d.ts.map +1 -1
  219. package/dist/schema-bridge.d.ts +76 -0
  220. package/dist/schema-bridge.d.ts.map +1 -0
  221. package/dist/search-params/define.d.ts +139 -0
  222. package/dist/search-params/define.d.ts.map +1 -0
  223. package/dist/search-params/index.d.ts +4 -7
  224. package/dist/search-params/index.d.ts.map +1 -1
  225. package/dist/search-params/index.js +32 -441
  226. package/dist/search-params/index.js.map +1 -1
  227. package/dist/search-params/registry.d.ts +2 -2
  228. package/dist/search-params/registry.d.ts.map +1 -1
  229. package/dist/search-params/wrappers.d.ts +53 -0
  230. package/dist/search-params/wrappers.d.ts.map +1 -0
  231. package/dist/segment-params/define.d.ts +78 -0
  232. package/dist/segment-params/define.d.ts.map +1 -0
  233. package/dist/segment-params/index.d.ts +3 -0
  234. package/dist/segment-params/index.d.ts.map +1 -0
  235. package/dist/segment-params/index.js +2 -0
  236. package/dist/server/access-gate.d.ts +4 -0
  237. package/dist/server/access-gate.d.ts.map +1 -1
  238. package/dist/server/action-client.d.ts +25 -6
  239. package/dist/server/action-client.d.ts.map +1 -1
  240. package/dist/server/action-encryption.d.ts +76 -0
  241. package/dist/server/action-encryption.d.ts.map +1 -0
  242. package/dist/server/action-handler.d.ts.map +1 -1
  243. package/dist/server/actions.d.ts +3 -6
  244. package/dist/server/actions.d.ts.map +1 -1
  245. package/dist/server/als-registry.d.ts +32 -4
  246. package/dist/server/als-registry.d.ts.map +1 -1
  247. package/dist/server/build-manifest.d.ts +2 -2
  248. package/dist/server/build-manifest.d.ts.map +1 -1
  249. package/dist/server/debug.d.ts +1 -1
  250. package/dist/server/default-logger.d.ts +22 -0
  251. package/dist/server/default-logger.d.ts.map +1 -0
  252. package/dist/server/deny-page-resolver.d.ts +52 -0
  253. package/dist/server/deny-page-resolver.d.ts.map +1 -0
  254. package/dist/server/deny-renderer.d.ts.map +1 -1
  255. package/dist/server/dev-holding-server.d.ts +52 -0
  256. package/dist/server/dev-holding-server.d.ts.map +1 -0
  257. package/dist/server/dev-warnings.d.ts +1 -21
  258. package/dist/server/dev-warnings.d.ts.map +1 -1
  259. package/dist/server/early-hints.d.ts +13 -5
  260. package/dist/server/early-hints.d.ts.map +1 -1
  261. package/dist/server/error-boundary-wrapper.d.ts +7 -1
  262. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  263. package/dist/server/fallback-error.d.ts +4 -3
  264. package/dist/server/fallback-error.d.ts.map +1 -1
  265. package/dist/server/flight-injection-state.d.ts +66 -0
  266. package/dist/server/flight-injection-state.d.ts.map +1 -0
  267. package/dist/server/flight-scripts.d.ts +42 -0
  268. package/dist/server/flight-scripts.d.ts.map +1 -0
  269. package/dist/server/flush.d.ts.map +1 -1
  270. package/dist/server/form-data.d.ts +29 -0
  271. package/dist/server/form-data.d.ts.map +1 -1
  272. package/dist/server/html-injectors.d.ts +51 -11
  273. package/dist/server/html-injectors.d.ts.map +1 -1
  274. package/dist/server/index.d.ts +5 -43
  275. package/dist/server/index.d.ts.map +1 -1
  276. package/dist/server/index.js +37 -2798
  277. package/dist/server/index.js.map +1 -1
  278. package/dist/server/internal.d.ts +46 -0
  279. package/dist/server/internal.d.ts.map +1 -0
  280. package/dist/server/internal.js +2883 -0
  281. package/dist/server/internal.js.map +1 -0
  282. package/dist/server/logger.d.ts +25 -7
  283. package/dist/server/logger.d.ts.map +1 -1
  284. package/dist/server/middleware-runner.d.ts +19 -4
  285. package/dist/server/middleware-runner.d.ts.map +1 -1
  286. package/dist/server/node-stream-transforms.d.ts +113 -0
  287. package/dist/server/node-stream-transforms.d.ts.map +1 -0
  288. package/dist/server/page-deny-boundary.d.ts +31 -0
  289. package/dist/server/page-deny-boundary.d.ts.map +1 -0
  290. package/dist/server/pipeline-interception.d.ts +1 -1
  291. package/dist/server/pipeline-interception.d.ts.map +1 -1
  292. package/dist/server/pipeline-metadata.d.ts +6 -0
  293. package/dist/server/pipeline-metadata.d.ts.map +1 -1
  294. package/dist/server/pipeline.d.ts +42 -10
  295. package/dist/server/pipeline.d.ts.map +1 -1
  296. package/dist/server/primitives.d.ts +69 -18
  297. package/dist/server/primitives.d.ts.map +1 -1
  298. package/dist/server/render-timeout.d.ts +51 -0
  299. package/dist/server/render-timeout.d.ts.map +1 -0
  300. package/dist/server/request-context.d.ts +112 -43
  301. package/dist/server/request-context.d.ts.map +1 -1
  302. package/dist/server/route-element-builder.d.ts +27 -1
  303. package/dist/server/route-element-builder.d.ts.map +1 -1
  304. package/dist/server/route-handler.d.ts.map +1 -1
  305. package/dist/server/route-matcher.d.ts +9 -2
  306. package/dist/server/route-matcher.d.ts.map +1 -1
  307. package/dist/server/rsc-entry/api-handler.d.ts +2 -2
  308. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  309. package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
  310. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  311. package/dist/server/rsc-entry/helpers.d.ts +48 -5
  312. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  313. package/dist/server/rsc-entry/index.d.ts +8 -3
  314. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  315. package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
  316. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  317. package/dist/server/rsc-entry/rsc-stream.d.ts +4 -1
  318. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  319. package/dist/server/rsc-entry/ssr-bridge.d.ts +1 -1
  320. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  321. package/dist/server/rsc-entry/ssr-renderer.d.ts +19 -4
  322. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  323. package/dist/server/safe-load.d.ts +46 -0
  324. package/dist/server/safe-load.d.ts.map +1 -0
  325. package/dist/server/sitemap-generator.d.ts +129 -0
  326. package/dist/server/sitemap-generator.d.ts.map +1 -0
  327. package/dist/server/sitemap-handler.d.ts +22 -0
  328. package/dist/server/sitemap-handler.d.ts.map +1 -0
  329. package/dist/server/slot-resolver.d.ts +1 -1
  330. package/dist/server/slot-resolver.d.ts.map +1 -1
  331. package/dist/server/ssr-entry.d.ts +22 -0
  332. package/dist/server/ssr-entry.d.ts.map +1 -1
  333. package/dist/server/ssr-render.d.ts +39 -21
  334. package/dist/server/ssr-render.d.ts.map +1 -1
  335. package/dist/server/ssr-wrappers.d.ts +50 -0
  336. package/dist/server/ssr-wrappers.d.ts.map +1 -0
  337. package/dist/server/status-code-resolver.d.ts +1 -1
  338. package/dist/server/status-code-resolver.d.ts.map +1 -1
  339. package/dist/server/stream-utils.d.ts +36 -0
  340. package/dist/server/stream-utils.d.ts.map +1 -0
  341. package/dist/server/tracing.d.ts +4 -4
  342. package/dist/server/tracing.d.ts.map +1 -1
  343. package/dist/server/tree-builder.d.ts +22 -19
  344. package/dist/server/tree-builder.d.ts.map +1 -1
  345. package/dist/server/types.d.ts +1 -4
  346. package/dist/server/types.d.ts.map +1 -1
  347. package/dist/server/version-skew.d.ts +61 -0
  348. package/dist/server/version-skew.d.ts.map +1 -0
  349. package/dist/shared/merge-search-params.d.ts +22 -0
  350. package/dist/shared/merge-search-params.d.ts.map +1 -0
  351. package/dist/shims/font-google.d.ts +1 -1
  352. package/dist/shims/font-google.d.ts.map +1 -1
  353. package/dist/shims/font-google.js +42 -0
  354. package/dist/shims/font-google.js.map +1 -0
  355. package/dist/shims/font-local.d.ts +26 -0
  356. package/dist/shims/font-local.d.ts.map +1 -0
  357. package/dist/shims/font-local.js +20 -0
  358. package/dist/shims/font-local.js.map +1 -0
  359. package/dist/shims/headers.d.ts +2 -1
  360. package/dist/shims/headers.d.ts.map +1 -1
  361. package/dist/shims/navigation-client.d.ts +1 -1
  362. package/dist/shims/navigation-client.d.ts.map +1 -1
  363. package/dist/shims/navigation.d.ts +3 -2
  364. package/dist/shims/navigation.d.ts.map +1 -1
  365. package/dist/utils/directive-parser.d.ts +5 -2
  366. package/dist/utils/directive-parser.d.ts.map +1 -1
  367. package/dist/utils/state-machine.d.ts +80 -0
  368. package/dist/utils/state-machine.d.ts.map +1 -0
  369. package/package.json +56 -22
  370. package/src/adapters/cloudflare-dev.ts +177 -0
  371. package/src/adapters/cloudflare-kv-cache.ts +142 -0
  372. package/src/adapters/cloudflare.ts +342 -28
  373. package/src/adapters/compress-module.ts +24 -4
  374. package/src/adapters/nitro.ts +52 -8
  375. package/src/adapters/wrangler.d.ts +7 -0
  376. package/src/cache/cache-api.ts +38 -0
  377. package/src/cache/handler-store.ts +68 -0
  378. package/src/cache/index.ts +81 -18
  379. package/src/cache/singleflight.ts +62 -4
  380. package/src/cache/sizeof.ts +31 -0
  381. package/src/cache/timber-cache.ts +24 -20
  382. package/src/cli.ts +16 -6
  383. package/src/client/browser-dev.ts +128 -1
  384. package/src/client/browser-entry/action-dispatch.ts +116 -0
  385. package/src/client/browser-entry/hmr.ts +81 -0
  386. package/src/client/browser-entry/hydrate.ts +145 -0
  387. package/src/client/browser-entry/index.ts +138 -0
  388. package/src/client/browser-entry/post-hydration.ts +119 -0
  389. package/src/client/browser-entry/router-init.ts +193 -0
  390. package/src/client/browser-entry/rsc-stream.ts +157 -0
  391. package/src/client/browser-entry/scroll.ts +27 -0
  392. package/src/client/error-boundary.tsx +48 -16
  393. package/src/client/error-reconstituter.tsx +65 -0
  394. package/src/client/form.tsx +9 -7
  395. package/src/client/history.ts +26 -4
  396. package/src/client/index.ts +19 -38
  397. package/src/client/internal.ts +57 -0
  398. package/src/client/link-pending-store.ts +111 -0
  399. package/src/client/link.tsx +329 -97
  400. package/src/client/nav-link-store.ts +47 -0
  401. package/src/client/navigation-api-types.ts +112 -0
  402. package/src/client/navigation-api.ts +332 -0
  403. package/src/client/navigation-context.ts +31 -6
  404. package/src/client/navigation-root.tsx +342 -0
  405. package/src/client/nuqs-adapter.tsx +16 -3
  406. package/src/client/router-ref.ts +1 -1
  407. package/src/client/router.ts +299 -72
  408. package/src/client/rsc-fetch.ts +97 -8
  409. package/src/client/segment-cache.ts +1 -1
  410. package/src/client/segment-outlet.tsx +86 -0
  411. package/src/client/ssr-data.ts +13 -5
  412. package/src/client/stale-reload.ts +72 -3
  413. package/src/client/top-loader.tsx +16 -8
  414. package/src/client/use-link-status.ts +7 -7
  415. package/src/client/use-params.ts +7 -5
  416. package/src/client/{use-navigation-pending.ts → use-pending-navigation.ts} +6 -6
  417. package/src/client/use-query-states.ts +3 -3
  418. package/src/client/use-router.ts +1 -1
  419. package/src/codec.ts +49 -0
  420. package/src/config-types.ts +225 -0
  421. package/src/content/index.ts +5 -13
  422. package/src/cookies/define-cookie.ts +78 -25
  423. package/src/cookies/index.ts +8 -0
  424. package/src/fonts/css.ts +2 -1
  425. package/src/index.ts +295 -354
  426. package/src/plugin-context.ts +240 -0
  427. package/src/plugins/adapter-build.ts +9 -3
  428. package/src/plugins/build-manifest.ts +13 -2
  429. package/src/plugins/build-report.ts +3 -3
  430. package/src/plugins/client-chunks.ts +65 -0
  431. package/src/plugins/content.ts +1 -1
  432. package/src/plugins/dev-browser-logs.ts +288 -0
  433. package/src/plugins/dev-error-overlay.ts +70 -1
  434. package/src/plugins/dev-logs.ts +1 -1
  435. package/src/plugins/dev-server.ts +70 -9
  436. package/src/plugins/entries.ts +71 -10
  437. package/src/plugins/fonts.ts +168 -61
  438. package/src/plugins/mdx.ts +1 -1
  439. package/src/plugins/routing.ts +57 -17
  440. package/src/plugins/server-action-exports.ts +1 -1
  441. package/src/plugins/server-bundle.ts +32 -1
  442. package/src/plugins/shims.ts +135 -35
  443. package/src/plugins/static-build.ts +17 -11
  444. package/src/routing/codegen.ts +165 -105
  445. package/src/routing/index.ts +2 -0
  446. package/src/routing/scanner.ts +93 -23
  447. package/src/routing/segment-classify.ts +89 -0
  448. package/src/routing/status-file-lint.ts +3 -2
  449. package/src/routing/types.ts +17 -4
  450. package/src/rsc-runtime/rsc.ts +2 -0
  451. package/src/rsc-runtime/ssr.ts +50 -0
  452. package/src/rsc-runtime/vendor-types.d.ts +7 -0
  453. package/src/{search-params/codecs.ts → schema-bridge.ts} +57 -20
  454. package/src/search-params/define.ts +482 -0
  455. package/src/search-params/index.ts +14 -20
  456. package/src/search-params/registry.ts +2 -2
  457. package/src/search-params/wrappers.ts +85 -0
  458. package/src/segment-params/define.ts +279 -0
  459. package/src/segment-params/index.ts +9 -0
  460. package/src/server/access-gate.tsx +70 -29
  461. package/src/server/action-client.ts +46 -11
  462. package/src/server/action-encryption.ts +144 -0
  463. package/src/server/action-handler.ts +21 -4
  464. package/src/server/actions.ts +10 -9
  465. package/src/server/als-registry.ts +34 -6
  466. package/src/server/build-manifest.ts +10 -4
  467. package/src/server/compress.ts +25 -7
  468. package/src/server/debug.ts +1 -1
  469. package/src/server/default-logger.ts +99 -0
  470. package/src/server/deny-page-resolver.ts +154 -0
  471. package/src/server/deny-renderer.ts +24 -38
  472. package/src/server/dev-holding-server.ts +185 -0
  473. package/src/server/dev-warnings.ts +4 -49
  474. package/src/server/early-hints.ts +36 -15
  475. package/src/server/error-boundary-wrapper.ts +74 -22
  476. package/src/server/fallback-error.ts +31 -15
  477. package/src/server/flight-injection-state.ts +113 -0
  478. package/src/server/flight-scripts.ts +62 -0
  479. package/src/server/flush.ts +2 -1
  480. package/src/server/form-data.ts +76 -0
  481. package/src/server/html-injectors.ts +280 -120
  482. package/src/server/index.ts +25 -177
  483. package/src/server/internal.ts +169 -0
  484. package/src/server/logger.ts +44 -36
  485. package/src/server/middleware-runner.ts +31 -4
  486. package/src/server/node-stream-transforms.ts +509 -0
  487. package/src/server/page-deny-boundary.tsx +56 -0
  488. package/src/server/pipeline-interception.ts +17 -16
  489. package/src/server/pipeline-metadata.ts +13 -0
  490. package/src/server/pipeline.ts +227 -62
  491. package/src/server/primitives.ts +111 -28
  492. package/src/server/render-timeout.ts +108 -0
  493. package/src/server/request-context.ts +293 -132
  494. package/src/server/route-element-builder.ts +283 -191
  495. package/src/server/route-handler.ts +24 -4
  496. package/src/server/route-matcher.ts +24 -20
  497. package/src/server/rsc-entry/api-handler.ts +15 -16
  498. package/src/server/rsc-entry/error-renderer.ts +300 -89
  499. package/src/server/rsc-entry/helpers.ts +134 -5
  500. package/src/server/rsc-entry/index.ts +200 -112
  501. package/src/server/rsc-entry/rsc-payload.ts +65 -18
  502. package/src/server/rsc-entry/rsc-stream.ts +65 -13
  503. package/src/server/rsc-entry/ssr-bridge.ts +14 -5
  504. package/src/server/rsc-entry/ssr-renderer.ts +168 -38
  505. package/src/server/safe-load.ts +60 -0
  506. package/src/server/sitemap-generator.ts +338 -0
  507. package/src/server/sitemap-handler.ts +126 -0
  508. package/src/server/slot-resolver.ts +244 -229
  509. package/src/server/ssr-entry.ts +211 -32
  510. package/src/server/ssr-render.ts +289 -67
  511. package/src/server/ssr-wrappers.tsx +139 -0
  512. package/src/server/status-code-resolver.ts +1 -1
  513. package/src/server/stream-utils.ts +213 -0
  514. package/src/server/tracing.ts +20 -9
  515. package/src/server/tree-builder.ts +92 -58
  516. package/src/server/types.ts +3 -6
  517. package/src/server/version-skew.ts +104 -0
  518. package/src/shared/merge-search-params.ts +55 -0
  519. package/src/shims/font-google.ts +1 -1
  520. package/src/shims/font-local.ts +34 -0
  521. package/src/shims/headers.ts +5 -1
  522. package/src/shims/navigation-client.ts +1 -1
  523. package/src/shims/navigation.ts +7 -2
  524. package/src/utils/directive-parser.ts +5 -2
  525. package/src/utils/state-machine.ts +111 -0
  526. package/dist/_chunks/als-registry-B7DbZ2hS.js.map +0 -1
  527. package/dist/_chunks/debug-gwlJkDuf.js.map +0 -1
  528. package/dist/_chunks/format-DviM89f0.js.map +0 -1
  529. package/dist/_chunks/interception-BOoWmLUA.js.map +0 -1
  530. package/dist/_chunks/request-context-DIkVh_jG.js +0 -330
  531. package/dist/_chunks/request-context-DIkVh_jG.js.map +0 -1
  532. package/dist/_chunks/tracing-CemImE6h.js.map +0 -1
  533. package/dist/_chunks/use-cookie-DX-l1_5E.js +0 -91
  534. package/dist/_chunks/use-cookie-DX-l1_5E.js.map +0 -1
  535. package/dist/_chunks/use-query-states-D5KaffOK.js.map +0 -1
  536. package/dist/cache/register-cached-function.d.ts +0 -17
  537. package/dist/cache/register-cached-function.d.ts.map +0 -1
  538. package/dist/client/browser-entry.d.ts +0 -21
  539. package/dist/client/browser-entry.d.ts.map +0 -1
  540. package/dist/client/link-status-provider.d.ts +0 -11
  541. package/dist/client/link-status-provider.d.ts.map +0 -1
  542. package/dist/client/transition-root.d.ts.map +0 -1
  543. package/dist/client/use-navigation-pending.d.ts.map +0 -1
  544. package/dist/cookies/index.js.map +0 -1
  545. package/dist/plugins/cache-transform.d.ts +0 -36
  546. package/dist/plugins/cache-transform.d.ts.map +0 -1
  547. package/dist/plugins/dynamic-transform.d.ts +0 -72
  548. package/dist/plugins/dynamic-transform.d.ts.map +0 -1
  549. package/dist/search-params/analyze.d.ts +0 -54
  550. package/dist/search-params/analyze.d.ts.map +0 -1
  551. package/dist/search-params/builtin-codecs.d.ts +0 -105
  552. package/dist/search-params/builtin-codecs.d.ts.map +0 -1
  553. package/dist/search-params/codecs.d.ts +0 -53
  554. package/dist/search-params/codecs.d.ts.map +0 -1
  555. package/dist/search-params/create.d.ts +0 -106
  556. package/dist/search-params/create.d.ts.map +0 -1
  557. package/dist/server/prerender.d.ts +0 -77
  558. package/dist/server/prerender.d.ts.map +0 -1
  559. package/dist/server/response-cache.d.ts +0 -54
  560. package/dist/server/response-cache.d.ts.map +0 -1
  561. package/src/cache/register-cached-function.ts +0 -103
  562. package/src/client/browser-entry.ts +0 -678
  563. package/src/client/link-status-provider.tsx +0 -30
  564. package/src/client/transition-root.tsx +0 -166
  565. package/src/plugins/cache-transform.ts +0 -199
  566. package/src/plugins/dynamic-transform.ts +0 -161
  567. package/src/search-params/analyze.ts +0 -192
  568. package/src/search-params/builtin-codecs.ts +0 -228
  569. package/src/search-params/create.ts +0 -321
  570. package/src/server/prerender.ts +0 -139
  571. package/src/server/response-cache.ts +0 -410
@@ -0,0 +1,240 @@
1
+ /**
2
+ * Plugin context — internal types and helpers for timber sub-plugins.
3
+ *
4
+ * These are NOT part of the user-facing API. They are consumed by
5
+ * sub-plugins (routing, entries, shims, etc.) via relative imports.
6
+ * The root entry point (index.ts) does not re-export them.
7
+ *
8
+ * Design doc: 18-build-system.md §"Shared Plugin Context"
9
+ */
10
+
11
+ import { existsSync } from 'node:fs';
12
+ import { join } from 'node:path';
13
+ import { createRequire } from 'node:module';
14
+ import type { RouteTree } from './routing/types';
15
+ import type { BuildManifest } from './server/build-manifest';
16
+ import type { StartupTimer } from './utils/startup-timer';
17
+ import { createStartupTimer } from './utils/startup-timer';
18
+ import type { TimberUserConfig, ClientJavascriptConfig } from './config-types.js';
19
+ import type { HoldingServer } from './server/dev-holding-server.js';
20
+
21
+ // Re-export for sub-plugin convenience — they import from plugin-context.ts
22
+ export type { TimberUserConfig, ClientJavascriptConfig } from './config-types.js';
23
+
24
+ // ── Client JavaScript config ─────────────────────────────────────────────
25
+
26
+ /** Fully resolved client JavaScript configuration (no optionals). */
27
+ export interface ResolvedClientJavascript {
28
+ disabled: boolean;
29
+ enableHMRInDev: boolean;
30
+ }
31
+
32
+ /**
33
+ * Resolve `clientJavascript` into a fully resolved config.
34
+ */
35
+ export function resolveClientJavascript(config: TimberUserConfig): ResolvedClientJavascript {
36
+ if (config.clientJavascript !== undefined) {
37
+ if (typeof config.clientJavascript === 'boolean') {
38
+ return {
39
+ disabled: !config.clientJavascript,
40
+ enableHMRInDev: !config.clientJavascript,
41
+ };
42
+ }
43
+ return {
44
+ disabled: config.clientJavascript.disabled,
45
+ enableHMRInDev: config.clientJavascript.enableHMRInDev ?? config.clientJavascript.disabled,
46
+ };
47
+ }
48
+ return { disabled: false, enableHMRInDev: false };
49
+ }
50
+
51
+ // ── Plugin Context ────────────────────────────────────────────────────────
52
+
53
+ /**
54
+ * Shared context object passed to all sub-plugins via closure.
55
+ *
56
+ * Sub-plugins communicate through this context — not through Vite's
57
+ * plugin API or global state.
58
+ * See design/18-build-system.md §"Shared Plugin Context".
59
+ */
60
+ export interface PluginContext {
61
+ config: TimberUserConfig;
62
+ /** Resolved client JavaScript configuration */
63
+ clientJavascript: ResolvedClientJavascript;
64
+ /** The scanned route tree (populated by timber-routing, consumed by timber-entries) */
65
+ routeTree: RouteTree | null;
66
+ /** Absolute path to the app/ directory */
67
+ appDir: string;
68
+ /** Absolute path to the project root */
69
+ root: string;
70
+ /** Whether the dev server is running (set by timber-root-sync in configResolved) */
71
+ dev: boolean;
72
+ /** CSS build manifest (populated by adapter after client build, null in dev) */
73
+ buildManifest: BuildManifest | null;
74
+ /** Per-build deployment ID for version skew detection (null in dev) */
75
+ deploymentId: string | null;
76
+ /** Startup timer for profiling cold start phases (active in dev, no-op in prod) */
77
+ timer: StartupTimer;
78
+ /** Holding server that binds the port during dev startup (closed in timber-dev-server) */
79
+ holdingServer?: HoldingServer | null;
80
+ /**
81
+ * Resolved absolute path to the build output directory.
82
+ *
83
+ * Defaults to `<root>/.timber/dist`. Can be overridden via
84
+ * `timber.config.ts` `buildDir` or Vite's `build.outDir`.
85
+ * Timber config takes precedence when both are set.
86
+ *
87
+ * Used by adapter-build and cli preview.
88
+ */
89
+ buildDir: string;
90
+ }
91
+
92
+ // ── App directory resolution ──────────────────────────────────────────────
93
+
94
+ /**
95
+ * Resolve the app directory. Checks (in order):
96
+ * 1. Explicit `configAppDir` from timber.config.ts
97
+ * 2. `<root>/app`
98
+ * 3. `<root>/src/app`
99
+ *
100
+ * Throws if none exist.
101
+ */
102
+ export function resolveAppDir(root: string, configAppDir?: string): string {
103
+ if (configAppDir) {
104
+ const explicit = join(root, configAppDir);
105
+ if (!existsSync(explicit)) {
106
+ throw new Error(`[timber] Configured appDir "${configAppDir}" does not exist at ${explicit}`);
107
+ }
108
+ return explicit;
109
+ }
110
+
111
+ const rootApp = join(root, 'app');
112
+ if (existsSync(rootApp)) return rootApp;
113
+
114
+ const srcApp = join(root, 'src', 'app');
115
+ if (existsSync(srcApp)) return srcApp;
116
+
117
+ throw new Error(
118
+ `[timber] Could not find app directory. Expected "app/" or "src/app/" in ${root}. ` +
119
+ `You can set appDir in timber.config.ts to specify a custom location.`
120
+ );
121
+ }
122
+
123
+ // ── Plugin context factory ────────────────────────────────────────────────
124
+
125
+ export function createPluginContext(config?: TimberUserConfig, root?: string): PluginContext {
126
+ const projectRoot = root ?? process.cwd();
127
+ const resolvedConfig: TimberUserConfig = { ...config };
128
+ return {
129
+ config: resolvedConfig,
130
+ clientJavascript: resolveClientJavascript(resolvedConfig),
131
+ routeTree: null,
132
+ appDir: join(projectRoot, 'app'),
133
+ root: projectRoot,
134
+ dev: false,
135
+ buildManifest: null,
136
+ deploymentId: null,
137
+ timer: createStartupTimer(),
138
+ holdingServer: null,
139
+ buildDir: resolveBuildDir(projectRoot, resolvedConfig.buildDir),
140
+ };
141
+ }
142
+
143
+ // ── Build directory resolution ────────────────────────────────────────────
144
+
145
+ /** Default build output directory (relative to root). */
146
+ export const DEFAULT_BUILD_DIR = join('.timber', 'dist');
147
+
148
+ /**
149
+ * Resolve the build output directory.
150
+ *
151
+ * Priority:
152
+ * 1. Explicit `timberBuildDir` from timber.config.ts
153
+ * 2. Explicit `viteBuildOutDir` from Vite's build.outDir (if not the default 'dist')
154
+ * 3. Default: `.timber/dist`
155
+ *
156
+ * Returns an absolute path.
157
+ */
158
+ export function resolveBuildDir(
159
+ root: string,
160
+ timberBuildDir?: string,
161
+ viteBuildOutDir?: string
162
+ ): string {
163
+ if (timberBuildDir) {
164
+ return join(root, timberBuildDir);
165
+ }
166
+ if (viteBuildOutDir && viteBuildOutDir !== 'dist') {
167
+ return join(root, viteBuildOutDir);
168
+ }
169
+ return join(root, DEFAULT_BUILD_DIR);
170
+ }
171
+
172
+ // ── Config file loading ───────────────────────────────────────────────────
173
+
174
+ /**
175
+ * Load timber.config.ts (or .js, .mjs) from the project root.
176
+ * Returns the config object or null if no config file is found.
177
+ *
178
+ * Uses require() which works for ESM modules on Node 22.12+.
179
+ * This keeps timber() synchronous — no async config loading needed.
180
+ */
181
+ export function loadTimberConfigFile(root: string): TimberUserConfig | null {
182
+ const configNames = ['timber.config.ts', 'timber.config.js', 'timber.config.mjs'];
183
+ const req = createRequire(join(root, 'package.json'));
184
+
185
+ for (const name of configNames) {
186
+ const configPath = join(root, name);
187
+ if (existsSync(configPath)) {
188
+ const mod = req(configPath);
189
+ return (mod.default ?? mod) as TimberUserConfig;
190
+ }
191
+ }
192
+ return null;
193
+ }
194
+
195
+ /**
196
+ * Detect config keys set in both inline (vite.config.ts) and file (timber.config.ts)
197
+ * and warn the user. The `output` key is excluded because it defaults to 'server'
198
+ * in createPluginContext and would always appear as an inline key.
199
+ *
200
+ * Returns the list of conflicting key names (for testing).
201
+ */
202
+ export function warnConfigConflicts(
203
+ inline: TimberUserConfig,
204
+ fileConfig: TimberUserConfig
205
+ ): string[] {
206
+ const conflicts: string[] = [];
207
+ for (const key of Object.keys(fileConfig) as (keyof TimberUserConfig)[]) {
208
+ if (key in inline && inline[key] !== undefined) {
209
+ conflicts.push(key);
210
+ }
211
+ }
212
+ if (conflicts.length > 0) {
213
+ console.warn(
214
+ `[timber] Config conflict: ${conflicts.map((k) => `"${k}"`).join(', ')} set in both ` +
215
+ `vite.config.ts (inline) and timber.config.ts. ` +
216
+ `Move all config to timber.config.ts to avoid confusion. ` +
217
+ `The inline value from vite.config.ts will be used.`
218
+ );
219
+ }
220
+ return conflicts;
221
+ }
222
+
223
+ /**
224
+ * Merge file-based config into ctx.config. Inline config (already in ctx.config)
225
+ * takes precedence — file config only fills in missing fields.
226
+ */
227
+ export function mergeFileConfig(ctx: PluginContext, fileConfig: TimberUserConfig): void {
228
+ const inline = ctx.config;
229
+ warnConfigConflicts(inline, fileConfig);
230
+
231
+ ctx.config = {
232
+ ...fileConfig,
233
+ ...inline,
234
+ ...(fileConfig.limits && inline.limits
235
+ ? { limits: { ...fileConfig.limits, ...inline.limits } }
236
+ : {}),
237
+ ...(fileConfig.dev && inline.dev ? { dev: { ...fileConfig.dev, ...inline.dev } } : {}),
238
+ ...(fileConfig.mdx && inline.mdx ? { mdx: { ...fileConfig.mdx, ...inline.mdx } } : {}),
239
+ };
240
+ }
@@ -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 '../plugin-context.js';
20
+ import type { TimberPlatformAdapter, TimberConfig } from '../adapters/types.js';
21
21
 
22
22
  export function timberAdapterBuild(ctx: PluginContext): Plugin {
23
23
  return {
@@ -35,7 +35,7 @@ export function timberAdapterBuild(ctx: PluginContext): Plugin {
35
35
  const adapter = ctx.config.adapter as TimberPlatformAdapter | undefined;
36
36
  if (!adapter || typeof adapter.buildOutput !== 'function') return;
37
37
 
38
- const buildDir = join(ctx.root, 'dist');
38
+ const buildDir = ctx.buildDir;
39
39
 
40
40
  // Serialize the build manifest as a JS module that sets the global.
41
41
  // The adapter writes this as _timber-manifest-init.mjs and imports it
@@ -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 '../plugin-context.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 '../plugin-context.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
 
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Client chunk grouping strategy for @vitejs/plugin-rsc.
3
+ *
4
+ * Groups client reference modules by layout boundary to balance route-scoped
5
+ * code splitting with HTTP request count. A constant group name would collapse
6
+ * all routes into one chunk (every page downloads every client component).
7
+ * Per-serverChunk grouping creates many sub-500B files. Layout-boundary
8
+ * grouping is the middle ground.
9
+ *
10
+ * See design/27-chunking-strategy.md, TIM-440, TIM-499.
11
+ */
12
+
13
+ /**
14
+ * Derive a chunk group name for a client reference module.
15
+ *
16
+ * Groups by the first non-group route segment under appDir so that all
17
+ * client components belonging to the same layout boundary land in one
18
+ * chunk. For example:
19
+ * - `facade:app/dashboard/settings/page.tsx` → `"client-dashboard"`
20
+ * - `facade:app/(group-a)/group-page-a/page.tsx` → `"client-group-page-a"`
21
+ * - `facade:app/layout.tsx` (root layout) → `"client-shared"`
22
+ * - `shared:...` (shared across chunks) → `"client-shared"`
23
+ *
24
+ * This balances route-scoped code splitting with HTTP request count:
25
+ * fewer chunks than per-serverChunk, but still avoids downloading every
26
+ * client component on every page.
27
+ */
28
+ export function clientChunkGroup(
29
+ meta: { id: string; normalizedId: string; serverChunk: string },
30
+ appDir: string
31
+ ): string {
32
+ const { normalizedId, serverChunk } = meta;
33
+
34
+ // Shared chunks (not associated with a single route entry) get one group.
35
+ if (serverChunk.startsWith('shared:')) return 'client-shared';
36
+
37
+ // Derive the layout boundary from the file's location relative to the
38
+ // app directory. normalizedId is root-relative (e.g. "app/dashboard/shell.tsx"
39
+ // or "src/app/dashboard/shell.tsx"). We find the "app/" prefix and walk
40
+ // segments after it to find the first non-group directory.
41
+ const relPath = normalizedId.replace(/\\/g, '/');
42
+
43
+ // Find the app directory boundary in the path. The last segment of appDir
44
+ // is the app folder name (usually "app").
45
+ const appDirName = appDir.replace(/\\/g, '/').split('/').pop() || 'app';
46
+ const appIdx = relPath.indexOf(appDirName + '/');
47
+ if (appIdx === -1) return 'client-shared';
48
+
49
+ const withinApp = relPath.slice(appIdx + appDirName.length + 1);
50
+ const segments = withinApp.split('/');
51
+
52
+ // Find first directory segment that isn't a route group like (group-a)
53
+ for (const seg of segments) {
54
+ // Skip the filename itself
55
+ if (seg.includes('.')) break;
56
+ // Skip route groups — parenthesized segments like (group-a)
57
+ if (seg.startsWith('(') && seg.endsWith(')')) continue;
58
+ // Found a real route segment
59
+ return `client-${seg}`;
60
+ }
61
+
62
+ // Root-level files (layout.tsx, page.tsx directly in app/) go into the
63
+ // shared group since the root layout is loaded on every page.
64
+ return 'client-shared';
65
+ }
@@ -11,7 +11,7 @@
11
11
  import type { Plugin } from 'vite';
12
12
  import { existsSync } from 'node:fs';
13
13
  import { join } from 'node:path';
14
- import type { PluginContext } from '#/index.js';
14
+ import type { PluginContext } from '../plugin-context.js';
15
15
 
16
16
  const CONFIG_FILE_NAMES = [
17
17
  'content-collections.ts',
@@ -0,0 +1,288 @@
1
+ /**
2
+ * timber-dev-browser-logs — Forwards browser console output to the server terminal.
3
+ *
4
+ * Injects a small inline script in dev mode that intercepts browser
5
+ * `console.error`, `console.warn`, and `console.info`, then forwards
6
+ * messages to the server via Vite's HMR WebSocket.
7
+ *
8
+ * The server-side listener formats and prints the messages with color-coded
9
+ * prefixes: [browser:error], [browser:warn], [browser:info].
10
+ *
11
+ * Dev-only: this plugin only runs during `vite dev`.
12
+ * No runtime overhead in production.
13
+ *
14
+ * See TIM-513 for design context.
15
+ * See design/18-build-system.md §"Dev Server" for sub-plugin architecture.
16
+ */
17
+
18
+ import type { Plugin, ViteDevServer } from 'vite';
19
+ import type { PluginContext } from '../plugin-context.js';
20
+
21
+ // ─── Types ───────────────────────────────────────────────────────────────
22
+
23
+ /** Log levels forwarded from the browser. */
24
+ export type BrowserLogLevel = 'error' | 'warn' | 'info';
25
+
26
+ /** Configuration value for devBrowserLogs in timber.config.ts. */
27
+ export type DevBrowserLogsConfig = BrowserLogLevel | 'none' | undefined;
28
+
29
+ /**
30
+ * Payload sent from browser to server via Vite's HMR WebSocket.
31
+ * Kept small — truncated before sending.
32
+ */
33
+ export interface BrowserLogPayload {
34
+ level: BrowserLogLevel;
35
+ /** Serialized message string. */
36
+ message: string;
37
+ /** Error stack trace, if the first argument was an Error. */
38
+ stack: string | null;
39
+ /** Source URL and line number, if available. */
40
+ source: string | null;
41
+ /** Timestamp in ms (Date.now()) from the browser. */
42
+ timestamp: number;
43
+ }
44
+
45
+ // ─── Constants ───────────────────────────────────────────────────────────
46
+
47
+ /** Max message size in bytes before truncation. */
48
+ const MAX_MESSAGE_BYTES = 2048;
49
+
50
+ /** HMR event name for browser→server log forwarding. */
51
+ const HMR_EVENT = 'timber:browser-log';
52
+
53
+ /** ANSI color codes for terminal output. */
54
+ const COLORS = {
55
+ red: '\x1b[31m',
56
+ yellow: '\x1b[33m',
57
+ blue: '\x1b[34m',
58
+ dim: '\x1b[2m',
59
+ reset: '\x1b[0m',
60
+ } as const;
61
+
62
+ /** Level severity ordering for threshold comparison. */
63
+ const LEVEL_SEVERITY: Record<BrowserLogLevel | 'none', number> = {
64
+ none: 0,
65
+ info: 1,
66
+ warn: 2,
67
+ error: 3,
68
+ };
69
+
70
+ // ─── Formatting ──────────────────────────────────────────────────────────
71
+
72
+ /**
73
+ * Format a browser log payload for server terminal output.
74
+ *
75
+ * Produces color-coded output like:
76
+ * [browser:error] Uncaught TypeError: x is not a function
77
+ * at App (app.tsx:10:5)
78
+ * [browser:warn] Deprecation warning (app/page.tsx:42:12)
79
+ */
80
+ export function formatBrowserLog(payload: BrowserLogPayload): string {
81
+ const { level, message, stack, source } = payload;
82
+
83
+ // Color-coded prefix
84
+ const color = level === 'error' ? COLORS.red : level === 'warn' ? COLORS.yellow : COLORS.blue;
85
+ const prefix = `${color}[browser:${level}]${COLORS.reset}`;
86
+
87
+ // Source suffix
88
+ const sourceSuffix = source ? ` ${COLORS.dim}(${source})${COLORS.reset}` : '';
89
+
90
+ let output = `${prefix} ${message}${sourceSuffix}`;
91
+
92
+ // Append stack trace indented
93
+ if (stack) {
94
+ const indented = stack
95
+ .split('\n')
96
+ .map((line) => ` ${COLORS.dim}${line}${COLORS.reset}`)
97
+ .join('\n');
98
+ output += `\n${indented}`;
99
+ }
100
+
101
+ return output;
102
+ }
103
+
104
+ // ─── Level Filtering ─────────────────────────────────────────────────────
105
+
106
+ /**
107
+ * Check if a log at `level` should be forwarded given the configured threshold.
108
+ *
109
+ * The threshold acts as a minimum severity:
110
+ * - 'error' → only errors
111
+ * - 'warn' → errors + warnings
112
+ * - 'info' → errors + warnings + info
113
+ * - 'none' → nothing
114
+ */
115
+ export function shouldForwardLevel(
116
+ level: BrowserLogLevel,
117
+ threshold: BrowserLogLevel | 'none'
118
+ ): boolean {
119
+ if (threshold === 'none') return false;
120
+ return LEVEL_SEVERITY[level] >= LEVEL_SEVERITY[threshold];
121
+ }
122
+
123
+ // ─── Truncation ──────────────────────────────────────────────────────────
124
+
125
+ /**
126
+ * Truncate a message to `maxBytes` to avoid flooding the terminal.
127
+ * Appends a suffix indicating how many bytes were dropped.
128
+ */
129
+ export function truncateMessage(message: string, maxBytes: number): string {
130
+ if (message.length <= maxBytes) return message;
131
+
132
+ const truncated = message.slice(0, maxBytes);
133
+ const droppedBytes = message.length - maxBytes;
134
+ return `${truncated}… [truncated ${droppedBytes} bytes]`;
135
+ }
136
+
137
+ // ─── Client Injection Script ─────────────────────────────────────────────
138
+
139
+ /**
140
+ * Generate the inline script injected into the browser in dev mode.
141
+ *
142
+ * This script:
143
+ * 1. Saves references to the original console methods
144
+ * 2. Wraps `console.error`, `console.warn`, `console.info`
145
+ * 3. Calls the original first (browser devtools still work)
146
+ * 4. Serializes and forwards via `import.meta.hot.send()`
147
+ * 5. Truncates messages to MAX_MESSAGE_BYTES
148
+ *
149
+ * The script is minimal and self-contained — no imports, no dependencies.
150
+ */
151
+ export function generateClientScript(threshold: BrowserLogLevel | 'none'): string {
152
+ if (threshold === 'none') return '';
153
+
154
+ // Only intercept levels that meet the threshold
155
+ const levels: BrowserLogLevel[] = ['error', 'warn', 'info'].filter((l) =>
156
+ shouldForwardLevel(l as BrowserLogLevel, threshold)
157
+ ) as BrowserLogLevel[];
158
+
159
+ if (levels.length === 0) return '';
160
+
161
+ return `
162
+ (function() {
163
+ if (!import.meta.hot) return;
164
+ var MAX_BYTES = ${MAX_MESSAGE_BYTES};
165
+ var levels = ${JSON.stringify(levels)};
166
+ var originals = {};
167
+
168
+ function serialize(arg) {
169
+ if (arg === null) return 'null';
170
+ if (arg === undefined) return 'undefined';
171
+ if (arg instanceof Error) return arg.stack || arg.message || String(arg);
172
+ if (typeof arg === 'object') {
173
+ try { return JSON.stringify(arg); } catch(e) { return String(arg); }
174
+ }
175
+ return String(arg);
176
+ }
177
+
178
+ function truncate(s) {
179
+ if (s.length <= MAX_BYTES) return s;
180
+ return s.slice(0, MAX_BYTES) + '... [truncated ' + (s.length - MAX_BYTES) + ' bytes]';
181
+ }
182
+
183
+ levels.forEach(function(level) {
184
+ originals[level] = console[level];
185
+ console[level] = function() {
186
+ originals[level].apply(console, arguments);
187
+ try {
188
+ var args = Array.prototype.slice.call(arguments);
189
+ var firstArg = args[0];
190
+ var stack = null;
191
+ var source = null;
192
+
193
+ if (firstArg instanceof Error) {
194
+ stack = firstArg.stack || null;
195
+ source = null;
196
+ }
197
+
198
+ var message = args.map(serialize).join(' ');
199
+ message = truncate(message);
200
+
201
+ import.meta.hot.send('${HMR_EVENT}', {
202
+ level: level,
203
+ message: message,
204
+ stack: stack,
205
+ source: source,
206
+ timestamp: Date.now()
207
+ });
208
+ } catch(e) {
209
+ // Never let log forwarding break the page
210
+ }
211
+ };
212
+ });
213
+ })();
214
+ `.trim();
215
+ }
216
+
217
+ // ─── Plugin ──────────────────────────────────────────────────────────────
218
+
219
+ /**
220
+ * Create the timber-dev-browser-logs Vite plugin.
221
+ *
222
+ * - `configureServer`: Listens for HMR messages and prints them to the terminal
223
+ * - `transformIndexHtml`: Injects the client-side interception script
224
+ *
225
+ * Only active during `vite dev` (apply: 'serve').
226
+ */
227
+ export function timberDevBrowserLogs(ctx: PluginContext): Plugin {
228
+ return {
229
+ name: 'timber-dev-browser-logs',
230
+ apply: 'serve',
231
+
232
+ configureServer(server: ViteDevServer) {
233
+ const threshold = ctx.config.devBrowserLogs ?? 'warn';
234
+ if (threshold === 'none') {
235
+ // Clear any stale script from a prior server instance (e.g. HMR reconfigure)
236
+ delete (globalThis as Record<string, unknown>).__timber_dev_browser_log_script;
237
+ return;
238
+ }
239
+
240
+ // Register the client injection script on globalThis so the RSC entry
241
+ // can include it in headHtml for all Timber route responses.
242
+ // transformIndexHtml only runs for Vite's index.html fallback, not
243
+ // for responses served by createTimberMiddleware (TIM-575).
244
+ const script = generateClientScript(threshold);
245
+ if (script) {
246
+ (globalThis as Record<string, unknown>).__timber_dev_browser_log_script =
247
+ `<script type="module">${script}</script>`;
248
+ }
249
+
250
+ // Listen for browser log messages via HMR WebSocket
251
+ server.hot.on(HMR_EVENT, (payload: BrowserLogPayload) => {
252
+ try {
253
+ // Validate level
254
+ if (!shouldForwardLevel(payload.level, threshold)) return;
255
+
256
+ // Truncate server-side too (defense in depth)
257
+ payload.message = truncateMessage(payload.message, MAX_MESSAGE_BYTES);
258
+
259
+ const formatted = formatBrowserLog(payload);
260
+
261
+ // Use the correct console method for the log level
262
+ if (payload.level === 'error') {
263
+ process.stderr.write(formatted + '\n');
264
+ } else {
265
+ process.stdout.write(formatted + '\n');
266
+ }
267
+ } catch {
268
+ // Never let log forwarding crash the server
269
+ }
270
+ });
271
+ },
272
+
273
+ transformIndexHtml() {
274
+ const threshold = ctx.config.devBrowserLogs ?? 'warn';
275
+ const script = generateClientScript(threshold);
276
+ if (!script) return [];
277
+
278
+ return [
279
+ {
280
+ tag: 'script',
281
+ attrs: { type: 'module' },
282
+ children: script,
283
+ injectTo: 'head' as const,
284
+ },
285
+ ];
286
+ },
287
+ };
288
+ }