/* * https://github.com/morethanwords/tweb * Copyright (C) 2019-2021 Eduard Kuzmenko * https://github.com/morethanwords/tweb/blob/master/LICENSE */ import DEBUG from "../config/debug"; import { IS_FIREFOX, IS_SAFARI } from "../environment/userAgent"; import { IS_SERVICE_WORKER, IS_WEB_WORKER } from "../helpers/context"; export enum LogTypes { None = 0, Error = 1, Warn = 2, Log = 4, Debug = 8 }; export const LOG_LEVELS = [LogTypes.None, LogTypes.Error, LogTypes.Warn, LogTypes.Log, LogTypes.Debug]; const _logTimer = Date.now(); function dT() { return '[' + ((Date.now() - _logTimer) / 1000).toFixed(3) + ']'; } let getCallerFunctionNameFromLine: (line: string) => string; const IS_WEBKIT = IS_SAFARI || IS_FIREFOX; if(IS_WEBKIT) { getCallerFunctionNameFromLine = (line) => { const splitted = line.split('@'); return splitted[0]; }; } else { getCallerFunctionNameFromLine = (line: string) => { const splitted = line.trim().split(' '); if(splitted.length === 3) { return splitted[1].slice(splitted[1].lastIndexOf('.') + 1); } }; } const STYLES_SUPPORTED = !IS_WEBKIT; const LINE_INDEX = IS_WEBKIT ? 2 : 3; function getCallerFunctionName() { const stack = new Error().stack; const lines = stack.split('\n'); const line = lines[LINE_INDEX] || lines[lines.length - 1]; // const match = line.match(/\.([^\.]+?)\s/); // line = match ? match[1] : line.trim(); const caller = getCallerFunctionNameFromLine(line) || ''; return '[' + caller + ']'; } export const LOGGER_STYLES = { reset: "\x1b[0m", bright: "\x1b[1m", dim: "\x1b[2m", underscore: "\x1b[4m", blink: "\x1b[5m", reverse: "\x1b[7m", hidden: "\x1b[8m", // Foreground (text) colors fg: { black: "\x1b[30m", red: "\x1b[31m", green: "\x1b[32m", yellow: "\x1b[33m", blue: "\x1b[34m", magenta: "\x1b[35m", cyan: "\x1b[36m", white: "\x1b[37m" }, // Background colors bg: { black: "\x1b[40m", red: "\x1b[41m", green: "\x1b[42m", yellow: "\x1b[43m", blue: "\x1b[44m", magenta: "\x1b[45m", cyan: "\x1b[46m", white: "\x1b[47m" } }; export type Logger = { (...args: any[]): void; warn(...args: any[]): void; info(...args: any[]): void; error(...args: any[]): void; trace(...args: any[]): void; debug(...args: any[]): void; assert(...args: any[]): void; // log(...args: any[]): void; setPrefix(newPrefix: string): void; setLevel(level: 0 | 1 | 2 | 3 | 4): void; bindPrefix(prefix: string): Logger; }; const methods: ['debug' | 'info' | 'warn' | 'error' | 'assert' | 'trace'/* | 'log' */, LogTypes][] = [ ["debug", LogTypes.Debug], ["info", LogTypes.Log], ["warn", LogTypes.Warn], ["error", LogTypes.Error], ["assert", LogTypes.Error], ["trace", LogTypes.Log], // ["log", LogTypes.Log] ]; export function logger(prefix: string, type: LogTypes = LogTypes.Log | LogTypes.Warn | LogTypes.Error, ignoreDebugReset = false, style = ''): Logger { let originalPrefix: string; if(!DEBUG && !ignoreDebugReset/* || true */) { type = LogTypes.Error; } if(!STYLES_SUPPORTED) { style = ''; } else if(!style) { if(IS_SERVICE_WORKER) style = LOGGER_STYLES.fg.yellow; else if(IS_WEB_WORKER) style = LOGGER_STYLES.fg.cyan; } let originalStyle = style; if(style) style = `%s ${style}%s`; else style = '%s'; //level = LogLevels.log | LogLevels.warn | LogLevels.error | LogLevels.debug const log: Logger = function(...args: any[]) { return type & LogTypes.Log && console.log(style, dT(), prefix, getCallerFunctionName(), ...args); } as any; methods.forEach(([method, logType]) => { log[method] = function(...args: any[]) { return type & logType && console[method](style, dT(), prefix, getCallerFunctionName(), ...args); }; }); log.setPrefix = function(newPrefix: string) { originalPrefix = newPrefix; prefix = '[' + newPrefix + ']'; }; log.setPrefix(prefix); log.setLevel = function(level: 0 | 1 | 2 | 3 | 4) { type = LOG_LEVELS.slice(0, level + 1).reduce((acc, v) => acc | v, 0) as any; }; log.bindPrefix = function(prefix: string) { return logger(`${originalPrefix}] [${prefix}`, type, ignoreDebugReset, originalStyle); }; return log; };