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.
- package/CHANGELOG.md +110 -0
- package/dist/cli/{chunk-ga0pf4aj.js → chunk-0n9xkp3d.js} +12 -3
- package/dist/cli/{chunk-ga0pf4aj.js.map → chunk-0n9xkp3d.js.map} +3 -3
- package/dist/cli/{chunk-43zcf4gz.js → chunk-0pmb4tr4.js} +541 -368
- package/dist/cli/chunk-0pmb4tr4.js.map +35 -0
- package/dist/cli/{chunk-9geymqns.js → chunk-0w6hs479.js} +15 -15
- package/dist/cli/{chunk-xkz5xbtv.js → chunk-124fvmzq.js} +2802 -1422
- package/dist/cli/chunk-124fvmzq.js.map +220 -0
- package/dist/cli/chunk-150jk7km.js +52 -0
- package/dist/cli/chunk-150jk7km.js.map +10 -0
- package/dist/cli/{chunk-y4ykbark.js → chunk-1f882900.js} +2 -2
- package/dist/cli/{chunk-5ffywsmb.js → chunk-297ajdcv.js} +8 -6
- package/dist/cli/{chunk-5ffywsmb.js.map → chunk-297ajdcv.js.map} +3 -3
- package/dist/cli/{chunk-h2a48yhd.js → chunk-32khwcb6.js} +120 -16
- package/dist/cli/{chunk-h2a48yhd.js.map → chunk-32khwcb6.js.map} +10 -10
- package/dist/cli/{chunk-5cg2rzgf.js → chunk-36bxs9c7.js} +20 -49
- package/dist/cli/{chunk-5cg2rzgf.js.map → chunk-36bxs9c7.js.map} +4 -5
- package/dist/cli/{chunk-py62fewh.js → chunk-53jqw8z0.js} +3 -3
- package/dist/cli/{chunk-5wj2qwn2.js → chunk-58bt3hag.js} +4 -4
- package/dist/cli/{chunk-e7vvk5ya.js → chunk-5cmts6dv.js} +3 -3
- package/dist/cli/{chunk-y5h4r2y0.js → chunk-60hz265r.js} +15 -5
- package/dist/cli/chunk-60hz265r.js.map +10 -0
- package/dist/cli/chunk-74wfhv79.js +65 -0
- package/dist/cli/chunk-74wfhv79.js.map +10 -0
- package/dist/cli/{chunk-g2z9x01v.js → chunk-9qzgg6mj.js} +3 -3
- package/dist/cli/{chunk-q3wxxq39.js → chunk-a57yh0h9.js} +5 -5
- package/dist/cli/{chunk-713mngdq.js → chunk-ave1wcbr.js} +76 -10
- package/dist/cli/chunk-ave1wcbr.js.map +14 -0
- package/dist/cli/{chunk-2n4ps1b3.js → chunk-bqxaqn5p.js} +40 -22
- package/dist/cli/chunk-bqxaqn5p.js.map +15 -0
- package/dist/cli/{chunk-jnwj5kjj.js → chunk-bxwhtvw8.js} +20 -7
- package/dist/cli/{chunk-jnwj5kjj.js.map → chunk-bxwhtvw8.js.map} +3 -3
- package/dist/cli/chunk-ckrcm08h.js +324 -0
- package/dist/cli/chunk-ckrcm08h.js.map +14 -0
- package/dist/cli/{chunk-2f3ndkpw.js → chunk-desvm72z.js} +3 -3
- package/dist/cli/{chunk-gp84za0h.js → chunk-dhwtqnnd.js} +2 -2
- package/dist/cli/{chunk-4h8z9vv5.js → chunk-dpy8qdjf.js} +93 -47
- package/dist/cli/chunk-dpy8qdjf.js.map +17 -0
- package/dist/cli/{chunk-2f7n4qzt.js → chunk-dqhg54mr.js} +1 -1
- package/dist/cli/{chunk-0gz36akr.js → chunk-dv2z0rzf.js} +21 -5
- package/dist/cli/chunk-dv2z0rzf.js.map +12 -0
- package/dist/cli/{chunk-cm89scdv.js → chunk-es8h0v3j.js} +9 -11
- package/dist/cli/{chunk-cm89scdv.js.map → chunk-es8h0v3j.js.map} +3 -3
- package/dist/cli/{chunk-zhvd6adm.js → chunk-gfc5fqvf.js} +14 -14
- package/dist/cli/{chunk-nd1821sk.js → chunk-gxtg6ed2.js} +33 -19
- package/dist/cli/chunk-gxtg6ed2.js.map +10 -0
- package/dist/cli/{chunk-p804f3pe.js → chunk-hvcxng5f.js} +6 -6
- package/dist/cli/{chunk-ta27feev.js → chunk-j1x92mx9.js} +21 -2
- package/dist/cli/chunk-j1x92mx9.js.map +10 -0
- package/dist/cli/{chunk-rekqz4qg.js → chunk-k3gr1nm9.js} +19 -16
- package/dist/cli/chunk-k3gr1nm9.js.map +10 -0
- package/dist/cli/{chunk-1n228xqb.js → chunk-kdpzw38a.js} +2 -2
- package/dist/cli/{chunk-cy5bm0j0.js → chunk-ms9z66nz.js} +2 -2
- package/dist/cli/{chunk-cy5bm0j0.js.map → chunk-ms9z66nz.js.map} +2 -2
- package/dist/cli/{chunk-zf748avv.js → chunk-nbyvgnnm.js} +193 -286
- package/dist/cli/chunk-nbyvgnnm.js.map +36 -0
- package/dist/cli/{chunk-6bm0xpgd.js → chunk-s0bdnc7v.js} +2 -2
- package/dist/cli/{chunk-yxmk4pec.js → chunk-sc93apfs.js} +17 -16
- package/dist/cli/{chunk-yxmk4pec.js.map → chunk-sc93apfs.js.map} +3 -3
- package/dist/cli/{chunk-cmtcnh9f.js → chunk-tfycddbt.js} +2 -2
- package/dist/cli/{chunk-9xr4dgee.js → chunk-twy7psdz.js} +29 -16
- package/dist/cli/chunk-twy7psdz.js.map +10 -0
- package/dist/cli/{chunk-ntv4qrt7.js → chunk-y4msrwm9.js} +15 -15
- package/dist/cli/{chunk-yj17vs39.js → chunk-ydp3065p.js} +5 -5
- package/dist/cli/index.js +24 -19
- package/dist/cli/index.js.map +3 -3
- package/dist/types/ai/ask-context.d.ts +6 -2
- package/dist/types/ai/ask.d.ts +24 -5
- package/dist/types/ai/component-markdown.d.ts +2 -0
- package/dist/types/ai/openapi-components.d.ts +4 -1
- package/dist/types/analytics/clics.d.ts +37 -0
- package/dist/types/analytics/index.d.ts +2 -0
- package/dist/types/analytics/schema.d.ts +18 -0
- package/dist/types/astro/integration.d.ts +11 -4
- package/dist/types/astro/markdown-negotiation.d.ts +3 -0
- package/dist/types/astro/pages.d.ts +10 -0
- package/dist/types/cli/init/scaffold.d.ts +1 -1
- package/dist/types/components/content/api-field.d.ts +4 -1
- package/dist/types/components/content/api-page.d.ts +6 -1
- package/dist/types/components/openapi/code-samples.d.ts +29 -0
- package/dist/types/components/openapi/helpers.d.ts +22 -1
- package/dist/types/components/openapi/security.d.ts +10 -0
- package/dist/types/components/openapi/snippets.d.ts +60 -0
- package/dist/types/core/changelog-index.d.ts +8 -0
- package/dist/types/core/config-input.d.ts +37 -6
- package/dist/types/core/data.d.ts +4 -0
- package/dist/types/core/i18n-ui.d.ts +2 -0
- package/dist/types/core/links.d.ts +8 -0
- package/dist/types/core/powered-by.d.ts +12 -0
- package/dist/types/core/probe.d.ts +2 -0
- package/dist/types/core/project-graph.d.ts +6 -0
- package/dist/types/core/redirect-patterns.d.ts +11 -3
- package/dist/types/core/schema.d.ts +228 -3
- package/dist/types/core/sources/cache.d.ts +3 -0
- package/dist/types/core/sources/contentful-rich-text.d.ts +11 -2
- package/dist/types/core/sources/contentful.d.ts +17 -1
- package/dist/types/core/sources/lexical.d.ts +5 -0
- package/dist/types/core/sources/lower.d.ts +10 -2
- package/dist/types/core/sources/normalize.d.ts +20 -1
- package/dist/types/core/sources/notion.d.ts +8 -0
- package/dist/types/core/sources/remote.d.ts +37 -10
- package/dist/types/core/sources/sanity.d.ts +1 -1
- package/dist/types/core/types.d.ts +17 -0
- package/dist/types/deploy/adapter-output.d.ts +2 -1
- package/dist/types/deploy/adapters/cloudflare.d.ts +7 -5
- package/dist/types/deploy/adapters/node.d.ts +58 -23
- package/dist/types/deploy/adapters/registry.d.ts +10 -0
- package/dist/types/deploy/adapters/types.d.ts +3 -2
- package/dist/types/deploy/cloudflare-negotiation.d.ts +5 -2
- package/dist/types/deploy/node-headers.d.ts +12 -4
- package/dist/types/deploy/platforms/cloudflare.d.ts +10 -7
- package/dist/types/deploy/platforms/node.d.ts +3 -1
- package/dist/types/deploy/platforms/types.d.ts +18 -7
- package/dist/types/deploy/platforms/vercel.d.ts +21 -2
- package/dist/types/deploy/redirects.d.ts +17 -1
- package/dist/types/deploy/sitemap.d.ts +2 -1
- package/dist/types/deploy/vercel-negotiation.d.ts +44 -21
- package/dist/types/narration/build.d.ts +34 -12
- package/dist/types/narration/provider.d.ts +96 -8
- package/dist/types/openapi/checks.d.ts +27 -0
- package/dist/types/openapi/graphql.d.ts +6 -0
- package/dist/types/openapi/model.d.ts +15 -4
- package/dist/types/openapi/parse.d.ts +3 -0
- package/dist/types/openapi/references.d.ts +16 -0
- package/dist/types/openapi/sentence.d.ts +11 -1
- package/dist/types/ratelimit/index.d.ts +1 -1
- package/dist/types/ratelimit/schema.d.ts +8 -0
- package/dist/types/ratelimit/upstash.d.ts +39 -14
- package/dist/types/reference/graphql.d.ts +76 -1
- package/dist/types/reference/index.d.ts +1 -1
- package/dist/types/reference/openapi.d.ts +2 -2
- package/dist/types/reference/options.d.ts +37 -1
- package/dist/types/reference/schema.d.ts +84 -0
- package/dist/types/search/adapters/registry.d.ts +3 -0
- package/dist/types/search/adapters/typesense.d.ts +14 -4
- package/dist/types/search/build.d.ts +3 -1
- package/dist/types/search/orama-index.d.ts +9 -9
- package/dist/types/search/sync/algolia.d.ts +5 -2
- package/dist/types/search/sync/index.d.ts +3 -1
- package/dist/types/search/sync/typesense.d.ts +11 -7
- package/dist/types/seo/jsonld.d.ts +11 -6
- package/dist/types/sources/contentful.d.ts +16 -0
- package/dist/types/sources/github-releases.d.ts +8 -1
- package/dist/types/sources/notion.d.ts +8 -0
- package/dist/types/sources/payload.d.ts +2 -0
- package/dist/types/sources/registry.d.ts +63 -0
- package/dist/types/sources/shared.d.ts +3 -0
- package/dist/types/sources/strapi.d.ts +2 -0
- package/docs/01-quickstart.mdx +4 -2
- package/docs/02-deployment.mdx +59 -13
- package/docs/03-upgrading.mdx +2 -1
- package/docs/04-migrating.mdx +9 -9
- package/docs/08-faq.mdx +12 -12
- package/docs/advanced/changelog.mdx +30 -2
- package/docs/advanced/custom-pages.mdx +1 -1
- package/docs/advanced/skills.mdx +1 -1
- package/docs/cli/audit.mdx +30 -7
- package/docs/cli/doctor.mdx +6 -2
- package/docs/cli/evals.mdx +4 -4
- package/docs/cli/translate.mdx +1 -0
- package/docs/cli/validate.mdx +4 -3
- package/docs/configuration/analytics.mdx +19 -1
- package/docs/configuration/assistant.mdx +6 -2
- package/docs/configuration/customization.mdx +4 -2
- package/docs/configuration/export.mdx +5 -3
- package/docs/configuration/index.mdx +4 -2
- package/docs/configuration/narration.mdx +43 -6
- package/docs/configuration/rate-limiting.mdx +23 -2
- package/docs/configuration/search.mdx +37 -14
- package/docs/content/components.mdx +2 -2
- package/docs/content/frontmatter.mdx +5 -3
- package/docs/content/i18n.mdx +2 -2
- package/docs/content/includes.mdx +1 -1
- package/docs/content/navigation.mdx +8 -6
- package/docs/content/sources/contentful.mdx +9 -4
- package/docs/content/sources/custom.mdx +7 -3
- package/docs/content/sources/github-releases.mdx +12 -2
- package/docs/content/sources/index.mdx +3 -3
- package/docs/content/sources/notion.mdx +17 -2
- package/docs/content/sources/obsidian.mdx +3 -1
- package/docs/content/sources/payload.mdx +5 -2
- package/docs/content/sources/remote-mdx.mdx +6 -0
- package/docs/content/sources/sanity.mdx +4 -2
- package/docs/content/sources/strapi.mdx +5 -2
- package/docs/content/syntax.mdx +2 -2
- package/docs/discoverability/agent-discovery.mdx +1 -1
- package/docs/discoverability/index.mdx +1 -1
- package/docs/discoverability/json-api.mdx +2 -0
- package/docs/discoverability/llms-txt.mdx +1 -1
- package/docs/discoverability/markdown.mdx +3 -1
- package/docs/discoverability/mcp.mdx +6 -0
- package/docs/discoverability/sitemap-and-robots.mdx +1 -1
- package/docs/discoverability/structured-data.mdx +8 -6
- package/docs/references/api-pages.mdx +1 -1
- package/docs/references/asyncapi.mdx +5 -1
- package/docs/references/graphql.mdx +15 -1
- package/docs/references/openapi.mdx +64 -8
- package/package.json +9 -9
- package/skills/blume/SKILL.md +1 -1
- package/skills/blume-migrate/SKILL.md +2 -2
- package/skills/blume-migrate/assets/{oxfmt@0.67.0.patch → oxfmt@0.71.0.patch} +7 -7
- package/skills/blume-migrate/references/docusaurus.md +4 -4
- package/skills/blume-migrate/references/fumadocs.md +17 -13
- package/skills/blume-migrate/references/monorepo.md +5 -5
- package/skills/blume-migrate/references/nextra.md +8 -5
- package/skills/blume-migrate/references/starlight.md +9 -7
- package/src/ai/ask-context.ts +33 -3
- package/src/ai/ask-limits.ts +13 -0
- package/src/ai/ask.ts +24 -6
- package/src/ai/changelog-markdown.ts +11 -6
- package/src/ai/component-markdown.ts +1 -1
- package/src/ai/cors.ts +12 -3
- package/src/ai/mcp/query.ts +14 -6
- package/src/ai/openapi-components.ts +28 -4
- package/src/ai/relative-links.ts +4 -38
- package/src/analytics/clics.ts +58 -0
- package/src/analytics/head.ts +5 -0
- package/src/analytics/index.ts +2 -0
- package/src/analytics/schema.ts +2 -0
- package/src/astro/generate.ts +91 -56
- package/src/astro/integration.ts +72 -22
- package/src/astro/markdown-negotiation.ts +3 -0
- package/src/astro/module-types.ts +3 -1
- package/src/astro/pages.ts +23 -0
- package/src/astro/render-deps.ts +10 -5
- package/src/astro/runtime-deps.ts +23 -2
- package/src/astro/templates.ts +129 -81
- package/src/audit/catalog.ts +19 -3
- package/src/audit/checks/links.ts +14 -1
- package/src/audit/checks/network.ts +110 -6
- package/src/audit/checks/redirects.ts +6 -4
- package/src/audit/checks/robots.ts +58 -2
- package/src/audit/run.ts +3 -0
- package/src/audit/types.ts +2 -0
- package/src/audit/url.ts +14 -5
- package/src/blume-modules.d.ts +5 -1
- package/src/cli/args.ts +51 -0
- package/src/cli/build-failure.ts +23 -0
- package/src/cli/commands/audit.ts +10 -1
- package/src/cli/commands/dev.ts +18 -2
- package/src/cli/commands/doctor.ts +45 -12
- package/src/cli/commands/eval.ts +36 -4
- package/src/cli/commands/init.ts +6 -4
- package/src/cli/commands/validate.ts +10 -1
- package/src/cli/init/scaffold.ts +9 -6
- package/src/cli/prepare.ts +6 -3
- package/src/cli/required-secrets.ts +3 -2
- package/src/components/content/ApiPlayground.astro +6 -2
- package/src/components/content/api-field.ts +4 -1
- package/src/components/content/api-page.ts +31 -7
- package/src/components/content/mermaid-element.ts +15 -1
- package/src/components/content/view-switcher.ts +7 -4
- package/src/components/islands/hooks.ts +27 -1
- package/src/components/layout/NavTree.astro +49 -5
- package/src/components/layout/NavTreeScript.astro +18 -0
- package/src/components/layout/PageActions.astro +139 -24
- package/src/components/layout/PageLayout.astro +13 -3
- package/src/components/layout/RootLayout.astro +27 -14
- package/src/components/layout/Search.astro +17 -3
- package/src/components/layout/TableOfContents.astro +24 -17
- package/src/components/layout/analytics-client.ts +8 -8
- package/src/components/layout/head-scripts.ts +6 -1
- package/src/components/layout/search/algolia.ts +10 -1
- package/src/components/layout/search/analytics.ts +42 -14
- package/src/components/layout/search/endpoint.ts +48 -5
- package/src/components/layout/search/pagefind.ts +114 -5
- package/src/components/layout/search/types.ts +12 -0
- package/src/components/layout/search/typesense.ts +18 -6
- package/src/components/openapi/AsyncApiOperation.astro +14 -7
- package/src/components/openapi/Authorization.astro +10 -0
- package/src/components/openapi/GraphqlOperation.astro +5 -0
- package/src/components/openapi/Operation.astro +24 -1
- package/src/components/openapi/ParametersTable.astro +8 -4
- package/src/components/openapi/Playground.astro +7 -1
- package/src/components/openapi/RequestBody.astro +19 -2
- package/src/components/openapi/Responses.astro +1 -0
- package/src/components/openapi/SchemaTable.astro +15 -3
- package/src/components/openapi/async-snippets.ts +61 -5
- package/src/components/openapi/async.ts +123 -29
- package/src/components/openapi/graphql-helpers.ts +35 -12
- package/src/components/openapi/helpers.ts +36 -2
- package/src/components/openapi/message-model.ts +54 -11
- package/src/components/openapi/message.ts +14 -4
- package/src/components/openapi/operation-model.ts +16 -7
- package/src/components/openapi/playground-client.ts +77 -58
- package/src/components/openapi/playground-schema.ts +1 -1
- package/src/components/openapi/schema-tree.ts +44 -14
- package/src/components/openapi/security.ts +10 -0
- package/src/components/openapi/snippets.ts +5 -3
- package/src/components/openapi/validate-json.ts +4 -3
- package/src/components/powered-by-middleware.ts +33 -0
- package/src/core/changelog-index.ts +31 -1
- package/src/core/component-diagnostics.ts +53 -0
- package/src/core/component-overrides.ts +32 -0
- package/src/core/config-input.ts +42 -6
- package/src/core/data.ts +2 -0
- package/src/core/diagnostics.ts +5 -0
- package/src/core/i18n-ui.ts +2 -0
- package/src/core/includes.ts +1 -1
- package/src/core/links.ts +47 -17
- package/src/core/powered-by.ts +12 -0
- package/src/core/probe.ts +26 -6
- package/src/core/project-graph.ts +59 -18
- package/src/core/redirect-patterns.ts +36 -7
- package/src/core/schema.ts +26 -6
- package/src/core/sources/cache.ts +6 -0
- package/src/core/sources/contentful-rich-text.ts +29 -6
- package/src/core/sources/contentful.ts +135 -25
- package/src/core/sources/filesystem.ts +26 -4
- package/src/core/sources/github-releases.ts +12 -1
- package/src/core/sources/lexical.ts +15 -10
- package/src/core/sources/lower.ts +19 -3
- package/src/core/sources/mdx-remote.ts +62 -10
- package/src/core/sources/normalize.ts +227 -41
- package/src/core/sources/notion.ts +34 -10
- package/src/core/sources/obsidian.ts +16 -3
- package/src/core/sources/payload.ts +38 -15
- package/src/core/sources/remote.ts +72 -15
- package/src/core/sources/resolve.ts +11 -1
- package/src/core/sources/sanity.ts +43 -25
- package/src/core/sources/strapi.ts +2 -2
- package/src/core/types.ts +18 -0
- package/src/core/ui-packs/ar.ts +1 -0
- package/src/core/ui-packs/bg.ts +1 -0
- package/src/core/ui-packs/bn.ts +1 -0
- package/src/core/ui-packs/ca.ts +1 -0
- package/src/core/ui-packs/cs.ts +1 -0
- package/src/core/ui-packs/da.ts +1 -0
- package/src/core/ui-packs/de.ts +1 -0
- package/src/core/ui-packs/el.ts +1 -0
- package/src/core/ui-packs/es.ts +1 -0
- package/src/core/ui-packs/fa.ts +1 -0
- package/src/core/ui-packs/fi.ts +1 -0
- package/src/core/ui-packs/fr.ts +1 -0
- package/src/core/ui-packs/he.ts +1 -0
- package/src/core/ui-packs/hi.ts +1 -0
- package/src/core/ui-packs/hr.ts +1 -0
- package/src/core/ui-packs/hu.ts +1 -0
- package/src/core/ui-packs/id.ts +1 -0
- package/src/core/ui-packs/it.ts +1 -0
- package/src/core/ui-packs/ja.ts +1 -0
- package/src/core/ui-packs/ko.ts +1 -0
- package/src/core/ui-packs/nl.ts +1 -0
- package/src/core/ui-packs/no.ts +1 -0
- package/src/core/ui-packs/pl.ts +1 -0
- package/src/core/ui-packs/pt-br.ts +1 -0
- package/src/core/ui-packs/pt.ts +1 -0
- package/src/core/ui-packs/ro.ts +1 -0
- package/src/core/ui-packs/ru.ts +1 -0
- package/src/core/ui-packs/sk.ts +1 -0
- package/src/core/ui-packs/sr.ts +1 -0
- package/src/core/ui-packs/sv.ts +1 -0
- package/src/core/ui-packs/th.ts +1 -0
- package/src/core/ui-packs/tr.ts +1 -0
- package/src/core/ui-packs/uk.ts +1 -0
- package/src/core/ui-packs/vi.ts +1 -0
- package/src/core/ui-packs/zh-tw.ts +1 -0
- package/src/core/ui-packs/zh.ts +1 -0
- package/src/deploy/adapter-output.ts +7 -2
- package/src/deploy/adapters/cloudflare.ts +7 -5
- package/src/deploy/adapters/node.ts +47 -9
- package/src/deploy/adapters/types.ts +7 -3
- package/src/deploy/artifacts.ts +2 -1
- package/src/deploy/cloudflare-negotiation.ts +36 -7
- package/src/deploy/headers.ts +15 -1
- package/src/deploy/node-headers.ts +32 -20
- package/src/deploy/platforms/cloudflare.ts +14 -9
- package/src/deploy/platforms/netlify.ts +2 -1
- package/src/deploy/platforms/node.ts +12 -2
- package/src/deploy/platforms/types.ts +21 -7
- package/src/deploy/platforms/vercel.ts +115 -17
- package/src/deploy/redirects.ts +66 -6
- package/src/deploy/rss.ts +3 -1
- package/src/deploy/sitemap.ts +39 -5
- package/src/deploy/vercel-negotiation.ts +325 -103
- package/src/eval/agents.ts +18 -1
- package/src/eval/prompts.ts +6 -3
- package/src/eval/report.ts +34 -13
- package/src/eval/run.ts +5 -0
- package/src/markdown/base-links.ts +15 -14
- package/src/markdown/package-commands.ts +9 -8
- package/src/markdown/relative-links.ts +3 -2
- package/src/narration/build.ts +218 -40
- package/src/narration/provider.ts +89 -9
- package/src/openapi/checks.ts +273 -0
- package/src/openapi/graphql-build.ts +21 -0
- package/src/openapi/graphql.ts +11 -0
- package/src/openapi/model.ts +15 -3
- package/src/openapi/parse.ts +127 -2
- package/src/openapi/references.ts +43 -3
- package/src/openapi/render-mdx.ts +68 -8
- package/src/openapi/sentence.ts +29 -2
- package/src/openapi/source.ts +39 -14
- package/src/ratelimit/index.ts +1 -1
- package/src/ratelimit/runtime.ts +37 -19
- package/src/ratelimit/upstash.ts +40 -10
- package/src/reference/graphql.ts +15 -1
- package/src/reference/index.ts +1 -0
- package/src/reference/openapi.ts +2 -2
- package/src/reference/options.ts +29 -1
- package/src/registry/eject.ts +8 -2
- package/src/search/adapters/locale-scope.ts +30 -0
- package/src/search/adapters/typesense.ts +14 -4
- package/src/search/build.ts +21 -3
- package/src/search/orama-index.ts +163 -31
- package/src/search/source-pages.ts +29 -0
- package/src/search/sync/algolia.ts +99 -9
- package/src/search/sync/index.ts +52 -13
- package/src/search/sync/typesense.ts +72 -27
- package/src/seo/jsonld.ts +38 -20
- package/src/sources/contentful.ts +12 -0
- package/src/sources/github-releases.ts +7 -1
- package/src/sources/notion.ts +7 -0
- package/src/sources/shared.ts +3 -0
- package/src/theme/color.ts +9 -10
- package/src/theme/entry.ts +43 -6
- package/src/translate/validate.ts +23 -1
- package/dist/cli/chunk-0gz36akr.js.map +0 -12
- package/dist/cli/chunk-2n4ps1b3.js.map +0 -15
- package/dist/cli/chunk-43zcf4gz.js.map +0 -36
- package/dist/cli/chunk-4ejxbzee.js +0 -39
- package/dist/cli/chunk-4ejxbzee.js.map +0 -10
- package/dist/cli/chunk-4h8z9vv5.js.map +0 -16
- package/dist/cli/chunk-713mngdq.js.map +0 -14
- package/dist/cli/chunk-9xr4dgee.js.map +0 -10
- package/dist/cli/chunk-amrb6hgh.js +0 -145
- package/dist/cli/chunk-amrb6hgh.js.map +0 -11
- package/dist/cli/chunk-nd1821sk.js.map +0 -10
- package/dist/cli/chunk-rekqz4qg.js.map +0 -10
- package/dist/cli/chunk-ta27feev.js.map +0 -10
- package/dist/cli/chunk-xkz5xbtv.js.map +0 -213
- package/dist/cli/chunk-y5h4r2y0.js.map +0 -10
- package/dist/cli/chunk-zf748avv.js.map +0 -37
- /package/dist/cli/{chunk-9geymqns.js.map → chunk-0w6hs479.js.map} +0 -0
- /package/dist/cli/{chunk-y4ykbark.js.map → chunk-1f882900.js.map} +0 -0
- /package/dist/cli/{chunk-py62fewh.js.map → chunk-53jqw8z0.js.map} +0 -0
- /package/dist/cli/{chunk-5wj2qwn2.js.map → chunk-58bt3hag.js.map} +0 -0
- /package/dist/cli/{chunk-e7vvk5ya.js.map → chunk-5cmts6dv.js.map} +0 -0
- /package/dist/cli/{chunk-g2z9x01v.js.map → chunk-9qzgg6mj.js.map} +0 -0
- /package/dist/cli/{chunk-q3wxxq39.js.map → chunk-a57yh0h9.js.map} +0 -0
- /package/dist/cli/{chunk-2f3ndkpw.js.map → chunk-desvm72z.js.map} +0 -0
- /package/dist/cli/{chunk-gp84za0h.js.map → chunk-dhwtqnnd.js.map} +0 -0
- /package/dist/cli/{chunk-2f7n4qzt.js.map → chunk-dqhg54mr.js.map} +0 -0
- /package/dist/cli/{chunk-zhvd6adm.js.map → chunk-gfc5fqvf.js.map} +0 -0
- /package/dist/cli/{chunk-p804f3pe.js.map → chunk-hvcxng5f.js.map} +0 -0
- /package/dist/cli/{chunk-1n228xqb.js.map → chunk-kdpzw38a.js.map} +0 -0
- /package/dist/cli/{chunk-6bm0xpgd.js.map → chunk-s0bdnc7v.js.map} +0 -0
- /package/dist/cli/{chunk-cmtcnh9f.js.map → chunk-tfycddbt.js.map} +0 -0
- /package/dist/cli/{chunk-ntv4qrt7.js.map → chunk-y4msrwm9.js.map} +0 -0
- /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 {
|
|
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
|
|
68
|
+
<SchemaTable
|
|
69
|
+
direction={direction}
|
|
70
|
+
expandAll={expandAll}
|
|
71
|
+
schema={schema}
|
|
72
|
+
schemas={schemas}
|
|
73
|
+
/>
|
|
57
74
|
</div>
|
|
58
75
|
</section>
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
import type { SchemaLike } from "./helpers.ts";
|
|
3
|
-
import {
|
|
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 {
|
|
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
|
-
/**
|
|
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
|
|
104
|
-
|
|
105
|
-
? `
|
|
106
|
-
|
|
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
|
|
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
|
|
254
|
+
export const namedChannelServers = (
|
|
247
255
|
channel: AsyncApiChannelObject | undefined,
|
|
248
256
|
document: AsyncApiDocument
|
|
249
|
-
):
|
|
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.
|
|
261
|
+
return Object.entries(all).flatMap(([name, server]) =>
|
|
262
|
+
isObject(server) ? [{ name, server }] : []
|
|
263
|
+
);
|
|
254
264
|
}
|
|
255
|
-
const servers:
|
|
265
|
+
const servers: NamedServer[] = [];
|
|
256
266
|
for (const ref of refs) {
|
|
257
|
-
const
|
|
267
|
+
const pointer = SERVER_REF.exec(
|
|
258
268
|
isObject(ref) && isString(ref.$ref) ? ref.$ref : ""
|
|
259
269
|
)?.groups?.name;
|
|
260
|
-
const
|
|
261
|
-
|
|
262
|
-
|
|
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
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
*
|
|
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
|
|
397
|
+
export const asyncApiSecurity = (
|
|
335
398
|
operation: AsyncApiOperationObject | undefined,
|
|
336
|
-
servers:
|
|
337
|
-
|
|
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
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
71
|
-
*
|
|
72
|
-
*
|
|
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
|
|
89
|
-
//
|
|
90
|
-
// fill it with inline. A defaulted non-null argument is
|
|
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
|
-
|
|
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
|
-
/**
|
|
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
|
-
|
|
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:
|
|
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
|
-
/**
|
|
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
|
-
|
|
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 {
|
|
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 = (
|
|
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
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
+
};
|