Skip to content

migration-script-runner/msr-core

Repository files navigation

Migration Script Runner

CircleCI Coverage Status Quality Gate Status Lines of Code GitHub issues License NPM Version NPM Downloads Static Badge

A database-agnostic migration framework for TypeScript and JavaScript projects.

MSR provides a lightweight, flexible framework for managing database migrations without locking you into a specific ORM or database system. Bring your own database implementation and let MSR handle the migration workflow, versioning, validation, and execution.


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

Enhanced type safety, metrics collection, and multi-format configuration:

  • πŸ›‘οΈ Generic Type Parameters - Database-specific type safety with <DB extends IDB> generics throughout the API (BREAKING: type parameters now required)
  • πŸ“Š Metrics Collection - Built-in collectors for observability with console, JSON, CSV, and logger-based output
  • πŸ“„ YAML, TOML, and XML Support - Use your preferred config format (.yaml, .toml, .xml) alongside JS/JSON
  • πŸ”Œ Plugin Architecture - Extensible loader system with optional peer dependencies keeps core lightweight
  • 🎚️ Log Level Control - Configurable log levels (error, warn, info, debug) to control output verbosity
  • πŸ’‘ Better Error Messages - Actionable error messages with installation instructions when formats aren't available
  • ✨ 100% Test Coverage - All statements, branches, functions, and lines covered

Important

v0.6.0 contains breaking changes: Type parameters are now required for all interfaces (e.g., IDatabaseMigrationHandler<IDB>) and the constructor signature changed to dependency injection pattern. Migration takes 10-30 minutes. See the v0.5.x β†’ v0.6.0 Migration Guide for step-by-step instructions.

β†’ View configuration docs


πŸ“œ Previous Releases

v0.5.0

Production-grade transaction management and cloud-native configuration:

  • πŸ”’ Transaction Management - Configurable modes (per-migration, per-batch, none) with automatic retry logic and isolation level control
  • βš™οΈ Environment Variables - Complete MSR_* configuration support following 12-factor app principles for Docker, Kubernetes, and CI/CD
  • πŸ“Š Enhanced Hooks - Transaction lifecycle hooks for monitoring and metrics collection
  • πŸš€ 100% Backward Compatible - Zero breaking changes from v0.4.x

β†’ View migration guide


✨ Features

  • πŸ”Œ Database Agnostic - Works with any database (SQL, NoSQL, NewSQL) by implementing a simple interface
  • πŸ›‘οΈ Type Safe - Full TypeScript support with complete type definitions
  • πŸ’Ύ Smart Rollback - Multiple strategies: backup/restore, down() methods, both, or none
  • πŸ”’ Transaction Control - Configurable transaction modes with automatic retry and isolation levels (v0.5.0)
  • βš™οΈ Environment Variables - Full 12-factor app configuration support with MSR_* variables (v0.5.0)
  • πŸ“„ Multi-Format Config - Support for JS, JSON, YAML, TOML, and XML configuration files (v0.6.0)
  • 🎚️ Log Level Control - Configurable verbosity (error, warn, info, debug) for different environments (v0.6.0)
  • πŸ“Š Migration Tracking - Maintains execution history in your database with checksums
  • βœ… Built-in Validation - Detects conflicts, missing files, and integrity issues
  • 🎨 Multiple Output Formats - ASCII tables, JSON, or silent output
  • πŸ“ Flexible Logging - Console, file, or custom loggers with level-aware filtering (v0.6.0)
  • πŸ“ˆ Metrics Collection - Built-in collectors for monitoring performance and tracking execution (v0.6.0)
  • πŸͺ Lifecycle Hooks - Process, script, backup, and transaction lifecycle hooks (v0.5.0)
  • πŸ“¦ Library-First Design - Returns structured results, safe for web servers and long-running apps

πŸ“¦ Installation

npm install @migration-script-runner/core

Or with yarn:

yarn add @migration-script-runner/core

πŸš€ Quick Start

1. Implement Database Handler

import { IDatabaseMigrationHandler, IDB, ISqlDB } from '@migration-script-runner/core';

// For SQL databases, implement ISqlDB
interface IMyDatabase extends ISqlDB {
  query(sql: string): Promise<unknown>;
}

export class MyDatabaseHandler implements IDatabaseMigrationHandler<IMyDatabase> {
  db: IMyDatabase;
  schemaVersion: ISchemaVersion<IMyDatabase>;
  backup?: IBackup<IMyDatabase>;

  async checkConnection(): Promise<void> {
    await this.db.query('SELECT 1');
  }

  getName(): string {
    return 'My Database Handler';
  }
}

2. Create Migration Script

TypeScript Migration:

