How to create Sequelize migrations and seeders in the zoppy-api project. Use this skill whenever the user wants to add a new database table, add/remove/modify columns, create foreign key constraints, or seed initial data. Trigger on phrases like "criar migration", "nova tabela", "adicionar coluna", "foreign key", "seeder", "rollback", or when a new domain entity needs a database table. Make sure to use this skill for any database schema changes, even if the user just says "criar tabela X" without mentioning migrations explicitly.
npx sequelize-cli migration:generate --name create-your-entity
This creates src/db/migrations/<timestamp>-create-your-entity.ts.
Migrations are plain CommonJS modules with up and down functions. Always implement down — it's needed for npm run rollback.
'use strict';
module.exports = {
async up(queryInterface, Sequelize) {
await queryInterface.createTable('YourEntities', {
id: {
allowNull: false,
primaryKey: true,
defaultValue: Sequelize.UUIDV4,
type: Sequelize.UUID
},
name: {
allowNull: false,
type: Sequelize.STRING
},
description: {
allowNull: true,
type: Sequelize.TEXT
},
// Always include soft delete + timestamps
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
},
deletedAt: {
allowNull: true,
type: Sequelize.DATE
}
});
},
async down(queryInterface) {
await queryInterface.dropTable('YourEntities');
}
};
Sequelize.UUIDV4 as default — never integer auto-incrementdeletedAt DATE NULL — all tables use paranoid soft deletecreatedAt and updatedAt — always allowNull: falseCompanies, MessageTemplates)companyId, createdAt)companyId: {
allowNull: false,
type: Sequelize.UUID,
references: { model: 'Companies', key: 'id' }
// Note: companyId usually doesn't have CASCADE — companies are soft-deleted
},
parentId: {
allowNull: false,
type: Sequelize.UUID,
references: { model: 'ParentEntities', key: 'id' },
onUpdate: 'CASCADE',
onDelete: 'CASCADE'
}
Use onDelete: 'CASCADE' for "owned" relationships (e.g., message items belong to a message group — delete items when group is deleted). Skip cascade for companyId — companies are soft-deleted, not hard-deleted.