@agent-scope/cli 1.16.0 → 1.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +236 -120
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +191 -81
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +193 -83
- package/dist/index.js.map +1 -1
- package/package.json +7 -6
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// src/program.ts
|
|
4
4
|
import { readFileSync as readFileSync11 } from "fs";
|
|
5
5
|
import { generateTest, loadTrace } from "@agent-scope/playwright";
|
|
6
|
-
import { Command as
|
|
6
|
+
import { Command as Command10 } from "commander";
|
|
7
7
|
|
|
8
8
|
// src/browser.ts
|
|
9
9
|
import { writeFileSync } from "fs";
|
|
@@ -1174,9 +1174,9 @@ function createRL() {
|
|
|
1174
1174
|
});
|
|
1175
1175
|
}
|
|
1176
1176
|
async function ask(rl, question) {
|
|
1177
|
-
return new Promise((
|
|
1177
|
+
return new Promise((resolve17) => {
|
|
1178
1178
|
rl.question(question, (answer) => {
|
|
1179
|
-
|
|
1179
|
+
resolve17(answer.trim());
|
|
1180
1180
|
});
|
|
1181
1181
|
});
|
|
1182
1182
|
}
|
|
@@ -1326,7 +1326,7 @@ function createInitCommand() {
|
|
|
1326
1326
|
|
|
1327
1327
|
// src/instrument/renders.ts
|
|
1328
1328
|
import { resolve as resolve7 } from "path";
|
|
1329
|
-
import { BrowserPool as
|
|
1329
|
+
import { BrowserPool as BrowserPool2 } from "@agent-scope/render";
|
|
1330
1330
|
import { Command as Command5 } from "commander";
|
|
1331
1331
|
|
|
1332
1332
|
// src/manifest-commands.ts
|
|
@@ -1507,6 +1507,7 @@ function createManifestCommand() {
|
|
|
1507
1507
|
|
|
1508
1508
|
// src/instrument/hooks.ts
|
|
1509
1509
|
import { resolve as resolve4 } from "path";
|
|
1510
|
+
import { getBrowserEntryScript as getBrowserEntryScript2 } from "@agent-scope/playwright";
|
|
1510
1511
|
import { Command as Cmd } from "commander";
|
|
1511
1512
|
import { chromium as chromium2 } from "playwright";
|
|
1512
1513
|
var MANIFEST_PATH2 = ".reactscope/manifest.json";
|
|
@@ -1764,6 +1765,7 @@ async function runHooksProfiling(componentName, filePath, props) {
|
|
|
1764
1765
|
try {
|
|
1765
1766
|
const context = await browser.newContext();
|
|
1766
1767
|
const page = await context.newPage();
|
|
1768
|
+
await page.addInitScript({ content: getBrowserEntryScript2() });
|
|
1767
1769
|
const htmlHarness = await buildComponentHarness(filePath, componentName, props, 1280);
|
|
1768
1770
|
await page.setContent(htmlHarness, { waitUntil: "load" });
|
|
1769
1771
|
await page.waitForFunction(
|
|
@@ -2152,30 +2154,12 @@ Available: ${available}`
|
|
|
2152
2154
|
|
|
2153
2155
|
// src/instrument/tree.ts
|
|
2154
2156
|
import { resolve as resolve6 } from "path";
|
|
2155
|
-
import { getBrowserEntryScript as
|
|
2156
|
-
import { BrowserPool as BrowserPool2 } from "@agent-scope/render";
|
|
2157
|
+
import { getBrowserEntryScript as getBrowserEntryScript3 } from "@agent-scope/playwright";
|
|
2157
2158
|
import { Command as Command4 } from "commander";
|
|
2159
|
+
import { chromium as chromium4 } from "playwright";
|
|
2158
2160
|
var MANIFEST_PATH4 = ".reactscope/manifest.json";
|
|
2159
2161
|
var DEFAULT_VIEWPORT_WIDTH = 375;
|
|
2160
2162
|
var DEFAULT_VIEWPORT_HEIGHT = 812;
|
|
2161
|
-
var _pool2 = null;
|
|
2162
|
-
async function getPool2() {
|
|
2163
|
-
if (_pool2 === null) {
|
|
2164
|
-
_pool2 = new BrowserPool2({
|
|
2165
|
-
size: { browsers: 1, pagesPerBrowser: 1 },
|
|
2166
|
-
viewportWidth: DEFAULT_VIEWPORT_WIDTH,
|
|
2167
|
-
viewportHeight: DEFAULT_VIEWPORT_HEIGHT
|
|
2168
|
-
});
|
|
2169
|
-
await _pool2.init();
|
|
2170
|
-
}
|
|
2171
|
-
return _pool2;
|
|
2172
|
-
}
|
|
2173
|
-
async function shutdownPool2() {
|
|
2174
|
-
if (_pool2 !== null) {
|
|
2175
|
-
await _pool2.close();
|
|
2176
|
-
_pool2 = null;
|
|
2177
|
-
}
|
|
2178
|
-
}
|
|
2179
2163
|
function mapNodeType(node) {
|
|
2180
2164
|
if (node.type === "forward_ref") return "forwardRef";
|
|
2181
2165
|
if (node.type === "host") return "host";
|
|
@@ -2387,11 +2371,13 @@ function formatInstrumentTree(root, showProviderDepth = false) {
|
|
|
2387
2371
|
}
|
|
2388
2372
|
async function runInstrumentTree(options) {
|
|
2389
2373
|
const { componentName, filePath } = options;
|
|
2390
|
-
const
|
|
2391
|
-
const slot = await pool.acquire();
|
|
2392
|
-
const { page } = slot;
|
|
2374
|
+
const browser = await chromium4.launch({ headless: true });
|
|
2393
2375
|
try {
|
|
2394
|
-
await
|
|
2376
|
+
const context = await browser.newContext({
|
|
2377
|
+
viewport: { width: DEFAULT_VIEWPORT_WIDTH, height: DEFAULT_VIEWPORT_HEIGHT }
|
|
2378
|
+
});
|
|
2379
|
+
const page = await context.newPage();
|
|
2380
|
+
await page.addInitScript({ content: getBrowserEntryScript3() });
|
|
2395
2381
|
const htmlHarness = await buildComponentHarness(
|
|
2396
2382
|
filePath,
|
|
2397
2383
|
componentName,
|
|
@@ -2444,7 +2430,7 @@ async function runInstrumentTree(options) {
|
|
|
2444
2430
|
}
|
|
2445
2431
|
return instrumentRoot;
|
|
2446
2432
|
} finally {
|
|
2447
|
-
|
|
2433
|
+
await browser.close();
|
|
2448
2434
|
}
|
|
2449
2435
|
}
|
|
2450
2436
|
function createInstrumentTreeCommand() {
|
|
@@ -2484,7 +2470,6 @@ Available: ${available}`
|
|
|
2484
2470
|
providerDepth: opts.providerDepth,
|
|
2485
2471
|
wastedRenders: opts.wastedRenders
|
|
2486
2472
|
});
|
|
2487
|
-
await shutdownPool2();
|
|
2488
2473
|
const fmt2 = resolveFormat2(opts.format);
|
|
2489
2474
|
if (fmt2 === "json") {
|
|
2490
2475
|
process.stdout.write(`${JSON.stringify(instrumentRoot, null, 2)}
|
|
@@ -2495,7 +2480,6 @@ Available: ${available}`
|
|
|
2495
2480
|
`);
|
|
2496
2481
|
}
|
|
2497
2482
|
} catch (err) {
|
|
2498
|
-
await shutdownPool2();
|
|
2499
2483
|
process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
|
|
2500
2484
|
`);
|
|
2501
2485
|
process.exit(1);
|
|
@@ -2815,22 +2799,22 @@ async function replayInteraction2(page, steps) {
|
|
|
2815
2799
|
}
|
|
2816
2800
|
}
|
|
2817
2801
|
}
|
|
2818
|
-
var
|
|
2819
|
-
async function
|
|
2820
|
-
if (
|
|
2821
|
-
|
|
2802
|
+
var _pool2 = null;
|
|
2803
|
+
async function getPool2() {
|
|
2804
|
+
if (_pool2 === null) {
|
|
2805
|
+
_pool2 = new BrowserPool2({
|
|
2822
2806
|
size: { browsers: 1, pagesPerBrowser: 2 },
|
|
2823
2807
|
viewportWidth: 1280,
|
|
2824
2808
|
viewportHeight: 800
|
|
2825
2809
|
});
|
|
2826
|
-
await
|
|
2810
|
+
await _pool2.init();
|
|
2827
2811
|
}
|
|
2828
|
-
return
|
|
2812
|
+
return _pool2;
|
|
2829
2813
|
}
|
|
2830
|
-
async function
|
|
2831
|
-
if (
|
|
2832
|
-
await
|
|
2833
|
-
|
|
2814
|
+
async function shutdownPool2() {
|
|
2815
|
+
if (_pool2 !== null) {
|
|
2816
|
+
await _pool2.close();
|
|
2817
|
+
_pool2 = null;
|
|
2834
2818
|
}
|
|
2835
2819
|
}
|
|
2836
2820
|
async function analyzeRenders(options) {
|
|
@@ -2847,7 +2831,7 @@ Available: ${available}`
|
|
|
2847
2831
|
const rootDir = process.cwd();
|
|
2848
2832
|
const filePath = resolve7(rootDir, descriptor.filePath);
|
|
2849
2833
|
const htmlHarness = await buildComponentHarness(filePath, options.componentName, {}, 1280);
|
|
2850
|
-
const pool = await
|
|
2834
|
+
const pool = await getPool2();
|
|
2851
2835
|
const slot = await pool.acquire();
|
|
2852
2836
|
const { page } = slot;
|
|
2853
2837
|
const startMs = performance.now();
|
|
@@ -2955,7 +2939,7 @@ function createInstrumentRendersCommand() {
|
|
|
2955
2939
|
interaction,
|
|
2956
2940
|
manifestPath: opts.manifest
|
|
2957
2941
|
});
|
|
2958
|
-
await
|
|
2942
|
+
await shutdownPool2();
|
|
2959
2943
|
if (opts.json || !isTTY()) {
|
|
2960
2944
|
process.stdout.write(`${JSON.stringify(result, null, 2)}
|
|
2961
2945
|
`);
|
|
@@ -2964,7 +2948,7 @@ function createInstrumentRendersCommand() {
|
|
|
2964
2948
|
`);
|
|
2965
2949
|
}
|
|
2966
2950
|
} catch (err) {
|
|
2967
|
-
await
|
|
2951
|
+
await shutdownPool2();
|
|
2968
2952
|
process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
|
|
2969
2953
|
`);
|
|
2970
2954
|
process.exit(1);
|
|
@@ -2989,7 +2973,7 @@ import { resolve as resolve8 } from "path";
|
|
|
2989
2973
|
import {
|
|
2990
2974
|
ALL_CONTEXT_IDS,
|
|
2991
2975
|
ALL_STRESS_IDS,
|
|
2992
|
-
BrowserPool as
|
|
2976
|
+
BrowserPool as BrowserPool3,
|
|
2993
2977
|
contextAxis,
|
|
2994
2978
|
RenderMatrix,
|
|
2995
2979
|
SatoriRenderer,
|
|
@@ -2999,22 +2983,22 @@ import {
|
|
|
2999
2983
|
import { Command as Command6 } from "commander";
|
|
3000
2984
|
var MANIFEST_PATH6 = ".reactscope/manifest.json";
|
|
3001
2985
|
var DEFAULT_OUTPUT_DIR = ".reactscope/renders";
|
|
3002
|
-
var
|
|
3003
|
-
async function
|
|
3004
|
-
if (
|
|
3005
|
-
|
|
2986
|
+
var _pool3 = null;
|
|
2987
|
+
async function getPool3(viewportWidth, viewportHeight) {
|
|
2988
|
+
if (_pool3 === null) {
|
|
2989
|
+
_pool3 = new BrowserPool3({
|
|
3006
2990
|
size: { browsers: 1, pagesPerBrowser: 4 },
|
|
3007
2991
|
viewportWidth,
|
|
3008
2992
|
viewportHeight
|
|
3009
2993
|
});
|
|
3010
|
-
await
|
|
2994
|
+
await _pool3.init();
|
|
3011
2995
|
}
|
|
3012
|
-
return
|
|
2996
|
+
return _pool3;
|
|
3013
2997
|
}
|
|
3014
|
-
async function
|
|
3015
|
-
if (
|
|
3016
|
-
await
|
|
3017
|
-
|
|
2998
|
+
async function shutdownPool3() {
|
|
2999
|
+
if (_pool3 !== null) {
|
|
3000
|
+
await _pool3.close();
|
|
3001
|
+
_pool3 = null;
|
|
3018
3002
|
}
|
|
3019
3003
|
}
|
|
3020
3004
|
function buildRenderer(filePath, componentName, viewportWidth, viewportHeight) {
|
|
@@ -3025,7 +3009,7 @@ function buildRenderer(filePath, componentName, viewportWidth, viewportHeight) {
|
|
|
3025
3009
|
_satori: satori,
|
|
3026
3010
|
async renderCell(props, _complexityClass) {
|
|
3027
3011
|
const startMs = performance.now();
|
|
3028
|
-
const pool = await
|
|
3012
|
+
const pool = await getPool3(viewportWidth, viewportHeight);
|
|
3029
3013
|
const htmlHarness = await buildComponentHarness(
|
|
3030
3014
|
filePath,
|
|
3031
3015
|
componentName,
|
|
@@ -3161,7 +3145,7 @@ Available: ${available}`
|
|
|
3161
3145
|
}
|
|
3162
3146
|
}
|
|
3163
3147
|
);
|
|
3164
|
-
await
|
|
3148
|
+
await shutdownPool3();
|
|
3165
3149
|
if (outcome.crashed) {
|
|
3166
3150
|
process.stderr.write(`\u2717 Render failed: ${outcome.error.message}
|
|
3167
3151
|
`);
|
|
@@ -3209,7 +3193,7 @@ Available: ${available}`
|
|
|
3209
3193
|
);
|
|
3210
3194
|
}
|
|
3211
3195
|
} catch (err) {
|
|
3212
|
-
await
|
|
3196
|
+
await shutdownPool3();
|
|
3213
3197
|
process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
|
|
3214
3198
|
`);
|
|
3215
3199
|
process.exit(1);
|
|
@@ -3294,7 +3278,7 @@ Available: ${available}`
|
|
|
3294
3278
|
concurrency
|
|
3295
3279
|
});
|
|
3296
3280
|
const result = await matrix.render();
|
|
3297
|
-
await
|
|
3281
|
+
await shutdownPool3();
|
|
3298
3282
|
process.stderr.write(
|
|
3299
3283
|
`Done. ${result.stats.totalCells} cells, avg ${result.stats.avgRenderTimeMs.toFixed(1)}ms
|
|
3300
3284
|
`
|
|
@@ -3339,7 +3323,7 @@ Available: ${available}`
|
|
|
3339
3323
|
process.stdout.write(formatMatrixCsv(componentName, result));
|
|
3340
3324
|
}
|
|
3341
3325
|
} catch (err) {
|
|
3342
|
-
await
|
|
3326
|
+
await shutdownPool3();
|
|
3343
3327
|
process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
|
|
3344
3328
|
`);
|
|
3345
3329
|
process.exit(1);
|
|
@@ -3436,13 +3420,13 @@ function registerRenderAll(renderCmd) {
|
|
|
3436
3420
|
workers.push(worker());
|
|
3437
3421
|
}
|
|
3438
3422
|
await Promise.all(workers);
|
|
3439
|
-
await
|
|
3423
|
+
await shutdownPool3();
|
|
3440
3424
|
process.stderr.write("\n");
|
|
3441
3425
|
const summary = formatSummaryText(results, outputDir);
|
|
3442
3426
|
process.stderr.write(`${summary}
|
|
3443
3427
|
`);
|
|
3444
3428
|
} catch (err) {
|
|
3445
|
-
await
|
|
3429
|
+
await shutdownPool3();
|
|
3446
3430
|
process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
|
|
3447
3431
|
`);
|
|
3448
3432
|
process.exit(1);
|
|
@@ -3488,29 +3472,29 @@ function createRenderCommand() {
|
|
|
3488
3472
|
import { existsSync as existsSync6, mkdirSync as mkdirSync4, rmSync, writeFileSync as writeFileSync6 } from "fs";
|
|
3489
3473
|
import { resolve as resolve9 } from "path";
|
|
3490
3474
|
import { generateManifest as generateManifest3 } from "@agent-scope/manifest";
|
|
3491
|
-
import { BrowserPool as
|
|
3475
|
+
import { BrowserPool as BrowserPool4, safeRender as safeRender3 } from "@agent-scope/render";
|
|
3492
3476
|
import { ComplianceEngine as ComplianceEngine2, TokenResolver as TokenResolver2 } from "@agent-scope/tokens";
|
|
3493
3477
|
var DEFAULT_BASELINE_DIR = ".reactscope/baseline";
|
|
3494
|
-
var
|
|
3495
|
-
async function
|
|
3496
|
-
if (
|
|
3497
|
-
|
|
3478
|
+
var _pool4 = null;
|
|
3479
|
+
async function getPool4(viewportWidth, viewportHeight) {
|
|
3480
|
+
if (_pool4 === null) {
|
|
3481
|
+
_pool4 = new BrowserPool4({
|
|
3498
3482
|
size: { browsers: 1, pagesPerBrowser: 4 },
|
|
3499
3483
|
viewportWidth,
|
|
3500
3484
|
viewportHeight
|
|
3501
3485
|
});
|
|
3502
|
-
await
|
|
3486
|
+
await _pool4.init();
|
|
3503
3487
|
}
|
|
3504
|
-
return
|
|
3488
|
+
return _pool4;
|
|
3505
3489
|
}
|
|
3506
|
-
async function
|
|
3507
|
-
if (
|
|
3508
|
-
await
|
|
3509
|
-
|
|
3490
|
+
async function shutdownPool4() {
|
|
3491
|
+
if (_pool4 !== null) {
|
|
3492
|
+
await _pool4.close();
|
|
3493
|
+
_pool4 = null;
|
|
3510
3494
|
}
|
|
3511
3495
|
}
|
|
3512
3496
|
async function renderComponent2(filePath, componentName, props, viewportWidth, viewportHeight) {
|
|
3513
|
-
const pool = await
|
|
3497
|
+
const pool = await getPool4(viewportWidth, viewportHeight);
|
|
3514
3498
|
const htmlHarness = await buildComponentHarness(filePath, componentName, props, viewportWidth);
|
|
3515
3499
|
const slot = await pool.acquire();
|
|
3516
3500
|
const { page } = slot;
|
|
@@ -3760,7 +3744,7 @@ async function runBaseline(options = {}) {
|
|
|
3760
3744
|
workers.push(worker());
|
|
3761
3745
|
}
|
|
3762
3746
|
await Promise.all(workers);
|
|
3763
|
-
await
|
|
3747
|
+
await shutdownPool4();
|
|
3764
3748
|
if (isTTY()) {
|
|
3765
3749
|
process.stderr.write("\n");
|
|
3766
3750
|
}
|
|
@@ -3814,7 +3798,7 @@ function registerBaselineSubCommand(reportCmd) {
|
|
|
3814
3798
|
import { existsSync as existsSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync7 } from "fs";
|
|
3815
3799
|
import { resolve as resolve10 } from "path";
|
|
3816
3800
|
import { generateManifest as generateManifest4 } from "@agent-scope/manifest";
|
|
3817
|
-
import { BrowserPool as
|
|
3801
|
+
import { BrowserPool as BrowserPool5, safeRender as safeRender4 } from "@agent-scope/render";
|
|
3818
3802
|
import { ComplianceEngine as ComplianceEngine3, TokenResolver as TokenResolver3 } from "@agent-scope/tokens";
|
|
3819
3803
|
var DEFAULT_BASELINE_DIR2 = ".reactscope/baseline";
|
|
3820
3804
|
function loadBaselineCompliance(baselineDir) {
|
|
@@ -3828,26 +3812,26 @@ function loadBaselineRenderJson2(baselineDir, componentName) {
|
|
|
3828
3812
|
if (!existsSync7(jsonPath)) return null;
|
|
3829
3813
|
return JSON.parse(readFileSync6(jsonPath, "utf-8"));
|
|
3830
3814
|
}
|
|
3831
|
-
var
|
|
3832
|
-
async function
|
|
3833
|
-
if (
|
|
3834
|
-
|
|
3815
|
+
var _pool5 = null;
|
|
3816
|
+
async function getPool5(viewportWidth, viewportHeight) {
|
|
3817
|
+
if (_pool5 === null) {
|
|
3818
|
+
_pool5 = new BrowserPool5({
|
|
3835
3819
|
size: { browsers: 1, pagesPerBrowser: 4 },
|
|
3836
3820
|
viewportWidth,
|
|
3837
3821
|
viewportHeight
|
|
3838
3822
|
});
|
|
3839
|
-
await
|
|
3823
|
+
await _pool5.init();
|
|
3840
3824
|
}
|
|
3841
|
-
return
|
|
3825
|
+
return _pool5;
|
|
3842
3826
|
}
|
|
3843
|
-
async function
|
|
3844
|
-
if (
|
|
3845
|
-
await
|
|
3846
|
-
|
|
3827
|
+
async function shutdownPool5() {
|
|
3828
|
+
if (_pool5 !== null) {
|
|
3829
|
+
await _pool5.close();
|
|
3830
|
+
_pool5 = null;
|
|
3847
3831
|
}
|
|
3848
3832
|
}
|
|
3849
3833
|
async function renderComponent3(filePath, componentName, props, viewportWidth, viewportHeight) {
|
|
3850
|
-
const pool = await
|
|
3834
|
+
const pool = await getPool5(viewportWidth, viewportHeight);
|
|
3851
3835
|
const htmlHarness = await buildComponentHarness(filePath, componentName, props, viewportWidth);
|
|
3852
3836
|
const slot = await pool.acquire();
|
|
3853
3837
|
const { page } = slot;
|
|
@@ -4096,7 +4080,7 @@ async function runDiff(options = {}) {
|
|
|
4096
4080
|
}
|
|
4097
4081
|
await Promise.all(workers);
|
|
4098
4082
|
}
|
|
4099
|
-
await
|
|
4083
|
+
await shutdownPool5();
|
|
4100
4084
|
if (isTTY() && total > 0) {
|
|
4101
4085
|
process.stderr.write("\n");
|
|
4102
4086
|
}
|
|
@@ -4702,9 +4686,140 @@ function buildStructuredReport(report) {
|
|
|
4702
4686
|
};
|
|
4703
4687
|
}
|
|
4704
4688
|
|
|
4689
|
+
// src/site-commands.ts
|
|
4690
|
+
import { createReadStream, existsSync as existsSync9, statSync } from "fs";
|
|
4691
|
+
import { createServer } from "http";
|
|
4692
|
+
import { extname, join as join3, resolve as resolve12 } from "path";
|
|
4693
|
+
import { buildSite } from "@agent-scope/site";
|
|
4694
|
+
import { Command as Command7 } from "commander";
|
|
4695
|
+
var MIME_TYPES = {
|
|
4696
|
+
".html": "text/html; charset=utf-8",
|
|
4697
|
+
".css": "text/css; charset=utf-8",
|
|
4698
|
+
".js": "application/javascript; charset=utf-8",
|
|
4699
|
+
".json": "application/json; charset=utf-8",
|
|
4700
|
+
".png": "image/png",
|
|
4701
|
+
".jpg": "image/jpeg",
|
|
4702
|
+
".jpeg": "image/jpeg",
|
|
4703
|
+
".svg": "image/svg+xml",
|
|
4704
|
+
".ico": "image/x-icon"
|
|
4705
|
+
};
|
|
4706
|
+
function registerBuild(siteCmd) {
|
|
4707
|
+
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(
|
|
4708
|
+
async (opts) => {
|
|
4709
|
+
try {
|
|
4710
|
+
const inputDir = resolve12(process.cwd(), opts.input);
|
|
4711
|
+
const outputDir = resolve12(process.cwd(), opts.output);
|
|
4712
|
+
if (!existsSync9(inputDir)) {
|
|
4713
|
+
throw new Error(
|
|
4714
|
+
`Input directory not found: ${inputDir}
|
|
4715
|
+
Run \`scope manifest generate\` and \`scope render\` first.`
|
|
4716
|
+
);
|
|
4717
|
+
}
|
|
4718
|
+
const manifestPath = join3(inputDir, "manifest.json");
|
|
4719
|
+
if (!existsSync9(manifestPath)) {
|
|
4720
|
+
throw new Error(
|
|
4721
|
+
`Manifest not found at ${manifestPath}
|
|
4722
|
+
Run \`scope manifest generate\` first.`
|
|
4723
|
+
);
|
|
4724
|
+
}
|
|
4725
|
+
process.stderr.write(`Building site from ${inputDir}\u2026
|
|
4726
|
+
`);
|
|
4727
|
+
await buildSite({
|
|
4728
|
+
inputDir,
|
|
4729
|
+
outputDir,
|
|
4730
|
+
basePath: opts.basePath,
|
|
4731
|
+
...opts.compliance !== void 0 && {
|
|
4732
|
+
compliancePath: resolve12(process.cwd(), opts.compliance)
|
|
4733
|
+
},
|
|
4734
|
+
title: opts.title
|
|
4735
|
+
});
|
|
4736
|
+
process.stderr.write(`Site written to ${outputDir}
|
|
4737
|
+
`);
|
|
4738
|
+
process.stdout.write(`${outputDir}
|
|
4739
|
+
`);
|
|
4740
|
+
} catch (err) {
|
|
4741
|
+
process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
|
|
4742
|
+
`);
|
|
4743
|
+
process.exit(1);
|
|
4744
|
+
}
|
|
4745
|
+
}
|
|
4746
|
+
);
|
|
4747
|
+
}
|
|
4748
|
+
function registerServe(siteCmd) {
|
|
4749
|
+
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) => {
|
|
4750
|
+
try {
|
|
4751
|
+
const port = Number.parseInt(opts.port, 10);
|
|
4752
|
+
if (Number.isNaN(port) || port < 1 || port > 65535) {
|
|
4753
|
+
throw new Error(`Invalid port: ${opts.port}`);
|
|
4754
|
+
}
|
|
4755
|
+
const serveDir = resolve12(process.cwd(), opts.dir);
|
|
4756
|
+
if (!existsSync9(serveDir)) {
|
|
4757
|
+
throw new Error(
|
|
4758
|
+
`Serve directory not found: ${serveDir}
|
|
4759
|
+
Run \`scope site build\` first.`
|
|
4760
|
+
);
|
|
4761
|
+
}
|
|
4762
|
+
const server = createServer((req, res) => {
|
|
4763
|
+
const rawUrl = req.url ?? "/";
|
|
4764
|
+
const urlPath = decodeURIComponent(rawUrl.split("?")[0] ?? "/");
|
|
4765
|
+
const filePath = join3(serveDir, urlPath.endsWith("/") ? `${urlPath}index.html` : urlPath);
|
|
4766
|
+
if (!filePath.startsWith(serveDir)) {
|
|
4767
|
+
res.writeHead(403, { "Content-Type": "text/plain" });
|
|
4768
|
+
res.end("Forbidden");
|
|
4769
|
+
return;
|
|
4770
|
+
}
|
|
4771
|
+
if (existsSync9(filePath) && statSync(filePath).isFile()) {
|
|
4772
|
+
const ext = extname(filePath).toLowerCase();
|
|
4773
|
+
const contentType = MIME_TYPES[ext] ?? "application/octet-stream";
|
|
4774
|
+
res.writeHead(200, { "Content-Type": contentType });
|
|
4775
|
+
createReadStream(filePath).pipe(res);
|
|
4776
|
+
return;
|
|
4777
|
+
}
|
|
4778
|
+
const htmlPath = `${filePath}.html`;
|
|
4779
|
+
if (existsSync9(htmlPath) && statSync(htmlPath).isFile()) {
|
|
4780
|
+
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
4781
|
+
createReadStream(htmlPath).pipe(res);
|
|
4782
|
+
return;
|
|
4783
|
+
}
|
|
4784
|
+
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
4785
|
+
res.end(`Not found: ${urlPath}`);
|
|
4786
|
+
});
|
|
4787
|
+
server.listen(port, () => {
|
|
4788
|
+
process.stderr.write(`Scope site running at http://localhost:${port}
|
|
4789
|
+
`);
|
|
4790
|
+
process.stderr.write(`Serving ${serveDir}
|
|
4791
|
+
`);
|
|
4792
|
+
process.stderr.write("Press Ctrl+C to stop.\n");
|
|
4793
|
+
});
|
|
4794
|
+
server.on("error", (err) => {
|
|
4795
|
+
if (err.code === "EADDRINUSE") {
|
|
4796
|
+
process.stderr.write(`Error: Port ${port} is already in use.
|
|
4797
|
+
`);
|
|
4798
|
+
} else {
|
|
4799
|
+
process.stderr.write(`Server error: ${err.message}
|
|
4800
|
+
`);
|
|
4801
|
+
}
|
|
4802
|
+
process.exit(1);
|
|
4803
|
+
});
|
|
4804
|
+
} catch (err) {
|
|
4805
|
+
process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
|
|
4806
|
+
`);
|
|
4807
|
+
process.exit(1);
|
|
4808
|
+
}
|
|
4809
|
+
});
|
|
4810
|
+
}
|
|
4811
|
+
function createSiteCommand() {
|
|
4812
|
+
const siteCmd = new Command7("site").description(
|
|
4813
|
+
"Build and serve the static component gallery site"
|
|
4814
|
+
);
|
|
4815
|
+
registerBuild(siteCmd);
|
|
4816
|
+
registerServe(siteCmd);
|
|
4817
|
+
return siteCmd;
|
|
4818
|
+
}
|
|
4819
|
+
|
|
4705
4820
|
// src/tokens/commands.ts
|
|
4706
|
-
import { existsSync as
|
|
4707
|
-
import { resolve as
|
|
4821
|
+
import { existsSync as existsSync12, readFileSync as readFileSync10 } from "fs";
|
|
4822
|
+
import { resolve as resolve16 } from "path";
|
|
4708
4823
|
import {
|
|
4709
4824
|
parseTokenFileSync as parseTokenFileSync2,
|
|
4710
4825
|
TokenParseError,
|
|
@@ -4712,19 +4827,19 @@ import {
|
|
|
4712
4827
|
TokenValidationError,
|
|
4713
4828
|
validateTokenFile
|
|
4714
4829
|
} from "@agent-scope/tokens";
|
|
4715
|
-
import { Command as
|
|
4830
|
+
import { Command as Command9 } from "commander";
|
|
4716
4831
|
|
|
4717
4832
|
// src/tokens/compliance.ts
|
|
4718
|
-
import { existsSync as
|
|
4719
|
-
import { resolve as
|
|
4833
|
+
import { existsSync as existsSync10, readFileSync as readFileSync8 } from "fs";
|
|
4834
|
+
import { resolve as resolve13 } from "path";
|
|
4720
4835
|
import {
|
|
4721
4836
|
ComplianceEngine as ComplianceEngine4,
|
|
4722
4837
|
TokenResolver as TokenResolver4
|
|
4723
4838
|
} from "@agent-scope/tokens";
|
|
4724
4839
|
var DEFAULT_STYLES_PATH = ".reactscope/compliance-styles.json";
|
|
4725
4840
|
function loadStylesFile(stylesPath) {
|
|
4726
|
-
const absPath =
|
|
4727
|
-
if (!
|
|
4841
|
+
const absPath = resolve13(process.cwd(), stylesPath);
|
|
4842
|
+
if (!existsSync10(absPath)) {
|
|
4728
4843
|
throw new Error(
|
|
4729
4844
|
`Compliance styles file not found at ${absPath}.
|
|
4730
4845
|
Run \`scope render all\` first to generate component styles, or use --styles to specify a path.
|
|
@@ -4891,38 +5006,38 @@ function registerCompliance(tokensCmd) {
|
|
|
4891
5006
|
}
|
|
4892
5007
|
|
|
4893
5008
|
// src/tokens/export.ts
|
|
4894
|
-
import { existsSync as
|
|
4895
|
-
import { resolve as
|
|
5009
|
+
import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync9 } from "fs";
|
|
5010
|
+
import { resolve as resolve14 } from "path";
|
|
4896
5011
|
import {
|
|
4897
5012
|
exportTokens,
|
|
4898
5013
|
parseTokenFileSync,
|
|
4899
5014
|
ThemeResolver,
|
|
4900
5015
|
TokenResolver as TokenResolver5
|
|
4901
5016
|
} from "@agent-scope/tokens";
|
|
4902
|
-
import { Command as
|
|
5017
|
+
import { Command as Command8 } from "commander";
|
|
4903
5018
|
var DEFAULT_TOKEN_FILE = "reactscope.tokens.json";
|
|
4904
5019
|
var CONFIG_FILE = "reactscope.config.json";
|
|
4905
5020
|
var SUPPORTED_FORMATS = ["css", "ts", "scss", "tailwind", "flat-json", "figma"];
|
|
4906
5021
|
function resolveTokenFilePath2(fileFlag) {
|
|
4907
5022
|
if (fileFlag !== void 0) {
|
|
4908
|
-
return
|
|
5023
|
+
return resolve14(process.cwd(), fileFlag);
|
|
4909
5024
|
}
|
|
4910
|
-
const configPath =
|
|
4911
|
-
if (
|
|
5025
|
+
const configPath = resolve14(process.cwd(), CONFIG_FILE);
|
|
5026
|
+
if (existsSync11(configPath)) {
|
|
4912
5027
|
try {
|
|
4913
5028
|
const raw = readFileSync9(configPath, "utf-8");
|
|
4914
5029
|
const config = JSON.parse(raw);
|
|
4915
5030
|
if (typeof config === "object" && config !== null && "tokens" in config && typeof config.tokens === "object" && config.tokens !== null && typeof config.tokens?.file === "string") {
|
|
4916
5031
|
const file = config.tokens.file;
|
|
4917
|
-
return
|
|
5032
|
+
return resolve14(process.cwd(), file);
|
|
4918
5033
|
}
|
|
4919
5034
|
} catch {
|
|
4920
5035
|
}
|
|
4921
5036
|
}
|
|
4922
|
-
return
|
|
5037
|
+
return resolve14(process.cwd(), DEFAULT_TOKEN_FILE);
|
|
4923
5038
|
}
|
|
4924
5039
|
function createTokensExportCommand() {
|
|
4925
|
-
return new
|
|
5040
|
+
return new Command8("export").description("Export design tokens to a downstream format").requiredOption("--format <fmt>", `Output format: ${SUPPORTED_FORMATS.join(", ")}`).option("--file <path>", "Path to token file (overrides config)").option("--out <path>", "Write output to file instead of stdout").option("--prefix <prefix>", "CSS/SCSS: prefix for variable names (e.g. 'scope')").option("--selector <selector>", "CSS: custom root selector (default: ':root')").option(
|
|
4926
5041
|
"--theme <name>",
|
|
4927
5042
|
"Include theme overrides for the named theme (applies to css, ts, scss, tailwind, figma)"
|
|
4928
5043
|
).action(
|
|
@@ -4938,7 +5053,7 @@ Supported formats: ${SUPPORTED_FORMATS.join(", ")}
|
|
|
4938
5053
|
const format = opts.format;
|
|
4939
5054
|
try {
|
|
4940
5055
|
const filePath = resolveTokenFilePath2(opts.file);
|
|
4941
|
-
if (!
|
|
5056
|
+
if (!existsSync11(filePath)) {
|
|
4942
5057
|
throw new Error(
|
|
4943
5058
|
`Token file not found at ${filePath}.
|
|
4944
5059
|
Create a reactscope.tokens.json file or use --file to specify a path.`
|
|
@@ -4983,7 +5098,7 @@ Available themes: ${themeNames.join(", ")}`
|
|
|
4983
5098
|
themes: themesMap
|
|
4984
5099
|
});
|
|
4985
5100
|
if (opts.out !== void 0) {
|
|
4986
|
-
const outPath =
|
|
5101
|
+
const outPath = resolve14(process.cwd(), opts.out);
|
|
4987
5102
|
writeFileSync9(outPath, output, "utf-8");
|
|
4988
5103
|
process.stderr.write(`Exported ${tokens.length} tokens to ${outPath}
|
|
4989
5104
|
`);
|
|
@@ -5099,8 +5214,8 @@ ${formatImpactSummary(report)}
|
|
|
5099
5214
|
|
|
5100
5215
|
// src/tokens/preview.ts
|
|
5101
5216
|
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync10 } from "fs";
|
|
5102
|
-
import { resolve as
|
|
5103
|
-
import { BrowserPool as
|
|
5217
|
+
import { resolve as resolve15 } from "path";
|
|
5218
|
+
import { BrowserPool as BrowserPool6, SpriteSheetGenerator } from "@agent-scope/render";
|
|
5104
5219
|
import { ComplianceEngine as ComplianceEngine6, ImpactAnalyzer as ImpactAnalyzer2, TokenResolver as TokenResolver7 } from "@agent-scope/tokens";
|
|
5105
5220
|
var DEFAULT_STYLES_PATH3 = ".reactscope/compliance-styles.json";
|
|
5106
5221
|
var DEFAULT_MANIFEST_PATH = ".reactscope/manifest.json";
|
|
@@ -5115,7 +5230,7 @@ async function renderComponentWithCssOverride(filePath, componentName, cssOverri
|
|
|
5115
5230
|
cssOverride
|
|
5116
5231
|
// injected as <style>
|
|
5117
5232
|
);
|
|
5118
|
-
const pool = new
|
|
5233
|
+
const pool = new BrowserPool6({
|
|
5119
5234
|
size: { browsers: 1, pagesPerBrowser: 1 },
|
|
5120
5235
|
viewportWidth: vpWidth,
|
|
5121
5236
|
viewportHeight: vpHeight
|
|
@@ -5280,8 +5395,8 @@ function registerPreview(tokensCmd) {
|
|
|
5280
5395
|
});
|
|
5281
5396
|
const spriteResult = await generator.generate(matrixResult);
|
|
5282
5397
|
const tokenLabel = tokenPath.replace(/\./g, "-");
|
|
5283
|
-
const outputPath = opts.output ??
|
|
5284
|
-
const outputDir =
|
|
5398
|
+
const outputPath = opts.output ?? resolve15(process.cwd(), DEFAULT_OUTPUT_DIR2, `preview-${tokenLabel}.png`);
|
|
5399
|
+
const outputDir = resolve15(outputPath, "..");
|
|
5285
5400
|
mkdirSync5(outputDir, { recursive: true });
|
|
5286
5401
|
writeFileSync10(outputPath, spriteResult.png);
|
|
5287
5402
|
const useJson = opts.format === "json" || opts.format !== "text" && !isTTY();
|
|
@@ -5342,24 +5457,24 @@ function buildTable2(headers, rows) {
|
|
|
5342
5457
|
}
|
|
5343
5458
|
function resolveTokenFilePath(fileFlag) {
|
|
5344
5459
|
if (fileFlag !== void 0) {
|
|
5345
|
-
return
|
|
5460
|
+
return resolve16(process.cwd(), fileFlag);
|
|
5346
5461
|
}
|
|
5347
|
-
const configPath =
|
|
5348
|
-
if (
|
|
5462
|
+
const configPath = resolve16(process.cwd(), CONFIG_FILE2);
|
|
5463
|
+
if (existsSync12(configPath)) {
|
|
5349
5464
|
try {
|
|
5350
5465
|
const raw = readFileSync10(configPath, "utf-8");
|
|
5351
5466
|
const config = JSON.parse(raw);
|
|
5352
5467
|
if (typeof config === "object" && config !== null && "tokens" in config && typeof config.tokens === "object" && config.tokens !== null && typeof config.tokens?.file === "string") {
|
|
5353
5468
|
const file = config.tokens.file;
|
|
5354
|
-
return
|
|
5469
|
+
return resolve16(process.cwd(), file);
|
|
5355
5470
|
}
|
|
5356
5471
|
} catch {
|
|
5357
5472
|
}
|
|
5358
5473
|
}
|
|
5359
|
-
return
|
|
5474
|
+
return resolve16(process.cwd(), DEFAULT_TOKEN_FILE2);
|
|
5360
5475
|
}
|
|
5361
5476
|
function loadTokens(absPath) {
|
|
5362
|
-
if (!
|
|
5477
|
+
if (!existsSync12(absPath)) {
|
|
5363
5478
|
throw new Error(
|
|
5364
5479
|
`Token file not found at ${absPath}.
|
|
5365
5480
|
Create a reactscope.tokens.json file or use --file to specify a path.`
|
|
@@ -5579,7 +5694,7 @@ function registerValidate(tokensCmd) {
|
|
|
5579
5694
|
).option("--file <path>", "Path to token file (overrides config)").option("--format <fmt>", "Output format: json or text (default: auto-detect)").action((opts) => {
|
|
5580
5695
|
try {
|
|
5581
5696
|
const filePath = resolveTokenFilePath(opts.file);
|
|
5582
|
-
if (!
|
|
5697
|
+
if (!existsSync12(filePath)) {
|
|
5583
5698
|
throw new Error(
|
|
5584
5699
|
`Token file not found at ${filePath}.
|
|
5585
5700
|
Create a reactscope.tokens.json file or use --file to specify a path.`
|
|
@@ -5653,7 +5768,7 @@ function outputValidationResult(filePath, errors, useJson) {
|
|
|
5653
5768
|
}
|
|
5654
5769
|
}
|
|
5655
5770
|
function createTokensCommand() {
|
|
5656
|
-
const tokensCmd = new
|
|
5771
|
+
const tokensCmd = new Command9("tokens").description(
|
|
5657
5772
|
"Query and validate design tokens from a reactscope.tokens.json file"
|
|
5658
5773
|
);
|
|
5659
5774
|
registerGet2(tokensCmd);
|
|
@@ -5670,7 +5785,7 @@ function createTokensCommand() {
|
|
|
5670
5785
|
|
|
5671
5786
|
// src/program.ts
|
|
5672
5787
|
function createProgram(options = {}) {
|
|
5673
|
-
const program2 = new
|
|
5788
|
+
const program2 = new Command10("scope").version(options.version ?? "0.1.0").description("Scope \u2014 React instrumentation toolkit");
|
|
5674
5789
|
program2.command("capture <url>").description("Capture a React component tree from a live URL and output as JSON").option("-o, --output <path>", "Write JSON to file instead of stdout").option("--pretty", "Pretty-print JSON output (default: minified)", false).option("--timeout <ms>", "Max wait time for React to mount (ms)", "10000").option("--wait <ms>", "Additional wait after page load before capture (ms)", "0").action(
|
|
5675
5790
|
async (url, opts) => {
|
|
5676
5791
|
try {
|
|
@@ -5764,6 +5879,7 @@ function createProgram(options = {}) {
|
|
|
5764
5879
|
registerDiffSubCommand(existingReportCmd);
|
|
5765
5880
|
registerPrCommentSubCommand(existingReportCmd);
|
|
5766
5881
|
}
|
|
5882
|
+
program2.addCommand(createSiteCommand());
|
|
5767
5883
|
return program2;
|
|
5768
5884
|
}
|
|
5769
5885
|
|