Mostrando postagens com marcador Node. Mostrar todas as postagens
Mostrando postagens com marcador Node. Mostrar todas as postagens

segunda-feira, 8 de janeiro de 2024

Desenvolvendo uma API TO-DO com Nest.js, Swagger, MySQL e Docker

 Este guia apresenta o passo a passo para construir uma API de lista de tarefas (TO-DO) usando Nest.js, Swagger para documentação, integração com MySQL e a implementação de Docker para facilitar a configuração e execução.

Passo 1: Configurando o Ambiente

Antes de iniciarmos, certifique-se de ter o Node.js e o npm instalados. Em seguida, instale o Nest.js globalmente utilizando o seguinte comando:

npm install -g @nestjs/cli

Agora, crie um novo projeto Nest.js:

nest new nest-todo-api
cd nest-todo-api

Vamos remover os arquivos abaixo que não serão necessários.

rm ./src/app.controller.spec.ts
rm ./src/app.controller.ts
rm ./src/app.service.ts

Passo 2: Instalando Dependências

Instale as dependências necessárias para a nossa API:

npm install @nestjs/swagger swagger-ui-express mysql2 typeorm @nestjs/typeorm

Passo 3: Criando o Módulo, Controller, Service e a Entidade para Tarefas

Agora, vamos criar um módulo, controller, service para as tarefas e uma entidade para representar a tabela no banco de dados:

nest generate module task
nest generate controller task
nest generate service task
nest generate class task/task.entity

Passo 4: Configurando o Banco de Dados e Entidade

Vamos configurar a conexão com o MySQL utilizando o TypeORM. No arquivo src/app.module.ts, adicione o seguinte trecho para configurar o banco de dados:

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { TaskModule } from './task/task.module';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'mysql',
      host: 'mysql',
      port: 3306,
      username: 'seu_usuario',
      password: 'sua_senha',
      database: 'todo_db',
      entities: [__dirname + '/**/*.entity{.ts,.js}'],
      synchronize: true,
    }),
    TaskModule,
  ],
})
export class AppModule {}

No arquivo task.entity.ts, adicione a seguinte definição de entidade:

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

@Entity()
export class Task {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  title: string;

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

No arquivo task.module.ts, adicione a seguinte definição:

import { Module } from '@nestjs/common';
import { TaskController } from './task.controller';
import { TaskService } from './task.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Task } from './task.entity/task.entity';

@Module({
  imports: [TypeOrmModule.forFeature([Task])],
  controllers: [TaskController],
  providers: [TaskService]
})
export class TaskModule {}

Passo 5: Implementando Operações CRUD

O service é responsável por interagir com o banco de dados para executar operações relacionadas às tarefas. Adicione a seguinte implementação em task.service.ts:

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Task } from './task.entity/task.entity';

@Injectable()
export class TaskService {
  constructor(
    @InjectRepository(Task)
    private taskRepository: Repository&ltTask&gt,
  ) {}

  async findAll(): Promise&ltTask[]&gt {
    return await this.taskRepository.find();
  }

  async create(task: Task): Promise&ltTask&gt {
    return await this.taskRepository.save(task);
  }

  async update(id: number, updatedTask: Task): Promise&ltTask&gt {
    const existingTask = await this.taskRepository.findOne(id);

    if (!existingTask) {
      throw new Error('Tarefa não encontrada');
    }

    existingTask.title = updatedTask.title;
    existingTask.description = updatedTask.description;

    return await this.taskRepository.save(existingTask);
  }

  async remove(id: number): Promise&ltvoid&gt {
    const existingTask = await this.taskRepository.findOne(id);

    if (!existingTask) {
      throw new Error('Tarefa não encontrada');
    }

    await this.taskRepository.remove(existingTask);
  }
}

No arquivo task.controller.ts, implemente as operações CRUD:

import { Controller, Get, Post, Body, Put, Param, Delete } from '@nestjs/common';
import { TaskService } from './task.service';
import { Task } from './task.entity/task.entity';

@Controller('tasks')
export class TaskController {
  constructor(private readonly taskService: TaskService) {}

  @Get()
  findAll(): Promise&ltTask[]&gt {
    return this.taskService.findAll();
  }

  @Post()
  create(@Body() task: Task): Promise&ltTask&gt {
    return this.taskService.create(task);
  }

  @Put(':id')
  update(@Param('id') id: string, @Body() task: Task): Promise&ltTask&gt {
    return this.taskService.update(+id, task);
  }

  @Delete(':id')
  remove(@Param('id') id: string): Promise&ltvoid&gt {
    return this.taskService.remove(+id);
  }
}

Passo 6: Integrando Swagger

No arquivo main.ts, adicione as configurações do Swagger:

import { NestFactory } from '@nestjs/core';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  const config = new DocumentBuilder()
    .setTitle('API TO-DO Nest.js')
    .setDescription('Documentação da API de TO-DO')
    .setVersion('1.0.0')
    .build();

  const document = SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('api', app, document);

  await app.listen(3000);
}
bootstrap();

