feat: implement unified configuration as single source of truth
- Make unified config lazy-loaded to avoid initialization issues - Replace direct config exports with getter functions - Rewrite utils/env.ts to use unified config instead of scattered access - Add show-config.js helper script for configuration management - Type-safe configuration access throughout the app - Smart defaults for all environments with environment overrides - Eliminates scattered process.env and import.meta.env access
This commit is contained in:
197
utils/env.ts
197
utils/env.ts
@@ -1,59 +1,29 @@
|
||||
// Environment utility to safely access environment variables
|
||||
// Compatible with both Vite (browser) and Node.js (Jest/server)
|
||||
/**
|
||||
* Environment Utilities - Single Source of Truth
|
||||
*
|
||||
* This module provides environment utilities that use the unified config
|
||||
* as the single source of truth for all environment variables.
|
||||
*
|
||||
* Use this instead of directly accessing process.env or import.meta.env
|
||||
*/
|
||||
|
||||
export interface EnvConfig {
|
||||
VITE_COUCHDB_URL?: string;
|
||||
VITE_COUCHDB_USERNAME?: string;
|
||||
VITE_COUCHDB_PASSWORD?: string;
|
||||
VITE_MAILGUN_API_KEY?: string;
|
||||
VITE_MAILGUN_DOMAIN?: string;
|
||||
VITE_MAILGUN_BASE_URL?: string;
|
||||
VITE_MAILGUN_FROM_NAME?: string;
|
||||
VITE_MAILGUN_FROM_EMAIL?: string;
|
||||
NODE_ENV?: string;
|
||||
COUCHDB_URL?: string;
|
||||
[key: string]: string | undefined;
|
||||
}
|
||||
import {
|
||||
getAppConfig,
|
||||
getDatabaseConfig,
|
||||
getAuthConfig,
|
||||
getEmailConfig,
|
||||
getOAuthConfig,
|
||||
getFeatureFlags,
|
||||
getLoggingConfig,
|
||||
getSecurityConfig,
|
||||
unifiedConfig,
|
||||
} from '../config/unified.config';
|
||||
|
||||
/**
|
||||
* Safely get environment variables from various sources
|
||||
* Works in both browser (Vite) and Node.js (Jest/server) environments
|
||||
* Get the current environment
|
||||
*/
|
||||
export function getEnv(): EnvConfig {
|
||||
let env: EnvConfig = {};
|
||||
|
||||
// Try to get from import.meta.env (Vite/browser)
|
||||
try {
|
||||
if (typeof globalThis !== 'undefined' && 'import' in globalThis) {
|
||||
const importMeta = (
|
||||
globalThis as { import?: { meta?: { env?: Record<string, string> } } }
|
||||
).import?.meta;
|
||||
if (importMeta?.env) {
|
||||
env = { ...env, ...importMeta.env };
|
||||
}
|
||||
}
|
||||
} catch (_e) {
|
||||
// Ignore errors accessing import.meta
|
||||
}
|
||||
|
||||
// Try to get from process.env (Node.js)
|
||||
try {
|
||||
if (typeof process !== 'undefined' && process.env) {
|
||||
env = { ...env, ...process.env };
|
||||
}
|
||||
} catch (_e) {
|
||||
// Ignore errors accessing process.env
|
||||
}
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a specific environment variable with optional fallback
|
||||
*/
|
||||
export function getEnvVar(key: string, fallback?: string): string | undefined {
|
||||
const env = getEnv();
|
||||
return env[key] || fallback;
|
||||
export function getEnvironment(): string {
|
||||
return getAppConfig().environment;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,35 +44,110 @@ export function isNode(): boolean {
|
||||
* Check if we're running in a test environment
|
||||
*/
|
||||
export function isTest(): boolean {
|
||||
const env = getEnv();
|
||||
return getAppConfig().environment === 'test';
|
||||
}
|
||||
|
||||
// Check for Jest environment
|
||||
if (
|
||||
typeof global !== 'undefined' &&
|
||||
'expect' in global &&
|
||||
'describe' in global
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for Node.js test environment variables
|
||||
if (typeof process !== 'undefined' && process.env) {
|
||||
if (process.env.NODE_ENV === 'test' || process.env.JEST_WORKER_ID) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check environment variables
|
||||
return env.NODE_ENV === 'test';
|
||||
/**
|
||||
* Check if we're running in development
|
||||
*/
|
||||
export function isDevelopment(): boolean {
|
||||
return getAppConfig().environment === 'development';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we're running in production
|
||||
*/
|
||||
export function isProduction(): boolean {
|
||||
const env = getEnv();
|
||||
return (
|
||||
env.NODE_ENV === 'production' ||
|
||||
(typeof process !== 'undefined' && process.env?.NODE_ENV === 'production')
|
||||
);
|
||||
return getAppConfig().environment === 'production';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we're running in staging
|
||||
*/
|
||||
export function isStaging(): boolean {
|
||||
return getAppConfig().environment === 'staging';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get application configuration
|
||||
*/
|
||||
export { getAppConfig };
|
||||
|
||||
/**
|
||||
* Get database configuration
|
||||
*/
|
||||
export { getDatabaseConfig };
|
||||
|
||||
/**
|
||||
* Get authentication configuration
|
||||
*/
|
||||
export { getAuthConfig };
|
||||
|
||||
/**
|
||||
* Get email configuration
|
||||
*/
|
||||
export { getEmailConfig };
|
||||
|
||||
/**
|
||||
* Get OAuth configuration
|
||||
*/
|
||||
export { getOAuthConfig };
|
||||
|
||||
/**
|
||||
* Get feature flags
|
||||
*/
|
||||
export { getFeatureFlags };
|
||||
|
||||
/**
|
||||
* Get logging configuration
|
||||
*/
|
||||
export { getLoggingConfig };
|
||||
|
||||
/**
|
||||
* Get security configuration
|
||||
*/
|
||||
export { getSecurityConfig };
|
||||
|
||||
/**
|
||||
* Get the full unified configuration
|
||||
* Use this sparingly - prefer the specific getters above
|
||||
*/
|
||||
export function getUnifiedConfig() {
|
||||
return unifiedConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy compatibility - get a specific environment variable
|
||||
* @deprecated Use the unified config getters instead
|
||||
*/
|
||||
export function getEnvVar(key: string, fallback?: string): string | undefined {
|
||||
console.warn(
|
||||
`getEnvVar('${key}') is deprecated. Use unified config instead.`
|
||||
);
|
||||
|
||||
// Try to map common environment variables to unified config
|
||||
switch (key) {
|
||||
case 'NODE_ENV':
|
||||
return getAppConfig().environment;
|
||||
case 'APP_NAME':
|
||||
case 'VITE_APP_NAME':
|
||||
return getAppConfig().name;
|
||||
case 'APP_BASE_URL':
|
||||
return getAppConfig().baseUrl;
|
||||
case 'VITE_COUCHDB_URL':
|
||||
case 'COUCHDB_URL':
|
||||
return getDatabaseConfig().url;
|
||||
case 'VITE_COUCHDB_USER':
|
||||
case 'COUCHDB_USER':
|
||||
return getDatabaseConfig().username;
|
||||
case 'VITE_COUCHDB_PASSWORD':
|
||||
case 'COUCHDB_PASSWORD':
|
||||
return getDatabaseConfig().password;
|
||||
case 'JWT_SECRET':
|
||||
return getAuthConfig().jwtSecret;
|
||||
case 'LOG_LEVEL':
|
||||
return getLoggingConfig().level;
|
||||
default:
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user