Created
July 13, 2023 11:44
-
-
Save juliusmarminge/67081c41e857a7ebbf9484b829487171 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument */ | |
import chalk from 'chalk' | |
interface Logger { | |
debug(message: string, ...optionalParameters: any[]): void | |
info(message: string, ...optionalParameters: any[]): void | |
warn(message: string, ...optionalParameters: any[]): void | |
error(message: string, ...optionalParameters: any[]): void | |
[x: string]: any | |
} | |
const levels = ['debug', 'info', 'warn', 'error'] as const | |
export type LogLevels = (typeof levels)[number] | |
const colorize = (level: LogLevels, message: string) => { | |
switch (level) { | |
case 'debug': { | |
return chalk.bgCyan(chalk.bold('[ DEBUG ]')) + ' ' + chalk.cyan(message) | |
} | |
case 'info': { | |
return chalk.bgWhite(chalk.bold('[ INFO ]')) + ' ' + chalk.white(message) | |
} | |
case 'warn': { | |
return ( | |
chalk.bgYellow(chalk.bold('[ WARN ]')) + ' ' + chalk.yellow(message) | |
) | |
} | |
case 'error': { | |
return chalk.bgRed(chalk.bold('[ ERROR ]')) + ' ' + chalk.red(message) | |
} | |
default: { | |
return message | |
} | |
} | |
} | |
class Logger implements Logger { | |
private subscriptions: { | |
fn: (m: { message: string; level: LogLevels; ts: number }) => void | |
level: LogLevels | |
}[] | |
constructor() { | |
this.subscriptions = [] | |
} | |
debug(message: string | Error | unknown, ...optionalParameters: any[]) { | |
if (message instanceof Error) { | |
this.log('debug', message.message, [ | |
optionalParameters, | |
message.stack, | |
message.cause, | |
]) | |
} else if (typeof message === 'string') { | |
this.log('debug', message, optionalParameters) | |
} else { | |
this.log('debug', JSON.stringify(message), optionalParameters) | |
} | |
} | |
info(message: string | Error | unknown, ...optionalParameters: any[]) { | |
if (message instanceof Error) { | |
this.log('info', message.message, [ | |
optionalParameters, | |
message.stack, | |
message.cause, | |
]) | |
} else if (typeof message === 'string') { | |
this.log('info', message, optionalParameters) | |
} else { | |
this.log('info', JSON.stringify(message), optionalParameters) | |
} | |
} | |
warn(message: string | Error | unknown, ...optionalParameters: any[]) { | |
if (message instanceof Error) { | |
this.log('warn', message.message, [ | |
optionalParameters, | |
message.stack, | |
message.cause, | |
]) | |
} else if (typeof message === 'string') { | |
this.log('warn', message, optionalParameters) | |
} else { | |
this.log('warn', JSON.stringify(message), optionalParameters) | |
} | |
} | |
error(message: string | Error | unknown, ...optionalParameters: any[]) { | |
if (message instanceof Error) { | |
this.log('error', message.message, [ | |
optionalParameters, | |
message.stack, | |
message.cause, | |
]) | |
} else if (typeof message === 'string') { | |
this.log('error', message, optionalParameters) | |
} else { | |
this.log('error', JSON.stringify(message), optionalParameters) | |
} | |
} | |
subscribe( | |
function_: (m: { message: string; level: LogLevels; ts: number }) => void, | |
level?: LogLevels, | |
) { | |
if (!level) level = 'info' | |
this.subscriptions.push({ fn: function_, level }) | |
} | |
unsubscribe( | |
function_: (m: { message: string; level: LogLevels; ts: number }) => void, | |
) { | |
this.subscriptions = this.subscriptions.filter( | |
({ fn: subFunction }) => subFunction !== function_, | |
) | |
} | |
private log(level: LogLevels, message: string, optionalParameters: any[]) { | |
const ts = Date.now() | |
const defaultLevel = 'info' | |
if (getLogLevels(defaultLevel).includes(level)) { | |
console[level](colorize(level, message), ...optionalParameters) | |
} | |
for (const { fn, level: subLevel } of this.subscriptions) { | |
if (getLogLevels(subLevel).includes(level)) fn({ message, level, ts }) | |
} | |
} | |
} | |
// get all log levels above and including the given level | |
const getLogLevels = (level: LogLevels): LogLevels[] => { | |
return levels.slice(levels.indexOf(level)) | |
} | |
export const logger = new Logger() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment