NestJS and TypeORM database configuration
Tags: javascript, nestjs, typeorm
Published: 2021-05-04 21:47:47

After some initial problems I had with this topic, I decided to spend some time to look into different options. Here is an overview of the results:

# Static configuration in the code

This is the most obvious way to configure the database. Just write the parameters (url, username, …) in the code, where you import the [TypeORM](https://docs.nestjs.com/techniques/database#typeorm-integration).

```
@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'localhost',
      port: 3306,
      username: 'root',
      password: 'root',
      database: 'test',
      entities: [],
      synchronize: true,
    }),
  ],
})
export class AppModule {}
```

There are a lot of problems with this. You can’t easily change this in a deployed application, it clutters your `app.module.ts` file and if you commit this to a public repository, you make your database access data public. Also if you always hard code configurations like this, you might end up having them all over the place in your code.
So while this is fine for a quick test in your development environment, I wouldn’t recommend using this for much more than that.

# Configuring TypeORM using ormconfig.json

TypeORM offers the possibility to pass configuration parameters for one or more databases using an `ormconfig.json` [file](https://typeorm.io/#/using-ormconfig/using-ormconfigjson).

This file includes all the relevant configuration options. In my case it was not much:

```
{
    "type": "mongodb",
    "url": "mongodb+srv://<username>:<password>@some.subdomains.of.mongodb.net/<databasename>"
}
```

When using the `ormconfig.json`, you should not put any options in the `app.module.ts`, where you import TypeORM.

Configuring TypeORM this way is a clean solution, you have one file for the database connection(s) and you can configure more than one database in this file. The downside is, that you have to have this additional file. So in some environments, where you may not be able to access all the files of the application, changing that database might be difficult.

# Configuring TypeORM with environment variables

As described [here](https://typeorm.io/#/using-ormconfig/using-environment-variables) it is possible to configure TypeORM using environment variables. TypeORM offers a list of different variables to use in this case. This uses either a `.env`-file or the actual environment variables.

A limitation of this method is, that it is only possible to configure one database. But if you only need one database in your application, this is a good way to quickly configure TypeORM depending on the environment.

# Configuring TypeORM with a configuration service

This combines the asynchronous configuration that is described in the NestJS [documentation] (https://docs.nestjs.com/techniques/database#async-configuration) with the config module from [NestJS](https://docs.nestjs.com/techniques/configuration), that supports in getting values from the environment variables. 

Basically you have to create a service, that can be injected into the TypeORM import and that implements the `TypeOrmOptionsFactory` interface. The values this service provides to TypeORM are retrieved from the NestJS config module.

For my mongodb this looks like this:

```
import { Injectable } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { TypeOrmModuleOptions, TypeOrmOptionsFactory } from "@nestjs/typeorm";

@Injectable()
export class MongoDBConfigService implements TypeOrmOptionsFactory {

    constructor(private configService: ConfigService) {}

    createTypeOrmOptions(): TypeOrmModuleOptions {
        return {
            type: 'mongodb',
            url: this.configService.get<string>('MONGODB_URL'),
            username: this.configService.get<string>('MONGODB_USER'),
            password: this.configService.get<string>('MONGODB_PASSWORD'),
    };
  }
}
```

You can create such a service per database you need. Using it to configure TypeORM in your `app.module.ts` would look like this:

```
@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true
    }),
    TypeOrmModule.forRootAsync({
      useClass: MongoDBConfigService,
      inject: [MongoDBConfigService]
    })
  ],
  controllers: [AppController],
  providers: [AppService, MongoDBConfigService],
})

export class AppModule {}
```

The advantage of this method, is that you can configure multiple databases from the environment of the app and keep your app.module.ts more or less clean. The downside is, it takes a few more steps to set up.


Since I am new to NestJS and TypeORM, I’m writing down what I’m learning. So if I missed a method to do this or anything I wrote is incorrect, please let me know!