This commit is contained in:
yohlo
2025-08-20 22:35:40 -05:00
commit f51c278cd3
169 changed files with 8173 additions and 0 deletions

199
src/lib/logger/index.ts Normal file
View File

@@ -0,0 +1,199 @@
type LogLevel = 'info' | 'success' | 'warn' | 'error';
interface LoggerOptions {
enabled?: boolean;
showTimestamp?: boolean;
collapsed?: boolean;
colors?: boolean;
}
// Cache for performance - update once per second max
let cachedTimestamp = '';
let lastTimestampUpdate = 0;
/**
* Get formatted timestamp with caching for performance
* Format: MM/DD HH:mm:ss
*/
function getTimestamp(): string {
const now = Date.now();
// Update cache only if more than 1 second has passed
if (now - lastTimestampUpdate > 1000) {
const date = new Date(now);
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
cachedTimestamp = `${month}/${day} ${hours}:${minutes}:${seconds}`;
lastTimestampUpdate = now;
}
return cachedTimestamp;
}
/**
* Get color and emoji for each log level
*/
function getLevelStyle(level: LogLevel): { color: string; label: string } {
const styles = {
info: { color: '#f5f5f5', label: 'INFO' },
success: { color: '#10B981', label: 'SUCCESS' },
warn: { color: '#F59E0B', label: 'WARN' },
error: { color: '#EF4444', label: 'ERROR' },
};
return styles[level] || styles.info;
}
/**
* Main logger class
*/
class Logger {
private options: LoggerOptions;
private context?: string;
constructor(context?: string, options: LoggerOptions = {}) {
this.context = context;
this.options = {
enabled: process.env.NODE_ENV !== 'production',
showTimestamp: true,
collapsed: true,
colors: true,
...options
};
}
/**
* Create a child logger with a specific context
*/
child(context: string, options?: LoggerOptions): Logger {
const childContext = this.context ? `${this.context} > ${context}` : context;
return new Logger(childContext, { ...this.options, ...options });
}
/**
* Core logging method
*/
private log(
level: LogLevel,
label: string,
data?: any,
...rest: any[]
): void {
if (!this.options.enabled) return;
const style = getLevelStyle(level);
const timestamp = this.options.showTimestamp ? `${getTimestamp()}` : '';
const context = this.context ? `${this.context}` : '';
const groupLabel = `${timestamp}${style.label}${context}${label}`;
const group = this.options.collapsed ? console.groupCollapsed : console.group;
if (this.options.colors && typeof window !== 'undefined') {
group(
`%c${groupLabel}`,
`color: ${style.color}; font-weight: bold;`
);
} else {
group(groupLabel);
}
if (data !== undefined) {
console.log(data);
}
if (rest.length > 0) {
for (const item of rest) {
console.log(item);
}
}
console.groupEnd();
}
/**
* log level methods
*/
info(label: string, data?: any, ...rest: any[]): void {
this.log('info', label, data, ...rest);
}
success(label: string, data?: any, ...rest: any[]): void {
this.log('success', label, data, ...rest);
}
warn(label: string, data?: any, ...rest: any[]): void {
this.log('warn', label, data, ...rest);
}
error(label: string, data?: any, ...rest: any[]): void {
this.log('error', label, data, ...rest);
}
simple(message: string): void {
if (!this.options.enabled) return;
const style = getLevelStyle('info');
const timestamp = this.options.showTimestamp ? `${getTimestamp()}` : '';
const context = this.context ? `${this.context}` : '';
const logMessage = `${timestamp}${style.label}${context}${message}`;
if (this.options.colors && typeof window !== 'undefined') {
console.log(`%c${logMessage}`, `color: ${style.color};`);
} else {
console.log(logMessage);
}
}
/**
* Measure performance of an operation
*/
async measure<T>(label: string, fn: () => Promise<T>): Promise<T> {
const start = performance.now();
try {
const result = await fn();
const duration = (performance.now() - start).toFixed(2);
this.success(`${label} completed`, {
duration: `${duration}ms`,
result
});
return result;
} catch (error) {
const duration = (performance.now() - start).toFixed(2);
this.error(`${label} failed`, {
duration: `${duration}ms`,
error
});
throw error;
}
}
/**
* Create a table log
*/
table(label: string, data: any[]): void {
if (!this.options.enabled) return;
const timestamp = this.options.showTimestamp ? `${getTimestamp()}` : '';
const context = this.context ? `${this.context}` : '';
console.group(`${timestamp}TABLE${context}${label}`);
console.table(data);
console.groupEnd();
}
}
export const logger = new Logger();
export { Logger };