@vizzly-testing/cli 0.14.0 → 0.15.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 +70 -68
- package/dist/commands/doctor.js +30 -34
- package/dist/commands/finalize.js +24 -23
- package/dist/commands/init.js +30 -28
- package/dist/commands/login.js +49 -55
- package/dist/commands/logout.js +14 -19
- package/dist/commands/project.js +83 -103
- package/dist/commands/run.js +77 -89
- package/dist/commands/status.js +48 -49
- package/dist/commands/tdd-daemon.js +90 -86
- package/dist/commands/tdd.js +59 -88
- package/dist/commands/upload.js +57 -57
- package/dist/commands/whoami.js +40 -45
- package/dist/index.js +2 -5
- package/dist/plugin-loader.js +15 -17
- package/dist/reporter/reporter-bundle.css +1 -1
- package/dist/reporter/reporter-bundle.iife.js +74 -41
- package/dist/sdk/index.js +36 -45
- package/dist/server/handlers/api-handler.js +14 -15
- package/dist/server/handlers/tdd-handler.js +34 -37
- package/dist/server/http-server.js +75 -869
- package/dist/server/middleware/cors.js +22 -0
- package/dist/server/middleware/json-parser.js +35 -0
- package/dist/server/middleware/response.js +79 -0
- package/dist/server/routers/assets.js +91 -0
- package/dist/server/routers/auth.js +144 -0
- package/dist/server/routers/baseline.js +163 -0
- package/dist/server/routers/cloud-proxy.js +146 -0
- package/dist/server/routers/config.js +126 -0
- package/dist/server/routers/dashboard.js +130 -0
- package/dist/server/routers/health.js +61 -0
- package/dist/server/routers/projects.js +168 -0
- package/dist/server/routers/screenshot.js +86 -0
- package/dist/services/auth-service.js +1 -1
- package/dist/services/build-manager.js +13 -40
- package/dist/services/config-service.js +2 -4
- package/dist/services/html-report-generator.js +6 -5
- package/dist/services/index.js +64 -0
- package/dist/services/project-service.js +121 -40
- package/dist/services/screenshot-server.js +9 -9
- package/dist/services/server-manager.js +11 -18
- package/dist/services/static-report-generator.js +3 -4
- package/dist/services/tdd-service.js +246 -103
- package/dist/services/test-runner.js +24 -25
- package/dist/services/uploader.js +5 -4
- package/dist/types/commands/init.d.ts +1 -2
- package/dist/types/index.d.ts +2 -3
- package/dist/types/plugin-loader.d.ts +1 -2
- package/dist/types/reporter/src/api/client.d.ts +178 -0
- package/dist/types/reporter/src/components/app-router.d.ts +1 -3
- package/dist/types/reporter/src/components/code-block.d.ts +4 -0
- package/dist/types/reporter/src/components/comparison/comparison-modes/onion-skin-mode.d.ts +10 -0
- package/dist/types/reporter/src/components/comparison/comparison-modes/overlay-mode.d.ts +11 -0
- package/dist/types/reporter/src/components/comparison/comparison-modes/shared/base-comparison-mode.d.ts +14 -0
- package/dist/types/reporter/src/components/comparison/comparison-modes/shared/image-renderer.d.ts +30 -0
- package/dist/types/reporter/src/components/comparison/comparison-modes/toggle-view.d.ts +8 -0
- package/dist/types/reporter/src/components/comparison/comparison-viewer.d.ts +4 -0
- package/dist/types/reporter/src/components/comparison/screenshot-display.d.ts +16 -0
- package/dist/types/reporter/src/components/design-system/alert.d.ts +9 -0
- package/dist/types/reporter/src/components/design-system/badge.d.ts +17 -0
- package/dist/types/reporter/src/components/design-system/button.d.ts +19 -0
- package/dist/types/reporter/src/components/design-system/card.d.ts +31 -0
- package/dist/types/reporter/src/components/design-system/empty-state.d.ts +13 -0
- package/dist/types/reporter/src/components/design-system/form-controls.d.ts +44 -0
- package/dist/types/reporter/src/components/design-system/health-ring.d.ts +7 -0
- package/dist/types/reporter/src/components/design-system/index.d.ts +11 -0
- package/dist/types/reporter/src/components/design-system/modal.d.ts +10 -0
- package/dist/types/reporter/src/components/design-system/skeleton.d.ts +19 -0
- package/dist/types/reporter/src/components/design-system/spinner.d.ts +10 -0
- package/dist/types/reporter/src/components/design-system/tabs.d.ts +13 -0
- package/dist/types/reporter/src/components/layout/header.d.ts +5 -0
- package/dist/types/reporter/src/components/layout/index.d.ts +2 -0
- package/dist/types/reporter/src/components/layout/layout.d.ts +6 -0
- package/dist/types/reporter/src/components/views/builds-view.d.ts +1 -0
- package/dist/types/reporter/src/components/views/comparison-detail-view.d.ts +1 -4
- package/dist/types/reporter/src/components/views/comparisons-view.d.ts +1 -6
- package/dist/types/reporter/src/components/views/stats-view.d.ts +1 -6
- package/dist/types/reporter/src/components/waiting-for-screenshots.d.ts +1 -0
- package/dist/types/reporter/src/hooks/queries/use-auth-queries.d.ts +15 -0
- package/dist/types/reporter/src/hooks/queries/use-cloud-queries.d.ts +6 -0
- package/dist/types/reporter/src/hooks/queries/use-config-queries.d.ts +6 -0
- package/dist/types/reporter/src/hooks/queries/use-tdd-queries.d.ts +9 -0
- package/dist/types/reporter/src/lib/query-client.d.ts +2 -0
- package/dist/types/reporter/src/lib/query-keys.d.ts +13 -0
- package/dist/types/sdk/index.d.ts +2 -4
- package/dist/types/server/handlers/tdd-handler.d.ts +2 -0
- package/dist/types/server/http-server.d.ts +1 -1
- package/dist/types/server/middleware/cors.d.ts +11 -0
- package/dist/types/server/middleware/json-parser.d.ts +10 -0
- package/dist/types/server/middleware/response.d.ts +50 -0
- package/dist/types/server/routers/assets.d.ts +6 -0
- package/dist/types/server/routers/auth.d.ts +9 -0
- package/dist/types/server/routers/baseline.d.ts +13 -0
- package/dist/types/server/routers/cloud-proxy.d.ts +11 -0
- package/dist/types/server/routers/config.d.ts +9 -0
- package/dist/types/server/routers/dashboard.d.ts +6 -0
- package/dist/types/server/routers/health.d.ts +11 -0
- package/dist/types/server/routers/projects.d.ts +9 -0
- package/dist/types/server/routers/screenshot.d.ts +11 -0
- package/dist/types/services/build-manager.d.ts +4 -3
- package/dist/types/services/config-service.d.ts +2 -3
- package/dist/types/services/index.d.ts +7 -0
- package/dist/types/services/project-service.d.ts +6 -4
- package/dist/types/services/screenshot-server.d.ts +5 -5
- package/dist/types/services/server-manager.d.ts +5 -3
- package/dist/types/services/tdd-service.d.ts +12 -1
- package/dist/types/services/test-runner.d.ts +3 -3
- package/dist/types/utils/output.d.ts +84 -0
- package/dist/utils/config-loader.js +24 -48
- package/dist/utils/global-config.js +2 -17
- package/dist/utils/output.js +445 -0
- package/dist/utils/security.js +3 -4
- package/docs/api-reference.md +0 -1
- package/docs/plugins.md +33 -34
- package/package.json +3 -2
- package/dist/container/index.js +0 -215
- package/dist/services/base-service.js +0 -154
- package/dist/types/container/index.d.ts +0 -59
- package/dist/types/reporter/src/components/comparison/viewer-modes/onion-viewer.d.ts +0 -3
- package/dist/types/reporter/src/components/comparison/viewer-modes/overlay-viewer.d.ts +0 -3
- package/dist/types/reporter/src/components/comparison/viewer-modes/side-by-side-viewer.d.ts +0 -3
- package/dist/types/reporter/src/components/comparison/viewer-modes/toggle-viewer.d.ts +0 -3
- package/dist/types/reporter/src/components/dashboard/dashboard-header.d.ts +0 -5
- package/dist/types/reporter/src/components/dashboard/dashboard-stats.d.ts +0 -4
- package/dist/types/reporter/src/components/dashboard/empty-state.d.ts +0 -8
- package/dist/types/reporter/src/components/ui/form-field.d.ts +0 -16
- package/dist/types/reporter/src/components/ui/status-badge.d.ts +0 -5
- package/dist/types/reporter/src/hooks/use-auth.d.ts +0 -10
- package/dist/types/reporter/src/hooks/use-baseline-actions.d.ts +0 -5
- package/dist/types/reporter/src/hooks/use-config.d.ts +0 -9
- package/dist/types/reporter/src/hooks/use-projects.d.ts +0 -10
- package/dist/types/reporter/src/hooks/use-report-data.d.ts +0 -7
- package/dist/types/reporter/src/hooks/use-vizzly-api.d.ts +0 -9
- package/dist/types/services/base-service.d.ts +0 -71
- package/dist/types/utils/console-ui.d.ts +0 -61
- package/dist/types/utils/logger-factory.d.ts +0 -26
- package/dist/types/utils/logger.d.ts +0 -79
- package/dist/utils/console-ui.js +0 -241
- package/dist/utils/logger-factory.js +0 -76
- package/dist/utils/logger.js +0 -231
|
@@ -2,7 +2,7 @@ import { writeFileSync, readFileSync, existsSync, unlinkSync, mkdirSync } from '
|
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
import { homedir } from 'os';
|
|
4
4
|
import { spawn } from 'child_process';
|
|
5
|
-
import
|
|
5
|
+
import * as output from '../utils/output.js';
|
|
6
6
|
import { tddCommand } from './tdd.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -11,7 +11,7 @@ import { tddCommand } from './tdd.js';
|
|
|
11
11
|
* @param {Object} globalOptions - Global CLI options
|
|
12
12
|
*/
|
|
13
13
|
export async function tddStartCommand(options = {}, globalOptions = {}) {
|
|
14
|
-
|
|
14
|
+
output.configure({
|
|
15
15
|
json: globalOptions.json,
|
|
16
16
|
verbose: globalOptions.verbose,
|
|
17
17
|
color: !globalOptions.noColor
|
|
@@ -19,9 +19,9 @@ export async function tddStartCommand(options = {}, globalOptions = {}) {
|
|
|
19
19
|
|
|
20
20
|
// Check if server already running
|
|
21
21
|
if (await isServerRunning(options.port || 47392)) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
let port = options.port || 47392;
|
|
23
|
+
output.info(`TDD server already running at http://localhost:${port}`);
|
|
24
|
+
output.info(`Dashboard: http://localhost:${port}/dashboard`);
|
|
25
25
|
if (options.open) {
|
|
26
26
|
openDashboard(port);
|
|
27
27
|
}
|
|
@@ -29,21 +29,21 @@ export async function tddStartCommand(options = {}, globalOptions = {}) {
|
|
|
29
29
|
}
|
|
30
30
|
try {
|
|
31
31
|
// Ensure .vizzly directory exists
|
|
32
|
-
|
|
32
|
+
let vizzlyDir = join(process.cwd(), '.vizzly');
|
|
33
33
|
if (!existsSync(vizzlyDir)) {
|
|
34
34
|
mkdirSync(vizzlyDir, {
|
|
35
35
|
recursive: true
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
|
-
|
|
38
|
+
let port = options.port || 47392;
|
|
39
39
|
|
|
40
40
|
// Show loading indicator if downloading baselines (but not in verbose mode since child shows progress)
|
|
41
41
|
if (options.baselineBuild && !globalOptions.verbose) {
|
|
42
|
-
|
|
42
|
+
output.startSpinner(`Downloading baselines from build ${options.baselineBuild}...`);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
// Spawn child process with stdio inherited during init for direct error visibility
|
|
46
|
-
|
|
46
|
+
let child = spawn(process.execPath, [process.argv[1],
|
|
47
47
|
// CLI entry point
|
|
48
48
|
'tdd', 'start', '--daemon-child',
|
|
49
49
|
// Special flag for child process
|
|
@@ -72,18 +72,22 @@ export async function tddStartCommand(options = {}, globalOptions = {}) {
|
|
|
72
72
|
});
|
|
73
73
|
|
|
74
74
|
// Timeout after 30 seconds to prevent indefinite wait
|
|
75
|
-
setTimeout(() => {
|
|
75
|
+
let timeoutId = setTimeout(() => {
|
|
76
76
|
if (!initComplete && !initFailed) {
|
|
77
77
|
initFailed = true;
|
|
78
78
|
resolve();
|
|
79
79
|
}
|
|
80
80
|
}, 30000);
|
|
81
|
+
|
|
82
|
+
// Clear timeout if we resolve early
|
|
83
|
+
child.on('disconnect', () => clearTimeout(timeoutId));
|
|
84
|
+
child.on('exit', () => clearTimeout(timeoutId));
|
|
81
85
|
});
|
|
82
86
|
if (initFailed) {
|
|
83
87
|
if (options.baselineBuild && !globalOptions.verbose) {
|
|
84
|
-
|
|
88
|
+
output.stopSpinner();
|
|
85
89
|
}
|
|
86
|
-
|
|
90
|
+
output.error('TDD server failed to start');
|
|
87
91
|
process.exit(1);
|
|
88
92
|
}
|
|
89
93
|
|
|
@@ -91,32 +95,32 @@ export async function tddStartCommand(options = {}, globalOptions = {}) {
|
|
|
91
95
|
child.unref();
|
|
92
96
|
|
|
93
97
|
// Verify server started with retries
|
|
94
|
-
|
|
95
|
-
|
|
98
|
+
let maxRetries = 10;
|
|
99
|
+
let retryDelay = 200; // Start with 200ms
|
|
96
100
|
let running = false;
|
|
97
101
|
for (let i = 0; i < maxRetries && !running; i++) {
|
|
98
102
|
await new Promise(resolve => setTimeout(resolve, retryDelay * (i + 1)));
|
|
99
103
|
running = await isServerRunning(port);
|
|
100
104
|
}
|
|
101
105
|
if (options.baselineBuild && !globalOptions.verbose) {
|
|
102
|
-
|
|
106
|
+
output.stopSpinner();
|
|
103
107
|
}
|
|
104
108
|
if (!running) {
|
|
105
|
-
|
|
109
|
+
output.error('Failed to start TDD server - server not responding to health checks');
|
|
106
110
|
process.exit(1);
|
|
107
111
|
}
|
|
108
|
-
|
|
112
|
+
output.success(`TDD server started at http://localhost:${port}`);
|
|
109
113
|
|
|
110
114
|
// Write server info to global location for SDK discovery (iOS/Swift can read this)
|
|
111
115
|
try {
|
|
112
|
-
|
|
116
|
+
let globalVizzlyDir = join(homedir(), '.vizzly');
|
|
113
117
|
if (!existsSync(globalVizzlyDir)) {
|
|
114
118
|
mkdirSync(globalVizzlyDir, {
|
|
115
119
|
recursive: true
|
|
116
120
|
});
|
|
117
121
|
}
|
|
118
|
-
|
|
119
|
-
|
|
122
|
+
let globalServerFile = join(globalVizzlyDir, 'server.json');
|
|
123
|
+
let serverInfo = {
|
|
120
124
|
pid: child.pid,
|
|
121
125
|
port: port.toString(),
|
|
122
126
|
startTime: Date.now()
|
|
@@ -125,27 +129,27 @@ export async function tddStartCommand(options = {}, globalOptions = {}) {
|
|
|
125
129
|
} catch {
|
|
126
130
|
// Non-fatal, SDK can still use health check
|
|
127
131
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
132
|
+
output.blank();
|
|
133
|
+
output.info('Dashboard:');
|
|
134
|
+
output.info(` http://localhost:${port}/`);
|
|
135
|
+
output.blank();
|
|
136
|
+
output.info('Available views:');
|
|
137
|
+
output.info(` Comparisons: http://localhost:${port}/`);
|
|
138
|
+
output.info(` Stats: http://localhost:${port}/stats`);
|
|
139
|
+
output.info(` Settings: http://localhost:${port}/settings`);
|
|
140
|
+
output.info(` Projects: http://localhost:${port}/projects`);
|
|
141
|
+
output.blank();
|
|
142
|
+
output.info('Next steps:');
|
|
143
|
+
output.info(' 1. Run your tests in watch mode (e.g., npm test -- --watch)');
|
|
144
|
+
output.info(' 2. View live visual comparisons in the dashboard');
|
|
145
|
+
output.info(' 3. Accept/reject baselines directly in the UI');
|
|
146
|
+
output.blank();
|
|
147
|
+
output.info('Stop server: npx vizzly dev stop');
|
|
144
148
|
if (options.open) {
|
|
145
149
|
openDashboard(port);
|
|
146
150
|
}
|
|
147
151
|
} catch (error) {
|
|
148
|
-
|
|
152
|
+
output.error('Failed to start TDD daemon', error);
|
|
149
153
|
process.exit(1);
|
|
150
154
|
}
|
|
151
155
|
}
|
|
@@ -156,11 +160,11 @@ export async function tddStartCommand(options = {}, globalOptions = {}) {
|
|
|
156
160
|
* @private
|
|
157
161
|
*/
|
|
158
162
|
export async function runDaemonChild(options = {}, globalOptions = {}) {
|
|
159
|
-
|
|
160
|
-
|
|
163
|
+
let vizzlyDir = join(process.cwd(), '.vizzly');
|
|
164
|
+
let port = options.port || 47392;
|
|
161
165
|
try {
|
|
162
166
|
// Use existing tddCommand but with daemon mode
|
|
163
|
-
|
|
167
|
+
let {
|
|
164
168
|
cleanup
|
|
165
169
|
} = await tddCommand(null,
|
|
166
170
|
// No test command - server only
|
|
@@ -175,9 +179,9 @@ export async function runDaemonChild(options = {}, globalOptions = {}) {
|
|
|
175
179
|
}
|
|
176
180
|
|
|
177
181
|
// Store our PID for the stop command
|
|
178
|
-
|
|
182
|
+
let pidFile = join(vizzlyDir, 'server.pid');
|
|
179
183
|
writeFileSync(pidFile, process.pid.toString());
|
|
180
|
-
|
|
184
|
+
let serverInfo = {
|
|
181
185
|
pid: process.pid,
|
|
182
186
|
port: port,
|
|
183
187
|
startTime: Date.now()
|
|
@@ -185,16 +189,16 @@ export async function runDaemonChild(options = {}, globalOptions = {}) {
|
|
|
185
189
|
writeFileSync(join(vizzlyDir, 'server.json'), JSON.stringify(serverInfo, null, 2));
|
|
186
190
|
|
|
187
191
|
// Set up graceful shutdown
|
|
188
|
-
|
|
192
|
+
let handleShutdown = async () => {
|
|
189
193
|
try {
|
|
190
194
|
// Clean up PID files
|
|
191
195
|
if (existsSync(pidFile)) unlinkSync(pidFile);
|
|
192
|
-
|
|
196
|
+
let serverFile = join(vizzlyDir, 'server.json');
|
|
193
197
|
if (existsSync(serverFile)) unlinkSync(serverFile);
|
|
194
198
|
|
|
195
199
|
// Clean up global server file
|
|
196
200
|
try {
|
|
197
|
-
|
|
201
|
+
let globalServerFile = join(homedir(), '.vizzly', 'server.json');
|
|
198
202
|
if (existsSync(globalServerFile)) unlinkSync(globalServerFile);
|
|
199
203
|
} catch {
|
|
200
204
|
// Non-fatal
|
|
@@ -227,14 +231,14 @@ export async function runDaemonChild(options = {}, globalOptions = {}) {
|
|
|
227
231
|
* @param {Object} globalOptions - Global CLI options
|
|
228
232
|
*/
|
|
229
233
|
export async function tddStopCommand(options = {}, globalOptions = {}) {
|
|
230
|
-
|
|
234
|
+
output.configure({
|
|
231
235
|
json: globalOptions.json,
|
|
232
236
|
verbose: globalOptions.verbose,
|
|
233
237
|
color: !globalOptions.noColor
|
|
234
238
|
});
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
239
|
+
let vizzlyDir = join(process.cwd(), '.vizzly');
|
|
240
|
+
let pidFile = join(vizzlyDir, 'server.pid');
|
|
241
|
+
let serverFile = join(vizzlyDir, 'server.json');
|
|
238
242
|
|
|
239
243
|
// First try to find process by PID file
|
|
240
244
|
let pid = null;
|
|
@@ -247,10 +251,10 @@ export async function tddStopCommand(options = {}, globalOptions = {}) {
|
|
|
247
251
|
}
|
|
248
252
|
|
|
249
253
|
// If no PID file or invalid, try to find by port using lsof
|
|
250
|
-
|
|
254
|
+
let port = options.port || 47392;
|
|
251
255
|
if (!pid) {
|
|
252
256
|
try {
|
|
253
|
-
|
|
257
|
+
let lsofProcess = spawn('lsof', ['-ti', `:${port}`], {
|
|
254
258
|
stdio: 'pipe'
|
|
255
259
|
});
|
|
256
260
|
let lsofOutput = '';
|
|
@@ -260,7 +264,7 @@ export async function tddStopCommand(options = {}, globalOptions = {}) {
|
|
|
260
264
|
await new Promise(resolve => {
|
|
261
265
|
lsofProcess.on('close', code => {
|
|
262
266
|
if (code === 0 && lsofOutput.trim()) {
|
|
263
|
-
|
|
267
|
+
let foundPid = parseInt(lsofOutput.trim().split('\n')[0], 10);
|
|
264
268
|
if (foundPid && !isNaN(foundPid)) {
|
|
265
269
|
pid = foundPid;
|
|
266
270
|
}
|
|
@@ -277,7 +281,7 @@ export async function tddStopCommand(options = {}, globalOptions = {}) {
|
|
|
277
281
|
}
|
|
278
282
|
}
|
|
279
283
|
if (!pid) {
|
|
280
|
-
|
|
284
|
+
output.warn('No TDD server running');
|
|
281
285
|
|
|
282
286
|
// Clean up any stale files
|
|
283
287
|
if (existsSync(pidFile)) unlinkSync(pidFile);
|
|
@@ -287,7 +291,7 @@ export async function tddStopCommand(options = {}, globalOptions = {}) {
|
|
|
287
291
|
try {
|
|
288
292
|
// Try to kill the process gracefully
|
|
289
293
|
process.kill(pid, 'SIGTERM');
|
|
290
|
-
|
|
294
|
+
output.info(`Stopping TDD server (PID: ${pid})...`);
|
|
291
295
|
|
|
292
296
|
// Give it a moment to shut down gracefully
|
|
293
297
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
@@ -297,7 +301,7 @@ export async function tddStopCommand(options = {}, globalOptions = {}) {
|
|
|
297
301
|
process.kill(pid, 0); // Just check if process exists
|
|
298
302
|
// If we get here, process is still running, force kill it
|
|
299
303
|
process.kill(pid, 'SIGKILL');
|
|
300
|
-
|
|
304
|
+
output.info('Force killed TDD server');
|
|
301
305
|
} catch {
|
|
302
306
|
// Process is gone, which is what we want
|
|
303
307
|
}
|
|
@@ -305,15 +309,15 @@ export async function tddStopCommand(options = {}, globalOptions = {}) {
|
|
|
305
309
|
// Clean up files
|
|
306
310
|
if (existsSync(pidFile)) unlinkSync(pidFile);
|
|
307
311
|
if (existsSync(serverFile)) unlinkSync(serverFile);
|
|
308
|
-
|
|
312
|
+
output.success('TDD server stopped');
|
|
309
313
|
} catch (error) {
|
|
310
314
|
if (error.code === 'ESRCH') {
|
|
311
315
|
// Process not found - clean up stale files
|
|
312
|
-
|
|
316
|
+
output.warn('TDD server was not running (cleaning up stale files)');
|
|
313
317
|
if (existsSync(pidFile)) unlinkSync(pidFile);
|
|
314
318
|
if (existsSync(serverFile)) unlinkSync(serverFile);
|
|
315
319
|
} else {
|
|
316
|
-
|
|
320
|
+
output.error('Error stopping TDD server', error);
|
|
317
321
|
}
|
|
318
322
|
}
|
|
319
323
|
}
|
|
@@ -324,20 +328,20 @@ export async function tddStopCommand(options = {}, globalOptions = {}) {
|
|
|
324
328
|
* @param {Object} globalOptions - Global CLI options
|
|
325
329
|
*/
|
|
326
330
|
export async function tddStatusCommand(options, globalOptions = {}) {
|
|
327
|
-
|
|
331
|
+
output.configure({
|
|
328
332
|
json: globalOptions.json,
|
|
329
333
|
verbose: globalOptions.verbose,
|
|
330
334
|
color: !globalOptions.noColor
|
|
331
335
|
});
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
336
|
+
let vizzlyDir = join(process.cwd(), '.vizzly');
|
|
337
|
+
let pidFile = join(vizzlyDir, 'server.pid');
|
|
338
|
+
let serverFile = join(vizzlyDir, 'server.json');
|
|
335
339
|
if (!existsSync(pidFile)) {
|
|
336
|
-
|
|
340
|
+
output.info('TDD server not running');
|
|
337
341
|
return;
|
|
338
342
|
}
|
|
339
343
|
try {
|
|
340
|
-
|
|
344
|
+
let pid = parseInt(readFileSync(pidFile, 'utf8').trim(), 10);
|
|
341
345
|
|
|
342
346
|
// Check if process is actually running
|
|
343
347
|
process.kill(pid, 0); // Signal 0 just checks if process exists
|
|
@@ -350,40 +354,40 @@ export async function tddStatusCommand(options, globalOptions = {}) {
|
|
|
350
354
|
}
|
|
351
355
|
|
|
352
356
|
// Try to check health endpoint
|
|
353
|
-
|
|
357
|
+
let health = await checkServerHealth(serverInfo.port);
|
|
354
358
|
if (health.running) {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
359
|
+
output.success(`TDD server running (PID: ${pid})`);
|
|
360
|
+
output.info(`Dashboard: http://localhost:${serverInfo.port}/`);
|
|
361
|
+
output.blank();
|
|
362
|
+
output.info('Available views:');
|
|
363
|
+
output.info(` Comparisons: http://localhost:${serverInfo.port}/`);
|
|
364
|
+
output.info(` Stats: http://localhost:${serverInfo.port}/stats`);
|
|
365
|
+
output.info(` Settings: http://localhost:${serverInfo.port}/settings`);
|
|
366
|
+
output.info(` Projects: http://localhost:${serverInfo.port}/projects`);
|
|
363
367
|
if (serverInfo.startTime) {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
+
let uptime = Math.floor((Date.now() - serverInfo.startTime) / 1000);
|
|
369
|
+
let hours = Math.floor(uptime / 3600);
|
|
370
|
+
let minutes = Math.floor(uptime % 3600 / 60);
|
|
371
|
+
let seconds = uptime % 60;
|
|
368
372
|
let uptimeStr = '';
|
|
369
373
|
if (hours > 0) uptimeStr += `${hours}h `;
|
|
370
374
|
if (minutes > 0 || hours > 0) uptimeStr += `${minutes}m `;
|
|
371
375
|
uptimeStr += `${seconds}s`;
|
|
372
|
-
|
|
373
|
-
|
|
376
|
+
output.blank();
|
|
377
|
+
output.info(`Uptime: ${uptimeStr}`);
|
|
374
378
|
}
|
|
375
379
|
} else {
|
|
376
|
-
|
|
380
|
+
output.warn('TDD server process exists but not responding to health checks');
|
|
377
381
|
}
|
|
378
382
|
} catch (error) {
|
|
379
383
|
if (error.code === 'ESRCH') {
|
|
380
|
-
|
|
384
|
+
output.warn('TDD server process not found (cleaning up stale files)');
|
|
381
385
|
unlinkSync(pidFile);
|
|
382
386
|
if (existsSync(serverFile)) {
|
|
383
387
|
unlinkSync(serverFile);
|
|
384
388
|
}
|
|
385
389
|
} else {
|
|
386
|
-
|
|
390
|
+
output.error('Error checking TDD server status', error);
|
|
387
391
|
}
|
|
388
392
|
}
|
|
389
393
|
}
|
|
@@ -394,7 +398,7 @@ export async function tddStatusCommand(options, globalOptions = {}) {
|
|
|
394
398
|
*/
|
|
395
399
|
async function isServerRunning(port = 47392) {
|
|
396
400
|
try {
|
|
397
|
-
|
|
401
|
+
let health = await checkServerHealth(port);
|
|
398
402
|
return health.running;
|
|
399
403
|
} catch {
|
|
400
404
|
return false;
|
|
@@ -407,8 +411,8 @@ async function isServerRunning(port = 47392) {
|
|
|
407
411
|
*/
|
|
408
412
|
async function checkServerHealth(port = 47392) {
|
|
409
413
|
try {
|
|
410
|
-
|
|
411
|
-
|
|
414
|
+
let response = await fetch(`http://localhost:${port}/health`);
|
|
415
|
+
let data = await response.json();
|
|
412
416
|
return {
|
|
413
417
|
running: response.ok,
|
|
414
418
|
port: data.port,
|
|
@@ -426,7 +430,7 @@ async function checkServerHealth(port = 47392) {
|
|
|
426
430
|
* @private
|
|
427
431
|
*/
|
|
428
432
|
function openDashboard(port = 47392) {
|
|
429
|
-
|
|
433
|
+
let url = `http://localhost:${port}/dashboard`;
|
|
430
434
|
|
|
431
435
|
// Cross-platform open command
|
|
432
436
|
let openCmd;
|