Como construir uma API utilizando Node.js e PostgreSQL
Emanuelly Leoncio. O Nest.js é um framework Node.js que permite desenvolver aplicações backend eficientes, escaláveis e organizadas. Por padrão, utiliza-se o TypeScript ou JavaScript.
Neste tutorial, iremos construir uma API com Nest.js, PostgreSQL e PrismaORM. Essa API irá simular um sistema de loja de roupas (store), e nele iremos adicionar e manipular os registros de roupas (clothes) e suas marcas (brands). Trabalharemos com os endpoints GET, POST, PUT e DELETE.
Instalação e preparação do projeto
Primeiramente, você precisará ter instalado em seu computador, o Node e npm. Com eles instalados, podemos dar seguimento ao tutorial.
Caso não tenha o Nest.js instalado, você poderá executar o seguinte comando no terminal:
Agora, vamos iniciar um novo projeto. Nossa API irá se chamar store-nestjs.
Para abrir o projeto no VSCode, rode:
E, em seguida:
Você notará que temos a seguinte estrutura de pastas:
Falando brevemente sobre cada um:
- main.ts: ponto de entrada, onde a aplicação é inicializada;
- app.module.ts: módulo raiz, que importa e organiza todos os outros módulos;
- app.controller.ts: responsável por lidar com as solicitações recebidas e retornar as respostas ao cliente;
- app.service.ts: encapsulam e gerenciam a lógica da aplicação. Por meio dele, pode-se reutilizar código, mantendo uma estrutura organizada e desacoplada em todo o aplicativo;
- pasta test e app.controller.spec.ts: arquivos de testes;
- .env: arquivo utilizado para configuração das variáveis de ambiente.
Com o VSCode aberto, vamos remover alguns arquivos que não iremos utilizar por hora. Remova:
- A pasta test;
- Os arquivos app.controller.spec.ts, app.controller.ts e app.service.ts.
Exclua também as importações, no app.module.ts, dos arquivos anteriormente removidos:
O app.module.ts ficará assim:
PrismaORM
O Prisma é uma ferramenta de mapeamento objeto-relacional (ORM), e será responsável pela criação e manipulação do banco de dados. A documentação dele pode ser acessada aqui.
Para darmos prosseguimento ao tutorial, iremos criar o nosso banco de dados. Para isso, instalaremos o prisma como dependência de desenvolvimento.
Agora, vamos iniciar o prisma no projeto:
Após rodar o comando acima, você notará que o arquivo schema.prisma foi inserido no projeto.
Configuração da conexão do banco de dados
No arquivo .env, iremos inserir os dados para conexão com o banco. As variáveis de ambiente ficarão da seguinte forma:
Em:
- SEU-USUARIO: coloque o usuário da sua configuração do postgres;
- SUA-SENHA: coloque a senha da sua configuração do postgres;
- NOME-BD: coloque o nome do banco de dados. Aqui chamaremos de store_nestjs.
Crie o banco de dados por meio do sql abaixo. Aqui estaremos utilizando o Beekeeper.
Criação das tabelas
Primeiramente, vamos criar a tabela brands. Nossa tabela terá como atributos o id e o nome da marca.
No arquivo schema.prisma, adicione:
Em seguida, vamos criar a migration, que se trata de um histórico do que está sendo criado e alterado no banco de dados. Assim, execute:
Agora, vamos criar a tabela clothes. Nesta tabela, teremos o id, o tipo e gênero da roupa, um barcode, e o id da marca, que será o vínculo com a tabela brands.
Insira no schema.prisma:
Execute novamente:
Observe que a cada alteração feita, uma nova migration é gerada. Com isso, temos toda a linha do tempo com as alterações do nosso banco.
Observe que no Beekeeper, foi gerado as tabelas prisma_migrations, brands e clothes.
Criação do module
Vamos criar uma nova resource, que irá trazer o controller, module e service para cada uma das nossas entidades, o Brand e o Clothe.
Execute:
Durante a execução irão aparecer duas perguntas. Selecione as opções abaixo:
Realize o mesmo processo para brand.
Remova os arquivos de teste, conforme indicado na figura abaixo:
Criação do DTO
Para a melhor organização do projeto, e manter as responsabilidades separadas, iremos trabalhar com o padrão DTO (Data Transfer Object). Crie os arquivos brand.dto.ts e clothe.dto.ts em cada respectiva pasta. Nesses arquivos, iremos detalhar quais serão os dados a serem manipulados e seus tipos (os mesmos atributos das tabelas que criamos anteriormente).
Em brand.dto.ts, insira o código:
Em clothe.dto.ts:
PrismaService
Crie o arquivo prismaService.ts dentro de src:
Adicione o código:
Agora, importe este service criado em cada um dos modules:
CRUD
Após toda esta preparação, vamos iniciar nosso CRUD de fato. Toda a lógica da “regra de negócio” da nossa aplicação ficará concentrada no service de cada entidade, no caso, brand e clothe.
Endpoint POST
Para brand e clothe, criaremos uma função assíncrona denominada create. Nela, primeiramente verificamos se o dado, que será enviado no body da requisição, já existe. Caso sim, retornará uma mensagem de erro. Se não, o novo dado será criado.
Em Brand, teremos:
Em clothe:
Em seguida, ajustamos os controllers de cada entidade, incluindo a chamada post.
Em clothe.controller:
Em brand.controller:
Para dar o start no projeto, execute:
Vamos testar a rota. No postman, vamos criar uma marca na rota localhost:3000/brand:
Agora, adicionaremos algumas roupas, na rota localhost:3000/clothe:
Podemos observar no banco de dados, que os registros foram criados com sucesso:
Seguiremos da mesma forma para os demais endpoints.
Endpoint GET
Em cada service, iremos criar uma função chamada findAll, que irá retornar todos os registros do banco de dados.
No clothe.service, adicione:
No brand.service:
Nos controllers, faremos a chamada para a rota GET:
Em brand.service:
Em clothe.service:
Agora, faremos o teste no postman para ambas as rotas:
Em brand: localhost:3000/brand
Em clothe: localhost:3000/clothe
Endpoint PUT
Esta rota será responsável por editar um registro. Para isso, precisamos passar o id do registro como parâmetro da rota. Após recebê-lo, verificamos se existe este id no banco. Caso positivo, este registro é editado com as informações passadas no body da requisição. Caso não seja encontrado, uma mensagem de erro é retornada.
Inserimos esta lógica no service de cada entidade.
No clothe.service, adicione:
No brand.service, insira:
Por fim, adicione no controller de cada um a rota put:
Para testar, no postman, vamos realizar a chamada, passando um id:
Em clothe: localhost:3000/clothe/2
Em brand: localhost:3000/brand/2
Endpoint Delete
Neste último endpoint, precisamos nos atentar ao seguinte detalhe: toda roupa é vinculada a uma marca. Assim, estabeleceremos que uma roupa não poderá existir sem ter uma marca vinculada a ela. Desta forma, ao remover o registro de uma marca, todas as roupas vinculadas a ela também deverão ser deletadas. Já os registros das roupas poderão ser deletados separadamente.
Vamos adicionar esta regra aos nossos service:
No brand.service:
No clothe.service, adicione:
Em cada controller, adicione a rota delete:
Agora, vamos realizar os nossos testes finais no postman.
Em clothe: localhost:3000/clothe
Em brand: localhost:3000/brand
Assim, finalizamos nossa aplicação com êxito!
Sucesso!
A Revelo Content Network acolhe todas as raças, etnias, nacionalidades, credos, gêneros, orientações, pontos de vista e ideologias, desde que promovam diversidade, equidade, inclusão e crescimento na carreira dos profissionais de tecnologia.