import { ConsoleApiName, display } from './display' let onMonitorErrorCollected: undefined | ((error: unknown) => void) let debugMode = false export function startMonitorErrorCollection(newOnMonitorErrorCollected: (error: unknown) => void) { onMonitorErrorCollected = newOnMonitorErrorCollected } export function setDebugMode(newDebugMode: boolean) { debugMode = newDebugMode } export function resetMonitor() { onMonitorErrorCollected = undefined debugMode = false } export function monitored unknown>( _: any, __: string, descriptor: TypedPropertyDescriptor ) { const originalMethod = descriptor.value! descriptor.value = function (this: any, ...args: Parameters) { const decorated = onMonitorErrorCollected ? monitor(originalMethod) : originalMethod return decorated.apply(this, args) as ReturnType } as T } export function monitor any>(fn: T): T { return function (this: any) { // eslint-disable-next-line @typescript-eslint/no-unsafe-return return callMonitored(fn, this, arguments as unknown as Parameters) } as unknown as T // consider output type has input type } export function callMonitored any>( fn: T, context: ThisParameterType, args: Parameters ): ReturnType | undefined export function callMonitored any>(fn: T): ReturnType | undefined export function callMonitored any>( fn: T, context?: any, args?: any ): ReturnType | undefined { try { // eslint-disable-next-line @typescript-eslint/no-unsafe-return return fn.apply(context, args) } catch (e) { displayIfDebugEnabled(ConsoleApiName.error, e) if (onMonitorErrorCollected) { try { onMonitorErrorCollected(e) } catch (e) { displayIfDebugEnabled(ConsoleApiName.error, e) } } } } export function displayIfDebugEnabled(api: ConsoleApiName, ...args: any[]) { if (debugMode) { display(api, '[MONITOR]', ...args) } }