ConfigLoader API

Utility class for loading configuration using environment variables and config files

Table of contents

  1. Overview
  2. EnvironmentVariables Enum
  3. Generic Type Parameter
  4. Instance Methods
    1. load()
    2. applyEnvironmentVariables()
    3. autoApplyEnvironmentVariables()
  5. Static Helper Methods
    1. loadFromEnv()
    2. loadObjectFromEnv()
    3. loadNestedFromEnv()
    4. loadFromFile()
    5. findConfigFile()
    6. applyEnvironmentVariables()
    7. validateRequired()
  6. Plugin Architecture (v0.6.0+)
    1. ConfigFileLoaderRegistry
    2. Built-in Loaders
    3. Error Messages
  7. Usage Patterns
    1. Automatic Loading
    2. Manual Loading
    3. Adapter Configuration
  8. Type Definitions
    1. Config
  9. Design Principles
    1. Database-Agnostic
    2. Adapter-Friendly
    3. Type-Safe
  10. Examples
    1. Complete Production Setup
    2. Development with .env File
    3. Custom Config Directory

Overview

ConfigLoader is an extensible utility class that provides waterfall configuration loading with support for:

  • Environment variables (MSR_*)
  • Configuration files in multiple formats (.js, .json, .yaml, .yml, .toml, .xml)
  • Built-in defaults
  • Constructor overrides

New in v0.7.0: Generic class design with instance methods that can be extended by database adapters for custom environment variable handling

New in v0.6.0: YAML, TOML, and XML configuration file support with optional peer dependencies

Import:

import { ConfigLoader } from '@migration-script-runner/core';

EnvironmentVariables Enum

ConfigLoader uses the EnvironmentVariables type union internally for type-safe access to environment variable names. This type and the underlying enums (CoreEnvVars, ValidationEnvVars, etc.) are also exported for your use:

import { EnvironmentVariables as ENV } from '@migration-script-runner/core';

// Type-safe access to environment variables
const folder = process.env[ENV.MSR_FOLDER];
const dryRun = process.env[ENV.MSR_DRY_RUN];
const tableName = process.env[ENV.MSR_TABLE_NAME];

Benefits:

  • Type safety - Compile-time checking prevents typos
  • Auto-completion - IDEs can suggest all available variable names
  • Refactoring - Rename safely across your codebase
  • Documentation - Each enum value has JSDoc comments with defaults

See Also:


Generic Type Parameter

New in v0.7.0:

class ConfigLoader<C extends Config = Config> implements IConfigLoader<C>

The ConfigLoader is now generic, allowing database adapters to extend it with custom configuration types.

Example:

// Core usage (default)
const loader = new ConfigLoader();
const config = loader.load();

// Adapter usage with custom config
class PostgreSqlConfigLoader extends ConfigLoader<PostgreSqlConfig> {
    applyEnvironmentVariables(config: PostgreSqlConfig): void {
        super.applyEnvironmentVariables(config); // Apply MSR_* vars
        // Add POSTGRES_* env vars
        if (process.env.POSTGRES_HOST) {
            config.host = process.env.POSTGRES_HOST;
        }
    }
}

Instance Methods

New in v0.7.0: load() and applyEnvironmentVariables() are now instance methods that can be overridden by adapters extending ConfigLoader.

load()

Load configuration using waterfall approach.

Signature:

load(
    overrides?: Partial<C>,
    options?: ConfigLoaderOptions
): C

Parameters: | Name | Type | Default | Description | |——|——|———|————-| | overrides | Partial<C> | undefined | Optional configuration overrides (highest priority) | | options | ConfigLoaderOptions | undefined | Loader options (baseDir, configFile) |

ConfigLoaderOptions:

interface ConfigLoaderOptions {
    baseDir?: string;      // Where to search for default config files
    configFile?: string;   // Specific config file to use (bypasses search)
}

Returns: C - Fully loaded configuration object

Priority Order:

  1. Built-in defaults (lowest)
  2. Config file
  3. .env files (v0.7.0+) - Loaded from config.envFileSources
  4. Environment variables
  5. Constructor overrides (highest)

Examples:

// Basic usage - instance method
const loader = new ConfigLoader();
const config = loader.load();

// With overrides (highest priority)
const config = loader.load({
    folder: './migrations',
    dryRun: true
});

// Using options object
const config = loader.load({}, {
    baseDir: '/app',
    configFile: './config/production.config.json'
});

// Specify config file explicitly
const config = loader.load({}, {
    configFile: './custom-config.yaml'
});

// Use with MigrationScriptExecutor
const executor = new MigrationScriptExecutor({
    handler,
    config: loader.load()
});

// Or pass loader to executor
const executor = new MigrationScriptExecutor({
    handler,
    configLoader: loader
});

Error Handling:

  • Invalid config files are logged as warnings but don’t stop loading
  • Falls back to defaults + environment variables if file loading fails

applyEnvironmentVariables()

New in v0.7.0: Instance method that can be overridden by adapters.

Apply environment variables to configuration object.

Signature:

applyEnvironmentVariables(config: C): void

Parameters: | Name | Type | Description | |——|——|————-| | config | C | Configuration object to modify with env vars |

Base Implementation:

  • Applies all MSR_* environment variables
  • Uses type coercion based on default values
  • Called automatically during load()

Extending for Adapters:

class PostgreSqlConfigLoader extends ConfigLoader {
    applyEnvironmentVariables(config: Config): void {
        // Apply base MSR_* variables
        super.applyEnvironmentVariables(config);

        // Add custom POSTGRES_* variables
        if (process.env.POSTGRES_HOST) {
            (config as any).host = process.env.POSTGRES_HOST;
        }
        if (process.env.POSTGRES_PORT) {
            (config as any).port = parseInt(process.env.POSTGRES_PORT);
        }
    }
}

autoApplyEnvironmentVariables()

New in v0.7.0: Automatic environment variable parsing using reflection and type inference.

Automatically discover and apply environment variables for any config object based on its structure. This eliminates the need for manual env var handling in adapters.

Signature:

protected autoApplyEnvironmentVariables(
    config: C,
    prefix: string,
    overrides?: Map<string, (config: C, envVarName: string) => void>
): void

Parameters: | Name | Type | Description | |——|——|————-| | config | C | Configuration object to populate from environment variables | | prefix | string | Environment variable prefix (e.g., ‘MSR’, ‘POSTGRES’) | | overrides | Map<string, Function> | Optional custom parsers for specific properties |

Features:

  • Automatic Type Detection: Detects primitives, arrays, nested objects, and complex objects
  • Type Coercion: Automatically converts env var strings to correct types
  • Naming Convention: Converts camelCase properties to SNAKE_CASE env vars
  • Nested Support: Handles nested objects with dot-notation (PREFIX_PROP_NESTED)
  • .env File Support (v0.7.0+): Automatically loads from files specified in config.envFileSources
  • Override System: Allows custom parsing logic for special cases

How It Works:

  1. Reflection-based Discovery: Iterates through all config properties
  2. Name Conversion: poolSizePOSTGRES_POOL_SIZE
  3. Type Detection: Analyzes default value type
  4. Automatic Parsing:
    • Primitives (string/number/boolean): Direct parsing with type coercion
    • Arrays: JSON parsing (special handling for RegExp arrays)
    • Plain Objects: JSON + dot-notation with precedence
    • Complex Objects: Recursive dot-notation parsing

Examples:

// Adapter with automatic parsing
class PostgreSqlConfigLoader extends ConfigLoader<PostgreSqlConfig> {
    applyEnvironmentVariables(config: PostgreSqlConfig): void {
        // Apply base MSR_* vars
        super.applyEnvironmentVariables(config);

        // Automatically apply POSTGRES_* vars - no manual mapping needed!
        this.autoApplyEnvironmentVariables(config, 'POSTGRES');
    }
}

