blume 2.1.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +94 -0
- package/dist/cli/{chunk-5cg2rzgf.js → chunk-073rdvgb.js} +19 -48
- package/dist/cli/{chunk-5cg2rzgf.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-rekqz4qg.js → chunk-313vnn40.js} +16 -15
- package/dist/cli/chunk-313vnn40.js.map +10 -0
- package/dist/cli/{chunk-gp84za0h.js → chunk-3v3ffbrj.js} +2 -2
- package/dist/cli/{chunk-9xr4dgee.js → chunk-3x6x3pph.js} +29 -16
- package/dist/cli/chunk-3x6x3pph.js.map +10 -0
- package/dist/cli/{chunk-0gz36akr.js → chunk-42t4jxdx.js} +21 -5
- package/dist/cli/chunk-42t4jxdx.js.map +12 -0
- package/dist/cli/{chunk-ta27feev.js → chunk-54ztw1nj.js} +21 -2
- package/dist/cli/chunk-54ztw1nj.js.map +10 -0
- package/dist/cli/{chunk-jnwj5kjj.js → chunk-5vjtgs6e.js} +20 -7
- package/dist/cli/{chunk-jnwj5kjj.js.map → chunk-5vjtgs6e.js.map} +3 -3
- package/dist/cli/chunk-66w9j7p6.js +322 -0
- package/dist/cli/chunk-66w9j7p6.js.map +14 -0
- package/dist/cli/{chunk-nd1821sk.js → chunk-7ppf1rva.js} +32 -18
- package/dist/cli/chunk-7ppf1rva.js.map +10 -0
- package/dist/cli/{chunk-p804f3pe.js → chunk-8y2kmjv8.js} +6 -6
- package/dist/cli/{chunk-2f7n4qzt.js → chunk-c1y538kd.js} +1 -1
- package/dist/cli/{chunk-1n228xqb.js → chunk-c887fj0s.js} +2 -2
- package/dist/cli/{chunk-y5h4r2y0.js → chunk-cfyg47zg.js} +15 -5
- package/dist/cli/chunk-cfyg47zg.js.map +10 -0
- package/dist/cli/{chunk-cmtcnh9f.js → chunk-dzwehpy7.js} +2 -2
- package/dist/cli/{chunk-h2a48yhd.js → chunk-e6atmn4h.js} +119 -15
- package/dist/cli/{chunk-h2a48yhd.js.map → chunk-e6atmn4h.js.map} +10 -10
- package/dist/cli/{chunk-5ffywsmb.js → chunk-e8xw9qkh.js} +8 -6
- package/dist/cli/{chunk-5ffywsmb.js.map → chunk-e8xw9qkh.js.map} +3 -3
- package/dist/cli/{chunk-ntv4qrt7.js → chunk-e9q7a2ak.js} +14 -14
- package/dist/cli/{chunk-xkz5xbtv.js → chunk-ehweg4fr.js} +2366 -1114
- package/dist/cli/chunk-ehweg4fr.js.map +218 -0
- package/dist/cli/{chunk-zf748avv.js → chunk-ep6nd0rn.js} +176 -281
- package/dist/cli/{chunk-zf748avv.js.map → chunk-ep6nd0rn.js.map} +11 -12
- package/dist/cli/{chunk-yxmk4pec.js → chunk-fdrkhpjy.js} +16 -15
- package/dist/cli/{chunk-yxmk4pec.js.map → chunk-fdrkhpjy.js.map} +3 -3
- package/dist/cli/{chunk-5wj2qwn2.js → chunk-ft9vfys6.js} +4 -4
- package/dist/cli/{chunk-4h8z9vv5.js → chunk-gb420vvz.js} +89 -46
- package/dist/cli/chunk-gb420vvz.js.map +17 -0
- package/dist/cli/{chunk-713mngdq.js → chunk-hebn0tpx.js} +76 -10
- package/dist/cli/chunk-hebn0tpx.js.map +14 -0
- package/dist/cli/{chunk-2n4ps1b3.js → chunk-htrwgabr.js} +40 -22
- package/dist/cli/chunk-htrwgabr.js.map +15 -0
- package/dist/cli/{chunk-zhvd6adm.js → chunk-hx3xqnk9.js} +13 -13
- package/dist/cli/chunk-j134vrp2.js +65 -0
- package/dist/cli/chunk-j134vrp2.js.map +10 -0
- package/dist/cli/{chunk-y4ykbark.js → chunk-kma9f6sf.js} +2 -2
- package/dist/cli/{chunk-py62fewh.js → chunk-mrcccgnh.js} +3 -3
- package/dist/cli/{chunk-2f3ndkpw.js → chunk-n0v7m8ry.js} +3 -3
- package/dist/cli/{chunk-43zcf4gz.js → chunk-ncj7w596.js} +522 -353
- package/dist/cli/chunk-ncj7w596.js.map +35 -0
- package/dist/cli/{chunk-9geymqns.js → chunk-nq1d20w2.js} +14 -14
- package/dist/cli/{chunk-g2z9x01v.js → chunk-nrns10mj.js} +3 -3
- package/dist/cli/{chunk-e7vvk5ya.js → chunk-sds923fa.js} +3 -3
- package/dist/cli/{chunk-cy5bm0j0.js → chunk-t2m5j4pr.js} +2 -2
- package/dist/cli/{chunk-cy5bm0j0.js.map → chunk-t2m5j4pr.js.map} +1 -1
- package/dist/cli/{chunk-yj17vs39.js → chunk-tdqhyxfz.js} +5 -5
- package/dist/cli/{chunk-q3wxxq39.js → chunk-tphac74f.js} +5 -5
- package/dist/cli/{chunk-6bm0xpgd.js → chunk-w1r4vase.js} +2 -2
- package/dist/cli/index.js +24 -19
- package/dist/cli/index.js.map +3 -3
- package/dist/types/ai/ask-context.d.ts +6 -2
- package/dist/types/ai/component-markdown.d.ts +2 -0
- package/dist/types/ai/openapi-components.d.ts +4 -1
- package/dist/types/astro/integration.d.ts +5 -4
- package/dist/types/astro/markdown-negotiation.d.ts +3 -0
- package/dist/types/astro/pages.d.ts +10 -0
- package/dist/types/cli/init/scaffold.d.ts +1 -1
- package/dist/types/components/content/api-field.d.ts +4 -1
- package/dist/types/components/content/api-page.d.ts +6 -1
- package/dist/types/components/openapi/code-samples.d.ts +29 -0
- package/dist/types/components/openapi/helpers.d.ts +22 -1
- package/dist/types/components/openapi/security.d.ts +10 -0
- package/dist/types/components/openapi/snippets.d.ts +60 -0
- package/dist/types/core/changelog-index.d.ts +8 -0
- package/dist/types/core/config-input.d.ts +30 -3
- package/dist/types/core/data.d.ts +4 -0
- package/dist/types/core/i18n-ui.d.ts +2 -0
- package/dist/types/core/links.d.ts +8 -0
- package/dist/types/core/probe.d.ts +2 -0
- package/dist/types/core/project-graph.d.ts +6 -0
- package/dist/types/core/redirect-patterns.d.ts +11 -3
- package/dist/types/core/schema.d.ts +119 -0
- 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/remote.d.ts +37 -10
- package/dist/types/core/sources/sanity.d.ts +1 -1
- package/dist/types/core/types.d.ts +17 -0
- package/dist/types/deploy/adapter-output.d.ts +2 -1
- package/dist/types/deploy/adapters/cloudflare.d.ts +7 -5
- package/dist/types/deploy/adapters/node.d.ts +58 -23
- package/dist/types/deploy/adapters/registry.d.ts +10 -0
- package/dist/types/deploy/adapters/types.d.ts +3 -2
- package/dist/types/deploy/platforms/cloudflare.d.ts +10 -7
- package/dist/types/deploy/platforms/node.d.ts +3 -1
- package/dist/types/deploy/platforms/types.d.ts +18 -7
- package/dist/types/deploy/platforms/vercel.d.ts +20 -1
- package/dist/types/deploy/redirects.d.ts +17 -1
- package/dist/types/deploy/sitemap.d.ts +2 -1
- package/dist/types/deploy/vercel-negotiation.d.ts +42 -21
- package/dist/types/openapi/checks.d.ts +27 -0
- package/dist/types/openapi/graphql.d.ts +6 -0
- package/dist/types/openapi/model.d.ts +15 -4
- package/dist/types/openapi/parse.d.ts +3 -0
- package/dist/types/openapi/references.d.ts +16 -0
- package/dist/types/ratelimit/index.d.ts +1 -1
- package/dist/types/ratelimit/schema.d.ts +8 -0
- package/dist/types/ratelimit/upstash.d.ts +39 -14
- package/dist/types/reference/graphql.d.ts +76 -1
- package/dist/types/reference/index.d.ts +1 -1
- package/dist/types/reference/openapi.d.ts +2 -2
- package/dist/types/reference/options.d.ts +37 -1
- package/dist/types/reference/schema.d.ts +84 -0
- package/dist/types/search/adapters/registry.d.ts +3 -0
- package/dist/types/search/adapters/typesense.d.ts +14 -4
- package/dist/types/search/build.d.ts +3 -1
- package/dist/types/search/orama-index.d.ts +9 -9
- package/dist/types/search/sync/algolia.d.ts +5 -2
- package/dist/types/search/sync/index.d.ts +3 -1
- package/dist/types/search/sync/typesense.d.ts +11 -7
- package/dist/types/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 +31 -13
- package/docs/advanced/changelog.mdx +11 -0
- package/docs/advanced/skills.mdx +1 -1
- package/docs/cli/audit.mdx +30 -7
- package/docs/cli/doctor.mdx +5 -1
- package/docs/cli/evals.mdx +4 -4
- package/docs/cli/translate.mdx +1 -0
- package/docs/cli/validate.mdx +4 -3
- package/docs/configuration/analytics.mdx +1 -1
- package/docs/configuration/assistant.mdx +6 -2
- package/docs/configuration/customization.mdx +4 -2
- package/docs/configuration/export.mdx +5 -3
- package/docs/configuration/index.mdx +3 -2
- package/docs/configuration/rate-limiting.mdx +23 -2
- package/docs/configuration/search.mdx +37 -14
- package/docs/content/components.mdx +2 -2
- package/docs/content/frontmatter.mdx +5 -3
- package/docs/content/i18n.mdx +2 -2
- package/docs/content/includes.mdx +1 -1
- package/docs/content/navigation.mdx +4 -4
- package/docs/content/sources/contentful.mdx +7 -4
- package/docs/content/sources/custom.mdx +7 -3
- package/docs/content/sources/github-releases.mdx +10 -2
- package/docs/content/sources/index.mdx +3 -3
- package/docs/content/sources/notion.mdx +1 -1
- package/docs/content/sources/obsidian.mdx +1 -1
- package/docs/content/sources/payload.mdx +3 -2
- package/docs/content/sources/remote-mdx.mdx +4 -0
- package/docs/content/sources/sanity.mdx +2 -2
- package/docs/content/sources/strapi.mdx +3 -2
- package/docs/content/syntax.mdx +2 -2
- package/docs/discoverability/agent-discovery.mdx +1 -1
- package/docs/discoverability/index.mdx +1 -1
- package/docs/discoverability/json-api.mdx +2 -0
- package/docs/discoverability/llms-txt.mdx +1 -1
- package/docs/discoverability/markdown.mdx +3 -1
- package/docs/discoverability/mcp.mdx +4 -0
- package/docs/discoverability/sitemap-and-robots.mdx +1 -1
- package/docs/references/api-pages.mdx +1 -1
- package/docs/references/asyncapi.mdx +3 -1
- package/docs/references/graphql.mdx +13 -1
- package/docs/references/openapi.mdx +50 -8
- package/package.json +9 -9
- package/skills/blume-migrate/SKILL.md +1 -1
- package/skills/blume-migrate/references/docusaurus.md +4 -4
- package/skills/blume-migrate/references/fumadocs.md +17 -13
- package/skills/blume-migrate/references/nextra.md +8 -5
- package/skills/blume-migrate/references/starlight.md +9 -7
- package/src/ai/ask-context.ts +33 -3
- package/src/ai/ask-limits.ts +13 -0
- package/src/ai/changelog-markdown.ts +11 -6
- package/src/ai/component-markdown.ts +1 -1
- package/src/ai/cors.ts +12 -3
- package/src/ai/mcp/query.ts +14 -6
- package/src/ai/openapi-components.ts +28 -4
- package/src/ai/relative-links.ts +4 -38
- package/src/astro/generate.ts +78 -48
- package/src/astro/integration.ts +16 -13
- package/src/astro/markdown-negotiation.ts +3 -0
- package/src/astro/module-types.ts +3 -1
- package/src/astro/pages.ts +23 -0
- package/src/astro/templates.ts +125 -80
- package/src/audit/catalog.ts +19 -3
- package/src/audit/checks/links.ts +14 -1
- package/src/audit/checks/network.ts +110 -6
- package/src/audit/checks/redirects.ts +6 -4
- package/src/audit/checks/robots.ts +58 -2
- package/src/audit/run.ts +3 -0
- package/src/audit/types.ts +2 -0
- package/src/audit/url.ts +14 -5
- package/src/blume-modules.d.ts +5 -1
- package/src/cli/args.ts +51 -0
- package/src/cli/build-failure.ts +23 -0
- package/src/cli/commands/audit.ts +10 -1
- package/src/cli/commands/dev.ts +18 -2
- package/src/cli/commands/doctor.ts +45 -12
- package/src/cli/commands/eval.ts +36 -4
- package/src/cli/commands/init.ts +6 -4
- package/src/cli/commands/validate.ts +10 -1
- package/src/cli/init/scaffold.ts +3 -3
- package/src/cli/prepare.ts +6 -3
- package/src/cli/required-secrets.ts +1 -1
- package/src/components/content/ApiPlayground.astro +6 -2
- package/src/components/content/api-field.ts +4 -1
- package/src/components/content/api-page.ts +31 -7
- package/src/components/content/mermaid-element.ts +15 -1
- package/src/components/islands/hooks.ts +27 -1
- package/src/components/layout/PageActions.astro +139 -24
- package/src/components/layout/RootLayout.astro +10 -2
- package/src/components/layout/Search.astro +17 -3
- package/src/components/layout/TableOfContents.astro +24 -17
- package/src/components/layout/head-scripts.ts +6 -1
- package/src/components/layout/search/algolia.ts +10 -1
- package/src/components/layout/search/analytics.ts +42 -14
- package/src/components/layout/search/endpoint.ts +48 -5
- package/src/components/layout/search/pagefind.ts +114 -5
- package/src/components/layout/search/types.ts +12 -0
- package/src/components/layout/search/typesense.ts +18 -6
- package/src/components/openapi/AsyncApiOperation.astro +14 -7
- package/src/components/openapi/Authorization.astro +10 -0
- package/src/components/openapi/GraphqlOperation.astro +5 -0
- package/src/components/openapi/Operation.astro +24 -1
- package/src/components/openapi/ParametersTable.astro +8 -4
- package/src/components/openapi/Playground.astro +7 -1
- package/src/components/openapi/RequestBody.astro +19 -2
- package/src/components/openapi/Responses.astro +1 -0
- package/src/components/openapi/SchemaTable.astro +15 -3
- package/src/components/openapi/async-snippets.ts +61 -5
- package/src/components/openapi/async.ts +123 -29
- package/src/components/openapi/graphql-helpers.ts +35 -12
- package/src/components/openapi/helpers.ts +36 -2
- package/src/components/openapi/message-model.ts +54 -11
- package/src/components/openapi/message.ts +14 -4
- package/src/components/openapi/operation-model.ts +16 -7
- package/src/components/openapi/playground-client.ts +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 +10 -0
- package/src/components/openapi/snippets.ts +5 -3
- package/src/components/openapi/validate-json.ts +4 -3
- package/src/core/changelog-index.ts +31 -1
- package/src/core/component-diagnostics.ts +53 -0
- package/src/core/component-overrides.ts +32 -0
- package/src/core/config-input.ts +31 -3
- package/src/core/data.ts +2 -0
- package/src/core/diagnostics.ts +5 -0
- package/src/core/i18n-ui.ts +2 -0
- package/src/core/includes.ts +1 -1
- package/src/core/links.ts +47 -17
- package/src/core/probe.ts +26 -6
- package/src/core/project-graph.ts +59 -18
- package/src/core/redirect-patterns.ts +36 -7
- package/src/core/schema.ts +21 -2
- 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 +227 -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/remote.ts +72 -15
- package/src/core/sources/resolve.ts +11 -1
- package/src/core/sources/sanity.ts +43 -25
- package/src/core/sources/strapi.ts +2 -2
- package/src/core/types.ts +18 -0
- package/src/core/ui-packs/ar.ts +1 -0
- package/src/core/ui-packs/bg.ts +1 -0
- package/src/core/ui-packs/bn.ts +1 -0
- package/src/core/ui-packs/ca.ts +1 -0
- package/src/core/ui-packs/cs.ts +1 -0
- package/src/core/ui-packs/da.ts +1 -0
- package/src/core/ui-packs/de.ts +1 -0
- package/src/core/ui-packs/el.ts +1 -0
- package/src/core/ui-packs/es.ts +1 -0
- package/src/core/ui-packs/fa.ts +1 -0
- package/src/core/ui-packs/fi.ts +1 -0
- package/src/core/ui-packs/fr.ts +1 -0
- package/src/core/ui-packs/he.ts +1 -0
- package/src/core/ui-packs/hi.ts +1 -0
- package/src/core/ui-packs/hr.ts +1 -0
- package/src/core/ui-packs/hu.ts +1 -0
- package/src/core/ui-packs/id.ts +1 -0
- package/src/core/ui-packs/it.ts +1 -0
- package/src/core/ui-packs/ja.ts +1 -0
- package/src/core/ui-packs/ko.ts +1 -0
- package/src/core/ui-packs/nl.ts +1 -0
- package/src/core/ui-packs/no.ts +1 -0
- package/src/core/ui-packs/pl.ts +1 -0
- package/src/core/ui-packs/pt-br.ts +1 -0
- package/src/core/ui-packs/pt.ts +1 -0
- package/src/core/ui-packs/ro.ts +1 -0
- package/src/core/ui-packs/ru.ts +1 -0
- package/src/core/ui-packs/sk.ts +1 -0
- package/src/core/ui-packs/sr.ts +1 -0
- package/src/core/ui-packs/sv.ts +1 -0
- package/src/core/ui-packs/th.ts +1 -0
- package/src/core/ui-packs/tr.ts +1 -0
- package/src/core/ui-packs/uk.ts +1 -0
- package/src/core/ui-packs/vi.ts +1 -0
- package/src/core/ui-packs/zh-tw.ts +1 -0
- package/src/core/ui-packs/zh.ts +1 -0
- package/src/deploy/adapter-output.ts +7 -2
- package/src/deploy/adapters/cloudflare.ts +7 -5
- package/src/deploy/adapters/node.ts +47 -9
- package/src/deploy/adapters/types.ts +7 -3
- package/src/deploy/artifacts.ts +2 -1
- package/src/deploy/platforms/cloudflare.ts +13 -9
- package/src/deploy/platforms/netlify.ts +2 -1
- package/src/deploy/platforms/node.ts +12 -2
- package/src/deploy/platforms/types.ts +21 -7
- package/src/deploy/platforms/vercel.ts +113 -16
- package/src/deploy/redirects.ts +66 -6
- package/src/deploy/rss.ts +3 -1
- package/src/deploy/sitemap.ts +39 -5
- package/src/deploy/vercel-negotiation.ts +290 -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/relative-links.ts +3 -2
- package/src/openapi/checks.ts +273 -0
- package/src/openapi/graphql-build.ts +21 -0
- package/src/openapi/graphql.ts +11 -0
- package/src/openapi/model.ts +15 -3
- package/src/openapi/parse.ts +127 -2
- package/src/openapi/references.ts +43 -3
- package/src/openapi/source.ts +39 -14
- package/src/ratelimit/index.ts +1 -1
- package/src/ratelimit/runtime.ts +37 -19
- package/src/ratelimit/upstash.ts +40 -10
- package/src/reference/graphql.ts +15 -1
- package/src/reference/index.ts +1 -0
- package/src/reference/openapi.ts +2 -2
- package/src/reference/options.ts +29 -1
- package/src/registry/eject.ts +3 -1
- package/src/search/adapters/locale-scope.ts +30 -0
- package/src/search/adapters/typesense.ts +14 -4
- package/src/search/build.ts +21 -3
- package/src/search/orama-index.ts +163 -31
- package/src/search/source-pages.ts +29 -0
- package/src/search/sync/algolia.ts +99 -9
- package/src/search/sync/index.ts +52 -13
- package/src/search/sync/typesense.ts +72 -27
- package/src/sources/contentful.ts +12 -0
- package/src/sources/github-releases.ts +7 -1
- package/src/sources/shared.ts +3 -0
- package/src/theme/entry.ts +29 -3
- package/src/translate/validate.ts +23 -1
- package/dist/cli/chunk-0gz36akr.js.map +0 -12
- package/dist/cli/chunk-2n4ps1b3.js.map +0 -15
- package/dist/cli/chunk-43zcf4gz.js.map +0 -36
- package/dist/cli/chunk-4ejxbzee.js +0 -39
- package/dist/cli/chunk-4ejxbzee.js.map +0 -10
- package/dist/cli/chunk-4h8z9vv5.js.map +0 -16
- package/dist/cli/chunk-713mngdq.js.map +0 -14
- package/dist/cli/chunk-9xr4dgee.js.map +0 -10
- package/dist/cli/chunk-amrb6hgh.js +0 -145
- package/dist/cli/chunk-amrb6hgh.js.map +0 -11
- package/dist/cli/chunk-nd1821sk.js.map +0 -10
- package/dist/cli/chunk-rekqz4qg.js.map +0 -10
- package/dist/cli/chunk-ta27feev.js.map +0 -10
- package/dist/cli/chunk-xkz5xbtv.js.map +0 -213
- package/dist/cli/chunk-y5h4r2y0.js.map +0 -10
- /package/dist/cli/{chunk-gp84za0h.js.map → chunk-3v3ffbrj.js.map} +0 -0
- /package/dist/cli/{chunk-p804f3pe.js.map → chunk-8y2kmjv8.js.map} +0 -0
- /package/dist/cli/{chunk-2f7n4qzt.js.map → chunk-c1y538kd.js.map} +0 -0
- /package/dist/cli/{chunk-1n228xqb.js.map → chunk-c887fj0s.js.map} +0 -0
- /package/dist/cli/{chunk-cmtcnh9f.js.map → chunk-dzwehpy7.js.map} +0 -0
- /package/dist/cli/{chunk-ntv4qrt7.js.map → chunk-e9q7a2ak.js.map} +0 -0
- /package/dist/cli/{chunk-5wj2qwn2.js.map → chunk-ft9vfys6.js.map} +0 -0
- /package/dist/cli/{chunk-zhvd6adm.js.map → chunk-hx3xqnk9.js.map} +0 -0
- /package/dist/cli/{chunk-y4ykbark.js.map → chunk-kma9f6sf.js.map} +0 -0
- /package/dist/cli/{chunk-py62fewh.js.map → chunk-mrcccgnh.js.map} +0 -0
- /package/dist/cli/{chunk-2f3ndkpw.js.map → chunk-n0v7m8ry.js.map} +0 -0
- /package/dist/cli/{chunk-9geymqns.js.map → chunk-nq1d20w2.js.map} +0 -0
- /package/dist/cli/{chunk-g2z9x01v.js.map → chunk-nrns10mj.js.map} +0 -0
- /package/dist/cli/{chunk-e7vvk5ya.js.map → chunk-sds923fa.js.map} +0 -0
- /package/dist/cli/{chunk-yj17vs39.js.map → chunk-tdqhyxfz.js.map} +0 -0
- /package/dist/cli/{chunk-q3wxxq39.js.map → chunk-tphac74f.js.map} +0 -0
- /package/dist/cli/{chunk-6bm0xpgd.js.map → chunk-w1r4vase.js.map} +0 -0
package/src/core/ui-packs/uk.ts
CHANGED
package/src/core/ui-packs/vi.ts
CHANGED
package/src/core/ui-packs/zh.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { cp, mkdir, rm } from "node:fs/promises";
|
|
|
3
3
|
|
|
4
4
|
import { dirname, join } from "pathe";
|
|
5
5
|
|
|
6
|
+
import { normalizeBasePath } from "../core/base-path.ts";
|
|
6
7
|
import type { ResolvedConfig } from "../core/schema.ts";
|
|
7
8
|
import type { ProjectContext } from "../core/types.ts";
|
|
8
9
|
import type { ResolvedDeployment } from "./adapters/registry.ts";
|
|
@@ -30,7 +31,8 @@ export const deployOutputDir = (
|
|
|
30
31
|
* served. A static build serves `dist/` wherever it lands; a server build
|
|
31
32
|
* serves what its platform declares — the Build Output tree's `static/` half
|
|
32
33
|
* on Vercel, Astro's `build.client` dir (`dist/client/`) on Node and
|
|
33
|
-
* Cloudflare, `dist/` on Netlify.
|
|
34
|
+
* Cloudflare, `dist/` on Netlify. On Vercel and Cloudflare that's its
|
|
35
|
+
* `<base>/` directory under `deployment.base`, where the files land.
|
|
34
36
|
*/
|
|
35
37
|
export const deployStaticDir = (
|
|
36
38
|
config: ResolvedConfig,
|
|
@@ -38,7 +40,10 @@ export const deployStaticDir = (
|
|
|
38
40
|
): string => {
|
|
39
41
|
const { deployment } = config;
|
|
40
42
|
return deployment.options.output === "server"
|
|
41
|
-
? deployPlatform(deployment).serverStaticDir(
|
|
43
|
+
? deployPlatform(deployment).serverStaticDir(
|
|
44
|
+
context,
|
|
45
|
+
normalizeBasePath(deployment.options.base)
|
|
46
|
+
)
|
|
42
47
|
: distDir(context);
|
|
43
48
|
};
|
|
44
49
|
|
|
@@ -23,11 +23,13 @@ export const cloudflareAdapterSchema = adapterDescriptorSchema(
|
|
|
23
23
|
);
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
|
-
* Cloudflare
|
|
27
|
-
* `dist/server` (with a
|
|
28
|
-
* text/markdown`) and serves
|
|
29
|
-
*
|
|
30
|
-
* (`
|
|
26
|
+
* Cloudflare. A server build targets Workers only (`@astrojs/cloudflare`
|
|
27
|
+
* dropped Pages in v13): it emits a Worker into `dist/server` (with a
|
|
28
|
+
* generated wrapper that answers `Accept: text/markdown`) and serves
|
|
29
|
+
* `dist/client` through the ASSETS binding. A static build
|
|
30
|
+
* (`output: "static"`) never loads the adapter, and its `dist/` deploys to
|
|
31
|
+
* Pages or to Workers static assets. `@astrojs/cloudflare` is an optional
|
|
32
|
+
* peer: install it in the project (`npm install @astrojs/cloudflare`).
|
|
31
33
|
*/
|
|
32
34
|
export const cloudflare = (
|
|
33
35
|
options: CloudflareOptions = {}
|
|
@@ -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
|
@@ -445,7 +445,8 @@ export const publishBuildArtifacts = async (
|
|
|
445
445
|
await buildNarration(project, distDir, logger);
|
|
446
446
|
|
|
447
447
|
// Upload the index to a hosted provider (Algolia, Orama Cloud, Typesense).
|
|
448
|
-
// 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.
|
|
449
450
|
await syncSearchProvider(project, {
|
|
450
451
|
start: logger.info.bind(logger),
|
|
451
452
|
success: logger.info.bind(logger),
|
|
@@ -305,17 +305,21 @@ export const bindCloudflareRateLimit = async (
|
|
|
305
305
|
};
|
|
306
306
|
|
|
307
307
|
/**
|
|
308
|
-
* Cloudflare
|
|
309
|
-
* `dist/server` and serves
|
|
310
|
-
*
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
*
|
|
314
|
-
*
|
|
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.
|
|
315
318
|
*/
|
|
316
319
|
export const cloudflarePlatform: DeployPlatform = {
|
|
317
320
|
astro: {
|
|
318
|
-
config: { session: false },
|
|
321
|
+
config: () => ({ session: false }),
|
|
322
|
+
configOptions: [],
|
|
319
323
|
options: adapterOptions,
|
|
320
324
|
package: CLOUDFLARE_ADAPTER_PACKAGE,
|
|
321
325
|
},
|
|
@@ -350,5 +354,5 @@ export const cloudflarePlatform: DeployPlatform = {
|
|
|
350
354
|
// build, and hoists its own `_headers`/`_redirects` back up to `dist/client`.
|
|
351
355
|
serverClientUnderBase: true,
|
|
352
356
|
serverOutputDir: distDir,
|
|
353
|
-
serverStaticDir: clientDir,
|
|
357
|
+
serverStaticDir: (context, base) => join(clientDir(context), base),
|
|
354
358
|
};
|
|
@@ -118,7 +118,8 @@ export const emitNetlifyPatternRedirects = async (
|
|
|
118
118
|
*/
|
|
119
119
|
export const netlifyPlatform: DeployPlatform = {
|
|
120
120
|
astro: {
|
|
121
|
-
config: {},
|
|
121
|
+
config: () => ({}),
|
|
122
|
+
configOptions: [],
|
|
122
123
|
options: () => ({}),
|
|
123
124
|
package: NETLIFY_ADAPTER_PACKAGE,
|
|
124
125
|
},
|
|
@@ -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
|
},
|
|
@@ -2,7 +2,10 @@ import type { JsonValue } from "../../core/adapter.ts";
|
|
|
2
2
|
import type { BlumeProject } from "../../core/project-graph.ts";
|
|
3
3
|
import type { ResolvedConfig } from "../../core/schema.ts";
|
|
4
4
|
import type { ProjectContext } from "../../core/types.ts";
|
|
5
|
-
import type {
|
|
5
|
+
import type {
|
|
6
|
+
DeployAdapterKind,
|
|
7
|
+
ResolvedDeployOptions,
|
|
8
|
+
} from "../adapters/registry.ts";
|
|
6
9
|
import type { DeployOutput } from "../adapters/types.ts";
|
|
7
10
|
|
|
8
11
|
/**
|
|
@@ -15,8 +18,16 @@ import type { DeployOutput } from "../adapters/types.ts";
|
|
|
15
18
|
|
|
16
19
|
/** How the generated `astro.config.mjs` constructs the `@astrojs/*` adapter. */
|
|
17
20
|
export interface AstroAdapterSpec {
|
|
18
|
-
/**
|
|
19
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Top-level `defineConfig` entries the adapter needs beside itself, some
|
|
23
|
+
* of them set from the deployment's own options.
|
|
24
|
+
*/
|
|
25
|
+
config: (options: ResolvedDeployOptions) => Record<string, JsonValue>;
|
|
26
|
+
/**
|
|
27
|
+
* The deployment options `config` reads, which therefore stay out of the
|
|
28
|
+
* passthrough to the `@astrojs/*` constructor.
|
|
29
|
+
*/
|
|
30
|
+
configOptions: string[];
|
|
20
31
|
/** Blume's own constructor options; the user's passthrough is spread over them. */
|
|
21
32
|
options: (context: ProjectContext) => Record<string, JsonValue>;
|
|
22
33
|
/** The package the config imports the adapter from. */
|
|
@@ -115,13 +126,16 @@ export interface DeployPlatform {
|
|
|
115
126
|
/**
|
|
116
127
|
* Whether the adapter moves a server build's client output under
|
|
117
128
|
* `deployment.base` (`dist/client/<base>/`, the directory Astro then hands
|
|
118
|
-
* `astro:build:done`) while the platform keeps serving `
|
|
119
|
-
*
|
|
129
|
+
* `astro:build:done`) while the platform keeps serving `dist/client` as
|
|
130
|
+
* the assets root. The files the platform reads there, like `_headers`,
|
|
120
131
|
* belong above the directory Astro reports.
|
|
121
132
|
*/
|
|
122
133
|
serverClientUnderBase: boolean;
|
|
123
134
|
/** Where a server build's deploy bundle lands. */
|
|
124
135
|
serverOutputDir: (context: ProjectContext) => string;
|
|
125
|
-
/**
|
|
126
|
-
|
|
136
|
+
/**
|
|
137
|
+
* The directory a server build serves as static files, given the normalized
|
|
138
|
+
* `deployment.base` for a platform that serves them from `<dir>/<base>/`.
|
|
139
|
+
*/
|
|
140
|
+
serverStaticDir: (context: ProjectContext, base: string) => string;
|
|
127
141
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
|
-
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
3
3
|
|
|
4
|
-
import { join } from "pathe";
|
|
4
|
+
import { dirname, join } from "pathe";
|
|
5
5
|
|
|
6
6
|
import { crossOriginDiscoveryPaths } from "../../ai/ai-catalog.ts";
|
|
7
7
|
import {
|
|
@@ -20,7 +20,10 @@ import {
|
|
|
20
20
|
SIGNATURES_DIRECTORY_PATH,
|
|
21
21
|
SIGNATURES_DIRECTORY_TYPE,
|
|
22
22
|
} from "../../ai/web-bot-auth.ts";
|
|
23
|
+
import { mountBasePath, normalizeBasePath } from "../../core/base-path.ts";
|
|
23
24
|
import type { BlumeProject } from "../../core/project-graph.ts";
|
|
25
|
+
import { isPatternPath, regexRedirect } from "../../core/redirect-patterns.ts";
|
|
26
|
+
import type { ResolvedConfig } from "../../core/schema.ts";
|
|
24
27
|
import type { ProjectContext } from "../../core/types.ts";
|
|
25
28
|
import { VERCEL_ADAPTER_PACKAGE } from "../adapters/vercel.ts";
|
|
26
29
|
import {
|
|
@@ -37,7 +40,9 @@ import {
|
|
|
37
40
|
import {
|
|
38
41
|
injectNegotiationRoutes,
|
|
39
42
|
injectRedirectRoutes,
|
|
43
|
+
rebaseAdapterRoutes,
|
|
40
44
|
} from "../vercel-negotiation.ts";
|
|
45
|
+
import type { VercelRoute } from "../vercel-negotiation.ts";
|
|
41
46
|
import { adapterRoot, toSiteUrl } from "./paths.ts";
|
|
42
47
|
import type { BuildLog, DeployPlatform, RedirectFile } from "./types.ts";
|
|
43
48
|
|
|
@@ -56,6 +61,14 @@ export const VERCEL_JSON_FILE: RedirectFile = {
|
|
|
56
61
|
const buildOutputDir = (context: ProjectContext): string =>
|
|
57
62
|
join(adapterRoot(context), ".vercel", "output");
|
|
58
63
|
|
|
64
|
+
/** The static files a server build serves, under the base's directory. */
|
|
65
|
+
const staticDir = (context: ProjectContext, base: string): string =>
|
|
66
|
+
join(buildOutputDir(context), "static", base);
|
|
67
|
+
|
|
68
|
+
/** The project's normalized `deployment.base`, `""` for none. */
|
|
69
|
+
const deploymentBase = (project: BlumeProject): string =>
|
|
70
|
+
normalizeBasePath(project.config.deployment.options.base);
|
|
71
|
+
|
|
59
72
|
/**
|
|
60
73
|
* Refuse to ship a function bundle that would crash at runtime: a bare import
|
|
61
74
|
* the adapter's dependency trace silently dropped (see
|
|
@@ -99,18 +112,21 @@ export const emitVercelNegotiation = async (
|
|
|
99
112
|
log: BuildLog
|
|
100
113
|
): Promise<void> => {
|
|
101
114
|
const { config, context } = project;
|
|
102
|
-
const
|
|
103
|
-
const configPath = join(outputDir, "config.json");
|
|
115
|
+
const configPath = join(buildOutputDir(context), "config.json");
|
|
104
116
|
if (!existsSync(configPath)) {
|
|
105
117
|
return;
|
|
106
118
|
}
|
|
119
|
+
const base = deploymentBase(project);
|
|
107
120
|
const routePaths = markdownRoutePaths(project);
|
|
121
|
+
// Keyed by the file's path in `static/`, under the base's directory.
|
|
108
122
|
const overrides: Record<string, string> = {};
|
|
109
123
|
if (hasApiCatalog(config)) {
|
|
110
|
-
overrides[API_CATALOG_PATH.slice(1)] =
|
|
124
|
+
overrides[mountBasePath(base, API_CATALOG_PATH).slice(1)] =
|
|
125
|
+
API_CATALOG_TYPE;
|
|
111
126
|
}
|
|
112
127
|
if (config.agents.webBotAuth.keys.length > 0) {
|
|
113
|
-
overrides[SIGNATURES_DIRECTORY_PATH.slice(1)] =
|
|
128
|
+
overrides[mountBasePath(base, SIGNATURES_DIRECTORY_PATH).slice(1)] =
|
|
129
|
+
SIGNATURES_DIRECTORY_TYPE;
|
|
114
130
|
}
|
|
115
131
|
// The homepage rewrite serves `/index.md` from the static layer, so its
|
|
116
132
|
// `x-markdown-tokens` estimate has to ride the routing config; the runtime
|
|
@@ -120,7 +136,7 @@ export const emitVercelNegotiation = async (
|
|
|
120
136
|
// The Markdown and JSON 404 routes point at the prerendered twins; only
|
|
121
137
|
// wire each when the build actually emitted it (a project that owns `/404`
|
|
122
138
|
// gets none).
|
|
123
|
-
const
|
|
139
|
+
const builtDir = staticDir(context, base);
|
|
124
140
|
const injected = injectNegotiationRoutes(
|
|
125
141
|
await readFile(configPath, "utf-8"),
|
|
126
142
|
routePaths,
|
|
@@ -128,13 +144,14 @@ export const emitVercelNegotiation = async (
|
|
|
128
144
|
overrides,
|
|
129
145
|
home ? markdownTokenCount(agentMarkdown(home)) : undefined,
|
|
130
146
|
{
|
|
131
|
-
json: existsSync(join(
|
|
132
|
-
markdown: existsSync(join(
|
|
147
|
+
json: existsSync(join(builtDir, "404.json")),
|
|
148
|
+
markdown: existsSync(join(builtDir, "404.md")),
|
|
133
149
|
},
|
|
134
150
|
crossOriginDiscoveryPaths(config),
|
|
135
151
|
// Downloaded content assets are prerendered static files; only a build
|
|
136
152
|
// that has them needs the SVG sandbox route.
|
|
137
|
-
existsSync(join(
|
|
153
|
+
existsSync(join(builtDir, "blume-assets")),
|
|
154
|
+
base
|
|
138
155
|
);
|
|
139
156
|
if (injected === null) {
|
|
140
157
|
log.warn(
|
|
@@ -175,6 +192,76 @@ export const emitVercelPatternRedirects = async (
|
|
|
175
192
|
await writeFile(configPath, injected, "utf-8");
|
|
176
193
|
};
|
|
177
194
|
|
|
195
|
+
type Redirect = ResolvedConfig["redirects"][number];
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* The exact redirects as Build Output routes, matched the way the pattern ones
|
|
199
|
+
* are (see `regexRedirect`): the served path, a trailing slash optional.
|
|
200
|
+
*/
|
|
201
|
+
const exactRedirectRoutes = (redirects: Redirect[]): VercelRoute[] =>
|
|
202
|
+
redirects
|
|
203
|
+
.filter((redirect) => !isPatternPath(redirect.from))
|
|
204
|
+
.map(({ from, status, to }) => ({
|
|
205
|
+
headers: { Location: encodeURI(to) },
|
|
206
|
+
src: regexRedirect({ parts: [{ kind: "text", text: from }], status, to })
|
|
207
|
+
.source,
|
|
208
|
+
status,
|
|
209
|
+
}));
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Move a server build's static files under `deployment.base`.
|
|
213
|
+
* `@astrojs/vercel` copies them to the root of the Build Output tree's
|
|
214
|
+
* `static/`, while the pages request `<base>/_astro/…` and link to
|
|
215
|
+
* `<base>/…`, so nothing the site asks for would be found. Moved to
|
|
216
|
+
* `static/<base>/`, they're served at the base, as the routes that
|
|
217
|
+
* {@link rebaseVercelRoutes} moves there expect.
|
|
218
|
+
*/
|
|
219
|
+
export const moveStaticUnderBase = async (
|
|
220
|
+
context: ProjectContext,
|
|
221
|
+
base: string
|
|
222
|
+
): Promise<void> => {
|
|
223
|
+
const root = staticDir(context, "");
|
|
224
|
+
if (!base || !existsSync(root)) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
// Through a sibling, since the target lies inside the directory it moves.
|
|
228
|
+
const staging = join(buildOutputDir(context), "static-unbased");
|
|
229
|
+
await rename(root, staging);
|
|
230
|
+
const target = staticDir(context, base);
|
|
231
|
+
await mkdir(dirname(target), { recursive: true });
|
|
232
|
+
await rename(staging, target);
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Move the adapter's routing config under `deployment.base` to match the
|
|
237
|
+
* static files (see `rebaseAdapterRoutes`), its exact redirects rebuilt from
|
|
238
|
+
* the configured ones. Resolves to false when the config can't be read: the
|
|
239
|
+
* adapter's routes would then miss every path under the base.
|
|
240
|
+
*/
|
|
241
|
+
export const rebaseVercelRoutes = async (
|
|
242
|
+
project: BlumeProject,
|
|
243
|
+
log: BuildLog
|
|
244
|
+
): Promise<boolean> => {
|
|
245
|
+
const base = deploymentBase(project);
|
|
246
|
+
const configPath = join(buildOutputDir(project.context), "config.json");
|
|
247
|
+
if (!base || !existsSync(configPath)) {
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
250
|
+
const rebased = rebaseAdapterRoutes(
|
|
251
|
+
await readFile(configPath, "utf-8"),
|
|
252
|
+
base,
|
|
253
|
+
exactRedirectRoutes(platformRedirects(project))
|
|
254
|
+
);
|
|
255
|
+
if (rebased === null) {
|
|
256
|
+
log.error(
|
|
257
|
+
`Could not move the routes in .vercel/output/config.json under the deployment base "${base}", so the site would not be served there.`
|
|
258
|
+
);
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
await writeFile(configPath, rebased, "utf-8");
|
|
262
|
+
return true;
|
|
263
|
+
};
|
|
264
|
+
|
|
178
265
|
/**
|
|
179
266
|
* Vercel. A server build's Build Output tree lands at `.vercel/output` — at
|
|
180
267
|
* the project root, because the adapter is handed that root up front: its
|
|
@@ -183,11 +270,14 @@ export const emitVercelPatternRedirects = async (
|
|
|
183
270
|
* Static assets are served from the tree's `static/` half, so the deploy
|
|
184
271
|
* artifacts are written there; headers (the discovery files', the sandbox on
|
|
185
272
|
* downloaded SVGs) arrive through the routing config rather than a
|
|
186
|
-
* `_headers` file, which Vercel never reads.
|
|
273
|
+
* `_headers` file, which Vercel never reads. The adapter ignores
|
|
274
|
+
* `deployment.base`, so under one the build moves the static files and the
|
|
275
|
+
* routes beneath it.
|
|
187
276
|
*/
|
|
188
277
|
export const vercelPlatform: DeployPlatform = {
|
|
189
278
|
astro: {
|
|
190
|
-
config: {},
|
|
279
|
+
config: () => ({}),
|
|
280
|
+
configOptions: [],
|
|
191
281
|
options: () => ({}),
|
|
192
282
|
package: VERCEL_ADAPTER_PACKAGE,
|
|
193
283
|
},
|
|
@@ -210,12 +300,19 @@ export const vercelPlatform: DeployPlatform = {
|
|
|
210
300
|
if (!ok) {
|
|
211
301
|
return false;
|
|
212
302
|
}
|
|
303
|
+
// A verify build moves its static files too, where the budget gate reads
|
|
304
|
+
// them (`serverStaticDir`).
|
|
305
|
+
await moveStaticUnderBase(context, deploymentBase(project));
|
|
213
306
|
// An isolated verify only proves the bundle would ship; the routing
|
|
214
307
|
// config is a deploy artifact and stays untouched.
|
|
215
|
-
if (
|
|
216
|
-
|
|
217
|
-
|
|
308
|
+
if (isolated) {
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
if (!(await rebaseVercelRoutes(project, log))) {
|
|
312
|
+
return false;
|
|
218
313
|
}
|
|
314
|
+
await emitVercelNegotiation(project, log);
|
|
315
|
+
await emitVercelPatternRedirects(project, log);
|
|
219
316
|
return true;
|
|
220
317
|
},
|
|
221
318
|
hiddenRuntime: {
|
|
@@ -231,5 +328,5 @@ export const vercelPlatform: DeployPlatform = {
|
|
|
231
328
|
redirectFiles: [VERCEL_JSON_FILE],
|
|
232
329
|
serverClientUnderBase: false,
|
|
233
330
|
serverOutputDir: buildOutputDir,
|
|
234
|
-
serverStaticDir:
|
|
331
|
+
serverStaticDir: staticDir,
|
|
235
332
|
};
|
package/src/deploy/redirects.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
normalizeBasePath,
|
|
3
|
+
normalizePath,
|
|
4
|
+
stripBasePath,
|
|
3
5
|
withAuthoredBasePath,
|
|
4
6
|
withBasePath,
|
|
5
7
|
withComposedBasePath,
|
|
@@ -11,6 +13,7 @@ import {
|
|
|
11
13
|
compileRedirects,
|
|
12
14
|
exactFirst,
|
|
13
15
|
expandRedirect,
|
|
16
|
+
isPatternPath,
|
|
14
17
|
underscoreRedirect,
|
|
15
18
|
vercelRedirect,
|
|
16
19
|
} from "../core/redirect-patterns.ts";
|
|
@@ -109,9 +112,60 @@ export const applyBaseToPlatformRedirects = (
|
|
|
109
112
|
: redirects;
|
|
110
113
|
};
|
|
111
114
|
|
|
115
|
+
/**
|
|
116
|
+
* The raw-Markdown copies Blume serves beside every page (`/guide.md`,
|
|
117
|
+
* `/guide.mdx`; see `rawMarkdownEndpointTemplate`).
|
|
118
|
+
*/
|
|
119
|
+
const MIRROR_EXTENSIONS = [".md", ".mdx"] as const;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Where a page's Markdown copy is served, from the page's served path and the
|
|
123
|
+
* deployment base that path carries: the endpoints name the root `index`.
|
|
124
|
+
*/
|
|
125
|
+
const mirrorPath = (path: string, base: string, extension: string): string => {
|
|
126
|
+
const route = stripBasePath(base, path);
|
|
127
|
+
return `${base}${route === "/" ? "/index" : route}${extension}`;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Based `redirects`, each exact one that moves a page followed by the same
|
|
132
|
+
* redirect for the page's Markdown copies: from a path no page is served at
|
|
133
|
+
* to one a page is, `/old.md` goes to `/new.md` (and `.mdx` alike), where it
|
|
134
|
+
* would otherwise 404 for an agent still reading the old URL. A pattern gets
|
|
135
|
+
* none; one that carries its capture over (`/beta/:slug*` → `/v2/:slug*`)
|
|
136
|
+
* already moves `/beta/guide.md` along. `pages` are the served page routes
|
|
137
|
+
* (carrying `basePath`, not `deployment.base`), and `bases` the deployment
|
|
138
|
+
* base each end carries: Astro's config leaves it off `from` (see
|
|
139
|
+
* {@link applyBaseToAstroRedirects}).
|
|
140
|
+
*/
|
|
141
|
+
export const withMirrorRedirects = (
|
|
142
|
+
redirects: Redirect[],
|
|
143
|
+
pages: RouteSet,
|
|
144
|
+
bases: { from: string; to: string }
|
|
145
|
+
): Redirect[] =>
|
|
146
|
+
redirects.flatMap((redirect) => {
|
|
147
|
+
const from = normalizePath(redirect.from);
|
|
148
|
+
const to = normalizePath(redirect.to);
|
|
149
|
+
const movesPage =
|
|
150
|
+
!isPatternPath(redirect.from) &&
|
|
151
|
+
servesRoute(pages, stripBasePath(bases.to, to)) &&
|
|
152
|
+
!servesRoute(pages, stripBasePath(bases.from, from));
|
|
153
|
+
return movesPage
|
|
154
|
+
? [
|
|
155
|
+
redirect,
|
|
156
|
+
...MIRROR_EXTENSIONS.map((extension) => ({
|
|
157
|
+
from: mirrorPath(from, bases.from, extension),
|
|
158
|
+
status: redirect.status,
|
|
159
|
+
to: mirrorPath(to, bases.to, extension),
|
|
160
|
+
})),
|
|
161
|
+
]
|
|
162
|
+
: [redirect];
|
|
163
|
+
});
|
|
164
|
+
|
|
112
165
|
/**
|
|
113
166
|
* The configured redirects as the host platform matches them, via
|
|
114
|
-
* {@link applyBaseToPlatformRedirects}
|
|
167
|
+
* {@link applyBaseToPlatformRedirects} plus the Markdown copies of each moved
|
|
168
|
+
* page ({@link withMirrorRedirects}), exact paths ahead of patterns: hosts
|
|
115
169
|
* try rules in order, and an exact redirect wins over a pattern that also
|
|
116
170
|
* covers its path. The one basing every consumer must share: the emitted
|
|
117
171
|
* redirect files and the server wrappers all compare these paths against
|
|
@@ -122,12 +176,18 @@ export const platformRedirects = (project: {
|
|
|
122
176
|
manifest: Pick<BlumeProject["manifest"], "routes">;
|
|
123
177
|
}): Redirect[] => {
|
|
124
178
|
const { config } = project;
|
|
179
|
+
const base = normalizeBasePath(config.deployment.options.base);
|
|
180
|
+
const pages = routeSetFor(project.manifest.routes);
|
|
125
181
|
return exactFirst(
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
182
|
+
withMirrorRedirects(
|
|
183
|
+
applyBaseToPlatformRedirects(
|
|
184
|
+
config.redirects,
|
|
185
|
+
config.basePath,
|
|
186
|
+
base,
|
|
187
|
+
pages
|
|
188
|
+
),
|
|
189
|
+
pages,
|
|
190
|
+
{ from: base, to: base }
|
|
131
191
|
)
|
|
132
192
|
);
|
|
133
193
|
};
|
package/src/deploy/rss.ts
CHANGED
|
@@ -78,7 +78,9 @@ export const buildRssFeeds = (project: BlumeProject): RssFeed[] => {
|
|
|
78
78
|
const items: RssItem[] = pages
|
|
79
79
|
.map((page) => ({
|
|
80
80
|
date: pageDate(page),
|
|
81
|
-
|
|
81
|
+
// A page with only a meta description (a GitHub release, whose
|
|
82
|
+
// summary goes in `seo.description`) still describes its item.
|
|
83
|
+
description: page.description ?? page.meta.seo.description,
|
|
82
84
|
// Encode like the sitemap does: a route with spaces or non-ASCII
|
|
83
85
|
// must still yield a valid <link>/<guid> URL after XML decoding.
|
|
84
86
|
link: encodeURI(`${base}${mountBasePath(deployBase, page.route)}`),
|