feat: build CLI core framework with Commander.js
Add CLI entry point with Commander.js, config management (~/.mcpctl/config.json with Zod validation), output formatters (table/json/yaml), config and status commands with dependency injection for testing. Fix sanitizeString regex ordering. 67 tests passing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
63
src/cli/src/commands/status.ts
Normal file
63
src/cli/src/commands/status.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { Command } from 'commander';
|
||||
import http from 'node:http';
|
||||
import { loadConfig } from '../config/index.js';
|
||||
import type { ConfigLoaderDeps } from '../config/index.js';
|
||||
import { formatJson, formatYaml } from '../formatters/index.js';
|
||||
import { APP_VERSION } from '@mcpctl/shared';
|
||||
|
||||
export interface StatusCommandDeps {
|
||||
configDeps: Partial<ConfigLoaderDeps>;
|
||||
log: (...args: string[]) => void;
|
||||
checkDaemon: (url: string) => Promise<boolean>;
|
||||
}
|
||||
|
||||
function defaultCheckDaemon(url: string): Promise<boolean> {
|
||||
return new Promise((resolve) => {
|
||||
const req = http.get(`${url}/health`, { timeout: 3000 }, (res) => {
|
||||
resolve(res.statusCode !== undefined && res.statusCode >= 200 && res.statusCode < 400);
|
||||
res.resume();
|
||||
});
|
||||
req.on('error', () => resolve(false));
|
||||
req.on('timeout', () => {
|
||||
req.destroy();
|
||||
resolve(false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const defaultDeps: StatusCommandDeps = {
|
||||
configDeps: {},
|
||||
log: (...args) => console.log(...args),
|
||||
checkDaemon: defaultCheckDaemon,
|
||||
};
|
||||
|
||||
export function createStatusCommand(deps?: Partial<StatusCommandDeps>): Command {
|
||||
const { configDeps, log, checkDaemon } = { ...defaultDeps, ...deps };
|
||||
|
||||
return new Command('status')
|
||||
.description('Show mcpctl status and connectivity')
|
||||
.option('-o, --output <format>', 'output format (table, json, yaml)', 'table')
|
||||
.action(async (opts: { output: string }) => {
|
||||
const config = loadConfig(configDeps);
|
||||
const daemonReachable = await checkDaemon(config.daemonUrl);
|
||||
|
||||
const status = {
|
||||
version: APP_VERSION,
|
||||
daemonUrl: config.daemonUrl,
|
||||
daemonReachable,
|
||||
registries: config.registries,
|
||||
outputFormat: config.outputFormat,
|
||||
};
|
||||
|
||||
if (opts.output === 'json') {
|
||||
log(formatJson(status));
|
||||
} else if (opts.output === 'yaml') {
|
||||
log(formatYaml(status));
|
||||
} else {
|
||||
log(`mcpctl v${status.version}`);
|
||||
log(`Daemon: ${status.daemonUrl} (${daemonReachable ? 'connected' : 'unreachable'})`);
|
||||
log(`Registries: ${status.registries.join(', ')}`);
|
||||
log(`Output: ${status.outputFormat}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user