blume 1.7.2 → 2.0.0
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 +19 -0
- package/CHANGELOG.md +227 -0
- package/README.md +34 -21
- package/dist/cli/chunk-11j0384y.js +148 -0
- package/dist/cli/chunk-11j0384y.js.map +10 -0
- package/dist/cli/{chunk-xhtpx3ff.js → chunk-1w8dp3qb.js} +17 -16
- package/dist/cli/{chunk-xhtpx3ff.js.map → chunk-1w8dp3qb.js.map} +3 -3
- package/dist/cli/chunk-2q1dwty4.js +75 -0
- package/dist/cli/chunk-2q1dwty4.js.map +11 -0
- package/dist/cli/chunk-41za066z.js +122 -0
- package/dist/cli/chunk-41za066z.js.map +11 -0
- package/dist/cli/chunk-5a2z0198.js +133 -0
- package/dist/cli/chunk-5a2z0198.js.map +10 -0
- package/dist/cli/{chunk-9he6crym.js → chunk-6k8vp3ta.js} +25 -13
- package/dist/cli/{chunk-9he6crym.js.map → chunk-6k8vp3ta.js.map} +4 -4
- package/dist/cli/{chunk-mt76t7dj.js → chunk-79njf86q.js} +133 -54
- package/dist/cli/chunk-79njf86q.js.map +11 -0
- package/dist/cli/{chunk-3w7b2vcx.js → chunk-7ez8ny0t.js} +2 -2
- package/dist/cli/{chunk-688e0dde.js → chunk-88cpgt6h.js} +1 -1
- package/dist/cli/chunk-a9kptbw5.js +361 -0
- package/dist/cli/chunk-a9kptbw5.js.map +14 -0
- package/dist/cli/chunk-abh8yjkn.js +31 -0
- package/dist/cli/chunk-abh8yjkn.js.map +10 -0
- package/dist/cli/chunk-b5aj94ah.js +91 -0
- package/dist/cli/chunk-b5aj94ah.js.map +10 -0
- package/dist/cli/{chunk-hs3gbh8p.js → chunk-bctazmbk.js} +9 -5
- package/dist/cli/chunk-bctazmbk.js.map +10 -0
- package/dist/cli/chunk-beat36xx.js +279 -0
- package/dist/cli/chunk-beat36xx.js.map +10 -0
- package/dist/cli/chunk-bnbmcwfb.js +145 -0
- package/dist/cli/chunk-bnbmcwfb.js.map +11 -0
- package/dist/cli/{chunk-9bkjd11x.js → chunk-bw22s759.js} +15 -5
- package/dist/cli/{chunk-9bkjd11x.js.map → chunk-bw22s759.js.map} +4 -4
- package/dist/cli/chunk-by2290sx.js +39 -0
- package/dist/cli/chunk-by2290sx.js.map +10 -0
- package/dist/cli/chunk-d1tadaw7.js +79 -0
- package/dist/cli/chunk-d1tadaw7.js.map +10 -0
- package/dist/cli/{chunk-t3tj0dgr.js → chunk-d80hr03s.js} +24 -19
- package/dist/cli/chunk-d80hr03s.js.map +15 -0
- package/dist/cli/chunk-ernrthtr.js +97 -0
- package/dist/cli/chunk-ernrthtr.js.map +10 -0
- package/dist/cli/chunk-f2972sbt.js +374 -0
- package/dist/cli/chunk-f2972sbt.js.map +10 -0
- package/dist/cli/{chunk-exeeb35e.js → chunk-f7t03s3g.js} +2 -2
- package/dist/cli/{chunk-2z47ypj8.js → chunk-fa25z98p.js} +16 -3
- package/dist/cli/chunk-fa25z98p.js.map +11 -0
- package/dist/cli/{chunk-12dxjqk7.js → chunk-fh5hj5jt.js} +44 -21
- package/dist/cli/chunk-fh5hj5jt.js.map +10 -0
- package/dist/cli/{chunk-8cd8tj54.js → chunk-j8mw0za6.js} +86 -57
- package/dist/cli/chunk-j8mw0za6.js.map +35 -0
- package/dist/cli/chunk-jts8mvcz.js +106 -0
- package/dist/cli/{chunk-2mzebbbz.js.map → chunk-jts8mvcz.js.map} +6 -4
- package/dist/cli/{chunk-ejjx8znq.js → chunk-mnqj32sj.js} +505 -536
- package/dist/cli/chunk-mnqj32sj.js.map +12 -0
- package/dist/cli/{chunk-196vjxp9.js → chunk-mwt1k8n7.js} +100 -372
- package/dist/cli/chunk-mwt1k8n7.js.map +10 -0
- package/dist/cli/chunk-nk3ts2xk.js +51 -0
- package/dist/cli/chunk-nk3ts2xk.js.map +10 -0
- package/dist/cli/{chunk-n9sra6sy.js → chunk-pat2zzwc.js} +10 -14
- package/dist/cli/{chunk-n9sra6sy.js.map → chunk-pat2zzwc.js.map} +2 -2
- package/dist/cli/chunk-pnnvybbk.js +176 -0
- package/dist/cli/chunk-pnnvybbk.js.map +11 -0
- package/dist/cli/{chunk-cvky9gb2.js → chunk-sqn5t4q0.js} +81 -87
- package/dist/cli/chunk-sqn5t4q0.js.map +10 -0
- package/dist/cli/{chunk-eevwt1sc.js → chunk-tzne8qfq.js} +15 -15
- package/dist/cli/{chunk-eevwt1sc.js.map → chunk-tzne8qfq.js.map} +1 -1
- package/dist/cli/chunk-xaz13gwg.js +12449 -0
- package/dist/cli/chunk-xaz13gwg.js.map +182 -0
- package/dist/cli/chunk-y3e45rc8.js +102 -0
- package/dist/cli/chunk-y3e45rc8.js.map +10 -0
- package/dist/cli/chunk-z01ze5c1.js +261 -0
- package/dist/cli/chunk-z01ze5c1.js.map +10 -0
- package/dist/cli/{chunk-5n7t497w.js → chunk-z1f5arsg.js} +247 -755
- package/dist/cli/chunk-z1f5arsg.js.map +36 -0
- package/dist/cli/{chunk-hdm2dkd2.js → chunk-zg2gtj10.js} +1086 -2596
- package/dist/cli/chunk-zg2gtj10.js.map +35 -0
- package/dist/cli/{chunk-ppfvdcd4.js → chunk-zxccj738.js} +1 -1
- package/dist/cli/index.js +214 -57
- package/dist/cli/index.js.map +8 -7
- package/dist/types/ai/agent-readability.d.ts +52 -0
- package/dist/types/ai/ai-catalog.d.ts +42 -0
- package/dist/types/ai/api/paths.d.ts +17 -0
- package/dist/types/ai/api-catalog.d.ts +18 -0
- package/dist/types/ai/ask.d.ts +368 -0
- package/dist/types/ai/changelog-markdown.d.ts +2 -0
- package/dist/types/ai/component-markdown.d.ts +2 -2
- package/dist/types/ai/index.d.ts +24 -0
- package/dist/types/ai/link-headers.d.ts +24 -0
- package/dist/types/ai/llms.d.ts +25 -0
- package/dist/types/ai/markdown.d.ts +45 -0
- package/dist/types/ai/mcp/discovery.d.ts +68 -0
- package/dist/types/ai/mcp/tools.d.ts +16 -0
- package/dist/types/ai/openapi-components.d.ts +43 -0
- package/dist/types/ai/relative-links.d.ts +26 -0
- package/dist/types/ai/serializers.d.ts +15 -0
- package/dist/types/ai/skills.d.ts +42 -0
- package/dist/types/ai/tar.d.ts +25 -0
- package/dist/types/ai/visibility.d.ts +17 -0
- package/dist/types/ai/web-bot-auth.d.ts +16 -0
- package/dist/types/analytics/adobe.d.ts +35 -0
- package/dist/types/analytics/amplitude.d.ts +50 -0
- package/dist/types/analytics/clarity.d.ts +31 -0
- package/dist/types/analytics/clearbit.d.ts +29 -0
- package/dist/types/analytics/cloudflare.d.ts +41 -0
- package/dist/types/analytics/fathom.d.ts +41 -0
- package/dist/types/analytics/google-analytics.d.ts +44 -0
- package/dist/types/analytics/google-tag-manager.d.ts +40 -0
- package/dist/types/analytics/head.d.ts +30 -0
- package/dist/types/analytics/heap.d.ts +40 -0
- package/dist/types/analytics/hightouch.d.ts +44 -0
- package/dist/types/analytics/hotjar.d.ts +33 -0
- package/dist/types/analytics/index.d.ts +61 -0
- package/dist/types/analytics/inline.d.ts +17 -0
- package/dist/types/analytics/logrocket.d.ts +44 -0
- package/dist/types/analytics/mixpanel.d.ts +67 -0
- package/dist/types/analytics/pirsch.d.ts +42 -0
- package/dist/types/analytics/plausible.d.ts +56 -0
- package/dist/types/analytics/posthog.d.ts +45 -0
- package/dist/types/analytics/schema.d.ts +320 -0
- package/dist/types/analytics/script.d.ts +46 -0
- package/dist/types/analytics/segment.d.ts +50 -0
- package/dist/types/analytics/vercel.d.ts +48 -0
- package/dist/types/astro/integration.d.ts +76 -0
- package/dist/types/astro/markdown-negotiation.d.ts +23 -0
- package/dist/types/astro/module-types.d.ts +14 -0
- package/dist/types/astro/pages.d.ts +44 -0
- package/dist/types/cli/env.d.ts +12 -0
- package/dist/types/cli/init/scaffold.d.ts +154 -0
- package/dist/types/components/layout/nav-utils.d.ts +11 -0
- package/dist/types/core/adapter.d.ts +47 -0
- package/dist/types/core/api-name.d.ts +7 -0
- package/dist/types/core/changelog-index.d.ts +13 -0
- package/dist/types/core/config-input.d.ts +209 -505
- package/dist/types/core/config.d.ts +60 -34
- package/dist/types/core/content-assets.d.ts +76 -0
- package/dist/types/core/custom-pages.d.ts +33 -0
- package/dist/types/core/data.d.ts +28 -11
- package/dist/types/core/define-components.d.ts +12 -9
- package/dist/types/core/deployment-env.d.ts +6 -11
- package/dist/types/core/frontmatter.d.ts +10 -0
- package/dist/types/core/graph.d.ts +18 -0
- package/dist/types/core/heading-markers.d.ts +54 -0
- package/dist/types/core/i18n-ui.d.ts +6 -2
- package/dist/types/core/i18n.d.ts +87 -0
- package/dist/types/core/includes.d.ts +138 -0
- package/dist/types/core/last-modified.d.ts +47 -0
- package/dist/types/core/links.d.ts +95 -0
- package/dist/types/core/locale-links.d.ts +60 -0
- package/dist/types/core/manifest.d.ts +17 -0
- package/dist/types/core/meta.d.ts +38 -0
- package/dist/types/core/nav-diagnostics.d.ts +26 -0
- package/dist/types/core/navigation.d.ts +6 -0
- package/dist/types/core/node-require.d.ts +19 -0
- package/dist/types/core/package-json.d.ts +13 -0
- package/dist/types/core/probe.d.ts +42 -0
- package/dist/types/core/project-graph.d.ts +51 -0
- package/dist/types/core/project.d.ts +2 -0
- package/dist/types/core/safe-href.d.ts +2 -0
- package/dist/types/core/safe-links.d.ts +26 -0
- package/dist/types/core/schema.d.ts +2291 -441
- package/dist/types/core/site-url.d.ts +16 -0
- package/dist/types/core/sources/assets.d.ts +36 -0
- package/dist/types/core/sources/cache.d.ts +37 -0
- package/dist/types/core/sources/collection.d.ts +28 -0
- package/dist/types/core/sources/contentful-rich-text.d.ts +31 -0
- package/dist/types/core/sources/contentful.d.ts +40 -0
- package/dist/types/core/sources/filesystem.d.ts +24 -0
- package/dist/types/core/sources/github-releases.d.ts +31 -0
- package/dist/types/core/sources/json.d.ts +30 -0
- package/dist/types/core/sources/lexical.d.ts +19 -0
- package/dist/types/core/sources/lower.d.ts +75 -0
- package/dist/types/core/sources/mdx-remote.d.ts +28 -0
- package/dist/types/core/sources/normalize.d.ts +147 -0
- package/dist/types/core/sources/notion.d.ts +131 -0
- package/dist/types/core/sources/obsidian.d.ts +46 -0
- package/dist/types/core/sources/payload.d.ts +39 -0
- package/dist/types/core/sources/portable-text.d.ts +42 -0
- package/dist/types/core/sources/read.d.ts +23 -0
- package/dist/types/core/sources/remote.d.ts +74 -0
- package/dist/types/core/sources/resolve.d.ts +19 -0
- package/dist/types/core/sources/sanity.d.ts +43 -0
- package/dist/types/core/sources/strapi-blocks.d.ts +12 -0
- package/dist/types/core/sources/strapi.d.ts +33 -0
- package/dist/types/core/sources/types.d.ts +7 -0
- package/dist/types/core/sources/watch.d.ts +45 -0
- package/dist/types/core/text-width.d.ts +11 -0
- package/dist/types/core/types.d.ts +20 -1
- package/dist/types/core/unrecognized-keys.d.ts +7 -0
- package/dist/types/core/versions.d.ts +72 -0
- package/dist/types/core/yaml.d.ts +9 -0
- package/dist/types/deploy/adapter-output.d.ts +45 -0
- package/dist/types/deploy/adapters/cloudflare.d.ts +40 -0
- package/dist/types/deploy/adapters/index.d.ts +29 -0
- package/dist/types/deploy/adapters/netlify.d.ts +37 -0
- package/dist/types/deploy/adapters/node.d.ts +37 -0
- package/dist/types/deploy/adapters/registry.d.ts +133 -0
- package/dist/types/deploy/adapters/types.d.ts +71 -0
- package/dist/types/deploy/adapters/vercel.d.ts +38 -0
- package/dist/types/deploy/artifacts.d.ts +65 -0
- package/dist/types/deploy/cloudflare-negotiation.d.ts +196 -0
- package/dist/types/deploy/function-bundle.d.ts +80 -0
- package/dist/types/deploy/headers.d.ts +50 -0
- package/dist/types/deploy/node-headers.d.ts +42 -0
- package/dist/types/deploy/platforms/cloudflare.d.ts +40 -0
- package/dist/types/deploy/platforms/index.d.ts +18 -0
- package/dist/types/deploy/platforms/netlify.d.ts +13 -0
- package/dist/types/deploy/platforms/node.d.ts +11 -0
- package/dist/types/deploy/platforms/paths.d.ts +27 -0
- package/dist/types/deploy/platforms/static.d.ts +10 -0
- package/dist/types/deploy/platforms/types.d.ts +104 -0
- package/dist/types/deploy/platforms/vercel.d.ts +32 -0
- package/dist/types/deploy/redirects.d.ts +53 -0
- package/dist/types/deploy/robots.d.ts +8 -0
- package/dist/types/deploy/rss.d.ts +31 -0
- package/dist/types/deploy/sitemap.d.ts +21 -0
- package/dist/types/deploy/vercel-negotiation.d.ts +109 -0
- package/dist/types/markdown/code-title.d.ts +32 -0
- package/dist/types/markdown/fence-meta.d.ts +23 -0
- package/dist/types/markdown/themes.d.ts +3 -3
- package/dist/types/openapi/asyncapi.d.ts +129 -0
- package/dist/types/openapi/graphql-build.d.ts +8 -0
- package/dist/types/openapi/graphql.d.ts +122 -0
- package/dist/types/openapi/model.d.ts +158 -0
- package/dist/types/openapi/parse.d.ts +57 -0
- package/dist/types/openapi/references.d.ts +37 -25
- package/dist/types/openapi/render-mdx.d.ts +33 -0
- package/dist/types/openapi/sentence.d.ts +7 -0
- package/dist/types/openapi/signature.d.ts +10 -0
- package/dist/types/openapi/source.d.ts +22 -0
- package/dist/types/openapi/spec-dependency-error.d.ts +10 -0
- package/dist/types/reference/asyncapi.d.ts +166 -0
- package/dist/types/reference/graphql.d.ts +181 -0
- package/dist/types/reference/index.d.ts +32 -0
- package/dist/types/reference/openapi.d.ts +165 -0
- package/dist/types/reference/options.d.ts +157 -0
- package/dist/types/reference/scalar.d.ts +136 -0
- package/dist/types/reference/schema.d.ts +630 -0
- package/dist/types/search/adapters/algolia.d.ts +32 -0
- package/dist/types/search/adapters/flexsearch.d.ts +12 -0
- package/dist/types/search/adapters/index.d.ts +31 -0
- package/dist/types/search/adapters/mixedbread.d.ts +22 -0
- package/dist/types/search/adapters/orama-cloud.d.ts +33 -0
- package/dist/types/search/adapters/orama.d.ts +13 -0
- package/dist/types/search/adapters/pagefind.d.ts +12 -0
- package/dist/types/search/adapters/registry.d.ts +228 -0
- package/dist/types/search/adapters/types.d.ts +34 -0
- package/dist/types/search/adapters/typesense.d.ts +42 -0
- package/dist/types/search/build.d.ts +23 -0
- package/dist/types/search/documents.d.ts +90 -0
- package/dist/types/search/facets.d.ts +3 -0
- package/dist/types/search/sync/algolia.d.ts +14 -0
- package/dist/types/search/sync/index.d.ts +14 -0
- package/dist/types/search/sync/orama-cloud.d.ts +10 -0
- package/dist/types/search/sync/typesense.d.ts +14 -0
- package/dist/types/sources/contentful.d.ts +68 -0
- package/dist/types/sources/custom.d.ts +20 -0
- package/dist/types/sources/filesystem.d.ts +42 -0
- package/dist/types/sources/github-releases.d.ts +46 -0
- package/dist/types/sources/index.d.ts +48 -0
- package/dist/types/sources/mdx-remote.d.ts +63 -0
- package/dist/types/sources/notion.d.ts +65 -0
- package/dist/types/sources/obsidian.d.ts +34 -0
- package/dist/types/sources/payload.d.ts +68 -0
- package/dist/types/sources/registry.d.ts +1414 -0
- package/dist/types/sources/sanity.d.ts +69 -0
- package/dist/types/sources/shared.d.ts +46 -0
- package/dist/types/sources/strapi.d.ts +66 -0
- package/dist/types/theme/icon-kind.d.ts +11 -0
- package/dist/types/theme/icons.d.ts +20 -0
- package/docs/01-quickstart.mdx +18 -18
- package/docs/02-deployment.mdx +50 -26
- package/docs/03-upgrading.mdx +351 -0
- package/docs/04-migrating.mdx +58 -0
- package/docs/08-faq.mdx +3 -3
- package/docs/advanced/blog.mdx +13 -6
- package/docs/advanced/changelog.mdx +23 -35
- package/docs/advanced/custom-pages.mdx +20 -8
- package/docs/advanced/meta.ts +1 -8
- package/docs/advanced/skills.mdx +8 -0
- package/docs/cli/audit.mdx +646 -0
- package/docs/cli/doctor.mdx +29 -0
- package/docs/{reference/eval.mdx → cli/evals.mdx} +9 -8
- package/docs/cli/index.mdx +105 -0
- package/docs/cli/meta.ts +7 -0
- package/docs/{reference → cli}/translate.mdx +1 -1
- package/docs/cli/validate.mdx +41 -0
- package/docs/cli/version.mdx +40 -0
- package/docs/configuration/analytics.mdx +350 -59
- package/docs/configuration/ask-ai.mdx +176 -61
- package/docs/configuration/customization.mdx +15 -9
- package/docs/configuration/index.mdx +52 -31
- package/docs/configuration/search.mdx +75 -54
- package/docs/configuration/theming.mdx +24 -15
- package/docs/content/components.mdx +21 -5
- package/docs/{reference → content}/frontmatter.mdx +37 -1
- package/docs/content/i18n.mdx +8 -6
- package/docs/content/includes.mdx +2 -4
- package/docs/content/index.mdx +1 -1
- package/docs/content/islands.mdx +10 -5
- package/docs/content/meta.mdx +1 -1
- package/docs/content/meta.ts +1 -0
- package/docs/content/navigation.mdx +12 -7
- package/docs/content/sources.mdx +145 -50
- package/docs/content/syntax.mdx +26 -12
- package/docs/content/versioning.mdx +3 -3
- package/docs/discoverability/agent-discovery.mdx +91 -10
- package/docs/discoverability/index.mdx +5 -5
- package/docs/discoverability/json-api.mdx +4 -4
- package/docs/discoverability/llms-txt.mdx +6 -6
- package/docs/discoverability/markdown.mdx +4 -4
- package/docs/discoverability/mcp.mdx +11 -11
- package/docs/discoverability/sitemap-and-robots.mdx +3 -3
- package/docs/index.mdx +2 -2
- package/docs/references/asyncapi.mdx +59 -0
- package/docs/{advanced → references}/graphql.mdx +45 -32
- package/docs/{reference → references}/meta.ts +2 -2
- package/docs/references/openapi.mdx +171 -0
- package/docs/references/scalar.mdx +64 -0
- package/package.json +42 -8
- package/skills/blume/SKILL.md +21 -8
- package/skills/blume-migrate/SKILL.md +22 -21
- package/skills/blume-migrate/assets/oxfmt@0.67.0.patch +49 -0
- package/skills/blume-migrate/references/docusaurus.md +5 -4
- package/skills/blume-migrate/references/fumadocs.md +4 -4
- package/skills/blume-migrate/references/mintlify.md +23 -8
- package/skills/blume-migrate/references/monorepo.md +6 -6
- package/skills/blume-migrate/references/starlight.md +4 -4
- package/src/ai/agent-readability.ts +26 -22
- package/src/ai/ai-catalog.ts +259 -0
- package/src/ai/api/handlers.ts +46 -11
- package/src/ai/api-catalog.ts +8 -8
- package/src/ai/ask-data.ts +1 -1
- package/src/ai/ask.ts +624 -100
- package/src/ai/changelog-markdown.ts +91 -0
- package/src/ai/component-markdown.ts +328 -12
- package/src/ai/index.ts +45 -0
- package/src/ai/link-headers.ts +19 -6
- package/src/ai/llms.ts +26 -15
- package/src/ai/markdown.ts +35 -5
- package/src/ai/mcp/data.ts +9 -5
- package/src/ai/mcp/discovery.ts +1 -1
- package/src/ai/openapi-components.ts +4 -1
- package/src/ai/relative-links.ts +170 -0
- package/src/ai/serializers.ts +2 -2
- package/src/ai/skills.ts +1 -1
- package/src/ai/web-bot-auth.ts +2 -2
- package/src/analytics/adobe.ts +46 -0
- package/src/analytics/amplitude.ts +79 -0
- package/src/analytics/clarity.ts +46 -0
- package/src/analytics/clearbit.ts +47 -0
- package/src/analytics/cloudflare.ts +67 -0
- package/src/analytics/fathom.ts +64 -0
- package/src/analytics/google-analytics.ts +84 -0
- package/src/analytics/google-tag-manager.ts +61 -0
- package/src/analytics/head.ts +130 -0
- package/src/analytics/heap.ts +65 -0
- package/src/analytics/hightouch.ts +77 -0
- package/src/analytics/hotjar.ts +47 -0
- package/src/analytics/index.ts +71 -0
- package/src/analytics/inline.ts +21 -0
- package/src/analytics/logrocket.ts +71 -0
- package/src/analytics/mixpanel.ts +92 -0
- package/src/analytics/pirsch.ts +66 -0
- package/src/analytics/plausible.ts +83 -0
- package/src/analytics/posthog.ts +78 -0
- package/src/analytics/schema.ts +60 -0
- package/src/analytics/script.ts +60 -0
- package/src/analytics/segment.ts +85 -0
- package/src/analytics/vercel.ts +50 -0
- package/src/astro/adapter-root.ts +7 -9
- package/src/astro/component-slots.ts +131 -91
- package/src/astro/generate.ts +114 -345
- package/src/astro/integration.ts +2 -6
- package/src/astro/pages.ts +13 -101
- package/src/astro/render-deps.ts +379 -0
- package/src/astro/runtime-deps.ts +201 -0
- package/src/astro/templates.ts +554 -541
- package/src/audit/agent.ts +24 -0
- package/src/audit/catalog.ts +2 -2
- package/src/audit/checks/assets.ts +2 -2
- package/src/audit/checks/dns-aid.ts +1 -1
- package/src/audit/checks/duplicates.ts +3 -1
- package/src/audit/checks/i18n.ts +1 -1
- package/src/audit/checks/indexability.ts +7 -7
- package/src/audit/checks/links.ts +2 -2
- package/src/audit/checks/llms.ts +6 -6
- package/src/audit/checks/network.ts +3 -3
- package/src/audit/checks/og-image.ts +2 -2
- package/src/audit/checks/robots.ts +1 -1
- package/src/audit/checks/sitemap.ts +2 -2
- package/src/audit/checks/social.ts +1 -1
- package/src/audit/run.ts +4 -3
- package/src/audit/terms.ts +31 -0
- package/src/audit/url.ts +13 -13
- package/src/cli/command-meta.ts +10 -0
- package/src/cli/commands/audit.ts +39 -20
- package/src/cli/commands/build.ts +71 -314
- package/src/cli/commands/check.ts +1 -0
- package/src/cli/commands/dev.ts +40 -1
- package/src/cli/commands/doctor.ts +90 -14
- package/src/cli/commands/eject.ts +44 -7
- package/src/cli/commands/eval.ts +2 -2
- package/src/cli/commands/init.ts +161 -41
- package/src/cli/commands/migrate.ts +121 -0
- package/src/cli/commands/preview.ts +7 -1
- package/src/cli/commands/translate.ts +2 -2
- package/src/cli/commands/upgrade.ts +141 -0
- package/src/cli/commands/version.ts +57 -44
- package/src/cli/eject-scripts.ts +121 -6
- package/src/cli/index.ts +11 -1
- package/src/cli/init/install.ts +70 -0
- package/src/cli/init/questions.ts +7 -0
- package/src/cli/init/scaffold.ts +459 -75
- package/src/cli/lazy-command.ts +37 -1
- package/src/cli/prepare.ts +40 -6
- package/src/cli/required-secrets.ts +38 -11
- package/src/cli/unknown-flags.ts +266 -0
- package/src/cli/yarn-pnp.ts +52 -0
- package/src/components/content/AccordionItem.astro +7 -1
- package/src/components/content/Card.astro +4 -3
- package/src/components/content/ColorItem.astro +22 -4
- package/src/components/content/GithubInfo.astro +2 -2
- package/src/components/content/Prompt.astro +25 -25
- package/src/components/content/Tabs.astro +3 -1
- package/src/components/content/Tile.astro +2 -3
- package/src/components/content/Tooltip.astro +57 -9
- package/src/components/content/content-strings.ts +34 -0
- package/src/components/content/diff.ts +1 -1
- package/src/components/content/mermaid-element.ts +13 -2
- package/src/components/content/prompt-markdown.ts +292 -0
- package/src/components/content/tooltip-id.ts +41 -0
- package/src/components/islands/hooks.ts +75 -3
- package/src/components/layout/Analytics.astro +21 -79
- package/src/components/layout/Banner.astro +3 -1
- package/src/components/layout/DiscoveryLinks.astro +69 -0
- package/src/components/layout/Header.astro +83 -20
- package/src/components/layout/LanguageSwitcher.astro +4 -1
- package/src/components/layout/Logo.astro +23 -2
- package/src/components/layout/NavSelector.astro +13 -2
- package/src/components/layout/NavTree.astro +12 -3
- package/src/components/layout/NavTreeScript.astro +17 -3
- package/src/components/layout/PageActions.astro +3 -3
- package/src/components/layout/PageFeedback.astro +11 -1
- package/src/components/layout/PageLayout.astro +52 -5
- package/src/components/layout/ReferenceLayout.astro +21 -12
- package/src/components/layout/RootLayout.astro +69 -43
- package/src/components/layout/Search.astro +30 -6
- package/src/components/layout/WebMcp.astro +1 -1
- package/src/components/layout/analytics-client.ts +101 -15
- package/src/components/layout/drawer-inert.ts +113 -15
- package/src/components/layout/dropdown-clamp.ts +105 -0
- package/src/components/layout/head-scripts.ts +15 -6
- package/src/components/layout/nav-utils.ts +17 -0
- package/src/components/layout/search/algolia.ts +8 -8
- package/src/components/layout/search/orama-cloud.ts +9 -7
- package/src/components/layout/search/typesense.ts +11 -17
- package/src/components/openapi/MessageComposer.astro +2 -2
- package/src/components/openapi/Playground.astro +2 -2
- package/src/components/openapi/playground-client.ts +79 -10
- package/src/core/changelog-index.ts +24 -0
- package/src/core/component-overrides.ts +399 -154
- package/src/core/config-input.ts +212 -543
- package/src/core/config.ts +130 -41
- package/src/core/custom-pages.ts +105 -0
- package/src/core/data.ts +32 -11
- package/src/core/define-components.ts +12 -9
- package/src/core/deployment-env.ts +18 -74
- package/src/core/diagnostics.ts +14 -7
- package/src/core/graph.ts +69 -25
- package/src/core/i18n-ui.ts +6 -2
- package/src/core/i18n.ts +17 -0
- package/src/core/includes.ts +156 -38
- package/src/core/last-modified.ts +6 -11
- package/src/core/links.ts +166 -2
- package/src/core/manifest.ts +10 -3
- package/src/core/navigation.ts +137 -19
- package/src/core/new-tab.ts +35 -0
- package/src/core/node-require.ts +21 -0
- package/src/core/project-graph.ts +42 -26
- package/src/core/project.ts +9 -4
- package/src/core/request-body.ts +61 -0
- package/src/core/safe-href.ts +28 -0
- package/src/core/safe-links.ts +68 -0
- package/src/core/schema.ts +531 -721
- package/src/core/server-features.ts +8 -9
- package/src/core/sources/assets.ts +47 -11
- package/src/core/sources/collection.ts +67 -0
- package/src/core/sources/contentful-rich-text.ts +285 -0
- package/src/core/sources/contentful.ts +173 -0
- package/src/core/sources/github-releases.ts +51 -1
- package/src/core/sources/json.ts +71 -0
- package/src/core/sources/lexical.ts +195 -0
- package/src/core/sources/lower.ts +226 -0
- package/src/core/sources/normalize.ts +52 -2
- package/src/core/sources/notion.ts +39 -28
- package/src/core/sources/payload.ts +135 -0
- package/src/core/sources/portable-text.ts +11 -16
- package/src/core/sources/remote.ts +226 -0
- package/src/core/sources/resolve.ts +104 -166
- package/src/core/sources/sanity.ts +16 -49
- package/src/core/sources/strapi-blocks.ts +124 -0
- package/src/core/sources/strapi.ts +191 -0
- package/src/core/sources/types.ts +12 -1
- package/src/core/types.ts +20 -1
- package/src/core/ui-packs/ar.ts +6 -2
- package/src/core/ui-packs/bg.ts +6 -2
- package/src/core/ui-packs/bn.ts +6 -2
- package/src/core/ui-packs/ca.ts +3 -1
- package/src/core/ui-packs/cs.ts +6 -2
- package/src/core/ui-packs/da.ts +6 -2
- package/src/core/ui-packs/de.ts +6 -2
- package/src/core/ui-packs/el.ts +3 -1
- package/src/core/ui-packs/es.ts +3 -1
- package/src/core/ui-packs/fa.ts +6 -2
- package/src/core/ui-packs/fi.ts +6 -2
- package/src/core/ui-packs/fr.ts +3 -1
- package/src/core/ui-packs/he.ts +6 -2
- package/src/core/ui-packs/hi.ts +6 -2
- package/src/core/ui-packs/hr.ts +6 -2
- package/src/core/ui-packs/hu.ts +6 -2
- package/src/core/ui-packs/id.ts +6 -2
- package/src/core/ui-packs/it.ts +3 -1
- package/src/core/ui-packs/ja.ts +3 -1
- package/src/core/ui-packs/ko.ts +3 -1
- package/src/core/ui-packs/nl.ts +6 -2
- package/src/core/ui-packs/no.ts +6 -2
- package/src/core/ui-packs/pl.ts +6 -2
- package/src/core/ui-packs/pt-br.ts +3 -1
- package/src/core/ui-packs/pt.ts +3 -1
- package/src/core/ui-packs/ro.ts +6 -2
- package/src/core/ui-packs/ru.ts +6 -2
- package/src/core/ui-packs/sk.ts +6 -2
- package/src/core/ui-packs/sr.ts +6 -2
- package/src/core/ui-packs/sv.ts +6 -2
- package/src/core/ui-packs/th.ts +3 -1
- package/src/core/ui-packs/tr.ts +6 -2
- package/src/core/ui-packs/uk.ts +6 -2
- package/src/core/ui-packs/vi.ts +3 -1
- package/src/core/ui-packs/zh-tw.ts +3 -1
- package/src/core/ui-packs/zh.ts +3 -1
- package/src/core/unrecognized-keys.ts +10 -0
- package/src/core/version-cut.ts +116 -8
- package/src/deploy/adapter-output.ts +57 -97
- package/src/deploy/adapters/cloudflare.ts +39 -0
- package/src/deploy/adapters/index.ts +41 -0
- package/src/deploy/adapters/netlify.ts +34 -0
- package/src/deploy/adapters/node.ts +34 -0
- package/src/deploy/adapters/registry.ts +127 -0
- package/src/deploy/adapters/types.ts +92 -0
- package/src/deploy/adapters/vercel.ts +35 -0
- package/src/deploy/artifacts.ts +67 -28
- package/src/deploy/cloudflare-negotiation.ts +179 -100
- package/src/deploy/function-bundle.ts +18 -3
- package/src/deploy/headers.ts +129 -22
- package/src/deploy/node-headers.ts +198 -0
- package/src/deploy/platforms/cloudflare.ts +312 -0
- package/src/deploy/platforms/index.ts +67 -0
- package/src/deploy/platforms/netlify.ts +52 -0
- package/src/deploy/platforms/node.ts +40 -0
- package/src/deploy/platforms/paths.ts +42 -0
- package/src/deploy/platforms/static.ts +29 -0
- package/src/deploy/platforms/types.ts +112 -0
- package/src/deploy/platforms/vercel.ts +193 -0
- package/src/deploy/redirects.ts +30 -18
- package/src/deploy/robots.ts +3 -3
- package/src/deploy/rss.ts +2 -2
- package/src/deploy/sitemap.ts +2 -2
- package/src/deploy/vercel-negotiation.ts +27 -4
- package/src/eval/agents.ts +32 -1
- package/src/eval/findings.ts +19 -11
- package/src/eval/report.ts +10 -2
- package/src/markdown/external-links.ts +65 -0
- package/src/markdown/include.ts +45 -27
- package/src/markdown/index.ts +34 -9
- package/src/markdown/inline-code.ts +12 -6
- package/src/markdown/relative-links.ts +324 -0
- package/src/markdown/themes.ts +3 -3
- package/src/migrate/migrate.ts +149 -0
- package/src/openapi/parse.ts +64 -16
- package/src/openapi/proxy.ts +62 -10
- package/src/openapi/references.ts +147 -147
- package/src/openapi/render-mdx.ts +32 -10
- package/src/openapi/scalar.ts +15 -13
- package/src/openapi/sentence.ts +14 -0
- package/src/openapi/source.ts +37 -21
- package/src/openapi/spec-dependency-error.ts +15 -0
- package/src/reference/asyncapi.ts +83 -0
- package/src/reference/graphql.ts +89 -0
- package/src/reference/index.ts +40 -0
- package/src/reference/openapi.ts +83 -0
- package/src/reference/options.ts +201 -0
- package/src/reference/scalar.ts +136 -0
- package/src/reference/schema.ts +88 -0
- package/src/registry/eject.ts +97 -42
- package/src/search/adapters/algolia.ts +46 -0
- package/src/search/adapters/flexsearch.ts +29 -0
- package/src/search/adapters/index.ts +39 -0
- package/src/search/adapters/mixedbread.ts +39 -0
- package/src/search/adapters/orama-cloud.ts +51 -0
- package/src/search/adapters/orama.ts +24 -0
- package/src/search/adapters/pagefind.ts +27 -0
- package/src/search/adapters/registry.ts +131 -0
- package/src/search/adapters/types.ts +46 -0
- package/src/search/adapters/typesense.ts +57 -0
- package/src/search/build.ts +33 -7
- package/src/search/documents.ts +6 -0
- package/src/search/sync/algolia.ts +12 -11
- package/src/search/sync/index.ts +35 -20
- package/src/search/sync/orama-cloud.ts +12 -9
- package/src/search/sync/typesense.ts +15 -13
- package/src/sources/contentful.ts +63 -0
- package/src/sources/custom.ts +38 -0
- package/src/sources/filesystem.ts +51 -0
- package/src/sources/github-releases.ts +52 -0
- package/src/sources/index.ts +60 -0
- package/src/sources/mdx-remote.ts +76 -0
- package/src/sources/notion.ts +63 -0
- package/src/sources/obsidian.ts +38 -0
- package/src/sources/payload.ts +60 -0
- package/src/sources/registry.ts +182 -0
- package/src/sources/sanity.ts +66 -0
- package/src/sources/shared.ts +52 -0
- package/src/sources/strapi.ts +58 -0
- package/src/theme/entry.ts +47 -2
- package/src/translate/report.ts +40 -7
- package/src/upgrade/upgrade.ts +499 -0
- package/dist/cli/chunk-12dxjqk7.js.map +0 -10
- package/dist/cli/chunk-196vjxp9.js.map +0 -13
- package/dist/cli/chunk-2mzebbbz.js +0 -69
- package/dist/cli/chunk-2z47ypj8.js.map +0 -11
- package/dist/cli/chunk-30e87n55.js +0 -108
- package/dist/cli/chunk-30e87n55.js.map +0 -10
- package/dist/cli/chunk-450a7rcr.js +0 -185
- package/dist/cli/chunk-450a7rcr.js.map +0 -11
- package/dist/cli/chunk-5n7t497w.js.map +0 -40
- package/dist/cli/chunk-61j18dwk.js +0 -5342
- package/dist/cli/chunk-61j18dwk.js.map +0 -58
- package/dist/cli/chunk-88by27n5.js +0 -17
- package/dist/cli/chunk-88by27n5.js.map +0 -10
- package/dist/cli/chunk-8cd8tj54.js.map +0 -34
- package/dist/cli/chunk-aztttvb3.js +0 -381
- package/dist/cli/chunk-aztttvb3.js.map +0 -12
- package/dist/cli/chunk-cvky9gb2.js.map +0 -11
- package/dist/cli/chunk-ejjx8znq.js.map +0 -15
- package/dist/cli/chunk-fmceyezb.js +0 -1007
- package/dist/cli/chunk-fmceyezb.js.map +0 -13
- package/dist/cli/chunk-hdm2dkd2.js.map +0 -48
- package/dist/cli/chunk-hs3gbh8p.js.map +0 -10
- package/dist/cli/chunk-jbj4qhfw.js +0 -30
- package/dist/cli/chunk-jbj4qhfw.js.map +0 -10
- package/dist/cli/chunk-mqb2ka8m.js +0 -68
- package/dist/cli/chunk-mqb2ka8m.js.map +0 -10
- package/dist/cli/chunk-mt76t7dj.js.map +0 -11
- package/dist/cli/chunk-q4rae3bg.js +0 -60
- package/dist/cli/chunk-q4rae3bg.js.map +0 -10
- package/dist/cli/chunk-ra1v2nc2.js +0 -35
- package/dist/cli/chunk-ra1v2nc2.js.map +0 -10
- package/dist/cli/chunk-t3tj0dgr.js.map +0 -15
- package/dist/cli/chunk-tqa1s0k8.js +0 -69
- package/dist/cli/chunk-tqa1s0k8.js.map +0 -11
- package/dist/cli/chunk-vh9w1sgp.js +0 -73
- package/dist/cli/chunk-vh9w1sgp.js.map +0 -10
- package/dist/cli/chunk-vkrsvbr5.js +0 -107
- package/dist/cli/chunk-vkrsvbr5.js.map +0 -11
- package/dist/cli/chunk-vrfp10qk.js +0 -81
- package/dist/cli/chunk-vrfp10qk.js.map +0 -10
- package/dist/cli/chunk-wjt80jps.js +0 -1049
- package/dist/cli/chunk-wjt80jps.js.map +0 -24
- package/docs/advanced/api-reference.mdx +0 -240
- package/docs/reference/cli.mdx +0 -197
- package/skills/blume-migrate/assets/oxfmt@0.55.0.patch +0 -20
- package/src/components/content/changelog-element.ts +0 -69
- package/src/search/providers.ts +0 -91
- /package/dist/cli/{chunk-3w7b2vcx.js.map → chunk-7ez8ny0t.js.map} +0 -0
- /package/dist/cli/{chunk-688e0dde.js.map → chunk-88cpgt6h.js.map} +0 -0
- /package/dist/cli/{chunk-exeeb35e.js.map → chunk-f7t03s3g.js.map} +0 -0
- /package/dist/cli/{chunk-ppfvdcd4.js.map → chunk-zxccj738.js.map} +0 -0
package/src/cli/init/scaffold.ts
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
2
|
-
import { mkdir, writeFile } from "node:fs/promises";
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
3
|
|
|
4
4
|
import { detect } from "package-manager-detector/detect";
|
|
5
5
|
import { basename, dirname, isAbsolute, join, relative } from "pathe";
|
|
6
6
|
|
|
7
7
|
import { blumePackageJson, toPackageName } from "../../core/package-json.ts";
|
|
8
|
+
import { contentful } from "../../sources/contentful.ts";
|
|
9
|
+
import { githubReleases } from "../../sources/github-releases.ts";
|
|
10
|
+
import { mdxRemote } from "../../sources/mdx-remote.ts";
|
|
11
|
+
import { notion } from "../../sources/notion.ts";
|
|
12
|
+
import { obsidian } from "../../sources/obsidian.ts";
|
|
13
|
+
import { payload } from "../../sources/payload.ts";
|
|
14
|
+
import type { AnySourceAdapter } from "../../sources/registry.ts";
|
|
15
|
+
import { sanity } from "../../sources/sanity.ts";
|
|
16
|
+
import { strapi } from "../../sources/strapi.ts";
|
|
8
17
|
|
|
9
18
|
export const TEMPLATES = ["docs", "api", "sdk", "changelog"] as const;
|
|
10
19
|
export type Template = (typeof TEMPLATES)[number];
|
|
@@ -19,6 +28,9 @@ export const SOURCE_KINDS = [
|
|
|
19
28
|
"github-releases",
|
|
20
29
|
"notion",
|
|
21
30
|
"sanity",
|
|
31
|
+
"contentful",
|
|
32
|
+
"payload",
|
|
33
|
+
"strapi",
|
|
22
34
|
"mdx-remote",
|
|
23
35
|
] as const;
|
|
24
36
|
export type SourceKind = (typeof SOURCE_KINDS)[number];
|
|
@@ -49,6 +61,8 @@ export interface ScaffoldLog {
|
|
|
49
61
|
/** A starter: a config fragment plus seed content files (paths relative to root). */
|
|
50
62
|
interface Starter {
|
|
51
63
|
configExtra: string;
|
|
64
|
+
/** Import lines the fragment needs, placed after the `defineConfig` import. */
|
|
65
|
+
configImports: string[];
|
|
52
66
|
files: (contentDir: string) => { content: string; path: string }[];
|
|
53
67
|
}
|
|
54
68
|
|
|
@@ -58,22 +72,24 @@ const page = (title: string, description: string, body: string): string =>
|
|
|
58
72
|
export const STARTERS = {
|
|
59
73
|
api: {
|
|
60
74
|
configExtra: `
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
75
|
+
reference: [
|
|
76
|
+
openapi({
|
|
77
|
+
route: "/api",
|
|
78
|
+
sources: [
|
|
79
|
+
{
|
|
80
|
+
label: "Petstore",
|
|
81
|
+
spec: "https://petstore3.swagger.io/api/v3/openapi.json",
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
}),
|
|
85
|
+
],`,
|
|
86
|
+
configImports: ['import { openapi } from "blume/reference";'],
|
|
71
87
|
files: (dir) => [
|
|
72
88
|
{
|
|
73
89
|
content: page(
|
|
74
90
|
"API Reference",
|
|
75
|
-
"
|
|
76
|
-
"
|
|
91
|
+
"Reference documentation for the API, generated from its OpenAPI spec, with every endpoint, its parameters, request bodies, and responses.",
|
|
92
|
+
"Your OpenAPI spec renders at [`/api`](/api). Point `openapi()` at your own spec in `blume.config.ts`."
|
|
77
93
|
),
|
|
78
94
|
path: join(dir, "index.mdx"),
|
|
79
95
|
},
|
|
@@ -87,29 +103,31 @@ export const STARTERS = {
|
|
|
87
103
|
{ label: "Changelog", path: "/changelog" },
|
|
88
104
|
],
|
|
89
105
|
},`,
|
|
106
|
+
configImports: [],
|
|
90
107
|
files: (dir) => [
|
|
91
108
|
{
|
|
92
109
|
content: page(
|
|
93
110
|
"Introduction",
|
|
94
|
-
"Welcome to your new
|
|
95
|
-
"
|
|
111
|
+
"Welcome to your new documentation site. Write guides as Markdown pages here, and log each release as an entry in the changelog folder.",
|
|
112
|
+
"Write your docs here, and log releases under `changelog/`: each entry joins the [changelog](/changelog), newest first."
|
|
96
113
|
),
|
|
97
114
|
path: join(dir, "index.mdx"),
|
|
98
115
|
},
|
|
99
116
|
{
|
|
100
|
-
content: `---\ntitle: v1.0.0\ntype: changelog\ndate: 2026-01-01\n---\n\nThe first release. Edit \`${dir}/changelog/v1-0-0.mdx\` or add new entries beside it.\n`,
|
|
117
|
+
content: `---\ntitle: v1.0.0\ndescription: The first release of the project. Replace this entry with your own release notes, and add a new file beside it for every version.\ntype: changelog\ndate: 2026-01-01\n---\n\nThe first release. Edit \`${dir}/changelog/v1-0-0.mdx\` or add new entries beside it.\n`,
|
|
101
118
|
path: join(dir, "changelog", "v1-0-0.mdx"),
|
|
102
119
|
},
|
|
103
120
|
],
|
|
104
121
|
},
|
|
105
122
|
docs: {
|
|
106
123
|
configExtra: "",
|
|
124
|
+
configImports: [],
|
|
107
125
|
files: (dir) => [
|
|
108
126
|
{
|
|
109
127
|
content: page(
|
|
110
128
|
"Introduction",
|
|
111
|
-
"Welcome to your new Blume
|
|
112
|
-
|
|
129
|
+
"Welcome to your new documentation site. Edit this page or add Markdown files beside it, and Blume turns each file into a page.",
|
|
130
|
+
`Welcome to **Blume**, the open-source docs framework for humans and agents.\n\nEdit \`${dir}/index.mdx\` and save: this page reloads with your changes.`
|
|
113
131
|
),
|
|
114
132
|
path: join(dir, "index.mdx"),
|
|
115
133
|
},
|
|
@@ -117,20 +135,21 @@ export const STARTERS = {
|
|
|
117
135
|
},
|
|
118
136
|
sdk: {
|
|
119
137
|
configExtra: "",
|
|
138
|
+
configImports: [],
|
|
120
139
|
files: (dir) => [
|
|
121
140
|
{
|
|
122
141
|
content: page(
|
|
123
142
|
"Introduction",
|
|
124
|
-
"Get started with the SDK.",
|
|
125
|
-
"
|
|
143
|
+
"Get started with the SDK. Install the package, configure a client, and make your first call in a few lines of code in your own app.",
|
|
144
|
+
"Install the SDK and make your first call. See [Installation](/installation)."
|
|
126
145
|
),
|
|
127
146
|
path: join(dir, "index.mdx"),
|
|
128
147
|
},
|
|
129
148
|
{
|
|
130
149
|
content: page(
|
|
131
150
|
"Installation",
|
|
132
|
-
"Install the SDK.",
|
|
133
|
-
"
|
|
151
|
+
"Install the SDK with the package manager your project already uses, then import it into your code to start making requests to the API.",
|
|
152
|
+
"```package-install\nyour-sdk\n```"
|
|
134
153
|
),
|
|
135
154
|
path: join(dir, "installation.mdx"),
|
|
136
155
|
},
|
|
@@ -139,11 +158,13 @@ export const STARTERS = {
|
|
|
139
158
|
} satisfies Record<Template, Starter>;
|
|
140
159
|
|
|
141
160
|
/**
|
|
142
|
-
*
|
|
161
|
+
* Add, install, and dev commands to print for the chosen package manager, plus the
|
|
143
162
|
* prefix that runs a locally installed bin (`exec`, e.g. `npx blume eject`) —
|
|
144
163
|
* dependency bins aren't on PATH, so a bare `blume …` hint would not run.
|
|
145
164
|
*/
|
|
146
165
|
export const commandsFor = (pm: PackageManager) => ({
|
|
166
|
+
// Adds a dependency: npm spells the verb `install`, the others `add`.
|
|
167
|
+
add: pm === "npm" ? "npm install" : `${pm} add`,
|
|
147
168
|
// `bun build` invokes Bun's bundler, not the package.json `build` script —
|
|
148
169
|
// unlike `bun dev`, the script name is shadowed by a builtin subcommand.
|
|
149
170
|
build: pm === "npm" || pm === "bun" ? `${pm} run build` : `${pm} build`,
|
|
@@ -166,6 +187,25 @@ export const detectPackageManager = (userAgent?: string): PackageManager => {
|
|
|
166
187
|
return name !== undefined && isPackageManager(name) ? name : "npm";
|
|
167
188
|
};
|
|
168
189
|
|
|
190
|
+
/**
|
|
191
|
+
* The nearest directory at or above `root` holding `.git` (a directory, or
|
|
192
|
+
* the file a worktree or submodule carries), or null outside a repository.
|
|
193
|
+
* Checked by presence rather than by asking git, so no path spelling is ever
|
|
194
|
+
* compared: git prints its toplevel with symlinks and Windows 8.3 short
|
|
195
|
+
* names resolved, which nothing in Node canonicalizes to.
|
|
196
|
+
*/
|
|
197
|
+
const repositoryRootOf = (root: string): string | null => {
|
|
198
|
+
let dir = root;
|
|
199
|
+
while (!existsSync(join(dir, ".git"))) {
|
|
200
|
+
const parent = dirname(dir);
|
|
201
|
+
if (parent === dir) {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
dir = parent;
|
|
205
|
+
}
|
|
206
|
+
return dir;
|
|
207
|
+
};
|
|
208
|
+
|
|
169
209
|
/**
|
|
170
210
|
* Detect an existing project's package manager from its lockfile /
|
|
171
211
|
* `packageManager` field (package-manager-detector), falling back to the
|
|
@@ -177,7 +217,15 @@ export const detectPackageManager = (userAgent?: string): PackageManager => {
|
|
|
177
217
|
export const detectProjectPackageManager = async (
|
|
178
218
|
root: string
|
|
179
219
|
): Promise<PackageManager> => {
|
|
180
|
-
|
|
220
|
+
// A workspace package keeps its lockfile and `packageManager` field at the
|
|
221
|
+
// repository root, so the walk climbs that far — but no further, or a
|
|
222
|
+
// `package.json` in an unrelated ancestor (a user's home directory, say)
|
|
223
|
+
// decides the project's commands. Outside a repository the project root is
|
|
224
|
+
// the only directory that can be trusted.
|
|
225
|
+
const detected = await detect({
|
|
226
|
+
cwd: root,
|
|
227
|
+
stopDir: repositoryRootOf(root) ?? root,
|
|
228
|
+
});
|
|
181
229
|
const name = detected?.name;
|
|
182
230
|
return name !== undefined && isPackageManager(name)
|
|
183
231
|
? name
|
|
@@ -218,59 +266,141 @@ export const titleize = (raw: string): string => {
|
|
|
218
266
|
const needsExplicitSources = (sources: SourceKind[]): boolean =>
|
|
219
267
|
sources.some((source) => source !== "filesystem");
|
|
220
268
|
|
|
269
|
+
/** The `blume/sources` factory each source kind is written with. */
|
|
270
|
+
const SOURCE_FACTORIES = {
|
|
271
|
+
contentful: "contentful",
|
|
272
|
+
filesystem: "filesystem",
|
|
273
|
+
"github-releases": "githubReleases",
|
|
274
|
+
"mdx-remote": "mdxRemote",
|
|
275
|
+
notion: "notion",
|
|
276
|
+
obsidian: "obsidian",
|
|
277
|
+
payload: "payload",
|
|
278
|
+
sanity: "sanity",
|
|
279
|
+
strapi: "strapi",
|
|
280
|
+
} satisfies Record<SourceKind, string>;
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* The descriptor each remote source kind scaffolds — the same placeholder
|
|
284
|
+
* options the emitted snippet shows — so the SDK deps and env vars `init`
|
|
285
|
+
* sets up are read off the adapter rather than kept in a parallel table.
|
|
286
|
+
*/
|
|
287
|
+
const SOURCE_DESCRIPTORS = {
|
|
288
|
+
contentful: contentful({
|
|
289
|
+
contentType: "doc",
|
|
290
|
+
prefix: "contentful",
|
|
291
|
+
space: "your-space-id",
|
|
292
|
+
}),
|
|
293
|
+
"github-releases": githubReleases({
|
|
294
|
+
owner: "your-org",
|
|
295
|
+
prefix: "changelog",
|
|
296
|
+
repo: "your-repo",
|
|
297
|
+
}),
|
|
298
|
+
"mdx-remote": mdxRemote({
|
|
299
|
+
github: { owner: "your-org", path: "docs", repo: "your-repo" },
|
|
300
|
+
prefix: "remote",
|
|
301
|
+
}),
|
|
302
|
+
notion: notion({ database: "your-database-id", prefix: "notion" }),
|
|
303
|
+
obsidian: obsidian({ prefix: "notes", vault: "vault" }),
|
|
304
|
+
payload: payload({
|
|
305
|
+
collection: "docs",
|
|
306
|
+
prefix: "payload",
|
|
307
|
+
url: "https://cms.example.com",
|
|
308
|
+
}),
|
|
309
|
+
sanity: sanity({
|
|
310
|
+
dataset: "production",
|
|
311
|
+
prefix: "sanity",
|
|
312
|
+
projectId: "your-project-id",
|
|
313
|
+
query: '*[_type == "doc"]',
|
|
314
|
+
}),
|
|
315
|
+
strapi: strapi({
|
|
316
|
+
contentType: "docs",
|
|
317
|
+
prefix: "strapi",
|
|
318
|
+
url: "https://cms.example.com",
|
|
319
|
+
}),
|
|
320
|
+
} satisfies Record<Exclude<SourceKind, "filesystem">, AnySourceAdapter>;
|
|
321
|
+
|
|
221
322
|
/**
|
|
222
323
|
* Config snippets for each remote source kind, with placeholder values to
|
|
223
324
|
* replace and comments naming the env var each source authenticates with.
|
|
224
325
|
*/
|
|
225
326
|
const SOURCE_SNIPPETS = {
|
|
327
|
+
contentful: ` // Entries of a Contentful content type. Reads CONTENTFUL_ACCESS_TOKEN
|
|
328
|
+
// from the environment.
|
|
329
|
+
contentful({
|
|
330
|
+
space: "your-space-id",
|
|
331
|
+
contentType: "doc",
|
|
332
|
+
prefix: "contentful",
|
|
333
|
+
}),`,
|
|
226
334
|
"github-releases": ` // Changelog entries from GitHub Releases. Private repos read
|
|
227
335
|
// GITHUB_TOKEN from the environment.
|
|
228
|
-
{
|
|
229
|
-
type: "github-releases",
|
|
336
|
+
githubReleases({
|
|
230
337
|
owner: "your-org",
|
|
231
338
|
repo: "your-repo",
|
|
232
339
|
prefix: "changelog",
|
|
233
|
-
},`,
|
|
340
|
+
}),`,
|
|
234
341
|
"mdx-remote": ` // MDX fetched from a GitHub repo. Private repos read GITHUB_TOKEN
|
|
235
342
|
// from the environment.
|
|
236
|
-
{
|
|
237
|
-
type: "mdx-remote",
|
|
343
|
+
mdxRemote({
|
|
238
344
|
github: { owner: "your-org", repo: "your-repo", path: "docs" },
|
|
239
345
|
prefix: "remote",
|
|
240
|
-
},`,
|
|
346
|
+
}),`,
|
|
241
347
|
notion: ` // Pages from a Notion database. Reads NOTION_TOKEN from the environment.
|
|
242
|
-
{
|
|
243
|
-
type: "notion",
|
|
348
|
+
notion({
|
|
244
349
|
database: "your-database-id",
|
|
245
350
|
prefix: "notion",
|
|
246
|
-
},`,
|
|
351
|
+
}),`,
|
|
247
352
|
obsidian: ` // An Obsidian vault, read in place. No export step, and no
|
|
248
353
|
// generated notes in your repo. Point \`vault\` at your vault directory,
|
|
249
354
|
// relative to this config file.
|
|
250
|
-
{
|
|
251
|
-
type: "obsidian",
|
|
355
|
+
obsidian({
|
|
252
356
|
vault: "vault",
|
|
253
357
|
prefix: "notes",
|
|
254
|
-
},`,
|
|
358
|
+
}),`,
|
|
359
|
+
payload: ` // Documents from a Payload collection. Reads PAYLOAD_API_KEY from
|
|
360
|
+
// the environment.
|
|
361
|
+
payload({
|
|
362
|
+
url: "https://cms.example.com",
|
|
363
|
+
collection: "docs",
|
|
364
|
+
prefix: "payload",
|
|
365
|
+
}),`,
|
|
255
366
|
sanity: ` // Documents from a Sanity dataset. Private datasets read SANITY_TOKEN
|
|
256
367
|
// from the environment.
|
|
257
|
-
{
|
|
258
|
-
type: "sanity",
|
|
368
|
+
sanity({
|
|
259
369
|
projectId: "your-project-id",
|
|
260
370
|
dataset: "production",
|
|
261
371
|
query: \`*[_type == "doc"]\`,
|
|
262
372
|
prefix: "sanity",
|
|
263
|
-
},`,
|
|
373
|
+
}),`,
|
|
374
|
+
strapi: ` // Entries of a Strapi content type. Reads STRAPI_API_TOKEN from
|
|
375
|
+
// the environment.
|
|
376
|
+
strapi({
|
|
377
|
+
url: "https://cms.example.com",
|
|
378
|
+
contentType: "docs",
|
|
379
|
+
prefix: "strapi",
|
|
380
|
+
}),`,
|
|
264
381
|
} satisfies Record<Exclude<SourceKind, "filesystem">, string>;
|
|
265
382
|
|
|
383
|
+
/** The selected kinds in canonical order (the multiselect returns pick order). */
|
|
384
|
+
const orderedSources = (sources: SourceKind[]): SourceKind[] =>
|
|
385
|
+
SOURCE_KINDS.filter((kind) => sources.includes(kind));
|
|
386
|
+
|
|
387
|
+
/** The `blume/sources` import line for the selected kinds, in canonical order. */
|
|
388
|
+
const sourcesImportFor = (sources: SourceKind[]): string =>
|
|
389
|
+
`import { ${orderedSources(sources)
|
|
390
|
+
.map((kind) => SOURCE_FACTORIES[kind])
|
|
391
|
+
.join(", ")} } from "blume/sources";\n`;
|
|
392
|
+
|
|
393
|
+
/** The chosen source kinds; no selection means the implicit local source. */
|
|
394
|
+
const selectedSources = (answers: InitAnswers): SourceKind[] =>
|
|
395
|
+
answers.sources.length === 0 ? ["filesystem"] : answers.sources;
|
|
396
|
+
|
|
266
397
|
/**
|
|
267
398
|
* The `content` block for the generated config, or an empty string when the
|
|
268
399
|
* defaults (filesystem source, `docs` root) apply — keeping the default
|
|
269
400
|
* scaffold byte-identical to a config with no `content` key at all.
|
|
270
401
|
*/
|
|
271
402
|
const contentBlockFor = (answers: InitAnswers): string => {
|
|
272
|
-
const sources =
|
|
273
|
-
answers.sources.length === 0 ? ["filesystem" as const] : answers.sources;
|
|
403
|
+
const sources = selectedSources(answers);
|
|
274
404
|
if (!needsExplicitSources(sources)) {
|
|
275
405
|
return answers.contentDir === "docs"
|
|
276
406
|
? ""
|
|
@@ -281,11 +411,10 @@ const contentBlockFor = (answers: InitAnswers): string => {
|
|
|
281
411
|
}
|
|
282
412
|
// Explicit sources replace the implicit filesystem desugar, so the local
|
|
283
413
|
// content dir must be listed alongside the other sources to stay included.
|
|
284
|
-
const entries =
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
: SOURCE_SNIPPETS[kind]
|
|
414
|
+
const entries = orderedSources(sources).map((kind) =>
|
|
415
|
+
kind === "filesystem"
|
|
416
|
+
? ` filesystem({ root: ${JSON.stringify(answers.contentDir)} }),`
|
|
417
|
+
: SOURCE_SNIPPETS[kind]
|
|
289
418
|
);
|
|
290
419
|
return `
|
|
291
420
|
content: {
|
|
@@ -296,32 +425,202 @@ ${entries.join("\n")}
|
|
|
296
425
|
};
|
|
297
426
|
|
|
298
427
|
/** The full `blume.config.ts` text for the chosen answers. */
|
|
299
|
-
export const buildConfig = (
|
|
300
|
-
answers
|
|
301
|
-
|
|
302
|
-
|
|
428
|
+
export const buildConfig = (answers: InitAnswers): string => {
|
|
429
|
+
const starter = STARTERS[answers.template];
|
|
430
|
+
const sources = selectedSources(answers);
|
|
431
|
+
// Only an explicit `sources` array calls factories; the shorthand `root`
|
|
432
|
+
// (or no content block at all) needs no import.
|
|
433
|
+
const sourcesImport = needsExplicitSources(sources)
|
|
434
|
+
? sourcesImportFor(sources)
|
|
435
|
+
: "";
|
|
436
|
+
const imports = [
|
|
437
|
+
'import { defineConfig } from "blume";',
|
|
438
|
+
...starter.configImports,
|
|
439
|
+
].join("\n");
|
|
440
|
+
return `${imports}
|
|
441
|
+
${sourcesImport}
|
|
303
442
|
export default defineConfig({
|
|
304
443
|
title: ${JSON.stringify(answers.title)},
|
|
305
|
-
description: "Documentation powered by Blume.",${
|
|
444
|
+
description: "Documentation powered by Blume.",${starter.configExtra}${contentBlockFor(answers)}
|
|
306
445
|
});
|
|
307
446
|
`;
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
/** The version range `init` pins for each SDK an adapter declares. */
|
|
450
|
+
const SDK_VERSIONS = new Map([
|
|
451
|
+
["@notionhq/client", "^5.26.0"],
|
|
452
|
+
["@sanity/client", "^8.6.1"],
|
|
453
|
+
]);
|
|
454
|
+
|
|
455
|
+
/** The scaffolded descriptors for the selected remote source kinds. */
|
|
456
|
+
const descriptorsFor = (sources: SourceKind[]): AnySourceAdapter[] =>
|
|
457
|
+
orderedSources(sources).flatMap((kind) =>
|
|
458
|
+
kind === "filesystem" ? [] : [SOURCE_DESCRIPTORS[kind]]
|
|
459
|
+
);
|
|
308
460
|
|
|
309
|
-
/** SDK dependencies
|
|
461
|
+
/** SDK dependencies the selected sources declare, read off their descriptors. */
|
|
310
462
|
const extraDepsFor = (sources: SourceKind[]) => {
|
|
311
463
|
const deps: Record<string, string> = {};
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
deps["@sanity/client"] = "^7.25.0";
|
|
464
|
+
for (const descriptor of descriptorsFor(sources)) {
|
|
465
|
+
for (const dep of descriptor.runtimeDeps) {
|
|
466
|
+
deps[dep] = SDK_VERSIONS.get(dep) ?? "latest";
|
|
467
|
+
}
|
|
317
468
|
}
|
|
318
469
|
return deps;
|
|
319
470
|
};
|
|
320
471
|
|
|
472
|
+
/**
|
|
473
|
+
* `pnpm-workspace.yaml` for a new pnpm project. pnpm runs a dependency's
|
|
474
|
+
* build script only once it's approved, and fails the install over any it
|
|
475
|
+
* wasn't told about. esbuild's postinstall checks its platform binary;
|
|
476
|
+
* `@scarf/scarf` is a telemetry postinstall a transitive dependency pulls in,
|
|
477
|
+
* and Blume doesn't need it to run.
|
|
478
|
+
*/
|
|
479
|
+
const PNPM_WORKSPACE = `allowBuilds:
|
|
480
|
+
esbuild: true
|
|
481
|
+
"@scarf/scarf": false
|
|
482
|
+
`;
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* `.yarnrc.yml` for a new Yarn Berry project. Berry installs with Plug'n'Play
|
|
486
|
+
* by default, which writes no `node_modules`; Blume's generated Astro project
|
|
487
|
+
* resolves its packages from one. Yarn Classic never reads this file.
|
|
488
|
+
*/
|
|
489
|
+
const YARNRC = `# Blume's generated Astro project resolves packages from node_modules, which
|
|
490
|
+
# Yarn's default Plug'n'Play install doesn't create.
|
|
491
|
+
nodeLinker: node-modules
|
|
492
|
+
`;
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* The nearest directory at or above `root` where `found` holds, searching up
|
|
496
|
+
* to the repository root — or to the filesystem root outside a repository,
|
|
497
|
+
* where a workspace can still enclose the project.
|
|
498
|
+
*/
|
|
499
|
+
const nearestAncestor = (
|
|
500
|
+
root: string,
|
|
501
|
+
found: (dir: string) => boolean
|
|
502
|
+
): string | null => {
|
|
503
|
+
const stop = repositoryRootOf(root);
|
|
504
|
+
let dir = root;
|
|
505
|
+
while (!found(dir)) {
|
|
506
|
+
const parent = dirname(dir);
|
|
507
|
+
if (dir === stop || parent === dir) {
|
|
508
|
+
return null;
|
|
509
|
+
}
|
|
510
|
+
dir = parent;
|
|
511
|
+
}
|
|
512
|
+
return dir;
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
/** Read a file, or `""` when it can't be read. */
|
|
516
|
+
const readText = (path: string): string => {
|
|
517
|
+
try {
|
|
518
|
+
return readFileSync(path, "utf-8");
|
|
519
|
+
} catch {
|
|
520
|
+
return "";
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
/** The pnpm workspace enclosing `root`: the directory of its `pnpm-workspace.yaml`. */
|
|
525
|
+
const pnpmWorkspaceRoot = (root: string): string | null =>
|
|
526
|
+
nearestAncestor(root, (dir) => existsSync(join(dir, "pnpm-workspace.yaml")));
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* The Yarn project enclosing `root`: a directory holding a lockfile, a
|
|
530
|
+
* `.yarnrc.yml`, or a `package.json` that declares workspaces.
|
|
531
|
+
*/
|
|
532
|
+
const yarnProjectRoot = (root: string): string | null =>
|
|
533
|
+
nearestAncestor(
|
|
534
|
+
root,
|
|
535
|
+
(dir) =>
|
|
536
|
+
existsSync(join(dir, "yarn.lock")) ||
|
|
537
|
+
existsSync(join(dir, ".yarnrc.yml")) ||
|
|
538
|
+
/"workspaces"\s*:/u.test(readText(join(dir, "package.json")))
|
|
539
|
+
);
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* The major version of the Yarn that ran `init`, read off the npm user agent
|
|
543
|
+
* (`yarn/4.5.1 npm/? node/v22…`), or undefined when something else ran it.
|
|
544
|
+
*/
|
|
545
|
+
export const yarnMajor = (userAgent?: string): number | undefined => {
|
|
546
|
+
const match = /^yarn\/(?<major>\d+)\./u.exec(userAgent ?? "");
|
|
547
|
+
return match?.groups?.major === undefined
|
|
548
|
+
? undefined
|
|
549
|
+
: Number(match.groups.major);
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
/** Environment `buildPlan` and `workspaceNote` read, injectable for tests. */
|
|
553
|
+
export interface PlanEnvironment {
|
|
554
|
+
/** `npm_config_user_agent` of the process that ran `init`. */
|
|
555
|
+
userAgent?: string;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* The package-manager config file a project `init` creates from scratch
|
|
560
|
+
* needs: pnpm's build approvals, or Yarn Berry's `node_modules` linker. An
|
|
561
|
+
* existing package.json, or a workspace the project joins, already owns that
|
|
562
|
+
* decision (see {@link workspaceNote}); Yarn Classic ignores `.yarnrc.yml`, so
|
|
563
|
+
* a user agent naming Yarn 1 skips it.
|
|
564
|
+
*/
|
|
565
|
+
const packageManagerConfigFor = (
|
|
566
|
+
root: string,
|
|
567
|
+
answers: InitAnswers,
|
|
568
|
+
env: PlanEnvironment
|
|
569
|
+
): ScaffoldFile[] => {
|
|
570
|
+
if (existsSync(join(root, "package.json"))) {
|
|
571
|
+
return [];
|
|
572
|
+
}
|
|
573
|
+
if (answers.packageManager === "pnpm" && pnpmWorkspaceRoot(root) === null) {
|
|
574
|
+
return [
|
|
575
|
+
{ content: PNPM_WORKSPACE, path: join(root, "pnpm-workspace.yaml") },
|
|
576
|
+
];
|
|
577
|
+
}
|
|
578
|
+
if (
|
|
579
|
+
answers.packageManager === "yarn" &&
|
|
580
|
+
yarnMajor(env.userAgent) !== 1 &&
|
|
581
|
+
yarnProjectRoot(root) === null
|
|
582
|
+
) {
|
|
583
|
+
return [{ content: YARNRC, path: join(root, ".yarnrc.yml") }];
|
|
584
|
+
}
|
|
585
|
+
return [];
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
/**
|
|
589
|
+
* What the project still needs from a workspace it joins, when `init` left
|
|
590
|
+
* that workspace's config alone: pnpm's approval for esbuild's build script
|
|
591
|
+
* (pnpm 10 and later fail the install without it), or Yarn Berry's
|
|
592
|
+
* `node_modules` linker. Undefined when the workspace already has it, or the
|
|
593
|
+
* project doesn't sit in one.
|
|
594
|
+
*/
|
|
595
|
+
export const workspaceNote = (
|
|
596
|
+
root: string,
|
|
597
|
+
answers: InitAnswers,
|
|
598
|
+
env: PlanEnvironment = {}
|
|
599
|
+
): string | undefined => {
|
|
600
|
+
if (answers.packageManager === "pnpm") {
|
|
601
|
+
const workspace = pnpmWorkspaceRoot(root);
|
|
602
|
+
const file = workspace && join(workspace, "pnpm-workspace.yaml");
|
|
603
|
+
if (!file || readText(file).includes("esbuild")) {
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
return `This project joins the pnpm workspace at ${file}. Approve esbuild's build script there before installing, or pnpm 10 and later stop the install:\n\n allowBuilds:\n esbuild: true`;
|
|
607
|
+
}
|
|
608
|
+
if (answers.packageManager !== "yarn" || yarnMajor(env.userAgent) === 1) {
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
const project = yarnProjectRoot(root);
|
|
612
|
+
const rc = project && join(project, ".yarnrc.yml");
|
|
613
|
+
if (!rc || /^nodeLinker:\s*["']?(?:node-modules|pnpm)/mu.test(readText(rc))) {
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
return `This project joins the Yarn project at ${project}. With Yarn 2 or later, set its linker in ${rc} so installs write the node_modules Blume's generated Astro project resolves packages from:\n\n nodeLinker: node-modules`;
|
|
617
|
+
};
|
|
618
|
+
|
|
321
619
|
/** Every file `init` should write for the given answers, package.json first. */
|
|
322
620
|
export const buildPlan = (
|
|
323
621
|
root: string,
|
|
324
|
-
answers: InitAnswers
|
|
622
|
+
answers: InitAnswers,
|
|
623
|
+
env: PlanEnvironment = {}
|
|
325
624
|
): ScaffoldFile[] => {
|
|
326
625
|
const files: ScaffoldFile[] = [
|
|
327
626
|
{
|
|
@@ -331,6 +630,7 @@ export const buildPlan = (
|
|
|
331
630
|
),
|
|
332
631
|
path: join(root, "package.json"),
|
|
333
632
|
},
|
|
633
|
+
...packageManagerConfigFor(root, answers, env),
|
|
334
634
|
{ content: buildConfig(answers), path: join(root, "blume.config.ts") },
|
|
335
635
|
];
|
|
336
636
|
// Seed pages only make sense when a local filesystem source will read them.
|
|
@@ -370,7 +670,7 @@ const writeFileSafe = async (
|
|
|
370
670
|
|
|
371
671
|
/**
|
|
372
672
|
* Write the plan's files, skipping any that already exist. Reports whether a
|
|
373
|
-
* `package.json` was newly created (it decides
|
|
673
|
+
* `package.json` was newly created (it decides whether `init` installs).
|
|
374
674
|
*/
|
|
375
675
|
export const applyPlan = async (
|
|
376
676
|
files: ScaffoldFile[],
|
|
@@ -385,34 +685,118 @@ export const applyPlan = async (
|
|
|
385
685
|
return { createdPackage };
|
|
386
686
|
};
|
|
387
687
|
|
|
388
|
-
/** Env vars the selected sources
|
|
389
|
-
const envVarsFor = (sources: SourceKind[]): string[] =>
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
688
|
+
/** Env vars the selected sources declare, deduplicated in a stable order. */
|
|
689
|
+
const envVarsFor = (sources: SourceKind[]): string[] => [
|
|
690
|
+
...new Set(
|
|
691
|
+
descriptorsFor(sources).flatMap((descriptor) => descriptor.requiredSecrets)
|
|
692
|
+
),
|
|
693
|
+
];
|
|
694
|
+
|
|
695
|
+
/** What an existing package.json — one `init` left alone — already wires up. */
|
|
696
|
+
export interface ExistingPackage {
|
|
697
|
+
/**
|
|
698
|
+
* Whether `blume` is installed where the project resolves it: its own
|
|
699
|
+
* `node_modules`, or an ancestor's in a hoisted workspace. Listing it isn't
|
|
700
|
+
* enough — a rerun of `init --no-install` lists it without installing it.
|
|
701
|
+
*/
|
|
702
|
+
blumeInstalled: boolean;
|
|
703
|
+
/** Every package it lists in `dependencies` or `devDependencies`. */
|
|
704
|
+
dependencies: string[];
|
|
705
|
+
/** Whether its `dev` script runs Blume. */
|
|
706
|
+
devRunsBlume: boolean;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
/** Whether a `node_modules/blume` sits in `root` or any directory above it. */
|
|
710
|
+
const blumeResolves = (root: string): boolean => {
|
|
711
|
+
let dir = root;
|
|
712
|
+
while (!existsSync(join(dir, "node_modules", "blume", "package.json"))) {
|
|
713
|
+
const parent = dirname(dir);
|
|
714
|
+
if (parent === dir) {
|
|
715
|
+
return false;
|
|
716
|
+
}
|
|
717
|
+
dir = parent;
|
|
718
|
+
}
|
|
719
|
+
return true;
|
|
720
|
+
};
|
|
721
|
+
|
|
722
|
+
/**
|
|
723
|
+
* Read the package.json `init` didn't write. An unreadable or malformed one
|
|
724
|
+
* reads as wiring nothing up, so the next steps list everything to add.
|
|
725
|
+
*/
|
|
726
|
+
export const readExistingPackage = async (
|
|
727
|
+
root: string
|
|
728
|
+
): Promise<ExistingPackage> => {
|
|
729
|
+
try {
|
|
730
|
+
// SAFETY: only the two dependency maps and the `dev` script are read, all
|
|
731
|
+
// optional; `String()` absorbs a script that isn't a string.
|
|
732
|
+
const pkg = JSON.parse(
|
|
733
|
+
await readFile(join(root, "package.json"), "utf-8")
|
|
734
|
+
) as {
|
|
735
|
+
dependencies?: Record<string, string>;
|
|
736
|
+
devDependencies?: Record<string, string>;
|
|
737
|
+
scripts?: Record<string, string>;
|
|
738
|
+
};
|
|
739
|
+
return {
|
|
740
|
+
blumeInstalled: blumeResolves(root),
|
|
741
|
+
dependencies: Object.keys({
|
|
742
|
+
...pkg.dependencies,
|
|
743
|
+
...pkg.devDependencies,
|
|
744
|
+
}),
|
|
745
|
+
devRunsBlume: String(pkg.scripts?.dev ?? "").includes("blume"),
|
|
746
|
+
};
|
|
747
|
+
} catch {
|
|
748
|
+
return {
|
|
749
|
+
blumeInstalled: blumeResolves(root),
|
|
750
|
+
dependencies: [],
|
|
751
|
+
devRunsBlume: false,
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
};
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* The next-steps message: `cd` hint, the install command when `init` did not
|
|
758
|
+
* run it itself, the dev command, and token setup. With an `existing`
|
|
759
|
+
* package.json — which `init` never edits — it first adds whatever of `blume`
|
|
760
|
+
* and the sources' SDKs isn't listed yet (or installs, when everything is
|
|
761
|
+
* listed but `blume` was never installed), then starts the dev server through
|
|
762
|
+
* the package runner unless its `dev` script already runs Blume. A `note` —
|
|
763
|
+
* what a workspace the project joins still needs — closes the message.
|
|
764
|
+
*/
|
|
399
765
|
export const nextSteps = (
|
|
400
766
|
answers: InitAnswers,
|
|
401
|
-
|
|
767
|
+
needsInstall: boolean,
|
|
768
|
+
existing?: ExistingPackage,
|
|
769
|
+
note?: string
|
|
402
770
|
): string => {
|
|
403
771
|
const commands = commandsFor(answers.packageManager);
|
|
404
772
|
const lines: string[] = [];
|
|
405
773
|
if (answers.directory !== ".") {
|
|
406
774
|
lines.push(`cd ${answers.directory}`);
|
|
407
775
|
}
|
|
408
|
-
if (
|
|
776
|
+
if (needsInstall) {
|
|
409
777
|
lines.push(commands.install);
|
|
410
778
|
}
|
|
411
|
-
|
|
779
|
+
if (existing) {
|
|
780
|
+
const missing = [
|
|
781
|
+
"blume",
|
|
782
|
+
...Object.keys(extraDepsFor(answers.sources)),
|
|
783
|
+
].filter((dep) => !existing.dependencies.includes(dep));
|
|
784
|
+
if (missing.length > 0) {
|
|
785
|
+
lines.push(`${commands.add} ${missing.join(" ")}`);
|
|
786
|
+
} else if (!(needsInstall || existing.blumeInstalled)) {
|
|
787
|
+
lines.push(commands.install);
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
lines.push(
|
|
791
|
+
existing && !existing.devRunsBlume
|
|
792
|
+
? `${commands.exec} blume dev`
|
|
793
|
+
: commands.dev
|
|
794
|
+
);
|
|
412
795
|
const envVars = envVarsFor(answers.sources);
|
|
413
796
|
const auth =
|
|
414
797
|
envVars.length > 0
|
|
415
798
|
? `\nSet ${envVars.join(" and ")} in .env.local so your sources can authenticate.\n`
|
|
416
799
|
: "";
|
|
417
|
-
|
|
800
|
+
const workspace = note ? `\n${note}\n` : "";
|
|
801
|
+
return `Next steps:\n\n ${lines.join("\n ")}\n${auth}${workspace}`;
|
|
418
802
|
};
|