@vscode/component-explorer-cli 0.2.1-1 → 0.2.1-10
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 +8 -0
- package/dist/_virtual/_build-info.js +1 -1
- package/dist/browserPage.d.ts +5 -5
- package/dist/browserPage.d.ts.map +1 -1
- package/dist/browserPage.js +35 -2
- package/dist/browserPage.js.map +1 -1
- package/dist/commands/acceptCommand.d.ts +1 -0
- package/dist/commands/acceptCommand.d.ts.map +1 -1
- package/dist/commands/acceptCommand.js +17 -8
- package/dist/commands/acceptCommand.js.map +1 -1
- package/dist/commands/artifactCommand.d.ts +14 -0
- package/dist/commands/artifactCommand.d.ts.map +1 -0
- package/dist/commands/checkStabilityCommand.d.ts +1 -0
- package/dist/commands/checkStabilityCommand.d.ts.map +1 -1
- package/dist/commands/checkStabilityCommand.js +22 -18
- package/dist/commands/checkStabilityCommand.js.map +1 -1
- package/dist/commands/compareCommand.d.ts +1 -0
- package/dist/commands/compareCommand.d.ts.map +1 -1
- package/dist/commands/compareCommand.js +30 -11
- package/dist/commands/compareCommand.js.map +1 -1
- package/dist/commands/mcpCommand.d.ts +5 -0
- package/dist/commands/mcpCommand.d.ts.map +1 -1
- package/dist/commands/mcpCommand.js +86 -16
- package/dist/commands/mcpCommand.js.map +1 -1
- package/dist/commands/{screenshotCommand.d.ts → renderCommand.d.ts} +4 -2
- package/dist/commands/renderCommand.d.ts.map +1 -0
- package/dist/commands/renderCommand.js +210 -0
- package/dist/commands/renderCommand.js.map +1 -0
- package/dist/commands/serveCommand.d.ts +2 -0
- package/dist/commands/serveCommand.d.ts.map +1 -1
- package/dist/commands/serveCommand.js +79 -41
- package/dist/commands/serveCommand.js.map +1 -1
- package/dist/commands/serviceDiffCommitsCommand.d.ts +16 -0
- package/dist/commands/serviceDiffCommitsCommand.d.ts.map +1 -0
- package/dist/commands/serviceDiffCommitsCommand.js +229 -0
- package/dist/commands/serviceDiffCommitsCommand.js.map +1 -0
- package/dist/commands/watchCommand.d.ts +1 -0
- package/dist/commands/watchCommand.d.ts.map +1 -1
- package/dist/commands/watchCommand.js +22 -27
- package/dist/commands/watchCommand.js.map +1 -1
- package/dist/componentExplorer.d.ts +18 -11
- package/dist/componentExplorer.d.ts.map +1 -1
- package/dist/componentExplorer.js +95 -66
- package/dist/componentExplorer.js.map +1 -1
- package/dist/{watchConfig.d.ts → config.d.ts} +28 -24
- package/dist/config.d.ts.map +1 -0
- package/dist/{watchConfig.js → config.js} +63 -23
- package/dist/config.js.map +1 -0
- package/dist/daemon/DaemonService.d.ts +3 -3
- package/dist/daemon/DaemonService.d.ts.map +1 -1
- package/dist/daemon/DaemonService.js +19 -36
- package/dist/daemon/DaemonService.js.map +1 -1
- package/dist/daemon/client.d.ts +5 -0
- package/dist/daemon/client.d.ts.map +1 -0
- package/dist/daemon/client.js +7 -0
- package/dist/daemon/client.js.map +1 -0
- package/dist/daemon/inProcessClient.d.ts +11 -0
- package/dist/daemon/inProcessClient.d.ts.map +1 -0
- package/dist/daemon/inProcessClient.js +35 -0
- package/dist/daemon/inProcessClient.js.map +1 -0
- package/dist/daemon/lifecycle.d.ts +4 -0
- package/dist/daemon/lifecycle.d.ts.map +1 -1
- package/dist/daemon/lifecycle.js +12 -2
- package/dist/daemon/lifecycle.js.map +1 -1
- package/dist/daemon/pipeClient.js +5 -3
- package/dist/daemon/pipeClient.js.map +1 -1
- package/dist/daemon/pipeName.d.ts +6 -0
- package/dist/daemon/pipeName.d.ts.map +1 -1
- package/dist/daemon/pipeName.js +8 -3
- package/dist/daemon/pipeName.js.map +1 -1
- package/dist/daemon/pipeServer.d.ts.map +1 -1
- package/dist/daemon/pipeServer.js +9 -3
- package/dist/daemon/pipeServer.js.map +1 -1
- package/dist/daemon/version.d.ts +1 -1
- package/dist/daemon/version.d.ts.map +1 -1
- package/dist/daemon/version.js +1 -1
- package/dist/dependencyInstaller.d.ts +1 -1
- package/dist/dependencyInstaller.d.ts.map +1 -1
- package/dist/evaluateFn.d.ts +21 -0
- package/dist/evaluateFn.d.ts.map +1 -0
- package/dist/evaluateFn.js +17 -0
- package/dist/evaluateFn.js.map +1 -0
- package/dist/explorerSession.d.ts +2 -3
- package/dist/explorerSession.d.ts.map +1 -1
- package/dist/explorerSession.js +3 -20
- package/dist/explorerSession.js.map +1 -1
- package/dist/git/gitUtils.d.ts +1 -0
- package/dist/git/gitUtils.d.ts.map +1 -1
- package/dist/git/gitUtils.js +5 -1
- package/dist/git/gitUtils.js.map +1 -1
- package/dist/index.js +11 -2
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +12 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +35 -2
- package/dist/logger.js.map +1 -1
- package/dist/manifest.schema.json +187 -0
- package/dist/mcp/McpServer.d.ts +1 -0
- package/dist/mcp/McpServer.d.ts.map +1 -1
- package/dist/mcp/McpServer.js +113 -20
- package/dist/mcp/McpServer.js.map +1 -1
- package/dist/packages/common/dist/renderManifest.js +46 -0
- package/dist/packages/common/dist/renderManifest.js.map +1 -0
- package/dist/packages/semver/dist/index.js +186 -0
- package/dist/packages/semver/dist/index.js.map +1 -0
- package/dist/packages/simple-api/dist/{chunk-3R7GHWBM.js → chunk-FJ7AVNQE.js} +2 -1
- package/dist/packages/simple-api/dist/chunk-FJ7AVNQE.js.map +1 -0
- package/dist/packages/simple-api/dist/{chunk-SGBCNXYH.js → chunk-TTRCY65Z.js} +4 -1
- package/dist/packages/simple-api/dist/chunk-TTRCY65Z.js.map +1 -0
- package/dist/packages/simple-api/dist/{chunk-TAEFVNPN.js → chunk-WNXMRXWV.js} +2 -1
- package/dist/packages/simple-api/dist/chunk-WNXMRXWV.js.map +1 -0
- package/dist/packages/simple-api/dist/express.js +1 -1
- package/dist/packages/simple-api/dist/express.js.map +1 -1
- package/dist/processTree.d.ts +9 -0
- package/dist/processTree.d.ts.map +1 -0
- package/dist/processTree.js +41 -0
- package/dist/processTree.js.map +1 -0
- package/dist/renderManifest.d.ts +5 -0
- package/dist/renderManifest.d.ts.map +1 -0
- package/dist/renderManifest.js +11 -0
- package/dist/renderManifest.js.map +1 -0
- package/dist/screenshotServiceClient.d.ts +31 -0
- package/dist/screenshotServiceClient.d.ts.map +1 -0
- package/dist/screenshotServiceClient.js +38 -0
- package/dist/screenshotServiceClient.js.map +1 -0
- package/dist/server/httpServer.d.ts +14 -0
- package/dist/server/httpServer.d.ts.map +1 -0
- package/dist/server/httpServer.js +114 -0
- package/dist/server/httpServer.js.map +1 -0
- package/dist/server/httpServer.test.d.ts.map +1 -0
- package/dist/server/serverConfig.d.ts +42 -0
- package/dist/server/serverConfig.d.ts.map +1 -0
- package/dist/server/serverConfig.js +60 -0
- package/dist/server/serverConfig.js.map +1 -0
- package/dist/server/types.d.ts +6 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/viteServer.d.ts +16 -0
- package/dist/server/viteServer.d.ts.map +1 -0
- package/dist/{httpServer.js → server/viteServer.js} +10 -110
- package/dist/server/viteServer.js.map +1 -0
- package/dist/utils.d.ts +11 -6
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +7 -6
- package/dist/utils.js.map +1 -1
- package/package.json +30 -19
- package/dist/commands/screenshotCommand.d.ts.map +0 -1
- package/dist/commands/screenshotCommand.js +0 -127
- package/dist/commands/screenshotCommand.js.map +0 -1
- package/dist/httpServer.d.ts +0 -36
- package/dist/httpServer.d.ts.map +0 -1
- package/dist/httpServer.js.map +0 -1
- package/dist/httpServer.test.d.ts.map +0 -1
- package/dist/packages/simple-api/dist/chunk-3R7GHWBM.js.map +0 -1
- package/dist/packages/simple-api/dist/chunk-SGBCNXYH.js.map +0 -1
- package/dist/packages/simple-api/dist/chunk-TAEFVNPN.js.map +0 -1
- package/dist/resolveProject.d.ts +0 -21
- package/dist/resolveProject.d.ts.map +0 -1
- package/dist/resolveProject.js +0 -39
- package/dist/resolveProject.js.map +0 -1
- package/dist/watchConfig.d.ts.map +0 -1
- package/dist/watchConfig.js.map +0 -1
- /package/dist/{httpServer.test.d.ts → server/httpServer.test.d.ts} +0 -0
|
@@ -1,60 +1,131 @@
|
|
|
1
1
|
import { Command, Option } from 'clipanion';
|
|
2
|
+
import * as path from 'node:path';
|
|
2
3
|
import '../external/vscode-observables/observables/dist/observableInternal/index.js';
|
|
4
|
+
import { DisposableStore } from '../external/vscode-observables/observables/dist/disposables.js';
|
|
3
5
|
import { observableValue } from '../external/vscode-observables/observables/dist/observableInternal/observables/observableValue.js';
|
|
4
6
|
import '../external/vscode-observables/observables/dist/observableInternal/debugLocation.js';
|
|
5
7
|
import '../external/vscode-observables/observables/dist/observableInternal/observables/derived.js';
|
|
6
8
|
import '../external/vscode-observables/observables/dist/observableInternal/utils/utils.js';
|
|
7
9
|
import '../external/vscode-observables/observables/dist/observableInternal/observables/observableFromEvent.js';
|
|
8
10
|
import { tryConnect, connectToExistingOrStartDaemon } from '../daemon/lifecycle.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
11
|
+
import { daemonPipeInfo } from '../daemon/pipeName.js';
|
|
12
|
+
import { DaemonConnection, ComponentExplorerMcpServer } from '../mcp/McpServer.js';
|
|
13
|
+
import { ResolvedConfig } from '../config.js';
|
|
14
|
+
import { DaemonService } from '../daemon/DaemonService.js';
|
|
15
|
+
import { createInProcessClient } from '../daemon/inProcessClient.js';
|
|
16
|
+
import { ConsoleLogger, verbosityToLogLevel, createLogFileOptions, logBuildInfo } from '../logger.js';
|
|
12
17
|
|
|
13
18
|
class McpCommand extends Command {
|
|
14
19
|
static paths = [['mcp']];
|
|
15
20
|
static usage = Command.Usage({
|
|
16
|
-
description: 'Start an MCP server over stdio.
|
|
21
|
+
description: 'Start an MCP server over stdio. By default runs as the daemon in-process.',
|
|
17
22
|
examples: [
|
|
18
|
-
['Start MCP server', '$0 mcp --project config.json'],
|
|
19
|
-
['
|
|
23
|
+
['Start MCP server (in-process daemon)', '$0 mcp --project config.json'],
|
|
24
|
+
['Connect to external daemon', '$0 mcp --project config.json --use-daemon'],
|
|
25
|
+
['Require existing daemon', '$0 mcp --project config.json --use-daemon --no-daemon-autostart'],
|
|
20
26
|
],
|
|
21
27
|
});
|
|
28
|
+
verbose = Option.Counter('-v,--verbose', 0, { description: 'Increase log verbosity (-v debug, -vv trace)' });
|
|
29
|
+
logFile = Option.String('--log-file', { description: 'Append logs to this file (works with -v/-vv)' });
|
|
22
30
|
project = Option.String('-p,--project', { required: true, description: 'Project: a directory, vite config file, or component-explorer.json' });
|
|
23
|
-
|
|
24
|
-
|
|
31
|
+
useDaemon = Option.Boolean('--use-daemon', false, { description: 'Connect to an external daemon process over a pipe instead of running in-process' });
|
|
32
|
+
noAutostart = Option.Boolean('--no-daemon-autostart', false, { description: 'Do not auto-start daemon; poll for it instead (requires --use-daemon)' });
|
|
33
|
+
noAutostartHint = Option.String('--no-daemon-hint', { description: 'Hint message shown when daemon is not running (used with --use-daemon --no-daemon-autostart)' });
|
|
25
34
|
callTimeout = Option.String('--call-timeout', { description: 'Timeout in seconds for daemon calls (default: 15)' });
|
|
26
35
|
async execute() {
|
|
27
|
-
const
|
|
28
|
-
|
|
36
|
+
const logger = new ConsoleLogger('mcp', this.context.stderr, verbosityToLogLevel(this.verbose), createLogFileOptions(this.logFile, this.verbose));
|
|
37
|
+
logBuildInfo(logger);
|
|
38
|
+
if (this.noAutostart && !this.useDaemon) {
|
|
39
|
+
this.context.stderr.write('Error: --no-daemon-autostart requires --use-daemon.\n');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const disposables = new DisposableStore();
|
|
43
|
+
const config = await ResolvedConfig.fromProjectPath(this.project, disposables);
|
|
44
|
+
if (!config.isFullConfig) {
|
|
29
45
|
this.context.stderr.write('Error: mcp requires a component-explorer.json config file.\n');
|
|
46
|
+
disposables.dispose();
|
|
30
47
|
return;
|
|
31
48
|
}
|
|
49
|
+
if (this.useDaemon) {
|
|
50
|
+
await this._runWithExternalDaemon(config, logger);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
await this._runInProcess(config, logger, disposables);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async _runInProcess(config, logger, disposables) {
|
|
57
|
+
logger.log('Starting in-process daemon...');
|
|
58
|
+
const service = await DaemonService.create(config, logger, undefined, {
|
|
59
|
+
idleTimeoutMs: 0, // no idle timeout for MCP — the MCP client controls lifetime
|
|
60
|
+
});
|
|
61
|
+
// Ensure cleanup on crashes/unexpected exits
|
|
62
|
+
let cleanedUp = false;
|
|
63
|
+
const cleanup = async () => {
|
|
64
|
+
if (cleanedUp) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
cleanedUp = true;
|
|
68
|
+
logger.debug('Cleaning up...');
|
|
69
|
+
await service.dispose();
|
|
70
|
+
disposables.dispose();
|
|
71
|
+
};
|
|
72
|
+
process.on('uncaughtException', async (err) => {
|
|
73
|
+
logger.log(`Uncaught exception: ${err.message}`);
|
|
74
|
+
await cleanup();
|
|
75
|
+
});
|
|
76
|
+
process.on('unhandledRejection', async (err) => {
|
|
77
|
+
logger.log(`Unhandled rejection: ${err instanceof Error ? err.message : String(err)}`);
|
|
78
|
+
await cleanup();
|
|
79
|
+
});
|
|
80
|
+
process.on('SIGINT', async () => {
|
|
81
|
+
logger.debug('Received SIGINT');
|
|
82
|
+
await cleanup();
|
|
83
|
+
process.exit(0);
|
|
84
|
+
});
|
|
85
|
+
const client = createInProcessClient(service.api, { clientName: 'mcp-inproc' });
|
|
86
|
+
const daemonObservable = observableValue('daemon', new DaemonConnection(client));
|
|
87
|
+
await ComponentExplorerMcpServer.create(daemonObservable, {
|
|
88
|
+
callTimeoutMs: this.callTimeout ? Number(this.callTimeout) * 1000 : undefined,
|
|
89
|
+
});
|
|
90
|
+
logger.log('MCP server ready (in-process daemon)');
|
|
91
|
+
await new Promise(() => { });
|
|
92
|
+
}
|
|
93
|
+
async _runWithExternalDaemon(config, logger) {
|
|
32
94
|
const daemonObservable = observableValue('daemon', undefined);
|
|
33
95
|
const mcpClientName = `mcp-${new Date().toISOString().replace(/[-:]/g, '').replace(/\.\d+Z$/, '')}`;
|
|
34
|
-
const
|
|
96
|
+
const configPath = path.resolve(this.project);
|
|
97
|
+
const { pipeName, source: pipeSource } = daemonPipeInfo(configPath);
|
|
98
|
+
logger.debug(`Daemon pipe: ${pipeName} (source: ${pipeSource})`);
|
|
35
99
|
let restartInProgress = false;
|
|
36
100
|
const pollFn = async () => {
|
|
37
101
|
const client = await tryConnect(pipeName, { clientName: mcpClientName });
|
|
38
102
|
if (client) {
|
|
39
103
|
const current = daemonObservable.get();
|
|
40
104
|
if (!current || current.isStale) {
|
|
105
|
+
logger.debug(`Daemon connection established`);
|
|
41
106
|
daemonObservable.set(new DaemonConnection(client), undefined);
|
|
42
107
|
}
|
|
43
108
|
return;
|
|
44
109
|
}
|
|
45
110
|
const current = daemonObservable.get();
|
|
46
111
|
if (current) {
|
|
112
|
+
logger.debug(`Daemon connection lost, will attempt restart`);
|
|
47
113
|
current.markStale();
|
|
48
114
|
daemonObservable.set(undefined, undefined);
|
|
49
115
|
}
|
|
50
116
|
if (!this.noAutostart && !restartInProgress) {
|
|
51
117
|
restartInProgress = true;
|
|
52
118
|
try {
|
|
53
|
-
const daemon = await connectToExistingOrStartDaemon(
|
|
119
|
+
const daemon = await connectToExistingOrStartDaemon(configPath, {
|
|
120
|
+
clientName: mcpClientName,
|
|
121
|
+
logger,
|
|
122
|
+
verbosity: this.verbose,
|
|
123
|
+
logFile: this.logFile,
|
|
124
|
+
});
|
|
54
125
|
daemonObservable.set(new DaemonConnection(daemon), undefined);
|
|
55
126
|
}
|
|
56
|
-
catch {
|
|
57
|
-
|
|
127
|
+
catch (err) {
|
|
128
|
+
logger.debug(`Daemon restart failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
58
129
|
}
|
|
59
130
|
finally {
|
|
60
131
|
restartInProgress = false;
|
|
@@ -63,13 +134,12 @@ class McpCommand extends Command {
|
|
|
63
134
|
};
|
|
64
135
|
await pollFn();
|
|
65
136
|
setInterval(pollFn, 5000);
|
|
66
|
-
// Create and connect the MCP server over stdio
|
|
67
137
|
await ComponentExplorerMcpServer.create(daemonObservable, {
|
|
68
138
|
pollFn,
|
|
69
139
|
noAutostartHint: this.noAutostartHint,
|
|
70
140
|
callTimeoutMs: this.callTimeout ? Number(this.callTimeout) * 1000 : undefined,
|
|
71
141
|
});
|
|
72
|
-
|
|
142
|
+
logger.log('MCP server ready (external daemon)');
|
|
73
143
|
await new Promise(() => { });
|
|
74
144
|
}
|
|
75
145
|
}
|
|
@@ -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":"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"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Command } from 'clipanion';
|
|
2
|
-
export declare class
|
|
2
|
+
export declare class RenderCommand extends Command {
|
|
3
3
|
static paths: string[][];
|
|
4
4
|
static usage: import("clipanion").Usage;
|
|
5
5
|
readonly verbose: number;
|
|
6
|
+
readonly logFile: string | undefined;
|
|
6
7
|
readonly filter: string | undefined;
|
|
7
8
|
readonly accept: boolean;
|
|
8
9
|
readonly project: string;
|
|
@@ -12,7 +13,8 @@ export declare class ScreenshotCommand extends Command {
|
|
|
12
13
|
readonly report: string | undefined;
|
|
13
14
|
readonly headed: boolean;
|
|
14
15
|
readonly timeout: string;
|
|
16
|
+
readonly useHashPaths: boolean;
|
|
15
17
|
execute(): Promise<number>;
|
|
16
18
|
private _runComparison;
|
|
17
19
|
}
|
|
18
|
-
//# sourceMappingURL=
|
|
20
|
+
//# sourceMappingURL=renderCommand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderCommand.d.ts","sourceRoot":"","sources":["../../src/commands/renderCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAc5C,qBAAa,aAAc,SAAQ,OAAO;IACzC,OAAgB,KAAK,aAAgB;IAErC,OAAgB,KAAK,4BAOlB;IAEH,QAAQ,CAAC,OAAO,SAAsG;IACtH,QAAQ,CAAC,OAAO,qBAAgG;IAChH,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;IAC/H,QAAQ,CAAC,YAAY,UAA8J;IAE7K,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;YA+HlB,cAAc;CA+B5B"}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { Command, Option } from 'clipanion';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import '../external/vscode-observables/observables/dist/observableInternal/index.js';
|
|
5
|
+
import { DisposableStore } from '../external/vscode-observables/observables/dist/disposables.js';
|
|
6
|
+
import '../external/vscode-observables/observables/dist/observableInternal/debugLocation.js';
|
|
7
|
+
import '../external/vscode-observables/observables/dist/observableInternal/observables/derived.js';
|
|
8
|
+
import '../external/vscode-observables/observables/dist/observableInternal/utils/utils.js';
|
|
9
|
+
import '../external/vscode-observables/observables/dist/observableInternal/observables/observableFromEvent.js';
|
|
10
|
+
import { PlaywrightBrowserPageFactory } from '../browserPage.js';
|
|
11
|
+
import { compareScreenshotsInMemory, printComparisonToConsole, writeComparisonReport } from '../comparison.js';
|
|
12
|
+
import { ConsoleLogger, verbosityToLogLevel, createLogFileOptions, logBuildInfo } from '../logger.js';
|
|
13
|
+
import { ResolvedConfig } from '../config.js';
|
|
14
|
+
import { ExplorerSession } from '../explorerSession.js';
|
|
15
|
+
import { FileSystemStorage } from '../storage.js';
|
|
16
|
+
import { matchGlob, writeFile } from '../utils.js';
|
|
17
|
+
import { getGitRoot, execGit } from '../git/gitUtils.js';
|
|
18
|
+
import { serializeManifest } from '../renderManifest.js';
|
|
19
|
+
import { MANIFEST_FILENAME } from '../packages/common/dist/renderManifest.js';
|
|
20
|
+
|
|
21
|
+
class RenderCommand extends Command {
|
|
22
|
+
static paths = [['render']];
|
|
23
|
+
static usage = Command.Usage({
|
|
24
|
+
description: 'Render screenshots of all fixtures and write a manifest',
|
|
25
|
+
examples: [
|
|
26
|
+
['Render all fixtures', '$0 render'],
|
|
27
|
+
['Render and accept as baseline', '$0 render --accept'],
|
|
28
|
+
['Filter by glob', '$0 render --filter "Button/*"'],
|
|
29
|
+
],
|
|
30
|
+
});
|
|
31
|
+
verbose = Option.Counter('-v,--verbose', 0, { description: 'Increase log verbosity (-v debug, -vv trace)' });
|
|
32
|
+
logFile = Option.String('--log-file', { description: 'Append logs to this file (works with -v/-vv)' });
|
|
33
|
+
filter = Option.String('--filter', { required: false, description: 'Filter fixtures by glob pattern' });
|
|
34
|
+
accept = Option.Boolean('--accept', false, { description: 'Write to baseline instead of current (mutually exclusive with --target)' });
|
|
35
|
+
project = Option.String('-p,--project', process.cwd(), { description: 'Project: a directory, vite config file, or component-explorer.json' });
|
|
36
|
+
target = Option.String('--target', { required: false, description: 'Screenshot output directory (default: .screenshots/current, or .screenshots/baseline with --accept)' });
|
|
37
|
+
compare = Option.Boolean('--compare', false, { description: 'Compare screenshots after capturing' });
|
|
38
|
+
compareTarget = Option.String('--compare-target', { required: false, description: 'Directory to compare against (default: .screenshots/baseline, or .screenshots/current with --accept)' });
|
|
39
|
+
report = Option.String('--report', { required: false, description: 'Output report folder (requires --compare)' });
|
|
40
|
+
headed = Option.Boolean('--headed', false, { description: 'Show the browser window (useful for debugging)' });
|
|
41
|
+
timeout = Option.String('--timeout', '30000', { description: 'Navigation timeout in milliseconds (default: 30000)' });
|
|
42
|
+
useHashPaths = Option.Boolean('--useHashPaths', false, { description: 'Use content-hash image paths (images/<hash>.png) for deduplication instead of fixture-id paths' });
|
|
43
|
+
async execute() {
|
|
44
|
+
// Validate mutually exclusive options
|
|
45
|
+
if (this.accept && this.target) {
|
|
46
|
+
this.context.stderr.write('Error: --accept and --target are mutually exclusive.\n');
|
|
47
|
+
return 1;
|
|
48
|
+
}
|
|
49
|
+
const logger = new ConsoleLogger('render', this.context.stdout, verbosityToLogLevel(this.verbose), createLogFileOptions(this.logFile, this.verbose));
|
|
50
|
+
logBuildInfo(logger);
|
|
51
|
+
const disposables = new DisposableStore();
|
|
52
|
+
const config = await ResolvedConfig.fromProjectPath(this.project, disposables);
|
|
53
|
+
const projectDir = config.configDir;
|
|
54
|
+
const serverConfig = config.sessions[0].server;
|
|
55
|
+
// Determine target directory
|
|
56
|
+
const defaultTarget = this.accept ? '.screenshots/baseline' : '.screenshots/current';
|
|
57
|
+
const targetDir = this.target ?? defaultTarget;
|
|
58
|
+
const targetPath = path.isAbsolute(targetDir) ? targetDir : path.join(projectDir, targetDir);
|
|
59
|
+
// Determine compare target directory
|
|
60
|
+
const defaultCompareTarget = this.accept ? '.screenshots/current' : '.screenshots/baseline';
|
|
61
|
+
const compareTargetDir = this.compareTarget ?? defaultCompareTarget;
|
|
62
|
+
const compareTargetPath = path.isAbsolute(compareTargetDir) ? compareTargetDir : path.join(projectDir, compareTargetDir);
|
|
63
|
+
const storage = new FileSystemStorage(targetPath);
|
|
64
|
+
const browserFactory = new PlaywrightBrowserPageFactory(this.headed, Number(this.timeout), logger);
|
|
65
|
+
const screenshots = new Map();
|
|
66
|
+
let session;
|
|
67
|
+
try {
|
|
68
|
+
this.context.stdout.write('Starting server...\n');
|
|
69
|
+
session = await ExplorerSession.create('render', serverConfig, browserFactory, { logger });
|
|
70
|
+
this.context.stdout.write(`Server running at ${session.serverUrl}\n`);
|
|
71
|
+
const listResult = await session.explorer.listFixtures();
|
|
72
|
+
if (listResult.loadError) {
|
|
73
|
+
this.context.stderr.write(`Warning: Fixture loading error: ${listResult.loadError}\n`);
|
|
74
|
+
}
|
|
75
|
+
const filtered = this.filter
|
|
76
|
+
? listResult.fixtures.filter(f => matchGlob(f.fixtureId, this.filter))
|
|
77
|
+
: listResult.fixtures;
|
|
78
|
+
this.context.stdout.write(`Found ${filtered.length} fixture(s)\n`);
|
|
79
|
+
const fixtureEntries = [];
|
|
80
|
+
const writtenHashes = new Set();
|
|
81
|
+
for (const fixture of filtered) {
|
|
82
|
+
const result = await session.explorer.screenshotFixture(fixture.fixtureId);
|
|
83
|
+
let imageHash;
|
|
84
|
+
let imagePath;
|
|
85
|
+
if (result.image) {
|
|
86
|
+
imageHash = createHash('sha256').update(result.image).digest('hex');
|
|
87
|
+
if (this.useHashPaths) {
|
|
88
|
+
imagePath = `images/${imageHash}.png`;
|
|
89
|
+
if (!writtenHashes.has(imageHash)) {
|
|
90
|
+
await storage.write(imagePath, result.image);
|
|
91
|
+
writtenHashes.add(imageHash);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
imagePath = `${fixture.fixtureId}.png`;
|
|
96
|
+
await storage.write(imagePath, result.image);
|
|
97
|
+
}
|
|
98
|
+
screenshots.set(fixture.fixtureId, { data: result.image, background: fixture.background, labels: fixture.labels });
|
|
99
|
+
}
|
|
100
|
+
fixtureEntries.push({
|
|
101
|
+
fixtureId: fixture.fixtureId,
|
|
102
|
+
imageHash,
|
|
103
|
+
imagePath,
|
|
104
|
+
background: fixture.background,
|
|
105
|
+
labels: [...fixture.labels],
|
|
106
|
+
expectedVisualDescriptions: [...fixture.expectedVisualDescriptions],
|
|
107
|
+
hasError: result.hasError,
|
|
108
|
+
error: result.error,
|
|
109
|
+
events: result.events,
|
|
110
|
+
renderTimeMs: result.renderTimeMs,
|
|
111
|
+
});
|
|
112
|
+
if (!result.image) {
|
|
113
|
+
this.context.stderr.write(` ✗ ${fixture.fixtureId} (no screenshot)\n`);
|
|
114
|
+
}
|
|
115
|
+
else if (result.hasError) {
|
|
116
|
+
this.context.stdout.write(` ⚠ ${fixture.fixtureId} (rendered with errors)\n`);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
this.context.stdout.write(` ✓ ${fixture.fixtureId}\n`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const gitRoot = await getGitRoot(projectDir);
|
|
123
|
+
const commitMetadata = await collectGitMetadata(gitRoot);
|
|
124
|
+
const repoOrigin = await getRepoOwnerAndName(gitRoot);
|
|
125
|
+
const manifest = {
|
|
126
|
+
version: 1,
|
|
127
|
+
repository: repoOrigin,
|
|
128
|
+
commit: commitMetadata,
|
|
129
|
+
fixtures: fixtureEntries,
|
|
130
|
+
};
|
|
131
|
+
const manifestPath = path.join(targetPath, MANIFEST_FILENAME);
|
|
132
|
+
await writeFile(manifestPath, Buffer.from(serializeManifest(manifest)));
|
|
133
|
+
this.context.stdout.write(`\nRendered to ${targetDir}/\n`);
|
|
134
|
+
this.context.stdout.write(` Manifest: ${manifestPath}\n`);
|
|
135
|
+
this.context.stdout.write(` ${fixtureEntries.length} fixtures, ${writtenHashes.size} unique images\n`);
|
|
136
|
+
}
|
|
137
|
+
finally {
|
|
138
|
+
await session?.dispose();
|
|
139
|
+
await browserFactory.dispose();
|
|
140
|
+
disposables.dispose();
|
|
141
|
+
}
|
|
142
|
+
if (this.compare) {
|
|
143
|
+
this.context.stdout.write(`\nComparing against ${compareTargetDir}...\n`);
|
|
144
|
+
return this._runComparison(screenshots, targetPath, compareTargetPath, projectDir);
|
|
145
|
+
}
|
|
146
|
+
return 0;
|
|
147
|
+
}
|
|
148
|
+
async _runComparison(screenshots, targetPath, compareTargetPath, projectDir) {
|
|
149
|
+
const compareStorage = new FileSystemStorage(compareTargetPath);
|
|
150
|
+
const result = await compareScreenshotsInMemory(screenshots, {
|
|
151
|
+
list: async () => [],
|
|
152
|
+
read: (id) => compareStorage.read(id),
|
|
153
|
+
exists: (id) => compareStorage.exists(id),
|
|
154
|
+
});
|
|
155
|
+
printComparisonToConsole(result, this.context.stdout);
|
|
156
|
+
if (this.report) {
|
|
157
|
+
const reportDir = path.isAbsolute(this.report) ? this.report : path.join(projectDir, this.report);
|
|
158
|
+
await writeComparisonReport({
|
|
159
|
+
reportDir,
|
|
160
|
+
result,
|
|
161
|
+
baselinePath: compareTargetPath,
|
|
162
|
+
currentPath: targetPath,
|
|
163
|
+
getBaselineData: (id) => compareStorage.read(`${id}.png`),
|
|
164
|
+
getCurrentData: async (id) => screenshots.get(id).data,
|
|
165
|
+
});
|
|
166
|
+
this.context.stdout.write(`\nReport written to: ${this.report}/\n`);
|
|
167
|
+
}
|
|
168
|
+
return (result.added.length > 0 || result.changed.length > 0) ? 1 : 0;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
async function collectGitMetadata(gitRoot) {
|
|
172
|
+
const hash = (await execGit(gitRoot, ['rev-parse', 'HEAD'])).trim();
|
|
173
|
+
const logOutput = (await execGit(gitRoot, [
|
|
174
|
+
'log', '-1', '--format=%an%n%ae%n%aI%n%s', 'HEAD',
|
|
175
|
+
])).trim();
|
|
176
|
+
const [authorName, authorEmail, timestamp, ...messageParts] = logOutput.split('\n');
|
|
177
|
+
let parentHashes = [];
|
|
178
|
+
try {
|
|
179
|
+
const parentOutput = (await execGit(gitRoot, ['rev-parse', 'HEAD^@'])).trim();
|
|
180
|
+
if (parentOutput) {
|
|
181
|
+
parentHashes = parentOutput.split('\n').map(s => s.trim()).filter(Boolean);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
// root commit has no parents
|
|
186
|
+
}
|
|
187
|
+
return {
|
|
188
|
+
hash,
|
|
189
|
+
parentHashes,
|
|
190
|
+
author: { name: authorName, email: authorEmail },
|
|
191
|
+
timestamp,
|
|
192
|
+
message: messageParts.join('\n'),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
async function getRepoOwnerAndName(gitRoot) {
|
|
196
|
+
try {
|
|
197
|
+
const remoteUrl = (await execGit(gitRoot, ['remote', 'get-url', 'origin'])).trim();
|
|
198
|
+
const match = remoteUrl.match(/[:/]([^/]+)\/([^/.]+?)(?:\.git)?$/);
|
|
199
|
+
if (match) {
|
|
200
|
+
return { owner: match[1], name: match[2] };
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
// no remote configured
|
|
205
|
+
}
|
|
206
|
+
return { owner: 'unknown', name: path.basename(gitRoot) };
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export { RenderCommand };
|
|
210
|
+
//# sourceMappingURL=renderCommand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderCommand.js","sources":["../../src/commands/renderCommand.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ 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 logFile: string | undefined;
|
|
6
7
|
readonly project: string;
|
|
7
8
|
readonly background: boolean;
|
|
8
9
|
readonly attach: boolean;
|
|
@@ -11,6 +12,7 @@ export declare class ServeCommand extends Command {
|
|
|
11
12
|
readonly headed: boolean;
|
|
12
13
|
readonly redirectionPort: string | undefined;
|
|
13
14
|
readonly redirectionHost: string | undefined;
|
|
15
|
+
readonly idleTimeoutMs: string;
|
|
14
16
|
execute(): Promise<void>;
|
|
15
17
|
private _killExistingAndWait;
|
|
16
18
|
private _ensureBackground;
|
|
@@ -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;AAiB5C,qBAAa,YAAa,SAAQ,OAAO;IACxC,OAAgB,KAAK,aAAe;IAEpC,OAAgB,KAAK,4BAkBlB;IAEH,QAAQ,CAAC,OAAO,SAAsG;IACtH,QAAQ,CAAC,OAAO,SAAwI;IACxJ,QAAQ,CAAC,UAAU,UAAoG;IACvH,QAAQ,CAAC,MAAM,UAAsG;IACrH,QAAQ,CAAC,IAAI,UAAkF;IAC/F,QAAQ,CAAC,aAAa,UAAqH;IAC3I,QAAQ,CAAC,MAAM,UAAwG;IACvH,QAAQ,CAAC,eAAe,qBAA8H;IACtJ,QAAQ,CAAC,eAAe,qBAAsH;
|
|
1
|
+
{"version":3,"file":"serveCommand.d.ts","sourceRoot":"","sources":["../../src/commands/serveCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAiB5C,qBAAa,YAAa,SAAQ,OAAO;IACxC,OAAgB,KAAK,aAAe;IAEpC,OAAgB,KAAK,4BAkBlB;IAEH,QAAQ,CAAC,OAAO,SAAsG;IACtH,QAAQ,CAAC,OAAO,qBAAgG;IAChH,QAAQ,CAAC,OAAO,SAAwI;IACxJ,QAAQ,CAAC,UAAU,UAAoG;IACvH,QAAQ,CAAC,MAAM,UAAsG;IACrH,QAAQ,CAAC,IAAI,UAAkF;IAC/F,QAAQ,CAAC,aAAa,UAAqH;IAC3I,QAAQ,CAAC,MAAM,UAAwG;IACvH,QAAQ,CAAC,eAAe,qBAA8H;IACtJ,QAAQ,CAAC,eAAe,qBAAsH;IAC9I,QAAQ,CAAC,aAAa,SAA0J;IAE1K,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YA+DhB,oBAAoB;YAkBpB,iBAAiB;YA8DjB,OAAO;IAiBrB,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,WAAW;YAeL,YAAY;IA6D1B,OAAO,CAAC,uBAAuB;CAyB/B"}
|