// Configuration class
class PostgreSqlConfig extends Config {
    host: string = 'localhost';
    port: number = 5432;
    ssl: boolean = false;
    poolSize: number = 10;
    poolConfig: { min: number; max: number } = {
        min: 2,
        max: 10
    };
}

// Environment variables (automatically mapped):
// POSTGRES_HOST=db.example.com → config.host = 'db.example.com'
// POSTGRES_PORT=3306 → config.port = 3306
// POSTGRES_SSL=true → config.ssl = true
// POSTGRES_POOL_SIZE=20 → config.poolSize = 20
// POSTGRES_POOL_CONFIG_MIN=5 → config.poolConfig.min = 5
// POSTGRES_POOL_CONFIG_MAX=50 → config.poolConfig.max = 50

With Custom Overrides:

class CustomConfigLoader extends ConfigLoader<CustomConfig> {
    applyEnvironmentVariables(config: CustomConfig): void {
        super.applyEnvironmentVariables(config);

        // Define custom parsing for specific properties
        const overrides = new Map();

        // Custom validation for port
        overrides.set('port', (cfg: CustomConfig, envVar: string) => {
            const value = process.env[envVar];
            if (value) {
                const port = parseInt(value, 10);
                if (port >= 1 && port <= 65535) {
                    cfg.port = port;
                } else {
                    console.warn(`Invalid port ${port}, using default`);
                }
            }
        });

        // Custom parsing for enum values
        overrides.set('logLevel', (cfg: CustomConfig, envVar: string) => {
            const level = process.env[envVar];
            if (level && ['error', 'warn', 'info', 'debug'].includes(level)) {
                cfg.logLevel = level as LogLevel;
            }
        });

        this.autoApplyEnvironmentVariables(config, 'CUSTOM', overrides);
    }
}

Benefits:

Zero Manual Mapping: New config properties automatically get env var support ✅ Type Safe: Uses TypeScript types for automatic coercion ✅ Consistent Naming: Automatic camelCaseSNAKE_CASE conversion ✅ Extensible: Override system for special cases ✅ Maintainable: No need to update applyEnvironmentVariables for new properties ✅ Adapter-Friendly: Works with any prefix (MSR_, POSTGRES_, MYSQL_, etc.)

Comparison:

// ❌ OLD WAY: Manual mapping (error-prone, requires updates)
class OldPostgresLoader extends ConfigLoader<PostgresConfig> {
    applyEnvironmentVariables(config: PostgresConfig): void {
        super.applyEnvironmentVariables(config);

        if (process.env.POSTGRES_HOST) {
            config.host = process.env.POSTGRES_HOST;
        }
        if (process.env.POSTGRES_PORT) {
            config.port = parseInt(process.env.POSTGRES_PORT);
        }
        if (process.env.POSTGRES_SSL) {
            config.ssl = process.env.POSTGRES_SSL === 'true';
        }
        // ... add 20 more properties manually ...
    }
}

// ✅ NEW WAY: Automatic mapping (maintainable, extensible)
class NewPostgresLoader extends ConfigLoader<PostgresConfig> {
    applyEnvironmentVariables(config: PostgresConfig): void {
        super.applyEnvironmentVariables(config);
        this.autoApplyEnvironmentVariables(config, 'POSTGRES');
    }
}

Static Helper Methods

These utility methods remain static and can be used by adapters for consistent type coercion:


loadFromEnv()

Load a single property from environment variable with automatic type coercion.

Signature:

static loadFromEnv<T extends string | number | boolean>(
    envVarName: string,
    defaultValue: T
): T

Parameters: | Name | Type | Description | |——|——|————-| | envVarName | string | Name of the environment variable | | defaultValue | T | Default value if env var not set (determines return type) |

Returns: T - Value from env var (coerced to type) or default value

Type Coercion:

  • boolean: 'true'/'1'/'yes'/'on'true, anything else → false
  • number: Parsed as float (returns NaN with warning if invalid)
  • string: Returned as-is

Examples:

// String value
const folder = ConfigLoader.loadFromEnv('MSR_FOLDER', './migrations');
// Returns: string from MSR_FOLDER or './migrations'

