@timber-js/app 0.2.0-alpha.1 → 0.2.0-alpha.100

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 (742) hide show
  1. package/LICENSE +8 -0
  2. package/dist/_chunks/actions-CQ8Z8VGL.js +1061 -0
  3. package/dist/_chunks/actions-CQ8Z8VGL.js.map +1 -0
  4. package/dist/_chunks/build-output-helper-DXnW0qjz.js +61 -0
  5. package/dist/_chunks/build-output-helper-DXnW0qjz.js.map +1 -0
  6. package/dist/_chunks/chunk-BYIpzuS7.js +39 -0
  7. package/dist/_chunks/define-B-Q_UMOD.js +195 -0
  8. package/dist/_chunks/define-B-Q_UMOD.js.map +1 -0
  9. package/dist/_chunks/define-CfBPoJb0.js +123 -0
  10. package/dist/_chunks/define-CfBPoJb0.js.map +1 -0
  11. package/dist/_chunks/define-cookie-BjpIt4UC.js +194 -0
  12. package/dist/_chunks/define-cookie-BjpIt4UC.js.map +1 -0
  13. package/dist/_chunks/format-Bcn-Iv1x.js +14 -0
  14. package/dist/_chunks/format-Bcn-Iv1x.js.map +1 -0
  15. package/dist/_chunks/handler-store-B-lqaGyh.js +54 -0
  16. package/dist/_chunks/handler-store-B-lqaGyh.js.map +1 -0
  17. package/dist/_chunks/logger-0m8MsKdc.js +291 -0
  18. package/dist/_chunks/logger-0m8MsKdc.js.map +1 -0
  19. package/dist/_chunks/merge-search-params-BphMdht_.js +122 -0
  20. package/dist/_chunks/merge-search-params-BphMdht_.js.map +1 -0
  21. package/dist/_chunks/{metadata-routes-CQCnF4VK.js → metadata-routes-BU684ls2.js} +1 -1
  22. package/dist/_chunks/{metadata-routes-CQCnF4VK.js.map → metadata-routes-BU684ls2.js.map} +1 -1
  23. package/dist/_chunks/navigation-root-BCYczjml.js +96 -0
  24. package/dist/_chunks/navigation-root-BCYczjml.js.map +1 -0
  25. package/dist/_chunks/registry-I2ss-lvy.js +20 -0
  26. package/dist/_chunks/registry-I2ss-lvy.js.map +1 -0
  27. package/dist/_chunks/router-ref-h3-UaCQv.js +28 -0
  28. package/dist/_chunks/router-ref-h3-UaCQv.js.map +1 -0
  29. package/dist/_chunks/schema-bridge-Cxu4l-7p.js +86 -0
  30. package/dist/_chunks/schema-bridge-Cxu4l-7p.js.map +1 -0
  31. package/dist/_chunks/segment-classify-BjfuctV2.js +137 -0
  32. package/dist/_chunks/segment-classify-BjfuctV2.js.map +1 -0
  33. package/dist/_chunks/segment-context-Dx_OizxD.js +34 -0
  34. package/dist/_chunks/segment-context-Dx_OizxD.js.map +1 -0
  35. package/dist/_chunks/{ssr-data-DLnbYpj1.js → ssr-data-B4CdH7rE.js} +1 -1
  36. package/dist/_chunks/ssr-data-B4CdH7rE.js.map +1 -0
  37. package/dist/_chunks/stale-reload-Bab885FO.js +64 -0
  38. package/dist/_chunks/stale-reload-Bab885FO.js.map +1 -0
  39. package/dist/_chunks/tracing-C8V-YGsP.js +329 -0
  40. package/dist/_chunks/tracing-C8V-YGsP.js.map +1 -0
  41. package/dist/_chunks/{use-query-states-DAhgj8Gx.js → use-query-states-B2XTqxDR.js} +7 -20
  42. package/dist/_chunks/use-query-states-B2XTqxDR.js.map +1 -0
  43. package/dist/_chunks/use-segment-params-BkpKAQ7D.js +185 -0
  44. package/dist/_chunks/use-segment-params-BkpKAQ7D.js.map +1 -0
  45. package/dist/_chunks/walkers-Tg0Alwcg.js +850 -0
  46. package/dist/_chunks/walkers-Tg0Alwcg.js.map +1 -0
  47. package/dist/_chunks/{format-DNt20Kt8.js → warnings-Cg47l5sk.js} +7 -45
  48. package/dist/_chunks/warnings-Cg47l5sk.js.map +1 -0
  49. package/dist/adapters/build-output-helper.d.ts +28 -0
  50. package/dist/adapters/build-output-helper.d.ts.map +1 -0
  51. package/dist/adapters/cloudflare-dev.d.ts +109 -0
  52. package/dist/adapters/cloudflare-dev.d.ts.map +1 -0
  53. package/dist/adapters/cloudflare-dev.js +73 -0
  54. package/dist/adapters/cloudflare-dev.js.map +1 -0
  55. package/dist/adapters/cloudflare-kv-cache.d.ts +64 -0
  56. package/dist/adapters/cloudflare-kv-cache.d.ts.map +1 -0
  57. package/dist/adapters/cloudflare-kv-cache.js +95 -0
  58. package/dist/adapters/cloudflare-kv-cache.js.map +1 -0
  59. package/dist/adapters/cloudflare.d.ts +148 -12
  60. package/dist/adapters/cloudflare.d.ts.map +1 -1
  61. package/dist/adapters/cloudflare.js +142 -38
  62. package/dist/adapters/cloudflare.js.map +1 -1
  63. package/dist/adapters/compress-module.d.ts.map +1 -1
  64. package/dist/adapters/nitro.d.ts +17 -1
  65. package/dist/adapters/nitro.d.ts.map +1 -1
  66. package/dist/adapters/nitro.js +143 -45
  67. package/dist/adapters/nitro.js.map +1 -1
  68. package/dist/adapters/shared.d.ts +16 -0
  69. package/dist/adapters/shared.d.ts.map +1 -0
  70. package/dist/cache/cache-api.d.ts +24 -0
  71. package/dist/cache/cache-api.d.ts.map +1 -0
  72. package/dist/cache/fast-hash.d.ts +22 -0
  73. package/dist/cache/fast-hash.d.ts.map +1 -0
  74. package/dist/cache/handler-store.d.ts +31 -0
  75. package/dist/cache/handler-store.d.ts.map +1 -0
  76. package/dist/cache/index.d.ts +23 -7
  77. package/dist/cache/index.d.ts.map +1 -1
  78. package/dist/cache/index.js +195 -84
  79. package/dist/cache/index.js.map +1 -1
  80. package/dist/cache/singleflight.d.ts +18 -1
  81. package/dist/cache/singleflight.d.ts.map +1 -1
  82. package/dist/cache/sizeof.d.ts +22 -0
  83. package/dist/cache/sizeof.d.ts.map +1 -0
  84. package/dist/cache/timber-cache.d.ts +1 -1
  85. package/dist/cache/timber-cache.d.ts.map +1 -1
  86. package/dist/cli.d.ts +6 -1
  87. package/dist/cli.d.ts.map +1 -1
  88. package/dist/cli.js +8 -3
  89. package/dist/cli.js.map +1 -1
  90. package/dist/client/browser-dev.d.ts +34 -1
  91. package/dist/client/browser-dev.d.ts.map +1 -1
  92. package/dist/client/browser-entry/action-dispatch.d.ts +17 -0
  93. package/dist/client/browser-entry/action-dispatch.d.ts.map +1 -0
  94. package/dist/client/browser-entry/hmr.d.ts +21 -0
  95. package/dist/client/browser-entry/hmr.d.ts.map +1 -0
  96. package/dist/client/browser-entry/hydrate.d.ts +46 -0
  97. package/dist/client/browser-entry/hydrate.d.ts.map +1 -0
  98. package/dist/client/browser-entry/index.d.ts +30 -0
  99. package/dist/client/browser-entry/index.d.ts.map +1 -0
  100. package/dist/client/browser-entry/post-hydration.d.ts +26 -0
  101. package/dist/client/browser-entry/post-hydration.d.ts.map +1 -0
  102. package/dist/client/browser-entry/router-init.d.ts +23 -0
  103. package/dist/client/browser-entry/router-init.d.ts.map +1 -0
  104. package/dist/client/browser-entry/rsc-stream.d.ts +24 -0
  105. package/dist/client/browser-entry/rsc-stream.d.ts.map +1 -0
  106. package/dist/client/browser-entry/scroll.d.ts +19 -0
  107. package/dist/client/browser-entry/scroll.d.ts.map +1 -0
  108. package/dist/client/error-boundary.d.ts +12 -5
  109. package/dist/client/error-boundary.d.ts.map +1 -1
  110. package/dist/client/error-boundary.js +26 -5
  111. package/dist/client/error-boundary.js.map +1 -1
  112. package/dist/client/error-reconstituter.d.ts +54 -0
  113. package/dist/client/error-reconstituter.d.ts.map +1 -0
  114. package/dist/client/form.d.ts +16 -27
  115. package/dist/client/form.d.ts.map +1 -1
  116. package/dist/client/history.d.ts +19 -4
  117. package/dist/client/history.d.ts.map +1 -1
  118. package/dist/client/index.d.ts +9 -24
  119. package/dist/client/index.d.ts.map +1 -1
  120. package/dist/client/index.js +312 -1109
  121. package/dist/client/index.js.map +1 -1
  122. package/dist/client/internal.d.ts +19 -0
  123. package/dist/client/internal.d.ts.map +1 -0
  124. package/dist/client/internal.js +964 -0
  125. package/dist/client/internal.js.map +1 -0
  126. package/dist/client/link-pending-store.d.ts +63 -0
  127. package/dist/client/link-pending-store.d.ts.map +1 -0
  128. package/dist/client/link.d.ts +73 -63
  129. package/dist/client/link.d.ts.map +1 -1
  130. package/dist/client/nav-link-store.d.ts +36 -0
  131. package/dist/client/nav-link-store.d.ts.map +1 -0
  132. package/dist/client/navigation-api-types.d.ts +90 -0
  133. package/dist/client/navigation-api-types.d.ts.map +1 -0
  134. package/dist/client/navigation-api.d.ts +115 -0
  135. package/dist/client/navigation-api.d.ts.map +1 -0
  136. package/dist/client/navigation-context.d.ts +22 -5
  137. package/dist/client/navigation-context.d.ts.map +1 -1
  138. package/dist/client/{transition-root.d.ts → navigation-root.d.ts} +42 -8
  139. package/dist/client/navigation-root.d.ts.map +1 -0
  140. package/dist/client/nuqs-adapter.d.ts.map +1 -1
  141. package/dist/client/router-ref.d.ts +1 -1
  142. package/dist/client/router.d.ts +70 -4
  143. package/dist/client/router.d.ts.map +1 -1
  144. package/dist/client/rsc-fetch.d.ts +38 -3
  145. package/dist/client/rsc-fetch.d.ts.map +1 -1
  146. package/dist/client/segment-cache.d.ts +1 -1
  147. package/dist/client/segment-cache.d.ts.map +1 -1
  148. package/dist/client/segment-context.d.ts +1 -1
  149. package/dist/client/segment-context.d.ts.map +1 -1
  150. package/dist/client/segment-merger.d.ts.map +1 -1
  151. package/dist/client/segment-outlet.d.ts +63 -0
  152. package/dist/client/segment-outlet.d.ts.map +1 -0
  153. package/dist/client/ssr-data.d.ts +13 -4
  154. package/dist/client/ssr-data.d.ts.map +1 -1
  155. package/dist/client/stale-reload.d.ts +15 -0
  156. package/dist/client/stale-reload.d.ts.map +1 -1
  157. package/dist/client/state.d.ts +1 -1
  158. package/dist/client/top-loader.d.ts +5 -5
  159. package/dist/client/top-loader.d.ts.map +1 -1
  160. package/dist/client/use-cookie.d.ts +8 -0
  161. package/dist/client/use-cookie.d.ts.map +1 -1
  162. package/dist/client/use-link-status.d.ts +5 -5
  163. package/dist/client/use-link-status.d.ts.map +1 -1
  164. package/dist/client/{use-navigation-pending.d.ts → use-pending-navigation.d.ts} +4 -4
  165. package/dist/client/use-pending-navigation.d.ts.map +1 -0
  166. package/dist/client/use-query-states.d.ts +1 -1
  167. package/dist/client/use-query-states.d.ts.map +1 -1
  168. package/dist/client/use-router.d.ts +1 -1
  169. package/dist/client/{use-params.d.ts → use-segment-params.d.ts} +7 -5
  170. package/dist/client/use-segment-params.d.ts.map +1 -0
  171. package/dist/codec.d.ts +33 -0
  172. package/dist/codec.d.ts.map +1 -0
  173. package/dist/codec.js +2 -0
  174. package/dist/config-types.d.ts +294 -0
  175. package/dist/config-types.d.ts.map +1 -0
  176. package/dist/config-validation.d.ts +51 -0
  177. package/dist/config-validation.d.ts.map +1 -0
  178. package/dist/content/index.d.ts +1 -10
  179. package/dist/content/index.d.ts.map +1 -1
  180. package/dist/content/index.js +0 -2
  181. package/dist/cookies/define-cookie.d.ts +98 -25
  182. package/dist/cookies/define-cookie.d.ts.map +1 -1
  183. package/dist/cookies/index.d.ts +2 -1
  184. package/dist/cookies/index.d.ts.map +1 -1
  185. package/dist/cookies/index.js +36 -72
  186. package/dist/cookies/index.js.map +1 -1
  187. package/dist/cookies/json-cookie.d.ts +64 -0
  188. package/dist/cookies/json-cookie.d.ts.map +1 -0
  189. package/dist/cookies/validation.d.ts +46 -0
  190. package/dist/cookies/validation.d.ts.map +1 -0
  191. package/dist/dev-tools/404-page.d.ts +46 -0
  192. package/dist/dev-tools/404-page.d.ts.map +1 -0
  193. package/dist/dev-tools/browser-logs.d.ts +84 -0
  194. package/dist/dev-tools/browser-logs.d.ts.map +1 -0
  195. package/dist/dev-tools/error-page.d.ts +58 -0
  196. package/dist/dev-tools/error-page.d.ts.map +1 -0
  197. package/dist/dev-tools/holding-server.d.ts +54 -0
  198. package/dist/dev-tools/holding-server.d.ts.map +1 -0
  199. package/dist/dev-tools/index.d.ts +31 -0
  200. package/dist/dev-tools/index.d.ts.map +1 -0
  201. package/dist/{server/dev-span-processor.d.ts → dev-tools/instrumentation.d.ts} +26 -6
  202. package/dist/dev-tools/instrumentation.d.ts.map +1 -0
  203. package/dist/{server/dev-logger.d.ts → dev-tools/logger.d.ts} +1 -1
  204. package/dist/dev-tools/logger.d.ts.map +1 -0
  205. package/dist/{plugins/dev-logs.d.ts → dev-tools/logs.d.ts} +2 -2
  206. package/dist/dev-tools/logs.d.ts.map +1 -0
  207. package/dist/dev-tools/overlay.d.ts +91 -0
  208. package/dist/dev-tools/overlay.d.ts.map +1 -0
  209. package/dist/dev-tools/stack-classifier.d.ts +34 -0
  210. package/dist/dev-tools/stack-classifier.d.ts.map +1 -0
  211. package/dist/dev-tools/terminal.d.ts +28 -0
  212. package/dist/dev-tools/terminal.d.ts.map +1 -0
  213. package/dist/{server/dev-warnings.d.ts → dev-tools/warnings.d.ts} +2 -22
  214. package/dist/dev-tools/warnings.d.ts.map +1 -0
  215. package/dist/fonts/bundle.d.ts +48 -0
  216. package/dist/fonts/bundle.d.ts.map +1 -0
  217. package/dist/fonts/css.d.ts +1 -0
  218. package/dist/fonts/css.d.ts.map +1 -1
  219. package/dist/fonts/dev-middleware.d.ts +22 -0
  220. package/dist/fonts/dev-middleware.d.ts.map +1 -0
  221. package/dist/fonts/local.d.ts +4 -2
  222. package/dist/fonts/local.d.ts.map +1 -1
  223. package/dist/fonts/pipeline.d.ts +167 -0
  224. package/dist/fonts/pipeline.d.ts.map +1 -0
  225. package/dist/fonts/transform.d.ts +64 -0
  226. package/dist/fonts/transform.d.ts.map +1 -0
  227. package/dist/fonts/types.d.ts +45 -1
  228. package/dist/fonts/types.d.ts.map +1 -1
  229. package/dist/fonts/virtual-modules.d.ts +103 -0
  230. package/dist/fonts/virtual-modules.d.ts.map +1 -0
  231. package/dist/index.d.ts +46 -152
  232. package/dist/index.d.ts.map +1 -1
  233. package/dist/index.js +14702 -12350
  234. package/dist/index.js.map +1 -1
  235. package/dist/plugin-context.d.ts +107 -0
  236. package/dist/plugin-context.d.ts.map +1 -0
  237. package/dist/plugins/adapter-build.d.ts +1 -1
  238. package/dist/plugins/adapter-build.d.ts.map +1 -1
  239. package/dist/plugins/build-manifest.d.ts +2 -2
  240. package/dist/plugins/build-manifest.d.ts.map +1 -1
  241. package/dist/plugins/build-report.d.ts +16 -4
  242. package/dist/plugins/build-report.d.ts.map +1 -1
  243. package/dist/plugins/chunks.d.ts +9 -1
  244. package/dist/plugins/chunks.d.ts.map +1 -1
  245. package/dist/plugins/client-chunks.d.ts +32 -0
  246. package/dist/plugins/client-chunks.d.ts.map +1 -0
  247. package/dist/plugins/content.d.ts +1 -1
  248. package/dist/plugins/content.d.ts.map +1 -1
  249. package/dist/plugins/dev-server.d.ts +1 -1
  250. package/dist/plugins/dev-server.d.ts.map +1 -1
  251. package/dist/plugins/entries.d.ts +8 -1
  252. package/dist/plugins/entries.d.ts.map +1 -1
  253. package/dist/plugins/fonts.d.ts +17 -65
  254. package/dist/plugins/fonts.d.ts.map +1 -1
  255. package/dist/plugins/mdx.d.ts +7 -1
  256. package/dist/plugins/mdx.d.ts.map +1 -1
  257. package/dist/plugins/routing.d.ts +1 -1
  258. package/dist/plugins/routing.d.ts.map +1 -1
  259. package/dist/plugins/server-bundle.d.ts.map +1 -1
  260. package/dist/plugins/shims.d.ts +6 -5
  261. package/dist/plugins/shims.d.ts.map +1 -1
  262. package/dist/plugins/static-build.d.ts +4 -4
  263. package/dist/plugins/static-build.d.ts.map +1 -1
  264. package/dist/routing/codegen-shared.d.ts +55 -0
  265. package/dist/routing/codegen-shared.d.ts.map +1 -0
  266. package/dist/routing/codegen-types.d.ts +52 -0
  267. package/dist/routing/codegen-types.d.ts.map +1 -0
  268. package/dist/routing/codegen.d.ts +2 -2
  269. package/dist/routing/codegen.d.ts.map +1 -1
  270. package/dist/routing/convention-lint.d.ts +41 -0
  271. package/dist/routing/convention-lint.d.ts.map +1 -0
  272. package/dist/routing/index.d.ts +5 -1
  273. package/dist/routing/index.d.ts.map +1 -1
  274. package/dist/routing/index.js +3 -2
  275. package/dist/routing/link-codegen.d.ts +90 -0
  276. package/dist/routing/link-codegen.d.ts.map +1 -0
  277. package/dist/routing/scanner.d.ts +1 -10
  278. package/dist/routing/scanner.d.ts.map +1 -1
  279. package/dist/routing/segment-classify.d.ts +75 -0
  280. package/dist/routing/segment-classify.d.ts.map +1 -0
  281. package/dist/routing/status-file-lint.d.ts +2 -1
  282. package/dist/routing/status-file-lint.d.ts.map +1 -1
  283. package/dist/routing/types.d.ts +77 -25
  284. package/dist/routing/types.d.ts.map +1 -1
  285. package/dist/routing/walkers.d.ts +51 -0
  286. package/dist/routing/walkers.d.ts.map +1 -0
  287. package/dist/rsc-runtime/rsc.d.ts +1 -1
  288. package/dist/rsc-runtime/rsc.d.ts.map +1 -1
  289. package/dist/rsc-runtime/ssr.d.ts +12 -0
  290. package/dist/rsc-runtime/ssr.d.ts.map +1 -1
  291. package/dist/schema-bridge.d.ts +76 -0
  292. package/dist/schema-bridge.d.ts.map +1 -0
  293. package/dist/search-params/define.d.ts +157 -0
  294. package/dist/search-params/define.d.ts.map +1 -0
  295. package/dist/search-params/index.d.ts +4 -7
  296. package/dist/search-params/index.d.ts.map +1 -1
  297. package/dist/search-params/index.js +34 -441
  298. package/dist/search-params/index.js.map +1 -1
  299. package/dist/search-params/registry.d.ts +2 -2
  300. package/dist/search-params/registry.d.ts.map +1 -1
  301. package/dist/search-params/wrappers.d.ts +53 -0
  302. package/dist/search-params/wrappers.d.ts.map +1 -0
  303. package/dist/segment-params/define.d.ts +95 -0
  304. package/dist/segment-params/define.d.ts.map +1 -0
  305. package/dist/segment-params/index.d.ts +3 -0
  306. package/dist/segment-params/index.d.ts.map +1 -0
  307. package/dist/segment-params/index.js +2 -0
  308. package/dist/server/access-gate.d.ts +8 -3
  309. package/dist/server/access-gate.d.ts.map +1 -1
  310. package/dist/server/action-client.d.ts +41 -6
  311. package/dist/server/action-client.d.ts.map +1 -1
  312. package/dist/server/action-encryption.d.ts +76 -0
  313. package/dist/server/action-encryption.d.ts.map +1 -0
  314. package/dist/server/action-handler.d.ts +35 -1
  315. package/dist/server/action-handler.d.ts.map +1 -1
  316. package/dist/server/actions.d.ts +3 -6
  317. package/dist/server/actions.d.ts.map +1 -1
  318. package/dist/server/als-registry.d.ts +33 -5
  319. package/dist/server/als-registry.d.ts.map +1 -1
  320. package/dist/server/asset-headers.d.ts +1 -15
  321. package/dist/server/asset-headers.d.ts.map +1 -1
  322. package/dist/server/build-manifest.d.ts +2 -2
  323. package/dist/server/build-manifest.d.ts.map +1 -1
  324. package/dist/server/cookie-context.d.ts +170 -0
  325. package/dist/server/cookie-context.d.ts.map +1 -0
  326. package/dist/server/cookie-parsing.d.ts +51 -0
  327. package/dist/server/cookie-parsing.d.ts.map +1 -0
  328. package/dist/server/debug.d.ts +82 -0
  329. package/dist/server/debug.d.ts.map +1 -0
  330. package/dist/server/default-logger.d.ts +22 -0
  331. package/dist/server/default-logger.d.ts.map +1 -0
  332. package/dist/server/deny-boundary.d.ts +90 -0
  333. package/dist/server/deny-boundary.d.ts.map +1 -0
  334. package/dist/server/deny-renderer.d.ts.map +1 -1
  335. package/dist/server/dev-source-map.d.ts +22 -0
  336. package/dist/server/dev-source-map.d.ts.map +1 -0
  337. package/dist/server/early-hints-sender.d.ts.map +1 -1
  338. package/dist/server/early-hints.d.ts +13 -5
  339. package/dist/server/early-hints.d.ts.map +1 -1
  340. package/dist/server/error-boundary-wrapper.d.ts +7 -1
  341. package/dist/server/error-boundary-wrapper.d.ts.map +1 -1
  342. package/dist/server/fallback-error.d.ts +12 -7
  343. package/dist/server/fallback-error.d.ts.map +1 -1
  344. package/dist/server/flight-injection-state.d.ts +66 -0
  345. package/dist/server/flight-injection-state.d.ts.map +1 -0
  346. package/dist/server/flight-scripts.d.ts +42 -0
  347. package/dist/server/flight-scripts.d.ts.map +1 -0
  348. package/dist/server/flush.d.ts.map +1 -1
  349. package/dist/server/form-data.d.ts +29 -0
  350. package/dist/server/form-data.d.ts.map +1 -1
  351. package/dist/server/html-injector-core.d.ts +212 -0
  352. package/dist/server/html-injector-core.d.ts.map +1 -0
  353. package/dist/server/html-injectors.d.ts +81 -41
  354. package/dist/server/html-injectors.d.ts.map +1 -1
  355. package/dist/server/index.d.ts +9 -46
  356. package/dist/server/index.d.ts.map +1 -1
  357. package/dist/server/index.js +158 -2899
  358. package/dist/server/index.js.map +1 -1
  359. package/dist/server/internal.d.ts +48 -0
  360. package/dist/server/internal.d.ts.map +1 -0
  361. package/dist/server/internal.js +2900 -0
  362. package/dist/server/internal.js.map +1 -0
  363. package/dist/server/logger.d.ts +39 -7
  364. package/dist/server/logger.d.ts.map +1 -1
  365. package/dist/server/middleware-runner.d.ts +36 -4
  366. package/dist/server/middleware-runner.d.ts.map +1 -1
  367. package/dist/server/node-stream-transforms.d.ts +110 -0
  368. package/dist/server/node-stream-transforms.d.ts.map +1 -0
  369. package/dist/server/param-coercion.d.ts +26 -0
  370. package/dist/server/param-coercion.d.ts.map +1 -0
  371. package/dist/server/pipeline-helpers.d.ts +95 -0
  372. package/dist/server/pipeline-helpers.d.ts.map +1 -0
  373. package/dist/server/pipeline-interception.d.ts +1 -1
  374. package/dist/server/pipeline-interception.d.ts.map +1 -1
  375. package/dist/server/pipeline-metadata.d.ts +6 -0
  376. package/dist/server/pipeline-metadata.d.ts.map +1 -1
  377. package/dist/server/pipeline-outcome.d.ts +49 -0
  378. package/dist/server/pipeline-outcome.d.ts.map +1 -0
  379. package/dist/server/pipeline-phases.d.ts +52 -0
  380. package/dist/server/pipeline-phases.d.ts.map +1 -0
  381. package/dist/server/pipeline.d.ts +93 -23
  382. package/dist/server/pipeline.d.ts.map +1 -1
  383. package/dist/server/port-resolution.d.ts +117 -0
  384. package/dist/server/port-resolution.d.ts.map +1 -0
  385. package/dist/server/primitives.d.ts +69 -18
  386. package/dist/server/primitives.d.ts.map +1 -1
  387. package/dist/server/render-timeout.d.ts +51 -0
  388. package/dist/server/render-timeout.d.ts.map +1 -0
  389. package/dist/server/request-context.d.ts +41 -109
  390. package/dist/server/request-context.d.ts.map +1 -1
  391. package/dist/server/route-element-builder.d.ts +27 -1
  392. package/dist/server/route-element-builder.d.ts.map +1 -1
  393. package/dist/server/route-handler.d.ts.map +1 -1
  394. package/dist/server/route-matcher.d.ts +21 -34
  395. package/dist/server/route-matcher.d.ts.map +1 -1
  396. package/dist/server/rsc-entry/action-middleware-runner.d.ts +66 -0
  397. package/dist/server/rsc-entry/action-middleware-runner.d.ts.map +1 -0
  398. package/dist/server/rsc-entry/api-handler.d.ts +2 -2
  399. package/dist/server/rsc-entry/api-handler.d.ts.map +1 -1
  400. package/dist/server/rsc-entry/error-renderer.d.ts +26 -13
  401. package/dist/server/rsc-entry/error-renderer.d.ts.map +1 -1
  402. package/dist/server/rsc-entry/helpers.d.ts +49 -6
  403. package/dist/server/rsc-entry/helpers.d.ts.map +1 -1
  404. package/dist/server/rsc-entry/index.d.ts +20 -3
  405. package/dist/server/rsc-entry/index.d.ts.map +1 -1
  406. package/dist/server/rsc-entry/render-route.d.ts +50 -0
  407. package/dist/server/rsc-entry/render-route.d.ts.map +1 -0
  408. package/dist/server/rsc-entry/rsc-payload.d.ts +3 -3
  409. package/dist/server/rsc-entry/rsc-payload.d.ts.map +1 -1
  410. package/dist/server/rsc-entry/rsc-stream.d.ts +20 -1
  411. package/dist/server/rsc-entry/rsc-stream.d.ts.map +1 -1
  412. package/dist/server/rsc-entry/ssr-bridge.d.ts +1 -1
  413. package/dist/server/rsc-entry/ssr-bridge.d.ts.map +1 -1
  414. package/dist/server/rsc-entry/ssr-renderer.d.ts +19 -4
  415. package/dist/server/rsc-entry/ssr-renderer.d.ts.map +1 -1
  416. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts +119 -0
  417. package/dist/server/rsc-entry/wrap-action-dispatch.d.ts.map +1 -0
  418. package/dist/server/rsc-prop-warnings.d.ts.map +1 -1
  419. package/dist/server/safe-load.d.ts +46 -0
  420. package/dist/server/safe-load.d.ts.map +1 -0
  421. package/dist/server/sensitive-fields.d.ts +74 -0
  422. package/dist/server/sensitive-fields.d.ts.map +1 -0
  423. package/dist/server/sitemap-generator.d.ts +129 -0
  424. package/dist/server/sitemap-generator.d.ts.map +1 -0
  425. package/dist/server/sitemap-handler.d.ts +22 -0
  426. package/dist/server/sitemap-handler.d.ts.map +1 -0
  427. package/dist/server/slot-resolver.d.ts +1 -1
  428. package/dist/server/slot-resolver.d.ts.map +1 -1
  429. package/dist/server/ssr-entry.d.ts +23 -0
  430. package/dist/server/ssr-entry.d.ts.map +1 -1
  431. package/dist/server/ssr-render.d.ts +39 -21
  432. package/dist/server/ssr-render.d.ts.map +1 -1
  433. package/dist/server/ssr-wrappers.d.ts +50 -0
  434. package/dist/server/ssr-wrappers.d.ts.map +1 -0
  435. package/dist/server/state-tree-diff.d.ts.map +1 -1
  436. package/dist/server/status-code-resolver.d.ts +16 -11
  437. package/dist/server/status-code-resolver.d.ts.map +1 -1
  438. package/dist/server/stream-utils.d.ts +36 -0
  439. package/dist/server/stream-utils.d.ts.map +1 -0
  440. package/dist/server/tracing.d.ts +15 -5
  441. package/dist/server/tracing.d.ts.map +1 -1
  442. package/dist/server/tree-builder.d.ts +62 -30
  443. package/dist/server/tree-builder.d.ts.map +1 -1
  444. package/dist/server/types.d.ts +49 -4
  445. package/dist/server/types.d.ts.map +1 -1
  446. package/dist/server/utils/escape-html.d.ts +14 -0
  447. package/dist/server/utils/escape-html.d.ts.map +1 -0
  448. package/dist/server/version-skew.d.ts +61 -0
  449. package/dist/server/version-skew.d.ts.map +1 -0
  450. package/dist/server/waituntil-bridge.d.ts.map +1 -1
  451. package/dist/shared/merge-search-params.d.ts +22 -0
  452. package/dist/shared/merge-search-params.d.ts.map +1 -0
  453. package/dist/shims/font-google.d.ts +1 -1
  454. package/dist/shims/font-google.d.ts.map +1 -1
  455. package/dist/shims/font-google.js +42 -0
  456. package/dist/shims/font-google.js.map +1 -0
  457. package/dist/shims/font-local.d.ts +26 -0
  458. package/dist/shims/font-local.d.ts.map +1 -0
  459. package/dist/shims/font-local.js +20 -0
  460. package/dist/shims/font-local.js.map +1 -0
  461. package/dist/shims/headers.d.ts +2 -1
  462. package/dist/shims/headers.d.ts.map +1 -1
  463. package/dist/shims/navigation-client.d.ts +3 -1
  464. package/dist/shims/navigation-client.d.ts.map +1 -1
  465. package/dist/shims/navigation.d.ts +11 -5
  466. package/dist/shims/navigation.d.ts.map +1 -1
  467. package/dist/utils/directive-parser.d.ts +1 -43
  468. package/dist/utils/directive-parser.d.ts.map +1 -1
  469. package/dist/utils/state-machine.d.ts +80 -0
  470. package/dist/utils/state-machine.d.ts.map +1 -0
  471. package/package.json +56 -22
  472. package/src/adapters/build-output-helper.ts +77 -0
  473. package/src/adapters/cloudflare-dev.ts +177 -0
  474. package/src/adapters/cloudflare-kv-cache.ts +142 -0
  475. package/src/adapters/cloudflare.ts +350 -76
  476. package/src/adapters/compress-module.ts +24 -4
  477. package/src/adapters/nitro.ts +148 -60
  478. package/src/adapters/shared.ts +40 -0
  479. package/src/adapters/wrangler.d.ts +7 -0
  480. package/src/cache/cache-api.ts +38 -0
  481. package/src/cache/fast-hash.ts +34 -0
  482. package/src/cache/handler-store.ts +68 -0
  483. package/src/cache/index.ts +81 -18
  484. package/src/cache/singleflight.ts +62 -4
  485. package/src/cache/sizeof.ts +31 -0
  486. package/src/cache/timber-cache.ts +41 -29
  487. package/src/cli.ts +16 -6
  488. package/src/client/browser-dev.ts +153 -1
  489. package/src/client/browser-entry/action-dispatch.ts +116 -0
  490. package/src/client/browser-entry/hmr.ts +81 -0
  491. package/src/client/browser-entry/hydrate.ts +145 -0
  492. package/src/client/browser-entry/index.ts +143 -0
  493. package/src/client/browser-entry/post-hydration.ts +119 -0
  494. package/src/client/browser-entry/router-init.ts +193 -0
  495. package/src/client/browser-entry/rsc-stream.ts +157 -0
  496. package/src/client/browser-entry/scroll.ts +27 -0
  497. package/src/client/error-boundary.tsx +97 -20
  498. package/src/client/error-reconstituter.tsx +65 -0
  499. package/src/client/form.tsx +31 -32
  500. package/src/client/history.ts +26 -4
  501. package/src/client/index.ts +77 -43
  502. package/src/client/internal.ts +58 -0
  503. package/src/client/link-pending-store.ts +111 -0
  504. package/src/client/link.tsx +432 -140
  505. package/src/client/nav-link-store.ts +47 -0
  506. package/src/client/navigation-api-types.ts +112 -0
  507. package/src/client/navigation-api.ts +332 -0
  508. package/src/client/navigation-context.ts +83 -18
  509. package/src/client/navigation-root.tsx +342 -0
  510. package/src/client/nuqs-adapter.tsx +16 -3
  511. package/src/client/router-ref.ts +1 -1
  512. package/src/client/router.ts +303 -78
  513. package/src/client/rsc-fetch.ts +112 -8
  514. package/src/client/segment-cache.ts +1 -1
  515. package/src/client/segment-context.ts +6 -1
  516. package/src/client/segment-merger.ts +2 -8
  517. package/src/client/segment-outlet.tsx +86 -0
  518. package/src/client/ssr-data.ts +13 -5
  519. package/src/client/stale-reload.ts +74 -7
  520. package/src/client/state.ts +2 -2
  521. package/src/client/top-loader.tsx +41 -25
  522. package/src/client/use-cookie.ts +29 -0
  523. package/src/client/use-link-status.ts +7 -7
  524. package/src/client/{use-navigation-pending.ts → use-pending-navigation.ts} +6 -6
  525. package/src/client/use-query-states.ts +9 -3
  526. package/src/client/use-router.ts +1 -1
  527. package/src/client/{use-params.ts → use-segment-params.ts} +7 -5
  528. package/src/codec.ts +45 -0
  529. package/src/config-types.ts +292 -0
  530. package/src/config-validation.ts +303 -0
  531. package/src/content/index.ts +5 -13
  532. package/src/cookies/define-cookie.ts +301 -55
  533. package/src/cookies/index.ts +12 -1
  534. package/src/cookies/json-cookie.ts +105 -0
  535. package/src/cookies/validation.ts +134 -0
  536. package/src/dev-tools/404-page.ts +387 -0
  537. package/src/dev-tools/browser-logs.ts +288 -0
  538. package/src/dev-tools/error-page.ts +509 -0
  539. package/src/dev-tools/holding-server.ts +187 -0
  540. package/src/dev-tools/index.ts +90 -0
  541. package/src/dev-tools/instrumentation.ts +176 -0
  542. package/src/{plugins/dev-logs.ts → dev-tools/logs.ts} +3 -3
  543. package/src/dev-tools/overlay.ts +456 -0
  544. package/src/dev-tools/stack-classifier.ts +75 -0
  545. package/src/dev-tools/terminal.ts +183 -0
  546. package/src/{server/dev-warnings.ts → dev-tools/warnings.ts} +6 -50
  547. package/src/fonts/bundle.ts +142 -0
  548. package/src/fonts/css.ts +2 -1
  549. package/src/fonts/dev-middleware.ts +74 -0
  550. package/src/fonts/local.ts +7 -3
  551. package/src/fonts/pipeline.ts +314 -0
  552. package/src/fonts/transform.ts +406 -0
  553. package/src/fonts/types.ts +50 -1
  554. package/src/fonts/virtual-modules.ts +227 -0
  555. package/src/index.ts +376 -315
  556. package/src/plugin-context.ts +240 -0
  557. package/src/plugins/adapter-build.ts +12 -4
  558. package/src/plugins/build-manifest.ts +13 -2
  559. package/src/plugins/build-report.ts +32 -21
  560. package/src/plugins/chunks.ts +9 -1
  561. package/src/plugins/client-chunks.ts +65 -0
  562. package/src/plugins/content.ts +1 -1
  563. package/src/plugins/dev-server.ts +154 -21
  564. package/src/plugins/entries.ts +119 -12
  565. package/src/plugins/fonts.ts +177 -524
  566. package/src/plugins/mdx.ts +52 -15
  567. package/src/plugins/routing.ts +225 -41
  568. package/src/plugins/server-action-exports.ts +1 -1
  569. package/src/plugins/server-bundle.ts +36 -1
  570. package/src/plugins/shims.ts +136 -35
  571. package/src/plugins/static-build.ts +17 -11
  572. package/src/routing/codegen-shared.ts +98 -0
  573. package/src/routing/codegen-types.ts +53 -0
  574. package/src/routing/codegen.ts +143 -176
  575. package/src/routing/convention-lint.ts +357 -0
  576. package/src/routing/index.ts +5 -1
  577. package/src/routing/interception.ts +1 -1
  578. package/src/routing/link-codegen.ts +294 -0
  579. package/src/routing/scanner.ts +107 -110
  580. package/src/routing/segment-classify.ts +188 -0
  581. package/src/routing/status-file-lint.ts +10 -7
  582. package/src/routing/types.ts +78 -25
  583. package/src/routing/walkers.ts +90 -0
  584. package/src/rsc-runtime/rsc.ts +2 -0
  585. package/src/rsc-runtime/ssr.ts +50 -0
  586. package/src/rsc-runtime/vendor-types.d.ts +7 -0
  587. package/src/{search-params/codecs.ts → schema-bridge.ts} +57 -20
  588. package/src/search-params/define.ts +538 -0
  589. package/src/search-params/index.ts +14 -20
  590. package/src/search-params/registry.ts +2 -2
  591. package/src/search-params/wrappers.ts +92 -0
  592. package/src/segment-params/define.ts +332 -0
  593. package/src/segment-params/index.ts +9 -0
  594. package/src/server/access-gate.tsx +79 -36
  595. package/src/server/action-client.ts +103 -20
  596. package/src/server/action-encryption.ts +144 -0
  597. package/src/server/action-handler.ts +112 -14
  598. package/src/server/actions.ts +10 -9
  599. package/src/server/als-registry.ts +35 -7
  600. package/src/server/asset-headers.ts +8 -34
  601. package/src/server/build-manifest.ts +10 -4
  602. package/src/server/compress.ts +25 -7
  603. package/src/server/cookie-context.ts +468 -0
  604. package/src/server/cookie-parsing.ts +135 -0
  605. package/src/server/debug.ts +137 -0
  606. package/src/server/default-logger.ts +99 -0
  607. package/src/server/deny-boundary.ts +218 -0
  608. package/src/server/deny-renderer.ts +33 -51
  609. package/src/server/dev-source-map.ts +31 -0
  610. package/src/server/early-hints-sender.ts +3 -2
  611. package/src/server/early-hints.ts +36 -15
  612. package/src/server/error-boundary-wrapper.ts +74 -22
  613. package/src/server/fallback-error.ts +74 -102
  614. package/src/server/flight-injection-state.ts +113 -0
  615. package/src/server/flight-scripts.ts +62 -0
  616. package/src/server/flush.ts +2 -1
  617. package/src/server/form-data.ts +76 -0
  618. package/src/server/html-injector-core.ts +403 -0
  619. package/src/server/html-injectors.ts +244 -223
  620. package/src/server/index.ts +31 -184
  621. package/src/server/internal.ts +176 -0
  622. package/src/server/logger.ts +67 -35
  623. package/src/server/middleware-runner.ts +75 -4
  624. package/src/server/node-stream-transforms.ts +369 -0
  625. package/src/server/param-coercion.ts +76 -0
  626. package/src/server/pipeline-helpers.ts +204 -0
  627. package/src/server/pipeline-interception.ts +17 -16
  628. package/src/server/pipeline-metadata.ts +13 -0
  629. package/src/server/pipeline-outcome.ts +167 -0
  630. package/src/server/pipeline-phases.ts +409 -0
  631. package/src/server/pipeline.ts +128 -387
  632. package/src/server/port-resolution.ts +215 -0
  633. package/src/server/primitives.ts +113 -29
  634. package/src/server/render-timeout.ts +108 -0
  635. package/src/server/request-context.ts +94 -337
  636. package/src/server/route-element-builder.ts +289 -198
  637. package/src/server/route-handler.ts +24 -4
  638. package/src/server/route-matcher.ts +44 -65
  639. package/src/server/rsc-entry/action-middleware-runner.ts +167 -0
  640. package/src/server/rsc-entry/api-handler.ts +16 -17
  641. package/src/server/rsc-entry/error-renderer.ts +305 -89
  642. package/src/server/rsc-entry/helpers.ts +136 -12
  643. package/src/server/rsc-entry/index.ts +330 -312
  644. package/src/server/rsc-entry/render-route.ts +304 -0
  645. package/src/server/rsc-entry/rsc-payload.ts +100 -18
  646. package/src/server/rsc-entry/rsc-stream.ts +90 -17
  647. package/src/server/rsc-entry/ssr-bridge.ts +14 -5
  648. package/src/server/rsc-entry/ssr-renderer.ts +177 -37
  649. package/src/server/rsc-entry/wrap-action-dispatch.ts +449 -0
  650. package/src/server/rsc-prop-warnings.ts +3 -1
  651. package/src/server/safe-load.ts +60 -0
  652. package/src/server/sensitive-fields.ts +230 -0
  653. package/src/server/sitemap-generator.ts +338 -0
  654. package/src/server/sitemap-handler.ts +126 -0
  655. package/src/server/slot-resolver.ts +245 -230
  656. package/src/server/ssr-entry.ts +215 -32
  657. package/src/server/ssr-render.ts +289 -67
  658. package/src/server/ssr-wrappers.tsx +139 -0
  659. package/src/server/state-tree-diff.ts +4 -1
  660. package/src/server/status-code-resolver.ts +112 -128
  661. package/src/server/stream-utils.ts +213 -0
  662. package/src/server/tracing.ts +44 -10
  663. package/src/server/tree-builder.ts +202 -90
  664. package/src/server/types.ts +55 -6
  665. package/src/server/utils/escape-html.ts +20 -0
  666. package/src/server/version-skew.ts +104 -0
  667. package/src/server/waituntil-bridge.ts +4 -1
  668. package/src/shared/merge-search-params.ts +55 -0
  669. package/src/shims/font-google.ts +1 -1
  670. package/src/shims/font-local.ts +34 -0
  671. package/src/shims/headers.ts +5 -1
  672. package/src/shims/navigation-client.ts +4 -3
  673. package/src/shims/navigation.ts +14 -7
  674. package/src/utils/directive-parser.ts +1 -390
  675. package/src/utils/state-machine.ts +111 -0
  676. package/dist/_chunks/als-registry-k-AtAQ9R.js +0 -41
  677. package/dist/_chunks/als-registry-k-AtAQ9R.js.map +0 -1
  678. package/dist/_chunks/format-DNt20Kt8.js.map +0 -1
  679. package/dist/_chunks/interception-DGDIjDbR.js +0 -676
  680. package/dist/_chunks/interception-DGDIjDbR.js.map +0 -1
  681. package/dist/_chunks/request-context-CRj2Zh1E.js +0 -329
  682. package/dist/_chunks/request-context-CRj2Zh1E.js.map +0 -1
  683. package/dist/_chunks/ssr-data-DLnbYpj1.js.map +0 -1
  684. package/dist/_chunks/tracing-DF0G3FB7.js +0 -173
  685. package/dist/_chunks/tracing-DF0G3FB7.js.map +0 -1
  686. package/dist/_chunks/use-cookie-dDbpCTx-.js +0 -91
  687. package/dist/_chunks/use-cookie-dDbpCTx-.js.map +0 -1
  688. package/dist/_chunks/use-query-states-DAhgj8Gx.js.map +0 -1
  689. package/dist/cache/register-cached-function.d.ts +0 -17
  690. package/dist/cache/register-cached-function.d.ts.map +0 -1
  691. package/dist/client/browser-entry.d.ts +0 -22
  692. package/dist/client/browser-entry.d.ts.map +0 -1
  693. package/dist/client/browser-links.d.ts +0 -32
  694. package/dist/client/browser-links.d.ts.map +0 -1
  695. package/dist/client/link-navigate-interceptor.d.ts +0 -28
  696. package/dist/client/link-navigate-interceptor.d.ts.map +0 -1
  697. package/dist/client/link-status-provider.d.ts +0 -11
  698. package/dist/client/link-status-provider.d.ts.map +0 -1
  699. package/dist/client/transition-root.d.ts.map +0 -1
  700. package/dist/client/use-navigation-pending.d.ts.map +0 -1
  701. package/dist/client/use-params.d.ts.map +0 -1
  702. package/dist/plugins/cache-transform.d.ts +0 -36
  703. package/dist/plugins/cache-transform.d.ts.map +0 -1
  704. package/dist/plugins/dev-error-overlay.d.ts +0 -60
  705. package/dist/plugins/dev-error-overlay.d.ts.map +0 -1
  706. package/dist/plugins/dev-logs.d.ts.map +0 -1
  707. package/dist/plugins/dynamic-transform.d.ts +0 -72
  708. package/dist/plugins/dynamic-transform.d.ts.map +0 -1
  709. package/dist/search-params/analyze.d.ts +0 -54
  710. package/dist/search-params/analyze.d.ts.map +0 -1
  711. package/dist/search-params/builtin-codecs.d.ts +0 -105
  712. package/dist/search-params/builtin-codecs.d.ts.map +0 -1
  713. package/dist/search-params/codecs.d.ts +0 -53
  714. package/dist/search-params/codecs.d.ts.map +0 -1
  715. package/dist/search-params/create.d.ts +0 -106
  716. package/dist/search-params/create.d.ts.map +0 -1
  717. package/dist/server/dev-fetch-instrumentation.d.ts +0 -22
  718. package/dist/server/dev-fetch-instrumentation.d.ts.map +0 -1
  719. package/dist/server/dev-logger.d.ts.map +0 -1
  720. package/dist/server/dev-span-processor.d.ts.map +0 -1
  721. package/dist/server/dev-warnings.d.ts.map +0 -1
  722. package/dist/server/manifest-status-resolver.d.ts +0 -58
  723. package/dist/server/manifest-status-resolver.d.ts.map +0 -1
  724. package/dist/server/prerender.d.ts +0 -77
  725. package/dist/server/prerender.d.ts.map +0 -1
  726. package/src/cache/register-cached-function.ts +0 -99
  727. package/src/client/browser-entry.ts +0 -686
  728. package/src/client/browser-links.ts +0 -90
  729. package/src/client/link-navigate-interceptor.tsx +0 -62
  730. package/src/client/link-status-provider.tsx +0 -30
  731. package/src/client/transition-root.tsx +0 -160
  732. package/src/plugins/cache-transform.ts +0 -199
  733. package/src/plugins/dev-error-overlay.ts +0 -230
  734. package/src/plugins/dynamic-transform.ts +0 -161
  735. package/src/search-params/analyze.ts +0 -192
  736. package/src/search-params/builtin-codecs.ts +0 -228
  737. package/src/search-params/create.ts +0 -321
  738. package/src/server/dev-fetch-instrumentation.ts +0 -96
  739. package/src/server/dev-span-processor.ts +0 -78
  740. package/src/server/manifest-status-resolver.ts +0 -215
  741. package/src/server/prerender.ts +0 -139
  742. /package/src/{server/dev-logger.ts → dev-tools/logger.ts} +0 -0
