blume 2.1.0 → 2.1.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 (397) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/dist/cli/{chunk-5cg2rzgf.js → chunk-073rdvgb.js} +19 -48
  3. package/dist/cli/{chunk-5cg2rzgf.js.map → chunk-073rdvgb.js.map} +4 -5
  4. package/dist/cli/{chunk-ga0pf4aj.js → chunk-0n9xkp3d.js} +12 -3
  5. package/dist/cli/{chunk-ga0pf4aj.js.map → chunk-0n9xkp3d.js.map} +3 -3
  6. package/dist/cli/chunk-150jk7km.js +52 -0
  7. package/dist/cli/chunk-150jk7km.js.map +10 -0
  8. package/dist/cli/{chunk-rekqz4qg.js → chunk-313vnn40.js} +16 -15
  9. package/dist/cli/chunk-313vnn40.js.map +10 -0
  10. package/dist/cli/{chunk-gp84za0h.js → chunk-3v3ffbrj.js} +2 -2
  11. package/dist/cli/{chunk-9xr4dgee.js → chunk-3x6x3pph.js} +29 -16
  12. package/dist/cli/chunk-3x6x3pph.js.map +10 -0
  13. package/dist/cli/{chunk-0gz36akr.js → chunk-42t4jxdx.js} +21 -5
  14. package/dist/cli/chunk-42t4jxdx.js.map +12 -0
  15. package/dist/cli/{chunk-ta27feev.js → chunk-54ztw1nj.js} +21 -2
  16. package/dist/cli/chunk-54ztw1nj.js.map +10 -0
  17. package/dist/cli/{chunk-jnwj5kjj.js → chunk-5vjtgs6e.js} +20 -7
  18. package/dist/cli/{chunk-jnwj5kjj.js.map → chunk-5vjtgs6e.js.map} +3 -3
  19. package/dist/cli/chunk-66w9j7p6.js +322 -0
  20. package/dist/cli/chunk-66w9j7p6.js.map +14 -0
  21. package/dist/cli/{chunk-nd1821sk.js → chunk-7ppf1rva.js} +32 -18
  22. package/dist/cli/chunk-7ppf1rva.js.map +10 -0
  23. package/dist/cli/{chunk-p804f3pe.js → chunk-8y2kmjv8.js} +6 -6
  24. package/dist/cli/{chunk-2f7n4qzt.js → chunk-c1y538kd.js} +1 -1
  25. package/dist/cli/{chunk-1n228xqb.js → chunk-c887fj0s.js} +2 -2
  26. package/dist/cli/{chunk-y5h4r2y0.js → chunk-cfyg47zg.js} +15 -5
  27. package/dist/cli/chunk-cfyg47zg.js.map +10 -0
  28. package/dist/cli/{chunk-cmtcnh9f.js → chunk-dzwehpy7.js} +2 -2
  29. package/dist/cli/{chunk-h2a48yhd.js → chunk-e6atmn4h.js} +119 -15
  30. package/dist/cli/{chunk-h2a48yhd.js.map → chunk-e6atmn4h.js.map} +10 -10
  31. package/dist/cli/{chunk-5ffywsmb.js → chunk-e8xw9qkh.js} +8 -6
  32. package/dist/cli/{chunk-5ffywsmb.js.map → chunk-e8xw9qkh.js.map} +3 -3
  33. package/dist/cli/{chunk-ntv4qrt7.js → chunk-e9q7a2ak.js} +14 -14
  34. package/dist/cli/{chunk-xkz5xbtv.js → chunk-ehweg4fr.js} +2366 -1114
  35. package/dist/cli/chunk-ehweg4fr.js.map +218 -0
  36. package/dist/cli/{chunk-zf748avv.js → chunk-ep6nd0rn.js} +176 -281
  37. package/dist/cli/{chunk-zf748avv.js.map → chunk-ep6nd0rn.js.map} +11 -12
  38. package/dist/cli/{chunk-yxmk4pec.js → chunk-fdrkhpjy.js} +16 -15
  39. package/dist/cli/{chunk-yxmk4pec.js.map → chunk-fdrkhpjy.js.map} +3 -3
  40. package/dist/cli/{chunk-5wj2qwn2.js → chunk-ft9vfys6.js} +4 -4
  41. package/dist/cli/{chunk-4h8z9vv5.js → chunk-gb420vvz.js} +89 -46
  42. package/dist/cli/chunk-gb420vvz.js.map +17 -0
  43. package/dist/cli/{chunk-713mngdq.js → chunk-hebn0tpx.js} +76 -10
  44. package/dist/cli/chunk-hebn0tpx.js.map +14 -0
  45. package/dist/cli/{chunk-2n4ps1b3.js → chunk-htrwgabr.js} +40 -22
  46. package/dist/cli/chunk-htrwgabr.js.map +15 -0
  47. package/dist/cli/{chunk-zhvd6adm.js → chunk-hx3xqnk9.js} +13 -13
  48. package/dist/cli/chunk-j134vrp2.js +65 -0
  49. package/dist/cli/chunk-j134vrp2.js.map +10 -0
  50. package/dist/cli/{chunk-y4ykbark.js → chunk-kma9f6sf.js} +2 -2
  51. package/dist/cli/{chunk-py62fewh.js → chunk-mrcccgnh.js} +3 -3
  52. package/dist/cli/{chunk-2f3ndkpw.js → chunk-n0v7m8ry.js} +3 -3
  53. package/dist/cli/{chunk-43zcf4gz.js → chunk-ncj7w596.js} +522 -353
  54. package/dist/cli/chunk-ncj7w596.js.map +35 -0
  55. package/dist/cli/{chunk-9geymqns.js → chunk-nq1d20w2.js} +14 -14
  56. package/dist/cli/{chunk-g2z9x01v.js → chunk-nrns10mj.js} +3 -3
  57. package/dist/cli/{chunk-e7vvk5ya.js → chunk-sds923fa.js} +3 -3
  58. package/dist/cli/{chunk-cy5bm0j0.js → chunk-t2m5j4pr.js} +2 -2
  59. package/dist/cli/{chunk-cy5bm0j0.js.map → chunk-t2m5j4pr.js.map} +1 -1
  60. package/dist/cli/{chunk-yj17vs39.js → chunk-tdqhyxfz.js} +5 -5
  61. package/dist/cli/{chunk-q3wxxq39.js → chunk-tphac74f.js} +5 -5
  62. package/dist/cli/{chunk-6bm0xpgd.js → chunk-w1r4vase.js} +2 -2
  63. package/dist/cli/index.js +24 -19
  64. package/dist/cli/index.js.map +3 -3
  65. package/dist/types/ai/ask-context.d.ts +6 -2
  66. package/dist/types/ai/component-markdown.d.ts +2 -0
  67. package/dist/types/ai/openapi-components.d.ts +4 -1
  68. package/dist/types/astro/integration.d.ts +5 -4
  69. package/dist/types/astro/markdown-negotiation.d.ts +3 -0
  70. package/dist/types/astro/pages.d.ts +10 -0
  71. package/dist/types/cli/init/scaffold.d.ts +1 -1
  72. package/dist/types/components/content/api-field.d.ts +4 -1
  73. package/dist/types/components/content/api-page.d.ts +6 -1
  74. package/dist/types/components/openapi/code-samples.d.ts +29 -0
  75. package/dist/types/components/openapi/helpers.d.ts +22 -1
  76. package/dist/types/components/openapi/security.d.ts +10 -0
  77. package/dist/types/components/openapi/snippets.d.ts +60 -0
  78. package/dist/types/core/changelog-index.d.ts +8 -0
  79. package/dist/types/core/config-input.d.ts +30 -3
  80. package/dist/types/core/data.d.ts +4 -0
  81. package/dist/types/core/i18n-ui.d.ts +2 -0
  82. package/dist/types/core/links.d.ts +8 -0
  83. package/dist/types/core/probe.d.ts +2 -0
  84. package/dist/types/core/project-graph.d.ts +6 -0
  85. package/dist/types/core/redirect-patterns.d.ts +11 -3
  86. package/dist/types/core/schema.d.ts +119 -0
  87. package/dist/types/core/sources/cache.d.ts +3 -0
  88. package/dist/types/core/sources/contentful-rich-text.d.ts +11 -2
  89. package/dist/types/core/sources/contentful.d.ts +17 -1
  90. package/dist/types/core/sources/lexical.d.ts +5 -0
  91. package/dist/types/core/sources/normalize.d.ts +20 -1
  92. package/dist/types/core/sources/remote.d.ts +37 -10
  93. package/dist/types/core/sources/sanity.d.ts +1 -1
  94. package/dist/types/core/types.d.ts +17 -0
  95. package/dist/types/deploy/adapter-output.d.ts +2 -1
  96. package/dist/types/deploy/adapters/cloudflare.d.ts +7 -5
  97. package/dist/types/deploy/adapters/node.d.ts +58 -23
  98. package/dist/types/deploy/adapters/registry.d.ts +10 -0
  99. package/dist/types/deploy/adapters/types.d.ts +3 -2
  100. package/dist/types/deploy/platforms/cloudflare.d.ts +10 -7
  101. package/dist/types/deploy/platforms/node.d.ts +3 -1
  102. package/dist/types/deploy/platforms/types.d.ts +18 -7
  103. package/dist/types/deploy/platforms/vercel.d.ts +20 -1
  104. package/dist/types/deploy/redirects.d.ts +17 -1
  105. package/dist/types/deploy/sitemap.d.ts +2 -1
  106. package/dist/types/deploy/vercel-negotiation.d.ts +42 -21
  107. package/dist/types/openapi/checks.d.ts +27 -0
  108. package/dist/types/openapi/graphql.d.ts +6 -0
  109. package/dist/types/openapi/model.d.ts +15 -4
  110. package/dist/types/openapi/parse.d.ts +3 -0
  111. package/dist/types/openapi/references.d.ts +16 -0
  112. package/dist/types/ratelimit/index.d.ts +1 -1
  113. package/dist/types/ratelimit/schema.d.ts +8 -0
  114. package/dist/types/ratelimit/upstash.d.ts +39 -14
  115. package/dist/types/reference/graphql.d.ts +76 -1
  116. package/dist/types/reference/index.d.ts +1 -1
  117. package/dist/types/reference/openapi.d.ts +2 -2
  118. package/dist/types/reference/options.d.ts +37 -1
  119. package/dist/types/reference/schema.d.ts +84 -0
  120. package/dist/types/search/adapters/registry.d.ts +3 -0
  121. package/dist/types/search/adapters/typesense.d.ts +14 -4
  122. package/dist/types/search/build.d.ts +3 -1
  123. package/dist/types/search/orama-index.d.ts +9 -9
  124. package/dist/types/search/sync/algolia.d.ts +5 -2
  125. package/dist/types/search/sync/index.d.ts +3 -1
  126. package/dist/types/search/sync/typesense.d.ts +11 -7
  127. package/dist/types/sources/contentful.d.ts +16 -0
  128. package/dist/types/sources/github-releases.d.ts +8 -1
  129. package/dist/types/sources/payload.d.ts +2 -0
  130. package/dist/types/sources/registry.d.ts +54 -0
  131. package/dist/types/sources/shared.d.ts +3 -0
  132. package/dist/types/sources/strapi.d.ts +2 -0
  133. package/docs/01-quickstart.mdx +4 -2
  134. package/docs/02-deployment.mdx +31 -13
  135. package/docs/advanced/changelog.mdx +11 -0
  136. package/docs/advanced/skills.mdx +1 -1
  137. package/docs/cli/audit.mdx +30 -7
  138. package/docs/cli/doctor.mdx +5 -1
  139. package/docs/cli/evals.mdx +4 -4
  140. package/docs/cli/translate.mdx +1 -0
  141. package/docs/cli/validate.mdx +4 -3
  142. package/docs/configuration/analytics.mdx +1 -1
  143. package/docs/configuration/assistant.mdx +6 -2
  144. package/docs/configuration/customization.mdx +4 -2
  145. package/docs/configuration/export.mdx +5 -3
  146. package/docs/configuration/index.mdx +3 -2
  147. package/docs/configuration/rate-limiting.mdx +23 -2
  148. package/docs/configuration/search.mdx +37 -14
  149. package/docs/content/components.mdx +2 -2
  150. package/docs/content/frontmatter.mdx +5 -3
  151. package/docs/content/i18n.mdx +2 -2
  152. package/docs/content/includes.mdx +1 -1
  153. package/docs/content/navigation.mdx +4 -4
  154. package/docs/content/sources/contentful.mdx +7 -4
  155. package/docs/content/sources/custom.mdx +7 -3
  156. package/docs/content/sources/github-releases.mdx +10 -2
  157. package/docs/content/sources/index.mdx +3 -3
  158. package/docs/content/sources/notion.mdx +1 -1
  159. package/docs/content/sources/obsidian.mdx +1 -1
  160. package/docs/content/sources/payload.mdx +3 -2
  161. package/docs/content/sources/remote-mdx.mdx +4 -0
  162. package/docs/content/sources/sanity.mdx +2 -2
  163. package/docs/content/sources/strapi.mdx +3 -2
  164. package/docs/content/syntax.mdx +2 -2
  165. package/docs/discoverability/agent-discovery.mdx +1 -1
  166. package/docs/discoverability/index.mdx +1 -1
  167. package/docs/discoverability/json-api.mdx +2 -0
  168. package/docs/discoverability/llms-txt.mdx +1 -1
  169. package/docs/discoverability/markdown.mdx +3 -1
  170. package/docs/discoverability/mcp.mdx +4 -0
  171. package/docs/discoverability/sitemap-and-robots.mdx +1 -1
  172. package/docs/references/api-pages.mdx +1 -1
  173. package/docs/references/asyncapi.mdx +3 -1
  174. package/docs/references/graphql.mdx +13 -1
  175. package/docs/references/openapi.mdx +50 -8
  176. package/package.json +9 -9
  177. package/skills/blume-migrate/SKILL.md +1 -1
  178. package/skills/blume-migrate/references/docusaurus.md +4 -4
  179. package/skills/blume-migrate/references/fumadocs.md +17 -13
  180. package/skills/blume-migrate/references/nextra.md +8 -5
  181. package/skills/blume-migrate/references/starlight.md +9 -7
  182. package/src/ai/ask-context.ts +33 -3
  183. package/src/ai/ask-limits.ts +13 -0
  184. package/src/ai/changelog-markdown.ts +11 -6
  185. package/src/ai/component-markdown.ts +1 -1
  186. package/src/ai/cors.ts +12 -3
  187. package/src/ai/mcp/query.ts +14 -6
  188. package/src/ai/openapi-components.ts +28 -4
  189. package/src/ai/relative-links.ts +4 -38
  190. package/src/astro/generate.ts +78 -48
  191. package/src/astro/integration.ts +16 -13
  192. package/src/astro/markdown-negotiation.ts +3 -0
  193. package/src/astro/module-types.ts +3 -1
  194. package/src/astro/pages.ts +23 -0
  195. package/src/astro/templates.ts +125 -80
  196. package/src/audit/catalog.ts +19 -3
  197. package/src/audit/checks/links.ts +14 -1
  198. package/src/audit/checks/network.ts +110 -6
  199. package/src/audit/checks/redirects.ts +6 -4
  200. package/src/audit/checks/robots.ts +58 -2
  201. package/src/audit/run.ts +3 -0
  202. package/src/audit/types.ts +2 -0
  203. package/src/audit/url.ts +14 -5
  204. package/src/blume-modules.d.ts +5 -1
  205. package/src/cli/args.ts +51 -0
  206. package/src/cli/build-failure.ts +23 -0
  207. package/src/cli/commands/audit.ts +10 -1
  208. package/src/cli/commands/dev.ts +18 -2
  209. package/src/cli/commands/doctor.ts +45 -12
  210. package/src/cli/commands/eval.ts +36 -4
  211. package/src/cli/commands/init.ts +6 -4
  212. package/src/cli/commands/validate.ts +10 -1
  213. package/src/cli/init/scaffold.ts +3 -3
  214. package/src/cli/prepare.ts +6 -3
  215. package/src/cli/required-secrets.ts +1 -1
  216. package/src/components/content/ApiPlayground.astro +6 -2
  217. package/src/components/content/api-field.ts +4 -1
  218. package/src/components/content/api-page.ts +31 -7
  219. package/src/components/content/mermaid-element.ts +15 -1
  220. package/src/components/islands/hooks.ts +27 -1
  221. package/src/components/layout/PageActions.astro +139 -24
  222. package/src/components/layout/RootLayout.astro +10 -2
  223. package/src/components/layout/Search.astro +17 -3
  224. package/src/components/layout/TableOfContents.astro +24 -17
  225. package/src/components/layout/head-scripts.ts +6 -1
  226. package/src/components/layout/search/algolia.ts +10 -1
  227. package/src/components/layout/search/analytics.ts +42 -14
  228. package/src/components/layout/search/endpoint.ts +48 -5
  229. package/src/components/layout/search/pagefind.ts +114 -5
  230. package/src/components/layout/search/types.ts +12 -0
  231. package/src/components/layout/search/typesense.ts +18 -6
  232. package/src/components/openapi/AsyncApiOperation.astro +14 -7
  233. package/src/components/openapi/Authorization.astro +10 -0
  234. package/src/components/openapi/GraphqlOperation.astro +5 -0
  235. package/src/components/openapi/Operation.astro +24 -1
  236. package/src/components/openapi/ParametersTable.astro +8 -4
  237. package/src/components/openapi/Playground.astro +7 -1
  238. package/src/components/openapi/RequestBody.astro +19 -2
  239. package/src/components/openapi/Responses.astro +1 -0
  240. package/src/components/openapi/SchemaTable.astro +15 -3
  241. package/src/components/openapi/async-snippets.ts +61 -5
  242. package/src/components/openapi/async.ts +123 -29
  243. package/src/components/openapi/graphql-helpers.ts +35 -12
  244. package/src/components/openapi/helpers.ts +36 -2
  245. package/src/components/openapi/message-model.ts +54 -11
  246. package/src/components/openapi/message.ts +14 -4
  247. package/src/components/openapi/operation-model.ts +16 -7
  248. package/src/components/openapi/playground-client.ts +24 -5
  249. package/src/components/openapi/playground-schema.ts +1 -1
  250. package/src/components/openapi/schema-tree.ts +44 -14
  251. package/src/components/openapi/security.ts +10 -0
  252. package/src/components/openapi/snippets.ts +5 -3
  253. package/src/components/openapi/validate-json.ts +4 -3
  254. package/src/core/changelog-index.ts +31 -1
  255. package/src/core/component-diagnostics.ts +53 -0
  256. package/src/core/component-overrides.ts +32 -0
  257. package/src/core/config-input.ts +31 -3
  258. package/src/core/data.ts +2 -0
  259. package/src/core/diagnostics.ts +5 -0
  260. package/src/core/i18n-ui.ts +2 -0
  261. package/src/core/includes.ts +1 -1
  262. package/src/core/links.ts +47 -17
  263. package/src/core/probe.ts +26 -6
  264. package/src/core/project-graph.ts +59 -18
  265. package/src/core/redirect-patterns.ts +36 -7
  266. package/src/core/schema.ts +21 -2
  267. package/src/core/sources/cache.ts +6 -0
  268. package/src/core/sources/contentful-rich-text.ts +29 -6
  269. package/src/core/sources/contentful.ts +135 -25
  270. package/src/core/sources/filesystem.ts +26 -4
  271. package/src/core/sources/github-releases.ts +12 -1
  272. package/src/core/sources/lexical.ts +15 -10
  273. package/src/core/sources/mdx-remote.ts +62 -10
  274. package/src/core/sources/normalize.ts +227 -41
  275. package/src/core/sources/notion.ts +7 -1
  276. package/src/core/sources/obsidian.ts +16 -3
  277. package/src/core/sources/payload.ts +38 -15
  278. package/src/core/sources/remote.ts +72 -15
  279. package/src/core/sources/resolve.ts +11 -1
  280. package/src/core/sources/sanity.ts +43 -25
  281. package/src/core/sources/strapi.ts +2 -2
  282. package/src/core/types.ts +18 -0
  283. package/src/core/ui-packs/ar.ts +1 -0
  284. package/src/core/ui-packs/bg.ts +1 -0
  285. package/src/core/ui-packs/bn.ts +1 -0
  286. package/src/core/ui-packs/ca.ts +1 -0
  287. package/src/core/ui-packs/cs.ts +1 -0
  288. package/src/core/ui-packs/da.ts +1 -0
  289. package/src/core/ui-packs/de.ts +1 -0
  290. package/src/core/ui-packs/el.ts +1 -0
  291. package/src/core/ui-packs/es.ts +1 -0
  292. package/src/core/ui-packs/fa.ts +1 -0
  293. package/src/core/ui-packs/fi.ts +1 -0
  294. package/src/core/ui-packs/fr.ts +1 -0
  295. package/src/core/ui-packs/he.ts +1 -0
  296. package/src/core/ui-packs/hi.ts +1 -0
  297. package/src/core/ui-packs/hr.ts +1 -0
  298. package/src/core/ui-packs/hu.ts +1 -0
  299. package/src/core/ui-packs/id.ts +1 -0
  300. package/src/core/ui-packs/it.ts +1 -0
  301. package/src/core/ui-packs/ja.ts +1 -0
  302. package/src/core/ui-packs/ko.ts +1 -0
  303. package/src/core/ui-packs/nl.ts +1 -0
  304. package/src/core/ui-packs/no.ts +1 -0
  305. package/src/core/ui-packs/pl.ts +1 -0
  306. package/src/core/ui-packs/pt-br.ts +1 -0
  307. package/src/core/ui-packs/pt.ts +1 -0
  308. package/src/core/ui-packs/ro.ts +1 -0
  309. package/src/core/ui-packs/ru.ts +1 -0
  310. package/src/core/ui-packs/sk.ts +1 -0
  311. package/src/core/ui-packs/sr.ts +1 -0
  312. package/src/core/ui-packs/sv.ts +1 -0
  313. package/src/core/ui-packs/th.ts +1 -0
  314. package/src/core/ui-packs/tr.ts +1 -0
  315. package/src/core/ui-packs/uk.ts +1 -0
  316. package/src/core/ui-packs/vi.ts +1 -0
  317. package/src/core/ui-packs/zh-tw.ts +1 -0
  318. package/src/core/ui-packs/zh.ts +1 -0
  319. package/src/deploy/adapter-output.ts +7 -2
  320. package/src/deploy/adapters/cloudflare.ts +7 -5
  321. package/src/deploy/adapters/node.ts +47 -9
  322. package/src/deploy/adapters/types.ts +7 -3
  323. package/src/deploy/artifacts.ts +2 -1
  324. package/src/deploy/platforms/cloudflare.ts +13 -9
  325. package/src/deploy/platforms/netlify.ts +2 -1
  326. package/src/deploy/platforms/node.ts +12 -2
  327. package/src/deploy/platforms/types.ts +21 -7
  328. package/src/deploy/platforms/vercel.ts +113 -16
  329. package/src/deploy/redirects.ts +66 -6
  330. package/src/deploy/rss.ts +3 -1
  331. package/src/deploy/sitemap.ts +39 -5
  332. package/src/deploy/vercel-negotiation.ts +290 -102
  333. package/src/eval/agents.ts +18 -1
  334. package/src/eval/prompts.ts +6 -3
  335. package/src/eval/report.ts +34 -13
  336. package/src/eval/run.ts +5 -0
  337. package/src/markdown/relative-links.ts +3 -2
  338. package/src/openapi/checks.ts +273 -0
  339. package/src/openapi/graphql-build.ts +21 -0
  340. package/src/openapi/graphql.ts +11 -0
  341. package/src/openapi/model.ts +15 -3
  342. package/src/openapi/parse.ts +127 -2
  343. package/src/openapi/references.ts +43 -3
  344. package/src/openapi/source.ts +39 -14
  345. package/src/ratelimit/index.ts +1 -1
  346. package/src/ratelimit/runtime.ts +37 -19
  347. package/src/ratelimit/upstash.ts +40 -10
  348. package/src/reference/graphql.ts +15 -1
  349. package/src/reference/index.ts +1 -0
  350. package/src/reference/openapi.ts +2 -2
  351. package/src/reference/options.ts +29 -1
  352. package/src/registry/eject.ts +3 -1
  353. package/src/search/adapters/locale-scope.ts +30 -0
  354. package/src/search/adapters/typesense.ts +14 -4
  355. package/src/search/build.ts +21 -3
  356. package/src/search/orama-index.ts +163 -31
  357. package/src/search/source-pages.ts +29 -0
  358. package/src/search/sync/algolia.ts +99 -9
  359. package/src/search/sync/index.ts +52 -13
  360. package/src/search/sync/typesense.ts +72 -27
  361. package/src/sources/contentful.ts +12 -0
  362. package/src/sources/github-releases.ts +7 -1
  363. package/src/sources/shared.ts +3 -0
  364. package/src/theme/entry.ts +29 -3
  365. package/src/translate/validate.ts +23 -1
  366. package/dist/cli/chunk-0gz36akr.js.map +0 -12
  367. package/dist/cli/chunk-2n4ps1b3.js.map +0 -15
  368. package/dist/cli/chunk-43zcf4gz.js.map +0 -36
  369. package/dist/cli/chunk-4ejxbzee.js +0 -39
  370. package/dist/cli/chunk-4ejxbzee.js.map +0 -10
  371. package/dist/cli/chunk-4h8z9vv5.js.map +0 -16
  372. package/dist/cli/chunk-713mngdq.js.map +0 -14
  373. package/dist/cli/chunk-9xr4dgee.js.map +0 -10
  374. package/dist/cli/chunk-amrb6hgh.js +0 -145
  375. package/dist/cli/chunk-amrb6hgh.js.map +0 -11
  376. package/dist/cli/chunk-nd1821sk.js.map +0 -10
  377. package/dist/cli/chunk-rekqz4qg.js.map +0 -10
  378. package/dist/cli/chunk-ta27feev.js.map +0 -10
  379. package/dist/cli/chunk-xkz5xbtv.js.map +0 -213
  380. package/dist/cli/chunk-y5h4r2y0.js.map +0 -10
  381. /package/dist/cli/{chunk-gp84za0h.js.map → chunk-3v3ffbrj.js.map} +0 -0
  382. /package/dist/cli/{chunk-p804f3pe.js.map → chunk-8y2kmjv8.js.map} +0 -0
  383. /package/dist/cli/{chunk-2f7n4qzt.js.map → chunk-c1y538kd.js.map} +0 -0
  384. /package/dist/cli/{chunk-1n228xqb.js.map → chunk-c887fj0s.js.map} +0 -0
  385. /package/dist/cli/{chunk-cmtcnh9f.js.map → chunk-dzwehpy7.js.map} +0 -0
  386. /package/dist/cli/{chunk-ntv4qrt7.js.map → chunk-e9q7a2ak.js.map} +0 -0
  387. /package/dist/cli/{chunk-5wj2qwn2.js.map → chunk-ft9vfys6.js.map} +0 -0
  388. /package/dist/cli/{chunk-zhvd6adm.js.map → chunk-hx3xqnk9.js.map} +0 -0
  389. /package/dist/cli/{chunk-y4ykbark.js.map → chunk-kma9f6sf.js.map} +0 -0
  390. /package/dist/cli/{chunk-py62fewh.js.map → chunk-mrcccgnh.js.map} +0 -0
  391. /package/dist/cli/{chunk-2f3ndkpw.js.map → chunk-n0v7m8ry.js.map} +0 -0
  392. /package/dist/cli/{chunk-9geymqns.js.map → chunk-nq1d20w2.js.map} +0 -0
  393. /package/dist/cli/{chunk-g2z9x01v.js.map → chunk-nrns10mj.js.map} +0 -0
  394. /package/dist/cli/{chunk-e7vvk5ya.js.map → chunk-sds923fa.js.map} +0 -0
  395. /package/dist/cli/{chunk-yj17vs39.js.map → chunk-tdqhyxfz.js.map} +0 -0
  396. /package/dist/cli/{chunk-q3wxxq39.js.map → chunk-tphac74f.js.map} +0 -0
  397. /package/dist/cli/{chunk-6bm0xpgd.js.map → chunk-w1r4vase.js.map} +0 -0
