import type { LingInstance, LingString } from '@/ling/lib'; import type { LogrOptions, LogEntry, MessageCategory, LogFilters, Logr, Transport } from './types.ts'; import { LogLevel } from './types.ts'; import { consoleTransport } from './transports.ts'; // ============================================================================ // ENGINE // ============================================================================ /** * Crea una instancia de `Logr` vinculada a una instancia de i18n. * * El logger no gestiona el locale internamente — lo delega al sistema i18n. * Cuando cambia el locale en i18n, los mensajes siguientes se resuelven * automáticamente al nuevo locale sin ninguna reconfiguración. * * Cada entrada se emite a todos los transports registrados. * Si no se especifican transports, usa `consoleTransport()` por defecto. * * @param ling - Instancia de i18n para resolución de mensajes localizados * @param options - Configuración de nivel, historial y transports * * @example * export const logr = createLogr(i18n, { * level : LogLevel.WARN, * transports: [ * consoleTransport(), * httpTransport({ url: 'https://logs.myapp.com', level: LogLevel.ERROR }), * ] * }); */ export function createLogr(ling: LingInstance, options: LogrOptions = {}): Logr { let level : LogLevel = options.level ?? LogLevel.WARN; let maxLogs : number = options.maxLogs ?? 1000; let transports : Transport[] = options.transports ?? [consoleTransport()]; let entries : LogEntry[] = []; // ------------------------------------------------------------------------- // Configuración // ------------------------------------------------------------------------- function setLevel(l: LogLevel): void { level = l; } function setMaxLogs(max: number): void { maxLogs = max; } // ------------------------------------------------------------------------- // Core interno // ------------------------------------------------------------------------- /** * Centraliza el procesamiento de todos los niveles. * Aplica el filtro de nivel, construye la entrada, gestiona el historial * y emite a todos los transports. */ function log( lvl : LogLevel, category: MessageCategory, message : LingString, context?: Record ): void { if (lvl < level) return; const entry: LogEntry = { timestamp: new Date(), level : lvl, category, message, context, }; // Historial en memoria entries.push(entry); if (entries.length > maxLogs) entries.shift(); // Resuelve el mensaje una sola vez y lo emite a todos los transports const resolvedMessage = ling.ts(entry.message); transports.forEach(t => t.write(entry, resolvedMessage)); } // ------------------------------------------------------------------------- // API pública // ------------------------------------------------------------------------- function debug(category: MessageCategory, message: LingString, context?: Record): void { log(LogLevel.DEBUG, category, message, context); } function info(category: MessageCategory, message: LingString, context?: Record): void { log(LogLevel.INFO, category, message, context); } function warn(category: MessageCategory, message: LingString, context?: Record): void { log(LogLevel.WARN, category, message, context); } function error(category: MessageCategory, message: LingString, context?: Record): void { log(LogLevel.ERROR, category, message, context); } function getLogs(filters?: LogFilters): LogEntry[] { let result = entries; if (filters?.level !== undefined) result = result.filter(e => e.level === filters.level); if (filters?.category !== undefined) result = result.filter(e => e.category === filters.category); if (filters?.since !== undefined) result = result.filter(e => e.timestamp >= filters.since!); return result; } function clear(): void { entries = []; } /** * Los mensajes se resuelven al locale activo en el momento * de llamar a serialization(), no al momento en que se registraron. */ function serialize(): string { return JSON.stringify( entries.map(e => ({ ...e, message : ling.ts(e.message), locale : ling.getLocale(), timestamp: e.timestamp.toISOString(), })), null, 2 ); } return { debug, info, warn, error, getLogs, clear, serialize, setLevel, setMaxLogs }; }