ops-toolkit 1.1.0 → 1.2.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/.release-it.json +2 -2
- package/CHANGELOG.md +2 -0
- package/README.md +258 -31
- package/bin/ops-toolkit.ts +4 -87
- package/dist/bin/ops-toolkit.js +11416 -0
- package/dist/index.js +10673 -2983
- package/docs/API.md +850 -0
- package/docs/ARCHITECTURE.md +433 -0
- package/docs/DEVELOPMENT.md +554 -0
- package/package.json +7 -7
- package/src/cli/app.ts +188 -0
- package/src/cli/command-discovery.ts +212 -0
- package/src/cli/command-registry.ts +136 -0
- package/src/commands/monitor/index.ts +199 -58
- package/src/index.ts +4 -77
- package/src/types/ui.ts +3 -3
- package/src/utils/config.ts +385 -64
- package/src/utils/error-handlers.ts +94 -0
- package/src/utils/error-reporter.ts +234 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/logger.ts +418 -22
- package/src/utils/system.ts +26 -3
package/src/cli/app.ts
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
import { Config } from '@/utils/config';
|
|
4
|
+
import { setupErrorHandlers } from '@/utils/error-handlers';
|
|
5
|
+
import { Logger } from '@/utils/logger';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import { program } from 'commander';
|
|
8
|
+
import figlet from 'figlet';
|
|
9
|
+
import { CommandDiscovery } from './command-discovery';
|
|
10
|
+
import { CommandRegistry, type CommandDefinition } from './command-registry';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* CLI应用程序主入口
|
|
14
|
+
* 统一处理CLI启动、命令注册和错误处理
|
|
15
|
+
*/
|
|
16
|
+
export class CLIApp {
|
|
17
|
+
private version: string;
|
|
18
|
+
private commandRegistry: CommandRegistry;
|
|
19
|
+
|
|
20
|
+
constructor(version: string = '1.2.0') {
|
|
21
|
+
this.version = version;
|
|
22
|
+
this.commandRegistry = new CommandRegistry(program);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 初始化CLI应用
|
|
27
|
+
*/
|
|
28
|
+
public async initialize(): Promise<void> {
|
|
29
|
+
this.setupProgram();
|
|
30
|
+
await this.registerCommands();
|
|
31
|
+
setupErrorHandlers();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 初始化程序配置
|
|
36
|
+
*/
|
|
37
|
+
private setupProgram(): void {
|
|
38
|
+
program.name('ops').description('全面的DevOps CLI工具包').version(this.version);
|
|
39
|
+
|
|
40
|
+
// 全局选项
|
|
41
|
+
program
|
|
42
|
+
.option('-d, --debug', '启用调试模式', false)
|
|
43
|
+
.option('-v, --verbose', '启用详细日志', false);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 注册所有命令
|
|
48
|
+
*/
|
|
49
|
+
private async registerCommands(): Promise<void> {
|
|
50
|
+
// 注册基础命令
|
|
51
|
+
const commands = this.getAllCommands();
|
|
52
|
+
this.commandRegistry.registerMultiple(commands);
|
|
53
|
+
|
|
54
|
+
// 发现并注册命令目录中的命令
|
|
55
|
+
const discovery = new CommandDiscovery(this.commandRegistry);
|
|
56
|
+
await discovery.discoverAndRegister();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* 获取所有命令定义
|
|
61
|
+
*/
|
|
62
|
+
private getAllCommands(): CommandDefinition[] {
|
|
63
|
+
return [
|
|
64
|
+
{
|
|
65
|
+
name: 'ui',
|
|
66
|
+
description: '启动交互式终端界面',
|
|
67
|
+
action: async () => {
|
|
68
|
+
await this.handleUICommand();
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
name: 'monitor',
|
|
73
|
+
description: '系统监控',
|
|
74
|
+
action: async () => {
|
|
75
|
+
await this.handleMonitorCommand();
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: 'logs',
|
|
80
|
+
description: '日志管理',
|
|
81
|
+
action: async () => {
|
|
82
|
+
await this.handleLogsCommand();
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: 'deploy',
|
|
87
|
+
description: '部署工具',
|
|
88
|
+
action: async () => {
|
|
89
|
+
await this.handleDeployCommand();
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
name: 'system',
|
|
94
|
+
description: '系统管理',
|
|
95
|
+
action: async () => {
|
|
96
|
+
await this.handleSystemCommand();
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* 显示欢迎信息
|
|
104
|
+
*/
|
|
105
|
+
private showWelcome(): void {
|
|
106
|
+
const welcomeText = figlet.textSync('ops-toolkit', {
|
|
107
|
+
font: 'Standard',
|
|
108
|
+
horizontalLayout: 'default',
|
|
109
|
+
verticalLayout: 'default',
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
console.log(chalk.cyan(welcomeText));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* 处理UI命令
|
|
117
|
+
*/
|
|
118
|
+
private async handleUICommand(): Promise<void> {
|
|
119
|
+
this.showWelcome();
|
|
120
|
+
console.log(chalk.green('🚀 ops-toolkit CLI正在运行!'));
|
|
121
|
+
console.log(chalk.blue('📋 可用命令:'));
|
|
122
|
+
console.log(chalk.white(' ops monitor - 系统监控'));
|
|
123
|
+
console.log(chalk.white(' ops logs - 日志管理'));
|
|
124
|
+
console.log(chalk.white(' ops deploy - 部署工具'));
|
|
125
|
+
console.log(chalk.white(' ops system - 系统管理'));
|
|
126
|
+
console.log(chalk.gray('\n🔧 UI功能即将推出...'));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* 处理监控命令
|
|
131
|
+
*/
|
|
132
|
+
private async handleMonitorCommand(): Promise<void> {
|
|
133
|
+
console.log(chalk.blue('📊 系统监控'));
|
|
134
|
+
console.log(chalk.yellow('⚠️ 监控功能即将推出...'));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* 处理日志命令
|
|
139
|
+
*/
|
|
140
|
+
private async handleLogsCommand(): Promise<void> {
|
|
141
|
+
console.log(chalk.blue('📋 日志管理'));
|
|
142
|
+
console.log(chalk.yellow('⚠️ 日志管理功能即将推出...'));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* 处理部署命令
|
|
147
|
+
*/
|
|
148
|
+
private async handleDeployCommand(): Promise<void> {
|
|
149
|
+
console.log(chalk.blue('🚀 部署工具'));
|
|
150
|
+
console.log(chalk.yellow('⚠️ 部署功能即将推出...'));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* 处理系统命令
|
|
155
|
+
*/
|
|
156
|
+
private async handleSystemCommand(): Promise<void> {
|
|
157
|
+
console.log(chalk.blue('⚙️ 系统管理'));
|
|
158
|
+
console.log(chalk.yellow('⚠️ 系统管理功能即将推出...'));
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* 启动CLI应用程序
|
|
163
|
+
*/
|
|
164
|
+
public async start(): Promise<void> {
|
|
165
|
+
try {
|
|
166
|
+
program.parse();
|
|
167
|
+
} catch (error) {
|
|
168
|
+
Logger.error('CLI启动失败');
|
|
169
|
+
if (error instanceof Error) {
|
|
170
|
+
Logger.error('错误详情', error);
|
|
171
|
+
}
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* 创建并启动CLI应用程序
|
|
179
|
+
*/
|
|
180
|
+
export async function createCLI(): Promise<void> {
|
|
181
|
+
await Config.initialize();
|
|
182
|
+
const config = Config.get();
|
|
183
|
+
const version = config?.version || '1.2.0';
|
|
184
|
+
|
|
185
|
+
const app = new CLIApp(version);
|
|
186
|
+
await app.initialize();
|
|
187
|
+
await app.start();
|
|
188
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { readdirSync, statSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { CommandRegistry, type CommandDefinition } from './command-registry';
|
|
4
|
+
import { Logger } from '@/utils/logger';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 命令发现器
|
|
8
|
+
* 自动发现并加载命令模块
|
|
9
|
+
*/
|
|
10
|
+
export class CommandDiscovery {
|
|
11
|
+
private commandRegistry: CommandRegistry;
|
|
12
|
+
private commandsDir: string;
|
|
13
|
+
|
|
14
|
+
constructor(
|
|
15
|
+
commandRegistry: CommandRegistry,
|
|
16
|
+
commandsDir: string = join(__dirname, '../commands')
|
|
17
|
+
) {
|
|
18
|
+
this.commandRegistry = commandRegistry;
|
|
19
|
+
this.commandsDir = commandsDir;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 发现并注册所有命令
|
|
24
|
+
*/
|
|
25
|
+
public async discoverAndRegister(): Promise<void> {
|
|
26
|
+
try {
|
|
27
|
+
const commandModules = await this.discoverCommandModules();
|
|
28
|
+
|
|
29
|
+
for (const modulePath of commandModules) {
|
|
30
|
+
try {
|
|
31
|
+
const commandModule = await import(modulePath);
|
|
32
|
+
await this.registerCommandFromModule(commandModule, modulePath);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
Logger.error(`加载命令模块失败: ${modulePath}`, error);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
} catch (error) {
|
|
38
|
+
Logger.error('命令发现过程失败', error);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 发现命令模块
|
|
44
|
+
*/
|
|
45
|
+
private async discoverCommandModules(): Promise<string[]> {
|
|
46
|
+
const modules: string[] = [];
|
|
47
|
+
|
|
48
|
+
if (!this.directoryExists(this.commandsDir)) {
|
|
49
|
+
Logger.warning(`命令目录不存在: ${this.commandsDir}`);
|
|
50
|
+
return modules;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const entries = readdirSync(this.commandsDir, { withFileTypes: true });
|
|
54
|
+
|
|
55
|
+
for (const entry of entries) {
|
|
56
|
+
const fullPath = join(this.commandsDir, entry.name);
|
|
57
|
+
|
|
58
|
+
if (entry.isDirectory()) {
|
|
59
|
+
// 查找目录中的 index.ts 或 index.js 文件
|
|
60
|
+
const indexFile = this.findIndexFile(fullPath);
|
|
61
|
+
if (indexFile) {
|
|
62
|
+
modules.push(indexFile);
|
|
63
|
+
}
|
|
64
|
+
} else if (this.isCommandFile(entry.name)) {
|
|
65
|
+
// 直接的命令文件
|
|
66
|
+
modules.push(fullPath);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return modules;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* 查找目录中的索引文件
|
|
75
|
+
*/
|
|
76
|
+
private findIndexFile(dirPath: string): string | null {
|
|
77
|
+
const possibleFiles = ['index.ts', 'index.js'];
|
|
78
|
+
|
|
79
|
+
for (const file of possibleFiles) {
|
|
80
|
+
const filePath = join(dirPath, file);
|
|
81
|
+
if (this.fileExists(filePath)) {
|
|
82
|
+
return filePath;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* 检查是否为命令文件
|
|
91
|
+
*/
|
|
92
|
+
private isCommandFile(filename: string): boolean {
|
|
93
|
+
return (
|
|
94
|
+
/\.(ts|js)$/.test(filename) &&
|
|
95
|
+
!filename.startsWith('.') &&
|
|
96
|
+
!filename.includes('.test.') &&
|
|
97
|
+
!filename.includes('.spec.')
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* 从模块注册命令
|
|
103
|
+
*/
|
|
104
|
+
private async registerCommandFromModule(
|
|
105
|
+
commandModule: unknown,
|
|
106
|
+
modulePath: string
|
|
107
|
+
): Promise<void> {
|
|
108
|
+
try {
|
|
109
|
+
const moduleObj = commandModule as Record<string, unknown>;
|
|
110
|
+
// 支持多种导出方式
|
|
111
|
+
let commandDef: CommandDefinition | undefined;
|
|
112
|
+
|
|
113
|
+
if (moduleObj.default && typeof moduleObj.default === 'object') {
|
|
114
|
+
// 默认导出对象
|
|
115
|
+
commandDef = moduleObj.default as CommandDefinition;
|
|
116
|
+
} else if (moduleObj.Command && typeof moduleObj.Command === 'object') {
|
|
117
|
+
// 命名导出 Command
|
|
118
|
+
commandDef = moduleObj.Command as CommandDefinition;
|
|
119
|
+
} else if (typeof commandModule === 'function') {
|
|
120
|
+
// 函数导出,转换为命令定义
|
|
121
|
+
commandDef = this.createCommandFromFunction(
|
|
122
|
+
commandModule as (...args: unknown[]) => void,
|
|
123
|
+
modulePath
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (commandDef && this.validateCommandDefinition(commandDef)) {
|
|
128
|
+
this.commandRegistry.register(commandDef);
|
|
129
|
+
Logger.info(`已注册命令: ${commandDef.name}`);
|
|
130
|
+
} else {
|
|
131
|
+
Logger.warning(`跳过无效的命令模块: ${modulePath}`);
|
|
132
|
+
}
|
|
133
|
+
} catch (error) {
|
|
134
|
+
Logger.error(`注册命令失败: ${modulePath}`, error);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* 从函数创建命令定义
|
|
140
|
+
*/
|
|
141
|
+
private createCommandFromFunction(
|
|
142
|
+
commandFn: (...args: unknown[]) => void,
|
|
143
|
+
modulePath: string
|
|
144
|
+
): CommandDefinition | undefined {
|
|
145
|
+
const commandName = this.extractCommandNameFromPath(modulePath);
|
|
146
|
+
|
|
147
|
+
if (!commandName) {
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
name: commandName,
|
|
153
|
+
description: `${commandName} 命令`,
|
|
154
|
+
action: async () => {
|
|
155
|
+
await commandFn();
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* 从文件路径提取命令名称
|
|
162
|
+
*/
|
|
163
|
+
private extractCommandNameFromPath(modulePath: string): string | null {
|
|
164
|
+
const parts = modulePath.split('/');
|
|
165
|
+
const lastPart = parts[parts.length - 1];
|
|
166
|
+
|
|
167
|
+
if (!lastPart) {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (lastPart === 'index.ts' || lastPart === 'index.js') {
|
|
172
|
+
// 从父目录名称提取
|
|
173
|
+
const parentDir = parts[parts.length - 2];
|
|
174
|
+
return parentDir || null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// 从文件名提取
|
|
178
|
+
const nameWithoutExt = lastPart.replace(/\.(ts|js)$/, '');
|
|
179
|
+
return nameWithoutExt || null;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* 验证命令定义
|
|
184
|
+
*/
|
|
185
|
+
private validateCommandDefinition(commandDef: CommandDefinition): boolean {
|
|
186
|
+
return !!(commandDef.name && commandDef.description && typeof commandDef.action === 'function');
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* 检查目录是否存在
|
|
191
|
+
*/
|
|
192
|
+
private directoryExists(path: string): boolean {
|
|
193
|
+
try {
|
|
194
|
+
const stats = statSync(path);
|
|
195
|
+
return stats.isDirectory();
|
|
196
|
+
} catch {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* 检查文件是否存在
|
|
203
|
+
*/
|
|
204
|
+
private fileExists(path: string): boolean {
|
|
205
|
+
try {
|
|
206
|
+
const stats = statSync(path);
|
|
207
|
+
return stats.isFile();
|
|
208
|
+
} catch {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import type { CommandOptions } from '@/types/commands';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 命令接口定义
|
|
6
|
+
*/
|
|
7
|
+
export interface CommandDefinition {
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
alias?: string;
|
|
11
|
+
options?: CommandOption[];
|
|
12
|
+
subcommands?: CommandDefinition[];
|
|
13
|
+
action: (options: CommandOptions) => Promise<void> | void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 命令选项定义
|
|
18
|
+
*/
|
|
19
|
+
export interface CommandOption {
|
|
20
|
+
flags: string;
|
|
21
|
+
description: string;
|
|
22
|
+
defaultValue?: string | boolean | string[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 命令注册器
|
|
27
|
+
*/
|
|
28
|
+
export class CommandRegistry {
|
|
29
|
+
private commands: Map<string, CommandDefinition> = new Map();
|
|
30
|
+
private program: Command;
|
|
31
|
+
|
|
32
|
+
constructor(program: Command) {
|
|
33
|
+
this.program = program;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 注册单个命令
|
|
38
|
+
*/
|
|
39
|
+
public register(commandDef: CommandDefinition): void {
|
|
40
|
+
this.commands.set(commandDef.name, commandDef);
|
|
41
|
+
this.setupCommand(commandDef);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 批量注册命令
|
|
46
|
+
*/
|
|
47
|
+
public registerMultiple(commandDefs: CommandDefinition[]): void {
|
|
48
|
+
commandDefs.forEach(commandDef => this.register(commandDef));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 设置命令到Commander程序
|
|
53
|
+
*/
|
|
54
|
+
private setupCommand(commandDef: CommandDefinition): void {
|
|
55
|
+
const cmd = this.program.command(commandDef.name).description(commandDef.description);
|
|
56
|
+
|
|
57
|
+
// 设置别名
|
|
58
|
+
if (commandDef.alias) {
|
|
59
|
+
cmd.alias(commandDef.alias);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// 设置选项
|
|
63
|
+
if (commandDef.options) {
|
|
64
|
+
commandDef.options.forEach(option => {
|
|
65
|
+
cmd.option(option.flags, option.description, option.defaultValue);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// 设置子命令
|
|
70
|
+
if (commandDef.subcommands) {
|
|
71
|
+
commandDef.subcommands.forEach(subcommandDef => {
|
|
72
|
+
this.setupSubcommand(cmd, subcommandDef);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// 设置动作
|
|
77
|
+
cmd.action(async options => {
|
|
78
|
+
try {
|
|
79
|
+
await commandDef.action(options);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.error(`命令 "${commandDef.name}" 执行失败:`, error);
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* 设置子命令
|
|
89
|
+
*/
|
|
90
|
+
private setupSubcommand(parentCmd: Command, subcommandDef: CommandDefinition): void {
|
|
91
|
+
const subcmd = parentCmd.command(subcommandDef.name).description(subcommandDef.description);
|
|
92
|
+
|
|
93
|
+
// 设置别名
|
|
94
|
+
if (subcommandDef.alias) {
|
|
95
|
+
subcmd.alias(subcommandDef.alias);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// 设置选项
|
|
99
|
+
if (subcommandDef.options) {
|
|
100
|
+
subcommandDef.options.forEach(option => {
|
|
101
|
+
subcmd.option(option.flags, option.description, option.defaultValue);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// 设置动作
|
|
106
|
+
subcmd.action(async options => {
|
|
107
|
+
try {
|
|
108
|
+
await subcommandDef.action(options);
|
|
109
|
+
} catch (error) {
|
|
110
|
+
console.error(`子命令 "${subcommandDef.name}" 执行失败:`, error);
|
|
111
|
+
process.exit(1);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* 获取所有注册的命令
|
|
118
|
+
*/
|
|
119
|
+
public getCommands(): CommandDefinition[] {
|
|
120
|
+
return Array.from(this.commands.values());
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* 根据名称获取命令
|
|
125
|
+
*/
|
|
126
|
+
public getCommand(name: string): CommandDefinition | undefined {
|
|
127
|
+
return this.commands.get(name);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* 检查命令是否存在
|
|
132
|
+
*/
|
|
133
|
+
public hasCommand(name: string): boolean {
|
|
134
|
+
return this.commands.has(name);
|
|
135
|
+
}
|
|
136
|
+
}
|