Major improvements: - Created startup orchestration system with health monitoring and graceful shutdown - Fixed user registration and login with simplified authentication flow - Rebuilt authentication forms from scratch with direct API integration - Implemented comprehensive debugging and error handling - Added Redis fallback functionality for disabled environments - Fixed CORS configuration for cross-origin frontend requests - Simplified password validation to 6+ characters (removed complexity requirements) - Added toast notifications at app level for better UX feedback - Created comprehensive startup/shutdown scripts with OODA methodology - Fixed database validation and connection issues - Implemented TokenService memory fallback when Redis is disabled Technical details: - New SimpleLoginForm.tsx and SimpleRegisterForm.tsx components - Enhanced CORS middleware with additional allowed origins - Simplified auth validators and removed strict password requirements - Added extensive logging and diagnostic capabilities - Fixed authentication middleware token validation - Implemented graceful Redis error handling throughout the stack - Created modular startup system with configurable health checks 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
380 lines
No EOL
9 KiB
JavaScript
380 lines
No EOL
9 KiB
JavaScript
/**
|
|
* 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
|
|
}; |