kist
Version:
Lightweight Package Pipeline Processor with Plugin Architecture
131 lines • 4.27 kB
JavaScript
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