function isPromise ( val ) { return val && typeof val === 'object' && 'then' in val && typeof val . then === 'function' ; } export enum LogLevel { trace = 0 , debug = 1 , info = 2 , error = 3 } function getTimeString ( ) { return `[${ new Date ( ) . toLocaleTimeString ( ) }]` ; } export function createLogger ( logLevel ) { function logPerf ( name , start ) { console . debug ( getTimeString ( ) , `${ name }: ${ Number ( process . hrtime . bigint ( ) - start ) / 1000000 }ms` ) ; } return { perf : < T extends any > ( name , cb ) : T => { if ( logLevel <= LogLevel . trace ) { const start = process . hrtime . bigint ( ) ; const val = cb ( ) ; if ( isPromise ( val ) ) { val . then ( ( ) => { logPerf ( name , start ) ; } ) ; } else { logPerf ( name , start ) ; } return val ; } return cb ( ) ; } , debug : ( ... args ) => { if ( logLevel <= LogLevel . debug ) { console . debug ( getTimeString ( ) , ... args ) ; } } , info : ( ... args ) => { if ( logLevel <= LogLevel . info ) { console . log ( getTimeString ( ) , ... args ) ; } } , error : ( ... args ) => { if ( logLevel <= LogLevel . error ) { console . log ( getTimeString ( ) , ... args ) ; } } , } ; } export type Logger = ReturnType < typeof createLogger > ;