@@ -40,8 +40,11 @@ Reply with ONLY this JSON object on a single line, no markdown fences:
40
40
  {"pass": true|false, "score": 0.0-1.0, "missing": ["expected facts absent or contradicted"], "notes": "one sentence"}`;
41
41
  };
42
42
 
43
- /** The `--fix` handoff prompt: where the report is and the ground rules. */
44
- export const evalFixPrompt = (reportPath: string): string =>
43
+ /**
44
+ * The `--fix` handoff prompt: where the report is, the ground rules, and the
45
+ * `blume eval` command that verifies the fixes (the run's own flags).
46
+ */
47
+ export const evalFixPrompt = (reportPath: string, command: string): string =>
45
48
  `Fix the documentation gaps found by \`blume eval\` in this project.
46
49
 
47
50
  The full report is at ${reportPath}. It is JSON: each entry in \`eval.results\` with status "fail" is one question the documentation could not answer. Each carries the \`question\`, the \`expected\` facts, the judge's \`missing\` facts, and the reader agent's \`answer\` (what the docs currently convey). The matching \`diagnostics\` entry names the source \`file\` of the page that should answer it.
@@ -51,7 +54,7 @@ Work through every failed question:
51
54
  2. Edit the documentation so it states the missing facts explicitly. Add prose, not filler; keep the page's voice.
52
55
  3. Never delete questions from the evals file or weaken expected facts.
53
56
 
54
- When you are done, run \`blume eval\` to verify, and repeat until every question passes.`;
57
+ When you are done, run \`${command}\` to verify, and repeat until every question passes.`;
55
58
 
