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
Works with any database system - SQL, NoSQL, NewSQL, or custom. Implement a simple interface and MSR handles the rest.
Generic type parameters provide database-specific type safety with full IDE autocomplete. Catch errors at compile time, not runtime.
Four rollback strategies: automatic backup/restore, down() methods, both, or none. Choose what fits your database best.
Automatically detects duplicate timestamps, missing files, and checksum mismatches before migrations run.
Returns structured results instead of process.exit(). Safe for web servers, workers, and any long-running application.
→ 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>, andMigrationScriptExecutor<DB>(BREAKING: type parameters now required) - 💡 Enhanced IDE Support - Full autocomplete and IntelliSense for database-specific methods (no more
as anycasting!) - 🛡️ Compile-Time Validation - Catch database errors at compile time, not runtime
- 🔍 Enhanced Type Guards - Type-preserving
isImperativeTransactional<DB>()andisCallbackTransactional<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
- Version Migration - Upgrade guides for migrating between MSR versions
- Development - Contributing, testing, and development workflow
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
Community & Support
- 📚 Documentation: Full documentation site
- 🐛 Issues: GitHub Issues
- 📦 npm: @migration-script-runner/core
- 💬 Discussions: GitHub Discussions
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.