import path from "path" ; import { Colorize , dim , green , grey , red , reset , yellow } from "kleur/colors" ; import { prefixError } from "./error" ; const cwd = process . cwd ( ) ; const cwdNodeModules = path . join ( cwd , "node_modules" ) ; export enum LogLevel { NONE , ERROR , WARN , INFO , DEBUG , VERBOSE } const LEVEL_PREFIX = { [ LogLevel . NONE ] : "" , [ LogLevel . ERROR ] : "err" , [ LogLevel . WARN ] : "wrn" , [ LogLevel . INFO ] : "inf" , [ LogLevel . DEBUG ] : "dbg" , [ LogLevel . VERBOSE ] : "vrb" , } ; const LEVEL_COLOUR = { [ LogLevel . NONE ] : reset , [ LogLevel . ERROR ] : red , [ LogLevel . WARN ] : yellow , [ LogLevel . INFO ] : green , [ LogLevel . DEBUG ] : grey , [ LogLevel . VERBOSE ] : ( input ) => dim ( grey ( input as any ) ) as any , } ; function dimInternalStackLine ( line ) { if ( line . startsWith ( "    at" ) && ( ! line . includes ( cwd ) || line . includes ( cwdNodeModules ) ) ) { return dim ( line ) ; } return line ; } export interface LogOptions { prefix ? : string ; suffix ? : string ; } export class Log { readonly #prefix : string ; readonly #suffix : string ; constructor ( readonly level = LogLevel . INFO , opts = { } ) { const prefix = opts . prefix ?? "mf" ; const suffix = opts . suffix ?? "" ; this . #prefix = prefix ? prefix + ":" : "" ; this . #suffix = suffix ? ":" + suffix : "" ; } log ( message ) { console . log ( message ) ; } logWithLevel ( level , message ) { if ( level <= this . level ) { const prefix = `[${ this . #prefix }${ LEVEL_PREFIX [ level ] }${ this . #suffix }]` ; this . log ( LEVEL_COLOUR [ level ] ( `${ prefix } ${ message }` ) ) ; } } error ( message ) { if ( this . level < LogLevel . ERROR ) { throw message ; } else if ( message . stack ) { const lines = message . stack . split ( "\n" ) . map ( dimInternalStackLine ) ; this . logWithLevel ( LogLevel . ERROR , lines . join ( "\n" ) ) ; } else { this . logWithLevel ( LogLevel . ERROR , message . toString ( ) ) ; } if ( ( message as any ) . cause ) { this . error ( prefixError ( "Cause" , ( message as any ) . cause ) ) ; } } warn ( message ) { this . logWithLevel ( LogLevel . WARN , message ) ; } info ( message ) { this . logWithLevel ( LogLevel . INFO , message ) ; } debug ( message ) { this . logWithLevel ( LogLevel . DEBUG , message ) ; } verbose ( message ) { this . logWithLevel ( LogLevel . VERBOSE , message ) ; } } export class NoOpLog extends Log { log ( ) { } error ( message ) { throw message ; } }