@spfn/core
Version:
SPFN Framework Core - File-based routing, transactions, repository pattern
509 lines (504 loc) • 14 kB
TypeScript
/**
* Environment Variable Management - Configuration Types
*
* Type definitions for centralized environment variable loading
*/
/**
* Options for loading environment variables
*/
interface LoadEnvironmentOptions {
/**
* Base directory for .env files
* @default process.cwd()
*/
basePath?: string;
/**
* Additional custom paths to load
* Loaded after standard files
* @default []
*/
customPaths?: string[];
/**
* Enable debug logging
* @default false
*/
debug?: boolean;
/**
* Override NODE_ENV for file selection
* @default process.env.NODE_ENV
*/
nodeEnv?: string;
/**
* Required environment variables
* Throws error if any are missing after loading
* @default []
*/
required?: string[];
/**
* Skip loading if environment already loaded
* Set to false to force reload (useful for testing)
* @default true
*/
useCache?: boolean;
}
/**
* Result of environment loading operation
*/
interface LoadResult {
/**
* Whether loading was successful overall
*/
success: boolean;
/**
* Files that were successfully loaded
*/
loaded: string[];
/**
* Files that failed to load (with reasons)
*/
failed: Array<{
path: string;
reason: string;
}>;
/**
* Environment variables that were parsed from files
*/
parsed: Record<string, string>;
/**
* Error messages if any critical errors occurred
*/
errors?: string[];
/**
* Warning messages for non-critical issues
*/
warnings: string[];
}
/**
* Options for getting environment variables
*/
interface GetEnvOptions {
/**
* Throw error if variable not found
* @default false
*/
required?: boolean;
/**
* Default value if variable not found
* Only used if required is false
*/
default?: string;
/**
* Custom validation function
* Return true if valid, false if invalid
*/
validator?: (value: string) => boolean;
/**
* Custom error message for validation failure
*/
validationError?: string;
}
/**
* Standard environment file names in priority order
*
* Next.js-style loading behavior:
* - development: .env → .env.development → .env.local → .env.development.local
* - production: .env → .env.production → .env.local → .env.production.local
* - test: .env → .env.test → (skip .env.local) → .env.test.local
*
* Note: .env.local is excluded in test environment for proper test isolation
*/
declare const ENV_FILE_PRIORITY: readonly [".env", ".env.{NODE_ENV}", ".env.local", ".env.{NODE_ENV}.local"];
/**
* Environment files that should only be loaded in test environment
*/
declare const TEST_ONLY_FILES: readonly [".env.test", ".env.test.local"];
/**
* Environment Variable Management - Core Loader
*
* Centralized singleton environment variable loader with dotenv priority support
*/
/**
* Load environment variables from .env files with Next.js-style priority
*
* Loading behavior by environment:
* - (no NODE_ENV): .env → .env.local
* - development: .env → .env.development → .env.local → .env.development.local
* - production: .env → .env.production → .env.local → .env.production.local
* - test: .env → .env.test → (skip .env.local) → .env.test.local
* - local: .env → .env.local → .env.local.local (duplicate .env.local prevented)
* - staging/qa/etc: .env → .env.{NODE_ENV} → .env.local → .env.{NODE_ENV}.local
*
* Notes:
* - .env.local is excluded in test environment for proper test isolation
* - Any custom NODE_ENV value is supported (staging, qa, uat, preview, etc.)
* - If NODE_ENV is not set, .env and .env.local are loaded
*
* @param options - Loading options
* @returns Load result with success status and loaded variables
*
* @example
* ```typescript
* // Simple usage (no NODE_ENV set)
* const result = loadEnvironment();
*
* // With NODE_ENV=local
* process.env.NODE_ENV = 'local';
* const result = loadEnvironment({
* debug: true,
* required: ['DATABASE_URL'],
* });
*
* // With custom environment
* process.env.NODE_ENV = 'staging';
* const result = loadEnvironment();
* ```
*/
declare function loadEnvironment(options?: LoadEnvironmentOptions): LoadResult;
/**
* Get an environment variable with optional validation
*
* @param key - Environment variable name
* @param options - Get options (default, required, validator)
* @returns Variable value or undefined
* @throws Error if required and not found, or validation fails
*
* @example
* ```typescript
* // Simple get
* const dbUrl = getEnvVar('DATABASE_URL');
*
* // With default
* const port = getEnvVar('PORT', { default: '3000' });
*
* // Required
* const apiKey = getEnvVar('API_KEY', { required: true });
*
* // With validation
* const url = getEnvVar('API_URL', {
* validator: (val) => val.startsWith('https://'),
* validationError: 'API_URL must use HTTPS',
* });
* ```
*/
declare function getEnvVar(key: string, options?: GetEnvOptions): string | undefined;
/**
* Get a required environment variable
*
* @param key - Environment variable name
* @returns Variable value
* @throws Error if not found
*
* @example
* ```typescript
* const dbUrl = requireEnvVar('DATABASE_URL');
* ```
*/
declare function requireEnvVar(key: string): string;
/**
* Check if an environment variable exists
*
* @param key - Environment variable name
* @returns True if variable exists and is non-empty
*
* @example
* ```typescript
* if (hasEnvVar('REDIS_URL')) {
* // Use Redis
* }
* ```
*/
declare function hasEnvVar(key: string): boolean;
/**
* Get multiple environment variables at once
*
* @param keys - Array of environment variable names
* @returns Object mapping keys to values (undefined if not found)
*
* @example
* ```typescript
* const { DATABASE_URL, REDIS_URL } = getEnvVars([
* 'DATABASE_URL',
* 'REDIS_URL',
* ]);
* ```
*/
declare function getEnvVars(keys: string[]): Record<string, string | undefined>;
/**
* Check if environment has been loaded
*
* @returns True if loadEnvironment has been called successfully
*
* @example
* ```typescript
* if (!isEnvironmentLoaded()) {
* loadEnvironment();
* }
* ```
*/
declare function isEnvironmentLoaded(): boolean;
/**
* Reset environment loading state
* FOR TESTING ONLY - DO NOT USE IN PRODUCTION
*
* @example
* ```typescript
* // In test cleanup
* afterEach(() => {
* resetEnvironment();
* });
* ```
*/
declare function resetEnvironment(): void;
/**
* Environment Variable Management - Validators
*
* Common validation functions for environment variables
*/
/**
* Validate that a value is a valid URL
*
* @param value - Value to validate
* @param options - Validation options
* @returns True if valid URL, false otherwise
*
* @example
* ```typescript
* const apiUrl = getEnvVar('API_URL', {
* validator: validateUrl,
* });
* ```
*/
declare function validateUrl(value: string, options?: {
protocol?: 'http' | 'https' | 'any';
}): boolean;
/**
* Create a URL validator with specific protocol requirement
*
* @param protocol - Required protocol ('http', 'https', or 'any')
* @returns Validator function
*
* @example
* ```typescript
* const apiUrl = getEnvVar('API_URL', {
* validator: createUrlValidator('https'),
* validationError: 'API_URL must use HTTPS',
* });
* ```
*/
declare function createUrlValidator(protocol?: 'http' | 'https' | 'any'): (value: string) => boolean;
/**
* Validate that a value is a valid number
*
* @param value - Value to validate
* @param options - Validation options
* @returns True if valid number, false otherwise
*
* @example
* ```typescript
* const port = getEnvVar('PORT', {
* validator: (val) => validateNumber(val, { min: 1, max: 65535 }),
* });
* ```
*/
declare function validateNumber(value: string, options?: {
min?: number;
max?: number;
integer?: boolean;
}): boolean;
/**
* Create a number validator with specific constraints
*
* @param options - Validation constraints
* @returns Validator function
*
* @example
* ```typescript
* const port = getEnvVar('PORT', {
* validator: createNumberValidator({ min: 1, max: 65535, integer: true }),
* validationError: 'PORT must be an integer between 1 and 65535',
* });
* ```
*/
declare function createNumberValidator(options?: {
min?: number;
max?: number;
integer?: boolean;
}): (value: string) => boolean;
/**
* Validate that a value is a valid boolean string
*
* @param value - Value to validate
* @returns True if valid boolean string, false otherwise
*
* @example
* ```typescript
* const debugMode = getEnvVar('DEBUG', {
* validator: validateBoolean,
* });
* ```
*/
declare function validateBoolean(value: string): boolean;
/**
* Parse a boolean environment variable
*
* @param value - Value to parse
* @returns Boolean value
*
* @example
* ```typescript
* const debug = parseBoolean(getEnvVar('DEBUG', { default: 'false' })!);
* ```
*/
declare function parseBoolean(value: string): boolean;
/**
* Validate that a value is one of allowed options
*
* @param value - Value to validate
* @param allowed - Array of allowed values
* @param caseInsensitive - Whether to perform case-insensitive comparison
* @returns True if value is in allowed list, false otherwise
*
* @example
* ```typescript
* const env = getEnvVar('NODE_ENV', {
* validator: (val) => validateEnum(val, ['development', 'production', 'test']),
* });
* ```
*/
declare function validateEnum(value: string, allowed: string[], caseInsensitive?: boolean): boolean;
/**
* Create an enum validator with specific allowed values
*
* @param allowed - Array of allowed values
* @param caseInsensitive - Whether to perform case-insensitive comparison
* @returns Validator function
*
* @example
* ```typescript
* const logLevel = getEnvVar('LOG_LEVEL', {
* validator: createEnumValidator(['debug', 'info', 'warn', 'error']),
* validationError: 'LOG_LEVEL must be one of: debug, info, warn, error',
* });
* ```
*/
declare function createEnumValidator(allowed: string[], caseInsensitive?: boolean): (value: string) => boolean;
/**
* Validate that a value matches a regular expression
*
* @param value - Value to validate
* @param pattern - Regular expression pattern
* @returns True if value matches pattern, false otherwise
*
* @example
* ```typescript
* const apiKey = getEnvVar('API_KEY', {
* validator: (val) => validatePattern(val, /^[A-Za-z0-9_-]{32}$/),
* });
* ```
*/
declare function validatePattern(value: string, pattern: RegExp): boolean;
/**
* Create a pattern validator with specific regex
*
* @param pattern - Regular expression pattern
* @returns Validator function
*
* @example
* ```typescript
* const apiKey = getEnvVar('API_KEY', {
* validator: createPatternValidator(/^[A-Za-z0-9_-]{32}$/),
* validationError: 'API_KEY must be 32 alphanumeric characters',
* });
* ```
*/
declare function createPatternValidator(pattern: RegExp): (value: string) => boolean;
/**
* Validate that a value is not empty
*
* @param value - Value to validate
* @returns True if not empty, false otherwise
*
* @example
* ```typescript
* const name = getEnvVar('APP_NAME', {
* validator: validateNotEmpty,
* });
* ```
*/
declare function validateNotEmpty(value: string): boolean;
/**
* Validate that a value has minimum length
*
* @param value - Value to validate
* @param minLength - Minimum required length
* @returns True if meets minimum length, false otherwise
*
* @example
* ```typescript
* const password = getEnvVar('DB_PASSWORD', {
* validator: (val) => validateMinLength(val, 8),
* });
* ```
*/
declare function validateMinLength(value: string, minLength: number): boolean;
/**
* Create a minimum length validator
*
* @param minLength - Minimum required length
* @returns Validator function
*
* @example
* ```typescript
* const password = getEnvVar('DB_PASSWORD', {
* validator: createMinLengthValidator(8),
* validationError: 'DB_PASSWORD must be at least 8 characters',
* });
* ```
*/
declare function createMinLengthValidator(minLength: number): (value: string) => boolean;
/**
* Combine multiple validators with AND logic
*
* @param validators - Array of validator functions
* @returns Combined validator function
*
* @example
* ```typescript
* const port = getEnvVar('PORT', {
* validator: combineValidators([
* validateNotEmpty,
* createNumberValidator({ min: 1, max: 65535, integer: true }),
* ]),
* });
* ```
*/
declare function combineValidators(validators: Array<(value: string) => boolean>): (value: string) => boolean;
/**
* Validate PostgreSQL connection string
*
* @param value - Value to validate
* @returns True if valid PostgreSQL URL, false otherwise
*
* @example
* ```typescript
* const dbUrl = getEnvVar('DATABASE_URL', {
* validator: validatePostgresUrl,
* });
* ```
*/
declare function validatePostgresUrl(value: string): boolean;
/**
* Validate Redis connection string
*
* @param value - Value to validate
* @returns True if valid Redis URL, false otherwise
*
* @example
* ```typescript
* const redisUrl = getEnvVar('REDIS_URL', {
* validator: validateRedisUrl,
* });
* ```
*/
declare function validateRedisUrl(value: string): boolean;
export { ENV_FILE_PRIORITY, type GetEnvOptions, type LoadEnvironmentOptions, type LoadResult, TEST_ONLY_FILES, combineValidators, createEnumValidator, createMinLengthValidator, createNumberValidator, createPatternValidator, createUrlValidator, getEnvVar, getEnvVars, hasEnvVar, isEnvironmentLoaded, loadEnvironment, parseBoolean, requireEnvVar, resetEnvironment, validateBoolean, validateEnum, validateMinLength, validateNotEmpty, validateNumber, validatePattern, validatePostgresUrl, validateRedisUrl, validateUrl };