blume 2.0.3 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -0
- package/CHANGELOG.md +142 -0
- package/README.md +1 -1
- package/dist/cli/{chunk-5f86nr5m.js → chunk-073rdvgb.js} +21 -48
- package/dist/cli/{chunk-5f86nr5m.js.map → chunk-073rdvgb.js.map} +4 -5
- 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-150jk7km.js +52 -0
- package/dist/cli/chunk-150jk7km.js.map +10 -0
- package/dist/cli/{chunk-9t7a85s3.js → chunk-313vnn40.js} +30 -19
- package/dist/cli/chunk-313vnn40.js.map +10 -0
- package/dist/cli/{chunk-tkacnehg.js → chunk-3v3ffbrj.js} +2 -2
- package/dist/cli/{chunk-q58y5e6a.js → chunk-3x6x3pph.js} +46 -24
- package/dist/cli/chunk-3x6x3pph.js.map +10 -0
- package/dist/cli/{chunk-1d7ve1dm.js → chunk-42t4jxdx.js} +37 -5
- package/dist/cli/chunk-42t4jxdx.js.map +12 -0
- package/dist/cli/{chunk-8ktnccpt.js → chunk-54ztw1nj.js} +21 -2
- package/dist/cli/chunk-54ztw1nj.js.map +10 -0
- package/dist/cli/{chunk-hm3vjy5s.js → chunk-5vjtgs6e.js} +28 -10
- package/dist/cli/{chunk-hm3vjy5s.js.map → chunk-5vjtgs6e.js.map} +4 -4
- package/dist/cli/chunk-66w9j7p6.js +322 -0
- package/dist/cli/chunk-66w9j7p6.js.map +14 -0
- package/dist/cli/{chunk-2hsdwb9n.js → chunk-7ppf1rva.js} +34 -18
- package/dist/cli/chunk-7ppf1rva.js.map +10 -0
- package/dist/cli/{chunk-r9rcc4w7.js → chunk-8y2kmjv8.js} +7 -7
- package/dist/cli/{chunk-r20tn01b.js → chunk-c1y538kd.js} +8 -2
- package/dist/cli/{chunk-r20tn01b.js.map → chunk-c1y538kd.js.map} +3 -3
- package/dist/cli/{chunk-2eytanqx.js → chunk-c887fj0s.js} +2 -2
- package/dist/cli/{chunk-p3v96n38.js → chunk-cfyg47zg.js} +16 -6
- package/dist/cli/chunk-cfyg47zg.js.map +10 -0
- package/dist/cli/chunk-cm89scdv.js +443 -0
- package/dist/cli/chunk-cm89scdv.js.map +11 -0
- package/dist/cli/{chunk-akbpwfxc.js → chunk-dzwehpy7.js} +2 -2
- package/dist/cli/{chunk-wrr3j9w9.js → chunk-e6atmn4h.js} +299 -72
- package/dist/cli/chunk-e6atmn4h.js.map +36 -0
- package/dist/cli/{chunk-tzmab476.js → chunk-e8xw9qkh.js} +8 -6
- package/dist/cli/{chunk-tzmab476.js.map → chunk-e8xw9qkh.js.map} +3 -3
- package/dist/cli/{chunk-6dsbexzp.js → chunk-e9q7a2ak.js} +17 -15
- package/dist/cli/{chunk-6dsbexzp.js.map → chunk-e9q7a2ak.js.map} +2 -2
- package/dist/cli/{chunk-pv29h0wf.js → chunk-ehweg4fr.js} +5155 -1249
- package/dist/cli/chunk-ehweg4fr.js.map +218 -0
- package/dist/cli/{chunk-c8chx29p.js → chunk-ep6nd0rn.js} +390 -318
- package/dist/cli/chunk-ep6nd0rn.js.map +36 -0
- package/dist/cli/{chunk-p73c0m7w.js → chunk-fdrkhpjy.js} +18 -15
- package/dist/cli/{chunk-p73c0m7w.js.map → chunk-fdrkhpjy.js.map} +3 -3
- package/dist/cli/{chunk-2z928egk.js → chunk-ft9vfys6.js} +5 -5
- package/dist/cli/{chunk-5m5nmvyq.js → chunk-gb420vvz.js} +316 -79
- package/dist/cli/chunk-gb420vvz.js.map +17 -0
- package/dist/cli/{chunk-vg9r4eb9.js → chunk-hebn0tpx.js} +86 -13
- package/dist/cli/chunk-hebn0tpx.js.map +14 -0
- package/dist/cli/{chunk-35d4wj9f.js → chunk-htrwgabr.js} +41 -23
- package/dist/cli/chunk-htrwgabr.js.map +15 -0
- package/dist/cli/{chunk-g4hq16wv.js → chunk-hx3xqnk9.js} +16 -14
- package/dist/cli/{chunk-g4hq16wv.js.map → chunk-hx3xqnk9.js.map} +2 -2
- package/dist/cli/chunk-j134vrp2.js +65 -0
- package/dist/cli/chunk-j134vrp2.js.map +10 -0
- package/dist/cli/{chunk-a58773jm.js → chunk-kma9f6sf.js} +2 -2
- package/dist/cli/chunk-kwrg63tm.js +31 -0
- package/dist/cli/chunk-kwrg63tm.js.map +10 -0
- package/dist/cli/{chunk-ey84smr6.js → chunk-mrcccgnh.js} +6 -6
- package/dist/cli/{chunk-ey84smr6.js.map → chunk-mrcccgnh.js.map} +1 -1
- package/dist/cli/{chunk-yfyb25rh.js → chunk-n0v7m8ry.js} +24 -8
- package/dist/cli/chunk-n0v7m8ry.js.map +14 -0
- package/dist/cli/{chunk-j85vccga.js → chunk-ncj7w596.js} +576 -367
- package/dist/cli/chunk-ncj7w596.js.map +35 -0
- package/dist/cli/{chunk-5xvm6tfj.js → chunk-nq1d20w2.js} +17 -15
- package/dist/cli/{chunk-5xvm6tfj.js.map → chunk-nq1d20w2.js.map} +2 -2
- package/dist/cli/{chunk-pehfxfta.js → chunk-nrns10mj.js} +6 -98
- package/dist/cli/chunk-nrns10mj.js.map +10 -0
- package/dist/cli/{chunk-crgn1q09.js → chunk-sds923fa.js} +4 -4
- package/dist/cli/chunk-t2m5j4pr.js +104 -0
- package/dist/cli/chunk-t2m5j4pr.js.map +11 -0
- package/dist/cli/{chunk-acanzt5p.js → chunk-tdqhyxfz.js} +6 -6
- package/dist/cli/chunk-tphac74f.js +126 -0
- package/dist/cli/chunk-tphac74f.js.map +11 -0
- package/dist/cli/chunk-w1r4vase.js +18 -0
- package/dist/cli/chunk-w1r4vase.js.map +10 -0
- package/dist/cli/{chunk-3em5wd2y.js → chunk-zccbjcj0.js} +4 -3
- package/dist/cli/{chunk-3em5wd2y.js.map → chunk-zccbjcj0.js.map} +2 -2
- package/dist/cli/index.js +31 -20
- package/dist/cli/index.js.map +5 -5
- package/dist/types/ai/agent-surface.d.ts +8 -7
- package/dist/types/ai/ai-catalog.d.ts +7 -0
- package/dist/types/ai/ask-context.d.ts +26 -0
- package/dist/types/ai/ask.d.ts +271 -58
- package/dist/types/ai/component-markdown.d.ts +2 -0
- package/dist/types/ai/index.d.ts +2 -2
- package/dist/types/ai/openapi-components.d.ts +4 -1
- package/dist/types/ai/site-skill.d.ts +26 -0
- package/dist/types/ai/skills.d.ts +16 -0
- package/dist/types/astro/integration.d.ts +9 -0
- package/dist/types/astro/markdown-negotiation.d.ts +3 -0
- package/dist/types/astro/pages.d.ts +10 -0
- package/dist/types/captcha/hcaptcha.d.ts +27 -0
- package/dist/types/captcha/index.d.ts +28 -0
- package/dist/types/captcha/schema.d.ts +29 -0
- package/dist/types/captcha/turnstile.d.ts +28 -0
- package/dist/types/cli/init/scaffold.d.ts +1 -1
- package/dist/types/components/content/api-field.d.ts +62 -0
- package/dist/types/components/content/api-page.d.ts +100 -0
- package/dist/types/components/layout/nav-utils.d.ts +26 -0
- package/dist/types/components/openapi/code-samples.d.ts +29 -0
- package/dist/types/components/openapi/helpers.d.ts +158 -0
- package/dist/types/components/openapi/security.d.ts +95 -0
- package/dist/types/components/openapi/snippets.d.ts +60 -0
- package/dist/types/consent/ethyca.d.ts +48 -0
- package/dist/types/consent/index.d.ts +37 -0
- package/dist/types/consent/native.d.ts +28 -0
- package/dist/types/consent/osano.d.ts +42 -0
- package/dist/types/consent/schema.d.ts +110 -0
- package/dist/types/core/changelog-index.d.ts +8 -0
- package/dist/types/core/config-input.d.ts +217 -23
- package/dist/types/core/data.d.ts +53 -4
- package/dist/types/core/footer.d.ts +8 -0
- package/dist/types/core/i18n-ui.d.ts +88 -0
- package/dist/types/core/includes.d.ts +8 -2
- package/dist/types/core/links.d.ts +8 -0
- package/dist/types/core/localizable.d.ts +7 -0
- package/dist/types/core/page-modes.d.ts +29 -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 +152 -0
- package/dist/types/core/related.d.ts +40 -0
- package/dist/types/core/schema.d.ts +670 -56
- 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/normalize.d.ts +20 -1
- package/dist/types/core/sources/read.d.ts +5 -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 +18 -1
- package/dist/types/core/variables.d.ts +42 -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/node-headers.d.ts +13 -2
- package/dist/types/deploy/platforms/cloudflare.d.ts +15 -7
- package/dist/types/deploy/platforms/netlify.d.ts +7 -0
- 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 +26 -1
- package/dist/types/deploy/redirects.d.ts +55 -11
- package/dist/types/deploy/sitemap.d.ts +2 -1
- package/dist/types/deploy/vercel-negotiation.d.ts +51 -21
- package/dist/types/markdown/code-title.d.ts +17 -0
- package/dist/types/markdown/features.d.ts +3 -2
- package/dist/types/narration/build.d.ts +70 -0
- package/dist/types/narration/provider.d.ts +26 -0
- package/dist/types/narration/script.d.ts +154 -0
- 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 +27 -10
- package/dist/types/openapi/overlay.d.ts +54 -0
- package/dist/types/openapi/parse.d.ts +16 -0
- package/dist/types/openapi/references.d.ts +30 -4
- package/dist/types/ratelimit/cloudflare.d.ts +39 -0
- package/dist/types/ratelimit/index.d.ts +27 -0
- package/dist/types/ratelimit/memory.d.ts +36 -0
- package/dist/types/ratelimit/schema.d.ts +119 -0
- package/dist/types/ratelimit/upstash.d.ts +46 -0
- package/dist/types/ratelimit/wrangler.d.ts +23 -0
- package/dist/types/reference/asyncapi.d.ts +10 -10
- package/dist/types/reference/graphql.d.ts +89 -11
- package/dist/types/reference/index.d.ts +1 -1
- package/dist/types/reference/openapi.d.ts +33 -12
- package/dist/types/reference/options.d.ts +82 -6
- package/dist/types/reference/scalar.d.ts +13 -0
- package/dist/types/reference/schema.d.ts +144 -36
- 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/documents.d.ts +12 -1
- package/dist/types/search/orama-index.d.ts +13 -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/metatags.d.ts +20 -0
- package/dist/types/sources/contentful.d.ts +16 -0
- package/dist/types/sources/github-releases.d.ts +8 -1
- package/dist/types/sources/payload.d.ts +2 -0
- package/dist/types/sources/registry.d.ts +54 -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 +71 -17
- package/docs/03-upgrading.mdx +4 -4
- package/docs/04-migrating.mdx +1 -1
- package/docs/advanced/changelog.mdx +13 -2
- package/docs/advanced/skills.mdx +15 -1
- package/docs/cli/audit.mdx +51 -8
- package/docs/cli/doctor.mdx +5 -1
- package/docs/cli/evals.mdx +4 -4
- package/docs/cli/index.mdx +1 -0
- package/docs/cli/translate.mdx +1 -0
- package/docs/cli/validate.mdx +4 -3
- package/docs/configuration/analytics.mdx +3 -1
- package/docs/configuration/assistant.mdx +194 -38
- package/docs/configuration/consent.mdx +100 -0
- package/docs/configuration/customization.mdx +8 -6
- package/docs/configuration/export.mdx +5 -3
- package/docs/configuration/index.mdx +64 -5
- package/docs/configuration/meta.ts +3 -0
- package/docs/configuration/narration.mdx +119 -0
- package/docs/configuration/rate-limiting.mdx +90 -0
- package/docs/configuration/search.mdx +63 -12
- package/docs/configuration/theming.mdx +3 -1
- package/docs/content/components.mdx +108 -2
- package/docs/content/frontmatter.mdx +80 -2
- package/docs/content/i18n.mdx +39 -4
- package/docs/content/includes.mdx +16 -0
- package/docs/content/meta.mdx +1 -0
- package/docs/content/meta.ts +1 -0
- package/docs/content/navigation.mdx +32 -10
- package/docs/content/sources/contentful.mdx +35 -0
- package/docs/content/sources/custom.mdx +43 -0
- package/docs/content/sources/github-releases.mdx +39 -0
- package/docs/content/sources/index.mdx +91 -0
- package/docs/content/sources/meta.ts +16 -0
- package/docs/content/sources/notion.mdx +32 -0
- package/docs/content/sources/obsidian.mdx +37 -0
- package/docs/content/sources/payload.mdx +31 -0
- package/docs/content/sources/remote-mdx.mdx +44 -0
- package/docs/content/sources/sanity.mdx +29 -0
- package/docs/content/sources/strapi.mdx +32 -0
- package/docs/content/syntax.mdx +69 -4
- package/docs/content/variables.mdx +41 -0
- package/docs/discoverability/agent-discovery.mdx +29 -2
- package/docs/discoverability/index.mdx +2 -2
- package/docs/discoverability/json-api.mdx +2 -0
- package/docs/discoverability/llms-txt.mdx +2 -2
- package/docs/discoverability/markdown.mdx +3 -1
- package/docs/discoverability/mcp.mdx +4 -0
- package/docs/discoverability/metadata.mdx +17 -0
- package/docs/discoverability/sitemap-and-robots.mdx +1 -1
- package/docs/references/api-pages.mdx +74 -0
- package/docs/references/asyncapi.mdx +4 -2
- package/docs/references/graphql.mdx +14 -2
- package/docs/references/meta.ts +1 -1
- package/docs/references/openapi.mdx +148 -7
- package/docs/references/scalar.mdx +3 -1
- package/package.json +43 -8
- package/skills/blume/SKILL.md +3 -0
- package/skills/blume-migrate/SKILL.md +6 -6
- package/skills/blume-migrate/references/docusaurus.md +7 -7
- package/skills/blume-migrate/references/fumadocs.md +17 -13
- package/skills/blume-migrate/references/mintlify.md +37 -19
- package/skills/blume-migrate/references/nextra.md +10 -7
- package/skills/blume-migrate/references/starlight.md +11 -8
- package/skills/blume-migrate/scripts/mintlify-codemod.mjs +60 -14
- package/skills/blume-write-skill/SKILL.md +82 -0
- package/src/ai/agent-readability.ts +2 -1
- package/src/ai/agent-surface.ts +9 -7
- package/src/ai/ai-catalog.ts +6 -3
- package/src/ai/ask-context.ts +103 -20
- package/src/ai/ask-data.ts +6 -0
- package/src/ai/ask-limits.ts +13 -0
- package/src/ai/ask-tools.ts +142 -0
- package/src/ai/ask.ts +354 -76
- package/src/ai/changelog-markdown.ts +11 -6
- package/src/ai/component-markdown.ts +76 -1
- package/src/ai/cors.ts +14 -3
- package/src/ai/index.ts +12 -0
- package/src/ai/llms.ts +6 -2
- package/src/ai/markdown.ts +2 -1
- package/src/ai/mcp/data.ts +6 -0
- package/src/ai/mcp/query.ts +14 -6
- package/src/ai/openapi-components.ts +36 -6
- package/src/ai/relative-links.ts +4 -38
- package/src/ai/site-skill.ts +274 -0
- package/src/ai/skills.ts +35 -2
- package/src/ai/write-skill.ts +97 -0
- package/src/astro/generate.ts +210 -66
- package/src/astro/index.ts +1 -0
- package/src/astro/integration.ts +42 -4
- package/src/astro/markdown-negotiation.ts +3 -0
- package/src/astro/module-types.ts +9 -1
- package/src/astro/pages.ts +23 -0
- package/src/astro/templates.ts +406 -108
- package/src/astro/variables.ts +31 -0
- package/src/audit/catalog.ts +38 -3
- package/src/audit/checks/contrast.ts +183 -0
- package/src/audit/checks/i18n.ts +2 -3
- package/src/audit/checks/indexability.ts +2 -3
- package/src/audit/checks/links.ts +19 -13
- 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/checks/sitemap.ts +2 -3
- package/src/audit/redirects.ts +46 -15
- package/src/audit/run.ts +5 -0
- package/src/audit/types.ts +4 -1
- package/src/audit/url.ts +14 -5
- package/src/blume-modules.d.ts +12 -1
- package/src/captcha/client.ts +152 -0
- package/src/captcha/hcaptcha.ts +36 -0
- package/src/captcha/index.ts +28 -0
- package/src/captcha/schema.ts +32 -0
- package/src/captcha/turnstile.ts +38 -0
- package/src/captcha/verify.ts +71 -0
- package/src/cli/args.ts +51 -0
- package/src/cli/build-failure.ts +23 -0
- package/src/cli/command-meta.ts +5 -0
- package/src/cli/commands/audit.ts +10 -1
- package/src/cli/commands/dev.ts +18 -2
- package/src/cli/commands/doctor.ts +67 -28
- package/src/cli/commands/eval.ts +36 -4
- package/src/cli/commands/init.ts +6 -4
- package/src/cli/commands/skill.ts +96 -0
- package/src/cli/commands/validate.ts +10 -1
- package/src/cli/index.ts +5 -0
- package/src/cli/init/scaffold.ts +3 -3
- package/src/cli/prepare.ts +6 -3
- package/src/cli/required-secrets.ts +72 -30
- package/src/components/BlumePage.astro +2 -0
- package/src/components/content/ApiEndpoint.astro +18 -0
- package/src/components/content/ApiField.astro +79 -0
- package/src/components/content/ApiPlayground.astro +66 -0
- package/src/components/content/ApiRail.astro +19 -0
- package/src/components/content/Color.astro +1 -0
- package/src/components/content/FileTree.astro +1 -0
- package/src/components/content/GithubInfo.astro +1 -0
- package/src/components/content/Panel.astro +1 -0
- package/src/components/content/ParamField.astro +25 -0
- package/src/components/content/RequestExample.astro +17 -0
- package/src/components/content/ResponseExample.astro +17 -0
- package/src/components/content/ResponseField.astro +32 -0
- package/src/components/content/Step.astro +1 -0
- package/src/components/content/Tile.astro +1 -0
- package/src/components/content/Tooltip.astro +1 -0
- package/src/components/content/Tree.astro +1 -0
- package/src/components/content/TypeTable.astro +4 -1
- package/src/components/content/View.astro +21 -0
- package/src/components/content/ViewSwitcher.astro +168 -0
- package/src/components/content/api-field.ts +103 -0
- package/src/components/content/api-page.ts +248 -0
- package/src/components/content/mermaid-element.ts +15 -1
- package/src/components/content/view-switcher.ts +71 -0
- package/src/components/index.ts +2 -0
- package/src/components/islands/Assistant.astro +10 -1
- package/src/components/islands/assistant.tsx +104 -14
- package/src/components/islands/code-question.ts +62 -0
- package/src/components/islands/hooks.ts +136 -21
- package/src/components/islands/support-link.ts +68 -0
- package/src/components/layout/Analytics.astro +11 -2
- package/src/components/layout/Banner.astro +14 -10
- package/src/components/layout/Breadcrumbs.astro +6 -2
- package/src/components/layout/ConsentBanner.astro +62 -0
- package/src/components/layout/ConsentHead.astro +38 -0
- package/src/components/layout/Directory.astro +94 -0
- package/src/components/layout/DrawerSwitchers.astro +51 -0
- package/src/components/layout/Empty.astro +2 -2
- package/src/components/layout/Header.astro +122 -80
- package/src/components/layout/LanguageSwitcher.astro +48 -15
- package/src/components/layout/NarrationPlayer.astro +1085 -0
- package/src/components/layout/NavSelector.astro +33 -7
- package/src/components/layout/PageActions.astro +139 -24
- package/src/components/layout/PageFeedback.astro +54 -49
- package/src/components/layout/PageLayout.astro +71 -3
- package/src/components/layout/ReferenceLayout.astro +17 -6
- package/src/components/layout/RelatedPages.astro +42 -0
- package/src/components/layout/RootLayout.astro +318 -47
- package/src/components/layout/Search.astro +47 -19
- package/src/components/layout/SiteFooter.astro +124 -0
- package/src/components/layout/SiteMetatags.astro +16 -0
- package/src/components/layout/TableOfContents.astro +24 -17
- package/src/components/layout/consent/native.ts +79 -0
- package/src/components/layout/consent/types.ts +37 -0
- package/src/components/layout/footer-links.ts +53 -0
- package/src/components/layout/footer-socials.ts +87 -0
- package/src/components/layout/head-scripts.ts +6 -1
- package/src/components/layout/locale-redirect.ts +107 -0
- package/src/components/layout/nav-utils.ts +83 -0
- package/src/components/layout/page-feedback.ts +96 -0
- package/src/components/layout/search/algolia.ts +10 -1
- package/src/components/layout/search/analytics.ts +126 -0
- package/src/components/layout/search/endpoint.ts +48 -5
- package/src/components/layout/search/flexsearch.ts +17 -5
- package/src/components/layout/search/orama-cloud.ts +26 -14
- package/src/components/layout/search/pagefind.ts +114 -5
- package/src/components/layout/search/types.ts +32 -0
- package/src/components/layout/search/typesense.ts +19 -3
- 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 +184 -13
- package/src/components/openapi/ParametersTable.astro +8 -4
- package/src/components/openapi/Playground.astro +7 -1
- package/src/components/openapi/RequestBody.astro +24 -5
- package/src/components/openapi/RequestPanel.astro +59 -7
- package/src/components/openapi/Responses.astro +7 -4
- package/src/components/openapi/SchemaTable.astro +15 -3
- package/src/components/openapi/async-snippets.ts +65 -9
- package/src/components/openapi/async.ts +123 -29
- package/src/components/openapi/code-samples.ts +97 -0
- 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 +24 -5
- package/src/components/openapi/playground-schema.ts +1 -1
- package/src/components/openapi/schema-tree.ts +44 -14
- package/src/components/openapi/security.ts +16 -3
- package/src/components/openapi/snippets.ts +873 -10
- package/src/components/openapi/validate-json.ts +4 -3
- package/src/components/props.ts +6 -0
- package/src/consent/client.ts +95 -0
- package/src/consent/clients.ts +19 -0
- package/src/consent/ethyca.ts +71 -0
- package/src/consent/head.ts +24 -0
- package/src/consent/index.ts +37 -0
- package/src/consent/init.ts +29 -0
- package/src/consent/native.ts +36 -0
- package/src/consent/osano.ts +59 -0
- package/src/consent/schema.ts +30 -0
- package/src/core/builtin-tags.ts +5 -0
- package/src/core/changelog-index.ts +31 -1
- package/src/core/client-address.ts +19 -0
- package/src/core/component-diagnostics.ts +53 -0
- package/src/core/component-overrides.ts +32 -0
- package/src/core/config-input.ts +225 -23
- package/src/core/data.ts +46 -4
- package/src/core/diagnostics.ts +8 -2
- package/src/core/footer.ts +26 -0
- package/src/core/graph.ts +39 -36
- package/src/core/i18n-ui.ts +84 -2
- package/src/core/includes.ts +21 -4
- package/src/core/links.ts +63 -19
- package/src/core/localizable.ts +26 -0
- package/src/core/navigation.ts +43 -12
- package/src/core/page-modes.ts +56 -0
- package/src/core/probe.ts +26 -6
- package/src/core/project-graph.ts +163 -16
- package/src/core/redirect-patterns.ts +520 -0
- package/src/core/related.ts +131 -0
- package/src/core/schema.ts +339 -66
- 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/mdx-remote.ts +62 -10
- package/src/core/sources/normalize.ts +228 -41
- package/src/core/sources/notion.ts +7 -1
- package/src/core/sources/obsidian.ts +16 -3
- package/src/core/sources/payload.ts +38 -15
- package/src/core/sources/read.ts +8 -3
- 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 +19 -1
- package/src/core/ui-packs/ar.ts +44 -0
- package/src/core/ui-packs/bg.ts +46 -0
- package/src/core/ui-packs/bn.ts +44 -0
- package/src/core/ui-packs/ca.ts +47 -0
- package/src/core/ui-packs/cs.ts +45 -0
- package/src/core/ui-packs/da.ts +46 -0
- package/src/core/ui-packs/de.ts +47 -0
- package/src/core/ui-packs/el.ts +46 -0
- package/src/core/ui-packs/es.ts +47 -0
- package/src/core/ui-packs/fa.ts +46 -0
- package/src/core/ui-packs/fi.ts +46 -0
- package/src/core/ui-packs/fr.ts +47 -0
- package/src/core/ui-packs/he.ts +44 -0
- package/src/core/ui-packs/hi.ts +45 -0
- package/src/core/ui-packs/hr.ts +46 -0
- package/src/core/ui-packs/hu.ts +45 -0
- package/src/core/ui-packs/id.ts +46 -0
- package/src/core/ui-packs/it.ts +46 -0
- package/src/core/ui-packs/ja.ts +46 -0
- package/src/core/ui-packs/ko.ts +45 -0
- package/src/core/ui-packs/nl.ts +47 -0
- package/src/core/ui-packs/no.ts +45 -0
- package/src/core/ui-packs/pl.ts +46 -0
- package/src/core/ui-packs/pt-br.ts +47 -0
- package/src/core/ui-packs/pt.ts +46 -0
- package/src/core/ui-packs/ro.ts +46 -0
- package/src/core/ui-packs/ru.ts +46 -0
- package/src/core/ui-packs/sk.ts +45 -0
- package/src/core/ui-packs/sr.ts +46 -0
- package/src/core/ui-packs/sv.ts +45 -0
- package/src/core/ui-packs/th.ts +44 -0
- package/src/core/ui-packs/tr.ts +46 -0
- package/src/core/ui-packs/uk.ts +46 -0
- package/src/core/ui-packs/vi.ts +46 -0
- package/src/core/ui-packs/zh-tw.ts +44 -0
- package/src/core/ui-packs/zh.ts +44 -0
- package/src/core/variables.ts +103 -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 +79 -9
- package/src/deploy/cloudflare-negotiation.ts +35 -5
- package/src/deploy/headers.ts +2 -1
- package/src/deploy/node-headers.ts +63 -9
- package/src/deploy/platforms/cloudflare.ts +45 -9
- package/src/deploy/platforms/netlify.ts +35 -2
- package/src/deploy/platforms/node.ts +12 -2
- package/src/deploy/platforms/types.ts +21 -7
- package/src/deploy/platforms/vercel.ts +149 -17
- package/src/deploy/redirects.ts +151 -24
- package/src/deploy/rss.ts +3 -1
- package/src/deploy/sitemap.ts +39 -5
- package/src/deploy/vercel-negotiation.ts +326 -102
- 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/api-rail.ts +259 -0
- package/src/markdown/code-title.ts +35 -9
- package/src/markdown/features.ts +3 -2
- package/src/markdown/fence-meta.ts +2 -0
- package/src/markdown/include.ts +11 -1
- package/src/markdown/index.ts +28 -5
- package/src/markdown/math.ts +4 -4
- package/src/markdown/relative-links.ts +3 -2
- package/src/markdown/variables.ts +56 -0
- package/src/markdown/views.ts +82 -0
- package/src/narration/build.ts +412 -0
- package/src/narration/player.ts +249 -0
- package/src/narration/provider.ts +29 -0
- package/src/narration/script.ts +592 -0
- package/src/og/card.ts +7 -6
- 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 +72 -27
- package/src/openapi/overlay.ts +256 -0
- package/src/openapi/parse.ts +182 -4
- package/src/openapi/references.ts +64 -8
- package/src/openapi/render-mdx.ts +5 -1
- package/src/openapi/scalar.ts +40 -6
- package/src/openapi/source.ts +40 -15
- package/src/ratelimit/cloudflare.ts +54 -0
- package/src/ratelimit/index.ts +30 -0
- package/src/ratelimit/memory.ts +45 -0
- package/src/ratelimit/runtime.ts +247 -0
- package/src/ratelimit/schema.ts +28 -0
- package/src/ratelimit/upstash.ts +60 -0
- package/src/ratelimit/wrangler.ts +70 -0
- package/src/reference/asyncapi.ts +2 -2
- package/src/reference/graphql.ts +20 -3
- package/src/reference/index.ts +1 -0
- package/src/reference/openapi.ts +21 -7
- package/src/reference/options.ts +80 -8
- package/src/reference/scalar.ts +33 -8
- package/src/registry/eject.ts +23 -5
- package/src/registry/registry.ts +7 -0
- 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/documents.ts +26 -2
- package/src/search/orama-index.ts +191 -34
- package/src/search/pagefind-ranking.ts +39 -0
- package/src/search/source-pages.ts +29 -0
- package/src/search/sync/algolia.ts +111 -10
- package/src/search/sync/index.ts +52 -13
- package/src/search/sync/orama-cloud.ts +3 -0
- package/src/search/sync/typesense.ts +76 -26
- package/src/seo/metatags.ts +67 -0
- package/src/sources/contentful.ts +12 -0
- package/src/sources/github-releases.ts +7 -1
- package/src/sources/shared.ts +3 -0
- package/src/theme/chrome-icons.ts +1 -0
- package/src/theme/color.ts +500 -0
- package/src/theme/entry.ts +85 -6
- package/src/theme/palette.ts +121 -45
- package/src/translate/prompts.ts +1 -0
- package/src/translate/validate.ts +31 -3
- package/src/upgrade/upgrade.ts +4 -171
- package/dist/cli/chunk-1d7ve1dm.js.map +0 -12
- package/dist/cli/chunk-2hsdwb9n.js.map +0 -10
- package/dist/cli/chunk-35d4wj9f.js.map +0 -15
- package/dist/cli/chunk-364znk6q.js +0 -75
- package/dist/cli/chunk-364znk6q.js.map +0 -11
- package/dist/cli/chunk-5m5nmvyq.js.map +0 -13
- package/dist/cli/chunk-8ktnccpt.js.map +0 -10
- package/dist/cli/chunk-9t7a85s3.js.map +0 -10
- package/dist/cli/chunk-b07cmahc.js +0 -145
- package/dist/cli/chunk-b07cmahc.js.map +0 -11
- package/dist/cli/chunk-c8chx29p.js.map +0 -36
- package/dist/cli/chunk-e04dxsz1.js +0 -39
- package/dist/cli/chunk-e04dxsz1.js.map +0 -10
- package/dist/cli/chunk-j85vccga.js.map +0 -36
- package/dist/cli/chunk-p3v96n38.js.map +0 -10
- package/dist/cli/chunk-pehfxfta.js.map +0 -10
- package/dist/cli/chunk-pv29h0wf.js.map +0 -190
- package/dist/cli/chunk-q58y5e6a.js.map +0 -10
- package/dist/cli/chunk-vg9r4eb9.js.map +0 -14
- package/dist/cli/chunk-wrr3j9w9.js.map +0 -35
- package/dist/cli/chunk-yfyb25rh.js.map +0 -14
- package/docs/content/sources.mdx +0 -334
- /package/dist/cli/{chunk-tkacnehg.js.map → chunk-3v3ffbrj.js.map} +0 -0
- /package/dist/cli/{chunk-r9rcc4w7.js.map → chunk-8y2kmjv8.js.map} +0 -0
- /package/dist/cli/{chunk-2eytanqx.js.map → chunk-c887fj0s.js.map} +0 -0
- /package/dist/cli/{chunk-akbpwfxc.js.map → chunk-dzwehpy7.js.map} +0 -0
- /package/dist/cli/{chunk-2z928egk.js.map → chunk-ft9vfys6.js.map} +0 -0
- /package/dist/cli/{chunk-a58773jm.js.map → chunk-kma9f6sf.js.map} +0 -0
- /package/dist/cli/{chunk-crgn1q09.js.map → chunk-sds923fa.js.map} +0 -0
- /package/dist/cli/{chunk-acanzt5p.js.map → chunk-tdqhyxfz.js.map} +0 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import type { OperationObject } from "@scalar/openapi-types/3.2";
|
|
2
|
+
|
|
3
|
+
import type { ApiDocument } from "./model.ts";
|
|
4
|
+
import { HTTP_METHODS } from "./model.ts";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Targeted checks for spec mistakes that would otherwise render silently
|
|
8
|
+
* wrong. This is not a validator — a linter such as Spectral or oasdiff owns
|
|
9
|
+
* that — and a spec that fails one of these still renders. Each check names
|
|
10
|
+
* one mistake whose symptom on the page is quiet: a path placeholder sent
|
|
11
|
+
* as literal text, a Try it input whose value goes nowhere, an Authorization
|
|
12
|
+
* section with no scheme to describe. Each reports a warning with its own
|
|
13
|
+
* code, so a build says what's wrong instead of shipping it.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/** One mistake a check found, before the source names the spec it's in. */
|
|
17
|
+
export interface SpecIssue {
|
|
18
|
+
code: string;
|
|
19
|
+
message: string;
|
|
20
|
+
suggestion: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** A `{name}` placeholder in a path template. */
|
|
24
|
+
const PATH_TEMPLATE = /\{(?<name>[^{}]+)\}/gu;
|
|
25
|
+
|
|
26
|
+
/** A reference to a parameter declared under `components.parameters`. */
|
|
27
|
+
const PARAMETER_REF = /^#\/components\/parameters\/(?<name>[^/]+)$/u;
|
|
28
|
+
|
|
29
|
+
/** How many operations a security-scheme warning names before counting the rest. */
|
|
30
|
+
const NAMED_OPERATIONS = 3;
|
|
31
|
+
|
|
32
|
+
/** One entry of a document's `paths` or `webhooks` map. */
|
|
33
|
+
type PathItem = NonNullable<ApiDocument["paths"]>[string];
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* How a warning names an operation: `GET /pets`, or a webhook by its name
|
|
37
|
+
* (`Webhook "newPet" (POST)`), since a webhook has no path.
|
|
38
|
+
*/
|
|
39
|
+
export const operationLabel = (
|
|
40
|
+
name: string,
|
|
41
|
+
method: string,
|
|
42
|
+
webhook: boolean
|
|
43
|
+
): string =>
|
|
44
|
+
webhook
|
|
45
|
+
? `Webhook "${name}" (${method.toUpperCase()})`
|
|
46
|
+
: `${method.toUpperCase()} ${name}`;
|
|
47
|
+
|
|
48
|
+
/** One entry of a `parameters` list: a parameter, or a `$ref` to one. */
|
|
49
|
+
type ParameterEntry = NonNullable<OperationObject["parameters"]>[number];
|
|
50
|
+
|
|
51
|
+
// The runtime object checks stand guard because the document was parsed from
|
|
52
|
+
// arbitrary YAML/JSON: a spec can put a scalar or null where the type
|
|
53
|
+
// promises an object.
|
|
54
|
+
const isObject = <Value>(value: Value): value is NonNullable<Value> =>
|
|
55
|
+
typeof value === "object" && value !== null;
|
|
56
|
+
|
|
57
|
+
/** A parameter's `name`, which a hand-written spec may have left out or mistyped. */
|
|
58
|
+
const isName = <Value>(value: Value): value is Value & string =>
|
|
59
|
+
typeof value === "string";
|
|
60
|
+
|
|
61
|
+
/** A declared list, or none when a hand-written spec put something else there. */
|
|
62
|
+
const listOf = <Item>(value: Item[] | undefined): NonNullable<Item>[] =>
|
|
63
|
+
Array.isArray(value) ? value.filter(isObject) : [];
|
|
64
|
+
|
|
65
|
+
/** A resolved parameter: one that isn't a `$ref`. */
|
|
66
|
+
type Parameter = Extract<ParameterEntry, { in: string }>;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The parameters an operation declares, its path item's and its own, `$ref`s
|
|
70
|
+
* resolved through `components.parameters`. One that doesn't resolve is left
|
|
71
|
+
* out, as the page leaves it out.
|
|
72
|
+
*/
|
|
73
|
+
const parametersOf = (
|
|
74
|
+
document: ApiDocument,
|
|
75
|
+
item: PathItem,
|
|
76
|
+
operation: OperationObject
|
|
77
|
+
): Parameter[] => {
|
|
78
|
+
const components = document.components?.parameters ?? {};
|
|
79
|
+
return [
|
|
80
|
+
...listOf<ParameterEntry>(item.parameters),
|
|
81
|
+
...listOf<ParameterEntry>(operation.parameters),
|
|
82
|
+
].flatMap((entry) => {
|
|
83
|
+
const refName =
|
|
84
|
+
"$ref" in entry
|
|
85
|
+
? PARAMETER_REF.exec(entry.$ref)?.groups?.name
|
|
86
|
+
: undefined;
|
|
87
|
+
const parameter = (refName ? components[refName] : undefined) ?? entry;
|
|
88
|
+
return "in" in parameter ? [parameter] : [];
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* A path whose template and declared path parameters disagree. A placeholder
|
|
94
|
+
* with no parameter gets no input in Try it and no row in the table, so
|
|
95
|
+
* requests send it as literal text; a parameter with no placeholder gets an
|
|
96
|
+
* input whose value never reaches the URL.
|
|
97
|
+
*/
|
|
98
|
+
const pathParameterIssues = (
|
|
99
|
+
signature: string,
|
|
100
|
+
path: string,
|
|
101
|
+
declared: Set<string>
|
|
102
|
+
): SpecIssue[] => {
|
|
103
|
+
const used = new Set(
|
|
104
|
+
[...path.matchAll(PATH_TEMPLATE)].map((match) => match.groups?.name ?? "")
|
|
105
|
+
);
|
|
106
|
+
const issues: SpecIssue[] = [];
|
|
107
|
+
for (const name of used) {
|
|
108
|
+
if (!declared.has(name)) {
|
|
109
|
+
issues.push({
|
|
110
|
+
code: "BLUME_OPENAPI_PATH_PARAMETER_MISSING",
|
|
111
|
+
message: `${signature} has {${name}} in its path but declares no "${name}" path parameter, so Try it and the code samples send "{${name}}" as literal text.`,
|
|
112
|
+
suggestion: `Declare "${name}" in the operation's or the path's \`parameters\`, with \`in: path\` and \`required: true\`.`,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
for (const name of declared) {
|
|
117
|
+
if (!used.has(name)) {
|
|
118
|
+
issues.push({
|
|
119
|
+
code: "BLUME_OPENAPI_PATH_PARAMETER_UNUSED",
|
|
120
|
+
message: `${signature} declares a "${name}" path parameter, but its path has no {${name}}, so the value Try it asks for never reaches the URL.`,
|
|
121
|
+
suggestion: `Add {${name}} to the path, or remove the parameter.`,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return issues;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
/** The scheme names a `security` list requires. */
|
|
129
|
+
const requiredSchemes = (
|
|
130
|
+
security: ApiDocument["security"] | OperationObject["security"]
|
|
131
|
+
): string[] =>
|
|
132
|
+
listOf(security).flatMap((requirement) => Object.keys(requirement));
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Security schemes a requirement names that `components.securitySchemes`
|
|
136
|
+
* doesn't define: the Authorization section has nothing to describe, and
|
|
137
|
+
* Try it and the code samples send no credential for them. One warning per
|
|
138
|
+
* scheme, naming where it's required: the root `security`, or the first few
|
|
139
|
+
* operations that list it.
|
|
140
|
+
*/
|
|
141
|
+
const securitySchemeIssues = (
|
|
142
|
+
document: ApiDocument,
|
|
143
|
+
requirers: Map<string, string[]>
|
|
144
|
+
): SpecIssue[] => {
|
|
145
|
+
const defined = document.components?.securitySchemes ?? {};
|
|
146
|
+
const root = new Set(requiredSchemes(document.security));
|
|
147
|
+
const issues: SpecIssue[] = [];
|
|
148
|
+
for (const scheme of new Set([...root, ...requirers.keys()])) {
|
|
149
|
+
if (Object.hasOwn(defined, scheme)) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
const operations = requirers.get(scheme) ?? [];
|
|
153
|
+
const more = operations.length - NAMED_OPERATIONS;
|
|
154
|
+
const where = root.has(scheme)
|
|
155
|
+
? "The spec's root `security` requires"
|
|
156
|
+
: `${operations.slice(0, NAMED_OPERATIONS).join(", ")}${more > 0 ? ` and ${more} more` : ""} ${operations.length === 1 ? "requires" : "require"}`;
|
|
157
|
+
issues.push({
|
|
158
|
+
code: "BLUME_OPENAPI_UNKNOWN_SECURITY_SCHEME",
|
|
159
|
+
message: `${where} the "${scheme}" security scheme, which \`components.securitySchemes\` doesn't define, so the Authorization section can't describe it and requests send no credential for it.`,
|
|
160
|
+
suggestion: `Define "${scheme}" in \`components.securitySchemes\`, or fix the name in \`security\`.`,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
return issues;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* An operation's `in: querystring` parameter (OpenAPI 3.2: the whole query
|
|
168
|
+
* string as one value), which the parameter table, Try it, and the code
|
|
169
|
+
* samples don't handle yet, so it would drop out of all three without a sign.
|
|
170
|
+
*/
|
|
171
|
+
const querystringIssue = (signature: string): SpecIssue => ({
|
|
172
|
+
code: "BLUME_OPENAPI_UNSUPPORTED",
|
|
173
|
+
message: `${signature} declares an \`in: querystring\` parameter, which OpenAPI 3.2 added and Blume doesn't render yet, so the page has no row or Try it input for it and the code samples leave the query string out.`,
|
|
174
|
+
suggestion:
|
|
175
|
+
"Describe the query string in the operation's `description` until Blume renders `querystring` parameters.",
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* A path item's `additionalOperations` (OpenAPI 3.2: methods beyond the ones
|
|
180
|
+
* a path item names directly, like `COPY`), which the extractor doesn't
|
|
181
|
+
* collect yet, so those operations would be missing without a sign.
|
|
182
|
+
*/
|
|
183
|
+
const additionalOperationsIssue = (
|
|
184
|
+
label: string,
|
|
185
|
+
methods: string[]
|
|
186
|
+
): SpecIssue => ({
|
|
187
|
+
code: "BLUME_OPENAPI_UNSUPPORTED",
|
|
188
|
+
message: `${label} declares \`additionalOperations\` (${methods.join(", ")}), which OpenAPI 3.2 added and Blume doesn't render yet, so those operations are missing from the reference.`,
|
|
189
|
+
suggestion:
|
|
190
|
+
"Document those operations on a page of their own until Blume renders `additionalOperations`.",
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* A root `x-webhooks` and no `webhooks`. It's the extension OpenAPI 3.0 tools
|
|
195
|
+
* read for webhooks, and upgrading a 3.0 spec renames it to `webhooks`; a spec
|
|
196
|
+
* already at 3.1 or later isn't upgraded, so it stays an extension and its
|
|
197
|
+
* webhooks would be missing without a sign.
|
|
198
|
+
*/
|
|
199
|
+
const xWebhooksIssues = (document: ApiDocument): SpecIssue[] =>
|
|
200
|
+
"x-webhooks" in document && document.webhooks === undefined
|
|
201
|
+
? [
|
|
202
|
+
{
|
|
203
|
+
code: "BLUME_OPENAPI_X_WEBHOOKS",
|
|
204
|
+
message:
|
|
205
|
+
"The spec declares its webhooks under `x-webhooks`, the extension OpenAPI 3.0 tools read. Blume reads it only from a 3.0 spec, which it upgrades, so these webhooks are missing from the reference.",
|
|
206
|
+
suggestion:
|
|
207
|
+
"Rename `x-webhooks` to `webhooks`, the field OpenAPI 3.1 added for them.",
|
|
208
|
+
},
|
|
209
|
+
]
|
|
210
|
+
: [];
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Check a parsed document for the mistakes above, and for the OpenAPI 3.2
|
|
214
|
+
* features Blume doesn't render yet. `$ref` path items are skipped: the
|
|
215
|
+
* extractor already reports them as missing from the reference.
|
|
216
|
+
*/
|
|
217
|
+
export const specIssues = (document: ApiDocument): SpecIssue[] => {
|
|
218
|
+
const issues: SpecIssue[] = [...xWebhooksIssues(document)];
|
|
219
|
+
// Scheme name -> the operations whose own `security` lists it.
|
|
220
|
+
const requirers = new Map<string, string[]>();
|
|
221
|
+
const visit = (name: string, item: PathItem, webhook: boolean): void => {
|
|
222
|
+
if (!isObject(item) || "$ref" in item) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
const additional = isObject(item.additionalOperations)
|
|
226
|
+
? Object.keys(item.additionalOperations)
|
|
227
|
+
: [];
|
|
228
|
+
if (additional.length > 0) {
|
|
229
|
+
issues.push(
|
|
230
|
+
additionalOperationsIssue(
|
|
231
|
+
webhook ? `Webhook "${name}"` : `Path "${name}"`,
|
|
232
|
+
additional
|
|
233
|
+
)
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
for (const method of HTTP_METHODS) {
|
|
237
|
+
const operation = item[method];
|
|
238
|
+
if (!isObject(operation)) {
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
const signature = operationLabel(name, method, webhook);
|
|
242
|
+
for (const scheme of requiredSchemes(operation.security)) {
|
|
243
|
+
requirers.set(scheme, [...(requirers.get(scheme) ?? []), signature]);
|
|
244
|
+
}
|
|
245
|
+
const parameters = parametersOf(document, item, operation);
|
|
246
|
+
// A webhook is keyed by its name, not a path: it has no template.
|
|
247
|
+
if (!webhook) {
|
|
248
|
+
issues.push(
|
|
249
|
+
...pathParameterIssues(
|
|
250
|
+
signature,
|
|
251
|
+
name,
|
|
252
|
+
new Set(
|
|
253
|
+
parameters
|
|
254
|
+
.filter((parameter) => parameter.in === "path")
|
|
255
|
+
.map((parameter) => parameter.name)
|
|
256
|
+
.filter(isName)
|
|
257
|
+
)
|
|
258
|
+
)
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
if (parameters.some((parameter) => parameter.in === "querystring")) {
|
|
262
|
+
issues.push(querystringIssue(signature));
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
for (const [path, item] of Object.entries(document.paths ?? {})) {
|
|
267
|
+
visit(path, item, false);
|
|
268
|
+
}
|
|
269
|
+
for (const [name, item] of Object.entries(document.webhooks ?? {})) {
|
|
270
|
+
visit(name, item, true);
|
|
271
|
+
}
|
|
272
|
+
return [...issues, ...securitySchemeIssues(document, requirers)];
|
|
273
|
+
};
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
parse,
|
|
27
27
|
print,
|
|
28
28
|
specifiedDirectives,
|
|
29
|
+
valueFromASTUntyped,
|
|
29
30
|
visit,
|
|
30
31
|
} from "graphql";
|
|
31
32
|
|
|
@@ -34,6 +35,7 @@ import type {
|
|
|
34
35
|
GraphqlEnumValue,
|
|
35
36
|
GraphqlField as ModelField,
|
|
36
37
|
GraphqlInputValue,
|
|
38
|
+
GraphqlJsonValue,
|
|
37
39
|
GraphqlTypeDef,
|
|
38
40
|
GraphqlTypeRef,
|
|
39
41
|
} from "./graphql.ts";
|
|
@@ -68,6 +70,21 @@ const defaultLiteral = (
|
|
|
68
70
|
return literal ? print(literal) : undefined;
|
|
69
71
|
};
|
|
70
72
|
|
|
73
|
+
/**
|
|
74
|
+
* The same default as the JSON a client sends in `variables`, which the
|
|
75
|
+
* example variables start from.
|
|
76
|
+
*/
|
|
77
|
+
const defaultJson = (
|
|
78
|
+
input: GraphQLArgument | GraphQLInputField
|
|
79
|
+
): GraphqlJsonValue | undefined => {
|
|
80
|
+
const literal = input.default?.literal;
|
|
81
|
+
// SAFETY: a const literal has no variables, so it lowers to JSON values
|
|
82
|
+
// only: numbers, strings, booleans, null, enum names, lists and objects.
|
|
83
|
+
return literal
|
|
84
|
+
? (valueFromASTUntyped(literal) as GraphqlJsonValue)
|
|
85
|
+
: undefined;
|
|
86
|
+
};
|
|
87
|
+
|
|
71
88
|
const inputValue = (
|
|
72
89
|
input: GraphQLArgument | GraphQLInputField
|
|
73
90
|
): GraphqlInputValue => {
|
|
@@ -80,6 +97,10 @@ const inputValue = (
|
|
|
80
97
|
if (printed !== undefined) {
|
|
81
98
|
value.default = printed;
|
|
82
99
|
}
|
|
100
|
+
const json = defaultJson(input);
|
|
101
|
+
if (json !== undefined) {
|
|
102
|
+
value.defaultValue = json;
|
|
103
|
+
}
|
|
83
104
|
// `deprecationReason` is null on non-deprecated members in some builds;
|
|
84
105
|
// absent means "not deprecated" downstream, so both collapse to absent.
|
|
85
106
|
if (
|
package/src/openapi/graphql.ts
CHANGED
|
@@ -58,6 +58,15 @@ export interface GraphqlTypeRef {
|
|
|
58
58
|
name: string;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
/** A GraphQL input value as JSON carries it in `variables` (enums by name). */
|
|
62
|
+
export type GraphqlJsonValue =
|
|
63
|
+
| string
|
|
64
|
+
| number
|
|
65
|
+
| boolean
|
|
66
|
+
| null
|
|
67
|
+
| GraphqlJsonValue[]
|
|
68
|
+
| { [key: string]: GraphqlJsonValue };
|
|
69
|
+
|
|
61
70
|
/** An argument or input-object field. */
|
|
62
71
|
export interface GraphqlInputValue {
|
|
63
72
|
name: string;
|
|
@@ -65,6 +74,8 @@ export interface GraphqlInputValue {
|
|
|
65
74
|
type: GraphqlTypeRef;
|
|
66
75
|
/** Default value printed as a GraphQL literal (`10`, `"asc"`, `[1, 2]`). */
|
|
67
76
|
default?: string;
|
|
77
|
+
/** The same default as JSON, for the example variables. */
|
|
78
|
+
defaultValue?: GraphqlJsonValue;
|
|
68
79
|
deprecationReason?: string;
|
|
69
80
|
}
|
|
70
81
|
|
package/src/openapi/model.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { Document, OperationObject } from "@scalar/openapi-types/3.
|
|
1
|
+
import type { Document, OperationObject } from "@scalar/openapi-types/3.2";
|
|
2
2
|
|
|
3
|
+
import type { GraphqlAuthOptions } from "../reference/options.ts";
|
|
3
4
|
import type {
|
|
4
5
|
AsyncApiAction,
|
|
5
6
|
AsyncApiDocument,
|
|
@@ -26,10 +27,18 @@ export { slugify } from "./references.ts";
|
|
|
26
27
|
* per-operation route so it becomes a first-class Blume page.
|
|
27
28
|
*/
|
|
28
29
|
|
|
29
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* A normalized OpenAPI document, internal `$ref`s intact. Typed as 3.2, which
|
|
32
|
+
* is backward compatible with 3.1, so one type covers both the upgraded 3.1
|
|
33
|
+
* documents and the 3.2 ones read as written.
|
|
34
|
+
*/
|
|
30
35
|
export type ApiDocument = Document;
|
|
31
36
|
|
|
32
|
-
/**
|
|
37
|
+
/**
|
|
38
|
+
* The HTTP methods an OpenAPI path item may declare, in spec order. `query`
|
|
39
|
+
* is OpenAPI 3.2's (the QUERY method: a safe request that carries a body); a
|
|
40
|
+
* 3.1 path item can't declare it, so listing it changes nothing there.
|
|
41
|
+
*/
|
|
33
42
|
export const HTTP_METHODS = [
|
|
34
43
|
"get",
|
|
35
44
|
"put",
|
|
@@ -39,6 +48,7 @@ export const HTTP_METHODS = [
|
|
|
39
48
|
"head",
|
|
40
49
|
"patch",
|
|
41
50
|
"trace",
|
|
51
|
+
"query",
|
|
42
52
|
] as const;
|
|
43
53
|
|
|
44
54
|
export type HttpMethod = (typeof HTTP_METHODS)[number];
|
|
@@ -46,6 +56,9 @@ export type HttpMethod = (typeof HTTP_METHODS)[number];
|
|
|
46
56
|
/** Group used for operations that declare no tag. */
|
|
47
57
|
const UNTAGGED = "Operations";
|
|
48
58
|
|
|
59
|
+
/** Group used for webhooks that declare no tag. */
|
|
60
|
+
const UNTAGGED_WEBHOOKS = "Webhooks";
|
|
61
|
+
|
|
49
62
|
/** A lower-case letter or digit followed by a capital: `addPet`, `v2List`. */
|
|
50
63
|
const CASE_BOUNDARY = /(?<before>[\p{Ll}\p{N}])(?<capital>\p{Lu})/gu;
|
|
51
64
|
/** The last capital of an acronym before a capitalized word: `HTTPResponse`. */
|
|
@@ -101,6 +114,12 @@ export interface ApiOperationRef {
|
|
|
101
114
|
deprecated: boolean;
|
|
102
115
|
/** The channel the operation acts on (AsyncAPI only). */
|
|
103
116
|
channelId?: string;
|
|
117
|
+
/**
|
|
118
|
+
* An OpenAPI 3.1 webhook: a request the API sends to the reader's endpoint
|
|
119
|
+
* rather than one it serves. `path` then holds the webhook's name, the key
|
|
120
|
+
* it has under the document's `webhooks`.
|
|
121
|
+
*/
|
|
122
|
+
webhook?: true;
|
|
104
123
|
}
|
|
105
124
|
|
|
106
125
|
/**
|
|
@@ -131,11 +150,13 @@ export interface ApiSpecData {
|
|
|
131
150
|
* (GraphQL only; OpenAPI documents carry their servers in the document).
|
|
132
151
|
*/
|
|
133
152
|
endpoint?: string;
|
|
153
|
+
/** How the GraphQL endpoint authenticates (GraphQL only). */
|
|
154
|
+
auth?: GraphqlAuthOptions;
|
|
134
155
|
/** Operations keyed by {@link ApiOperationRef.key}. */
|
|
135
156
|
operations: Record<string, ApiOperationRef>;
|
|
136
157
|
tags: ApiTagRef[];
|
|
137
|
-
/** Code-sample languages to render per operation. */
|
|
138
|
-
codeSamples: string[];
|
|
158
|
+
/** Code-sample languages to render per operation; `false` for none. */
|
|
159
|
+
codeSamples: string[] | false;
|
|
139
160
|
/** Whether nested schema rows start expanded. */
|
|
140
161
|
expandSchemas: boolean;
|
|
141
162
|
/**
|
|
@@ -301,6 +322,11 @@ export const tagSlugger = (): ((name: string) => string) => {
|
|
|
301
322
|
};
|
|
302
323
|
};
|
|
303
324
|
|
|
325
|
+
/** One entry of a document's `paths` or `webhooks` map. */
|
|
326
|
+
type PathItemEntry =
|
|
327
|
+
| NonNullable<ApiDocument["paths"]>[string]
|
|
328
|
+
| NonNullable<ApiDocument["webhooks"]>[string];
|
|
329
|
+
|
|
304
330
|
/** An operation before the collector assigns its unique key and route. */
|
|
305
331
|
type CollectedOperation = Omit<ApiOperationRef, "route" | "tagSlug">;
|
|
306
332
|
|
|
@@ -386,10 +412,10 @@ export const operationCollector = (
|
|
|
386
412
|
|
|
387
413
|
/**
|
|
388
414
|
* Flatten a 3.1 document into a route-mapped operation list and its ordered
|
|
389
|
-
* tags. Operations inherit the first tag they declare; keys
|
|
390
|
-
* a repeated `operationId` still yields distinct routes.
|
|
391
|
-
* anything skipped (a `$ref` path item
|
|
392
|
-
* aren't silent.
|
|
415
|
+
* tags, webhooks included. Operations inherit the first tag they declare; keys
|
|
416
|
+
* are de-duplicated so a repeated `operationId` still yields distinct routes.
|
|
417
|
+
* `warnings` reports anything skipped (a `$ref` path item), so missing
|
|
418
|
+
* operations aren't silent.
|
|
393
419
|
*/
|
|
394
420
|
export const extractOperations = (
|
|
395
421
|
document: ApiDocument,
|
|
@@ -404,16 +430,24 @@ export const extractOperations = (
|
|
|
404
430
|
);
|
|
405
431
|
const collector = operationCollector(baseRoute, tagMeta);
|
|
406
432
|
|
|
407
|
-
|
|
433
|
+
// A path item's operations, filed under `name`: a path for `paths`, the
|
|
434
|
+
// webhook's key for `webhooks`.
|
|
435
|
+
const addPathItem = (
|
|
436
|
+
name: string,
|
|
437
|
+
item: PathItemEntry,
|
|
438
|
+
webhook: boolean
|
|
439
|
+
): void => {
|
|
408
440
|
// A parsed spec can carry a null path item despite the type; skip it.
|
|
409
441
|
if (!item) {
|
|
410
|
-
|
|
442
|
+
return;
|
|
411
443
|
}
|
|
412
444
|
if ("$ref" in item) {
|
|
413
445
|
warnings.push(
|
|
414
|
-
|
|
446
|
+
webhook
|
|
447
|
+
? `Webhook "${name}" is a $ref to a shared path item; referenced path items are not resolved, so it is missing from the reference. Inline the path item under "webhooks" to render it.`
|
|
448
|
+
: `Path "${name}" is a $ref to a shared path item; referenced path items are not resolved, so its operations are missing from the reference. Inline the path item under "paths" to render it.`
|
|
415
449
|
);
|
|
416
|
-
|
|
450
|
+
return;
|
|
417
451
|
}
|
|
418
452
|
for (const method of HTTP_METHODS) {
|
|
419
453
|
const operation = item[method];
|
|
@@ -421,26 +455,35 @@ export const extractOperations = (
|
|
|
421
455
|
continue;
|
|
422
456
|
}
|
|
423
457
|
const operationId = specText(operation.operationId);
|
|
424
|
-
|
|
458
|
+
const entry: CollectedOperation = {
|
|
425
459
|
deprecated: operation.deprecated ?? false,
|
|
426
460
|
description: specText(operation.description) ?? "",
|
|
427
|
-
|
|
461
|
+
// A webhook without an operationId is keyed by its name, which is
|
|
462
|
+
// already an identifier (`newPet` -> `new-pet`).
|
|
463
|
+
key: operationKey(
|
|
464
|
+
method,
|
|
465
|
+
name,
|
|
466
|
+
operationId ?? (webhook ? name : undefined)
|
|
467
|
+
),
|
|
428
468
|
method,
|
|
429
469
|
operationId,
|
|
430
|
-
path,
|
|
470
|
+
path: name,
|
|
431
471
|
summary: specText(operation.summary) ?? "",
|
|
432
|
-
tag:
|
|
433
|
-
|
|
472
|
+
tag:
|
|
473
|
+
specText(operation.tags?.[0]) ??
|
|
474
|
+
(webhook ? UNTAGGED_WEBHOOKS : UNTAGGED),
|
|
475
|
+
};
|
|
476
|
+
collector.add(webhook ? { ...entry, webhook: true } : entry);
|
|
434
477
|
}
|
|
435
|
-
}
|
|
478
|
+
};
|
|
436
479
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
);
|
|
480
|
+
for (const [path, item] of Object.entries(document.paths ?? {})) {
|
|
481
|
+
addPathItem(path, item, false);
|
|
482
|
+
}
|
|
483
|
+
// OpenAPI 3.1 webhooks: requests the API sends rather than serves. They
|
|
484
|
+
// follow the paths, so an untagged webhook group sits after the endpoints.
|
|
485
|
+
for (const [name, item] of Object.entries(document.webhooks ?? {})) {
|
|
486
|
+
addPathItem(name, item, true);
|
|
444
487
|
}
|
|
445
488
|
|
|
446
489
|
return { ...collector.finish(), warnings };
|
|
@@ -458,7 +501,9 @@ export const operationObject = (
|
|
|
458
501
|
// (AsyncAPI documents go to `asyncApiOperationObject`), so the spec's
|
|
459
502
|
// document is the OpenAPI shape.
|
|
460
503
|
const document = spec.document as ApiDocument;
|
|
461
|
-
const item =
|
|
504
|
+
const item = ref.webhook
|
|
505
|
+
? document.webhooks?.[ref.path]
|
|
506
|
+
: document.paths?.[ref.path];
|
|
462
507
|
const operation = method === undefined ? undefined : item?.[method];
|
|
463
508
|
return isOperation(operation) ? operation : undefined;
|
|
464
509
|
};
|