/** * 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)); } };