/* monkey-patch console methods to prefix messages with file:line for easier logs */ (() => { const cwd = process.cwd(); const cwdRe = new RegExp("^[^/]*" + cwd.replace("/", "\\/") + "/([^:]*:[0-9]*).*$"); const methods = ["log", "warn", "error", "info", "debug"] as const; function getCallerFileLine(): string { try { // Create an Error to capture stack const err = new Error(); if (!err.stack) return "unknown:0 -"; const lines = err.stack.split("\n").slice(1); // Find the first stack line that is not this file for (let i = 0; i < lines.length; i++) { const line = lines[i]; if (!line) continue; if (line.indexOf("console-line") !== -1) continue; // skip this helper // Try to extract file:line from the line. Use a stricter capture so we // don't accidentally include leading whitespace or the 'at' token. const m = line.match(/\(?(\S+:\d+:\d+)\)?$/); if (m && m[1]) { return m[1].trim() + " -"; } } // Fallback: try to extract file:line:col from the third stack line even // if it contains leading whitespace and the 'at' prefix. If that fails, // fall back to the cwd-based replace and trim whitespace. const fallback = err.stack.split("\n")[3] || ""; const m2 = fallback.match(/\(?(\S+:\d+:\d+)\)?$/); if (m2 && m2[1]) return m2[1].trim() + " -"; const replaced = fallback.replace(cwdRe, "$1 -").trim(); return replaced || "unknown:0 -"; } catch (e) { return "unknown:0 -"; } } methods.forEach((method) => { const orig = (console as any)[method] || console.log; (console as any)[method] = function (...args: any[]) { try { const prefix = getCallerFileLine(); // Separate Error objects from other args so we can print their stacks // line-by-line with the same prefix. This keeps stack traces intact // while ensuring every printed line shows the caller prefix. const errorArgs = args.filter((a: any) => a instanceof Error) as Error[]; const otherArgs = args.filter((a: any) => !(a instanceof Error)); // Print non-error args in a single call (preserving original formatting) const processedOther = otherArgs.map((a: any) => (a instanceof Error ? a.stack || a.toString() : a)); if (processedOther.length > 0) { orig.apply(this, [prefix, ...processedOther]); } // For each Error, print each line of its stack as a separate prefixed log // entry so lines that begin with ' at' are not orphaned. errorArgs.forEach((err) => { const stack = err.stack || err.toString(); stack.split("\n").forEach((line) => { orig.apply(this, [prefix, line]); }); }); } catch (e) { try { orig.apply(this, args); } catch (e2) { /* swallow */ } } }; }); })();