// migrations/V202501280100_create_users.ts
import { IRunnableScript, IMigrationInfo, IDB } from '@migration-script-runner/core';

export default class CreateUsers implements IRunnableScript<IDB> {
  async up(db: IDB, info: IMigrationInfo): Promise<string> {
    await db.query(`
      CREATE TABLE users (
        id INT PRIMARY KEY,
        email VARCHAR(255) NOT NULL UNIQUE
      )
    `);
    return 'Users table created';
  }

  async down(db: IDB): Promise<string> {
    await db.query('DROP TABLE users');
    return 'Users table dropped';
  }
}

SQL Migration:

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

3. Run Migrations

import { MigrationScriptExecutor, Config } from '@migration-script-runner/core';
import { MyDatabaseHandler } from './database-handler';

const config = new Config();
config.folder = './migrations';
config.logLevel = 'info';  // v0.6.0: 'error' | 'warn' | 'info' | 'debug'

const handler = new MyDatabaseHandler();
const executor = new MigrationScriptExecutor<IMyDatabase>({ handler }, config);

// Library usage - returns structured result
const result = await executor.up();

if (result.success) {
  console.log(`βœ… Executed ${result.executed.length} migrations`);
} else {
  console.error('❌ Migration failed:', result.errors);
  process.exit(1);
}

Quick Config Examples:

# Environment variable configuration (v0.5.0+)
MSR_FOLDER=./migrations
MSR_LOG_LEVEL=debug  # v0.6.0: Control output verbosity

# Or use config file (v0.6.0+)
# msr.config.yaml
folder: ./migrations
logLevel: debug  # error | warn | info | debug

πŸ“š Documentation

πŸ“– Full Documentation - Complete guides, API reference, and examples

Getting Started

Configuration & Customization

Reference

Upgrading


🌱 Why MSR Exists

MSR was born from a real problem: In 2017, while building a mobile app with Firebase, a small team needed to backup and restore production data multiple times a week. Manual processes meant constant risk of corrupting critical data before the app even launched. The solution? A JavaScript tool that automated migrations with automatic backups and intelligent rollback.

Six years and many projects later, that prototype became MSR - completely rewritten in TypeScript with a database-agnostic architecture. The core insight: migration tools should be as flexible as your stack. Whether you're migrating Firebase collections or PostgreSQL tables, using SQL files or TypeScript logic, MSR adapts to your needs instead of forcing you into rigid patterns.

Today, MSR powers migrations across multiple database platforms with features traditional tools don't offer: built-in backup/restore, polyglot migrations (SQL + TypeScript + JavaScript), custom validators, transaction control, and deep customization. It's designed for real-world scenarios where you need both the simplicity of SQL migrations and the power of programmatic logic.

Read the full origin story β†’


🎯 Why MSR?

Bring your own database. MSR doesn't lock you into a specific ORM or database system. Whether you're using PostgreSQL, MongoDB, DynamoDB, or a custom database, MSR handles the migration workflow while you maintain full control.

Perfect for:

  • πŸ”Œ Any database system (SQL, NoSQL, NewSQL, or custom)
  • 🎯 Production applications (returns structured results instead of calling process.exit())
  • πŸ›‘οΈ Type-safe migrations with full TypeScript support
  • πŸ“¦ Library or CLI usage in web servers, workers, or serverless functions
  • ⚑ Flexible workflows with multiple rollback strategies and lifecycle hooks
  • 🐳 Container deployments with environment variable configuration (v0.5.0)

What makes MSR different:

  • Library-first design - Safe for web servers and long-running applications
  • True database agnosticism - No SQL assumptions, works with any database
  • Production-grade transactions - Configurable modes with automatic retry and isolation control (v0.5.0)
  • Cloud-native configuration - Complete environment variable support for Docker/Kubernetes (v0.5.0)
  • Multiple rollback strategies - Choose backup, down() methods, both, or none
  • SQL file support - Use .up.sql and .down.sql files alongside TypeScript migrations
  • Well tested - 100% code coverage with mutation testing

🀝 Contributing

Contributions are welcome! Please read our Contributing Guide for guidelines on code style, testing requirements, and pull request process.

See our GitHub Issues for tasks that need help.


πŸ“„ License

This project is licensed under the MIT License with Commons Clause and Attribution Requirements.

Note

Quick Summary:

  • βœ… Free to use in your applications (including commercial)
  • βœ… Free to modify and contribute
  • ❌ Cannot sell MSR or database adapters as standalone products
  • πŸ”’ Database adapters require attribution

See the LICENSE file or read the License Documentation for detailed examples and FAQ.


πŸ“ž Support


By Volodymyr Lavrynovych β€’ Created in Ukraine πŸ‡ΊπŸ‡¦

About

Migration Script Runner

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •