Config Manager
Type-safe environment variable handling with validation for AWS Lambda functions and Node.js applications.
Overview
The Config Manager module provides validated environment variable getters and converters with comprehensive type safety:
- Environment Variable Getters: Type-safe retrieval of environment variables with validation
- Environment Variable Converters: Validated conversion of values to environment variable strings
- Zod Schema Validation: Built-in validation for strings, numbers, and booleans
- Error Handling: Clear error messages for invalid environment variables
Environment Variable Getters
Type-safe functions to retrieve and validate environment variables at runtime.
String Variables
import { envVar } from '@leighton-digital/lambda-toolkit/config-manager';
// Get a validated string environment variable
const apiUrl = envVar.getString('API_URL');
// Returns: string (validated to be 2-100 characters)
const databaseName = envVar.getString('DATABASE_NAME');
// Throws error if DATABASE_NAME is undefined, empty, or invalid length
Boolean Variables
import { envVar } from '@leighton-digital/lambda-toolkit/config-manager';
// Get a validated boolean environment variable
const enableDebug = envVar.getBoolean('ENABLE_DEBUG');
// Returns: boolean (from "true" or "false" string)
const enableCache = envVar.getBoolean('ENABLE_CACHE');
// Throws error if ENABLE_CACHE is not "true" or "false" (case-insensitive)
Number Variables
import { envVar } from '@leighton-digital/lambda-toolkit/config-manager';
// Get a validated number environment variable
const port = envVar.getNumber('PORT');
// Returns: number (parsed from string)
const maxRetries = envVar.getNumber('MAX_RETRIES');
// Throws error if MAX_RETRIES is not a valid number or contains only whitespace
Environment Variable Converters
Validated conversion functions to prepare values for setting as environment variables.
String Conversion
import { envVar } from '@leighton-digital/lambda-toolkit/config-manager';
// Validate and prepare string for environment variable
const validatedString = envVar.fromString({
  variableName: 'API_ENDPOINT',
  value: 'https://api.example.com'
});
// Returns: 'https://api.example.com' (validated)
// Set environment variable
process.env.API_ENDPOINT = validatedString;
Boolean Conversion
import { envVar } from '@leighton-digital/lambda-toolkit/config-manager';
// Convert boolean to environment variable string
const debugString = envVar.fromBoolean({
  variableName: 'DEBUG_MODE',
  value: true
});
// Returns: 'true'
const cacheString = envVar.fromBoolean({
  variableName: 'ENABLE_CACHE',
  value: false
});
// Returns: 'false'
// Set environment variables
process.env.DEBUG_MODE = debugString;
process.env.ENABLE_CACHE = cacheString;
Number Conversion
import { envVar } from '@leighton-digital/lambda-toolkit/config-manager';
// Convert number to environment variable string
const portString = envVar.fromNumber({
  variableName: 'SERVER_PORT',
  value: 3000
});
// Returns: '3000'
const timeoutString = envVar.fromNumber({
  variableName: 'TIMEOUT_MS',
  value: 5000
});
// Returns: '5000'
// Set environment variables
process.env.SERVER_PORT = portString;
process.env.TIMEOUT_MS = timeoutString;
Lambda Integration Examples
Configuration Validation at Startup
import { envVar } from '@leighton-digital/lambda-toolkit/config-manager';
import { withHttpHandler } from '@leighton-digital/lambda-toolkit/lambda';
// Validate configuration at module load time
const config = {
  apiUrl: envVar.getString('API_URL'),
  enableDebug: envVar.getBoolean('ENABLE_DEBUG'),
  maxRetries: envVar.getNumber('MAX_RETRIES'),
  timeout: envVar.getNumber('TIMEOUT_MS'),
};
export const handler = withHttpHandler(async ({ event, metrics }) => {
  // Configuration is already validated and typed
  const response = await fetch(config.apiUrl, {
    timeout: config.timeout,
  });
  if (config.enableDebug) {
    metrics.addMetric('DebugRequest', 1);
  }
  return {
    statusCode: 200,
    body: { message: 'Success' },
  };
});
Dynamic Configuration
import { envVar } from '@leighton-digital/lambda-toolkit/config-manager';
export const handler = withHttpHandler(async ({ event }) => {
  // Get stage-specific configuration
  const stage = envVar.getString('STAGE');
  const tableName = envVar.getString(`TABLE_NAME_${stage.toUpperCase()}`);
  // Use stage-specific settings
  const enableAdvancedFeatures = envVar.getBoolean(`ENABLE_ADVANCED_${stage.toUpperCase()}`);
  return {
    statusCode: 200,
    body: {
      stage,
      tableName,
      advancedFeaturesEnabled: enableAdvancedFeatures,
    },
  };
});
Environment Variable Preparation for CDK
import { envVar } from '@leighton-digital/lambda-toolkit/config-manager';
import { Function } from 'aws-cdk-lib/aws-lambda';
export class MyLambdaStack extends Stack {
  constructor(scope: Construct, id: string, props: StackProps) {
    super(scope, id, props);
    // Prepare environment variables with validation
    const environment = {
      API_URL: envVar.fromString({
        variableName: 'API_URL',
        value: 'https://api.production.com'
      }),
      ENABLE_CACHE: envVar.fromBoolean({
        variableName: 'ENABLE_CACHE',
        value: true
      }),
      MAX_CONNECTIONS: envVar.fromNumber({
        variableName: 'MAX_CONNECTIONS',
        value: 100
      }),
    };
    new Function(this, 'MyFunction', {
      // ... other props
      environment,
    });
  }
}
Validation Rules
String Validation
- Minimum length: 2 characters
- Maximum length: 100 characters
- Throws error: If undefined, empty, or outside length bounds
Boolean Validation
- Valid values: "true" or "false" (case-insensitive)
- Conversion: Transforms to actual boolean type
- Throws error: If not exactly "true" or "false"
Number Validation
- Format: Must be a valid numeric string
- Whitespace: Cannot be only whitespace
- Maximum length: 10 characters
- Conversion: Transforms to actual number type
- Throws error: If not a valid number or NaN
Error Handling
All validation errors provide clear, actionable error messages:
import { envVar } from '@leighton-digital/lambda-toolkit/config-manager';
try {
  const invalidString = envVar.getString('MISSING_VAR');
} catch (error) {
  console.error(error.message);
  // "Invalid environment variable: MISSING_VAR: [ZodError details]"
}
try {
  const invalidBoolean = envVar.getBoolean('INVALID_BOOL');
} catch (error) {
  console.error(error.message);
  // "Invalid environment variable: INVALID_BOOL: [ZodError details]"
}
try {
  const invalidNumber = envVar.getNumber('INVALID_NUM');
} catch (error) {
  console.error(error.message);
  // "Invalid environment variable: INVALID_NUM: [ZodError details]"
}
Advanced Examples
Configuration Factory
import { envVar } from '@leighton-digital/lambda-toolkit/config-manager';
interface AppConfig {
  database: {
    host: string;
    port: number;
    ssl: boolean;
  };
  api: {
    baseUrl: string;
    timeout: number;
    retries: number;
  };
  features: {
    enableCache: boolean;
    enableMetrics: boolean;
  };
}
function loadConfig(): AppConfig {
  return {
    database: {
      host: envVar.getString('DB_HOST'),
      port: envVar.getNumber('DB_PORT'),
      ssl: envVar.getBoolean('DB_SSL'),
    },
    api: {
      baseUrl: envVar.getString('API_BASE_URL'),
      timeout: envVar.getNumber('API_TIMEOUT_MS'),
      retries: envVar.getNumber('API_MAX_RETRIES'),
    },
    features: {
      enableCache: envVar.getBoolean('ENABLE_CACHE'),
      enableMetrics: envVar.getBoolean('ENABLE_METRICS'),
    },
  };
}
// Load and validate all configuration at startup
const config = loadConfig();
Testing with Environment Variables
import { envVar } from '@leighton-digital/lambda-toolkit/config-manager';
describe('Environment Configuration', () => {
  const originalEnv = process.env;
  beforeEach(() => {
    process.env = { ...originalEnv };
  });
  afterAll(() => {
    process.env = originalEnv;
  });
  it('should load valid configuration', () => {
    // Set test environment variables
    process.env.API_URL = envVar.fromString({
      variableName: 'API_URL',
      value: 'https://test-api.example.com'
    });
    process.env.ENABLE_DEBUG = envVar.fromBoolean({
      variableName: 'ENABLE_DEBUG',
      value: true
    });
    process.env.PORT = envVar.fromNumber({
      variableName: 'PORT',
      value: 3000
    });
    // Test getters
    expect(envVar.getString('API_URL'))
      .toBe('https://test-api.example.com');
    expect(envVar.getBoolean('ENABLE_DEBUG'))
      .toBe(true);
    expect(envVar.getNumber('PORT'))
      .toBe(3000);
  });
});
Environment-Specific Configuration
import { envVar } from '@leighton-digital/lambda-toolkit/config-manager';
function getEnvironmentConfig(stage: string) {
  const configs = {
    development: {
      apiUrl: 'https://dev-api.example.com',
      enableDebug: true,
      maxConnections: 10,
    },
    staging: {
      apiUrl: 'https://staging-api.example.com',
      enableDebug: false,
      maxConnections: 50,
    },
    production: {
      apiUrl: 'https://api.example.com',
      enableDebug: false,
      maxConnections: 100,
    },
  };
  const stageConfig = configs[stage] || configs.development;
  return {
    API_URL: envVar.fromString({
      variableName: 'API_URL',
      value: stageConfig.apiUrl
    }),
    ENABLE_DEBUG: envVar.fromBoolean({
      variableName: 'ENABLE_DEBUG',
      value: stageConfig.enableDebug
    }),
    MAX_CONNECTIONS: envVar.fromNumber({
      variableName: 'MAX_CONNECTIONS',
      value: stageConfig.maxConnections
    }),
  };
}
Best Practices
- Early Validation: Load and validate environment variables at module initialization to fail fast
- Type Safety: Use the typed getters to ensure runtime type safety
- Error Handling: Wrap configuration loading in try-catch blocks for graceful error handling
- Testing: Use converters to prepare test environment variables with proper validation
- Documentation: Document required environment variables and their validation rules
- Defaults: Consider using fallback patterns for optional configuration values
- Security: Never log environment variable values, especially sensitive data like API keys
Dependencies
Required
- zod- Schema validation library for runtime type checking
Peer Dependencies
None - this module works standalone with any Node.js environment.
Environment Variable Naming
Follow these conventions for consistency:
- Use UPPER_SNAKE_CASEfor environment variable names
- Use descriptive names that indicate purpose (e.g., DATABASE_URL,ENABLE_FEATURE_X)
- Include units in names when relevant (e.g., TIMEOUT_MS,MAX_SIZE_MB)
- Use prefixes for grouped variables (e.g., DB_HOST,DB_PORT,DB_NAME)