@vscode/component-explorer-cli 0.1.1-2 → 0.1.1-21
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/LICENSE +21 -0
- package/README.md +177 -0
- package/SECURITY.md +14 -0
- package/dist/WorktreePool.d.ts +22 -0
- package/dist/WorktreePool.d.ts.map +1 -0
- package/dist/WorktreePool.js +58 -0
- package/dist/WorktreePool.js.map +1 -0
- package/dist/WorktreePool.test.d.ts +2 -0
- package/dist/WorktreePool.test.d.ts.map +1 -0
- package/dist/_virtual/_build-info.js +4 -0
- package/dist/_virtual/_build-info.js.map +1 -0
- package/dist/browserPage.d.ts +5 -0
- package/dist/browserPage.d.ts.map +1 -1
- package/dist/browserPage.js +28 -2
- package/dist/browserPage.js.map +1 -1
- package/dist/commands/acceptCommand.d.ts +2 -1
- package/dist/commands/acceptCommand.d.ts.map +1 -1
- package/dist/commands/acceptCommand.js +15 -8
- package/dist/commands/acceptCommand.js.map +1 -1
- package/dist/commands/checkStabilityCommand.d.ts +12 -0
- package/dist/commands/checkStabilityCommand.d.ts.map +1 -0
- package/dist/commands/checkStabilityCommand.js +84 -0
- package/dist/commands/checkStabilityCommand.js.map +1 -0
- package/dist/commands/compareCommand.d.ts +6 -1
- package/dist/commands/compareCommand.d.ts.map +1 -1
- package/dist/commands/compareCommand.js +64 -71
- package/dist/commands/compareCommand.js.map +1 -1
- package/dist/commands/mcpCommand.d.ts +4 -1
- package/dist/commands/mcpCommand.d.ts.map +1 -1
- package/dist/commands/mcpCommand.js +51 -8
- package/dist/commands/mcpCommand.js.map +1 -1
- package/dist/commands/screenshotCommand.d.ts +9 -2
- package/dist/commands/screenshotCommand.d.ts.map +1 -1
- package/dist/commands/screenshotCommand.js +73 -15
- package/dist/commands/screenshotCommand.js.map +1 -1
- package/dist/commands/serveCommand.d.ts +6 -1
- package/dist/commands/serveCommand.d.ts.map +1 -1
- package/dist/commands/serveCommand.js +104 -23
- package/dist/commands/serveCommand.js.map +1 -1
- package/dist/commands/watchCommand.d.ts +3 -2
- package/dist/commands/watchCommand.d.ts.map +1 -1
- package/dist/commands/watchCommand.js +28 -80
- package/dist/commands/watchCommand.js.map +1 -1
- package/dist/comparison.d.ts +70 -0
- package/dist/comparison.d.ts.map +1 -0
- package/dist/comparison.js +264 -0
- package/dist/comparison.js.map +1 -0
- package/dist/component-explorer-config.schema.json +222 -0
- package/dist/componentExplorer.d.ts +40 -2
- package/dist/componentExplorer.d.ts.map +1 -1
- package/dist/componentExplorer.js +118 -24
- package/dist/componentExplorer.js.map +1 -1
- package/dist/daemon/DaemonContext.d.ts +4 -0
- package/dist/daemon/DaemonContext.d.ts.map +1 -0
- package/dist/daemon/DaemonService.d.ts +146 -21
- package/dist/daemon/DaemonService.d.ts.map +1 -1
- package/dist/daemon/DaemonService.js +620 -123
- package/dist/daemon/DaemonService.js.map +1 -1
- package/dist/daemon/dynamicSessions.test.d.ts +2 -0
- package/dist/daemon/dynamicSessions.test.d.ts.map +1 -0
- package/dist/daemon/lifecycle.d.ts +8 -3
- package/dist/daemon/lifecycle.d.ts.map +1 -1
- package/dist/daemon/lifecycle.js +27 -10
- package/dist/daemon/lifecycle.js.map +1 -1
- package/dist/daemon/pipeClient.d.ts +6 -1
- package/dist/daemon/pipeClient.d.ts.map +1 -1
- package/dist/daemon/pipeClient.js +101 -8
- package/dist/daemon/pipeClient.js.map +1 -1
- package/dist/daemon/pipeServer.d.ts +2 -1
- package/dist/daemon/pipeServer.d.ts.map +1 -1
- package/dist/daemon/pipeServer.js +56 -6
- package/dist/daemon/pipeServer.js.map +1 -1
- package/dist/daemon/types.d.ts +12 -0
- package/dist/daemon/types.d.ts.map +1 -0
- package/dist/daemon/version.d.ts +10 -0
- package/dist/daemon/version.d.ts.map +1 -0
- package/dist/daemon/version.js +17 -0
- package/dist/daemon/version.js.map +1 -0
- package/dist/dependencyInstaller.d.ts +2 -2
- package/dist/dependencyInstaller.d.ts.map +1 -1
- package/dist/dependencyInstaller.js +1 -1
- package/dist/dependencyInstaller.js.map +1 -1
- package/dist/external/vscode-observables/observables/dist/disposables.js +24 -1
- package/dist/external/vscode-observables/observables/dist/disposables.js.map +1 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/commonFacade/deps.js +1 -4
- package/dist/external/vscode-observables/observables/dist/observableInternal/commonFacade/deps.js.map +1 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/index.js +2 -5
- package/dist/external/vscode-observables/observables/dist/observableInternal/index.js.map +1 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/logging/consoleObservableLogger.js +30 -6
- package/dist/external/vscode-observables/observables/dist/observableInternal/logging/consoleObservableLogger.js.map +1 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/observables/baseObservable.js +1 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/observables/baseObservable.js.map +1 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/observables/derived.js +12 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/observables/derived.js.map +1 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/utils/utilsCancellation.js +55 -0
- package/dist/external/vscode-observables/observables/dist/observableInternal/utils/utilsCancellation.js.map +1 -0
- package/dist/formatValue.d.ts +2 -0
- package/dist/formatValue.d.ts.map +1 -0
- package/dist/formatValue.js +96 -0
- package/dist/formatValue.js.map +1 -0
- package/dist/formatValue.test.d.ts +2 -0
- package/dist/formatValue.test.d.ts.map +1 -0
- package/dist/git/gitIndexResolver.d.ts +25 -0
- package/dist/git/gitIndexResolver.d.ts.map +1 -0
- package/dist/git/gitIndexResolver.js +91 -0
- package/dist/git/gitIndexResolver.js.map +1 -0
- package/dist/git/gitIndexResolver.test.d.ts +2 -0
- package/dist/git/gitIndexResolver.test.d.ts.map +1 -0
- package/dist/git/gitService.d.ts +2 -0
- package/dist/git/gitService.d.ts.map +1 -1
- package/dist/git/gitService.js +6 -0
- package/dist/git/gitService.js.map +1 -1
- package/dist/git/gitUtils.js +1 -1
- package/dist/git/gitUtils.js.map +1 -1
- package/dist/git/gitWorktreeManager.d.ts +6 -0
- package/dist/git/gitWorktreeManager.d.ts.map +1 -1
- package/dist/git/gitWorktreeManager.js +42 -13
- package/dist/git/gitWorktreeManager.js.map +1 -1
- package/dist/git/gitWorktreeManager.test.d.ts +2 -0
- package/dist/git/gitWorktreeManager.test.d.ts.map +1 -0
- package/dist/git/testUtils.d.ts +13 -0
- package/dist/git/testUtils.d.ts.map +1 -0
- package/dist/httpServer.d.ts +6 -1
- package/dist/httpServer.d.ts.map +1 -1
- package/dist/httpServer.js +30 -10
- package/dist/httpServer.js.map +1 -1
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +1 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +7 -1
- package/dist/logger.js.map +1 -1
- package/dist/mcp/McpServer.d.ts +47 -4
- package/dist/mcp/McpServer.d.ts.map +1 -1
- package/dist/mcp/McpServer.js +913 -155
- package/dist/mcp/McpServer.js.map +1 -1
- package/dist/mcp/TaskManager.d.ts +28 -0
- package/dist/mcp/TaskManager.d.ts.map +1 -0
- package/dist/mcp/TaskManager.js +54 -0
- package/dist/mcp/TaskManager.js.map +1 -0
- package/dist/packages/simple-api/dist/chunk-3R7GHWBM.js +137 -0
- package/dist/packages/simple-api/dist/chunk-3R7GHWBM.js.map +1 -0
- package/dist/packages/simple-api/dist/chunk-SGBCNXYH.js +24 -0
- package/dist/packages/simple-api/dist/chunk-SGBCNXYH.js.map +1 -0
- package/dist/packages/simple-api/dist/chunk-TAEFVNPN.js +27 -0
- package/dist/packages/simple-api/dist/chunk-TAEFVNPN.js.map +1 -0
- package/dist/packages/simple-api/dist/express.js +104 -0
- package/dist/packages/simple-api/dist/express.js.map +1 -0
- package/dist/resolveProject.d.ts +21 -0
- package/dist/resolveProject.d.ts.map +1 -0
- package/dist/resolveProject.js +39 -0
- package/dist/resolveProject.js.map +1 -0
- package/dist/utils.d.ts +31 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +49 -0
- package/dist/utils.js.map +1 -0
- package/dist/watchConfig.d.ts +52 -9
- package/dist/watchConfig.d.ts.map +1 -1
- package/dist/watchConfig.js +67 -62
- package/dist/watchConfig.js.map +1 -1
- package/package.json +31 -8
- package/dist/external/vscode-observables/observables/dist/observableInternal/logging/debugger/debuggerRpc.js +0 -72
- package/dist/external/vscode-observables/observables/dist/observableInternal/logging/debugger/debuggerRpc.js.map +0 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/logging/debugger/devToolsLogger.js +0 -447
- package/dist/external/vscode-observables/observables/dist/observableInternal/logging/debugger/devToolsLogger.js.map +0 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/logging/debugger/rpc.js +0 -64
- package/dist/external/vscode-observables/observables/dist/observableInternal/logging/debugger/rpc.js.map +0 -1
- package/dist/external/vscode-observables/observables/dist/observableInternal/logging/debugger/utils.js +0 -52
- package/dist/external/vscode-observables/observables/dist/observableInternal/logging/debugger/utils.js.map +0 -1
|
@@ -1,89 +1,82 @@
|
|
|
1
1
|
import { Command, Option } from 'clipanion';
|
|
2
|
-
import
|
|
2
|
+
import * as fs from 'node:fs/promises';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { compareScreenshotsOnDisk, printComparisonToConsole, writeComparisonReport } from '../comparison.js';
|
|
5
|
+
import { ConsoleLogger, verbosityToLogLevel, logBuildInfo } from '../logger.js';
|
|
3
6
|
import { FileSystemStorage } from '../storage.js';
|
|
7
|
+
import { resolveProject } from '../resolveProject.js';
|
|
8
|
+
import { listPngFiles, matchGlob } from '../utils.js';
|
|
4
9
|
|
|
5
10
|
class CompareCommand extends Command {
|
|
6
|
-
static paths = [['compare']];
|
|
11
|
+
static paths = [['screenshot:compare']];
|
|
7
12
|
static usage = Command.Usage({
|
|
8
|
-
description: 'Compare
|
|
13
|
+
description: 'Compare screenshot directories (file-level only)',
|
|
9
14
|
examples: [
|
|
10
|
-
['Compare default directories', '$0 compare'],
|
|
15
|
+
['Compare default directories', '$0 screenshot:compare'],
|
|
16
|
+
['Compare with custom paths', '$0 screenshot:compare --baseline ./golden --current ./actual'],
|
|
17
|
+
['Generate report folder', '$0 screenshot:compare --report ./report'],
|
|
11
18
|
],
|
|
12
19
|
});
|
|
13
20
|
verbose = Option.Counter('-v,--verbose', 0, { description: 'Increase log verbosity (-v debug, -vv trace)' });
|
|
14
|
-
|
|
21
|
+
filter = Option.String('--filter', { required: false, description: 'Filter fixtures by glob pattern' });
|
|
22
|
+
project = Option.String('-p,--project', process.cwd(), { description: 'Project: a directory, vite config file, or component-explorer.json' });
|
|
23
|
+
baseline = Option.String('--baseline', '.screenshots/baseline', { description: 'Baseline screenshots directory' });
|
|
24
|
+
current = Option.String('--current', '.screenshots/current', { description: 'Current screenshots directory' });
|
|
25
|
+
report = Option.String('--report', { required: false, description: 'Output report folder (contains report.json, report.md, and changed screenshots)' });
|
|
26
|
+
failOnLabels = Option.Array('--fail-on-labels', { required: false, description: 'Only fail when fixtures with any of these labels have changes' });
|
|
15
27
|
async execute() {
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const currentData = await storage.read(`current/${file}`);
|
|
33
|
-
if (buffersEqual(baselineData, currentData)) {
|
|
34
|
-
unchanged.push(file);
|
|
35
|
-
}
|
|
36
|
-
else {
|
|
37
|
-
changed.push(file);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
28
|
+
const resolved = await resolveProject(this.project);
|
|
29
|
+
const projectDir = resolved.projectDir;
|
|
30
|
+
const _logger = new ConsoleLogger('compare', this.context.stdout, verbosityToLogLevel(this.verbose));
|
|
31
|
+
logBuildInfo(_logger);
|
|
32
|
+
const baselineDir = path.isAbsolute(this.baseline) ? this.baseline : path.join(projectDir, this.baseline);
|
|
33
|
+
const currentDir = path.isAbsolute(this.current) ? this.current : path.join(projectDir, this.current);
|
|
34
|
+
const baselineStorage = new FileSystemStorage(baselineDir);
|
|
35
|
+
const currentStorage = new FileSystemStorage(currentDir);
|
|
36
|
+
// List all PNG files
|
|
37
|
+
let baselineFiles = await listPngFiles(baselineDir);
|
|
38
|
+
let currentFiles = await listPngFiles(currentDir);
|
|
39
|
+
// Apply filter if specified
|
|
40
|
+
if (this.filter) {
|
|
41
|
+
const filterFn = (file) => matchGlob(file.replace(/\.png$/, ''), this.filter);
|
|
42
|
+
baselineFiles = baselineFiles.filter(filterFn);
|
|
43
|
+
currentFiles = currentFiles.filter(filterFn);
|
|
40
44
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
const currentMetadata = await readFixturesJson(currentDir);
|
|
46
|
+
const baselineMetadata = await readFixturesJson(baselineDir);
|
|
47
|
+
const result = await compareScreenshotsOnDisk({ list: async () => currentFiles, read: (id) => currentStorage.read(id), exists: (id) => currentStorage.exists(id) }, { list: async () => baselineFiles, read: (id) => baselineStorage.read(id), exists: (id) => baselineStorage.exists(id) }, currentFiles, baselineFiles, { currentMetadata, baselineMetadata });
|
|
48
|
+
printComparisonToConsole(result, this.context.stdout);
|
|
49
|
+
if (this.report) {
|
|
50
|
+
const reportDir = path.isAbsolute(this.report) ? this.report : path.join(process.cwd(), this.report);
|
|
51
|
+
await writeComparisonReport({
|
|
52
|
+
reportDir,
|
|
53
|
+
result,
|
|
54
|
+
baselinePath: this.baseline,
|
|
55
|
+
currentPath: this.current,
|
|
56
|
+
getBaselineData: (id) => baselineStorage.read(`${id}.png`),
|
|
57
|
+
getCurrentData: (id) => currentStorage.read(`${id}.png`),
|
|
58
|
+
});
|
|
59
|
+
this.context.stdout.write(`\nReport written to: ${this.report}/\n`);
|
|
45
60
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
if (removed.length > 0) {
|
|
53
|
-
this.context.stdout.write(`Removed (${removed.length}):\n`);
|
|
54
|
-
for (const f of removed) {
|
|
55
|
-
this.context.stdout.write(` - ${f}\n`);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
if (changed.length > 0) {
|
|
59
|
-
this.context.stdout.write(`Changed (${changed.length}):\n`);
|
|
60
|
-
for (const f of changed) {
|
|
61
|
-
this.context.stdout.write(` ~ ${f}\n`);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
if (unchanged.length > 0) {
|
|
65
|
-
this.context.stdout.write(`Unchanged (${unchanged.length}):\n`);
|
|
66
|
-
for (const f of unchanged) {
|
|
67
|
-
this.context.stdout.write(` = ${f}\n`);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
const hasDiffs = added.length > 0 || removed.length > 0 || changed.length > 0;
|
|
71
|
-
if (hasDiffs) {
|
|
72
|
-
this.context.stdout.write('\nDifferences found.\n');
|
|
73
|
-
return 1;
|
|
74
|
-
}
|
|
75
|
-
this.context.stdout.write('\nNo differences.\n');
|
|
76
|
-
return 0;
|
|
61
|
+
const hasDiffs = this.failOnLabels
|
|
62
|
+
? hasChangesWithLabels(result, this.failOnLabels)
|
|
63
|
+
: result.added.length > 0 || result.removed.length > 0 || result.changed.length > 0;
|
|
64
|
+
return hasDiffs ? 1 : 0;
|
|
77
65
|
}
|
|
78
66
|
}
|
|
79
|
-
function
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
67
|
+
function hasChangesWithLabels(result, labels) {
|
|
68
|
+
const labelSet = new Set(labels);
|
|
69
|
+
const hasLabel = (id) => result.fixtures[id]?.labels?.some(l => labelSet.has(l)) ?? false;
|
|
70
|
+
return result.added.some(hasLabel) || result.removed.some(hasLabel) || result.changed.some(hasLabel);
|
|
71
|
+
}
|
|
72
|
+
async function readFixturesJson(dir) {
|
|
73
|
+
try {
|
|
74
|
+
const data = await fs.readFile(path.join(dir, 'fixtures.json'), 'utf-8');
|
|
75
|
+
return JSON.parse(data);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return undefined;
|
|
85
79
|
}
|
|
86
|
-
return true;
|
|
87
80
|
}
|
|
88
81
|
|
|
89
82
|
export { CompareCommand };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compareCommand.js","sources":["../../src/commands/compareCommand.ts"],"sourcesContent":[null],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"compareCommand.js","sources":["../../src/commands/compareCommand.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,10 @@ import { Command } from 'clipanion';
|
|
|
2
2
|
export declare class McpCommand extends Command {
|
|
3
3
|
static paths: string[][];
|
|
4
4
|
static usage: import("clipanion").Usage;
|
|
5
|
-
readonly
|
|
5
|
+
readonly project: string;
|
|
6
|
+
readonly noAutostart: boolean;
|
|
7
|
+
readonly noAutostartHint: string | undefined;
|
|
8
|
+
readonly callTimeout: string | undefined;
|
|
6
9
|
execute(): Promise<void>;
|
|
7
10
|
}
|
|
8
11
|
//# sourceMappingURL=mcpCommand.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcpCommand.d.ts","sourceRoot":"","sources":["../../src/commands/mcpCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"mcpCommand.d.ts","sourceRoot":"","sources":["../../src/commands/mcpCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAO5C,qBAAa,UAAW,SAAQ,OAAO;IACtC,OAAgB,KAAK,aAAa;IAElC,OAAgB,KAAK,4BAMlB;IAEH,QAAQ,CAAC,OAAO,SAA2I;IAC3J,QAAQ,CAAC,WAAW,UAAoH;IACxI,QAAQ,CAAC,eAAe,qBAAyI;IACjK,QAAQ,CAAC,WAAW,qBAAyG;IAEvH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CA4C9B"}
|
|
@@ -1,22 +1,65 @@
|
|
|
1
1
|
import { Command, Option } from 'clipanion';
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
2
|
+
import '../external/vscode-observables/observables/dist/observableInternal/index.js';
|
|
3
|
+
import { observableValue } from '../external/vscode-observables/observables/dist/observableInternal/observables/observableValue.js';
|
|
4
|
+
import '../external/vscode-observables/observables/dist/observableInternal/debugLocation.js';
|
|
5
|
+
import '../external/vscode-observables/observables/dist/observableInternal/observables/derived.js';
|
|
6
|
+
import '../external/vscode-observables/observables/dist/observableInternal/utils/utils.js';
|
|
7
|
+
import '../external/vscode-observables/observables/dist/observableInternal/observables/observableFromEvent.js';
|
|
8
|
+
import { ensureDaemon, tryConnect } from '../daemon/lifecycle.js';
|
|
9
|
+
import { daemonPipeName } from '../daemon/pipeName.js';
|
|
10
|
+
import { DaemonConnection, ComponentExplorerMcpServer } from '../mcp/McpServer.js';
|
|
11
|
+
import { resolveProject } from '../resolveProject.js';
|
|
4
12
|
|
|
5
13
|
class McpCommand extends Command {
|
|
6
14
|
static paths = [['mcp']];
|
|
7
15
|
static usage = Command.Usage({
|
|
8
16
|
description: 'Start an MCP server over stdio. Auto-starts a daemon if not already running.',
|
|
9
17
|
examples: [
|
|
10
|
-
['Start MCP server', '$0 mcp
|
|
18
|
+
['Start MCP server', '$0 mcp --project config.json'],
|
|
19
|
+
['Require existing daemon', '$0 mcp --project config.json --no-daemon-autostart'],
|
|
11
20
|
],
|
|
12
21
|
});
|
|
13
|
-
|
|
22
|
+
project = Option.String('-p,--project,-c', { required: true, description: 'Project: a directory, vite config file, or component-explorer.json' });
|
|
23
|
+
noAutostart = Option.Boolean('--no-daemon-autostart', false, { description: 'Do not auto-start daemon; poll for it instead' });
|
|
24
|
+
noAutostartHint = Option.String('--no-daemon-hint', { description: 'Hint message shown when daemon is not running (used with --no-daemon-autostart)' });
|
|
25
|
+
callTimeout = Option.String('--call-timeout', { description: 'Timeout in seconds for daemon calls (default: 15)' });
|
|
14
26
|
async execute() {
|
|
15
|
-
|
|
16
|
-
|
|
27
|
+
const resolved = await resolveProject(this.project);
|
|
28
|
+
if (resolved.kind !== 'explorerConfig') {
|
|
29
|
+
this.context.stderr.write('Error: mcp requires a component-explorer.json config file.\n');
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const daemonObservable = observableValue('daemon', undefined);
|
|
33
|
+
const mcpClientName = `mcp12-${new Date().toISOString().replace(/[-:]/g, '').replace(/\.\d+Z$/, '')}`;
|
|
34
|
+
let pollFn;
|
|
35
|
+
if (this.noAutostart) {
|
|
36
|
+
const pipeName = daemonPipeName(resolved.configPath);
|
|
37
|
+
pollFn = async () => {
|
|
38
|
+
const client = await tryConnect(pipeName, { clientName: mcpClientName });
|
|
39
|
+
if (client) {
|
|
40
|
+
if (!daemonObservable.get()) {
|
|
41
|
+
daemonObservable.set(new DaemonConnection(client), undefined);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
daemonObservable.set(undefined, undefined);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
await pollFn();
|
|
49
|
+
setInterval(pollFn, 5000);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const daemon = await ensureDaemon(resolved.configPath, { clientName: mcpClientName });
|
|
53
|
+
daemonObservable.set(new DaemonConnection(daemon), undefined);
|
|
54
|
+
}
|
|
17
55
|
// Create and connect the MCP server over stdio
|
|
18
|
-
|
|
19
|
-
|
|
56
|
+
await ComponentExplorerMcpServer.create(daemonObservable, {
|
|
57
|
+
pollFn,
|
|
58
|
+
noAutostartHint: this.noAutostartHint,
|
|
59
|
+
callTimeoutMs: this.callTimeout ? Number(this.callTimeout) * 1000 : undefined,
|
|
60
|
+
});
|
|
61
|
+
// Keep the process alive until the MCP connection closes
|
|
62
|
+
await new Promise(() => { });
|
|
20
63
|
}
|
|
21
64
|
}
|
|
22
65
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcpCommand.js","sources":["../../src/commands/mcpCommand.ts"],"sourcesContent":[null],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mcpCommand.js","sources":["../../src/commands/mcpCommand.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;;;;;;;AAOM,MAAO,UAAW,SAAQ,OAAO,CAAA;IACtC,OAAgB,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AAEjC,IAAA,OAAgB,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;AACrC,QAAA,WAAW,EAAE,8EAA8E;AAC3F,QAAA,QAAQ,EAAE;YACT,CAAC,kBAAkB,EAAE,8BAA8B,CAAC;YACpD,CAAC,yBAAyB,EAAE,oDAAoD,CAAC;AACjF,SAAA;AACD,KAAA,CAAC;AAEO,IAAA,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,oEAAoE,EAAE,CAAC;AACjJ,IAAA,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,uBAAuB,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,+CAA+C,EAAE,CAAC;AAC9H,IAAA,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,kBAAkB,EAAE,EAAE,WAAW,EAAE,iFAAiF,EAAE,CAAC;AACvJ,IAAA,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,EAAE,WAAW,EAAE,mDAAmD,EAAE,CAAC;AAE5H,IAAA,MAAM,OAAO,GAAA;QACZ,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC;AACnD,QAAA,IAAI,QAAQ,CAAC,IAAI,KAAK,gBAAgB,EAAE;YACvC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,8DAA8D,CAAC;YACzF;QACD;QAEA,MAAM,gBAAgB,GAAG,eAAe,CACvC,QAAQ,EACR,SAAS,CACT;QAED,MAAM,aAAa,GAAG,CAAA,MAAA,EAAS,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA,CAAE;AAErG,QAAA,IAAI,MAAyC;AAC7C,QAAA,IAAI,IAAI,CAAC,WAAW,EAAE;YACrB,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC,UAAU,CAAC;YACpD,MAAM,GAAG,YAAW;AACnB,gBAAA,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,QAAQ,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC;gBACxE,IAAI,MAAM,EAAE;AACX,oBAAA,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,EAAE;wBAC5B,gBAAgB,CAAC,GAAG,CAAC,IAAI,gBAAgB,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;oBAC9D;gBACD;qBAAO;AACN,oBAAA,gBAAgB,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC;gBAC3C;AACD,YAAA,CAAC;YACD,MAAM,MAAM,EAAE;AACd,YAAA,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC;QAC1B;aAAO;AACN,YAAA,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC;YACrF,gBAAgB,CAAC,GAAG,CAAC,IAAI,gBAAgB,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;QAC9D;;QAGe,MAAM,0BAA0B,CAAC,MAAM,CAAC,gBAAgB,EAAE;YACxE,MAAM;YACN,eAAe,EAAE,IAAI,CAAC,eAAe;AACrC,YAAA,aAAa,EAAE,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,IAAI,GAAG,SAAS;AAC7E,SAAA;;QAGD,MAAM,IAAI,OAAO,CAAO,MAAK,EAAE,CAAC,CAAC;IAClC;;;;;"}
|
|
@@ -5,7 +5,14 @@ export declare class ScreenshotCommand extends Command {
|
|
|
5
5
|
readonly verbose: number;
|
|
6
6
|
readonly filter: string | undefined;
|
|
7
7
|
readonly accept: boolean;
|
|
8
|
-
readonly
|
|
9
|
-
|
|
8
|
+
readonly project: string;
|
|
9
|
+
readonly target: string | undefined;
|
|
10
|
+
readonly compare: boolean;
|
|
11
|
+
readonly compareTarget: string | undefined;
|
|
12
|
+
readonly report: string | undefined;
|
|
13
|
+
readonly headed: boolean;
|
|
14
|
+
readonly timeout: string;
|
|
15
|
+
execute(): Promise<number>;
|
|
16
|
+
private _runComparison;
|
|
10
17
|
}
|
|
11
18
|
//# sourceMappingURL=screenshotCommand.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screenshotCommand.d.ts","sourceRoot":"","sources":["../../src/commands/screenshotCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"screenshotCommand.d.ts","sourceRoot":"","sources":["../../src/commands/screenshotCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAW5C,qBAAa,iBAAkB,SAAQ,OAAO;IAC7C,OAAgB,KAAK,aAAoB;IAEzC,OAAgB,KAAK,4BAOlB;IAEH,QAAQ,CAAC,OAAO,SAAsG;IACtH,QAAQ,CAAC,MAAM,qBAAkG;IACjH,QAAQ,CAAC,MAAM,UAAiI;IAChJ,QAAQ,CAAC,OAAO,SAAuI;IACvJ,QAAQ,CAAC,MAAM,qBAAsK;IACrL,QAAQ,CAAC,OAAO,UAA8F;IAC9G,QAAQ,CAAC,aAAa,qBAA+K;IACrM,QAAQ,CAAC,MAAM,qBAA4G;IAC3H,QAAQ,CAAC,MAAM,UAAwG;IACvH,QAAQ,CAAC,OAAO,SAA+G;IAEzH,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;YAwElB,cAAc;CA+B5B"}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { Command, Option } from 'clipanion';
|
|
2
|
+
import * as path from 'node:path';
|
|
2
3
|
import { PlaywrightBrowserPageFactory } from '../browserPage.js';
|
|
4
|
+
import { compareScreenshotsInMemory, printComparisonToConsole, writeComparisonReport } from '../comparison.js';
|
|
3
5
|
import { BrowserComponentExplorer } from '../componentExplorer.js';
|
|
4
6
|
import { DefaultComponentExplorerHttpServerFactory } from '../httpServer.js';
|
|
5
|
-
import { ConsoleLogger, verbosityToLogLevel } from '../logger.js';
|
|
7
|
+
import { ConsoleLogger, verbosityToLogLevel, logBuildInfo } from '../logger.js';
|
|
8
|
+
import { resolveProject, resolvedProjectToViteProjectRef } from '../resolveProject.js';
|
|
6
9
|
import { FileSystemStorage } from '../storage.js';
|
|
7
|
-
import {
|
|
10
|
+
import { matchGlob, writeFile } from '../utils.js';
|
|
8
11
|
|
|
9
12
|
class ScreenshotCommand extends Command {
|
|
10
13
|
static paths = [['screenshot']];
|
|
@@ -18,19 +21,42 @@ class ScreenshotCommand extends Command {
|
|
|
18
21
|
});
|
|
19
22
|
verbose = Option.Counter('-v,--verbose', 0, { description: 'Increase log verbosity (-v debug, -vv trace)' });
|
|
20
23
|
filter = Option.String('--filter', { required: false, description: 'Filter fixtures by glob pattern' });
|
|
21
|
-
accept = Option.Boolean('--accept', false, { description: 'Write
|
|
22
|
-
|
|
24
|
+
accept = Option.Boolean('--accept', false, { description: 'Write to baseline instead of current (mutually exclusive with --target)' });
|
|
25
|
+
project = Option.String('-p,--project', process.cwd(), { description: 'Project: a directory, vite config file, or component-explorer.json' });
|
|
26
|
+
target = Option.String('--target', { required: false, description: 'Screenshot output directory (default: .screenshots/current, or .screenshots/baseline with --accept)' });
|
|
27
|
+
compare = Option.Boolean('--compare', false, { description: 'Compare screenshots after capturing' });
|
|
28
|
+
compareTarget = Option.String('--compare-target', { required: false, description: 'Directory to compare against (default: .screenshots/baseline, or .screenshots/current with --accept)' });
|
|
29
|
+
report = Option.String('--report', { required: false, description: 'Output report folder (requires --compare)' });
|
|
30
|
+
headed = Option.Boolean('--headed', false, { description: 'Show the browser window (useful for debugging)' });
|
|
31
|
+
timeout = Option.String('--timeout', '30000', { description: 'Navigation timeout in milliseconds (default: 30000)' });
|
|
23
32
|
async execute() {
|
|
33
|
+
// Validate mutually exclusive options
|
|
34
|
+
if (this.accept && this.target) {
|
|
35
|
+
this.context.stderr.write('Error: --accept and --target are mutually exclusive.\n');
|
|
36
|
+
return 1;
|
|
37
|
+
}
|
|
24
38
|
const logger = new ConsoleLogger('screenshot', this.context.stdout, verbosityToLogLevel(this.verbose));
|
|
25
|
-
|
|
26
|
-
const
|
|
39
|
+
logBuildInfo(logger);
|
|
40
|
+
const resolved = await resolveProject(this.project);
|
|
41
|
+
const projectDir = resolved.projectDir;
|
|
42
|
+
const viteProject = resolvedProjectToViteProjectRef(resolved);
|
|
43
|
+
// Determine target directory
|
|
44
|
+
const defaultTarget = this.accept ? '.screenshots/baseline' : '.screenshots/current';
|
|
45
|
+
const targetDir = this.target ?? defaultTarget;
|
|
46
|
+
const targetPath = path.isAbsolute(targetDir) ? targetDir : path.join(projectDir, targetDir);
|
|
47
|
+
// Determine compare target directory
|
|
48
|
+
const defaultCompareTarget = this.accept ? '.screenshots/current' : '.screenshots/baseline';
|
|
49
|
+
const compareTargetDir = this.compareTarget ?? defaultCompareTarget;
|
|
50
|
+
const compareTargetPath = path.isAbsolute(compareTargetDir) ? compareTargetDir : path.join(projectDir, compareTargetDir);
|
|
51
|
+
const storage = new FileSystemStorage(targetPath);
|
|
27
52
|
const serverFactory = new DefaultComponentExplorerHttpServerFactory();
|
|
28
|
-
const browserFactory = new PlaywrightBrowserPageFactory();
|
|
53
|
+
const browserFactory = new PlaywrightBrowserPageFactory(this.headed, Number(this.timeout), logger);
|
|
54
|
+
const screenshots = new Map();
|
|
29
55
|
let server;
|
|
30
56
|
let explorer;
|
|
31
57
|
try {
|
|
32
58
|
this.context.stdout.write('Starting Vite dev server...\n');
|
|
33
|
-
server = await serverFactory.createViteServer(
|
|
59
|
+
server = await serverFactory.createViteServer(viteProject, { logger });
|
|
34
60
|
this.context.stdout.write(`Server running at ${server.url}\n`);
|
|
35
61
|
explorer = new BrowserComponentExplorer(browserFactory, server, logger);
|
|
36
62
|
const fixtures = await explorer.listFixtures();
|
|
@@ -39,23 +65,55 @@ class ScreenshotCommand extends Command {
|
|
|
39
65
|
: fixtures;
|
|
40
66
|
this.context.stdout.write(`Found ${filtered.length} fixture(s)\n`);
|
|
41
67
|
for (const fixture of filtered) {
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
68
|
+
const result = await explorer.screenshotFixture(fixture.fixtureId);
|
|
69
|
+
await storage.write(`${fixture.fixtureId}.png`, result.image);
|
|
70
|
+
screenshots.set(fixture.fixtureId, { data: result.image, background: fixture.background, labels: fixture.labels });
|
|
45
71
|
this.context.stdout.write(` ✓ ${fixture.fixtureId}\n`);
|
|
46
72
|
}
|
|
47
|
-
|
|
73
|
+
await writeFixturesJson(targetPath, filtered);
|
|
74
|
+
this.context.stdout.write(`\nScreenshots saved to ${targetDir}/\n`);
|
|
48
75
|
}
|
|
49
76
|
finally {
|
|
50
77
|
await explorer?.dispose();
|
|
51
78
|
await browserFactory.dispose();
|
|
52
79
|
await server?.dispose();
|
|
53
80
|
}
|
|
81
|
+
// Compare if requested
|
|
82
|
+
if (this.compare) {
|
|
83
|
+
this.context.stdout.write(`\nComparing against ${compareTargetDir}...\n`);
|
|
84
|
+
return this._runComparison(screenshots, targetPath, compareTargetPath, projectDir);
|
|
85
|
+
}
|
|
86
|
+
return 0;
|
|
87
|
+
}
|
|
88
|
+
async _runComparison(screenshots, targetPath, compareTargetPath, projectDir) {
|
|
89
|
+
const compareStorage = new FileSystemStorage(compareTargetPath);
|
|
90
|
+
const result = await compareScreenshotsInMemory(screenshots, {
|
|
91
|
+
list: async () => [],
|
|
92
|
+
read: (id) => compareStorage.read(id),
|
|
93
|
+
exists: (id) => compareStorage.exists(id),
|
|
94
|
+
});
|
|
95
|
+
printComparisonToConsole(result, this.context.stdout);
|
|
96
|
+
if (this.report) {
|
|
97
|
+
const reportDir = path.isAbsolute(this.report) ? this.report : path.join(projectDir, this.report);
|
|
98
|
+
await writeComparisonReport({
|
|
99
|
+
reportDir,
|
|
100
|
+
result,
|
|
101
|
+
baselinePath: compareTargetPath,
|
|
102
|
+
currentPath: targetPath,
|
|
103
|
+
getBaselineData: (id) => compareStorage.read(`${id}.png`),
|
|
104
|
+
getCurrentData: async (id) => screenshots.get(id).data,
|
|
105
|
+
});
|
|
106
|
+
this.context.stdout.write(`\nReport written to: ${this.report}/\n`);
|
|
107
|
+
}
|
|
108
|
+
return (result.added.length > 0 || result.changed.length > 0) ? 1 : 0;
|
|
54
109
|
}
|
|
55
110
|
}
|
|
56
|
-
function
|
|
57
|
-
const
|
|
58
|
-
|
|
111
|
+
async function writeFixturesJson(targetDir, fixtures) {
|
|
112
|
+
const metadata = {};
|
|
113
|
+
for (const f of fixtures) {
|
|
114
|
+
metadata[f.fixtureId] = { background: f.background, labels: f.labels };
|
|
115
|
+
}
|
|
116
|
+
await writeFile(path.join(targetDir, 'fixtures.json'), Buffer.from(JSON.stringify(metadata, null, 2)));
|
|
59
117
|
}
|
|
60
118
|
|
|
61
119
|
export { ScreenshotCommand };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screenshotCommand.js","sources":["../../src/commands/screenshotCommand.ts"],"sourcesContent":[null],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"screenshotCommand.js","sources":["../../src/commands/screenshotCommand.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -3,14 +3,19 @@ export declare class ServeCommand extends Command {
|
|
|
3
3
|
static paths: string[][];
|
|
4
4
|
static usage: import("clipanion").Usage;
|
|
5
5
|
readonly verbose: number;
|
|
6
|
-
readonly
|
|
6
|
+
readonly project: string;
|
|
7
7
|
readonly background: boolean;
|
|
8
8
|
readonly attach: boolean;
|
|
9
9
|
readonly kill: boolean;
|
|
10
|
+
readonly killIfRunning: boolean;
|
|
11
|
+
readonly redirectionPort: string | undefined;
|
|
12
|
+
readonly redirectionHost: string | undefined;
|
|
10
13
|
execute(): Promise<void>;
|
|
14
|
+
private _killExistingAndWait;
|
|
11
15
|
private _ensureBackground;
|
|
12
16
|
private _attach;
|
|
13
17
|
private _printEvent;
|
|
14
18
|
private _startDaemon;
|
|
19
|
+
private _startRedirectionServer;
|
|
15
20
|
}
|
|
16
21
|
//# sourceMappingURL=serveCommand.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serveCommand.d.ts","sourceRoot":"","sources":["../../src/commands/serveCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"serveCommand.d.ts","sourceRoot":"","sources":["../../src/commands/serveCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAe5C,qBAAa,YAAa,SAAQ,OAAO;IACxC,OAAgB,KAAK,aAAe;IAEpC,OAAgB,KAAK,4BAkBlB;IAEH,QAAQ,CAAC,OAAO,SAAsG;IACtH,QAAQ,CAAC,OAAO,SAA2I;IAC3J,QAAQ,CAAC,UAAU,UAAoG;IACvH,QAAQ,CAAC,MAAM,UAAsG;IACrH,QAAQ,CAAC,IAAI,UAAkF;IAC/F,QAAQ,CAAC,aAAa,UAAqH;IAC3I,QAAQ,CAAC,eAAe,qBAA8H;IACtJ,QAAQ,CAAC,eAAe,qBAAsH;IAExI,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YA2DhB,oBAAoB;YAkBpB,iBAAiB;YA0BjB,OAAO;IAgBrB,OAAO,CAAC,WAAW;YAeL,YAAY;IAgD1B,OAAO,CAAC,uBAAuB;CAyB/B"}
|