blume 1.7.3 → 2.0.1

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 (690) hide show
  1. package/AGENTS.md +19 -0
  2. package/CHANGELOG.md +245 -0
  3. package/README.md +34 -21
  4. package/dist/cli/{chunk-vacwm2hv.js → chunk-27g6wdth.js} +2 -2
  5. package/dist/cli/{chunk-ps4m1xh4.js → chunk-2hn4b8z7.js} +513 -550
  6. package/dist/cli/chunk-2hn4b8z7.js.map +12 -0
  7. package/dist/cli/chunk-5shv93fd.js +39 -0
  8. package/dist/cli/chunk-5shv93fd.js.map +10 -0
  9. package/dist/cli/chunk-6crbhc3x.js +361 -0
  10. package/dist/cli/chunk-6crbhc3x.js.map +14 -0
  11. package/dist/cli/{chunk-8cjtbafj.js → chunk-6hsn950k.js} +109 -383
  12. package/dist/cli/chunk-6hsn950k.js.map +10 -0
  13. package/dist/cli/chunk-6vm74dry.js +148 -0
  14. package/dist/cli/chunk-6vm74dry.js.map +10 -0
  15. package/dist/cli/{chunk-yg63d42r.js → chunk-79jhk4py.js} +87 -58
  16. package/dist/cli/chunk-79jhk4py.js.map +35 -0
  17. package/dist/cli/chunk-82bbrxdn.js +51 -0
  18. package/dist/cli/chunk-82bbrxdn.js.map +10 -0
  19. package/dist/cli/chunk-abh8yjkn.js +31 -0
  20. package/dist/cli/chunk-abh8yjkn.js.map +10 -0
  21. package/dist/cli/chunk-ah61y8py.js +75 -0
  22. package/dist/cli/chunk-ah61y8py.js.map +11 -0
  23. package/dist/cli/{chunk-dwgcp5sm.js → chunk-ce574jw2.js} +1 -1
  24. package/dist/cli/chunk-ch6g3ar0.js +102 -0
  25. package/dist/cli/chunk-ch6g3ar0.js.map +10 -0
  26. package/dist/cli/chunk-dh8cwk36.js +279 -0
  27. package/dist/cli/chunk-dh8cwk36.js.map +10 -0
  28. package/dist/cli/{chunk-rqy0s5wh.js → chunk-epjnccmv.js} +17 -16
  29. package/dist/cli/{chunk-rqy0s5wh.js.map → chunk-epjnccmv.js.map} +3 -3
  30. package/dist/cli/chunk-f2z5v128.js +97 -0
  31. package/dist/cli/chunk-f2z5v128.js.map +10 -0
  32. package/dist/cli/{chunk-2z47ypj8.js → chunk-fa25z98p.js} +16 -3
  33. package/dist/cli/chunk-fa25z98p.js.map +11 -0
  34. package/dist/cli/{chunk-1jefwnfs.js → chunk-fs23ddbb.js} +1076 -2592
  35. package/dist/cli/chunk-fs23ddbb.js.map +35 -0
  36. package/dist/cli/{chunk-e7f42gdj.js → chunk-fxypxtvm.js} +2 -2
  37. package/dist/cli/{chunk-bvwwhd84.js → chunk-fz5wtpmh.js} +15 -15
  38. package/dist/cli/{chunk-bvwwhd84.js.map → chunk-fz5wtpmh.js.map} +1 -1
  39. package/dist/cli/chunk-hdpx1tax.js +91 -0
  40. package/dist/cli/chunk-hdpx1tax.js.map +10 -0
  41. package/dist/cli/{chunk-ct47dqpx.js → chunk-jts8mvcz.js} +67 -7
  42. package/dist/cli/{chunk-2mzebbbz.js.map → chunk-jts8mvcz.js.map} +6 -4
  43. package/dist/cli/{chunk-ahnw3kxw.js → chunk-jwyddg7y.js} +27 -22
  44. package/dist/cli/chunk-jwyddg7y.js.map +15 -0
  45. package/dist/cli/{chunk-cjtn640a.js → chunk-kdp5q7ke.js} +43 -20
  46. package/dist/cli/chunk-kdp5q7ke.js.map +10 -0
  47. package/dist/cli/{chunk-5g0w1e2c.js → chunk-kpf8rrjc.js} +28 -16
  48. package/dist/cli/{chunk-5g0w1e2c.js.map → chunk-kpf8rrjc.js.map} +4 -4
  49. package/dist/cli/chunk-m3vmjgmq.js +133 -0
  50. package/dist/cli/chunk-m3vmjgmq.js.map +10 -0
  51. package/dist/cli/{chunk-b27xqwn9.js → chunk-mb2919y2.js} +9 -5
  52. package/dist/cli/chunk-mb2919y2.js.map +10 -0
  53. package/dist/cli/{chunk-5qk08vmp.js → chunk-q5163e60.js} +133 -54
  54. package/dist/cli/chunk-q5163e60.js.map +11 -0
  55. package/dist/cli/chunk-qkqwkpte.js +12437 -0
  56. package/dist/cli/chunk-qkqwkpte.js.map +182 -0
  57. package/dist/cli/{chunk-4x36ddpw.js → chunk-qs4q5p4e.js} +81 -87
  58. package/dist/cli/chunk-qs4q5p4e.js.map +10 -0
  59. package/dist/cli/{chunk-0xjyb285.js → chunk-qwsrynx5.js} +15 -5
  60. package/dist/cli/{chunk-0xjyb285.js.map → chunk-qwsrynx5.js.map} +4 -4
  61. package/dist/cli/chunk-s1p84fyh.js +261 -0
  62. package/dist/cli/chunk-s1p84fyh.js.map +10 -0
  63. package/dist/cli/chunk-s6jhgk0q.js +176 -0
  64. package/dist/cli/chunk-s6jhgk0q.js.map +11 -0
  65. package/dist/cli/chunk-vtk4a6dg.js +374 -0
  66. package/dist/cli/chunk-vtk4a6dg.js.map +10 -0
  67. package/dist/cli/{chunk-k79xp7av.js → chunk-wgm7m9qk.js} +230 -700
  68. package/dist/cli/chunk-wgm7m9qk.js.map +36 -0
  69. package/dist/cli/chunk-wm7js3j9.js +145 -0
  70. package/dist/cli/chunk-wm7js3j9.js.map +11 -0
  71. package/dist/cli/chunk-yt5n7ppj.js +79 -0
  72. package/dist/cli/chunk-yt5n7ppj.js.map +10 -0
  73. package/dist/cli/{chunk-3r45185y.js → chunk-yw7dm696.js} +9 -11
  74. package/dist/cli/{chunk-3r45185y.js.map → chunk-yw7dm696.js.map} +3 -3
  75. package/dist/cli/{chunk-nn13znc2.js → chunk-zxcczpyx.js} +1 -1
  76. package/dist/cli/chunk-zxh4d9vy.js +122 -0
  77. package/dist/cli/chunk-zxh4d9vy.js.map +11 -0
  78. package/dist/cli/index.js +214 -57
  79. package/dist/cli/index.js.map +8 -7
  80. package/dist/types/ai/agent-readability.d.ts +52 -0
  81. package/dist/types/ai/ai-catalog.d.ts +42 -0
  82. package/dist/types/ai/api/paths.d.ts +17 -0
  83. package/dist/types/ai/api-catalog.d.ts +18 -0
  84. package/dist/types/ai/ask-context.d.ts +7 -7
  85. package/dist/types/ai/ask.d.ts +368 -0
  86. package/dist/types/ai/changelog-markdown.d.ts +2 -0
  87. package/dist/types/ai/component-markdown.d.ts +2 -2
  88. package/dist/types/ai/index.d.ts +24 -0
  89. package/dist/types/ai/link-headers.d.ts +24 -0
  90. package/dist/types/ai/llms.d.ts +25 -0
  91. package/dist/types/ai/markdown.d.ts +45 -0
  92. package/dist/types/ai/mcp/discovery.d.ts +68 -0
  93. package/dist/types/ai/mcp/tools.d.ts +16 -0
  94. package/dist/types/ai/openapi-components.d.ts +43 -0
  95. package/dist/types/ai/relative-links.d.ts +26 -0
  96. package/dist/types/ai/serializers.d.ts +15 -0
  97. package/dist/types/ai/skills.d.ts +42 -0
  98. package/dist/types/ai/tar.d.ts +25 -0
  99. package/dist/types/ai/visibility.d.ts +17 -0
  100. package/dist/types/ai/web-bot-auth.d.ts +16 -0
  101. package/dist/types/analytics/adobe.d.ts +35 -0
  102. package/dist/types/analytics/amplitude.d.ts +50 -0
  103. package/dist/types/analytics/clarity.d.ts +31 -0
  104. package/dist/types/analytics/clearbit.d.ts +29 -0
  105. package/dist/types/analytics/cloudflare.d.ts +41 -0
  106. package/dist/types/analytics/fathom.d.ts +41 -0
  107. package/dist/types/analytics/google-analytics.d.ts +44 -0
  108. package/dist/types/analytics/google-tag-manager.d.ts +40 -0
  109. package/dist/types/analytics/head.d.ts +30 -0
  110. package/dist/types/analytics/heap.d.ts +40 -0
  111. package/dist/types/analytics/hightouch.d.ts +44 -0
  112. package/dist/types/analytics/hotjar.d.ts +33 -0
  113. package/dist/types/analytics/index.d.ts +61 -0
  114. package/dist/types/analytics/inline.d.ts +17 -0
  115. package/dist/types/analytics/logrocket.d.ts +44 -0
  116. package/dist/types/analytics/mixpanel.d.ts +67 -0
  117. package/dist/types/analytics/pirsch.d.ts +42 -0
  118. package/dist/types/analytics/plausible.d.ts +56 -0
  119. package/dist/types/analytics/posthog.d.ts +45 -0
  120. package/dist/types/analytics/schema.d.ts +320 -0
  121. package/dist/types/analytics/script.d.ts +46 -0
  122. package/dist/types/analytics/segment.d.ts +50 -0
  123. package/dist/types/analytics/vercel.d.ts +48 -0
  124. package/dist/types/astro/integration.d.ts +76 -0
  125. package/dist/types/astro/markdown-negotiation.d.ts +23 -0
  126. package/dist/types/astro/module-types.d.ts +14 -0
  127. package/dist/types/astro/pages.d.ts +44 -0
  128. package/dist/types/cli/env.d.ts +12 -0
  129. package/dist/types/cli/init/scaffold.d.ts +154 -0
  130. package/dist/types/components/layout/nav-utils.d.ts +11 -0
  131. package/dist/types/core/adapter.d.ts +47 -0
  132. package/dist/types/core/api-name.d.ts +7 -0
  133. package/dist/types/core/changelog-index.d.ts +13 -0
  134. package/dist/types/core/config-input.d.ts +197 -526
  135. package/dist/types/core/config.d.ts +61 -35
  136. package/dist/types/core/content-assets.d.ts +76 -0
  137. package/dist/types/core/custom-pages.d.ts +33 -0
  138. package/dist/types/core/data.d.ts +30 -15
  139. package/dist/types/core/define-components.d.ts +12 -9
  140. package/dist/types/core/deployment-env.d.ts +6 -11
  141. package/dist/types/core/frontmatter.d.ts +10 -0
  142. package/dist/types/core/graph.d.ts +18 -0
  143. package/dist/types/core/heading-markers.d.ts +54 -0
  144. package/dist/types/core/i18n-ui.d.ts +12 -10
  145. package/dist/types/core/i18n.d.ts +87 -0
  146. package/dist/types/core/includes.d.ts +138 -0
  147. package/dist/types/core/last-modified.d.ts +47 -0
  148. package/dist/types/core/links.d.ts +95 -0
  149. package/dist/types/core/locale-links.d.ts +60 -0
  150. package/dist/types/core/manifest.d.ts +17 -0
  151. package/dist/types/core/meta.d.ts +38 -0
  152. package/dist/types/core/nav-diagnostics.d.ts +26 -0
  153. package/dist/types/core/navigation.d.ts +6 -0
  154. package/dist/types/core/node-require.d.ts +19 -0
  155. package/dist/types/core/package-json.d.ts +13 -0
  156. package/dist/types/core/probe.d.ts +42 -0
  157. package/dist/types/core/project-graph.d.ts +51 -0
  158. package/dist/types/core/project.d.ts +2 -0
  159. package/dist/types/core/safe-href.d.ts +2 -0
  160. package/dist/types/core/safe-links.d.ts +26 -0
  161. package/dist/types/core/schema.d.ts +2284 -454
  162. package/dist/types/core/site-url.d.ts +16 -0
  163. package/dist/types/core/sources/assets.d.ts +36 -0
  164. package/dist/types/core/sources/cache.d.ts +37 -0
  165. package/dist/types/core/sources/collection.d.ts +28 -0
  166. package/dist/types/core/sources/contentful-rich-text.d.ts +31 -0
  167. package/dist/types/core/sources/contentful.d.ts +40 -0
  168. package/dist/types/core/sources/filesystem.d.ts +24 -0
  169. package/dist/types/core/sources/github-releases.d.ts +31 -0
  170. package/dist/types/core/sources/json.d.ts +30 -0
  171. package/dist/types/core/sources/lexical.d.ts +19 -0
  172. package/dist/types/core/sources/lower.d.ts +75 -0
  173. package/dist/types/core/sources/mdx-remote.d.ts +28 -0
  174. package/dist/types/core/sources/normalize.d.ts +147 -0
  175. package/dist/types/core/sources/notion.d.ts +131 -0
  176. package/dist/types/core/sources/obsidian.d.ts +46 -0
  177. package/dist/types/core/sources/payload.d.ts +39 -0
  178. package/dist/types/core/sources/portable-text.d.ts +42 -0
  179. package/dist/types/core/sources/read.d.ts +23 -0
  180. package/dist/types/core/sources/remote.d.ts +74 -0
  181. package/dist/types/core/sources/resolve.d.ts +19 -0
  182. package/dist/types/core/sources/sanity.d.ts +43 -0
  183. package/dist/types/core/sources/strapi-blocks.d.ts +12 -0
  184. package/dist/types/core/sources/strapi.d.ts +33 -0
  185. package/dist/types/core/sources/types.d.ts +7 -0
  186. package/dist/types/core/sources/watch.d.ts +45 -0
  187. package/dist/types/core/text-width.d.ts +11 -0
  188. package/dist/types/core/types.d.ts +15 -1
  189. package/dist/types/core/unrecognized-keys.d.ts +7 -0
  190. package/dist/types/core/versions.d.ts +72 -0
  191. package/dist/types/core/yaml.d.ts +9 -0
  192. package/dist/types/deploy/adapter-output.d.ts +45 -0
  193. package/dist/types/deploy/adapters/cloudflare.d.ts +40 -0
  194. package/dist/types/deploy/adapters/index.d.ts +29 -0
  195. package/dist/types/deploy/adapters/netlify.d.ts +37 -0
  196. package/dist/types/deploy/adapters/node.d.ts +37 -0
  197. package/dist/types/deploy/adapters/registry.d.ts +133 -0
  198. package/dist/types/deploy/adapters/types.d.ts +71 -0
  199. package/dist/types/deploy/adapters/vercel.d.ts +38 -0
  200. package/dist/types/deploy/artifacts.d.ts +65 -0
  201. package/dist/types/deploy/cloudflare-negotiation.d.ts +196 -0
  202. package/dist/types/deploy/function-bundle.d.ts +80 -0
  203. package/dist/types/deploy/headers.d.ts +50 -0
  204. package/dist/types/deploy/node-headers.d.ts +42 -0
  205. package/dist/types/deploy/platforms/cloudflare.d.ts +40 -0
  206. package/dist/types/deploy/platforms/index.d.ts +18 -0
  207. package/dist/types/deploy/platforms/netlify.d.ts +13 -0
  208. package/dist/types/deploy/platforms/node.d.ts +11 -0
  209. package/dist/types/deploy/platforms/paths.d.ts +27 -0
  210. package/dist/types/deploy/platforms/static.d.ts +10 -0
  211. package/dist/types/deploy/platforms/types.d.ts +104 -0
  212. package/dist/types/deploy/platforms/vercel.d.ts +32 -0
  213. package/dist/types/deploy/redirects.d.ts +53 -0
  214. package/dist/types/deploy/robots.d.ts +8 -0
  215. package/dist/types/deploy/rss.d.ts +31 -0
  216. package/dist/types/deploy/sitemap.d.ts +21 -0
  217. package/dist/types/deploy/vercel-negotiation.d.ts +109 -0
  218. package/dist/types/markdown/code-title.d.ts +32 -0
  219. package/dist/types/markdown/fence-meta.d.ts +23 -0
  220. package/dist/types/markdown/themes.d.ts +3 -3
  221. package/dist/types/openapi/asyncapi.d.ts +129 -0
  222. package/dist/types/openapi/graphql-build.d.ts +8 -0
  223. package/dist/types/openapi/graphql.d.ts +122 -0
  224. package/dist/types/openapi/model.d.ts +158 -0
  225. package/dist/types/openapi/parse.d.ts +57 -0
  226. package/dist/types/openapi/references.d.ts +37 -25
  227. package/dist/types/openapi/render-mdx.d.ts +33 -0
  228. package/dist/types/openapi/sentence.d.ts +7 -0
  229. package/dist/types/openapi/signature.d.ts +10 -0
  230. package/dist/types/openapi/source.d.ts +22 -0
  231. package/dist/types/openapi/spec-dependency-error.d.ts +10 -0
  232. package/dist/types/reference/asyncapi.d.ts +166 -0
  233. package/dist/types/reference/graphql.d.ts +181 -0
  234. package/dist/types/reference/index.d.ts +32 -0
  235. package/dist/types/reference/openapi.d.ts +165 -0
  236. package/dist/types/reference/options.d.ts +157 -0
  237. package/dist/types/reference/scalar.d.ts +136 -0
  238. package/dist/types/reference/schema.d.ts +630 -0
  239. package/dist/types/search/adapters/algolia.d.ts +32 -0
  240. package/dist/types/search/adapters/flexsearch.d.ts +12 -0
  241. package/dist/types/search/adapters/index.d.ts +31 -0
  242. package/dist/types/search/adapters/mixedbread.d.ts +22 -0
  243. package/dist/types/search/adapters/orama-cloud.d.ts +33 -0
  244. package/dist/types/search/adapters/orama.d.ts +13 -0
  245. package/dist/types/search/adapters/pagefind.d.ts +12 -0
  246. package/dist/types/search/adapters/registry.d.ts +228 -0
  247. package/dist/types/search/adapters/types.d.ts +34 -0
  248. package/dist/types/search/adapters/typesense.d.ts +42 -0
  249. package/dist/types/search/build.d.ts +23 -0
  250. package/dist/types/search/documents.d.ts +90 -0
  251. package/dist/types/search/facets.d.ts +3 -0
  252. package/dist/types/search/orama-index.d.ts +1 -1
  253. package/dist/types/search/sync/algolia.d.ts +14 -0
  254. package/dist/types/search/sync/index.d.ts +14 -0
  255. package/dist/types/search/sync/orama-cloud.d.ts +10 -0
  256. package/dist/types/search/sync/typesense.d.ts +14 -0
  257. package/dist/types/sources/contentful.d.ts +68 -0
  258. package/dist/types/sources/custom.d.ts +20 -0
  259. package/dist/types/sources/filesystem.d.ts +42 -0
  260. package/dist/types/sources/github-releases.d.ts +46 -0
  261. package/dist/types/sources/index.d.ts +48 -0
  262. package/dist/types/sources/mdx-remote.d.ts +63 -0
  263. package/dist/types/sources/notion.d.ts +65 -0
  264. package/dist/types/sources/obsidian.d.ts +34 -0
  265. package/dist/types/sources/payload.d.ts +68 -0
  266. package/dist/types/sources/registry.d.ts +1414 -0
  267. package/dist/types/sources/sanity.d.ts +69 -0
  268. package/dist/types/sources/shared.d.ts +46 -0
  269. package/dist/types/sources/strapi.d.ts +66 -0
  270. package/dist/types/theme/icon-kind.d.ts +11 -0
  271. package/dist/types/theme/icons.d.ts +20 -0
  272. package/docs/01-quickstart.mdx +18 -18
  273. package/docs/02-deployment.mdx +52 -28
  274. package/docs/03-upgrading.mdx +364 -0
  275. package/docs/04-migrating.mdx +58 -0
  276. package/docs/08-faq.mdx +5 -5
  277. package/docs/advanced/blog.mdx +13 -6
  278. package/docs/advanced/changelog.mdx +23 -35
  279. package/docs/advanced/custom-pages.mdx +22 -10
  280. package/docs/advanced/meta.ts +1 -8
  281. package/docs/advanced/skills.mdx +8 -0
  282. package/docs/cli/audit.mdx +646 -0
  283. package/docs/cli/doctor.mdx +29 -0
  284. package/docs/{reference/eval.mdx → cli/evals.mdx} +12 -11
  285. package/docs/cli/index.mdx +105 -0
  286. package/docs/cli/meta.ts +7 -0
  287. package/docs/{reference → cli}/translate.mdx +9 -9
  288. package/docs/cli/validate.mdx +41 -0
  289. package/docs/cli/version.mdx +40 -0
  290. package/docs/configuration/analytics.mdx +350 -59
  291. package/docs/configuration/assistant.mdx +357 -0
  292. package/docs/configuration/customization.mdx +16 -10
  293. package/docs/configuration/index.mdx +50 -31
  294. package/docs/configuration/meta.ts +1 -1
  295. package/docs/configuration/search.mdx +76 -55
  296. package/docs/configuration/theming.mdx +24 -15
  297. package/docs/content/components.mdx +21 -5
  298. package/docs/{reference → content}/frontmatter.mdx +35 -1
  299. package/docs/content/i18n.mdx +9 -7
  300. package/docs/content/includes.mdx +2 -4
  301. package/docs/content/index.mdx +1 -1
  302. package/docs/content/islands.mdx +11 -6
  303. package/docs/content/meta.mdx +1 -1
  304. package/docs/content/meta.ts +1 -0
  305. package/docs/content/navigation.mdx +9 -7
  306. package/docs/content/sources.mdx +145 -50
  307. package/docs/content/syntax.mdx +16 -12
  308. package/docs/content/versioning.mdx +3 -3
  309. package/docs/discoverability/agent-discovery.mdx +12 -12
  310. package/docs/discoverability/index.mdx +4 -4
  311. package/docs/discoverability/json-api.mdx +4 -4
  312. package/docs/discoverability/llms-txt.mdx +6 -6
  313. package/docs/discoverability/markdown.mdx +4 -4
  314. package/docs/discoverability/mcp.mdx +11 -11
  315. package/docs/discoverability/sitemap-and-robots.mdx +3 -3
  316. package/docs/index.mdx +4 -4
  317. package/docs/references/asyncapi.mdx +59 -0
  318. package/docs/{advanced → references}/graphql.mdx +45 -32
  319. package/docs/{reference → references}/meta.ts +2 -2
  320. package/docs/references/openapi.mdx +171 -0
  321. package/docs/references/scalar.mdx +64 -0
  322. package/package.json +42 -8
  323. package/skills/blume/SKILL.md +23 -10
  324. package/skills/blume-migrate/SKILL.md +22 -21
  325. package/skills/blume-migrate/assets/oxfmt@0.67.0.patch +49 -0
  326. package/skills/blume-migrate/references/docusaurus.md +5 -4
  327. package/skills/blume-migrate/references/fumadocs.md +4 -4
  328. package/skills/blume-migrate/references/mintlify.md +23 -8
  329. package/skills/blume-migrate/references/monorepo.md +6 -6
  330. package/skills/blume-migrate/references/starlight.md +4 -4
  331. package/src/ai/agent-readability.ts +25 -26
  332. package/src/ai/ai-catalog.ts +50 -32
  333. package/src/ai/api/handlers.ts +46 -11
  334. package/src/ai/api/paths.ts +1 -1
  335. package/src/ai/api-catalog.ts +8 -8
  336. package/src/ai/ask-context.ts +7 -7
  337. package/src/ai/ask-data.ts +3 -3
  338. package/src/ai/ask.ts +637 -100
  339. package/src/ai/changelog-markdown.ts +91 -0
  340. package/src/ai/component-markdown.ts +328 -12
  341. package/src/ai/cors.ts +3 -3
  342. package/src/ai/index.ts +45 -0
  343. package/src/ai/link-headers.ts +7 -6
  344. package/src/ai/llms.ts +20 -15
  345. package/src/ai/markdown.ts +35 -5
  346. package/src/ai/mcp/data.ts +9 -5
  347. package/src/ai/openapi-components.ts +5 -2
  348. package/src/ai/relative-links.ts +170 -0
  349. package/src/ai/serializers.ts +3 -3
  350. package/src/ai/skills.ts +1 -1
  351. package/src/ai/visibility.ts +1 -1
  352. package/src/ai/web-bot-auth.ts +2 -2
  353. package/src/analytics/adobe.ts +46 -0
  354. package/src/analytics/amplitude.ts +79 -0
  355. package/src/analytics/clarity.ts +46 -0
  356. package/src/analytics/clearbit.ts +47 -0
  357. package/src/analytics/cloudflare.ts +67 -0
  358. package/src/analytics/fathom.ts +64 -0
  359. package/src/analytics/google-analytics.ts +84 -0
  360. package/src/analytics/google-tag-manager.ts +61 -0
  361. package/src/analytics/head.ts +130 -0
  362. package/src/analytics/heap.ts +65 -0
  363. package/src/analytics/hightouch.ts +77 -0
  364. package/src/analytics/hotjar.ts +47 -0
  365. package/src/analytics/index.ts +71 -0
  366. package/src/analytics/inline.ts +21 -0
  367. package/src/analytics/logrocket.ts +71 -0
  368. package/src/analytics/mixpanel.ts +92 -0
  369. package/src/analytics/pirsch.ts +66 -0
  370. package/src/analytics/plausible.ts +83 -0
  371. package/src/analytics/posthog.ts +78 -0
  372. package/src/analytics/schema.ts +60 -0
  373. package/src/analytics/script.ts +60 -0
  374. package/src/analytics/segment.ts +85 -0
  375. package/src/analytics/vercel.ts +50 -0
  376. package/src/astro/adapter-root.ts +7 -9
  377. package/src/astro/component-slots.ts +131 -91
  378. package/src/astro/generate.ts +129 -361
  379. package/src/astro/integration.ts +2 -6
  380. package/src/astro/module-types.ts +1 -1
  381. package/src/astro/pages.ts +13 -101
  382. package/src/astro/render-deps.ts +379 -0
  383. package/src/astro/runtime-deps.ts +201 -0
  384. package/src/astro/templates.ts +575 -562
  385. package/src/audit/agent.ts +24 -0
  386. package/src/audit/catalog.ts +2 -2
  387. package/src/audit/checks/assets.ts +2 -2
  388. package/src/audit/checks/dns-aid.ts +1 -1
  389. package/src/audit/checks/duplicates.ts +3 -1
  390. package/src/audit/checks/i18n.ts +1 -1
  391. package/src/audit/checks/indexability.ts +7 -7
  392. package/src/audit/checks/links.ts +2 -2
  393. package/src/audit/checks/llms.ts +6 -6
  394. package/src/audit/checks/network.ts +3 -3
  395. package/src/audit/checks/og-image.ts +2 -2
  396. package/src/audit/checks/robots.ts +1 -1
  397. package/src/audit/checks/sitemap.ts +2 -2
  398. package/src/audit/checks/social.ts +1 -1
  399. package/src/audit/run.ts +4 -3
  400. package/src/audit/terms.ts +31 -0
  401. package/src/audit/url.ts +13 -13
  402. package/src/blume-modules.d.ts +2 -2
  403. package/src/cli/command-meta.ts +10 -0
  404. package/src/cli/commands/audit.ts +40 -21
  405. package/src/cli/commands/build.ts +71 -316
  406. package/src/cli/commands/check.ts +1 -0
  407. package/src/cli/commands/dev.ts +40 -1
  408. package/src/cli/commands/doctor.ts +92 -14
  409. package/src/cli/commands/eject.ts +44 -7
  410. package/src/cli/commands/eval.ts +5 -5
  411. package/src/cli/commands/init.ts +161 -41
  412. package/src/cli/commands/migrate.ts +121 -0
  413. package/src/cli/commands/preview.ts +7 -1
  414. package/src/cli/commands/translate.ts +5 -5
  415. package/src/cli/commands/upgrade.ts +141 -0
  416. package/src/cli/commands/version.ts +57 -44
  417. package/src/cli/eject-scripts.ts +121 -6
  418. package/src/cli/index.ts +11 -1
  419. package/src/cli/init/install.ts +70 -0
  420. package/src/cli/init/questions.ts +7 -0
  421. package/src/cli/init/scaffold.ts +459 -75
  422. package/src/cli/lazy-command.ts +37 -1
  423. package/src/cli/prepare.ts +40 -6
  424. package/src/cli/required-secrets.ts +39 -12
  425. package/src/cli/unknown-flags.ts +266 -0
  426. package/src/cli/yarn-pnp.ts +52 -0
  427. package/src/components/content/AccordionItem.astro +7 -1
  428. package/src/components/content/Card.astro +4 -3
  429. package/src/components/content/ColorItem.astro +22 -4
  430. package/src/components/content/GithubInfo.astro +2 -2
  431. package/src/components/content/Prompt.astro +25 -25
  432. package/src/components/content/Tabs.astro +3 -1
  433. package/src/components/content/Tile.astro +2 -3
  434. package/src/components/content/Tooltip.astro +57 -9
  435. package/src/components/content/content-strings.ts +34 -0
  436. package/src/components/content/diff.ts +1 -1
  437. package/src/components/content/mermaid-element.ts +13 -2
  438. package/src/components/content/prompt-markdown.ts +292 -0
  439. package/src/components/content/tooltip-id.ts +41 -0
  440. package/src/components/copy-feedback.ts +1 -1
  441. package/src/components/islands/{AskAI.astro → Assistant.astro} +10 -10
  442. package/src/components/islands/{ask-ai.tsx → assistant.tsx} +23 -23
  443. package/src/components/islands/hooks.ts +36 -11
  444. package/src/components/layout/Analytics.astro +21 -79
  445. package/src/components/layout/Banner.astro +3 -1
  446. package/src/components/layout/DiscoveryLinks.astro +69 -0
  447. package/src/components/layout/Header.astro +93 -30
  448. package/src/components/layout/LanguageSwitcher.astro +4 -1
  449. package/src/components/layout/Logo.astro +23 -2
  450. package/src/components/layout/NavSelector.astro +13 -2
  451. package/src/components/layout/NavTree.astro +12 -3
  452. package/src/components/layout/NavTreeScript.astro +17 -3
  453. package/src/components/layout/PageActions.astro +3 -3
  454. package/src/components/layout/PageFeedback.astro +11 -1
  455. package/src/components/layout/PageLayout.astro +58 -11
  456. package/src/components/layout/Pagination.astro +7 -7
  457. package/src/components/layout/ReferenceLayout.astro +22 -13
  458. package/src/components/layout/RootLayout.astro +75 -72
  459. package/src/components/layout/Search.astro +43 -19
  460. package/src/components/layout/WebMcp.astro +1 -1
  461. package/src/components/layout/analytics-client.ts +73 -16
  462. package/src/components/layout/drawer-inert.ts +113 -15
  463. package/src/components/layout/dropdown-clamp.ts +105 -0
  464. package/src/components/layout/head-scripts.ts +15 -6
  465. package/src/components/layout/nav-utils.ts +17 -0
  466. package/src/components/layout/search/algolia.ts +8 -8
  467. package/src/components/layout/search/orama-cloud.ts +9 -7
  468. package/src/components/layout/search/typesense.ts +11 -17
  469. package/src/components/openapi/MessageComposer.astro +2 -2
  470. package/src/components/openapi/Playground.astro +2 -2
  471. package/src/components/openapi/description.ts +2 -2
  472. package/src/components/openapi/playground-client.ts +79 -10
  473. package/src/core/changelog-index.ts +24 -0
  474. package/src/core/code-fences.ts +1 -1
  475. package/src/core/component-overrides.ts +399 -154
  476. package/src/core/config-input.ts +201 -566
  477. package/src/core/config.ts +131 -42
  478. package/src/core/custom-pages.ts +105 -0
  479. package/src/core/data.ts +34 -15
  480. package/src/core/define-components.ts +12 -9
  481. package/src/core/deployment-env.ts +18 -74
  482. package/src/core/diagnostics.ts +14 -7
  483. package/src/core/graph.ts +69 -25
  484. package/src/core/i18n-ui.ts +41 -11
  485. package/src/core/i18n.ts +17 -0
  486. package/src/core/includes.ts +156 -38
  487. package/src/core/last-modified.ts +6 -11
  488. package/src/core/links.ts +166 -2
  489. package/src/core/manifest.ts +10 -3
  490. package/src/core/navigation.ts +115 -16
  491. package/src/core/new-tab.ts +35 -0
  492. package/src/core/node-require.ts +21 -0
  493. package/src/core/project-graph.ts +42 -26
  494. package/src/core/project.ts +9 -4
  495. package/src/core/request-body.ts +61 -0
  496. package/src/core/safe-href.ts +28 -0
  497. package/src/core/safe-links.ts +68 -0
  498. package/src/core/schema.ts +528 -745
  499. package/src/core/server-features.ts +10 -11
  500. package/src/core/sources/assets.ts +47 -11
  501. package/src/core/sources/collection.ts +67 -0
  502. package/src/core/sources/contentful-rich-text.ts +285 -0
  503. package/src/core/sources/contentful.ts +173 -0
  504. package/src/core/sources/github-releases.ts +51 -1
  505. package/src/core/sources/json.ts +71 -0
  506. package/src/core/sources/lexical.ts +195 -0
  507. package/src/core/sources/lower.ts +226 -0
  508. package/src/core/sources/normalize.ts +52 -2
  509. package/src/core/sources/notion.ts +39 -28
  510. package/src/core/sources/payload.ts +135 -0
  511. package/src/core/sources/portable-text.ts +11 -16
  512. package/src/core/sources/remote.ts +226 -0
  513. package/src/core/sources/resolve.ts +104 -166
  514. package/src/core/sources/sanity.ts +16 -49
  515. package/src/core/sources/strapi-blocks.ts +124 -0
  516. package/src/core/sources/strapi.ts +191 -0
  517. package/src/core/sources/types.ts +12 -1
  518. package/src/core/types.ts +15 -1
  519. package/src/core/ui-packs/ar.ts +10 -7
  520. package/src/core/ui-packs/bg.ts +10 -7
  521. package/src/core/ui-packs/bn.ts +10 -7
  522. package/src/core/ui-packs/ca.ts +7 -6
  523. package/src/core/ui-packs/cs.ts +10 -7
  524. package/src/core/ui-packs/da.ts +10 -7
  525. package/src/core/ui-packs/de.ts +10 -7
  526. package/src/core/ui-packs/el.ts +7 -6
  527. package/src/core/ui-packs/es.ts +7 -6
  528. package/src/core/ui-packs/fa.ts +10 -7
  529. package/src/core/ui-packs/fi.ts +10 -7
  530. package/src/core/ui-packs/fr.ts +7 -6
  531. package/src/core/ui-packs/he.ts +10 -7
  532. package/src/core/ui-packs/hi.ts +10 -7
  533. package/src/core/ui-packs/hr.ts +10 -7
  534. package/src/core/ui-packs/hu.ts +10 -7
  535. package/src/core/ui-packs/id.ts +10 -7
  536. package/src/core/ui-packs/it.ts +7 -6
  537. package/src/core/ui-packs/ja.ts +7 -6
  538. package/src/core/ui-packs/ko.ts +7 -6
  539. package/src/core/ui-packs/nl.ts +10 -7
  540. package/src/core/ui-packs/no.ts +10 -7
  541. package/src/core/ui-packs/pl.ts +10 -7
  542. package/src/core/ui-packs/pt-br.ts +7 -6
  543. package/src/core/ui-packs/pt.ts +7 -6
  544. package/src/core/ui-packs/ro.ts +10 -7
  545. package/src/core/ui-packs/ru.ts +10 -7
  546. package/src/core/ui-packs/sk.ts +10 -7
  547. package/src/core/ui-packs/sr.ts +10 -7
  548. package/src/core/ui-packs/sv.ts +10 -7
  549. package/src/core/ui-packs/th.ts +7 -6
  550. package/src/core/ui-packs/tr.ts +10 -7
  551. package/src/core/ui-packs/uk.ts +10 -7
  552. package/src/core/ui-packs/vi.ts +7 -6
  553. package/src/core/ui-packs/zh-tw.ts +7 -6
  554. package/src/core/ui-packs/zh.ts +7 -6
  555. package/src/core/unrecognized-keys.ts +10 -0
  556. package/src/core/version-cut.ts +116 -8
  557. package/src/deploy/adapter-output.ts +57 -97
  558. package/src/deploy/adapters/cloudflare.ts +39 -0
  559. package/src/deploy/adapters/index.ts +41 -0
  560. package/src/deploy/adapters/netlify.ts +34 -0
  561. package/src/deploy/adapters/node.ts +34 -0
  562. package/src/deploy/adapters/registry.ts +127 -0
  563. package/src/deploy/adapters/types.ts +92 -0
  564. package/src/deploy/adapters/vercel.ts +35 -0
  565. package/src/deploy/artifacts.ts +55 -27
  566. package/src/deploy/cloudflare-negotiation.ts +179 -100
  567. package/src/deploy/function-bundle.ts +18 -3
  568. package/src/deploy/headers.ts +124 -23
  569. package/src/deploy/node-headers.ts +198 -0
  570. package/src/deploy/platforms/cloudflare.ts +312 -0
  571. package/src/deploy/platforms/index.ts +67 -0
  572. package/src/deploy/platforms/netlify.ts +52 -0
  573. package/src/deploy/platforms/node.ts +40 -0
  574. package/src/deploy/platforms/paths.ts +42 -0
  575. package/src/deploy/platforms/static.ts +29 -0
  576. package/src/deploy/platforms/types.ts +112 -0
  577. package/src/deploy/platforms/vercel.ts +193 -0
  578. package/src/deploy/redirects.ts +30 -18
  579. package/src/deploy/robots.ts +3 -3
  580. package/src/deploy/rss.ts +2 -2
  581. package/src/deploy/sitemap.ts +2 -2
  582. package/src/deploy/vercel-negotiation.ts +2 -2
  583. package/src/eval/agents.ts +32 -1
  584. package/src/eval/findings.ts +19 -11
  585. package/src/eval/report.ts +10 -2
  586. package/src/markdown/external-links.ts +65 -0
  587. package/src/markdown/include.ts +45 -27
  588. package/src/markdown/index.ts +34 -9
  589. package/src/markdown/inline-code.ts +12 -6
  590. package/src/markdown/relative-links.ts +324 -0
  591. package/src/markdown/themes.ts +3 -3
  592. package/src/migrate/migrate.ts +149 -0
  593. package/src/openapi/parse.ts +64 -16
  594. package/src/openapi/proxy.ts +62 -10
  595. package/src/openapi/references.ts +147 -147
  596. package/src/openapi/render-mdx.ts +32 -10
  597. package/src/openapi/scalar.ts +15 -13
  598. package/src/openapi/sentence.ts +14 -0
  599. package/src/openapi/source.ts +37 -21
  600. package/src/openapi/spec-dependency-error.ts +15 -0
  601. package/src/reference/asyncapi.ts +83 -0
  602. package/src/reference/graphql.ts +89 -0
  603. package/src/reference/index.ts +40 -0
  604. package/src/reference/openapi.ts +83 -0
  605. package/src/reference/options.ts +201 -0
  606. package/src/reference/scalar.ts +136 -0
  607. package/src/reference/schema.ts +88 -0
  608. package/src/registry/eject.ts +109 -53
  609. package/src/search/adapters/algolia.ts +46 -0
  610. package/src/search/adapters/flexsearch.ts +29 -0
  611. package/src/search/adapters/index.ts +39 -0
  612. package/src/search/adapters/mixedbread.ts +39 -0
  613. package/src/search/adapters/orama-cloud.ts +51 -0
  614. package/src/search/adapters/orama.ts +24 -0
  615. package/src/search/adapters/pagefind.ts +27 -0
  616. package/src/search/adapters/registry.ts +131 -0
  617. package/src/search/adapters/types.ts +46 -0
  618. package/src/search/adapters/typesense.ts +57 -0
  619. package/src/search/build.ts +8 -4
  620. package/src/search/documents.ts +8 -2
  621. package/src/search/orama-index.ts +1 -1
  622. package/src/search/sync/algolia.ts +12 -11
  623. package/src/search/sync/index.ts +35 -20
  624. package/src/search/sync/orama-cloud.ts +12 -9
  625. package/src/search/sync/typesense.ts +15 -13
  626. package/src/sources/contentful.ts +63 -0
  627. package/src/sources/custom.ts +38 -0
  628. package/src/sources/filesystem.ts +51 -0
  629. package/src/sources/github-releases.ts +52 -0
  630. package/src/sources/index.ts +60 -0
  631. package/src/sources/mdx-remote.ts +76 -0
  632. package/src/sources/notion.ts +63 -0
  633. package/src/sources/obsidian.ts +38 -0
  634. package/src/sources/payload.ts +60 -0
  635. package/src/sources/registry.ts +182 -0
  636. package/src/sources/sanity.ts +66 -0
  637. package/src/sources/shared.ts +52 -0
  638. package/src/sources/strapi.ts +58 -0
  639. package/src/theme/entry.ts +24 -2
  640. package/src/translate/report.ts +40 -7
  641. package/src/upgrade/upgrade.ts +499 -0
  642. package/dist/cli/chunk-0qymqwzz.js +0 -164
  643. package/dist/cli/chunk-0qymqwzz.js.map +0 -15
  644. package/dist/cli/chunk-1jefwnfs.js.map +0 -48
  645. package/dist/cli/chunk-2mzebbbz.js +0 -69
  646. package/dist/cli/chunk-2z47ypj8.js.map +0 -11
  647. package/dist/cli/chunk-4x36ddpw.js.map +0 -11
  648. package/dist/cli/chunk-5093q3n7.js +0 -68
  649. package/dist/cli/chunk-5093q3n7.js.map +0 -10
  650. package/dist/cli/chunk-5qk08vmp.js.map +0 -11
  651. package/dist/cli/chunk-7s8hm3b6.js +0 -5347
  652. package/dist/cli/chunk-7s8hm3b6.js.map +0 -58
  653. package/dist/cli/chunk-8cjtbafj.js.map +0 -13
  654. package/dist/cli/chunk-97r59kpr.js +0 -381
  655. package/dist/cli/chunk-97r59kpr.js.map +0 -12
  656. package/dist/cli/chunk-ahnw3kxw.js.map +0 -15
  657. package/dist/cli/chunk-b27xqwn9.js.map +0 -10
  658. package/dist/cli/chunk-bf6bt1xt.js +0 -185
  659. package/dist/cli/chunk-bf6bt1xt.js.map +0 -11
  660. package/dist/cli/chunk-cjtn640a.js.map +0 -10
  661. package/dist/cli/chunk-ct47dqpx.js.map +0 -11
  662. package/dist/cli/chunk-esphfr8p.js +0 -107
  663. package/dist/cli/chunk-esphfr8p.js.map +0 -11
  664. package/dist/cli/chunk-ex56aa81.js +0 -1016
  665. package/dist/cli/chunk-ex56aa81.js.map +0 -13
  666. package/dist/cli/chunk-garjf5z9.js +0 -30
  667. package/dist/cli/chunk-garjf5z9.js.map +0 -10
  668. package/dist/cli/chunk-js7saxwm.js +0 -1045
  669. package/dist/cli/chunk-js7saxwm.js.map +0 -22
  670. package/dist/cli/chunk-k79xp7av.js.map +0 -39
  671. package/dist/cli/chunk-ps4m1xh4.js.map +0 -15
  672. package/dist/cli/chunk-q4rae3bg.js +0 -60
  673. package/dist/cli/chunk-q4rae3bg.js.map +0 -10
  674. package/dist/cli/chunk-rz9jmfhz.js +0 -108
  675. package/dist/cli/chunk-rz9jmfhz.js.map +0 -10
  676. package/dist/cli/chunk-vh9w1sgp.js +0 -73
  677. package/dist/cli/chunk-vh9w1sgp.js.map +0 -10
  678. package/dist/cli/chunk-vrfp10qk.js +0 -81
  679. package/dist/cli/chunk-vrfp10qk.js.map +0 -10
  680. package/dist/cli/chunk-yg63d42r.js.map +0 -34
  681. package/docs/advanced/api-reference.mdx +0 -240
  682. package/docs/configuration/ask-ai.mdx +0 -256
  683. package/docs/reference/cli.mdx +0 -197
  684. package/skills/blume-migrate/assets/oxfmt@0.55.0.patch +0 -20
  685. package/src/components/content/changelog-element.ts +0 -69
  686. package/src/search/providers.ts +0 -91
  687. /package/dist/cli/{chunk-vacwm2hv.js.map → chunk-27g6wdth.js.map} +0 -0
  688. /package/dist/cli/{chunk-dwgcp5sm.js.map → chunk-ce574jw2.js.map} +0 -0
  689. /package/dist/cli/{chunk-e7f42gdj.js.map → chunk-fxypxtvm.js.map} +0 -0
  690. /package/dist/cli/{chunk-nn13znc2.js.map → chunk-zxcczpyx.js.map} +0 -0
