@graphql-mesh/utils
Version:
120 lines (119 loc) • 4.25 kB
JavaScript
import { process } from '@graphql-mesh/cross-helpers';
const ANSI_CODES = {
black: '\x1b[30m',
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
magenta: '\x1b[35m',
cyan: '\x1b[36m',
white: '\x1b[37m',
reset: '\x1b[0m',
bold: '\x1b[1m',
orange: '\x1b[48:5:166m',
};
export const warnColor = msg => ANSI_CODES.orange + msg + ANSI_CODES.reset;
export const infoColor = msg => ANSI_CODES.cyan + msg + ANSI_CODES.reset;
export const errorColor = msg => ANSI_CODES.red + msg + ANSI_CODES.reset;
export const debugColor = msg => ANSI_CODES.magenta + msg + ANSI_CODES.reset;
export const titleBold = msg => ANSI_CODES.bold + msg + ANSI_CODES.reset;
export var LogLevel;
(function (LogLevel) {
LogLevel[LogLevel["debug"] = 0] = "debug";
LogLevel[LogLevel["info"] = 1] = "info";
LogLevel[LogLevel["warn"] = 2] = "warn";
LogLevel[LogLevel["error"] = 3] = "error";
LogLevel[LogLevel["silent"] = 4] = "silent";
})(LogLevel || (LogLevel = {}));
const noop = () => { };
function truthy(val) {
return val === true || val === 1 || ['1', 't', 'true', 'y', 'yes'].includes(String(val));
}
function getTimestamp() {
return new Date().toISOString();
}
function handleLazyMessage(lazyArgs) {
return lazyArgs.flat(Infinity).flatMap(arg => {
if (typeof arg === 'function') {
return arg();
}
return arg;
});
}
export class DefaultLogger {
constructor(name, logLevel = truthy(process.env.DEBUG) ||
truthy(globalThis.DEBUG) ||
(this.name && String(process.env.DEBUG || globalThis.DEBUG || '').includes(this.name))
? LogLevel.debug
: LogLevel.info,
/** @deprecated Trimming messages is no longer supported. This argument is unused and will be removed in future versions. */
_trim, console = globalThis.console) {
this.name = name;
this.logLevel = logLevel;
this.console = console;
}
get prefix() {
return this.name
? `[${titleBold(this.name.toString().trim())}] ` /* trailing space because prefix is directly used in logged message */
: ``;
}
/** Logs a message at {@link LogLevel.info} but without the "INFO" prefix. */
log(...args) {
if (this.logLevel > LogLevel.info) {
return noop;
}
this.console.log(`[${getTimestamp()}] ${this.prefix}`.trim() /* trim in case prefix is empty */, ...args);
}
warn(...args) {
if (this.logLevel > LogLevel.warn) {
return noop;
}
this.console.warn(`[${getTimestamp()}] WARN ${this.prefix}${ANSI_CODES.orange}`, ...args, ANSI_CODES.reset);
}
info(...args) {
if (this.logLevel > LogLevel.info) {
return noop;
}
this.console.info(`[${getTimestamp()}] INFO ${this.prefix}${ANSI_CODES.cyan}`, ...args, ANSI_CODES.reset);
}
error(...args) {
if (this.logLevel > LogLevel.error) {
return noop;
}
this.console.error(`[${getTimestamp()}] ERROR ${this.prefix}${ANSI_CODES.red}`, ...args, ANSI_CODES.reset);
}
debug(...lazyArgs) {
if (this.logLevel > LogLevel.debug) {
return noop;
}
const flattenedArgs = handleLazyMessage(lazyArgs);
this.console.debug(`[${getTimestamp()}] DEBUG ${this.prefix}${ANSI_CODES.magenta}`, ...flattenedArgs, ANSI_CODES.reset);
}
child(name) {
name = stringifyName(name);
if (this.name?.includes(name)) {
return this;
}
return new DefaultLogger(this.name ? `${this.name}, ${name}` : name, this.logLevel, undefined, this.console);
}
addPrefix(prefix) {
prefix = stringifyName(prefix);
if (!this.name?.includes(prefix)) {
this.name = this.name ? `${this.name}, ${prefix}` : prefix;
}
return this;
}
toJSON() {
return undefined;
}
}
function stringifyName(name) {
if (typeof name === 'string' || typeof name === 'number') {
return `${name}`;
}
const names = [];
for (const [key, value] of Object.entries(name)) {
names.push(`${key}=${value}`);
}
return `${names.join(', ')}`;
}