UNPKG

seyfert

Version:

The most advanced framework for discord bots

261 lines (260 loc) 8.41 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Logger = exports.LogLevels = void 0; exports.formatMemoryUsage = formatMemoryUsage; const node_fs_1 = require("node:fs"); const node_path_1 = require("node:path"); const colors_1 = require("./colors"); const utils_1 = require("./utils"); var LogLevels; (function (LogLevels) { LogLevels[LogLevels["Debug"] = 0] = "Debug"; LogLevels[LogLevels["Info"] = 1] = "Info"; LogLevels[LogLevels["Warn"] = 2] = "Warn"; LogLevels[LogLevels["Error"] = 3] = "Error"; LogLevels[LogLevels["Fatal"] = 4] = "Fatal"; })(LogLevels || (exports.LogLevels = LogLevels = {})); /** * Represents a logger utility for logging messages with various log levels. */ class Logger { /** * The options for configuring the logger. */ options; static saveOnFile; static dirname = 'seyfert-logs'; static streams = {}; static fileNames = {}; static createdDir; static __assignFileName = self => { const date = new Date(); return `${self.name}-${date.getMonth() + 1}-${date.getDate()}-${date.getFullYear()}-${date.getTime()}.log`; }; /** * The custom callback function for logging. */ static __callback = (self, level, args) => { const color = Logger.colorFunctions.get(level) ?? Logger.noColor; const memoryData = process.memoryUsage?.(); const date = new Date(); return [ (0, colors_1.brightBlack)(formatMemoryUsage(memoryData?.rss ?? 0)), (0, colors_1.bgBrightWhite)((0, colors_1.black)(`[${date.toLocaleDateString()} ${date.toLocaleTimeString()}]`)), color(Logger.prefixes.get(level) ?? 'DEBUG'), self.name ? `${self.name} >` : '>', ...args, ]; }; /** * Allows customization of the logging behavior by providing a custom callback function. * @param cb The custom callback function for logging. * @example * Logger.customize((logger, level, args) => { * // Custom logging implementation * }); */ static customize(cb) { Logger.__callback = cb; } /** * Customizes the logging filename by providing a callback function. * The callback receives the logger instance and should return the desired filename. * * @param cb - A function that takes the logger instance and returns a string * representing the customized filename for the log. * @example * Logger.customizeFilename((logger) => { * return `${logger.name}-${Date.now()}.log`; * }); */ static customizeFilename(cb) { Logger.__assignFileName = cb; } static async clearLogs() { for (const i of await node_fs_1.promises.readdir((0, node_path_1.join)(process.cwd(), Logger.dirname), { withFileTypes: true })) { if (Logger.streams[i.name]) await new Promise((res, rej) => Logger.streams[i.name].close(err => { if (err) return rej(err); res(err); })); await node_fs_1.promises.unlink((0, node_path_1.join)(process.cwd(), Logger.dirname, i.name)).catch(() => undefined); delete Logger.streams[i.name]; } } /** * Constructs a new Logger instance with the provided options. * @param options The options for configuring the logger. */ constructor(options) { this.options = (0, utils_1.MergeOptions)(Logger.DEFAULT_OPTIONS, options); } /** * Sets the log level of the logger. */ set level(level) { this.options.logLevel = level; } /** * Gets the log level of the logger. */ get level() { return this.options.logLevel; } set saveOnFile(saveOnFile) { this.options.saveOnFile = saveOnFile; } get saveOnFile() { return this.options.saveOnFile; } /** * Sets whether the logger is active or not. */ set active(active) { this.options.active = active; } /** * Gets whether the logger is active or not. */ get active() { return this.options.active; } /** * Sets the name of the logger. */ set name(name) { this.options.name = name; } /** * Gets the name of the logger. */ get name() { return this.options.name; } /** * Logs a message with the specified log level. * @param level The log level. * @param args The arguments to log. * @returns The logged message. */ rawLog(level, ...args) { if (!this.active) return; if (level < this.level) return; const log = Logger.__callback(this, level, args); if (!log) return; this.__write(log); return console.log(...log); } /** * Logs a debug message. * @param args The arguments to log. */ debug(...args) { this.rawLog(LogLevels.Debug, ...args); } /** * Logs an info message. * @param args The arguments to log. */ info(...args) { this.rawLog(LogLevels.Info, ...args); } /** * Logs a warning message. * @param args The arguments to log. */ warn(...args) { this.rawLog(LogLevels.Warn, ...args); } /** * Logs an error message. * @param args The arguments to log. */ error(...args) { this.rawLog(LogLevels.Error, ...args); } /** * Logs a fatal error message. * @param args The arguments to log. */ fatal(...args) { this.rawLog(LogLevels.Fatal, ...args); } __write(log) { if (this.saveOnFile || Logger.saveOnFile === 'all' || Logger.saveOnFile?.includes(this.name)) { if (!(Logger.createdDir || (0, node_fs_1.existsSync)((0, node_path_1.join)(process.cwd(), Logger.dirname)))) { Logger.createdDir = true; (0, node_fs_1.mkdirSync)((0, node_path_1.join)(process.cwd(), Logger.dirname), { recursive: true }); } const fileName = (Logger.fileNames[this.name] ??= (() => { return (Logger.fileNames[this.name] = Logger.__assignFileName(this)); })()); if (!Logger.streams[fileName]) { Logger.streams[fileName] = (0, node_fs_1.createWriteStream)((0, node_path_1.join)(process.cwd(), Logger.dirname, fileName)); } Logger.streams[fileName].write(`${(0, colors_1.stripColor)(log.join(' '))}\n`); } } /** * The default options for the logger. */ static DEFAULT_OPTIONS = { logLevel: LogLevels.Debug, name: 'seyfert', active: true, saveOnFile: false, }; /** * A function that returns the input string as is, without any color modification. * @param msg The message to log. * @returns The input message as is. */ static noColor(msg) { return msg; } /** * A map containing color functions for different log levels. */ static colorFunctions = new Map([ [LogLevels.Debug, colors_1.gray], [LogLevels.Info, colors_1.cyan], [LogLevels.Warn, colors_1.yellow], [LogLevels.Error, colors_1.red], [LogLevels.Fatal, (str) => (0, colors_1.red)((0, colors_1.bold)((0, colors_1.italic)(str)))], ]); /** * A map containing prefixes for different log levels. */ static prefixes = new Map([ [LogLevels.Debug, 'DEBUG'], [LogLevels.Info, 'INFO'], [LogLevels.Warn, 'WARN'], [LogLevels.Error, 'ERROR'], [LogLevels.Fatal, 'FATAL'], ]); } exports.Logger = Logger; /** * Formats memory usage data into a string. * @param data The memory usage data. * @returns The formatted string representing memory usage. */ function formatMemoryUsage(bytes) { const gigaBytes = bytes / 1024 ** 3; if (gigaBytes >= 1) { return `[RAM Usage ${gigaBytes.toFixed(3)} GB]`; } const megaBytes = bytes / 1024 ** 2; if (megaBytes >= 1) { return `[RAM Usage ${megaBytes.toFixed(2)} MB]`; } const kiloBytes = bytes / 1024; if (kiloBytes >= 1) { return `[RAM Usage ${kiloBytes.toFixed(2)} KB]`; } return `[RAM Usage ${bytes.toFixed(2)} B]`; }