From 0eb6fa1fb0917cb556d88575c90977ee0010e5f0 Mon Sep 17 00:00:00 2001 From: Benjamin Wegener Date: Sun, 19 Nov 2023 17:09:50 +0000 Subject: [PATCH] feat(logger) helper class added --- lib/core/Logger.js | 134 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 lib/core/Logger.js diff --git a/lib/core/Logger.js b/lib/core/Logger.js new file mode 100644 index 0000000..17217fd --- /dev/null +++ b/lib/core/Logger.js @@ -0,0 +1,134 @@ +class Logger { + static #enabled = true; + static #lastMessage = ''; + static #spamIndex = 0; + static #defaultOptions = new Map([ + ['spamThreshold', 5], + ['namespace', ''], + ['receiver', 'console'], // can be 'console' or object/function + ]); + + /** + * Enables the logger. + */ + static enable() { + Logger.toggle(true); + } + + /** + * Disables the logger. + */ + static disable() { + Logger.toggle(false); + } + + static toggle(value = !Logger.#enabled) { + if (typeof value !== 'boolean') + throw new TypeError('value must be a boolean'); + Logger.#enabled = value; + } + + /** + * Sets the default options for the Logger. + * @param {Map} options - The options to set. + * @throws {TypeError} If options is not an instance of Map. + */ + static setDefaultOptions(options) { + if (!(options instanceof Map)) + throw new TypeError('options must be a Map'); + + for (const [key, value] of Logger.#defaultOptions.entries()) { + if ( + key === 'receiver' && + !!options.get(key) && + value != options.get(key) && + !['function', 'object'].includes(typeof options.get(key)) + ) { + throw new TypeError( + 'receiver must be one of: `console`, `function`, `object`' + ); + } + Logger.#defaultOptions.set(key, options.get(key) ?? value); + } + } + + /** + * Logs a message with the specified level and options. + * + * @param {string} message - The message to be logged. + * @param {string} level - The log level (e.g., 'info', 'warn', 'error'). + * @param {object} [options] - The optional log options. + * @param {number} [options.spamThreshold] - The spam threshold for duplicate messages. + * @param {string} [options.namespace] - The namespace for the log message. + */ + static log(message, level, options = Logger.#defaultOptions) { + if (!Logger.#enabled) return; + + const { + spamThreshold = Logger.#defaultOptions.spamThreshold, + namespace, + } = options; + + if (Logger.#lastMessage === message) { + if (spamThreshold <= Logger.#spamIndex) return; + Logger.#spamIndex++; + } + + if (typeof console[level] === 'function') { + console[level]( + `[${ + namespace ? namespace + ' - ' : '' + }${level.toUpperCase()}] ${message}` + ); + } else { + console.log( + `[${namespace ? namespace + ' - ' : ''}LOG] ${message}` + ); + } + + if (Logger.#lastMessage !== message) _spamIndex = 0; + Logger.#lastMessage = message; + } + + /** + * Logs an error message. + * + * @param {string} message - The error message to log. + * @param {object} options - The options for logging. Default is Logger.#defaultOptions. + */ + static error(message, options = Logger.#defaultOptions) { + Logger.log(message, 'error', options); + } + + /** + * Logs an informational message. + * + * @param {string} message - The message to be logged. + * @param {object} options - The options for logging. (optional) + */ + static info(message, options = Logger.#defaultOptions) { + Logger.log(message, 'info', options); + } + + /** + * Logs a warning message. + * + * @param {string} message - The warning message to be logged. + * @param {object} options - The options for logging. Default is Logger.#defaultOptions. + */ + static warn(message, options = Logger.#defaultOptions) { + Logger.log(message, 'warn', options); + } + + /** + * Logs a warning message. + * + * @param {string} message - The warning message to be logged. + * @param {object} [options=Logger.#defaultOptions] - The options for the warning log. + */ + static warning(message, options = Logger.#defaultOptions) { + Logger.warn(message, options); + } +} + +export default Logger;