type LogLevel = "error" | "warn" | "info" | "http" | "debug"; export interface LogEntry { level: LogLevel; timestamp: string; message: any; metadata?: any; } interface Error { code: string; message: string; userHint?: string; detail?: string; error?: any; actionable?: boolean; } class BrowserLogger { private async sendLog(entry: LogEntry) { try { // Only send logs to server in production if (process.env.NODE_ENV === "production") { await fetch("/api/logs", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(entry), }); } // Always log to console in development const consoleMethod = entry.level === "debug" ? "log" : entry.level; // @ts-ignore console[consoleMethod as keyof Console]( `[${entry.level}] ${entry.timestamp}: `, entry.message, entry.metadata || "", ); } catch (err) { console.error("Failed to send log to server:", err); // @ts-ignore console[entry.level as keyof Console](entry.message); } } private createLogEntry( level: LogLevel, message: any, metadata?: any, ): LogEntry { return { level, timestamp: new Date().toISOString(), message, metadata, }; } error(message: any, metadata?: any) { this.sendLog(this.createLogEntry("error", message, metadata)); } warn(message: any, metadata?: any) { this.sendLog(this.createLogEntry("warn", message, metadata)); } info(message: any, metadata?: any) { this.sendLog(this.createLogEntry("info", message, metadata)); } http(message: any, metadata?: any) { this.sendLog(this.createLogEntry("http", message, metadata)); } debug(message: any, metadata?: any) { this.sendLog(this.createLogEntry("debug", message, metadata)); } } const ClientLogger = new BrowserLogger(); function getError(payload: Error, error?: any) { ClientLogger.error(payload); if (error) { ClientLogger.error(error); } return { code: payload.code, message: payload.message, userHint: payload.userHint, detail: payload.detail, error: error, actionable: payload.actionable, } as Error; } export { ClientLogger, getError };