Files
memory-infrastructure-palace/code/websites/pokedex.online/server/utils/env-validator.js

186 lines
4.9 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Environment Variable Validation
*
* Validates required environment variables at startup and provides
* helpful error messages for production deployments.
*/
/**
* Required environment variables for production
*/
const REQUIRED_ENV_VARS = {
// Server Configuration
NODE_ENV: {
required: true,
description: 'Environment mode (development, production)',
validate: val => ['development', 'production', 'test'].includes(val)
},
PORT: {
required: true,
description: 'Server port number',
validate: val =>
!isNaN(parseInt(val)) && parseInt(val) > 0 && parseInt(val) < 65536
},
// Optional but recommended for production
SESSION_SECRET: {
required: false,
description: 'Secret key for session encryption',
warn: val =>
!val || val.length < 32
? 'SESSION_SECRET should be at least 32 characters for security'
: null
},
FRONTEND_URL: {
required: false,
description: 'Frontend URL for CORS (required in production)',
warn: (val, env) =>
env.NODE_ENV === 'production' && !val
? 'FRONTEND_URL should be set in production for proper CORS'
: null
},
// Challonge OAuth (optional)
CHALLONGE_CLIENT_ID: {
required: false,
description: 'Challonge OAuth client ID'
},
CHALLONGE_CLIENT_SECRET: {
required: false,
description: 'Challonge OAuth client secret'
},
CHALLONGE_REDIRECT_URI: {
required: false,
description: 'OAuth redirect URI'
}
};
/**
* Validate environment variables
* @returns {Object} Validation result with errors and warnings
*/
export function validateEnvironment() {
const errors = [];
const warnings = [];
const missing = [];
// Check required variables
for (const [key, config] of Object.entries(REQUIRED_ENV_VARS)) {
const value = process.env[key];
// Check if required variable is missing
if (config.required && !value) {
errors.push(
`Missing required environment variable: ${key} - ${config.description}`
);
missing.push(key);
continue;
}
// Validate value if present
if (value && config.validate && !config.validate(value)) {
errors.push(
`Invalid value for ${key}: "${value}" - ${config.description}`
);
}
// Check for warnings
if (config.warn) {
const warning = config.warn(value, process.env);
if (warning) {
warnings.push(`${key}: ${warning}`);
}
}
}
return {
valid: errors.length === 0,
errors,
warnings,
missing
};
}
/**
* Validate environment and exit if critical errors found
* @param {boolean} exitOnError - Whether to exit process on validation errors (default: true)
*/
export function validateOrExit(exitOnError = true) {
const result = validateEnvironment();
// Print validation results
console.log('\n🔍 Environment Validation:');
console.log(` NODE_ENV: ${process.env.NODE_ENV || 'not set'}`);
console.log(` PORT: ${process.env.PORT || 'not set'}`);
// Show errors
if (result.errors.length > 0) {
console.error('\n❌ Environment Validation Errors:');
result.errors.forEach(error => console.error(` - ${error}`));
if (result.missing.length > 0) {
console.error('\n💡 Tip: Create a .env file with these variables:');
result.missing.forEach(key => {
console.error(` ${key}=your_value_here`);
});
console.error('\n See .env.example for reference');
}
if (exitOnError) {
console.error('\n❌ Server cannot start due to environment errors\n');
process.exit(1);
}
} else {
console.log(' ✅ All required variables present');
}
// Show warnings
if (result.warnings.length > 0) {
console.warn('\n⚠ Environment Warnings:');
result.warnings.forEach(warning => console.warn(` - ${warning}`));
}
console.log('');
return result;
}
/**
* Get configuration object with validated environment variables
* @returns {Object} Configuration object
*/
export function getConfig() {
return {
nodeEnv: process.env.NODE_ENV || 'development',
port: parseInt(process.env.PORT || '3001'),
isProduction: process.env.NODE_ENV === 'production',
isDevelopment: process.env.NODE_ENV === 'development',
// Challonge OAuth
challonge: {
clientId: process.env.CHALLONGE_CLIENT_ID,
clientSecret: process.env.CHALLONGE_CLIENT_SECRET,
redirectUri: process.env.CHALLONGE_REDIRECT_URI,
configured: !!(
process.env.CHALLONGE_CLIENT_ID && process.env.CHALLONGE_CLIENT_SECRET
)
},
// CORS
cors: {
origin:
process.env.NODE_ENV === 'production'
? process.env.FRONTEND_URL
: [
'http://localhost:5173',
'http://localhost:5174',
'http://localhost:5175'
]
},
// Security
session: {
secret: process.env.SESSION_SECRET || 'dev-secret-change-in-production'
}
};
}