blume 1.6.6 → 1.7.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/CHANGELOG.md +17 -0
- package/dist/cli/{chunk-nyqzjdhj.js → chunk-0qhq7b8q.js} +5 -5
- package/dist/cli/{chunk-cnvm6k3e.js → chunk-18tjv4f7.js} +11 -11
- package/dist/cli/{chunk-62qsssnh.js → chunk-5d4q7121.js} +401 -145
- package/dist/cli/chunk-5d4q7121.js.map +40 -0
- package/dist/cli/{chunk-ag1zyr5x.js → chunk-9qs6acpw.js} +11 -11
- package/dist/cli/{chunk-aerwpe14.js → chunk-agy5rzxy.js} +98 -15
- package/dist/cli/chunk-agy5rzxy.js.map +15 -0
- package/dist/cli/{chunk-x1vrdjyk.js → chunk-cfw6x4rm.js} +5 -5
- package/dist/cli/{chunk-bawgnt8x.js → chunk-ckh3a410.js} +3 -3
- package/dist/cli/{chunk-j00ezcg5.js → chunk-drke6t0h.js} +9 -9
- package/dist/cli/{chunk-3k0kzs6d.js → chunk-j6pxe0dt.js} +2 -2
- package/dist/cli/{chunk-n0y172hf.js → chunk-jk1zwka1.js} +4 -4
- package/dist/cli/{chunk-f75cqye8.js → chunk-jxkxjsc1.js} +10 -10
- package/dist/cli/{chunk-s4k1pnvf.js → chunk-kwx90v78.js} +11 -11
- package/dist/cli/{chunk-9sh49q0h.js → chunk-n0nyat6g.js} +2 -2
- package/dist/cli/{chunk-wkq5tbtq.js → chunk-qq9nm3qd.js} +3 -3
- package/dist/cli/{chunk-etsqspj6.js → chunk-s102bysw.js} +2 -2
- package/dist/cli/{chunk-wb067mv3.js → chunk-s5dsk8bj.js} +18 -7
- package/dist/cli/chunk-s5dsk8bj.js.map +13 -0
- package/dist/cli/{chunk-m3p3wahd.js → chunk-tnskyrej.js} +4 -4
- package/dist/cli/{chunk-vv237fp3.js → chunk-v2ymm99c.js} +26 -12
- package/dist/cli/{chunk-vv237fp3.js.map → chunk-v2ymm99c.js.map} +3 -3
- package/dist/cli/{chunk-5yvt556e.js → chunk-v5mm027v.js} +2 -2
- package/dist/cli/{chunk-vv3f8mb6.js → chunk-xv91q4nm.js} +24 -24
- package/dist/cli/{chunk-vv3f8mb6.js.map → chunk-xv91q4nm.js.map} +3 -3
- package/dist/cli/{chunk-0ewz4trd.js → chunk-y3g15rvv.js} +6 -6
- package/dist/cli/{chunk-tc89yh2r.js → chunk-ye9zdkgv.js} +2 -2
- package/dist/cli/{chunk-n4qjabmt.js → chunk-ynacq3ev.js} +4 -4
- package/dist/cli/{chunk-s4jn7f1q.js → chunk-zr3ygrq3.js} +2 -2
- package/dist/cli/index.js +13 -13
- package/dist/types/components/layout/nav-utils.d.ts +33 -1
- package/dist/types/theme/fonts.d.ts +22 -22
- package/docs/02-deployment.mdx +21 -0
- package/docs/content/navigation.mdx +2 -0
- package/docs/content/syntax.mdx +1 -1
- package/docs/discoverability/open-graph.mdx +4 -0
- package/package.json +1 -1
- package/src/astro/generate.ts +141 -5
- package/src/astro/integration.ts +12 -1
- package/src/astro/module-types.ts +9 -0
- package/src/astro/templates.ts +171 -11
- package/src/cli/commands/build.ts +28 -0
- package/src/components/Icon.astro +24 -0
- package/src/components/icon-sprite-middleware.ts +41 -0
- package/src/components/icon-sprite.ts +93 -0
- package/src/components/layout/IconSprite.astro +11 -0
- package/src/components/layout/NavTree.astro +156 -188
- package/src/components/layout/NavTreeCache.astro +45 -0
- package/src/components/layout/NavTreeScript.astro +256 -0
- package/src/components/layout/PageActions.astro +11 -5
- package/src/components/layout/PageLayout.astro +7 -0
- package/src/components/layout/ReferenceLayout.astro +7 -0
- package/src/components/layout/RootLayout.astro +30 -2
- package/src/components/layout/nav-cache.ts +49 -0
- package/src/components/layout/nav-utils.ts +69 -1
- package/src/markdown/language-icon.ts +64 -20
- package/src/markdown/mermaid.ts +11 -0
- package/src/og/cache.ts +236 -0
- package/src/og/card.ts +12 -4
- package/src/og/index.ts +8 -1
- package/src/registry/eject.ts +23 -8
- package/src/theme/entry.ts +41 -7
- package/src/theme/fonts.ts +30 -23
- package/dist/cli/chunk-62qsssnh.js.map +0 -36
- package/dist/cli/chunk-aerwpe14.js.map +0 -15
- package/dist/cli/chunk-wb067mv3.js.map +0 -13
- /package/dist/cli/{chunk-nyqzjdhj.js.map → chunk-0qhq7b8q.js.map} +0 -0
- /package/dist/cli/{chunk-cnvm6k3e.js.map → chunk-18tjv4f7.js.map} +0 -0
- /package/dist/cli/{chunk-ag1zyr5x.js.map → chunk-9qs6acpw.js.map} +0 -0
- /package/dist/cli/{chunk-x1vrdjyk.js.map → chunk-cfw6x4rm.js.map} +0 -0
- /package/dist/cli/{chunk-bawgnt8x.js.map → chunk-ckh3a410.js.map} +0 -0
- /package/dist/cli/{chunk-j00ezcg5.js.map → chunk-drke6t0h.js.map} +0 -0
- /package/dist/cli/{chunk-3k0kzs6d.js.map → chunk-j6pxe0dt.js.map} +0 -0
- /package/dist/cli/{chunk-n0y172hf.js.map → chunk-jk1zwka1.js.map} +0 -0
- /package/dist/cli/{chunk-f75cqye8.js.map → chunk-jxkxjsc1.js.map} +0 -0
- /package/dist/cli/{chunk-s4k1pnvf.js.map → chunk-kwx90v78.js.map} +0 -0
- /package/dist/cli/{chunk-9sh49q0h.js.map → chunk-n0nyat6g.js.map} +0 -0
- /package/dist/cli/{chunk-wkq5tbtq.js.map → chunk-qq9nm3qd.js.map} +0 -0
- /package/dist/cli/{chunk-etsqspj6.js.map → chunk-s102bysw.js.map} +0 -0
- /package/dist/cli/{chunk-m3p3wahd.js.map → chunk-tnskyrej.js.map} +0 -0
- /package/dist/cli/{chunk-5yvt556e.js.map → chunk-v5mm027v.js.map} +0 -0
- /package/dist/cli/{chunk-0ewz4trd.js.map → chunk-y3g15rvv.js.map} +0 -0
- /package/dist/cli/{chunk-tc89yh2r.js.map → chunk-ye9zdkgv.js.map} +0 -0
- /package/dist/cli/{chunk-n4qjabmt.js.map → chunk-ynacq3ev.js.map} +0 -0
- /package/dist/cli/{chunk-s4jn7f1q.js.map → chunk-zr3ygrq3.js.map} +0 -0
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/cli/commands/build.ts", "../src/deploy/cloudflare-negotiation.ts", "../src/deploy/function-bundle.ts", "../src/deploy/vercel-negotiation.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import { existsSync } from \"node:fs\";\nimport { readdir, readFile, stat, writeFile } from \"node:fs/promises\";\n\nimport { build } from \"astro\";\nimport { defineCommand } from \"citty\";\nimport { join } from \"pathe\";\n\nimport {\n API_CATALOG_PATH,\n API_CATALOG_TYPE,\n hasApiCatalog,\n} from \"../../ai/api-catalog.ts\";\nimport { pageJsonPath } from \"../../ai/api/paths.ts\";\nimport { buildHomeLinkHeader } from \"../../ai/link-headers.ts\";\nimport {\n agentMarkdown,\n buildRawMarkdown,\n markdownRoutePaths,\n markdownTokenCount,\n} from \"../../ai/markdown.ts\";\nimport {\n SIGNATURES_DIRECTORY_PATH,\n SIGNATURES_DIRECTORY_TYPE,\n} from \"../../ai/web-bot-auth.ts\";\nimport { publishBuildProject } from \"../../astro/integration.ts\";\nimport { ensureGitignore } from \"../../core/gitignore.ts\";\nimport type { BlumeProject } from \"../../core/project-graph.ts\";\nimport type { ResolvedConfig } from \"../../core/schema.ts\";\nimport { serverFeatures } from \"../../core/server-features.ts\";\nimport type { ProjectContext } from \"../../core/types.ts\";\nimport {\n ADAPTER_IGNORE_DIRS,\n deployStaticDir,\n servesClientSubdir,\n surfaceAdapterOutput,\n} from \"../../deploy/adapter-output.ts\";\nimport {\n injectWorkerNegotiation,\n NEGOTIATION_WORKER_FILE,\n} from \"../../deploy/cloudflare-negotiation.ts\";\nimport {\n auditVercelFunctions,\n blumeDependencyNames,\n functionBundleVerdict,\n} from \"../../deploy/function-bundle.ts\";\nimport { platformRedirects } from \"../../deploy/redirects.ts\";\nimport { injectNegotiationRoutes } from \"../../deploy/vercel-negotiation.ts\";\nimport { commandMeta } from \"../command-meta.ts\";\nimport { refuseIfDevRunning } from \"../dev-lock.ts\";\nimport { logger } from \"../log.ts\";\nimport { prepareProject } from \"../prepare.ts\";\n\nconst ADAPTERS = [\"vercel\", \"node\", \"netlify\", \"cloudflare\"] as const;\n\nconst isAdapter = (value: string): value is (typeof ADAPTERS)[number] =>\n ADAPTERS.some((adapter) => adapter === value);\n\nconst BUDGET_JS = \"budget-js\";\nconst BUDGET_CSS = \"budget-css\";\n\ninterface BudgetArgs {\n \"budget-css\"?: string;\n \"budget-js\"?: string;\n}\n\n/**\n * Reject a non-numeric performance budget. `Number(\"250kb\")` is `NaN` and\n * `total > NaN` is always false, so a typo'd flag would silently pass the gate;\n * fail up front instead.\n */\nconst validateBudgetFlags = (args: BudgetArgs): void => {\n for (const flag of [BUDGET_JS, BUDGET_CSS] as const) {\n const value = args[flag];\n const parsed = Number(value);\n // Equivalent to `!(parsed > 0)` but without the inverted check: this must\n // also reject `NaN` (a typo'd flag like \"250kb\"), which `parsed <= 0` alone\n // would let through since `NaN <= 0` is false.\n if (value !== undefined && (Number.isNaN(parsed) || parsed <= 0)) {\n logger.error(\n `Invalid --${flag} \"${value}\" (expected a positive number of kB).`\n );\n process.exit(1);\n }\n }\n};\n\n/**\n * Splice `Accept: text/markdown` negotiation routes into the Vercel adapter's\n * Build Output config, so a content-page request that prefers Markdown gets the\n * page's prerendered `.md` mirror (content pages are prerendered even in server\n * output, so Astro middleware never sees them — the routing layer is the only\n * request-time hook). Vercel server builds only; the adapter writes the config\n * straight to the project root (see `withAdapterRoot`).\n */\nconst emitVercelNegotiation = async (\n project: BlumeProject,\n routePaths: string[],\n root: string\n): Promise<void> => {\n const { config } = project;\n const configPath = join(root, \".vercel\", \"output\", \"config.json\");\n if (!existsSync(configPath)) {\n return;\n }\n const overrides: Record<string, string> = {};\n if (hasApiCatalog(config)) {\n overrides[API_CATALOG_PATH.slice(1)] = API_CATALOG_TYPE;\n }\n if (config.ai.webBotAuth.keys.length > 0) {\n overrides[SIGNATURES_DIRECTORY_PATH.slice(1)] = SIGNATURES_DIRECTORY_TYPE;\n }\n // The homepage rewrite serves `/index.md` from the static layer, so its\n // `x-markdown-tokens` estimate has to ride the routing config; the runtime\n // endpoint stamps it on dev/server-rendered responses itself.\n const rawMarkdown = await buildRawMarkdown(project);\n const home = rawMarkdown[\"/\"];\n // The Markdown and JSON 404 routes point at the prerendered twins; only\n // wire each when the build actually emitted it (a project that owns `/404`\n // gets none).\n const staticDir = join(root, \".vercel\", \"output\", \"static\");\n const injected = injectNegotiationRoutes(\n await readFile(configPath, \"utf-8\"),\n routePaths,\n buildHomeLinkHeader(config, routePaths),\n overrides,\n home ? markdownTokenCount(agentMarkdown(home)) : undefined,\n {\n json: existsSync(join(staticDir, \"404.json\")),\n markdown: existsSync(join(staticDir, \"404.md\")),\n }\n );\n if (injected === null) {\n logger.warn(\n \"Could not wire Accept: text/markdown negotiation into .vercel/output/config.json — raw Markdown stays available at the .md URLs.\"\n );\n return;\n }\n await writeFile(configPath, injected, \"utf-8\");\n logger.success(\n \"Wired Accept: text/markdown negotiation into the Vercel routing config\"\n );\n};\n\n/**\n * Refuse to ship a Vercel function bundle that would crash at runtime: a bare\n * import the adapter's dependency trace silently dropped (see\n * `deploy/function-bundle.ts`). A missing package that is one of Blume's own\n * dependencies is fatal — the generated runtime imports it, so every request\n * would die; a project's own external import is reported as a warning and left\n * to the author.\n */\nconst checkVercelFunctionBundles = async (\n outputDir: string,\n root: string\n): Promise<void> => {\n const audits = await auditVercelFunctions(outputDir);\n if (audits.length === 0) {\n return;\n }\n const own = blumeDependencyNames();\n let fatal = false;\n for (const audit of audits) {\n const verdict = functionBundleVerdict(audit, root, own);\n if (verdict.fatal) {\n fatal = true;\n logger.error(verdict.message);\n } else {\n logger.warn(verdict.message);\n }\n }\n if (fatal) {\n process.exit(1);\n }\n};\n\nconst warnCloudflareNegotiationSkipped = (): void =>\n logger.warn(\n \"Could not wire Accept: text/markdown negotiation into dist/server/wrangler.json — raw Markdown stays available at the .md URLs.\"\n );\n\n/**\n * Wire `Accept: text/markdown` negotiation into a Cloudflare server build. The\n * ASSETS binding serves the prerendered content pages before the Worker runs —\n * and even a request that reaches the Worker is answered by the adapter's\n * handler from that binding, ahead of the only place middleware runs — so the\n * negotiation lives in a generated wrapper Worker, routed to by\n * `assets.run_worker_first` (see `deploy/cloudflare-negotiation.ts`). Both\n * pieces are spliced into the adapter's emitted `dist/server` bundle.\n */\nconst emitCloudflareNegotiation = async (\n project: BlumeProject,\n routePaths: string[]\n): Promise<void> => {\n const { config, context } = project;\n const serverDir = join(\n context.distDir ?? join(context.root, \"dist\"),\n \"server\"\n );\n const wranglerPath = join(serverDir, \"wrangler.json\");\n if (!existsSync(wranglerPath)) {\n warnCloudflareNegotiationSkipped();\n return;\n }\n // The homepage mirror is served from the static layer, so its\n // `x-markdown-tokens` estimate rides the wrapper Worker, mirroring the\n // Vercel routing config.\n const rawMarkdown = await buildRawMarkdown(project);\n const home = rawMarkdown[\"/\"];\n const injected = injectWorkerNegotiation(\n await readFile(wranglerPath, \"utf-8\"),\n {\n base: config.deployment.base,\n // The manifest routes guard the wrapper's redirect table; `routePaths`\n // also carries the synthesized homepage mirror, which must not block a\n // configured root redirect.\n contentRoutePaths: project.manifest.routes.map((route) => route.path),\n homeLinkHeader: buildHomeLinkHeader(config, routePaths),\n homeTokens: home ? markdownTokenCount(agentMarkdown(home)) : undefined,\n // Exactly the per-page JSON documents the API emits (see `pageParams`):\n // the non-hidden routes with agent Markdown, when the API is on.\n pageJsonPaths: config.ai.api\n ? project.manifest.routes\n .filter(\n (route) => !route.hidden && rawMarkdown[route.path] !== undefined\n )\n .map((route) => pageJsonPath(route.path))\n : [],\n // The wrapper Worker matches full served URLs, so the redirects are\n // based the same way the platform files are — it answers any the\n // worker-first rules claim, where `_redirects` is never consulted and\n // Astro would default their status.\n redirects: platformRedirects(config),\n routePaths,\n }\n );\n if (injected === null) {\n warnCloudflareNegotiationSkipped();\n return;\n }\n await writeFile(\n join(serverDir, NEGOTIATION_WORKER_FILE),\n injected.worker,\n \"utf-8\"\n );\n await writeFile(wranglerPath, injected.wrangler, \"utf-8\");\n logger.success(\n \"Wired Accept: text/markdown negotiation into the Cloudflare Worker\"\n );\n};\n\nconst formatBytes = (bytes: number): string => {\n if (bytes < 1024) {\n return `${bytes} B`;\n }\n const digits = bytes < 1024 * 100 ? 1 : 0;\n return `${(bytes / 1024).toFixed(digits)} kB`;\n};\n\n/** Sizes of `dist/_astro/*.<ext>`, largest first (empty when none exist). */\nconst astroAssets = async (\n distDir: string,\n ext: string\n): Promise<{ name: string; size: number }[]> => {\n const astroDir = join(distDir, \"_astro\");\n if (!existsSync(astroDir)) {\n return [];\n }\n const entries = await readdir(astroDir);\n const files = entries.filter((name) => name.endsWith(`.${ext}`));\n const sized = await Promise.all(\n files.map(async (name) => {\n const info = await stat(join(astroDir, name));\n return { name, size: info.size };\n })\n );\n return sized.toSorted((a, b) => b.size - a.size);\n};\n\nconst totalSize = (assets: { size: number }[]): number =>\n assets.reduce((sum, asset) => sum + asset.size, 0);\n\n/**\n * Print the client JavaScript Astro shipped, largest first, plus the total. A\n * dependency-free bundle report — the interactive weight of a docs site is its\n * `_astro/*.js`, so this surfaces regressions without a visualizer.\n */\nconst reportBundleSizes = async (distDir: string): Promise<void> => {\n const sized = await astroAssets(distDir, \"js\");\n if (sized.length === 0) {\n logger.info(\"No client JavaScript emitted — the site ships zero JS.\");\n return;\n }\n const rows = sized\n .slice(0, 15)\n .map((file) => ` ${formatBytes(file.size).padStart(8)} ${file.name}`);\n logger.box(\n [\n `Client JavaScript — ${sized.length} file(s), ${formatBytes(totalSize(sized))} total`,\n \"\",\n ...rows,\n sized.length > 15 ? ` … and ${sized.length - 15} more` : null,\n ]\n .filter((line) => line !== null)\n .join(\"\\n\")\n );\n};\n\n/**\n * Enforce a performance budget on the built client assets: fail the build when\n * total `_astro/*.js` (or `*.css`) exceeds the given kB cap. Budgets that would\n * otherwise be \"documented, not measured\" become a real CI gate. Returns whether\n * every budget passed.\n */\nconst enforceBudget = async (\n distDir: string,\n args: BudgetArgs\n): Promise<\"fail\" | \"pass\" | \"skip\"> => {\n const checks: { ext: string; limitKb: number; name: string }[] = [\n ...(args[BUDGET_JS]\n ? [{ ext: \"js\", limitKb: Number(args[BUDGET_JS]), name: \"JavaScript\" }]\n : []),\n ...(args[BUDGET_CSS]\n ? [{ ext: \"css\", limitKb: Number(args[BUDGET_CSS]), name: \"CSS\" }]\n : []),\n ];\n if (checks.length === 0) {\n return \"skip\";\n }\n let passed = true;\n for (const check of checks) {\n // oxlint-disable-next-line no-await-in-loop -- a couple of sequential reads\n const total = totalSize(await astroAssets(distDir, check.ext));\n const limit = check.limitKb * 1024;\n if (total > limit) {\n passed = false;\n logger.error(\n `${check.name} budget exceeded: ${formatBytes(total)} > ${check.limitKb} kB`\n );\n } else {\n logger.success(\n `${check.name} budget: ${formatBytes(total)} / ${check.limitKb} kB`\n );\n }\n }\n return passed ? \"pass\" : \"fail\";\n};\n\n/**\n * Run the optional bundle report (`--analyze`) and performance-budget gate\n * against the directory whose `_astro/` client assets the deploy serves.\n * Shared by real and isolated builds — an isolated CI run passing\n * `--budget-js` must still fail on an exceeded budget rather than silently\n * skipping the check. Exits non-zero when a budget is exceeded.\n */\nexport const runClientAssetChecks = async (\n staticDir: string,\n args: { analyze?: boolean } & BudgetArgs\n): Promise<void> => {\n if (args.analyze) {\n await reportBundleSizes(staticDir);\n }\n if ((await enforceBudget(staticDir, args)) === \"fail\") {\n process.exit(1);\n }\n};\n\n/**\n * Root of an isolated build's output. The runtime-local `dist/`, except for a\n * Vercel server build, whose deploy bundle lands at `<runtime>/.vercel/output`\n * and is never surfaced to the project root.\n */\nexport const isolatedOutputDir = (\n config: ResolvedConfig,\n context: ProjectContext\n): string => {\n const { adapter, output } = config.deployment;\n if (output === \"server\" && adapter === \"vercel\") {\n return join(context.outDir, \".vercel\", \"output\");\n }\n return context.distDir ?? join(context.outDir, \"dist\");\n};\n\n/**\n * Directory holding an isolated build's client `_astro/` assets. Mirrors\n * `deployStaticDir`, except that an isolated build never surfaces the adapter\n * bundle to the project root — a Vercel server build's static output stays at\n * `<runtime>/.vercel/output/static`, where `deployStaticDir` would instead\n * point at the project-root copy (a previous real build's assets, or nothing).\n * Node and Cloudflare server builds serve one level down, at `client/` — see\n * {@link servesClientSubdir}.\n */\nexport const isolatedStaticDir = (\n config: ResolvedConfig,\n context: ProjectContext\n): string => {\n const { adapter, output } = config.deployment;\n const outputDir = isolatedOutputDir(config, context);\n if (output === \"server\" && adapter === \"vercel\") {\n return join(outputDir, \"static\");\n }\n if (servesClientSubdir(config.deployment)) {\n return join(outputDir, \"client\");\n }\n return outputDir;\n};\n\n/**\n * Print the build summary box and run the optional bundle report / budget\n * gate against the served static dir. The deploy artifacts themselves\n * (search index, llms.txt, sitemap, robots, redirect and header files, …)\n * were written by the integration's `astro:build:done` hook during\n * `build()` — see `deploy/artifacts.ts`. Exits non-zero if a budget is\n * exceeded.\n */\nconst reportBuild = async (\n project: BlumeProject,\n distDir: string,\n args: { analyze?: boolean } & BudgetArgs\n): Promise<void> => {\n const { config } = project;\n const features = serverFeatures(config);\n // The sitemap needs both the flag and a `site` (absolute URLs) — only the\n // latter deserves the remediation hint.\n const sitemapNote = config.seo.sitemap\n ? \"no (set deployment.site)\"\n : \"no (seo.sitemap is false)\";\n logger.box(\n [\n `Output ${config.deployment.output}`,\n `Adapter ${config.deployment.adapter ?? \"none\"}`,\n `Site ${config.deployment.site ?? \"not set\"}`,\n `Search ${config.search.provider}`,\n `Redirects ${config.redirects.length}`,\n `Sitemap ${config.deployment.site && config.seo.sitemap ? \"yes\" : sitemapNote}`,\n `Robots ${config.seo.robots ? \"yes\" : \"no\"}`,\n `Agent JSON ${config.seo.agentReadability ? \"yes\" : \"no\"}`,\n `LLM files ${config.ai.llmsTxt.enabled ? \"yes\" : \"no\"}`,\n `Server features ${features.length > 0 ? features.join(\", \") : \"none\"}`,\n ].join(\"\\n\")\n );\n\n await runClientAssetChecks(distDir, args);\n\n // Only reachable with --no-strict (strict aborts earlier): repeat the missing\n // count next to the success banner so it can't scroll away unseen.\n if (project.droppedPages > 0) {\n logger.warn(\n `${project.droppedPages} page(s) failed frontmatter validation and are missing from this build.`\n );\n }\n logger.success(`Built to ${distDir}`);\n};\n\nexport const buildCommand = defineCommand({\n args: {\n adapter: {\n description: \"Server adapter: vercel | node | netlify | cloudflare.\",\n type: \"string\",\n },\n analyze: {\n description: \"Report client JavaScript bundle sizes after the build.\",\n type: \"boolean\",\n },\n base: {\n description: \"Base path the site is served under (e.g. /docs).\",\n type: \"string\",\n },\n [BUDGET_CSS]: {\n description: \"Fail if total client CSS exceeds this many kB.\",\n type: \"string\",\n },\n [BUDGET_JS]: {\n description: \"Fail if total client JavaScript exceeds this many kB.\",\n type: \"string\",\n },\n isolated: {\n description:\n \"Build into an isolated .blume-verify runtime (and its own dist) so a running dev server and the real dist/ are untouched. For verifying changes while `blume dev` runs.\",\n type: \"boolean\",\n },\n output: {\n description: \"Output mode: static | server.\",\n type: \"string\",\n },\n preview: {\n description: \"Include drafts and unpublished CMS content.\",\n type: \"boolean\",\n },\n strict: {\n default: true,\n description:\n \"Fail on error diagnostics (default; pass --no-strict to build anyway, dropping pages that fail validation).\",\n type: \"boolean\",\n },\n },\n meta: commandMeta.build,\n async run({ args }) {\n const root = process.cwd();\n\n // `--isolated` (or BLUME_RUNTIME_DIR) relocates the whole runtime to a\n // sibling dir so this build never touches a live dev server's `.blume/` or\n // the user's real `dist/`. A non-default runtime dir has no dev lock, so the\n // refusal below lets it proceed; a plain build still refuses.\n const runtimeDir = args.isolated\n ? \".blume-verify\"\n : process.env.BLUME_RUNTIME_DIR;\n refuseIfDevRunning(root, \"building\", { isolatedHint: true, runtimeDir });\n if (args.isolated) {\n await ensureGitignore(root, [\".blume-verify/\"]);\n }\n\n if (args.output && args.output !== \"static\" && args.output !== \"server\") {\n logger.error(`Invalid --output \"${args.output}\" (use static | server).`);\n process.exit(1);\n }\n if (args.adapter && !isAdapter(args.adapter)) {\n logger.error(\n `Invalid --adapter \"${args.adapter}\" (use ${ADAPTERS.join(\" | \")}).`\n );\n process.exit(1);\n }\n validateBudgetFlags(args);\n\n const project = await prepareProject({\n mode: \"build\",\n overrides: {\n // SAFETY: an invalid --adapter exited above; a set flag is an ADAPTERS\n // member.\n adapter: args.adapter as (typeof ADAPTERS)[number] | undefined,\n base: args.base,\n // SAFETY: an invalid --output exited above; a set flag is static or\n // server.\n output: args.output as \"server\" | \"static\" | undefined,\n },\n preview: args.preview,\n root,\n runtimeDir,\n strict: args.strict,\n });\n\n logger.start(\n `Building ${project.graph.pages.length} page(s) (${project.config.deployment.output} output)`\n );\n\n // Hand the scanned project to the integration: its `astro:build:done`\n // hook writes the deploy artifacts (search index, llms.txt, sitemap, …)\n // into Astro's client output during the build. An isolated build is a\n // throwaway verify that only needs to confirm the site compiles and\n // renders, so it publishes nothing — no network post-steps (a hosted\n // search sync would push), no deploy artifacts.\n if (!runtimeDir) {\n publishBuildProject(project);\n }\n\n await build({\n logLevel: \"info\",\n root: project.context.outDir,\n });\n\n // The bundle report and budget gate still run for an isolated build —\n // `blume build --isolated --budget-js 100` exiting 0 without measuring\n // anything would be a silent false pass in CI.\n if (runtimeDir) {\n if (\n project.config.deployment.output === \"server\" &&\n project.config.deployment.adapter === \"vercel\"\n ) {\n await checkVercelFunctionBundles(\n isolatedOutputDir(project.config, project.context),\n root\n );\n }\n await runClientAssetChecks(\n isolatedStaticDir(project.config, project.context),\n args\n );\n logger.success(\n `Isolated build OK — output at ${isolatedOutputDir(project.config, project.context)} (not published).`\n );\n return;\n }\n\n // A server adapter's deploy bundle is a build artifact — keep it out of\n // version control (Vercel's own CLI ignores `.vercel/` for the same reason).\n // Ignoring it is independent of whether the bundle had to be moved below:\n // Vercel writes straight to the project root, Netlify does not.\n const { adapter } = project.config.deployment;\n const ignoreDir = adapter ? ADAPTER_IGNORE_DIRS[adapter] : undefined;\n if (project.config.deployment.output === \"server\" && ignoreDir) {\n await ensureGitignore(root, [ignoreDir]);\n }\n\n // Netlify writes its deploy bundle relative to the Astro root — which Blume\n // points at the hidden `.blume` runtime — so the bundle lands where the\n // deploy platform never looks. Surface it up to the project root before\n // publishing artifacts into the served static dir.\n const surfaced = await surfaceAdapterOutput(\n project.config,\n project.context\n );\n if (surfaced.moved) {\n logger.success(`Surfaced ${adapter} output to ${surfaced.to}`);\n }\n\n if (project.config.deployment.output === \"server\" && adapter === \"vercel\") {\n await checkVercelFunctionBundles(join(root, \".vercel\", \"output\"), root);\n await emitVercelNegotiation(project, markdownRoutePaths(project), root);\n }\n\n if (\n project.config.deployment.output === \"server\" &&\n adapter === \"cloudflare\"\n ) {\n await emitCloudflareNegotiation(project, markdownRoutePaths(project));\n }\n\n await reportBuild(\n project,\n deployStaticDir(project.config, project.context),\n args\n );\n },\n});\n",
|
|
5
|
+
"import { existsSync } from \"node:fs\";\nimport { readdir, readFile, stat, writeFile } from \"node:fs/promises\";\n\nimport { build } from \"astro\";\nimport { defineCommand } from \"citty\";\nimport { join } from \"pathe\";\n\nimport {\n API_CATALOG_PATH,\n API_CATALOG_TYPE,\n hasApiCatalog,\n} from \"../../ai/api-catalog.ts\";\nimport { pageJsonPath } from \"../../ai/api/paths.ts\";\nimport { buildHomeLinkHeader } from \"../../ai/link-headers.ts\";\nimport {\n agentMarkdown,\n buildRawMarkdown,\n markdownRoutePaths,\n markdownTokenCount,\n} from \"../../ai/markdown.ts\";\nimport {\n SIGNATURES_DIRECTORY_PATH,\n SIGNATURES_DIRECTORY_TYPE,\n} from \"../../ai/web-bot-auth.ts\";\nimport { publishBuildProject } from \"../../astro/integration.ts\";\nimport { ensureGitignore } from \"../../core/gitignore.ts\";\nimport type { BlumeProject } from \"../../core/project-graph.ts\";\nimport type { ResolvedConfig } from \"../../core/schema.ts\";\nimport { serverFeatures } from \"../../core/server-features.ts\";\nimport type { ProjectContext } from \"../../core/types.ts\";\nimport {\n ADAPTER_IGNORE_DIRS,\n deployStaticDir,\n servesClientSubdir,\n surfaceAdapterOutput,\n} from \"../../deploy/adapter-output.ts\";\nimport {\n injectWorkerNegotiation,\n NEGOTIATION_WORKER_FILE,\n} from \"../../deploy/cloudflare-negotiation.ts\";\nimport {\n auditVercelFunctions,\n blumeDependencyNames,\n functionBundleVerdict,\n} from \"../../deploy/function-bundle.ts\";\nimport { platformRedirects } from \"../../deploy/redirects.ts\";\nimport { injectNegotiationRoutes } from \"../../deploy/vercel-negotiation.ts\";\nimport { cardCacheTally, ogCacheDir, pruneCardCache } from \"../../og/cache.ts\";\nimport { commandMeta } from \"../command-meta.ts\";\nimport { refuseIfDevRunning } from \"../dev-lock.ts\";\nimport { logger } from \"../log.ts\";\nimport { prepareProject } from \"../prepare.ts\";\n\nconst ADAPTERS = [\"vercel\", \"node\", \"netlify\", \"cloudflare\"] as const;\n\nconst isAdapter = (value: string): value is (typeof ADAPTERS)[number] =>\n ADAPTERS.some((adapter) => adapter === value);\n\nconst BUDGET_JS = \"budget-js\";\nconst BUDGET_CSS = \"budget-css\";\n\ninterface BudgetArgs {\n \"budget-css\"?: string;\n \"budget-js\"?: string;\n}\n\n/**\n * Reject a non-numeric performance budget. `Number(\"250kb\")` is `NaN` and\n * `total > NaN` is always false, so a typo'd flag would silently pass the gate;\n * fail up front instead.\n */\nconst validateBudgetFlags = (args: BudgetArgs): void => {\n for (const flag of [BUDGET_JS, BUDGET_CSS] as const) {\n const value = args[flag];\n const parsed = Number(value);\n // Equivalent to `!(parsed > 0)` but without the inverted check: this must\n // also reject `NaN` (a typo'd flag like \"250kb\"), which `parsed <= 0` alone\n // would let through since `NaN <= 0` is false.\n if (value !== undefined && (Number.isNaN(parsed) || parsed <= 0)) {\n logger.error(\n `Invalid --${flag} \"${value}\" (expected a positive number of kB).`\n );\n process.exit(1);\n }\n }\n};\n\n/**\n * Splice `Accept: text/markdown` negotiation routes into the Vercel adapter's\n * Build Output config, so a content-page request that prefers Markdown gets the\n * page's prerendered `.md` mirror (content pages are prerendered even in server\n * output, so Astro middleware never sees them — the routing layer is the only\n * request-time hook). Vercel server builds only; the adapter writes the config\n * straight to the project root (see `withAdapterRoot`).\n */\nconst emitVercelNegotiation = async (\n project: BlumeProject,\n routePaths: string[],\n root: string\n): Promise<void> => {\n const { config } = project;\n const configPath = join(root, \".vercel\", \"output\", \"config.json\");\n if (!existsSync(configPath)) {\n return;\n }\n const overrides: Record<string, string> = {};\n if (hasApiCatalog(config)) {\n overrides[API_CATALOG_PATH.slice(1)] = API_CATALOG_TYPE;\n }\n if (config.ai.webBotAuth.keys.length > 0) {\n overrides[SIGNATURES_DIRECTORY_PATH.slice(1)] = SIGNATURES_DIRECTORY_TYPE;\n }\n // The homepage rewrite serves `/index.md` from the static layer, so its\n // `x-markdown-tokens` estimate has to ride the routing config; the runtime\n // endpoint stamps it on dev/server-rendered responses itself.\n const rawMarkdown = await buildRawMarkdown(project);\n const home = rawMarkdown[\"/\"];\n // The Markdown and JSON 404 routes point at the prerendered twins; only\n // wire each when the build actually emitted it (a project that owns `/404`\n // gets none).\n const staticDir = join(root, \".vercel\", \"output\", \"static\");\n const injected = injectNegotiationRoutes(\n await readFile(configPath, \"utf-8\"),\n routePaths,\n buildHomeLinkHeader(config, routePaths),\n overrides,\n home ? markdownTokenCount(agentMarkdown(home)) : undefined,\n {\n json: existsSync(join(staticDir, \"404.json\")),\n markdown: existsSync(join(staticDir, \"404.md\")),\n }\n );\n if (injected === null) {\n logger.warn(\n \"Could not wire Accept: text/markdown negotiation into .vercel/output/config.json — raw Markdown stays available at the .md URLs.\"\n );\n return;\n }\n await writeFile(configPath, injected, \"utf-8\");\n logger.success(\n \"Wired Accept: text/markdown negotiation into the Vercel routing config\"\n );\n};\n\n/**\n * Refuse to ship a Vercel function bundle that would crash at runtime: a bare\n * import the adapter's dependency trace silently dropped (see\n * `deploy/function-bundle.ts`). A missing package that is one of Blume's own\n * dependencies is fatal — the generated runtime imports it, so every request\n * would die; a project's own external import is reported as a warning and left\n * to the author.\n */\nconst checkVercelFunctionBundles = async (\n outputDir: string,\n root: string\n): Promise<void> => {\n const audits = await auditVercelFunctions(outputDir);\n if (audits.length === 0) {\n return;\n }\n const own = blumeDependencyNames();\n let fatal = false;\n for (const audit of audits) {\n const verdict = functionBundleVerdict(audit, root, own);\n if (verdict.fatal) {\n fatal = true;\n logger.error(verdict.message);\n } else {\n logger.warn(verdict.message);\n }\n }\n if (fatal) {\n process.exit(1);\n }\n};\n\nconst warnCloudflareNegotiationSkipped = (): void =>\n logger.warn(\n \"Could not wire Accept: text/markdown negotiation into dist/server/wrangler.json — raw Markdown stays available at the .md URLs.\"\n );\n\n/**\n * Wire `Accept: text/markdown` negotiation into a Cloudflare server build. The\n * ASSETS binding serves the prerendered content pages before the Worker runs —\n * and even a request that reaches the Worker is answered by the adapter's\n * handler from that binding, ahead of the only place middleware runs — so the\n * negotiation lives in a generated wrapper Worker, routed to by\n * `assets.run_worker_first` (see `deploy/cloudflare-negotiation.ts`). Both\n * pieces are spliced into the adapter's emitted `dist/server` bundle.\n */\nconst emitCloudflareNegotiation = async (\n project: BlumeProject,\n routePaths: string[]\n): Promise<void> => {\n const { config, context } = project;\n const serverDir = join(\n context.distDir ?? join(context.root, \"dist\"),\n \"server\"\n );\n const wranglerPath = join(serverDir, \"wrangler.json\");\n if (!existsSync(wranglerPath)) {\n warnCloudflareNegotiationSkipped();\n return;\n }\n // The homepage mirror is served from the static layer, so its\n // `x-markdown-tokens` estimate rides the wrapper Worker, mirroring the\n // Vercel routing config.\n const rawMarkdown = await buildRawMarkdown(project);\n const home = rawMarkdown[\"/\"];\n const injected = injectWorkerNegotiation(\n await readFile(wranglerPath, \"utf-8\"),\n {\n base: config.deployment.base,\n // The manifest routes guard the wrapper's redirect table; `routePaths`\n // also carries the synthesized homepage mirror, which must not block a\n // configured root redirect.\n contentRoutePaths: project.manifest.routes.map((route) => route.path),\n homeLinkHeader: buildHomeLinkHeader(config, routePaths),\n homeTokens: home ? markdownTokenCount(agentMarkdown(home)) : undefined,\n // Exactly the per-page JSON documents the API emits (see `pageParams`):\n // the non-hidden routes with agent Markdown, when the API is on.\n pageJsonPaths: config.ai.api\n ? project.manifest.routes\n .filter(\n (route) => !route.hidden && rawMarkdown[route.path] !== undefined\n )\n .map((route) => pageJsonPath(route.path))\n : [],\n // The wrapper Worker matches full served URLs, so the redirects are\n // based the same way the platform files are — it answers any the\n // worker-first rules claim, where `_redirects` is never consulted and\n // Astro would default their status.\n redirects: platformRedirects(config),\n routePaths,\n }\n );\n if (injected === null) {\n warnCloudflareNegotiationSkipped();\n return;\n }\n await writeFile(\n join(serverDir, NEGOTIATION_WORKER_FILE),\n injected.worker,\n \"utf-8\"\n );\n await writeFile(wranglerPath, injected.wrangler, \"utf-8\");\n logger.success(\n \"Wired Accept: text/markdown negotiation into the Cloudflare Worker\"\n );\n};\n\n/**\n * Report how many OG cards the build read back from the on-disk cache against\n * how many it rendered (the endpoint tallies both), so a warm rebuild shows\n * where the time went. With `prune`, also drop the cached cards this build\n * never asked for — renamed pages, edited descriptions, cards from an earlier\n * Blume version — so a persisted cache holds exactly the current site's cards.\n */\nconst reportCardCache = async (\n project: BlumeProject,\n prune: boolean\n): Promise<void> => {\n const cards = cardCacheTally();\n if (!cards) {\n return;\n }\n logger.info(\n `OG cards: ${cards.hits} reused from the cache, ${cards.misses} rendered`\n );\n if (prune) {\n await pruneCardCache(ogCacheDir(project.context));\n }\n};\n\nconst formatBytes = (bytes: number): string => {\n if (bytes < 1024) {\n return `${bytes} B`;\n }\n const digits = bytes < 1024 * 100 ? 1 : 0;\n return `${(bytes / 1024).toFixed(digits)} kB`;\n};\n\n/** Sizes of `dist/_astro/*.<ext>`, largest first (empty when none exist). */\nconst astroAssets = async (\n distDir: string,\n ext: string\n): Promise<{ name: string; size: number }[]> => {\n const astroDir = join(distDir, \"_astro\");\n if (!existsSync(astroDir)) {\n return [];\n }\n const entries = await readdir(astroDir);\n const files = entries.filter((name) => name.endsWith(`.${ext}`));\n const sized = await Promise.all(\n files.map(async (name) => {\n const info = await stat(join(astroDir, name));\n return { name, size: info.size };\n })\n );\n return sized.toSorted((a, b) => b.size - a.size);\n};\n\nconst totalSize = (assets: { size: number }[]): number =>\n assets.reduce((sum, asset) => sum + asset.size, 0);\n\n/**\n * Print the client JavaScript Astro shipped, largest first, plus the total. A\n * dependency-free bundle report — the interactive weight of a docs site is its\n * `_astro/*.js`, so this surfaces regressions without a visualizer.\n */\nconst reportBundleSizes = async (distDir: string): Promise<void> => {\n const sized = await astroAssets(distDir, \"js\");\n if (sized.length === 0) {\n logger.info(\"No client JavaScript emitted — the site ships zero JS.\");\n return;\n }\n const rows = sized\n .slice(0, 15)\n .map((file) => ` ${formatBytes(file.size).padStart(8)} ${file.name}`);\n logger.box(\n [\n `Client JavaScript — ${sized.length} file(s), ${formatBytes(totalSize(sized))} total`,\n \"\",\n ...rows,\n sized.length > 15 ? ` … and ${sized.length - 15} more` : null,\n ]\n .filter((line) => line !== null)\n .join(\"\\n\")\n );\n};\n\n/**\n * Enforce a performance budget on the built client assets: fail the build when\n * total `_astro/*.js` (or `*.css`) exceeds the given kB cap. Budgets that would\n * otherwise be \"documented, not measured\" become a real CI gate. Returns whether\n * every budget passed.\n */\nconst enforceBudget = async (\n distDir: string,\n args: BudgetArgs\n): Promise<\"fail\" | \"pass\" | \"skip\"> => {\n const checks: { ext: string; limitKb: number; name: string }[] = [\n ...(args[BUDGET_JS]\n ? [{ ext: \"js\", limitKb: Number(args[BUDGET_JS]), name: \"JavaScript\" }]\n : []),\n ...(args[BUDGET_CSS]\n ? [{ ext: \"css\", limitKb: Number(args[BUDGET_CSS]), name: \"CSS\" }]\n : []),\n ];\n if (checks.length === 0) {\n return \"skip\";\n }\n let passed = true;\n for (const check of checks) {\n // oxlint-disable-next-line no-await-in-loop -- a couple of sequential reads\n const total = totalSize(await astroAssets(distDir, check.ext));\n const limit = check.limitKb * 1024;\n if (total > limit) {\n passed = false;\n logger.error(\n `${check.name} budget exceeded: ${formatBytes(total)} > ${check.limitKb} kB`\n );\n } else {\n logger.success(\n `${check.name} budget: ${formatBytes(total)} / ${check.limitKb} kB`\n );\n }\n }\n return passed ? \"pass\" : \"fail\";\n};\n\n/**\n * Run the optional bundle report (`--analyze`) and performance-budget gate\n * against the directory whose `_astro/` client assets the deploy serves.\n * Shared by real and isolated builds — an isolated CI run passing\n * `--budget-js` must still fail on an exceeded budget rather than silently\n * skipping the check. Exits non-zero when a budget is exceeded.\n */\nexport const runClientAssetChecks = async (\n staticDir: string,\n args: { analyze?: boolean } & BudgetArgs\n): Promise<void> => {\n if (args.analyze) {\n await reportBundleSizes(staticDir);\n }\n if ((await enforceBudget(staticDir, args)) === \"fail\") {\n process.exit(1);\n }\n};\n\n/**\n * Root of an isolated build's output. The runtime-local `dist/`, except for a\n * Vercel server build, whose deploy bundle lands at `<runtime>/.vercel/output`\n * and is never surfaced to the project root.\n */\nexport const isolatedOutputDir = (\n config: ResolvedConfig,\n context: ProjectContext\n): string => {\n const { adapter, output } = config.deployment;\n if (output === \"server\" && adapter === \"vercel\") {\n return join(context.outDir, \".vercel\", \"output\");\n }\n return context.distDir ?? join(context.outDir, \"dist\");\n};\n\n/**\n * Directory holding an isolated build's client `_astro/` assets. Mirrors\n * `deployStaticDir`, except that an isolated build never surfaces the adapter\n * bundle to the project root — a Vercel server build's static output stays at\n * `<runtime>/.vercel/output/static`, where `deployStaticDir` would instead\n * point at the project-root copy (a previous real build's assets, or nothing).\n * Node and Cloudflare server builds serve one level down, at `client/` — see\n * {@link servesClientSubdir}.\n */\nexport const isolatedStaticDir = (\n config: ResolvedConfig,\n context: ProjectContext\n): string => {\n const { adapter, output } = config.deployment;\n const outputDir = isolatedOutputDir(config, context);\n if (output === \"server\" && adapter === \"vercel\") {\n return join(outputDir, \"static\");\n }\n if (servesClientSubdir(config.deployment)) {\n return join(outputDir, \"client\");\n }\n return outputDir;\n};\n\n/**\n * Print the build summary box and run the optional bundle report / budget\n * gate against the served static dir. The deploy artifacts themselves\n * (search index, llms.txt, sitemap, robots, redirect and header files, …)\n * were written by the integration's `astro:build:done` hook during\n * `build()` — see `deploy/artifacts.ts`. Exits non-zero if a budget is\n * exceeded.\n */\nconst reportBuild = async (\n project: BlumeProject,\n distDir: string,\n args: { analyze?: boolean } & BudgetArgs\n): Promise<void> => {\n const { config } = project;\n const features = serverFeatures(config);\n // The sitemap needs both the flag and a `site` (absolute URLs) — only the\n // latter deserves the remediation hint.\n const sitemapNote = config.seo.sitemap\n ? \"no (set deployment.site)\"\n : \"no (seo.sitemap is false)\";\n logger.box(\n [\n `Output ${config.deployment.output}`,\n `Adapter ${config.deployment.adapter ?? \"none\"}`,\n `Site ${config.deployment.site ?? \"not set\"}`,\n `Search ${config.search.provider}`,\n `Redirects ${config.redirects.length}`,\n `Sitemap ${config.deployment.site && config.seo.sitemap ? \"yes\" : sitemapNote}`,\n `Robots ${config.seo.robots ? \"yes\" : \"no\"}`,\n `Agent JSON ${config.seo.agentReadability ? \"yes\" : \"no\"}`,\n `LLM files ${config.ai.llmsTxt.enabled ? \"yes\" : \"no\"}`,\n `Server features ${features.length > 0 ? features.join(\", \") : \"none\"}`,\n ].join(\"\\n\")\n );\n\n await runClientAssetChecks(distDir, args);\n\n // Only reachable with --no-strict (strict aborts earlier): repeat the missing\n // count next to the success banner so it can't scroll away unseen.\n if (project.droppedPages > 0) {\n logger.warn(\n `${project.droppedPages} page(s) failed frontmatter validation and are missing from this build.`\n );\n }\n logger.success(`Built to ${distDir}`);\n};\n\nexport const buildCommand = defineCommand({\n args: {\n adapter: {\n description: \"Server adapter: vercel | node | netlify | cloudflare.\",\n type: \"string\",\n },\n analyze: {\n description: \"Report client JavaScript bundle sizes after the build.\",\n type: \"boolean\",\n },\n base: {\n description: \"Base path the site is served under (e.g. /docs).\",\n type: \"string\",\n },\n [BUDGET_CSS]: {\n description: \"Fail if total client CSS exceeds this many kB.\",\n type: \"string\",\n },\n [BUDGET_JS]: {\n description: \"Fail if total client JavaScript exceeds this many kB.\",\n type: \"string\",\n },\n isolated: {\n description:\n \"Build into an isolated .blume-verify runtime (and its own dist) so a running dev server and the real dist/ are untouched. For verifying changes while `blume dev` runs.\",\n type: \"boolean\",\n },\n output: {\n description: \"Output mode: static | server.\",\n type: \"string\",\n },\n preview: {\n description: \"Include drafts and unpublished CMS content.\",\n type: \"boolean\",\n },\n strict: {\n default: true,\n description:\n \"Fail on error diagnostics (default; pass --no-strict to build anyway, dropping pages that fail validation).\",\n type: \"boolean\",\n },\n },\n meta: commandMeta.build,\n async run({ args }) {\n const root = process.cwd();\n\n // `--isolated` (or BLUME_RUNTIME_DIR) relocates the whole runtime to a\n // sibling dir so this build never touches a live dev server's `.blume/` or\n // the user's real `dist/`. A non-default runtime dir has no dev lock, so the\n // refusal below lets it proceed; a plain build still refuses.\n const runtimeDir = args.isolated\n ? \".blume-verify\"\n : process.env.BLUME_RUNTIME_DIR;\n refuseIfDevRunning(root, \"building\", { isolatedHint: true, runtimeDir });\n if (args.isolated) {\n await ensureGitignore(root, [\".blume-verify/\"]);\n }\n\n if (args.output && args.output !== \"static\" && args.output !== \"server\") {\n logger.error(`Invalid --output \"${args.output}\" (use static | server).`);\n process.exit(1);\n }\n if (args.adapter && !isAdapter(args.adapter)) {\n logger.error(\n `Invalid --adapter \"${args.adapter}\" (use ${ADAPTERS.join(\" | \")}).`\n );\n process.exit(1);\n }\n validateBudgetFlags(args);\n\n const project = await prepareProject({\n mode: \"build\",\n overrides: {\n // SAFETY: an invalid --adapter exited above; a set flag is an ADAPTERS\n // member.\n adapter: args.adapter as (typeof ADAPTERS)[number] | undefined,\n base: args.base,\n // SAFETY: an invalid --output exited above; a set flag is static or\n // server.\n output: args.output as \"server\" | \"static\" | undefined,\n },\n preview: args.preview,\n root,\n runtimeDir,\n strict: args.strict,\n });\n\n logger.start(\n `Building ${project.graph.pages.length} page(s) (${project.config.deployment.output} output)`\n );\n\n // Hand the scanned project to the integration: its `astro:build:done`\n // hook writes the deploy artifacts (search index, llms.txt, sitemap, …)\n // into Astro's client output during the build. An isolated build is a\n // throwaway verify that only needs to confirm the site compiles and\n // renders, so it publishes nothing — no network post-steps (a hosted\n // search sync would push), no deploy artifacts.\n if (!runtimeDir) {\n publishBuildProject(project);\n }\n\n await build({\n logLevel: \"info\",\n root: project.context.outDir,\n });\n\n // A real build also prunes the cache; an isolated verify must not evict\n // cards a live dev server is still serving.\n await reportCardCache(project, !runtimeDir);\n\n // The bundle report and budget gate still run for an isolated build —\n // `blume build --isolated --budget-js 100` exiting 0 without measuring\n // anything would be a silent false pass in CI.\n if (runtimeDir) {\n if (\n project.config.deployment.output === \"server\" &&\n project.config.deployment.adapter === \"vercel\"\n ) {\n await checkVercelFunctionBundles(\n isolatedOutputDir(project.config, project.context),\n root\n );\n }\n await runClientAssetChecks(\n isolatedStaticDir(project.config, project.context),\n args\n );\n logger.success(\n `Isolated build OK — output at ${isolatedOutputDir(project.config, project.context)} (not published).`\n );\n return;\n }\n\n // A server adapter's deploy bundle is a build artifact — keep it out of\n // version control (Vercel's own CLI ignores `.vercel/` for the same reason).\n // Ignoring it is independent of whether the bundle had to be moved below:\n // Vercel writes straight to the project root, Netlify does not.\n const { adapter } = project.config.deployment;\n const ignoreDir = adapter ? ADAPTER_IGNORE_DIRS[adapter] : undefined;\n if (project.config.deployment.output === \"server\" && ignoreDir) {\n await ensureGitignore(root, [ignoreDir]);\n }\n\n // Netlify writes its deploy bundle relative to the Astro root — which Blume\n // points at the hidden `.blume` runtime — so the bundle lands where the\n // deploy platform never looks. Surface it up to the project root before\n // publishing artifacts into the served static dir.\n const surfaced = await surfaceAdapterOutput(\n project.config,\n project.context\n );\n if (surfaced.moved) {\n logger.success(`Surfaced ${adapter} output to ${surfaced.to}`);\n }\n\n if (project.config.deployment.output === \"server\" && adapter === \"vercel\") {\n await checkVercelFunctionBundles(join(root, \".vercel\", \"output\"), root);\n await emitVercelNegotiation(project, markdownRoutePaths(project), root);\n }\n\n if (\n project.config.deployment.output === \"server\" &&\n adapter === \"cloudflare\"\n ) {\n await emitCloudflareNegotiation(project, markdownRoutePaths(project));\n }\n\n await reportBuild(\n project,\n deployStaticDir(project.config, project.context),\n args\n );\n },\n});\n",
|
|
6
6
|
"/**\n * `Accept: text/markdown` content negotiation for Cloudflare server builds.\n *\n * Blume prerenders every content page — even under `deployment.output:\n * \"server\"` — and on Cloudflare the ASSETS binding serves those files before\n * the Worker script runs, so no server-side code (Astro middleware included)\n * ever sees a content-page request. Worse, even a content-page request that\n * does reach the Worker is answered by `@astrojs/cloudflare`'s handler\n * straight from the ASSETS binding, ahead of `app.render` — the only place\n * middleware runs — because `app.match` resolves a prerendered route to\n * nothing and the handler then falls back to the binding.\n *\n * Negotiation therefore needs two coordinated pieces, both applied to the\n * adapter's emitted deploy bundle after `astro build`:\n *\n * 1. `assets.run_worker_first` in `dist/server/wrangler.json`, scoped to the\n * content routes so the platform routes their requests to the Worker\n * instead of serving the static HTML directly (other assets keep their\n * zero-Worker fast path).\n * 2. A generated entry Worker that fronts the adapter's: when the client\n * prefers `text/markdown` it serves the page's prerendered `.md` mirror\n * from the ASSETS binding, and it delegates everything else to the Astro\n * Worker untouched.\n *\n * The prerendered per-page JSON documents (`/api/docs/pages/{route}.json`)\n * are the one prerendered surface the adapter's fallback does *not* cover.\n * They come from a prerendered *dynamic* route, and for those Astro's\n * `matchRequest` returns the first non-prerendered route matching the same\n * path — on a server build that is the `/api/[...path]` catch-all, which\n * answers with a 404 problem document; `fallbackToAssets` never runs. The\n * static-pathname endpoints (`pages.json`, `navigation.json`) are unaffected:\n * they sit in the manifest's asset set, which the handler serves from the\n * binding first. So whenever a worker-first rule claims a page JSON URL, the\n * wrapper answers it from the binding itself, keyed by the exact set of\n * documents the build emitted. The generated rule sets that would claim every\n * `.json` file — a subpath base and the coarse fallback — exempt `*.json`\n * outright, keeping those files on the zero-Worker path; the wrapper branch\n * covers the remaining claims (a content section under `/api`, or\n * user-configured rules).\n *\n * Cloudflare does not apply `_headers` to worker-first routes, so the wrapper\n * also re-stamps what the static layer would otherwise add on the routes it\n * takes over: the homepage agent-discovery `Link` header and the Markdown\n * `charset=utf-8` (see `deploy/headers.ts`). The raw `.md`/`.mdx` URLs are\n * exempted from worker-first routing with negative rules, keeping their\n * `_headers` treatment and their zero-Worker serving path.\n *\n * Configured redirects are baked into the wrapper as well, and answered there\n * with their exact configured status. On a server build Blume routes\n * `redirects` through Astro's own config, and `@astrojs/cloudflare` turns\n * those into `_redirects` entries carrying the exact status — but only\n * Cloudflare's static layer reads that file, and a worker-first route never\n * reaches it. Astro's SSR redirect handler would answer instead, and it honors\n * the configured status only when the destination resolves to a discrete\n * route: Blume serves every page from `[...slug]`, so it never does, and\n * `computeRedirectStatus` defaults a GET to **301** — a permanent redirect\n * that browsers cache indefinitely. The wrapper checking its own redirect\n * table before delegating closes that hole at zero rule cost: unlike negative\n * `run_worker_first` exemptions, a baked-in table spends nothing against\n * Wrangler's 100-rule / 100-character limits, cannot collide with\n * user-configured rules (or a bare `true`), and needs no basing gymnastics —\n * its keys are full served URLs, which is exactly what the Worker sees.\n * Redirects outside every worker-first rule still never invoke the Worker;\n * the static layer serves them from `_redirects` as before.\n */\n\nimport { normalizePath } from \"../core/base-path.ts\";\n\n/** Filename of the generated wrapper Worker, next to the adapter's entry. */\nexport const NEGOTIATION_WORKER_FILE = \"blume-worker.mjs\";\n\n/**\n * Wrangler's limits on `assets.run_worker_first`: at most 100 rules of at\n * most 100 characters each. A rule set over either limit fails\n * `wrangler deploy` outright, so the builder falls back to a coarse set.\n */\nconst MAX_RULES = 100;\nconst MAX_RULE_LENGTH = 100;\n\n/**\n * Coarse fallback when the grouped rules would exceed Wrangler's limits:\n * route everything through the Worker except the fingerprinted build assets\n * and the raw AI-ready endpoints, whose `charset=utf-8` comes from `_headers`\n * (not applied on worker-first routes) and whose responses never negotiate.\n * The prerendered `.json` documents are exempted for the same reason, and\n * because the Astro Worker would hand the per-page ones to the `/api/`\n * catch-all (see the module comment); a miss on an exempted path still\n * invokes the Worker, so unknown `.json` URLs keep their problem document.\n */\nconst FALLBACK_RULES = [\n \"/*\",\n \"!/_astro/*\",\n \"!/*.md\",\n \"!/*.mdx\",\n \"!/*.txt\",\n \"!/*.json\",\n];\n\n/**\n * The deployment base as a rule/URL prefix: trailing slash stripped, empty\n * for a root deploy — the same normalization the dev middleware applies in\n * `astro/markdown-negotiation.ts`.\n */\nconst basePrefix = (base?: string): string =>\n base && base !== \"/\" ? base.replace(/\\/$/u, \"\") : \"\";\n\n/** A value as `JSON.parse` produces it (the wrangler config's value space). */\ntype JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [key: string]: JsonValue };\n\n/** Narrow a parsed JSON value to a plain (non-array) object. */\nconst isJsonObject = (\n value: JsonValue | undefined\n): value is { [key: string]: JsonValue } =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\n/** Narrow a parsed JSON value to a string. */\nconst isJsonString = (value: JsonValue | undefined): value is string =>\n typeof value === \"string\";\n\nconst isNegativeRule = (rule: string): boolean => rule.startsWith(\"!\");\n\nconst ruleBody = (rule: string): string =>\n isNegativeRule(rule) ? rule.slice(1) : rule;\n\n/**\n * The `run_worker_first` rules for the given content routes: the routes that\n * must reach the Worker for negotiation, grouped by first path segment so the\n * set stays far under Wrangler's 100-rule cap on real sites. Nested groups\n * get a `/{segment}/*` glob plus negative rules exempting their raw\n * `.md`/`.mdx` mirrors; a bare route gets its exact path in both request\n * spellings (with and without the trailing slash) so no unrelated URL pays\n * the Worker hop. On a subpath deploy the whole base is routed as one group —\n * every route lives under it anyway — with the raw endpoints and the\n * prerendered `.json` documents exempted like the coarse fallback does.\n *\n * Configured redirects need no exemption from these rules: the wrapper Worker\n * answers any it claims from its baked-in redirect table with the configured\n * status (see the module comment).\n */\nexport const buildRunWorkerFirstRules = (\n routePaths: readonly string[],\n base?: string\n): string[] => {\n const prefix = encodeURI(basePrefix(base));\n if (prefix) {\n return [\n prefix,\n `${prefix}/*`,\n `!${prefix}/*.md`,\n `!${prefix}/*.mdx`,\n `!${prefix}/*.txt`,\n `!${prefix}/*.json`,\n `!${prefix}/_astro/*`,\n ];\n }\n const groups = new Map<string, { bare: boolean; nested: boolean }>();\n let home = false;\n for (const route of routePaths) {\n if (route === \"/\") {\n home = true;\n continue;\n }\n const segments = route.split(\"/\").filter(Boolean);\n const head = segments[0] ?? \"\";\n const group = groups.get(head) ?? { bare: false, nested: false };\n if (segments.length === 1) {\n group.bare = true;\n } else {\n group.nested = true;\n }\n groups.set(head, group);\n }\n const rules: string[] = home ? [\"/\"] : [];\n const negatives: string[] = [];\n for (const [head, group] of groups) {\n const segment = `/${encodeURI(head)}`;\n if (group.bare) {\n rules.push(segment);\n }\n if (group.nested) {\n rules.push(`${segment}/*`);\n negatives.push(`!${segment}/*.md`, `!${segment}/*.mdx`);\n } else {\n rules.push(`${segment}/`);\n }\n }\n return [...rules, ...negatives];\n};\n\n/**\n * Whether `other` is a same-polarity glob that already covers `rule`.\n * Wrangler's deploy-time validator *rejects* a rule set containing a rule\n * another glob makes redundant, so covered rules must be dropped, not kept.\n */\nconst coveredBy = (rule: string, other: string): boolean =>\n other !== rule &&\n isNegativeRule(other) === isNegativeRule(rule) &&\n ruleBody(other).endsWith(\"*\") &&\n ruleBody(rule).startsWith(ruleBody(other).slice(0, -1));\n\n/**\n * Merge the generated rules into a user-configured `run_worker_first` (which\n * flows into the adapter's emitted config from the project's own wrangler\n * file). `true` already routes everything through the Worker, so it is kept\n * as-is; an array is unioned with the generated rules and then swept for\n * redundancy, since coverage by a glob is equivalent routing but a hard\n * validation error at deploy time.\n */\nexport const mergeRunWorkerFirstRules = (\n existing: JsonValue | undefined,\n added: readonly string[]\n): string[] | true => {\n if (existing === true) {\n return true;\n }\n const user = Array.isArray(existing)\n ? existing.filter((rule): rule is string => typeof rule === \"string\")\n : [];\n const merged = [...user, ...added.filter((rule) => !user.includes(rule))];\n return merged.filter(\n (rule) => !merged.some((other) => coveredBy(rule, other))\n );\n};\n\nconst withinWranglerLimits = (rules: string[] | true): boolean =>\n rules === true ||\n (rules.length <= MAX_RULES &&\n rules.every((rule) => rule.length <= MAX_RULE_LENGTH));\n\n/** A configured redirect the wrapper Worker serves itself. */\nexport interface WorkerRedirect {\n /**\n * Served path of the redirect, based the way the host platform matches it\n * (see `applyBaseToPlatformRedirects`) — the full URL path the Worker sees.\n */\n from: string;\n /** Configured HTTP status (301, 302, 307, or 308). */\n status: number;\n /** Destination, percent-encoded into the `Location` header. */\n to: string;\n}\n\nexport interface NegotiationWorkerOptions {\n /** Import specifier of the adapter's built entry, relative to the Worker. */\n mainSpecifier: string;\n /** Content routes with a raw-Markdown mirror (see `markdownRoutePaths`). */\n routePaths: readonly string[];\n /** Name of the assets binding the wrapper serves the `.md` mirrors from. */\n assetsBinding: string;\n /** `deployment.base` for subpath deploys. */\n base?: string;\n /** Homepage agent-discovery `Link` header (see `ai/link-headers.ts`). */\n homeLinkHeader?: string | null;\n /** Estimated token count of the homepage Markdown mirror. */\n homeTokens?: number;\n /** Configured redirects the wrapper answers with their exact status. */\n redirects?: readonly WorkerRedirect[];\n /**\n * Base-less served paths of the prerendered per-page JSON documents the\n * build emitted (see `pageJsonPath`), decoded. The wrapper answers exactly\n * these from the assets binding, since the Astro Worker would route them to\n * the `/api/` catch-all (see the module comment).\n */\n pageJsonPaths?: readonly string[];\n}\n\n/**\n * The wrapper Worker module. The negotiation helpers are a JavaScript copy of\n * `astro/markdown-negotiation.ts` — the deploy bundle is uploaded with\n * `no_bundle`, so the module must be self-contained; behavioral parity with\n * the dev middleware is enforced by `test/cloudflare-negotiation.test.ts`.\n */\nexport const buildNegotiationWorker = (\n options: NegotiationWorkerOptions\n): string => {\n const routes = JSON.stringify(options.routePaths);\n const pageJson = JSON.stringify(options.pageJsonPaths ?? []);\n const binding = JSON.stringify(options.assetsBinding);\n const prefix = JSON.stringify(encodeURI(basePrefix(options.base)));\n const homeLinkHeader = JSON.stringify(options.homeLinkHeader ?? null);\n const homeTokens = JSON.stringify(\n options.homeTokens === undefined ? null : String(options.homeTokens)\n );\n // Keyed by the normalized served path; the runtime lookup decodes and\n // trims the request path the same way, so both spellings of a URL match.\n // The destination is percent-encoded here because it ships as a `Location`\n // header, which cannot carry non-ASCII.\n const redirects = JSON.stringify(\n Object.fromEntries(\n (options.redirects ?? []).map((redirect) => [\n normalizePath(redirect.from),\n [encodeURI(redirect.to), redirect.status],\n ])\n )\n );\n return `// Generated by Blume. Do not edit; this file is recreated on each build.\n//\n// Request-time \\`Accept: text/markdown\\` negotiation for a Cloudflare server\n// build. \\`assets.run_worker_first\\` routes content-page requests here instead\n// of the platform's static layer; a client that prefers Markdown gets the\n// page's prerendered \\`.md\\` mirror from the assets binding, a configured\n// redirect is answered with its exact configured status, and a prerendered\n// per-page JSON document is served from the binding (the Astro Worker would\n// route it to the \\`/api/\\` catch-all, because Astro resolves a prerendered\n// dynamic route to the first live route on the same path). Every other\n// request is delegated to the Astro Worker untouched. \\`_headers\\` does not\n// apply to worker-first routes, so the homepage Link header and the Markdown\n// charset are re-stamped here.\nimport server from ${JSON.stringify(options.mainSpecifier)};\n\nconst ROUTES = new Set(${routes});\nconst PAGE_JSON = new Set(${pageJson});\nconst BASE_PREFIX = ${prefix};\nconst ASSETS_BINDING = ${binding};\nconst HOME_LINK_HEADER = ${homeLinkHeader};\nconst HOME_TOKENS = ${homeTokens};\nconst REDIRECTS = ${redirects};\n\n// Configured redirects live in \\`_redirects\\`, which only the static layer\n// reads — a worker-first route never reaches it. Answering from this baked-in\n// copy keeps the exact configured status; delegating instead would let Astro's\n// SSR handler default a GET to a permanent 301.\nconst redirectFor = (pathname) => {\n const trimmed =\n pathname !== \"/\" && pathname.endsWith(\"/\") ? pathname.slice(0, -1) : pathname;\n const path = safeDecode(trimmed);\n return Object.hasOwn(REDIRECTS, path) ? REDIRECTS[path] : null;\n};\n\n// The request path with the deployment base removed: the whole path on a\n// root deploy, \\`\"\"\\` for the bare base, \\`null\\` for a path outside the base.\nconst stripBase = (pathname) => {\n if (!BASE_PREFIX) {\n return pathname;\n }\n if (pathname === BASE_PREFIX) {\n return \"\";\n }\n return pathname.startsWith(BASE_PREFIX + \"/\")\n ? pathname.slice(BASE_PREFIX.length)\n : null;\n};\n\n// Decoded for the lookups, which are keyed by decoded paths; a malformed\n// escape keeps the raw path, which simply won't match anything.\nconst safeDecode = (path) => {\n try {\n return decodeURIComponent(path);\n } catch {\n return path;\n }\n};\n\n// \\`_redirects\\` semantics, which the static layer applies to these same\n// paths: the request's query string is forwarded unless the destination\n// carries its own, and a destination fragment stays after the query.\nconst redirectLocation = (destination, search) => {\n const hashIndex = destination.indexOf(\"#\");\n const bare = hashIndex === -1 ? destination : destination.slice(0, hashIndex);\n if (!search || bare.includes(\"?\")) {\n return destination;\n }\n return hashIndex === -1\n ? bare + search\n : bare + search + destination.slice(hashIndex);\n};\n\nconst parseAccept = (accept) =>\n accept.split(\",\").map((part) => {\n const segments = part.trim().split(\";\");\n const type = (segments[0] ?? \"\").trim().toLowerCase();\n const qSegment = segments\n .slice(1)\n .map((segment) => segment.trim())\n .find((segment) => segment.startsWith(\"q=\"));\n const q = qSegment ? Number(qSegment.slice(2)) : 1;\n return { q: Number.isNaN(q) ? 1 : q, type };\n });\n\nconst prefersMarkdown = (accept) => {\n if (!accept) {\n return false;\n }\n let markdownQ = -1;\n let htmlQ = 0;\n for (const { q, type } of parseAccept(accept)) {\n if (type === \"text/markdown\" || type === \"text/x-markdown\") {\n markdownQ = Math.max(markdownQ, q);\n } else if (type === \"text/html\") {\n htmlQ = Math.max(htmlQ, q);\n }\n }\n return markdownQ > 0 && markdownQ >= htmlQ;\n};\n\nconst markdownVariantUrl = (rawUrl) => {\n const queryIndex = rawUrl.indexOf(\"?\");\n const query = queryIndex === -1 ? \"\" : rawUrl.slice(queryIndex);\n const rawPath = queryIndex === -1 ? rawUrl : rawUrl.slice(0, queryIndex);\n const rest = stripBase(rawPath);\n if (rest === null) {\n return null;\n }\n const path = rest || \"/\";\n const trimmed = path !== \"/\" && path.endsWith(\"/\") ? path.slice(0, -1) : path;\n const pathname = safeDecode(trimmed);\n if (!ROUTES.has(pathname)) {\n return null;\n }\n const target = pathname === \"/\" ? \"/index\" : pathname;\n return BASE_PREFIX + encodeURI(target) + \".md\" + query;\n};\n\n// Exactly the per-page JSON documents the build emitted, so a URL the site\n// never generated (a hidden page, a path outside the API) takes the normal\n// route to the Astro Worker and its problem document.\nconst isPageJson = (pathname) => {\n const rest = stripBase(pathname);\n return rest !== null && PAGE_JSON.has(safeDecode(rest));\n};\n\nconst isHomePath = (pathname) => {\n const rest = stripBase(pathname);\n return rest === \"\" || rest === \"/\";\n};\n\nconst withHeaders = (response, apply) => {\n const patched = new Response(response.body, response);\n apply(patched.headers);\n return patched;\n};\n\nexport default {\n async fetch(request, env, context) {\n const url = new URL(request.url);\n // Before the method guard: the static layer applies \\`_redirects\\` to every\n // method, so the wrapper does too.\n const redirect = redirectFor(url.pathname);\n if (redirect !== null) {\n return new Response(null, {\n headers: { location: redirectLocation(redirect[0], url.search) },\n status: redirect[1],\n });\n }\n if (request.method !== \"GET\" && request.method !== \"HEAD\") {\n return server.fetch(request, env, context);\n }\n const assets = env[ASSETS_BINDING];\n // The request goes through untouched, so a conditional revalidation\n // reaches the binding and comes back as a 304 — anything but a miss is\n // the document's own answer. A miss falls through to the Astro Worker.\n if (assets !== undefined && isPageJson(url.pathname)) {\n const asset = await assets.fetch(request);\n if (asset.status !== 404) {\n return asset;\n }\n }\n const variant = markdownVariantUrl(url.pathname + url.search);\n const home = isHomePath(url.pathname);\n if (\n variant !== null &&\n assets !== undefined &&\n prefersMarkdown(request.headers.get(\"accept\"))\n ) {\n const asset = await assets.fetch(\n new Request(new URL(variant, url), request)\n );\n if (asset.ok) {\n return withHeaders(asset, (headers) => {\n headers.set(\"content-type\", \"text/markdown; charset=utf-8\");\n headers.append(\"vary\", \"Accept\");\n if (home) {\n if (HOME_LINK_HEADER !== null) {\n headers.set(\"link\", HOME_LINK_HEADER);\n }\n if (HOME_TOKENS !== null) {\n headers.set(\"x-markdown-tokens\", HOME_TOKENS);\n }\n }\n });\n }\n }\n const response = await server.fetch(request, env, context);\n if (variant === null && !(home && HOME_LINK_HEADER !== null)) {\n return response;\n }\n return withHeaders(response, (headers) => {\n if (variant !== null) {\n headers.append(\"vary\", \"Accept\");\n }\n if (home && HOME_LINK_HEADER !== null && !headers.has(\"link\")) {\n headers.set(\"link\", HOME_LINK_HEADER);\n }\n });\n },\n};\n`;\n};\n\nexport interface WorkerNegotiation {\n /** Updated `wrangler.json` text (worker-first rules + swapped `main`). */\n wrangler: string;\n /** The wrapper Worker module, to write as {@link NEGOTIATION_WORKER_FILE}. */\n worker: string;\n}\n\nexport interface WorkerNegotiationOptions extends Omit<\n NegotiationWorkerOptions,\n \"assetsBinding\" | \"mainSpecifier\"\n> {\n /**\n * The manifest content routes, based like `routePaths` — the guard that\n * keeps the wrapper's redirect table off real pages. Defaults to\n * `routePaths`, which also carries the synthesized homepage mirror (see\n * `markdownRoutePaths`); passing the manifest routes keeps that synthetic\n * `/` from blocking a configured root redirect.\n */\n contentRoutePaths?: readonly string[];\n}\n\n/**\n * Wire the negotiation into the adapter's emitted `dist/server/wrangler.json`:\n * point `main` at the wrapper Worker and scope `assets.run_worker_first` to\n * the content routes (merged with any user-configured rules). Returns the\n * updated config text plus the wrapper module, or `null` when there is\n * nothing to do or nowhere safe to do it: no routes, unparsable config, no\n * usable `main` or assets binding (the wrapper serves the `.md` mirrors from\n * it), an already-swapped `main` (the original entry is unrecoverable), or a\n * rule set that cannot fit Wrangler's limits even after the coarse fallback.\n *\n * The configured redirects are baked into the wrapper, which answers any the\n * worker-first rules claim with the exact configured status (see the module\n * comment) — whichever rules do the claiming: the generated groups, the\n * coarse fallback's `/*`, or the user's own (including a bare `true`). A\n * redirect at a content route's own path is never baked: the page owns it,\n * and answering a redirect there would take a real page off the air. When\n * `null` is returned no rule set is written at all, so every request stays on\n * the static layer and `_redirects` serves the configured statuses as before.\n */\nexport const injectWorkerNegotiation = (\n wranglerText: string,\n options: WorkerNegotiationOptions\n): WorkerNegotiation | null => {\n if (options.routePaths.length === 0) {\n return null;\n }\n let config: JsonValue;\n try {\n config = JSON.parse(wranglerText);\n } catch {\n return null;\n }\n if (!isJsonObject(config)) {\n return null;\n }\n const { main } = config;\n if (\n !isJsonString(main) ||\n main.length === 0 ||\n main === NEGOTIATION_WORKER_FILE\n ) {\n return null;\n }\n const { assets } = config;\n if (!isJsonObject(assets) || !isJsonString(assets.binding)) {\n return null;\n }\n const {\n contentRoutePaths = options.routePaths,\n redirects = [],\n ...workerOptions\n } = options;\n // The content-route guard compares against redirect `from`s, which carry the\n // full `{deployment.base}{basePath}` stack; the routes carry only\n // `basePath`, so the deployment base is applied here.\n const deployPrefix = basePrefix(options.base);\n const guardRoutes = new Set(\n contentRoutePaths.map((route) =>\n normalizePath(\n deployPrefix && route !== \"/\"\n ? `${deployPrefix}${route}`\n : deployPrefix || route\n )\n )\n );\n const workerRedirects = redirects.filter(\n (redirect) =>\n redirect.from.startsWith(\"/\") &&\n !guardRoutes.has(normalizePath(redirect.from))\n );\n let rules = mergeRunWorkerFirstRules(\n assets.run_worker_first,\n buildRunWorkerFirstRules(options.routePaths, options.base)\n );\n if (!withinWranglerLimits(rules)) {\n rules = mergeRunWorkerFirstRules(assets.run_worker_first, FALLBACK_RULES);\n }\n if (!withinWranglerLimits(rules)) {\n return null;\n }\n if (rules !== true) {\n assets.run_worker_first = rules;\n }\n config.main = NEGOTIATION_WORKER_FILE;\n const mainSpecifier =\n main.startsWith(\".\") || main.startsWith(\"/\") ? main : `./${main}`;\n const worker = buildNegotiationWorker({\n ...workerOptions,\n assetsBinding: assets.binding,\n mainSpecifier,\n redirects: workerRedirects,\n });\n // The adapter and Wrangler both write this file unformatted; match them.\n return { worker, wrangler: JSON.stringify(config) };\n};\n",
|
|
7
7
|
"import { existsSync, readFileSync } from \"node:fs\";\nimport { readdir, readFile } from \"node:fs/promises\";\nimport { builtinModules } from \"node:module\";\n\nimport { init, parse } from \"es-module-lexer\";\nimport { dirname, join, relative } from \"pathe\";\nimport { z } from \"zod\";\n\nimport { packageRoot } from \"../core/package-root.ts\";\n\n/**\n * Post-build audit of a Vercel serverless function bundle.\n *\n * The Vercel adapter traces the server entry with `@vercel/nft` and copies\n * every file it reaches into `.vercel/output/functions/_render.func`. A bare\n * import the trace cannot resolve — a package that isn't reachable by walking\n * `node_modules` up from the chunk that imports it — is dropped *silently*,\n * and the deployed function dies on its first request with\n * `ERR_MODULE_NOT_FOUND` (Vercel reports it as `FUNCTION_INVOCATION_FAILED`).\n * Under an isolated linker (pnpm, Bun's `isolated` mode) that is exactly the\n * shape of Blume's own runtime dependencies: the SSR build leaves them\n * external, and they live under `blume`'s store directory, not the project\n * root. Nothing before deploy surfaces it — the build is green, a warm-cache\n * preview is green — so the bundle is re-checked here with Node's own\n * resolution rule: a package is present when some `node_modules/<name>` on\n * the walk from the importing chunk up to the function root exists.\n */\n\n/** A bare package import the function bundle cannot satisfy. */\nexport interface MissingPackage {\n /** Function-relative paths of the chunks that import the package. */\n importers: string[];\n name: string;\n}\n\n/** One function directory's audit result. */\nexport interface FunctionBundleAudit {\n /** Absolute path of the `*.func` directory. */\n dir: string;\n missing: MissingPackage[];\n}\n\nconst BUILTINS = new Set(builtinModules);\n\n/** Specifier prefixes that never name an installed package. */\nconst NON_PACKAGE_PREFIXES = [\"node:\", \"astro:\", \"virtual:\", \"data:\", \"\\0\"];\n\n/**\n * The package a bare specifier resolves through (`@scope/name` or `name`), or\n * null for relative/absolute paths, Node builtins, and virtual ids.\n */\nexport const packageName = (specifier: string): string | null => {\n if (\n specifier.startsWith(\".\") ||\n specifier.startsWith(\"/\") ||\n NON_PACKAGE_PREFIXES.some((prefix) => specifier.startsWith(prefix)) ||\n BUILTINS.has(specifier)\n ) {\n return null;\n }\n const segments = specifier.split(\"/\");\n if (specifier.startsWith(\"@\")) {\n return segments.length >= 2 ? `${segments[0]}/${segments[1]}` : null;\n }\n return segments[0] || null;\n};\n\n/**\n * Fallback static specifiers for a module the lexer rejects: a side-effect\n * `import \"x\"` or an `import`/`export … from \"x\"` clause. Only `import` takes\n * the bare-string form — `export \"x\"` is not syntax, so a runtime message\n * quoting `export 'ALL'` must not match.\n */\nconst STATIC_IMPORT =\n /(?:^|[;\\s}])(?:import\\s*[\"'](?<bare>[^\"'\\n]+)[\"']|(?:import|export)\\s*[\\w$*{},\\s]*?\\s*from\\s*[\"'](?<from>[^\"'\\n]+)[\"'])/gu;\n\n/** Fallback dynamic `import(\"…\")` specifiers. */\nconst DYNAMIC_IMPORT = /\\bimport\\(\\s*[\"'](?<dynamic>[^\"'\\n]+)[\"']\\s*\\)/gu;\n\n/**\n * Textual best effort for a module `es-module-lexer` cannot parse: every\n * quoted specifier in import position, string contents included.\n */\nconst scannedSpecifiers = (source: string): string[] => {\n const specifiers: string[] = [];\n for (const pattern of [STATIC_IMPORT, DYNAMIC_IMPORT]) {\n for (const match of source.matchAll(pattern)) {\n const groups = match.groups ?? {};\n specifiers.push(groups.bare ?? groups.from ?? groups.dynamic ?? \"\");\n }\n }\n return specifiers;\n};\n\n/**\n * Every specifier a module's syntax imports, read with `es-module-lexer` so\n * text inside string literals never counts. That matters for Blume's data\n * chunks: the MCP snapshot is `JSON.parse(\"…\")` over every page's Markdown,\n * and a code sample there reading `import { config } from 'dotenv'` is prose\n * to a bundle audit, not a module the function needs. `import.meta` carries no\n * specifier and a template-literal `import(\\`pkg/${x}\\`)` is a glob the\n * bundler already resolved, so neither names a package.\n */\nconst lexedSpecifiers = (source: string, name: string): string[] => {\n const [imports] = parse(source, name);\n const specifiers: string[] = [];\n for (const entry of imports) {\n if (entry.type === \"dynamic\" && entry.glob) {\n continue;\n }\n if (entry.specifier) {\n specifiers.push(entry.specifier);\n }\n }\n return specifiers;\n};\n\n/**\n * Every bare package name a module's source imports. A module the lexer\n * rejects (an unterminated string, an invalid escape in a specifier) falls\n * back to the textual scan rather than going unaudited.\n */\nexport const importedPackages = async (\n source: string,\n name = \"module\"\n): Promise<string[]> => {\n await init();\n let specifiers: string[];\n try {\n specifiers = lexedSpecifiers(source, name);\n } catch {\n specifiers = scannedSpecifiers(source);\n }\n const names = new Set<string>();\n for (const specifier of specifiers) {\n const packageId = packageName(specifier);\n if (packageId) {\n names.add(packageId);\n }\n }\n return [...names];\n};\n\n/** Whether `node_modules/<name>` exists on the walk from `from` up to `root`. */\nconst resolvable = (name: string, from: string, root: string): boolean => {\n let dir = from;\n for (;;) {\n if (existsSync(join(dir, \"node_modules\", name, \"package.json\"))) {\n return true;\n }\n if (dir === root) {\n return false;\n }\n const parent = dirname(dir);\n if (parent === dir) {\n return false;\n }\n dir = parent;\n }\n};\n\nconst MODULE_FILE = /\\.(?:m?js|cjs)$/u;\n\n/** The one `.vc-config.json` field the audit reads; the rest passes through. */\nconst vcConfigSchema = z.looseObject({ handler: z.string().optional() });\n\n/** Every JavaScript module under `dir`, skipping any `node_modules`. */\nconst listModules = async (dir: string): Promise<string[]> => {\n const files: string[] = [];\n const entries = await readdir(dir, { withFileTypes: true });\n for (const entry of entries) {\n const path = join(dir, entry.name);\n if (entry.isDirectory()) {\n if (entry.name !== \"node_modules\") {\n // oxlint-disable-next-line no-await-in-loop -- sequential walk keeps ordering deterministic\n files.push(...(await listModules(path)));\n }\n } else if (entry.isFile() && MODULE_FILE.test(entry.name)) {\n files.push(path);\n }\n }\n return files;\n};\n\n/**\n * Audit one function directory: read its `.vc-config.json` handler, scan\n * every module beside the handler (the adapter's `dist/server` tree) for bare\n * imports, and report the packages no `node_modules` on the walk up to the\n * function root provides. A function without a handler has nothing to check.\n */\nexport const auditFunctionBundle = async (\n funcDir: string\n): Promise<MissingPackage[]> => {\n const configPath = join(funcDir, \".vc-config.json\");\n if (!existsSync(configPath)) {\n return [];\n }\n const config = vcConfigSchema.safeParse(\n JSON.parse(await readFile(configPath, \"utf-8\"))\n );\n if (!config.success || !config.data.handler) {\n return [];\n }\n const serverDir = dirname(join(funcDir, config.data.handler));\n if (!existsSync(serverDir)) {\n return [];\n }\n const missing = new Map<string, string[]>();\n for (const file of await listModules(serverDir)) {\n // oxlint-disable-next-line no-await-in-loop -- sequential read keeps the importer lists ordered\n const source = await readFile(file, \"utf-8\");\n // oxlint-disable-next-line no-await-in-loop -- the lexer runs per file, in the same order\n for (const name of await importedPackages(source, file)) {\n if (resolvable(name, dirname(file), funcDir)) {\n continue;\n }\n const importers = missing.get(name) ?? [];\n importers.push(relative(funcDir, file));\n missing.set(name, importers);\n }\n }\n return [...missing]\n .map(([name, importers]) => ({ importers, name }))\n .toSorted((a, b) => a.name.localeCompare(b.name));\n};\n\n/**\n * Audit every function in a Vercel Build Output tree (`.vercel/output`).\n * Functions with nothing missing are omitted; an output tree without a\n * `functions/` directory (a static build) yields nothing.\n */\nexport const auditVercelFunctions = async (\n outputDir: string\n): Promise<FunctionBundleAudit[]> => {\n const functionsDir = join(outputDir, \"functions\");\n if (!existsSync(functionsDir)) {\n return [];\n }\n const audits: FunctionBundleAudit[] = [];\n const entries = await readdir(functionsDir, { withFileTypes: true });\n for (const entry of entries.toSorted((a, b) => (a.name < b.name ? -1 : 1))) {\n if (!(entry.isDirectory() && entry.name.endsWith(\".func\"))) {\n continue;\n }\n const dir = join(functionsDir, entry.name);\n // oxlint-disable-next-line no-await-in-loop -- sequential audit keeps the report ordered\n const missing = await auditFunctionBundle(dir);\n if (missing.length > 0) {\n audits.push({ dir, missing });\n }\n }\n return audits;\n};\n\n/** Blume's own runtime dependency names, from its published `package.json`. */\nexport const blumeDependencyNames = (): Set<string> => {\n const manifest: { dependencies?: Record<string, string> } = JSON.parse(\n readFileSync(join(packageRoot(), \"package.json\"), \"utf-8\")\n );\n return new Set(Object.keys(manifest.dependencies ?? {}));\n};\n\n/** What a build should do about an audit: nothing, warn, or fail. */\nexport interface FunctionBundleVerdict {\n /**\n * A missing package is one of Blume's own dependencies — the runtime Blume\n * generated imports it, so the function is certain to crash. Anything else\n * (a project's own external import) is reported but left to the author.\n */\n fatal: boolean;\n message: string;\n}\n\n/**\n * Describe a function's missing packages and how to fix them. Vercel's trace\n * only reaches packages resolvable from the project root, so the remedy is a\n * root-level dependency entry for each — the same mirror rule Blume's native\n * dependencies (`sharp`, `takumi-js`) already follow.\n */\nexport const functionBundleVerdict = (\n audit: FunctionBundleAudit,\n root: string,\n ownDependencies: ReadonlySet<string>\n): FunctionBundleVerdict => {\n const names = audit.missing.map((entry) => entry.name);\n const lines = audit.missing.map(\n (entry) => ` - ${entry.name} (imported by ${entry.importers.join(\", \")})`\n );\n const fatal = names.some((name) => ownDependencies.has(name));\n const message = [\n `The Vercel function bundle at ${relative(root, audit.dir) || audit.dir} is missing packages its server code imports, so the deployed function would fail on every request with ERR_MODULE_NOT_FOUND:`,\n ...lines,\n \"Vercel's dependency trace only includes packages resolvable from the project root; under an isolated linker (pnpm, Bun's isolated mode) Blume's own dependencies are not. Add them to the project's package.json so the trace can find them:\",\n ` npm install -D ${names.join(\" \")}`,\n ].join(\"\\n\");\n return { fatal, message };\n};\n",
|
|
8
8
|
"/**\n * `Accept: text/markdown` content negotiation for Vercel server builds.\n *\n * Blume prerenders every content page — even under `deployment.output:\n * \"server\"` — so a page request never reaches Astro middleware: Vercel serves\n * the prerendered HTML straight from its static layer. Request-time negotiation\n * therefore has to live in the platform's routing config. The Vercel adapter\n * emits a Build Output API `config.json`; these helpers splice extra routes\n * into it so a content-page request that prefers `text/markdown` is rewritten\n * (not redirected) to the page's prerendered `.md` mirror — the deployed\n * counterpart of the dev-server rewrite in `astro/markdown-negotiation.ts`.\n * The same routing config also answers a *missing* page: a request that\n * prefers Markdown (or asks for a `.md` URL no page backs) gets the\n * prerendered Markdown 404 body with the 404 status, instead of the HTML\n * shell, and one that prefers JSON (or asks for a `.json` URL) gets the\n * prerendered problem-details 404.\n */\n\n/**\n * Regex for the `accept` header condition. Written to hold under both matching\n * semantics a router may apply — full-string and substring — by anchoring the\n * end and letting `(.*,)?` absorb any earlier list entries: it requires a\n * `text/markdown` or `text/x-markdown` entry terminated by `;`, `,`, or the end\n * of the header. Kept lookaround-free so it stays valid in RE2, and lowercase\n * only — real agents send lowercase media types, and q-values are not compared\n * (a client sending `text/markdown` at `q=0` is pathological). Browsers never\n * send `text/markdown`, so ordinary page requests are unaffected.\n */\nexport const ACCEPT_MARKDOWN_HEADER_VALUE =\n \"(.*,)?\\\\s*text/(x-)?markdown(\\\\s*[;,].*)?$\";\n\n/**\n * The JSON counterpart, for the problem-details 404: `application/json` or\n * `application/problem+json`. Browsers never send either on a navigation\n * (the catch-all wildcard does not match), so ordinary page requests are\n * unaffected.\n */\nexport const ACCEPT_JSON_HEADER_VALUE =\n \"(.*,)?\\\\s*application/(problem\\\\+)?json(\\\\s*[;,].*)?$\";\n\n/**\n * A Build Output API route — the subset these helpers read and write. Parsed\n * routes keep whatever other fields they carry at runtime; only these are\n * typed.\n */\nexport interface VercelRoute {\n continue?: boolean;\n dest?: string;\n handle?: string;\n has?: { key?: string; type: string; value?: string }[];\n headers?: Record<string, string>;\n src?: string;\n status?: number;\n}\n\n/** Whether a parsed route field is a real string (the config is raw JSON). */\nconst isString = (value: string | undefined): value is string =>\n typeof value === \"string\";\n\nconst ACCEPT_MARKDOWN_CONDITION: VercelRoute[\"has\"] = [\n { key: \"accept\", type: \"header\", value: ACCEPT_MARKDOWN_HEADER_VALUE },\n];\n\nconst ACCEPT_JSON_CONDITION: VercelRoute[\"has\"] = [\n { key: \"accept\", type: \"header\", value: ACCEPT_JSON_HEADER_VALUE },\n];\n\nconst VARY_ACCEPT = { vary: \"Accept\" };\n\n/** Where the prerendered Markdown 404 (`pages/404.md.ts`) lands. */\nconst NOT_FOUND_MARKDOWN_DEST = \"/404.md\";\n\n/** Where the prerendered JSON 404 (`pages/404.json.ts`) lands. */\nconst NOT_FOUND_JSON_DEST = \"/404.json\";\n\n/** The adapter's own not-found fallback — the anchor the Markdown 404 precedes. */\nconst NOT_FOUND_HTML_DEST = \"/404.html\";\n\n/**\n * Miss-phase routes that answer a missing page with the Markdown 404 body: any\n * path when the client prefers Markdown, and any `.md`/`.mdx` URL (a request\n * for a raw-Markdown mirror that has no page wants Markdown back, not the HTML\n * shell). Both keep the 404 status. Spliced immediately before the adapter's\n * `/404.html` fallback, so they run after every server route (the MCP\n * endpoint, server islands, images) has had its turn and never hijack a\n * request one of those would have answered.\n */\nconst NOT_FOUND_MARKDOWN_ROUTES: readonly VercelRoute[] = [\n {\n dest: NOT_FOUND_MARKDOWN_DEST,\n has: ACCEPT_MARKDOWN_CONDITION,\n headers: VARY_ACCEPT,\n src: \"^/.*$\",\n status: 404,\n },\n { dest: NOT_FOUND_MARKDOWN_DEST, src: \"^/.*\\\\.mdx?$\", status: 404 },\n];\n\n/**\n * The JSON 404's miss-phase routes, the problem-details twin of the Markdown\n * ones: any path when the client prefers JSON, and any `.json` URL no file\n * backs. Spliced at the same anchor, after every server route — so the\n * `/api/` catch-all (which answers its own namespace with a problem document)\n * has already had its turn.\n */\nconst NOT_FOUND_JSON_ROUTES: readonly VercelRoute[] = [\n {\n dest: NOT_FOUND_JSON_DEST,\n has: ACCEPT_JSON_CONDITION,\n headers: VARY_ACCEPT,\n src: \"^/.*$\",\n status: 404,\n },\n { dest: NOT_FOUND_JSON_DEST, src: \"^/.*\\\\.json$\", status: 404 },\n];\n\n/** Which prerendered 404 twins the build emitted, so their routes get wired. */\nexport interface NotFoundVariants {\n json?: boolean;\n markdown?: boolean;\n}\n\n/**\n * Vercel rejects route `src` patterns longer than 4096 characters, so route\n * alternations are split across as many route entries as needed. The budget\n * leaves headroom for the `^(` … `)/?$` wrapper.\n */\nconst MAX_ALTERNATION_LENGTH = 3900;\n\nconst REGEX_SPECIALS = /[$()*+.?[\\]^{|}\\\\]/gu;\n\n/**\n * A route path as it appears on the wire (percent-encoded, matching the layout\n * of the prerendered files), escaped for literal use inside the alternation.\n * Escaping runs after encoding; the `%` an encode introduces is not a regex\n * metacharacter.\n */\nconst routePattern = (route: string): string =>\n encodeURI(route).replace(REGEX_SPECIALS, \"\\\\$&\");\n\n/** Group patterns so each group's alternation stays under the `src` limit. */\nconst chunkPatterns = (patterns: readonly string[]): string[][] => {\n const chunks: string[][] = [];\n let current: string[] = [];\n let length = 0;\n for (const pattern of patterns) {\n if (\n current.length > 0 &&\n length + pattern.length + 1 > MAX_ALTERNATION_LENGTH\n ) {\n chunks.push(current);\n current = [];\n length = 0;\n }\n current.push(pattern);\n length += pattern.length + 1;\n }\n if (current.length > 0) {\n chunks.push(current);\n }\n return chunks;\n};\n\nexport interface NegotiationRoutes {\n /**\n * `Vary: Accept` for the plain-HTML side of every negotiated URL, so shared\n * caches keep the two variants apart. Spliced *before* `handle:\n * \"filesystem\"` with `continue`: main-phase headers accumulate and ride on\n * whatever ultimately serves the request. Routes placed after the filesystem\n * marker are the miss phase — they run only when no static file matches, and\n * every Blume content page is a prerendered static file, so a header route\n * there never fires.\n */\n headerRoutes: VercelRoute[];\n /**\n * The negotiation itself: header-conditional rewrites to the `.md` mirror.\n * Spliced *before* `handle: \"filesystem\"` so they run ahead of static-file\n * matching; the rewritten path then resolves to the prerendered `.md` file.\n */\n rewriteRoutes: VercelRoute[];\n}\n\n/**\n * Build the routes for the given content-route paths (the routes that have a\n * raw-Markdown mirror, straight from the manifest). Paths are matched with an\n * optional trailing slash and rewritten `/{route}` → `/{route}.md`; the home\n * page's mirror lives at `/index.md`. When `homeTokens` is given, the home\n * rewrite also stamps `x-markdown-tokens` — the estimated token count of the\n * homepage mirror (Cloudflare's Markdown for Agents convention). Only the home\n * route can carry it: the other rewrites are chunked alternations spanning\n * many pages, and a count is per-page.\n */\nexport const buildNegotiationRoutes = (\n routePaths: readonly string[],\n homeTokens?: number\n): NegotiationRoutes => {\n const home = routePaths.includes(\"/\");\n const rest = routePaths\n .filter((path) => path !== \"/\")\n .map((path) => routePattern(path));\n const chunks = chunkPatterns(rest);\n\n const rewriteRoutes: VercelRoute[] = home\n ? [\n {\n dest: \"/index.md\",\n has: ACCEPT_MARKDOWN_CONDITION,\n headers:\n homeTokens === undefined\n ? VARY_ACCEPT\n : { ...VARY_ACCEPT, \"x-markdown-tokens\": String(homeTokens) },\n src: \"^/$\",\n },\n ]\n : [];\n for (const chunk of chunks) {\n rewriteRoutes.push({\n dest: \"$1.md\",\n has: ACCEPT_MARKDOWN_CONDITION,\n headers: VARY_ACCEPT,\n src: `^(${chunk.join(\"|\")})/?$`,\n });\n }\n\n const headerChunks = chunkPatterns(home ? [\"/\", ...rest] : rest);\n const headerRoutes: VercelRoute[] = headerChunks.map((chunk) => ({\n continue: true,\n headers: VARY_ACCEPT,\n src: `^(?:${chunk.join(\"|\")})/?$`,\n }));\n\n return { headerRoutes, rewriteRoutes };\n};\n\n/** The `src` of the injected homepage `Link` header route. */\nconst HOME_SRC = \"^/$\";\n\n/**\n * Whether a route is one this module previously injected, so re-injection\n * replaces rather than duplicates. Rewrites are identified by their `accept`\n * condition; the `Vary` routes by their exact three-field shape (a\n * user-authored route of that identical shape would be semantically equal to\n * the one re-added); the homepage `Link` route by its three-field\n * continue-with-link shape (the Build Output config is adapter-generated, so\n * no user-authored route competes in this file); the Markdown 404 routes by\n * their `/404.md` destination.\n */\nconst isNegotiationRoute = (route: VercelRoute): boolean =>\n route.has?.some(\n (condition) => condition.value === ACCEPT_MARKDOWN_HEADER_VALUE\n ) === true ||\n (route.dest === NOT_FOUND_MARKDOWN_DEST && route.status === 404) ||\n (route.dest === NOT_FOUND_JSON_DEST && route.status === 404) ||\n (route.continue === true &&\n route.headers?.vary === \"Accept\" &&\n isString(route.src) &&\n Object.keys(route).length === 3) ||\n (route.continue === true &&\n isString(route.headers?.link) &&\n route.src === HOME_SRC &&\n Object.keys(route).length === 3);\n\n/**\n * Splice the negotiation routes into a Build Output `config.json`, plus — when\n * given — a homepage `Link` header route for agent discovery (see\n * `ai/link-headers.ts`), applied the same way the `Vary` routes are: in the\n * main phase before `handle: \"filesystem\"` with `continue`, so the header\n * rides on the prerendered homepage response. `contentTypeOverrides` maps static-dir\n * relative paths to media types via the Build Output `overrides` field — the\n * platform's mechanism for extensionless static files (e.g. the Web Bot Auth\n * signature directory). The trailing-slash redirect that collapses `/docs/`\n * onto `/docs` is not spliced here: the generated config sets Astro's\n * `trailingSlash: \"never\"`, which the adapter turns into the platform's own\n * 308 route ahead of everything below (so a slashed Markdown request takes\n * that hop first, then negotiates). For each 404 twin the build emitted (`notFound.markdown` for\n * `404.md`, `notFound.json` for `404.json`), its routes go into the miss\n * phase right before the adapter's `/404.html` fallback — and nowhere when\n * that fallback is absent, since a `dest` with no file behind it would serve\n * nothing. Returns the updated JSON\n * text (tab-indented, like the adapter's own output), or `null` when there is\n * nowhere safe to splice: an unparsable config, no `routes` array, or no\n * `handle: \"filesystem\"` marker to anchor the splice.\n */\nexport const injectNegotiationRoutes = (\n configText: string,\n routePaths: readonly string[],\n homeLinkHeader?: string | null,\n contentTypeOverrides?: Record<string, string>,\n homeTokens?: number,\n notFound: NotFoundVariants = {}\n): string | null => {\n const overrideEntries = Object.entries(contentTypeOverrides ?? {});\n let config: {\n overrides?: Record<string, { contentType?: string; path?: string }>;\n routes?: VercelRoute[];\n };\n try {\n config = JSON.parse(configText);\n } catch {\n return null;\n }\n if (!Array.isArray(config.routes)) {\n return null;\n }\n for (const [path, contentType] of overrideEntries) {\n // Keyed assignment, so re-injection replaces rather than duplicates and a\n // user's own override of the same path is simply refreshed.\n config.overrides = { ...config.overrides, [path]: { contentType } };\n }\n const routes = config.routes.filter((route) => !isNegotiationRoute(route));\n const filesystemIndex = routes.findIndex(\n (route) => route.handle === \"filesystem\"\n );\n if (filesystemIndex === -1) {\n return null;\n }\n const { headerRoutes, rewriteRoutes } = buildNegotiationRoutes(\n routePaths,\n homeTokens\n );\n if (homeLinkHeader) {\n headerRoutes.push({\n continue: true,\n headers: { link: homeLinkHeader },\n src: HOME_SRC,\n });\n }\n // Headers first: `continue` routes accumulate, so a request the rewrite\n // route then terminates (Markdown negotiation on the homepage) still carries\n // the Link header.\n routes.splice(filesystemIndex, 0, ...headerRoutes, ...rewriteRoutes);\n const notFoundRoutes = [\n ...(notFound.markdown ? NOT_FOUND_MARKDOWN_ROUTES : []),\n ...(notFound.json ? NOT_FOUND_JSON_ROUTES : []),\n ];\n if (notFoundRoutes.length > 0) {\n const fallbackIndex = routes.findIndex(\n (route) => route.status === 404 && route.dest === NOT_FOUND_HTML_DEST\n );\n if (fallbackIndex !== -1) {\n routes.splice(fallbackIndex, 0, ...notFoundRoutes);\n }\n }\n config.routes = routes;\n return `${JSON.stringify(config, null, \"\\t\")}\\n`;\n};\n"
|
|
9
9
|
],
|
|
10
|
-
"mappings": "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",
|
|
11
|
-
"debugId": "
|
|
10
|
+
"mappings": "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",
|
|
11
|
+
"debugId": "3FC854B7668321DC64756E2164756E21",
|
|
12
12
|
"names": []
|
|
13
13
|
}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
hashText,
|
|
8
8
|
nextFenceState,
|
|
9
9
|
targetOffsetIn
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-s102bysw.js";
|
|
11
11
|
import {
|
|
12
12
|
normalizeBasePath
|
|
13
13
|
} from "./chunk-27gtm2ym.js";
|
|
@@ -182,4 +182,4 @@ var collectContentAssets = async (project) => {
|
|
|
182
182
|
export { readExpandedEntryText, isRelativeImageTarget, resolveRelativeImage, rewriteRelativeImages, collectContentAssets };
|
|
183
183
|
|
|
184
184
|
//# debugId=2D2EF7E4F8223F9E64756E2164756E21
|
|
185
|
-
//# sourceMappingURL=chunk-
|
|
185
|
+
//# sourceMappingURL=chunk-v5mm027v.js.map
|
|
@@ -247,22 +247,22 @@ var FALLBACKS = {
|
|
|
247
247
|
serif: ["ui-serif", "Georgia", "serif"]
|
|
248
248
|
};
|
|
249
249
|
var GOOGLE_FONTS = {
|
|
250
|
-
"dm-sans": { category: "sans", family: "DM Sans", weights: [400
|
|
250
|
+
"dm-sans": { category: "sans", family: "DM Sans", weights: ["400..700"] },
|
|
251
251
|
figtree: {
|
|
252
252
|
category: "sans",
|
|
253
253
|
family: "Figtree",
|
|
254
|
-
weights: [400
|
|
254
|
+
weights: ["400..700"]
|
|
255
255
|
},
|
|
256
256
|
"fira-code": {
|
|
257
257
|
category: "mono",
|
|
258
258
|
family: "Fira Code",
|
|
259
|
-
weights: [400
|
|
259
|
+
weights: ["400..700"]
|
|
260
260
|
},
|
|
261
|
-
geist: { category: "sans", family: "Geist", weights: [400
|
|
261
|
+
geist: { category: "sans", family: "Geist", weights: ["400..700"] },
|
|
262
262
|
"geist-mono": {
|
|
263
263
|
category: "mono",
|
|
264
264
|
family: "Geist Mono",
|
|
265
|
-
weights: [400
|
|
265
|
+
weights: ["400..600"]
|
|
266
266
|
},
|
|
267
267
|
"ibm-plex-mono": {
|
|
268
268
|
category: "mono",
|
|
@@ -272,81 +272,81 @@ var GOOGLE_FONTS = {
|
|
|
272
272
|
"ibm-plex-sans": {
|
|
273
273
|
category: "sans",
|
|
274
274
|
family: "IBM Plex Sans",
|
|
275
|
-
weights: [400
|
|
275
|
+
weights: ["400..700"]
|
|
276
276
|
},
|
|
277
277
|
"ibm-plex-serif": {
|
|
278
278
|
category: "serif",
|
|
279
279
|
family: "IBM Plex Serif",
|
|
280
280
|
weights: [400, 500, 600]
|
|
281
281
|
},
|
|
282
|
-
inter: { category: "sans", family: "Inter", weights: [400
|
|
282
|
+
inter: { category: "sans", family: "Inter", weights: ["400..700"] },
|
|
283
283
|
"inter-tight": {
|
|
284
284
|
category: "sans",
|
|
285
285
|
family: "Inter Tight",
|
|
286
|
-
weights: [400
|
|
286
|
+
weights: ["400..700"]
|
|
287
287
|
},
|
|
288
288
|
"jetbrains-mono": {
|
|
289
289
|
category: "mono",
|
|
290
290
|
family: "JetBrains Mono",
|
|
291
|
-
weights: [400
|
|
291
|
+
weights: ["400..700"]
|
|
292
292
|
},
|
|
293
|
-
lora: { category: "serif", family: "Lora", weights: [400
|
|
293
|
+
lora: { category: "serif", family: "Lora", weights: ["400..700"] },
|
|
294
294
|
manrope: {
|
|
295
295
|
category: "sans",
|
|
296
296
|
family: "Manrope",
|
|
297
|
-
weights: [400
|
|
297
|
+
weights: ["400..700"]
|
|
298
298
|
},
|
|
299
299
|
merriweather: {
|
|
300
300
|
category: "serif",
|
|
301
301
|
family: "Merriweather",
|
|
302
|
-
weights: [400
|
|
302
|
+
weights: ["400..700"]
|
|
303
303
|
},
|
|
304
304
|
"open-sans": {
|
|
305
305
|
category: "sans",
|
|
306
306
|
family: "Open Sans",
|
|
307
|
-
weights: [400
|
|
307
|
+
weights: ["400..700"]
|
|
308
308
|
},
|
|
309
309
|
"playfair-display": {
|
|
310
310
|
category: "serif",
|
|
311
311
|
family: "Playfair Display",
|
|
312
|
-
weights: [400
|
|
312
|
+
weights: ["400..700"]
|
|
313
313
|
},
|
|
314
314
|
"plus-jakarta-sans": {
|
|
315
315
|
category: "sans",
|
|
316
316
|
family: "Plus Jakarta Sans",
|
|
317
|
-
weights: [400
|
|
317
|
+
weights: ["400..700"]
|
|
318
318
|
},
|
|
319
|
-
roboto: { category: "sans", family: "Roboto", weights: [400
|
|
319
|
+
roboto: { category: "sans", family: "Roboto", weights: ["400..700"] },
|
|
320
320
|
"roboto-mono": {
|
|
321
321
|
category: "mono",
|
|
322
322
|
family: "Roboto Mono",
|
|
323
|
-
weights: [400
|
|
323
|
+
weights: ["400..700"]
|
|
324
324
|
},
|
|
325
325
|
"source-code-pro": {
|
|
326
326
|
category: "mono",
|
|
327
327
|
family: "Source Code Pro",
|
|
328
|
-
weights: [400
|
|
328
|
+
weights: ["400..600"]
|
|
329
329
|
},
|
|
330
330
|
"source-sans-3": {
|
|
331
331
|
category: "sans",
|
|
332
332
|
family: "Source Sans 3",
|
|
333
|
-
weights: [400
|
|
333
|
+
weights: ["400..700"]
|
|
334
334
|
},
|
|
335
335
|
"source-serif-4": {
|
|
336
336
|
category: "serif",
|
|
337
337
|
family: "Source Serif 4",
|
|
338
|
-
weights: [400
|
|
338
|
+
weights: ["400..700"]
|
|
339
339
|
},
|
|
340
340
|
"space-grotesk": {
|
|
341
341
|
category: "sans",
|
|
342
342
|
family: "Space Grotesk",
|
|
343
|
-
weights: [400
|
|
343
|
+
weights: ["400..700"]
|
|
344
344
|
},
|
|
345
345
|
"space-mono": { category: "mono", family: "Space Mono", weights: [400, 700] },
|
|
346
346
|
"work-sans": {
|
|
347
347
|
category: "sans",
|
|
348
348
|
family: "Work Sans",
|
|
349
|
-
weights: [400
|
|
349
|
+
weights: ["400..600"]
|
|
350
350
|
}
|
|
351
351
|
};
|
|
352
352
|
var FONT_SLUGS = Object.keys(GOOGLE_FONTS);
|
|
@@ -5310,5 +5310,5 @@ ${moreIssues}`
|
|
|
5310
5310
|
|
|
5311
5311
|
export { SITE_INFERRING_ADAPTERS, applyDeploymentEnv, slugify, resolveReferences, referenceRoutes, blumeReferences, hasScalarReferences, builtinProxyKinds, needsPlaygroundProxy, GOOGLE_FONTS, isFontSlug, fontLocaleCodes, buildFontEntries, buildFontsCss, configuredFonts, createModuleLoader, resolveRuntimeDir, resolveProjectContext, PUBLIC_API_URL, repoUrl, editBaseUrl, apiUrl, UI_PACKS, EN_UI, resolveUIStrings, pageMetaSchema, folderMetaSchema, VERSION_ID, loadConfig };
|
|
5312
5312
|
|
|
5313
|
-
//# debugId=
|
|
5314
|
-
//# sourceMappingURL=chunk-
|
|
5313
|
+
//# debugId=EFC817EB4CCD759864756E2164756E21
|
|
5314
|
+
//# sourceMappingURL=chunk-xv91q4nm.js.map
|