UNPKG

cmte

Version:

Design by Committee™ except it's just you and LLMs

87 lines (72 loc) 2.75 kB
import winston from 'winston'; import path from 'path'; import fs from 'fs'; // Ensure logs directory exists const logsDir = path.join(process.cwd(), 'logs'); if (!fs.existsSync(logsDir)) { fs.mkdirSync(logsDir); } // Default console format const consoleFormat = winston.format.combine( winston.format.colorize(), winston.format.printf(({ level, message }) => `${level}: ${message}`) ); // Default file format const fileFormat = winston.format.combine( winston.format.timestamp(), winston.format.json() ); // Create a basic logger instance initially (might be used before configure is called) // It will only log to console by default until configured. const logger = winston.createLogger({ level: 'info', // Default level before configuration format: winston.format.json(), // Default format transports: [ new winston.transports.Console({ format: consoleFormat, level: 'info' // Default console level }) ], exitOnError: false }); // --- Configuration Function --- let isConfigured = false; function configureLogger(options = {}) { // Prevent multiple configurations in the same process if (isConfigured) { logger.debug('Logger already configured. Skipping reconfiguration.'); return; } const { debug = false, dryrun = false } = options; // Determine levels based on debug flag AND dryrun const consoleLevel = debug ? 'debug' : (dryrun ? 'warn' : 'info'); // Console: warn for dryrun, info otherwise, debug overrides const fileLevel = debug ? 'debug' : 'warn'; // File: Still warn/error by default, debug if requested // Generate timestamped filename (only once per process) const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const logFilename = path.join(logsDir, `cmte-${timestamp}.log`); // Clear existing transports before adding configured ones logger.clear(); // Add Console Transport logger.add(new winston.transports.Console({ format: consoleFormat, level: consoleLevel })); // Add File Transport logger.add(new winston.transports.File({ filename: logFilename, format: fileFormat, level: fileLevel // Set level based on debug flag })); // Update the logger's overall level (only needs to be debug if debug is enabled) if (debug) { logger.level = 'debug'; // logger.info('Console logging enabled (Level: debug)'); // Already logged when transport added } else { // Ensure level is at least info for console or warn for file if not debugging logger.level = dryrun ? 'warn' : 'info'; } isConfigured = true; logger.debug('Logger configured', { consoleLevel, fileLevel, logFilename }); } // Export the configure function and the logger instance export { logger, configureLogger };