Como criar API com NestJS e PostgreSQL
NestJS e PostgreSQL são uma boa combinação para criar API.
Olá pessoal, Neste caso, aprenderemos sobre o NestJS. NestJS é um dos frameworks populares de javascript para o back-end. Vamos nos concentrar em como criar API com NestJS.
NestJS é uma estrutura para criar aplicativos Node.js eficientes e escaláveis do lado do servidor. Sob o capô, o Nest faz uso de estruturas de servidor HTTP robustas como o Express (o padrão) e, opcionalmente, pode ser configurado para usar o Fastify também!
A documentação é realmente agradável de entender e concluir. Clique neste link abaixo para ler mais informações.
Se você quiser criar REST API, Graphql, Websockets, Microservice e etc. Absolutamente você pode usar o NestJS porque tudo está pronto para usar e basta seguir o padrão do NestJs.
O padrão do NestJs se parece com um Angular 2+, portanto, se sua formação é Frontend Developer (Angular) e você deseja expandir sua habilidade para se tornar um Backend Developer com um padrão semelhante ao Angular, este artigo é ideal para você.
O PostgreSQL é um poderoso sistema de banco de dados objeto-relacional de código aberto que usa e estende a linguagem SQL combinada com muitos recursos que armazenam e dimensionam com segurança as cargas de trabalho de dados mais complicadas.
Mas, não quero falar muito sobre o PostgreSQL, apenas para introdução e se você quiser ler mais informações, pode visitar este link abaixo.
Neste caso, usaremos um banco de dados gratuito PostgreSQL dahttps://elephantsql.com/. Então, certifique-se de ter criado uma conta.
Vamos criar uma API com NestJS juntos. Em primeiro lugar, presumo que você tenha instalado NodeJs e NPM. Nesse caso, estou usando nodejs versão 16.18.1 e npm versão 8.19.2
Sugiro que você use o NVM para gerenciar muitas versões do nodejs e facilmente alterar a versão do nodejs.
Instalação
Você precisa instalar o NestJS CLI. Use a versão 9.0.0 do NestJS para garantir que tenhamos a mesma versão para criar a API com o NestJS para evitar erros inesperados.
npm i -g @nestjs/[email protected]
Após a conclusão da instalação. Vamos iniciar o projeto para executar este comando.
nest new nestjs-todolist
Então, você precisa instalar este pacote para o utilitário criar API com PostgreSQL.
npm i --save @nestjs/config @nestjs/typeorm typeorm pg
Em seguida, no app.module.ts, precisamos atualizar assim
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
TypeOrmModule.forRoot({
type: 'postgres',
url: process.env.DATABASE_URL,
autoLoadEntities: true,
synchronize: true,
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
- TypeOrmModule é um módulo para configurar o banco de dados como você sabe que estamos usando Postgres. Mas, podemos usar outro tipo de banco de dados, como mysql, mongo, postgres, etc.
Basta clicar no botão para criar uma nova instância .
Depois disso, preencha o nome e escolha um plano gratuito. Em seguida, clique no botão Selecionar Região .
Depois disso, escolha o centro de dados. Por padrão, ele selecionará automaticamente dependendo de onde você é. Exemplo: quando você é da Europa, será selecionado na UE. Então, basta clicar no botão Revisar para a próxima etapa.
Se todas as informações forem válidas, basta clicar no botão para criar uma instância . Apenas espere um minuto. Após finalizar basta clicar no detalhe do banco de dados da instância. Assim, a página de detalhes se parece com esta imagem abaixo
Depois disso, copie o link da URL da sua instância de banco de dados e cole no arquivo .env com o nome da variável DATABASE_URL .
Precisamos garantir que a conexão entre o PostgreSQL e o projeto não seja um erro. apenas execute este comando
npm run start
Criar API
Toda a configuração está feita. Vamos pular para o tutorial principal e criar uma API. Precisamos gerar um módulo, controlador, serviços, classe e interface.
Ah sim, esqueci de mencionar o poderoso CLI NestJS. Podemos gerar um arquivo e olhar a imagem abaixo.
Em seguida, execute este comando para gerar o módulo, controlador, classe, interface e serviços.
npx nest generate module todolist && npx nest generate controller todolist/controllers/todolist && npx nest generate service todolist/services/todolist && npx nest generate interface todolist/interfaces/todolist
Command Generate NestJs
Crie uma entidade de arquivo para todolist com o nome de arquivo todolist.entity.ts na pasta src/todolist/entities e adicione este script
import {
Column,
CreateDateColumn,
Entity,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
export enum StatusTodo {
TODO = 'todo',
PROGRESS = 'progress',
COMPLETED = 'completed',
}
@Entity()
export class TodolistEntity {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@Column()
description: string;
@Column({ type: 'enum', default: StatusTodo.TODO, enum: StatusTodo })
status: string;
@Column({ nullable: true, type: 'bigint', default: new Date().getTime() })
due_date: number;
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn()
updatedAt: Date;
}
- @PrimaryGeneratedColum é uma função para gerar um id com incremento automático como chave primária.
- @Column é uma função para definir um campo na tabela
- O status de todolist é enum StatusTodo com o valor padrão todo.
- A razão pela qual estamos usando o número em due_date é para lidar com fusos horários diferentes.
Depois disso, precisamos criar o DTO (Data Transfer Object) para garantir que a solicitação de propriedade do cliente esteja disponível no back-end. Além disso, para validação, precisamos instalar esta biblioteca
npm i --save class-validator class-transformer
import { IsNotEmpty, IsNumber, IsString, Length } from "class-validator";
export class TodolistDto {
@IsNotEmpty()
@IsString()
@Length(10, 20)
title: string;
@IsNotEmpty()
@IsString()
@Length(0, 40)
description: string;
@IsString()
status: string;
@IsNumber()
@IsNotEmpty()
due_date: number;
}
- @IsString() é uma função para validar o valor da propriedade deve string
- @Length() é uma função para validar o valor mínimo e máximo do caractere
- @IsNumber() é uma função para validar o valor da propriedade caso o número
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe());
await app.listen(3000);
}
bootstrap();
export interface Todolist {
id: number;
title: string;
description: string;
status: string;
due_date: number;
createdAt: Date;
updatedAt: Date;
}
Depois disso, abra o arquivo todolist.module.ts e importe typeorm com um recurso da entidade todolist.
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { TodolistController } from './controllers/todolist/todolist.controller';
import { TodolistEntity } from './entities/todolist.entity';
import { TodolistService } from './services/todolist/todolist.service';
@Module({
imports: [TypeOrmModule.forFeature([TodolistEntity])],
controllers: [TodolistController],
providers: [TodolistService]
})
export class TodolistModule {}
npm run start
Vamos voltar ao IDE para criar a API. Abra o arquivo todolist.controller.ts. A função do controlador no NestJS é lidar com solicitações de usuários, responder a usuários e definir rotas API.
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Post,
Put,
} from '@nestjs/common';
import { TodolistDto } from 'src/todolist/dtos/todolist.dto';
import { TodolistService } from 'src/todolist/services/todolist/todolist.service';
@Controller('todolist')
export class TodolistController {
constructor(private readonly todolistService: TodolistService) {}
@Get()
findAll() {
return this.todolistService.findAll();
}
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {
return this.todolistService.findOne(id);
}
@Post()
create(@Body() todolistDto: TodolistDto) {
return this.todolistService.create(todolistDto);
}
@Put(':id')
update(
@Param('id', ParseIntPipe) id: number,
@Body() todolistDto: TodolistDto,
) {
return this.todolistService.update(id, todolistDto);
}
@Delete(':id')
delete(@Param('id', ParseIntPipe) id: number) {
return this.todolistService.delete(id);
}
}
- Precisamos injetar o serviço todolist de dependência para gerenciar dados de nestjs para o banco de dados com typeorm.
- @Param() é uma função para capturar o parâmetro path na API de rota. exemplo: /todolist/:id
- @Body() é uma função para obter todas as solicitações de campo dos clientes por DTO
- @GET(), @POST() , @PUT(), @DELETE() é método em HTTP
- ParseIntPipe é uma função para converter o id ou parâmetro em um número.
import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { TodolistDto } from 'src/todolist/dtos/todolist.dto';
import { TodolistEntity } from 'src/todolist/entities/todolist.entity';
import { Todolist } from 'src/todolist/interfaces/todolist/todolist.interface';
import { Repository } from 'typeorm';
@Injectable()
export class TodolistService {
constructor(
@InjectRepository(TodolistEntity)
private todolistRepository: Repository<TodolistEntity>,
) {}
async delete(id: number) {
const todolist: Todolist = await this.todolistRepository.findOneBy({ id });
if (!todolist) {
throw new HttpException(
`Todolist with id=${id} not found!`,
HttpStatus.BAD_REQUEST,
);
}
return this.todolistRepository.delete(id);
}
async update(id: number, todolistDto: TodolistDto) {
const todolist: Todolist = await this.todolistRepository.findOneBy({ id });
if (!todolist) {
throw new HttpException(
`Todolist with id=${id} not found!`,
HttpStatus.BAD_REQUEST,
);
}
return this.todolistRepository.update(id, todolistDto);
}
async findOne(id: number) {
const todolist: Todolist = await this.todolistRepository.findOneBy({ id });
if (!todolist) {
throw new HttpException(
`Todolist with id=${id} not found!`,
HttpStatus.BAD_REQUEST,
);
}
return todolist;
}
async findAll() {
return await this.todolistRepository.find();
}
async create(todolistDto: TodolistDto) {
const newTodolist = await this.todolistRepository.create({
...todolistDto,
});
const saveTodolist = await this.todolistRepository.save(newTodolist);
if (!saveTodolist) {
throw new HttpException(`Create todolist failed`, HttpStatus.BAD_REQUEST);
}
return saveTodolist;
}
}
- Neste caso, estamos usando async await, significa que é Promise, mas se você quiser ser Observable é claro que é possível, você só precisa convertê-lo para observable.
- this.todolistRepository é uma função de instância de typeorm com vários métodos para gerenciar dados em um banco de dados, como localizar, localizarOneBy, criar, salvar, atualizar e excluir.
- HttpException é uma função do nestjs para lançar dados quando os dados não são encontrados ou recebem algum erro.
- HttpStatus é uma função para definir todos os códigos de status HTTP como 200, 300, 400 e 500.
- Todolist no tipo const todolist é para declarar todas as propriedades da resposta.
API de teste
Para testar a API, podemos usar o Postman. Antes de testar, certifique-se de que o projeto nestjs esteja em execução. Você pode usar este comando para reconstruir automaticamente quando houver alterações no projeto.
npm run start:dev
- OBTER TUDO
- PEGUE UM
- ATUALIZAR
- EXCLUIR
- Validação
- Verificar do ElephantSQL
Desafio
Apenas para o exercício, você pode tentar criar uma API para atualizar o status da lista de tarefas de progresso, como tarefas, progresso e concluído. Mantenha-o Espírito!
fechando
Espero que este artigo seja útil e melhore suas habilidades. Claro, ainda estou aprendendo como você sabe, porque quando formos aprendizes de longa data, saberemos que o mundo é muito amplo. Se você quiser entrar em contato comigo, não hesite em contactar-me em [email protected] Obrigado.
Referências
#nestjs #postgresql #backend #tutorial #restapi





































![O que é uma lista vinculada, afinal? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)