sequelize-schema-sync
v1.3.1
Published
Drizzle-like migrations for Sequelize - sync your models to database schema automatically
Maintainers
Readme
sequelize-schema-sync
🔥 Drizzle-like migrations for Sequelize - Automatically generate migrations from your Sequelize models, just like Drizzle ORM but for Sequelize!
✨ Features
- 📦 Models as Source of Truth - Define your schema using Sequelize models
- 🔄 Automatic Migration Generation - Compare models vs database and generate migrations
- 🚀 CLI Commands - Simple commands for generate, migrate, and rollback
- 📝 TypeScript Support - Full TypeScript support with type definitions
- 🎯 Powered by Umzug - Built on the reliable Umzug migration framework
- 🛠️ Production Ready - Handles complex schema changes, foreign keys, and more
- 📁 Directory-based Loading - Auto-discover models from directories
- 🔍 Dry-run Mode - Preview changes before generating migrations
- 🎲 Smart Naming - Auto-generates migration names when not provided
🚀 Quick Start
Installation
npm install sequelize-schema-sync
# or
yarn add sequelize-schema-syncBasic Setup
- Initialize configuration:
npx sequelize-schema-sync init- Configure your models in
schema-sync.config.ts:
import { Sequelize } from 'sequelize';
import { SchemaSyncConfig } from 'sequelize-schema-sync';
import { User } from './models/User';
import { Post } from './models/Post';
const sequelize = new Sequelize({
dialect: 'postgres', // or 'mysql', 'sqlite', etc.
host: 'localhost',
database: 'myapp',
username: 'user',
password: 'password',
});
const config: SchemaSyncConfig = {
sequelize,
// Option 1: Provide models array directly
models: [User, Post],
// Option 2: Auto-discover from directory (recommended)
// modelsPath: './models',
migrationsPath: './migrations',
};
export default config;- Generate your first migration:
npx sequelize-schema-sync generate- Apply migrations:
npx sequelize-schema-sync migrate📋 CLI Commands
generate
Generate a new migration based on model changes
npx sequelize-schema-sync generate
npx sequelize-schema-sync generate --name "add_user_avatar"
npx sequelize-schema-sync generate --dry-runOptions:
-n, --name <name>- Custom migration name--dry-run- Preview changes without generating files
migrate
Run all pending migrations
npx sequelize-schema-sync migraterollback
Rollback the last applied migration
npx sequelize-schema-sync rollbackstatus
Show migration status
npx sequelize-schema-sync statusinit
Initialize a new schema-sync.config.ts file
npx sequelize-schema-sync init📖 How It Works
- Define Models: Create your Sequelize models as usual
- Run Generate: The tool compares your models against the current database schema
- Automatic Diff: Detects changes like new tables, columns, type changes, etc.
- Generate Migration: Creates a timestamped migration file with
upanddownfunctions - Apply Changes: Use the migrate command to apply changes to your database
🏗️ Example Migration
When you change your models, the tool generates migrations like this:
import { QueryInterface, DataTypes } from 'sequelize';
export async function up(queryInterface: QueryInterface): Promise<void> {
await queryInterface.createTable('users', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
createdAt: {
type: DataTypes.DATE,
allowNull: false
},
updatedAt: {
type: DataTypes.DATE,
allowNull: false
}
});
}
export async function down(queryInterface: QueryInterface): Promise<void> {
await queryInterface.dropTable('users');
}📁 Model Loading Options
Option 1: Direct Model Array (Simple)
const config: SchemaSyncConfig = {
sequelize,
models: [User, Post, Comment], // Import and list your models
migrationsPath: './migrations',
};Option 2: Directory-based Loading (Recommended)
const config: SchemaSyncConfig = {
sequelize,
modelsPath: './models', // Auto-discover models from directory
migrationsPath: './migrations',
};Model Factory Pattern:
// models/User.ts
export const UserModel = (sequelize: Sequelize) => {
const User = sequelize.define('User', {
email: DataTypes.STRING,
name: DataTypes.STRING,
});
return User;
};🔍 Dry-run Mode
Preview what changes will be made before generating migrations:
npx sequelize-schema-sync generate --dry-runExample Output:
📊 Schema Analysis Results:
==================================================
Found 2 table(s) with changes:
📄 Table: users
Action: alter
→ Will modify 2 column(s):
- email: change
- avatar: add
📄 Table: posts
Action: create
→ Will create table with 5 columns: id, title, content, userId, createdAt
💡 To generate the migration file, run without --dry-run flag🎯 Supported Schema Changes
- ✅ Create new tables
- ✅ Drop tables
- ✅ Add columns
- ✅ Remove columns
- ✅ Change column types
- ✅ Add/remove primary keys
- ✅ Add/remove auto-increment
- ✅ Add/remove unique constraints
- ✅ Change default values
- ✅ Add/remove foreign keys
🛠️ Advanced Configuration
const config: SchemaSyncConfig = {
sequelize,
modelsPath: './models',
migrationsPath: './migrations',
// Optional: Custom config path
configPath: './custom-config.ts',
};⚙️ Sequelize Define Options
Configure global options for all your models using Sequelize's define option:
Basic Configuration
const sequelize = new Sequelize({
dialect: 'sqlite',
storage: './database.sqlite',
// Global define options for all models
define: {
charset: 'utf8mb4',
collate: 'utf8mb4_general_ci',
// Use snake_case for all auto-generated fields (timestamps, foreign keys, etc.)
underscored: true,
// Prevent table name pluralization
freezeTableName: true,
timestamps: true,
},
});MySQL/MariaDB Configuration
For MySQL and MariaDB, set charset and collation in both define and dialectOptions:
const sequelize = new Sequelize({
dialect: 'mysql',
host: 'localhost',
database: 'myapp',
username: 'user',
password: 'password',
// MySQL-specific options
dialectOptions: {
charset: 'utf8mb4',
collate: 'utf8mb4_general_ci',
},
// Global define options
define: {
charset: 'utf8mb4',
collate: 'utf8mb4_general_ci',
// Use snake_case for all auto-generated fields (timestamps, foreign keys, etc.)
underscored: true,
freezeTableName: true,
timestamps: true,
},
});Define Options Explained
| Option | Description | Example |
|--------|-------------|---------|
| charset | Character set for tables | 'utf8mb4' |
| collate | Collation for string comparisons | 'utf8mb4_general_ci' |
| underscored | Use snake_case for all auto-generated fields | true → createdAt becomes created_at, userId becomes user_id |
| freezeTableName | Prevent table name pluralization | true → User table stays User, not Users |
| timestamps | Add createdAt/updatedAt automatically | true |
Model Override Example
Individual models can override global define options:
// models/User.ts
export const UserModel = (sequelize: Sequelize) => {
return User.init({
email: DataTypes.STRING,
firstName: DataTypes.STRING, // Will be first_name in DB with underscored: true
}, {
sequelize,
modelName: 'User',
// Global options apply, but you can override:
// freezeTableName: false, // Would override global setting
// underscored: false, // Would override global setting
});
};📚 Examples
Check out the example/ directory for complete working examples:
- Directory-based model loading
- Factory function patterns
- TypeScript migration generation
- Migration execution and rollback
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
� Acknowledgments
- Built on top of Umzug for migration management
- Inspired by Drizzle ORM migration approach
- Powered by Sequelize
