import errorStackParser , { StackFrame } from 'error-stack-parser' ; import { RC_Config } from './shared-types' ; const startTime = Date . now ( ) ; export const colorize = ( light , code ) => ( str ) => '\x1B[' + light + ';' + code + 'm' + str + '\x1b[0m' ; export const blue = colorize ( 1 , 34 ) ; export const red = colorize ( 1 , 31 ) ; export const yellow = colorize ( 1 , 33 ) ; export const grey = colorize ( 0 , 37 ) ; export const green = colorize ( 1 , 37 ) ; export const cyan = colorize ( 1 , 36 ) ; const emojiFontCss = 'font-family: Roboto, "Apple Color Emoji", NotoEmoji, "Helvetica Neue", Arial, Helvetica, NotoMono, sans-serif !important;' ; const LoggerVariants = [ { log : console . debug , level : 'DEBUG' , emoji : '🕸️' , symbol : '[D]' } , { log : console . info , level : 'INFO' , emoji : 'ℹ️' , symbol : blue ( '[i]' ) } , { log : console . warn , level : 'WARNING' , emoji : '⚠️' , symbol : yellow ( '[w]' ) , } , { log : console . error , level : 'ERROR' , emoji : '🚨' , symbol : red ( '[E]' ) , } , { log : console . error , level : 'CRITICAL' , emoji : '🚨🚨' , symbol : red ( '[C]' ) , } , ] ; export function printProcessLogLevelInfo ( ) { console . info ( `%cLogging Levels:\n${ LoggerVariants . map ( v => `${ v . emoji } ${ v . level }` ) . join ( '\n' ) }` , emojiFontCss ) ; } type LogHandlerFunction = ( channel : string , level : string , stacktrace : ReturnType < typeof getStackTrace > , ... args : any [ ] ) => void ; let handler ; let rc = { } as any ; export function setLogHandler ( LogHandler , rcObject ) { handler = LogHandler ; rc = rcObject ; } function log ( { channel , isMainProcess } , level , stacktrace , args ) { const variant = LoggerVariants [ level ] ; if ( ! handler ) { console . log ( 'Failed to log message - Handler not initialized yet' ) ; console . log ( `Log Message: ${ channel } ${ level } ${ args . join ( ' ' ) }` ) ; throw Error ( 'Failed to log message - Handler not initialized yet' ) ; } handler ( channel , variant . level , stacktrace , ... args ) ; if ( rc [ 'log-to-console' ] ) { if ( isMainProcess ) { const beginning = `${ Math . round ( ( Date . now ( ) - startTime ) / 100 ) / 10 }s ${ LoggerVariants [ level ] . symbol }${ grey ( channel ) }:` ; if ( ! stacktrace ) { console . log ( beginning , ... args ) ; } else { console . log ( beginning , ... args , red ( Array . isArray ( stacktrace ) ? stacktrace . map ( s => `\n${ s . toString ( ) }` ) . join ( ) : stacktrace ) ) ; } } else { const prefix = `%c${ variant . emoji }%c${ channel }` ; const prefixStyle = [ emojiFontCss , 'color:blueviolet;' ] ; if ( stacktrace ) { variant . log ( prefix , ... prefixStyle , stacktrace , ... args ) ; } else { variant . log ( prefix , ... prefixStyle , ... args ) ; } } } } function getStackTrace ( ) { const rawStack = errorStackParser . parse ( new Error ( 'Get Stacktrace' ) ) ; const stack = rawStack . slice ( 2 , rawStack . length ) ; return rc [ 'machine-readable-stacktrace' ] ? stack : stack . map ( s => `\n${ s . toString ( ) }` ) . join ( ) ; } export class Logger { isMainProcess = typeof window === 'undefined' ; constructor ( public readonly channel ) { if ( channel === 'core/event' ) { this . getStackTrace = ( ) => '' ; } } getStackTrace ( ) { const rawStack = errorStackParser . parse ( new Error ( 'Get Stacktrace' ) ) ; const stack = rawStack . slice ( 2 , rawStack . length ) ; return rc [ 'machine-readable-stacktrace' ] ? stack : stack . map ( s => `\n${ s . toString ( ) }` ) . join ( ) ; } debug ( ... args ) { if ( ! rc [ 'log-debug' ] ) return ; log ( this , 0 , '' , args ) ; } info ( ... args ) { log ( this , 1 , '' , args ) ; } warn ( ... args ) { log ( this , 2 , this . getStackTrace ( ) , args ) ; } error ( ... args ) { log ( this , 3 , this . getStackTrace ( ) , args ) ; } critical ( ... args ) { log ( this , 4 , this . getStackTrace ( ) , args ) ; } } export function getLogger ( channel ) { return new Logger ( channel ) ; }