import { createLogger, format, transports } from 'winston' import Transport from 'winston-transport' import type { SqliteCache } from './adapters/cache/sqlite.js' /** * Custom winston transport that writes log entries to a SqliteCache instance. */ export class SqliteTransport extends Transport { private cache: SqliteCache constructor(cache: SqliteCache, opts?: Transport.TransportStreamOptions) { super(opts) this.cache = cache } log(info: { level: string; message: string }, callback: () => void): void { setImmediate(() => this.emit('logged', info)) this.cache.writeLog(info.level, info.message) callback() } } /** * Global logger instance. Starts with console transport only. * The SQLite transport is added later once a SqliteCache is available. */ export const logger = createLogger({ level: 'info', format: format.combine( format.timestamp(), format.printf(({ timestamp, level, message }) => { return `${timestamp as string} [${level}] ${message as string}` }), ), transports: [ new transports.Console(), ], }) /** * Attaches the SQLite transport to the global logger. * Called once during startup after the SqliteCache is created. */ export function attachSqliteTransport(cache: SqliteCache): void { logger.add(new SqliteTransport(cache)) } /** * Removes the console transport from the logger. * Called when the process is running as a background service. */ export function removeConsoleTransport(): void { logger.transports .filter(t => t instanceof transports.Console) .forEach(t => logger.remove(t)) }