core/logger.tstypescript
/**
* Logger utility with different log levels and debugging support
*/
export enum LogLevel {
ERROR = 0,
WARN = 1,
INFO = 2,
DEBUG = 3,
}
// Check if we're in production - will be replaced by Vite's define
const isProduction = process.env.NODE_ENV === 'production';
// Check if debug mode is enabled via URL parameters or window.nextConfig
const isDebugModeEnabled = (): boolean => {
if (typeof window === 'undefined') return false;
const params = new URLSearchParams(window.location.search);
const windowConfig = (window as any).nextConfig;
return (
params.get('debug') === 'true' ||
params.get('debugger') === 'true' ||
windowConfig?.debug === true ||
windowConfig?.debugger === true
);
};
// Interface for logger methods
interface ILogger {
error(message: string, ...args: any[]): void;
warn(message: string, ...args: any[]): void;
info(message: string, ...args: any[]): void;
debug(message: string, ...args: any[]): void;
}
/**
* Console logger used across the SDK. Each instance carries a context label shown as a prefix; the static global level filters what prints.
*
* @category Core
*/
export class Logger implements ILogger {
private context: string;
private static globalLevel: LogLevel = LogLevel.INFO;
constructor(context: string) {
this.context = context;
}
public static setLogLevel(level: LogLevel): void {
Logger.globalLevel = level;
}
public static getLogLevel(): LogLevel {
return Logger.globalLevel;
}
public error(message: string, ...args: any[]): void {
// Always log errors, even in production
if (Logger.globalLevel >= LogLevel.ERROR) {
console.error(`[${this.context}] ${message}`, ...args);
}
}
public warn(message: string, ...args: any[]): void {
if (isProduction && !isDebugModeEnabled()) {
// This will be completely removed by Terser's dead code elimination
return;
}
if (Logger.globalLevel >= LogLevel.WARN) {
console.warn(`[${this.context}] ${message}`, ...args);
}
}
public info(message: string, ...args: any[]): void {
if (isProduction && !isDebugModeEnabled()) {
// This will be completely removed by Terser's dead code elimination
return;
}
if (Logger.globalLevel >= LogLevel.INFO) {
console.info(`[${this.context}] ${message}`, ...args);
}
}
public debug(message: string, ...args: any[]): void {
if (isProduction && !isDebugModeEnabled()) {
// This will be completely removed by Terser's dead code elimination
return;
}
if (Logger.globalLevel >= LogLevel.DEBUG) {
console.debug(`[${this.context}] ${message}`, ...args);
}
}
}
// Production logger that only logs errors (unless debug mode is enabled)
class ProductionLogger extends Logger {
constructor(context: string) {
super(context);
}
public override warn(message: string, ...args: any[]): void {
if (isDebugModeEnabled()) {
super.warn(message, ...args);
}
// Otherwise no-op in production
}
public override info(message: string, ...args: any[]): void {
if (isDebugModeEnabled()) {
super.info(message, ...args);
}
// Otherwise no-op in production
}
public override debug(message: string, ...args: any[]): void {
if (isDebugModeEnabled()) {
super.debug(message, ...args);
}
// Otherwise no-op in production
}
}
// Factory function for creating loggers
export function createLogger(context: string): Logger {
// In production, use ProductionLogger which respects debug mode
if (isProduction) {
return new ProductionLogger(context);
}
// In development, use regular logger
return new Logger(context);
}