UNPKG

@4players/odin-common

Version:

A collection of commonly used type definitions and utility functions across ODIN web projects

225 lines (224 loc) 7.76 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LogHandler = exports.PRETTY_FORMATTER = exports.DEFAULT_FORMATTER = exports.Logger = exports.LogFunctions = exports.LogSymbols = exports.LogLevelNames = exports.LogLevels = exports.LogVerbosity = void 0; exports.getLevelByName = getLevelByName; exports.getLevelName = getLevelName; exports.getLogger = getLogger; exports.error = error; exports.warn = warn; exports.info = info; exports.debug = debug; const result_1 = require("./result"); const validation_1 = require("./validation"); var LogVerbosity; (function (LogVerbosity) { LogVerbosity[LogVerbosity["NONE"] = 0] = "NONE"; LogVerbosity[LogVerbosity["ERROR"] = 1] = "ERROR"; LogVerbosity[LogVerbosity["WARN"] = 2] = "WARN"; LogVerbosity[LogVerbosity["INFO"] = 3] = "INFO"; LogVerbosity[LogVerbosity["DEBUG"] = 4] = "DEBUG"; })(LogVerbosity || (exports.LogVerbosity = LogVerbosity = {})); exports.LogLevels = Object.values(LogVerbosity).filter((key) => !isNaN(Number(key))); exports.LogLevelNames = Object.keys(LogVerbosity).filter((key) => isNaN(Number(key))); exports.LogSymbols = { [LogVerbosity.NONE]: '⚫', [LogVerbosity.ERROR]: '🔴', [LogVerbosity.WARN]: '🟡', [LogVerbosity.INFO]: '🔵', [LogVerbosity.DEBUG]: '🟣', }; exports.LogFunctions = { [LogVerbosity.NONE]: console.log, [LogVerbosity.ERROR]: console.error, [LogVerbosity.WARN]: console.warn, [LogVerbosity.INFO]: console.info, [LogVerbosity.DEBUG]: console.debug, }; function getLevelByName(name) { const level = LogVerbosity[name]; if (level === undefined) { return (0, result_1.failure)(`invalid log level name '${name}'; valid names are: ${exports.LogLevelNames.join(', ')}`); } return (0, result_1.success)(level); } function getLevelName(level) { const name = LogVerbosity[level]; if (name === undefined) { return (0, result_1.failure)(`invalid log level ${level}; valid levels are: ${exports.LogLevels[0]}-${exports.LogLevels[exports.LogLevels.length - 1]}`); } return (0, result_1.success)(name); } const LOG_DEFAULT_ID = 'default'; const LOG_COLLECTION = new Map(); function getLogger(name = LOG_DEFAULT_ID) { let logger = LOG_COLLECTION.get(name); if (!logger) { logger = new Logger('WARN', name); } return logger; } function error(msg, ...args) { if (msg instanceof Function) { return getLogger(LOG_DEFAULT_ID).error(msg, ...args); } return getLogger(LOG_DEFAULT_ID).error(msg, ...args); } function warn(msg, ...args) { if (msg instanceof Function) { return getLogger(LOG_DEFAULT_ID).warn(msg, ...args); } return getLogger(LOG_DEFAULT_ID).warn(msg, ...args); } function info(msg, ...args) { if (msg instanceof Function) { return getLogger(LOG_DEFAULT_ID).info(msg, ...args); } return getLogger(LOG_DEFAULT_ID).info(msg, ...args); } function debug(msg, ...args) { if (msg instanceof Function) { return getLogger(LOG_DEFAULT_ID).debug(msg, ...args); } return getLogger(LOG_DEFAULT_ID).debug(msg, ...args); } class Logger { constructor(level, name, options) { this.name = name ?? LOG_DEFAULT_ID; if ((0, validation_1.isNumber)(level)) { this._Level = (0, result_1.unwrap)(getLevelByName((0, result_1.unwrap)(getLevelName(level)))); } else { this._Level = (0, result_1.unwrap)(getLevelByName(level)); } this._Handlers = options?.handlers || [new LogHandler(level)]; LOG_COLLECTION.set(this.name, this); } get level() { return this._Level; } set level(value) { this.levelName = (0, result_1.unwrap)(getLevelName(value)); } get levelName() { return (0, result_1.unwrap)(getLevelName(this._Level)); } set levelName(value) { this._Level = (0, result_1.unwrap)(getLevelByName(value)); this._Handlers.forEach((handler) => (handler.level = this._Level)); } get handlers() { return this._Handlers; } addHandler(handler) { this._Handlers.push(handler); } removeHandler(handler) { const index = this._Handlers.indexOf(handler); if (index !== -1) this._Handlers.splice(index, 1); } log(level, msg, ...args) { if (this.level < level) { return msg instanceof Function ? undefined : msg; } let fnResult; let message; if (msg instanceof Function) { fnResult = msg(); message = this.asString(fnResult); } else { message = this.asString(msg); } this._Handlers.forEach((handler) => { handler.handle({ date: new Date(), level, levelName: (0, result_1.unwrap)(getLevelName(level)), logger: this.name, message, args, }); }); return msg instanceof Function ? fnResult : msg; } error(msg, ...args) { return this.log(LogVerbosity.ERROR, msg, ...args); } warn(msg, ...args) { return this.log(LogVerbosity.WARN, msg, ...args); } info(msg, ...args) { return this.log(LogVerbosity.INFO, msg, ...args); } debug(msg, ...args) { return this.log(LogVerbosity.DEBUG, msg, ...args); } asString(data, isProperty = false) { if (typeof data === 'string') { if (isProperty) return `"${data}"`; return data; } else if (data === null || typeof data === 'number' || typeof data === 'bigint' || typeof data === 'boolean' || typeof data === 'undefined' || typeof data === 'symbol') { return String(data); } else if (data instanceof Error) { return data.stack; } else if (typeof data === 'object') { return `{${Object.entries(data) .map(([k, v]) => `"${k}":${this.asString(v, true)}`) .join(',')}}`; } return 'undefined'; } } exports.Logger = Logger; const DEFAULT_FORMATTER = ({ message }) => message; exports.DEFAULT_FORMATTER = DEFAULT_FORMATTER; const PRETTY_FORMATTER = (record) => { const date = `[${record.date.toISOString()}]`; const level = `[${record.levelName}]`; const logger = record.logger !== LOG_DEFAULT_ID ? `[${record.logger}] ` : ''; const symbol = exports.LogSymbols[record.level]; return `${date} ${symbol} ${level.padEnd(7, ' ')} ${logger}${record.message}`; }; exports.PRETTY_FORMATTER = PRETTY_FORMATTER; class LogHandler { constructor(level, formatter = exports.DEFAULT_FORMATTER) { if ((0, validation_1.isNumber)(level)) { this._Level = (0, result_1.unwrap)(getLevelByName((0, result_1.unwrap)(getLevelName(level)))); } else { this._Level = (0, result_1.unwrap)(getLevelByName(level)); } this._FormatterFn = formatter; } get level() { return this._Level; } set level(value) { this.levelName = (0, result_1.unwrap)(getLevelName(value)); } get levelName() { return (0, result_1.unwrap)(getLevelName(this._Level)); } set levelName(value) { this._Level = (0, result_1.unwrap)(getLevelByName(value)); } handle(record) { if (this._Level < record.level) return; this.log(this._FormatterFn(record), record); } log(formattedString, record) { exports.LogFunctions[record.level](formattedString, ...record.args); } } exports.LogHandler = LogHandler;