The pnpm migrate command safely manages database schema changes. It automatically generates migrations based on Entity definitions and can apply them consistently across multiple databases.
Basic Concept
Migration is a system for version controlling database schema changes:
Entity-based : Auto-generate migrations from Entity definitions
Sequential execution : Apply migrations in creation order
Multi-DB support : Manage multiple databases simultaneously
Auto-detection : Automatically detect Entity changes and generate code
Commands
status - Check Status
Check the current migration status.
Output example :
Development Master: ✓ Up to date (v20240115_143022)
Testing: ⚠ 2 pending migrations
Production: ✓ Up to date (v20240115_143022)
Prepared migrations:
• 20240116_101530_add_user_profile
• 20240116_102045_create_posts_table
Status types :
✓ Up to date: All migrations applied
⚠ N pending: N migrations not yet applied
❌ Error: Database connection failed
run - Run Migrations
Apply all pending migrations.
Execution process :
Running migrations...
Development Master:
✓ 20240116_101530_add_user_profile (0.2s)
✓ 20240116_102045_create_posts_table (0.3s)
Testing:
✓ 20240116_101530_add_user_profile (0.2s)
✓ 20240116_102045_create_posts_table (0.3s)
All migrations completed successfully!
Auto-generation and application :
Detect Entity changes
Auto-generate migration code
Apply sequentially to all target DBs
Sonamu analyzes Entity definitions and automatically generates necessary migrations. No need
to manually write migration files.
Migration Generation
Auto-generation
When you modify an Entity, Sonamu automatically generates a migration.
// Change Entity definition
const UserEntity = {
properties: [
{
name: "email" ,
type: "string" ,
length: 255 ,
},
// Add new field
{
name: "phone" ,
type: "string" ,
length: 20 ,
nullable: true ,
},
],
};
# Check status
pnpm migrate status
# Output:
# Prepared migrations:
# • 20240116_103045_add_phone_to_users
# Apply
pnpm migrate run
Migration Files
Generated migration files are stored in the src/migrations/ directory.
src/migrations/20240116_103045_add_phone_to_users.ts
import type { Knex } from "knex" ;
export async function up ( knex : Knex ) : Promise < void > {
await knex . schema . alterTable ( "users" , ( table ) => {
table . string ( "phone" , 20 ). nullable ();
});
}
export async function down ( knex : Knex ) : Promise < void > {
await knex . schema . alterTable ( "users" , ( table ) => {
table . dropColumn ( "phone" );
});
}
Structure :
up(): Apply migration (create tables, add columns, etc.)
down(): Rollback migration (revert changes)
Supported Changes
Changes that Sonamu auto-detects and generates migrations for:
Change Type Description Example Table creation Add new Entity Create PostEntity Column addition Add new property Add phone field Column modification Change type/length varchar(100) → varchar(255)Column deletion Remove property Delete deprecated_field Index addition Define index indexes arrayForeign key addition Define relationship belongsTo relation
Multi-Database Management
Sonamu can manage multiple databases simultaneously.
Database Configuration
export default {
database: {
// Development environment - master
development_master: {
client: "mysql2" ,
connection: {
host: "localhost" ,
database: "myapp_dev" ,
user: "root" ,
password: "password" ,
},
},
// Development environment - slave (read-only)
development_slave: {
// Slaves are automatically ignored
},
// Test environment
test: {
client: "mysql2" ,
connection: {
host: "localhost" ,
database: "myapp_test" ,
user: "root" ,
password: "password" ,
},
},
// Production environment
production: {
client: "mysql2" ,
connection: {
host: "prod-db.example.com" ,
database: "myapp_prod" ,
user: "root" ,
password: process . env . DB_PASSWORD ,
},
},
} ,
} ;
Migration targets :
Databases ending with _master
All databases not ending with _slave
Batch Application
# Apply to all databases
pnpm migrate run
# Output:
# Development Master: ✓ 2 migrations applied
# Testing: ✓ 2 migrations applied
# Production: ✓ 2 migrations applied
Practical Workflow
1. Change Entity
const UserEntity = {
properties: [
// Existing fields...
{
name: "profile_image" ,
type: "string" ,
nullable: true ,
},
],
};
2. Check Status
Prepared migrations:
• 20240116_110230_add_profile_image_to_users
3. Apply Migration
✓ All migrations applied successfully!
4. Update Code
class UserModelClass extends BaseModelClass {
async updateProfileImage ( userId : number , imageUrl : string ) {
await this . getPuri ( "w" ). update ({ profile_image: imageUrl }). where ( "id" , userId );
}
}
Advanced Usage (Programmatic)
Advanced features not provided via CLI commands can be implemented using the Migrator class directly.
Using Migrator Class
src/scripts/migration-tools.ts
import { Migrator } from "sonamu" ;
const migrator = new Migrator ();
// Rollback (last batch)
await migrator . runAction ( "rollback" , [ "development_master" ]);
// Select specific databases only
await migrator . runAction ( "apply" , [ "test" ]);
// Check status (programmatic)
const status = await migrator . getStatus ();
console . log ( status );
Rollback Script
src/scripts/rollback-migration.ts
import { Migrator , Sonamu } from "sonamu" ;
Sonamu . runScript ( async () => {
const migrator = new Migrator ();
console . log ( "Rolling back last migration batch..." );
await migrator . runAction ( "rollback" , [ "development_master" , "test" ]);
console . log ( "Rollback completed!" );
});
Run :
pnpm tsx src/scripts/rollback-migration.ts
Data loss risk : Rollback can delete tables or columns, so use very carefully in
production .
Available Actions
Actions supported by Migrator.runAction():
Action Description Use Case applyApply migrations Apply new schema changes rollbackRollback last batch Revert mistaken migrations
Troubleshooting
Migration Conflict
Problem : Multiple developers create migrations simultaneously
Error: Migration conflict detected
Solution :
# 1. Get latest code
git pull
# 2. Check migration status
pnpm migrate status
# 3. Regenerate migrations if needed
pnpm migrate run
Database Connection Failed
Problem : DB connection failed
Error: connect ECONNREFUSED 127.0.0.1:3306
Solution :
# 1. Check MySQL is running
mysql -u root -p -e "SHOW DATABASES;"
# 2. Check connection info
cat sonamu.config.ts
# 3. Create database
mysql -u root -p -e "CREATE DATABASE myapp_dev;"
Migration Order Error
Problem : Applied in wrong order
Error: Foreign key constraint violation
Solution :
When there are foreign key references, referenced tables must be created first.
Fix method 1: Programmatic rollback and reapply
// Rollback
const migrator = new Migrator ();
await migrator . runAction ( "rollback" , [ "development_master" ]);
// Modify migration filename (adjust timestamp)
// 20240116_110230_*.ts → 20240116_110231_*.ts
// Reapply
await migrator . runAction ( "apply" , [ "development_master" ]);
Fix method 2: Adjust Entity definition order
// Adjust Entity file order to create users table first
// Then run pnpm migrate run
Best Practices
1. Apply Frequently
# Migrate frequently in small units
pnpm migrate run # Daily
2. Test Before Production
# Verify in test DB first
pnpm migrate status
pnpm migrate run
# Apply to production if no issues
3. Backup Required
# Backup before production migration
mysqldump -u root -p myapp_prod > backup_ $( date +%Y%m%d ) .sql
# Apply migration
pnpm migrate run
4. Consider Rollback Possibility
// ✅ Rollback possible - down() function properly defined
export async function up ( knex : Knex ) {
await knex . schema . alterTable ( "users" , ( table ) => {
table . string ( "phone" ). nullable ();
});
}
export async function down ( knex : Knex ) {
await knex . schema . alterTable ( "users" , ( table ) => {
table . dropColumn ( "phone" );
});
}
5. Version Control with Git
# Commit migration files to Git
git add src/migrations/
git commit -m "Add phone field to users table"
# Share with team
git push
Next Steps
Entity Learn more about Entity definitions