UNPKG

chia-agent

Version:
346 lines (345 loc) 11.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Logger = exports.jsonLogFormatter = exports.simpleLogFormatter = exports.defaultLogFormatter = exports.DEFAULT_LOGGER_NAME = void 0; exports.isValidLogLevel = isValidLogLevel; exports.normalizeLogLevel = normalizeLogLevel; exports.setDefaultLogLevel = setDefaultLogLevel; exports.getDefaultLogLevel = getDefaultLogLevel; exports.setDefaultWriter = setDefaultWriter; exports.setDefaultFormatter = setDefaultFormatter; exports.getDefaultFormatter = getDefaultFormatter; exports.getLogger = getLogger; exports.clearLoggerCache = clearLoggerCache; exports.createConsoleWriter = createConsoleWriter; exports.createNullWriter = createNullWriter; exports.stringify = stringify; exports.getLogLevel = getLogLevel; exports.setLogLevel = setLogLevel; const LOG_LEVELS = [ "error", "warning", "info", "debug", "trace", "none", ]; function isValidLogLevel(level) { return LOG_LEVELS.includes(level.toLowerCase()); } function normalizeLogLevel(level) { const normalized = level.toLowerCase(); if (isValidLogLevel(normalized)) { return normalized; } return null; } const logPriority = { none: 9999, error: 5, warning: 4, info: 3, debug: 2, trace: 1, }; class ConsoleWriter { write(message, level) { switch (level) { case "error": console.error(message); break; case "warning": console.warn(message); break; case "info": console.info(message); break; case "debug": console.debug(message); break; case "trace": console.trace(message); break; default: console.log(message); } } } class NullWriter { write(_message, _level) { // Suppress all output } } // Global defaults let defaultLogLevel = "error"; if (process.env.LOG_LEVEL) { const normalizedLevel = normalizeLogLevel(process.env.LOG_LEVEL); if (normalizedLevel) { defaultLogLevel = normalizedLevel; } else { console.warn(`Invalid LOG_LEVEL environment variable: ${process.env.LOG_LEVEL}. Using default: error`); } } let defaultWriter = process.env.LOG_SUPPRESS === "true" ? new NullWriter() : new ConsoleWriter(); // Logger instance cache const loggerCache = new Map(); // Configuration functions for global defaults function setDefaultLogLevel(level) { // Normalize for JavaScript users who might pass uppercase const normalized = normalizeLogLevel(level); if (!normalized) { throw new Error(`Invalid log level: ${level}. Valid levels are: ${LOG_LEVELS.join(", ")}`); } defaultLogLevel = normalized; } function getDefaultLogLevel() { return defaultLogLevel; } function setDefaultWriter(writer) { defaultWriter = writer; } function setDefaultFormatter(formatter) { defaultFormatter = formatter; } function getDefaultFormatter() { return defaultFormatter; } exports.DEFAULT_LOGGER_NAME = "default"; // Default formatter const defaultLogFormatter = (context) => { const timestamp = context.timestamp.toISOString(); const levelStr = context.level.toUpperCase(); const nameStr = context.loggerName === exports.DEFAULT_LOGGER_NAME ? "" : ` [${context.loggerName}]`; return `${timestamp} [${levelStr}]${nameStr} - ${context.message}`; }; exports.defaultLogFormatter = defaultLogFormatter; // Simple formatter without timestamp const simpleLogFormatter = (context) => { const levelStr = context.level.toUpperCase(); const nameStr = context.loggerName === exports.DEFAULT_LOGGER_NAME ? "" : `[${context.loggerName}] `; return `[${levelStr}] ${nameStr}${context.message}`; }; exports.simpleLogFormatter = simpleLogFormatter; // JSON formatter const jsonLogFormatter = (context) => { return JSON.stringify({ timestamp: context.timestamp.toISOString(), level: context.level, logger: context.loggerName, message: context.message, }); }; exports.jsonLogFormatter = jsonLogFormatter; let defaultFormatter = exports.defaultLogFormatter; // Factory function with caching function getLogger(name = exports.DEFAULT_LOGGER_NAME) { let logger = loggerCache.get(name); if (!logger) { logger = new Logger(name, defaultLogLevel, defaultWriter, defaultFormatter); loggerCache.set(name, logger); } return logger; } // Clear logger cache (useful for testing) function clearLoggerCache() { loggerCache.clear(); } // Helper to create writers function createConsoleWriter() { return new ConsoleWriter(); } function createNullWriter() { return new NullWriter(); } function stringify(obj, indent) { if (typeof obj === "string") { return obj; } else if (typeof obj === "number") { return `${obj}`; } else if (typeof obj === "boolean") { return `${obj}`; } else if (typeof obj === "bigint") { return `${obj}n`; } else if (typeof obj === "symbol") { return obj.toString(); } else if (typeof obj === "undefined") { return "undefined"; } else if (typeof obj === "function") { return "[Function]"; } else if (obj === null) { return "null"; } try { // Deep clone the object while removing circular references const seen = new WeakSet(); const deepCloneWithoutCircular = (value, path = []) => { // Handle primitives and null if (value === null || typeof value !== "object") { if (typeof value === "bigint") { return `${value}n`; } else if (typeof value === "function") { return "[Function]"; } else if (typeof value === "symbol") { return value.toString(); } return value; } // Check for circular reference if (seen.has(value)) { return undefined; // This will cause the property to be omitted } seen.add(value); try { // Handle arrays if (Array.isArray(value)) { const clonedArray = []; for (let i = 0; i < value.length; i++) { const clonedValue = deepCloneWithoutCircular(value[i], [ ...path, String(i), ]); if (clonedValue !== undefined) { clonedArray.push(clonedValue); } } return clonedArray; } // Handle objects const cloned = {}; for (const key in value) { if (Object.prototype.hasOwnProperty.call(value, key)) { const clonedValue = deepCloneWithoutCircular(value[key], [ ...path, key, ]); if (clonedValue !== undefined) { cloned[key] = clonedValue; } } } return cloned; } finally { // Remove from seen set when we're done processing this level seen.delete(value); } }; const clonedObj = deepCloneWithoutCircular(obj); return JSON.stringify(clonedObj, null, indent); } catch (error) { const msg = error && typeof error === "object" && "message" in error ? error.message : "Unknown error"; return `[Error stringifying object: ${msg}]`; } } class Logger { constructor(name, logLevel, writer, formatter) { // Normalize for JavaScript users who might pass uppercase const normalized = normalizeLogLevel(logLevel); if (!normalized) { throw new Error(`Invalid log level: ${logLevel}. Valid levels are: ${LOG_LEVELS.join(", ")}`); } this._name = name; this._logLevel = normalized; this._writer = writer; this._formatter = formatter || defaultFormatter; } // Allow changing log level for this specific logger setLogLevel(level) { // Normalize for JavaScript users who might pass uppercase const normalized = normalizeLogLevel(level); if (!normalized) { throw new Error(`Invalid log level: ${level}. Valid levels are: ${LOG_LEVELS.join(", ")}`); } this._logLevel = normalized; } getLogLevel() { return this._logLevel; } // Allow changing writer for this specific logger setWriter(writer) { this._writer = writer; } getWriter() { return this._writer; } getName() { return this._name; } setFormatter(formatter) { this._formatter = formatter; } getFormatter() { return this._formatter; } _shouldWrite(logLevel) { return logPriority[this._logLevel] <= logPriority[logLevel]; } _formatMessage(level, body) { const context = { timestamp: new Date(), level, loggerName: this._name, message: body, }; return this._formatter(context); } trace(msg) { if (this._shouldWrite("trace")) { const message = typeof msg === "function" ? msg() : msg; this._writer.write(this._formatMessage("trace", stringify(message)), "trace"); } } debug(msg) { if (this._shouldWrite("debug")) { const message = typeof msg === "function" ? msg() : msg; this._writer.write(this._formatMessage("debug", stringify(message)), "debug"); } } info(msg) { if (this._shouldWrite("info")) { const message = typeof msg === "function" ? msg() : msg; this._writer.write(this._formatMessage("info", stringify(message)), "info"); } } warning(msg) { if (this._shouldWrite("warning")) { const message = typeof msg === "function" ? msg() : msg; this._writer.write(this._formatMessage("warning", stringify(message)), "warning"); } } error(msg) { if (this._shouldWrite("error")) { const message = typeof msg === "function" ? msg() : msg; this._writer.write(this._formatMessage("error", stringify(message)), "error"); } } } exports.Logger = Logger; // For backward compatibility function getLogLevel() { return getDefaultLogLevel(); } function setLogLevel(level) { // Normalize for JavaScript users who might pass uppercase const normalized = normalizeLogLevel(level); if (!normalized) { throw new Error(`Invalid log level: ${level}. Valid levels are: ${LOG_LEVELS.join(", ")}`); } setDefaultLogLevel(normalized); }