@@ -1,581 +1,234 @@
1
1
  /**
2
- * timber-fonts — Vite sub-plugin for build-time font processing.
2
+ * timber-fonts — Vite sub-plugin shell for build-time font processing.
3
3
  *
4
- * Handles:
5
- * - Virtual module resolution for `@timber/fonts/google` and `@timber/fonts/local`
6
- * - Static analysis of font function calls during `transform`
7
- * - @font-face CSS generation and scoped class output
8
- * - Size-adjusted fallback font generation
4
+ * This file is intentionally thin: it wires the Vite plugin hooks to the
5
+ * pipeline + per-concern modules under `../fonts/`. All real logic lives
6
+ * in:
9
7
  *
10
- * Does NOT handle (separate tasks):
11
- * - Google Fonts downloading/caching (timber-nk5)
12
- * - Build manifest / Early Hints integration (timber-qnx)
8
+ * - `../fonts/pipeline.ts` — `FontPipeline` (state, mutators)
9
+ * - `../fonts/transform.ts` — transform-hook logic, parsing helpers
10
+ * - `../fonts/dev-middleware.ts` — dev font binary server
11
+ * - `../fonts/virtual-modules.ts` — virtual module ID constants + source
12
+ *
13
+ * The public exports below are the stable API that the test suite and
14
+ * other parts of the framework import. Anything new should be added to
15
+ * one of the per-concern modules and re-exported here only if external
16
+ * consumers need it.
13
17
  *
14
18
  * Design doc: 24-fonts.md
15
19
  */
