9router/src/lib/consoleLogBuffer.js
2026-03-02 09:31:16 +07:00

79 lines
1.8 KiB
JavaScript

import { EventEmitter } from "events";
import { CONSOLE_LOG_CONFIG } from "@/shared/constants/config.js";
const consoleLevels = ["log", "info", "warn", "error", "debug"];
if (!global._consoleLogBufferState) {
global._consoleLogBufferState = {
logs: [],
patched: false,
originals: {},
emitter: new EventEmitter(),
};
global._consoleLogBufferState.emitter.setMaxListeners(50);
}
const state = global._consoleLogBufferState;
// Ensure emitter exists (handles hot reload with stale global)
if (!state.emitter) {
state.emitter = new EventEmitter();
state.emitter.setMaxListeners(50);
}
function toLogLine(level, args) {
return args.map(formatArg).join(" ");
}
// Strip ANSI escape codes so terminal colors don't bleed into UI
const ANSI_RE = /\x1b\[[0-9;]*m/g;
function stripAnsi(str) {
return str.replace(ANSI_RE, "");
}
function formatArg(arg) {
if (typeof arg === "string") return stripAnsi(arg);
if (arg instanceof Error) return stripAnsi(arg.stack || arg.message || String(arg));
try {
return stripAnsi(JSON.stringify(arg));
} catch {
return stripAnsi(String(arg));
}
}
function appendLine(line) {
state.logs.push(line);
const maxLines = CONSOLE_LOG_CONFIG.maxLines;
if (state.logs.length > maxLines) {
state.logs = state.logs.slice(-maxLines);
}
state.emitter.emit("line", line);
}
export function initConsoleLogCapture() {
if (state.patched) return;
for (const level of consoleLevels) {
state.originals[level] = console[level];
console[level] = (...args) => {
appendLine(toLogLine(level, args));
state.originals[level](...args);
};
}
state.patched = true;
}
export function getConsoleLogs() {
return state.logs;
}
export function clearConsoleLogs() {
state.logs = [];
state.emitter.emit("clear");
}
export function getConsoleEmitter() {
return state.emitter;
}