UNPKG

kist

Version:

Lightweight Package Pipeline Processor with Plugin Architecture

131 lines 4.27 kB
import { AbstractProcess } from "../abstract/AbstractProcess.js"; export class ProgressReporter extends AbstractProcess { constructor(options) { var _a, _b, _c; super(); this.completed = 0; this.startTime = 0; this.lastUpdateTime = 0; this.lastReportedPercentage = -1; this.isRunning = false; this.total = options.total; this.label = options.label || "Processing"; this.showPercentage = (_a = options.showPercentage) !== null && _a !== void 0 ? _a : true; this.showEta = (_b = options.showEta) !== null && _b !== void 0 ? _b : true; this.updateInterval = (_c = options.updateInterval) !== null && _c !== void 0 ? _c : 100; this.formatFn = options.formatFn; } start() { this.startTime = performance.now(); this.lastUpdateTime = this.startTime; this.completed = 0; this.isRunning = true; this.report(); } increment(amount = 1) { this.completed = Math.min(this.completed + amount, this.total); this.maybeReport(); } setCompleted(value) { this.completed = Math.min(Math.max(0, value), this.total); this.maybeReport(); } finish() { this.completed = this.total; this.isRunning = false; this.report(true); } cancel() { this.isRunning = false; this.logWarn(`${this.label}: Cancelled at ${this.getPercentage().toFixed(1)}%`); } getState() { const elapsed = performance.now() - this.startTime; const rate = this.completed / (elapsed / 1000) || 0; const remaining = this.total - this.completed; const eta = rate > 0 ? (remaining / rate) * 1000 : null; return { completed: this.completed, total: this.total, percentage: this.getPercentage(), elapsed, eta, rate, label: this.label, }; } getPercentage() { return this.total > 0 ? (this.completed / this.total) * 100 : 0; } getElapsed() { return performance.now() - this.startTime; } maybeReport() { const now = performance.now(); if (now - this.lastUpdateTime >= this.updateInterval) { this.report(); this.lastUpdateTime = now; } } report(force = false) { const percentage = Math.floor(this.getPercentage()); if (!force && percentage === this.lastReportedPercentage) { return; } this.lastReportedPercentage = percentage; const state = this.getState(); let message; if (this.formatFn) { message = this.formatFn(state); } else { message = this.formatProgress(state); } this.logInfo(message); } formatProgress(state) { const parts = [state.label]; parts.push(`${state.completed}/${state.total}`); if (this.showPercentage) { parts.push(`(${state.percentage.toFixed(1)}%)`); } if (this.showEta && state.eta !== null && state.completed < state.total) { parts.push(`ETA: ${this.formatDuration(state.eta)}`); } if (state.completed === state.total) { parts.push(`Done in ${this.formatDuration(state.elapsed)}`); } return parts.join(" "); } formatDuration(ms) { if (ms < 1000) { return `${Math.round(ms)}ms`; } if (ms < 60000) { return `${(ms / 1000).toFixed(1)}s`; } const minutes = Math.floor(ms / 60000); const seconds = Math.round((ms % 60000) / 1000); return `${minutes}m ${seconds}s`; } } export function createFileProgress(fileCount, label = "Processing files") { return new ProgressReporter({ total: fileCount, label, showPercentage: true, showEta: true, }); } export function createBuildProgress(stepCount, label = "Building") { return new ProgressReporter({ total: stepCount, label, showPercentage: true, showEta: true, updateInterval: 250, }); } //# sourceMappingURL=ProgressReporter.js.map