- using eventbus in recipe editor - migrate to logging instead of console log - fix case swap not saved, value not update after change, topping slot bug Signed-off-by: pakintada@gmail.com <Pakin>
91 lines
2.3 KiB
TypeScript
91 lines
2.3 KiB
TypeScript
/**
|
|
* Lightweight logger that suppresses output in production.
|
|
*
|
|
* In development (npm run dev): logs are shown with a prefix tag.
|
|
* In production (npm run build): all console output is suppressed
|
|
* so logs are never exposed to the browser inspector.
|
|
*
|
|
* Usage:
|
|
* import { logger } from '$lib/core/utils/logger';
|
|
* logger.info('hello', someVar);
|
|
* logger.error('failed', err);
|
|
*/
|
|
|
|
type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error';
|
|
|
|
const LOG_LEVEL_RANK: Record<LogLevel, number> = {
|
|
trace: -1,
|
|
debug: 0,
|
|
info: 1,
|
|
warn: 2,
|
|
error: 3
|
|
};
|
|
|
|
const ENV_LOG_LEVEL: LogLevel =
|
|
(import.meta.env.PUBLIC_APP_LOG_LEVEL as LogLevel) || 'info';
|
|
const IS_DEV = import.meta.env.DEV;
|
|
|
|
function shouldLog(level: LogLevel): boolean {
|
|
return IS_DEV && LOG_LEVEL_RANK[level] >= LOG_LEVEL_RANK[ENV_LOG_LEVEL];
|
|
}
|
|
|
|
function formatArgs(level: LogLevel, args: any[]): any[] {
|
|
return [`[${level.toUpperCase()}]`, ...args];
|
|
}
|
|
|
|
/**
|
|
* Extract caller location (file:line) from a stack trace.
|
|
* Stack frame format: " at method (file:///path/file.ts:10:20)"
|
|
* The 3rd frame (index 2) is the caller of the method that created the Error.
|
|
*/
|
|
function getCallerLocation(): string {
|
|
try {
|
|
const stack = new Error().stack?.split('\n');
|
|
if (!stack || stack.length < 3) return 'unknown';
|
|
// stack[0] = "Error", stack[1] = " at getCallerLocation (...)",
|
|
// stack[2] = " at Logger.trace (...)" — skip both
|
|
const caller = stack[2]?.trim();
|
|
// Extract path from common formats:
|
|
// "at method (file:///path/file.ts:10:20)" or "at file:///path/file.ts:10:20"
|
|
const match = caller.match(/(?:\(|at\s+)([^(]+?\.\w+):(\d+)/);
|
|
if (match) return `${match[1]}:${match[2]}`;
|
|
return caller || 'unknown';
|
|
} catch {
|
|
return 'unknown';
|
|
}
|
|
}
|
|
|
|
class Logger {
|
|
trace(...args: any[]) {
|
|
if (shouldLog('trace')) {
|
|
const location = getCallerLocation();
|
|
console.debug(`[TRACE:${location}]`, ...args);
|
|
}
|
|
}
|
|
|
|
debug(...args: any[]) {
|
|
if (shouldLog('debug')) {
|
|
console.debug(...formatArgs('debug', args));
|
|
}
|
|
}
|
|
|
|
info(...args: any[]) {
|
|
if (shouldLog('info')) {
|
|
console.info(...formatArgs('info', args));
|
|
}
|
|
}
|
|
|
|
warn(...args: any[]) {
|
|
if (shouldLog('warn')) {
|
|
console.warn(...formatArgs('warn', args));
|
|
}
|
|
}
|
|
|
|
error(...args: any[]) {
|
|
if (shouldLog('error')) {
|
|
console.error(...formatArgs('error', args));
|
|
}
|
|
}
|
|
}
|
|
|
|
export const logger = new Logger();
|