@lovrozagar/flare 0.1.0

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 (387) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +11 -0
  3. package/package.json +146 -0
  4. package/scripts/download-fonts.ts +136 -0
  5. package/scripts/populate-fonts.ts +721 -0
  6. package/src/await.ts +2 -0
  7. package/src/boundaries/index.ts +99 -0
  8. package/src/broadcast/channel.ts +65 -0
  9. package/src/broadcast/context.ts +12 -0
  10. package/src/broadcast/index.ts +75 -0
  11. package/src/broadcast/provider.tsx +7 -0
  12. package/src/build-location.ts +2 -0
  13. package/src/caches/index.ts +384 -0
  14. package/src/client/index.ts +75 -0
  15. package/src/client.tsx +2 -0
  16. package/src/codegen/index.ts +41 -0
  17. package/src/components/await.tsx +140 -0
  18. package/src/components/dev-error-overlay.tsx +154 -0
  19. package/src/components/direction-script.tsx +22 -0
  20. package/src/components/index.ts +150 -0
  21. package/src/components/locale-script.tsx +26 -0
  22. package/src/components/reset-css.tsx +14 -0
  23. package/src/components/ssr-context.tsx +37 -0
  24. package/src/components/theme-script.tsx +22 -0
  25. package/src/components/view-transition-css.tsx +21 -0
  26. package/src/config/index.ts +84 -0
  27. package/src/create-client-only-fn.ts +1 -0
  28. package/src/create-isomorphic-fn.ts +2 -0
  29. package/src/create-layout.ts +1 -0
  30. package/src/create-page.ts +1 -0
  31. package/src/create-path-segment.ts +1 -0
  32. package/src/create-query-client-getter.ts +2 -0
  33. package/src/create-root-layout.ts +1 -0
  34. package/src/create-router.ts +8 -0
  35. package/src/create-server-only-fn.ts +1 -0
  36. package/src/dedupe/index.ts +151 -0
  37. package/src/defer/index.ts +82 -0
  38. package/src/direction/index.tsx +163 -0
  39. package/src/direction.ts +3 -0
  40. package/src/duration/index.ts +18 -0
  41. package/src/env-fn/index.ts +101 -0
  42. package/src/env-fn.ts +2 -0
  43. package/src/errors/index.ts +166 -0
  44. package/src/fonts/abeezee.ts +50 -0
  45. package/src/fonts/abel.ts +26 -0
  46. package/src/fonts/abril-fatface.ts +34 -0
  47. package/src/fonts/acme.ts +26 -0
  48. package/src/fonts/advent-pro.ts +92 -0
  49. package/src/fonts/alegreya-sans.ts +228 -0
  50. package/src/fonts/alegreya.ts +228 -0
  51. package/src/fonts/alex-brush.ts +42 -0
  52. package/src/fonts/alfa-slab-one.ts +42 -0
  53. package/src/fonts/alice.ts +48 -0
  54. package/src/fonts/amatic-sc.ts +94 -0
  55. package/src/fonts/amiri.ts +114 -0
  56. package/src/fonts/antic-slab.ts +26 -0
  57. package/src/fonts/anton.ts +42 -0
  58. package/src/fonts/archivo-black.ts +34 -0
  59. package/src/fonts/archivo-narrow.ts +114 -0
  60. package/src/fonts/archivo.ts +66 -0
  61. package/src/fonts/arimo.ts +256 -0
  62. package/src/fonts/arvo.ts +50 -0
  63. package/src/fonts/asap.ts +66 -0
  64. package/src/fonts/assistant.ts +64 -0
  65. package/src/fonts/baloo-2.ts +82 -0
  66. package/src/fonts/barlow-condensed.ts +114 -0
  67. package/src/fonts/barlow-semi-condensed.ts +114 -0
  68. package/src/fonts/barlow.ts +114 -0
  69. package/src/fonts/be-vietnam-pro.ts +114 -0
  70. package/src/fonts/bebas-neue.ts +34 -0
  71. package/src/fonts/besley.ts +82 -0
  72. package/src/fonts/biorhyme.ts +50 -0
  73. package/src/fonts/bitter.ts +94 -0
  74. package/src/fonts/black-ops-one.ts +49 -0
  75. package/src/fonts/bree-serif.ts +34 -0
  76. package/src/fonts/bricolage-grotesque.ts +66 -0
  77. package/src/fonts/cabin.ts +114 -0
  78. package/src/fonts/cairo.ts +66 -0
  79. package/src/fonts/cardo.ts +193 -0
  80. package/src/fonts/catamaran.ts +41 -0
  81. package/src/fonts/caveat.ts +78 -0
  82. package/src/fonts/chakra-petch.ts +142 -0
  83. package/src/fonts/chivo.ts +66 -0
  84. package/src/fonts/cinzel.ts +50 -0
  85. package/src/fonts/comfortaa.ts +109 -0
  86. package/src/fonts/commissioner.ts +64 -0
  87. package/src/fonts/component.tsx +27 -0
  88. package/src/fonts/cormorant-garamond.ts +171 -0
  89. package/src/fonts/cormorant.ts +170 -0
  90. package/src/fonts/courgette.ts +34 -0
  91. package/src/fonts/courier-prime.ts +82 -0
  92. package/src/fonts/create-font.ts +47 -0
  93. package/src/fonts/create-registry-font.ts +40 -0
  94. package/src/fonts/crete-round.ts +50 -0
  95. package/src/fonts/crimson-text.ts +114 -0
  96. package/src/fonts/css.ts +86 -0
  97. package/src/fonts/dancing-script.ts +66 -0
  98. package/src/fonts/dm-mono.ts +50 -0
  99. package/src/fonts/dm-sans.ts +50 -0
  100. package/src/fonts/dm-serif-display.ts +50 -0
  101. package/src/fonts/domine.ts +50 -0
  102. package/src/fonts/dosis.ts +66 -0
  103. package/src/fonts/eb-garamond.ts +228 -0
  104. package/src/fonts/eczar.ts +94 -0
  105. package/src/fonts/encode-sans.ts +42 -0
  106. package/src/fonts/epilogue.ts +66 -0
  107. package/src/fonts/exo-2.ts +94 -0
  108. package/src/fonts/exo.ts +66 -0
  109. package/src/fonts/figtree.ts +82 -0
  110. package/src/fonts/fira-code.ts +121 -0
  111. package/src/fonts/fira-sans-condensed.ts +228 -0
  112. package/src/fonts/fira-sans.ts +228 -0
  113. package/src/fonts/fjalla-one.ts +49 -0
  114. package/src/fonts/font-urls.gen.json +1962 -0
  115. package/src/fonts/fraunces.ts +66 -0
  116. package/src/fonts/fredoka.ts +64 -0
  117. package/src/fonts/gelasio.ts +114 -0
  118. package/src/fonts/gloria-hallelujah.ts +34 -0
  119. package/src/fonts/gothic-a1.ts +124 -0
  120. package/src/fonts/great-vibes.ts +64 -0
  121. package/src/fonts/gudea.ts +66 -0
  122. package/src/fonts/heebo.ts +57 -0
  123. package/src/fonts/hind-siliguri.ts +66 -0
  124. package/src/fonts/hind.ts +66 -0
  125. package/src/fonts/ibm-plex-mono.ts +172 -0
  126. package/src/fonts/ibm-plex-sans-arabic.ts +80 -0
  127. package/src/fonts/ibm-plex-sans.ts +199 -0
  128. package/src/fonts/ibm-plex-serif.ts +171 -0
  129. package/src/fonts/inconsolata.ts +66 -0
  130. package/src/fonts/index.ts +4 -0
  131. package/src/fonts/indie-flower.ts +34 -0
  132. package/src/fonts/instrument-sans.ts +82 -0
  133. package/src/fonts/instrument-serif.ts +50 -0
  134. package/src/fonts/inter-display.ts +52 -0
  135. package/src/fonts/inter-tight.ts +124 -0
  136. package/src/fonts/inter.ts +123 -0
  137. package/src/fonts/jetbrains-mono.ts +199 -0
  138. package/src/fonts/josefin-sans.ts +114 -0
  139. package/src/fonts/josefin-slab.ts +50 -0
  140. package/src/fonts/jost.ts +64 -0
  141. package/src/fonts/kalam.ts +66 -0
  142. package/src/fonts/kanit.ts +142 -0
  143. package/src/fonts/karla.ts +82 -0
  144. package/src/fonts/khand.ts +66 -0
  145. package/src/fonts/lato.ts +82 -0
  146. package/src/fonts/league-spartan.ts +42 -0
  147. package/src/fonts/lexend-deca.ts +42 -0
  148. package/src/fonts/lexend.ts +42 -0
  149. package/src/fonts/libre-baskerville.ts +82 -0
  150. package/src/fonts/libre-franklin.ts +95 -0
  151. package/src/fonts/lilita-one.ts +34 -0
  152. package/src/fonts/lobster-two.ts +50 -0
  153. package/src/fonts/lobster.ts +56 -0
  154. package/src/fonts/lora.ts +235 -0
  155. package/src/fonts/m-plus-rounded-1c.ts +138 -0
  156. package/src/fonts/manrope.ts +109 -0
  157. package/src/fonts/maven-pro.ts +66 -0
  158. package/src/fonts/merriweather-sans.ts +142 -0
  159. package/src/fonts/merriweather.ts +171 -0
  160. package/src/fonts/montserrat-alternates.ts +171 -0
  161. package/src/fonts/montserrat.ts +94 -0
  162. package/src/fonts/mukta.ts +66 -0
  163. package/src/fonts/mulish.ts +170 -0
  164. package/src/fonts/nanum-gothic.ts +34 -0
  165. package/src/fonts/nanum-myeongjo.ts +34 -0
  166. package/src/fonts/neuton.ts +66 -0
  167. package/src/fonts/newsreader.ts +114 -0
  168. package/src/fonts/noticia-text.ts +114 -0
  169. package/src/fonts/noto-sans-arabic.ts +58 -0
  170. package/src/fonts/noto-sans-hk.ts +49 -0
  171. package/src/fonts/noto-sans-jp.ts +49 -0
  172. package/src/fonts/noto-sans-kr.ts +49 -0
  173. package/src/fonts/noto-sans-sc.ts +49 -0
  174. package/src/fonts/noto-sans-tc.ts +49 -0
  175. package/src/fonts/noto-sans.ts +140 -0
  176. package/src/fonts/noto-serif-jp.ts +80 -0
  177. package/src/fonts/noto-serif.ts +140 -0
  178. package/src/fonts/nunito-sans.ts +170 -0
  179. package/src/fonts/nunito.ts +170 -0
  180. package/src/fonts/old-standard-tt.ts +133 -0
  181. package/src/fonts/onest.ts +48 -0
  182. package/src/fonts/open-sans.ts +340 -0
  183. package/src/fonts/orbitron.ts +34 -0
  184. package/src/fonts/oswald.ts +94 -0
  185. package/src/fonts/outfit.ts +34 -0
  186. package/src/fonts/overpass.ts +94 -0
  187. package/src/fonts/oxygen.ts +50 -0
  188. package/src/fonts/pacifico.ts +56 -0
  189. package/src/fonts/passion-one.ts +50 -0
  190. package/src/fonts/pathway-gothic-one.ts +34 -0
  191. package/src/fonts/permanent-marker.ts +26 -0
  192. package/src/fonts/philosopher.ts +172 -0
  193. package/src/fonts/play.ts +109 -0
  194. package/src/fonts/playfair-display.ts +142 -0
  195. package/src/fonts/plus-jakarta-sans.ts +142 -0
  196. package/src/fonts/poppins.ts +114 -0
  197. package/src/fonts/prompt.ts +142 -0
  198. package/src/fonts/pt-sans-narrow.ts +78 -0
  199. package/src/fonts/pt-sans.ts +138 -0
  200. package/src/fonts/pt-serif.ts +138 -0
  201. package/src/fonts/public-sans.ts +66 -0
  202. package/src/fonts/questrial.ts +42 -0
  203. package/src/fonts/quicksand.ts +66 -0
  204. package/src/fonts/rajdhani.ts +66 -0
  205. package/src/fonts/raleway.ts +94 -0
  206. package/src/fonts/recursive.ts +80 -0
  207. package/src/fonts/red-hat-display.ts +82 -0
  208. package/src/fonts/red-rose.ts +66 -0
  209. package/src/fonts/registry.gen.ts +173 -0
  210. package/src/fonts/righteous.ts +34 -0
  211. package/src/fonts/roboto-condensed.ts +124 -0
  212. package/src/fonts/roboto-flex.ts +64 -0
  213. package/src/fonts/roboto-mono.ts +199 -0
  214. package/src/fonts/roboto-slab.ts +72 -0
  215. package/src/fonts/roboto.ts +156 -0
  216. package/src/fonts/rokkitt.ts +66 -0
  217. package/src/fonts/rubik.ts +199 -0
  218. package/src/fonts/sacramento.ts +34 -0
  219. package/src/fonts/saira.ts +66 -0
  220. package/src/fonts/sarabun.ts +142 -0
  221. package/src/fonts/satisfy.ts +26 -0
  222. package/src/fonts/sawarabi-mincho.ts +41 -0
  223. package/src/fonts/shadows-into-light.ts +34 -0
  224. package/src/fonts/signika-negative.ts +66 -0
  225. package/src/fonts/signika.ts +66 -0
  226. package/src/fonts/slabo-27px.ts +34 -0
  227. package/src/fonts/sora.ts +50 -0
  228. package/src/fonts/source-code-pro.ts +228 -0
  229. package/src/fonts/source-sans-3.ts +228 -0
  230. package/src/fonts/source-serif-4.ts +199 -0
  231. package/src/fonts/space-grotesk.ts +66 -0
  232. package/src/fonts/space-mono.ts +114 -0
  233. package/src/fonts/spectral.ts +170 -0
  234. package/src/fonts/tajawal.ts +50 -0
  235. package/src/fonts/teko.ts +66 -0
  236. package/src/fonts/tenor-sans.ts +41 -0
  237. package/src/fonts/tinos.ts +256 -0
  238. package/src/fonts/titillium-web.ts +82 -0
  239. package/src/fonts/types.ts +43 -0
  240. package/src/fonts/ubuntu-condensed.ts +63 -0
  241. package/src/fonts/ubuntu-mono.ts +195 -0
  242. package/src/fonts/ubuntu.ts +195 -0
  243. package/src/fonts/unbounded.ts +94 -0
  244. package/src/fonts/unicode-ranges.gen.ts +28 -0
  245. package/src/fonts/urbanist.ts +50 -0
  246. package/src/fonts/varela-round.ts +49 -0
  247. package/src/fonts/vollkorn.ts +199 -0
  248. package/src/fonts/work-sans.ts +66 -0
  249. package/src/fonts/yanone-kaffeesatz.ts +128 -0
  250. package/src/fonts/yantramanav.ts +66 -0
  251. package/src/fonts/yellowtail.ts +34 -0
  252. package/src/fonts/young-serif.ts +34 -0
  253. package/src/fonts/zen-kaku-gothic-new.ts +64 -0
  254. package/src/fonts/zilla-slab.ts +82 -0
  255. package/src/form/index.tsx +205 -0
  256. package/src/generators/index.ts +1589 -0
  257. package/src/head-client/index.ts +649 -0
  258. package/src/history/index.ts +210 -0
  259. package/src/hooks.ts +61 -0
  260. package/src/hydrate/index.tsx +381 -0
  261. package/src/hydration/index.ts +187 -0
  262. package/src/i18n/index.ts +250 -0
  263. package/src/i18n/jsx.tsx +42 -0
  264. package/src/i18n/message-format.ts +174 -0
  265. package/src/image/index.tsx +473 -0
  266. package/src/image.ts +12 -0
  267. package/src/intercept-outlet/index.tsx +18 -0
  268. package/src/intercept-outlet.ts +2 -0
  269. package/src/internal/index.ts +143 -0
  270. package/src/internal/once-idle.ts +24 -0
  271. package/src/internal.ts +12 -0
  272. package/src/lazy/index.tsx +205 -0
  273. package/src/link/index.tsx +367 -0
  274. package/src/loader-pipeline/index.ts +639 -0
  275. package/src/locale/index.tsx +137 -0
  276. package/src/locale.ts +3 -0
  277. package/src/logger.ts +22 -0
  278. package/src/middleware/builtins/api-proxy.ts +64 -0
  279. package/src/middleware/builtins/cdn-proxy.ts +58 -0
  280. package/src/middleware/builtins/i18n.ts +256 -0
  281. package/src/middleware/builtins/keepalive.ts +24 -0
  282. package/src/middleware/builtins/markdown-negotiation.ts +141 -0
  283. package/src/middleware/builtins/static-assets.ts +32 -0
  284. package/src/middleware/index.ts +223 -0
  285. package/src/module-graph/index.ts +181 -0
  286. package/src/mount/index.ts +146 -0
  287. package/src/navigate.ts +1 -0
  288. package/src/navigation/index.ts +1278 -0
  289. package/src/navigation/types.ts +59 -0
  290. package/src/navigation-progress/index.tsx +247 -0
  291. package/src/navigation-progress.ts +1 -0
  292. package/src/ndjson-client/index.ts +376 -0
  293. package/src/ndjson-server/index.ts +284 -0
  294. package/src/outlet/index.tsx +633 -0
  295. package/src/outlet/types.ts +243 -0
  296. package/src/plugins/css-transform.ts +70 -0
  297. package/src/plugins/dev-cdn-cache.ts +454 -0
  298. package/src/plugins/dev-dashboard/client.tsx +2603 -0
  299. package/src/plugins/dev-dashboard/match-route-tree.ts +159 -0
  300. package/src/plugins/dev-dashboard/plugin.ts +404 -0
  301. package/src/plugins/dev-prerender.ts +168 -0
  302. package/src/plugins/dev-server.ts +327 -0
  303. package/src/plugins/generate-watch.ts +32 -0
  304. package/src/plugins/image-plugin.ts +171 -0
  305. package/src/plugins/index.ts +445 -0
  306. package/src/plugins/options.ts +37 -0
  307. package/src/plugins/parse-utils.ts +59 -0
  308. package/src/plugins/prerender-plugin.ts +144 -0
  309. package/src/plugins/purge.ts +242 -0
  310. package/src/plugins/server-fn.ts +641 -0
  311. package/src/plugins/service-worker.ts +225 -0
  312. package/src/plugins/solid-jsx.d.ts +12 -0
  313. package/src/plugins/sx-ast/atomic.ts +166 -0
  314. package/src/plugins/sx-ast/evaluator.ts +235 -0
  315. package/src/plugins/sx-ast/index.ts +372 -0
  316. package/src/plugins/sx-ast/parser.ts +22 -0
  317. package/src/plugins/sx-ast/rewrite.ts +763 -0
  318. package/src/plugins/sx.d.ts +14 -0
  319. package/src/plugins/tw-compile.ts +240 -0
  320. package/src/plugins/types.ts +41 -0
  321. package/src/plugins/virtual.d.ts +110 -0
  322. package/src/plugins/virtual.ts +184 -0
  323. package/src/preload/index.ts +77 -0
  324. package/src/prerender/index.ts +431 -0
  325. package/src/query-client/index.tsx +168 -0
  326. package/src/registry/index.ts +88 -0
  327. package/src/reset-css.ts +1 -0
  328. package/src/revalidation/index.ts +84 -0
  329. package/src/rewrite/index.ts +83 -0
  330. package/src/route-builder/create-layout.ts +655 -0
  331. package/src/route-builder/create-page.ts +806 -0
  332. package/src/route-builder/create-path-segment.ts +34 -0
  333. package/src/route-builder/create-root-layout.ts +608 -0
  334. package/src/route-builder/index.ts +49 -0
  335. package/src/route-builder/register.ts +242 -0
  336. package/src/route-builder/types.ts +294 -0
  337. package/src/router-config/index.ts +91 -0
  338. package/src/router-primitives/index.ts +25 -0
  339. package/src/router-primitives/location.ts +29 -0
  340. package/src/router-primitives/match-id.ts +111 -0
  341. package/src/router-primitives/paths.ts +109 -0
  342. package/src/router-primitives/tree.ts +243 -0
  343. package/src/router-primitives/types.ts +74 -0
  344. package/src/router.ts +31 -0
  345. package/src/search-engine/bing.ts +32 -0
  346. package/src/search-engine/google-jwt.ts +95 -0
  347. package/src/search-engine/google.ts +139 -0
  348. package/src/search-engine/index-now.ts +64 -0
  349. package/src/search-engine/index.ts +12 -0
  350. package/src/security/index.ts +230 -0
  351. package/src/server/index.ts +286 -0
  352. package/src/server-context/browser.ts +113 -0
  353. package/src/server-context/index.ts +217 -0
  354. package/src/server-fn/index.ts +710 -0
  355. package/src/server-fn-query.ts +169 -0
  356. package/src/server-handler/etag.ts +51 -0
  357. package/src/server-handler/headers.ts +5 -0
  358. package/src/server-handler/index.ts +1664 -0
  359. package/src/server-handler/types.ts +24 -0
  360. package/src/server-handler/validate-static-params.ts +130 -0
  361. package/src/server.ts +2 -0
  362. package/src/service-worker/template.ts +153 -0
  363. package/src/service-worker-hook/index.ts +70 -0
  364. package/src/sitemap/index.ts +231 -0
  365. package/src/ssr/critical-css.ts +150 -0
  366. package/src/ssr/head-prefix.ts +65 -0
  367. package/src/ssr/head.ts +259 -0
  368. package/src/ssr/index.tsx +879 -0
  369. package/src/state-parser/index.ts +266 -0
  370. package/src/store/filesystem.ts +131 -0
  371. package/src/store/index.ts +29 -0
  372. package/src/styles/index.ts +1200 -0
  373. package/src/styles/sx-types.ts +11 -0
  374. package/src/testing/index.ts +251 -0
  375. package/src/testing.ts +2 -0
  376. package/src/theme/index.tsx +232 -0
  377. package/src/theme.ts +3 -0
  378. package/src/tracing/index.ts +4 -0
  379. package/src/tracing/noop.ts +13 -0
  380. package/src/tracing/otel.ts +37 -0
  381. package/src/tracing/timing.ts +34 -0
  382. package/src/tracing/types.ts +9 -0
  383. package/src/url/index.ts +140 -0
  384. package/src/use-router.ts +11 -0
  385. package/src/use-suspense-query.ts +2 -0
  386. package/src/validation/index.ts +57 -0
  387. package/src/view-transition-css.ts +1 -0
