feat: improve unified config system and build process
- Enhance unified config environment variable loading with better precedence - Add environment-aware validation (production validation only when NODE_ENV=production) - Add environment-specific build commands (build:dev, build:prod, build:staging) - Improve configuration debugging with cleaner logging - Remove unnecessary development warnings - Provides more flexible and maintainable configuration system
This commit is contained in:
@@ -512,14 +512,24 @@ const defaultConfig: UnifiedConfig = {
|
||||
|
||||
/**
|
||||
* Get environment variable with fallback
|
||||
* Reads from .env file via process.env or import.meta.env
|
||||
*/
|
||||
function getEnvVar(key: string, fallback: string = ''): string {
|
||||
if (typeof process !== 'undefined' && process.env) {
|
||||
return process.env[key] || fallback;
|
||||
// First try process.env (Node.js, includes .env via dotenv or build process)
|
||||
if (typeof process !== 'undefined' && process.env && process.env[key]) {
|
||||
return process.env[key]!;
|
||||
}
|
||||
if (typeof import.meta !== 'undefined' && import.meta.env) {
|
||||
return import.meta.env[key] || fallback;
|
||||
|
||||
// Then try import.meta.env (Vite/browser, includes .env via Vite's loadEnv)
|
||||
if (
|
||||
typeof import.meta !== 'undefined' &&
|
||||
import.meta.env &&
|
||||
import.meta.env[key]
|
||||
) {
|
||||
return import.meta.env[key];
|
||||
}
|
||||
|
||||
// Use fallback if not found
|
||||
return fallback;
|
||||
}
|
||||
|
||||
@@ -543,7 +553,8 @@ function getNumberEnvVar(key: string, fallback: number = 0): number {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load configuration from environment variables
|
||||
* Load configuration from environment variables (.env file)
|
||||
* This provides environment-specific overrides for the unified config
|
||||
*/
|
||||
function loadFromEnvironment(config: UnifiedConfig): UnifiedConfig {
|
||||
return {
|
||||
@@ -701,8 +712,9 @@ function validateConfig(config: UnifiedConfig): void {
|
||||
const errors: string[] = [];
|
||||
const warnings: string[] = [];
|
||||
|
||||
// Production-specific validations
|
||||
if (config.app.environment === 'production') {
|
||||
// Production-specific validations (only when NODE_ENV is explicitly production)
|
||||
const isActualProduction = getEnvVar('NODE_ENV') === 'production';
|
||||
if (config.app.environment === 'production' && isActualProduction) {
|
||||
if (config.auth.jwtSecret === defaultConfig.auth.jwtSecret) {
|
||||
errors.push('JWT_SECRET must be changed in production');
|
||||
}
|
||||
@@ -718,22 +730,6 @@ function validateConfig(config: UnifiedConfig): void {
|
||||
}
|
||||
}
|
||||
|
||||
// Development warnings for default secrets
|
||||
if (config.app.environment === 'development') {
|
||||
if (config.auth.jwtSecret === defaultConfig.auth.jwtSecret) {
|
||||
warnings.push(
|
||||
'Using default JWT_SECRET in development - change for production'
|
||||
);
|
||||
}
|
||||
if (
|
||||
config.security.sessionSecret === defaultConfig.security.sessionSecret
|
||||
) {
|
||||
warnings.push(
|
||||
'Using default SESSION_SECRET in development - change for production'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Email configuration validation
|
||||
if (
|
||||
config.features.enableEmailVerification &&
|
||||
@@ -768,9 +764,10 @@ function validateConfig(config: UnifiedConfig): void {
|
||||
|
||||
/**
|
||||
* Create unified configuration
|
||||
* Uses .env file as primary source for environment-specific overrides
|
||||
*/
|
||||
export function createUnifiedConfig(): UnifiedConfig {
|
||||
// Determine environment
|
||||
// Determine environment from .env file or NODE_ENV
|
||||
const nodeEnv = getEnvVar('NODE_ENV', 'development') as Environment;
|
||||
const environment = ['development', 'staging', 'production', 'test'].includes(
|
||||
nodeEnv
|
||||
@@ -783,6 +780,7 @@ export function createUnifiedConfig(): UnifiedConfig {
|
||||
|
||||
/**
|
||||
* Create unified configuration for specific environment
|
||||
* Priority: .env file overrides > environment-specific config > defaults
|
||||
*/
|
||||
export function createUnifiedConfigForEnvironment(
|
||||
environment: Environment
|
||||
@@ -791,15 +789,15 @@ export function createUnifiedConfigForEnvironment(
|
||||
let config = { ...defaultConfig };
|
||||
config.app.environment = environment;
|
||||
|
||||
// Apply environment-specific overrides
|
||||
// Apply environment-specific overrides (lower priority)
|
||||
if (environmentConfigs[environment]) {
|
||||
config = deepMerge(config, environmentConfigs[environment]);
|
||||
}
|
||||
|
||||
// Apply environment variable overrides
|
||||
// Apply .env file overrides (highest priority)
|
||||
config = loadFromEnvironment(config);
|
||||
|
||||
// Compute derived values
|
||||
// Compute derived values after all overrides
|
||||
config.container.imageUrl = `${config.container.registry}/${config.container.repository}:${config.container.tag}`;
|
||||
|
||||
// Validate configuration
|
||||
@@ -927,7 +925,7 @@ export function exportAsEnvVars(
|
||||
*/
|
||||
export function logConfig(): void {
|
||||
if (unifiedConfig.features.debugMode) {
|
||||
console.warn('🔧 Unified Configuration:', {
|
||||
console.warn('🔧 Unified Configuration (Single Source of Truth):', {
|
||||
environment: unifiedConfig.app.environment,
|
||||
app: unifiedConfig.app.name,
|
||||
version: unifiedConfig.app.version,
|
||||
@@ -936,7 +934,13 @@ export function logConfig(): void {
|
||||
url: unifiedConfig.database.url,
|
||||
useMock: unifiedConfig.database.useMock,
|
||||
},
|
||||
container: {
|
||||
registry: unifiedConfig.container.registry,
|
||||
repository: unifiedConfig.container.repository,
|
||||
imageUrl: unifiedConfig.container.imageUrl,
|
||||
},
|
||||
features: unifiedConfig.features,
|
||||
configSource: '.env file overrides applied',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user