@migration-script-runner/core
v0.8.4
Published
Migration Script Runner - Core Framework
Maintainers
Readme
Migration Script Runner
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.8.0
Production-ready locking, enhanced type safety, and critical bug fixes:
- 🔒 Migration Locking - Prevent concurrent migrations with database-level locking mechanism for multi-instance deployments
- 🛡️ Lock Ownership Verification - Two-phase locking with ownership verification prevents race conditions and ensures safe execution
- 🖥️ Lock CLI Commands - New
lock:statusandlock:releasecommands for managing locks in production environments - 🔧 Handler Generic Type - Type-safe handler access in adapters with optional second generic parameter (no more casting!)
- 🐛 Down Migration Fix - Fixed TypeError when rolling back migrations (migration records now properly matched with filesystem scripts)
- 📦 npm Provenance - Enhanced supply chain security with build provenance attestations
- ✨ 100% Backwards Compatible - Zero breaking changes from v0.7.x, all features are opt-in
✅ NO BREAKING CHANGES in v0.8.0: Fully backwards compatible with v0.7.x. Locking is disabled by default and can be enabled when ready. Handler generic type is optional with sensible defaults. See the v0.7.x → v0.8.0 Migration Guide for upgrade instructions and new features.
📜 Previous Releases
For information about previous releases, see the Version Migration Guide.
✨ Features
- 🔒 Migration Locking - Database-level locking prevents concurrent migrations in multi-instance deployments (v0.8.0)
- 🖥️ CLI Factory - Built-in command-line interface with migrate, list, down, validate, backup, and lock commands (v0.7.0+)
- 🔌 Database Agnostic - Works with any database (SQL, NoSQL, NewSQL) by implementing a simple interface
- 🛡️ Type Safe - Full TypeScript support with complete type definitions and handler generics (v0.8.0)
- 💾 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)
- 🗂️ .env File Support - Load configuration from .env, .env.production, .env.local, etc. with priority control (v0.7.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/coreOr 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 | debugCLI Usage (v0.7.0)
Create a CLI for your database adapter:
// cli.ts
import { createCLI, MigrationScriptExecutor } from '@migration-script-runner/core';
import { MyDatabaseHandler } from './database-handler';
const program = createCLI({
name: 'my-db-migrate',
version: '1.0.0',
description: 'Database migration CLI',
createExecutor: (config) => {
const handler = new MyDatabaseHandler();
return new MigrationScriptExecutor({ handler, config });
}
});
program.parse(process.argv);Run migrations from command line:
# Run all pending migrations
npx my-db-migrate migrate
# List all migrations with status
npx my-db-migrate list
# Rollback last migration
npx my-db-migrate down
# Validate migrations without running
npx my-db-migrate validate
# Create database backup
npx my-db-migrate backup
# Check lock status (v0.8.0)
npx my-db-migrate lock:status
# Force-release stuck lock (v0.8.0)
npx my-db-migrate lock:release --force
# Run migration without locking (v0.8.0)
npx my-db-migrate migrate --no-lock
# Use environment-specific config
npx my-db-migrate migrate --config-file .env.production📚 Documentation
📖 Full Documentation - Complete guides, API reference, and examples
Getting Started
- Getting Started Guide - Complete setup walkthrough
- Writing Migrations - Best practices and patterns
- SQL Migrations - Using .sql migration files
- Version Control - Target specific versions
Configuration & Customization
- Configuration - Migration settings, validation, rollback strategies
- Custom Loggers - Console, file, or cloud logging
- Metrics Collection - Built-in collectors for observability and performance monitoring
- Render Strategies - ASCII tables, JSON, or custom formats
- Validation - Custom validation rules
Reference
- API Reference - Complete API documentation
- Recipes - Common patterns (PostgreSQL, MongoDB, testing)
- Comparison - Compare with other migration tools
Upgrading
- Version Migration - Upgrade guides between versions
🌱 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.
🎯 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.sqland.down.sqlfiles 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.
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
- 📚 Documentation: https://migration-script-runner.github.io/msr-core/
- 🐛 Issues: https://github.com/migration-script-runner/msr-core/issues
- 💬 Discussions: https://github.com/migration-script-runner/msr-core/discussions
- 📦 npm: https://www.npmjs.com/package/@migration-script-runner/core
By Volodymyr Lavrynovych • Created in Ukraine 🇺🇦
