@simonecoelhosfo/optimizely-mcp-server
Version:
Optimizely MCP Server for AI assistants with integrated CLI tools
123 lines ⢠4.95 kB
JavaScript
/**
* Clean Progress Reporter - Simple, reliable progress display
* No complex libraries, just clean console output that works
*/
import chalk from 'chalk';
export class CleanProgressReporter {
totalSteps = 0;
currentStep = 0;
currentProject = '';
constructor() {
// Simple, no dependencies
}
/**
* Start sync operation
*/
startSync(operation, options) {
console.log(chalk.bold.blue(`\nš Optimizely Cache Sync`));
console.log(chalk.gray(`${operation} ⢠${new Date().toLocaleTimeString()}\n`));
}
/**
* Set total steps
*/
setTotalSteps(projectCount, entitiesPerProject, totalSteps) {
this.totalSteps = totalSteps || (projectCount * entitiesPerProject);
console.log(chalk.gray(`Total steps: ${this.totalSteps} operations across ${projectCount} projects\n`));
this.showProgress();
}
/**
* Update progress for a specific phase
*/
updateProgress(progress) {
const { phase, message } = progress;
if (phase === 'projects') {
// Handle project messages
if (message.includes('Syncing project:')) {
const projectMatch = message.match(/Syncing project:\s*(.+)/);
if (projectMatch) {
const projectName = projectMatch[1].trim();
if (projectName !== this.currentProject) {
console.log(chalk.bold.cyan(`\nš¦ ${projectName}:`));
this.currentProject = projectName;
}
}
return;
}
// Handle entity messages
if (message.includes('Syncing') && !message.includes('Syncing project:')) {
const entityMatch = message.match(/Syncing\s+(\w+)/i);
if (entityMatch) {
const entityType = entityMatch[1].toLowerCase();
console.log(chalk.yellow(` ā³ Downloading ${entityType}...`));
}
return;
}
if (message.includes('synced') || message.includes('completed')) {
const entityMatch = message.match(/(\w+)\s+(?:synced|completed)/i);
if (entityMatch) {
const entityType = entityMatch[1].toLowerCase();
const recordMatch = message.match(/\((\d+) records?\)/);
const recordCount = recordMatch ? ` (${recordMatch[1]} records)` : '';
console.log(chalk.green(` ā
${entityType} completed${recordCount}`));
this.currentStep++;
this.showProgress();
}
return;
}
}
// Handle individual entity phases (project_12345_experiments format)
if (phase.startsWith('project_') && phase.includes('_')) {
const parts = phase.split('_');
if (parts.length >= 3) {
const entityType = parts.slice(2).join('_');
if (progress.percent >= 100) {
const recordMatch = message.match(/\((\d+) records?\)/);
const recordCount = recordMatch ? ` (${recordMatch[1]} records)` : '';
console.log(chalk.green(` ā
${entityType} completed${recordCount}`));
this.currentStep++;
this.showProgress();
}
}
}
}
/**
* Show simple progress indicator - only at key milestones
*/
showProgress() {
if (this.totalSteps === 0)
return;
const percent = Math.round((this.currentStep / this.totalSteps) * 100);
// Only show progress at 25%, 50%, 75%, 100% or every 5 steps
const showUpdate = percent % 25 === 0 || this.currentStep % 5 === 0 || this.currentStep === this.totalSteps;
if (showUpdate) {
const barLength = 20;
const filledLength = Math.round((barLength * this.currentStep) / this.totalSteps);
const bar = 'ā'.repeat(filledLength) + 'ā'.repeat(barLength - filledLength);
console.log(chalk.cyan(`Progress: [${bar}] ${percent}% (${this.currentStep}/${this.totalSteps})`));
}
}
/**
* Complete sync operation
*/
completeSync(result) {
console.log(chalk.bold.green('\n⨠Sync Completed Successfully!'));
if (result.duration) {
console.log(chalk.gray(`ā±ļø Completed in ${(result.duration / 1000).toFixed(1)}s`));
}
console.log(chalk.gray(`š Processed ${this.totalSteps} operations\n`));
}
/**
* Report error
*/
error(error) {
console.error(chalk.red.bold('\nā Sync Failed!'));
console.error(chalk.red(error.message));
}
/**
* Clean up
*/
dispose() {
// Nothing to clean up
}
}
//# sourceMappingURL=CleanProgressReporter.js.map