// Boolean value
const dryRun = ConfigLoader.loadFromEnv('MSR_DRY_RUN', false);
// MSR_DRY_RUN=true → true
// MSR_DRY_RUN=1 → true
// MSR_DRY_RUN=false → false
// MSR_DRY_RUN not set → false (default)

// Number value
const limit = ConfigLoader.loadFromEnv('MSR_DISPLAY_LIMIT', 0);
// MSR_DISPLAY_LIMIT=20 → 20
// MSR_DISPLAY_LIMIT not set → 0 (default)

// In adapters (custom env vars)
class PostgreSQLConfig extends Config {
    host: string = ConfigLoader.loadFromEnv('PG_HOST', 'localhost');
    port: number = ConfigLoader.loadFromEnv('PG_PORT', 5432);
    ssl: boolean = ConfigLoader.loadFromEnv('PG_SSL', false);
}

loadObjectFromEnv()

Load a complex object from a JSON environment variable.

Signature:

static loadObjectFromEnv<T extends object>(
    envVarName: string,
    defaultValue: T
): T

Parameters: | Name | Type | Description | |——|——|————-| | envVarName | string | Name of the environment variable containing JSON | | defaultValue | T | Default object if env var not set or invalid |

Returns: T - Parsed object merged with default value

Examples:

// Pool configuration from JSON
const poolConfig = ConfigLoader.loadObjectFromEnv('PG_POOL', {
    min: 2,
    max: 10,
    idleTimeoutMillis: 30000
});

// Environment:
// PG_POOL='{"max":20,"idleTimeoutMillis":60000}'
// Result: { min: 2, max: 20, idleTimeoutMillis: 60000 }

// Invalid JSON falls back to default
// PG_POOL='invalid json'
// Result: { min: 2, max: 10, idleTimeoutMillis: 30000 }

Error Handling:

  • Invalid JSON logs warning and returns default value
  • Missing env var returns default value
  • Parsed JSON is merged with default (not replaced)

loadNestedFromEnv()

Load a nested object from dot-notation environment variables (recommended).

Signature:

static loadNestedFromEnv<T extends Record<string, any>>(
    prefix: string,
    defaultValue: T
): T

Parameters: | Name | Type | Description | |——|——|————-| | prefix | string | Prefix for environment variables (e.g., ‘MSR_LOGGING’) | | defaultValue | T | Default object structure with types |

Returns: T - Object built from env vars or default value

Naming Convention:

  • camelCase properties → SNAKE_CASE env vars
  • maxFilesMAX_FILES
  • logSuccessfulLOG_SUCCESSFUL

Examples:

// Logging configuration
const logging = ConfigLoader.loadNestedFromEnv('MSR_LOGGING', {
    enabled: false,
    path: './logs',
    maxFiles: 10
});

// Environment:
// MSR_LOGGING_ENABLED=true
// MSR_LOGGING_PATH=./custom/logs
// MSR_LOGGING_MAX_FILES=20
// Result: { enabled: true, path: './custom/logs', maxFiles: 20 }

// Backup configuration
const backup = ConfigLoader.loadNestedFromEnv('MSR_BACKUP', {
    folder: './backups',
    timestamp: true,
    deleteBackup: true
});

// Environment:
// MSR_BACKUP_FOLDER=/var/backups
// MSR_BACKUP_TIMESTAMP=false
// Result: { folder: '/var/backups', timestamp: false, deleteBackup: true }

Type Coercion:

  • Automatic type coercion based on default value types
  • Boolean, number, and string types supported
  • Missing env vars keep default values

loadFromFile()

Load configuration from a file in any supported format.

Signature:

static loadFromFile<T = any>(filePath: string): T

Parameters: | Name | Type | Description | |——|——|————-| | filePath | string | Path to configuration file (absolute or relative) |

Returns: T - Configuration object from file

Throws: Error if file not found, format not supported, or parsing fails

Supported Formats:

