# NodeJS

## erview

This section provides exemple guide on how the API functions, including the structure, key endpoints, and how to interact with the system. This API is designed to provide a robust and scalable solution for developers, with clear separation of concerns through models, controllers, and services.

***

Here are some basic examples:

<details>

<summary>API Routes</summary>

The API is built using **NestJS**, and the routes are defined in the `src/users/` module. Each route points to a specific controller that handles the business logic through service methods.

### User Routes

*   **GET /users**

    **Description**: Fetches all users from the database.

    **Response**: An array of users in JSON format.

    **Status Codes**:

    * 200: Success
    * 500: Internal server error
*   **POST /users**

    **Description**: Creates a new user.

```javascript
{
  "name": "John Doe",
  "email": "john.doe@example.com"
}
```

**Response**: The newly created user.

**Status Codes**:

* 201: Created
* 400: Bad request (e.g., invalid input)
* 500: Internal server error

The API routes are centralized in the **UsersModule** and handled by the **UsersController** as follows:

```javascript
// src/users/users.controller.ts
import { Controller, Get, Post, Body } from '@nestjs/common';
import { UsersService } from './users.service';

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Get()
  getAllUsers() {
    return this.usersService.findAll();
  }

  @Post()
  createUser(@Body() createUserDto: CreateUserDto) {
    return this.usersService.create(createUserDto);
  }
}
```

The business logic is handled by the `UsersService`, and the `CreateUserDto` is a data transfer object (DTO) for validation.

</details>

***

<details>

<summary>Controllers</summary>

Controllers handle the business logic for each API endpoint. In **NestJS**, controllers are defined within a specific module folder (e.g., `src/users/`), and they communicate with services to fetch or manipulate data.

### User Controller

**createUser: Creates a new user with the data provided in the request body.**

```javascript
// src/users/users.controller.ts
import { Controller, Post, Body, Res, HttpStatus } from '@nestjs/common';
import { UsersService } from './users.service';
import { CreateUserDto } from './dto/create-user.dto';
import { Response } from 'express';

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Post()
  async createUser(@Body() createUserDto: CreateUserDto, @Res() res: Response) {
    try {
      const user = await this.usersService.create(createUserDto);
      return res.status(HttpStatus.CREATED).json(user);
    } catch (error) {
      return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ message: 'Server Error' });
    }
  }
}
```

**getAllUsers**: Fetches all users from the database and returns them in JSON format.

```javascript
import { Controller, Get, Res, HttpStatus } from '@nestjs/common';
import { UsersService } from './users.service';
import { Response } from 'express';

@Controller('users')
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Get()
  async getAllUsers(@Res() res: Response) {
    try {
      const users = await this.usersService.findAll();
      return res.status(HttpStatus.OK).json(users);
    } catch (error) {
      return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ message: 'Server Error' });
    }
  }
}
```

#### **Explanation:**

* In **NestJS**, controllers handle the HTTP requests and responses.
* The `UsersController` communicates with the `UsersService` to handle database operations.
* The `CreateUserDto` is used to validate and transfer the user data in `createUser`.

</details>

***

<details>

<summary>Models</summary>

In **NestJS**, models are defined using **TypeORM**, an ORM (Object Relational Mapping) tool that allows easy interaction with the database. The models are located in the `src/users/` folder and define the structure of the tables in the database.

### User Model

The `User` model represents a user in the system. It defines the columns and data types in the database, such as `id`, `name`, and `email`.

```javascript
// src/users/user.entity.ts
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

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

  @Column({ type: 'varchar', length: 255, nullable: false })
  name: string;

  @Column({ type: 'varchar', length: 255, nullable: false, unique: true })
  email: string;
}
```

#### **Explanation**:

* **Entity**: The `User` class is marked as an entity with the `@Entity()` decorator, representing a table in the database.
* **PrimaryGeneratedColumn**: The `id` field is automatically generated and serves as the primary key.
* **Column**: The `name` and `email` fields are defined with specific types and constraints (e.g., `varchar`, `unique`, `nullable`).

</details>

***

<details>

<summary>Middlewares</summary>

Middlewares are used to handle requests before they reach the route handler. They are applied globally or to specific routes to enforce security policies, handle errors, or validate input.

### Cors Middleware

The CORS functionality can be handled directly in the `main.ts` file of the NestJS application using built-in middleware, but if you want to implement a custom CORS middleware like the one in your

```javascript
// src/common/middleware/cors.middleware.ts
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class CorsMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
    next();
  }
}
```

