UNPKG

@push.rocks/smartlog

Version:

A minimalistic, distributed, and extensible logging tool supporting centralized log management.

345 lines 24.6 kB
import * as plugins from './smartlog-source-interactive.plugins.js'; /** * Utility to detect if the environment is interactive * Checks for TTY capability and common CI environment variables */ const isInteractive = () => { try { return Boolean( // Check TTY capability process.stdout && process.stdout.isTTY && // Additional checks for non-interactive environments !('CI' in process.env) && !process.env.GITHUB_ACTIONS && !process.env.JENKINS_URL && !process.env.GITLAB_CI && !process.env.TRAVIS && !process.env.CIRCLECI && process.env.TERM !== 'dumb'); } catch (e) { // If any error occurs (e.g., in browser environments without process), // assume a non-interactive environment to be safe return false; } }; // Helper to log messages in non-interactive mode const logMessage = (message, prefix = '') => { if (prefix) { console.log(`${prefix} ${message}`); } else { console.log(message); } }; // Spinner frames and styles const spinnerFrames = { dots: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'], line: ['|', '/', '-', '\\'], star: ['✶', '✸', '✹', '✺', '✹', '✷'], simple: ['-', '\\', '|', '/'] }; // Color names mapping to ANSI color codes const colors = { black: '\u001b[30m', red: '\u001b[31m', green: '\u001b[32m', yellow: '\u001b[33m', blue: '\u001b[34m', magenta: '\u001b[35m', cyan: '\u001b[36m', white: '\u001b[37m', gray: '\u001b[90m', reset: '\u001b[0m' }; /** * A class for creating interactive spinners * Automatically handles non-interactive environments */ export class SmartlogSourceInteractive { constructor() { this.textContent = 'loading'; this.currentFrame = 0; this.interval = null; this.started = false; this.spinnerStyle = 'dots'; this.color = 'cyan'; this.frameInterval = 80; this.frames = spinnerFrames[this.spinnerStyle]; this.interactive = isInteractive(); } /** * Sets the text for the spinner and starts it if not already started */ text(textArg) { this.textContent = textArg; if (!this.interactive) { // In non-interactive mode, just log the message with a loading indicator logMessage(textArg, '[Loading]'); this.started = true; return; } if (!this.started) { this.started = true; this.start(); } else { this.renderFrame(); } } /** * Starts the spinner animation */ start() { if (!this.interactive) { return; // No animation in non-interactive mode } if (this.interval) { clearInterval(this.interval); } this.renderFrame(); this.interval = setInterval(() => { this.currentFrame = (this.currentFrame + 1) % this.frames.length; this.renderFrame(); }, this.frameInterval); } /** * Renders the current frame of the spinner */ renderFrame() { if (!this.started || !this.interactive) return; const frame = this.frames[this.currentFrame]; const colorCode = colors[this.color]; const resetCode = colors.reset; // Only use ANSI escape codes in interactive mode process.stdout.write('\r\x1b[2K'); // Clear the current line process.stdout.write(`${colorCode}${frame}${resetCode} ${this.textContent}`); } /** * Stops the spinner */ stop() { // Always clear the interval even in non-interactive mode // This prevents memory leaks in tests and long-running applications if (this.interval) { clearInterval(this.interval); this.interval = null; } if (!this.interactive) { return; // No need to clear the line in non-interactive mode } process.stdout.write('\r\x1b[2K'); // Clear the current line } /** * Marks the spinner as successful and optionally displays a success message */ finishSuccess(textArg) { const message = textArg || this.textContent; // Always stop the spinner first to clean up intervals this.stop(); if (!this.interactive) { logMessage(message, '[Success]'); } else { const successSymbol = colors.green + '✓' + colors.reset; process.stdout.write(`${successSymbol} ${message}\n`); } this.started = false; } /** * Marks the spinner as failed and optionally displays a failure message */ finishFail(textArg) { const message = textArg || this.textContent; // Always stop the spinner first to clean up intervals this.stop(); if (!this.interactive) { logMessage(message, '[Failed]'); } else { const failSymbol = colors.red + '✗' + colors.reset; process.stdout.write(`${failSymbol} ${message}\n`); } this.started = false; } /** * Marks the current spinner as successful and starts a new one */ successAndNext(textArg) { this.finishSuccess(); this.text(textArg); } /** * Marks the current spinner as failed and starts a new one */ failAndNext(textArg) { this.finishFail(); this.text(textArg); } /** * Sets the spinner style */ setSpinnerStyle(style) { this.spinnerStyle = style; this.frames = spinnerFrames[style]; return this; } /** * Sets the spinner color */ setColor(colorName) { if (colorName in colors) { this.color = colorName; } return this; } /** * Sets the animation speed in milliseconds */ setSpeed(ms) { this.frameInterval = ms; if (this.started) { this.stop(); this.start(); } return this; } /** * Gets the current started state */ isStarted() { return this.started; } } export class SmartlogProgressBar { constructor(options) { this.current = 0; this.color = 'green'; this.startTime = null; this.lastRenderTime = 0; this.lastLoggedPercent = 0; this.logThreshold = 10; // Log every 10% in non-interactive mode this.total = options.total; this.width = options.width || 30; this.completeChar = options.complete || '█'; this.incomplete = options.incomplete || '░'; this.renderThrottle = options.renderThrottle || 16; this.clear = options.clear !== undefined ? options.clear : false; this.showEta = options.showEta !== undefined ? options.showEta : true; this.showPercent = options.showPercent !== undefined ? options.showPercent : true; this.showCount = options.showCount !== undefined ? options.showCount : true; this.interactive = isInteractive(); } /** * Update the progress bar to a specific value */ update(value) { if (this.startTime === null) { this.startTime = Date.now(); } this.current = Math.min(value, this.total); if (!this.interactive) { // In non-interactive mode, log progress at certain thresholds const percent = Math.floor((this.current / this.total) * 100); const currentThreshold = Math.floor(percent / this.logThreshold) * this.logThreshold; if (currentThreshold > this.lastLoggedPercent || percent === 100) { this.lastLoggedPercent = currentThreshold; logMessage(`Progress: ${percent}% (${this.current}/${this.total})`); } return this; } // Throttle rendering to avoid excessive updates in interactive mode const now = Date.now(); if (now - this.lastRenderTime < this.renderThrottle) { return this; } this.lastRenderTime = now; this.render(); return this; } /** * Increment the progress bar by a value */ increment(value = 1) { return this.update(this.current + value); } /** * Mark the progress bar as complete */ complete() { this.update(this.total); if (!this.interactive) { logMessage(`Completed: 100% (${this.total}/${this.total})`); return this; } if (this.clear) { process.stdout.write('\r\x1b[2K'); } else { process.stdout.write('\n'); } return this; } /** * Set the color of the progress bar */ setColor(colorName) { if (colorName in colors) { this.color = colorName; } return this; } /** * Render the progress bar */ render() { if (!this.interactive) { return; // Don't render in non-interactive mode } // Calculate percent complete const percent = Math.floor((this.current / this.total) * 100); const completeLength = Math.round((this.current / this.total) * this.width); const incompleteLength = this.width - completeLength; // Build the progress bar const completePart = colors[this.color] + this.completeChar.repeat(completeLength) + colors.reset; const incompletePart = this.incomplete.repeat(incompleteLength); const progressBar = `[${completePart}${incompletePart}]`; // Calculate ETA if needed let etaStr = ''; if (this.showEta && this.startTime !== null && this.current > 0) { const elapsed = (Date.now() - this.startTime) / 1000; const rate = this.current / elapsed; const remaining = Math.max(0, this.total - this.current); const eta = Math.round(remaining / rate); const mins = Math.floor(eta / 60); const secs = eta % 60; etaStr = ` eta: ${mins}m${secs}s`; } // Build additional information const percentStr = this.showPercent ? ` ${percent}%` : ''; const countStr = this.showCount ? ` ${this.current}/${this.total}` : ''; // Clear the line and render process.stdout.write('\r\x1b[2K'); process.stdout.write(`${progressBar}${percentStr}${countStr}${etaStr}`); } } // For backward compatibility with 'source-ora' module export class SmartlogSourceOra extends SmartlogSourceInteractive { // Add a stub for the oraInstance property for backward compatibility get oraInstance() { // Use public methods instead of accessing private properties const instance = this; return { get text() { return ''; }, // We can't access private textContent directly start: () => instance.text(''), // This starts the spinner stop: () => instance.stop(), succeed: (text) => instance.finishSuccess(text), fail: (text) => instance.finishFail(text) }; } set oraInstance(value) { // No-op, just for compatibility } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c19zb3VyY2VfaW50ZXJhY3RpdmUvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSwwQ0FBMEMsQ0FBQztBQUVwRTs7O0dBR0c7QUFDSCxNQUFNLGFBQWEsR0FBRyxHQUFHLEVBQUU7SUFDekIsSUFBSSxDQUFDO1FBQ0gsT0FBTyxPQUFPO1FBQ1osdUJBQXVCO1FBQ3ZCLE9BQU8sQ0FBQyxNQUFNLElBQUksT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLO1lBRXRDLHFEQUFxRDtZQUNyRCxDQUFDLENBQUMsSUFBSSxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUM7WUFDdEIsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWM7WUFDM0IsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLFdBQVc7WUFDeEIsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLFNBQVM7WUFDdEIsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU07WUFDbkIsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVE7WUFDckIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUM1QixDQUFDO0lBQ0osQ0FBQztJQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDWCx1RUFBdUU7UUFDdkUsa0RBQWtEO1FBQ2xELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztBQUNILENBQUMsQ0FBQztBQUVGLGlEQUFpRDtBQUNqRCxNQUFNLFVBQVUsR0FBRyxDQUFDLE9BQWUsRUFBRSxNQUFNLEdBQUcsRUFBRSxFQUFFLEVBQUU7SUFDbEQsSUFBSSxNQUFNLEVBQUUsQ0FBQztRQUNYLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxNQUFNLElBQUksT0FBTyxFQUFFLENBQUMsQ0FBQztJQUN0QyxDQUFDO1NBQU0sQ0FBQztRQUNOLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxD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