Setting Up a NestJS Project with TypeORM

Cover Image for Setting Up a NestJS Project with TypeORM
Majid Ali Khan
Majid Ali Khan

28-06-2024

Step 1: Install NestJS CLI

First, install the NestJS CLI globally:

npm i -g @nestjs/cli

Step 2: Create a New NestJS Project

Generate a new NestJS project using the CLI:

nest new backend

I named my project "backend" because I'm using a monorepo setup, with the backend and frontend in the same repository.

Step 3: Understand the Project Structure

The project will come with some starter files:

/src
 - app.controller.spec.ts
 - app.controller.ts
 - app.module.ts
 - app.service.ts
 - main.ts

Step 4: Configure Environments

We'll create a configuration module to handle different environments (test, development, production).

1. Generate the configuration module and service:
nest g module config
nest g service config

These commands will create the necessary files and folder structure.

2. Import the ConfigModule in AppModule:

import { Module } from '@nestjs/common';
import { ConfigModule } from './config/config.module';

@Module({
  imports: [
    ConfigModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
3. Modify ConfigService:

import { Injectable } from '@nestjs/common';
import * as dotenv from 'dotenv';
import * as fs from 'fs';

@Injectable()
export class ConfigService {
  private envConfig: { [key: string]: string };

  constructor() {
    const nodeEnv = process.env.NODE_ENV;
    console.log(nodeEnv);

    const envFile = `${nodeEnv}.env`;
    this.envConfig = dotenv.parse(fs.readFileSync(envFile));
  }

  loadEnv(envFile: string): void {
    this.envConfig = dotenv.parse(fs.readFileSync(envFile));
  }

  get(key: string): string {
    return this.envConfig[key];
  }
}

Create the required environment files in the src directory, like .env.test, .env.development, and .env.production.

Step 6: Edit package.json Scripts

Update the package.json to start the NestJS server with the specified environment:

"scripts": {
  "build": "nest build",
  "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
  "start": "NODE_ENV=production node dist/main",
  "start:dev": "cross-env NODE_ENV=development nest start --watch",
  "start:debug": "cross-env NODE_ENV=development nest start --debug --watch",
  "start:prod": "NODE_ENV=production node dist/main"
}

Step 7: Modify main.ts to Load Environment Files

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { CorsOptions } from '@nestjs/common/interfaces/external/cors-options.interface';
import { ConfigService } from './config/config.service';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  const configService = app.get(ConfigService);
  app.setGlobalPrefix('/api/v1');
  app.enableCors({ origin: '*' } as CorsOptions);

  const env = process.env.NODE_ENV || 'dev';
  const envFile = `${env}.env`;
  configService.loadEnv(envFile);

  await app.listen(3000);
}
bootstrap();

Step 8: Install TypeORM

For our model classes, we'll use TypeORM. Install it with the following command:

npm i --save @nestjs/typeorm typeorm

Step 9: Create TypeORM Configuration

Create a typeOrmConfig.ts file in src/config:

import { TypeOrmModuleOptions } from '@nestjs/typeorm';
import { ConfigService } from './config.service';

export const typeOrmConfig: TypeOrmModuleOptions = {
  type: 'postgres',
  host: new ConfigService().get('HOST'),
  port: parseInt(new ConfigService().get('PORT')),
  username: new ConfigService().get('USERNAME'),
  password: new ConfigService().get('PASSWORD'),
  database: new ConfigService().get('DATABASE'),
  entities: [__dirname + '/../**/*.entity.js'],
  synchronize: false,
};

The ConfigService().get() method retrieves environment variables from the specified environment file.

Step 10: Use TypeORM Configuration in AppModule

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { typeOrmConfig } from './config/typeOrmConfig';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule } from './config/config.module';

@Module({
  imports: [
    TypeOrmModule.forRoot(typeOrmConfig),
    ConfigModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

Step 11: Modify main.ts for Database Connection

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { createConnection } from 'typeorm';
import { typeOrmConfig } from './config/typeOrmConfig';
import { CorsOptions } from '@nestjs/common/interfaces/external/cors-options.interface';
import { ConfigService } from './config/config.service';

async function bootstrap() {
  try {
    await createConnection(typeOrmConfig as any);
    console.log('Database connection successful');
  } catch (error) {
    console.error('Database connection error:', error.message);
  }

  const app = await NestFactory.create(AppModule);
  const configService = app.get(ConfigService);
  app.setGlobalPrefix('/api/v1');
  app.enableCors({ origin: '*' } as CorsOptions);

  const env = process.env.NODE_ENV || 'dev';
  const envFile = `${env}.env`;
  configService.loadEnv(envFile);

  await app.listen(3000);
}
bootstrap();

Conclusion

Our basic NestJS project setup with typeorm is now complete. Run the project and check for any issues or errors. If you encounter any problems, look for typos, check imports, or refer to the NestJS documentation for troubleshooting.

After running npm start dev, you should see output similar to this:

> backend@0.0.1 start
NODE_ENV=development node dist/main dev
>

development
development
development
development
development
Database connection successful
[Nest] 17928  - 06/28/2024, 4:56:01 PM     LOG [NestFactory] Starting Nest application...
development
[Nest] 17928  - 06/28/2024, 4:56:01 PM     LOG [InstanceLoader] TypeOrmModule dependencies initialized +31ms
[Nest] 17928  - 06/28/2024, 4:56:01 PM     LOG [InstanceLoader] ConfigModule dependencies initialized +1ms
[Nest] 17928  - 06/28/2024, 4:56:01 PM     LOG [InstanceLoader] AppModule dependencies initialized +1ms
[Nest] 17928  - 06/28/2024, 4:56:03 PM     LOG [InstanceLoader] TypeOrmCoreModule dependencies initialized +1928ms
[Nest] 17928  - 06/28/2024, 4:56:03 PM     LOG [InstanceLoader] TypeOrmModule dependencies initialized +1ms
[Nest] 17928  - 06/28/2024, 4:56:03 PM     LOG [NestApplication] Nest application successfully started +6ms
#nestcli#nestjs#typeorm
Majid Ali Khan
Open for Remote Work