export type LogHook = ( level : LogLevels , ... args : any [ ] ) => any ; export type LoggerFunction = ( ... args : any [ ] ) => void ; export type LogLevels = 'log' | 'warn' | 'error' ; export interface ILogger { log : LoggerFunction ; warn : LoggerFunction ; error : LoggerFunction ; } export interface IGenericLogger { print ( level , ... args ) : void ; } const CONSOLE = console ; const EMPTY_FUNCTION = ( ) => { } ; const _HOOKS = { } ; function addArg ( func , value ) { return ( ( ... args ) => func ( value , ... args ) ) ; } function wrapLogFn ( level , func , value ? ) { const funcWrapped = ( ... args ) => { _HOOKS [ level ] ?. apply ( null , args ) ; func ( ... args ) ; } ; return value ? addArg ( funcWrapped , value ) : funcWrapped ; } export class ConsoleLogger implements ILogger , IGenericLogger { public static SetHook ( level , hook ) { _HOOKS [ level ] = hook ; } private _log : LoggerFunction ; private _warn : LoggerFunction ; private _error : LoggerFunction ; private _name : string ; get log ( ) { return this . _log ; } get warn ( ) { return this . _warn ; } get error ( ) { return this . _error ; } constructor ( name , enabled = true , private readonly defaultLogger = CONSOLE ) { this . _name = name ; if ( enabled ) { this . enable ( ) ; } else { this . disable ( ) ; } } enable ( overrideName = null ) { this . _name = overrideName || this . _name ; this . _log = wrapLogFn ( 'log' , this . defaultLogger . log , this . _name ) ; this . _warn = wrapLogFn ( 'warn' , this . defaultLogger . warn , this . _name ) ; this . _error = wrapLogFn ( 'error' , this . defaultLogger . error , this . _name ) ; } print ( level , ... args ) { switch ( level ) { case 'warn' : { return this . warn ( ... args ) ; } case 'error' : { return this . error ( ... args ) ; } case 'log' : default : { return this . log ( ... args ) ; } } } disable ( ) { this . _log = EMPTY_FUNCTION ; this . _warn = EMPTY_FUNCTION ; this . _error = EMPTY_FUNCTION ; } flush ( ) { } } export class BufferedConsoleLogger implements ILogger { private _name : string ; private _logs : string [ ] ; private _level = 1 ; private _log = CONSOLE . log ; constructor ( name ) { this . _name = name || '' ; } log ( ... args ) { this . _logs . push ( '\t--->' , ... args ) ; } warn ( ... args ) { this . _logs . push ( '\t---> [WARN]' , ... args ) ; this . _raiseLevel ( 2 ) ; } error ( ... args ) { this . _logs . push ( '\t---> [ERROR]' , ... args ) ; this . _raiseLevel ( 3 ) ; } flush ( ) { if ( this . _logs . length > 0 ) { this . _log ( this . _name , ... this . _logs ) ; this . _logs . length = 0 ; } } private _raiseLevel ( l ) { if ( l > this . _level ) { this . _level = l ; if ( l >= 3 ) { this . _log = CONSOLE . error ; } else if ( l >= 2 ) { this . _log = CONSOLE . warn ; } } } }