blume 2.1.0 → 2.1.2

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 (450) hide show
  1. package/CHANGELOG.md +110 -0
  2. package/dist/cli/{chunk-ga0pf4aj.js → chunk-0n9xkp3d.js} +12 -3
  3. package/dist/cli/{chunk-ga0pf4aj.js.map → chunk-0n9xkp3d.js.map} +3 -3
  4. package/dist/cli/{chunk-43zcf4gz.js → chunk-0pmb4tr4.js} +541 -368
  5. package/dist/cli/chunk-0pmb4tr4.js.map +35 -0
  6. package/dist/cli/{chunk-9geymqns.js → chunk-0w6hs479.js} +15 -15
  7. package/dist/cli/{chunk-xkz5xbtv.js → chunk-124fvmzq.js} +2802 -1422
  8. package/dist/cli/chunk-124fvmzq.js.map +220 -0
  9. package/dist/cli/chunk-150jk7km.js +52 -0
  10. package/dist/cli/chunk-150jk7km.js.map +10 -0
  11. package/dist/cli/{chunk-y4ykbark.js → chunk-1f882900.js} +2 -2
  12. package/dist/cli/{chunk-5ffywsmb.js → chunk-297ajdcv.js} +8 -6
  13. package/dist/cli/{chunk-5ffywsmb.js.map → chunk-297ajdcv.js.map} +3 -3
  14. package/dist/cli/{chunk-h2a48yhd.js → chunk-32khwcb6.js} +120 -16
  15. package/dist/cli/{chunk-h2a48yhd.js.map → chunk-32khwcb6.js.map} +10 -10
  16. package/dist/cli/{chunk-5cg2rzgf.js → chunk-36bxs9c7.js} +20 -49
  17. package/dist/cli/{chunk-5cg2rzgf.js.map → chunk-36bxs9c7.js.map} +4 -5
  18. package/dist/cli/{chunk-py62fewh.js → chunk-53jqw8z0.js} +3 -3
  19. package/dist/cli/{chunk-5wj2qwn2.js → chunk-58bt3hag.js} +4 -4
  20. package/dist/cli/{chunk-e7vvk5ya.js → chunk-5cmts6dv.js} +3 -3
  21. package/dist/cli/{chunk-y5h4r2y0.js → chunk-60hz265r.js} +15 -5
  22. package/dist/cli/chunk-60hz265r.js.map +10 -0
  23. package/dist/cli/chunk-74wfhv79.js +65 -0
  24. package/dist/cli/chunk-74wfhv79.js.map +10 -0
  25. package/dist/cli/{chunk-g2z9x01v.js → chunk-9qzgg6mj.js} +3 -3
  26. package/dist/cli/{chunk-q3wxxq39.js → chunk-a57yh0h9.js} +5 -5
  27. package/dist/cli/{chunk-713mngdq.js → chunk-ave1wcbr.js} +76 -10
  28. package/dist/cli/chunk-ave1wcbr.js.map +14 -0
  29. package/dist/cli/{chunk-2n4ps1b3.js → chunk-bqxaqn5p.js} +40 -22
  30. package/dist/cli/chunk-bqxaqn5p.js.map +15 -0
  31. package/dist/cli/{chunk-jnwj5kjj.js → chunk-bxwhtvw8.js} +20 -7
  32. package/dist/cli/{chunk-jnwj5kjj.js.map → chunk-bxwhtvw8.js.map} +3 -3
  33. package/dist/cli/chunk-ckrcm08h.js +324 -0
  34. package/dist/cli/chunk-ckrcm08h.js.map +14 -0
  35. package/dist/cli/{chunk-2f3ndkpw.js → chunk-desvm72z.js} +3 -3
  36. package/dist/cli/{chunk-gp84za0h.js → chunk-dhwtqnnd.js} +2 -2
  37. package/dist/cli/{chunk-4h8z9vv5.js → chunk-dpy8qdjf.js} +93 -47
  38. package/dist/cli/chunk-dpy8qdjf.js.map +17 -0
  39. package/dist/cli/{chunk-2f7n4qzt.js → chunk-dqhg54mr.js} +1 -1
  40. package/dist/cli/{chunk-0gz36akr.js → chunk-dv2z0rzf.js} +21 -5
  41. package/dist/cli/chunk-dv2z0rzf.js.map +12 -0
  42. package/dist/cli/{chunk-cm89scdv.js → chunk-es8h0v3j.js} +9 -11
  43. package/dist/cli/{chunk-cm89scdv.js.map → chunk-es8h0v3j.js.map} +3 -3
  44. package/dist/cli/{chunk-zhvd6adm.js → chunk-gfc5fqvf.js} +14 -14
  45. package/dist/cli/{chunk-nd1821sk.js → chunk-gxtg6ed2.js} +33 -19
  46. package/dist/cli/chunk-gxtg6ed2.js.map +10 -0
  47. package/dist/cli/{chunk-p804f3pe.js → chunk-hvcxng5f.js} +6 -6
  48. package/dist/cli/{chunk-ta27feev.js → chunk-j1x92mx9.js} +21 -2
  49. package/dist/cli/chunk-j1x92mx9.js.map +10 -0
  50. package/dist/cli/{chunk-rekqz4qg.js → chunk-k3gr1nm9.js} +19 -16
  51. package/dist/cli/chunk-k3gr1nm9.js.map +10 -0
  52. package/dist/cli/{chunk-1n228xqb.js → chunk-kdpzw38a.js} +2 -2
  53. package/dist/cli/{chunk-cy5bm0j0.js → chunk-ms9z66nz.js} +2 -2
  54. package/dist/cli/{chunk-cy5bm0j0.js.map → chunk-ms9z66nz.js.map} +2 -2
  55. package/dist/cli/{chunk-zf748avv.js → chunk-nbyvgnnm.js} +193 -286
  56. package/dist/cli/chunk-nbyvgnnm.js.map +36 -0
  57. package/dist/cli/{chunk-6bm0xpgd.js → chunk-s0bdnc7v.js} +2 -2
  58. package/dist/cli/{chunk-yxmk4pec.js → chunk-sc93apfs.js} +17 -16
  59. package/dist/cli/{chunk-yxmk4pec.js.map → chunk-sc93apfs.js.map} +3 -3
  60. package/dist/cli/{chunk-cmtcnh9f.js → chunk-tfycddbt.js} +2 -2
  61. package/dist/cli/{chunk-9xr4dgee.js → chunk-twy7psdz.js} +29 -16
  62. package/dist/cli/chunk-twy7psdz.js.map +10 -0
  63. package/dist/cli/{chunk-ntv4qrt7.js → chunk-y4msrwm9.js} +15 -15
  64. package/dist/cli/{chunk-yj17vs39.js → chunk-ydp3065p.js} +5 -5
  65. package/dist/cli/index.js +24 -19
  66. package/dist/cli/index.js.map +3 -3
  67. package/dist/types/ai/ask-context.d.ts +6 -2
  68. package/dist/types/ai/ask.d.ts +24 -5
  69. package/dist/types/ai/component-markdown.d.ts +2 -0
  70. package/dist/types/ai/openapi-components.d.ts +4 -1
  71. package/dist/types/analytics/clics.d.ts +37 -0
  72. package/dist/types/analytics/index.d.ts +2 -0
  73. package/dist/types/analytics/schema.d.ts +18 -0
  74. package/dist/types/astro/integration.d.ts +11 -4
  75. package/dist/types/astro/markdown-negotiation.d.ts +3 -0
  76. package/dist/types/astro/pages.d.ts +10 -0
  77. package/dist/types/cli/init/scaffold.d.ts +1 -1
  78. package/dist/types/components/content/api-field.d.ts +4 -1
  79. package/dist/types/components/content/api-page.d.ts +6 -1
  80. package/dist/types/components/openapi/code-samples.d.ts +29 -0
  81. package/dist/types/components/openapi/helpers.d.ts +22 -1
  82. package/dist/types/components/openapi/security.d.ts +10 -0
  83. package/dist/types/components/openapi/snippets.d.ts +60 -0
  84. package/dist/types/core/changelog-index.d.ts +8 -0
  85. package/dist/types/core/config-input.d.ts +37 -6
  86. package/dist/types/core/data.d.ts +4 -0
  87. package/dist/types/core/i18n-ui.d.ts +2 -0
  88. package/dist/types/core/links.d.ts +8 -0
  89. package/dist/types/core/powered-by.d.ts +12 -0
  90. package/dist/types/core/probe.d.ts +2 -0
  91. package/dist/types/core/project-graph.d.ts +6 -0
  92. package/dist/types/core/redirect-patterns.d.ts +11 -3
  93. package/dist/types/core/schema.d.ts +228 -3
  94. package/dist/types/core/sources/cache.d.ts +3 -0
  95. package/dist/types/core/sources/contentful-rich-text.d.ts +11 -2
  96. package/dist/types/core/sources/contentful.d.ts +17 -1
  97. package/dist/types/core/sources/lexical.d.ts +5 -0
  98. package/dist/types/core/sources/lower.d.ts +10 -2
  99. package/dist/types/core/sources/normalize.d.ts +20 -1
  100. package/dist/types/core/sources/notion.d.ts +8 -0
  101. package/dist/types/core/sources/remote.d.ts +37 -10
  102. package/dist/types/core/sources/sanity.d.ts +1 -1
  103. package/dist/types/core/types.d.ts +17 -0
  104. package/dist/types/deploy/adapter-output.d.ts +2 -1
  105. package/dist/types/deploy/adapters/cloudflare.d.ts +7 -5
  106. package/dist/types/deploy/adapters/node.d.ts +58 -23
  107. package/dist/types/deploy/adapters/registry.d.ts +10 -0
  108. package/dist/types/deploy/adapters/types.d.ts +3 -2
  109. package/dist/types/deploy/cloudflare-negotiation.d.ts +5 -2
  110. package/dist/types/deploy/node-headers.d.ts +12 -4
  111. package/dist/types/deploy/platforms/cloudflare.d.ts +10 -7
  112. package/dist/types/deploy/platforms/node.d.ts +3 -1
  113. package/dist/types/deploy/platforms/types.d.ts +18 -7
  114. package/dist/types/deploy/platforms/vercel.d.ts +21 -2
  115. package/dist/types/deploy/redirects.d.ts +17 -1
  116. package/dist/types/deploy/sitemap.d.ts +2 -1
  117. package/dist/types/deploy/vercel-negotiation.d.ts +44 -21
  118. package/dist/types/narration/build.d.ts +34 -12
  119. package/dist/types/narration/provider.d.ts +96 -8
  120. package/dist/types/openapi/checks.d.ts +27 -0
  121. package/dist/types/openapi/graphql.d.ts +6 -0
  122. package/dist/types/openapi/model.d.ts +15 -4
  123. package/dist/types/openapi/parse.d.ts +3 -0
  124. package/dist/types/openapi/references.d.ts +16 -0
  125. package/dist/types/openapi/sentence.d.ts +11 -1
  126. package/dist/types/ratelimit/index.d.ts +1 -1
  127. package/dist/types/ratelimit/schema.d.ts +8 -0
  128. package/dist/types/ratelimit/upstash.d.ts +39 -14
  129. package/dist/types/reference/graphql.d.ts +76 -1
  130. package/dist/types/reference/index.d.ts +1 -1
  131. package/dist/types/reference/openapi.d.ts +2 -2
  132. package/dist/types/reference/options.d.ts +37 -1
  133. package/dist/types/reference/schema.d.ts +84 -0
  134. package/dist/types/search/adapters/registry.d.ts +3 -0
  135. package/dist/types/search/adapters/typesense.d.ts +14 -4
  136. package/dist/types/search/build.d.ts +3 -1
  137. package/dist/types/search/orama-index.d.ts +9 -9
  138. package/dist/types/search/sync/algolia.d.ts +5 -2
  139. package/dist/types/search/sync/index.d.ts +3 -1
  140. package/dist/types/search/sync/typesense.d.ts +11 -7
  141. package/dist/types/seo/jsonld.d.ts +11 -6
  142. package/dist/types/sources/contentful.d.ts +16 -0
  143. package/dist/types/sources/github-releases.d.ts +8 -1
  144. package/dist/types/sources/notion.d.ts +8 -0
  145. package/dist/types/sources/payload.d.ts +2 -0
  146. package/dist/types/sources/registry.d.ts +63 -0
  147. package/dist/types/sources/shared.d.ts +3 -0
  148. package/dist/types/sources/strapi.d.ts +2 -0
  149. package/docs/01-quickstart.mdx +4 -2
  150. package/docs/02-deployment.mdx +59 -13
  151. package/docs/03-upgrading.mdx +2 -1
  152. package/docs/04-migrating.mdx +9 -9
  153. package/docs/08-faq.mdx +12 -12
  154. package/docs/advanced/changelog.mdx +30 -2
  155. package/docs/advanced/custom-pages.mdx +1 -1
  156. package/docs/advanced/skills.mdx +1 -1
  157. package/docs/cli/audit.mdx +30 -7
  158. package/docs/cli/doctor.mdx +6 -2
  159. package/docs/cli/evals.mdx +4 -4
  160. package/docs/cli/translate.mdx +1 -0
  161. package/docs/cli/validate.mdx +4 -3
  162. package/docs/configuration/analytics.mdx +19 -1
  163. package/docs/configuration/assistant.mdx +6 -2
  164. package/docs/configuration/customization.mdx +4 -2
  165. package/docs/configuration/export.mdx +5 -3
  166. package/docs/configuration/index.mdx +4 -2
  167. package/docs/configuration/narration.mdx +43 -6
  168. package/docs/configuration/rate-limiting.mdx +23 -2
  169. package/docs/configuration/search.mdx +37 -14
  170. package/docs/content/components.mdx +2 -2
  171. package/docs/content/frontmatter.mdx +5 -3
  172. package/docs/content/i18n.mdx +2 -2
  173. package/docs/content/includes.mdx +1 -1
  174. package/docs/content/navigation.mdx +8 -6
  175. package/docs/content/sources/contentful.mdx +9 -4
  176. package/docs/content/sources/custom.mdx +7 -3
  177. package/docs/content/sources/github-releases.mdx +12 -2
  178. package/docs/content/sources/index.mdx +3 -3
  179. package/docs/content/sources/notion.mdx +17 -2
  180. package/docs/content/sources/obsidian.mdx +3 -1
  181. package/docs/content/sources/payload.mdx +5 -2
  182. package/docs/content/sources/remote-mdx.mdx +6 -0
  183. package/docs/content/sources/sanity.mdx +4 -2
  184. package/docs/content/sources/strapi.mdx +5 -2
  185. package/docs/content/syntax.mdx +2 -2
  186. package/docs/discoverability/agent-discovery.mdx +1 -1
  187. package/docs/discoverability/index.mdx +1 -1
  188. package/docs/discoverability/json-api.mdx +2 -0
  189. package/docs/discoverability/llms-txt.mdx +1 -1
  190. package/docs/discoverability/markdown.mdx +3 -1
  191. package/docs/discoverability/mcp.mdx +6 -0
  192. package/docs/discoverability/sitemap-and-robots.mdx +1 -1
  193. package/docs/discoverability/structured-data.mdx +8 -6
  194. package/docs/references/api-pages.mdx +1 -1
  195. package/docs/references/asyncapi.mdx +5 -1
  196. package/docs/references/graphql.mdx +15 -1
  197. package/docs/references/openapi.mdx +64 -8
  198. package/package.json +9 -9
  199. package/skills/blume/SKILL.md +1 -1
  200. package/skills/blume-migrate/SKILL.md +2 -2
  201. package/skills/blume-migrate/assets/{oxfmt@0.67.0.patch → oxfmt@0.71.0.patch} +7 -7
  202. package/skills/blume-migrate/references/docusaurus.md +4 -4
  203. package/skills/blume-migrate/references/fumadocs.md +17 -13
  204. package/skills/blume-migrate/references/monorepo.md +5 -5
  205. package/skills/blume-migrate/references/nextra.md +8 -5
  206. package/skills/blume-migrate/references/starlight.md +9 -7
  207. package/src/ai/ask-context.ts +33 -3
  208. package/src/ai/ask-limits.ts +13 -0
  209. package/src/ai/ask.ts +24 -6
  210. package/src/ai/changelog-markdown.ts +11 -6
  211. package/src/ai/component-markdown.ts +1 -1
  212. package/src/ai/cors.ts +12 -3
  213. package/src/ai/mcp/query.ts +14 -6
  214. package/src/ai/openapi-components.ts +28 -4
  215. package/src/ai/relative-links.ts +4 -38
  216. package/src/analytics/clics.ts +58 -0
  217. package/src/analytics/head.ts +5 -0
  218. package/src/analytics/index.ts +2 -0
  219. package/src/analytics/schema.ts +2 -0
  220. package/src/astro/generate.ts +91 -56
  221. package/src/astro/integration.ts +72 -22
  222. package/src/astro/markdown-negotiation.ts +3 -0
  223. package/src/astro/module-types.ts +3 -1
  224. package/src/astro/pages.ts +23 -0
  225. package/src/astro/render-deps.ts +10 -5
  226. package/src/astro/runtime-deps.ts +23 -2
  227. package/src/astro/templates.ts +129 -81
  228. package/src/audit/catalog.ts +19 -3
  229. package/src/audit/checks/links.ts +14 -1
  230. package/src/audit/checks/network.ts +110 -6
  231. package/src/audit/checks/redirects.ts +6 -4
  232. package/src/audit/checks/robots.ts +58 -2
  233. package/src/audit/run.ts +3 -0
  234. package/src/audit/types.ts +2 -0
  235. package/src/audit/url.ts +14 -5
  236. package/src/blume-modules.d.ts +5 -1
  237. package/src/cli/args.ts +51 -0
  238. package/src/cli/build-failure.ts +23 -0
  239. package/src/cli/commands/audit.ts +10 -1
  240. package/src/cli/commands/dev.ts +18 -2
  241. package/src/cli/commands/doctor.ts +45 -12
  242. package/src/cli/commands/eval.ts +36 -4
  243. package/src/cli/commands/init.ts +6 -4
  244. package/src/cli/commands/validate.ts +10 -1
  245. package/src/cli/init/scaffold.ts +9 -6
  246. package/src/cli/prepare.ts +6 -3
  247. package/src/cli/required-secrets.ts +3 -2
  248. package/src/components/content/ApiPlayground.astro +6 -2
  249. package/src/components/content/api-field.ts +4 -1
  250. package/src/components/content/api-page.ts +31 -7
  251. package/src/components/content/mermaid-element.ts +15 -1
  252. package/src/components/content/view-switcher.ts +7 -4
  253. package/src/components/islands/hooks.ts +27 -1
  254. package/src/components/layout/NavTree.astro +49 -5
  255. package/src/components/layout/NavTreeScript.astro +18 -0
  256. package/src/components/layout/PageActions.astro +139 -24
  257. package/src/components/layout/PageLayout.astro +13 -3
  258. package/src/components/layout/RootLayout.astro +27 -14
  259. package/src/components/layout/Search.astro +17 -3
  260. package/src/components/layout/TableOfContents.astro +24 -17
  261. package/src/components/layout/analytics-client.ts +8 -8
  262. package/src/components/layout/head-scripts.ts +6 -1
  263. package/src/components/layout/search/algolia.ts +10 -1
  264. package/src/components/layout/search/analytics.ts +42 -14
  265. package/src/components/layout/search/endpoint.ts +48 -5
  266. package/src/components/layout/search/pagefind.ts +114 -5
  267. package/src/components/layout/search/types.ts +12 -0
  268. package/src/components/layout/search/typesense.ts +18 -6
  269. package/src/components/openapi/AsyncApiOperation.astro +14 -7
  270. package/src/components/openapi/Authorization.astro +10 -0
  271. package/src/components/openapi/GraphqlOperation.astro +5 -0
  272. package/src/components/openapi/Operation.astro +24 -1
  273. package/src/components/openapi/ParametersTable.astro +8 -4
  274. package/src/components/openapi/Playground.astro +7 -1
  275. package/src/components/openapi/RequestBody.astro +19 -2
  276. package/src/components/openapi/Responses.astro +1 -0
  277. package/src/components/openapi/SchemaTable.astro +15 -3
  278. package/src/components/openapi/async-snippets.ts +61 -5
  279. package/src/components/openapi/async.ts +123 -29
  280. package/src/components/openapi/graphql-helpers.ts +35 -12
  281. package/src/components/openapi/helpers.ts +36 -2
  282. package/src/components/openapi/message-model.ts +54 -11
  283. package/src/components/openapi/message.ts +14 -4
  284. package/src/components/openapi/operation-model.ts +16 -7
  285. package/src/components/openapi/playground-client.ts +77 -58
  286. package/src/components/openapi/playground-schema.ts +1 -1
  287. package/src/components/openapi/schema-tree.ts +44 -14
  288. package/src/components/openapi/security.ts +10 -0
  289. package/src/components/openapi/snippets.ts +5 -3
  290. package/src/components/openapi/validate-json.ts +4 -3
  291. package/src/components/powered-by-middleware.ts +33 -0
  292. package/src/core/changelog-index.ts +31 -1
  293. package/src/core/component-diagnostics.ts +53 -0
  294. package/src/core/component-overrides.ts +32 -0
  295. package/src/core/config-input.ts +42 -6
  296. package/src/core/data.ts +2 -0
  297. package/src/core/diagnostics.ts +5 -0
  298. package/src/core/i18n-ui.ts +2 -0
  299. package/src/core/includes.ts +1 -1
  300. package/src/core/links.ts +47 -17
  301. package/src/core/powered-by.ts +12 -0
  302. package/src/core/probe.ts +26 -6
  303. package/src/core/project-graph.ts +59 -18
  304. package/src/core/redirect-patterns.ts +36 -7
  305. package/src/core/schema.ts +26 -6
  306. package/src/core/sources/cache.ts +6 -0
  307. package/src/core/sources/contentful-rich-text.ts +29 -6
  308. package/src/core/sources/contentful.ts +135 -25
  309. package/src/core/sources/filesystem.ts +26 -4
  310. package/src/core/sources/github-releases.ts +12 -1
  311. package/src/core/sources/lexical.ts +15 -10
  312. package/src/core/sources/lower.ts +19 -3
  313. package/src/core/sources/mdx-remote.ts +62 -10
  314. package/src/core/sources/normalize.ts +227 -41
  315. package/src/core/sources/notion.ts +34 -10
  316. package/src/core/sources/obsidian.ts +16 -3
  317. package/src/core/sources/payload.ts +38 -15
  318. package/src/core/sources/remote.ts +72 -15
  319. package/src/core/sources/resolve.ts +11 -1
  320. package/src/core/sources/sanity.ts +43 -25
  321. package/src/core/sources/strapi.ts +2 -2
  322. package/src/core/types.ts +18 -0
  323. package/src/core/ui-packs/ar.ts +1 -0
  324. package/src/core/ui-packs/bg.ts +1 -0
  325. package/src/core/ui-packs/bn.ts +1 -0
  326. package/src/core/ui-packs/ca.ts +1 -0
  327. package/src/core/ui-packs/cs.ts +1 -0
  328. package/src/core/ui-packs/da.ts +1 -0
  329. package/src/core/ui-packs/de.ts +1 -0
  330. package/src/core/ui-packs/el.ts +1 -0
  331. package/src/core/ui-packs/es.ts +1 -0
  332. package/src/core/ui-packs/fa.ts +1 -0
  333. package/src/core/ui-packs/fi.ts +1 -0
  334. package/src/core/ui-packs/fr.ts +1 -0
  335. package/src/core/ui-packs/he.ts +1 -0
  336. package/src/core/ui-packs/hi.ts +1 -0
  337. package/src/core/ui-packs/hr.ts +1 -0
  338. package/src/core/ui-packs/hu.ts +1 -0
  339. package/src/core/ui-packs/id.ts +1 -0
  340. package/src/core/ui-packs/it.ts +1 -0
  341. package/src/core/ui-packs/ja.ts +1 -0
  342. package/src/core/ui-packs/ko.ts +1 -0
  343. package/src/core/ui-packs/nl.ts +1 -0
  344. package/src/core/ui-packs/no.ts +1 -0
  345. package/src/core/ui-packs/pl.ts +1 -0
  346. package/src/core/ui-packs/pt-br.ts +1 -0
  347. package/src/core/ui-packs/pt.ts +1 -0
  348. package/src/core/ui-packs/ro.ts +1 -0
  349. package/src/core/ui-packs/ru.ts +1 -0
  350. package/src/core/ui-packs/sk.ts +1 -0
  351. package/src/core/ui-packs/sr.ts +1 -0
  352. package/src/core/ui-packs/sv.ts +1 -0
  353. package/src/core/ui-packs/th.ts +1 -0
  354. package/src/core/ui-packs/tr.ts +1 -0
  355. package/src/core/ui-packs/uk.ts +1 -0
  356. package/src/core/ui-packs/vi.ts +1 -0
  357. package/src/core/ui-packs/zh-tw.ts +1 -0
  358. package/src/core/ui-packs/zh.ts +1 -0
  359. package/src/deploy/adapter-output.ts +7 -2
  360. package/src/deploy/adapters/cloudflare.ts +7 -5
  361. package/src/deploy/adapters/node.ts +47 -9
  362. package/src/deploy/adapters/types.ts +7 -3
  363. package/src/deploy/artifacts.ts +2 -1
  364. package/src/deploy/cloudflare-negotiation.ts +36 -7
  365. package/src/deploy/headers.ts +15 -1
  366. package/src/deploy/node-headers.ts +32 -20
  367. package/src/deploy/platforms/cloudflare.ts +14 -9
  368. package/src/deploy/platforms/netlify.ts +2 -1
  369. package/src/deploy/platforms/node.ts +12 -2
  370. package/src/deploy/platforms/types.ts +21 -7
  371. package/src/deploy/platforms/vercel.ts +115 -17
  372. package/src/deploy/redirects.ts +66 -6
  373. package/src/deploy/rss.ts +3 -1
  374. package/src/deploy/sitemap.ts +39 -5
  375. package/src/deploy/vercel-negotiation.ts +325 -103
  376. package/src/eval/agents.ts +18 -1
  377. package/src/eval/prompts.ts +6 -3
  378. package/src/eval/report.ts +34 -13
  379. package/src/eval/run.ts +5 -0
  380. package/src/markdown/base-links.ts +15 -14
  381. package/src/markdown/package-commands.ts +9 -8
  382. package/src/markdown/relative-links.ts +3 -2
  383. package/src/narration/build.ts +218 -40
  384. package/src/narration/provider.ts +89 -9
  385. package/src/openapi/checks.ts +273 -0
  386. package/src/openapi/graphql-build.ts +21 -0
  387. package/src/openapi/graphql.ts +11 -0
  388. package/src/openapi/model.ts +15 -3
  389. package/src/openapi/parse.ts +127 -2
  390. package/src/openapi/references.ts +43 -3
  391. package/src/openapi/render-mdx.ts +68 -8
  392. package/src/openapi/sentence.ts +29 -2
  393. package/src/openapi/source.ts +39 -14
  394. package/src/ratelimit/index.ts +1 -1
  395. package/src/ratelimit/runtime.ts +37 -19
  396. package/src/ratelimit/upstash.ts +40 -10
  397. package/src/reference/graphql.ts +15 -1
  398. package/src/reference/index.ts +1 -0
  399. package/src/reference/openapi.ts +2 -2
  400. package/src/reference/options.ts +29 -1
  401. package/src/registry/eject.ts +8 -2
  402. package/src/search/adapters/locale-scope.ts +30 -0
  403. package/src/search/adapters/typesense.ts +14 -4
  404. package/src/search/build.ts +21 -3
  405. package/src/search/orama-index.ts +163 -31
  406. package/src/search/source-pages.ts +29 -0
  407. package/src/search/sync/algolia.ts +99 -9
  408. package/src/search/sync/index.ts +52 -13
  409. package/src/search/sync/typesense.ts +72 -27
  410. package/src/seo/jsonld.ts +38 -20
  411. package/src/sources/contentful.ts +12 -0
  412. package/src/sources/github-releases.ts +7 -1
  413. package/src/sources/notion.ts +7 -0
  414. package/src/sources/shared.ts +3 -0
  415. package/src/theme/color.ts +9 -10
  416. package/src/theme/entry.ts +43 -6
  417. package/src/translate/validate.ts +23 -1
  418. package/dist/cli/chunk-0gz36akr.js.map +0 -12
  419. package/dist/cli/chunk-2n4ps1b3.js.map +0 -15
  420. package/dist/cli/chunk-43zcf4gz.js.map +0 -36
  421. package/dist/cli/chunk-4ejxbzee.js +0 -39
  422. package/dist/cli/chunk-4ejxbzee.js.map +0 -10
  423. package/dist/cli/chunk-4h8z9vv5.js.map +0 -16
  424. package/dist/cli/chunk-713mngdq.js.map +0 -14
  425. package/dist/cli/chunk-9xr4dgee.js.map +0 -10
  426. package/dist/cli/chunk-amrb6hgh.js +0 -145
  427. package/dist/cli/chunk-amrb6hgh.js.map +0 -11
  428. package/dist/cli/chunk-nd1821sk.js.map +0 -10
  429. package/dist/cli/chunk-rekqz4qg.js.map +0 -10
  430. package/dist/cli/chunk-ta27feev.js.map +0 -10
  431. package/dist/cli/chunk-xkz5xbtv.js.map +0 -213
  432. package/dist/cli/chunk-y5h4r2y0.js.map +0 -10
  433. package/dist/cli/chunk-zf748avv.js.map +0 -37
  434. /package/dist/cli/{chunk-9geymqns.js.map → chunk-0w6hs479.js.map} +0 -0
  435. /package/dist/cli/{chunk-y4ykbark.js.map → chunk-1f882900.js.map} +0 -0
  436. /package/dist/cli/{chunk-py62fewh.js.map → chunk-53jqw8z0.js.map} +0 -0
  437. /package/dist/cli/{chunk-5wj2qwn2.js.map → chunk-58bt3hag.js.map} +0 -0
  438. /package/dist/cli/{chunk-e7vvk5ya.js.map → chunk-5cmts6dv.js.map} +0 -0
  439. /package/dist/cli/{chunk-g2z9x01v.js.map → chunk-9qzgg6mj.js.map} +0 -0
  440. /package/dist/cli/{chunk-q3wxxq39.js.map → chunk-a57yh0h9.js.map} +0 -0
  441. /package/dist/cli/{chunk-2f3ndkpw.js.map → chunk-desvm72z.js.map} +0 -0
  442. /package/dist/cli/{chunk-gp84za0h.js.map → chunk-dhwtqnnd.js.map} +0 -0
  443. /package/dist/cli/{chunk-2f7n4qzt.js.map → chunk-dqhg54mr.js.map} +0 -0
  444. /package/dist/cli/{chunk-zhvd6adm.js.map → chunk-gfc5fqvf.js.map} +0 -0
  445. /package/dist/cli/{chunk-p804f3pe.js.map → chunk-hvcxng5f.js.map} +0 -0
  446. /package/dist/cli/{chunk-1n228xqb.js.map → chunk-kdpzw38a.js.map} +0 -0
  447. /package/dist/cli/{chunk-6bm0xpgd.js.map → chunk-s0bdnc7v.js.map} +0 -0
  448. /package/dist/cli/{chunk-cmtcnh9f.js.map → chunk-tfycddbt.js.map} +0 -0
  449. /package/dist/cli/{chunk-ntv4qrt7.js.map → chunk-y4msrwm9.js.map} +0 -0
  450. /package/dist/cli/{chunk-yj17vs39.js.map → chunk-ydp3065p.js.map} +0 -0
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  import Description from "./Description.astro";
3
3
  import type { SchemaLike } from "./helpers.ts";
