Skip to content

Releases: migration-script-runner/msr-core

v0.8.4 - TConfig Generic Support in CLI

Choose a tag to compare

@vlavrynovych vlavrynovych released this 20 Dec 16:06

🎯 TConfig Generic Support in CLI

Minor release adding TConfig generic parameter to createCLI for type-safe custom configuration types.


✨ New Feature

#152: TConfig Generic Parameter in createCLI

Added third generic parameter TConfig extends Config = Config to CLIOptions and createCLI for full type safety with custom configuration types.

Problem Solved:
Firebase adapter team identified that createCLI lacked custom config type support. The extendFlags and createExecutor callbacks received base Config type, forcing type casts to access custom properties like databaseUrl and applicationCredentials.

Solution:

// Before v0.8.4 (required casting)
const program = createCLI({
  extendFlags: (config, flags) => {
    (config as FirebaseConfig).databaseUrl = flags.databaseUrl; // ❌
  }
});

// After v0.8.4 (fully typed)
const program = createCLI<IFirebaseDB, FirebaseAdapter, FirebaseConfig>({
  extendFlags: (config, flags) => {
    config.databaseUrl = flags.databaseUrl; // βœ… Full type safety!
  }
});

Benefits:

  • βœ… No type casting needed in extendFlags and createExecutor
  • βœ… Full IntelliSense for custom config properties
  • βœ… Consistent with THandler (#138) and executor TConfig (#144)
  • βœ… Fully backward compatible with default TConfig = Config

πŸ“Š Quality Metrics

  • Tests: 1572 passing (+4 new tests)
  • Coverage: 100% maintained (2815/1450/581/2713)
  • Build: TypeScript compiles without errors
  • Backward Compatibility: βœ… No breaking changes

πŸ“š Documentation

Updated docs/guides/cli-adapter-development.md with:

  • Complete Firebase example using TConfig generic
  • Before/after comparison highlighting type safety improvements
  • Integration with addCustomOptions and extendFlags (v0.8.3)

πŸ”— Related

  • #138: THandler generic for type-safe handler access (v0.8.0)
  • #144: TConfig generic in executor interfaces (v0.8.2)
  • #151: addCustomOptions/extendFlags callbacks (v0.8.3)

This release completes the type safety story from v0.8.0 through v0.8.4.


πŸ“¦ Installation

npm install @migration-script-runner/core@0.8.4

πŸš€ Usage Example

interface FirebaseConfig extends Config {
  databaseUrl: string;
  applicationCredentials: string;
  connectionTimeout?: number;
}

const program = createCLI<IFirebaseDB, FirebaseAdapter, FirebaseConfig>({
  name: 'msr-firebase',
  
  addCustomOptions: (program) => {
    program
      .option('--database-url <url>', 'Firebase Database URL')
      .option('--credentials <path>', 'Service account key');
  },
  
  extendFlags: (config, flags) => {
    // βœ… config is typed as FirebaseConfig!
    config.databaseUrl = flags.databaseUrl as string;
    config.applicationCredentials = flags.credentials as string;
  },
  
  createExecutor: async (config) => {
    // βœ… config.databaseUrl has full IntelliSense!
    return FirebaseAdapter.getInstance({ config });
  }
});

πŸ”„ Migration Guide

No migration required - fully backward compatible.

Existing code without the third generic parameter continues to work:

// Still works - defaults to base Config type
createCLI({ createExecutor: (config) => ... });

To adopt type safety for custom configs, add the third generic:

// Enhanced with type safety
createCLI<IDB, Adapter, CustomConfig>({ ... });

v0.8.3 - Adapter-Specific CLI Flags

Choose a tag to compare

@vlavrynovych vlavrynovych released this 20 Dec 15:22

πŸš€ What's New

Adapter-Specific CLI Flags (#151)

Adapters can now add their own database-specific command-line flags that integrate seamlessly with MSR's configuration system.

New Callbacks:

  • addCustomOptions(program) - Register custom CLI flags during setup
  • extendFlags(config, flags) - Map flag values to config at execution

Benefits:

  • βœ… Single-command execution without environment variables
  • βœ… Highest priority in config waterfall
  • βœ… Perfect for CI/CD pipelines
  • βœ… Appears in --help output automatically
  • βœ… Fully backward compatible (callbacks optional)

πŸ“¦ Example Usage

Firebase Adapter

const program = createCLI({
  name: 'msr-firebase',
  
  addCustomOptions: (program) => {
    program
      .option('--database-url <url>', 'Firebase Database URL')
      .option('--credentials <path>', 'Service account key');
  },
  
  extendFlags: (config, flags) => {
    if (flags.databaseUrl) config.databaseUrl = flags.databaseUrl;
    if (flags.credentials) config.credentials = flags.credentials;
  },
  
  createExecutor: async (config) => FirebaseAdapter.getInstance({ config })
});

CLI Usage:

npx msr-firebase migrate \
  --database-url https://my-project.firebaseio.com \
  --credentials ./serviceAccountKey.json

MongoDB Adapter

npx msr-mongodb migrate \
  --mongo-uri mongodb://localhost:27017/mydb \
  --auth-source admin \
  --ssl

πŸ“Š Quality Metrics

  • Tests: 1568 passing (+8 new tests)
  • Coverage: 100% maintained (2815/1450/581/2713)
  • Documentation: 120+ lines with Firebase & MongoDB examples
  • Build: TypeScript compiles without errors

πŸ”„ Config Waterfall Priority

Custom CLI flags have the highest priority:

  1. Built-in defaults (lowest)
  2. Config file (if --config-file provided)
  3. Environment variables (MSR_*)
  4. options.config (if provided)
  5. Standard CLI flags (--folder, --table-name, etc.)
  6. Custom CLI flags via extendFlags (highest)

πŸ“š Documentation

See the complete guide in CLI Adapter Development


πŸ”§ Installation

npm install @migration-script-runner/core@0.8.3

⬆️ Migration from v0.8.2

No breaking changes. Existing adapters continue to work without modification.

To opt-in:

  1. Add addCustomOptions callback to register your custom flags
  2. Add extendFlags callback to map flag values to config
  3. Update your adapter's config type if needed

🎯 Use Cases

Perfect for:

  • Database Connections: URLs, hosts, ports, credentials
  • Authentication: Service account keys, tokens, API keys
  • Performance: Connection pools, timeouts, retry settings
  • Feature Flags: Enable/disable specific functionality
  • CI/CD Pipelines: Single-command execution without env setup

v0.8.2 - Developer Experience Improvements

Choose a tag to compare

@vlavrynovych vlavrynovych released this 19 Dec 23:29

MSR Core v0.8.2 - Developer Experience Improvements

Release Date: December 20, 2025

🎯 Overview

MSR Core v0.8.2 focuses on developer experience improvements for adapter development, making it easier and faster to create database adapters with better type safety, reduced boilerplate, and clearer error messages.

✨ What's New

#144: Generic Config Type Support

Added TConfig generic parameter enabling full type safety for database-specific configuration properties.

// Before v0.8.2: Required wrapper interfaces
interface IFirebaseOptions extends IExecutorOptions<IDB> {
    config: FirebaseConfig;  // Override base Config
}

// v0.8.2: Native generic support
interface IFirebaseOptions extends IExecutorOptions<IDB, FirebaseConfig> {
    // config is automatically typed as FirebaseConfig!
}

Benefits:

  • βœ… Type-safe custom config properties
  • βœ… Zero type assertions needed
  • βœ… Fully backward compatible

#145: Async Executor Support in CLI

CLI now supports Promise<Executor> return type from createExecutor.

// v0.8.2: Async executor creation
const program = createCLI({
    createExecutor: async (config) => {
        return MyAdapter.getInstance({ config });  // βœ… Async!
    }
});

Benefits:

  • βœ… Async database connections supported
  • βœ… No more unsafe type casts
  • βœ… Fully backward compatible

#146: Better Documentation and Error Messages

Enhanced API documentation and runtime validation with helpful error messages.

Improvements:

  • πŸ”– PUBLIC/INTERNAL API markers in JSDoc
  • πŸ“‹ Comprehensive troubleshooting guide (185 lines)
  • ❌ Helpful runtime errors with solutions
  • πŸ“Š Interface comparison tables

Error Example:

TypeError: Handler is required in IMigrationExecutorDependencies.

Common causes:
  1. Using IExecutorOptions in constructor instead of IMigrationExecutorDependencies
  2. Forgetting to create handler before passing to super()

Solutions:
  β€’ For async initialization: Use a factory method pattern:
    static async getInstance(options: IExecutorOptions<DB>): Promise<MyExecutor> {
      const handler = await MyHandler.connect(options.config);
      return new MyExecutor({ handler, ...options });
    }

#147: createInstance Factory Pattern

Added standardized factory method for async adapter initialization.

// Before v0.8.2: Manual pattern (~10 lines)
static async getInstance(options: IOptions): Promise<MyAdapter> {
    const handler = await MyHandler.getInstance(options.config);
    return new MyAdapter({ handler, ...options });
}

// v0.8.2: createInstance helper (3 lines)
static async getInstance(options: IOptions): Promise<MyAdapter> {
    return MigrationScriptExecutor.createInstance(
        MyAdapter, options, (config) => MyHandler.getInstance(config)
    );
}

Benefits:

  • βœ… Standardized pattern across ecosystem
  • βœ… Reduces boilerplate by 70%
  • βœ… Type-safe with full generic support
  • βœ… Documentation now async-first (9/10 adapters are async)

πŸ“Š Key Metrics

  • Tests: 1560 passing (+11 from v0.8.1)
  • Coverage: 100% on all metrics (2811/1448/581/2709)
  • Breaking Changes: None (fully backward compatible)
  • Documentation: 4 major files updated

πŸ“š Documentation Updates

Major Updates:

  • getting-started.md: Restructured to show async pattern first
  • cli-adapter-development.md: New Quick Start, Complete Example, Troubleshooting section (185 lines)
  • api/core-classes.md: Added createInstance() documentation
  • design-patterns.md: Added async adapter factory pattern section

New Sections:

  • Troubleshooting guide with 6 common issues
  • IExecutorOptions vs IMigrationExecutorDependencies comparison
  • Async adapter initialization guide (210 lines)
  • Custom config types guide (247 lines, added in v0.8.1)

πŸ”§ Migration Guide

No breaking changes. All changes are backward compatible.

Recommended Updates:

  1. Use createInstance for async adapters:
static async getInstance(options: IOptions): Promise<MyAdapter> {
    return MigrationScriptExecutor.createInstance(
        MyAdapter, options, async (config) => MyHandler.connect(config)
    );
}
  1. Add generic config type:
// Define custom config
class AppConfig extends Config {
    databaseUrl?: string;
}

// Use TConfig generic
class MyAdapter extends MigrationScriptExecutor<IDB, MyHandler, AppConfig> {
    // this.config is now typed as AppConfig!
}
  1. Update CLI for async:
const program = createCLI({
    createExecutor: async (config) => MyAdapter.getInstance({ config })
});

πŸš€ Installation

npm install @migration-script-runner/core@0.8.2

πŸ“– Full Changelog

Features

  • #144: Generic config type support with TConfig parameter
  • #145: CLI async executor support with Promise<Executor>
  • #146: Enhanced documentation with PUBLIC/INTERNAL markers
  • #147: createInstance factory pattern for async adapters

Documentation

  • Added comprehensive troubleshooting guide
  • Restructured to show async-first approach
  • Added interface comparison tables
  • Enhanced JSDoc with clear examples

Tests

  • Added 11 new tests (runtime validation, async patterns)
  • Maintained 100% coverage on all metrics

πŸ”— Related Releases

  • v0.8.1: Locking lifecycle, LockingOrchestrator, getHandler()
  • v0.8.0: Locking mechanism, THandler generic, down migration fixes

🎯 Next Steps

  • v1.0.0 (planned): Make MigrationScriptExecutor abstract class (#150)
  • Focus on ecosystem growth with improved adapter DX

πŸ‘₯ Contributors


Full Milestone: https://github.com/migration-script-runner/msr-core/milestone/14

v0.8.1 - Locking Enhancements

Choose a tag to compare

@vlavrynovych vlavrynovych released this 18 Dec 23:50

Migration Script Runner v0.8.1

Release Date: December 19, 2025

Minor enhancements and improvements to v0.8.0 locking features, including a breaking change for ILockingService implementations.


πŸŽ‰ What's New

Handler Access API (#142)

Added getHandler() public method to MigrationScriptExecutor for direct handler access.

Benefits:

  • Direct handler access for CLI custom commands
  • Removes adapter-specific workarounds (e.g., FirebaseRunner.getHandler())
  • Full type safety through THandler generic parameter
  • Simplifies CLI development for database-specific operations

Example:

// CLI custom command
const handler = executor.getHandler();
console.log('Handler version:', handler.getVersion());

// Type-safe access with THandler generic
class MyAdapter extends MigrationScriptExecutor<IDB, PostgresHandler> {
    getConnectionInfo() {
        return this.getHandler().pool.idleCount; // Fully typed\!
    }
}

Locking Service Lifecycle (#140) ⚠️ BREAKING CHANGE

Added required initialization methods to ILockingService interface for explicit lifecycle management.

New Required Methods:

interface ILockingService<DB extends IDB> {
    // Existing methods...
    
    // NEW in v0.8.1 - REQUIRED
    initLockStorage(): Promise<void>;
    ensureLockStorageAccessible(): Promise<boolean>;
}

Benefits:

  • βœ… Fail-fast: Setup errors occur at initialization, not first lock acquisition
  • βœ… Explicit lifecycle: Clear when lock storage is created
  • βœ… Pre-flight validation: Detect configuration/permission issues early
  • βœ… Improved testability: Setup tested separately from lock operations

Implementation Example:

// PostgreSQL
async initLockStorage() {
    await this.db.query(`
        CREATE TABLE IF NOT EXISTS migration_locks (
            executor_id VARCHAR(255) PRIMARY KEY,
            locked_at TIMESTAMP NOT NULL,
            expires_at TIMESTAMP NOT NULL
        )
    `);
}

async ensureLockStorageAccessible() {
    try {
        await this.db.query('SELECT 1');
        return true;
    } catch {
        return false;
    }
}

Lock Orchestration Service (#141)

Added LockingOrchestrator service using decorator pattern for centralized lock management.

What Was Added:

  • LockingOrchestrator Service: Wraps ILockingService implementations
  • ILockingHooks Interface: 9 optional hook methods for observability
  • Integration: Seamless integration into MigrationWorkflowOrchestrator

Features:

  • Retry logic with configurable attempts/delays
  • Two-phase locking (acquire β†’ verify ownership)
  • Lifecycle hooks for metrics, alerts, and audit logging
  • Comprehensive error handling with context preservation

Hook Methods:

interface ILockingHooks {
    onBeforeAcquireLock?(executorId: string, timeout: number): Promise<void>;
    onLockAcquired?(executorId: string, status: ILockStatus): Promise<void>;
    onLockAcquisitionFailed?(executorId: string, currentOwner: string): Promise<void>;
    onAcquireRetry?(executorId: string, attempt: number, currentOwner: string): Promise<void>;
    onOwnershipVerificationFailed?(executorId: string): Promise<void>;
    onBeforeReleaseLock?(executorId: string): Promise<void>;
    onLockReleased?(executorId: string): Promise<void>;
    onForceReleaseLock?(status: ILockStatus | null): Promise<void>;
    onLockError?(operation: string, error: Error, executorId?: string): Promise<void>;
}

Benefits:

  • Consistent lock orchestration across all database adapters
  • Centralized observability through hooks
  • Adapters stay focused on database-specific operations only

πŸ“Š Statistics

  • Issues Closed: 3 (#140, #141, #142)
  • Tests Added: 45 new unit/integration tests
  • Total Tests: 1547 passing (up from 1497 in v0.8.0)
  • Coverage: 100% on all metrics (statements, branches, functions, lines)
  • Breaking Changes: 1 (#140 - required methods in ILockingService)

⚠️ Breaking Changes

ILockingService Interface (#140)

All ILockingService implementations must now implement two required methods:

  1. initLockStorage(): Promise<void>
  2. ensureLockStorageAccessible(): Promise<boolean>

Migration Steps:

  1. Add both methods to your ILockingService implementation
  2. Call initLockStorage() during handler initialization
  3. Optionally call ensureLockStorageAccessible() for pre-flight checks

Example Update:

class MyLockingService implements ILockingService<IDB> {
    // Existing methods...
    
    // ADD THESE:
    async initLockStorage(): Promise<void> {
        // Create lock storage structures (tables, indexes, paths)
    }
    
    async ensureLockStorageAccessible(): Promise<boolean> {
        // Verify storage is accessible
        return true;
    }
}

πŸ“¦ Installation

npm install @migration-script-runner/core@0.8.1

πŸ”— Links


πŸ™ Acknowledgments

Special thanks to the Firebase adapter (#67) for identifying the need for lifecycle management methods in the locking interface.

v0.8.0 - Production-Ready Locking & Enhanced Type Safety

Choose a tag to compare

@vlavrynovych vlavrynovych released this 18 Dec 19:05

πŸŽ‰ What's New in v0.8.0

Production-ready release with migration locking, enhanced type safety, and critical bug fixes. 100% backwards compatible with v0.7.x - all features are opt-in.


✨ Features

πŸ”’ Migration Locking (#85, #120)

Prevent concurrent migrations with database-level locking mechanism for multi-instance deployments.

Why you need it:

  • Prevents race conditions in Kubernetes/Docker deployments
  • Avoids corrupted migration state in CI/CD pipelines
  • Essential for multi-instance production environments

Implementation:

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

class MyDatabaseLockingService implements ILockingService<MyDB> {
  async acquireLock(executorId: string, timeout: number): Promise<boolean> {
    // Database-specific lock acquisition
  }
  async verifyLockOwnership(executorId: string): Promise<boolean> {
    // Two-phase verification prevents race conditions
  }
  async releaseLock(executorId: string): Promise<void> {
    // Release lock after migration
  }
  // ... other methods
}

// Add to handler
handler.lockingService = new MyDatabaseLockingService(db);

Configuration (optional):

config.locking.enabled = true;        // Default when service provided
config.locking.timeout = 600_000;     // 10 minutes
config.locking.retryAttempts = 0;     // Fail-fast (recommended)
config.locking.retryDelay = 1000;     // 1 second between retries

CLI Commands:

# Check lock status
msr lock:status

# Force-release stuck lock
msr lock:release --force

# Disable locking for single run
msr migrate --no-lock

πŸ“– Locking Configuration Docs | Lock Commands Guide


πŸ”§ Handler Generic Type Parameter (#138)

Type-safe handler access in adapters with optional second generic parameter - eliminates casting workarounds!

BEFORE (v0.7.x):

class MyAdapter extends MigrationScriptExecutor<IDB> {
  private getHandler(): MyHandler {
    return this['handler'] as MyHandler;  // ❌ Casting required
  }

  getConnectionInfo() {
    const handler = this.getHandler();
    return handler.config.host;  // No IDE autocomplete
  }
}

AFTER (v0.8.0):

class MyAdapter extends MigrationScriptExecutor<IDB, MyHandler> {
  getConnectionInfo() {
    // βœ… Type-safe access - no casting needed\!
    return this.handler.config.host;  // Full IDE autocomplete
  }
}

Benefits:

  • βœ… Full IDE autocomplete support
  • βœ… Compile-time type checking
  • βœ… No casting or workarounds needed
  • βœ… Cleaner, more maintainable adapter code

πŸ› Bug Fixes

Down Migration TypeError (#139)

Issue: Calling executor.down(targetVersion) threw TypeError: s.init is not a function.

Root Cause: Migration records from database lacked filepath property needed for loading script files.

Fix: Added matchMigratedWithScripts() helper to match database records with filesystem scripts before rollback.

Impact: Down migrations now work correctly. No code changes needed - fix is automatic.


πŸ“¦ npm Provenance (#133)

Enhanced supply chain security with build provenance attestations. Published packages now include verifiable build information.

npm publish --provenance

πŸ”„ Backwards Compatibility

βœ… 100% backwards compatible with v0.7.x

  • All existing code works without modifications
  • Locking is disabled by default (opt-in via lockingService)
  • Handler generic type has sensible default (IDatabaseMigrationHandler<DB>)
  • Bug fixes are transparent
  • No deprecated features

Migration Time: 5-10 minutes (optional feature adoption)

πŸ“– Migration Guide


πŸ“Š Stats

  • 8 Issues Closed
  • 1,497 Tests Passing (100% coverage maintained)
  • Zero Breaking Changes

πŸ™ Contributors

Thanks to everyone who contributed to this release!


πŸ“š Documentation


πŸš€ Upgrade Instructions

npm install @migration-script-runner/core@^0.8.0

Or with yarn:

yarn upgrade @migration-script-runner/core@^0.8.0

That's it! Everything continues to work. Enable locking when ready for production.


Full Changelog: v0.7.3...v0.8.0

v0.7.4: Automated npm Publishing

Choose a tag to compare

@vlavrynovych vlavrynovych released this 17 Dec 22:23
198bc3b

πŸ” Automated npm Publishing (#133)

Implemented tag-based automated npm publishing workflow with cryptographic provenance.

What's Changed

New Publishing Workflow:

  • βœ… Tag-based publishing: Push git tag (e.g., v0.8.0) to automatically trigger npm publish
  • βœ… Provenance signing: Packages are cryptographically signed with GitHub Actions build information
  • βœ… Automated workflow: .github/workflows/npm-publish.yml handles build, test, and publish
  • βœ… Security: Uses npm granular access tokens with bypass 2FA for CI/CD

Workflow Features:

  • Triggers on v* tags or manual dispatch
  • Runs prepublishOnly hook automatically (build + test)
  • Publishes with provenance via id-token: write permission
  • Uses NPM_TOKEN secret (granular access token, 90-day expiration)

Technical Changes:

  • Updated workflow to Node 20
  • Simplified workflow (removed version check job)
  • Fixed package.json repository URL format (git+https:// prefix)

Usage:

# Create and push tag
git tag v0.8.0
git push origin v0.8.0

# Workflow automatically publishes to npm

Full Changelog: v0.7.0...v0.7.4

v0.7.0 - CLI Factory, .env Support, and Improved Architecture

Choose a tag to compare

@vlavrynovych vlavrynovych released this 13 Dec 16:56

πŸŽ‰ What's New in v0.7.0

Enhanced architecture, adapter extensibility, and CLI factory for production-ready migration tooling.

✨ New Features

πŸ–₯️ CLI Factory (#59)

  • Create command-line interfaces with built-in commands (migrate, list, down, validate, backup)
  • Factory pattern using Commander.js for type-safe CLI creation
  • Extensible via extendCLI callback for custom database-specific commands
  • Full configuration waterfall support (defaults β†’ file β†’ env β†’ CLI flags)

πŸ—‚οΈ .env File Support (#129)

  • Load configuration from .env, .env.production, .env.local files
  • Configurable priority control via config.envFileSources
  • Integrated with auto-envparse v2.1.0
  • Environment-specific config without manual dotenv setup

🎨 Facade Pattern (#62)

  • Services grouped into 4 logical facades (core, execution, output, orchestration)
  • Protected facades allow adapters to extend executor and access internal services
  • Cleaner architecture with clear service boundaries
  • 70% code reduction (1564 β†’ 467 lines in MigrationScriptExecutor)

🏭 Factory Pattern (#97)

  • Dedicated MigrationServicesFactory for service initialization
  • Constructor complexity reduced by 83% (142 β†’ 23 lines)
  • Improved maintainability and testability

✨ Extensible Configuration (#123)

  • New IConfigLoader interface for custom environment variable handling
  • Generic ConfigLoader<C> supports adapter-specific config types
  • IExecutorOptions<DB> separates required from optional dependencies
  • Adapters can extend ConfigLoader to add custom env vars

πŸ”¨ Breaking Changes

Constructor Signature Change

// OLD (v0.6.0)
new MigrationScriptExecutor({ handler }, config)

// NEW (v0.7.0)
new MigrationScriptExecutor({ handler, config })

Config moved from second parameter into dependencies object.

Service Properties Removed
Internal services no longer exposed as public properties. Use public API methods:

  • executor.backupService β†’ executor.createBackup()
  • executor.migrationScanner β†’ executor.list()
  • executor.validationService β†’ executor.validate()

Or extend MigrationScriptExecutor to access protected facades.

Migration Time: 15-30 minutes

β†’ Full Migration Guide


πŸ“Š Statistics

  • 100% Test Coverage - 1400 tests passing (2549/2549 statements)
  • Zero Quality Issues - All SonarCloud checks passing
  • 83% Constructor Reduction - From 142 lines to 23 lines
  • 70% Code Reduction - MigrationScriptExecutor: 1564 β†’ 467 lines

πŸ“š Documentation


🎯 Highlights

  • Production-Ready CLI - Built-in commands with extensibility
  • Better Encapsulation - Facade pattern with protected access
  • Adapter Friendly - Extensible ConfigLoader and executor
  • Reduced Complexity - 83% constructor reduction
  • .env File Support - No manual dotenv setup needed
  • 100% Backward Compatible API - Only constructor signature changed

πŸ”— Related Issues

  • #59 - CLI Factory implementation
  • #62 - Facade Pattern refactoring
  • #97 - GOD class decomposition
  • #122 - Pre-commit hooks with Husky
  • #123 - Interface segregation (IExecutorOptions)
  • #124 - Code review and quality improvements
  • #125 - Documentation review
  • #126 - Auto-apply environment variables
  • #128 - Integrate auto-envparse library
  • #129 - Upgrade to auto-envparse v2.1.0

πŸ“¦ Installation

npm install @migration-script-runner/core@^0.7.0

πŸš€ Quick Start

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

const program = createCLI({
  name: 'my-db-migrate',
  version: '1.0.0',
  createExecutor: (config) => {
    const handler = new MyDatabaseHandler();
    return new MigrationScriptExecutor({ handler, config });
  }
});

program.parse(process.argv);

Full Changelog: v0.6.0...v0.7.0

v0.6.0 - Observability & Configuration Flexibility

Choose a tag to compare

@vlavrynovych vlavrynovych released this 04 Dec 22:04
e8021e5

πŸŽ‰ What's New in v0.6.0

Observability, configuration flexibility, and enhanced type safety

This release brings comprehensive metrics collection, flexible configuration formats, and significantly improved type safety through generic parameters. Note: Contains breaking changes - see migration guide below.


⚠️ Breaking Changes

1. Generic Type Parameters (REQUIRED)

All interfaces now require explicit type parameters:

// ❌ v0.5.x - No type parameter
class MyHandler implements IDatabaseMigrationHandler {

// βœ… v0.6.0 - Type parameter required
class MyHandler implements IDatabaseMigrationHandler<IDB> {

Affected interfaces: IDatabaseMigrationHandler, IRunnableScript, MigrationScript, ISchemaVersion, IBackup, ITransactionManager

Migration time: 10-30 minutes to add <IDB> to all implementations

2. Constructor Signature Change

// v0.5.x
const executor = new MigrationScriptExecutor(handler, config);

// v0.6.0
const executor = new MigrationScriptExecutor({ handler }, config);

What changed: Handler now wrapped in dependency injection object { handler }

See Migration Guide for complete upgrade instructions.


✨ Major Features

πŸ“Š Metrics & Observability (#80)

Complete metrics collection system for production monitoring:

  • Metrics Collectors: JSON, CSV, and Logger-based collectors
  • MetricsCollectorHook: Automatic lifecycle event tracking
  • Performance Tracking: Migration duration, success rates, error tracking
  • CI/CD Integration: Machine-readable JSON/CSV output for reporting
  • Composite Support: Use multiple collectors simultaneously
import { JsonMetricsCollector, CsvMetricsCollector } from '@migration-script-runner/core';

const executor = new MigrationScriptExecutor({
  handler,
  metricsCollectors: [
    new JsonMetricsCollector({ 
      filePath: './metrics/migrations.json',
      pretty: true 
    }),
    new CsvMetricsCollector({ 
      filePath: './metrics/history.csv' 
    })
  ]
}, config);

Output: Structured metrics with timing, success/failure tracking, and rollback information for dashboards and alerts.

βš™οΈ Multi-Format Configuration (#98)

Support for YAML, TOML, and XML configuration files:

  • YAML Support: .yaml and .yml files (requires js-yaml)
  • TOML Support: .toml files (requires @iarna/toml)
  • XML Support: .xml files (requires fast-xml-parser)
  • Automatic Detection: ConfigLoader picks the right format
  • Extensible: Add custom loaders via IConfigFileLoader
# All formats now supported:
msr.config.js    # JavaScript (built-in)
msr.config.json  # JSON (built-in)
msr.config.yaml  # YAML (optional)
msr.config.toml  # TOML (optional)
msr.config.xml   # XML (optional)

🧬 Generic Type Parameters (#114)

Database-specific type safety throughout the API:

  • Type-Safe Handlers: IDatabaseMigrationHandler<YourDB>
  • Type-Safe Scripts: MigrationScript<YourDB>
  • Type-Safe Hooks: All hooks now generic over database type
  • Better IntelliSense: Full autocomplete for your database interface
  • Compile-Time Safety: Catch type mismatches before runtime
interface MyDB extends IDB {
  query(sql: string): Promise<ResultSet>;
  execute(sql: string): Promise<void>;
}

// Full type safety:
const handler: IDatabaseMigrationHandler<MyDB> = { /* ... */ };
const executor = new MigrationScriptExecutor<MyDB>({ handler }, config);

πŸŽ›οΈ Banner Control (#100)

Toggle ASCII banner display for clean CI/CD logs:

config.showBanner = false;  // Disable banner
// Or via environment variable:
// MSR_SHOW_BANNER=false

πŸ› Debug Logging (#115)

Granular log level control for troubleshooting:

config.logLevel = 'debug';  // 'error' | 'warn' | 'info' | 'debug'
// Or via environment variable:
// MSR_LOG_LEVEL=debug

πŸ“š Documentation

Enhanced Content

  • Origin Story (#104): Project history and design philosophy
  • Getting Started Guide (#108): Local testing and development setup
  • Migration Guide (#110): v0.5.x β†’ v0.6.0 upgrade path
  • SEO Improvements (#101): Sitemap.xml for better discoverability
  • Google Analytics (#111, #112): Production site analytics

Quality Improvements

  • Comprehensive API documentation
  • Real-world code examples
  • Configuration reference updates
  • Better search and navigation

πŸ”§ Quality & Security

Code Quality (#109)

  • 43 of 46 SonarCloud issues resolved (93% improvement)
  • Zero any types in production code
  • 100% test coverage maintained (1,224 tests passing)
  • All BLOCKER and CRITICAL issues fixed
  • Improved code consistency and readability

Security (#117)

  • Fixed npm security vulnerabilities in dependencies
  • Updated coveralls package to secure version
  • All security audits passing

πŸ”— Migration Guide

From v0.5.x: See v0.5.x β†’ v0.6.0 Migration Guide

Required changes (10-30 minutes):

  1. Add type parameters to interfaces:
// Update all implementations
class MyHandler implements IDatabaseMigrationHandler<IDB> {
const migration: IRunnableScript<IDB> = { /* ... */ };
  1. Update constructor calls:
// Change from:
new MigrationScriptExecutor(handler, config)

// To:
new MigrationScriptExecutor({ handler }, config)

Optional enhancements:

// 1. Add metrics collection (optional)
import { JsonMetricsCollector } from '@migration-script-runner/core';
executor.metricsCollectors = [
  new JsonMetricsCollector({ filePath: './metrics.json' })
];

// 2. Use YAML config (optional)
// Convert msr.config.js β†’ msr.config.yaml
// npm install js-yaml

// 3. Enhance with database-specific types (optional but recommended)
const executor = new MigrationScriptExecutor<YourDB>({ handler }, config);

πŸ“¦ Installation

npm install @migration-script-runner/core@0.6.0

Optional peer dependencies:

# For YAML support:
npm install js-yaml

# For TOML support:
npm install @iarna/toml

# For XML support:
npm install fast-xml-parser

πŸ“ˆ Stats

  • 13 issues closed
  • 43 code quality improvements
  • 100% test coverage (1,224 tests)
  • 2 breaking changes (see migration guide)

Full Changelog: v0.5.0...v0.6.0

v0.5.0 - Transaction Management & Cloud-Native Configuration

Choose a tag to compare

@vlavrynovych vlavrynovych released this 01 Dec 23:57

πŸŽ‰ What's New in v0.5.0

Production-grade transaction management and cloud-native configuration

This release brings powerful new capabilities for production deployments while maintaining 100% backward compatibility with v0.4.x. All existing code continues to work without modifications.


✨ Major Features

πŸ”’ Transaction Management (#76)

Complete transaction support with automatic retry logic and isolation control:

  • Configurable Modes: PER_MIGRATION, PER_BATCH, or NONE
  • Automatic Retry: Exponential backoff for transient failures (deadlocks, timeouts)
  • Isolation Levels: READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
  • SQL Support: ITransactionalDB interface with begin/commit/rollback
  • NoSQL Support: ICallbackTransactionalDB for MongoDB, Firestore, DynamoDB
  • Transaction Hooks: Monitor lifecycle events for metrics and logging
const config = new Config();
config.transaction.mode = TransactionMode.PER_MIGRATION;
config.transaction.isolation = IsolationLevel.READ_COMMITTED;
config.transaction.retries = 5;
config.transaction.retryBackoff = true;

βš™οΈ Environment Variables (#84)

Complete 12-factor app configuration for cloud-native deployments:

  • 33 MSR_ Variables*: Full configuration through environment variables
  • Organized Categories: Core, Validation, Logging, Backup, Rollback, Transaction
  • Docker/Kubernetes Ready: Perfect for containerized deployments
  • CI/CD Integration: Environment-based configuration for pipelines
  • ConfigLoader: Automatic waterfall loading (env β†’ file β†’ defaults β†’ overrides)
export MSR_FOLDER=./migrations
export MSR_TRANSACTION_MODE=PER_MIGRATION
export MSR_TRANSACTION_RETRIES=5
export MSR_VALIDATE_BEFORE_RUN=true

πŸ“Š Enhanced Lifecycle Hooks

New transaction lifecycle hooks for monitoring and metrics:

  • beforeTransactionBegin - Before transaction starts
  • afterCommit - After successful commit
  • onCommitRetry - On retry attempts
  • beforeRollback - Before rollback on failure

πŸš€ Improvements

  • Code Quality (#94): Comprehensive code review addressing 47 SonarQube findings
  • Documentation (#95): Complete migration guide and updated docs for v0.5.0
  • Type Safety: Enhanced interfaces with better TypeScript support
  • Error Handling: Improved error messages and validation

πŸ“š Documentation


πŸ”„ Migration from v0.4.x

Estimated Time: 5-15 minutes
Complexity: Low - No breaking changes

Quick Upgrade

npm install @migration-script-runner/core@^0.5.0

Your existing v0.4.x code works without modifications. New features are opt-in.

β†’ View complete migration guide


πŸ’ͺ No Breaking Changes

v0.5.0 maintains 100% backward compatibility:

  • βœ… All v0.4.x APIs work unchanged
  • βœ… All existing migrations continue to work
  • βœ… New features are optional and opt-in
  • βœ… Zero code changes required

πŸ“¦ Installation

npm install @migration-script-runner/core@0.5.0

Or with yarn:

yarn add @migration-script-runner/core@0.5.0

πŸ™ Credits

Special thanks to all contributors and community members who provided feedback and suggestions for this release.


πŸ› Issues & Support


Full Changelog: v0.4.0...v0.5.0

v0.4.0 - SQL Support, API Improvements & Enhanced Developer Experience

Choose a tag to compare

@vlavrynovych vlavrynovych released this 30 Nov 17:34

πŸŽ‰ Release Highlights

Version 0.4.0 is a major release introducing SQL migration files, simplified API, and comprehensive developer experience improvements.


✨ New Features

SQL Migration Support (#58)

  • First-class SQL file support - Use .up.sql and .down.sql files alongside TypeScript migrations
  • ISqlDB interface - Type-safe SQL execution with query(sql: string) method
  • Loader architecture - Extensible system supporting multiple file types (TypeScriptLoader, SqlLoader)
  • Hybrid projects - Mix TypeScript and SQL migrations in the same project

Example:

-- V202501280100_create_users.up.sql
CREATE TABLE users (
  id INT PRIMARY KEY,
  email VARCHAR(255) NOT NULL UNIQUE
);

Simplified API (#81)

  • Industry-standard method names - up() and down() replace migrate(), migrateTo(), downTo()
  • Backward compatible - migrate() still works as an alias to up()
  • Clearer semantics - More intuitive API aligned with migration tool conventions

Migration:

// Before (v0.3.x)
await executor.migrateTo(202501280005);
await executor.downTo(202501280002);

// After (v0.4.0)
await executor.up(202501280005);
await executor.down(202501280002);

Developer Experience Enhancements

Dry Run Mode (#73)

  • Preview migrations without execution
  • Perfect for CI/CD validation
  • See what would be executed before running
config.dryRun = true;
await executor.up(); // Shows plan, doesn't execute

Execution Summary Logging (#72)

  • Detailed migration logs with complete audit trail
  • Automatic file rotation and retention
  • JSON and text formats
  • Success and failure logging
config.logging.enabled = true;
config.logging.folder = './logs';
config.logging.format = 'JSON';

Connection Validation (#88)

  • Early connection checking with checkConnection()
  • Fail fast with clear error messages
  • Required for all IDB implementations
class MyDB implements IDB {
  async checkConnection(): Promise<void> {
    await this.db.ping();
  }
}

Multi-pattern Support

  • filePatterns (array) replaces filePattern (single)
  • Support multiple file types simultaneously
  • Cleaner configuration for hybrid projects
config.filePatterns = [
  /^V(\d{12})_.*\.ts$/,
  /^V(\d{12})_.*\.up\.sql$/
];

πŸ”§ Breaking Changes

1. filePattern β†’ filePatterns (High Impact)

// Before
config.filePattern = /^V(\d{12})_.*\.ts$/;

// After
config.filePatterns = [/^V(\d{12})_.*\.ts$/];

2. API Method Renames (High Impact)

  • migrateTo(version) β†’ up(version)
  • downTo(version) β†’ down(version)
  • migrate() still works as alias to up()

3. IDB.checkConnection() Required (High Impact)

All database implementations must implement checkConnection() method.

4. Interface Property Renames (Medium Impact)

  • ISchemaVersion.migrations β†’ migrationRecords
  • IMigrationScript.getAll() β†’ getAllExecuted()

5. Service Method Renames (Low Impact)

  • IMigrationService.readMigrationScripts() β†’ findMigrationScripts()
  • IMigrationService.getBeforeMigrateScript() β†’ findBeforeMigrateScript()

6. IBackup Parameter Rename (Low Impact)

  • restore(data) β†’ restore(backupData)

πŸ“š Documentation

New Guides

Updated Documentation

  • All API documentation updated with new method names
  • Configuration guides updated for new options
  • All recipes and examples updated to v0.4.0 API
  • Reorganized interface documentation for better navigation

πŸ› οΈ Architecture Improvements

  • Extensible loader system - IMigrationScriptLoader and ILoaderRegistry interfaces
  • Enhanced type safety - Improved type definitions across all interfaces
  • Better error handling - More descriptive error messages and validation

πŸ“¦ Installation

npm install @migration-script-runner/core@0.4.0

πŸ”„ Upgrade Instructions

See the v0.3.x β†’ v0.4.0 Migration Guide for detailed upgrade instructions with examples.

Quick checklist:

  • Update filePattern to filePatterns (array)
  • Replace migrateTo() with up(), downTo() with down()
  • Add checkConnection() method to your IDB implementation
  • Update interface property names if using custom implementations
  • Test migrations in development environment

πŸ“– Full Documentation

https://migration-script-runner.github.io/msr-core/


πŸ™ Contributors

Thank you to everyone who contributed to this release through issues, discussions, and feedback!


Released: January 30, 2025
Milestone: v0.4.0