16
20
 
17
- import type { Plugin } from 'vite';
18
- import type { PluginContext } from '#/index.js';
19
- import type { ExtractedFont, GoogleFontConfig } from '#/fonts/types.js';
20
- import type { ManifestFontEntry } from '#/server/build-manifest.js';
21
- import { generateVariableClass, generateFontFamilyClass } from '#/fonts/css.js';
22
- import { generateFallbackCss, buildFontStack } from '#/fonts/fallbacks.js';
23
- import { processLocalFont } from '#/fonts/local.js';
24
- import { inferFontFormat } from '#/fonts/local.js';
25
- import { downloadAndCacheFonts, type CachedFont } from '#/fonts/google.js';
21
+ import type { Plugin, ViteDevServer } from 'vite';
22
+ import type { PluginContext } from '../plugin-context.js';
26
23
  import {
27
- extractFontConfigAst,
28
- extractLocalFontConfigAst,
29
- detectDynamicFontCallAst,
30
- } from '#/fonts/ast.js';
31
-
32
- const VIRTUAL_GOOGLE = '@timber/fonts/google';
33
- const VIRTUAL_LOCAL = '@timber/fonts/local';
34
- const RESOLVED_GOOGLE = '\0@timber/fonts/google';
35
- const RESOLVED_LOCAL = '\0@timber/fonts/local';
36
-
37
- /**
38
- * Registry of fonts extracted during transform.
39
- * Keyed by a unique font ID derived from family + config.
40
- */
41
- export type FontRegistry = Map<string, ExtractedFont>;
42
-
43
- /**
44
- * Convert a font family name to a PascalCase export name.
45
- * e.g. "JetBrains Mono" → "JetBrains_Mono"
46
- */
47
- function familyToExportName(family: string): string {
48
- return family.replace(/\s+/g, '_');
49
- }
50
-
51
- /**
52
- * Convert a font family name to a scoped class name.
53
- * e.g. "JetBrains Mono" → "timber-font-jetbrains-mono"
54
- */
55
- function familyToClassName(family: string): string {
56
- return `timber-font-${family.toLowerCase().replace(/\s+/g, '-')}`;
57
- }
58
-
59
- /**
60
- * Generate a unique font ID from family + config hash.
61
- */
62
- function generateFontId(family: string, config: GoogleFontConfig): string {
63
- const weights = normalizeToArray(config.weight);
64
- const styles = normalizeToArray(config.style);
65
- const subsets = config.subsets ?? ['latin'];
66
- return `${family.toLowerCase()}-${weights.join(',')}-${styles.join(',')}-${subsets.join(',')}`;
67
- }
68
-
69
- /**
70
- * Normalize a string or string array to an array.
71
- */
72
- function normalizeToArray(value: string | string[] | undefined): string[] {
73
- if (!value) return ['400'];
74
- return Array.isArray(value) ? value : [value];
75
- }
76
-
77
- /**
78
- * Normalize style to an array.
79
- */
80
- function normalizeStyleArray(value: string | string[] | undefined): string[] {
81
- if (!value) return ['normal'];
82
- return Array.isArray(value) ? value : [value];
83
- }
84
-
85
- /**
86
- * Extract static font config from a font function call in source code.
87
- *
88
- * Parses patterns like:
89
- * const inter = Inter({ subsets: ['latin'], weight: '400', display: 'swap', variable: '--font-sans' })
90
- *
91
- * Returns null if the call cannot be statically analyzed.
92
- *
93
- * Uses acorn AST parsing for robust handling of comments, trailing commas,
94
- * and multi-line configs.
95
- */
96
- export function extractFontConfig(callSource: string): GoogleFontConfig | null {
97
- return extractFontConfigAst(callSource);
98
- }
99
-
100
- /**
101
- * Detect if a source file contains dynamic/computed font function calls
102
- * that cannot be statically analyzed.
103
- *
104
- * Returns the offending expression if found, null if all calls are static.
105
- *
106
- * Uses acorn AST parsing for accurate detection.
107
- */
108
- export function detectDynamicFontCall(source: string, importedNames: string[]): string | null {
109
- return detectDynamicFontCallAst(source, importedNames);
110
- }
111
-
112
- /**
113
- * Regex that matches imports from either `@timber/fonts/google` or `next/font/google`.
114
- * The shims plugin resolves `next/font/google` to the same virtual module,
115
- * but the source code still contains the original import specifier.
116
- */
117
- const GOOGLE_FONT_IMPORT_RE =
118
- /import\s*\{([^}]+)\}\s*from\s*['"](?:@timber\/fonts\/google|next\/font\/google)['"]/g;
119
-
120
- /**
121
- * Parse import specifiers from a source file that imports from
122
- * `@timber/fonts/google` or `next/font/google`.
123
- *
124
- * Returns the list of imported font names (e.g. ['Inter', 'JetBrains_Mono']).
125
- */
126
- export function parseGoogleFontImports(source: string): string[] {
127
- const importPattern = new RegExp(GOOGLE_FONT_IMPORT_RE.source, 'g');
128
- const names: string[] = [];
129
-
130
- let match;
131
- while ((match = importPattern.exec(source)) !== null) {
132
- const specifiers = match[1]
133
- .split(',')
134
- .map((s) => s.trim())
135
- .filter(Boolean);
136
- for (const spec of specifiers) {
137
- // Handle `Inter as MyInter` — we want the local name
138
- const parts = spec.split(/\s+as\s+/);
139
- names.push(parts[parts.length - 1].trim());
140
- }
141
- }
142
-
143
- return names;
144
- }
145
-
146
- /**
147
- * Parse the original (remote) font family names from imports.
148
- *
149
- * Returns a map of local name → family name.
150
- * e.g. { Inter: 'Inter', JetBrains_Mono: 'JetBrains Mono' }
151
- */
152
- export function parseGoogleFontFamilies(source: string): Map<string, string> {
153
- const importPattern = new RegExp(GOOGLE_FONT_IMPORT_RE.source, 'g');
154
- const families = new Map<string, string>();
155
-
156
- let match;
157
- while ((match = importPattern.exec(source)) !== null) {
158
- const specifiers = match[1]
159
- .split(',')
160
- .map((s) => s.trim())
161
- .filter(Boolean);
162
- for (const spec of specifiers) {
163
- const parts = spec.split(/\s+as\s+/);
164
- const originalName = parts[0].trim();
165
- const localName = parts[parts.length - 1].trim();
166
- // Convert export name back to family name: JetBrains_Mono → JetBrains Mono
167
- const family = originalName.replace(/_/g, ' ');
168
- families.set(localName, family);
169
- }
170
- }
171
-
172
- return families;
173
- }
174
-
175
- /**
176
- * Generate the virtual module source for `@timber/fonts/google`.
177
- *
178
- * Each Google Font family gets a named export that returns a FontResult.
179
- * In this base implementation, the functions return static data.
180
- * The Google Fonts download task (timber-nk5) will add real font file URLs.
181
- */
182
- function generateGoogleVirtualModule(registry: FontRegistry): string {
183
- // Collect unique families from the registry
184
- const families = new Set<string>();
185
- for (const font of registry.values()) {
186
- if (font.provider === 'google') families.add(font.family);
187
- }
188
-
189
- const lines = [
190
- '// Auto-generated virtual module: @timber/fonts/google',
191
- '// Each export is a font loader function that returns a FontResult.',
192
- '',
193
- ];
194
-
195
- // If no fonts registered yet, export a generic loader for any font
196
- // This is the initial load — the transform hook will process actual calls
197
- lines.push('function createFontResult(family, config) {');
198
- lines.push(' return {');
199
- lines.push(' className: `timber-font-${family.toLowerCase().replace(/\\s+/g, "-")}`,');
200
- lines.push(' style: { fontFamily: family },');
201
- lines.push(' variable: config?.variable,');
202
- lines.push(' };');
203
- lines.push('}');
204
- lines.push('');
205
-
206
- // Export a Proxy-based default that handles any font name import
207
- lines.push('export default new Proxy({}, {');
208
- lines.push(' get(_, prop) {');
209
- lines.push(' if (typeof prop === "string") {');
210
- lines.push(' return (config) => createFontResult(prop.replace(/_/g, " "), config);');
211
- lines.push(' }');
212
- lines.push(' }');
213
- lines.push('});');
214
-
215
- // Also export known families as named exports for tree-shaking
216
- for (const family of families) {
217
- const exportName = familyToExportName(family);
218
- lines.push('');
219
- lines.push(`export function ${exportName}(config) {`);
220
- lines.push(` return createFontResult('${family}', config);`);
221
- lines.push('}');
222
- }
223
-
224
- return lines.join('\n');
225
- }
226
-
227
- /**
228
- * Generate the virtual module source for `@timber/fonts/local`.
229
- */
230
- function generateLocalVirtualModule(): string {
231
- return [
232
- '// Auto-generated virtual module: @timber/fonts/local',
233
- '',
234
- 'export default function localFont(config) {',
235
- ' const family = config?.family || "Local Font";',
236
- ' return {',
237
- ' className: `timber-font-${family.toLowerCase().replace(/\\s+/g, "-")}`,',
238
- ' style: { fontFamily: family },',
239
- ' variable: config?.variable,',
240
- ' };',
241
- '}',
242
- ].join('\n');
243
- }
244
-
245
- /**
246
- * Generate the CSS output for all extracted fonts.
247
- *
248
- * Includes @font-face rules, fallback @font-face rules, and scoped classes.
249
- */
250
- export function generateAllFontCss(registry: FontRegistry): string {
251
- const cssParts: string[] = [];
252
-
253
- for (const font of registry.values()) {
254
- // Generate fallback @font-face if metrics are available
255
- const fallbackCss = generateFallbackCss(font.family);
256
- if (fallbackCss) cssParts.push(fallbackCss);
257
-
258
- // Generate scoped class
259
- if (font.variable) {
260
- cssParts.push(generateVariableClass(font.className, font.variable, font.fontFamily));
261
- } else {
262
- cssParts.push(generateFontFamilyClass(font.className, font.fontFamily));
263
- }
264
- }
265
-
266
- return cssParts.join('\n\n');
267
- }
268
-
269
- /**
270
- * Parse the local name used for the default import of `@timber/fonts/local`.
271
- *
272
- * Handles:
273
- * import localFont from '@timber/fonts/local'
274
- * import myLoader from '@timber/fonts/local'
275
- */
276
- export function parseLocalFontImportName(source: string): string | null {
277
- const match = source.match(
278
- /import\s+(\w+)\s+from\s*['"](?:@timber\/fonts\/local|next\/font\/local)['"]/
279
- );
280
- return match ? match[1] : null;
281
- }
282
-
283
- /**
284
- * Transform local font calls in source code.
285
- *
286
- * Finds `localFont({ ... })` calls, extracts the config,
287
- * registers the font, and replaces the call with a static FontResult.
288
- */
289
- function transformLocalFonts(
290
- transformedCode: string,
291
- originalCode: string,
292
- importerId: string,
293
- registry: FontRegistry,
294
- emitError: (msg: string) => void
295
- ): string {
296
- const localName = parseLocalFontImportName(originalCode);
297
- if (!localName) return transformedCode;
298
-
299
- // Check for dynamic calls
300
- const dynamicCall = detectDynamicFontCall(originalCode, [localName]);
301
- if (dynamicCall) {
302
- emitError(
303
- `Font function calls must be statically analyzable. ` +
304
- `Found dynamic call: ${dynamicCall}. ` +
305
- `Pass a literal object with string/array values instead.`
306
- );
307
- }
308
-
309
- // Find all calls: const varName = localFont({ ... })
310
- const callPattern = new RegExp(
311
- `(?:const|let|var)\\s+(\\w+)\\s*=\\s*${localName}\\s*\\(\\s*(\\{[\\s\\S]*?\\})\\s*\\)`,
312
- 'g'
313
- );
314
-
315
- let callMatch;
316
- while ((callMatch = callPattern.exec(originalCode)) !== null) {
317
- const varName = callMatch[1];
318
- const configSource = callMatch[2];
319
- const fullMatch = callMatch[0];
320
-
321
- const config = extractLocalFontConfigAst(`(${configSource})`);
322
- if (!config) {
323
- emitError(
324
- `Could not statically analyze local font config. ` +
325
- `Ensure src is a string or array of { path, weight?, style? } objects.`
326
- );
327
- return transformedCode;
328
- }
329
-
330
- const extracted = processLocalFont(config, importerId);
331
- registry.set(extracted.id, extracted);
332
-
333
- const resultObj = extracted.variable
334
- ? `{ className: "${extracted.className}", style: { fontFamily: "${extracted.fontFamily}" }, variable: "${extracted.variable}" }`
335
- : `{ className: "${extracted.className}", style: { fontFamily: "${extracted.fontFamily}" } }`;
336
-
337
- const replacement = `const ${varName} = ${resultObj}`;
338
- transformedCode = transformedCode.replace(fullMatch, replacement);
339
- }
340
-
341
- // Remove the import statement
342
- transformedCode = transformedCode.replace(
343
- /import\s+\w+\s+from\s*['"](?:@timber\/fonts\/local|next\/font\/local)['"];?\s*\n?/g,
344
- ''
345
- );
346
-
347
- return transformedCode;
348
- }
24
+ downloadAndCacheFonts,
25
+ generateProductionFontFaces,
26
+ resolveDevFontFaces,
27
+ } from '../fonts/google.js';
28
+ import { FontPipeline } from '../fonts/pipeline.js';
29
+ import { runFontsTransform } from '../fonts/transform.js';
30
+ import { installFontDevMiddleware } from '../fonts/dev-middleware.js';
31
+ import { emitFontAssets, writeFontManifest, groupCachedFontsByFamily } from '../fonts/bundle.js';
32
+ import {
33
+ RESOLVED_GOOGLE,
34
+ RESOLVED_LOCAL,
35
+ VIRTUAL_GOOGLE,
36
+ VIRTUAL_LOCAL,
37
+ generateGoogleVirtualModule,
38
+ generateLocalVirtualModule,
39
+ } from '../fonts/virtual-modules.js';
40
+
41
+ // ── Public re-exports ────────────────────────────────────────────────────
42
+ //
43
+ // These exports are part of the stable surface area imported by tests and
44
+ // downstream consumers. Do NOT change their names or signatures without
45
+ // updating every caller. New helpers should be added to the per-concern
46
+ // module first and re-exported here only if external code needs them.
47
+
48
+ export { FontPipeline, pruneRegistryEntries, type FontRegistry } from '../fonts/pipeline.js';
49
+ export {
50
+ generateFontId,
51
+ extractFontConfig,
52
+ detectDynamicFontCall,
53
+ parseGoogleFontImports,
54
+ parseGoogleFontFamilies,
55
+ parseLocalFontImportName,
56
+ } from '../fonts/transform.js';
57
+ export { generateFontCss, generateAllFontCss } from '../fonts/virtual-modules.js';
349
58
 
350
59
  /**
351
60
  * Create the timber-fonts Vite plugin.
352
61
  */
353
62
  export function timberFonts(ctx: PluginContext): Plugin {
354
- const registry: FontRegistry = new Map();
355
- /** Fonts downloaded during buildStart (production only). */
356
- let cachedFonts: CachedFont[] = [];
63
+ const pipeline = new FontPipeline();
357
64
 
358
65
  return {
359
66
  name: 'timber-fonts',
360
67
 
361
68
  /**
362
- * Resolve `@timber/fonts/google` and `@timber/fonts/local` to virtual modules.
69
+ * `enforce: 'pre'` is load-bearing for the font CSS pipeline (TIM-828).
70
+ *
71
+ * The transform hook injects a side-effect
72
+ * `import 'virtual:timber-font-css/<hash>.css'` into every file that
73
+ * registers a font. @vitejs/plugin-rsc's `rsc:rsc-css-export-transform`
74
+ * later inspects each server component's source for CSS imports and
75
+ * wraps the default export in `import.meta.viteRsc.loadCss(...)` so
76
+ * the matched virtual CSS module ends up `preinit`'d as
77
+ * `<link rel="stylesheet" data-rsc-css-href=...>`.
78
+ *
79
+ * If timber-fonts ran in normal order it would inject the CSS import
80
+ * *after* plugin-rsc had already scanned the source, and the font CSS
81
+ * would be silently dropped from the rendered HTML. Running in the
82
+ * `pre` slot guarantees our injected import is visible to plugin-rsc's
83
+ * later CSS-export scan.
84
+ */
85
+ enforce: 'pre',
86
+
87
+ /**
88
+ * Resolve `@timber/fonts/google`, `@timber/fonts/local`, and the
89
+ * per-importer `virtual:timber-font-css/<hash>.css` modules injected
90
+ * by the transform hook.
91
+ *
92
+ * Strips the `\0` prefix added by the RSC plugin's re-imports and the
93
+ * absolute root prefix added by SSR build entries before comparing
94
+ * against the public IDs. The `.css` suffix on font-css ids is
95
+ * preserved so Vite's CSS pipeline (`isCSSRequest`) recognises the
96
+ * resolved id as CSS.
363
97
  */
364
98
  resolveId(id: string) {
365
- if (id === VIRTUAL_GOOGLE) return RESOLVED_GOOGLE;
366
- if (id === VIRTUAL_LOCAL) return RESOLVED_LOCAL;
99
+ let cleanId = id.startsWith('\0') ? id.slice(1) : id;
100
+ if (cleanId.startsWith(ctx.root)) {
101
+ const stripped = cleanId.slice(ctx.root.length);
102
+ if (stripped.startsWith('/') || stripped.startsWith('\\')) {
103
+ cleanId = stripped.slice(1);
104
+ } else {
105
+ cleanId = stripped;
106
+ }
107
+ }
108
+
109
+ if (cleanId === VIRTUAL_GOOGLE) return RESOLVED_GOOGLE;
110
+ if (cleanId === VIRTUAL_LOCAL) return RESOLVED_LOCAL;
111
+ if (pipeline.cssIdMap.matches(cleanId)) return '\0' + cleanId;
367
112
  return null;
368
113
  },
369
114
 
370
115
  /**
371
116
  * Return generated source for font virtual modules.
117
+ *
118
+ * The per-importer `virtual:timber-font-css/<hash>.css` modules
119
+ * return the combined font CSS for the specific importer that
120
+ * registered them. Vite's CSS pipeline handles injection from here:
121
+ * in dev the module rides the CSS HMR channel; in production it is
122
+ * emitted as a real CSS asset and @vitejs/plugin-rsc's `collectCss`
123
+ * walks the RSC module graph to find it.
124
+ *
125
+ * In dev mode we also lazily resolve Google `@font-face` descriptors
126
+ * from the CDN here, since `buildStart` is a no-op in dev.
372
127
  */
373
- load(id: string) {
374
- if (id === RESOLVED_GOOGLE) return generateGoogleVirtualModule(registry);
128
+ async load(id: string) {
129
+ if (id === RESOLVED_GOOGLE) return generateGoogleVirtualModule(pipeline.fonts());
375
130
  if (id === RESOLVED_LOCAL) return generateLocalVirtualModule();
131
+
132
+ if (pipeline.cssIdMap.matches(id)) {
133
+ const importer = pipeline.cssIdMap.importerFor(id);
134
+ if (!importer) {
135
+ // Hash is valid but no importer is registered — return an empty
136
+ // CSS module rather than `null`. This can happen if Vite's
137
+ // module graph invalidates the virtual module between the
138
+ // transform that registered the hash and the load that asks
139
+ // for it (e.g. after an HMR edit that removes every font from
140
+ // the file). An empty stylesheet is a valid, safe no-op.
141
+ return '';
142
+ }
143
+
144
+ if (ctx.dev) {
145
+ for (const font of pipeline.googleFonts()) {
146
+ if (font.importer !== importer) continue;
147
+ if (pipeline.hasFaces(font.id)) continue;
148
+ try {
149
+ const faces = await resolveDevFontFaces(font);
150
+ pipeline.attachFaces(font.id, faces);
151
+ } catch (e) {
152
+ // Fail gracefully — fonts fall back to system fonts. Don't
153
+ // cache the failure so transient errors (network blips, rate
154
+ // limits) are retried on the next request. See TIM-636.
155
+ const msg = e instanceof Error ? e.message : String(e);
156
+ console.warn(
157
+ `[timber-fonts] Failed to resolve Google font "${font.family}": ${msg}. Will retry on next request.`
158
+ );
159
+ }
160
+ }
161
+ }
162
+
163
+ return pipeline.getCssForSegment(importer);
164
+ }
376
165
  return null;
377
166
  },
378
167
 
168
+ /**
169
+ * Serve local font files in dev mode under `/_timber/fonts/<basename>`.
170
+ * Font CSS goes through Vite's CSS pipeline (virtual modules), not
171
+ * this middleware.
172
+ */
173
+ configureServer(server: ViteDevServer) {
174
+ installFontDevMiddleware(server, pipeline);
175
+ },
176
+
379
177
  /**
380
178
  * Download and cache Google Fonts during production builds.
381
179
  *
382
- * In dev mode this is a no-op — fonts point to the Google CDN.
180
+ * In dev mode this is a no-op — fonts point to the Google CDN and are
181
+ * resolved lazily inside `load()` when the side-effect module runs.
383
182
  * The registry is populated by the transform hook which runs before
384
- * buildStart in the build pipeline, so all fonts are known here.
183
+ * `buildStart` in the build pipeline, so all fonts are known here.
385
184
  */
386
185
  async buildStart() {
387
186
  if (ctx.dev) return;
388
187
 
389
- const googleFonts = [...registry.values()].filter((f) => f.provider === 'google');
188
+ const googleFonts = [...pipeline.googleFonts()];
390
189
  if (googleFonts.length === 0) return;
391
190
 
392
- cachedFonts = await downloadAndCacheFonts(googleFonts, ctx.root);
191
+ const cachedFonts = await downloadAndCacheFonts(googleFonts, ctx.root);
192
+
193
+ // Build a family→CachedFont[] lookup, then attach the cached files
194
+ // and resolved @font-face descriptors to each registered Google
195
+ // font. Multiple fonts that share a family hold references to the
196
+ // same `CachedFont` objects; the bundle emitter dedupes by
197
+ // `hashedFilename` so each binary is written to disk exactly once.
198
+ const cachedByFamily = groupCachedFontsByFamily(cachedFonts);
199
+ for (const font of googleFonts) {
200
+ const familyCached = cachedByFamily.get(font.family.toLowerCase()) ?? [];
201
+ pipeline.attachCachedFiles(font.id, familyCached);
202
+ pipeline.attachFaces(font.id, generateProductionFontFaces(familyCached, font.display));
203
+ }
393
204
  },
394
205
 
395
206
  /**
396
207
  * Scan source files for font function calls and extract static config.
397
208
  *
398
- * When a file imports from `@timber/fonts/google`, we:
399
- * 1. Parse the import specifiers to get font family names
400
- * 2. Find each font function call and extract its config
401
- * 3. Validate that all calls are statically analyzable
402
- * 4. Register extracted fonts in the registry
403
- * 5. Replace the function call with a static FontResult object
209
+ * Delegates to `runFontsTransform`. Errors raised through the
210
+ * `this.error` callback are surfaced as Vite plugin errors.
404
211
  */
405
212
  transform(code: string, id: string) {
406
- // Skip virtual modules and node_modules
407
- if (id.startsWith('\0') || id.includes('node_modules')) return null;
408
-
409
- const hasGoogleImport =
410
- code.includes('@timber/fonts/google') || code.includes('next/font/google');
411
- const hasLocalImport =
412
- code.includes('@timber/fonts/local') || code.includes('next/font/local');
413
- if (!hasGoogleImport && !hasLocalImport) return null;
414
-
415
- let transformedCode = code;
416
-
417
- // ── Google font transform ──────────────────────────────────────────
418
- if (hasGoogleImport) {
419
- const families = parseGoogleFontFamilies(code);
420
- if (families.size > 0) {
421
- const importedNames = [...families.keys()];
422
-
423
- const dynamicCall = detectDynamicFontCall(code, importedNames);
424
- if (dynamicCall) {
425
- this.error(
426
- `Font function calls must be statically analyzable. ` +
427
- `Found dynamic call: ${dynamicCall}. ` +
428
- `Pass a literal object with string/array values instead.`
429
- );
430
- }
431
-
432
- for (const [localName, family] of families) {
433
- const callPattern = new RegExp(
434
- `(?:const|let|var)\\s+(\\w+)\\s*=\\s*${localName}\\s*\\(\\s*(\\{[\\s\\S]*?\\})\\s*\\)`,
435
- 'g'
436
- );
437
-
438
- let callMatch;
439
- while ((callMatch = callPattern.exec(code)) !== null) {
440
- const varName = callMatch[1];
441
- const configSource = callMatch[2];
442
- const fullMatch = callMatch[0];
443
-
444
- const config = extractFontConfig(`(${configSource})`);
445
- if (!config) {
446
- this.error(
447
- `Could not statically analyze font config for ${family}. ` +
448
- `Ensure all config values are string literals or arrays of string literals.`
449
- );
450
- return null;
451
- }
452
-
453
- const fontId = generateFontId(family, config);
454
- const className = familyToClassName(family);
455
- const fontStack = buildFontStack(family);
456
- const display = config.display ?? 'swap';
457
-
458
- const extracted: ExtractedFont = {
459
- id: fontId,
460
- family,
461
- provider: 'google',
462
- weights: normalizeToArray(config.weight),
463
- styles: normalizeStyleArray(config.style),
464
- subsets: config.subsets ?? ['latin'],
465
- display,
466
- variable: config.variable,
467
- className,
468
- fontFamily: fontStack,
469
- importer: id,
470
- };
471
-
472
- registry.set(fontId, extracted);
473
-
474
- const resultObj = config.variable
475
- ? `{ className: "${className}", style: { fontFamily: "${fontStack}" }, variable: "${config.variable}" }`
476
- : `{ className: "${className}", style: { fontFamily: "${fontStack}" } }`;
477
-
478
- const replacement = `const ${varName} = ${resultObj}`;
479
- transformedCode = transformedCode.replace(fullMatch, replacement);
480
- }
481
- }
482
-
483
- transformedCode = transformedCode.replace(
484
- /import\s*\{[^}]+\}\s*from\s*['"](?:@timber\/fonts\/google|next\/font\/google)['"];?\s*\n?/g,
485
- ''
486
- );
487
- }
488
- }
489
-
490
- // ── Local font transform ───────────────────────────────────────────
491
- if (hasLocalImport) {
492
- transformedCode = transformLocalFonts(
493
- transformedCode,
494
- code,
495
- id,
496
- registry,
497
- this.error.bind(this)
498
- );
499
- }
500
-
501
- if (transformedCode !== code) {
502
- return { code: transformedCode, map: null };
503
- }
504
-
505
- return null;
213
+ return runFontsTransform(code, id, pipeline, (msg) => this.error(msg));
506
214
  },
507
215
 
508
216
  /**
509
- * Emit font files and metadata into the build output.
510
- *
511
- * For Google fonts: emits the downloaded, content-hashed woff2 files
512
- * and writes ManifestFontEntry arrays using real hashed URLs.
217
+ * Emit font binaries and build-manifest entries.
513
218
  *
514
- * For local fonts: emits entries using the source file paths.
515
- *
516
- * In dev mode the build manifest is null, so this is a no-op.
219
+ * Google fonts use the content-hashed filenames produced during
220
+ * `buildStart`. Local fonts are emitted by basename. Font CSS is
221
+ * handled by Vite's CSS pipeline via virtual modules — we only emit
222
+ * binaries here.
517
223
  */
518
224
  generateBundle() {
519
- // Emit cached Google Font files into the build output
520
- for (const cf of cachedFonts) {
521
- this.emitFile({
522
- type: 'asset',
523
- fileName: `_timber/fonts/${cf.hashedFilename}`,
524
- source: cf.data,
525
- });
526
- }
527
-
225
+ emitFontAssets(
226
+ pipeline,
227
+ (asset) => this.emitFile(asset),
228
+ (msg) => this.warn(msg)
229
+ );
528
230
  if (!ctx.buildManifest) return;
529
-
530
- // Build a lookup from font family → cached files for manifest entries
531
- const cachedByFamily = new Map<string, CachedFont[]>();
532
- for (const cf of cachedFonts) {
533
- const key = cf.face.family.toLowerCase();
534
- const arr = cachedByFamily.get(key) ?? [];
535
- arr.push(cf);
536
- cachedByFamily.set(key, arr);
537
- }
538
-
539
- const fontsByImporter = new Map<string, ManifestFontEntry[]>();
540
-
541
- for (const font of registry.values()) {
542
- const entries = fontsByImporter.get(font.importer) ?? [];
543
-
544
- if (font.provider === 'local' && font.localSources) {
545
- // Local fonts: one entry per source file
546
- for (const src of font.localSources) {
547
- const filename = src.path.split('/').pop() ?? src.path;
548
- const format = inferFontFormat(src.path);
549
- entries.push({
550
- href: `/_timber/fonts/${filename}`,
551
- format,
552
- crossOrigin: 'anonymous',
553
- });
554
- }
555
- } else {
556
- // Google fonts: use real content-hashed URLs from cached downloads
557
- const familyKey = font.family.toLowerCase();
558
- const familyCached = cachedByFamily.get(familyKey) ?? [];
559
- for (const cf of familyCached) {
560
- entries.push({
561
- href: `/_timber/fonts/${cf.hashedFilename}`,
562
- format: 'woff2',
563
- crossOrigin: 'anonymous',
564
- });
565
- }
566
- }
567
-
568
- fontsByImporter.set(font.importer, entries);
569
- }
570
-
571
- // Normalize importer paths to be relative to project root (matching
572
- // how Vite's manifest.json keys work for css/js).
573
- for (const [importer, entries] of fontsByImporter) {
574
- const relativePath = importer.startsWith(ctx.root)
575
- ? importer.slice(ctx.root.length + 1)
576
- : importer;
577
- ctx.buildManifest.fonts[relativePath] = entries;
578
- }
231
+ writeFontManifest(pipeline, ctx.buildManifest, ctx.root);
579
232
  },
580
233
  };
581
234
  }