@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
JavaScript
"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;
}