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;