Trying out NestJS part 2: Creating REST endpoints
Published: 2021-01-27 11:40:03

*This article was originally published on my [personal blog](https://arnaudcortisse.com/blog).* 

## Introduction

In my [last blog post](https://dev.to/arnaudcortisse/trying-out-nestjs-part-1-setting-up-dev-environment-for-your-react-nestjs-applications-that-rocks-12f6), I talked about why I wanted to give NestJS a try and what project I would build in order to evaluate it.

In this blog post, I'd like to set up the CRUD endpoints for the `Tasks` concept.

## Before going on

One of the main benefits of using NestJS is that it's very opinionated about the way you should structure your application. As a result, you'll end up with an application that's loosely coupled and highly testable without even thinking about it. 

However, NestJS can be hard to apprehend (especially if you are a junior developer). In my opinion, it's very important that you understand what `Dependency Injection` (and broadly speaking, the SOLID principles) and DI containers are since NestJS relies heavily on those concepts.

## Setting up new endpoints

The source code for this part of the project is available here: https://github.com/arnaud-cortisse/trying-out-nestjs-part-2.

Creating CRUD endpoints is not very exciting. It's actually very tedious because the code always look the same.
Fortunately, NestJS provides [a sweet tool](https://docs.nestjs.com/recipes/crud-generator) to generate all the boilerplate required to setup REST endpoints.

### Using the CRUD generator

Before using the CRUD generator, please install the following package:

```
npm install @nestjs/mapped-types
```

In the root of your project, just type in

```
nest g resource tasks
```

You will be prompted with several choices. In this case, we're interested in developing a REST API.

```
? What transport layer do you use? (Use arrow keys)
❯ REST API
  GraphQL (code first)
  GraphQL (schema first)
  Microservice (non-HTTP)
  WebSockets
```

Then, choose YES.

```
? Would you like to generate CRUD entry points? (Y/n)
```

You should have the following output:

```
CREATE src/tasks/tasks.controller.spec.ts (566 bytes)
CREATE src/tasks/tasks.controller.ts (890 bytes)
CREATE src/tasks/tasks.module.ts (247 bytes)
CREATE src/tasks/tasks.service.spec.ts (453 bytes)
CREATE src/tasks/tasks.service.ts (609 bytes)
CREATE src/tasks/dto/create-task.dto.ts (30 bytes)
CREATE src/tasks/dto/update-task.dto.ts (169 bytes)
CREATE src/tasks/entities/task.entity.ts (21 bytes)
UPDATE src/app.module.ts (312 bytes)
```

The NestJS CLI has just generated a lot of boilerplate code for you.

Let's have a closer look into some of the generated files.

#### tasks.service.ts

It's a [service](https://docs.nestjs.com/providers) that's going to deal with the data storage and retrieval.

```
import { Injectable } from '@nestjs/common';
import { CreateTaskDto } from './dto/create-task.dto';
import { UpdateTaskDto } from './dto/update-task.dto';

@Injectable()
export class TasksService {
  create(createTaskDto: CreateTaskDto) {
    return 'This action adds a new task';
  }

  findAll() {
    return `This action returns all tasks`;
  }

  findOne(id: number) {
    return `This action returns a #${id} task`;
  }

  update(id: number, updateTaskDto: UpdateTaskDto) {
    return `This action updates a #${id} task`;
  }

  remove(id: number) {
    return `This action removes a #${id} task`;
  }
}
```

`@Injectable()` is a [TypeScript decorator](https://www.typescriptlang.org/docs/handbook/decorators.html).
Decorating classes with `@Injectable` allows them to act as [providers](https://docs.nestjs.com/providers), that is, instances of classes that can be injected in other instances of classes (at runtime) via [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection).

#### tasks.controller.ts

It's a [controller](https://docs.nestjs.com/controllers) that's going to handle incoming requests related to `Tasks`.

```
import { Controller, Get, Post, Body, Put, Param, Delete } from '@nestjs/common';
import { TasksService } from './tasks.service';
import { CreateTaskDto } from './dto/create-task.dto';
import { UpdateTaskDto } from './dto/update-task.dto';

@Controller('tasks')
export class TasksController {
  constructor(private readonly tasksService: TasksService) {}

  @Post()
  create(@Body() createTaskDto: CreateTaskDto) {
    return this.tasksService.create(createTaskDto);
  }

  @Get()
  findAll() {
    return this.tasksService.findAll();
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.tasksService.findOne(+id);
  }

  @Put(':id')
  update(@Param('id') id: string, @Body() updateTaskDto: UpdateTaskDto) {
    return this.tasksService.update(+id, updateTaskDto);
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return this.tasksService.remove(+id);
  }
}
```

`@Controller()` is a [TypeScript decorator](https://www.typescriptlang.org/docs/handbook/decorators.html).
Decorating classes with `@Controller`, along with methods decorated with HTTP verbs (`@Get()`, `@Post()` etc.), allows you to declare the routing of your app.

You can also notice that the constructor expects an instance of `TaskService` (the class we talked about earlier). Behind the scene, an instance of the `TaskService` is going to be injected by the DI container (built in the NestJS runtime, see [custom-providers](https://docs.nestjs.com/fundamentals/custom-providers)).

#### tasks.module.ts

It's a [module](https://docs.nestjs.com/modules) that's going to hold all the instances of classes related to the `Tasks`.

```
import { Module } from '@nestjs/common';
import { TasksService } from './tasks.service';
import { TasksController } from './tasks.controller';

@Module({
  controllers: [TasksController],
  providers: [TasksService]
})
export class TasksModule {}
```

`@Module()` is a [TypeScript decorator](https://www.typescriptlang.org/docs/handbook/decorators.html).
Decorating classes with `@Module` allows for regrouping and encapsulating code that's closely related.

It's also going to affect how the DI container behaves.

#### app.module.ts

The app module is the root module (see [modules](https://docs.nestjs.com/modules)). It's created inside `main.ts`, at startup. 

```
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TasksModule } from './tasks/tasks.module';

@Module({
  imports: [TasksModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
```

You can see the CRUD generator updated `imports` and now references `TasksModule`, which is required for our app to expose all the routes declared inside `TasksController`. `TasksModule` is going to be directly connected to the `AppModule` in the application graph. 

Not putting `TasksModule` inside the imports array would cause your tasks routes not to be available. 

### Test current setup

Go in the root of your project and type in

```
docker-compose up --build
```

Once everything is up and running, go to `http://localhost:3001/tasks` and verify that your get the message "`This action returns all tasks`". 

### Final words

As you can see, setting up new REST endpoints with NestJS is extremely easy. 

However, you might be thinking there are way too many files and concepts involved. While I think that's quite true for such a small project, keep in mind that NestJS shines best when dealing with medium to large size projects.