Based on work of mandarvl at sequelize-typescript-migration.
Full credits to mmRoshani, mandarvl, kimjbstar, mricharz, syon-development, viinzzz and lou2013 for the awesome lib.
npm i @techntools/sequelize-typescript-migration
// Or
yarn add @techntools/sequelize-typescript-migrationIt is based on sequelize-typescript and does not support "sequelize" based model codes and you need prior knowledge of migration of Sequelize.
This scans models and its decorators to find changes, and generates migration code with this changes so don't need to write up, down function manually. This is like makemigration in django framework.
After generation is successful, you can use "migrate" in Sequelize Migration Manual
Sometimes, undo(down) action may not work, then you should modify manually. Maybe it's because of ordering of relations of models. That issue is currently in the works.
- sequelize@^6.37.7
- sequelize-typescript@^2.1.6
import { join } from 'path'
import { Sequelize } from "sequelize-typescript";
import { SequelizeTypescriptMigration } from "sequelize-typescript-migration-lts";
const sequelize: Sequelize = new Sequelize({
// .. options
});
await SequelizeTypescriptMigration.makeMigration(sequelize, {
outDir: join(__dirname, './migrations'),
migrationName: "add-awesome-field-in-my-table",
preview: false,
});If you have these two models and run first makeMigration, it detects all table changes from nothing.
@Table
export class CarBrand extends Model<CarBrand> {
@Column
name: string;
@Default(true)
@Column(DataType.BOOLEAN)
isCertified: boolean;
@Column
imgUrl: string;
@Column
orderNo: number;
@Column
carsCount: number;
}@Table
export class Car extends Model<Car> {
@Column
name: string;
@ForeignKey(() => CarBrand)
@Column
carBrandId: number;
@BelongsTo(() => CarBrand)
carBrand: CarBrand;
}This will generate 00000001-noname.js in migrations path.
"use strict";
var Sequelize = require("sequelize");
/**
* Actions summary:
*
* createTable "CarBrands", deps: []
* createTable "Cars", deps: [CarBrands]
*
**/
var info = {
revision: 1,
name: "noname",
created: "2020-04-12T15:49:58.814Z",
comment: "",
};
var migrationCommands = [
{
fn: "createTable",
params: [
"CarBrands",
{
id: {
autoIncrement: true,
primaryKey: true,
allowNull: false,
type: Sequelize.INTEGER,
},
name: {
type: Sequelize.STRING,
},
isCertified: {
type: Sequelize.BOOLEAN,
},
imgUrl: {
type: Sequelize.STRING,
},
orderNo: {
type: Sequelize.INTEGER,
},
carsCount: {
type: Sequelize.INTEGER,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
},
},
{},
],
},
{
fn: "createTable",
params: [
"Cars",
{
id: {
autoIncrement: true,
primaryKey: true,
allowNull: false,
type: Sequelize.INTEGER,
},
name: {
type: Sequelize.STRING,
},
carBrandId: {
onDelete: "NO ACTION",
onUpdate: "CASCADE",
references: {
model: "CarBrands",
key: "id",
},
allowNull: true,
type: Sequelize.INTEGER,
},
createdAt: {
allowNull: false,
type: Sequelize.DATE,
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE,
},
},
{},
],
},
];
var rollbackCommands = [
{
fn: "dropTable",
params: ["Cars"],
},
{
fn: "dropTable",
params: ["CarBrands"],
},
];
module.exports = {
pos: 0,
up: function (queryInterface, Sequelize) {
var index = this.pos;
return new Promise(function (resolve, reject) {
function next() {
if (index < migrationCommands.length) {
let command = migrationCommands[index];
console.log("[#" + index + "] execute: " + command.fn);
index++;
queryInterface[command.fn]
.apply(queryInterface, command.params)
.then(next, reject);
} else resolve();
}
next();
});
},
down: function (queryInterface, Sequelize) {
var index = this.pos;
return new Promise(function (resolve, reject) {
function next() {
if (index < rollbackCommands.length) {
let command = rollbackCommands[index];
console.log("[#" + index + "] execute: " + command.fn);
index++;
queryInterface[command.fn]
.apply(queryInterface, command.params)
.then(next, reject);
} else resolve();
}
next();
});
},
info: info,
};Run npx sequelize db:migrate --to 00000001-noname.js to apply this
Make sure to have writeMigration in your System under development and that sequelize is all set up.
If you change a model and re-run the backend there should be a new file under db/migrations, but the database won't update automatically. There are easy but important steps:
- Rename the file's name as well as the content (Info: name), so that everyone knows what this migration is about
- Migrate your database with
sequelize db:migrate - Re-Serve the backend. You should see no changes.
- Test the automatically created file's down function with
sequelize db:migrate:undo - If there are any troubles, fix the auto-generated file (ordering!)
- Run
sequelize db:migrate:undoand continue your amazing work