56
59
  /** The `eval init` prompt: draft a starter evals file from the docs. */
57
60
  export const initPrompt = (evalsPath: string): string =>
@@ -10,27 +10,40 @@ import { duration, money, seconds } from "../cli/report-format.ts";
10
10
  import { countBySeverity } from "../core/diagnostics.ts";
11
11
  import type { EvalResult, QuestionResult, QuestionStatus } from "./run.ts";
12
12
 
13
+ /** How a question reads in the report: its status, or `warn` for a warned miss. */
14
+ type ShownStatus = QuestionStatus | "warn";
15
+
13
16
  const GLYPH = {
14
17
  error: "!",
15
18
  fail: "✖",
16
19
  pass: "✔",
17
20
  skip: "⊘",
18
- } satisfies Record<QuestionStatus, string>;
21
+ warn: "⚠",
22
+ } satisfies Record<ShownStatus, string>;
19
23
 
20
24
  const STATUS_COLOR = {
21
25
  error: colors.yellow,
22
26
  fail: colors.red,
23
27
  pass: colors.green,
24
28
  skip: colors.dim,
25
- } satisfies Record<QuestionStatus, ColorFunction>;
29
+ warn: colors.yellow,
30
+ } satisfies Record<ShownStatus, ColorFunction>;
31
+
32
+ /**
33
+ * A failed `severity: warning` question: its miss never counts against the
34
+ * gate, so the report shows and counts it as a warning, not a failure.
35
+ */
36
+ const warned = (result: QuestionResult): boolean =>
37
+ result.status === "fail" && result.severity === "warning";
26
38
 
