UNPKG

iop

Version:
355 lines 13.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.logger = exports.Logger = void 0; class Logger { constructor(options = {}) { this.startTime = Date.now(); this.stepStartTime = Date.now(); this.activeSpinner = null; this.spinnerChars = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]; this.spinnerIndex = 0; // Track phase lines for in-place updates this.phaseLines = new Map(); this.currentOutputLine = 0; this.isVerbose = options.verbose || false; } // Getter for verbose mode get verbose() { return this.isVerbose; } // Setup-specific methods setupStart(message) { console.log(`${message}\n`); this.startTime = Date.now(); } setupComplete() { this.clearSpinner(); const totalDuration = Date.now() - this.startTime; console.log(`\n[✓] Setup completed successfully in ${this.formatDuration(totalDuration)}`); } setupFailed(error) { this.clearSpinner(); const totalDuration = Date.now() - this.startTime; console.log(`\n[✗] Setup failed after ${this.formatDuration(totalDuration)}`); if (this.isVerbose && error) { console.error(`Error details: ${error}`); } } // Main phase headers deploymentStart(releaseId) { this.startTime = Date.now(); } phase(message) { this.clearSpinner(); this.startSpinner(message, 0); } phaseComplete(message, duration) { this.clearSpinner(); const elapsed = duration || Date.now() - this.stepStartTime; console.log(`[✓] ${message} (${this.formatDuration(elapsed)})`); this.currentOutputLine++; } phaseError(message, error) { this.clearSpinner(); console.log(`[✗] ${message}`); if (error && this.isVerbose) { console.error(` Error details: ${error}`); } } // Tree-style logging for hierarchical operations step(message, level = 0) { this.clearSpinner(); const indent = this.getIndent(level); this.startSpinner(`${indent}${message}`, level); } stepComplete(message, duration, level = 0) { this.clearSpinner(); const indent = this.getIndent(level); const elapsed = duration || Date.now() - this.stepStartTime; console.log(`${indent}[✓] ${message} (${this.formatDuration(elapsed)})`); } stepLast(message, duration, level = 0) { this.clearSpinner(); const indent = this.getIndent(level); const elapsed = duration || Date.now() - this.stepStartTime; console.log(`${indent}[✓] ${message} (${this.formatDuration(elapsed)})`); } stepError(message, error, level = 0) { this.clearSpinner(); const indent = this.getIndent(level); console.log(`${indent}[✗] ${message}`); if (error && this.isVerbose) { console.error(`${indent} Error: ${error}`); } } // Server-specific operations server(hostname) { this.clearSpinner(); console.log(` └─ ${hostname}`); } // New method for app-specific deployment logging appDeployment(appName, servers, isLast = false) { this.clearSpinner(); const symbol = isLast ? "└─" : "├─"; if (servers.length === 1) { console.log(` ${symbol} ${appName}${servers[0]}`); } else { console.log(` ${symbol} ${appName}${servers.join(", ")}`); } this.currentOutputLine++; } // Service deployment progress logging serviceDeploymentStep(serviceName, message, isLast = false) { this.clearSpinner(); const symbol = isLast ? "└─" : "├─"; this.startSpinnerAtPosition(` ${symbol} `, `${serviceName}${message}`, 2); } serviceDeploymentComplete(serviceName, message, duration, isLast = false) { this.clearSpinner(); const symbol = isLast ? "└─" : "├─"; const elapsed = duration || Date.now() - this.stepStartTime; console.log(` ${symbol} [✓] ${serviceName}${message} (${this.formatDuration(elapsed)})`); this.currentOutputLine++; } serviceDeploymentSkipped(serviceName, reason, isLast = false) { this.clearSpinner(); const symbol = isLast ? "└─" : "├─"; console.log(` ${symbol} [✓] ${serviceName}${reason}`); this.currentOutputLine++; } // Build steps that work within a phase buildStep(message, isLast = false) { // Don't clear the main spinner, just pause it and show the step const wasSpinning = this.activeSpinner !== null; if (wasSpinning) { // Pause the main spinner this.clearSpinner(); } const symbol = isLast ? "└─" : "├─"; this.startSpinnerAtPosition(` ${symbol} `, message, 2); } buildStepComplete(message, duration, isLast = false) { this.clearSpinner(); const symbol = isLast ? "└─" : "├─"; const elapsed = duration || Date.now() - this.stepStartTime; console.log(` ${symbol} [✓] ${message} (${this.formatDuration(elapsed)})`); this.currentOutputLine++; // If this was the last step, don't restart the main spinner // The main phase will complete and show its own checkmark } // Complete a build phase with timing (replaces the [i] with [✓]) buildPhaseComplete(message, duration, subStepCount = 0) { this.clearSpinner(); // Move cursor up past all sub-steps to overwrite the [i] line const linesToMoveUp = subStepCount + 1; // +1 for the current position process.stdout.write(`\x1b[${linesToMoveUp}A\x1b[2K`); console.log(`[✓] ${message} (${this.formatDuration(duration)})`); // Move cursor back down to the bottom if (subStepCount > 0) { process.stdout.write(`\x1b[${subStepCount}B`); } } serverStep(message, isLast = false, isLastParent = false) { this.clearSpinner(); const symbol = isLast ? "└─" : "├─"; const prefix = isLastParent ? " " : " │ "; this.startSpinnerAtPosition(`${prefix}${symbol} `, message, 2); } serverStepComplete(message, duration, isLast = false, isLastParent = false) { this.clearSpinner(); const symbol = isLast ? "└─" : "├─"; const prefix = isLastParent ? " " : " │ "; const elapsed = duration || Date.now() - this.stepStartTime; console.log(`${prefix}${symbol} [✓] ${message} (${this.formatDuration(elapsed)})`); this.currentOutputLine++; } serverStepError(message, error, isLast = false, isLastParent = false) { this.clearSpinner(); const symbol = isLast ? "└─" : "├─"; const prefix = isLastParent ? " " : " │ "; console.log(`${prefix}${symbol} [✗] ${message}`); if (error && this.isVerbose) { console.error(`${prefix} Error: ${error}`); } } // Final results deploymentComplete(appUrls = []) { this.clearSpinner(); if (appUrls.length > 0) { const isPlural = appUrls.length > 1; const appText = isPlural ? "apps are" : "app is"; console.log(`\nYour ${appText} live at:`); appUrls.forEach((appUrl, index) => { const isLast = index === appUrls.length - 1; const symbol = isLast ? "└─" : "├─"; console.log(` ${symbol} ${appUrl.appName}${appUrl.url}`); }); } } deploymentFailed(error) { this.clearSpinner(); const totalDuration = Date.now() - this.startTime; console.log(`[✗] Deployment failed after ${this.formatDuration(totalDuration)}`); if (this.isVerbose && error) { console.error(`\nError details: ${error}`); } } // Verbose logging (only shown if verbose mode is enabled) verboseLog(message) { if (this.isVerbose) { this.clearSpinner(); console.log(` ${message}`); // Restart spinner if one was active if (this.activeSpinner) { this.restartSpinner(); } } } // Warning messages warn(message) { this.clearSpinner(); console.warn(`[!] ${message}`); } // Error messages error(message, error) { this.clearSpinner(); console.error(`[✗] ${message}`); if (error && this.isVerbose) { console.error(` Error details: ${error}`); } } // Info messages info(message) { this.clearSpinner(); console.log(`[i] ${message}`); } // Simple parent phase (shows [ ] initially, then [✓] when complete) phaseStart(message) { this.clearSpinner(); console.log(`[ ] ${message}`); this.phaseLines.set(message, this.currentOutputLine); this.currentOutputLine++; } phaseEnd(message) { this.clearSpinner(); const phaseLineNumber = this.phaseLines.get(message); if (phaseLineNumber !== undefined) { // Calculate how many lines to move up const linesToMoveUp = this.currentOutputLine - phaseLineNumber; if (linesToMoveUp > 0) { // Move cursor up to the phase line process.stdout.write(`\u001b[${linesToMoveUp}A`); // Clear the line and write new content process.stdout.write('\u001b[2K\r'); process.stdout.write(`[✓] ${message}`); // Move cursor back down to current position and to start of line process.stdout.write(`\u001b[${linesToMoveUp}B\r`); } else { // If we're on the same line, just update it process.stdout.write('\u001b[2K\r'); process.stdout.write(`[✓] ${message}\n`); } // Clean up this.phaseLines.delete(message); } else { // Fallback to regular output console.log(`[✓] ${message}`); } } // Spinner management startSpinner(message, level = 0) { this.clearSpinner(); const startTime = Date.now(); this.stepStartTime = startTime; const updateSpinner = () => { const elapsed = Date.now() - startTime; const spinner = this.spinnerChars[this.spinnerIndex]; const timeStr = this.formatDuration(elapsed); // Clear the current line and write the spinner process.stdout.write("\r\x1b[K"); process.stdout.write(`[${spinner}] ${message}... (${timeStr})`); this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerChars.length; }; // Initial display updateSpinner(); // Set up interval for updates const interval = setInterval(updateSpinner, 100); this.activeSpinner = { startTime, interval, message, level, }; } startSpinnerAtPosition(prefix, message, level = 0) { this.clearSpinner(); const startTime = Date.now(); this.stepStartTime = startTime; const updateSpinner = () => { const elapsed = Date.now() - startTime; const spinner = this.spinnerChars[this.spinnerIndex]; const timeStr = this.formatDuration(elapsed); // Clear the current line and write the spinner with prefix positioning process.stdout.write("\r\x1b[K"); process.stdout.write(`${prefix}[${spinner}] ${message}... (${timeStr})`); this.spinnerIndex = (this.spinnerIndex + 1) % this.spinnerChars.length; }; // Initial display updateSpinner(); // Set up interval for updates const interval = setInterval(updateSpinner, 100); this.activeSpinner = { startTime, interval, message: `${prefix}${message}`, // Store full message for restart level, }; } clearSpinner() { if (this.activeSpinner) { clearInterval(this.activeSpinner.interval); // Clear the current line process.stdout.write("\r\x1b[K"); this.activeSpinner = null; } } restartSpinner() { if (this.activeSpinner) { const { message, level } = this.activeSpinner; this.startSpinner(message, level); } } // Helper methods getIndent(level) { return " ".repeat(level); } formatDuration(ms) { if (ms < 1000) { return `${ms}ms`; } const seconds = (ms / 1000).toFixed(1); return `${seconds}s`; } // Time tracking startStep() { this.stepStartTime = Date.now(); } getStepDuration() { return Date.now() - this.stepStartTime; } // Clean up on exit cleanup() { this.clearSpinner(); } // Public method to clear spinner when needed clear() { this.clearSpinner(); } } exports.Logger = Logger; // Export a default logger instance exports.logger = new Logger(); //# sourceMappingURL=logger.js.map