UNPKG

khodkar-cli

Version:

A TypeScript CLI application that extracts business rules and logic from codebases for customer support knowledge bases

194 lines 6.83 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ProgressTracker = void 0; const ora_1 = __importDefault(require("ora")); const chalk_1 = __importDefault(require("chalk")); class ProgressTracker { options; spinner; startTime; verbose; showETA; updateInterval; constructor(options = {}) { this.options = options; this.verbose = options.verbose || false; this.showETA = options.showETA || true; this.updateInterval = options.updateInterval || 1000; this.startTime = Date.now(); this.spinner = (0, ora_1.default)({ text: 'Initializing...', spinner: 'dots', color: 'blue' }); } start(message) { if (message) { this.spinner.text = message; } if (!this.verbose) { this.spinner.start(); } else { console.log(chalk_1.default.blue(`🚀 ${this.spinner.text}`)); } } update(progress) { const percentage = Math.round((progress.filesProcessed / progress.totalFiles) * 100); const eta = this.calculateETA(progress); let message = `${progress.currentPhase}: ${progress.currentFile} (${progress.filesProcessed}/${progress.totalFiles} - ${percentage}%)`; if (this.showETA && eta) { message += ` - ETA: ${this.formatDuration(eta)}`; } if (this.verbose) { this.spinner.stop(); console.log(chalk_1.default.gray(` ${message}`)); if (!this.isComplete(progress)) { this.spinner.start(); } } else { this.spinner.text = message; } } updatePhase(phase, message) { const phaseMessages = { scanning: '🔍 Scanning files...', analyzing: '🤖 Analyzing with LLM...', formatting: '📝 Formatting output...', complete: '✅ Complete!' }; const displayMessage = message || phaseMessages[phase]; if (this.verbose) { this.spinner.stop(); console.log(chalk_1.default.blue(displayMessage)); if (phase !== 'complete') { this.spinner.start(); } } else { this.spinner.text = displayMessage; } } succeed(message) { if (this.verbose) { this.spinner.stop(); console.log(chalk_1.default.green(`✅ ${message || 'Complete!'}`)); } else { this.spinner.succeed(message); } } fail(message) { if (this.verbose) { this.spinner.stop(); console.error(chalk_1.default.red(`❌ ${message || 'Failed!'}`)); } else { this.spinner.fail(message); } } warn(message) { if (this.verbose) { this.spinner.stop(); console.warn(chalk_1.default.yellow(`⚠ ${message}`)); this.spinner.start(); } else { // For non-verbose mode, just update the spinner text briefly const originalText = this.spinner.text; this.spinner.text = chalk_1.default.yellow(`⚠ ${message}`); setTimeout(() => { this.spinner.text = originalText; }, 2000); } } info(message) { if (this.verbose) { this.spinner.stop(); console.log(chalk_1.default.blue(`ℹ ${message}`)); this.spinner.start(); } } stop() { this.spinner.stop(); } calculateETA(progress) { if (progress.filesProcessed === 0) { return null; } const elapsed = Date.now() - this.startTime; const rate = progress.filesProcessed / elapsed; // files per ms const remaining = progress.totalFiles - progress.filesProcessed; return remaining / rate; } formatDuration(ms) { const seconds = Math.floor(ms / 1000); const minutes = Math.floor(seconds / 60); const hours = Math.floor(minutes / 60); if (hours > 0) { return `${hours}h ${minutes % 60}m`; } else if (minutes > 0) { return `${minutes}m ${seconds % 60}s`; } else { return `${seconds}s`; } } isComplete(progress) { return progress.currentPhase === 'complete' || progress.filesProcessed >= progress.totalFiles; } // Static utility methods static createFileProgressBar(current, total, width = 40) { const percentage = current / total; const filled = Math.round(width * percentage); const empty = width - filled; const bar = '█'.repeat(filled) + '░'.repeat(empty); const percent = Math.round(percentage * 100); return `[${bar}] ${percent}% (${current}/${total})`; } static formatFileSize(bytes) { const units = ['B', 'KB', 'MB', 'GB']; let size = bytes; let unitIndex = 0; while (size >= 1024 && unitIndex < units.length - 1) { size /= 1024; unitIndex++; } return `${size.toFixed(1)} ${units[unitIndex]}`; } static formatProcessingRate(filesProcessed, timeElapsed) { const rate = filesProcessed / (timeElapsed / 1000); // files per second if (rate < 1) { return `${(rate * 60).toFixed(1)} files/min`; } else { return `${rate.toFixed(1)} files/sec`; } } // Method to create a summary of the analysis createSummary(totalFiles, rulesExtracted, errors) { const elapsed = Date.now() - this.startTime; const rate = ProgressTracker.formatProcessingRate(totalFiles, elapsed); console.log('\n' + chalk_1.default.bold('Analysis Summary:')); console.log(` ${chalk_1.default.green('✓')} Files processed: ${totalFiles}`); console.log(` ${chalk_1.default.green('✓')} Rules extracted: ${rulesExtracted}`); console.log(` ${chalk_1.default.blue('ℹ')} Processing rate: ${rate}`); console.log(` ${chalk_1.default.blue('ℹ')} Total time: ${this.formatDuration(elapsed)}`); if (errors.length > 0) { console.log(` ${chalk_1.default.yellow('⚠')} Errors encountered: ${errors.length}`); if (this.verbose) { errors.forEach(error => { console.log(` ${chalk_1.default.gray('•')} ${error}`); }); } } } } exports.ProgressTracker = ProgressTracker; //# sourceMappingURL=progress-tracker.js.map