diff --git a/server/utils/startupLog.js b/server/utils/startupLog.js new file mode 100644 index 0000000..6c55a89 --- /dev/null +++ b/server/utils/startupLog.js @@ -0,0 +1,177 @@ +const os = require('os'); +const path = require('path'); +const fs = require('fs'); + +/** + * Startup Log Utility + * Displays comprehensive system information and branding on server start + */ + +function getSystemInfo() { + return { + hostname: os.hostname(), + platform: os.platform(), + arch: os.arch(), + nodeVersion: process.version, + cpuCores: os.cpus().length, + totalMemory: (os.totalmem() / 1024 / 1024 / 1024).toFixed(2) + ' GB', + freeMemory: (os.freemem() / 1024 / 1024 / 1024).toFixed(2) + ' GB', + uptime: process.uptime().toFixed(2) + 's' + }; +} + +function getProcessInfo() { + const memUsage = process.memoryUsage(); + return { + pid: process.pid, + heapUsed: (memUsage.heapUsed / 1024 / 1024).toFixed(2) + ' MB', + heapTotal: (memUsage.heapTotal / 1024 / 1024).toFixed(2) + ' MB', + external: (memUsage.external / 1024 / 1024).toFixed(2) + ' MB' + }; +} + +function checkDirectories(dirs) { + const status = {}; + dirs.forEach(({ name, path: dirPath }) => { + status[name] = { + exists: fs.existsSync(dirPath), + path: dirPath, + writable: false + }; + + // Check write permissions if directory exists + if (status[name].exists) { + try { + fs.accessSync(dirPath, fs.constants.W_OK); + status[name].writable = true; + } catch (err) { + status[name].writable = false; + } + } + }); + return status; +} + +function getAppVersion() { + try { + const packagePath = path.join(__dirname, '../../package.json'); + if (fs.existsSync(packagePath)) { + const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf8')); + return pkg.version || 'unknown'; + } + } catch (err) { + // Silently fail + } + return 'unknown'; +} + +function logStartupBanner(config = {}) { + const { + appName = 'BREEDR', + port = 3000, + environment = 'development', + dataDir = './data', + uploadPath = './uploads', + staticPath = './static', + dbStatus = 'unknown' + } = config; + + const version = getAppVersion(); + const sysInfo = getSystemInfo(); + const procInfo = getProcessInfo(); + const timestamp = new Date().toISOString(); + + const directories = [ + { name: 'Data', path: dataDir }, + { name: 'Uploads', path: uploadPath }, + { name: 'Static', path: staticPath } + ]; + const dirStatus = checkDirectories(directories); + + // ASCII Banner + console.log('\n'); + console.log('╔══════════════════════════════════════════════════════════╗'); + console.log('║ ║'); + console.log('║ ██████╗ ██████╗ ███████╗███████╗██████╗ ██████╗ ║'); + console.log('║ ██╔══██╗██╔══██╗██╔════╝██╔════╝██╔══██╗██╔══██╗ ║'); + console.log('║ ██████╔╝██████╔╝█████╗ █████╗ ██║ ██║██████╔╝ ║'); + console.log('║ ██╔══██╗██╔══██╗██╔══╝ ██╔══╝ ██║ ██║██╔══██╗ ║'); + console.log('║ ██████╔╝██║ ██║███████╗███████╗██████╔╝██║ ██║ ║'); + console.log('║ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚═════╝ ╚═╝ ╚═╝ ║'); + console.log('║ ║'); + console.log('║ Dog Breeding Genealogy Management System ║'); + console.log('║ ║'); + console.log('╚══════════════════════════════════════════════════════════╝'); + console.log(''); + + // Application Info + console.log('┌─────────────────────────────────────────────────────────┐'); + console.log('│ 📦 APPLICATION INFO │'); + console.log('├─────────────────────────────────────────────────────────┤'); + console.log(`│ Version : ${version.padEnd(40)} │`); + console.log(`│ Environment : ${environment.padEnd(40)} │`); + console.log(`│ Started : ${timestamp.padEnd(40)} │`); + console.log(`│ Node.js : ${sysInfo.nodeVersion.padEnd(40)} │`); + console.log('└─────────────────────────────────────────────────────────┘'); + console.log(''); + + // Server Configuration + console.log('┌─────────────────────────────────────────────────────────┐'); + console.log('│ 🌐 SERVER CONFIGURATION │'); + console.log('├─────────────────────────────────────────────────────────┤'); + console.log(`│ Port : ${String(port).padEnd(40)} │`); + console.log(`│ Access URL : http://localhost:${port}${' '.repeat(27)} │`); + console.log(`│ Database : ${dbStatus.padEnd(40)} │`); + console.log('└─────────────────────────────────────────────────────────┘'); + console.log(''); + + // Directory Status + console.log('┌─────────────────────────────────────────────────────────┐'); + console.log('│ 📁 DIRECTORY STATUS │'); + console.log('├─────────────────────────────────────────────────────────┤'); + Object.entries(dirStatus).forEach(([name, status]) => { + const statusIcon = status.exists ? (status.writable ? '✓' : '⚠') : '✗'; + const statusText = status.exists ? (status.writable ? 'OK' : 'READ-ONLY') : 'MISSING'; + console.log(`│ ${statusIcon} ${name.padEnd(10)} : ${statusText.padEnd(10)} ${status.path.substring(0, 25).padEnd(25)} │`); + }); + console.log('└─────────────────────────────────────────────────────────┘'); + console.log(''); + + // System Resources + console.log('┌─────────────────────────────────────────────────────────┐'); + console.log('│ 💻 SYSTEM RESOURCES │'); + console.log('├─────────────────────────────────────────────────────────┤'); + console.log(`│ Hostname : ${sysInfo.hostname.padEnd(40)} │`); + console.log(`│ Platform : ${sysInfo.platform.padEnd(40)} │`); + console.log(`│ Architecture : ${sysInfo.arch.padEnd(40)} │`); + console.log(`│ CPU Cores : ${String(sysInfo.cpuCores).padEnd(40)} │`); + console.log(`│ Total Memory : ${sysInfo.totalMemory.padEnd(40)} │`); + console.log(`│ Free Memory : ${sysInfo.freeMemory.padEnd(40)} │`); + console.log('└─────────────────────────────────────────────────────────┘'); + console.log(''); + + // Process Info + console.log('┌─────────────────────────────────────────────────────────┐'); + console.log('│ ⚙️ PROCESS INFO │'); + console.log('├─────────────────────────────────────────────────────────┤'); + console.log(`│ PID : ${String(procInfo.pid).padEnd(40)} │`); + console.log(`│ Heap Used : ${procInfo.heapUsed.padEnd(40)} │`); + console.log(`│ Heap Total : ${procInfo.heapTotal.padEnd(40)} │`); + console.log(`│ External : ${procInfo.external.padEnd(40)} │`); + console.log(`│ Uptime : ${sysInfo.uptime.padEnd(40)} │`); + console.log('└─────────────────────────────────────────────────────────┘'); + console.log(''); + + // Ready message + console.log('🚀 Server is ready and listening for connections'); + console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'); + console.log(''); +} + +module.exports = { + logStartupBanner, + getSystemInfo, + getProcessInfo, + checkDirectories, + getAppVersion +}; \ No newline at end of file