27
39
  /** Longest id gets the room; everything shorter aligns to it. */
28
40
  const ID_PAD = 28;
29
41
 
30
42
  /** One question's progress/report line: glyph, id, status, score, time, cost. */
31
43
  export const questionLine = (result: QuestionResult): string => {
32
- const color = STATUS_COLOR[result.status];
33
- const glyph = color(GLYPH[result.status]);
44
+ const shown: ShownStatus = warned(result) ? "warn" : result.status;
45
+ const color = STATUS_COLOR[shown];
46
+ const glyph = color(GLYPH[shown]);
34
47
  const id = result.id.padEnd(ID_PAD);
35
48
  if (result.status === "skip") {
36
49
  return ` ${glyph} ${id} ${colors.dim("skipped")}`;
@@ -38,7 +51,7 @@ export const questionLine = (result: QuestionResult): string => {
38
51
  const score = result.score === undefined ? "" : result.score.toFixed(2);
39
52
  const cost = money(result.costUsd);
40
53
  const cells = [
41
- color(result.status),
54
+ color(shown),
42
55
  score,
43
56
  colors.dim(seconds(result.durationMs)),
44
57
  cost === "" ? "" : colors.dim(cost),
@@ -75,9 +88,12 @@ export const questionDetails = (
75
88
  /** The one-line totals: `9 passed · 2 failed · 1 skipped · 1m 42s · $0.71`. */
76
89
  export const summaryLine = (result: EvalResult): string => {
77
90
  const { counts } = result;
91
+ const warnings = result.results.filter(warned).length;
92
+ const failures = counts.fail - warnings;
78
93
  const parts = [
79
94
  `${counts.pass} passed`,
80
- counts.fail > 0 ? `${counts.fail} failed` : "",
95
+ failures > 0 ? `${failures} failed` : "",
96
+ warnings > 0 ? `${warnings} warned` : "",
81
97
  counts.error > 0 ? `${counts.error} errored` : "",
82
98
  counts.skip > 0 ? `${counts.skip} skipped` : "",
83
99
  duration(result.durationMs),
@@ -98,10 +114,11 @@ export const startLine = (id: string, index: number, total: number): string =>
98
114
  * `fix:` pointers for failed questions, naming the file that resolves each. A
99
115
  * question whose agent run errored gets a `run failed:` line pointing at the
100
116
  * question instead: the run never graded the docs, so there's no page to fix.
117
+ * A `severity: warning` question's miss is a warning line instead.
101
118
  */
102
119
  export const fixLines = (result: EvalResult, root: string): string[] =>
103
120
  result.diagnostics
104
- .filter((diagnostic) => diagnostic.code !== "BLUME_EVAL_ROUTE_UNKNOWN")
121
+ .filter((diagnostic) => diagnostic.severity !== "warning")
105
122
  .map((finding) => {
106
123
  const site = finding.file
107
124
  ? `${relative(root, finding.file)}${finding.line ? `:${finding.line}` : ""}`
@@ -113,10 +130,13 @@ export const fixLines = (result: EvalResult, root: string): string[] =>
113
130
  return ` ${label} ${site} ${colors.dim(finding.message)}`;
114
131
  });
115
132
 
116
- /** Dim warnings for route hints that no longer match a page. */
133
+ /**
134
+ * Dim warnings: route hints that no longer match a page, and the misses of
135
+ * `severity: warning` questions.
136
+ */
117
137
  export const warningLines = (result: EvalResult, root: string): string[] =>
118
138
  result.diagnostics
119
- .filter((diagnostic) => diagnostic.code === "BLUME_EVAL_ROUTE_UNKNOWN")
139
+ .filter((diagnostic) => diagnostic.severity === "warning")
120
140
  .map((finding) => {
121
141
  const site = finding.file
122
142
  ? ` ${relative(root, finding.file)}${finding.line ? `:${finding.line}` : ""}`
@@ -140,10 +160,11 @@ export const formatEvalReport = (
140
160
  }
141
161
  lines.push("");
142
162
 
143
- // The finding tells the author which file fixes which failure.
144
- const failures = fixLines(result, root);
145
- lines.push(...failures);
146
- if (failures.length > 0) {
163
+ // The finding tells the author which file fixes which failure, warnings
164
+ // first, as the command prints them.
165
+ const findings = [...warningLines(result, root), ...fixLines(result, root)];
166
+ lines.push(...findings);
167
+ if (findings.length > 0) {
147
168
  lines.push("");
148
169
  }
149
170
 
package/src/eval/run.ts CHANGED
@@ -40,6 +40,8 @@ export interface QuestionResult {
40
40
  question: string;
41
41
  routes: string[];
42
42
  score?: number;
43
+ /** The question's severity: a `warning` miss is reported as a warning. */
44
+ severity?: EvalQuestion["severity"];
43
45
  status: QuestionStatus;
44
46
  }
45
47
 
@@ -99,6 +101,7 @@ const errored = (
99
101
  missing: [],
100
102
  question: question.question,
101
103
  routes: question.routes,
104
+ severity: question.severity,
102
105
  status: "error",
103
106
  });
104
107
 
@@ -177,6 +180,7 @@ const runQuestion = async (
177
180
  question: question.question,
178
181
  routes: question.routes,
179
182
  score: verdict.score,
183
+ severity: question.severity,
180
184
  status: verdict.pass ? "pass" : "fail",
181
185
  };
182
186
  };
@@ -250,6 +254,7 @@ export const runEval = async (options: EvalRunOptions): Promise<EvalResult> => {
250
254
  missing: [],
251
255
  question: question.question,
252
256
  routes: question.routes,
257
+ severity: question.severity,
253
258
  status: "skip",
254
259
  });
255
260
  continue;
@@ -266,8 +266,9 @@ export const relativeLinksPlugin = (
266
266
 
267
267
  // A component's string `href` (`<Card href="./install">`) is the same kind
268
268
  // of link, and `blume validate` reads it as one. Lowercase elements are
269
- // raw HTML in a `.md` page, which neither rewrites nor checks, so only
270
- // components are rewritten; an expression-valued `href={…}` is left alone.
269
+ // raw HTML in a `.md` page, which isn't rewritten, so only components are
270
+ // rewritten (validate reads a raw `<a href>` as the browser does); an
271
+ // expression-valued `href={…}` is left alone.
271
272
  const rewriteHref = (node: JsxNode, ctx: RelativeLinksContext): void => {
272
273
  if (!node.name || !COMPONENT_NAME.test(node.name)) {
273
274
  return;
@@ -0,0 +1,273 @@
1
+ import type { OperationObject } from "@scalar/openapi-types/3.2";
2
+
3
+ import type { ApiDocument } from "./model.ts";
4
+ import { HTTP_METHODS } from "./model.ts";
5
+
6
+ /**
7
+ * Targeted checks for spec mistakes that would otherwise render silently
8
+ * wrong. This is not a validator — a linter such as Spectral or oasdiff owns
9
+ * that — and a spec that fails one of these still renders. Each check names
10
+ * one mistake whose symptom on the page is quiet: a path placeholder sent
11
+ * as literal text, a Try it input whose value goes nowhere, an Authorization
12
+ * section with no scheme to describe. Each reports a warning with its own
13
+ * code, so a build says what's wrong instead of shipping it.
14
+ */
15
+
16
+ /** One mistake a check found, before the source names the spec it's in. */
17
+ export interface SpecIssue {
18
+ code: string;
19
+ message: string;
20
+ suggestion: string;
21
+ }
22
+
23
+ /** A `{name}` placeholder in a path template. */
24
+ const PATH_TEMPLATE = /\{(?<name>[^{}]+)\}/gu;
25
+
26
+ /** A reference to a parameter declared under `components.parameters`. */
27
+ const PARAMETER_REF = /^#\/components\/parameters\/(?<name>[^/]+)$/u;
28
+
29
+ /** How many operations a security-scheme warning names before counting the rest. */
30
+ const NAMED_OPERATIONS = 3;
31
+
32
+ /** One entry of a document's `paths` or `webhooks` map. */
33
+ type PathItem = NonNullable<ApiDocument["paths"]>[string];
34
+
35
+ /**
36
+ * How a warning names an operation: `GET /pets`, or a webhook by its name
37
+ * (`Webhook "newPet" (POST)`), since a webhook has no path.
38
+ */
39
+ export const operationLabel = (
40
+ name: string,
41
+ method: string,
42
+ webhook: boolean
43
+ ): string =>
44
+ webhook
45
+ ? `Webhook "${name}" (${method.toUpperCase()})`
46
+ : `${method.toUpperCase()} ${name}`;
47
+
48
+ /** One entry of a `parameters` list: a parameter, or a `$ref` to one. */
49
+ type ParameterEntry = NonNullable<OperationObject["parameters"]>[number];
50
+
51
+ // The runtime object checks stand guard because the document was parsed from
52
+ // arbitrary YAML/JSON: a spec can put a scalar or null where the type
53
+ // promises an object.
54
+ const isObject = <Value>(value: Value): value is NonNullable<Value> =>
55
+ typeof value === "object" && value !== null;
56
+
57
+ /** A parameter's `name`, which a hand-written spec may have left out or mistyped. */
58
+ const isName = <Value>(value: Value): value is Value & string =>
59
+ typeof value === "string";
60
+
61
+ /** A declared list, or none when a hand-written spec put something else there. */
62
+ const listOf = <Item>(value: Item[] | undefined): NonNullable<Item>[] =>
63
+ Array.isArray(value) ? value.filter(isObject) : [];
64
+
65
+ /** A resolved parameter: one that isn't a `$ref`. */
66
+ type Parameter = Extract<ParameterEntry, { in: string }>;
67
+
68
+ /**
69
+ * The parameters an operation declares, its path item's and its own, `$ref`s
70
+ * resolved through `components.parameters`. One that doesn't resolve is left
71
+ * out, as the page leaves it out.
72
+ */
73
+ const parametersOf = (
74
+ document: ApiDocument,
75
+ item: PathItem,
76
+ operation: OperationObject
77
+ ): Parameter[] => {
78
+ const components = document.components?.parameters ?? {};
79
+ return [
80
+ ...listOf<ParameterEntry>(item.parameters),
81
+ ...listOf<ParameterEntry>(operation.parameters),
82
+ ].flatMap((entry) => {
83
+ const refName =
84
+ "$ref" in entry
85
+ ? PARAMETER_REF.exec(entry.$ref)?.groups?.name
86
+ : undefined;
87
+ const parameter = (refName ? components[refName] : undefined) ?? entry;
88
+ return "in" in parameter ? [parameter] : [];
89
+ });
90
+ };
91
+
92
+ /**
93
+ * A path whose template and declared path parameters disagree. A placeholder
94
+ * with no parameter gets no input in Try it and no row in the table, so
95
+ * requests send it as literal text; a parameter with no placeholder gets an
96
+ * input whose value never reaches the URL.
97
+ */
98
+ const pathParameterIssues = (
99
+ signature: string,
100
+ path: string,
101
+ declared: Set<string>
102
+ ): SpecIssue[] => {
103
+ const used = new Set(
104
+ [...path.matchAll(PATH_TEMPLATE)].map((match) => match.groups?.name ?? "")
105
+ );
106
+ const issues: SpecIssue[] = [];
107
+ for (const name of used) {
108
+ if (!declared.has(name)) {
109
+ issues.push({
110
+ code: "BLUME_OPENAPI_PATH_PARAMETER_MISSING",
111
+ message: `${signature} has {${name}} in its path but declares no "${name}" path parameter, so Try it and the code samples send "{${name}}" as literal text.`,
112
+ suggestion: `Declare "${name}" in the operation's or the path's \`parameters\`, with \`in: path\` and \`required: true\`.`,
113
+ });
114
+ }
115
+ }
116
+ for (const name of declared) {
117
+ if (!used.has(name)) {
118
+ issues.push({
119
+ code: "BLUME_OPENAPI_PATH_PARAMETER_UNUSED",
120
+ message: `${signature} declares a "${name}" path parameter, but its path has no {${name}}, so the value Try it asks for never reaches the URL.`,
121
+ suggestion: `Add {${name}} to the path, or remove the parameter.`,
122
+ });
123
+ }
124
+ }
125
+ return issues;
126
+ };
127
+
128
+ /** The scheme names a `security` list requires. */
129
+ const requiredSchemes = (
130
+ security: ApiDocument["security"] | OperationObject["security"]
131
+ ): string[] =>
132
+ listOf(security).flatMap((requirement) => Object.keys(requirement));
133
+
134
+ /**
135
+ * Security schemes a requirement names that `components.securitySchemes`
136
+ * doesn't define: the Authorization section has nothing to describe, and
137
+ * Try it and the code samples send no credential for them. One warning per
138
+ * scheme, naming where it's required: the root `security`, or the first few
139
+ * operations that list it.
140
+ */
141
+ const securitySchemeIssues = (
142
+ document: ApiDocument,
143
+ requirers: Map<string, string[]>
144
+ ): SpecIssue[] => {
145
+ const defined = document.components?.securitySchemes ?? {};
146
+ const root = new Set(requiredSchemes(document.security));
147
+ const issues: SpecIssue[] = [];
148
+ for (const scheme of new Set([...root, ...requirers.keys()])) {
149
+ if (Object.hasOwn(defined, scheme)) {
150
+ continue;
151
+ }
152
+ const operations = requirers.get(scheme) ?? [];
153
+ const more = operations.length - NAMED_OPERATIONS;
154
+ const where = root.has(scheme)
155
+ ? "The spec's root `security` requires"
156
+ : `${operations.slice(0, NAMED_OPERATIONS).join(", ")}${more > 0 ? ` and ${more} more` : ""} ${operations.length === 1 ? "requires" : "require"}`;
157
+ issues.push({
158
+ code: "BLUME_OPENAPI_UNKNOWN_SECURITY_SCHEME",
159
+ message: `${where} the "${scheme}" security scheme, which \`components.securitySchemes\` doesn't define, so the Authorization section can't describe it and requests send no credential for it.`,
160
+ suggestion: `Define "${scheme}" in \`components.securitySchemes\`, or fix the name in \`security\`.`,
161
+ });
162
+ }
163
+ return issues;
164
+ };
165
+
166
+ /**
167
+ * An operation's `in: querystring` parameter (OpenAPI 3.2: the whole query
168
+ * string as one value), which the parameter table, Try it, and the code
169
+ * samples don't handle yet, so it would drop out of all three without a sign.
170
+ */
171
+ const querystringIssue = (signature: string): SpecIssue => ({
172
+ code: "BLUME_OPENAPI_UNSUPPORTED",
173
+ message: `${signature} declares an \`in: querystring\` parameter, which OpenAPI 3.2 added and Blume doesn't render yet, so the page has no row or Try it input for it and the code samples leave the query string out.`,
174
+ suggestion:
175
+ "Describe the query string in the operation's `description` until Blume renders `querystring` parameters.",
176
+ });
177
+
178
+ /**
179
+ * A path item's `additionalOperations` (OpenAPI 3.2: methods beyond the ones
180
+ * a path item names directly, like `COPY`), which the extractor doesn't
181
+ * collect yet, so those operations would be missing without a sign.
182
+ */
183
+ const additionalOperationsIssue = (
184
+ label: string,
185
+ methods: string[]
186
+ ): SpecIssue => ({
187
+ code: "BLUME_OPENAPI_UNSUPPORTED",
188
+ message: `${label} declares \`additionalOperations\` (${methods.join(", ")}), which OpenAPI 3.2 added and Blume doesn't render yet, so those operations are missing from the reference.`,
189
+ suggestion:
190
+ "Document those operations on a page of their own until Blume renders `additionalOperations`.",
191
+ });
192
+
193
+ /**
194
+ * A root `x-webhooks` and no `webhooks`. It's the extension OpenAPI 3.0 tools
195
+ * read for webhooks, and upgrading a 3.0 spec renames it to `webhooks`; a spec
196
+ * already at 3.1 or later isn't upgraded, so it stays an extension and its
197
+ * webhooks would be missing without a sign.
198
+ */
199
+ const xWebhooksIssues = (document: ApiDocument): SpecIssue[] =>
200
+ "x-webhooks" in document && document.webhooks === undefined
201
+ ? [
202
+ {
203
+ code: "BLUME_OPENAPI_X_WEBHOOKS",
204
+ message:
205
+ "The spec declares its webhooks under `x-webhooks`, the extension OpenAPI 3.0 tools read. Blume reads it only from a 3.0 spec, which it upgrades, so these webhooks are missing from the reference.",
206
+ suggestion:
207
+ "Rename `x-webhooks` to `webhooks`, the field OpenAPI 3.1 added for them.",
208
+ },
209
+ ]
210
+ : [];
211
+
212
+ /**
213
+ * Check a parsed document for the mistakes above, and for the OpenAPI 3.2
214
+ * features Blume doesn't render yet. `$ref` path items are skipped: the
215
+ * extractor already reports them as missing from the reference.
216
+ */
217
+ export const specIssues = (document: ApiDocument): SpecIssue[] => {
218
+ const issues: SpecIssue[] = [...xWebhooksIssues(document)];
219
+ // Scheme name -> the operations whose own `security` lists it.
220
+ const requirers = new Map<string, string[]>();
221
+ const visit = (name: string, item: PathItem, webhook: boolean): void => {
222
+ if (!isObject(item) || "$ref" in item) {
223
+ return;
224
+ }
225
+ const additional = isObject(item.additionalOperations)
226
+ ? Object.keys(item.additionalOperations)
227
+ : [];
228
+ if (additional.length > 0) {
229
+ issues.push(
230
+ additionalOperationsIssue(
231
+ webhook ? `Webhook "${name}"` : `Path "${name}"`,
232
+ additional
233
+ )
234
+ );
235
+ }
236
+ for (const method of HTTP_METHODS) {
237
+ const operation = item[method];
238
+ if (!isObject(operation)) {
239
+ continue;
240
+ }
241
+ const signature = operationLabel(name, method, webhook);
242
+ for (const scheme of requiredSchemes(operation.security)) {
243
+ requirers.set(scheme, [...(requirers.get(scheme) ?? []), signature]);
244
+ }
245
+ const parameters = parametersOf(document, item, operation);
246
+ // A webhook is keyed by its name, not a path: it has no template.
247
+ if (!webhook) {
248
+ issues.push(
249
+ ...pathParameterIssues(
250
+ signature,
251
+ name,
252
+ new Set(
253
+ parameters
254
+ .filter((parameter) => parameter.in === "path")
255
+ .map((parameter) => parameter.name)
256
+ .filter(isName)
257
+ )
258
+ )
259
+ );
260
+ }
261
+ if (parameters.some((parameter) => parameter.in === "querystring")) {
262
+ issues.push(querystringIssue(signature));
263
+ }
264
+ }
265
+ };
266
+ for (const [path, item] of Object.entries(document.paths ?? {})) {
267
+ visit(path, item, false);
268
+ }
269
+ for (const [name, item] of Object.entries(document.webhooks ?? {})) {
270
+ visit(name, item, true);
271
+ }
272
+ return [...issues, ...securitySchemeIssues(document, requirers)];
273
+ };
@@ -26,6 +26,7 @@ import {
26
26
  parse,
27
27
  print,
28
28
  specifiedDirectives,
29
+ valueFromASTUntyped,
29
30
  visit,
30
31
  } from "graphql";
31
32
 
@@ -34,6 +35,7 @@ import type {
34
35
  GraphqlEnumValue,
35
36
  GraphqlField as ModelField,
36
37
  GraphqlInputValue,
38
+ GraphqlJsonValue,
37
39
  GraphqlTypeDef,
38
40
  GraphqlTypeRef,
39
41
  } from "./graphql.ts";
@@ -68,6 +70,21 @@ const defaultLiteral = (
68
70
  return literal ? print(literal) : undefined;
69
71
  };
70
72
 
73
+ /**
74
+ * The same default as the JSON a client sends in `variables`, which the
75
+ * example variables start from.
76
+ */
77
+ const defaultJson = (
78
+ input: GraphQLArgument | GraphQLInputField
79
+ ): GraphqlJsonValue | undefined => {
80
+ const literal = input.default?.literal;
81
+ // SAFETY: a const literal has no variables, so it lowers to JSON values
82
+ // only: numbers, strings, booleans, null, enum names, lists and objects.
83
+ return literal
84
+ ? (valueFromASTUntyped(literal) as GraphqlJsonValue)
85
+ : undefined;
86
+ };
87
+
71
88
  const inputValue = (
72
89
  input: GraphQLArgument | GraphQLInputField
73
90
  ): GraphqlInputValue => {
@@ -80,6 +97,10 @@ const inputValue = (
80
97
  if (printed !== undefined) {
81
98
  value.default = printed;
82
99
  }
100
+ const json = defaultJson(input);
101
+ if (json !== undefined) {
102
+ value.defaultValue = json;
103
+ }
83
104
  // `deprecationReason` is null on non-deprecated members in some builds;
84
105
  // absent means "not deprecated" downstream, so both collapse to absent.
85
106
  if (
@@ -58,6 +58,15 @@ export interface GraphqlTypeRef {
58
58
  name: string;
59
59
  }
60
60
 
61
+ /** A GraphQL input value as JSON carries it in `variables` (enums by name). */
62
+ export type GraphqlJsonValue =
63
+ | string
64
+ | number
65
+ | boolean
66
+ | null
67
+ | GraphqlJsonValue[]
68
+ | { [key: string]: GraphqlJsonValue };
69
+
61
70
  /** An argument or input-object field. */
62
71
  export interface GraphqlInputValue {
63
72
  name: string;
@@ -65,6 +74,8 @@ export interface GraphqlInputValue {
65
74
  type: GraphqlTypeRef;
66
75
  /** Default value printed as a GraphQL literal (`10`, `"asc"`, `[1, 2]`). */
67
76
  default?: string;
77
+ /** The same default as JSON, for the example variables. */
78
+ defaultValue?: GraphqlJsonValue;
68
79
  deprecationReason?: string;
69
80
  }
70
81
 
@@ -1,5 +1,6 @@
1
- import type { Document, OperationObject } from "@scalar/openapi-types/3.1";
1
+ import type { Document, OperationObject } from "@scalar/openapi-types/3.2";
2
2
 
3
+ import type { GraphqlAuthOptions } from "../reference/options.ts";
3
4
  import type {
4
5
  AsyncApiAction,
5
6
  AsyncApiDocument,
@@ -26,10 +27,18 @@ export { slugify } from "./references.ts";
26
27
  * per-operation route so it becomes a first-class Blume page.
27
28
  */
28
29
 
29
- /** A normalized OpenAPI 3.1 document, internal `$ref`s intact. */
30
+ /**
31
+ * A normalized OpenAPI document, internal `$ref`s intact. Typed as 3.2, which
32
+ * is backward compatible with 3.1, so one type covers both the upgraded 3.1
33
+ * documents and the 3.2 ones read as written.
34
+ */
30
35
  export type ApiDocument = Document;
31
36
 
32
- /** The HTTP methods an OpenAPI path item may declare, in spec order. */
37
+ /**
38
+ * The HTTP methods an OpenAPI path item may declare, in spec order. `query`
39
+ * is OpenAPI 3.2's (the QUERY method: a safe request that carries a body); a
40
+ * 3.1 path item can't declare it, so listing it changes nothing there.
41
+ */
33
42
  export const HTTP_METHODS = [
34
43
  "get",
35
44
  "put",
@@ -39,6 +48,7 @@ export const HTTP_METHODS = [
39
48
  "head",
40
49
  "patch",
41
50
  "trace",
51
+ "query",
42
52
  ] as const;
43
53
 
44
54
  export type HttpMethod = (typeof HTTP_METHODS)[number];
@@ -140,6 +150,8 @@ export interface ApiSpecData {
140
150
  * (GraphQL only; OpenAPI documents carry their servers in the document).
141
151
  */
142
152
  endpoint?: string;
153
+ /** How the GraphQL endpoint authenticates (GraphQL only). */
154
+ auth?: GraphqlAuthOptions;
143
155
  /** Operations keyed by {@link ApiOperationRef.key}. */
144
156
  operations: Record<string, ApiOperationRef>;
145
157
  tags: ApiTagRef[];