Assim como outras estruturas do Node.js, o Nest.js oferece um conjunto de ferramentas completo para a criação de serviços de back-end robustos e com alta capacidade de escalabilidade. É essencial, no entanto, compreender como implementar as operações de Criação, Leitura, Atualização e Exclusão (CRUD) no Nest.js de forma eficiente, visto que essas operações são cruciais no desenvolvimento de APIs.
Este guia demonstrará como criar uma API REST CRUD em Nest.js, utilizando TypeORM e um banco de dados PostgreSQL.
Primeiros passos com Nest.js
Para iniciar, instale a ferramenta de linha de comando do Nest.js:
npm i -g @nestjs/cli
Em seguida, crie um novo projeto executando o seguinte comando:
nest new crud-app
A ferramenta CLI solicitará que você escolha um gerenciador de pacotes; selecione a opção de sua preferência. Utilizaremos o npm, o gerenciador de pacotes padrão do Node.
A CLI irá criar um projeto Nest.js básico com todos os arquivos de configuração necessários, assim como as dependências iniciais para a execução do aplicativo.
Finalmente, navegue até o diretório do projeto e inicie o servidor de desenvolvimento.
cd crud-app
npm run start
Você pode acessar o código completo deste projeto em seu repositório do GitHub.
Criação de um banco de dados PostgreSQL
Este tutorial utilizará uma instância do PostgreSQL na nuvem, mas você também pode configurar um banco de dados PostgreSQL local. É possível instalar o PostgreSQL em sistemas Windows, macOS ou Linux.
Para configurar uma instância do PostgreSQL na nuvem:
- Acesse ElephantSQL, inscreva-se e faça login na página inicial de sua conta.
- Clique no botão “Criar nova instância”, localizado no canto superior esquerdo da página, para criar uma nova instância para o seu aplicativo.
- Preencha o nome da sua instância, selecione o plano gratuito e, por fim, escolha a região para finalizar o processo de configuração.
- Após a criação da instância do banco de dados, acesse a página de configurações e copie o URL do banco de dados fornecido.
Configuração da conexão com o banco de dados
No diretório raiz do seu projeto, crie um arquivo chamado .env e cole a URL de conexão com o banco de dados conforme o exemplo abaixo:
DATABASE_URL="<sua url de conexão aqui>"
Agora, instale os seguintes pacotes:
npm install pg typeorm @nestjs/typeorm @nestjs/config
Em seguida, crie um módulo de banco de dados utilizando a ferramenta CLI.
nest g module database
Abra o arquivo database/database.module.ts e adicione o código de configuração do banco de dados abaixo:
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from '../users/models/user.entity';
@Module({
imports: [
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (configService: ConfigService) => ({
type: 'postgres',
url: configService.get('DATABASE_URL'),
entities: [User],
synchronize: true,
}),
}),
],
})
export class DatabaseModule {}
Este módulo de banco de dados administra a conexão, configurando o módulo TypeORM com os parâmetros de conexão necessários, incluindo a URL do banco de dados.
Além disso, define a entidade “Usuário” como parte da configuração, especificando a estrutura e as propriedades dos dados armazenados na tabela do banco de dados PostgreSQL.
Neste estágio, o código pode gerar um erro, pois a entidade “Usuários” ainda não foi criada. Isso será feito nas etapas seguintes.
Atualize o arquivo app.module.ts
Por fim, atualize o módulo principal do aplicativo para incluir a configuração do módulo de banco de dados.
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { DatabaseModule } from './database/database.module';
@Module({
imports: [
ConfigModule.forRoot({
envFilePath: '.env',
}),
DatabaseModule,
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Definição de um módulo de usuários
O módulo de usuários atua como um componente centralizado, sendo o responsável por encapsular e gerenciar a lógica necessária para implementar a funcionalidade CRUD da API.
Execute o seguinte comando no terminal para criar o módulo de usuários da API.
nest g module users
A ferramenta CLI atualiza automaticamente o arquivo app.module.ts para refletir as alterações realizadas, além de criar o módulo de usuário. Isso garante que o módulo recém-criado, “users”, seja integrado corretamente à configuração do módulo do aplicativo.
Criação de uma entidade de usuário
TypeORM é uma biblioteca de Mapeamento Objeto-Relacional (ORM) que simplifica as interações com o banco de dados em aplicativos que utilizam TypeScript, mapeando objetos JavaScript para tabelas do banco de dados.
Ao criar uma entidade de usuário usando TypeORM, você define a estrutura e as propriedades dos dados do usuário no banco de dados PostgreSQL.
No diretório de usuários, crie um novo arquivo models/user.entity.ts e adicione o seguinte código:
import { Entity, PrimaryGeneratedColumn, Column, } from "typeorm";
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;@Column()
name: string;@Column()
email: string;
}
A entidade “Usuário” define a estrutura dos dados de usuário armazenados no banco de dados. Neste caso, define “id” como a coluna de chave primária, juntamente com as colunas “nome” e “e-mail”, com suas respectivas propriedades.
Criação do serviço de API CRUD
Agora, crie o serviço de API que irá gerenciar a lógica das operações CRUD executando o seguinte comando:
nest g service users
Abra o arquivo user-auth.service.ts e adicione este código:
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import {User} from './models/user.entity';
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private userRepository: Repository<User>,
) {}async findAll(): Promise<User[]> {
return this.userRepository.find();
}async findOne(id: number): Promise<User> {
return this.userRepository.findOne({ where: { id } });
}async create(user: Partial<User>): Promise<User> {
const newuser = this.userRepository.create(user);
return this.userRepository.save(newuser);
}async update(id: number, user: Partial<User>): Promise<User> {
await this.userRepository.update(id, user);
return this.userRepository.findOne({ where: { id } });
}async delete(id: number): Promise<void> {
await this.userRepository.delete(id);
}
}
Essa classe UsersService define vários métodos de API dedicados ao tratamento de operações CRUD. Esses métodos incluem buscar todos os dados dos usuários, encontrar um usuário específico usando seu número de ID, criar um novo usuário, atualizar um usuário existente e um método para excluir os dados de um usuário específico no banco de dados.
Definição de um controlador para a API
Crie um controlador que irá gerenciar os endpoints da API para as operações relacionadas ao usuário.
nest g controller users
Em seguida, adicione o código abaixo ao arquivo users.controller.ts.
import { Controller, Get, Post, Body, Put, Param, Delete, NotFoundException, HttpCode } from '@nestjs/common';
import { UsersService } from './users.service';
import { User } from './models/user.entity';
@Controller('api/users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}@Get()
async findAll(): Promise<User[]> {
return this.usersService.findAll();
}@Post()
@HttpCode(201)
async create(@Body() user: User): Promise<User> {
const createdUser = await this.usersService.create(user);
return createdUser;
}@Put(':id')
async update (@Param('id') id: number, @Body() user: User): Promise<any> {
await this.usersService.update(id, user);
return { message: 'User updated successfully' };
}@Delete(':id')
async delete(@Param('id') id: number): Promise<any> {
const user = await this.usersService.findOne(id);if (!user) {
throw new NotFoundException('User does not exist!');
}await this.usersService.delete(id);
return { message: 'User deleted successfully' };
}
}
O controlador gerencia os endpoints de API para operações de usuário. Ele processa solicitações GET para recuperar todos os usuários, solicitações POST para criar novos usuários, solicitações PUT para atualizar usuários existentes e solicitações DELETE para excluir usuários.
Ao utilizar o UsersService e interagir com a entidade User, este controlador fornece uma API completa para gerenciar operações relacionadas ao usuário nos dados armazenados no banco de dados.
Atualize o arquivo users.module.ts
Finalmente, atualize o arquivo users.module.ts conforme mostrado abaixo para garantir a inclusão da entidade User e do módulo TypeORM, que estabelece a conexão com o banco de dados.
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './models/user.entity';
@Module({
imports: [TypeOrmModule.forFeature([User])],
controllers: [UsersController],
providers: [UsersService]
})
export class UsersModule {}
Por fim, inicie o servidor de desenvolvimento para testar as operações CRUD utilizando o Postman.
npm run start
O servidor será iniciado na porta 3000 e você poderá enviar solicitações de API para ele em http://localhost:3000/api/users.
Construindo aplicações de back-end com Nest.js
Se você está desenvolvendo uma API REST simples ou uma aplicação web complexa, o Nest.js oferece um conjunto completo de recursos e funcionalidades para construir um sistema de back-end robusto e confiável.
O Nest.js oferece uma abordagem mais estruturada para o desenvolvimento de projetos em comparação com o Express.js. Isso assegura que você possa criar, escalar e manter aplicações complexas com confiança, graças ao seu padrão de design organizado e modular.