#### **Applying the Middleware**

To apply this custom middleware globally or to specific routes, it needs to be configured in your module:

```javascript
// src/app.module.ts
import { Module, MiddlewareConsumer, RequestMethod } from '@nestjs/common';
import { CorsMiddleware } from './common/middleware/cors.middleware';

@Module({
  imports: [],
  controllers: [],
  providers: [],
})
export class AppModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(CorsMiddleware)
      .forRoutes({ path: '*', method: RequestMethod.ALL });
  }
}
```

#### **Explanation**:

* **CorsMiddleware**: The custom middleware is implemented as a class using the `NestMiddleware` interface.
* **use()** method: It applies the necessary CORS headers and calls `next()` to pass control to the next middleware or route handler.
* **AppModule**: The middleware is applied globally to all routes using `.forRoutes({ path: '*', method: RequestMethod.ALL })`.

Alternatively, CORS can also be configured in the `main.ts` file with:

```javascript
app.enableCors({
  origin: '*',
  methods: 'GET,POST,PUT,DELETE',
  allowedHeaders: 'Content-Type,Authorization',
});
```

</details>

***

<details>

<summary>Error Handling</summary>

Errors are caught at the controller level, and proper status codes and messages are returned. For centralized error handling, you can add an error-handling middleware like the following:

```javascript
// src/common/middleware/error-handler.middleware.ts
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class ErrorHandlerMiddleware implements NestMiddleware {
  use(err: any, req: Request, res: Response, next: NextFunction) {
    const statusCode = res.statusCode !== 200 ? res.statusCode : 500;
    res.status(statusCode).json({
      message: err.message,
      stack: process.env.NODE_ENV === 'production' ? null : err.stack,
    });
  }
}
```

#### **Applying the Middleware**

To apply the error-handling middleware globally or to specific routes, configure it in the `AppModule`:

```javascript
// src/app.module.ts
import { Module, MiddlewareConsumer } from '@nestjs/common';
import { ErrorHandlerMiddleware } from './common/middleware/error-handler.middleware';

@Module({
  imports: [],
  controllers: [],
  providers: [],
})
export class AppModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(ErrorHandlerMiddleware)
      .forRoutes('*'); // Apply to all routes
  }
}

```

</details>

***

<details>

<summary>Authentication</summary>

In the full version of the API, JWT authentication is implemented to secure certain routes. Here's a basic example of how JWT middleware can be used:

```javascript
// src/auth/jwt-auth.guard.ts
import { Injectable, CanActivate, ExecutionContext, UnauthorizedException } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { Request } from 'express';

@Injectable()
export class JwtAuthGuard implements CanActivate {
  constructor(private readonly jwtService: JwtService) {}

  canActivate(context: ExecutionContext): boolean {
    const request = context.switchToHttp().getRequest<Request>();
    const token = this.extractTokenFromHeader(request);

    if (!token) {
      throw new UnauthorizedException('Access denied.');
    }

    try {
      const verified = this.jwtService.verify(token, {
        secret: process.env.JWT_SECRET,
      });
      request.user = verified;
      return true;
    } catch (error) {
      throw new UnauthorizedException('Invalid token');
    }
  }

  private extractTokenFromHeader(request: Request): string | null {
    const authHeader = request.headers.authorization;
    if (!authHeader) {
      return null;
    }

    const token = authHeader.replace('Bearer ', '');
    return token || null;
  }
}
```

</details>

***

<details>

<summary>Testing</summary>

Unit tests for the API are written using **Jest** and **Supertest** to ensure the functionality of the routes and controllers in **NestJS**. Here’s an example of a test for the `GET /users` route:

```javascript
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';

describe('UsersController (e2e)', () => {
  let app: INestApplication;

  beforeAll(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();
    await app.init();
  });

  it('/users (GET) should return all users', async () => {
    const res = await request(app.getHttpServer()).get('/users');
    expect(res.status).toBe(200);
    expect(Array.isArray(res.body)).toBeTruthy();
  });

  afterAll(async () => {
    await app.close();
  });
});
```

#### **Explanation**:

* **TestingModule**: In **NestJS**, tests are created with a `TestingModule` that allows you to instantiate and initialize the application or modules you want to test.
* **request(app.getHttpServer())**: This method creates an HTTP server for the **NestJS** application, which is then used with **Supertest** to make requests.
* **beforeAll/afterAll**: These hooks initialize and tear down the application before and after all tests are run.

</details>

***
