UNPKG

simplest-fancy-logger

Version:

A lightweight and easy-to-use logging library for Node.js applications

164 lines (135 loc) 4.23 kB
import fs from "fs" import path from "path" import chalk from "chalk" const logLevels = { error: 0, warn: 1, info: 2, debug: 3, } as const const levelColors = { error: "red", warn: "yellow", info: "green", debug: "blue", } as const const levelEmojis = { error: "❌", warn: "⚠️", info: "✅", debug: "🐛", } as const type LogLevel = "error" | "warn" | "info" | "debug" interface SimpleLoggerOptions { logLevel?: LogLevel logFile?: string logFormat?: string dateFormat?: string maxFileSize?: number maxFiles?: number } class SimpleLogger { logLevel: "error" | "warn" | "info" | "debug" logFile: string | null logFormat: string dateFormat: string maxFileSize: number maxFiles: number constructor(options: SimpleLoggerOptions = {}) { this.logLevel = options.logLevel || "info" this.logFile = options.logFile || null this.logFormat = options.logFormat || "[{level}] [{timestamp}] - {message} - {emoji}" this.dateFormat = options.dateFormat || "yyyy-mm-dd HH:MM:ss" this.maxFileSize = options.maxFileSize || 1024 * 1024 * 10 // 10MB this.maxFiles = options.maxFiles || 5 } log(level: LogLevel, message: string) { if (logLevels[level] <= logLevels[this.logLevel]) { const timestamp = this.formatDate(new Date()) const logMessage = this.formatMessage(timestamp, level, message) console.log(logMessage) if (this.logFile) { this.writeToFile(logMessage) } } } formatDate(date: Date) { const year = String(date.getFullYear()) const month = String(date.getMonth() + 1).padStart(2, "0") const day = String(date.getDate()).padStart(2, "0") const hours = String(date.getHours()).padStart(2, "0") const minutes = String(date.getMinutes()).padStart(2, "0") const seconds = String(date.getSeconds()).padStart(2, "0") return this.dateFormat .replace("yyyy", year) .replace("mm", month) .replace("dd", day) .replace("HH", hours) .replace("MM", minutes) .replace("ss", seconds) } formatMessage(timestamp: string, level: LogLevel, message: string) { const levelColor = levelColors[level] || "white" const levelEmoji = levelEmojis[level] || "" const formattedMessage = this.logFormat .replace("{timestamp}", chalk.magenta(timestamp)) .replace("{level}", chalk[levelColor](level.toUpperCase())) .replace("{message}", message) .replace("{emoji}", levelEmoji) return formattedMessage } writeToFile(logMessage: string) { if (!this.logFile) { return } const fileSize = fs.existsSync(this.logFile) ? fs.statSync(this.logFile).size : 0 if (fileSize >= this.maxFileSize) { this.rotateLogFile() } fs.appendFileSync(this.logFile, logMessage + "\n") } rotateLogFile() { if (!this.logFile) { return } const extension = path.extname(this.logFile) const baseName = path.basename(this.logFile, extension) const dirName = path.dirname(this.logFile) // Correcting the deletion and rotation logic const oldestFile = path.join( dirName, `${baseName}.${this.maxFiles}${extension}` ) if (fs.existsSync(oldestFile)) { fs.unlinkSync(oldestFile) } for (let i = this.maxFiles - 1; i > 0; i--) { const currentFile = path.join(dirName, `${baseName}.${i}${extension}`) const newFile = path.join(dirName, `${baseName}.${i + 1}${extension}`) if (fs.existsSync(currentFile)) { fs.renameSync(currentFile, newFile) } } const newFirstFile = path.join(dirName, `${baseName}.1${extension}`) if (fs.existsSync(this.logFile)) { fs.renameSync(this.logFile, newFirstFile) } } error(message: string) { this.log("error", message) } warn(message: string) { this.log("warn", message) } info(message: string) { this.log("info", message) } debug(message: string) { this.log("debug", message) } } // module export default export default SimpleLogger