Create Custom Database Module in NestJS with TypeORM MySQL/PostgreSQL

Intro
First, Check out these articles for
Custom Database Setup for Sequelize: https://www.freecodecamp.org/news/build-web-apis-with-nestjs-beginners-guide/
Custom Database Setup for MongoDB: https://dev.to/10xtarun/create-custom-database-module-in-nestjs-4kim
I got a lot of inspiration from these articles especially from the first by Victor
Setup Project
We Create new nest project as,
$ nest new custom-db-project
We will also install all we need,
$ npm install --save @nestjs/typeorm @nestjs/config typeorm mysql2 dotenv
Now generate the custom database module as,
$ nest generate module core/database
...
Let's Code
Database Interface
Inside the database folder, create an interfaces folder, then create a dbConfig.interface.ts file inside it. This is for the database configuration interface.
Each of the database environments should optionally have the following properties.
export interface IDatabaseConfigAttributes {
    username?: string;
    password?: string;
    database?: string;
    host?: string;
    port?: number;
    type?: string;
    urlDatabase?: string;
    entities?: string[];
    migrationsTableName?: string;
    migrations?: string[];
    cli?: {
        migrationsDir?: string;
    }
    synchronize?: boolean;
}

export interface IDatabaseConfig {
    development: IDatabaseConfigAttributes;
    test: IDatabaseConfigAttributes;
    production: IDatabaseConfigAttributes;
}
Database Configuration
Now, let’s create a database environment configuration. Inside the database folder, create a database.config.ts file.
import * as dotenv from 'dotenv';
import { IDatabaseConfig } from './interfaces/dbConfig.interface';

dotenv.config();

let entities = [__dirname + '/**/*.entity{.ts,.js}']

let migrationsDir = 'src/migration';
let migrations = [migrationsDir + '/*.ts']

export const databaseConfig: IDatabaseConfig = {
    development: {
        username: process.env.DB_USER,
        password: process.env.DB_PASS,
        database: process.env.DB_NAME_DEVELOPMENT,
        host: process.env.DB_HOST,
        port: +process.env.DB_PORT,
        type: process.env.DB_DIALECT,
        entities: entities,
        migrationsTableName: process.env.DB_MIGRATION_TABLE_NAME,
        migrations: migrations,
        cli: {
            migrationsDir: migrationsDir
        },
        synchronize: true
    },
    test: {
        username: process.env.DB_USER,
        password: process.env.DB_PASS,
        database: process.env.DB_NAME_TEST,
        host: process.env.DB_HOST,
        port: +process.env.DB_PORT,
        type: process.env.DB_DIALECT,
        entities: entities,
        migrationsTableName: process.env.DB_MIGRATION_TABLE_NAME,
        migrations: migrations,
        cli: {
            migrationsDir: migrationsDir
        },
        synchronize: true
    },
    production: {
        username: process.env.DB_USER,
        password: process.env.DB_PASS,
        database: process.env.DB_NAME_PRODUCTION,
        host: process.env.DB_HOST,
        port: +process.env.DB_PORT,
        type: process.env.DB_DIALECT,
        entities: entities,
        migrationsTableName: process.env.DB_MIGRATION_TABLE_NAME,
        migrations: migrations,
        cli: {
            migrationsDir: migrationsDir
        },
        synchronize: true
    },
};
The environment will determine which configuration should be used.
.env file
On our project root folder, create a .env file
DB_HOST=localhost
DB_PORT=3306
DB_USER=database_user_name
DB_PASS=database_password
DB_DIALECT=postgres
DB_NAME_TEST=test_database_name
DB_NAME_DEVELOPMENT=development_database_name
DB_NAME_PRODUCTION=production_database_name
DB_MIGRATION_TABLE_NAME=migration
Don't forget to add .env to your .gitignore file.
Import the @nestjs/config
Import the @nestjs/config into your app root module:
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { DatabaseModule } from './core/database/database.module';

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true }),
    DatabaseModule
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
Victor Pointed out that Setting the ConfigModule.forRoot({ isGlobal: true }) to isGlobal: true will make the .env properties available throughout the application.
Database Provider
Let’s create a database provider. Inside the database folder, create a file called database.providers.ts.
The core directory will contain all our core setups, configuration, shared modules, pipes, guards, and middlewares.
In the database.providers.ts let's add
import { TypeOrmModule } from '@nestjs/typeorm';
import { TYPEORM ,DEVELOPMENT, TEST, PRODUCTION } from '../constants';
import { databaseConfig } from './database.config';

export const databaseProviders = [{
    provide: TYPEORM,
    useFactory: async () => {
      let config;
      switch (process.env.NODE_ENV) {
      case DEVELOPMENT:
         config = databaseConfig.development;
         break;
      case TEST:
         config = databaseConfig.test;
         break;
      case PRODUCTION:
         config = databaseConfig.production;
         break;
      default:
         config = databaseConfig.development;
      }

      const typeOrm = TypeOrmModule.forRoot(config);

      return typeOrm
    },
}];
Here, the application decides what environment we are currently running on and then chooses the environment configuration.
Best practice: It is a good idea to keep all string values in a constant file and export it to avoid misspelling those values. You'll also have a single place to change things.
Inside the core folder, create a constants folder and inside it create an index.ts file. Paste the following code:
export const TYPEORM = 'TYPEORM';
export const DEVELOPMENT = 'development';
export const TEST = 'test';
export const PRODUCTION = 'production';
I hope this article helps someone. Check out the article by Victor to get started with Nestjs

86

This website collects cookies to deliver better user experience

Create Custom Database Module in NestJS with TypeORM MySQL/PostgreSQL