99 lines
3.3 KiB
TypeScript
99 lines
3.3 KiB
TypeScript
import { Logger } from '../../interfaces/Logger';
|
||
|
||
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
||
|
||
export class ConsoleLogger implements Logger {
|
||
private readonly COLORS: Record<LogLevel, string> = {
|
||
debug: '#888888',
|
||
info: '#00aaff',
|
||
warn: '#ffaa00',
|
||
error: '#ff4444',
|
||
};
|
||
|
||
private readonly EMOJIS: Record<LogLevel, string> = {
|
||
debug: '🐛',
|
||
info: 'ℹ️',
|
||
warn: '⚠️',
|
||
error: '❌',
|
||
};
|
||
|
||
private readonly PREFIXES: Record<LogLevel, string> = {
|
||
debug: 'DEBUG',
|
||
info: 'INFO',
|
||
warn: 'WARN',
|
||
error: 'ERROR',
|
||
};
|
||
|
||
private shouldLog(level: LogLevel): boolean {
|
||
if (process.env.NODE_ENV === 'test') return level === 'error';
|
||
if (process.env.NODE_ENV === 'production') return level !== 'debug';
|
||
return true;
|
||
}
|
||
|
||
private formatOutput(level: LogLevel, source: string, message: string, context?: unknown, error?: Error): void {
|
||
const color = this.COLORS[level];
|
||
const emoji = this.EMOJIS[level];
|
||
const prefix = this.PREFIXES[level];
|
||
|
||
// Edge runtime doesn't support console.groupCollapsed/groupEnd
|
||
// Fallback to simple logging for compatibility
|
||
const supportsGrouping = typeof console.groupCollapsed === 'function' && typeof console.groupEnd === 'function';
|
||
|
||
if (supportsGrouping) {
|
||
// Safe to call - we've verified both functions exist
|
||
(console as any).groupCollapsed(`%c${emoji} [${source.toUpperCase()}] ${prefix}: ${message}`, `color: ${color}; font-weight: bold;`);
|
||
} else {
|
||
// Simple format for edge runtime
|
||
console.log(`${emoji} [${source.toUpperCase()}] ${prefix}: ${message}`);
|
||
}
|
||
|
||
console.log(`%cTimestamp:`, 'color: #666; font-weight: bold;', new Date().toISOString());
|
||
console.log(`%cSource:`, 'color: #666; font-weight: bold;', source);
|
||
|
||
if (context) {
|
||
console.log(`%cContext:`, 'color: #666; font-weight: bold;');
|
||
// console.dir may not be available in edge runtime
|
||
if (typeof console.dir === 'function') {
|
||
console.dir(context, { depth: 3, colors: true });
|
||
} else {
|
||
console.log(JSON.stringify(context, null, 2));
|
||
}
|
||
}
|
||
|
||
if (error) {
|
||
console.log(`%cError Details:`, 'color: #666; font-weight: bold;');
|
||
console.log(`%cType:`, 'color: #ff4444; font-weight: bold;', error.name);
|
||
console.log(`%cMessage:`, 'color: #ff4444; font-weight: bold;', error.message);
|
||
|
||
if (process.env.NODE_ENV === 'development' && error.stack) {
|
||
console.log(`%cStack Trace:`, 'color: #666; font-weight: bold;');
|
||
console.log(error.stack);
|
||
}
|
||
}
|
||
|
||
if (supportsGrouping) {
|
||
// Safe to call - we've verified the function exists
|
||
(console as any).groupEnd();
|
||
}
|
||
}
|
||
|
||
debug(message: string, context?: unknown): void {
|
||
if (!this.shouldLog('debug')) return;
|
||
this.formatOutput('debug', 'website', message, context);
|
||
}
|
||
|
||
info(message: string, context?: unknown): void {
|
||
if (!this.shouldLog('info')) return;
|
||
this.formatOutput('info', 'website', message, context);
|
||
}
|
||
|
||
warn(message: string, context?: unknown): void {
|
||
if (!this.shouldLog('warn')) return;
|
||
this.formatOutput('warn', 'website', message, context);
|
||
}
|
||
|
||
error(message: string, error?: Error, context?: unknown): void {
|
||
if (!this.shouldLog('error')) return;
|
||
this.formatOutput('error', 'website', message, context, error);
|
||
}
|
||
} |