@agent-scope/cli 1.16.0 → 1.17.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/dist/cli.js +165 -33
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +129 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +131 -4
- package/dist/index.js.map +1 -1
- package/package.json +7 -6
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { existsSync, writeFileSync, readFileSync, mkdirSync, appendFileSync, readdirSync, rmSync } from 'fs';
|
|
2
|
-
import { resolve, join, dirname } from 'path';
|
|
1
|
+
import { existsSync, writeFileSync, readFileSync, mkdirSync, appendFileSync, readdirSync, rmSync, statSync, createReadStream } from 'fs';
|
|
2
|
+
import { resolve, join, extname, dirname } from 'path';
|
|
3
3
|
import { generateManifest } from '@agent-scope/manifest';
|
|
4
4
|
import { SpriteSheetGenerator, safeRender, BrowserPool, ALL_CONTEXT_IDS, contextAxis, stressAxis, ALL_STRESS_IDS, RenderMatrix, SatoriRenderer } from '@agent-scope/render';
|
|
5
5
|
import { TokenResolver, ComplianceEngine, parseTokenFileSync, ThemeResolver, exportTokens, validateTokenFile, TokenValidationError, TokenParseError, ImpactAnalyzer } from '@agent-scope/tokens';
|
|
@@ -9,6 +9,8 @@ import { createRequire } from 'module';
|
|
|
9
9
|
import * as readline from 'readline';
|
|
10
10
|
import { chromium } from 'playwright';
|
|
11
11
|
import { loadTrace, generateTest, getBrowserEntryScript } from '@agent-scope/playwright';
|
|
12
|
+
import { createServer } from 'http';
|
|
13
|
+
import { buildSite } from '@agent-scope/site';
|
|
12
14
|
|
|
13
15
|
// src/ci/commands.ts
|
|
14
16
|
async function buildComponentHarness(filePath, componentName, props, viewportWidth, projectCss) {
|
|
@@ -1107,9 +1109,9 @@ function createRL() {
|
|
|
1107
1109
|
});
|
|
1108
1110
|
}
|
|
1109
1111
|
async function ask(rl, question) {
|
|
1110
|
-
return new Promise((
|
|
1112
|
+
return new Promise((resolve17) => {
|
|
1111
1113
|
rl.question(question, (answer) => {
|
|
1112
|
-
|
|
1114
|
+
resolve17(answer.trim());
|
|
1113
1115
|
});
|
|
1114
1116
|
});
|
|
1115
1117
|
}
|
|
@@ -4609,6 +4611,130 @@ function buildStructuredReport(report) {
|
|
|
4609
4611
|
route: report.route?.pattern ?? null
|
|
4610
4612
|
};
|
|
4611
4613
|
}
|
|
4614
|
+
var MIME_TYPES = {
|
|
4615
|
+
".html": "text/html; charset=utf-8",
|
|
4616
|
+
".css": "text/css; charset=utf-8",
|
|
4617
|
+
".js": "application/javascript; charset=utf-8",
|
|
4618
|
+
".json": "application/json; charset=utf-8",
|
|
4619
|
+
".png": "image/png",
|
|
4620
|
+
".jpg": "image/jpeg",
|
|
4621
|
+
".jpeg": "image/jpeg",
|
|
4622
|
+
".svg": "image/svg+xml",
|
|
4623
|
+
".ico": "image/x-icon"
|
|
4624
|
+
};
|
|
4625
|
+
function registerBuild(siteCmd) {
|
|
4626
|
+
siteCmd.command("build").description("Build a static HTML gallery from .reactscope/ output").option("-i, --input <path>", "Path to .reactscope input directory", ".reactscope").option("-o, --output <path>", "Output directory for generated site", ".reactscope/site").option("--base-path <path>", "Base URL path prefix for subdirectory deployment", "/").option("--compliance <path>", "Path to compliance batch report JSON").option("--title <text>", "Site title", "Scope \u2014 Component Gallery").action(
|
|
4627
|
+
async (opts) => {
|
|
4628
|
+
try {
|
|
4629
|
+
const inputDir = resolve(process.cwd(), opts.input);
|
|
4630
|
+
const outputDir = resolve(process.cwd(), opts.output);
|
|
4631
|
+
if (!existsSync(inputDir)) {
|
|
4632
|
+
throw new Error(
|
|
4633
|
+
`Input directory not found: ${inputDir}
|
|
4634
|
+
Run \`scope manifest generate\` and \`scope render\` first.`
|
|
4635
|
+
);
|
|
4636
|
+
}
|
|
4637
|
+
const manifestPath = join(inputDir, "manifest.json");
|
|
4638
|
+
if (!existsSync(manifestPath)) {
|
|
4639
|
+
throw new Error(
|
|
4640
|
+
`Manifest not found at ${manifestPath}
|
|
4641
|
+
Run \`scope manifest generate\` first.`
|
|
4642
|
+
);
|
|
4643
|
+
}
|
|
4644
|
+
process.stderr.write(`Building site from ${inputDir}\u2026
|
|
4645
|
+
`);
|
|
4646
|
+
await buildSite({
|
|
4647
|
+
inputDir,
|
|
4648
|
+
outputDir,
|
|
4649
|
+
basePath: opts.basePath,
|
|
4650
|
+
...opts.compliance !== void 0 && {
|
|
4651
|
+
compliancePath: resolve(process.cwd(), opts.compliance)
|
|
4652
|
+
},
|
|
4653
|
+
title: opts.title
|
|
4654
|
+
});
|
|
4655
|
+
process.stderr.write(`Site written to ${outputDir}
|
|
4656
|
+
`);
|
|
4657
|
+
process.stdout.write(`${outputDir}
|
|
4658
|
+
`);
|
|
4659
|
+
} catch (err) {
|
|
4660
|
+
process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
|
|
4661
|
+
`);
|
|
4662
|
+
process.exit(1);
|
|
4663
|
+
}
|
|
4664
|
+
}
|
|
4665
|
+
);
|
|
4666
|
+
}
|
|
4667
|
+
function registerServe(siteCmd) {
|
|
4668
|
+
siteCmd.command("serve").description("Serve the built static site locally").option("-p, --port <number>", "Port to listen on", "3000").option("-d, --dir <path>", "Directory to serve", ".reactscope/site").action((opts) => {
|
|
4669
|
+
try {
|
|
4670
|
+
const port = Number.parseInt(opts.port, 10);
|
|
4671
|
+
if (Number.isNaN(port) || port < 1 || port > 65535) {
|
|
4672
|
+
throw new Error(`Invalid port: ${opts.port}`);
|
|
4673
|
+
}
|
|
4674
|
+
const serveDir = resolve(process.cwd(), opts.dir);
|
|
4675
|
+
if (!existsSync(serveDir)) {
|
|
4676
|
+
throw new Error(
|
|
4677
|
+
`Serve directory not found: ${serveDir}
|
|
4678
|
+
Run \`scope site build\` first.`
|
|
4679
|
+
);
|
|
4680
|
+
}
|
|
4681
|
+
const server = createServer((req, res) => {
|
|
4682
|
+
const rawUrl = req.url ?? "/";
|
|
4683
|
+
const urlPath = decodeURIComponent(rawUrl.split("?")[0] ?? "/");
|
|
4684
|
+
const filePath = join(serveDir, urlPath.endsWith("/") ? `${urlPath}index.html` : urlPath);
|
|
4685
|
+
if (!filePath.startsWith(serveDir)) {
|
|
4686
|
+
res.writeHead(403, { "Content-Type": "text/plain" });
|
|
4687
|
+
res.end("Forbidden");
|
|
4688
|
+
return;
|
|
4689
|
+
}
|
|
4690
|
+
if (existsSync(filePath) && statSync(filePath).isFile()) {
|
|
4691
|
+
const ext = extname(filePath).toLowerCase();
|
|
4692
|
+
const contentType = MIME_TYPES[ext] ?? "application/octet-stream";
|
|
4693
|
+
res.writeHead(200, { "Content-Type": contentType });
|
|
4694
|
+
createReadStream(filePath).pipe(res);
|
|
4695
|
+
return;
|
|
4696
|
+
}
|
|
4697
|
+
const htmlPath = `${filePath}.html`;
|
|
4698
|
+
if (existsSync(htmlPath) && statSync(htmlPath).isFile()) {
|
|
4699
|
+
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
4700
|
+
createReadStream(htmlPath).pipe(res);
|
|
4701
|
+
return;
|
|
4702
|
+
}
|
|
4703
|
+
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
4704
|
+
res.end(`Not found: ${urlPath}`);
|
|
4705
|
+
});
|
|
4706
|
+
server.listen(port, () => {
|
|
4707
|
+
process.stderr.write(`Scope site running at http://localhost:${port}
|
|
4708
|
+
`);
|
|
4709
|
+
process.stderr.write(`Serving ${serveDir}
|
|
4710
|
+
`);
|
|
4711
|
+
process.stderr.write("Press Ctrl+C to stop.\n");
|
|
4712
|
+
});
|
|
4713
|
+
server.on("error", (err) => {
|
|
4714
|
+
if (err.code === "EADDRINUSE") {
|
|
4715
|
+
process.stderr.write(`Error: Port ${port} is already in use.
|
|
4716
|
+
`);
|
|
4717
|
+
} else {
|
|
4718
|
+
process.stderr.write(`Server error: ${err.message}
|
|
4719
|
+
`);
|
|
4720
|
+
}
|
|
4721
|
+
process.exit(1);
|
|
4722
|
+
});
|
|
4723
|
+
} catch (err) {
|
|
4724
|
+
process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
|
|
4725
|
+
`);
|
|
4726
|
+
process.exit(1);
|
|
4727
|
+
}
|
|
4728
|
+
});
|
|
4729
|
+
}
|
|
4730
|
+
function createSiteCommand() {
|
|
4731
|
+
const siteCmd = new Command("site").description(
|
|
4732
|
+
"Build and serve the static component gallery site"
|
|
4733
|
+
);
|
|
4734
|
+
registerBuild(siteCmd);
|
|
4735
|
+
registerServe(siteCmd);
|
|
4736
|
+
return siteCmd;
|
|
4737
|
+
}
|
|
4612
4738
|
var DEFAULT_STYLES_PATH = ".reactscope/compliance-styles.json";
|
|
4613
4739
|
function loadStylesFile(stylesPath) {
|
|
4614
4740
|
const absPath = resolve(process.cwd(), stylesPath);
|
|
@@ -5628,6 +5754,7 @@ function createProgram(options = {}) {
|
|
|
5628
5754
|
registerDiffSubCommand(existingReportCmd);
|
|
5629
5755
|
registerPrCommentSubCommand(existingReportCmd);
|
|
5630
5756
|
}
|
|
5757
|
+
program.addCommand(createSiteCommand());
|
|
5631
5758
|
return program;
|
|
5632
5759
|
}
|
|
5633
5760
|
|