No post anterior sobre NestJS aprendemos a como criar nosso primeiro projeto, o clássico Hello World a partir do Nest CLI, uma ferramenta por linha de comando que permite criar arquivos e estruturas de forma prática e rápida. Agora vamos dar mais um passo e criar nosso primeiro CRUD (Create, Read, Update, Delete) com NestJS.
Lembrando que você pode acessar a documentação do Nest CLI para se aprofundar nos recursos que ele possui.
Curso TypeScript - Fundamentos
Conhecer o cursoCriando Projeto do Zero
Caso você não tenha o ambiente Node.js e NestJS instalado, veja os seguintes artigos:
Após as instalações e configurações feitas, vamos criar nosso projeto utilizando o Nest CLI com o seguinte comando no terminal:
nest new crud-project
O comando acima irá criar os arquivos para a base do nosso projeto e instalar o package manager que vamos utilizar (você pode escolher entre npm
, yarn
ou pnpm
). Para este artigo escolhi o npm
.
Ao final da execução do comando, teremos uma estrutura da seguinte forma:
Ótimo! A base da nossa aplicação já está criada, neste exemplo vamos fazer um gerenciador de usuários, para isto precisamos criar toda a estrutura que irá prover o CRUD, como os arquivos referentes as camadas de entidade, controller, service e repository:
- Entidade: são os modelos da aplicação que irão espelhar as tabelas do banco de dados.
- Controller: é a camada responsável pelas rotas, respostas e requisições.
- Service: é a camada responsável pela aplicação das regras de negócio.
- Repository: é a camada responsável pela comunicação com o banco de dados.
Mais uma vez podemos utilizar o Nest CLI para nos auxiliar na criação destes arquivos, para isto vamos utilizar o comando:
nest g res users --no-spec
Obs.: Antes de utilizar o comando verifique o diretório do projeto, após criarmos o projeto com o nest new nome-do-projeto
, provavelmente será necessário acessar pelo terminal o diretório criado, portanto, com o comando cd nome-do-projeto
.
Explicando este comando, a flag g
representa o comando generate
, ou seja, estamos solicitando que o Nest CLI gere um arquivo, combinando a flag res
estamos apontando para gerar um resource
, assim, criando todos os arquivos referente a estrutura do Nest para a entidade users
.
A flag --no-spec
é utilizada para não gerar os arquivos de teste, que não serão necessários para este artigo, mas caso seja interessante para o seu projeto, basta ignorar.
Antes de gerar os arquivos, o Nest CLI irá perguntar qual padrão que será utilizado, como REST, GraphQL, Microservice, etc. Para fins de exemplo, iremos utilizar o padrão REST.
Após a execução do comando, teremos a estrutura do nosso domínio users
criada automaticamente:
Algo importante a complementar é que além de gerar os arquivos, o Nest CLI também agiliza na importação dos módulos. Como criamos o novo domínio users
, é necessário a importação referente a este domínio no módulo principal da nossa aplicação, o app.module
:
Perceba que o UsersModule
foi importado automaticamente, isso é importante pois além de poupar tempo de quem está desenvolvendo também elimina possíveis erros que podem ser ocasionados por esquecimento ou erros de digitação.
Definindo entidade user e configurando banco de dados
Curso Node.js - Fundamentos
Conhecer o cursoNeste momento precisamos definir a nossa entidade user
e quais propriedades ela terá. Para facilitar vamos ter apenas três propriedades: id, nome, idade.
O arquivo user.entity.ts
ficará como abaixo:
export class User {
id: number;
nome: string;
idade: number;
}
Perfeito! Temos a nossa entidade já com suas devidas propriedades, mas precisamos ter um banco de dados para salvar e manipular essas informações, para isso, vamos utilizar o TypeORM com o SQLite para fins didáticos. Não se preocupe sobre o ORM, vamos nos aprofundar nele em posts futuros. Lembrando que o foco deste artigo é que você consiga criar seu CRUD com NestJS.
Para instalar o TypeORM e o driver de conexão do SQLite vamos utilizar o npm, com o seguinte comando:
npm i @nestjs/typeorm typeorm sqlite3
Após a instalação, vamos criar o arquivo de configuração do banco de dados no diretório /src
e vamos chama-lo de ormconfig.ts
:
import { DataSourceOptions } from 'typeorm';
export const config: DataSourceOptions = {
type: 'sqlite',
database: '.db/sql',
synchronize: true, // Obs: use synchronize: true somente em desenvolvimento.
entities: [__dirname + '/**/*.entity{.ts,.js}'],
};
E então importar a configuração no modulo da aplicação app.module.ts
, passando a constante config
no TypeOrmModule.forRoot()
, como abaixo:
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UsersModule } from './users/users.module';
import { config } from './ormconfig';
@Module({
imports: [UsersModule, TypeOrmModule.forRoot(config)],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
O próximo passo será configurar a entidade users para que o TypeORM mapeie e crie o espelho da tabela no banco:
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class User {
@PrimaryGeneratedColumn('increment')
id: number;
@Column()
nome: string;
@Column()
idade: number;
}
Veja que utilizamos o decorator @Entity()
para apontar que a classe User é uma entidade, e suas propriedades sendo colunas, assim como o id sendo uma chave primária.
Desta forma podemos testar se tudo está ocorrendo conforme o esperado, vamos executar nossa aplicação e cruzar os dedos! 🤞
Para isto, basta executar o seguinte comando:
npm run start
Finalmente, vamos ao CRUD com NestJS!
Curso Express - Desenvolvendo aplicações web
Conhecer o cursoAgora que já temos a nossa aplicação criada e configurada, nós vamos começar de fato com o desenvolvimento das funcionalidades de CRUD.
Criando um usuário
Primeiramente vamos criar um usuário, para isto precisamos definir as propriedades no arquivo create-user.dto
, neste caso, o id será gerado automaticamente, portanto vamos passar o nome e idade:
export class CreateUserDto {
nome: string;
idade: number;
}
Ótimo, agora o próprio TypeORM nos fornece uma série de recursos que podemos utilizar em nossa aplicação, como injetar um repositório referente a entidade que estamos trabalhando na camada de service, como por exemplo no users.service.ts
:
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private userRepository: Repository<User>,
) {}
create(createUserDto: CreateUserDto) {
return this.userRepository.save(createUserDto);
}
}
Para isso, utilizamos o @InjectRepository(User)
e então criamos um objeto do tipo Repository
passando no construtor da classe UsersService
, utilizando a injeção de dependências. Desta forma podemos chamar os métodos que irão se comunicar com o banco e efetivamente manipular os dados, neste primeiro exemplo estamos criando um usuário utilizando o método create()
, e agora vamos para a camada do controller.
O controller é o responsável pelas rotas e pelas requests/responses, para criar um recurso vamos utilizar o verbo POST e chamar o método create do service, conforme abaixo:
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Post()
create(@Body() createUserDto: CreateUserDto) {
return this.usersService.create(createUserDto);
}
}
Obs: Caso você não tenha conhecimento em APIs REST e protocolo HTTP recomendo fortemente a leitura do artigo O que é HTTP e sobre REST.
Agora é simples, no controller temos a rota users e a requisição POST, onde vamos receber um createUserDto
, chamar o método create
do usersService
para criar um novo registro.
Obs: Por padrão a aplicação é criada utilizando a porta 3000, você pode alterar no arquivo main.ts
.
Para testar utilizamos o insomnia, fizemos uma requisição POST para http://localhost:3000/users passando o JSON com as propriedades nome e idade (que definimos no CreateUserDto), com isso tivemos o retorno que o registro foi salvo e possui o id: 1. Ótimo, nossa rota para criar usuários está funcionando corretamente.
Atualizando um usuário
Curso Nest.js - Fundamentos
Conhecer o cursoPara atualizar um registro, vamos utilizar o verbo PATCH, veja que há um método em nosso controller criado pelo Nest CLI, vamos usá-lo.
@Patch(':id')
update(@Param('id') id: number, @Body() updateUserDto: UpdateUserDto) {
return this.usersService.update(id, updateUserDto);
}
Neste caso temos na rota o id, ou seja, precisamos passar na url o id do registro que queremos atualizar, para este exemplo, ficará: http://localhost:3000/users/1, desta forma vamos atualizar o usuário de id igual a 1.
O arquivo UpdateUserDto
está estendendo parte do CreateUserDto
, portanto, neste momento não precisamos alterar este arquivo, pois vamos atualizar o nome e/ou idade de qualquer forma.
Por fim, precisamos criar o método em nosso service que irá atualizar efetivamente o usuário:
update(id: number, updateUserDto: UpdateUserDto) {
return this.userRepository.update(id, updateUserDto);
}
Seguindo a ideia do create
, neste momento usamos o método update
, passamos o id do registro a ser atualizado e o dto com as novas informações.
Perfeito, temos o retorno 200 OK e a informação que um registro foi alterado.
Criando lista e buscando usuário único
Mas fica a pergunta, como podemos ver efetivamente o registro alterado? Podemos criar uma lista ou buscar um único usuário de forma bem prática. Ao criar os arquivos com o Nest CLI, no controller há as seguintes rotas:
@Get()
findAll() {
return this.usersService.findAll();
}
@Get(':id')
findOne(@Param('id') id: number) {
return this.usersService.findOne(id);
}
Perceba que são duas rotas utilizando o verbo HTTP GET, onde na primeira nós vamos obter a lista de registros, e na outra passamos o id para obter este único registro. Então vamos criar essas buscas em nosso service:
findAll() {
return this.userRepository.find();
}
findOne(id: number) {
return this.userRepository.findOneBy({ id: id });
}
Agora vamos criar outro registro com as mesmas informações do primeiro só para termos mais de um usuário em nossa base, e então verificar a busca referente a lista, e então, um único registro da forma correta.
Usuário de id igual a 2 criado com sucesso.
Lista de usuários conforme o espero, repare que o registro de id igual a 1 foi atualizado com sucesso.
Por fim, vamos buscar um registro pelo seu id único:
Utilizando o verbo HTTP GET, passamos o id igual a 1 na url e como esperado o retorno foi do único usuário de id igual a 1.
Portanto, criamos um usuário, atualizamos, podemos listar todos os usuário ou buscar por um único registro, agora só está faltando um recurso de nosso CRUD, o delete, então vamos ver como podemos remover um registro.
Removendo um usuário
Para criar nossa função de remover usuários basta seguirmos a lógica das ações anteriores, com isto vamos utilizar o método remove do service da nossa aplicação:
remove(id: number) {
return this.userRepository.delete(id);
}
Podemos utilizar o repository com o método delete
passando apenas o id do registro que queremos excluir e agora chamar o método remove
na camada de controller.
@Delete(':id')
remove(@Param('id') id: number) {
return this.usersService.remove(id);
}
Lembrando que neste caso utilizamos o verbo HTTP DELETE e passamos o id como parâmetro.
Vamos testar!
De acordo com a imagem acima, excluímos com sucesso o registro de id igual a 1, ao buscar a lista de usuários, portanto, vamos obter somente o usuário de id igual a 2:
Conclusão
Neste artigo aprendemos passo a passo a criar um CRUD com NestJS, utilizando ferramentas como o Nest CLI, vimos por cima o uso do TypeORM e como trabalhamos com as camadas de entidade, controller, service e repository. O NestJS nos permite criar sistemas Web e APIs de forma prática e robusta, como veremos nos próximos artigos sobre serialização, validação, autenticação e outros recursos que podemos utilizar com este framework.
Ah, antes que me esqueça, você pode acessar o código da aplicação desenvolvida neste artigo através do repositório no GitHub 😁
Nesse artigo vimos vários recursos do NestJS, mas isso é apenas o começo, existem muitos outros recursos e funcionalidades disponíveis neste incrível framework, caso queira aprender mais sobre NestJS saiba que aqui na TreinaWeb nós temos o curso NestJS - Fundamentos que possui 02h07 de videos e um total de 18 exercícios. Conheça também nossos outros cursos de TypeScript.
Veja quais são os tópicos abordados durante o curso de NestJS - Fundamentos:
- Conhecendo a estrutura;
- Utilizando Nest CLI;
- Entendendo Rotas, Controllers e Views;
- Conexão com banco de dados;
- Usando TypeORM;
- Template Engine.