2025-05-12 15:20:40 -05:00

123 lines
4.6 KiB
JavaScript

/**
* Enhanced logger utility with date-fns for date formatting
* Original code inspired by https://github.com/Mirasaki/logger
*/
const chalk = require('chalk');
const { format, formatInTimeZone } = require('date-fns-tz');
// Define log levels and their corresponding styles
const LOG_LEVELS = {
SYSLOG: { color: 'greenBright', prefix: '[SYSLOG]' },
SYSERR: { color: 'redBright', prefix: '[SYSERR]' },
SUCCESS: { color: 'greenBright', prefix: '[SUCCESS]' },
INFO: { color: 'blueBright', prefix: '[INFO]' },
DEBUG: { color: 'magentaBright', prefix: '[DEBUG]' },
DATA: { color: 'yellowBright', prefix: '[DATA]' },
COMMAND: { color: 'whiteBright', prefix: '[CMD]' },
EVENT: { color: 'cyanBright', prefix: '[EVENT]' },
ERROR: { color: 'redBright', prefix: '[ERROR]' },
WARN: { color: 'yellowBright', prefix: '[WARN]' }
};
// Create tag list with chalk styling
const tagList = Object.entries(LOG_LEVELS).reduce((acc, [key, { color, prefix }]) => ({
...acc,
[key]: chalk[color](prefix)
}), {});
// Calculate longest tag length for alignment
const longestTagLength = Math.max(...Object.values(tagList).map(t => t.length));
/**
* Get formatted tag with proper spacing
* @param {string} tag - The log level tag
* @returns {string} Formatted tag with spacing
*/
const getTag = (tag) => `${tagList[tag]}${' '.repeat(longestTagLength - tagList[tag].length)}`;
/**
* Get formatted timestamp
* @returns {string} Formatted timestamp with styling
*/
const timestamp = () => {
const now = new Date();
const formattedDate = formatInTimeZone(now, 'UTC', 'yyyy-MM-dd HH:mm:ss');
return chalk.whiteBright.bold(`[${formattedDate}]`);
};
/**
* Create a log message with proper formatting
* @param {string} level - Log level
* @param {string} type - Optional type identifier
* @param {string} message - Log message
* @returns {string} Formatted log message
*/
const createLogMessage = (level, type, message) => {
const typeTag = type ? `${chalk.whiteBright.bgBlue.bold(`[${type}]`)}:` : ':';
return `${timestamp()} ${getTag(level)} ${typeTag} ${message}`;
};
/**
* Format error stack trace with proper styling
* @param {Error} err - Error object
* @returns {string} Formatted error stack trace
*/
const formatErrorStack = (err) => {
if (!err.stack) return chalk.red(err);
return err.stack
.split('\n')
.map((msg, index) => {
if (index === 0) return chalk.red(msg);
const isFailedFunctionCall = index === 1;
const traceStartIndex = msg.indexOf('(');
const traceEndIndex = msg.lastIndexOf(')');
const hasTrace = traceStartIndex !== -1;
const functionCall = msg.slice(
msg.indexOf('at') + 3,
hasTrace ? traceStartIndex - 1 : msg.length
);
const trace = msg.slice(traceStartIndex, traceEndIndex + 1);
return ` ${chalk.grey('at')} ${isFailedFunctionCall
? `${chalk.redBright(functionCall)} ${chalk.red.underline(trace)}`
: `${chalk.greenBright(functionCall)} ${chalk.grey(trace)}`
}`;
})
.join('\n');
};
module.exports = {
syslog: (type, str) => console.info(createLogMessage('SYSLOG', type, str)),
syserr: (type, str) => console.error(createLogMessage('SYSERR', type, str)),
success: (type, str) => console.log(createLogMessage('SUCCESS', type, str)),
info: (type, str) => console.info(createLogMessage('INFO', type, str)),
debug: (type, str) => console.log(createLogMessage('DEBUG', type, str)),
data: (type, str) => console.log(createLogMessage('DATA', type, str)),
command: (type, str) => console.log(createLogMessage('COMMAND', type, str)),
event: (type, str) => console.log(createLogMessage('EVENT', type, str)),
error: (type, str) => console.log(createLogMessage('ERROR', type, str)),
warn: (type, str) => console.log(createLogMessage('WARN', type, str)),
startLog: (identifier) => console.log(`${timestamp()} ${getTag('DEBUG')} ${chalk.greenBright('[START]')} ${identifier}`),
endLog: (identifier) => console.log(`${timestamp()} ${getTag('DEBUG')} ${chalk.redBright('[ END ]')} ${identifier}`),
timestamp,
getExecutionTime: (hrtime) => {
const timeSinceHrMs = (
process.hrtime(hrtime)[0] * 1000 +
hrtime[1] / 1000000
).toFixed(2);
return `${chalk.yellowBright((timeSinceHrMs / 1000).toFixed(2))} seconds (${chalk.yellowBright(timeSinceHrMs)} ms)`;
},
printErr: (err) => {
if (!(err instanceof Error)) {
console.error(err);
return;
}
console.error(formatErrorStack(err));
}
};