Continuing from the last article, we should already have a defined ConfigModule and environment variables.
To set up the data base connection in this case it's just a matter of a few lines of code.
In my example I will use a Postgresql database, but it can be any type of database.
- Install the
npm install --save @nestjs/typeorm typeorm@0.3 pg
.pg
is the Postgresql driver used by Typeorm to connect to the database. For each individual database it will be a different driver, e.g.sql2
,mongoose
and others. The typeorm we installed is v0.3, in the nestJs documentation it is recommended to use the v0.2 but it's compatible and newer, If you dislike it you can use v0.2. - Create in the project's folder a
typeorm
folder with atypeorm.service.ts
file. - Add to the file the following:
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { TypeOrmModuleOptions, TypeOrmOptionsFactory } from '@nestjs/typeorm';
import { IEnvironment } from './../environments/env.interface';
@Injectable()
export class TypeOrmConfigService implements TypeOrmOptionsFactory {
constructor(private config: ConfigService) {}
public createTypeOrmOptions(): TypeOrmModuleOptions {
const db = this.config.get<IEnvironment['database']>('database') as IEnvironment['database'];
const productionMode = this.config.get<IEnvironment['production']>('production') as IEnvironment['production'];
return {
type: 'postgres',
host: db.host,
port: db.port,
database: db.database,
username: db.username,
password: db.password,
// migrations: ['dist/migrations/*.{ts,js}'],
logger: 'file',
synchronize: !productionMode, // never use TRUE in production!
autoLoadEntities: true,
};
}
}
Special mentions about this:
- migrations are disabled. We will come back to them in a different article because they are managed outside of Nx and NestJs using the TypeOrm Cli.
- the synchronize is turned on only in non-production environment
Now all that it remained is to use this class in the AppModule(or a separate DatabaseModule if you would like to have a more granular approach)
- Go to
app.module.ts
and add in the importsTypeOrmModule.forRootAsync({ useClass: TypeOrmConfigService })
For example, my app.module.ts looks like this
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import { getEnvConfig } from './environments/env-config';
import { envValidation } from './environments/env-validator';
import { TypeOrmConfigService } from './typeorm/typeorm.service';
@Module({
imports: [
ConfigModule.forRoot({
load: [getEnvConfig],
isGlobal: true,
cache: true,
validate: envValidation,
}),
TypeOrmModule.forRootAsync({ useClass: TypeOrmConfigService })
],
controllers: [],
providers: [],
})
export class AppModule {}
That was it, next step would be creating models and services. A good documentation about that is here
Thanks for reading!
Top comments (8)
You nailed it bro, I wonder how can i run migrations on production environment with docker.
Personally I wouldn't run anything from docker, it's not exacyly it's purpose.
Most probably you would do better with a custom script and config for production env.
In that way you can run local migrations without deploying the code to the docker image, and you just need the connection string and the migrations.
Doing migrations has changed since type orm 0.3 old cli into typeormoptions are not there anymore. am i right?
From what I read on their website you just need to create a class for migrations and use it in a cli command. Technically you can inject/create the options object in the same way and reuse it in that class.
Unfortunately I can't provide yet some boilerplate for that. In my current project I switched rather early on from Typeorm to MikroOrm, but in this aspect they seem rather similar so this approach should work.
The only noticeable difference is that for MikroOrm I managed to find a third party executable that is able to run for a specific project, for this you might need to either have a global config or a custom script to run from a different path.
Looking forward into your posts about migration, i'm still trying to grasp the concepts of monorepo and all that jazz witnin this series of posts worked well for me, I also tried your approach into mirkoorm and it worked, still my concerns are on migrations, what third party tool did you use?
I used @alexy4744/nx-mikro-orm-cli
I can actually provide some snippets for this., they might be useful for after you use the instructions from the package's page.
./mikro-orm.base.ts - at the root of the nx project I have a config that can be propagated for any number of projects
Please change any paths that might be different for your project.
Then in my
backend
project I have/apps/backend/project.json -> under the "target" options
/apps/backend/mikro-orm.ts
As you can see I just reused the functions from the previous articles to get the env variables from the env file or from the environment.
Also in the
data acces
folder which for me hosts the entities i have aDatabaseSeeder.ts
file that gets the repositories and populates the data.I cannot post that one as it is 100% custom made for my project's needs and it wouldn't be useful at all, but I can post a small snippet
I hope this helps!
There must be something wrong with webpack i tried your approach it wont detect entities on runtime thats just sad, i just made another class to do my migrations i use this approach on runtime i use your previous service inject approach, but i manually override entity locations. Thank you!
Yes. Webpack packs everything together in a single bundle and i suppose the paths are ruined in that case.
For that Nest has the "autoLoadEntories" option vut you need to import every entity in the ORM's module for it to work.