Configure TypeORM migrations in 5 minutes
Tags: nestjs, typeorm, javascript, typescript
Published: 2023-10-15 08:39:24

Database migrations are a crucial part of any robust, scalable application, allowing you to manipulate your database schema without touching the data. If you're building a NestJS application, you'll find that TypeORM is one of the most powerful tools available for this. In this blog post, we'll delve into how to manage database migrations effectively in TypeORM.

## Setting Up the NestJS App Module

The first step to handling migrations in TypeORM is to set up your `app.module.ts` file. You can configure the `TypeOrmModule` to automatically run migrations when the application starts.

Here is an example:

```typescript
// app.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigService } from '@nestjs/config';

@Module({
  imports: [
    TypeOrmModule.forRootAsync({
      inject: [ConfigService],
      useFactory: (config: ConfigService) => ({
        type: 'postgres',
        url: config.get<string>('DB_URL'),
        migrations: ['/migrations/*{.ts,.js}'],
        migrationsTableName: '_migrations',
        migrationsRun: true,  // Auto-run migrations
        entities: ['dist/**/*.entity{.ts,.js}'],
        synchronize: !!config.get<string>('DB_SYNC') || false,
        logging: true,
      }),
    }),
    // Other modules
  ],
})
export class AppModule {}
```

### Key Points

- `migrationsRun: true`: This will run the migration files automatically when your application starts.
- `synchronize: false`: This should be set to false in production as it can drop your database tables.

## Install TS-Node

You will need `ts-node` to execute TypeScript files directly for migration purposes.

Install it as a development dependency:

```bash
npm install ts-node --save-dev
```

## NPM Scripts for Migrations

Add these scripts in your `package.json` file:

```json
{
  "scripts": {
    "typeorm": "ts-node ./node_modules/typeorm/cli",
    "typeorm:run-migrations": "npm run typeorm migration:run -- -d ./typeOrm.config.ts",
    "typeorm:generate-migration": "npm run typeorm -- -d ./typeOrm.config.ts migration:generate ./migrations/$npm_config_name",
    "typeorm:create-migration": "npm run typeorm -- migration:create ./migrations/$npm_config_name",
    "typeorm:revert-migration": "npm run typeorm -- -d ./typeOrm.config.ts migration:revert"
  }
}
```

## TypeORM Configuration

Create a `typeorm.config.ts` file:

```typescript
// typeorm.config.ts
import { DataSource } from 'typeorm';
import { ConfigService } from '@nestjs/config';
import { config } from 'dotenv';

config();

const configService = new ConfigService();

export default new DataSource({
  type: 'postgres',
  url: configService.get<string>('DB_URL'),
  entities: ['dist/**/*.entity{.ts,.js}'],
  migrations: ['dist/migrations/*.js'],
});
```

## The Magic of `generate-migration`: Auto-detecting Changes in Entities

One of the most powerful features of TypeORM is its ability to automatically detect changes in your entities and generate the appropriate migration files for you. This saves you the manual labor of writing SQL queries for each change in your entity. The `generate-migration` command comes in very handy for this purpose.

### How It Works

The `generate-migration` command compares the entities in your project with your database's current state and generates a new migration file containing all the SQL queries needed to transition your database schema to match your entities.

Here's how you can use it:

```bash
npm run typeorm:generate-migration -- --name=YourMigrationName
```

Replace `YourMigrationName` with a name that describes the changes in this migration.

### Example

Suppose you have an existing `User` entity, and you add a new column `email`. 

```typescript
@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column()  // Newly added
  email: string;
}
```

If you run `generate-migration`, TypeORM will automatically detect the new `email` column and generate the necessary SQL query to add this column to the `user` table in your database.

### Important Note

Although this feature is incredibly helpful, it's not a complete substitute for understanding your database schema and migrations. It is good practice to review the generated migration files and test them in a controlled environment before applying them to your production database.

## Using the NPM Scripts

Now you can use the following commands:

- Run Migrations: \`\`\`npm run typeorm:run-migrations\`\`\`
- Generate Migrations: \`\`\`npm run typeorm:generate-migration -- --name=MigrationName\`\`\`
- Create Empty Migration: \`\`\`npm run typeorm:create-migration -- --name=MigrationName\`\`\`
- Revert Last Migration: \`\`\`npm run typeorm:revert-migration\`\`\`

And that's it! You're now ready to manage your database schema changes effectively using migrations in TypeORM with a NestJS application.

Would you like to know more details about any specific part of the process? I'd be happy to clarify or go into more detail!