import { isNode } from "./platform" ; import { Stack } from "./stack" ; export enum Level { debug , info , notice , warning , error , critical , alert , emergency } const colours = { debug : "cyan" , info : "green" , notice : "grey" , warning : "blue" , error : "red" , critical : "magenta" , alert : "magenta" , emergency : "magenta" } ; export interface Writer { write ? ( dateTime , level , id , msg ) : void ; rawWrite ? ( dateTime , level , id , msg ) : void ; } class ConsoleWriter implements Writer { write ( dateTime , level , id , msg ) { if ( isNode ) { console . log ( `[${ dateTime }] ${ Level [ level ] . toUpperCase ( ) } ${ id }:  ${ msg }` ) ; } else { console . log ( `[${ dateTime }] %c${ Level [ level ] . toUpperCase ( ) }%c ${ id }:  ${ msg }` , `color:${ colours [ Level [ level ] ] }` , "" ) ; } } } export class Logging { private static _instance : Logging ; private _levelStack = new Stack < Level > ( ) ; private _level = Level . info ; private _filter : string = "" ; private _writer : Writer = new ConsoleWriter ( ) ; public static Instance ( ) { return this . _instance || ( this . _instance = new this ( ) ) ; } private constructor ( ) { } private stringify ( obj ) { const cache = [ ] ; return JSON . stringify ( obj , function ( _key , value ) { if ( typeof value === "object" && value !== null ) { if ( cache . indexOf ( value ) !== - 1 ) { return ; } cache . push ( value ) ; } return value ; } , 2 ) ; } writer ( ) ; writer ( _ ) ; writer ( _ ? ) { if ( _ === void 0 ) return this . _writer ; this . _writer = _ ; return this ; } log ( level , id , msg ) { if ( level < this . _level ) return ; if ( this . _filter && this . _filter !== id ) return ; const dateTime = new Date ( ) . toISOString ( ) ; if ( this . _writer . rawWrite ) { this . _writer . rawWrite ( dateTime , level , id , msg ) ; } else { if ( typeof msg !== "string" ) { msg = this . stringify ( msg ) ; } if ( this . _writer . write ) { this . _writer . write ( dateTime , level , id , msg ) ; } } } debug ( id , msg ) { this . log ( Level . debug , id , msg ) ; } info ( id , msg ) { this . log ( Level . info , id , msg ) ; } notice ( id , msg ) { this . log ( Level . notice , id , msg ) ; } warning ( id , msg ) { this . log ( Level . warning , id , msg ) ; } error ( id , msg ) { this . log ( Level . error , id , msg ) ; } critical ( id , msg ) { this . log ( Level . critical , id , msg ) ; } alert ( id , msg ) { this . log ( Level . alert , id , msg ) ; } emergency ( id , msg ) { this . log ( Level . emergency , id , msg ) ; } level ( ) ; level ( _ ) ; level ( _ ? ) { if ( _ === void 0 ) return this . _level ; this . _level = _ ; return this ; } pushLevel ( _ ) { this . _levelStack . push ( this . _level ) ; this . _level = _ ; return this ; } popLevel ( ) { this . _level = this . _levelStack . pop ( ) ! ; return this ; } filter ( ) ; filter ( _ ) ; filter ( _ ? ) { if ( _ === void 0 ) return this . _filter ; this . _filter = _ ; return this ; } } export const logger = Logging . Instance ( ) ; export class ScopedLogging { protected _scopeID : string ; constructor ( scopeID ) { this . _scopeID = scopeID ; } debug ( msg ) { logger . debug ( this . _scopeID , msg ) ; } info ( msg ) { logger . info ( this . _scopeID , msg ) ; } notice ( msg ) { logger . notice ( this . _scopeID , msg ) ; } warning ( msg ) { logger . warning ( this . _scopeID , msg ) ; } error ( msg ) { logger . error ( this . _scopeID , msg ) ; } critical ( msg ) { logger . critical ( this . _scopeID , msg ) ; } alert ( msg ) { logger . alert ( this . _scopeID , msg ) ; } emergency ( msg ) { logger . emergency ( this . _scopeID , msg ) ; } pushLevel ( _ ) { logger . pushLevel ( _ ) ; return this ; } popLevel ( ) { logger . popLevel ( ) ; return this ; } } export function scopedLogger ( scopeID , filter = false ) { if ( filter ) { logger . filter ( scopeID ) ; } return new ScopedLogging ( scopeID ) ; }