Format Extensions Dependency Required
JavaScript .js Built-in ✅ Always available
JSON .json Built-in ✅ Always available
YAML .yaml, .yml js-yaml ⚠️ Optional peer dependency
TOML .toml @iarna/toml ⚠️ Optional peer dependency
XML .xml fast-xml-parser ⚠️ Optional peer dependency

Installing Optional Dependencies:

# For YAML support
npm install js-yaml

# For TOML support
npm install @iarna/toml

# For XML support
npm install fast-xml-parser

# Install all optional formats
npm install js-yaml @iarna/toml fast-xml-parser

Examples:

// Load from JSON file (always available)
const config = ConfigLoader.loadFromFile('./config/production.json');

// Load from JavaScript file (always available)
const config = ConfigLoader.loadFromFile('./config/production.js');

// Load from YAML file (requires js-yaml)
const config = ConfigLoader.loadFromFile('./config/production.yaml');

// Load from TOML file (requires @iarna/toml)
const config = ConfigLoader.loadFromFile('./config/production.toml');

// Load from XML file (requires fast-xml-parser)
const config = ConfigLoader.loadFromFile('./config/production.xml');

// With type parameter
const config = ConfigLoader.loadFromFile<Partial<Config>>('./msr.config.yaml');

// Handle ES module default export automatically
// File: module.exports = { default: { ... } }
// Returns: { ... } (unwraps default)

Error Handling:

  • Throws Error with detailed message if file not found
  • Throws Error if file format not supported (unknown extension)
  • Throws Error if optional dependency not installed (with installation instructions)
  • Throws Error if file cannot be parsed (with parsing details)

findConfigFile()

Find config file using search priority.

Signature:

static findConfigFile(baseDir?: string): string | undefined

Parameters: | Name | Type | Default | Description | |——|——|———|————-| | baseDir | string | process.cwd() | Base directory to search |

Returns: string | undefined - Path to config file if found, undefined otherwise

Search Priority:

  1. MSR_CONFIG_FILE environment variable (if set)
  2. ./msr.config.js (if exists)
  3. ./msr.config.json (if exists)
  4. ./msr.config.yaml (if exists)
  5. ./msr.config.yml (if exists)
  6. ./msr.config.toml (if exists)
  7. ./msr.config.xml (if exists)

Examples:

// Find config in current directory
const configPath = ConfigLoader.findConfigFile();
if (configPath) {
    console.log(`Using config: ${configPath}`);
}

// Find config in specific directory
const configPath = ConfigLoader.findConfigFile('/app');

// Check for custom config location
process.env.MSR_CONFIG_FILE = './config/custom.config.js';
const configPath = ConfigLoader.findConfigFile();
// Returns: '/absolute/path/to/config/custom.config.js' (if exists)

Warnings:

  • Logs warning if MSR_CONFIG_FILE points to non-existent file
  • Returns undefined silently if no config files found

applyEnvironmentVariables()

Apply MSR_* environment variables to config object.

Signature:

static applyEnvironmentVariables(config: Config): void

Parameters: | Name | Type | Description | |——|——|————-| | config | Config | Config object to apply env vars to (modified in-place) |

Returns: void (modifies config in-place)

Environment Variables Applied:

  • Simple properties: MSR_FOLDER, MSR_TABLE_NAME, etc.
  • Boolean flags: MSR_DRY_RUN, MSR_RECURSIVE, etc.
  • Nested objects: MSR_LOGGING_*, MSR_BACKUP_*
  • File patterns: MSR_FILE_PATTERNS (JSON array)

Examples:

const config = new Config();
ConfigLoader.applyEnvironmentVariables(config);

// Environment:
// MSR_FOLDER=./migrations
// MSR_DRY_RUN=true
// MSR_LOGGING_ENABLED=true
// Result: config.folder = './migrations', config.dryRun = true, etc.

Type Coercion:

  • Uses type coercion based on existing config property types
  • See loadFromEnv() for coercion rules

validateRequired()

Validate that required environment variables are set.

Signature:

static validateRequired(requiredVars: string[]): void

Parameters: | Name | Type | Description | |——|——|————-| | requiredVars | string[] | Array of required environment variable names |

