import log4js from "log4js"; import { LogLevel, Sink } from "@logtape/logtape"; //#region src/mod.d.ts /** * Logger interface for log4js-compatible loggers. * @since 2.0.0 */ interface Logger { trace: LogMethod; debug: LogMethod; info: LogMethod; warn: LogMethod; error: LogMethod; fatal: LogMethod; addContext: (key: string, value: unknown) => void; removeContext: (key: string) => void; clearContext: () => void; } /** * Log method signature for log4js. * @since 2.0.0 */ interface LogMethod { (message: string, ...args: unknown[]): void; } /** * log4js log level type. * @since 2.0.0 */ type Log4jsLevel = "trace" | "debug" | "info" | "warn" | "error" | "fatal"; /** * Strategy for handling LogTape properties in log4js. * @since 2.0.0 */ type ContextStrategy = "mdc" | "args"; /** * Strategy for handling existing log4js context. * @since 2.0.0 */ type ContextPreservation = "preserve" | "merge" | "replace"; /** * Base configuration options shared by all context strategies. * @since 2.0.0 */ interface Log4jsSinkOptionsBase { /** * Mapping between LogTape log levels and log4js log levels. * * By default, LogTape levels are mapped as follows: * * - `trace` → `trace` * - `debug` → `debug` * - `info` → `info` * - `warning` → `warn` * - `error` → `error` * - `fatal` → `fatal` */ readonly levelsMap?: Readonly>; /** * Custom mapper function to convert LogTape categories to log4js category strings. * * By default, LogTape categories are joined with dots (e.g., `["app", "db"]` becomes `"app.db"`). * * @param category The LogTape category array * @returns The log4js category string * @default (category) => category.join(".") * * @example * ```typescript * // Use :: as separator * categoryMapper: (cat) => cat.join("::") * ``` * * @example * ```typescript * // Custom logic for category mapping * categoryMapper: (cat) => { * if (cat.length === 0) return "default"; * return cat.join("."); * } * ``` */ readonly categoryMapper?: (category: readonly string[]) => string; /** * Custom formatter for interpolated values in log messages. * * This function is used to convert values that are interpolated into * log messages (e.g., the `name` in * `logger.info("Hello, {name}!", { name: "world" })`). * * @param value The value to format * @returns A string representation of the value * @default `inspect` (from `node:util` module) */ readonly valueFormatter?: (value: unknown) => string; } /** * Configuration options for log4js sink with MDC (Mapped Diagnostic Context) strategy. * @since 2.0.0 */ interface Log4jsSinkOptionsMdc extends Log4jsSinkOptionsBase { /** * Strategy for handling LogTape properties. * * Use `"mdc"` to leverage log4js's built-in MDC (Mapped Diagnostic Context) feature. * * @default "mdc" */ readonly contextStrategy?: "mdc"; /** * Strategy for handling existing log4js context when using MDC strategy. * * - `"preserve"` (default): Preserve existing context by saving and restoring it * - `"merge"`: Merge LogTape properties with existing context (existing values take precedence) * - `"replace"`: Replace existing context with LogTape properties * * @default "preserve" * * @example * ```typescript * // Preserve existing context (default) * const sink = getLog4jsSink(undefined, undefined, { * contextStrategy: "mdc", * contextPreservation: "preserve" * }); * ``` * * @example * ```typescript * // Merge with existing context * const sink = getLog4jsSink(undefined, undefined, { * contextStrategy: "mdc", * contextPreservation: "merge" * }); * ``` */ readonly contextPreservation?: ContextPreservation; } /** * Configuration options for log4js sink with args strategy. * @since 2.0.0 */ interface Log4jsSinkOptionsArgs extends Log4jsSinkOptionsBase { /** * Strategy for handling LogTape properties. * * Use `"args"` to pass properties as additional arguments to log methods. */ readonly contextStrategy: "args"; } /** * Configuration options for the log4js sink. * * This is a discriminated union type based on the `contextStrategy` option. * When `contextStrategy` is `"mdc"` (or omitted), the `contextPreservation` option * is available. When `contextStrategy` is `"args"`, the `contextPreservation` option * is not allowed. * * @example Basic usage with default options (MDC strategy) * ```typescript * const sink = getLog4jsSink(); * ``` * * @example Custom level mapping * ```typescript * const sink = getLog4jsSink(undefined, undefined, { * levelsMap: { * "trace": "debug", * "debug": "debug", * "info": "info", * "warning": "warn", * "error": "error", * "fatal": "fatal" * } * }); * ``` * * @example Custom category mapping * ```typescript * const sink = getLog4jsSink(undefined, undefined, { * categoryMapper: (category) => category.join("::") * }); * ``` * * @example Using MDC strategy with preserve (default) * ```typescript * const sink = getLog4jsSink(undefined, undefined, { * contextStrategy: "mdc", * contextPreservation: "preserve" * }); * ``` * * @example Using args strategy * ```typescript * const sink = getLog4jsSink(undefined, undefined, { * contextStrategy: "args" * // contextPreservation is not allowed here * }); * ``` * * @since 2.0.0 */ type Log4jsSinkOptions = Log4jsSinkOptionsMdc | Log4jsSinkOptionsArgs; /** * Creates a LogTape sink that forwards log records to a log4js logger. * * This function creates a sink function that can be used with LogTape's * configuration system. The sink will format LogTape log records and * forward them to the provided log4js logger instance or create one * based on the LogTape category. * * @example Basic usage with default log4js logger * ```typescript * import log4js from "log4js"; * import { configure } from "@logtape/logtape"; * import { getLog4jsSink } from "@logtape/adaptor-log4js"; * * log4js.configure({ * appenders: { out: { type: "stdout" } }, * categories: { default: { appenders: ["out"], level: "info" } } * }); * * await configure({ * sinks: { * log4js: getLog4jsSink() * }, * loggers: [ * { category: ["myapp"], sinks: ["log4js"] } * ] * }); * ``` * * @example With custom log4js logger * ```typescript * import log4js from "log4js"; * import { getLog4jsSink } from "@logtape/adaptor-log4js"; * * const logger = log4js.getLogger("custom"); * const sink = getLog4jsSink(logger); * ``` * * @example With custom options * ```typescript * const sink = getLog4jsSink(undefined, { * categoryMapper: (cat) => cat.join("::"), * contextStrategy: "args", * levelsMap: { * "trace": "debug", * "debug": "debug", * "info": "info", * "warning": "warn", * "error": "error", * "fatal": "fatal" * } * }); * ``` * * @param log4jsModule The log4js module instance. If not provided, log4js will be imported dynamically. * @param logger The log4js logger instance to forward logs to. If not provided, * a logger will be created for each LogTape category using log4js.getLogger(). * @param options Configuration options for the sink behavior. * @returns A sink function that can be used with LogTape's configure() function. * @since 2.0.0 */ declare function getLog4jsSink(log4jsModule?: typeof log4js, logger?: Logger, options?: Log4jsSinkOptions): Sink; /** * Automatically configures LogTape to route all logs to log4js. * * This is a convenience function that automatically sets up LogTape to forward * all log records to log4js. By default, it creates loggers based on LogTape * categories using log4js.getLogger(), but you can provide a custom logger * as the second parameter. * * @param log4jsModule The log4js module instance. If not provided, log4js will be imported dynamically. * @param logger Optional log4js logger instance to use for all logs. * @param options Configuration options for the log4js sink behavior. * * @example Basic auto-configuration * ```typescript * import log4js from "log4js"; * import { install } from "@logtape/adaptor-log4js"; * * log4js.configure({ * appenders: { out: { type: "stdout" } }, * categories: { default: { appenders: ["out"], level: "info" } } * }); * * // Automatically route all LogTape logs to log4js * install(log4js); * * // Now any LogTape-enabled library will log through log4js * import { getLogger } from "@logtape/logtape"; * const logger = getLogger("my-app"); * logger.info("This will be logged through log4js"); * ``` * * @example Auto-configuration with custom logger * ```typescript * import log4js from "log4js"; * import { install } from "@logtape/adaptor-log4js"; * * const customLogger = log4js.getLogger("myapp"); * * // Install with custom logger * install(log4js, customLogger); * ``` * * @example Auto-configuration with custom options * ```typescript * import log4js from "log4js"; * import { install } from "@logtape/adaptor-log4js"; * * install(log4js, undefined, { * categoryMapper: (cat) => cat.join("::"), * contextStrategy: "args" * }); * ``` * * @since 2.0.0 */ declare function install(log4jsModule: typeof log4js, logger?: Logger, options?: Log4jsSinkOptions): void; //#endregion export { ContextPreservation, ContextStrategy, Log4jsLevel, Log4jsSinkOptions, Log4jsSinkOptionsArgs, Log4jsSinkOptionsBase, Log4jsSinkOptionsMdc, LogMethod, Logger, getLog4jsSink, install };