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
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
1
3
|
import { adapterDescriptorSchema } from "../../core/adapter.ts";
|
|
2
4
|
import type { DeployAdapter, DeployOptions } from "./types.ts";
|
|
3
5
|
import { deployOptionsSchema, serverRuntimeDeps } from "./types.ts";
|
|
@@ -6,18 +8,54 @@ import { deployOptionsSchema, serverRuntimeDeps } from "./types.ts";
|
|
|
6
8
|
export const NODE_ADAPTER_PACKAGE = "@astrojs/node";
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* defaults `mode` to `"standalone"`; an option you pass wins. `host` and
|
|
12
|
-
* `port` are forwarded too, but `@astrojs/node` replaces both with Astro's
|
|
13
|
-
* own server settings, so the standalone server listens on `localhost:4321`
|
|
14
|
-
* unless the `HOST` and `PORT` environment variables are set when it starts.
|
|
11
|
+
* A host the server trusts forwarded headers for, in Astro's
|
|
12
|
+
* `security.allowedDomains` shape: each field set must match.
|
|
15
13
|
*/
|
|
16
|
-
|
|
14
|
+
// oxlint-disable-next-line typescript/consistent-type-definitions -- interface loses the implicit index signature a deploy option's JsonValue needs
|
|
15
|
+
export type NodeAllowedDomain = {
|
|
16
|
+
/** The host, like `docs.example.com`; `*.example.com` matches subdomains. */
|
|
17
|
+
hostname?: string;
|
|
18
|
+
/** The port, as a string. */
|
|
19
|
+
port?: string;
|
|
20
|
+
/** The scheme, like `https`. */
|
|
21
|
+
protocol?: string;
|
|
22
|
+
};
|
|
17
23
|
|
|
18
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Options for {@link node}: `output`, `site`, `base`, and `allowedDomains`,
|
|
26
|
+
* plus any option of `@astrojs/node` forwarded verbatim (`mode`,
|
|
27
|
+
* `staticHeaders`, …). Blume defaults `mode` to `"standalone"`; an option you
|
|
28
|
+
* pass wins. `host` and `port` are forwarded too, but `@astrojs/node`
|
|
29
|
+
* replaces both with Astro's own server settings, so the standalone server
|
|
30
|
+
* listens on `localhost:4321` unless the `HOST` and `PORT` environment
|
|
31
|
+
* variables are set when it starts.
|
|
32
|
+
*/
|
|
33
|
+
export type NodeOptions = DeployOptions & {
|
|
34
|
+
/**
|
|
35
|
+
* The hosts a reverse proxy in front of the server answers for, set as
|
|
36
|
+
* Astro's `security.allowedDomains`. A request whose `Host` (or
|
|
37
|
+
* `X-Forwarded-Host`) matches one is trusted to name the reader in
|
|
38
|
+
* `X-Forwarded-For`, which the rate limit counts by; otherwise every
|
|
39
|
+
* reader counts as the proxy's address. Only list them when a proxy sets
|
|
40
|
+
* that header on every request, since a reader could otherwise send their
|
|
41
|
+
* own.
|
|
42
|
+
*/
|
|
43
|
+
allowedDomains?: NodeAllowedDomain[];
|
|
44
|
+
};
|
|
19
45
|
|
|
20
|
-
export
|
|
46
|
+
export type NodeAdapter = DeployAdapter<"node", NodeOptions>;
|
|
47
|
+
|
|
48
|
+
export const nodeOptionsSchema = deployOptionsSchema.extend({
|
|
49
|
+
allowedDomains: z
|
|
50
|
+
.array(
|
|
51
|
+
z.strictObject({
|
|
52
|
+
hostname: z.string().min(1).optional(),
|
|
53
|
+
port: z.string().min(1).optional(),
|
|
54
|
+
protocol: z.string().min(1).optional(),
|
|
55
|
+
})
|
|
56
|
+
)
|
|
57
|
+
.optional(),
|
|
58
|
+
});
|
|
21
59
|
|
|
22
60
|
export const nodeAdapterSchema = adapterDescriptorSchema(
|
|
23
61
|
"node",
|
|
@@ -84,13 +84,17 @@ const NAMED_OPTIONS = new Set(["base", "output", "site"]);
|
|
|
84
84
|
|
|
85
85
|
/**
|
|
86
86
|
* The options Blume does not name — what reaches the `@astrojs/*` adapter's
|
|
87
|
-
* constructor verbatim.
|
|
87
|
+
* constructor verbatim. `configOptions` are the ones a host adapter names
|
|
88
|
+
* itself, for the Astro config rather than the constructor.
|
|
88
89
|
*/
|
|
89
90
|
export const deployPassthrough = (
|
|
90
|
-
options: DeployOptions
|
|
91
|
+
options: DeployOptions,
|
|
92
|
+
configOptions: readonly string[] = []
|
|
91
93
|
): Record<string, JsonValue> =>
|
|
92
94
|
Object.fromEntries(
|
|
93
|
-
Object.entries(options).filter(
|
|
95
|
+
Object.entries(options).filter(
|
|
96
|
+
([key]) => !(NAMED_OPTIONS.has(key) || configOptions.includes(key))
|
|
97
|
+
)
|
|
94
98
|
);
|
|
95
99
|
|
|
96
100
|
/**
|
package/src/deploy/artifacts.ts
CHANGED
|
@@ -14,6 +14,11 @@ import { API_CATALOG_PATH, buildApiCatalog } from "../ai/api-catalog.ts";
|
|
|
14
14
|
import { buildHomeLinkHeader } from "../ai/link-headers.ts";
|
|
15
15
|
import { buildLlmsFiles } from "../ai/llms.ts";
|
|
16
16
|
import { markdownRoutePaths } from "../ai/markdown.ts";
|
|
17
|
+
import {
|
|
18
|
+
buildSiteSkill,
|
|
19
|
+
SKILL_MD_PATH,
|
|
20
|
+
siteSkillName,
|
|
21
|
+
} from "../ai/site-skill.ts";
|
|
17
22
|
import {
|
|
18
23
|
AGENT_SKILLS_DIR,
|
|
19
24
|
AGENT_SKILLS_INDEX_PATH,
|
|
@@ -29,6 +34,7 @@ import { normalizeBasePath } from "../core/base-path.ts";
|
|
|
29
34
|
import { discoverPagesSync } from "../core/custom-pages.ts";
|
|
30
35
|
import type { BlumeProject } from "../core/project-graph.ts";
|
|
31
36
|
import type { ResolvedConfig } from "../core/schema.ts";
|
|
37
|
+
import { buildNarration } from "../narration/build.ts";
|
|
32
38
|
import { buildSearchIndex } from "../search/build.ts";
|
|
33
39
|
import { syncSearchProvider } from "../search/sync/index.ts";
|
|
34
40
|
import { readsHeaderFiles } from "./adapter-output.ts";
|
|
@@ -212,7 +218,8 @@ export const emitHeaderFiles = async (
|
|
|
212
218
|
|
|
213
219
|
/**
|
|
214
220
|
* Collect the Agent Skills `agents.skills` publishes, once per build, so both the
|
|
215
|
-
* skills surface and llms.txt (which lists them) read the same set
|
|
221
|
+
* skills surface and llms.txt (which lists them) read the same set (the
|
|
222
|
+
* generated site skill joins them in {@link publishedSkills}). Empty
|
|
216
223
|
* when the feature is off, the directory is missing, nothing in it is
|
|
217
224
|
* publishable (each with a warning), or a user-shipped
|
|
218
225
|
* `public/.well-known/agent-skills/index.json` already owns the surface.
|
|
@@ -248,6 +255,57 @@ const collectConfiguredSkills = async (
|
|
|
248
255
|
return skills;
|
|
249
256
|
};
|
|
250
257
|
|
|
258
|
+
/**
|
|
259
|
+
* Every skill the build publishes: the `agents.skills` ones, plus the
|
|
260
|
+
* generated site skill unless one of those shares its name (the hand-written
|
|
261
|
+
* one wins) or a user-shipped index owns the surface.
|
|
262
|
+
*/
|
|
263
|
+
const publishedSkills = async (
|
|
264
|
+
project: BlumeProject,
|
|
265
|
+
distDir: string,
|
|
266
|
+
surface: { mcp: boolean; userIndex: boolean },
|
|
267
|
+
logger: ArtifactLogger
|
|
268
|
+
): Promise<SkillArtifact[]> => {
|
|
269
|
+
const configured = await collectConfiguredSkills(project, distDir, logger);
|
|
270
|
+
// The skill lists the MCP server only when the build serves it.
|
|
271
|
+
const site = surface.userIndex
|
|
272
|
+
? null
|
|
273
|
+
: buildSiteSkill({
|
|
274
|
+
...project,
|
|
275
|
+
config: advertisedConfig(project.config, {
|
|
276
|
+
mcp: surface.mcp,
|
|
277
|
+
skills: true,
|
|
278
|
+
}),
|
|
279
|
+
});
|
|
280
|
+
return site && !configured.some((skill) => skill.name === site.name)
|
|
281
|
+
? [site, ...configured]
|
|
282
|
+
: configured;
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Serve the site skill at `/skill.md` too, the path agents try first: the
|
|
287
|
+
* generated one, or a same-named hand-written skill that is a lone
|
|
288
|
+
* `SKILL.md` (an archive's relative references need its other files). A
|
|
289
|
+
* `public/skill.md` wins.
|
|
290
|
+
*/
|
|
291
|
+
const emitSkillMd = async (
|
|
292
|
+
project: BlumeProject,
|
|
293
|
+
distDir: string,
|
|
294
|
+
skills: readonly SkillArtifact[],
|
|
295
|
+
logger: ArtifactLogger
|
|
296
|
+
): Promise<void> => {
|
|
297
|
+
const target = join(distDir, SKILL_MD_PATH.slice(1));
|
|
298
|
+
const name = siteSkillName(project);
|
|
299
|
+
const skill = skills.find(
|
|
300
|
+
(candidate) => candidate.name === name && candidate.type === "skill-md"
|
|
301
|
+
);
|
|
302
|
+
if (!(project.config.agents.skillMd && skill) || existsSync(target)) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
await writeFile(target, skill.content);
|
|
306
|
+
logger.info(`Generated ${SKILL_MD_PATH.slice(1)} (the "${name}" skill)`);
|
|
307
|
+
};
|
|
308
|
+
|
|
251
309
|
/**
|
|
252
310
|
* Publish the collected Agent Skills: copy each skill artifact under
|
|
253
311
|
* `.well-known/agent-skills/` and emit the discovery index. A user-shipped
|
|
@@ -382,8 +440,13 @@ export const publishBuildArtifacts = async (
|
|
|
382
440
|
logger.info(`Indexed ${indexed} page(s) for search`);
|
|
383
441
|
}
|
|
384
442
|
|
|
443
|
+
// Generated narration reads the built pages, so it runs once they exist.
|
|
444
|
+
// Nothing happens without `narration.provider`.
|
|
445
|
+
await buildNarration(project, distDir, logger);
|
|
446
|
+
|
|
385
447
|
// Upload the index to a hosted provider (Algolia, Orama Cloud, Typesense).
|
|
386
|
-
// Skipped with a warning when its admin key isn't configured
|
|
448
|
+
// Skipped with a warning when its admin key isn't configured; with the key
|
|
449
|
+
// set, a failed sync fails the build.
|
|
387
450
|
await syncSearchProvider(project, {
|
|
388
451
|
start: logger.info.bind(logger),
|
|
389
452
|
success: logger.info.bind(logger),
|
|
@@ -394,18 +457,24 @@ export const publishBuildArtifacts = async (
|
|
|
394
457
|
const userSkillsIndex = existsSync(
|
|
395
458
|
join(distDir, AGENT_SKILLS_INDEX_PATH.slice(1))
|
|
396
459
|
);
|
|
397
|
-
const
|
|
460
|
+
const mcp = servesMcp(
|
|
461
|
+
project,
|
|
462
|
+
project.context.pagesRoot
|
|
463
|
+
? discoverPagesSync(project.context.pagesRoot)
|
|
464
|
+
: []
|
|
465
|
+
);
|
|
466
|
+
const skills = await publishedSkills(
|
|
467
|
+
project,
|
|
468
|
+
distDir,
|
|
469
|
+
{ mcp, userIndex: userSkillsIndex },
|
|
470
|
+
logger
|
|
471
|
+
);
|
|
398
472
|
// The discovery documents advertise what this build serves: no MCP server
|
|
399
473
|
// when a page took its route, no skills index when nothing was published.
|
|
400
474
|
const advertised: BlumeProject = {
|
|
401
475
|
...project,
|
|
402
476
|
config: advertisedConfig(project.config, {
|
|
403
|
-
mcp
|
|
404
|
-
project,
|
|
405
|
-
project.context.pagesRoot
|
|
406
|
-
? discoverPagesSync(project.context.pagesRoot)
|
|
407
|
-
: []
|
|
408
|
-
),
|
|
477
|
+
mcp,
|
|
409
478
|
skills: skills.length > 0 || userSkillsIndex,
|
|
410
479
|
}),
|
|
411
480
|
};
|
|
@@ -444,6 +513,7 @@ export const publishBuildArtifacts = async (
|
|
|
444
513
|
|
|
445
514
|
await emitWellKnownFiles(advertised.config, distDir, skills, logger);
|
|
446
515
|
await emitAgentSkills(project, distDir, skills, logger);
|
|
516
|
+
await emitSkillMd(project, distDir, skills, logger);
|
|
447
517
|
|
|
448
518
|
await emitRedirectFiles(advertised, distDir, logger);
|
|
449
519
|
await emitHeaderFiles(advertised, distDir, logger);
|
|
@@ -85,6 +85,7 @@ import {
|
|
|
85
85
|
OPENAPI_PATH,
|
|
86
86
|
} from "../ai/api/paths.ts";
|
|
87
87
|
import { normalizeBasePath, normalizePath } from "../core/base-path.ts";
|
|
88
|
+
import { compileRedirects, isPatternPath } from "../core/redirect-patterns.ts";
|
|
88
89
|
import { CONTENT_ASSETS_ROOT, SVG_ASSET_HEADERS } from "./headers.ts";
|
|
89
90
|
import type { NotFoundVariants } from "./vercel-negotiation.ts";
|
|
90
91
|
|
|
@@ -289,12 +290,18 @@ export const buildNegotiationWorker = (
|
|
|
289
290
|
// header, which cannot carry non-ASCII.
|
|
290
291
|
const redirects = JSON.stringify(
|
|
291
292
|
Object.fromEntries(
|
|
292
|
-
(options.redirects ?? [])
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
293
|
+
(options.redirects ?? [])
|
|
294
|
+
.filter((redirect) => !isPatternPath(redirect.from))
|
|
295
|
+
.map((redirect) => [
|
|
296
|
+
normalizePath(redirect.from),
|
|
297
|
+
[encodeURI(redirect.to), redirect.status],
|
|
298
|
+
])
|
|
296
299
|
)
|
|
297
300
|
);
|
|
301
|
+
// Patterns (`/beta/:slug*`) are tried in order after the exact paths.
|
|
302
|
+
const patternRedirects = JSON.stringify(
|
|
303
|
+
compileRedirects(options.redirects ?? [])
|
|
304
|
+
);
|
|
298
305
|
return `// Generated by Blume. Do not edit; this file is recreated on each build.
|
|
299
306
|
//
|
|
300
307
|
// Request-time \`Accept: text/markdown\` negotiation for a Cloudflare server
|
|
@@ -319,6 +326,9 @@ const ASSETS_BINDING = ${binding};
|
|
|
319
326
|
const HOME_LINK_HEADER = ${homeLinkHeader};
|
|
320
327
|
const HOME_TOKENS = ${homeTokens};
|
|
321
328
|
const REDIRECTS = ${redirects};
|
|
329
|
+
const PATTERN_REDIRECTS = ${patternRedirects}.map(
|
|
330
|
+
([source, location, status]) => [new RegExp(source, "u"), location, status]
|
|
331
|
+
);
|
|
322
332
|
const NOT_FOUND = ${notFound};
|
|
323
333
|
const SVG_ASSET_HEADERS = ${JSON.stringify(SVG_ASSET_HEADERS)};
|
|
324
334
|
|
|
@@ -335,11 +345,31 @@ const isSvgAsset = (pathname) => {
|
|
|
335
345
|
// reads — a worker-first route never reaches it. Answering from this baked-in
|
|
336
346
|
// copy keeps the exact configured status; delegating instead would let Astro's
|
|
337
347
|
// SSR handler default a GET to a permanent 301.
|
|
348
|
+
// An exact path is looked up first, then each pattern is tried in order, its
|
|
349
|
+
// Location template filled with the captures, encoded so a capture can't grow
|
|
350
|
+
// a query or fragment.
|
|
338
351
|
const redirectFor = (pathname) => {
|
|
339
352
|
const trimmed =
|
|
340
353
|
pathname !== "/" && pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
|
|
341
354
|
const path = safeDecode(trimmed);
|
|
342
|
-
|
|
355
|
+
if (Object.hasOwn(REDIRECTS, path)) {
|
|
356
|
+
return REDIRECTS[path];
|
|
357
|
+
}
|
|
358
|
+
const decoded = safeDecode(pathname);
|
|
359
|
+
for (const [pattern, location, status] of PATTERN_REDIRECTS) {
|
|
360
|
+
const match = pattern.exec(decoded);
|
|
361
|
+
if (match) {
|
|
362
|
+
return [
|
|
363
|
+
location.replace(/\\$(\\d+)/gu, (_reference, index) =>
|
|
364
|
+
encodeURI(match[Number(index)] ?? "")
|
|
365
|
+
.replaceAll("?", "%3F")
|
|
366
|
+
.replaceAll("#", "%23")
|
|
367
|
+
),
|
|
368
|
+
status,
|
|
369
|
+
];
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return null;
|
|
343
373
|
};
|
|
344
374
|
|
|
345
375
|
// The request path with the deployment base removed: the whole path on a
|
package/src/deploy/headers.ts
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
API_CATALOG_TYPE,
|
|
5
5
|
hasApiCatalog,
|
|
6
6
|
} from "../ai/api-catalog.ts";
|
|
7
|
+
import { servesSkillsIndex } from "../ai/skills.ts";
|
|
7
8
|
import {
|
|
8
9
|
SIGNATURES_DIRECTORY_PATH,
|
|
9
10
|
SIGNATURES_DIRECTORY_TYPE,
|
|
@@ -128,7 +129,7 @@ export const headerRules = (
|
|
|
128
129
|
}
|
|
129
130
|
// Published skills live at the deployment base, and the RFC wants their
|
|
130
131
|
// archives served as application/gzip explicitly.
|
|
131
|
-
if (config
|
|
132
|
+
if (servesSkillsIndex(config)) {
|
|
132
133
|
rules.push(
|
|
133
134
|
{
|
|
134
135
|
name: "Content-Type",
|
|
@@ -15,6 +15,8 @@ import {
|
|
|
15
15
|
} from "../ai/web-bot-auth.ts";
|
|
16
16
|
import { normalizeBasePath, normalizePath } from "../core/base-path.ts";
|
|
17
17
|
import type { BlumeProject } from "../core/project-graph.ts";
|
|
18
|
+
import { compileRedirects, isPatternPath } from "../core/redirect-patterns.ts";
|
|
19
|
+
import type { CompiledRedirect } from "../core/redirect-patterns.ts";
|
|
18
20
|
import type { ResolvedConfig } from "../core/schema.ts";
|
|
19
21
|
import { SVG_ASSET_HEADERS, svgAssetPath } from "./headers.ts";
|
|
20
22
|
import { distDir } from "./platforms/paths.ts";
|
|
@@ -106,11 +108,12 @@ const patternRules = (
|
|
|
106
108
|
export type NodeRedirects = Record<string, [string, number]>;
|
|
107
109
|
|
|
108
110
|
/**
|
|
109
|
-
* The configured redirects, based the way the host matches them (see
|
|
111
|
+
* The configured exact redirects, based the way the host matches them (see
|
|
110
112
|
* `platformRedirects`) and keyed for the wrapper's lookup, the `Location`
|
|
111
113
|
* percent-encoded as Astro sends it. A redirect at a content route's own path
|
|
112
114
|
* is left out: the prerendered page owns that URL, and the static handler
|
|
113
|
-
* serves it before Astro's redirect ever could.
|
|
115
|
+
* serves it before Astro's redirect ever could. Patterns are compiled apart
|
|
116
|
+
* ({@link nodePatternRedirects}).
|
|
114
117
|
*/
|
|
115
118
|
export const nodeRedirects = (project: BlumeProject): NodeRedirects => {
|
|
116
119
|
const { config } = project;
|
|
@@ -125,7 +128,13 @@ export const nodeRedirects = (project: BlumeProject): NodeRedirects => {
|
|
|
125
128
|
);
|
|
126
129
|
return Object.fromEntries(
|
|
127
130
|
platformRedirects(project)
|
|
128
|
-
.filter(
|
|
131
|
+
.filter(
|
|
132
|
+
(redirect) =>
|
|
133
|
+
!(
|
|
134
|
+
isPatternPath(redirect.from) ||
|
|
135
|
+
pages.has(normalizePath(redirect.from))
|
|
136
|
+
)
|
|
137
|
+
)
|
|
129
138
|
.map((redirect) => [
|
|
130
139
|
normalizePath(redirect.from),
|
|
131
140
|
[encodeURI(redirect.to), redirect.status],
|
|
@@ -133,12 +142,27 @@ export const nodeRedirects = (project: BlumeProject): NodeRedirects => {
|
|
|
133
142
|
);
|
|
134
143
|
};
|
|
135
144
|
|
|
145
|
+
/**
|
|
146
|
+
* The configured pattern redirects (`/beta/:slug*`), based the way the host
|
|
147
|
+
* matches them and compiled for the wrapper, which tries them in order after
|
|
148
|
+
* the exact ones. None can match a page: the scan rejects a pattern that
|
|
149
|
+
* does (`BLUME_REDIRECT_MATCHES_PAGE`).
|
|
150
|
+
*/
|
|
151
|
+
export const nodePatternRedirects = (
|
|
152
|
+
project: BlumeProject
|
|
153
|
+
): CompiledRedirect[] =>
|
|
154
|
+
project.config.redirects.length === 0
|
|
155
|
+
? []
|
|
156
|
+
: compileRedirects(platformRedirects(project));
|
|
157
|
+
|
|
136
158
|
/** What the wrapper needs beyond the header rules. */
|
|
137
159
|
export interface NodeEntryOptions {
|
|
138
160
|
/** `deployment.base`, normalized (`""` at the root). */
|
|
139
161
|
base?: string;
|
|
140
162
|
/** The configured redirects, from {@link nodeRedirects}. */
|
|
141
163
|
redirects?: NodeRedirects;
|
|
164
|
+
/** The configured pattern redirects, from {@link nodePatternRedirects}. */
|
|
165
|
+
patternRedirects?: CompiledRedirect[];
|
|
142
166
|
}
|
|
143
167
|
|
|
144
168
|
/**
|
|
@@ -177,6 +201,9 @@ const BASE = ${JSON.stringify(options.base ?? "")};
|
|
|
177
201
|
const RULES = new Map(${JSON.stringify(exactRules(rules))});
|
|
178
202
|
const PATTERNS = ${JSON.stringify(patternRules(rules))};
|
|
179
203
|
const REDIRECTS = ${JSON.stringify(options.redirects ?? {})};
|
|
204
|
+
const PATTERN_REDIRECTS = ${JSON.stringify(options.patternRedirects ?? [])}.map(
|
|
205
|
+
([source, location, status]) => [new RegExp(source, "u"), location, status]
|
|
206
|
+
);
|
|
180
207
|
const safeDecode = (path) => {
|
|
181
208
|
try {
|
|
182
209
|
return decodeURIComponent(path);
|
|
@@ -210,16 +237,37 @@ const applyHeaders = (req, res) => {
|
|
|
210
237
|
}
|
|
211
238
|
}
|
|
212
239
|
};
|
|
240
|
+
// A pattern redirect's Location: its template, each $n filled with that
|
|
241
|
+
// capture, encoded so it can't grow a query or fragment.
|
|
242
|
+
const fillLocation = (location, match) =>
|
|
243
|
+
location.replace(/\\$(\\d+)/gu, (_reference, index) =>
|
|
244
|
+
encodeURI(match[Number(index)] ?? "")
|
|
245
|
+
.replaceAll("?", "%3F")
|
|
246
|
+
.replaceAll("#", "%23")
|
|
247
|
+
);
|
|
248
|
+
// The configured redirect for a decoded path: an exact one, else the first
|
|
249
|
+
// pattern that matches it.
|
|
250
|
+
const redirectFor = (path) => {
|
|
251
|
+
const trimmed = path !== "/" && path.endsWith("/") ? path.slice(0, -1) : path;
|
|
252
|
+
if (Object.hasOwn(REDIRECTS, trimmed)) {
|
|
253
|
+
return REDIRECTS[trimmed];
|
|
254
|
+
}
|
|
255
|
+
for (const [pattern, location, status] of PATTERN_REDIRECTS) {
|
|
256
|
+
const match = pattern.exec(path);
|
|
257
|
+
if (match) {
|
|
258
|
+
return [fillLocation(location, match), status];
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return null;
|
|
262
|
+
};
|
|
213
263
|
// Answer a configured redirect with its exact status; Astro's handler would
|
|
214
264
|
// send a 301 (a 308 for other methods) whatever the configured one.
|
|
215
265
|
const answerRedirect = (req, res) => {
|
|
216
|
-
const
|
|
217
|
-
|
|
218
|
-
const key = safeDecode(trimmed);
|
|
219
|
-
if (!Object.hasOwn(REDIRECTS, key)) {
|
|
266
|
+
const redirect = redirectFor(safeDecode(urlPath(req)));
|
|
267
|
+
if (redirect === null) {
|
|
220
268
|
return false;
|
|
221
269
|
}
|
|
222
|
-
const [location, status] =
|
|
270
|
+
const [location, status] = redirect;
|
|
223
271
|
res.writeHead(status, { location });
|
|
224
272
|
res.end();
|
|
225
273
|
return true;
|
|
@@ -291,7 +339,12 @@ export const wrapNodeEntry = async (
|
|
|
291
339
|
: []),
|
|
292
340
|
];
|
|
293
341
|
const redirects = nodeRedirects(project);
|
|
294
|
-
|
|
342
|
+
const patternRedirects = nodePatternRedirects(project);
|
|
343
|
+
if (
|
|
344
|
+
rules.length === 0 &&
|
|
345
|
+
Object.keys(redirects).length === 0 &&
|
|
346
|
+
patternRedirects.length === 0
|
|
347
|
+
) {
|
|
295
348
|
return;
|
|
296
349
|
}
|
|
297
350
|
const serverDir = join(distDir(project.context), "server");
|
|
@@ -311,6 +364,7 @@ export const wrapNodeEntry = async (
|
|
|
311
364
|
entry,
|
|
312
365
|
nodeEntryWrapper(rules, {
|
|
313
366
|
base: normalizeBasePath(project.config.deployment.options.base),
|
|
367
|
+
patternRedirects,
|
|
314
368
|
redirects,
|
|
315
369
|
}),
|
|
316
370
|
"utf-8"
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
import { normalizeBasePath } from "../../core/base-path.ts";
|
|
15
15
|
import type { BlumeProject } from "../../core/project-graph.ts";
|
|
16
16
|
import type { ProjectContext } from "../../core/types.ts";
|
|
17
|
+
import { withRateLimitBinding } from "../../ratelimit/wrangler.ts";
|
|
17
18
|
import { CLOUDFLARE_ADAPTER_PACKAGE } from "../adapters/cloudflare.ts";
|
|
18
19
|
import {
|
|
19
20
|
injectWorkerNegotiation,
|
|
@@ -274,17 +275,51 @@ export const nameCloudflareWorker = async (
|
|
|
274
275
|
};
|
|
275
276
|
|
|
276
277
|
/**
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
278
|
+
* Declare the Workers rate limiting binding `rateLimit: cloudflare()` counts
|
|
279
|
+
* with in the built Worker's config, which `wrangler deploy` reads.
|
|
280
|
+
*/
|
|
281
|
+
export const bindCloudflareRateLimit = async (
|
|
282
|
+
project: BlumeProject,
|
|
283
|
+
log: BuildLog
|
|
284
|
+
): Promise<void> => {
|
|
285
|
+
const { rateLimit } = project.config;
|
|
286
|
+
if (rateLimit?.kind !== "cloudflare") {
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
const wranglerPath = join(
|
|
290
|
+
distDir(project.context),
|
|
291
|
+
"server",
|
|
292
|
+
"wrangler.json"
|
|
293
|
+
);
|
|
294
|
+
const bound = existsSync(wranglerPath)
|
|
295
|
+
? withRateLimitBinding(await readFile(wranglerPath, "utf-8"), rateLimit)
|
|
296
|
+
: null;
|
|
297
|
+
if (bound === null) {
|
|
298
|
+
log.warn(
|
|
299
|
+
"Could not declare the rate limiting binding in dist/server/wrangler.json — the routes count in memory instead."
|
|
300
|
+
);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
await writeFile(wranglerPath, bound, "utf-8");
|
|
304
|
+
log.success("Declared the Workers rate limiting binding");
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Cloudflare. A server build targets Workers only (`@astrojs/cloudflare`
|
|
309
|
+
* dropped Pages in v13): it emits the Worker into `dist/server` and serves
|
|
310
|
+
* `dist/client` through the ASSETS binding, which honors `_headers` from that
|
|
311
|
+
* directory exactly as Pages does — so the file applies to both output modes
|
|
312
|
+
* here. A static build never loads the adapter; its `dist/` deploys to Pages,
|
|
313
|
+
* whose build environment `env` detects, or to Workers static assets (Workers
|
|
314
|
+
* Builds exposes no site URL to detect). Without a configured driver the
|
|
315
|
+
* adapter force-enables KV-backed sessions and declares a `SESSION` binding
|
|
316
|
+
* that `wrangler deploy` then demands a namespace for, even though Blume
|
|
317
|
+
* never reads `Astro.session`; `session: false` opts the project out.
|
|
284
318
|
*/
|
|
285
319
|
export const cloudflarePlatform: DeployPlatform = {
|
|
286
320
|
astro: {
|
|
287
|
-
config: { session: false },
|
|
321
|
+
config: () => ({ session: false }),
|
|
322
|
+
configOptions: [],
|
|
288
323
|
options: adapterOptions,
|
|
289
324
|
package: CLOUDFLARE_ADAPTER_PACKAGE,
|
|
290
325
|
},
|
|
@@ -298,6 +333,7 @@ export const cloudflarePlatform: DeployPlatform = {
|
|
|
298
333
|
if (!isolated) {
|
|
299
334
|
await nameCloudflareWorker(project, log);
|
|
300
335
|
await emitCloudflareNegotiation(project, log);
|
|
336
|
+
await bindCloudflareRateLimit(project, log);
|
|
301
337
|
await emitCloudflareDeployConfig(project.context);
|
|
302
338
|
}
|
|
303
339
|
return true;
|
|
@@ -318,5 +354,5 @@ export const cloudflarePlatform: DeployPlatform = {
|
|
|
318
354
|
// build, and hoists its own `_headers`/`_redirects` back up to `dist/client`.
|
|
319
355
|
serverClientUnderBase: true,
|
|
320
356
|
serverOutputDir: distDir,
|
|
321
|
-
serverStaticDir: clientDir,
|
|
357
|
+
serverStaticDir: (context, base) => join(clientDir(context), base),
|
|
322
358
|
};
|
|
@@ -9,7 +9,11 @@ import type { BlumeProject } from "../../core/project-graph.ts";
|
|
|
9
9
|
import { NETLIFY_ADAPTER_PACKAGE } from "../adapters/netlify.ts";
|
|
10
10
|
import { buildNetlifyConfigHeaders } from "../headers.ts";
|
|
11
11
|
import type { NetlifyConfigHeaders } from "../headers.ts";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
buildNetlifyRedirects,
|
|
14
|
+
netlifyPatternRedirects,
|
|
15
|
+
platformRedirects,
|
|
16
|
+
} from "../redirects.ts";
|
|
13
17
|
import { distDir, toSiteUrl } from "./paths.ts";
|
|
14
18
|
import type { BuildLog, DeployPlatform, RedirectFile } from "./types.ts";
|
|
15
19
|
|
|
@@ -76,6 +80,33 @@ export const emitNetlifyHeaders = async (
|
|
|
76
80
|
await writeFile(configPath, JSON.stringify(frameworks), "utf-8");
|
|
77
81
|
};
|
|
78
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Carry the pattern redirects (`/beta/:slug*`) into a server build, as
|
|
85
|
+
* `redirects` in the Frameworks API config: Astro's `redirects` carry only
|
|
86
|
+
* the exact ones, since it can't prerender a pattern's pages, so the adapter
|
|
87
|
+
* never writes these. Netlify appends them after any rules of the user's own.
|
|
88
|
+
*/
|
|
89
|
+
export const emitNetlifyPatternRedirects = async (
|
|
90
|
+
project: BlumeProject
|
|
91
|
+
): Promise<void> => {
|
|
92
|
+
const ours = netlifyPatternRedirects(platformRedirects(project));
|
|
93
|
+
const configPath = join(project.context.root, NETLIFY_CONFIG_FILE);
|
|
94
|
+
if (ours.length === 0 || !existsSync(configPath)) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
// Only `redirects` is read; every other key rides through as parsed.
|
|
98
|
+
const frameworks: { redirects?: { from: string }[] } = JSON.parse(
|
|
99
|
+
await readFile(configPath, "utf-8")
|
|
100
|
+
);
|
|
101
|
+
// A second pass over the same build replaces its own entries.
|
|
102
|
+
const froms = new Set(ours.map((entry) => entry.from));
|
|
103
|
+
frameworks.redirects = [
|
|
104
|
+
...(frameworks.redirects ?? []).filter((entry) => !froms.has(entry.from)),
|
|
105
|
+
...ours,
|
|
106
|
+
];
|
|
107
|
+
await writeFile(configPath, JSON.stringify(frameworks), "utf-8");
|
|
108
|
+
};
|
|
109
|
+
|
|
79
110
|
/**
|
|
80
111
|
* Netlify. A server build runs on Netlify Functions from the Frameworks API
|
|
81
112
|
* tree the adapter writes to `.netlify/v1`, relative to the Astro root —
|
|
@@ -87,7 +118,8 @@ export const emitNetlifyHeaders = async (
|
|
|
87
118
|
*/
|
|
88
119
|
export const netlifyPlatform: DeployPlatform = {
|
|
89
120
|
astro: {
|
|
90
|
-
config: {},
|
|
121
|
+
config: () => ({}),
|
|
122
|
+
configOptions: [],
|
|
91
123
|
options: () => ({}),
|
|
92
124
|
package: NETLIFY_ADAPTER_PACKAGE,
|
|
93
125
|
},
|
|
@@ -106,6 +138,7 @@ export const netlifyPlatform: DeployPlatform = {
|
|
|
106
138
|
// never surfaces it.
|
|
107
139
|
if (!isolated) {
|
|
108
140
|
await emitNetlifyHeaders(project, log);
|
|
141
|
+
await emitNetlifyPatternRedirects(project);
|
|
109
142
|
}
|
|
110
143
|
return true;
|
|
111
144
|
},
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { JsonValue } from "../../core/adapter.ts";
|
|
1
2
|
import { NODE_ADAPTER_PACKAGE } from "../adapters/node.ts";
|
|
2
3
|
import { wrapNodeEntry } from "../node-headers.ts";
|
|
3
4
|
import { clientDir, distDir } from "./paths.ts";
|
|
@@ -11,11 +12,20 @@ import type { DeployPlatform } from "./types.ts";
|
|
|
11
12
|
* discovery files and downloaded SVGs need instead, and answers the
|
|
12
13
|
* configured redirects with their exact status, which Astro's own handler
|
|
13
14
|
* would default to 301 or 308. No platform env to detect: the site URL has to
|
|
14
|
-
* be configured.
|
|
15
|
+
* be configured. `allowedDomains` becomes Astro's `security.allowedDomains`,
|
|
16
|
+
* which a server behind a reverse proxy needs before Astro reads the reader's
|
|
17
|
+
* address from `X-Forwarded-For`.
|
|
15
18
|
*/
|
|
16
19
|
export const nodePlatform: DeployPlatform = {
|
|
17
20
|
astro: {
|
|
18
|
-
config: {}
|
|
21
|
+
config: ({ allowedDomains }) => {
|
|
22
|
+
const config: Record<string, JsonValue> = {};
|
|
23
|
+
if (allowedDomains) {
|
|
24
|
+
config.security = { allowedDomains };
|
|
25
|
+
}
|
|
26
|
+
return config;
|
|
27
|
+
},
|
|
28
|
+
configOptions: ["allowedDomains"],
|
|
19
29
|
options: () => ({ mode: "standalone" }),
|
|
20
30
|
package: NODE_ADAPTER_PACKAGE,
|
|
21
31
|
},
|