UNPKG

@naturalcycles/js-lib

Version:

Standard library for universal (browser + Node.js) javascript

139 lines (125 loc) 4.03 kB
import type { MutateOptions } from '../types.js' // copy-pasted to avoid weird circular dependency const _noop = (..._args: any[]): undefined => undefined /** * These levels follow console.* naming, * so you can use console[level] safely. * * `debug` is not enabled by default, and is useful when debugging is needed. * * `log` is considered default level, and is enabled by default. * * `warn` is for warnings - things that are not super-severe to be an error, but should not happen * * `error` level would only log errors * * @experimental */ export type CommonLogLevel = 'debug' | 'log' | 'warn' | 'error' export const commonLogLevelNumber: Record<CommonLogLevel, number> = { debug: 10, log: 20, warn: 20, error: 30, } /** * Function that takes any number of arguments and logs them all. * It is expected that logged arguments are separated by "space", like console.log does. * * @experimental */ export type CommonLogFunction = (...args: any[]) => void export type CommonLogWithLevelFunction = (level: CommonLogLevel, args: any[]) => void /** * Interface is inspired/compatible with `console.*` * So, `console` is a valid CommonLogger implementation as-is. * * @experimental */ export interface CommonLogger { debug: CommonLogFunction log: CommonLogFunction warn: CommonLogFunction error: CommonLogFunction } /** * SimpleLogger that does nothing (noop). */ export const commonLoggerNoop: CommonLogger = { debug: _noop, log: _noop, warn: _noop, error: _noop, } /** * Creates a "child" logger that is "limited" to the specified CommonLogLevel. */ export function createCommonLoggerAtLevel( logger: CommonLogger = console, minLevel: CommonLogLevel = 'log', opt: MutateOptions = {}, ): CommonLogger { const level = commonLogLevelNumber[minLevel] if (opt.mutate) { if (level > commonLogLevelNumber['debug']) { logger.debug = _noop if (level > commonLogLevelNumber['log']) { logger.log = _noop if (level > commonLogLevelNumber['warn']) { logger.warn = _noop if (level > commonLogLevelNumber['error']) { logger.error = _noop } } } } return logger } if (level <= commonLogLevelNumber['debug']) { // All levels are kept return logger } if (level > commonLogLevelNumber['error']) { // "Log nothing" logger return commonLoggerNoop } return { debug: _noop, // otherwise it is "log everything" logger (same logger as input) log: level <= commonLogLevelNumber['log'] ? logger.log.bind(logger) : _noop, warn: level <= commonLogLevelNumber['warn'] ? logger.warn.bind(logger) : _noop, error: logger.error.bind(logger), // otherwise it's "log nothing" logger (same as noopLogger) } } /** * Creates a "proxy" CommonLogger that pipes log messages to all provided sub-loggers. */ export function commonLoggerPipe(loggers: CommonLogger[]): CommonLogger { return { debug: (...args) => loggers.forEach(logger => logger.debug(...args)), log: (...args) => loggers.forEach(logger => logger.log(...args)), warn: (...args) => loggers.forEach(logger => logger.warn(...args)), error: (...args) => loggers.forEach(logger => logger.error(...args)), } } /** * Creates a "child" CommonLogger with prefix (one or multiple). */ export function commonLoggerPrefix(logger: CommonLogger, ...prefixes: any[]): CommonLogger { return { debug: (...args) => logger.debug(...prefixes, ...args), log: (...args) => logger.log(...prefixes, ...args), warn: (...args) => logger.warn(...prefixes, ...args), error: (...args) => logger.error(...prefixes, ...args), } } /** * Creates a CommonLogger from a single function that takes `level` and `args`. */ export function commonLoggerCreate(fn: CommonLogWithLevelFunction): CommonLogger { return { debug: (...args) => fn('debug', args), log: (...args) => fn('log', args), warn: (...args) => fn('warn', args), error: (...args) => fn('error', args), } }