Learning to build an API in NestJS (Node + Typescript) - Part 02
Tags: node, nestjs, typescript, beginners
Published: 2022-11-05 16:11:30

## Intro

_If you have been following this series, skip the intro!_

This is the second part of a series about learning NestJs for people who have experience building web applications but in languages other than typescript. 

The structure of these articles is not scripted :cop: neither random :confused:. My goal is to lay out everything I learn with as much depth as I can understand. I try to build working code that I understand and can replicate in upcoming real projects. That's why I don't write about any `foo bar` examples.

This is my learning process :books:... hopefully it will serve you as well.

The articles are written at the same time as I code and read the docs for what I am trying to build. After the draft is completed, I revise it, edit it, and reorder stuff to make reading this article easier for you and me in the future.

## Recap

At this point, we managed to code a module composed of a controller which returns a simple string when requesting its path.
Now we could start interacting with our endpoints, maybe adding some POST, PUT and DELETE requests. For that, we should probably know how to manage data. The concepts of imports and providers remain unexplored and seem to be what we need.

Let's dive into the [documentation](https://docs.nestjs.com/providers) for providers.

## Providers
Right off the bat, the analogy with service injection is made. So, we could think of providers as services that will be injected into other parts of the app, such as modules or controllers, or even other services?

Let's make a service for our controller to consume it. The database part will come later. For now, focus on getting a service up and running.

Again, a decorator is needed to make our service an injectable entity.
These four methods seem reasonable to develop:

```ts
import { Injectable } from '@nestjs/common';

@Injectable()
export default class ExampleService {
  get(id: string) {
    return 'Hello';
  }

  getAll() {
    return ['Hello'];
  }

  create(entity: string) {
    return 'Hello';
  }

  delete(id: string) {
    return 'Hello';
  }

  update(entity: string) {
    return 'Hello';
  }
}
```
Now inject it into the module! :sunglasses:
After this step, the service should be accessible at runtime by our controller.

```ts
import { Module } from '@nestjs/common';
import ExampleController from './example.controller';
import ExampleService from './example.service';

@Module({
  controllers: [ExampleController],
  providers: [ExampleService],
  imports: [],
  exports: [],
})
export default class ExampleModule {}
```
In the controller, let's make up some endpoints and call our newly created service. The injection is realized by adding the service as a parameter to the controller constructor.
```ts
import {
  Body,
  Controller,
  Delete,
  Get,
  Param,
  Post,
  Put,
} from '@nestjs/common';
import ExampleService from './example.service';

@Controller('example')
export default class ExampleController {
  constructor(private readonly exampleService: ExampleService) {}

  @Get()
  index() {
    return this.exampleService.getAll();
  }

  @Get(':id')
  details(@Param('id') id: string) {
    return this.exampleService.get(id);
  }

  @Post()
  create(@Body() dto: string) {
    return this.exampleService.create(dto);
  }

  @Put()
  update(@Body() dto: string) {
    return this.exampleService.update(dto);
  }

  @Delete(':id')
  delete(@Param('id') id: string) {
    return this.exampleService.delete(id);
  }
}
```
When running the app in watch mode, our changes seem to go unnoticed... Where are the routes we just defined!? :open_mouth:

![Recently added endpoints are missing from the registered routes listing](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hqwqer9gcq327wbtj99x.png)

## Imports
It so happens that this is what imports are for. Following the NestJS architecture, we need to import the Module into the main AppModule.
```ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import ExampleModule from './example/example.module';

@Module({
  imports: [ExampleModule],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
```
And just like that... :boom:

![Endpoint routed successfully](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/41qlp319rc0lkot0craa.png)

Right now, there is not much more to say about imports. Maybe we will return to this topic in the future.

## Where to go now? :confused:
I would like to implement something useful. Authentication comes to mind given that almost every application needs it. But I don't want to mess with database access or data encryption for the time being. So I will code a _semi-public_ scheme. No users, for now, just an unguarded endpoint that always returns a valid token and a bunch of real authenticated endpoints properly guarded.

## Wrap up
Congratulations if you made it this far! :smile::raised_hands:

In this article, we managed to implement a super basic service, inject it into a controller, route endpoints properly, capture params (query parameters, URI embedded parameters, and request body), and import a module to the main module.

That's all for now. I would like to make the next article completely about coding this authentication structure and not mix it up with this one.