@@ -1,25 +1,30 @@
1
1
  import { existsSync } from "node:fs";
2
2
 
3
- import { dirname, extname, isAbsolute, resolve } from "pathe";
3
+ import { basename, dirname, extname, isAbsolute, join, resolve } from "pathe";
4
4
  import ts from "typescript";
5
5
 
6
+ import { BlumeError } from "./diagnostics.ts";
6
7
  import type { HydrationMode } from "./schema.ts";
8
+ import type { Diagnostic } from "./types.ts";
7
9
 
8
10
  /**
9
11
  * Static analysis of a user `components.ts`/`.tsx`.
10
12
  *
11
13
  * Astro can only hydrate a component it imports *statically by path*, so to honor
12
- * hydration on overrides (the `islands` group and `client:*` layout/mdx
13
- * descriptors) Blume needs each override's source path and client mode at
14
- * generate time — before Vite compiles anything. We read that here by parsing the
15
- * file with the TypeScript compiler API (never executing it, so `.astro`/React
14
+ * hydration on overrides Blume needs each override's source path and client mode
15
+ * at generate time — before Vite compiles anything. We read that here by parsing
16
+ * the file with the TypeScript compiler API (never executing it, so `.astro`/React
16
17
  * imports don't need a Node loader).
17
18
  *
18
- * Only statically-analyzable authoring is understood: a default export that is an
19
- * object literal or a `defineComponents({ ... })` call, with entries that are
20
- * imported identifiers, path strings, or `{ component, client, media }` object
21
- * literals. Anything else falls back to the runtime overrides object (which can
22
- * still render a static component, just not hydrate it).
19
+ * Only statically-analyzable authoring is accepted: a default export that is an
20
+ * object literal or a `defineComponents({ ... })` call, whose `mdx`/`layout`
21
+ * groups are object literals with entries that are imported identifiers, path
22
+ * strings, or `{ component, client, media }` object literals, and a relative
23
+ * or absolute path must name a file that exists. Anything else is a config
24
+ * error ({@link ComponentOverridesError}, `BLUME_COMPONENTS_INVALID`) naming the
25
+ * entry, its line, and the accepted forms — there is no runtime fallback, so an
26
+ * override that can't be planned never silently renders without hydration, and
27
+ * a missing file never surfaces as a bundler error inside the generated runtime.
23
28
  */