4
+ import type { SchemaDirection } from "./schema-tree.ts";
4
5
  import SchemaTable from "./SchemaTable.astro";
5
6
 
6
7
  interface MediaTypeLike {
@@ -19,9 +20,20 @@ interface Props {
19
20
  expandAll?: boolean;
20
21
  /** The heading's level: 2 on an operation, deeper inside a callback. */
21
22
  level?: number;
23
+ /**
24
+ * `request` (the default) leaves out `readOnly` fields; a webhook or
25
+ * callback, which the API sends, reads like a response instead.
26
+ */
27
+ direction?: SchemaDirection;
22
28
  }
23
29
 
24
- const { requestBody, schemas, expandAll = false, level = 2 } = Astro.props;
30
+ const {
31
+ requestBody,
32
+ schemas,
33
+ expandAll = false,
34
+ level = 2,
35
+ direction = "request",
36
+ } = Astro.props;
25
37
 
26
38
  const entries = Object.entries(requestBody.content ?? {});
27
39
  const chosen = entries.find(([type]) => type.includes("json")) ?? entries[0];
@@ -53,6 +65,11 @@ const schema = chosen?.[1]?.schema ?? {};
53
65
  )
54
66
  }
55
67
  <div class="mt-3">
56
- <SchemaTable expandAll={expandAll} schema={schema} schemas={schemas} />
68
+ <SchemaTable
69
+ direction={direction}
70
+ expandAll={expandAll}
71
+ schema={schema}
72
+ schemas={schemas}
73
+ />
57
74
  </div>
