// File: server/rr/rr-logger.js // Console logger for RR flows with safe JSON. No socket emission by default. const baseLogger = require("../utils/logger"); function RRLogger(_socket, defaults = {}) { function safeSerialize(value) { try { const seen = new WeakSet(); return JSON.stringify(value, (key, val) => { if (typeof val === "bigint") return val.toString(); if (val instanceof Error) return { name: val.name, message: val.message, stack: val.stack }; if (typeof val === "function") return undefined; if (typeof val === "object" && val !== null) { if (seen.has(val)) return "[Circular]"; seen.add(val); if (val instanceof Date) return val.toISOString(); if (val instanceof Map) return Object.fromEntries(val); if (val instanceof Set) return Array.from(val); if (typeof Buffer !== "undefined" && Buffer.isBuffer?.(val)) return ``; } return val; }); } catch { try { return String(value); } catch { return "[Unserializable]"; } } } return function log(level = "info", message = "", ctx = {}) { const lvl = String(level || "info").toLowerCase(); const iso = new Date().toISOString(); const msgStr = typeof message === "string" ? message : safeSerialize(message); const mergedCtx = ctx && typeof ctx === "object" ? { ...defaults, ...ctx } : { ...defaults }; const ctxStr = Object.keys(mergedCtx || {}).length ? ` ${safeSerialize(mergedCtx)}` : ""; const line = `[RR] ${iso} [${lvl.toUpperCase()}] ${msgStr}${ctxStr}`; const logger = baseLogger?.logger || baseLogger || console; const fn = (logger[lvl] || logger.log || logger.info || console[lvl] || console.log).bind(logger); try { fn(line); } catch { try { console.log(line); } catch {} } }; } module.exports = RRLogger;