Passo 7: Configurando Dockerfile e Compose

Crie o arquivo Dockerfile na raiz do projeto e adicione as configurações:

FROM node:20

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 3000

CMD ["npm", "run", "start"]

Crie o arquivo docker-compose.yml na raiz do projeto e adicione as configurações:

version: '3'
services:
  # MySQL Service
  mysql:
    image: mysql:latest
    environment:
      MYSQL_ROOT_PASSWORD: root_senha
      MYSQL_DATABASE: todo_db
      MYSQL_USER: seu_usuario
      MYSQL_PASSWORD: sua_senha
    ports:
      - "3306:3306"
    networks:
      - app-network

  # Nest.js App Service
  nest-app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    depends_on:
      - mysql
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

Passo 8: Executando o Projeto

Execute o comando abaixo:

docker compose up

Acesse o Swagger em http://localhost:3000/api para visualizar e testar as operações CRUD da sua API TO-DO.

O projeto deste post está no meu github link.

quinta-feira, 25 de fevereiro de 2021

Unit Test com Node, Typescript e Jest

Vamos aproveitar o post anterior (AWS Lambda, Node e Typescript), e vamos incluir no projeto o "jest", com ele conseguimos criar unit test.

Passos:

1) Inserir dependências

npm install --save-dev babel-jest @babel/core @babel/preset-env @babel/preset-typescript @types/jest babel-jest jest


2)  No elemento "scripts" do arquivo "package.json" altere para "jest" o valor do elemento "test"

3) Vamos incluir o type "jest" no arquivo "tsconfig.json"

4) Para a compilação do projeto, vamos deixar de fora o diretório que irá conter os arquivos de testes, para isso, vamos colocar o elemento "exclude" no arquivo "tsconfig.json"

5) Agora vamos criar o arquivo de configuração do babel, na raiz do projeto crie o arquivo "babel.config.js" com as seguintes configs:

6) Crie o diretório "test" e o arquivo "hello.world.test.ts"

7) Agora execute o comando

npm run test


Site do Jest - link 

O projeto deste post está no meu github link.

sexta-feira, 19 de fevereiro de 2021

AWS Lambda, Node e Typescript

Neste post vou mostrar como criar um AWS Lambda utilizando Node e Typescript. 

O projeto será organizado para o exemplo deste post e para entendimento que o mesmo projeto possa ser reaproveitado (módulos) em outros lambdas, por exemplo, um projeto que componha todas as operações/funções (lambda) de uma API.

Passos: 

1) Instalação npm:

sudo apt-get install npm

2) Instalação Node:

sudo npm cache clean -f
sudo npm install -g n
sudo n stable

3) Instalação typescript:

sudo npm install -g typescript

4) - Criação do projeto:

mkdir LambdaNodeTypescript
cd LambdaNodeTypescript
tsc --init
npm init

5) Com o projeto criado, abra o mesmo com alguma ferramenta de desenvolvimento de sua preferencia, neste exemplo será utilizado o Visual Studio Code. Execute:

code .

6) Vamos continuar as configurações agora usando o terminal do Visual Studio Code. Vamos acrescentar as seguintes dependências do projeto para desenvolvimento com o Typescript. execute os seguintes comandos:

npm install @types/node --save-dev
npm install aws-sdk --save-dev
npm install @types/aws-lambda --save-dev


7) Depois vamos configurar a parte de build, agora vamos criar as classes que irão compor nosso projeto. Vamos criar um modulo de controller, para isso crie um dir "controller" e o seguinte arquivo "hello.world.controller.ts". Nesta classe que iremos deixar nossas regra de negocio.


8) Vamos agora criar o handler, crie um dir com o nome "handler", e crie o arquivo "hello.world.handler.ts".


9) Vamos criar o index, para podermos declarar o método de execução do lambda, que no caso do exemplo é o "execute".

10) Agora vamos configurar o build e test do projeto, para o build, vamos alterar o arquivo "tsconfig.json" da seguinte maneira:


Agora vamos alterar o arquivo "package.json":


11) Execute o comando para gerar o arquivo zip.

npm run all

12) Vamos criar um AWS Lambda, acesse a console, selecione "Lambda" e depois "Create function":

 

13) Em "Function Name" preencha com "LambdaNodeTypescript", selecione a ultima runtime do node disponível e selecione a role para execução e click em "Create Function"


14) Com a função criada, vamos fazer o upload do zip do projeto, em  "Action" selecione "Upload a .zip file"


15) Click em "Upload", selecione o arquivo zip do projeto e click em "Save"


16) Vamos apontar agora para o método "execute", vá em "Runtime settings" e click em "Edit" 

17) Em "Handler" altera para "index.execute" e click em "Save"

18) Vamos criar um evento de teste para o nosso Lambda, selecione "Configure test events"

19) Em "Event name" preencha com "test1" e passe um json em branco e click em "Create"

20) Vamos testar, certifique-se que o evento de teste criado anteriormente está selecionado e click em "Test".


O projeto deste post está no meu github link.