58
75
  </section>
@@ -64,6 +64,7 @@ const items = Object.entries(responses);
64
64
  {schema && (
65
65
  <div class="mt-3">
66
66
  <SchemaTable
67
+ direction="response"
67
68
  expandAll={expandAll}
68
69
  schema={schema}
69
70
  schemas={schemas}
@@ -1,6 +1,10 @@
1
1
  ---
2
2
  import type { SchemaLike } from "./helpers.ts";
3
- import { type SchemaNode, schemaTree } from "./schema-tree.ts";
3
+ import {
4
+ type SchemaDirection,
5
+ type SchemaNode,
6
+ schemaTree,
7
+ } from "./schema-tree.ts";
4
8
  import SchemaProperty from "./SchemaProperty.astro";
5
9
 
6
10
  interface Props {
@@ -10,13 +14,21 @@ interface Props {
10
14
  node?: SchemaNode;
11
15
  schemas: Record<string, SchemaLike>;
12
16
  expandAll?: boolean;
17
+ /** Which way the data travels, which decides the fields left out. */
18
+ direction?: SchemaDirection;
13
19
  }
14
20
 
15
- const { schema = {}, node: planned, schemas, expandAll = false } = Astro.props;
21
+ const {
22
+ schema = {},
23
+ node: planned,
24
+ schemas,
25
+ expandAll = false,
26
+ direction,
27
+ } = Astro.props;
16
28
 
17
29
  // The whole tree is planned once, at the top-level table, so that which named
18
30
  // schemas expand is decided for the tree as a whole (see `schema-tree.ts`).
19
- const node = planned ?? schemaTree(schema, schemas);
31
+ const node = planned ?? schemaTree(schema, schemas, direction);
20
32
  ---
21
33
 
22
34
  {
@@ -25,7 +25,12 @@ export interface MessageSample {
25
25
  address: string;
26
26
  /** Example payload value (undefined when none could be derived). */
27
27
  payload?: unknown;
28
- /** First server the channel is available on, if any. */
28
+ /** Example Kafka message key, when the message's binding declares one. */
29
+ key?: string;
30
+ /**
31
+ * First server the channel is available on, if any, its `security` entries
32
+ * resolved to scheme objects.
33
+ */
29
34
  server?: AsyncApiServerObject;
30
35
  }
31
36
 
@@ -98,12 +103,63 @@ const webSocketSnippet = (sample: MessageSample): string => {
98
103
  ].join("\n");
99
104
  };
100
105
 
106
+ /** librdkafka's `sasl.mechanisms` value for each AsyncAPI SASL scheme type. */
107
+ const SASL_MECHANISMS = new Map([
108
+ ["gssapi", "GSSAPI"],
109
+ ["plain", "PLAIN"],
110
+ ["scramSha256", "SCRAM-SHA-256"],
111
+ ["scramSha512", "SCRAM-SHA-512"],
112
+ ]);
113
+
114
+ /**
115
+ * The `-X` properties kcat hands librdkafka to reach the server: TLS for
116
+ * `kafka-secure`, and the first SASL scheme the server declares, with its
117
+ * credentials read from the environment (Kerberos brings its own).
118
+ */
119
+ const kafkaSecurityFlags = (server?: AsyncApiServerObject): string[] => {
120
+ const tls = server?.protocol?.toLowerCase() === "kafka-secure";
121
+ const mechanism = (server?.security ?? [])
122
+ .map((entry) => SASL_MECHANISMS.get(String(entry?.type)))
123
+ .find((value) => value !== undefined);
124
+ if (mechanism === undefined) {
125
+ return tls ? ["-X security.protocol=SSL"] : [];
126
+ }
127
+ const flags = [
128
+ `-X security.protocol=${tls ? "SASL_SSL" : "SASL_PLAINTEXT"}`,
129
+ `-X sasl.mechanisms=${mechanism}`,
130
+ ];
131
+ if (mechanism !== "GSSAPI") {
132
+ flags.push(
133
+ '-X sasl.username="$KAFKA_USERNAME"',
134
+ '-X sasl.password="$KAFKA_PASSWORD"'
135
+ );
136
+ }
137
+ return flags;
138
+ };
139
+
140
+ /**
141
+ * The separator between key and value: kcat splits each produced line at its
142
+ * first `|`, and prints consumed keys before one.
143
+ */
144
+ const KEY_DELIMITER = "|";
145
+
101
146
  const kcatSnippet = (sample: MessageSample): string => {
102
147
  const broker = sample.server?.host ?? "localhost:9092";
103
- const base = `kcat -b ${shellQuote(broker)} -t ${shellQuote(sample.address)}`;
104
- return sample.action === "receive"
105
- ? `echo ${shellQuote(payloadInline(sample))} | ${base} -P`
106
- : `${base} -C`;
148
+ const mode = sample.action === "receive" ? "-P" : "-C";
149
+ const keyed =
150
+ sample.key === undefined ? "" : ` -K ${shellQuote(KEY_DELIMITER)}`;
151
+ const command = [
152
+ `kcat -b ${shellQuote(broker)} -t ${shellQuote(sample.address)} ${mode}${keyed}`,
153
+ ...kafkaSecurityFlags(sample.server),
154
+ ].join(" \\\n ");
155
+ if (sample.action !== "receive") {
156
+ return command;
157
+ }
158
+ const line =
159
+ sample.key === undefined
160
+ ? payloadInline(sample)
161
+ : `${sample.key}${KEY_DELIMITER}${payloadInline(sample)}`;
162
+ return `echo ${shellQuote(line)} | ${command}`;
107
163
  };
108
164
 
109
165
  const mosquittoSnippet = (sample: MessageSample): string => {
@@ -8,6 +8,8 @@ import type {
8
8
  } from "../../openapi/asyncapi.ts";
9
9
  import type { ParameterLike, SchemaLike } from "./helpers.ts";
10
10
  import { resolveComponentRef } from "./helpers.ts";
11
+ import type { OperationSecurity, SecuritySchemeLike } from "./security.ts";
12
+ import { resolveAsyncApiSecurity } from "./security.ts";
11
13
 
12
14
  /**
13
15
  * Runtime helpers for the AsyncAPI components — the async counterpart of
@@ -239,32 +241,61 @@ export const channelParameters = (
239
241
 
240
242
  const SERVER_REF = /^#\/servers\/(?<name>[^/]+)$/u;
241
243
 
244
+ /** A server paired with its key under the document's `servers`. */
245
+ export interface NamedServer {
246
+ name: string;
247
+ server: AsyncApiServerObject;
248
+ }
249
+
242
250
  /**
243
- * The servers a channel is available on: its `servers` refs when declared,
244
- * else every server the document declares (the spec's default).
251
+ * The servers a channel is available on, by name: its `servers` refs when
252
+ * declared, else every server the document declares (the spec's default).
245
253
  */
246
- export const channelServers = (
254
+ export const namedChannelServers = (
247
255
  channel: AsyncApiChannelObject | undefined,
248
256
  document: AsyncApiDocument
249
- ): AsyncApiServerObject[] => {
257
+ ): NamedServer[] => {
250
258
  const all = document.servers ?? {};
251
259
  const refs = channel?.servers;
252
260
  if (!Array.isArray(refs) || refs.length === 0) {
253
- return Object.values(all).filter(isObject);
261
+ return Object.entries(all).flatMap(([name, server]) =>
262
+ isObject(server) ? [{ name, server }] : []
263
+ );
254
264
  }
255
- const servers: AsyncApiServerObject[] = [];
265
+ const servers: NamedServer[] = [];
256
266
  for (const ref of refs) {
257
- const name = SERVER_REF.exec(
267
+ const pointer = SERVER_REF.exec(
258
268
  isObject(ref) && isString(ref.$ref) ? ref.$ref : ""
259
269
  )?.groups?.name;
260
- const server = name === undefined ? undefined : all[unescapePointer(name)];
261
- if (isObject(server)) {
262
- servers.push(server);
270
+ const name = pointer === undefined ? undefined : unescapePointer(pointer);
271
+ const server = name === undefined ? undefined : all[name];
272
+ if (name !== undefined && isObject(server)) {
273
+ servers.push({ name, server });
263
274
  }
264
275
  }
265
276
  return servers;
266
277
  };
267
278
 
279
+ /**
280
+ * A server's `security` entries with their `$ref`s into
281
+ * `components.securitySchemes` resolved (non-objects dropped), for the
282
+ * samples, which read the scheme off the server they're built from.
283
+ */
284
+ export const resolvedServerSecurity = (
285
+ server: AsyncApiServerObject,
286
+ components?: Components
287
+ ): AsyncApiRefLike[] =>
288
+ (Array.isArray(server.security) ? server.security : [])
289
+ .filter(isObject)
290
+ .map((entry) => resolveComponentRef(entry, components, "securitySchemes"));
291
+
292
+ /** The servers a channel is available on; see {@link namedChannelServers}. */
293
+ export const channelServers = (
294
+ channel: AsyncApiChannelObject | undefined,
295
+ document: AsyncApiDocument
296
+ ): AsyncApiServerObject[] =>
297
+ namedChannelServers(channel, document).map(({ server }) => server);
298
+
268
299
  /** A protocol-keyed `bindings` map, whatever object it sits on. */
269
300
  type BindingMap = Record<string, AsyncApiSpecValue>;
270
301
 
@@ -291,6 +322,34 @@ export const resolveBindings = (
291
322
  return isObject(target) ? target : undefined;
292
323
  };
293
324
 
325
+ /** The `kafka` object of a bindings map, a `$ref`'d map resolved. */
326
+ const kafkaBinding = (
327
+ bindings: BindingMap | undefined,
328
+ components?: Components
329
+ ): Record<string, AsyncApiSpecValue> | undefined => {
330
+ const kafka = resolveBindings(bindings, components)?.kafka;
331
+ return isObject(kafka) ? kafka : undefined;
332
+ };
333
+
334
+ /**
335
+ * A Kafka channel binding's `topic`, which names the topic when it differs
336
+ * from the channel address. The samples produce to and consume from it.
337
+ */
338
+ export const kafkaTopic = (
339
+ channel: AsyncApiChannelObject | undefined,
340
+ components?: Components
341
+ ): string | undefined => {
342
+ const topic = kafkaBinding(channel?.bindings, components)?.topic;
343
+ return isString(topic) && topic !== "" ? topic : undefined;
344
+ };
345
+
346
+ /** The schema of a message's Kafka key (its `kafka` binding's `key`). */
347
+ export const kafkaKeySchema = (
348
+ message: AsyncApiMessageLike | undefined,
349
+ components?: Components
350
+ ): SchemaLike | undefined =>
351
+ schemaOf(kafkaBinding(message?.bindings, components)?.key);
352
+
294
353
  /** Normalize protocol spellings onto the binding key they document. */
295
354
  const PROTOCOL_ALIASES = {
296
355
  "kafka-secure": "kafka",
@@ -326,35 +385,70 @@ export const protocolOf = (
326
385
  };
327
386
 
328
387
  /**
329
- * The security list an operation actually enforces: its own `security` when
330
- * declared, else the union of its servers' — connecting already requires the
331
- * server's schemes. Server entries dedupe by `$ref`, so two servers sharing a
332
- * scheme render it once.
388
+ * The security an operation renders: its own `security` when declared, else
389
+ * the union of its servers' — connecting already requires the server's
390
+ * schemes. Server entries dedupe by `$ref`, so two servers sharing a scheme
391
+ * render it once. Each server's list stands alone, though: when the servers
392
+ * disagree (a production cluster behind SASL beside a local broker with no
393
+ * security), a scheme only some servers declare names them, and
394
+ * `unauthenticatedServers` lists the ones that declare none, rather than one
395
+ * server's scheme reading as required on all of them.
333
396
  */
334
- export const asyncApiSecurityEntries = (
397
+ export const asyncApiSecurity = (
335
398
  operation: AsyncApiOperationObject | undefined,
336
- servers: AsyncApiServerObject[]
337
- ): AsyncApiRefLike[] => {
399
+ servers: NamedServer[],
400
+ schemes: Record<string, SecuritySchemeLike> | undefined
401
+ ): OperationSecurity => {
338
402
  if (Array.isArray(operation?.security)) {
339
- return operation.security;
403
+ return resolveAsyncApiSecurity(operation.security, schemes);
340
404
  }
341
- const entries: AsyncApiRefLike[] = [];
342
- const seen = new Set<string>();
343
- for (const server of servers) {
344
- for (const entry of server.security ?? []) {
345
- if (!isObject(entry)) {
405
+ const entries: { entry: AsyncApiRefLike; servers: string[] }[] = [];
406
+ const byRef = new Map<string, string[]>();
407
+ const unauthenticated: string[] = [];
408
+ for (const { name, server } of servers) {
409
+ const declared = Array.isArray(server.security)
410
+ ? server.security.filter(isObject)
411
+ : [];
412
+ if (declared.length === 0) {
413
+ unauthenticated.push(name);
414
+ }
415
+ for (const entry of declared) {
416
+ const shared = isString(entry.$ref) ? byRef.get(entry.$ref) : undefined;
417
+ if (shared) {
418
+ shared.push(name);
346
419
  continue;
347
420
  }
421
+ const names = [name];
348
422
  if (isString(entry.$ref)) {
349
- if (seen.has(entry.$ref)) {
350
- continue;
351
- }
352
- seen.add(entry.$ref);
423
+ byRef.set(entry.$ref, names);
353
424
  }
354
- entries.push(entry);
425
+ entries.push({ entry, servers: names });
355
426
  }
356
427
  }
357
- return entries;
428
+ const agree =
429
+ entries.length === 0 ||
430
+ (unauthenticated.length === 0 &&
431
+ entries.every((item) => item.servers.length === servers.length));
432
+ if (agree) {
433
+ return resolveAsyncApiSecurity(
434
+ entries.map(({ entry }) => entry),
435
+ schemes
436
+ );
437
+ }
438
+ return {
439
+ // A scheme every server declares needs no server list of its own.
440
+ alternatives: entries.map(({ entry, servers: names }) =>
441
+ resolveAsyncApiSecurity([entry], schemes)
442
+ .alternatives.flat()
443
+ .map((resolved) =>
444
+ names.length === servers.length
445
+ ? resolved
446
+ : { ...resolved, servers: names }
447
+ )
448
+ ),
449
+ optional: false,
450
+ unauthenticatedServers: unauthenticated,
451
+ };
358
452
  };
359
453
 
360
454
  /** One protocol's binding fields, ready for a key/value table. */
@@ -10,8 +10,11 @@ import {
10
10
  isGraphqlOperationKind,
11
11
  } from "../../openapi/graphql.ts";
12
12
  import type { ApiSpecData } from "../../openapi/model.ts";
13
+ import { endpointSecurity } from "../content/api-page.ts";
13
14
  import type { SpecValue } from "./helpers.ts";
15
+ import { playgroundAuth } from "./operation-model.ts";
14
16
  import type { PlaygroundModel } from "./request.ts";
17
+ import type { OperationSecurity } from "./security.ts";
15
18
 
16
19
  /**
17
20
  * Build-time logic behind the GraphQL reference pages: the generated example
@@ -67,9 +70,10 @@ const isComposite = (document: GraphqlDocument, name: string): boolean => {
67
70
 
68
71
  /**
69
72
  * A valid selection set for a composite type, or undefined for leaves: every
70
- * scalar/enum field, plus nested composites while `depth` allows. A composite
71
- * with nothing selectable at this depth falls back to `__typename`, which is
72
- * legal on any composite — the set must never come out empty.
73
+ * scalar/enum field, plus nested composites while `depth` allows, deprecated
74
+ * fields left out so the example doesn't teach them. A composite with nothing
75
+ * selectable at this depth falls back to `__typename`, which is legal on any
76
+ * composite — the set must never come out empty.
73
77
  */
74
78
  export const selectionSet = (
75
79
  document: GraphqlDocument,
@@ -85,10 +89,12 @@ export const selectionSet = (
85
89
  }
86
90
  const selections: GraphqlSelection[] = [];
87
91
  for (const field of type.fields ?? []) {
88
- // A field with an argument that must be supplied — non-null and no
89
- // default — can't ride an example selection; there is nothing valid to
90
- // fill it with inline. A defaulted non-null argument is omittable.
92
+ // A deprecated field stays out of the example. So does a field with an
93
+ // argument that must be supplied — non-null and no default: there is
94
+ // nothing valid to fill it with inline. A defaulted non-null argument is
95
+ // omittable.
91
96
  if (
97
+ field.deprecationReason !== undefined ||
92
98
  field.args.some(
93
99
  (arg) => arg.type.display.endsWith("!") && arg.default === undefined
94
100
  )
@@ -189,10 +195,14 @@ const sampleForRef = (
189
195
  if (type?.kind === "enum") {
190
196
  named = type.enumValues?.[0]?.name ?? null;
191
197
  } else if (type?.kind === "input" && depth > 0) {
198
+ // A field with a default starts at it, the value a client leaving it
199
+ // out gets.
192
200
  named = Object.fromEntries(
193
201
  (type.inputFields ?? []).map((field) => [
194
202
  field.name,
195
- sampleForRef(document, field.type, depth - 1),
203
+ field.defaultValue === undefined
204
+ ? sampleForRef(document, field.type, depth - 1)
205
+ : field.defaultValue,
196
206
  ])
197
207
  );
198
208
  } else if (type?.kind === "input") {
@@ -203,7 +213,10 @@ const sampleForRef = (
203
213
  return wrapLists(ref.display, named);
204
214
  };
205
215
 
206
- /** Example `variables` for a root field's arguments; undefined when it has none. */
216
+ /**
217
+ * Example `variables` for a root field's arguments, each starting at its
218
+ * declared default when it has one; undefined when it has none.
219
+ */
207
220
  export const exampleVariables = (
208
221
  document: GraphqlDocument,
209
222
  field: GraphqlField
@@ -212,7 +225,9 @@ export const exampleVariables = (
212
225
  ? Object.fromEntries(
213
226
  field.args.map((arg) => [
214
227
  arg.name,
215
- sampleForRef(document, arg.type, VARIABLE_DEPTH),
228
+ arg.defaultValue === undefined
229
+ ? sampleForRef(document, arg.type, VARIABLE_DEPTH)
230
+ : arg.defaultValue,
216
231
  ])
217
232
  )
218
233
  : undefined;
@@ -271,19 +286,27 @@ export const exampleResponse = (
271
286
  return { data };
272
287
  };
273
288
 
289
+ /**
290
+ * The security every operation of a GraphQL reference enforces: its `auth`
291
+ * option, read the way a hand-written endpoint reads the site's `api.auth`.
292
+ */
293
+ export const graphqlSecurity = (spec: ApiSpecData): OperationSecurity =>
294
+ endpointSecurity(undefined, spec.auth);
295
+
274
296
  /**
275
297
  * The playground/request model for one GraphQL operation: a plain POST whose
276
298
  * JSON body carries the query and variables. Reusing `PlaygroundModel` means
277
299
  * the OpenAPI playground UI, its client module, and `buildRequest` all work
278
- * unchanged — the samples show byte-for-byte what the Send button transmits.
300
+ * unchanged — the samples show byte-for-byte what the Send button transmits,
301
+ * the configured `auth` credential included.
279
302
  */
280
303
  export const graphqlPlaygroundModel = (
281
304
  spec: ApiSpecData,
282
305
  query: string,
283
306
  variables?: GraphqlSampleObject
284
307
  ): PlaygroundModel => ({
285
- auth: [],
286
- authOptional: true,
308
+ auth: playgroundAuth(graphqlSecurity(spec)),
309
+ authOptional: false,
287
310
  body: {
288
311
  contentType: "application/json",
289
312
  example: JSON.stringify(
@@ -135,7 +135,23 @@ export const mergeParameters = (
135
135
  export const refName = (ref: string): string =>
136
136
  REF_PATTERN.exec(ref)?.groups?.name ?? ref.split("/").at(-1) ?? ref;
137
137
 
138
- /** Resolve one level of `$ref` against the document's component schemas. */
138
+ /**
139
+ * The one member of an `allOf` that only wraps it: `allOf: [{ $ref }]` beside
140
+ * a `description`, `readOnly`, or `default`, which is how drf-spectacular and
141
+ * other generators attach keywords a 3.0 `$ref` can't carry. `undefined` for
142
+ * a real composition: several members, or properties or branches of its own.
143
+ */
144
+ export const soleAllOfMember = (schema: SchemaLike): SchemaLike | undefined =>
145
+ schema.allOf?.length === 1 &&
146
+ !(schema.properties || schema.oneOf || schema.anyOf)
147
+ ? schema.allOf[0]
148
+ : undefined;
149
+
150
+ /**
151
+ * Resolve one level of `$ref` against the document's component schemas. A
152
+ * single-member `allOf` wrapper resolves like its member, with the wrapper's
153
+ * own keywords on top: its `description` is about this field.
154
+ */
139
155
  export const resolveSchema = (
140
156
  schemas: Record<string, SchemaLike>,
141
157
  schema?: SchemaLike
@@ -143,6 +159,11 @@ export const resolveSchema = (
143
159
  if (!schema) {
144
160
  return {};
145
161
  }
162
+ const member = soleAllOfMember(schema);
163
+ if (member) {
164
+ const { allOf: _wrapped, ...own } = schema;
165
+ return { ...resolveSchema(schemas, member), ...own };
166
+ }
146
167
  if (isString(schema.$ref)) {
147
168
  const name = REF_PATTERN.exec(schema.$ref)?.groups?.name;
148
169
  if (name && schemas[name]) {
@@ -152,6 +173,16 @@ export const resolveSchema = (
152
173
  return schema;
153
174
  };
154
175
 
176
+ /**
177
+ * A parameter's description: its own, else its schema's (resolved one `$ref`
178
+ * level), which is where generators like Elysia and oRPC write it.
179
+ */
180
+ export const parameterDescription = (
181
+ param: { description?: string; schema?: SchemaLike },
182
+ schemas: Record<string, SchemaLike>
183
+ ): string | undefined =>
184
+ param.description ?? resolveSchema(schemas, param.schema).description;
185
+
155
186
  const declaredTypeList = (type: string | string[] | undefined): string[] => {
156
187
  if (!type) {
157
188
  return [];
@@ -177,6 +208,8 @@ const isNullType = (schema: SchemaLike): boolean => {
177
208
  * (`Pet`, `Pet[]`) without resolving — which also means circular refs through
178
209
  * array items can't recurse forever. A `null` member stays out of a union's
179
210
  * label: rows mark it with {@link isNullable}, as they do `type: [T, "null"]`.
211
+ * A single-member `allOf` wrapper labels as its member; a real composition is
212
+ * an `object`.
180
213
  */
181
214
  export const typeLabel = (schema: SchemaLike): string => {
182
215
  if (isString(schema.$ref)) {
@@ -192,7 +225,8 @@ export const typeLabel = (schema: SchemaLike): string => {
192
225
  return [...new Set(labels)].join(" | ") || "any";
193
226
  }
194
227
  if (schema.allOf) {
195
- return "object";
228
+ const member = soleAllOfMember(schema);
229
+ return member ? typeLabel(member) : "object";
196
230
  }
197
231
  const types = nonNullTypes(schema.type);
198
232
  const arrayLabel = (): string => `${typeLabel(schema.items ?? {})}[]`;
@@ -1,10 +1,15 @@
1
1
  import type {
2
2
  AsyncApiAction,
3
+ AsyncApiDocument,
3
4
  AsyncApiServerObject,
4
5
  } from "../../openapi/asyncapi.ts";
5
6
  import { withServerDefaults } from "../../openapi/model.ts";
6
7
  import type { AsyncApiMessageLike, NamedMessage } from "./async.ts";
7
- import { payloadSchema } from "./async.ts";
8
+ import {
9
+ kafkaKeySchema,
10
+ payloadSchema,
11
+ resolvedServerSecurity,
12
+ } from "./async.ts";
8
13
  import { exampleValue, toJson } from "./helpers.ts";
9
14
  import type { ParameterLike, SchemaLike } from "./helpers.ts";
10
15
  import type {
@@ -76,14 +81,34 @@ const messagePayload = (
76
81
  };
77
82
  };
78
83
 
84
+ /**
85
+ * The first message's Kafka key as the kcat sample writes it: sampled from
86
+ * its binding's `key` schema the way a payload is (a declared example wins),
87
+ * a non-string value as JSON. None when the message declares no key.
88
+ */
89
+ const messageKey = (
90
+ message: AsyncApiMessageLike | undefined,
91
+ schemas: Record<string, SchemaLike>,
92
+ components: AsyncApiDocument["components"]
93
+ ): string | undefined => {
94
+ const schema = kafkaKeySchema(message, components);
95
+ const key = inputValue(schema ? exampleValue(schema, schemas) : null);
96
+ return key === "" ? undefined : key;
97
+ };
98
+
79
99
  /**
80
100
  * A server's base URL for the picker. Falls back to the bare host when the
81
101
  * spec omits `protocol` — a label is a label, and the snippet builders read
82
102
  * the server object itself rather than this string. Server variables in the
83
103
  * host and pathname (`{env}.events.example.com`) resolve to their declared
84
104
  * defaults, in the label and in the object the samples and connect URL read.
105
+ * Security refs resolve here too, so the kcat sample can name the server's
106
+ * SASL mechanism.
85
107
  */
86
- const serverOption = (spec: AsyncApiServerObject): MessageServerOption => {
108
+ const serverOption = (
109
+ spec: AsyncApiServerObject,
110
+ components: AsyncApiDocument["components"]
111
+ ): MessageServerOption => {
87
112
  const server = { ...spec };
88
113
  if (spec.host !== undefined) {
89
114
  server.host = withServerDefaults(spec.host, spec.variables);
@@ -91,6 +116,9 @@ const serverOption = (spec: AsyncApiServerObject): MessageServerOption => {
91
116
  if (spec.pathname !== undefined) {
92
117
  server.pathname = withServerDefaults(spec.pathname, spec.variables);
93
118
  }
119
+ if (spec.security !== undefined) {
120
+ server.security = resolvedServerSecurity(spec, components);
121
+ }
94
122
  const host = `${server.host ?? ""}${server.pathname ?? ""}`;
95
123
  return {
96
124
  label: server.protocol ? `${server.protocol}://${host}` : host,
@@ -102,17 +130,32 @@ const serverOption = (spec: AsyncApiServerObject): MessageServerOption => {
102
130
  export const messageModel = (args: {
103
131
  action: AsyncApiAction;
104
132
  address: string;
133
+ /** The document's `components`, which bindings and security refs resolve against. */
134
+ components?: AsyncApiDocument["components"];
105
135
  messages: NamedMessage[];
106
136
  parameters: ParameterLike[];
107
137
  protocol?: string;
108
138
  schemas: Record<string, SchemaLike>;
109
139
  servers: AsyncApiServerObject[];
110
- }): MessageModel => ({
111
- action: args.action,
112
- address: args.address,
113
- connectable: Object.hasOwn(LIVE_PROTOCOLS, args.protocol ?? ""),
114
- params: messageParams(args.parameters),
115
- payload: messagePayload(args.messages[0]?.message, args.schemas),
116
- protocol: args.protocol,
117
- servers: args.servers.map(serverOption),
118
- });
140
+ }): MessageModel => {
141
+ const model: MessageModel = {
142
+ action: args.action,
143
+ address: args.address,
144
+ connectable: Object.hasOwn(LIVE_PROTOCOLS, args.protocol ?? ""),
145
+ params: messageParams(args.parameters),
146
+ payload: messagePayload(args.messages[0]?.message, args.schemas),
147
+ protocol: args.protocol,
148
+ servers: args.servers.map((server) =>
149
+ serverOption(server, args.components)
150
+ ),
151
+ };
152
+ const key = messageKey(
153
+ args.messages[0]?.message,
154
+ args.schemas,
155
+ args.components
156
+ );
157
+ if (key !== undefined) {
158
+ model.key = key;
159
+ }
160
+ return model;
161
+ };