UNPKG

semantic-ds-toolkit

Version:

Performance-first semantic layer for modern data stacks - Stable Column Anchors & intelligent inference

292 lines • 10.7 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BatchProgressReporter = exports.HealthCheckProgressReporter = exports.InitProgressReporter = exports.InferenceProgressReporter = exports.ProgressReporter = void 0; exports.createProgressBar = createProgressBar; const chalk_1 = __importDefault(require("chalk")); const ora_1 = __importDefault(require("ora")); class ProgressReporter { steps = []; currentStep = null; spinner = null; startTime = 0; options; constructor(options = {}) { this.options = { showTimer: true, showDetails: false, compact: false, emoji: true, ...options }; } addSteps(steps) { this.steps = steps.map(step => ({ ...step, status: 'pending' })); } start(title) { this.startTime = Date.now(); if (title) { console.log(chalk_1.default.blue.bold(`\nšŸš€ ${title}\n`)); } this.renderProgress(); } startStep(stepId, text) { const step = this.steps.find(s => s.id === stepId); if (!step) return; this.currentStep = stepId; step.status = 'running'; if (text) step.text = text; if (this.spinner) { this.spinner.stop(); } const emoji = this.getStatusEmoji('running'); this.spinner = (0, ora_1.default)(`${emoji} ${step.text}`).start(); } updateStep(stepId, text, details) { const step = this.steps.find(s => s.id === stepId); if (!step) return; step.text = text; if (details) step.details = details; if (this.currentStep === stepId && this.spinner) { const emoji = this.getStatusEmoji('running'); this.spinner.text = `${emoji} ${step.text}`; } } completeStep(stepId, text, details) { const step = this.steps.find(s => s.id === stepId); if (!step) return; step.status = 'completed'; if (text) step.text = text; if (details) step.details = details; if (this.currentStep === stepId && this.spinner) { const emoji = this.getStatusEmoji('completed'); this.spinner.succeed(`${emoji} ${step.text}`); this.spinner = null; this.currentStep = null; } if (this.options.showDetails && details) { console.log(chalk_1.default.gray(` ${details}`)); } } failStep(stepId, error, details) { const step = this.steps.find(s => s.id === stepId); if (!step) return; step.status = 'failed'; step.details = error; if (this.currentStep === stepId && this.spinner) { const emoji = this.getStatusEmoji('failed'); this.spinner.fail(`${emoji} ${step.text} - ${error}`); this.spinner = null; this.currentStep = null; } if (details) { console.log(chalk_1.default.red(` ${details}`)); } } skipStep(stepId, reason) { const step = this.steps.find(s => s.id === stepId); if (!step) return; step.status = 'skipped'; if (reason) step.details = reason; const emoji = this.getStatusEmoji('skipped'); console.log(chalk_1.default.yellow(`${emoji} ${step.text} - Skipped${reason ? `: ${reason}` : ''}`)); } complete(title) { if (this.spinner) { this.spinner.stop(); } const elapsed = (Date.now() - this.startTime) / 1000; const completed = this.steps.filter(s => s.status === 'completed').length; const failed = this.steps.filter(s => s.status === 'failed').length; const skipped = this.steps.filter(s => s.status === 'skipped').length; console.log(); if (title) { console.log(chalk_1.default.green.bold(`āœ… ${title}`)); } console.log(chalk_1.default.cyan(`šŸ“Š Summary:`)); console.log(chalk_1.default.white(` āœ… Completed: ${completed}`)); if (failed > 0) { console.log(chalk_1.default.red(` āŒ Failed: ${failed}`)); } if (skipped > 0) { console.log(chalk_1.default.yellow(` ā­ļø Skipped: ${skipped}`)); } if (this.options.showTimer) { console.log(chalk_1.default.gray(` ā±ļø Time: ${elapsed.toFixed(1)}s`)); } console.log(); } renderProgress() { if (this.options.compact) return; console.log(chalk_1.default.cyan('šŸ“‹ Progress:')); this.steps.forEach((step, index) => { const emoji = this.getStatusEmoji(step.status); const number = `${(index + 1).toString().padStart(2, ' ')}.`; console.log(chalk_1.default.gray(` ${number} ${emoji} ${step.text}`)); }); console.log(); } getStatusEmoji(status) { if (!this.options.emoji) { const symbols = { pending: 'ā—‹', running: 'ā—', completed: 'āœ“', failed: 'āœ—', skipped: 'āŠ' }; return symbols[status]; } const emojis = { pending: 'ā³', running: 'šŸ”„', completed: 'āœ…', failed: 'āŒ', skipped: 'ā­ļø' }; return emojis[status]; } // Utility methods for common workflows async runWithProgress(stepId, text, fn, successText) { this.startStep(stepId, text); try { const result = await fn(); this.completeStep(stepId, successText || text); return result; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; this.failStep(stepId, errorMessage); throw error; } } createSubProgress(parentStepId) { const subProgress = new ProgressReporter({ ...this.options, compact: true, showTimer: false }); // Link sub-progress to parent step const parentStep = this.steps.find(s => s.id === parentStepId); if (parentStep) { parentStep.subSteps = parentStep.subSteps || []; } return subProgress; } } exports.ProgressReporter = ProgressReporter; // Specialized progress reporters for common tasks class InferenceProgressReporter extends ProgressReporter { constructor(options = {}) { super(options); this.addSteps([ { id: 'load', text: 'Loading data files' }, { id: 'analyze', text: 'Analyzing data patterns' }, { id: 'infer', text: 'Running semantic inference' }, { id: 'validate', text: 'Validating results' }, { id: 'save', text: 'Saving semantic mappings' } ]); } async loadData(loader) { return this.runWithProgress('load', 'Loading and parsing data files...', loader, 'Data loaded successfully'); } async analyzePatterns(analyzer) { return this.runWithProgress('analyze', 'Analyzing data patterns and structure...', analyzer, 'Pattern analysis complete'); } async runInference(inferrer) { return this.runWithProgress('infer', 'Running semantic inference engine...', inferrer, 'Semantic inference complete'); } async validateResults(validator) { return this.runWithProgress('validate', 'Validating semantic mappings...', validator, 'Results validated'); } async saveResults(saver) { return this.runWithProgress('save', 'Saving semantic mappings...', saver, 'Results saved successfully'); } } exports.InferenceProgressReporter = InferenceProgressReporter; class InitProgressReporter extends ProgressReporter { constructor(options = {}) { super(options); this.addSteps([ { id: 'validate', text: 'Validating project directory' }, { id: 'create', text: 'Creating project structure' }, { id: 'config', text: 'Generating configuration files' }, { id: 'samples', text: 'Creating sample files' }, { id: 'deps', text: 'Installing dependencies' } ]); } } exports.InitProgressReporter = InitProgressReporter; class HealthCheckProgressReporter extends ProgressReporter { constructor(options = {}) { super(options); this.addSteps([ { id: 'scan', text: 'Scanning project files' }, { id: 'coverage', text: 'Analyzing semantic coverage' }, { id: 'performance', text: 'Running performance checks' }, { id: 'validation', text: 'Validating configuration' }, { id: 'report', text: 'Generating health report' } ]); } } exports.HealthCheckProgressReporter = HealthCheckProgressReporter; // Progress bar utilities class BatchProgressReporter { total; current = 0; spinner; lastUpdate = 0; constructor(total, title) { this.total = total; this.spinner = (0, ora_1.default)(this.getProgressText()).start(); } increment(message) { this.current++; const now = Date.now(); // Throttle updates to avoid spam if (now - this.lastUpdate > 100) { this.spinner.text = this.getProgressText(message); this.lastUpdate = now; } if (this.current >= this.total) { this.complete(); } } complete(message) { this.spinner.succeed(message || `āœ… Processed ${this.total} items`); } fail(error) { this.spinner.fail(`āŒ Failed: ${error}`); } getProgressText(message) { const percentage = Math.round((this.current / this.total) * 100); const bar = this.createProgressBar(percentage); const suffix = message ? ` - ${message}` : ''; return `${bar} ${percentage}% (${this.current}/${this.total})${suffix}`; } createProgressBar(percentage) { const width = 20; const filled = Math.round((percentage / 100) * width); const empty = width - filled; return `[${'ā–ˆ'.repeat(filled)}${' '.repeat(empty)}]`; } } exports.BatchProgressReporter = BatchProgressReporter; // Export utility function for quick progress bars function createProgressBar(total, title) { return new BatchProgressReporter(total, title); } //# sourceMappingURL=progress-reporter.js.map