/** * Shattered Void MMO - Startup Configuration * * Central configuration file for the startup system, allowing easy customization * of startup behavior, timeouts, and service settings. */ const path = require('path'); /** * Default startup configuration */ const defaultConfig = { // Environment settings environment: { mode: process.env.NODE_ENV || 'development', logLevel: process.env.LOG_LEVEL || 'info', enableDebug: process.env.NODE_ENV === 'development' }, // Backend server configuration backend: { port: parseInt(process.env.PORT) || 3000, host: process.env.HOST || '0.0.0.0', script: 'src/server.js', startupTimeout: 30000, healthEndpoint: '/health', gracefulShutdownTimeout: 10000 }, // Frontend configuration frontend: { enabled: process.env.ENABLE_FRONTEND !== 'false', port: parseInt(process.env.FRONTEND_PORT) || 5173, host: process.env.FRONTEND_HOST || '0.0.0.0', directory: './frontend', buildDirectory: './frontend/dist', startupTimeout: 45000, buildTimeout: 120000, devCommand: 'dev', buildCommand: 'build', previewCommand: 'preview' }, // Database configuration database: { enabled: process.env.DISABLE_DATABASE !== 'true', connectionTimeout: 10000, migrationTimeout: 60000, seedTimeout: 30000, autoMigrate: process.env.AUTO_MIGRATE !== 'false', autoSeed: process.env.AUTO_SEED === 'true', integrityChecks: process.env.SKIP_DB_INTEGRITY !== 'true', retryAttempts: 3, retryDelay: 2000 }, // Redis configuration redis: { enabled: process.env.DISABLE_REDIS !== 'true', optional: true, connectionTimeout: 5000, retryAttempts: 3, retryDelay: 1000, host: process.env.REDIS_HOST || 'localhost', port: parseInt(process.env.REDIS_PORT) || 6379 }, // Health monitoring configuration healthMonitoring: { enabled: process.env.ENABLE_HEALTH_MONITORING !== 'false', interval: parseInt(process.env.HEALTH_CHECK_INTERVAL) || 30000, timeout: 5000, alertThresholds: { responseTime: 5000, memoryUsage: 80, cpuUsage: 90, errorRate: 10, consecutiveFailures: 3 }, systemMetricsInterval: 10000, historySize: 100 }, // Startup process configuration startup: { maxRetries: parseInt(process.env.STARTUP_MAX_RETRIES) || 3, retryDelay: parseInt(process.env.STARTUP_RETRY_DELAY) || 2000, enableBanner: process.env.DISABLE_BANNER !== 'true', enableColors: process.env.DISABLE_COLORS !== 'true', verboseLogging: process.env.VERBOSE_STARTUP === 'true', failFast: process.env.FAIL_FAST === 'true', gracefulShutdown: true }, // Pre-flight checks configuration preflightChecks: { enabled: process.env.SKIP_PREFLIGHT !== 'true', timeout: 30000, required: { nodeVersion: true, npmAvailability: true, environmentConfig: true, directoryStructure: true, packageDependencies: true, portAvailability: true, databaseConfig: true, logDirectories: true, filePermissions: true, systemMemory: true, diskSpace: true }, optional: { redisConfig: true, frontendDependencies: true }, requirements: { nodeMinVersion: 18, memoryMinGB: 1, diskSpaceMaxUsage: 90 } }, // Logging configuration logging: { level: process.env.LOG_LEVEL || 'info', colorize: process.env.DISABLE_COLORS !== 'true', timestamp: true, includeProcessId: true, startupLog: true, errorStackTrace: process.env.NODE_ENV === 'development' }, // Performance configuration performance: { measureStartupTime: true, measurePhaseTime: true, memoryMonitoring: true, cpuMonitoring: process.env.NODE_ENV === 'development', performanceReporting: process.env.PERFORMANCE_REPORTING === 'true' }, // Security configuration security: { hidePasswords: true, sanitizeEnvironment: true, validatePorts: true, checkFilePermissions: true }, // Development specific settings development: { hotReload: true, autoRestart: process.env.AUTO_RESTART === 'true', debugEndpoints: process.env.ENABLE_DEBUG_ENDPOINTS === 'true', verboseErrors: true, showDeprecations: true }, // Production specific settings production: { compressionEnabled: true, cachingEnabled: true, minifyAssets: true, enableCDN: process.env.ENABLE_CDN === 'true', healthEndpoints: true, metricsCollection: true }, // Service dependencies dependencies: { required: ['database'], optional: ['redis', 'frontend'], order: ['database', 'redis', 'backend', 'frontend', 'healthMonitoring'] }, // Error handling errorHandling: { retryFailedServices: true, continueOnOptionalFailure: true, detailedErrorMessages: process.env.NODE_ENV === 'development', errorNotifications: process.env.ERROR_NOTIFICATIONS === 'true', crashReporting: process.env.CRASH_REPORTING === 'true' }, // Paths and directories paths: { root: process.cwd(), src: path.join(process.cwd(), 'src'), config: path.join(process.cwd(), 'config'), logs: path.join(process.cwd(), 'logs'), scripts: path.join(process.cwd(), 'scripts'), frontend: path.join(process.cwd(), 'frontend'), database: path.join(process.cwd(), 'src', 'database'), migrations: path.join(process.cwd(), 'src', 'database', 'migrations'), seeds: path.join(process.cwd(), 'src', 'database', 'seeds') } }; /** * Environment-specific configurations */ const environmentConfigs = { development: { backend: { startupTimeout: 20000 }, frontend: { startupTimeout: 30000 }, database: { integrityChecks: false, autoSeed: true }, healthMonitoring: { interval: 15000 }, logging: { level: 'debug' }, startup: { verboseLogging: true, failFast: false } }, production: { backend: { startupTimeout: 45000 }, frontend: { enabled: false // Assume pre-built assets are served by nginx/CDN }, database: { integrityChecks: true, autoSeed: false, retryAttempts: 5 }, healthMonitoring: { interval: 60000, alertThresholds: { responseTime: 3000, memoryUsage: 85, cpuUsage: 85 } }, logging: { level: 'warn' }, startup: { verboseLogging: false, failFast: true }, errorHandling: { retryFailedServices: true, continueOnOptionalFailure: false } }, staging: { backend: { startupTimeout: 30000 }, database: { integrityChecks: true, autoSeed: true }, healthMonitoring: { interval: 30000 }, logging: { level: 'info' } }, testing: { backend: { port: 0, // Use random available port startupTimeout: 10000 }, frontend: { enabled: false }, database: { autoMigrate: true, autoSeed: true, integrityChecks: false }, healthMonitoring: { enabled: false }, preflightChecks: { enabled: false }, startup: { enableBanner: false, verboseLogging: false } } }; /** * Merge configurations based on environment */ function mergeConfigs(base, override) { const result = { ...base }; for (const [key, value] of Object.entries(override)) { if (typeof value === 'object' && value !== null && !Array.isArray(value)) { result[key] = mergeConfigs(result[key] || {}, value); } else { result[key] = value; } } return result; } /** * Get configuration for current environment */ function getConfig() { const environment = process.env.NODE_ENV || 'development'; const envConfig = environmentConfigs[environment] || {}; return mergeConfigs(defaultConfig, envConfig); } /** * Validate configuration */ function validateConfig(config) { const errors = []; // Validate ports if (config.backend.port < 1 || config.backend.port > 65535) { errors.push(`Invalid backend port: ${config.backend.port}`); } if (config.frontend.enabled && (config.frontend.port < 1 || config.frontend.port > 65535)) { errors.push(`Invalid frontend port: ${config.frontend.port}`); } // Validate timeouts if (config.backend.startupTimeout < 1000) { errors.push('Backend startup timeout too low (minimum 1000ms)'); } if (config.database.connectionTimeout < 1000) { errors.push('Database connection timeout too low (minimum 1000ms)'); } // Validate required paths const requiredPaths = ['root', 'src', 'config']; for (const pathKey of requiredPaths) { if (!config.paths[pathKey]) { errors.push(`Missing required path: ${pathKey}`); } } if (errors.length > 0) { throw new Error(`Configuration validation failed:\n${errors.join('\n')}`); } return true; } /** * Export configuration */ const config = getConfig(); validateConfig(config); module.exports = { config, getConfig, validateConfig, defaultConfig, environmentConfigs };