Lesson 01-NestJS Fundamentals

Core Concepts

Core Concepts

Modules

  • Modules are the fundamental building blocks of a NestJS application, used to organize related controllers, services, and providers.
  • Functionality can be shared and reused by importing other modules.

Controllers

  • Controllers handle client requests and return responses.
  • Decorators are used to define routes and HTTP methods.

Services

  • Services contain business logic, typically used for data operations or complex computations.
  • Services are utilized by controllers or other services through dependency injection.

Providers

  • Providers can be services, factories, or values, managed by the dependency injection system.
  • Any object that can be injected into other classes is considered a provider.

Dependency Injection

  • NestJS uses dependency injection to manage dependencies between objects.
  • This enhances code testability and maintainability.

Decorators

  • Decorators are used for metaprogramming, adding metadata to classes, properties, methods, or parameters.
  • They form the foundation of many core NestJS concepts.

Pipes

  • Pipes are used to transform and validate incoming data.
  • They execute before controller methods to ensure data conforms to the expected format.

Interceptors

  • Interceptors can act before a request reaches a controller or after a response is sent to the client.
  • They are useful for logging, error handling, and more.

Guards

  • Guards determine whether a request is allowed to reach a controller method.
  • Commonly used for implementing authorization and authentication logic.

Exception Filters

  • Filters capture and handle exceptions.
  • They help standardize error handling strategies.

Advantages

  • Modular Architecture: Modular design facilitates code organization and reuse.
  • Dependency Injection: Simplifies dependency management between objects.
  • Testability: Dependency injection and clear architecture make unit testing straightforward.
  • High Performance: NestJS leverages Node.js’s non-blocking I/O capabilities.
  • Type Safety: TypeScript support provides static type checking and an improved development experience.
  • Flexibility: Compatible with pure JavaScript, allowing gradual migration to TypeScript.

Features

  • Highly Configurable: Framework behavior can be customized based on project needs.
  • Community Support: Active community and extensive documentation resources.
  • Plugin Ecosystem: Numerous third-party modules and integration options.

Use Cases

  • Web APIs: Building RESTful or GraphQL APIs.
  • Microservices Architecture: Supports loosely coupled and independently deployable services.
  • Enterprise Applications: Suitable for large, complex applications.
  • Real-Time Applications: Utilizes WebSocket for real-time communication.

Large-Scale Project Applications

  • Scalability: NestJS’s modular architecture supports easy expansion and refactoring.
  • Maintainability: Clear code organization and dependency injection aid long-term maintenance.
  • Team Collaboration: Comprehensive documentation and consistent coding styles facilitate collaboration in multi-developer environments.

Quick Start

Installing the Nest CLI

First, install the Nest CLI, a command-line tool for quickly creating and managing Nest applications.

npm install -g @nestjs/cli

Creating a New Nest Project

Use the Nest CLI to create a new Nest project:

nest new my-nest-app
cd my-nest-app

Starting the Development Server

Start the Nest development server:

npm run start:dev

You can now visit http://localhost:3000 to view the default NestJS welcome page.

Project Structure Analysis

The directory structure of a NestJS project is as follows:

