UNPKG

@nowarajs/logger

Version:

Type-safe logging library for Bun with advanced TypeScript body intersection, modular sink pattern, transform streams, and immutable API design.

190 lines (189 loc) 7.04 kB
import { TypedEventEmitter } from '@nowarajs/typed-event-emitter'; import type { LoggerEvent } from './events/logger-events'; import type { BodiesIntersection } from './types/bodies-intersection'; import type { LoggerSink } from './types/logger-sink'; import type { SinkMap } from './types/sink-map'; /** * Logger provides a flexible, type-safe logging system that allows multiple sinks for log output. * The logger uses a transform stream to process log entries and execute the logging sinks. * * Logger extends the TypedEventEmitter class to emit typed events when an error occurs or when the logger ends. * The logger can log messages with different levels: error, warn, info, debug, and log. * * @template TSinks - The map of sink names to LoggerStrategy types. */ export declare class Logger<TSinks extends SinkMap = {}> extends TypedEventEmitter<LoggerEvent> { /** * The map of sinks. */ private readonly _sinks; /** * The transform stream for processing log entries. */ private readonly _logStream; /** * The queue of pending log entries. */ private readonly _pendingLogs; /** * The maximum number of pending logs. * @defaultValue 10_000 */ private readonly _maxPendingLogs; /** * Flag to indicate if the logger is currently writing logs. */ private _isWriting; /** * Construct a Logger. * * @template TStrategies - The map of sink names to LoggerStrategy types. * * @param sinks - Initial sinks map. * * @param maxPendingLogs - Maximum number of logs in the queue (default: 10_000) */ constructor(sinks?: TSinks, maxPendingLogs?: number); /** * Register a new logging sink. * * @template Key - The name of the sink. * @template Sink - The sink type. * * @param name - The name of the sink. * @param sink - The sink to add. It must implement {@link LoggerSink}. * * @throws ({@link BaseError}) - If the sink is already added. * * @returns A new Logger instance with the added sink. */ registerSink<Key extends string, Sink extends LoggerSink>(name: Key, sink: Sink): Logger<TSinks & Record<Key, Sink>>; /** * Unregister a logging sink. * * @template Key - The name of the sink. * * @param name - The name of the sink to remove. * * @throws ({@link BaseError}) - If the sink is not found. * * @returns A new Logger instance without the removed sink. */ unregisterSink<Key extends keyof TSinks>(name: Key): Logger<Omit<TSinks, Key>>; /** * Register multiple sinks at once. * * @template TNew - The new sinks to add. * * @param sinks - An array of tuples where each tuple contains the sink name and the sink instance. * * @throws ({@link BaseError}) - If any sink is already added. * * @returns A new Logger instance with the added sinks. */ registerSinks<TNew extends [string, LoggerSink][] = [string, LoggerSink][]>(sinks: TNew): Logger<TSinks & { [K in TNew[number][0]]: Extract<TNew[number], [K, LoggerSink]>[1]; }>; /** * Unregister multiple sinks at once. * * @template Keys - The names of the sinks to remove. * * @param names - An array of sink names to remove. * * @throws ({@link BaseError}) - If any sink is not found. * * @returns A new Logger instance without the removed sinks. */ unregisterSinks<Keys extends Extract<keyof TSinks, string>>(names: Keys[]): Logger<Omit<TSinks, Keys>>; /** * Remove all sinks. * * @returns A new Logger instance without any sinks. */ clearSinks(): Logger; /** * Log an error message. * * @template SNames - The names of the sinks to use. * * @param object - The object to log. * @param sinksNames - The names of the sinks to use. If not provided, all sinks will be used. * * @throws ({@link BaseError}) - If no sink is added. */ error<SNames extends (keyof TSinks)[] = (keyof TSinks)[]>(object: BodiesIntersection<TSinks, SNames[number]>, sinksNames?: SNames): void; /** * Log a warning message. * * @template SNames - The names of the sinks to use. * * @param object - The object to log. * @param sinksNames - The names of the sinks to use. If not provided, all sinks will be used. * * @throws ({@link BaseError}) - If no sink is added. */ warn<SNames extends (keyof TSinks)[] = (keyof TSinks)[]>(object: BodiesIntersection<TSinks, SNames[number]>, sinksNames?: SNames): void; /** * Log an info message. * * @template SNames - The names of the sinks to use. * * @param object - The object to log. * @param sinksNames - The names of the sinks to use. If not provided, all sinks will be used. * * @throws ({@link BaseError}) - If no sink is added. */ info<SNames extends (keyof TSinks)[] = (keyof TSinks)[]>(object: BodiesIntersection<TSinks, SNames[number]>, sinksNames?: SNames): void; /** * Log a debug message. * * @template SNames - The names of the sinks to use. * * @param object - The object to log. * @param sinksNames - The names of the sinks to use. If not provided, all sinks will be used. * * @throws ({@link BaseError}) - If no sink is added. */ debug<SNames extends (keyof TSinks)[] = (keyof TSinks)[]>(object: BodiesIntersection<TSinks, SNames[number]>, sinksNames?: SNames): void; /** * Log a generic message. * * @template SNames - The names of the sinks to use. * * @param object - The object to log. * @param sinksNames - The names of the sinks to use. If not provided, all sinks will be used. * * @throws ({@link BaseError}) - If no sink is added. */ log<SNames extends (keyof TSinks)[] = (keyof TSinks)[]>(object: BodiesIntersection<TSinks, SNames[number]>, sinksNames?: SNames): void; /** * Internal: execute all sinks for a log event. * * @template TLogObject - The type of the log object. * * @param level - The log level. * @param date - The date of the log event. * @param object - The object to log. * @param sinksNames - The names of the sinks to use. If not provided, all sinks will be used. * * @throws ({@link BaseError}) - If a sink throws. */ private _executeStrategies; /** * Internal: queue a log event and start writing if not already. * * @template TLogObject - The type of the log object. * * @param level - The log level. * @param object - The object to log. * @param sinksNames - The names of the sinks to use. If not provided, all sinks will be used. * * @throws ({@link BaseError}) - If no sink is added. */ private _out; /** * Internal: process the log queue and emit 'end' when done. */ private _writeLog; }