sequelize-schema-sync
Version:
Drizzle-like migrations for Sequelize - sync your models to database schema automatically
347 lines (277 loc) • 8.95 kB
Markdown
# sequelize-schema-sync
🔥 **Drizzle-like migrations for Sequelize** - Automatically generate migrations from your Sequelize models, just like Drizzle ORM but for Sequelize!
[](https://badge.fury.io/js/sequelize-schema-sync)
[](https://opensource.org/licenses/MIT)
## ✨ 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
```bash
npm install sequelize-schema-sync
# or
yarn add sequelize-schema-sync
```
### Basic Setup
1. **Initialize configuration**:
```bash
npx sequelize-schema-sync init
```
2. **Configure your models in `schema-sync.config.ts`**:
```typescript
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;
```
3. **Generate your first migration**:
```bash
npx sequelize-schema-sync generate
```
4. **Apply migrations**:
```bash
npx sequelize-schema-sync migrate
```
## 📋 CLI Commands
### `generate`
Generate a new migration based on model changes
```bash
npx sequelize-schema-sync generate
npx sequelize-schema-sync generate --name "add_user_avatar"
npx sequelize-schema-sync generate --dry-run
```
**Options:**
- `-n, --name <name>` - Custom migration name
- `--dry-run` - Preview changes without generating files
### `migrate`
Run all pending migrations
```bash
npx sequelize-schema-sync migrate
```
### `rollback`
Rollback the last applied migration
```bash
npx sequelize-schema-sync rollback
```
### `status`
Show migration status
```bash
npx sequelize-schema-sync status
```
### `init`
Initialize a new `schema-sync.config.ts` file
```bash
npx sequelize-schema-sync init
```
## 📖 How It Works
1. **Define Models**: Create your Sequelize models as usual
2. **Run Generate**: The tool compares your models against the current database schema
3. **Automatic Diff**: Detects changes like new tables, columns, type changes, etc.
4. **Generate Migration**: Creates a timestamped migration file with `up` and `down` functions
5. **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:
```typescript
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)
```typescript
const config: SchemaSyncConfig = {
sequelize,
models: [User, Post, Comment], // Import and list your models
migrationsPath: './migrations',
};
```
### Option 2: Directory-based Loading (Recommended)
```typescript
const config: SchemaSyncConfig = {
sequelize,
modelsPath: './models', // Auto-discover models from directory
migrationsPath: './migrations',
};
```
**Model Factory Pattern:**
```typescript
// 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:
```bash
npx sequelize-schema-sync generate --dry-run
```
**Example 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
```typescript
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
```typescript
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`:
```typescript
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:
```typescript
// 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/`](./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](LICENSE) file for details.
## � Acknowledgments
- Built on top of [Umzug](https://github.com/sequelize/umzug) for migration management
- Inspired by [Drizzle ORM](https://orm.drizzle.team/) migration approach
- Powered by [Sequelize](https://sequelize.org/)