Returns: void

Throws: Error with list of missing variables if any are not set

Examples:

// Validate required variables
ConfigLoader.validateRequired([
    'DATABASE_URL',
    'MSR_FOLDER',
    'MSR_TABLE_NAME'
]);

// If missing, throws error like:
// Error: Missing required environment variables:
//   - DATABASE_URL
//   - MSR_FOLDER
// Please set these variables before running.

// In adapter, ensure critical env vars are set
class PostgreSQLAdapter {
    constructor() {
        ConfigLoader.validateRequired([
            'PG_HOST',
            'PG_DATABASE',
            'PG_USER',
            'PG_PASSWORD'
        ]);
    }
}

Use Cases:

  • Validate deployment configuration
  • Ensure required secrets are set
  • Fail-fast with clear error messages
  • Database adapter initialization

Plugin Architecture (v0.6.0+)

ConfigLoader uses a plugin-based architecture for loading different file formats:

ConfigFileLoaderRegistry

Central registry managing all config file loaders.

import { ConfigFileLoaderRegistry } from '@migration-script-runner/core';

// Check supported extensions
const extensions = ConfigFileLoaderRegistry.getSupportedExtensions();
// Returns: ['.js', '.json', '.yaml', '.yml', '.toml', '.xml']

// Check if format is supported
const hasYaml = ConfigFileLoaderRegistry.hasLoaderForExtension('.yaml');
// Returns: true (if js-yaml is installed)

// Get loader for specific file
const loader = ConfigFileLoaderRegistry.getLoader('config.yaml');
if (loader) {
    const config = loader.load('config.yaml');
}

Built-in Loaders

Loader Extensions Always Available
JsJsonLoader .js, .json ✅ Yes
YamlLoader .yaml, .yml ⚠️ Requires js-yaml
TomlLoader .toml ⚠️ Requires @iarna/toml
XmlLoader .xml ⚠️ Requires fast-xml-parser

Error Messages

Improved error handling with actionable messages:

// If js-yaml not installed
Error: Cannot load YAML file config.yaml: js-yaml is not installed.
Install it with: npm install js-yaml
Original error: Cannot find module 'js-yaml'

// If format not supported
Error: No loader registered for file type '.ini'.
Supported extensions: .js, .json, .yaml, .yml, .toml, .xml

// If file cannot be parsed
Error: Failed to load configuration from config.yaml:
Unexpected token at line 5, column 3

Usage Patterns

Automatic Loading

Recommended: Let MSR load configuration automatically:

import { MigrationScriptExecutor } from '@migration-script-runner/core';

// Automatically loads: defaults → file → env vars
const executor = new MigrationScriptExecutor({ handler });
await executor.up();

Manual Loading

Advanced: Load configuration explicitly:

import { ConfigLoader, MigrationScriptExecutor } from '@migration-script-runner/core';

// Load with waterfall
const config = ConfigLoader.load();

// Or load with overrides
const config = ConfigLoader.load({
    dryRun: true,
    strictValidation: true
});

const executor = new MigrationScriptExecutor({ handler , config });
await executor.migrate();

Adapter Configuration

For Database Adapters: Load adapter-specific environment variables:

import { ConfigLoader, Config } from '@migration-script-runner/core';

export class PostgreSQLConfig extends Config {
    // Adapter-specific properties
    host: string = ConfigLoader.loadFromEnv('PG_HOST', 'localhost');
    port: number = ConfigLoader.loadFromEnv('PG_PORT', 5432);
    database: string = ConfigLoader.loadFromEnv('PG_DATABASE', 'postgres');
    user: string = ConfigLoader.loadFromEnv('PG_USER', 'postgres');
    password: string = ConfigLoader.loadFromEnv('PG_PASSWORD', '');
    ssl: boolean = ConfigLoader.loadFromEnv('PG_SSL', false);

    // Pool configuration
    pool = ConfigLoader.loadNestedFromEnv('PG_POOL', {
        min: 2,
        max: 10,
        idleTimeoutMillis: 30000
    });

