DEV Community

Anshul Jangale
Anshul Jangale

Posted on • Edited on

1 1 1

Migrations with Sequelize-Typescript

Sequelize is a popular ORM for Node.js, but using it with TypeScript—especially for migrations—can be challenging. This guide will walk you through setting up Sequelize properly with TypeScript, focusing on database migrations.

Sequelize officially supports TypeScript, but its Sequelize-cli tool generates JavaScript files for migrations. This creates several issues:

  • TypeScript errors in your project
  • ESLint parsing errors
  • Inconsistent codebase with mixed JS/TS files

Solution Overview
We'll implement a proper TypeScript setup for Sequelize migrations by:

  1. Creating a custom .sequelizerc configuration
  2. Setting up a workflow for TypeScript migrations
  3. Configuring project files correctly
  4. Creating a script to automate migration generation

Step 1: Project Setup

First, ensure your tsconfig.json is properly configured:

{
  "compilerOptions": {
    "target": "es2016",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "module": "commonjs",
    "rootDir": "./src",
    "baseUrl": "./",
    "outDir": "./dist",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  },
  "exclude": ["node_modules", "__tests__"],
  "include": ["src/**/*.ts"]
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Create a Custom .sequelizerc File

Create a .sequelizerc file in your project root:

const { resolve } = require('path');

module.exports = {
    config: resolve('build/db/config.js'),
    'seeders-path': resolve('build/db/seeders'),
    'migrations-path': resolve('build/db/migrations'),
    'models-path': resolve('db/models')
};
Enter fullscreen mode Exit fullscreen mode

Step 3: TypeScript Migration Workflow

To create and run migrations with TypeScript:

  • Generate migration files using the CLI:

npx sequelize-cli migration:create --name add-some-table

  • The migration file will be generated in "build/db/migrations". Move the generated file to your actual application TypeScript migrations folder and rename it with a .ts extension.

  • Replace the content with this TypeScript template:

import { QueryInterface, DataTypes, QueryTypes } from 'sequelize';

/** @type {import("sequelize-cli").Migration} */
module.exports = {
    up: (queryInterface: QueryInterface): Promise<void> => queryInterface.sequelize.transaction(
        async (transaction) => {
          // here go all migration changes
        }
    ),

    down: (queryInterface: QueryInterface): Promise<void> => queryInterface.sequelize.transaction(
        async (transaction) => {
          // here go all migration undo changes
        }
    )
};
Enter fullscreen mode Exit fullscreen mode
  • add necessary changes to the migration file

OR ANOTHER OPTION (RUNNING SCRIPT)

TO AUTOMATE THIS STEP YOU CAN CREATE A SCRIPT WHICH WILL AUTOMATICALLY CREATE THIS FILE

  • Generate migration files using the CLI:

npx sequelize-cli migration:create --name add-some-table

import fs from 'fs';
import path from 'path';

// Get migration name from command-line arguments
const migrationName = process.argv[2];

if (!migrationName) {
  console.error('❌ Please provide a migration name.');
  process.exit(1);
}

// Define paths
const migrationsDir = path.resolve(__dirname, 'db/migrations');
const timestamp = new Date().toISOString().replace(/\D/g, '').slice(0, 14); // YYYYMMDDHHMMSS
const fileName = `${timestamp}-${migrationName}.ts`;
const filePath = path.join(migrationsDir, fileName);

// Migration template
const migrationTemplate = `import { QueryInterface, DataTypes } from "sequelize";

/** @type {import("sequelize-cli").Migration} */
export default {
  up: async (queryInterface: QueryInterface): Promise<void> => {
    await queryInterface.sequelize.transaction(async (transaction) => {

    //your code here 

    });
  },

  down: async (queryInterface: QueryInterface): Promise<void> => {
    await queryInterface.sequelize.transaction(async (transaction) => {

      //your code here

    });
  },
};

`;

// Ensure migrations directory exists
if (!fs.existsSync(migrationsDir)) {
  fs.mkdirSync(migrationsDir, { recursive: true });
}

// Write migration file
fs.writeFileSync(filePath, migrationTemplate);

console.log(`✅ Migration created: ${filePath}`);

Enter fullscreen mode Exit fullscreen mode

To run this script:
npx ts-node path/to/generateMigration.ts add-some-table

Step 4: Running Migrations

To run migrations, you need to:

Compile your TypeScript files
Run the migrations on the compiled JavaScript files

Add these scripts to your package.json:


"scripts": {
  "dev": "ts-node-dev --respawn --transpile-only src/index.ts",
  "build": "tsc -p .",
  "start": "node build/dist/index.js",
  "prestart": "npm install --production",
  "migrate:generate":"npx ts-node src/generateMigration.ts",
  "migrate": "tsc -p . & npx sequelize-cli db:migrate ",
  "migrate:undo": "npx sequelize-cli db:migrate:undo ",
  "migrate:undo:all": "npx sequelize-cli db:migrate:undo:all "
},
Enter fullscreen mode Exit fullscreen mode

Conclusion

By following these steps, you've successfully set up Sequelize with TypeScript for migrations. This approach gives you:

  • Type safety in your migrations
  • Consistent codebase with TypeScript throughout
  • Properly working ESLint
  • Streamlined migration workflow

Your development process is now more robust and you can enjoy the benefits of TypeScript while using Sequelize migrations.

AWS GenAI LIVE image

Real challenges. Real solutions. Real talk.

From technical discussions to philosophical debates, AWS and AWS Partners examine the impact and evolution of gen AI.

Learn more

Top comments (0)

AWS Q Developer image

Your AI Code Assistant

Automate your code reviews. Catch bugs before your coworkers. Fix security issues in your code. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

👋 Kindness is contagious

DEV is better (more customized, reading settings like dark mode etc) when you're signed in!

Okay