@rasla/express-logify
Version:
A beautiful, fast, and type-safe logging middleware for Express.js applications
131 lines (130 loc) • 4.33 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Logger = void 0;
const chalk_1 = __importDefault(require("chalk"));
const fs_1 = require("fs");
const path_1 = require("path");
const LOG_COLORS = {
debug: chalk_1.default.gray,
info: chalk_1.default.blue,
warn: chalk_1.default.yellow,
error: chalk_1.default.red,
};
class Logger {
constructor(options = {}) {
this.options = { ...Logger.DEFAULT_OPTIONS, ...options };
this.initializeFileLogger();
}
debug(input) {
this.log('debug', input);
}
info(input) {
this.log('info', input);
}
warn(input) {
this.log('warn', input);
}
error(input) {
this.log('error', input);
}
log(level, input) {
if (!this.shouldLog(level))
return;
const entry = this.createLogEntry(level, input);
const formattedMessage = this.formatLogEntry(entry);
if (this.options.console) {
const colorize = LOG_COLORS[level] || chalk_1.default.white;
console.log(colorize(formattedMessage));
}
if (this.options.file) {
this.writeToFile(formattedMessage);
}
}
shouldLog(level) {
const levels = ['debug', 'info', 'warn', 'error'];
const configuredLevel = levels.indexOf(this.options.level || 'info');
const currentLevel = levels.indexOf(level);
return currentLevel >= configuredLevel;
}
createLogEntry(level, input) {
const timestamp = new Date();
if (typeof input === 'string') {
return {
timestamp,
level,
method: '',
path: '',
statusCode: 0,
duration: 0,
message: input,
};
}
return {
timestamp,
level,
method: input.method || '',
path: input.path || '',
statusCode: input.statusCode || 0,
duration: input.duration || 0,
message: input.message || '',
ip: input.ip,
};
}
formatLogEntry(entry) {
const format = this.options.format || Logger.DEFAULT_OPTIONS.format;
const timestamp = entry.timestamp.toISOString();
const level = entry.level.toUpperCase().padEnd(5);
const method = (entry.method || '').toUpperCase().padEnd(7);
const path = entry.path || '-';
const statusCode = entry.statusCode ? `${entry.statusCode}` : '';
const duration = entry.duration ? `${entry.duration}` : '';
const message = entry.message || '';
const ip = entry.ip && this.options.includeIp ? ` from ${entry.ip}` : '';
return format
.replace('{timestamp}', timestamp)
.replace('{level}', level)
.replace('{method}', method)
.replace('{path}', path)
.replace('{statusCode}', statusCode)
.replace('{duration}', duration)
.replace('{message}', message)
.replace('{ip}', ip)
.trim();
}
writeToFile(message) {
if (this.options.file && this.options.filePath) {
try {
(0, fs_1.appendFileSync)(this.options.filePath, message + '\n');
}
catch (error) {
console.error('Failed to write to log file:', error);
}
}
}
initializeFileLogger() {
if (this.options.file && this.options.filePath) {
try {
const dir = (0, path_1.dirname)(this.options.filePath);
if (!(0, fs_1.existsSync)(dir)) {
(0, fs_1.mkdirSync)(dir, { recursive: true });
}
}
catch (error) {
console.error('Failed to initialize log directory:', error);
}
}
}
}
exports.Logger = Logger;
Logger.DEFAULT_OPTIONS = {
console: true,
file: false,
filePath: './logs/app.log',
level: 'info',
skip: [],
includeIp: false,
format: '[{timestamp}] {level} [{method}] {path} - {statusCode} {duration}ms{ip}',
};
;