24
29
 
25
30
  export type OverrideFramework = "react" | "svelte" | "vue";
@@ -38,35 +43,36 @@ export interface OverrideImport {
38
43
  export interface NormalizedOverride {
39
44
  /** Present when the override should hydrate; drives the `client:*` directive. */
40
45
  client?: HydrationMode;
41
- /**
42
- * True when the value is a bare imported identifier, so the runtime overrides
43
- * object already holds a usable component (no generated import needed for a
44
- * non-hydrated entry). False for path strings and `{ component }` descriptors.
45
- */
46
- identifier: boolean;
47
46
  key: string;
48
47
  /** Media query for `client: "media"`. */
49
48
  media?: string;
50
- /**
51
- * How to obtain the component. `null` means it couldn't be resolved to a file,
52
- * so the runtime overrides object is used (static render only).
53
- */
54
- source: OverrideImport | null;
49
+ /** How to obtain the component. */
50
+ source: OverrideImport;
55
51
  }
56
52
 
57
53
  export interface ComponentOverrideAnalysis {
58
- islands: NormalizedOverride[];
59
54
  layout: NormalizedOverride[];
60
55
  mdx: NormalizedOverride[];
61
56
  warnings: string[];
62
57
  }
63
58
 
64
- const GROUPS = ["mdx", "layout", "islands"] as const;
59
+ /** The analysis of a project with no `components.ts`. */
60
+ export const emptyComponentOverrides = (): ComponentOverrideAnalysis => ({
61
+ layout: [],
62
+ mdx: [],
63
+ warnings: [],
64
+ });
65
+
66
+ const GROUPS = ["mdx", "layout"] as const;
65
67
  const GROUP_SET = new Set<string>(GROUPS);
66
68
  type Group = (typeof GROUPS)[number];
67
69
 
68
70
  const isGroup = (name: string): name is Group => GROUP_SET.has(name);
69
71
 
72
+ /** The authoring forms an override accepts; the fix every rejection points at. */
73
+ export const ACCEPTED_OVERRIDE_FORMS =
74
+ "Each override must be an imported identifier, a path string, or a `{ component, client, media }` object literal whose `component` is an imported identifier or a path string.";
75
+
70
76
  const FRAMEWORK_BY_EXT = new Map<string, OverrideFramework>([
71
77
  ["jsx", "react"],
72
78
  ["svelte", "svelte"],
@@ -100,29 +106,51 @@ const HYDRATION_MODES: ReadonlySet<string> = new Set<HydrationMode>([
100
106
  "visible",
101
107
  ]);
102
108
 
109
+ const HYDRATION_MODE_LIST = '"load", "idle", "visible", "media", or "only"';
110
+
103
111
  const isHydrationMode = (value: string): value is HydrationMode =>
104
112
  HYDRATION_MODES.has(value);
105
113
 
106
114
  interface ImportBinding {
107
115
  /** Exported name: `"default"` or a named export. */
108
116
  imported: string;
117
+ /** The import statement, where a missing file is reported. */
118
+ node: ts.ImportDeclaration;
109
119
  specifier: string;
110
120
  }
111
121
 
122
+ /** Why one entry was rejected, and the node it's about (for its line). */
123
+ interface Rejection {
124
+ message: string;
125
+ /** A path that names no file: the fix is the path, not the entry's form. */
126
+ missingFile?: boolean;
127
+ node?: ts.Node;
128
+ }
129
+
112
130
  /** An override's declared component before framework/path resolution. */
113
131
  interface RawDescriptor {
114
132
  client?: HydrationMode;
115
- hadComponent: boolean;
116
133
  media?: string;
117
134
  source: OverrideImport | null;
118
135
  }
119
136
 
120
- const emptyAnalysis = (): ComponentOverrideAnalysis => ({
121
- islands: [],
122
- layout: [],
123
- mdx: [],
124
- warnings: [],
125
- });
137
+ /** Everything one analysis pass needs to resolve and report an entry. */
138
+ interface AnalysisContext {
139
+ dir: string;
140
+ /** Rejections collected across the file; thrown together at the end. */
141
+ errors: Rejection[];
142
+ imports: Map<string, ImportBinding>;
143
+ warnings: string[];
144
+ }
145
+
146
+ const reject = (
147
+ context: AnalysisContext,
148
+ message: string,
149
+ node?: ts.Node,
150
+ missingFile?: boolean
151
+ ): void => {
152
+ context.errors.push({ message, missingFile, node });
153
+ };
126
154
 
127
155
  const propName = (name: ts.PropertyName): string | undefined =>
128
156
  ts.isIdentifier(name) || ts.isStringLiteral(name) ? name.text : undefined;
@@ -144,13 +172,18 @@ const addImportBindings = (
144
172
  return;
145
173
  }
146
174
  if (clause.name) {
147
- map.set(clause.name.text, { imported: "default", specifier });
175
+ map.set(clause.name.text, {
176
+ imported: "default",
177
+ node: statement,
178
+ specifier,
179
+ });
148
180
  }
149
181
  const named = clause.namedBindings;
150
182
  if (named && ts.isNamedImports(named)) {
151
183
  for (const element of named.elements) {
152
184
  map.set(element.name.text, {
153
185
  imported: (element.propertyName ?? element.name).text,
186
+ node: statement,
154
187
  specifier,
155
188
  });
156
189
  }
@@ -188,16 +221,13 @@ const unwrapObject = (
188
221
  return undefined;
189
222
  };
190
223
 
191
- const findDefaultExportObject = (
224
+ const findDefaultExport = (
192
225
  sourceFile: ts.SourceFile
193
- ): ts.ObjectLiteralExpression | undefined => {
194
- for (const statement of sourceFile.statements) {
195
- if (ts.isExportAssignment(statement) && !statement.isExportEquals) {
196
- return unwrapObject(statement.expression);
197
- }
198
- }
199
- return undefined;
200
- };
226
+ ): ts.ExportAssignment | undefined =>
227
+ sourceFile.statements.find(
228
+ (statement): statement is ts.ExportAssignment =>
229
+ ts.isExportAssignment(statement) && !statement.isExportEquals
230
+ );
201
231
 
202
232
  const probeExtension = (base: string): string | null => {
203
233
  for (const extension of COMPONENT_EXTS) {
@@ -209,6 +239,30 @@ const probeExtension = (base: string): string | null => {
209
239
  return null;
210
240
  };
211
241
 
242
+ // A `.js` specifier in a TypeScript file may name its `.ts`/`.tsx` source, as
243
+ // Vite resolves it; the same holds for `.jsx` and `.mjs`.
244
+ const SCRIPT_EXT = /\.(?:jsx?|mjs)$/u;
245
+ const TS_SOURCE_EXTS = ["ts", "tsx", "mts"];
246
+
247
+ /**
248
+ * Whether a local path names something the bundler can import: the file
249
+ * itself, the file with a component extension added, a folder's `index`, or
250
+ * the TypeScript source a `.js` specifier stands for.
251
+ */
252
+ const resolvesLocally = (absolute: string): boolean => {
253
+ if (existsSync(absolute) || probeExtension(absolute)) {
254
+ return true;
255
+ }
256
+ if (probeExtension(join(absolute, "index"))) {
257
+ return true;
258
+ }
259
+ const base = absolute.replace(SCRIPT_EXT, "");
260
+ return (
261
+ base !== absolute &&
262
+ TS_SOURCE_EXTS.some((extension) => existsSync(`${base}.${extension}`))
263
+ );
264
+ };
265
+
212
266
  /** Resolve a module specifier to a wrapper-importable path + framework. */
213
267
  const toImport = (
214
268
  specifier: string,
@@ -237,88 +291,191 @@ const toImport = (
237
291
  };
238
292
  };
239
293
 
294
+ /**
295
+ * Resolve a specifier to its import, or record that the file it names doesn't
296
+ * exist. A bare package specifier is left to the bundler.
297
+ */
298
+ const sourceFor = (
299
+ specifier: string,
300
+ imported: string,
301
+ label: string,
302
+ node: ts.Node,
303
+ context: AnalysisContext
304
+ ): OverrideImport | null => {
305
+ const local = specifier.startsWith(".") || isAbsolute(specifier);
306
+ if (local && !resolvesLocally(resolve(context.dir, specifier))) {
307
+ reject(
308
+ context,
309
+ `${label} points at "${specifier}", but no file exists there; fix the path or restore the file.`,
310
+ node,
311
+ true
312
+ );
313
+ return null;
314
+ }
315
+ return toImport(specifier, imported, context.dir);
316
+ };
317
+
318
+ /**
319
+ * Resolve an identifier to the import it names, or record why it can't be: a
320
+ * local binding (a `const`, a function declared in the file) has no source path
321
+ * a wrapper could import.
322
+ */
240
323
  const resolveIdentifier = (
241
324
  name: string,
242
- imports: Map<string, ImportBinding>,
243
- dir: string
325
+ label: string,
326
+ node: ts.Node,
327
+ context: AnalysisContext
244
328
  ): OverrideImport | null => {
245
- const binding = imports.get(name);
246
- return binding ? toImport(binding.specifier, binding.imported, dir) : null;
329
+ const binding = context.imports.get(name);
330
+ if (binding) {
331
+ return sourceFor(
332
+ binding.specifier,
333
+ binding.imported,
334
+ label,
335
+ binding.node,
336
+ context
337
+ );
338
+ }
339
+ reject(
340
+ context,
341
+ `${label} refers to "${name}", which isn't imported in this file; import the component from its file.`,
342
+ node
343
+ );
344
+ return null;
247
345
  };
248
346
 
347
+ const ALLOWED_FIELDS =
348
+ "only `component`, `client`, and `media` are allowed in a descriptor.";
349
+
249
350
  /** Fold one descriptor-object property into the accumulating descriptor. */
250
351
  const applyDescriptorProperty = (
251
352
  descriptor: RawDescriptor,
252
353
  property: ts.ObjectLiteralElementLike,
253
- imports: Map<string, ImportBinding>,
254
- dir: string
354
+ label: string,
355
+ context: AnalysisContext
255
356
  ): void => {
256
357
  if (ts.isShorthandPropertyAssignment(property)) {
257
358
  if (property.name.text === "component") {
258
- descriptor.hadComponent = true;
259
- descriptor.source = resolveIdentifier(property.name.text, imports, dir);
359
+ descriptor.source = resolveIdentifier(
360
+ property.name.text,
361
+ `${label}'s \`component\``,
362
+ property,
363
+ context
364
+ );
365
+ return;
366
+ }
367
+ const shorthand = property.name.text;
368
+ if (shorthand === "client" || shorthand === "media") {
369
+ reject(
370
+ context,
371
+ `${label} writes \`${shorthand}\` as a shorthand property; only \`component\` may be shorthand, \`${shorthand}\` must be a string literal.`,
372
+ property
373
+ );
374
+ return;
260
375
  }
376
+ reject(
377
+ context,
378
+ `${label} has a \`${shorthand}\` field; ${ALLOWED_FIELDS}`,
379
+ property
380
+ );
261
381
  return;
262
382
  }
263
383
  if (!ts.isPropertyAssignment(property)) {
384
+ reject(
385
+ context,
386
+ `${label} contains a spread, method, or accessor; write it as a plain \`{ component, client, media }\` object literal.`,
387
+ property
388
+ );
264
389
  return;
265
390
  }
266
391
  const name = propName(property.name);
267
392
  const init = property.initializer;
268
393
  if (name === "component") {
269
- descriptor.hadComponent = true;
270
394
  if (ts.isStringLiteral(init)) {
271
- descriptor.source = toImport(init.text, "default", dir);
395
+ descriptor.source = sourceFor(
396
+ init.text,
397
+ "default",
398
+ `${label}'s \`component\``,
399
+ init,
400
+ context
401
+ );
272
402
  } else if (ts.isIdentifier(init)) {
273
- descriptor.source = resolveIdentifier(init.text, imports, dir);
403
+ descriptor.source = resolveIdentifier(
404
+ init.text,
405
+ `${label}'s \`component\``,
406
+ init,
407
+ context
408
+ );
409
+ } else {
410
+ reject(
411
+ context,
412
+ `${label}'s \`component\` must be an imported identifier or a path string.`,
413
+ init
414
+ );
274
415
  }
275
- } else if (
276
- name === "client" &&
277
- ts.isStringLiteral(init) &&
278
- isHydrationMode(init.text)
279
- ) {
280
- descriptor.client = init.text;
281
- } else if (name === "media" && ts.isStringLiteral(init)) {
282
- descriptor.media = init.text;
416
+ } else if (name === "client") {
417
+ if (ts.isStringLiteral(init) && isHydrationMode(init.text)) {
418
+ descriptor.client = init.text;
419
+ } else {
420
+ reject(
421
+ context,
422
+ `${label}'s \`client\` must be a string literal: ${HYDRATION_MODE_LIST}.`,
423
+ init
424
+ );
425
+ }
426
+ } else if (name === "media") {
427
+ if (ts.isStringLiteral(init)) {
428
+ descriptor.media = init.text;
429
+ } else {
430
+ reject(context, `${label}'s \`media\` must be a string literal.`, init);
431
+ }
432
+ } else {
433
+ reject(
434
+ context,
435
+ `${label} has a \`${name ?? property.name.getText()}\` field; ${ALLOWED_FIELDS}`,
436
+ property
437
+ );
283
438
  }
284
439
  };
285
440
 
441
+ /**
442
+ * Read a `{ component, client, media }` descriptor. Returns null (after
443
+ * recording the reason) when it can't be planned.
444
+ */
286
445
  const readDescriptor = (
287
446
  object: ts.ObjectLiteralExpression,
288
- imports: Map<string, ImportBinding>,
289
- dir: string
290
- ): RawDescriptor => {
291
- const descriptor: RawDescriptor = { hadComponent: false, source: null };
447
+ label: string,
448
+ context: AnalysisContext
449
+ ): RawDescriptor | null => {
450
+ const descriptor: RawDescriptor = { source: null };
451
+ const before = context.errors.length;
452
+ let hadComponent = false;
292
453
  for (const property of object.properties) {
293
- applyDescriptorProperty(descriptor, property, imports, dir);
454
+ if (property.name && propName(property.name) === "component") {
455
+ hadComponent = true;
456
+ }
457
+ applyDescriptorProperty(descriptor, property, label, context);
458
+ }
459
+ if (!hadComponent) {
460
+ reject(
461
+ context,
462
+ `${label} is an object literal without a \`component\` field.`,
463
+ object
464
+ );
294
465
  }
295
- return descriptor;
466
+ return context.errors.length === before ? descriptor : null;
296
467
  };
297
468
 
298
469
  /** Apply cross-cutting validation and produce the final normalized override. */
299
470
  const finalize = (
300
471
  key: string,
301
- group: Group,
302
472
  descriptor: RawDescriptor,
303
473
  label: string,
304
- identifier: boolean,
305
474
  warnings: string[]
306
475
  ): NormalizedOverride | null => {
307
476
  const { client, media, source } = descriptor;
308
-
309
- if (group === "islands") {
310
- if (!source) {
311
- warnings.push(
312
- `Island override "${key}" couldn't be resolved to a file. Reference it by an imported component or a path string with an extension.`
313
- );
314
- return null;
315
- }
316
- if (!source.framework) {
317
- warnings.push(
318
- `Island override "${key}" (${label}) is not a React, Vue, or Svelte component; only framework components can be islands.`
319
- );
320
- return null;
321
- }
477
+ if (!source) {
478
+ return null;
322
479
  }
323
480
 
324
481
  if (client === "media" && !media) {
@@ -327,19 +484,19 @@ const finalize = (
327
484
  );
328
485
  }
329
486
 
330
- if (client === "only" && source && !source.framework) {
487
+ if (client === "only" && !source.framework) {
331
488
  warnings.push(
332
489
  `Override "${key}" uses client: "only" but its framework couldn't be inferred; reference a .tsx/.jsx/.vue/.svelte file.`
333
490
  );
334
491
  }
335
492
 
336
- if (!client && source?.framework) {
493
+ if (!client && source.framework) {
337
494
  warnings.push(
338
495
  `Override "${key}" points to a ${FRAMEWORK_LABEL[source.framework]} component (${label}) but has no hydration mode, so it renders as static HTML with no interactivity. Add one, e.g. \`${key}: { component: ${JSON.stringify(label)}, client: "load" }\`.`
339
496
  );
340
497
  }
341
498
 
342
- const normalized: NormalizedOverride = { identifier, key, source };
499
+ const normalized: NormalizedOverride = { key, source };
343
500
  if (client) {
344
501
  normalized.client = client;
345
502
  }
@@ -349,37 +506,48 @@ const finalize = (
349
506
  return normalized;
350
507
  };
351
508
 
509
+ /** Normalize one `key: value` entry of a group, or record why it's rejected. */
352
510
  const normalizeEntry = (
353
511
  entry: ts.ObjectLiteralElementLike,
354
512
  group: Group,
355
- imports: Map<string, ImportBinding>,
356
- dir: string,
357
- warnings: string[]
513
+ context: AnalysisContext
358
514
  ): NormalizedOverride | null => {
359
- const defaultClient: HydrationMode | undefined =
360
- group === "islands" ? "visible" : undefined;
515
+ const { warnings } = context;
361
516
 
362
517
  if (ts.isShorthandPropertyAssignment(entry)) {
363
518
  const name = entry.name.text;
364
519
  return finalize(
365
520
  name,
366
- group,
367
- {
368
- client: defaultClient,
369
- hadComponent: true,
370
- source: resolveIdentifier(name, imports, dir),
371
- },
521
+ { source: resolveIdentifier(name, `${group}.${name}`, entry, context) },
372
522
  name,
373
- true,
374
523
  warnings
375
524
  );
376
525
  }
377
526
 
378
- if (!ts.isPropertyAssignment(entry)) {
527
+ if (ts.isSpreadAssignment(entry)) {
528
+ reject(
529
+ context,
530
+ `${group} contains a spread (\`...${entry.expression.getText()}\`); list each override explicitly.`,
531
+ entry
532
+ );
379
533
  return null;
380
534
  }
381
535
  const key = propName(entry.name);
382
536
  if (!key) {
537
+ reject(
538
+ context,
539
+ `${group} has an entry with a computed key (\`${entry.name.getText()}\`); keys must be plain names.`,
540
+ entry
541
+ );
542
+ return null;
543
+ }
544
+ const label = `${group}.${key}`;
545
+ if (!ts.isPropertyAssignment(entry)) {
546
+ reject(
547
+ context,
548
+ `${label} is a method or accessor, which Blume can't analyze statically.`,
549
+ entry
550
+ );
383
551
  return null;
384
552
  }
385
553
  const value = entry.initializer;
@@ -387,100 +555,155 @@ const normalizeEntry = (
387
555
  if (ts.isIdentifier(value)) {
388
556
  return finalize(
389
557
  key,
390
- group,
391
- {
392
- client: defaultClient,
393
- hadComponent: true,
394
- source: resolveIdentifier(value.text, imports, dir),
395
- },
558
+ { source: resolveIdentifier(value.text, label, entry, context) },
396
559
  value.text,
397
- true,
398
560
  warnings
399
561
  );
400
562
  }
401
563
  if (ts.isStringLiteral(value)) {
402
564
  return finalize(
403
565
  key,
404
- group,
405
- {
406
- client: defaultClient,
407
- hadComponent: true,
408
- source: toImport(value.text, "default", dir),
409
- },
566
+ { source: sourceFor(value.text, "default", label, value, context) },
410
567
  value.text,
411
- false,
412
568
  warnings
413
569
  );
414
570
  }
415
571
  if (ts.isObjectLiteralExpression(value)) {
416
- const descriptor = readDescriptor(value, imports, dir);
417
- if (!descriptor.hadComponent) {
418
- warnings.push(
419
- `Override "${key}" is an object without a \`component\` field; expected \`{ component, client }\`.`
420
- );
421
- return null;
422
- }
423
- if (!descriptor.source) {
424
- warnings.push(
425
- `Override "${key}"'s \`component\` couldn't be resolved to a file. Reference an imported component or a path string with an extension.`
426
- );
427
- return null;
428
- }
429
- return finalize(
430
- key,
431
- group,
432
- { ...descriptor, client: descriptor.client ?? defaultClient },
433
- key,
434
- false,
435
- warnings
436
- );
572
+ const descriptor = readDescriptor(value, label, context);
573
+ return descriptor ? finalize(key, descriptor, key, warnings) : null;
437
574
  }
438
575
 
439
- // An inline function/expression: keep it on the runtime object (static only).
440
- return { identifier: false, key, source: null };
576
+ reject(
577
+ context,
578
+ `${label} is an inline expression, which Blume can't analyze statically.`,
579
+ entry
580
+ );
581
+ return null;
441
582
  };
442
583
 
443
- /** Normalize one top-level `{ mdx | layout | islands }` group into `result`. */
584
+ /** Normalize one top-level `{ mdx | layout }` group into `result`. */
444
585
  const collectGroupOverrides = (
445
586
  property: ts.ObjectLiteralElementLike,
446
- imports: Map<string, ImportBinding>,
447
- dir: string,
587
+ context: AnalysisContext,
448
588
  result: ComponentOverrideAnalysis
449
589
  ): void => {
450
- if (!ts.isPropertyAssignment(property)) {
590
+ if (ts.isSpreadAssignment(property)) {
591
+ reject(
592
+ context,
593
+ `The top-level object contains a spread (\`...${property.expression.getText()}\`); list \`mdx\` and \`layout\` explicitly.`,
594
+ property
595
+ );
451
596
  return;
452
597
  }
453
598
  const name = propName(property.name);
599
+ if (name === "islands") {
600
+ reject(
601
+ context,
602
+ 'The `islands` group was folded into `mdx`: move each entry there and give it a `client` mode, e.g. `mdx: { Counter: { component: Counter, client: "visible" } }`.',
603
+ property
604
+ );
605
+ return;
606
+ }
607
+ if (!(name && isGroup(name))) {
608
+ reject(
609
+ context,
610
+ `\`${name ?? property.name.getText()}\` isn't an override group; use \`mdx\` or \`layout\`.`,
611
+ property
612
+ );
613
+ return;
614
+ }
454
615
  if (
455
- !(name && isGroup(name)) ||
616
+ !ts.isPropertyAssignment(property) ||
456
617
  !ts.isObjectLiteralExpression(property.initializer)
457
618
  ) {
619
+ reject(
620
+ context,
621
+ `\`${name}\` must be an object literal of overrides.`,
622
+ property
623
+ );
458
624
  return;
459
625
  }
460
626
  for (const entry of property.initializer.properties) {
461
- const normalized = normalizeEntry(
462
- entry,
463
- name,
464
- imports,
465
- dir,
466
- result.warnings
467
- );
627
+ const normalized = normalizeEntry(entry, name, context);
468
628
  if (normalized) {
469
629
  result[name].push(normalized);
470
630
  }
471
631
  }
472
632
  };
473
633
 
634
+ /**
635
+ * A `components.ts` Blume can't plan. The diagnostic lists every rejected entry
636
+ * at once (at the first one's line); `issues` holds each on its own, with its
637
+ * line, for a caller that reports them one by one (`blume upgrade`).
638
+ */
639
+ export class ComponentOverridesError extends BlumeError {
640
+ readonly issues: Diagnostic[];
641
+
642
+ constructor(diagnostic: Diagnostic, issues: Diagnostic[]) {
643
+ super(diagnostic);
644
+ this.name = "ComponentOverridesError";
645
+ this.issues = issues;
646
+ }
647
+ }
648
+
649
+ /** A rejection as a diagnostic, at its node's line when it has one. */
650
+ const rejectionDiagnostic = (
651
+ filePath: string,
652
+ sourceFile: ts.SourceFile,
653
+ rejection: Rejection
654
+ ): Diagnostic => {
655
+ const position = rejection.node
656
+ ? sourceFile.getLineAndCharacterOfPosition(
657
+ rejection.node.getStart(sourceFile)
658
+ )
659
+ : undefined;
660
+ return {
661
+ code: "BLUME_COMPONENTS_INVALID",
662
+ column: position && position.character + 1,
663
+ file: filePath,
664
+ line: position && position.line + 1,
665
+ message: rejection.message,
666
+ severity: "error",
667
+ suggestion: rejection.missingFile ? undefined : ACCEPTED_OVERRIDE_FORMS,
668
+ };
669
+ };
670
+
671
+ const invalidOverrides = (
672
+ filePath: string,
673
+ sourceFile: ts.SourceFile,
674
+ rejections: Rejection[]
675
+ ): ComponentOverridesError => {
676
+ const issues = rejections.map((rejection) =>
677
+ rejectionDiagnostic(filePath, sourceFile, rejection)
678
+ );
679
+ const first = issues.find((issue) => issue.line !== undefined);
680
+ return new ComponentOverridesError(
681
+ {
682
+ code: "BLUME_COMPONENTS_INVALID",
683
+ column: first?.column,
684
+ file: filePath,
685
+ line: first?.line,
686
+ message: `${basename(filePath)} has ${rejections.length} override(s) Blume can't plan:\n${rejections.map((rejection) => ` - ${rejection.message}`).join("\n")}`,
687
+ severity: "error",
688
+ suggestion: rejections.every((rejection) => rejection.missingFile)
689
+ ? undefined
690
+ : ACCEPTED_OVERRIDE_FORMS,
691
+ },
692
+ issues
693
+ );
694
+ };
695
+
474
696
  /**
475
697
  * Parse a user `components.ts`/`.tsx` and return its normalized overrides. Never
476
- * executes the file. On a parse failure or unrecognized shape, returns empty
477
- * groups so generation falls back to the plain runtime overrides object.
698
+ * executes the file. Throws a `BLUME_COMPONENTS_INVALID`
699
+ * {@link ComponentOverridesError} listing every entry that isn't one of the
700
+ * accepted forms or points at a file that doesn't exist.
478
701
  */
479
702
  export const analyzeComponentOverrides = (
480
703
  source: string,
481
704
  filePath: string
482
705
  ): ComponentOverrideAnalysis => {
483
- const result = emptyAnalysis();
706
+ const result = emptyComponentOverrides();
484
707
  const sourceFile = ts.createSourceFile(
485
708
  filePath,
486
709
  source,
@@ -489,17 +712,39 @@ export const analyzeComponentOverrides = (
489
712
  filePath.endsWith("tsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS
490
713
  );
491
714
 
492
- const object = findDefaultExportObject(sourceFile);
715
+ const exported = findDefaultExport(sourceFile);
716
+ if (!exported) {
717
+ throw invalidOverrides(filePath, sourceFile, [
718
+ {
719
+ message:
720
+ "No default export was found; export `defineComponents({ mdx, layout })` (or a plain object literal) as the default.",
721
+ },
722
+ ]);
723
+ }
724
+ const object = unwrapObject(exported.expression);
493
725
  if (!object) {
494
- return result;
726
+ throw invalidOverrides(filePath, sourceFile, [
727
+ {
728
+ message:
729
+ "The default export isn't an object literal or a `defineComponents({ ... })` call.",
730
+ node: exported,
731
+ },
732
+ ]);
495
733
  }
496
734
 
497
- const imports = collectImports(sourceFile);
498
- const dir = dirname(filePath);
735
+ const context: AnalysisContext = {
736
+ dir: dirname(filePath),
737
+ errors: [],
738
+ imports: collectImports(sourceFile),
739
+ warnings: result.warnings,
740
+ };
499
741
 
500
742
  for (const property of object.properties) {
501
- collectGroupOverrides(property, imports, dir, result);
743
+ collectGroupOverrides(property, context, result);
502
744
  }
503
745
 
746
+ if (context.errors.length > 0) {
747
+ throw invalidOverrides(filePath, sourceFile, context.errors);
748
+ }
504
749
  return result;
505
750
  };