Starting a NestJS Project: A Comprehensive Guide

Starting a NestJS Project: A Comprehensive Guide

· 4 min read

Introduction

In today's rapidly evolving application development landscape, efficient and scalable setup is essential for building robust applications. At CyberMind Works, we leverage NestJS and Mikro-ORM to create scalable, maintainable, and high-performance applications. This blog post will guide you through the steps to set up NestJS with Mikro-ORM as the ORM of choice.

Why Choose NestJS?

NestJS offers a robust architecture that incorporates elements from Object-Oriented Programming (OOP), Functional Programming (FP), and Functional Reactive Programming (FRP). Here are key reasons why NestJS is an excellent choice:

  1. TypeScript Support: Ensures type safety and scalability.
  2. Modular Architecture: Promotes code reusability and maintainability.
  3. Dependency Injection: Simplifies testing and managing complex dependencies.
  4. Seamless Integration: Works well with other libraries such as TypeORM and Mongoose.

Why We Chose Mikro-ORM?

Mikro-ORM is a TypeScript ORM for Node.js based on Data Mapper, Unit of Work, and Identity Map patterns. It supports various SQL and NoSQL databases and provides advanced features like migrations, seeding, and caching. Mikro-ORM's flexibility, TypeScript support, and active development community make it an excellent choice for our applications.

Project Setup: Setting Up NestJS

Prerequisites

Ensure you have the following installed on your machine:

  • Node.js (version 12 or later)
  • npm (Node Package Manager)

Installation

  1. Install NestJS CLI: The CLI is a powerful tool for initializing, developing, and maintaining NestJS applications.
npm install -g @nestjs/cli

1. Create a New Project: Use the CLI to create a new project.

nest new project-name

2. Navigate to Project Directory:

cd project-name

Project Structure

NestJS provides a well-organized project structure out of the box:

  • src/: Contains the main application code.
  • app.module.ts: The root module.
  • main.ts: The entry point.
  • test/: Contains unit and end-to-end tests.

Adding Mikro-ORM

Next, we will add Mikro-ORM to our NestJS project.

1. Install Mikro-ORM and dependencies:

npm install @mikro-orm/core @mikro-orm/migrations @mikro-orm/nestjs

# For PostgreSQL, use:
npm install @mikro-orm/postgresql pg

2. Install TypeScript and other necessary tools:

npm install typescript ts-node @types/node --save-dev

Configuring Mikro-ORM

To configure Mikro-ORM, we need to set up the `mikro-orm.config.ts` file and configure it in our NestJS project.

Create `mikro-orm.config.ts` in the project root:

import { Logger, NotFoundException } from '@nestjs/common';
import { LoadStrategy, defineConfig } from '@mikro-orm/core';
import { SqlHighlighter } from '@mikro-orm/sql-highlighter';
import { TsMorphMetadataProvider } from '@mikro-orm/reflection';
import { PostgreSqlDriver } from '@mikro-orm/postgresql';
import { Migrator } from '@mikro-orm/migrations';
import 'dotenv/config';

const logger = new Logger('MikroORM');

const config = defineConfig({
  entities: ['dist/**/*.entity.js'],
  entitiesTs: ['src/**/*.entity.ts'],
  driver: PostgreSqlDriver,
  loadStrategy: LoadStrategy.JOINED,
  clientUrl: 'postgresql://postgres:password@localhost:5432/db_name' as string,
  highlighter: new SqlHighlighter(),
  debug: true,
  logger: logger.log.bind(logger),
  metadataProvider: TsMorphMetadataProvider,
  allowGlobalContext: true,
  migrations: {
    tableName: 'mikro_orm_migrations',
    path: './migrations',
    glob: '!(*.d).{js,ts}',
    transactional: true,
    disableForeignKeys: true,
    allOrNothing: true,
    dropTables: false,
    safe: true,
    emit: 'ts', // migration generation mode
  },
  extensions: [Migrator],
  findOneOrFailHandler: (entityName) => {
    throw new NotFoundException(`${entityName} not found`);
  },
});

export default config;

3. Configure Mikro-ORM in app.module.ts:

import { Module } from '@nestjs/common';
import { MikroOrmModule } from '@mikro-orm/nestjs';
import mikroOrmConfig from './mikro-orm.config';

@Module({
  imports: [
    MikroOrmModule.forRoot(mikroOrmConfig),
    // Other modules
  ],
  controllers: [],
  providers: [],
})
export class AppModule {}

Defining Entities

Entities in Mikro-ORM are the models for your database tables. Let's define an example User entity.

1. Create `user.entity.ts` in the `src/entities` directory

import { Entity, PrimaryKey, Property } from '@mikro-orm/core';

@Entity()
export class User {
  
  @PrimaryKey()
  id!: number;

  @Property()
  name!: string;

  @Property()
  email!: string;

  @Property()
  createdAt = new Date();
}

2. Add mikro-orm dependency to `package.json`

"mikro-orm": {
  "useTsNode": true,
  "configPaths": [
    "./src/mikro-orm.config.ts",
    "./dist/mikro-orm.config.js"
  ]
}

3. Running Migrations

Migrations are essential for managing database schema changes. Mikro-ORM

provides a straightforward way to handle migrations.

Prerequisites

Install mikro-orm/cli

npm i @mikro-orm/cli

1. Create an initial migration:

npx mikro-orm migration:create

2. Run the migration:

npx mikro-orm migration:up

Conclusion

By leveraging NestJS with Mikro-ORM, we have a powerful setup for building scalable and maintainable applications. Mikro-ORM's rich feature set and seamless integration with NestJS enable us to manage our database operations efficiently. Whether you are starting a new project or looking to enhance your current setup, this combination provides a solid foundation for your application development needs.

For further reading and detailed configurations, refer to the following resources:

NestJS Documentation: https://docs.nestjs.com

Mikro-ORM Documentation: https://mikro-orm.io/docs/quick-start

Happy coding!

Harish Bisu

About Harish Bisu

Harish Bisu is an Intern at CyberMind Works, focusing on backend development. He is gaining practical experience and actively contributing to key backend projects within the development team.

Link copied
Copyright © 2024 CyberMind Works. All rights reserved.