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 {array} data - 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(data, level, options = Logger.#defaultOptions) { if (!Logger.#enabled) return; const { spamThreshold = Logger.#defaultOptions.spamThreshold, namespace, } = options; if (Logger.#lastMessage === data) { if (spamThreshold <= Logger.#spamIndex) return; Logger.#spamIndex++; } if (typeof console[level] === 'function') { console[level]( `[${namespace ? namespace + ' - ' : ''}${level.toUpperCase()}]`, ...data ); } else { console.log(`[${namespace ? namespace + ' - ' : ''}LOG]`, ...data); } if (Logger.#lastMessage !== data) this.#spamIndex = 0; Logger.#lastMessage = data; } /** * Logs an error. * * @param {string} data - The error data to log. */ static error() { Logger.#log([...arguments], 'error'); } /** * Logs an information. * * @param {string} data - The data to be logged. */ static info() { Logger.#log([...arguments], 'info'); } /** * Logs a warning. * * @param {string} data - The warning data to be logged. */ static warn() { Logger.#log([...arguments], 'warn'); } /** * wrapper for logging warnings. */ static warning() { Logger.#log([...arguments], 'warn'); } } export default Logger;