ccman 0.0.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/.editorconfig +15 -0
- package/.eslintrc.js +28 -0
- package/.github/workflows/release.yml +213 -0
- package/.prettierrc +10 -0
- package/CLAUDE.md +215 -0
- package/README.md +361 -0
- package/README_zh.md +361 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +476 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/ConfigManager.d.ts +67 -0
- package/dist/config/ConfigManager.d.ts.map +1 -0
- package/dist/config/ConfigManager.js +226 -0
- package/dist/config/ConfigManager.js.map +1 -0
- package/dist/config/EnvironmentManager.d.ts +83 -0
- package/dist/config/EnvironmentManager.d.ts.map +1 -0
- package/dist/config/EnvironmentManager.js +280 -0
- package/dist/config/EnvironmentManager.js.map +1 -0
- package/dist/config/constants.d.ts +40 -0
- package/dist/config/constants.d.ts.map +1 -0
- package/dist/config/constants.js +97 -0
- package/dist/config/constants.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/shell/ShellManager.d.ts +73 -0
- package/dist/shell/ShellManager.d.ts.map +1 -0
- package/dist/shell/ShellManager.js +391 -0
- package/dist/shell/ShellManager.js.map +1 -0
- package/dist/types/index.d.ts +55 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/version.d.ts +67 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +199 -0
- package/dist/utils/version.js.map +1 -0
- package/docs/npm-publish-guide.md +71 -0
- package/docs/release-guide.md +86 -0
- package/docs/version-management.md +64 -0
- package/jest.config.js +22 -0
- package/package.json +57 -0
- package/release-temp/README.md +361 -0
- package/release-temp/package.json +57 -0
- package/scripts/publish-local.sh +91 -0
- package/scripts/quick-release.sh +100 -0
- package/scripts/release.sh +430 -0
- package/src/cli.ts +510 -0
- package/src/config/ConfigManager.ts +227 -0
- package/src/config/EnvironmentManager.ts +327 -0
- package/src/config/constants.ts +64 -0
- package/src/index.ts +5 -0
- package/src/shell/ShellManager.ts +416 -0
- package/src/types/index.ts +60 -0
- package/src/utils/version.ts +189 -0
- package/tsconfig.json +25 -0
package/src/cli.ts
ADDED
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import inquirer from 'inquirer';
|
|
6
|
+
import { EnvironmentManager } from './config/EnvironmentManager';
|
|
7
|
+
import { AddEnvOptions } from './types';
|
|
8
|
+
import { getCurrentVersion } from './utils/version';
|
|
9
|
+
|
|
10
|
+
const program = new Command();
|
|
11
|
+
const envManager = new EnvironmentManager();
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 统一的 use 环境交互逻辑
|
|
15
|
+
*/
|
|
16
|
+
async function performUseEnvironment(name: string, options?: {
|
|
17
|
+
autoWrite?: boolean;
|
|
18
|
+
autoSource?: boolean;
|
|
19
|
+
skipSuccessMessage?: boolean;
|
|
20
|
+
}): Promise<void> {
|
|
21
|
+
const result = await envManager.useEnvironment(name, {
|
|
22
|
+
autoWriteShell: options?.autoWrite,
|
|
23
|
+
autoSource: options?.autoSource
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
if (!options?.skipSuccessMessage) {
|
|
27
|
+
console.log(chalk.green(`✓ Switched to environment "${name}"`));
|
|
28
|
+
console.log(` Base URL: ${result.env.baseUrl}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (result.shellWriteResult?.success) {
|
|
32
|
+
console.log(chalk.green(`✓ Environment variables written to ${result.shellWriteResult.filePath}`));
|
|
33
|
+
|
|
34
|
+
if (options?.autoSource) {
|
|
35
|
+
if (result.sourceResult?.success) {
|
|
36
|
+
console.log(chalk.green('✓ Shell configuration sourced automatically'));
|
|
37
|
+
console.log(chalk.yellow('⚠️ Note: Auto-sourcing may not work in all terminal environments'));
|
|
38
|
+
} else {
|
|
39
|
+
console.log(chalk.red(`✗ Failed to source shell config: ${result.sourceResult?.error}`));
|
|
40
|
+
console.log(chalk.cyan('Please run manually: source ~/.bashrc (or ~/.zshrc)'));
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
// 询问用户是否要自动 source
|
|
44
|
+
const sourceAnswer = await inquirer.prompt([
|
|
45
|
+
{
|
|
46
|
+
type: 'list',
|
|
47
|
+
name: 'sourceChoice',
|
|
48
|
+
message: 'How would you like to apply the environment variables?',
|
|
49
|
+
choices: [
|
|
50
|
+
{ name: 'Manual - I will restart terminal or source manually (Recommended)', value: 'manual' },
|
|
51
|
+
{ name: 'Auto-source - Try to source automatically (May not work in all environments)', value: 'auto' }
|
|
52
|
+
],
|
|
53
|
+
default: 'manual'
|
|
54
|
+
}
|
|
55
|
+
]);
|
|
56
|
+
|
|
57
|
+
if (sourceAnswer.sourceChoice === 'auto') {
|
|
58
|
+
console.log(chalk.yellow('⚠️ Attempting auto-source - this may not work in all terminal environments'));
|
|
59
|
+
const sourceResult = await envManager.getShellManager().autoSourceShell();
|
|
60
|
+
|
|
61
|
+
if (sourceResult.success) {
|
|
62
|
+
console.log(chalk.green('✓ Shell configuration sourced successfully'));
|
|
63
|
+
} else {
|
|
64
|
+
console.log(chalk.red(`✗ Auto-source failed: ${sourceResult.error}`));
|
|
65
|
+
console.log(chalk.cyan('Please run manually: source ~/.bashrc (or ~/.zshrc)'));
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
console.log(chalk.cyan('To apply changes, restart your terminal or run:'));
|
|
69
|
+
console.log(chalk.cyan('source ~/.bashrc (or ~/.zshrc)'));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
} else if (options?.autoWrite !== false) {
|
|
73
|
+
console.log(chalk.yellow('Environment variables have been set, but may not persist.'));
|
|
74
|
+
console.log(chalk.cyan('Consider running: source <(ccman env)'));
|
|
75
|
+
} else {
|
|
76
|
+
console.log(chalk.yellow('To set environment variables manually, run:'));
|
|
77
|
+
console.log(chalk.cyan('source <(ccman env)'));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
program
|
|
82
|
+
.name('ccman')
|
|
83
|
+
.description('Claude Code Manager - Manage Claude Code API configurations')
|
|
84
|
+
.version(getCurrentVersion());
|
|
85
|
+
|
|
86
|
+
// 列出所有环境
|
|
87
|
+
program
|
|
88
|
+
.command('list')
|
|
89
|
+
.alias('ls')
|
|
90
|
+
.description('List all environment groups')
|
|
91
|
+
.action(() => {
|
|
92
|
+
const environments = envManager.listEnvironments();
|
|
93
|
+
|
|
94
|
+
if (environments.length === 0) {
|
|
95
|
+
console.log(chalk.yellow('No environment groups found. Use "ccman add" to create one.'));
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
console.log();
|
|
100
|
+
environments.forEach(env => {
|
|
101
|
+
const marker = env.isCurrent ? chalk.green('* ') : ' ';
|
|
102
|
+
const name = env.isCurrent ? chalk.green(env.name) : env.name;
|
|
103
|
+
console.log(`${marker}${name.padEnd(15)} ${env.baseUrl}`);
|
|
104
|
+
|
|
105
|
+
if (env.lastUsed) {
|
|
106
|
+
const lastUsed = new Date(env.lastUsed).toLocaleDateString();
|
|
107
|
+
console.log(`${' '.repeat(17)} Last used: ${lastUsed}`);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
console.log();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// 添加环境
|
|
114
|
+
program
|
|
115
|
+
.command('add <name> <baseUrl> [apiKey]')
|
|
116
|
+
.description('Add a new environment group')
|
|
117
|
+
.option('--no-auto-write', 'Do not automatically write to shell config')
|
|
118
|
+
.action(async (name: string, baseUrl: string, apiKey?: string, options?: { autoWrite: boolean }) => {
|
|
119
|
+
try {
|
|
120
|
+
if (!apiKey) {
|
|
121
|
+
const answer = await inquirer.prompt([
|
|
122
|
+
{
|
|
123
|
+
type: 'password',
|
|
124
|
+
name: 'apiKey',
|
|
125
|
+
message: 'Enter API Key:',
|
|
126
|
+
mask: '*'
|
|
127
|
+
}
|
|
128
|
+
]);
|
|
129
|
+
apiKey = answer.apiKey;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const addOptions: AddEnvOptions = {
|
|
133
|
+
name,
|
|
134
|
+
baseUrl,
|
|
135
|
+
apiKey: apiKey!,
|
|
136
|
+
autoWriteShell: options?.autoWrite
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const env = await envManager.addEnvironment(addOptions);
|
|
140
|
+
console.log(chalk.green(`✓ Added environment group "${name}"`));
|
|
141
|
+
console.log(` Base URL: ${env.baseUrl}`);
|
|
142
|
+
console.log(` Created: ${new Date(env.createdAt).toLocaleString()}`);
|
|
143
|
+
|
|
144
|
+
// 询问是否设为当前环境
|
|
145
|
+
const currentEnv = envManager.getCurrentEnvironment();
|
|
146
|
+
if (!currentEnv || currentEnv.name !== name) {
|
|
147
|
+
const useAnswer = await inquirer.prompt([
|
|
148
|
+
{
|
|
149
|
+
type: 'confirm',
|
|
150
|
+
name: 'useCurrent',
|
|
151
|
+
message: `Set "${name}" as current environment?`,
|
|
152
|
+
default: true
|
|
153
|
+
}
|
|
154
|
+
]);
|
|
155
|
+
|
|
156
|
+
if (useAnswer.useCurrent) {
|
|
157
|
+
await performUseEnvironment(name, {
|
|
158
|
+
autoWrite: options?.autoWrite,
|
|
159
|
+
skipSuccessMessage: true // 因为前面已经显示了添加成功的信息
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
} catch (error) {
|
|
165
|
+
console.error(chalk.red(`✗ Error: ${error}`));
|
|
166
|
+
process.exit(1);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// 删除环境
|
|
171
|
+
program
|
|
172
|
+
.command('remove <name>')
|
|
173
|
+
.alias('rm')
|
|
174
|
+
.description('Remove an environment group')
|
|
175
|
+
.action(async (name: string) => {
|
|
176
|
+
try {
|
|
177
|
+
const env = envManager.getEnvironment(name);
|
|
178
|
+
if (!env) {
|
|
179
|
+
console.error(chalk.red(`✗ Environment "${name}" not found`));
|
|
180
|
+
process.exit(1);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const answer = await inquirer.prompt([
|
|
184
|
+
{
|
|
185
|
+
type: 'confirm',
|
|
186
|
+
name: 'confirm',
|
|
187
|
+
message: `Are you sure you want to remove environment "${name}"?`,
|
|
188
|
+
default: false
|
|
189
|
+
}
|
|
190
|
+
]);
|
|
191
|
+
|
|
192
|
+
if (answer.confirm) {
|
|
193
|
+
await envManager.removeEnvironment(name);
|
|
194
|
+
console.log(chalk.green(`✓ Removed environment "${name}"`));
|
|
195
|
+
} else {
|
|
196
|
+
console.log(chalk.yellow('Operation cancelled'));
|
|
197
|
+
}
|
|
198
|
+
} catch (error) {
|
|
199
|
+
console.error(chalk.red(`✗ Error: ${error}`));
|
|
200
|
+
process.exit(1);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// 使用环境
|
|
205
|
+
program
|
|
206
|
+
.command('use <name>')
|
|
207
|
+
.description('Switch to an environment group')
|
|
208
|
+
.option('--no-auto-write', 'Do not automatically write to shell config')
|
|
209
|
+
.option('--auto-source', 'Automatically source shell config after writing (risky)')
|
|
210
|
+
.action(async (name: string, options?: { autoWrite: boolean; autoSource: boolean }) => {
|
|
211
|
+
try {
|
|
212
|
+
await performUseEnvironment(name, {
|
|
213
|
+
autoWrite: options?.autoWrite,
|
|
214
|
+
autoSource: options?.autoSource
|
|
215
|
+
});
|
|
216
|
+
} catch (error) {
|
|
217
|
+
console.error(chalk.red(`✗ Error: ${error}`));
|
|
218
|
+
process.exit(1);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// 显示当前环境
|
|
223
|
+
program
|
|
224
|
+
.command('current')
|
|
225
|
+
.description('Show current environment group')
|
|
226
|
+
.action(() => {
|
|
227
|
+
const currentEnv = envManager.getCurrentEnvironment();
|
|
228
|
+
|
|
229
|
+
if (!currentEnv) {
|
|
230
|
+
console.log(chalk.yellow('No environment is currently active.'));
|
|
231
|
+
console.log('Use "ccman use <name>" to activate an environment.');
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
console.log();
|
|
236
|
+
console.log(chalk.green(`Current environment: ${currentEnv.name}`));
|
|
237
|
+
console.log(`Base URL: ${currentEnv.baseUrl}`);
|
|
238
|
+
console.log(`API Key: ${'*'.repeat(Math.min(currentEnv.apiKey.length, 20))}`);
|
|
239
|
+
console.log(`Created: ${new Date(currentEnv.createdAt).toLocaleString()}`);
|
|
240
|
+
|
|
241
|
+
if (currentEnv.lastUsed) {
|
|
242
|
+
console.log(`Last used: ${new Date(currentEnv.lastUsed).toLocaleString()}`);
|
|
243
|
+
}
|
|
244
|
+
console.log();
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// 生成环境变量脚本
|
|
248
|
+
program
|
|
249
|
+
.command('env')
|
|
250
|
+
.description('Generate shell script to set environment variables')
|
|
251
|
+
.action(() => {
|
|
252
|
+
try {
|
|
253
|
+
const script = envManager.generateEnvScript();
|
|
254
|
+
console.log(script);
|
|
255
|
+
} catch (error) {
|
|
256
|
+
console.error(chalk.red(`✗ Error: ${error}`));
|
|
257
|
+
process.exit(1);
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
// 测试环境
|
|
262
|
+
program
|
|
263
|
+
.command('test [name]')
|
|
264
|
+
.description('Test environment configuration (defaults to current)')
|
|
265
|
+
.action(async (name?: string) => {
|
|
266
|
+
const result = await envManager.testEnvironment(name);
|
|
267
|
+
|
|
268
|
+
if (result.success) {
|
|
269
|
+
console.log(chalk.green(`✓ ${result.message}`));
|
|
270
|
+
} else {
|
|
271
|
+
console.error(chalk.red(`✗ ${result.message}`));
|
|
272
|
+
if (result.error) {
|
|
273
|
+
console.error(chalk.gray(`Details: ${result.error}`));
|
|
274
|
+
}
|
|
275
|
+
process.exit(1);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
// 显示统计信息
|
|
280
|
+
program
|
|
281
|
+
.command('status')
|
|
282
|
+
.description('Show CCM status and statistics')
|
|
283
|
+
.action(() => {
|
|
284
|
+
const stats = envManager.getStats();
|
|
285
|
+
const environments = envManager.listEnvironments();
|
|
286
|
+
|
|
287
|
+
console.log();
|
|
288
|
+
console.log(chalk.blue('CCM Status:'));
|
|
289
|
+
console.log(`Total environments: ${stats.totalEnvironments}`);
|
|
290
|
+
console.log(`Current environment: ${stats.currentEnvironment || 'None'}`);
|
|
291
|
+
console.log(`Shell integration: ${stats.hasShellIntegration ? 'Enabled' : 'Disabled'}`);
|
|
292
|
+
|
|
293
|
+
if (environments.length > 0) {
|
|
294
|
+
console.log();
|
|
295
|
+
console.log(chalk.blue('Recent environments:'));
|
|
296
|
+
const sortedEnvs = environments
|
|
297
|
+
.filter(env => env.lastUsed)
|
|
298
|
+
.sort((a, b) => new Date(b.lastUsed!).getTime() - new Date(a.lastUsed!).getTime())
|
|
299
|
+
.slice(0, 3);
|
|
300
|
+
|
|
301
|
+
sortedEnvs.forEach(env => {
|
|
302
|
+
const lastUsed = new Date(env.lastUsed!).toLocaleDateString();
|
|
303
|
+
console.log(` ${env.name} (${lastUsed})`);
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
console.log();
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
// 清除所有配置
|
|
310
|
+
program
|
|
311
|
+
.command('clear')
|
|
312
|
+
.alias('clearall')
|
|
313
|
+
.description('Clear all environments and shell integration (DESTRUCTIVE)')
|
|
314
|
+
.action(async () => {
|
|
315
|
+
try {
|
|
316
|
+
// 确认操作
|
|
317
|
+
const confirmAnswer = await inquirer.prompt([
|
|
318
|
+
{
|
|
319
|
+
type: 'confirm',
|
|
320
|
+
name: 'confirmed',
|
|
321
|
+
message: chalk.red('⚠️ This will remove ALL environments and shell integration. Are you sure?'),
|
|
322
|
+
default: false
|
|
323
|
+
}
|
|
324
|
+
]);
|
|
325
|
+
|
|
326
|
+
if (!confirmAnswer.confirmed) {
|
|
327
|
+
console.log(chalk.yellow('Operation cancelled.'));
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// 执行清除
|
|
332
|
+
console.log(chalk.yellow('Clearing CCM configuration...'));
|
|
333
|
+
const result = await envManager.clearAll();
|
|
334
|
+
|
|
335
|
+
// 显示结果
|
|
336
|
+
console.log();
|
|
337
|
+
if (result.success) {
|
|
338
|
+
console.log(chalk.green(`✓ ${result.message}`));
|
|
339
|
+
} else {
|
|
340
|
+
console.log(chalk.red(`✗ ${result.message}`));
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// 显示详细信息
|
|
344
|
+
if (result.details.length > 0) {
|
|
345
|
+
console.log();
|
|
346
|
+
result.details.forEach(detail => {
|
|
347
|
+
if (detail.startsWith('✓')) {
|
|
348
|
+
console.log(chalk.green(detail));
|
|
349
|
+
} else if (detail.startsWith('⚠')) {
|
|
350
|
+
console.log(chalk.yellow(detail));
|
|
351
|
+
} else if (detail.startsWith('✗')) {
|
|
352
|
+
console.log(chalk.red(detail));
|
|
353
|
+
} else {
|
|
354
|
+
console.log(detail);
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
console.log();
|
|
360
|
+
console.log(chalk.cyan('CCM has been reset to initial state.'));
|
|
361
|
+
console.log(chalk.cyan('You can start fresh with: ccman config'));
|
|
362
|
+
|
|
363
|
+
} catch (error) {
|
|
364
|
+
console.error(chalk.red(`✗ Error: ${error}`));
|
|
365
|
+
process.exit(1);
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
// 交互式配置
|
|
370
|
+
program
|
|
371
|
+
.command('config')
|
|
372
|
+
.description('Interactive configuration')
|
|
373
|
+
.action(async () => {
|
|
374
|
+
const environments = envManager.listEnvironments();
|
|
375
|
+
|
|
376
|
+
if (environments.length === 0) {
|
|
377
|
+
console.log(chalk.yellow('No environments found. Let\'s create your first one.'));
|
|
378
|
+
|
|
379
|
+
const answers = await inquirer.prompt([
|
|
380
|
+
{ type: 'input', name: 'name', message: 'Environment name:', default: 'default' },
|
|
381
|
+
{ type: 'input', name: 'baseUrl', message: 'Base URL:', default: 'https://api.anthropic.com' },
|
|
382
|
+
{ type: 'password', name: 'apiKey', message: 'API Key:', mask: '*' },
|
|
383
|
+
{ type: 'confirm', name: 'autoWrite', message: 'Automatically write to shell config?', default: true }
|
|
384
|
+
]);
|
|
385
|
+
|
|
386
|
+
try {
|
|
387
|
+
await envManager.addEnvironment({
|
|
388
|
+
name: answers.name,
|
|
389
|
+
baseUrl: answers.baseUrl,
|
|
390
|
+
apiKey: answers.apiKey,
|
|
391
|
+
autoWriteShell: answers.autoWrite
|
|
392
|
+
});
|
|
393
|
+
console.log(chalk.green(`✓ Created environment "${answers.name}"`));
|
|
394
|
+
} catch (error) {
|
|
395
|
+
console.error(chalk.red(`✗ Error: ${error}`));
|
|
396
|
+
}
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const choices = environments.map(env => ({
|
|
401
|
+
name: `${env.name} (${env.baseUrl})${env.isCurrent ? ' [current]' : ''}`,
|
|
402
|
+
value: env.name
|
|
403
|
+
}));
|
|
404
|
+
|
|
405
|
+
const action = await inquirer.prompt([
|
|
406
|
+
{
|
|
407
|
+
type: 'list',
|
|
408
|
+
name: 'action',
|
|
409
|
+
message: 'What would you like to do?',
|
|
410
|
+
choices: [
|
|
411
|
+
{ name: 'Switch environment', value: 'switch' },
|
|
412
|
+
{ name: 'Add new environment', value: 'add' },
|
|
413
|
+
{ name: 'Edit environment', value: 'edit' },
|
|
414
|
+
{ name: 'Remove environment', value: 'remove' },
|
|
415
|
+
{ name: 'Show current status', value: 'status' }
|
|
416
|
+
]
|
|
417
|
+
}
|
|
418
|
+
]);
|
|
419
|
+
|
|
420
|
+
switch (action.action) {
|
|
421
|
+
case 'switch':
|
|
422
|
+
const switchAnswer = await inquirer.prompt([
|
|
423
|
+
{
|
|
424
|
+
type: 'list',
|
|
425
|
+
name: 'name',
|
|
426
|
+
message: 'Select environment:',
|
|
427
|
+
choices
|
|
428
|
+
}
|
|
429
|
+
]);
|
|
430
|
+
try {
|
|
431
|
+
await performUseEnvironment(switchAnswer.name);
|
|
432
|
+
} catch (error) {
|
|
433
|
+
console.error(chalk.red(`✗ Error: ${error}`));
|
|
434
|
+
}
|
|
435
|
+
break;
|
|
436
|
+
|
|
437
|
+
case 'add':
|
|
438
|
+
const addAnswers = await inquirer.prompt([
|
|
439
|
+
{ type: 'input', name: 'name', message: 'Environment name:' },
|
|
440
|
+
{ type: 'input', name: 'baseUrl', message: 'Base URL:' },
|
|
441
|
+
{ type: 'password', name: 'apiKey', message: 'API Key:', mask: '*' }
|
|
442
|
+
]);
|
|
443
|
+
try {
|
|
444
|
+
await envManager.addEnvironment(addAnswers);
|
|
445
|
+
console.log(chalk.green(`✓ Added environment "${addAnswers.name}"`));
|
|
446
|
+
} catch (error) {
|
|
447
|
+
console.error(chalk.red(`✗ Error: ${error}`));
|
|
448
|
+
}
|
|
449
|
+
break;
|
|
450
|
+
|
|
451
|
+
case 'edit':
|
|
452
|
+
const editEnvAnswer = await inquirer.prompt([
|
|
453
|
+
{
|
|
454
|
+
type: 'list',
|
|
455
|
+
name: 'name',
|
|
456
|
+
message: 'Select environment to edit:',
|
|
457
|
+
choices
|
|
458
|
+
}
|
|
459
|
+
]);
|
|
460
|
+
|
|
461
|
+
const currentConfig = envManager.getEnvironment(editEnvAnswer.name);
|
|
462
|
+
if (currentConfig) {
|
|
463
|
+
const editAnswers = await inquirer.prompt([
|
|
464
|
+
{ type: 'input', name: 'baseUrl', message: 'Base URL:', default: currentConfig.baseUrl },
|
|
465
|
+
{ type: 'password', name: 'apiKey', message: 'API Key:', mask: '*', default: currentConfig.apiKey }
|
|
466
|
+
]);
|
|
467
|
+
|
|
468
|
+
try {
|
|
469
|
+
await envManager.updateEnvironment(editEnvAnswer.name, {
|
|
470
|
+
baseUrl: editAnswers.baseUrl,
|
|
471
|
+
apiKey: editAnswers.apiKey
|
|
472
|
+
});
|
|
473
|
+
console.log(chalk.green(`✓ Updated environment "${editEnvAnswer.name}"`));
|
|
474
|
+
} catch (error) {
|
|
475
|
+
console.error(chalk.red(`✗ Error: ${error}`));
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
break;
|
|
479
|
+
|
|
480
|
+
case 'status':
|
|
481
|
+
{
|
|
482
|
+
const stats = envManager.getStats();
|
|
483
|
+
const environments = envManager.listEnvironments();
|
|
484
|
+
|
|
485
|
+
console.log();
|
|
486
|
+
console.log(chalk.blue('CCM Status:'));
|
|
487
|
+
console.log(`Total environments: ${stats.totalEnvironments}`);
|
|
488
|
+
console.log(`Current environment: ${stats.currentEnvironment || 'None'}`);
|
|
489
|
+
console.log(`Shell integration: ${stats.hasShellIntegration ? 'Enabled' : 'Disabled'}`);
|
|
490
|
+
|
|
491
|
+
if (environments.length > 0) {
|
|
492
|
+
console.log();
|
|
493
|
+
console.log(chalk.blue('Recent environments:'));
|
|
494
|
+
environments
|
|
495
|
+
.sort((a, b) => new Date(b.lastUsed || b.createdAt).getTime() - new Date(a.lastUsed || a.createdAt).getTime())
|
|
496
|
+
.slice(0, 3)
|
|
497
|
+
.forEach(env => {
|
|
498
|
+
const marker = env.isCurrent ? chalk.green('* ') : ' ';
|
|
499
|
+
const name = env.isCurrent ? chalk.green(env.name) : env.name;
|
|
500
|
+
console.log(`${marker}${name.padEnd(15)} ${env.baseUrl}`);
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
console.log();
|
|
504
|
+
}
|
|
505
|
+
break;
|
|
506
|
+
}
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
// 解析命令行参数
|
|
510
|
+
program.parse();
|