@@ -0,0 +1,445 @@
1
+ import { existsSync, watch } from "node:fs";
2
+ import { dirname, join, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import type { Options as SolidPluginOptions } from "vite-plugin-solid";
5
+ import solid from "vite-plugin-solid";
6
+ import { runGenerate } from "../generators/index.ts";
7
+ import { EMPTY_OBJ } from "../internal/index.ts";
8
+ import type { LogLevel } from "../logger.ts";
9
+ import { createCssTransformPlugin } from "./css-transform.ts";
10
+ import { createDevCdnCachePlugin } from "./dev-cdn-cache.ts";
11
+ import { createDevDashboardPlugin } from "./dev-dashboard/plugin.ts";
12
+ import { createDevPrerenderPlugin } from "./dev-prerender.ts";
13
+ import { createDevServerPlugin, createPreviewServerPlugin } from "./dev-server.ts";
14
+ import { createImagePlugin } from "./image-plugin.ts";
15
+ import { createPrerenderPlugin, type PrerenderPluginConfig } from "./prerender-plugin.ts";
16
+ import { createPurgePlugin, createPurgeTestIdsPlugin, type PurgeConfig, resolvePurgeConfig } from "./purge.ts";
17
+ import { createServerFnPlugin } from "./server-fn.ts";
18
+ import {
19
+ createServiceWorkerDisabledPlugin,
20
+ createServiceWorkerPlugin,
21
+ normalizeSwConfig,
22
+ type ServiceWorkerConfig,
23
+ } from "./service-worker.ts";
24
+ import { createSxAstPlugin } from "./sx-ast/index.ts";
25
+ import type { SxAstOptions } from "./sx-ast/index.ts";
26
+ import type { ResolvedEntries, VitePlugin } from "./types.ts";
27
+ import { createVirtualPlugin } from "./virtual.ts";
28
+ import { resolveFlareOptions } from "./options.ts";
29
+ import { safeRunGenerate, shouldTriggerGenerate } from "./generate-watch.ts";
30
+
31
+ /* ── Re-exports ─────────────────────────────────────────────────────── */
32
+
33
+ export { createSxAstPlugin } from "./sx-ast/index.ts";
34
+ export type { SxAstOptions } from "./sx-ast/index.ts";
35
+ export { createCssTransformPlugin } from "./css-transform.ts";
36
+ export { createDevServerPlugin, createPreviewServerPlugin } from "./dev-server.ts";
37
+ export { createImagePlugin } from "./image-plugin.ts";
38
+ export { extractParenContent, findMatchingBraceSimple } from "./parse-utils.ts";
39
+ export type { PrerenderPluginConfig, SitemapPluginConfig } from "./prerender-plugin.ts";
40
+ export { createPrerenderPlugin } from "./prerender-plugin.ts";
41
+ export {
42
+ createServerFnPlugin,
43
+ dropDeadImports,
44
+ generateServerFnMapSource,
45
+ replaceServerFnConfigs,
46
+ scanServerFnFiles,
47
+ stripHandlerBodies,
48
+ transformEnvFns,
49
+ } from "./server-fn.ts";
50
+ export type { ResolvedEntries, VitePlugin } from "./types.ts";
51
+ export { createVirtualPlugin } from "./virtual.ts";
52
+
53
+ /* ── Types ───────────────────────────────────────────────────────────── */
54
+
55
+ export interface FlareImageConfig {
56
+ exclude?: RegExp;
57
+ quality?: number;
58
+ widths?: number[];
59
+ }
60
+
61
+ export interface CodegenConfig {
62
+ /**
63
+ * Derive virtual paths from `src/routes/` folder layout.
64
+ * Default: `true`.
65
+ *
66
+ * When true, route files must use suffixes under a `_name_` root scope:
67
+ * `*.page.tsx`, `*.layout.tsx`, `*.root-layout.tsx`, `*.path-segment.tsx`.
68
+ * Example: `src/routes/_root_/about/about.page.tsx` → `createPage("_root_/about")`.
69
+ * String-style files (`about.tsx` + handwritten `createPage("...")`) are rejected.
70
+ * Set `false` to keep owning virtual-path strings yourself.
71
+ */
72
+ fsVirtualPaths?: boolean;
73
+ routesFilePath?: string;
74
+ typesFilePath?: string;
75
+ }
76
+
77
+ /* codegen is always on — only configures where/how, never disables */
78
+
79
+ export interface DevConfig {
80
+ cdnCache?: boolean;
81
+ dashboard?: boolean;
82
+ serverTiming?: boolean;
83
+ staticCache?: boolean;
84
+ }
85
+
86
+ export interface FlarePluginConfig {
87
+ alias?: Record<string, string>;
88
+ /**
89
+ * URL prefix for built assets. Defaults to `"/assets"`.
90
+ * Must start with `"/"` and not end with `"/"` (except `"/"` which means root-relative).
91
+ * No query strings or hash fragments. Throws at plugin construction on bad input.
92
+ */
93
+ assetsBase?: string;
94
+ codegen?: CodegenConfig;
95
+ dev?: DevConfig | boolean;
96
+ entry?: { client?: string; server?: string };
97
+ ignorePrefix?: string;
98
+ image?: FlareImageConfig;
99
+ logLevel?: LogLevel;
100
+ port?: number;
101
+ prerender?: PrerenderPluginConfig | boolean;
102
+ purge?: PurgeConfig | boolean;
103
+ serviceWorker?: ServiceWorkerConfig | boolean;
104
+ solid?: Partial<SolidPluginOptions>;
105
+ sx?: SxAstOptions;
106
+ }
107
+
108
+ /* ── Config resolvers ────────────────────────────────────────────────── */
109
+
110
+ export function resolveCodegenConfig(raw?: CodegenConfig): {
111
+ fsVirtualPaths: boolean;
112
+ routesFilePath: string;
113
+ typesFilePath: string;
114
+ } {
115
+ return {
116
+ fsVirtualPaths: raw?.fsVirtualPaths ?? true,
117
+ routesFilePath: raw?.routesFilePath ?? "src/_gen/routes.gen.ts",
118
+ typesFilePath: raw?.typesFilePath ?? "src/_gen/types.gen.d.ts",
119
+ };
120
+ }
121
+
122
+ export function resolveDevConfig(raw?: DevConfig | boolean): {
123
+ cdnCache: boolean;
124
+ dashboard: boolean;
125
+ serverTiming: boolean;
126
+ staticCache: boolean;
127
+ } {
128
+ if (raw === false) return { cdnCache: false, dashboard: false, serverTiming: false, staticCache: false };
129
+ if (raw === undefined || raw === true)
130
+ return { cdnCache: true, dashboard: true, serverTiming: true, staticCache: true };
131
+ return {
132
+ cdnCache: raw.cdnCache ?? true,
133
+ dashboard: raw.dashboard ?? true,
134
+ serverTiming: raw.serverTiming ?? true,
135
+ staticCache: raw.staticCache ?? true,
136
+ };
137
+ }
138
+
139
+ /* ── Module map ──────────────────────────────────────────────────────── */
140
+
141
+ const FLARE_PREFIX = "@lovrozagar/flare/";
142
+
143
+ const MODULE_MAP: Record<string, { client: string; ssr: string }> = {
144
+ hydrate: { client: "dist/client/hydrate.js", ssr: "dist/ssr/hydrate.js" },
145
+ link: { client: "dist/client/link.js", ssr: "dist/ssr/link.js" },
146
+ outlet: { client: "dist/client/outlet.js", ssr: "dist/ssr/outlet.js" },
147
+ ssr: { client: "dist/client/ssr.js", ssr: "dist/ssr/ssr.js" },
148
+ };
149
+
150
+ /* ── Conventions ─────────────────────────────────────────────────────── */
151
+
152
+ const ENTRY_EXTENSIONS = [".tsx", ".ts"];
153
+
154
+ function resolveEntry(root: string, base: string, override?: string): string {
155
+ if (override) {
156
+ if (!existsSync(join(root, override))) {
157
+ throw new Error(`Flare: entry.${base} path "${override}" not found`);
158
+ }
159
+ return override;
160
+ }
161
+ for (const ext of ENTRY_EXTENSIONS) {
162
+ if (existsSync(join(root, `src/${base}${ext}`))) return `src/${base}${ext}`;
163
+ }
164
+ throw new Error(`Flare: missing src/${base}.tsx or src/${base}.ts`);
165
+ }
166
+
167
+ /* ── Resolver ────────────────────────────────────────────────────────── */
168
+
169
+ function createResolverPlugin(): VitePlugin {
170
+ const flareRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
171
+ const hasDist = existsSync(join(flareRoot, "dist"));
172
+
173
+ return {
174
+ enforce: "pre",
175
+ name: "flare:resolver",
176
+ resolveId(this: { environment?: { name?: string } }, id: string): string | null {
177
+ if (!hasDist) return null;
178
+ if (!id.startsWith(FLARE_PREFIX)) return null;
179
+
180
+ const subpath = id.slice(FLARE_PREFIX.length);
181
+ const mapping = MODULE_MAP[subpath];
182
+ if (!mapping) return null;
183
+
184
+ const env = this.environment?.name ?? "client";
185
+ return env === "ssr" ? mapping.ssr : mapping.client;
186
+ },
187
+ };
188
+ }
189
+
190
+ /* ── Generate ────────────────────────────────────────────────────────── */
191
+
192
+ function createGeneratePlugin(config: FlarePluginConfig, codegen: ReturnType<typeof resolveCodegenConfig>): VitePlugin {
193
+ const ignorePrefix = config.ignorePrefix ?? "_";
194
+
195
+ const generateOpts = {
196
+ fsCodegen: codegen.fsVirtualPaths,
197
+ ignorePrefix,
198
+ outputPath: codegen.routesFilePath,
199
+ rootDir: "",
200
+ typesOutputPath: codegen.typesFilePath,
201
+ };
202
+
203
+ return {
204
+ buildStart(this: { environment?: { config?: { root?: string } } }) {
205
+ const root = this.environment?.config?.root ?? process.cwd();
206
+ runGenerate({ ...generateOpts, rootDir: root });
207
+ },
208
+ configureServer(server: unknown) {
209
+ const srv = server as {
210
+ httpServer?: { on?: (event: string, fn: () => void) => void } | null;
211
+ config?: { root?: string };
212
+ };
213
+ const root = srv.config?.root ?? process.cwd();
214
+ const srcDir = join(root, "src");
215
+ let debounceTimer: ReturnType<typeof setTimeout> | undefined;
216
+
217
+ const watcher = watch(srcDir, { recursive: true }, (_event, filename) => {
218
+ if (!shouldTriggerGenerate(filename, String(_event), codegen.fsVirtualPaths)) return;
219
+
220
+ clearTimeout(debounceTimer);
221
+ debounceTimer = setTimeout(() => {
222
+ safeRunGenerate({ ...generateOpts, rootDir: root });
223
+ }, 100);
224
+ });
225
+
226
+ srv.httpServer?.on?.("close", () => {
227
+ clearTimeout(debounceTimer);
228
+ watcher.close();
229
+ });
230
+ return undefined;
231
+ },
232
+ name: "flare:generate",
233
+ };
234
+ }
235
+
236
+ /* ── SSR Build ───────────────────────────────────────────────────────── */
237
+
238
+ function createSsrBuildPlugin(
239
+ entries: ResolvedEntries,
240
+ config: FlarePluginConfig,
241
+ assetsBase: string,
242
+ assetsDir: string,
243
+ ): VitePlugin {
244
+ return {
245
+ config() {
246
+ return {
247
+ appType: "custom",
248
+ build: {
249
+ assetsDir,
250
+ },
251
+ builder: {
252
+ async buildApp(builder: { build: (env: unknown) => Promise<void>; environments: Record<string, unknown> }) {
253
+ await builder.build(builder.environments.client);
254
+ await builder.build(builder.environments.ssr);
255
+ },
256
+ sharedPlugins: true,
257
+ },
258
+ environments: {
259
+ client: {
260
+ build: {
261
+ manifest: true,
262
+ outDir: "dist/client",
263
+ rolldownOptions: {
264
+ external: ["node:async_hooks"],
265
+ input: entries.client,
266
+ output: {
267
+ assetFileNames: `${assetsDir}/[hash].[ext]`,
268
+ chunkFileNames: `${assetsDir}/[hash].js`,
269
+ entryFileNames: `${assetsDir}/client-[hash].js`,
270
+ },
271
+ },
272
+ },
273
+ },
274
+ ssr: {
275
+ build: {
276
+ minify: true,
277
+ outDir: "dist/server",
278
+ rolldownOptions: {
279
+ input: entries.server,
280
+ output: {
281
+ entryFileNames: "server.js",
282
+ },
283
+ },
284
+ },
285
+ },
286
+ },
287
+ optimizeDeps: {
288
+ include: ["solid-js", "solid-js/web", "solid-js/store"],
289
+ },
290
+ resolve: {
291
+ ...(config.alias ? { alias: config.alias } : {}),
292
+ dedupe: ["solid-js", "solid-js/web", "solid-js/store"],
293
+ },
294
+ server: {
295
+ ...(config.port ? { port: config.port } : {}),
296
+ watch: {
297
+ ignored: ["**/_gen/**", "**/*.gen.ts", "**/*.gen.tsx"],
298
+ },
299
+ },
300
+ ssr: {
301
+ noExternal: ["solid-js", "@lovrozagar/flare", "@tanstack/solid-query"],
302
+ },
303
+ };
304
+ },
305
+
306
+ configResolved(resolved: unknown) {
307
+ const r = resolved as { base: string; build?: { assetsDir?: string } };
308
+ /*
309
+ * Flare does not set Vite `base` — asset paths are controlled via
310
+ * rolldown output.*FileNames. Guard against a consumer setting
311
+ * build.assetsDir that conflicts with the flare-derived dir.
312
+ */
313
+ if (r.build?.assetsDir && r.build.assetsDir !== assetsDir) {
314
+ throw new Error(
315
+ `flare: vite "build.assetsDir" (${JSON.stringify(r.build.assetsDir)}) does not match assetsBase-derived dir (${JSON.stringify(assetsDir)}). Remove build.assetsDir from vite.config.ts.`,
316
+ );
317
+ }
318
+ },
319
+
320
+ name: "flare:ssr-build",
321
+ };
322
+ }
323
+
324
+ /* ── CSS Scope Plugin ────────────────────────────────────────────────── */
325
+
326
+ const CSS_ATTR_RE = /css="([^"]*)"/g;
327
+
328
+ function hashCSS(str: string): string {
329
+ let h = 0x811c9dc5;
330
+ for (let i = 0; i < str.length; i++) {
331
+ h = Math.imul(h ^ str.charCodeAt(i), 0x01000193);
332
+ }
333
+ h = Math.imul(h ^ (h >>> 16), 0x85ebca6b);
334
+ return (h >>> 0).toString(36);
335
+ }
336
+
337
+ export function createCssScopePlugin(): VitePlugin {
338
+ return {
339
+ enforce: "pre",
340
+ name: "flare:css-scope",
341
+ transform(code: string, id: string): { code: string; map: null } | null {
342
+ if (!id.endsWith(".tsx") && !id.endsWith(".jsx")) return null;
343
+ if (!CSS_ATTR_RE.test(code)) return null;
344
+
345
+ CSS_ATTR_RE.lastIndex = 0;
346
+ const transformed = code.replace(CSS_ATTR_RE, (_match, rawValue: string) => {
347
+ const cssValue = rawValue.replace(/&quot;/g, '"');
348
+ const hash = hashCSS(cssValue.trim());
349
+ const escaped = cssValue.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
350
+ return `data-c={__flare_registerCSSByName__("${hash}", "${escaped}")}`;
351
+ });
352
+
353
+ const importLine =
354
+ 'import { registerCSSByName as __flare_registerCSSByName__ } from "@lovrozagar/flare/styles"\n';
355
+ return { code: `${importLine}${transformed}`, map: null };
356
+ },
357
+ };
358
+ }
359
+
360
+ /* ── tw= diagnostic plugin ───────────────────────────────────────────── */
361
+
362
+ /* Warn authors who still write tw="..." — the attribute was dropped in favour of class=. */
363
+ function createTwDeprecatedPlugin(): VitePlugin {
364
+ return {
365
+ enforce: "pre",
366
+ name: "flare:tw-deprecated",
367
+ transform(this: { warn: (msg: string) => void }, code: string, id: string): null {
368
+ if (!id.endsWith(".tsx") && !id.endsWith(".jsx")) return null;
369
+ if (!code.includes("tw=")) return null;
370
+ this.warn(`[flare:tw] tw="..." attribute was dropped. Put Tailwind utilities in class="...". (${id})`);
371
+ return null;
372
+ },
373
+ };
374
+ }
375
+
376
+ /* ── Main export ─────────────────────────────────────────────────────── */
377
+
378
+ export function flare(config: FlarePluginConfig = EMPTY_OBJ): VitePlugin[] {
379
+ const root = process.cwd();
380
+ const resolvedOptions = resolveFlareOptions(config);
381
+ const resolvedCodegen = resolveCodegenConfig(config.codegen);
382
+ const resolvedDev = resolveDevConfig(config.dev);
383
+ const resolvedPurge = resolvePurgeConfig(config.purge);
384
+ const entries: ResolvedEntries = {
385
+ client: resolveEntry(root, "client", config.entry?.client),
386
+ server: resolveEntry(root, "server", config.entry?.server),
387
+ };
388
+
389
+ const solidConfig = {
390
+ extensions: [".tsx", ".jsx"],
391
+ hydratable: true,
392
+ ssr: true,
393
+ ...config.solid,
394
+ };
395
+
396
+ const resolvedSw = normalizeSwConfig(config.serviceWorker);
397
+
398
+ /* TS 7: vite + vite-plugin-solid Plugin identities overflow. Keep this list on VitePlugin. */
399
+ const plugins: VitePlugin[] = [
400
+ createTwDeprecatedPlugin(),
401
+ /* manifest: true always enabled so virtual:flare-sx-manifest is populated at SSR build time */
402
+ ...(config.sx
403
+ ? [createSxAstPlugin({ ...config.sx, manifest: true }, resolvedOptions.assetsBase) as unknown as VitePlugin]
404
+ : []),
405
+ createCssScopePlugin(),
406
+ solid(solidConfig) as unknown as VitePlugin,
407
+ createImagePlugin(config, resolvedOptions.assetsBase, resolvedOptions.assetsDir),
408
+ createResolverPlugin(),
409
+ createGeneratePlugin(config, resolvedCodegen),
410
+ createSsrBuildPlugin(entries, config, resolvedOptions.assetsBase, resolvedOptions.assetsDir),
411
+ createDevServerPlugin(entries, resolvedOptions.assetsBase),
412
+ createPreviewServerPlugin(resolvedOptions.assetsBase),
413
+ createVirtualPlugin(config, entries, resolvedCodegen),
414
+ createServerFnPlugin(config),
415
+ createCssTransformPlugin(),
416
+ (resolvedSw
417
+ ? createServiceWorkerPlugin(resolvedSw, resolvedOptions.assetsBase)
418
+ : createServiceWorkerDisabledPlugin()) as unknown as VitePlugin,
419
+ ];
420
+
421
+ /* Purge plugins */
422
+ if (resolvedPurge.console || resolvedPurge.debugger) {
423
+ plugins.push(createPurgePlugin(resolvedPurge));
424
+ }
425
+ if (resolvedPurge.testIds) {
426
+ plugins.push(createPurgeTestIdsPlugin(resolvedPurge.testIds));
427
+ }
428
+
429
+ if (config.prerender) {
430
+ plugins.push(createPrerenderPlugin(config));
431
+ }
432
+
433
+ /* Dev-only plugins */
434
+ if (resolvedDev.dashboard) {
435
+ plugins.push(createDevDashboardPlugin(config));
436
+ }
437
+ if (resolvedDev.cdnCache) {
438
+ plugins.push(createDevCdnCachePlugin());
439
+ }
440
+ if (resolvedDev.staticCache) {
441
+ plugins.push(createDevPrerenderPlugin(config, entries));
442
+ }
443
+
444
+ return plugins;
445
+ }
@@ -0,0 +1,37 @@
1
+ /** Resolved flare plugin options — frozen, constructed once at plugin entry. */
2
+ export interface ResolvedFlareOptions {
3
+ /** URL prefix for emitted assets. Empty string means root-relative ("/file.js"). */
4
+ readonly assetsBase: string;
5
+ /** On-disk directory inside outDir where assets are written. No leading slash. */
6
+ readonly assetsDir: string;
7
+ }
8
+
9
+ /** Validated, normalized assetsBase string. Throws with option name on violation. `"/"` → `""`. */
10
+ export function validateAssetsBase(value: unknown): string {
11
+ if (typeof value !== "string") {
12
+ throw new Error(`flare: assetsBase must be a string (got ${JSON.stringify(value)})`);
13
+ }
14
+ if (value.length === 0) {
15
+ throw new Error(`flare: assetsBase must not be empty (got ${JSON.stringify(value)})`);
16
+ }
17
+ /* Root-slash case — valid, normalizes to empty string so concat works uniformly */
18
+ if (value === "/") return "";
19
+ if (!value.startsWith("/")) {
20
+ throw new Error(`flare: assetsBase must start with "/" (got ${JSON.stringify(value)})`);
21
+ }
22
+ if (value.endsWith("/")) {
23
+ throw new Error(`flare: assetsBase must not end with "/" (got ${JSON.stringify(value)})`);
24
+ }
25
+ if (value.includes("?") || value.includes("#")) {
26
+ throw new Error(`flare: assetsBase must not contain "?" or "#" (got ${JSON.stringify(value)})`);
27
+ }
28
+ return value;
29
+ }
30
+
31
+ /** Resolves raw flare plugin config into a frozen, validated options object. */
32
+ export function resolveFlareOptions(raw: { assetsBase?: unknown }): ResolvedFlareOptions {
33
+ const assetsBase = raw.assetsBase === undefined ? "/assets" : validateAssetsBase(raw.assetsBase);
34
+ /* strip leading "/" — "/app/assets" → "app/assets", "" (root) → "assets" fallback */
35
+ const assetsDir = assetsBase === "" ? "assets" : assetsBase.slice(1);
36
+ return Object.freeze({ assetsBase, assetsDir });
37
+ }
@@ -0,0 +1,59 @@
1
+ /** String-aware brace matcher for JS/TS object literals */
2
+ export function findMatchingBraceSimple(str: string, start: number): number {
3
+ let depth = 0;
4
+ for (let i = start; i < str.length; i++) {
5
+ const ch = str[i];
6
+ /* Skip string literals */
7
+ if (ch === '"' || ch === "'") {
8
+ const q = ch;
9
+ i++;
10
+ while (i < str.length && str[i] !== q) {
11
+ if (str[i] === "\\") i++;
12
+ i++;
13
+ }
14
+ continue;
15
+ }
16
+ /* Skip template literals */
17
+ if (ch === "`") {
18
+ i++;
19
+ while (i < str.length && str[i] !== "`") {
20
+ if (str[i] === "\\") i++;
21
+ else if (str[i] === "$" && i + 1 < str.length && str[i + 1] === "{") {
22
+ i += 2;
23
+ let tDepth = 1;
24
+ while (i < str.length && tDepth > 0) {
25
+ if (str[i] === "{") tDepth++;
26
+ else if (str[i] === "}") tDepth--;
27
+ if (tDepth > 0) i++;
28
+ }
29
+ }
30
+ i++;
31
+ }
32
+ continue;
33
+ }
34
+ if (ch === "{") depth++;
35
+ else if (ch === "}") {
36
+ depth--;
37
+ if (depth === 0) return i;
38
+ }
39
+ }
40
+ return str.length - 1;
41
+ }
42
+
43
+ /**
44
+ * Extract the content inside the outermost parens starting at `start`.
45
+ * Returns [innerContent, endIndex] where endIndex points to the closing `)`.
46
+ */
47
+ export function extractParenContent(code: string, start: number): [string, number] | null {
48
+ if (code[start] !== "(") return null;
49
+ let depth = 1;
50
+ let i = start + 1;
51
+ for (; i < code.length; i++) {
52
+ if (code[i] === "(") depth++;
53
+ else if (code[i] === ")") {
54
+ depth--;
55
+ if (depth === 0) return [code.slice(start + 1, i), i];
56
+ }
57
+ }
58
+ return null;
59
+ }
@@ -0,0 +1,144 @@
1
+ import { existsSync, mkdirSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { scanSourceFiles } from "../generators/index.ts";
4
+ import { buildPrerenderRoutes, prerender, writePrerenderOutput } from "../prerender/index.ts";
5
+ import { buildSitemapFromDefs, type ChangeFreq, generateRobotsTxt, type SitemapEntry } from "../sitemap/index.ts";
6
+ import type { VitePlugin } from "./types.ts";
7
+
8
+ interface ServerModuleHandler {
9
+ fetch: (request: Request, env?: unknown) => Promise<Response>;
10
+ getStaticParams?: () => Promise<Map<string, Record<string, string | string[]>[]>>;
11
+ }
12
+
13
+ interface ServerModule {
14
+ handler?: ServerModuleHandler;
15
+ server?: ServerModuleHandler;
16
+ }
17
+
18
+ export interface SitemapPluginConfig {
19
+ additionalEntries?: SitemapEntry[];
20
+ changefreq?: ChangeFreq | Record<string, ChangeFreq>;
21
+ exclude?: string[];
22
+ origin: string;
23
+ priority?: number | Record<string, number>;
24
+ robotsTxt?: boolean | string;
25
+ }
26
+
27
+ export interface PrerenderPluginConfig {
28
+ concurrency?: number;
29
+ env?: Record<string, unknown> | (() => Record<string, unknown> | Promise<Record<string, unknown>>);
30
+ exclude?: string[];
31
+ origin?: string;
32
+ sitemap?: SitemapPluginConfig;
33
+ }
34
+
35
+ export function createPrerenderPlugin(config: {
36
+ ignorePrefix?: string;
37
+ prerender?: PrerenderPluginConfig | boolean;
38
+ }): VitePlugin {
39
+ const prerenderConfig = typeof config.prerender === "object" ? config.prerender : ({} as PrerenderPluginConfig);
40
+
41
+ return {
42
+ async closeBundle(this: { environment?: { config?: { root?: string }; name?: string } }): Promise<void> {
43
+ /* Only run during SSR build (after client is already built) */
44
+ const envName = this.environment?.name;
45
+ if (envName !== "ssr") return;
46
+
47
+ const root = this.environment?.config?.root ?? process.cwd();
48
+ const ignorePrefix = config.ignorePrefix ?? "_";
49
+
50
+ /* 1. Scan source for route definitions (needed by both sitemap and prerender) */
51
+ const defs = scanSourceFiles({ ignorePrefix, rootDir: root });
52
+ const staticDir = join(root, "dist/static");
53
+
54
+ /* 2. Generate sitemap if configured */
55
+ const sitemapConfig = prerenderConfig.sitemap;
56
+ if (sitemapConfig) {
57
+ mkdirSync(staticDir, { recursive: true });
58
+ const sitemapResult = buildSitemapFromDefs(defs, {
59
+ additionalEntries: sitemapConfig.additionalEntries,
60
+ changefreq: sitemapConfig.changefreq,
61
+ exclude: sitemapConfig.exclude,
62
+ origin: sitemapConfig.origin,
63
+ priority: sitemapConfig.priority,
64
+ });
65
+
66
+ for (const file of sitemapResult.files) {
67
+ writeFileSync(join(staticDir, file.path), file.content, "utf-8");
68
+ }
69
+
70
+ if (sitemapConfig.robotsTxt !== false && sitemapConfig.robotsTxt !== undefined) {
71
+ const sitemapUrl = `${sitemapConfig.origin}/sitemap.xml`;
72
+ const rules = typeof sitemapConfig.robotsTxt === "string" ? sitemapConfig.robotsTxt : undefined;
73
+ writeFileSync(join(staticDir, "robots.txt"), generateRobotsTxt(sitemapUrl, rules), "utf-8");
74
+ }
75
+
76
+ process.stderr.write(`[flare:prerender] Generated sitemap with ${sitemapResult.urls.length} URL(s)\n`);
77
+ }
78
+
79
+ /* 3. Import built server handler (needed for getStaticParams before buildPrerenderRoutes) */
80
+ const serverPath = join(root, "dist/server/server.js");
81
+ if (!existsSync(serverPath)) return;
82
+
83
+ /* Cloudflare Workers unenv polyfills access globalThis.Cloudflare at module
84
+ evaluation time. Shim it so the server module can load in plain Node.js. */
85
+ const g = globalThis as Record<string, unknown>;
86
+ if (!g.Cloudflare || typeof g.Cloudflare !== "object") {
87
+ g.Cloudflare = { compatibilityFlags: {} };
88
+ } else if (!(g.Cloudflare as Record<string, unknown>).compatibilityFlags) {
89
+ (g.Cloudflare as Record<string, unknown>).compatibilityFlags = {};
90
+ }
91
+
92
+ const mod = (await import(`${serverPath}?t=${Date.now()}`)) as ServerModule;
93
+
94
+ /* 4. Resolve static params for dynamic routes */
95
+ const hasDynamic = defs.some(
96
+ (d) => d.type === "page" && (d.cache.ssg === "dynamic" || d.cache.isr === "dynamic"),
97
+ );
98
+ const resolvedHandler = mod.server ?? mod.handler;
99
+ if (!resolvedHandler) return;
100
+ const staticParams =
101
+ hasDynamic && resolvedHandler.getStaticParams ? await resolvedHandler.getStaticParams() : undefined;
102
+
103
+ /* 5. Convert to prerender routes */
104
+ const routes = buildPrerenderRoutes(defs, staticParams);
105
+ if (routes.length === 0) return;
106
+
107
+ /* 6. Run prerender engine */
108
+ const origin = prerenderConfig.origin ?? "http://localhost";
109
+ const result = await prerender({
110
+ concurrency: prerenderConfig.concurrency,
111
+ env: prerenderConfig.env,
112
+ exclude: prerenderConfig.exclude,
113
+ handler: resolvedHandler,
114
+ origin,
115
+ routes,
116
+ });
117
+
118
+ /* Log errors */
119
+ for (const err of result.errors) {
120
+ process.stderr.write(`[flare:prerender] Error ${err.pathname}: ${err.message}\n`);
121
+ }
122
+
123
+ if (result.entries.length === 0) return;
124
+
125
+ /* 7. Generate output files + manifest */
126
+ const output = writePrerenderOutput(result.entries);
127
+
128
+ /* 8. Write to dist/static/ */
129
+ mkdirSync(staticDir, { recursive: true });
130
+
131
+ for (const file of output.files) {
132
+ const filePath = join(staticDir, file.path);
133
+ mkdirSync(dirname(filePath), { recursive: true });
134
+ writeFileSync(filePath, file.content, "utf-8");
135
+ }
136
+
137
+ /* 9. Write manifest */
138
+ writeFileSync(join(staticDir, "manifest.json"), JSON.stringify(output.manifest, null, 2), "utf-8");
139
+
140
+ process.stderr.write(`[flare:prerender] Pre-rendered ${result.entries.length} route(s)\n`);
141
+ },
142
+ name: "flare:prerender",
143
+ };
144
+ }