    constructor() {
        super();

        // Validate required variables
        ConfigLoader.validateRequired([
            'PG_HOST',
            'PG_DATABASE',
            'PG_USER',
            'PG_PASSWORD'
        ]);
    }
}

Type Definitions

Config

class Config {
    // Migration settings
    folder: string;
    tableName: string;
    beforeMigrateName: string;
    displayLimit: number;
    recursive: boolean;
    filePatterns: RegExp[];

    // Validation settings
    validateBeforeRun: boolean;
    strictValidation: boolean;
    downMethodPolicy: DownMethodPolicy;
    customValidators: IValidator[];

    // Rollback settings
    rollbackStrategy: RollbackStrategy;

    // Logging configuration
    logging: IExecutionSummaryConfig;

    // Backup configuration
    backup?: BackupConfig;

    // Dry run mode
    dryRun: boolean;
}

Design Principles

Database-Agnostic

ConfigLoader is database-agnostic and does not parse database-specific connection strings:

// ❌ NOT in ConfigLoader
ConfigLoader.parseDatabaseUrl('postgres://...');

// ✅ Use in database adapters
class PostgreSQLAdapter {
    parseConnectionString(url: string) {
        // Database-specific parsing
    }
}

Adapter-Friendly

Helper methods designed for database adapters to use:

class MyDatabaseConfig extends Config {
    // Use ConfigLoader helpers for your own env vars
    dbHost = ConfigLoader.loadFromEnv('DB_HOST', 'localhost');
    dbPort = ConfigLoader.loadFromEnv('DB_PORT', 5432);

    connection = ConfigLoader.loadNestedFromEnv('DB_CONNECTION', {
        timeout: 5000,
        retries: 3
    });
}

Type-Safe

Automatic type coercion based on default values:

// Type inferred from default value
const enabled = ConfigLoader.loadFromEnv('ENABLED', false);
// Type: boolean

const port = ConfigLoader.loadFromEnv('PORT', 5432);
// Type: number

const host = ConfigLoader.loadFromEnv('HOST', 'localhost');
// Type: string

Examples

Complete Production Setup

import { ConfigLoader, MigrationScriptExecutor } from '@migration-script-runner/core';
import { PostgreSQLHandler } from '@migration-script-runner/postgresql';

// Validate required environment variables
ConfigLoader.validateRequired([
    'DATABASE_URL',
    'MSR_FOLDER'
]);

// Load configuration
const config = ConfigLoader.load({
    // Override for this specific run
    strictValidation: process.env.CI === 'true'
});

// Create executor
const handler = new PostgreSQLHandler(process.env.DATABASE_URL);
const executor = new MigrationScriptExecutor({ handler , config });

// Run migrations
await executor.migrate();

Development with .env File

Auto-loading in v0.7.0+: MSR automatically loads .env files without requiring dotenv package. By default, it looks for .env.local, .env, and env files in priority order.

# .env.local (for local development, add to .gitignore)
MSR_FOLDER=./migrations
MSR_DRY_RUN=false
MSR_LOGGING_ENABLED=true
MSR_LOGGING_PATH=./logs
MSR_BACKUP_DELETE_BACKUP=true
import { MigrationScriptExecutor } from '@migration-script-runner/core';

// v0.7.0+: Automatically loads from .env files
const executor = new MigrationScriptExecutor({ handler });
await executor.up();

// Or configure which .env files to load
const config = new Config();
config.envFileSources = ['.env.local', '.env']; // Default
// config.envFileSources = ['.env.production', '.env']; // Production
// config.envFileSources = []; // Disable .env loading

const executor = new MigrationScriptExecutor({ handler, config });
await executor.up();

Custom Config Directory

import { ConfigLoader } from '@migration-script-runner/core';

// Load from custom directory
const config = ConfigLoader.load({}, '/app/config');

// Or use MSR_CONFIG_FILE
process.env.MSR_CONFIG_FILE = './config/production.config.js';
const config = ConfigLoader.load();