const path = require('path'); const fs = require('fs'); const logger = require('./logger'); class ConfigLoader { constructor() { this.config = {}; this.env = process.env.NODE_ENV || 'development'; this.loadConfig(); } loadConfig() { try { // Load base configuration this.loadBaseConfig(); // Load environment-specific configuration this.loadEnvConfig(); // Validate configuration this.validateConfig(); logger.info(`Configuration loaded for environment: ${this.env}`); } catch (error) { logger.error('Configuration loading failed:', error); throw error; } } loadBaseConfig() { // Load from appConfig.js const { appConfig } = require('../config/appConfig'); this.config = { ...appConfig }; } loadEnvConfig() { const envFile = path.join(__dirname, '../../', `env.${this.env}`); if (fs.existsSync(envFile)) { logger.info(`Loading environment configuration from: ${envFile}`); // Parse environment file const envContent = fs.readFileSync(envFile, 'utf8'); const envVars = this.parseEnvFile(envContent); // Override configuration with environment-specific values Object.assign(process.env, envVars); // Reload configuration with new environment variables const { appConfig } = require('../config/appConfig'); this.config = { ...appConfig }; } else { logger.warn(`Environment configuration file not found: ${envFile}`); } } parseEnvFile(content) { const envVars = {}; const lines = content.split('\n'); for (const line of lines) { const trimmedLine = line.trim(); // Skip empty lines and comments if (!trimmedLine || trimmedLine.startsWith('#')) { continue; } // Parse KEY=VALUE format const equalIndex = trimmedLine.indexOf('='); if (equalIndex > 0) { const key = trimmedLine.substring(0, equalIndex).trim(); const value = trimmedLine.substring(equalIndex + 1).trim(); // Remove quotes if present const cleanValue = value.replace(/^["']|["']$/g, ''); envVars[key] = cleanValue; } } return envVars; } validateConfig() { const errors = []; const warnings = []; // Required fields validation if (!this.config.apis.groq.apiKey) { errors.push('GROQ_API_KEY is required'); } if (!this.config.auth.jwtSecret) { errors.push('JWT_SECRET is required'); } if (!this.config.database.password) { errors.push('DB_PASSWORD is required'); } // Environment-specific validations if (this.env === 'production') { if (this.config.auth.jwtSecret === 'dev_secret_key_change_in_production') { errors.push('JWT_SECRET must be changed for production'); } if (!this.config.database.ssl) { warnings.push('Database SSL is recommended for production'); } } // Log warnings warnings.forEach(warning => { logger.warn(`Configuration warning: ${warning}`); }); // Throw errors if (errors.length > 0) { const errorMessage = `Configuration errors: ${errors.join(', ')}`; logger.error(errorMessage); throw new Error(errorMessage); } } get(key, defaultValue = null) { const keys = key.split('.'); let value = this.config; for (const k of keys) { if (value && typeof value === 'object' && k in value) { value = value[k]; } else { return defaultValue; } } return value; } getAll() { return this.config; } getServerConfig() { return this.config.server; } getDatabaseConfig() { return this.config.database; } getApiConfig() { return this.config.apis; } getAuthConfig() { return this.config.auth; } getUploadConfig() { return this.config.upload; } getRateLimitConfig() { return this.config.rateLimit; } getLoggingConfig() { return this.config.logging; } getModelConfig() { return this.config.models; } getSecurityConfig() { return this.config.security; } getMonitoringConfig() { return this.config.monitoring; } getDevelopmentConfig() { return this.config.development; } isDevelopment() { return this.env === 'development'; } isProduction() { return this.env === 'production'; } isTest() { return this.env === 'test'; } getEnvironment() { return this.env; } } // Create singleton instance const configLoader = new ConfigLoader(); module.exports = configLoader;