Migrating from v0.1.x to v0.2.0
Guide for upgrading from v0.1.x to v0.2.0 of Firebase Migration Script Runner.
Table of Contents
- Overview
- Breaking Changes
- Step-by-Step Upgrade Guide
- Code Examples
- CLI Migration (Optional)
- Troubleshooting
- Verification Checklist
- New Features You Can Use (Optional)
- Common Migration Scenarios
- Testing Your Migration
- Rollback Plan
- Getting Help
- References
- Summary
Overview
v0.2.0 is a major upgrade that brings production-ready features and aligns with the MSR Core v0.8.1 ecosystem. This release contains one breaking change (package name) and introduces powerful new features for distributed deployments.
What’s New in v0.2.0
- 🔒 Migration Locking - Prevent concurrent migrations in Kubernetes, Docker, and multi-instance deployments
- ⬆️ MSR Core v0.8.1 - Latest core with bug fixes, handler access API, and improved locking lifecycle
- 🔧 Type-Safe API - Full TypeScript support with generic type parameters
- 🖥️ Lock Management CLI - Commands for monitoring and managing migration locks
- 📚 Comprehensive Documentation - 300+ line locking guide with deployment examples
- 🧪 Production Tested - Battle-tested in distributed environments
Migration Effort
Estimated Time: 5-15 minutes
Complexity: Low
- One breaking change (package name)
- Simple find-and-replace for imports
- All existing code continues to work after package update
- Optional new features can be adopted incrementally
Breaking Changes
1. Package Name Changed
The npm package name has changed to follow the organization’s scoped naming convention.
BEFORE (v0.1.x):
{
"dependencies": {
"msr-firebase": "^0.1.6"
}
}
AFTER (v0.2.0):
{
"dependencies": {
"@migration-script-runner/firebase": "^0.2.0"
}
}
Impact: You must update your package.json and all import statements.
Migration Required: Yes
Step-by-Step Upgrade Guide
Follow these steps carefully to ensure a smooth migration.
Step 1: Update Dependencies
Update your package.json:
# Remove old package
npm uninstall msr-firebase
# Install new scoped package
npm install @migration-script-runner/firebase@^0.2.0
Or with yarn:
yarn remove msr-firebase
yarn add @migration-script-runner/firebase@^0.2.0
Step 2: Update Package Name in package.json
BEFORE:
{
"dependencies": {
"msr-firebase": "^0.1.6"
}
}
AFTER:
{
"dependencies": {
"@migration-script-runner/firebase": "^0.2.0"
}
}
Step 3: Update Imports
Find and replace all import statements in your codebase.
In Your Migration Scripts
BEFORE:
import { IEntity } from 'msr-firebase';
import * as admin from 'firebase-admin';
export const up = async (db: admin.database.Database) => {
// Migration code
};
AFTER:
import { IEntity } from '@migration-script-runner/firebase';
import * as admin from 'firebase-admin';
export const up = async (db: admin.database.Database) => {
// Migration code
};
In Your Application Code
BEFORE:
import { FirebaseRunner, FirebaseConfig } from 'msr-firebase';
AFTER:
import { FirebaseRunner, FirebaseConfig } from '@migration-script-runner/firebase';
Step 4: Update CLI Usage (if applicable)
If you’re using the CLI directly, update your npm scripts:
BEFORE:
{
"scripts": {
"migrate": "msr-firebase migrate",
"rollback": "msr-firebase down"
}
}
AFTER:
{
"scripts": {
"migrate": "msr-firebase migrate",
"rollback": "msr-firebase down"
}
}
Note: The CLI command name remains msr-firebase (no change).
Step 5: Build Your Project
Compile TypeScript to ensure no import errors:
npm run build
Step 6: Run Tests
Verify everything works:
npm test
Step 7: Test Migrations
Test migrations in a development environment:
# Using Firebase Emulator
firebase emulators:start --only database
# In another terminal, run migrations
export FIREBASE_DATABASE_URL=http://localhost:9000
npx msr-firebase migrate
Code Examples
Complete Before/After Examples
Example 1: Basic Migration Script
BEFORE (v0.1.x):
// migrations/1234567890-add-users-table.ts
import { IEntity } from 'msr-firebase';
import * as admin from 'firebase-admin';
export const up = async (db: admin.database.Database) => {
await db.ref('users').set({
user1: { name: 'Alice', email: 'alice@example.com' }
});
};
export const down = async (db: admin.database.Database) => {
await db.ref('users').remove();
};
AFTER (v0.2.0):
// migrations/1234567890-add-users-table.ts
import { IEntity } from '@migration-script-runner/firebase';
import * as admin from 'firebase-admin';
export const up = async (db: admin.database.Database) => {
await db.ref('users').set({
user1: { name: 'Alice', email: 'alice@example.com' }
});
};
export const down = async (db: admin.database.Database) => {
await db.ref('users').remove();
};
Changes:
- Line 2: Import path changed to
@migration-script-runner/firebase
Example 2: Programmatic Usage
BEFORE (v0.1.x):
// src/migrate.ts
import { FirebaseHandler, FirebaseRunner, FirebaseConfig } from 'msr-firebase';
async function runMigrations() {
const config = new FirebaseConfig();
config.folder = './migrations';
config.tableName = 'schema_version';
config.databaseUrl = process.env.FIREBASE_DATABASE_URL;
const handler = await FirebaseHandler.getInstance(config);
const runner = new FirebaseRunner({ handler, config });
const result = await runner.migrate();
console.log(`Migrations completed: ${result.executed.length}`);
}
runMigrations().catch(console.error);
AFTER (v0.2.0):
// src/migrate.ts
import { FirebaseHandler, FirebaseRunner, FirebaseConfig } from '@migration-script-runner/firebase';
async function runMigrations() {
const config = new FirebaseConfig();
config.folder = './migrations';
config.tableName = 'schema_version';
config.databaseUrl = process.env.FIREBASE_DATABASE_URL;
const handler = await FirebaseHandler.getInstance(config);
const runner = new FirebaseRunner({ handler, config });
const result = await runner.migrate();
console.log(`Migrations completed: ${result.executed.length}`);
}
runMigrations().catch(console.error);
Changes:
- Line 2: Import path changed to
@migration-script-runner/firebase
Example 3: Using Services
BEFORE (v0.1.x):
// src/data-service.ts
import { FirebaseDataService, IEntity } from 'msr-firebase';
import * as admin from 'firebase-admin';
interface IUser extends IEntity {
name: string;
email: string;
}
class UserService {
private dataService: FirebaseDataService;
constructor(db: admin.database.Database) {
this.dataService = new FirebaseDataService(db);
}
async getUser(path: string): Promise<IUser | null> {
return await this.dataService.getObject<IUser>(path);
}
}
AFTER (v0.2.0):
// src/data-service.ts
import { FirebaseDataService, IEntity } from '@migration-script-runner/firebase';
import * as admin from 'firebase-admin';
interface IUser extends IEntity {
name: string;
email: string;
}
class UserService {
private dataService: FirebaseDataService;
constructor(db: admin.database.Database) {
this.dataService = new FirebaseDataService(db);
}
async getUser(path: string): Promise<IUser | null> {
return await this.dataService.getObject<IUser>(path);
}
}
Changes:
- Line 2: Import path changed to
@migration-script-runner/firebase
CLI Migration (Optional)
If you’re upgrading to use the CLI for the first time, follow these steps:
1. Install Package Globally (Optional)
npm install -g @migration-script-runner/firebase
Or use npx (recommended):
npx msr-firebase --version
2. Create Configuration File
Create msr.config.js in your project root:
module.exports = {
folder: './migrations',
tableName: 'schema_version',
locking: {
enabled: process.env.NODE_ENV === 'production',
timeout: 600000 // 10 minutes
}
};
3. Set Environment Variables
export FIREBASE_DATABASE_URL=https://your-project.firebaseio.com
export GOOGLE_APPLICATION_CREDENTIALS=./serviceAccountKey.json
4. Run Migrations
# Create new migration
npx msr-firebase create add-posts-table
# Apply all pending migrations
npx msr-firebase migrate
# Roll back last migration
npx msr-firebase down
# Check migration status
npx msr-firebase list
5. Use New Lock Commands (v0.2.0)
# Check lock status
npx msr-firebase lock:status
# Force-release stuck lock
npx msr-firebase lock:release --force
Troubleshooting
Issue 1: Module Not Found Error
Error:
Error: Cannot find module 'msr-firebase'
Solution:
- Ensure you’ve uninstalled the old package:
npm uninstall msr-firebase - Install the new package:
npm install @migration-script-runner/firebase - Update all import statements to use
@migration-script-runner/firebase - Clear node_modules and reinstall:
rm -rf node_modules && npm install
Issue 2: TypeScript Compilation Errors
Error:
Cannot find module 'msr-firebase' or its corresponding type declarations
Solution:
- Update all imports to
@migration-script-runner/firebase - Delete
dist/directory:rm -rf dist - Rebuild:
npm run build
Issue 3: Import Errors in Migration Scripts
Error:
Error: Cannot find module 'msr-firebase' from 'migrations/...'
Solution: Update imports in all migration script files:
# On Linux/Mac
find ./migrations -type f -name "*.ts" -exec sed -i '' 's/msr-firebase/@migration-script-runner\/firebase/g' {} +
# On Windows (PowerShell)
Get-ChildItem -Path ./migrations -Filter *.ts -Recurse | ForEach-Object {
(Get-Content $_.FullName) -replace 'msr-firebase', '@migration-script-runner/firebase' | Set-Content $_.FullName
}
Issue 4: CLI Command Not Found
Error:
msr-firebase: command not found
Solution:
- Use npx instead:
npx msr-firebase migrate - Or install globally:
npm install -g @migration-script-runner/firebase - Verify installation:
npm list -g @migration-script-runner/firebase
Issue 5: Lock Errors After Upgrade
Error:
LockOperationError: Failed to acquire lock
Solution: This is expected if you have an existing migration running or a stale lock:
- Check lock status:
npx msr-firebase lock:status - If lock is stale, force-release:
npx msr-firebase lock:release --force - Retry migration:
npx msr-firebase migrate
Verification Checklist
Use this checklist to ensure your migration is complete:
Package Updates
- Removed old
msr-firebasepackage frompackage.json - Installed new
@migration-script-runner/firebasepackage - Updated package version to
^0.2.0
Import Statements
- Updated imports in all migration scripts
- Updated imports in application code
- Updated imports in test files
- No references to
msr-firebaseremain in codebase
Build & Tests
- TypeScript compiles without errors
- All unit tests pass
- All integration tests pass
- No import errors in console
Migration Testing
- Tested migration creation:
npx msr-firebase create test-migration - Tested migration execution:
npx msr-firebase migrate(in dev environment) - Tested rollback:
npx msr-firebase down(in dev environment) - Tested migration status:
npx msr-firebase list
Production Readiness (Optional)
- Reviewed locking configuration for production
- Tested lock commands:
lock:statusandlock:release - Updated deployment scripts/CI/CD pipelines
- Verified environment variables are set correctly
Documentation
- Updated README if you have project-specific docs
- Updated package.json scripts if needed
- Updated deployment documentation
- Informed team members of the upgrade
New Features You Can Use (Optional)
After completing the migration, consider adopting these new v0.2.0 features:
1. Migration Locking (Recommended for Production)
Prevent concurrent migrations in distributed environments:
// msr.config.js
module.exports = {
folder: './migrations',
tableName: 'schema_version',
locking: {
enabled: process.env.NODE_ENV === 'production',
timeout: 600000, // 10 minutes
retryAttempts: 3,
retryDelay: 5000
}
};
Benefits:
- Prevents race conditions in Kubernetes/Docker deployments
- Automatic lock expiration and cleanup
- Force-release stuck locks with CLI
2. Lock CLI Commands
Manage migration locks:
# Check current lock status
npx msr-firebase lock:status
# Force-release stuck lock
npx msr-firebase lock:release --force
Output Example:
Lock Status: LOCKED
Locked by: server-prod-12345-a1b2c3d4
Locked at: 2025-12-18T10:00:00.000Z
Expires at: 2025-12-18T10:10:00.000Z
Process ID: 12345
Another migration is currently running.
If you believe this is a stale lock, use: npx msr-firebase lock:release --force
3. Type-Safe Handler Access
Use generic type parameters for better type safety:
import { FirebaseRunner, FirebaseHandler } from '@migration-script-runner/firebase';
// Type-safe handler access
const runner = new FirebaseRunner({ handler, config });
const handler: FirebaseHandler = runner.getHandler();
// Full IDE autocomplete support
const connectionInfo = runner.getConnectionInfo();
console.log(connectionInfo.databaseUrl);
Common Migration Scenarios
Scenario 1: Basic Application
Time: 5 minutes
- Update
package.jsondependencies - Run find-and-replace:
msr-firebase→@migration-script-runner/firebase - Rebuild and test
npm uninstall msr-firebase
npm install @migration-script-runner/firebase@^0.2.0
npm run build
npm test
Scenario 2: Kubernetes/Docker Deployment
Time: 10-15 minutes
- Complete basic migration (Scenario 1)
- Enable locking in configuration
- Test lock behavior in staging
- Update deployment manifests
- Deploy to production
// msr.config.js (production)
module.exports = {
folder: './migrations',
tableName: 'schema_version',
locking: {
enabled: true,
timeout: 600000
}
};
Scenario 3: Monorepo with Multiple Services
Time: 15-30 minutes
- Update root
package.json(if shared) - Update each service’s imports
- Update shared migration scripts
- Test each service independently
- Test inter-service migration coordination
# Update all services
for dir in services/*/; do
cd "$dir"
npm uninstall msr-firebase
npm install @migration-script-runner/firebase@^0.2.0
npm run build && npm test
cd ../..
done
Testing Your Migration
1. Local Testing with Emulator
# Start Firebase Emulator
firebase emulators:start --only database
# In another terminal
export FIREBASE_DATABASE_URL=http://localhost:9000
npx msr-firebase migrate
2. Staging Environment Testing
# Set staging credentials
export FIREBASE_DATABASE_URL=https://your-project-staging.firebaseio.com
export GOOGLE_APPLICATION_CREDENTIALS=./staging-key.json
# Run migrations
npx msr-firebase migrate
# Verify
npx msr-firebase list
3. Lock Behavior Testing (if enabled)
# Start first migration
npx msr-firebase migrate &
# Try concurrent migration (should fail with lock error)
npx msr-firebase migrate
# Check lock status
npx msr-firebase lock:status
Rollback Plan
If you encounter critical issues, you can rollback:
# Reinstall old package
npm uninstall @migration-script-runner/firebase
npm install msr-firebase@^0.1.6
# Revert import changes (if you used git)
git checkout HEAD -- .
# Or manually revert imports
# (reverse all @migration-script-runner/firebase → msr-firebase)
Note: It’s recommended to test the upgrade in a development/staging environment before production.
Getting Help
If you encounter issues during migration:
- Check Documentation: https://migration-script-runner.github.io/msr-firebase/
- GitHub Issues: https://github.com/migration-script-runner/msr-firebase/issues
- MSR Core Docs: https://migration-script-runner.github.io/msr-core/
- Open New Issue: Use
v0.2.0andmigrationlabels
References
- MSR Core v0.7→v0.8 Migration Guide
- Migration Locking Guide
- Configuration Reference
- CLI Usage Guide
- API Documentation
Summary
v0.2.0 brings production-ready features with minimal migration effort.
Key Takeaways
- ✅ One breaking change: package name
msr-firebase→@migration-script-runner/firebase - 🔄 Simple migration: update package + find-and-replace imports
- 🔒 New features: Migration locking, lock CLI commands, type-safe API
- ⏱️ 5-15 minutes for most projects
- 🔙 Easy rollback if needed
Recommended Actions
- Upgrade immediately - Simple find-and-replace migration
- Test in development - Verify all migrations work
- Enable locking for production - Prevent concurrent migration issues
- Update CI/CD pipelines - Use new package name in deployment scripts
Migration at a Glance
# Quick migration (5 minutes)
npm uninstall msr-firebase
npm install @migration-script-runner/firebase@^0.2.0
# Update imports (use your IDE's find-and-replace)
# Find: from 'msr-firebase'
# Replace: from '@migration-script-runner/firebase'
npm run build && npm test
Happy migrating! 🚀