claude-switcher
Version:
Cross-platform CLI tool for switching between different Claude AI model configurations. Supports automatic backup, rollback, and multi-platform configuration management for Claude API integrations.
230 lines (229 loc) • 8.62 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProgressUtils = exports.ProgressIndicator = void 0;
const chalk_1 = __importDefault(require("chalk"));
class ProgressIndicator {
constructor(message) {
this.interval = null;
this.currentFrame = 0;
this.isRunning = false;
this.message = message;
}
start() {
if (this.isRunning)
return;
this.isRunning = true;
this.currentFrame = 0;
process.stdout.write('\x1B[?25l');
this.interval = setInterval(() => {
this.render();
this.currentFrame = (this.currentFrame + 1) % ProgressIndicator.SPINNER_FRAMES.length;
}, 100);
}
stop(successMessage) {
if (!this.isRunning)
return;
this.isRunning = false;
if (this.interval) {
clearInterval(this.interval);
this.interval = null;
}
process.stdout.write('\r\x1B[K');
process.stdout.write('\x1B[?25h');
if (successMessage) {
console.log(chalk_1.default.green('✓'), successMessage);
}
}
stopWithError(errorMessage) {
this.stop();
console.log(chalk_1.default.red('✗'), errorMessage);
}
updateMessage(newMessage) {
this.message = newMessage;
}
render() {
const spinner = ProgressIndicator.SPINNER_FRAMES[this.currentFrame];
const output = `${chalk_1.default.cyan(spinner)} ${this.message}`;
process.stdout.write(`\r${output}`);
}
static createProgressBar(current, total, width = 30) {
const percentage = Math.min(100, Math.max(0, (current / total) * 100));
const completed = Math.floor((percentage / 100) * width);
const remaining = width - completed;
const completedBar = ProgressIndicator.PROGRESS_CHARS.complete.repeat(completed);
const remainingBar = ProgressIndicator.PROGRESS_CHARS.incomplete.repeat(remaining);
const percentageText = `${Math.round(percentage)}%`.padStart(4);
return `${chalk_1.default.green(completedBar)}${chalk_1.default.gray(remainingBar)} ${chalk_1.default.cyan(percentageText)}`;
}
static displayStepProgress(steps, currentStep) {
console.log(chalk_1.default.blue.bold('\n进度:'));
steps.forEach((step, index) => {
let icon;
let color;
if (index < currentStep) {
icon = '✓';
color = chalk_1.default.green;
}
else if (index === currentStep) {
icon = '▶';
color = chalk_1.default.cyan;
}
else {
icon = '○';
color = chalk_1.default.gray;
}
console.log(` ${color(icon)} ${color(step)}`);
});
console.log();
}
static async confirmWithTimeout(message, timeoutSeconds = 30) {
return new Promise((resolve) => {
const inquirer = require('inquirer');
let answered = false;
const timeoutId = setTimeout(() => {
if (!answered) {
answered = true;
console.log(chalk_1.default.yellow(`\n⏰ 超时 (${timeoutSeconds}秒),默认选择: 否`));
resolve(false);
}
}, timeoutSeconds * 1000);
let remainingTime = timeoutSeconds;
const countdownInterval = setInterval(() => {
if (answered) {
clearInterval(countdownInterval);
return;
}
remainingTime--;
if (remainingTime > 0) {
process.stdout.write(`\r${message} (${remainingTime}秒后自动选择"否") `);
}
}, 1000);
inquirer.prompt([
{
type: 'confirm',
name: 'confirmed',
message: message,
default: false
}
]).then((answers) => {
if (!answered) {
answered = true;
clearTimeout(timeoutId);
clearInterval(countdownInterval);
resolve(answers.confirmed);
}
}).catch(() => {
if (!answered) {
answered = true;
clearTimeout(timeoutId);
clearInterval(countdownInterval);
resolve(false);
}
});
});
}
static async withLoading(promise, message) {
const indicator = new ProgressIndicator(message);
try {
indicator.start();
const result = await promise;
indicator.stop();
return result;
}
catch (error) {
indicator.stopWithError('操作失败');
throw error;
}
}
static async withMultipleProgress(operations) {
console.log(chalk_1.default.blue.bold('\n执行多个操作:\n'));
const results = [];
const statuses = operations.map(() => 'pending');
const updateDisplay = () => {
process.stdout.write(`\x1B[${operations.length}A`);
operations.forEach((op, index) => {
let icon;
let color;
switch (statuses[index]) {
case 'pending':
icon = '⏳';
color = chalk_1.default.yellow;
break;
case 'running':
icon = '🔄';
color = chalk_1.default.cyan;
break;
case 'completed':
icon = '✅';
color = chalk_1.default.green;
break;
case 'failed':
icon = '❌';
color = chalk_1.default.red;
break;
default:
icon = '❓';
color = chalk_1.default.gray;
}
console.log(` ${icon} ${color(op.label)}`);
});
};
operations.forEach(op => console.log(` ⏳ ${chalk_1.default.yellow(op.label)}`));
const promises = operations.map(async (op, index) => {
try {
statuses[index] = 'running';
updateDisplay();
const result = await op.promise;
results[index] = result;
statuses[index] = 'completed';
updateDisplay();
return result;
}
catch (error) {
statuses[index] = 'failed';
updateDisplay();
throw error;
}
});
await Promise.all(promises);
console.log();
return results;
}
}
exports.ProgressIndicator = ProgressIndicator;
ProgressIndicator.SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
ProgressIndicator.PROGRESS_CHARS = {
complete: '█',
incomplete: '░',
current: '▓'
};
class ProgressUtils {
static showFileOperation(operation, fileName) {
const message = `${operation} ${chalk_1.default.cyan(fileName)}`;
const indicator = new ProgressIndicator(message);
indicator.start();
return indicator;
}
static showConfigOperation(operation, configName) {
const message = `${operation} ${chalk_1.default.cyan(configName)} 配置`;
const indicator = new ProgressIndicator(message);
indicator.start();
return indicator;
}
static displaySummary(operations, totalTime) {
console.log(chalk_1.default.blue.bold('\n操作摘要:'));
console.log(chalk_1.default.green(`✓ 成功完成 ${operations.length} 个操作`));
console.log(chalk_1.default.gray(`⏱️ 总耗时: ${(totalTime / 1000).toFixed(2)} 秒`));
if (operations.length > 0) {
console.log(chalk_1.default.gray('\n已完成的操作:'));
operations.forEach((op, index) => {
console.log(chalk_1.default.gray(` ${index + 1}. ${op}`));
});
}
console.log();
}
}
exports.ProgressUtils = ProgressUtils;