// file: crates/ksp-app-store-desk/frontend/ts/frontend_log.ts // version: 1 import { invoke } from "@tauri-apps/api/core"; import type { FrontendLogPayloadDto } from "./bindings/ksp_app_store_desk/frontend_logging/FrontendLogPayloadDto.ts"; export type FrontendLogLevel = "trace" | "debug" | "info" | "warn" | "error"; export type FrontendLogTargetId = "frontend" | "main" | "splash"; type ConsoleMethod = (...items: unknown[]) => void; const originalConsole = { trace: console.trace.bind(console), debug: console.debug.bind(console), log: console.log.bind(console), info: console.info.bind(console), warn: console.warn.bind(console), error: console.error.bind(console), }; function stringifyItem(item: unknown): string { if (item instanceof Error) { return item.stack ?? item.message; } if (typeof item === "string") { return item; } try { const serialized = JSON.stringify(item); return serialized ?? String(item); } catch { return String(item); } } function formatMessage(items: unknown[]): string { return items.map(item => stringifyItem(item)).join(" "); } async function sendFrontendLog(level: FrontendLogLevel, targetId: FrontendLogTargetId, message: string): Promise { const payload: FrontendLogPayloadDto = { level, targetId, message, }; await invoke("emit_frontend_log", { payload }); } function writeOriginalConsole(level: FrontendLogLevel, message: string): void { return level === "trace" ? originalConsole.trace(message) : level === "debug" ? originalConsole.debug(message) : level === "info" ? originalConsole.info(message) : level === "warn" ? originalConsole.warn(message) : originalConsole.error(message); } export async function emitFrontendLog(level: FrontendLogLevel, targetId: FrontendLogTargetId, message: string): Promise { writeOriginalConsole(level, message); await sendFrontendLog(level, targetId, message); } export function frontendTrace(targetId: FrontendLogTargetId, ...items: unknown[]): void { const message = formatMessage(items); originalConsole.trace(message); void sendFrontendLog("trace", targetId, message).catch(caughtError => originalConsole.error("KSP frontend logging bridge failed", caughtError)); } export function frontendDebug(targetId: FrontendLogTargetId, ...items: unknown[]): void { const message = formatMessage(items); originalConsole.debug(message); void sendFrontendLog("debug", targetId, message).catch(caughtError => originalConsole.error("KSP frontend logging bridge failed", caughtError)); } export function frontendInfo(targetId: FrontendLogTargetId, ...items: unknown[]): void { const message = formatMessage(items); originalConsole.info(message); void sendFrontendLog("info", targetId, message).catch(caughtError => originalConsole.error("KSP frontend logging bridge failed", caughtError)); } export function frontendWarn(targetId: FrontendLogTargetId, ...items: unknown[]): void { const message = formatMessage(items); originalConsole.warn(message); void sendFrontendLog("warn", targetId, message).catch(caughtError => originalConsole.error("KSP frontend logging bridge failed", caughtError)); } export function frontendError(targetId: FrontendLogTargetId, ...items: unknown[]): void { const message = formatMessage(items); originalConsole.error(message); void sendFrontendLog("error", targetId, message).catch(caughtError => originalConsole.error("KSP frontend logging bridge failed", caughtError)); } function buildConsoleBridge(level: FrontendLogLevel, targetId: FrontendLogTargetId, original: ConsoleMethod): ConsoleMethod { return (...items: unknown[]) => { original(...items); void sendFrontendLog(level, targetId, formatMessage(items)).catch(caughtError => originalConsole.error("KSP frontend logging bridge failed", caughtError)); }; } export function installFrontendConsoleBridge(targetId: FrontendLogTargetId): void { console.trace = buildConsoleBridge("trace", targetId, originalConsole.trace); console.debug = buildConsoleBridge("debug", targetId, originalConsole.debug); console.log = buildConsoleBridge("info", targetId, originalConsole.log); console.info = buildConsoleBridge("info", targetId, originalConsole.info); console.warn = buildConsoleBridge("warn", targetId, originalConsole.warn); console.error = buildConsoleBridge("error", targetId, originalConsole.error); }