@bettercms-ai/preview-runtime 0.1.0 → 0.2.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/README.md +12 -0
- package/dist/cli.js +46 -11
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,6 +36,18 @@ bcms-preview validate
|
|
|
36
36
|
{ "components": [{ "id": "cmp_1", "source": { "path": "src/components/Hero.astro" } }] }
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
+
## Sections extracted from pages
|
|
40
|
+
|
|
41
|
+
A component does not have to be a standalone file with its fields as props. A section
|
|
42
|
+
`npx @bettercms-ai/convert --componentize` extracted from a page (a file starting
|
|
43
|
+
`// @bettercms-ai/convert section v…`) is recognised by that marker and rendered with its section contract:
|
|
44
|
+
`<Section blockId="bcms-preview" overrides={props} page={{}} />`, so the live props arrive as the instance's
|
|
45
|
+
own copy. Record those sources with the MCP tool `submit_componentize_receipt`, or `set_component_source`
|
|
46
|
+
with `kind: "section"` for a section written by hand to the same contract.
|
|
47
|
+
|
|
48
|
+
A failed validation reports what broke — the app server's own error lines first — and the dashboard shows
|
|
49
|
+
it under "Runtime + console".
|
|
50
|
+
|
|
39
51
|
## How a preview renders
|
|
40
52
|
|
|
41
53
|
- **Astro**: built with `output: "server"` and `@astrojs/node`, so `.astro` components render on the
|
package/dist/cli.js
CHANGED
|
@@ -10,6 +10,7 @@ var here = dirname(fileURLToPath(import.meta.url));
|
|
|
10
10
|
var PREVIEW_BASE = "/__bettercms/component-preview";
|
|
11
11
|
var COMPONENT_EXTENSIONS = /* @__PURE__ */ new Set([".astro", ".tsx", ".jsx", ".ts", ".js", ".mjs"]);
|
|
12
12
|
var IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
13
|
+
var SECTION_MARKER_PREFIX = "// @bettercms-ai/convert section v";
|
|
13
14
|
var CliFailure = class extends Error {
|
|
14
15
|
};
|
|
15
16
|
function fail(message) {
|
|
@@ -54,7 +55,9 @@ function validateManifest(root, manifest) {
|
|
|
54
55
|
if (named !== void 0 && named !== "default" && !IDENTIFIER.test(named)) {
|
|
55
56
|
fail(`component ${entry.id}: export "${named}" is not a valid identifier`);
|
|
56
57
|
}
|
|
57
|
-
|
|
58
|
+
const head = readFileSync(join(root, path), "utf8").slice(0, 512);
|
|
59
|
+
const kind = entry.source.kind === "section" || head.includes(SECTION_MARKER_PREFIX) ? "section" : "file";
|
|
60
|
+
return { id: entry.id, source: { path, export: named ?? "default", kind } };
|
|
58
61
|
});
|
|
59
62
|
}
|
|
60
63
|
function detectFramework(root) {
|
|
@@ -76,6 +79,7 @@ function bin(root, name) {
|
|
|
76
79
|
function registrySource(fromDir, root, entries) {
|
|
77
80
|
const imports = [];
|
|
78
81
|
const keys = [];
|
|
82
|
+
const kinds = [];
|
|
79
83
|
entries.forEach((entry, index) => {
|
|
80
84
|
let specifier = relative(fromDir, join(root, entry.source.path)).split(sep).join("/");
|
|
81
85
|
if (!specifier.startsWith(".")) specifier = `./${specifier}`;
|
|
@@ -83,6 +87,7 @@ function registrySource(fromDir, root, entries) {
|
|
|
83
87
|
const local = `Component${index}`;
|
|
84
88
|
imports.push(entry.source.export === "default" ? `import ${local} from ${JSON.stringify(specifier)};` : `import { ${entry.source.export} as ${local} } from ${JSON.stringify(specifier)};`);
|
|
85
89
|
keys.push(` ${JSON.stringify(entry.id)}: ${local},`);
|
|
90
|
+
kinds.push(` ${JSON.stringify(entry.id)}: ${JSON.stringify(entry.source.kind ?? "file")},`);
|
|
86
91
|
});
|
|
87
92
|
return `${imports.join("\n")}
|
|
88
93
|
|
|
@@ -90,6 +95,10 @@ export const registry: Record<string, any> = {
|
|
|
90
95
|
${keys.join("\n")}
|
|
91
96
|
};
|
|
92
97
|
|
|
98
|
+
export const kinds: Record<string, "file" | "section"> = {
|
|
99
|
+
${kinds.join("\n")}
|
|
100
|
+
};
|
|
101
|
+
|
|
93
102
|
export const has = (componentId: string): boolean => Object.prototype.hasOwnProperty.call(registry, componentId);
|
|
94
103
|
`;
|
|
95
104
|
}
|
|
@@ -160,17 +169,18 @@ ${handler("GET", "() => handleHealth()")}`);
|
|
|
160
169
|
writeFileSync(join(gen, "render.astro"), `---
|
|
161
170
|
${styles}
|
|
162
171
|
import { renderEntry, renderHeaders } from "./server.mjs";
|
|
163
|
-
import { registry } from "./registry";
|
|
172
|
+
import { registry, kinds } from "./registry";
|
|
164
173
|
export const prerender = false;
|
|
165
174
|
const headers = renderHeaders();
|
|
166
175
|
const entry = renderEntry(Astro.url.searchParams.get("id"));
|
|
167
176
|
const Component = entry ? registry[entry.componentId] : undefined;
|
|
177
|
+
const section = entry ? kinds[entry.componentId] === "section" : false;
|
|
168
178
|
for (const [name, value] of Object.entries(headers)) Astro.response.headers.set(name, value);
|
|
169
179
|
if (!entry || !Component) return new Response("Not found", { status: 404, headers });
|
|
170
180
|
---
|
|
171
181
|
<html lang="en" data-bcms-preview-render="1">
|
|
172
182
|
<head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /></head>
|
|
173
|
-
<body
|
|
183
|
+
<body>{section ? <Component blockId="bcms-preview" overrides={entry.props} page={{}} /> : <Component {...entry.props} />}</body>
|
|
174
184
|
</html>
|
|
175
185
|
`);
|
|
176
186
|
writeFileSync(wrapper, `import user from "./${configName}";
|
|
@@ -260,7 +270,7 @@ export function GET() {
|
|
|
260
270
|
mkdirSync(join(gen, "render"), { recursive: true });
|
|
261
271
|
writeFileSync(join(gen, "render", "page.tsx"), `import { notFound } from "next/navigation";
|
|
262
272
|
import { renderEntry } from "../server.mjs";
|
|
263
|
-
import { registry } from "../registry";
|
|
273
|
+
import { registry, kinds } from "../registry";
|
|
264
274
|
|
|
265
275
|
export const dynamic = "force-dynamic";
|
|
266
276
|
|
|
@@ -272,7 +282,9 @@ export default async function BetterCMSComponentPreview({ searchParams }: { sear
|
|
|
272
282
|
// The marker the runtime page checks before acknowledging: a 404 or an error page never carries it.
|
|
273
283
|
return (
|
|
274
284
|
<>
|
|
275
|
-
|
|
285
|
+
{kinds[entry.componentId] === "section"
|
|
286
|
+
? <Component blockId="bcms-preview" overrides={entry.props} page={{}} />
|
|
287
|
+
: <Component {...entry.props} />}
|
|
276
288
|
<template data-bcms-preview-render="1" />
|
|
277
289
|
</>
|
|
278
290
|
);
|
|
@@ -333,7 +345,12 @@ function buildPreviewRuntime(input) {
|
|
|
333
345
|
} finally {
|
|
334
346
|
restore();
|
|
335
347
|
}
|
|
336
|
-
return {
|
|
348
|
+
return {
|
|
349
|
+
framework,
|
|
350
|
+
out,
|
|
351
|
+
components: entries.map((e) => e.id),
|
|
352
|
+
kinds: Object.fromEntries(entries.map((e) => [e.id, e.source.kind ?? "file"]))
|
|
353
|
+
};
|
|
337
354
|
}
|
|
338
355
|
|
|
339
356
|
// src/validate.ts
|
|
@@ -399,7 +416,7 @@ function ensureBrowser() {
|
|
|
399
416
|
throw new ValidationFailure("COMPONENT_VALIDATION_BROWSER_UNAVAILABLE", "A headless browser could not be installed on this runner.");
|
|
400
417
|
}
|
|
401
418
|
}
|
|
402
|
-
async function renderInBrowser(url, viewports, tokenNames) {
|
|
419
|
+
async function renderInBrowser(url, viewports, tokenNames, options) {
|
|
403
420
|
ensureBrowser();
|
|
404
421
|
const { chromium } = await import("playwright");
|
|
405
422
|
const browser = await chromium.launch();
|
|
@@ -428,6 +445,9 @@ async function renderInBrowser(url, viewports, tokenNames) {
|
|
|
428
445
|
if (!response?.ok() || rendered === 0) {
|
|
429
446
|
runtimeErrors += 1;
|
|
430
447
|
problems.push(`${viewport.name}: the component page did not render (HTTP ${response?.status() ?? "none"})`);
|
|
448
|
+
} else if (options.section && await page.locator("[data-bcms-block]").count() === 0) {
|
|
449
|
+
runtimeErrors += 1;
|
|
450
|
+
problems.push(`${viewport.name}: the section rendered without its [data-bcms-block] root`);
|
|
431
451
|
}
|
|
432
452
|
const missing = await page.evaluate((names) => {
|
|
433
453
|
const referenced = /* @__PURE__ */ new Set();
|
|
@@ -529,8 +549,9 @@ async function validateComponent() {
|
|
|
529
549
|
const manifestPath = join2(work, "manifest.json");
|
|
530
550
|
writeFileSync2(manifestPath, JSON.stringify({ components: manifest.components.map(({ id: id2, source }) => ({ id: id2, source })) }));
|
|
531
551
|
const out = join2(work, "runtime");
|
|
552
|
+
let built;
|
|
532
553
|
try {
|
|
533
|
-
buildPreviewRuntime({ root: process.cwd(), manifestPath, out });
|
|
554
|
+
built = buildPreviewRuntime({ root: process.cwd(), manifestPath, out });
|
|
534
555
|
} catch (error) {
|
|
535
556
|
throw new ValidationFailure("COMPONENT_PREVIEW_BUILD_FAILED", `The preview build failed: ${error.message}`);
|
|
536
557
|
}
|
|
@@ -552,8 +573,18 @@ async function validateComponent() {
|
|
|
552
573
|
BCMS_PREVIEW_ORIGIN: local,
|
|
553
574
|
BCMS_PREVIEW_VALIDATOR_KEY: validatorKey
|
|
554
575
|
},
|
|
555
|
-
stdio: ["ignore", "
|
|
576
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
556
577
|
});
|
|
578
|
+
const serverErrors = [];
|
|
579
|
+
const collect = (stream) => (chunk) => {
|
|
580
|
+
stream.write(chunk);
|
|
581
|
+
for (const line of chunk.toString("utf8").split("\n")) {
|
|
582
|
+
const clean = line.replace(/\x1b\[[0-9;]*m/g, "").trim();
|
|
583
|
+
if (serverErrors.length < 5 && /\b(error|exception)\b/i.test(clean)) serverErrors.push(clean.slice(0, 200));
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
runtime.stdout?.on("data", collect(process.stdout));
|
|
587
|
+
runtime.stderr?.on("data", collect(process.stderr));
|
|
557
588
|
if (!await waitForOk(`${local}${PREVIEW_ROUTE_BASE}/health`, 6e4)) {
|
|
558
589
|
throw new ValidationFailure("COMPONENT_PREVIEW_RUNTIME_DID_NOT_START", "The preview runtime did not start within 60 seconds.");
|
|
559
590
|
}
|
|
@@ -569,7 +600,8 @@ async function validateComponent() {
|
|
|
569
600
|
const render = await renderInBrowser(
|
|
570
601
|
`${local}${PREVIEW_ROUTE_BASE}/render?id=${encodeURIComponent(id)}`,
|
|
571
602
|
nativeViewports,
|
|
572
|
-
manifest.brandTokenNames
|
|
603
|
+
manifest.brandTokenNames,
|
|
604
|
+
{ section: built.kinds[componentId] === "section" }
|
|
573
605
|
);
|
|
574
606
|
const tarball = join2(work, "bundle.tgz");
|
|
575
607
|
if (spawnSync2("tar", ["-czf", tarball, "-C", out, "."], { stdio: "inherit" }).status !== 0) {
|
|
@@ -588,7 +620,10 @@ async function validateComponent() {
|
|
|
588
620
|
runtime: {
|
|
589
621
|
status: render.runtimeErrors === 0 && render.consoleErrors === 0 ? "passed" : "failed",
|
|
590
622
|
runtimeErrors: render.runtimeErrors,
|
|
591
|
-
consoleErrors: render.consoleErrors
|
|
623
|
+
consoleErrors: render.consoleErrors,
|
|
624
|
+
// Only on a failure, and bounded: the server's own error lines first (the real cause), then what the
|
|
625
|
+
// browser saw. The database stores them and the panel shows the first one.
|
|
626
|
+
...render.runtimeErrors + render.consoleErrors > 0 ? { problems: [...serverErrors.map((line) => `server: ${line}`), ...render.problems].slice(0, 10).map((line) => line.slice(0, 200)) } : {}
|
|
592
627
|
},
|
|
593
628
|
visual: { status: "baseline-missing", reviewRequired: true, viewports: render.results }
|
|
594
629
|
};
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/build.ts","../src/validate.ts","../src/cli.ts"],"sourcesContent":["/**\n * Builds a component preview runtime from an unmodified Next.js or Astro app. Used by `bcms-preview build`\n * and by the validator.\n *\n * The manifest names which file implements which component:\n * { \"components\": [{ \"id\": \"cmp_1\", \"source\": { \"path\": \"src/components/Hero.astro\" } }] }\n *\n * 🔴 NOTHING IN THE CUSTOMER'S REPOSITORY IS CHANGED. Routes and a registry are generated into the\n * checkout, the framework builds, the result is packaged as a runtime release, and every generated file\n * is removed again — including when the build fails. In CI the checkout is thrown away anyway; on a\n * developer machine this is the difference between a tool and a mess.\n */\nimport { spawnSync } from \"node:child_process\";\nimport { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { dirname, extname, join, relative, resolve, sep } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\ntype ManifestEntry = { id: string; source: { path: string; export?: string } };\ntype Manifest = { components: ManifestEntry[] };\ntype Framework = \"astro\" | \"next\";\n\nconst here = dirname(fileURLToPath(import.meta.url));\nconst PREVIEW_BASE = \"/__bettercms/component-preview\";\nconst COMPONENT_EXTENSIONS = new Set([\".astro\", \".tsx\", \".jsx\", \".ts\", \".js\", \".mjs\"]);\nconst IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;\n\n/**\n * 🔴 THROWN, NOT `process.exit`. Writes to a piped stderr are asynchronous in Node, so exiting on the\n * next line dropped the message: in CI the step failed with no reason in the log at all. The single\n * handler at the bottom prints and sets the exit code, and the process ends once the write has flushed.\n */\nexport class CliFailure extends Error {}\n\nexport function fail(message: string): never {\n throw new CliFailure(message);\n}\n\n/**\n * Files a framework build rewrites in place. `next build` edits tsconfig.json and next-env.d.ts; an\n * `npm install --no-save` still rewrites the lockfile. Restored afterwards, so a preview build leaves the\n * app exactly as it found it.\n */\nfunction snapshot(root: string, names: string[]): () => void {\n const saved = names.map((name) => {\n const file = join(root, name);\n return { file, content: existsSync(file) ? readFileSync(file) : null };\n });\n return () => {\n for (const { file, content } of saved) {\n if (content === null) rmSync(file, { force: true });\n else writeFileSync(file, content);\n }\n };\n}\n\nconst MUTATED_BY_BUILD = [\"tsconfig.json\", \"next-env.d.ts\", \"package-lock.json\", \"pnpm-lock.yaml\", \"yarn.lock\", \"bun.lock\"];\n\nfunction readJson<T>(file: string): T {\n try {\n return JSON.parse(readFileSync(file, \"utf8\")) as T;\n } catch (error) {\n fail(`could not read ${file}: ${(error as Error).message}`);\n }\n}\n\n/** Manifest paths travel from an API into generated imports: relative, inside the app, and real. */\nexport function validateManifest(root: string, manifest: Manifest): ManifestEntry[] {\n if (!manifest || !Array.isArray(manifest.components) || manifest.components.length === 0) {\n fail(\"the manifest lists no components\");\n }\n const seen = new Set<string>();\n return manifest.components.map((entry) => {\n if (!entry || typeof entry.id !== \"string\" || !entry.id.trim()) fail(\"a manifest entry has no id\");\n if (seen.has(entry.id)) fail(`component ${entry.id} is listed twice`);\n seen.add(entry.id);\n const path = entry.source?.path;\n if (typeof path !== \"string\" || path.startsWith(\"/\") || path.includes(\"\\\\\") || path.split(\"/\").includes(\"..\")) {\n fail(`component ${entry.id} has an unsafe source path: ${String(path)}`);\n }\n if (!COMPONENT_EXTENSIONS.has(extname(path))) fail(`component ${entry.id}: unsupported file type ${extname(path)}`);\n if (!existsSync(join(root, path))) fail(`component ${entry.id}: ${path} does not exist`);\n const named = entry.source.export;\n if (named !== undefined && named !== \"default\" && !IDENTIFIER.test(named)) {\n fail(`component ${entry.id}: export \"${named}\" is not a valid identifier`);\n }\n return { id: entry.id, source: { path, export: named ?? \"default\" } };\n });\n}\n\nfunction detectFramework(root: string): Framework {\n const pkg = readJson<{ dependencies?: Record<string, string>; devDependencies?: Record<string, string> }>(join(root, \"package.json\"));\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n if (deps.astro) return \"astro\";\n if (deps.next) return \"next\";\n fail(\"this app depends on neither astro nor next\");\n}\n\nfunction run(root: string, command: string, args: string[]) {\n const result = spawnSync(command, args, { cwd: root, stdio: \"inherit\", env: process.env });\n if (result.status !== 0) throw new Error(`${command} ${args.join(\" \")} exited with ${result.status}`);\n}\n\nfunction bin(root: string, name: string): string {\n const local = join(root, \"node_modules\", \".bin\", name);\n if (!existsSync(local)) fail(`${name} is not installed in ${root}. Install the app's dependencies first.`);\n return local;\n}\n\n/** A registry module: one import per component, keyed by component id. */\nfunction registrySource(fromDir: string, root: string, entries: ManifestEntry[]): string {\n const imports: string[] = [];\n const keys: string[] = [];\n entries.forEach((entry, index) => {\n let specifier = relative(fromDir, join(root, entry.source.path)).split(sep).join(\"/\");\n if (!specifier.startsWith(\".\")) specifier = `./${specifier}`;\n // TypeScript sources are imported without their extension, the way the app itself imports them.\n if ([\".tsx\", \".ts\", \".jsx\", \".js\"].includes(extname(specifier))) specifier = specifier.slice(0, -extname(specifier).length);\n const local = `Component${index}`;\n imports.push(entry.source.export === \"default\"\n ? `import ${local} from ${JSON.stringify(specifier)};`\n : `import { ${entry.source.export} as ${local} } from ${JSON.stringify(specifier)};`);\n keys.push(` ${JSON.stringify(entry.id)}: ${local},`);\n });\n return `${imports.join(\"\\n\")}\\n\\nexport const registry: Record<string, any> = {\\n${keys.join(\"\\n\")}\\n};\\n\\nexport const has = (componentId: string): boolean => Object.prototype.hasOwnProperty.call(registry, componentId);\\n`;\n}\n\nfunction writeRuntimeLibrary(dir: string) {\n writeFileSync(join(dir, \"server.mjs\"), readFileSync(join(here, \"server.js\"), \"utf8\"));\n const types = join(here, \"server.d.ts\");\n if (existsSync(types)) writeFileSync(join(dir, \"server.d.mts\"), readFileSync(types, \"utf8\"));\n writeFileSync(join(dir, \"shell.ts\"), `export default ${JSON.stringify(readFileSync(join(here, \"shell.global.js\"), \"utf8\"))};\\n`);\n}\n\n/** CSS the app's layouts import. The render page has no layout, so it imports them itself. */\nfunction astroGlobalStyles(root: string): string[] {\n const found = new Set<string>();\n const scan = (dir: string) => {\n if (!existsSync(dir)) return;\n for (const name of readdirSync(dir)) {\n const full = join(dir, name);\n if (statSync(full).isDirectory()) scan(full);\n else if (name.endsWith(\".astro\")) {\n for (const match of readFileSync(full, \"utf8\").matchAll(/^\\s*import\\s+[\"']([^\"']+\\.css)[\"'];?/gm)) {\n const target = resolve(dirname(full), match[1]!);\n if (target.startsWith(root) && existsSync(target)) found.add(target);\n }\n }\n }\n };\n scan(join(root, \"src\", \"layouts\"));\n return [...found];\n}\n\nconst ASTRO_NODE_ADAPTER: Record<string, string> = { \"5\": \"^9\", \"6\": \"^10\", \"7\": \"^11\" };\n\nfunction ensureAstroNodeAdapter(root: string) {\n const require = createRequire(join(root, \"package.json\"));\n try {\n require.resolve(\"@astrojs/node\");\n return;\n } catch {\n // Not installed: add it without touching package.json or the lockfile.\n }\n const astroVersion = readJson<{ version: string }>(require.resolve(\"astro/package.json\")).version;\n const range = ASTRO_NODE_ADAPTER[astroVersion.split(\".\")[0]!];\n if (!range) fail(`Astro ${astroVersion} is not supported for component previews yet`);\n run(root, \"npm\", [\"install\", \"--no-save\", \"--no-audit\", \"--no-fund\", `@astrojs/node@${range}`]);\n}\n\nfunction buildAstro(root: string, entries: ManifestEntry[], out: string) {\n const configName = [\"astro.config.mjs\", \"astro.config.js\", \"astro.config.ts\", \"astro.config.mts\"].find((f) => existsSync(join(root, f)));\n if (!configName) fail(\"no astro.config file found\");\n ensureAstroNodeAdapter(root);\n\n const gen = join(root, \".bcms-preview\");\n const wrapper = join(root, \"astro.config.bcms-preview.mjs\");\n rmSync(gen, { recursive: true, force: true });\n mkdirSync(gen, { recursive: true });\n try {\n writeRuntimeLibrary(gen);\n writeFileSync(join(gen, \"registry.ts\"), registrySource(gen, root, entries));\n const handler = (method: string, body: string) =>\n `export const prerender = false;\\nexport const ${method} = ${body};\\n`;\n writeFileSync(join(gen, \"runtime.ts\"), `import { handleRuntime } from \"./server.mjs\";\\nimport shell from \"./shell\";\\n${handler(\"GET\", \"() => handleRuntime(shell)\")}`);\n writeFileSync(join(gen, \"session.ts\"), `import { handleSession } from \"./server.mjs\";\\nimport { has } from \"./registry\";\\n${handler(\"POST\", \"({ request }: { request: Request }) => handleSession(request, has)\")}`);\n writeFileSync(join(gen, \"props.ts\"), `import { handleProps } from \"./server.mjs\";\\nimport { has } from \"./registry\";\\n${handler(\"POST\", \"({ request }: { request: Request }) => handleProps(request, has)\")}`);\n writeFileSync(join(gen, \"health.ts\"), `import { handleHealth } from \"./server.mjs\";\\n${handler(\"GET\", \"() => handleHealth()\")}`);\n const styles = astroGlobalStyles(root)\n .map((file) => `import ${JSON.stringify(relative(gen, file).split(sep).join(\"/\"))};`)\n .join(\"\\n\");\n writeFileSync(join(gen, \"render.astro\"), `---\n${styles}\nimport { renderEntry, renderHeaders } from \"./server.mjs\";\nimport { registry } from \"./registry\";\nexport const prerender = false;\nconst headers = renderHeaders();\nconst entry = renderEntry(Astro.url.searchParams.get(\"id\"));\nconst Component = entry ? registry[entry.componentId] : undefined;\nfor (const [name, value] of Object.entries(headers)) Astro.response.headers.set(name, value);\nif (!entry || !Component) return new Response(\"Not found\", { status: 404, headers });\n---\n<html lang=\"en\" data-bcms-preview-render=\"1\">\n <head><meta charset=\"utf-8\" /><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" /></head>\n <body><Component {...entry.props} /></body>\n</html>\n`);\n writeFileSync(wrapper, `import user from \"./${configName}\";\nimport node from \"@astrojs/node\";\n\nconst routes = [\"runtime.ts\", \"session.ts\", \"props.ts\", \"render.astro\", \"health.ts\"];\n\nexport default {\n ...user,\n output: \"server\",\n base: ${JSON.stringify(PREVIEW_BASE)},\n adapter: node({ mode: \"standalone\" }),\n integrations: [\n ...(user.integrations ?? []),\n {\n name: \"bettercms-component-preview\",\n hooks: {\n \"astro:config:setup\": ({ injectRoute }) => {\n for (const file of routes) {\n injectRoute({\n pattern: \"/__bcms/\" + file.replace(/\\\\.(ts|astro)$/, \"\"),\n entrypoint: new URL(\"./.bcms-preview/\" + file, import.meta.url),\n prerender: false,\n });\n }\n },\n },\n },\n ],\n};\n`);\n rmSync(join(root, \"dist\"), { recursive: true, force: true });\n run(root, bin(root, \"astro\"), [\"build\", \"--config\", \"astro.config.bcms-preview.mjs\"]);\n } finally {\n rmSync(gen, { recursive: true, force: true });\n rmSync(wrapper, { force: true });\n }\n\n const app = join(out, \"app\");\n mkdirSync(app, { recursive: true });\n cpSync(join(root, \"dist\"), app, { recursive: true });\n cpSync(join(root, \"package.json\"), join(app, \"package.json\"));\n // Astro does not bundle its dependencies, so the server entry needs them on disk.\n cpSync(join(root, \"node_modules\"), join(app, \"node_modules\"), { recursive: true, verbatimSymlinks: true });\n writeFileSync(join(out, \"bcms-runtime.json\"), `${JSON.stringify({ kind: \"node\", dir: \"app\", entry: \"server/entry.mjs\" })}\\n`);\n}\n\nfunction buildNext(root: string, entries: ManifestEntry[], out: string) {\n const appDir = [\"app\", join(\"src\", \"app\")].map((d) => join(root, d)).find((d) => existsSync(d));\n if (!appDir) fail(\"no App Router directory (app/ or src/app/) found\");\n const configName = [\"next.config.mjs\", \"next.config.js\", \"next.config.ts\", \"next.config.cjs\"].find((f) => existsSync(join(root, f)));\n\n // `%5F%5Fbcms` is how a URL segment starting with an underscore is spelled in the App Router: a plain\n // `__bcms` folder is a PRIVATE folder and silently produces no routes at all.\n const gen = join(appDir, \"%5F%5Fbcms\");\n const userConfig = configName ? join(root, configName.replace(\"next.config\", \"next.config.bcms-user\")) : null;\n const wrapperName = configName && configName.endsWith(\".ts\") ? \"next.config.ts\" : \"next.config.mjs\";\n rmSync(gen, { recursive: true, force: true });\n mkdirSync(gen, { recursive: true });\n if (configName && userConfig) renameSync(join(root, configName), userConfig);\n try {\n writeRuntimeLibrary(gen);\n writeFileSync(join(gen, \"registry.ts\"), registrySource(gen, root, entries));\n const route = (name: string, source: string) => {\n mkdirSync(join(gen, name), { recursive: true });\n writeFileSync(join(gen, name, \"route.ts\"), `export const dynamic = \"force-dynamic\";\\n${source}`);\n };\n route(\"runtime\", `import { handleRuntime } from \"../server.mjs\";\\nimport shell from \"../shell\";\\nexport function GET() {\\n return handleRuntime(shell);\\n}\\n`);\n route(\"session\", `import { handleSession } from \"../server.mjs\";\\nimport { has } from \"../registry\";\\nexport function POST(request: Request) {\\n return handleSession(request, has);\\n}\\n`);\n route(\"props\", `import { handleProps } from \"../server.mjs\";\\nimport { has } from \"../registry\";\\nexport function POST(request: Request) {\\n return handleProps(request, has);\\n}\\n`);\n route(\"health\", `import { handleHealth } from \"../server.mjs\";\\nexport function GET() {\\n return handleHealth();\\n}\\n`);\n mkdirSync(join(gen, \"render\"), { recursive: true });\n writeFileSync(join(gen, \"render\", \"page.tsx\"), `import { notFound } from \"next/navigation\";\nimport { renderEntry } from \"../server.mjs\";\nimport { registry } from \"../registry\";\n\nexport const dynamic = \"force-dynamic\";\n\nexport default async function BetterCMSComponentPreview({ searchParams }: { searchParams: Promise<{ id?: string }> }) {\n const { id } = await searchParams;\n const entry = renderEntry(id);\n const Component = entry ? registry[entry.componentId] : undefined;\n if (!entry || !Component) notFound();\n // The marker the runtime page checks before acknowledging: a 404 or an error page never carries it.\n return (\n <>\n <Component {...entry.props} />\n <template data-bcms-preview-render=\"1\" />\n </>\n );\n}\n`);\n const importUser = userConfig ? `import user from \"./${relative(root, userConfig)}\";` : \"const user = {};\";\n writeFileSync(join(root, wrapperName), `${importUser}\n\n// No frame-ancestors here: next.config headers are fixed at build time, and the dashboard origin the\n// render frame must allow is runtime configuration. The platform's proxy sets it for this whole prefix.\nconst RENDER_HEADERS = [\n { key: \"referrer-policy\", value: \"no-referrer\" },\n { key: \"cache-control\", value: \"no-store\" },\n];\n\nexport default async function betterCMSComponentPreviewConfig(phase, context) {\n const resolved = typeof user === \"function\" ? await user(phase, context) : user;\n const userHeaders = resolved.headers;\n return {\n ...resolved,\n output: \"standalone\",\n basePath: ${JSON.stringify(PREVIEW_BASE)},\n async headers() {\n const own = typeof userHeaders === \"function\" ? await userHeaders() : [];\n return [...own, { source: \"/__bcms/render\", headers: RENDER_HEADERS }];\n },\n };\n}\n`);\n rmSync(join(root, \".next\"), { recursive: true, force: true });\n run(root, bin(root, \"next\"), [\"build\"]);\n } finally {\n rmSync(gen, { recursive: true, force: true });\n rmSync(join(root, wrapperName), { force: true });\n if (configName && userConfig && existsSync(userConfig)) renameSync(userConfig, join(root, configName));\n }\n\n const standalone = join(root, \".next\", \"standalone\");\n if (!existsSync(join(standalone, \"server.js\"))) fail(\"next build produced no standalone server\");\n const app = join(out, \"app\");\n mkdirSync(app, { recursive: true });\n cpSync(standalone, app, { recursive: true, verbatimSymlinks: true });\n if (existsSync(join(root, \".next\", \"static\"))) cpSync(join(root, \".next\", \"static\"), join(app, \".next\", \"static\"), { recursive: true });\n if (existsSync(join(root, \"public\"))) cpSync(join(root, \"public\"), join(app, \"public\"), { recursive: true });\n writeFileSync(join(out, \"bcms-runtime.json\"), `${JSON.stringify({ kind: \"node\", dir: \"app\", entry: \"server.js\" })}\\n`);\n}\n\nexport function buildPreviewRuntime(input: { root: string; manifestPath: string; out: string }) {\n const root = resolve(input.root);\n const out = resolve(input.out);\n const entries = validateManifest(root, readJson<Manifest>(resolve(input.manifestPath)));\n const framework = detectFramework(root);\n\n rmSync(out, { recursive: true, force: true });\n mkdirSync(out, { recursive: true });\n const restore = snapshot(root, MUTATED_BY_BUILD);\n try {\n if (framework === \"astro\") buildAstro(root, entries, out);\n else buildNext(root, entries, out);\n } finally {\n restore();\n }\n return { framework, out, components: entries.map((e) => e.id) };\n}\n","/**\n * `bcms-preview validate` — validates one component in CI with nothing configured in the repository.\n *\n * Run by `.github/workflows/bcms-component-validation.yml`, which BetterCMS commits and dispatches. In\n * order: build a preview runtime from the app as it is, render the component with its default props in a\n * real browser at every native viewport, check brand tokens and the console, package the runtime — and only\n * then claim the request, upload the bundle the platform will serve previews from, and complete it.\n *\n * 🔴 NOTHING FAILS SILENTLY. A component whose checks fail is still COMPLETED — failed evidence is a\n * result the dashboard shows, with the failing checks. Anything that prevents a result (no source file\n * recorded, a build that breaks, a runtime that never starts, no browser) FAILS the request with a named\n * code and the reason, so the panel says what happened instead of waiting for the request to expire.\n */\nimport { spawn, spawnSync, type ChildProcess } from \"node:child_process\";\nimport { createHash, randomBytes } from \"node:crypto\";\nimport { mkdtempSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { createServer } from \"node:net\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { buildPreviewRuntime, CliFailure } from \"./build\";\n\nconst PREVIEW_ROUTE_BASE = \"/__bettercms/component-preview/__bcms\";\nconst RUNTIME_PATH = `${PREVIEW_ROUTE_BASE}/runtime`;\n\ntype Viewport = { name: string; width: number; height: number };\ntype RequestTarget = {\n componentId: string;\n componentVersion: number;\n candidateId: string;\n familyKey: string;\n familyContractHash: string;\n schemaHash: string;\n brandContractHash: string;\n dependenciesHash: string;\n commitSha: string;\n adapterHash: string;\n familyManifestHash: string;\n nativeViewports: Viewport[];\n};\ntype Manifest = {\n components: { id: string; source: { path: string; export: string }; defaultProps: Record<string, unknown> }[];\n brandTokenNames: string[];\n};\n\nclass ValidationFailure extends Error {\n constructor(readonly code: string, message: string) {\n super(message);\n this.name = \"ValidationFailure\";\n }\n}\n\nfunction required(name: string): string {\n const value = process.env[name]?.trim();\n if (!value) throw new CliFailure(`${name} is not set. This command runs inside the BetterCMS component validation workflow.`);\n return value;\n}\n\nconst sha256 = (data: string | Buffer) => createHash(\"sha256\").update(data).digest(\"hex\");\n\nfunction canonical(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(canonical).join(\",\")}]`;\n if (value && typeof value === \"object\") {\n return `{${Object.keys(value as Record<string, unknown>).sort()\n .map((key) => `${JSON.stringify(key)}:${canonical((value as Record<string, unknown>)[key])}`).join(\",\")}}`;\n }\n return JSON.stringify(value);\n}\n\nfunction freePort(): Promise<number> {\n return new Promise((resolve, reject) => {\n const server = createServer();\n server.once(\"error\", reject);\n server.listen(0, \"127.0.0.1\", () => {\n const address = server.address();\n const port = typeof address === \"object\" && address ? address.port : 0;\n server.close(() => resolve(port));\n });\n });\n}\n\nasync function waitForOk(url: string, timeoutMs: number): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n try {\n if ((await fetch(url)).ok) return true;\n } catch {\n // not up yet\n }\n await new Promise((r) => setTimeout(r, 500));\n }\n return false;\n}\n\n/** Install Chromium for the bundled Playwright. On a Linux CI runner, with its system dependencies. */\nfunction ensureBrowser() {\n const require = createRequire(import.meta.url);\n const cli = join(dirname(require.resolve(\"playwright/package.json\")), \"cli.js\");\n const args = [cli, \"install\", \"chromium\"];\n if (process.platform === \"linux\" && process.env.CI) args.push(\"--with-deps\");\n const result = spawnSync(process.execPath, args, { stdio: \"inherit\" });\n if (result.status !== 0) {\n throw new ValidationFailure(\"COMPONENT_VALIDATION_BROWSER_UNAVAILABLE\", \"A headless browser could not be installed on this runner.\");\n }\n}\n\nasync function renderInBrowser(url: string, viewports: Viewport[], tokenNames: string[]) {\n ensureBrowser();\n const { chromium } = await import(\"playwright\");\n const browser = await chromium.launch();\n try {\n let consoleErrors = 0;\n let runtimeErrors = 0;\n const missingTokens = new Set<string>();\n const results: { name: string; width: number; height: number; status: \"baseline-missing\"; candidateDigest: string }[] = [];\n const problems: string[] = [];\n for (const viewport of viewports) {\n const page = await browser.newPage({ viewport: { width: viewport.width, height: viewport.height } });\n page.on(\"console\", (message) => {\n if (message.type() === \"error\") {\n consoleErrors += 1;\n problems.push(`${viewport.name} console: ${message.text().slice(0, 200)}`);\n }\n });\n page.on(\"pageerror\", (error) => {\n runtimeErrors += 1;\n problems.push(`${viewport.name} error: ${error.message.slice(0, 200)}`);\n });\n const response = await page.goto(url, { waitUntil: \"load\", timeout: 45_000 });\n await page.waitForLoadState(\"networkidle\", { timeout: 15_000 }).catch(() => {});\n const rendered = await page.locator(\"[data-bcms-preview-render]\").count();\n if (!response?.ok() || rendered === 0) {\n runtimeErrors += 1;\n problems.push(`${viewport.name}: the component page did not render (HTTP ${response?.status() ?? \"none\"})`);\n }\n /**\n * A token is MISSING only when the rendered page uses it and it resolves to nothing. `--bcms-*` are\n * guaranteed on pages BetterCMS renders itself, not in a customer's framework build, so asking\n * \"is every token defined?\" would fail every starter while saying nothing about the component. The\n * question worth a failure is \"does this component reference a brand token the app never defines?\"\n * — a component that will render unstyled on the live site. Cross-origin stylesheets cannot be read\n * and are skipped.\n */\n const missing = await page.evaluate((names: string[]) => {\n const referenced = new Set<string>();\n const scan = (text: string) => {\n for (const match of text.matchAll(/var\\(\\s*(--[A-Za-z0-9_-]+)/g)) referenced.add(match[1]!);\n };\n for (const sheet of Array.from(document.styleSheets)) {\n try {\n for (const rule of Array.from(sheet.cssRules)) scan(rule.cssText);\n } catch {\n // cross-origin sheet\n }\n }\n document.querySelectorAll(\"[style]\").forEach((element) => scan(element.getAttribute(\"style\") ?? \"\"));\n const style = getComputedStyle(document.documentElement);\n return names.filter((name) => referenced.has(name) && !style.getPropertyValue(name).trim());\n }, tokenNames);\n for (const token of missing) missingTokens.add(token);\n const png = await page.screenshot({ fullPage: true });\n results.push({\n name: viewport.name,\n width: viewport.width,\n height: viewport.height,\n // No baseline exists for a first validation. The database requires this exact shape for it:\n // no baseline or diff digest, and the check marked as needing review.\n status: \"baseline-missing\",\n candidateDigest: `sha256:${sha256(png)}`,\n });\n await page.close();\n }\n return { results, consoleErrors, runtimeErrors, missingTokens: [...missingTokens].sort(), problems };\n } finally {\n await browser.close();\n }\n}\n\nexport async function validateComponent() {\n const apiUrl = required(\"BCMS_API_URL\");\n const apiKey = required(\"BCMS_API_KEY\");\n const projectId = required(\"BCMS_PROJECT_ID\");\n const requestId = required(\"BCMS_REQUEST_ID\");\n const componentId = required(\"BCMS_COMPONENT_ID\");\n const commitSha = required(\"BCMS_COMMIT_SHA\");\n const familyKey = required(\"BCMS_FAMILY_KEY\");\n const previewOrigin = required(\"BCMS_PREVIEW_ORIGIN\");\n const nativeViewports = JSON.parse(required(\"BCMS_NATIVE_VIEWPORTS\")) as Viewport[];\n\n const api = async <T>(path: string, init: { method?: string; body?: unknown; claim?: string } = {}): Promise<T> => {\n const response = await fetch(new URL(path, apiUrl), {\n method: init.method ?? \"GET\",\n headers: {\n authorization: `Bearer ${apiKey}`,\n \"content-type\": \"application/json\",\n ...(init.claim ? { \"x-bcms-component-claim\": init.claim } : {}),\n },\n ...(init.body === undefined ? {} : { body: JSON.stringify(init.body) }),\n });\n const text = await response.text();\n let parsed: { data?: unknown; error?: unknown; message?: unknown } | null = null;\n try {\n parsed = JSON.parse(text);\n } catch {\n parsed = null;\n }\n if (!response.ok) {\n const code = typeof parsed?.error === \"string\" && /^[A-Z][A-Z0-9_]*$/.test(parsed.error) ? parsed.error : `API_HTTP_${response.status}`;\n const detail = typeof parsed?.message === \"string\" ? parsed.message : typeof parsed?.error === \"string\" ? parsed.error : text.slice(0, 300);\n throw new ValidationFailure(code, `${init.method ?? \"GET\"} ${path} answered ${response.status}: ${detail}`);\n }\n return ((parsed && \"data\" in parsed ? parsed.data : parsed) ?? {}) as T;\n };\n\n const claimPath = `/api/v1/projects/${projectId}/component-implementation/implementation-requests/${requestId}`;\n let claim: { request: RequestTarget; claimCapability: string } | null = null;\n /**\n * 🔴 CLAIMED LAST, NOT FIRST. A claim credential lives minutes, and `complete` refuses an expired one.\n * Claiming before a framework build, a browser install and a render meant every real run finished with\n * a credential that had already lapsed — and the request sat \"running\" until it expired. Everything slow\n * happens first; the claim is followed only by an upload and the completion.\n */\n const claimRequest = async () => {\n claim = await api<{ request: RequestTarget; claimCapability: string }>(`${claimPath}/claim`, {\n method: \"POST\",\n body: {\n componentId,\n commitSha,\n adapter: { protocol: \"bcms-component-runtime-v1\", kind: \"project-route\", path: RUNTIME_PATH, familyKey, previewOrigin, nativeViewports },\n providerRunId: required(\"BCMS_RUN_ID\"),\n providerRunAttempt: Number(process.env.BCMS_RUN_ATTEMPT) || 1,\n providerRunUrl: required(\"BCMS_RUN_URL\"),\n workflowRef: required(\"BCMS_WORKFLOW_REF\"),\n // The server caps this at the request's own expiry and at ten minutes.\n credentialExpiresAt: new Date(Date.now() + 10 * 60_000 - 5_000).toISOString(),\n },\n });\n return claim;\n };\n\n const work = mkdtempSync(join(tmpdir(), \"bcms-validate-\"));\n let runtime: ChildProcess | null = null;\n try {\n const manifest = await api<Manifest>(`/api/v1/projects/${projectId}/component-preview/manifest`);\n const entry = manifest.components.find((c) => c.id === componentId);\n if (!entry) {\n throw new ValidationFailure(\n \"COMPONENT_SOURCE_NOT_RECORDED\",\n \"No file is recorded as this component's source. The agent that writes a component records it with set_component_source.\",\n );\n }\n\n const manifestPath = join(work, \"manifest.json\");\n writeFileSync(manifestPath, JSON.stringify({ components: manifest.components.map(({ id, source }) => ({ id, source })) }));\n const out = join(work, \"runtime\");\n try {\n buildPreviewRuntime({ root: process.cwd(), manifestPath, out });\n } catch (error) {\n throw new ValidationFailure(\"COMPONENT_PREVIEW_BUILD_FAILED\", `The preview build failed: ${(error as Error).message}`);\n }\n\n const runtimeManifest = JSON.parse(readFileSync(join(out, \"bcms-runtime.json\"), \"utf8\")) as { dir: string; entry: string };\n const port = await freePort();\n const validatorKey = randomBytes(32).toString(\"base64url\");\n const local = `http://127.0.0.1:${port}`;\n // 🔴 The customer's code runs in this process tree. It gets no BetterCMS API key.\n const { BCMS_API_KEY: _withheld, ...inherited } = process.env;\n runtime = spawn(process.execPath, [join(out, runtimeManifest.dir, runtimeManifest.entry)], {\n cwd: join(out, runtimeManifest.dir),\n env: {\n ...inherited,\n NODE_ENV: \"production\",\n PORT: String(port),\n HOST: \"127.0.0.1\",\n HOSTNAME: \"127.0.0.1\",\n BCMS_API_URL: apiUrl,\n BCMS_DASHBOARD_ORIGIN: local,\n BCMS_PREVIEW_ORIGIN: local,\n BCMS_PREVIEW_VALIDATOR_KEY: validatorKey,\n },\n stdio: [\"ignore\", \"inherit\", \"inherit\"],\n });\n if (!(await waitForOk(`${local}${PREVIEW_ROUTE_BASE}/health`, 60_000))) {\n throw new ValidationFailure(\"COMPONENT_PREVIEW_RUNTIME_DID_NOT_START\", \"The preview runtime did not start within 60 seconds.\");\n }\n\n const stored = await fetch(`${local}${PREVIEW_ROUTE_BASE}/props`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"x-bcms-validator-key\": validatorKey },\n body: JSON.stringify({ componentId, props: entry.defaultProps }),\n });\n if (!stored.ok) {\n throw new ValidationFailure(\"COMPONENT_PREVIEW_RUNTIME_REFUSED\", `The preview runtime refused the component (HTTP ${stored.status}).`);\n }\n const { id } = (await stored.json()) as { id: string };\n\n // The viewports the dispatch declared are exactly the ones the claim records as the adapter's.\n const render = await renderInBrowser(\n `${local}${PREVIEW_ROUTE_BASE}/render?id=${encodeURIComponent(id)}`,\n nativeViewports,\n manifest.brandTokenNames,\n );\n\n const tarball = join(work, \"bundle.tgz\");\n if (spawnSync(\"tar\", [\"-czf\", tarball, \"-C\", out, \".\"], { stdio: \"inherit\" }).status !== 0) {\n throw new ValidationFailure(\"COMPONENT_PREVIEW_BUNDLE_PACK_FAILED\", \"The preview runtime could not be packaged.\");\n }\n const bytes = readFileSync(tarball);\n runtime.kill();\n runtime = null;\n\n const target = (await claimRequest()).request;\n const checks = {\n brandKit: {\n status: render.missingTokens.length === 0 ? \"passed\" : \"failed\",\n contractHash: target.brandContractHash,\n missingTokens: render.missingTokens,\n },\n runtime: {\n status: render.runtimeErrors === 0 && render.consoleErrors === 0 ? \"passed\" : \"failed\",\n runtimeErrors: render.runtimeErrors,\n consoleErrors: render.consoleErrors,\n },\n visual: { status: \"baseline-missing\", reviewRequired: true, viewports: render.results },\n };\n\n // Uploaded before completing: validated evidence pointing at a runtime nobody can start renders nothing.\n const upload = await api<{ uploadUrl: string; uploadKey: string }>(`/api/v1/projects/${projectId}/artifacts/upload-url`, { method: \"POST\" });\n const put = await fetch(upload.uploadUrl, { method: \"PUT\", body: bytes, headers: { \"content-type\": \"application/gzip\" } });\n if (!put.ok) {\n throw new ValidationFailure(\"COMPONENT_PREVIEW_BUNDLE_UPLOAD_FAILED\", `Storage refused the preview bundle (HTTP ${put.status}).`);\n }\n await api(`/api/v1/projects/${projectId}/component-preview/bundles`, {\n method: \"POST\",\n body: { commitSha: target.commitSha, uploadKey: upload.uploadKey, checksum: `sha256:${sha256(bytes)}`, sizeBytes: bytes.byteLength },\n });\n\n const evidenceDigest = `sha256:${sha256(canonical({ requestId, commitSha: target.commitSha, checks }))}`;\n await api(`${claimPath}/complete`, {\n method: \"POST\",\n claim: claim!.claimCapability,\n body: {\n componentId: target.componentId,\n candidateId: target.candidateId,\n componentVersion: target.componentVersion,\n familyKey: target.familyKey,\n familyContractHash: target.familyContractHash,\n schemaHash: target.schemaHash,\n brandContractHash: target.brandContractHash,\n dependenciesHash: target.dependenciesHash,\n commitSha: target.commitSha,\n adapterHash: target.adapterHash,\n familyManifestHash: target.familyManifestHash,\n nativeViewports: target.nativeViewports,\n checks,\n evidenceDigest,\n },\n });\n\n const passed = checks.brandKit.status === \"passed\" && checks.runtime.status === \"passed\";\n console.log(`bcms-preview: validation ${passed ? \"PASSED\" : \"FAILED\"} for ${componentId}`);\n if (!passed) {\n if (render.missingTokens.length) console.log(` brand tokens used but not defined: ${render.missingTokens.join(\", \")}`);\n for (const problem of render.problems) console.log(` ${problem}`);\n }\n } catch (error) {\n const code = error instanceof ValidationFailure ? error.code : \"COMPONENT_VALIDATION_FAILED\";\n const message = (error as Error).message.slice(0, 2000);\n // A failure before the claim is still reported: claim, then fail at once, so the dashboard names the\n // reason instead of showing \"running\" until the request expires.\n const reported = claim ?? await claimRequest().catch((claimError) => {\n console.error(`bcms-preview: could not claim the request to report the failure: ${(claimError as Error).message}`);\n return null;\n });\n if (reported) {\n await api(`${claimPath}/fail`, {\n method: \"POST\",\n claim: reported.claimCapability,\n body: { componentId, errorCode: code, errorMessage: message },\n }).catch((reportError) => console.error(`bcms-preview: could not report the failure: ${(reportError as Error).message}`));\n }\n throw new CliFailure(`${code}: ${message}`);\n } finally {\n runtime?.kill();\n rmSync(work, { recursive: true, force: true });\n }\n}\n","/**\n * bcms-preview\n *\n * bcms-preview build --manifest <file> --out <dir> [--cwd <dir>]\n * bcms-preview validate (in CI; configured entirely by BCMS_* environment variables)\n */\nimport { buildPreviewRuntime, CliFailure } from \"./build\";\nimport { validateComponent } from \"./validate\";\n\nfunction arg(name: string): string | undefined {\n const index = process.argv.indexOf(`--${name}`);\n return index === -1 ? undefined : process.argv[index + 1];\n}\n\nasync function main() {\n const command = process.argv[2];\n if (command === \"build\") {\n const manifestPath = arg(\"manifest\");\n const out = arg(\"out\");\n if (!manifestPath || !out) throw new CliFailure(\"usage: bcms-preview build --manifest <file> --out <dir> [--cwd <dir>]\");\n console.log(JSON.stringify(buildPreviewRuntime({ root: arg(\"cwd\") ?? process.cwd(), manifestPath, out })));\n return;\n }\n if (command === \"validate\") {\n await validateComponent();\n return;\n }\n throw new CliFailure(\"usage: bcms-preview <build|validate>\");\n}\n\n/**\n * One handler for every failure, and no `process.exit`: writes to a piped stderr are asynchronous, so\n * exiting right after the write dropped the message and CI showed a failed step with no reason.\n */\nmain().catch((error) => {\n console.error(`bcms-preview: ${error instanceof CliFailure ? error.message : (error as Error).stack ?? String(error)}`);\n process.exitCode = 1;\n});\n"],"mappings":"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","names":["require","spawnSync","readFileSync","rmSync","writeFileSync","createRequire","dirname","join","resolve","require","createRequire","join","dirname","spawnSync","writeFileSync","id","readFileSync","rmSync"]}
|
|
1
|
+
{"version":3,"sources":["../src/build.ts","../src/validate.ts","../src/cli.ts"],"sourcesContent":["/**\n * Builds a component preview runtime from an unmodified Next.js or Astro app. Used by `bcms-preview build`\n * and by the validator.\n *\n * The manifest names which file implements which component:\n * { \"components\": [{ \"id\": \"cmp_1\", \"source\": { \"path\": \"src/components/Hero.astro\" } }] }\n *\n * 🔴 NOTHING IN THE CUSTOMER'S REPOSITORY IS CHANGED. Routes and a registry are generated into the\n * checkout, the framework builds, the result is packaged as a runtime release, and every generated file\n * is removed again — including when the build fails. In CI the checkout is thrown away anyway; on a\n * developer machine this is the difference between a tool and a mess.\n */\nimport { spawnSync } from \"node:child_process\";\nimport { cpSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { dirname, extname, join, relative, resolve, sep } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/**\n * `file`: a component module whose props ARE the component's fields — rendered with the props spread.\n * `section`: a section `npx @bettercms-ai/convert --componentize` extracted from a page. Its props are always\n * `{ blockId, bind, overrides, page }`, so it is rendered with the live props as `overrides`.\n */\ntype SourceKind = \"file\" | \"section\";\ntype ManifestEntry = { id: string; source: { path: string; export?: string; kind?: SourceKind } };\ntype Manifest = { components: ManifestEntry[] };\ntype Framework = \"astro\" | \"next\";\n\nconst here = dirname(fileURLToPath(import.meta.url));\nconst PREVIEW_BASE = \"/__bettercms/component-preview\";\nconst COMPONENT_EXTENSIONS = new Set([\".astro\", \".tsx\", \".jsx\", \".ts\", \".js\", \".mjs\"]);\nconst IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;\n/** Every section file the codemod writes carries this (`// @bettercms-ai/convert section v2`, earlier `v1`). */\nconst SECTION_MARKER_PREFIX = \"// @bettercms-ai/convert section v\";\n\n/**\n * 🔴 THROWN, NOT `process.exit`. Writes to a piped stderr are asynchronous in Node, so exiting on the\n * next line dropped the message: in CI the step failed with no reason in the log at all. The single\n * handler at the bottom prints and sets the exit code, and the process ends once the write has flushed.\n */\nexport class CliFailure extends Error {}\n\nexport function fail(message: string): never {\n throw new CliFailure(message);\n}\n\n/**\n * Files a framework build rewrites in place. `next build` edits tsconfig.json and next-env.d.ts; an\n * `npm install --no-save` still rewrites the lockfile. Restored afterwards, so a preview build leaves the\n * app exactly as it found it.\n */\nfunction snapshot(root: string, names: string[]): () => void {\n const saved = names.map((name) => {\n const file = join(root, name);\n return { file, content: existsSync(file) ? readFileSync(file) : null };\n });\n return () => {\n for (const { file, content } of saved) {\n if (content === null) rmSync(file, { force: true });\n else writeFileSync(file, content);\n }\n };\n}\n\nconst MUTATED_BY_BUILD = [\"tsconfig.json\", \"next-env.d.ts\", \"package-lock.json\", \"pnpm-lock.yaml\", \"yarn.lock\", \"bun.lock\"];\n\nfunction readJson<T>(file: string): T {\n try {\n return JSON.parse(readFileSync(file, \"utf8\")) as T;\n } catch (error) {\n fail(`could not read ${file}: ${(error as Error).message}`);\n }\n}\n\n/** Manifest paths travel from an API into generated imports: relative, inside the app, and real. */\nexport function validateManifest(root: string, manifest: Manifest): ManifestEntry[] {\n if (!manifest || !Array.isArray(manifest.components) || manifest.components.length === 0) {\n fail(\"the manifest lists no components\");\n }\n const seen = new Set<string>();\n return manifest.components.map((entry) => {\n if (!entry || typeof entry.id !== \"string\" || !entry.id.trim()) fail(\"a manifest entry has no id\");\n if (seen.has(entry.id)) fail(`component ${entry.id} is listed twice`);\n seen.add(entry.id);\n const path = entry.source?.path;\n if (typeof path !== \"string\" || path.startsWith(\"/\") || path.includes(\"\\\\\") || path.split(\"/\").includes(\"..\")) {\n fail(`component ${entry.id} has an unsafe source path: ${String(path)}`);\n }\n if (!COMPONENT_EXTENSIONS.has(extname(path))) fail(`component ${entry.id}: unsupported file type ${extname(path)}`);\n if (!existsSync(join(root, path))) fail(`component ${entry.id}: ${path} does not exist`);\n const named = entry.source.export;\n if (named !== undefined && named !== \"default\" && !IDENTIFIER.test(named)) {\n fail(`component ${entry.id}: export \"${named}\" is not a valid identifier`);\n }\n // A section is recognised by its own marker as well as by the manifest: a source recorded before kinds\n // existed defaults to `file`, and rendering a section as a file hands it none of its copy.\n const head = readFileSync(join(root, path), \"utf8\").slice(0, 512);\n const kind: SourceKind = entry.source.kind === \"section\" || head.includes(SECTION_MARKER_PREFIX) ? \"section\" : \"file\";\n return { id: entry.id, source: { path, export: named ?? \"default\", kind } };\n });\n}\n\nfunction detectFramework(root: string): Framework {\n const pkg = readJson<{ dependencies?: Record<string, string>; devDependencies?: Record<string, string> }>(join(root, \"package.json\"));\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n if (deps.astro) return \"astro\";\n if (deps.next) return \"next\";\n fail(\"this app depends on neither astro nor next\");\n}\n\nfunction run(root: string, command: string, args: string[]) {\n const result = spawnSync(command, args, { cwd: root, stdio: \"inherit\", env: process.env });\n if (result.status !== 0) throw new Error(`${command} ${args.join(\" \")} exited with ${result.status}`);\n}\n\nfunction bin(root: string, name: string): string {\n const local = join(root, \"node_modules\", \".bin\", name);\n if (!existsSync(local)) fail(`${name} is not installed in ${root}. Install the app's dependencies first.`);\n return local;\n}\n\n/** A registry module: one import per component, keyed by component id. */\nfunction registrySource(fromDir: string, root: string, entries: ManifestEntry[]): string {\n const imports: string[] = [];\n const keys: string[] = [];\n const kinds: string[] = [];\n entries.forEach((entry, index) => {\n let specifier = relative(fromDir, join(root, entry.source.path)).split(sep).join(\"/\");\n if (!specifier.startsWith(\".\")) specifier = `./${specifier}`;\n // TypeScript sources are imported without their extension, the way the app itself imports them.\n if ([\".tsx\", \".ts\", \".jsx\", \".js\"].includes(extname(specifier))) specifier = specifier.slice(0, -extname(specifier).length);\n const local = `Component${index}`;\n imports.push(entry.source.export === \"default\"\n ? `import ${local} from ${JSON.stringify(specifier)};`\n : `import { ${entry.source.export} as ${local} } from ${JSON.stringify(specifier)};`);\n keys.push(` ${JSON.stringify(entry.id)}: ${local},`);\n kinds.push(` ${JSON.stringify(entry.id)}: ${JSON.stringify(entry.source.kind ?? \"file\")},`);\n });\n return `${imports.join(\"\\n\")}\\n\\nexport const registry: Record<string, any> = {\\n${keys.join(\"\\n\")}\\n};\\n\\nexport const kinds: Record<string, \"file\" | \"section\"> = {\\n${kinds.join(\"\\n\")}\\n};\\n\\nexport const has = (componentId: string): boolean => Object.prototype.hasOwnProperty.call(registry, componentId);\\n`;\n}\n\nfunction writeRuntimeLibrary(dir: string) {\n writeFileSync(join(dir, \"server.mjs\"), readFileSync(join(here, \"server.js\"), \"utf8\"));\n const types = join(here, \"server.d.ts\");\n if (existsSync(types)) writeFileSync(join(dir, \"server.d.mts\"), readFileSync(types, \"utf8\"));\n writeFileSync(join(dir, \"shell.ts\"), `export default ${JSON.stringify(readFileSync(join(here, \"shell.global.js\"), \"utf8\"))};\\n`);\n}\n\n/** CSS the app's layouts import. The render page has no layout, so it imports them itself. */\nfunction astroGlobalStyles(root: string): string[] {\n const found = new Set<string>();\n const scan = (dir: string) => {\n if (!existsSync(dir)) return;\n for (const name of readdirSync(dir)) {\n const full = join(dir, name);\n if (statSync(full).isDirectory()) scan(full);\n else if (name.endsWith(\".astro\")) {\n for (const match of readFileSync(full, \"utf8\").matchAll(/^\\s*import\\s+[\"']([^\"']+\\.css)[\"'];?/gm)) {\n const target = resolve(dirname(full), match[1]!);\n if (target.startsWith(root) && existsSync(target)) found.add(target);\n }\n }\n }\n };\n scan(join(root, \"src\", \"layouts\"));\n return [...found];\n}\n\nconst ASTRO_NODE_ADAPTER: Record<string, string> = { \"5\": \"^9\", \"6\": \"^10\", \"7\": \"^11\" };\n\nfunction ensureAstroNodeAdapter(root: string) {\n const require = createRequire(join(root, \"package.json\"));\n try {\n require.resolve(\"@astrojs/node\");\n return;\n } catch {\n // Not installed: add it without touching package.json or the lockfile.\n }\n const astroVersion = readJson<{ version: string }>(require.resolve(\"astro/package.json\")).version;\n const range = ASTRO_NODE_ADAPTER[astroVersion.split(\".\")[0]!];\n if (!range) fail(`Astro ${astroVersion} is not supported for component previews yet`);\n run(root, \"npm\", [\"install\", \"--no-save\", \"--no-audit\", \"--no-fund\", `@astrojs/node@${range}`]);\n}\n\nfunction buildAstro(root: string, entries: ManifestEntry[], out: string) {\n const configName = [\"astro.config.mjs\", \"astro.config.js\", \"astro.config.ts\", \"astro.config.mts\"].find((f) => existsSync(join(root, f)));\n if (!configName) fail(\"no astro.config file found\");\n ensureAstroNodeAdapter(root);\n\n const gen = join(root, \".bcms-preview\");\n const wrapper = join(root, \"astro.config.bcms-preview.mjs\");\n rmSync(gen, { recursive: true, force: true });\n mkdirSync(gen, { recursive: true });\n try {\n writeRuntimeLibrary(gen);\n writeFileSync(join(gen, \"registry.ts\"), registrySource(gen, root, entries));\n const handler = (method: string, body: string) =>\n `export const prerender = false;\\nexport const ${method} = ${body};\\n`;\n writeFileSync(join(gen, \"runtime.ts\"), `import { handleRuntime } from \"./server.mjs\";\\nimport shell from \"./shell\";\\n${handler(\"GET\", \"() => handleRuntime(shell)\")}`);\n writeFileSync(join(gen, \"session.ts\"), `import { handleSession } from \"./server.mjs\";\\nimport { has } from \"./registry\";\\n${handler(\"POST\", \"({ request }: { request: Request }) => handleSession(request, has)\")}`);\n writeFileSync(join(gen, \"props.ts\"), `import { handleProps } from \"./server.mjs\";\\nimport { has } from \"./registry\";\\n${handler(\"POST\", \"({ request }: { request: Request }) => handleProps(request, has)\")}`);\n writeFileSync(join(gen, \"health.ts\"), `import { handleHealth } from \"./server.mjs\";\\n${handler(\"GET\", \"() => handleHealth()\")}`);\n const styles = astroGlobalStyles(root)\n .map((file) => `import ${JSON.stringify(relative(gen, file).split(sep).join(\"/\"))};`)\n .join(\"\\n\");\n writeFileSync(join(gen, \"render.astro\"), `---\n${styles}\nimport { renderEntry, renderHeaders } from \"./server.mjs\";\nimport { registry, kinds } from \"./registry\";\nexport const prerender = false;\nconst headers = renderHeaders();\nconst entry = renderEntry(Astro.url.searchParams.get(\"id\"));\nconst Component = entry ? registry[entry.componentId] : undefined;\nconst section = entry ? kinds[entry.componentId] === \"section\" : false;\nfor (const [name, value] of Object.entries(headers)) Astro.response.headers.set(name, value);\nif (!entry || !Component) return new Response(\"Not found\", { status: 404, headers });\n---\n<html lang=\"en\" data-bcms-preview-render=\"1\">\n <head><meta charset=\"utf-8\" /><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" /></head>\n <body>{section ? <Component blockId=\"bcms-preview\" overrides={entry.props} page={{}} /> : <Component {...entry.props} />}</body>\n</html>\n`);\n writeFileSync(wrapper, `import user from \"./${configName}\";\nimport node from \"@astrojs/node\";\n\nconst routes = [\"runtime.ts\", \"session.ts\", \"props.ts\", \"render.astro\", \"health.ts\"];\n\nexport default {\n ...user,\n output: \"server\",\n base: ${JSON.stringify(PREVIEW_BASE)},\n adapter: node({ mode: \"standalone\" }),\n integrations: [\n ...(user.integrations ?? []),\n {\n name: \"bettercms-component-preview\",\n hooks: {\n \"astro:config:setup\": ({ injectRoute }) => {\n for (const file of routes) {\n injectRoute({\n pattern: \"/__bcms/\" + file.replace(/\\\\.(ts|astro)$/, \"\"),\n entrypoint: new URL(\"./.bcms-preview/\" + file, import.meta.url),\n prerender: false,\n });\n }\n },\n },\n },\n ],\n};\n`);\n rmSync(join(root, \"dist\"), { recursive: true, force: true });\n run(root, bin(root, \"astro\"), [\"build\", \"--config\", \"astro.config.bcms-preview.mjs\"]);\n } finally {\n rmSync(gen, { recursive: true, force: true });\n rmSync(wrapper, { force: true });\n }\n\n const app = join(out, \"app\");\n mkdirSync(app, { recursive: true });\n cpSync(join(root, \"dist\"), app, { recursive: true });\n cpSync(join(root, \"package.json\"), join(app, \"package.json\"));\n // Astro does not bundle its dependencies, so the server entry needs them on disk.\n cpSync(join(root, \"node_modules\"), join(app, \"node_modules\"), { recursive: true, verbatimSymlinks: true });\n writeFileSync(join(out, \"bcms-runtime.json\"), `${JSON.stringify({ kind: \"node\", dir: \"app\", entry: \"server/entry.mjs\" })}\\n`);\n}\n\nfunction buildNext(root: string, entries: ManifestEntry[], out: string) {\n const appDir = [\"app\", join(\"src\", \"app\")].map((d) => join(root, d)).find((d) => existsSync(d));\n if (!appDir) fail(\"no App Router directory (app/ or src/app/) found\");\n const configName = [\"next.config.mjs\", \"next.config.js\", \"next.config.ts\", \"next.config.cjs\"].find((f) => existsSync(join(root, f)));\n\n // `%5F%5Fbcms` is how a URL segment starting with an underscore is spelled in the App Router: a plain\n // `__bcms` folder is a PRIVATE folder and silently produces no routes at all.\n const gen = join(appDir, \"%5F%5Fbcms\");\n const userConfig = configName ? join(root, configName.replace(\"next.config\", \"next.config.bcms-user\")) : null;\n const wrapperName = configName && configName.endsWith(\".ts\") ? \"next.config.ts\" : \"next.config.mjs\";\n rmSync(gen, { recursive: true, force: true });\n mkdirSync(gen, { recursive: true });\n if (configName && userConfig) renameSync(join(root, configName), userConfig);\n try {\n writeRuntimeLibrary(gen);\n writeFileSync(join(gen, \"registry.ts\"), registrySource(gen, root, entries));\n const route = (name: string, source: string) => {\n mkdirSync(join(gen, name), { recursive: true });\n writeFileSync(join(gen, name, \"route.ts\"), `export const dynamic = \"force-dynamic\";\\n${source}`);\n };\n route(\"runtime\", `import { handleRuntime } from \"../server.mjs\";\\nimport shell from \"../shell\";\\nexport function GET() {\\n return handleRuntime(shell);\\n}\\n`);\n route(\"session\", `import { handleSession } from \"../server.mjs\";\\nimport { has } from \"../registry\";\\nexport function POST(request: Request) {\\n return handleSession(request, has);\\n}\\n`);\n route(\"props\", `import { handleProps } from \"../server.mjs\";\\nimport { has } from \"../registry\";\\nexport function POST(request: Request) {\\n return handleProps(request, has);\\n}\\n`);\n route(\"health\", `import { handleHealth } from \"../server.mjs\";\\nexport function GET() {\\n return handleHealth();\\n}\\n`);\n mkdirSync(join(gen, \"render\"), { recursive: true });\n writeFileSync(join(gen, \"render\", \"page.tsx\"), `import { notFound } from \"next/navigation\";\nimport { renderEntry } from \"../server.mjs\";\nimport { registry, kinds } from \"../registry\";\n\nexport const dynamic = \"force-dynamic\";\n\nexport default async function BetterCMSComponentPreview({ searchParams }: { searchParams: Promise<{ id?: string }> }) {\n const { id } = await searchParams;\n const entry = renderEntry(id);\n const Component = entry ? registry[entry.componentId] : undefined;\n if (!entry || !Component) notFound();\n // The marker the runtime page checks before acknowledging: a 404 or an error page never carries it.\n return (\n <>\n {kinds[entry.componentId] === \"section\"\n ? <Component blockId=\"bcms-preview\" overrides={entry.props} page={{}} />\n : <Component {...entry.props} />}\n <template data-bcms-preview-render=\"1\" />\n </>\n );\n}\n`);\n const importUser = userConfig ? `import user from \"./${relative(root, userConfig)}\";` : \"const user = {};\";\n writeFileSync(join(root, wrapperName), `${importUser}\n\n// No frame-ancestors here: next.config headers are fixed at build time, and the dashboard origin the\n// render frame must allow is runtime configuration. The platform's proxy sets it for this whole prefix.\nconst RENDER_HEADERS = [\n { key: \"referrer-policy\", value: \"no-referrer\" },\n { key: \"cache-control\", value: \"no-store\" },\n];\n\nexport default async function betterCMSComponentPreviewConfig(phase, context) {\n const resolved = typeof user === \"function\" ? await user(phase, context) : user;\n const userHeaders = resolved.headers;\n return {\n ...resolved,\n output: \"standalone\",\n basePath: ${JSON.stringify(PREVIEW_BASE)},\n async headers() {\n const own = typeof userHeaders === \"function\" ? await userHeaders() : [];\n return [...own, { source: \"/__bcms/render\", headers: RENDER_HEADERS }];\n },\n };\n}\n`);\n rmSync(join(root, \".next\"), { recursive: true, force: true });\n run(root, bin(root, \"next\"), [\"build\"]);\n } finally {\n rmSync(gen, { recursive: true, force: true });\n rmSync(join(root, wrapperName), { force: true });\n if (configName && userConfig && existsSync(userConfig)) renameSync(userConfig, join(root, configName));\n }\n\n const standalone = join(root, \".next\", \"standalone\");\n if (!existsSync(join(standalone, \"server.js\"))) fail(\"next build produced no standalone server\");\n const app = join(out, \"app\");\n mkdirSync(app, { recursive: true });\n cpSync(standalone, app, { recursive: true, verbatimSymlinks: true });\n if (existsSync(join(root, \".next\", \"static\"))) cpSync(join(root, \".next\", \"static\"), join(app, \".next\", \"static\"), { recursive: true });\n if (existsSync(join(root, \"public\"))) cpSync(join(root, \"public\"), join(app, \"public\"), { recursive: true });\n writeFileSync(join(out, \"bcms-runtime.json\"), `${JSON.stringify({ kind: \"node\", dir: \"app\", entry: \"server.js\" })}\\n`);\n}\n\nexport function buildPreviewRuntime(input: { root: string; manifestPath: string; out: string }) {\n const root = resolve(input.root);\n const out = resolve(input.out);\n const entries = validateManifest(root, readJson<Manifest>(resolve(input.manifestPath)));\n const framework = detectFramework(root);\n\n rmSync(out, { recursive: true, force: true });\n mkdirSync(out, { recursive: true });\n const restore = snapshot(root, MUTATED_BY_BUILD);\n try {\n if (framework === \"astro\") buildAstro(root, entries, out);\n else buildNext(root, entries, out);\n } finally {\n restore();\n }\n return {\n framework,\n out,\n components: entries.map((e) => e.id),\n kinds: Object.fromEntries(entries.map((e) => [e.id, e.source.kind ?? \"file\"])) as Record<string, SourceKind>,\n };\n}\n","/**\n * `bcms-preview validate` — validates one component in CI with nothing configured in the repository.\n *\n * Run by `.github/workflows/bcms-component-validation.yml`, which BetterCMS commits and dispatches. In\n * order: build a preview runtime from the app as it is, render the component with its default props in a\n * real browser at every native viewport, check brand tokens and the console, package the runtime — and only\n * then claim the request, upload the bundle the platform will serve previews from, and complete it.\n *\n * 🔴 NOTHING FAILS SILENTLY. A component whose checks fail is still COMPLETED — failed evidence is a\n * result the dashboard shows, with the failing checks. Anything that prevents a result (no source file\n * recorded, a build that breaks, a runtime that never starts, no browser) FAILS the request with a named\n * code and the reason, so the panel says what happened instead of waiting for the request to expire.\n */\nimport { spawn, spawnSync, type ChildProcess } from \"node:child_process\";\nimport { createHash, randomBytes } from \"node:crypto\";\nimport { mkdtempSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { createServer } from \"node:net\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { buildPreviewRuntime, CliFailure } from \"./build\";\n\nconst PREVIEW_ROUTE_BASE = \"/__bettercms/component-preview/__bcms\";\nconst RUNTIME_PATH = `${PREVIEW_ROUTE_BASE}/runtime`;\n\ntype Viewport = { name: string; width: number; height: number };\ntype RequestTarget = {\n componentId: string;\n componentVersion: number;\n candidateId: string;\n familyKey: string;\n familyContractHash: string;\n schemaHash: string;\n brandContractHash: string;\n dependenciesHash: string;\n commitSha: string;\n adapterHash: string;\n familyManifestHash: string;\n nativeViewports: Viewport[];\n};\ntype Manifest = {\n components: { id: string; source: { path: string; export: string }; defaultProps: Record<string, unknown> }[];\n brandTokenNames: string[];\n};\n\nclass ValidationFailure extends Error {\n constructor(readonly code: string, message: string) {\n super(message);\n this.name = \"ValidationFailure\";\n }\n}\n\nfunction required(name: string): string {\n const value = process.env[name]?.trim();\n if (!value) throw new CliFailure(`${name} is not set. This command runs inside the BetterCMS component validation workflow.`);\n return value;\n}\n\nconst sha256 = (data: string | Buffer) => createHash(\"sha256\").update(data).digest(\"hex\");\n\nfunction canonical(value: unknown): string {\n if (Array.isArray(value)) return `[${value.map(canonical).join(\",\")}]`;\n if (value && typeof value === \"object\") {\n return `{${Object.keys(value as Record<string, unknown>).sort()\n .map((key) => `${JSON.stringify(key)}:${canonical((value as Record<string, unknown>)[key])}`).join(\",\")}}`;\n }\n return JSON.stringify(value);\n}\n\nfunction freePort(): Promise<number> {\n return new Promise((resolve, reject) => {\n const server = createServer();\n server.once(\"error\", reject);\n server.listen(0, \"127.0.0.1\", () => {\n const address = server.address();\n const port = typeof address === \"object\" && address ? address.port : 0;\n server.close(() => resolve(port));\n });\n });\n}\n\nasync function waitForOk(url: string, timeoutMs: number): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n try {\n if ((await fetch(url)).ok) return true;\n } catch {\n // not up yet\n }\n await new Promise((r) => setTimeout(r, 500));\n }\n return false;\n}\n\n/** Install Chromium for the bundled Playwright. On a Linux CI runner, with its system dependencies. */\nfunction ensureBrowser() {\n const require = createRequire(import.meta.url);\n const cli = join(dirname(require.resolve(\"playwright/package.json\")), \"cli.js\");\n const args = [cli, \"install\", \"chromium\"];\n if (process.platform === \"linux\" && process.env.CI) args.push(\"--with-deps\");\n const result = spawnSync(process.execPath, args, { stdio: \"inherit\" });\n if (result.status !== 0) {\n throw new ValidationFailure(\"COMPONENT_VALIDATION_BROWSER_UNAVAILABLE\", \"A headless browser could not be installed on this runner.\");\n }\n}\n\nasync function renderInBrowser(url: string, viewports: Viewport[], tokenNames: string[], options: { section: boolean }) {\n ensureBrowser();\n const { chromium } = await import(\"playwright\");\n const browser = await chromium.launch();\n try {\n let consoleErrors = 0;\n let runtimeErrors = 0;\n const missingTokens = new Set<string>();\n const results: { name: string; width: number; height: number; status: \"baseline-missing\"; candidateDigest: string }[] = [];\n const problems: string[] = [];\n for (const viewport of viewports) {\n const page = await browser.newPage({ viewport: { width: viewport.width, height: viewport.height } });\n page.on(\"console\", (message) => {\n if (message.type() === \"error\") {\n consoleErrors += 1;\n problems.push(`${viewport.name} console: ${message.text().slice(0, 200)}`);\n }\n });\n page.on(\"pageerror\", (error) => {\n runtimeErrors += 1;\n problems.push(`${viewport.name} error: ${error.message.slice(0, 200)}`);\n });\n const response = await page.goto(url, { waitUntil: \"load\", timeout: 45_000 });\n await page.waitForLoadState(\"networkidle\", { timeout: 15_000 }).catch(() => {});\n const rendered = await page.locator(\"[data-bcms-preview-render]\").count();\n if (!response?.ok() || rendered === 0) {\n runtimeErrors += 1;\n problems.push(`${viewport.name}: the component page did not render (HTTP ${response?.status() ?? \"none\"})`);\n } else if (options.section && (await page.locator(\"[data-bcms-block]\").count()) === 0) {\n // The codemod stamps data-bcms-block on every section root, and the editor resolves a section's\n // fields by walking up to it: a section without one renders but cannot be edited.\n runtimeErrors += 1;\n problems.push(`${viewport.name}: the section rendered without its [data-bcms-block] root`);\n }\n /**\n * A token is MISSING only when the rendered page uses it and it resolves to nothing. `--bcms-*` are\n * guaranteed on pages BetterCMS renders itself, not in a customer's framework build, so asking\n * \"is every token defined?\" would fail every starter while saying nothing about the component. The\n * question worth a failure is \"does this component reference a brand token the app never defines?\"\n * — a component that will render unstyled on the live site. Cross-origin stylesheets cannot be read\n * and are skipped.\n */\n const missing = await page.evaluate((names: string[]) => {\n const referenced = new Set<string>();\n const scan = (text: string) => {\n for (const match of text.matchAll(/var\\(\\s*(--[A-Za-z0-9_-]+)/g)) referenced.add(match[1]!);\n };\n for (const sheet of Array.from(document.styleSheets)) {\n try {\n for (const rule of Array.from(sheet.cssRules)) scan(rule.cssText);\n } catch {\n // cross-origin sheet\n }\n }\n document.querySelectorAll(\"[style]\").forEach((element) => scan(element.getAttribute(\"style\") ?? \"\"));\n const style = getComputedStyle(document.documentElement);\n return names.filter((name) => referenced.has(name) && !style.getPropertyValue(name).trim());\n }, tokenNames);\n for (const token of missing) missingTokens.add(token);\n const png = await page.screenshot({ fullPage: true });\n results.push({\n name: viewport.name,\n width: viewport.width,\n height: viewport.height,\n // No baseline exists for a first validation. The database requires this exact shape for it:\n // no baseline or diff digest, and the check marked as needing review.\n status: \"baseline-missing\",\n candidateDigest: `sha256:${sha256(png)}`,\n });\n await page.close();\n }\n return { results, consoleErrors, runtimeErrors, missingTokens: [...missingTokens].sort(), problems };\n } finally {\n await browser.close();\n }\n}\n\nexport async function validateComponent() {\n const apiUrl = required(\"BCMS_API_URL\");\n const apiKey = required(\"BCMS_API_KEY\");\n const projectId = required(\"BCMS_PROJECT_ID\");\n const requestId = required(\"BCMS_REQUEST_ID\");\n const componentId = required(\"BCMS_COMPONENT_ID\");\n const commitSha = required(\"BCMS_COMMIT_SHA\");\n const familyKey = required(\"BCMS_FAMILY_KEY\");\n const previewOrigin = required(\"BCMS_PREVIEW_ORIGIN\");\n const nativeViewports = JSON.parse(required(\"BCMS_NATIVE_VIEWPORTS\")) as Viewport[];\n\n const api = async <T>(path: string, init: { method?: string; body?: unknown; claim?: string } = {}): Promise<T> => {\n const response = await fetch(new URL(path, apiUrl), {\n method: init.method ?? \"GET\",\n headers: {\n authorization: `Bearer ${apiKey}`,\n \"content-type\": \"application/json\",\n ...(init.claim ? { \"x-bcms-component-claim\": init.claim } : {}),\n },\n ...(init.body === undefined ? {} : { body: JSON.stringify(init.body) }),\n });\n const text = await response.text();\n let parsed: { data?: unknown; error?: unknown; message?: unknown } | null = null;\n try {\n parsed = JSON.parse(text);\n } catch {\n parsed = null;\n }\n if (!response.ok) {\n const code = typeof parsed?.error === \"string\" && /^[A-Z][A-Z0-9_]*$/.test(parsed.error) ? parsed.error : `API_HTTP_${response.status}`;\n const detail = typeof parsed?.message === \"string\" ? parsed.message : typeof parsed?.error === \"string\" ? parsed.error : text.slice(0, 300);\n throw new ValidationFailure(code, `${init.method ?? \"GET\"} ${path} answered ${response.status}: ${detail}`);\n }\n return ((parsed && \"data\" in parsed ? parsed.data : parsed) ?? {}) as T;\n };\n\n const claimPath = `/api/v1/projects/${projectId}/component-implementation/implementation-requests/${requestId}`;\n let claim: { request: RequestTarget; claimCapability: string } | null = null;\n /**\n * 🔴 CLAIMED LAST, NOT FIRST. A claim credential lives minutes, and `complete` refuses an expired one.\n * Claiming before a framework build, a browser install and a render meant every real run finished with\n * a credential that had already lapsed — and the request sat \"running\" until it expired. Everything slow\n * happens first; the claim is followed only by an upload and the completion.\n */\n const claimRequest = async () => {\n claim = await api<{ request: RequestTarget; claimCapability: string }>(`${claimPath}/claim`, {\n method: \"POST\",\n body: {\n componentId,\n commitSha,\n adapter: { protocol: \"bcms-component-runtime-v1\", kind: \"project-route\", path: RUNTIME_PATH, familyKey, previewOrigin, nativeViewports },\n providerRunId: required(\"BCMS_RUN_ID\"),\n providerRunAttempt: Number(process.env.BCMS_RUN_ATTEMPT) || 1,\n providerRunUrl: required(\"BCMS_RUN_URL\"),\n workflowRef: required(\"BCMS_WORKFLOW_REF\"),\n // The server caps this at the request's own expiry and at ten minutes.\n credentialExpiresAt: new Date(Date.now() + 10 * 60_000 - 5_000).toISOString(),\n },\n });\n return claim;\n };\n\n const work = mkdtempSync(join(tmpdir(), \"bcms-validate-\"));\n let runtime: ChildProcess | null = null;\n try {\n const manifest = await api<Manifest>(`/api/v1/projects/${projectId}/component-preview/manifest`);\n const entry = manifest.components.find((c) => c.id === componentId);\n if (!entry) {\n throw new ValidationFailure(\n \"COMPONENT_SOURCE_NOT_RECORDED\",\n \"No file is recorded as this component's source. The agent that writes a component records it with set_component_source.\",\n );\n }\n\n const manifestPath = join(work, \"manifest.json\");\n writeFileSync(manifestPath, JSON.stringify({ components: manifest.components.map(({ id, source }) => ({ id, source })) }));\n const out = join(work, \"runtime\");\n let built: ReturnType<typeof buildPreviewRuntime>;\n try {\n built = buildPreviewRuntime({ root: process.cwd(), manifestPath, out });\n } catch (error) {\n throw new ValidationFailure(\"COMPONENT_PREVIEW_BUILD_FAILED\", `The preview build failed: ${(error as Error).message}`);\n }\n\n const runtimeManifest = JSON.parse(readFileSync(join(out, \"bcms-runtime.json\"), \"utf8\")) as { dir: string; entry: string };\n const port = await freePort();\n const validatorKey = randomBytes(32).toString(\"base64url\");\n const local = `http://127.0.0.1:${port}`;\n // 🔴 The customer's code runs in this process tree. It gets no BetterCMS API key.\n const { BCMS_API_KEY: _withheld, ...inherited } = process.env;\n runtime = spawn(process.execPath, [join(out, runtimeManifest.dir, runtimeManifest.entry)], {\n cwd: join(out, runtimeManifest.dir),\n env: {\n ...inherited,\n NODE_ENV: \"production\",\n PORT: String(port),\n HOST: \"127.0.0.1\",\n HOSTNAME: \"127.0.0.1\",\n BCMS_API_URL: apiUrl,\n BCMS_DASHBOARD_ORIGIN: local,\n BCMS_PREVIEW_ORIGIN: local,\n BCMS_PREVIEW_VALIDATOR_KEY: validatorKey,\n },\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n /**\n * The app's own server errors (`TypeError: Cannot read properties of undefined`) are the real reason a\n * render fails — the browser only sees \"500\". Still echoed to the CI log; the first few are kept for the\n * evidence so the panel can say what broke.\n */\n const serverErrors: string[] = [];\n const collect = (stream: NodeJS.WriteStream) => (chunk: Buffer) => {\n stream.write(chunk);\n for (const line of chunk.toString(\"utf8\").split(\"\\n\")) {\n const clean = line.replace(/\\x1b\\[[0-9;]*m/g, \"\").trim();\n if (serverErrors.length < 5 && /\\b(error|exception)\\b/i.test(clean)) serverErrors.push(clean.slice(0, 200));\n }\n };\n runtime.stdout?.on(\"data\", collect(process.stdout));\n runtime.stderr?.on(\"data\", collect(process.stderr));\n if (!(await waitForOk(`${local}${PREVIEW_ROUTE_BASE}/health`, 60_000))) {\n throw new ValidationFailure(\"COMPONENT_PREVIEW_RUNTIME_DID_NOT_START\", \"The preview runtime did not start within 60 seconds.\");\n }\n\n const stored = await fetch(`${local}${PREVIEW_ROUTE_BASE}/props`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"x-bcms-validator-key\": validatorKey },\n body: JSON.stringify({ componentId, props: entry.defaultProps }),\n });\n if (!stored.ok) {\n throw new ValidationFailure(\"COMPONENT_PREVIEW_RUNTIME_REFUSED\", `The preview runtime refused the component (HTTP ${stored.status}).`);\n }\n const { id } = (await stored.json()) as { id: string };\n\n // The viewports the dispatch declared are exactly the ones the claim records as the adapter's.\n const render = await renderInBrowser(\n `${local}${PREVIEW_ROUTE_BASE}/render?id=${encodeURIComponent(id)}`,\n nativeViewports,\n manifest.brandTokenNames,\n { section: built.kinds[componentId] === \"section\" },\n );\n\n const tarball = join(work, \"bundle.tgz\");\n if (spawnSync(\"tar\", [\"-czf\", tarball, \"-C\", out, \".\"], { stdio: \"inherit\" }).status !== 0) {\n throw new ValidationFailure(\"COMPONENT_PREVIEW_BUNDLE_PACK_FAILED\", \"The preview runtime could not be packaged.\");\n }\n const bytes = readFileSync(tarball);\n runtime.kill();\n runtime = null;\n\n const target = (await claimRequest()).request;\n const checks = {\n brandKit: {\n status: render.missingTokens.length === 0 ? \"passed\" : \"failed\",\n contractHash: target.brandContractHash,\n missingTokens: render.missingTokens,\n },\n runtime: {\n status: render.runtimeErrors === 0 && render.consoleErrors === 0 ? \"passed\" : \"failed\",\n runtimeErrors: render.runtimeErrors,\n consoleErrors: render.consoleErrors,\n // Only on a failure, and bounded: the server's own error lines first (the real cause), then what the\n // browser saw. The database stores them and the panel shows the first one.\n ...(render.runtimeErrors + render.consoleErrors > 0\n ? { problems: [...serverErrors.map((line) => `server: ${line}`), ...render.problems].slice(0, 10).map((line) => line.slice(0, 200)) }\n : {}),\n },\n visual: { status: \"baseline-missing\", reviewRequired: true, viewports: render.results },\n };\n\n // Uploaded before completing: validated evidence pointing at a runtime nobody can start renders nothing.\n const upload = await api<{ uploadUrl: string; uploadKey: string }>(`/api/v1/projects/${projectId}/artifacts/upload-url`, { method: \"POST\" });\n const put = await fetch(upload.uploadUrl, { method: \"PUT\", body: bytes, headers: { \"content-type\": \"application/gzip\" } });\n if (!put.ok) {\n throw new ValidationFailure(\"COMPONENT_PREVIEW_BUNDLE_UPLOAD_FAILED\", `Storage refused the preview bundle (HTTP ${put.status}).`);\n }\n await api(`/api/v1/projects/${projectId}/component-preview/bundles`, {\n method: \"POST\",\n body: { commitSha: target.commitSha, uploadKey: upload.uploadKey, checksum: `sha256:${sha256(bytes)}`, sizeBytes: bytes.byteLength },\n });\n\n const evidenceDigest = `sha256:${sha256(canonical({ requestId, commitSha: target.commitSha, checks }))}`;\n await api(`${claimPath}/complete`, {\n method: \"POST\",\n claim: claim!.claimCapability,\n body: {\n componentId: target.componentId,\n candidateId: target.candidateId,\n componentVersion: target.componentVersion,\n familyKey: target.familyKey,\n familyContractHash: target.familyContractHash,\n schemaHash: target.schemaHash,\n brandContractHash: target.brandContractHash,\n dependenciesHash: target.dependenciesHash,\n commitSha: target.commitSha,\n adapterHash: target.adapterHash,\n familyManifestHash: target.familyManifestHash,\n nativeViewports: target.nativeViewports,\n checks,\n evidenceDigest,\n },\n });\n\n const passed = checks.brandKit.status === \"passed\" && checks.runtime.status === \"passed\";\n console.log(`bcms-preview: validation ${passed ? \"PASSED\" : \"FAILED\"} for ${componentId}`);\n if (!passed) {\n if (render.missingTokens.length) console.log(` brand tokens used but not defined: ${render.missingTokens.join(\", \")}`);\n for (const problem of render.problems) console.log(` ${problem}`);\n }\n } catch (error) {\n const code = error instanceof ValidationFailure ? error.code : \"COMPONENT_VALIDATION_FAILED\";\n const message = (error as Error).message.slice(0, 2000);\n // A failure before the claim is still reported: claim, then fail at once, so the dashboard names the\n // reason instead of showing \"running\" until the request expires.\n const reported = claim ?? await claimRequest().catch((claimError) => {\n console.error(`bcms-preview: could not claim the request to report the failure: ${(claimError as Error).message}`);\n return null;\n });\n if (reported) {\n await api(`${claimPath}/fail`, {\n method: \"POST\",\n claim: reported.claimCapability,\n body: { componentId, errorCode: code, errorMessage: message },\n }).catch((reportError) => console.error(`bcms-preview: could not report the failure: ${(reportError as Error).message}`));\n }\n throw new CliFailure(`${code}: ${message}`);\n } finally {\n runtime?.kill();\n rmSync(work, { recursive: true, force: true });\n }\n}\n","/**\n * bcms-preview\n *\n * bcms-preview build --manifest <file> --out <dir> [--cwd <dir>]\n * bcms-preview validate (in CI; configured entirely by BCMS_* environment variables)\n */\nimport { buildPreviewRuntime, CliFailure } from \"./build\";\nimport { validateComponent } from \"./validate\";\n\nfunction arg(name: string): string | undefined {\n const index = process.argv.indexOf(`--${name}`);\n return index === -1 ? undefined : process.argv[index + 1];\n}\n\nasync function main() {\n const command = process.argv[2];\n if (command === \"build\") {\n const manifestPath = arg(\"manifest\");\n const out = arg(\"out\");\n if (!manifestPath || !out) throw new CliFailure(\"usage: bcms-preview build --manifest <file> --out <dir> [--cwd <dir>]\");\n console.log(JSON.stringify(buildPreviewRuntime({ root: arg(\"cwd\") ?? process.cwd(), manifestPath, out })));\n return;\n }\n if (command === \"validate\") {\n await validateComponent();\n return;\n }\n throw new CliFailure(\"usage: bcms-preview <build|validate>\");\n}\n\n/**\n * One handler for every failure, and no `process.exit`: writes to a piped stderr are asynchronous, so\n * exiting right after the write dropped the message and CI showed a failed step with no reason.\n */\nmain().catch((error) => {\n console.error(`bcms-preview: ${error instanceof CliFailure ? error.message : (error as Error).stack ?? String(error)}`);\n process.exitCode = 1;\n});\n"],"mappings":"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","names":["require","spawnSync","readFileSync","rmSync","writeFileSync","createRequire","dirname","join","resolve","require","createRequire","join","dirname","spawnSync","writeFileSync","id","readFileSync","rmSync"]}
|
package/package.json
CHANGED