Você já usa o NestJS?

Você já usa o NestJS?

Já falamos sobre frameworks por aqui, e já até mencionamos o NestJS. Mas hoje vamos explorar um pouco mais e reforçar a importância desse framework durante o desenvolvimento de nossas aplicações.

O NestJS:

NestJS é um framework em Javascript para desenvolver APIs. Simples assim.

Sendo um framework, o NestJS ajuda bastante o processo de desenvolvimento de uma aplicação, trazendo ótimas ferramentas como Swagger, ORMs, Gerenciador de Cache, validações com DTOs, GraphQL e até mesmo um grande suporte a microsserviços, de um jeito bastante fácil e simplificado.

Se você está acostumado a desenvolver APIs puramente com Express ou Fastify, pode até achar um pouco estranho, pois o NestJS conta com uma estrutura bastante particular, com uso de módulos e decorators como base de toda a aplicação, mas é mesmo uma questão de adaptação, toda essa diferença é mesmo uma grande ajuda.

Vamos explorar um pouco mais:

Controllers

Toda API começa na definição de rotas e controllers. Geralmente, fazemos criamos nossas rotas, apontando para um controller que irá fazer todo o gerenciamento de funcionalidade.

No NestJS, é diferente e um pouco mais fácil. Com o uso de decorators, agrupamos nossa definição de rotas diretamente no controller e em suas funções, já de cara definindo o endpoint das rotas e método a ser utilizado, em uma estrutura como essa:

import { Controller, Get, Body } from '@nestjs/common';
import { RequestDto } from '../requestDto.dto';

@Controller('nome_da_rota_aqui')
export class ExampleController {
  @Get('nome_endpoint_aqui')
  getExample(): string {
    return 'Retorno qualquer de um GET';
  }

  @Post()
  postExample(@Body() request: RequestDto) {
    return 'Retorno qualquer de um POST';
  }
}

Ainda nos controllers, algo bem interessante é a criação de DTOs e validação dos payloads enviados. Podemos criar uma classe, em que nossas propriedades recebem um decorator indicando a validação a ser usada. Basta usar essa classe como tipagem de uma variável no controller, e a partir desta definição, automaticamente o NestJS irá validar a sua rota. Um exemplo de um DTO é como:

import { IsNotEmpty, IsEmail } from "class-validator";

export class RequestDto {
    @IsNotEmpty()
    nome: string;

    @IsEmail()
    email: string;
}

Entities

As entities são responsáveis por cuidar do gerenciamento de banco de dados. Em nosso exemplo, vamos utilizar o TypeORM, mas você poderia também trazer o Prisma ou até o Moongose para o NestJS.

O uso de entities segue o padrão da ORM que você irá utilizar, mas a lógica é sempre a mesma: definir os campos e as colunas de sua tabela no banco de dados a partir dos decorators:

import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

@Entity('nome_da_tabela')
export class App {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column()
  name: string;

  @Column({ nullable: true })
  lastName: string;

  @Column()
  email: string;
}

Services

Os services são bastante importantes no desenvolvimento de uma API, afinal, é em um service que acontece todo o gerenciamento de funcionalidades da aplicação.

No NestJS, um service nada mais é do que uma classe, que contém as nossas funções. O interessante é que o Nest trabalha com uma injeção de dependencias, mantendo um baixo nível de acoplamento entre nossas funções. Por isso, é bastante fácil trazer outras ferramentas, como um repositório do TypeORM, ou uma ferramenta de requisições HTTP para dentro do nosso service, assim como é bastante tranquilo exportar este mesmo service e usar em outro contexto da aplicação.

Um service no NestJS segue a seguinte estrutura:

import { NewAppData } from './../dto/app.dto';
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { App } from '../entities/app.entity';
import { Repository } from 'typeorm';
import { HttpService } from '@nestjs/axios';

@Injectable()
export class AppService {
  constructor(
    private httpService: HttpService,
    @InjectRepository(App)
    private appRepository: Repository<App>,
  ) {}

  getHello(): string {
    return 'Hello World!';
  }

  addNewAppData(data: NewAppData): Promise<App> {
    const app = {
      name: data.name,
    };

    return this.appRepository.save(app);
  }

  findAppDataById(dataId): Promise<App> {
    return this.appRepository.findOne({ where: { id: dataId } });
  }
}

Módulos

Tudo no NestJS acaba em um módulo. Um módulo é responsável por inicializar os nossos controllers, services, entities e outras ferramentas dentro de nossa aplicação.

Se você está familiarizado com o Angular, é a mesmo padrão: tudo que criamos dentro do NestJS deve ser inicializado num módulo.

Você pode ter a quantidade de módulos que quiser e organizar da melhor forma que puder imaginar, o que pode trazer ao NestJS uma ótima funcionalidade de gerenciamento de módulos. Por exemplo, você pode centralizar toda uma funcionalidade de “Usuários” dentro de um “UserModule” que irá conter todos os controllers, services e entities utilizados neste contexto, e então, aplicar este módulo no “AppModule”, módulo base do NestJS.

Um módulo no NestJS é como o exemplo abaixo:

import { App } from './entities/app.entity';
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { Database } from './helpers/database';
import { AppService } from './services/app.service';
import { AppController } from './controllers/app.controller';
import { ExampleModule } from '../example.module';

@Module({
  imports: [
    ExampleModule,
    ConfigModule.forRoot(),
    Database.build(),
    Database.registerEntities([App]),
  ],
  controllers: [AppController],
  providers: [AppService],
  exports: [AppService],
})
export class AppModule {}

De forma bastante simplificada, este é o NestJS.

Ainda há muito a ser explorado e traremos estes pontos em nossos próximos textos da devGo, mas que esteja claro os benefícios: as ferramentas disponíveis, a estrutura simplificada, a agilidade no desenvolvimento e a facilidade de adaptação ao framework.

E você? Já usa o NestJS ou algum outro framework? Participe do nosso canal no Discord e conte para gente!