UNPKG

@re-shell/cli

Version:

Full-stack development platform uniting microservices and microfrontends. Build complete applications with .NET (ASP.NET Core Web API, Minimal API), Java (Spring Boot, Quarkus, Micronaut, Vert.x), Rust (Actix-Web, Warp, Rocket, Axum), Python (FastAPI, Dja

296 lines (295 loc) 10.4 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Logger = exports.LogLevel = void 0; exports.createLogger = createLogger; exports.getGlobalLogger = getGlobalLogger; exports.setGlobalLogger = setGlobalLogger; const chalk_1 = __importDefault(require("chalk")); const fs = __importStar(require("fs-extra")); const path = __importStar(require("path")); const util_1 = require("util"); var LogLevel; (function (LogLevel) { LogLevel[LogLevel["DEBUG"] = 0] = "DEBUG"; LogLevel[LogLevel["INFO"] = 1] = "INFO"; LogLevel[LogLevel["WARN"] = 2] = "WARN"; LogLevel[LogLevel["ERROR"] = 3] = "ERROR"; LogLevel[LogLevel["SUCCESS"] = 4] = "SUCCESS"; LogLevel[LogLevel["SILENT"] = 99] = "SILENT"; })(LogLevel || (exports.LogLevel = LogLevel = {})); class Logger { constructor(options = {}) { this.currentFileSize = 0; this.rotationIndex = 0; this.level = options.level ?? LogLevel.INFO; this.file = options.file; this.maxFileSize = options.maxFileSize ?? 10 * 1024 * 1024; // 10MB this.maxFiles = options.maxFiles ?? 5; this.json = options.json ?? false; this.timestamp = options.timestamp ?? true; this.color = options.color ?? process.stdout.isTTY; this.context = options.context ?? {}; if (this.file) { this.initializeFile(); } } initializeFile() { if (!this.file) return; const dir = path.dirname(this.file); fs.ensureDirSync(dir); // Check if file exists and get size if (fs.existsSync(this.file)) { const stats = fs.statSync(this.file); this.currentFileSize = stats.size; } // Create write stream this.fileStream = fs.createWriteStream(this.file, { flags: 'a' }); } rotateFile() { if (!this.file || !this.fileStream) return; // Close current stream this.fileStream.end(); // Rotate files for (let i = this.maxFiles - 1; i > 0; i--) { const oldFile = `${this.file}.${i}`; const newFile = `${this.file}.${i + 1}`; if (fs.existsSync(oldFile)) { if (i === this.maxFiles - 1) { fs.unlinkSync(oldFile); // Delete oldest } else { fs.renameSync(oldFile, newFile); } } } // Rename current file fs.renameSync(this.file, `${this.file}.1`); // Reset and create new file this.currentFileSize = 0; this.fileStream = fs.createWriteStream(this.file, { flags: 'a' }); } shouldLog(level) { return level >= this.level; } formatMessage(entry) { if (this.json) { return JSON.stringify({ level: LogLevel[entry.level], timestamp: entry.timestamp.toISOString(), message: entry.message, ...this.context, ...entry.context, ...(entry.error && { error: { name: entry.error.name, message: entry.error.message, stack: entry.error.stack } }) }); } let message = ''; // Add timestamp if (this.timestamp) { const time = entry.timestamp.toLocaleTimeString(); message += this.color ? chalk_1.default.gray(`[${time}]`) : `[${time}]`; message += ' '; } // Add level const levelStr = this.getLevelString(entry.level); message += levelStr + ' '; // Add message message += entry.message; // Add context if (entry.context && Object.keys(entry.context).length > 0) { const contextStr = JSON.stringify(entry.context, null, 2); message += '\n' + (this.color ? chalk_1.default.gray(contextStr) : contextStr); } // Add error if (entry.error) { message += '\n' + (this.color ? chalk_1.default.red(entry.error.stack || entry.error.message) : (entry.error.stack || entry.error.message)); } return message; } getLevelString(level) { switch (level) { case LogLevel.DEBUG: return this.color ? chalk_1.default.gray('DEBUG') : 'DEBUG'; case LogLevel.INFO: return this.color ? chalk_1.default.blue('INFO') : 'INFO'; case LogLevel.WARN: return this.color ? chalk_1.default.yellow('WARN') : 'WARN'; case LogLevel.ERROR: return this.color ? chalk_1.default.red('ERROR') : 'ERROR'; case LogLevel.SUCCESS: return this.color ? chalk_1.default.green('SUCCESS') : 'SUCCESS'; default: return 'UNKNOWN'; } } log(entry) { if (!this.shouldLog(entry.level)) return; const message = this.formatMessage(entry); // Console output if (entry.level === LogLevel.ERROR) { console.error(message); } else { console.log(message); } // File output if (this.fileStream) { const fileMessage = this.json ? message : message.replace(/\x1b\[[0-9;]*m/g, ''); // Remove color codes const data = fileMessage + '\n'; this.fileStream.write(data); this.currentFileSize += Buffer.byteLength(data); // Check if rotation needed if (this.currentFileSize >= this.maxFileSize) { this.rotateFile(); } } } debug(message, ...args) { this.log({ level: LogLevel.DEBUG, timestamp: new Date(), message: (0, util_1.format)(message, ...args), context: this.extractContext(args) }); } info(message, ...args) { this.log({ level: LogLevel.INFO, timestamp: new Date(), message: (0, util_1.format)(message, ...args), context: this.extractContext(args) }); } warn(message, ...args) { this.log({ level: LogLevel.WARN, timestamp: new Date(), message: (0, util_1.format)(message, ...args), context: this.extractContext(args) }); } error(message, error, ...args) { const isError = error instanceof Error; this.log({ level: LogLevel.ERROR, timestamp: new Date(), message: (0, util_1.format)(message, ...(isError ? args : [error, ...args])), context: this.extractContext(args), error: isError ? error : undefined }); } success(message, ...args) { this.log({ level: LogLevel.SUCCESS, timestamp: new Date(), message: (0, util_1.format)(message, ...args), context: this.extractContext(args) }); } extractContext(args) { const lastArg = args[args.length - 1]; if (lastArg && typeof lastArg === 'object' && !Array.isArray(lastArg) && !(lastArg instanceof Error) && !(lastArg instanceof Date)) { return lastArg; } return undefined; } setLevel(level) { this.level = level; } getLevel() { return this.level; } child(context) { return new Logger({ level: this.level, file: this.file, maxFileSize: this.maxFileSize, maxFiles: this.maxFiles, json: this.json, timestamp: this.timestamp, color: this.color, context: { ...this.context, ...context } }); } close() { if (this.fileStream) { this.fileStream.end(); this.fileStream = undefined; } } } exports.Logger = Logger; // Global logger instance let globalLogger = null; function createLogger(options) { return new Logger(options); } function getGlobalLogger() { if (!globalLogger) { const logLevel = process.env.LOG_LEVEL ? LogLevel[process.env.LOG_LEVEL.toUpperCase()] ?? LogLevel.INFO : LogLevel.INFO; const logFile = process.env.LOG_FILE || (process.env.CI ? undefined : path.join(process.cwd(), '.re-shell', 'logs', 'cli.log')); globalLogger = new Logger({ level: logLevel, file: logFile, json: process.env.LOG_JSON === 'true', timestamp: true, color: !process.env.CI && !process.env.NO_COLOR }); } return globalLogger; } function setGlobalLogger(logger) { if (globalLogger) { globalLogger.close(); } globalLogger = logger; }