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.
@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.
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 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 with the config module from NestJS, 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!
Top comments (3)
Hey! I just found this answer and while I could get it to work with
isGlobal: true
, I didn't want that so I fiddled around a bit and figured out..isGlobal: true
MongoDBConfigService
fromAppModule
'sproviders: []
, it's not needed.MongoDBConfigService
fromTypeOrmModule
'sinject: []
, it's not needed (remove inject entirely).import: [ConfigModule],
insideTypeOrmModule
's config object.Thank you Raphael, I was looking for something like this
Thank you Raphael!!!