my-nest-app/
├── src/
│   ├── app.controller.ts
│   ├── app.module.ts
│   ├── main.ts
│   ├── common/
│   │   ├── dto/
│   │   ├── exceptions/
│   │   ├── guards/
│   │   ├── interceptors/
│   │   ├── pipes/
│   ├── config/
│   │   ├── config.module.ts
│   │   ├── environment/
│   │   │   ├── development.env
│   │   │   ├── production.env
│   │   ├── config.service.ts
│   ├── core/
│   │   ├── app.filter.ts
│   │   ├── app.interceptor.ts
│   ├── entities/
│   ├── services/
│   ├── modules/
│   │   ├── auth/
│   │   │   ├── auth.controller.ts
│   │   │   ├── auth.module.ts
│   │   │   ├── auth.service.ts
│   │   │   ├── dto/
│   │   │   │   ├── create-auth.dto.ts
│   │   │   │   ├── update-auth.dto.ts
│   │   │   ├── guards/
│   │   │   │   ├── auth.guard.ts
│   │   │   ├── interceptors/
│   │   │   │   ├── auth.interceptor.ts
│   │   │   ├── pipes/
│   │   │   │   ├── auth.pipe.ts
│   │   │   ├── auth.strategy.ts
│   │   │   ├── exceptions/
│   │   │   │   ├── auth.exception.ts
│   │   │   ├── auth.service.spec.ts
│   │   │   ├── auth.service.ts
│   │   │   ├── auth.module.ts
│   │   │   ├── auth.controller.ts
│   │   ├── users/
│   │   │   ├── users.controller.ts
│   │   │   ├── users.module.ts
│   │   │   ├── users.service.ts
│   │   │   ├── dto/
│   │   │   │   ├── create-user.dto.ts
│   │   │   │   ├── update-user.dto.ts
│   │   │   ├── guards/
│   │   │   │   ├── user.guard.ts
│   │   │   ├── interceptors/
│   │   │   │   ├── user.interceptor.ts
│   │   │   ├── pipes/
│   │   │   │   ├── user.pipe.ts
│   │   │   ├── users.service.spec.ts
│   │   │   ├── users.service.ts
│   │   │   ├── users.module.ts
│   │   │   ├── users.controller.ts
│   ├── database/
│   │   ├── database.module.ts
│   │   ├── prisma/
│   │   │   ├── index.ts
│   │   ├── typeorm/
│   │   │   ├── index.ts
│   ├── tests/
│   │   ├── app.e2e-spec.ts
│   │   ├── app.spec.ts
├── e2e/
│   ├── app.e2e-spec.ts
│   ├── app.e2e.ts
├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── tsconfig.build.json
├── tsconfig.json
└── ...

Directory Structure Analysis

- `src/`: Contains all source code.
  - `app.controller.ts`: Default controller.
  - `app.module.ts`: Root module.
  - `main.ts`: Application entry point.
  - `common/`: Shared DTOs, exceptions, guards, interceptors, and pipes.
  - `config/`: Configuration module and services.
  - `core/`: Core application-level filters and interceptors.
  - `entities/`: Data models.
  - `services/`: Business logic layer.
  - `modules/`: Different functional modules of the application.
    - `auth/`: Authentication-related controllers, services, DTOs, etc.
    - `users/`: User-related controllers, services, DTOs, etc.
  - `database/`: Database-related configurations.
  - `tests/`: Unit test files.
- `e2e/`: End-to-end test files.
- `.gitignore`: Git ignore file.
- `README.md`: Project documentation.
- `package-lock.json`: Package lock file.
- `package.json`: Project dependencies and script configurations.
- `tsconfig.build.json`: TypeScript build configuration.
- `tsconfig.json`: Main TypeScript configuration file.

Controller

Controllers handle HTTP requests and send data back to the client.

// src/modules/auth/auth.controller.ts
import { Body, Controller, Post } from '@nestjs/common';
import { AuthService } from './auth.service';
import { LoginDto } from './dto/login.dto';

@Controller('auth')
export class AuthController {
  constructor(private readonly authService: AuthService) {}

  @Post('login')
  login(@Body() loginDto: LoginDto) {
    return this.authService.login(loginDto);
  }
}

Module

Modules are a core concept in NestJS, used to organize and configure components.

// src/modules/auth/auth.module.ts
import { Module } from '@nestjs/common';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';

@Module({
  controllers: [AuthController],
  providers: [AuthService],
})
export class AuthModule {}

DTO (Data Transfer Object)

// src/modules/auth/dto/login.dto.ts
import { IsEmail, IsString } from 'class-validator';

export class LoginDto {
  @IsEmail()
  email: string;

  @IsString()
  password: string;
}

Provider

Providers define business logic and services.

// src/services/hello.service.ts
import { Injectable } from '@nestjs/common';

@Injectable()
export class HelloService {
  getHello(): string {
    return 'Hello from service!';
  }
}

Using a Service in a Controller:

// src/app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { HelloService } from './services/hello.service';

@Controller()
export class AppController {
  constructor(private readonly helloService: HelloService) {}

  @Get()
  getHello(): string {
    return this.helloService.getHello();
  }
}

Injecting Services

NestJS uses dependency injection to manage dependencies between components.

Registering a Service in a Module:

// src/app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { HelloService } from './services/hello.service';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [HelloService],
})
export class AppModule {}
Share your love