Migration Script Runner Logo Migration Script Runner

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

Get started now View all features View on GitHub


Why MSR?

Bring your own database. MSR provides a lightweight, flexible framework for managing database migrations without locking 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 over your database operations.

Perfect for

  • 🔌 Any database system - SQL, NoSQL, NewSQL, or custom databases
  • 🎯 Production applications - Returns structured results instead of calling process.exit()
  • 🛡️ Type-safe migrations - Full TypeScript support with type definitions
  • 📦 Library or CLI - Use as a library in your app or run from command line
  • Flexible workflows - Multiple rollback strategies, validation, and hooks

Key Features

🔌

Database Agnostic

Bring your own database

Works with any database system - SQL, NoSQL, NewSQL, or custom. Implement a simple interface and MSR handles the rest.

🛡️

Type Safe

Full TypeScript support

Generic type parameters provide database-specific type safety with full IDE autocomplete. Catch errors at compile time, not runtime.

💾

Smart Rollback

4 strategies for every scenario

Four rollback strategies: automatic backup/restore, down() methods, both, or none. Choose what fits your database best.

Built-in Validation

Prevent errors before they happen

Automatically detects duplicate timestamps, missing files, and checksum mismatches before migrations run.

🎯

Production Ready

Library-first design

Returns structured results instead of process.exit(). Safe for web servers, workers, and any long-running application.

🪝

Extensible

Customize everything

Lifecycle hooks, custom loggers, output renderers, and validators. Extend MSR to match your workflow perfectly.

→ View all features - Complete feature list with detailed descriptions


What’s New in v0.6.0

🎉 Latest release brings database-specific type safety:

  • 🎯 Generic Type Parameters - Full type safety for database-specific operations with IDatabaseMigrationHandler<DB>, IRunnableScript<DB>, and MigrationScriptExecutor<DB> (BREAKING: type parameters now required)
  • 💡 Enhanced IDE Support - Full autocomplete and IntelliSense for database-specific methods (no more as any casting!)
  • 🛡️ Compile-Time Validation - Catch database errors at compile time, not runtime
  • 🔍 Enhanced Type Guards - Type-preserving isImperativeTransactional<DB>() and isCallbackTransactional<DB, TxContext>() functions
  • 🔨 Breaking Changes - Type parameters required for all interfaces, constructor signature changed to dependency injection pattern

Quick Start

Installation

npm install @migration-script-runner/core

1. Implement Database Handler

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

// Define your database type for full type safety (v0.6.0+)
interface IMyDatabase extends IDB {
  query(sql: string, params?: unknown[]): Promise<unknown[]>;
}

export class MyDatabaseHandler implements IDatabaseMigrationHandler<IMyDatabase> {
  db: IMyDatabase;  // ✅ Typed database connection
  schemaVersion: ISchemaVersion<IMyDatabase>;

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

  getVersion(): string {
    return '1.0.0';
  }

  // Implement schema version tracking and optionally backup
}

2. Create Migration Script

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

interface IMyDatabase extends IDB {
  query(sql: string): Promise<unknown[]>;
}

export default class CreateUsers implements IRunnableScript<IMyDatabase> {
  async up(db: IMyDatabase, info: IMigrationInfo): Promise<string> {
    // ✅ Full autocomplete for db.query() - no casting needed!
    await db.query(`
      CREATE TABLE users (
        id INT PRIMARY KEY AUTO_INCREMENT,
        email VARCHAR(255) NOT NULL UNIQUE,
        name VARCHAR(255)
      )
    `);
    return 'Users table created';
  }

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

3. Run Migrations

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

const config = new Config();
config.folder = './migrations';

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

// Library usage - returns result object
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);
}

Documentation

Getting Started

  • Getting Started - Installation, basic usage, and quick start
  • Guides - Comprehensive guides and practical examples

Reference

  • API Reference - Complete API documentation for all classes and interfaces
  • Configuration - Migration, validation, rollback, and backup settings

Advanced

  • Extending MSR - Extend MSR with custom loggers, renderers, and validators
  • Architecture - System design, components, and data flow

Project


What Makes MSR Different?

Library-First Design

Unlike most migration tools, MSR returns structured results instead of calling process.exit(). This makes it safe to use in:

  • Web servers (Express, Fastify, NestJS)
  • Background workers
  • Serverless functions
  • Any long-running application

True Database Agnosticism

MSR doesn’t assume SQL or any specific database system. Use it with:

  • SQL databases: PostgreSQL, MySQL, SQLite
  • NoSQL databases: MongoDB, DynamoDB, Cassandra
  • NewSQL databases: CockroachDB, TiDB
  • Custom systems: Your proprietary database or data store

Flexible Rollback Strategies

Choose the right rollback strategy for your needs:

  • BACKUP - Automatic backup and restore (default, safest)
  • DOWN - Execute down() methods for rollback
  • BOTH - Try down() first, fallback to backup
  • NONE - No rollback (for append-only systems)

Project Status

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


Community & Support


License

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

Quick Summary:

  • Free to use in your applications and products
  • Free to modify and contribute
  • Cannot sell MSR or adapters as standalone products
  • 🔒 Attribution required for database adapters and extensions

Read the full license documentation for detailed examples and FAQ.


Made in Ukraine