Repositório contendo as atividades da disciplina Arquitetura de Aplicações com Node.Js - professor Samuel Martins da Silva, parte integrante do curso de Especialização em Arquitetura de Software Distribuído, oferta 9, turma 1, PUC Minas 2025.
CRLF vs. LF: Normalizing Line Endings in Git
echo > .gitattributes
Checar a versão ativa do Node.JS
node --version
# v24.5.0 (latest version)
Checar as versões instaladas usando o nvm:
nwm ls
# v22.18.0
# -> v24.5.0
# default -> node (-> v24.5.0)
# iojs -> N/A (default)
# unstable -> N/A (default)
# node -> stable (-> v24.5.0) (default)
# stable -> 24.5 (-> v24.5.0) (default)
# lts/* -> lts/jod (-> v22.18.0)
# lts/argon -> v4.9.1 (-> N/A)
# lts/boron -> v6.17.1 (-> N/A)
# lts/carbon -> v8.17.0 (-> N/A)
# lts/dubnium -> v10.24.1 (-> N/A)
# lts/erbium -> v12.22.12 (-> N/A)
# lts/fermium -> v14.21.3 (-> N/A)
# lts/gallium -> v16.20.2 (-> N/A)
# lts/hydrogen -> v18.20.8 (-> N/A)
# lts/iron -> v20.19.4 (-> N/A)
# lts/jod -> v22.18.0
Configurar o alias default para apontar para a versão LTS:
nvm alias default 22.18.0
Mudar para a última versão LTS instalada (LTS = suporte de longa duração) usando o nvm
nvm use default
Comandos adicionados ao arquivo .bashrc
para evitar digitá-los a cada nova instância do bash criada:
nvm alias default 22.18.0
nvm use default
node -v
npm i -g @nestjs/cli
nest new project-manager-api
# selected npm as package manager
Após a criação do projeto, os arquivos da pasta project-manager-api
foram movidos para a raiz do repositório e a pasta project-manager-api
foi removida. Com isso, o script para executar o projeto recém-criado foi alterado, removendo a necessidade de alterar o diretório do shell.
mv ./project-manager-api/* ./
rm -r ./project-manager-api
npm run start
# npm run start:dev - to watch files
# Create folders
mkdir src/domain
mkdir src/domain/entities
mkdir src/domain/interfaces
mkdir src/domain/use-cases
mkdir src/domain/use-cases/projects
mkdir src/domain/use-cases/tasks
mkdir src/domain/use-cases/users
mkdir src/gateways
mkdir src/gateways/controllers
mkdir src/gateways/controllers/projects
mkdir src/gateways/controllers/tasks
mkdir src/gateways/controllers/users
mkdir src/gateways/guards
mkdir src/infrastructure
mkdir src/infrastructure/auth
mkdir src/infrastructure/database
mkdir src/infrastructure/database/entities
mkdir src/infrastructure/database/repositories
# Add empty .gitignore in each one to preserve folder structure while no file is added
echo > src/domain/.gitignore
echo > src/domain/entities/.gitignore
echo > src/domain/interfaces/.gitignore
echo > src/domain/use-cases/.gitignore
echo > src/domain/use-cases/projects/.gitignore
echo > src/domain/use-cases/tasks/.gitignore
echo > src/domain/use-cases/users/.gitignore
echo > src/gateways/.gitignore
echo > src/gateways/controllers/.gitignore
echo > src/gateways/controllers/projects/.gitignore
echo > src/gateways/controllers/tasks/.gitignore
echo > src/gateways/controllers/users/.gitignore
echo > src/gateways/guards/.gitignore
echo > src/infrastructure/.gitignore
echo > src/infrastructure/auth/.gitignore
echo > src/infrastructure/database/.gitignore
echo > src/infrastructure/database/entities/.gitignore
echo > src/infrastructure/database/repositories/.gitignore
# Controllers
echo > src/gateways/controllers/controller.module.ts
# [Controllers](https://docs.nestjs.com/controllers)
nest g controller gateways/controllers/projects
nest g controller gateways/controllers/tasks
nest g controller gateways/controllers/users
# Interfaces
echo > src/domain/interfaces/user.interface.ts
echo > src/domain/interfaces/task.interface.ts
echo > src/domain/interfaces/project.interface.ts
# Entities
echo > src/domain/entities/project.ts
echo > src/domain/entities/task.ts
echo > src/domain/entities/user.ts
Instalação das dependências adicionais
# [TypeORM module for Nest](https://www.npmjs.com/package/@nestjs/typeorm)
# [TypeORM repository](https://github.com/nestjs/typeorm)
# [TypeORM is an ORM that can run in Node.js, Browser, Cordova, Ionic, React Native, NativeScript, Expo, and Electron platforms and can be used with TypeScript and JavaScript (ES2021)](https://www.npmjs.com/package/typeorm)
# [ORM for TypeScript and JavaScript](https://github.com/typeorm/typeorm)
# [Asynchronous, non-blocking SQLite3 bindings for Node.js](https://www.npmjs.com/package/sqlite3)
# [SQLite3 bindings for Node.js repository](https://github.com/TryGhost/node-sqlite3)
# [Allows use of decorator and non-decorator based validation. Internally uses validator.js to perform validation. Class-validator works on both browser and node.js platforms.](https://www.npmjs.com/package/class-validator)
# [Decorator-based property validation for classes.](https://github.com/typestack/class-validator)
# [Class-transformer allows you to transform plain object to some instance of class and versa](https://www.npmjs.com/package/class-transformer)
# [Decorator-based transformation, serialization, and deserialization between objects and classes.](https://github.com/typestack/class-transformer)
npm install --save @nestjs/typeorm typeorm sqlite3 class-validator class-transformer
# [Mapped Types module for Nest used by the @nestjs/graphql and @nestjs/swagger packages.](https://www.npmjs.com/package/@nestjs/mapped-types)
# [Configuration module for Nest framework (node.js) 🐺](https://github.com/nestjs/mapped-types)
npm install --save @nestjs/mapped-types
nest g module domain
nest g module domain/use-cases
nest g module domain/use-cases/projects
nest g module domain/use-cases/tasks
nest g module domain/use-cases/users
nest g module infrastructure
nest g module infrastructure/database
nest g module infrastructure/auth
nest g module gateways
nest g service domain/use-cases/projects/get-all-projects --flat
nest g service domain/use-cases/projects/get-project-by-id --flat
nest g service domain/use-cases/projects/create-project --flat
nest g service domain/use-cases/tasks/get-all-tasks --flat
nest g service domain/use-cases/tasks/get-task-by-id --flat
nest g service domain/use-cases/tasks/create-task --flat
nest g service domain/use-cases/tasks/update-task --flat
nest g service domain/use-cases/users/create-user --flat
nest g service domain/use-cases/users/get-user-by-id --flat
nest g service domain/use-cases/users/get-all-users --flat
nest g service infrastructure/database/repositories/projects.repository --flat --no-spec
nest g service infrastructure/database/repositories/tasks.repository --flat --no-spec
nest g service infrastructure/database/repositories/users.repository --flat --no-spec
echo > src/infrastructure/database/entities/project.entity.ts
echo > src/infrastructure/database/entities/task.entity.ts
echo > src/infrastructure/database/entities/user.entity.ts
mkdir src/domain/repositories
# Interfaces
echo "import { DeepPartial } from 'typeorm';" > src/domain/repositories/projects-repository.interface.ts
echo "import { DeepPartial } from 'typeorm';" > src/domain/repositories/tasks-repository.interface.ts
echo "import { DeepPartial } from 'typeorm';" > src/domain/repositories/users-repository.interface.ts
# Implementations
echo "import { Injectable } from '@nestjs/common';" > src/infrastructure/database/repositories/projects.repository.service.ts
echo "import { DataSource, DeepPartial, Repository } from 'typeorm';" >> src/infrastructure/database/repositories/projects.repository.service.ts
echo >> src/infrastructure/database/repositories/projects.repository.service.ts
echo "@Injectable()" >> src/infrastructure/database/repositories/projects.repository.service.ts
echo "export class" >> src/infrastructure/database/repositories/projects.repository.service.ts
echo "import { Injectable } from '@nestjs/common';" > src/infrastructure/database/repositories/tasks.repository.service.ts
echo "import { DataSource, DeepPartial, Repository } from 'typeorm';" >> src/infrastructure/database/repositories/tasks.repository.service.ts
echo >> src/infrastructure/database/repositories/tasks.repository.service.ts
echo "@Injectable()" >> src/infrastructure/database/repositories/tasks.repository.service.ts
echo "export class" >> src/infrastructure/database/repositories/tasks.repository.service.ts
echo "import { Injectable } from '@nestjs/common';" > src/infrastructure/database/repositories/users.repository.service.ts
echo "import { DataSource, DeepPartial, Repository } from 'typeorm';" >> src/infrastructure/database/repositories/users.repository.service.ts
echo >> src/infrastructure/database/repositories/users.repository.service.ts
echo "@Injectable()" >> src/infrastructure/database/repositories/users.repository.service.ts
echo "export class" >> src/infrastructure/database/repositories/users.repository.service.ts
mkdir src/gateways/controllers/projects/dtos
echo > src/gateways/controllers/projects/dtos/create-project.dto.ts
echo > src/gateways/controllers/projects/dtos/update-project.dto.ts
mkdir src/gateways/controllers/tasks/dtos
echo > src/gateways/controllers/tasks/dtos/create-task.dto.ts
echo > src/gateways/controllers/tasks/dtos/update-task.dto.ts
mkdir src/gateways/controllers/users/dtos
echo > src/gateways/controllers/users/dtos/create-user.dto.ts
echo > src/gateways/controllers/users/dtos/update-user.dto.ts
Interface para implementação dos casos de uso
echo > src/domain/use-cases/base-use-case.ts
Instalação do newman usando a linha de comando
# https://learning.postman.com/docs/collections/using-newman-cli/installing-running-newman/
npm install -g newman
Instruções básicas de uso do newman
Usage: newman [options] [command]
Options:
-v, --version output the version number
-h, --help display help for command
Commands:
run [options] <collection> Initiate a Postman Collection run from a given URL or path
To get available options for a command:
newman <command> -h
Os arquivos do Postman foram organizados em Collections e Environments e um script global do PowerShell, chamado Global.CollectionRunner.ps1
foi criado para executar todas as requisições de uma dada coleção de forma automatizada, permitindo salvar logs em arquivo para posterior avaliação.
Uma das possíveis formas de chamar esse script global é
.\Global.CollectionRunner.ps1 -WriteLog yes -LocalEnvironment yes -Verbosity yes
Internamente ao script, chama-se um ou mais scripts do PowerShell para rodar cada coleção individual. No presente momento, há apenas um script Assignment2.CollectionRunner.ps1
que executa toda a coleção Assignment em um comando similar ao apresentado abaixo:
newman run "$($collectionFileName)" --insecure -e "../Environments/$($envFile)" --verbose | Out-File -FilePath "$($collectionName).log" -Encoding oem
e o sumário de uma execução bem sucedida é apresentado no arquivo Collections\Assignment2.log
conforme mostrado abaixo:
┌─────────────────────────┬─────────────────────┬────────────────────┐
│ │ executed │ failed │
├─────────────────────────┼─────────────────────┼────────────────────┤
│ iterations │ 1 │ 0 │
├─────────────────────────┼─────────────────────┼────────────────────┤
│ requests │ 9 │ 0 │
├─────────────────────────┼─────────────────────┼────────────────────┤
│ test-scripts │ 9 │ 0 │
├─────────────────────────┼─────────────────────┼────────────────────┤
│ prerequest-scripts │ 0 │ 0 │
├─────────────────────────┼─────────────────────┼────────────────────┤
│ assertions │ 18 │ 0 │
├─────────────────────────┴─────────────────────┴────────────────────┤
│ total run duration: 1201ms │
├────────────────────────────────────────────────────────────────────┤
│ total data received: 831B (approx) │
├────────────────────────────────────────────────────────────────────┤
│ average response time: 39ms [min: 8ms, max: 132ms, s.d.: 38ms] │
├────────────────────────────────────────────────────────────────────┤
│ average DNS lookup time: 903µs [min: 903µs, max: 903µs, s.d.: 0µs] │
├────────────────────────────────────────────────────────────────────┤
│ average first byte time: 36ms [min: 6ms, max: 129ms, s.d.: 39ms] │
└────────────────────────────────────────────────────────────────────┘
Após a inicialização da aplicação, sem arquivo prévio de banco de dados, foram realizadas requisições para a API usando o Postman e os resultados e testes embutidos no Postman serão apresentados a seguir. A Figura 1 mostra o estado da aplicação logo após o startup usando o comando npm run start
:
Figura 1: Estado da aplicação após a inicialização
As primeiras três requisições ao banco visavam registrar o estado inicial do banco de dados - sem usuários, projetos e tarefas. As Figuras 2, 3, 4, 5, 6 e 7 mostram as requisições e os respectivos testes escritos em Javascript na interface do Postman - que podem ser conferidos diretamente na coleção Assignment2.postman_collection.json
Figura 2: Requisição para retornar todos os usuários do banco - Banco de dados vazio
Figura 3: Requisição para retornar todos os usuários do banco - Testes
Figura 4: Requisição para retornar todos os projetos do banco - Banco de dados vazio
Figura 5: Requisição para retornar todos os projetos do banco - Testes
Figura 6: Requisição para retornar todas as tarefas do banco - Banco de dados vazio
Figura 7: Requisição para retornar todas as tarefas do banco - Testes
As próximas operações consistem da criação de um usuário (Figuras 8 e 9), um projeto para esse usuário (Figuras 12 e 13) e de uma tarefa (Figuras 16 e 17) para esse projeto e testes na própria requisição e requisição de GET por ID para checar a operação anterior de POST (Figuras 10 e 11 - Usuário; Figuras 14 e 15 - Projeto; Figuras 18 e 19 - Tarefas).
Figura 8: Criação de um usuário - Requisição
Figura 9: Criação de um usuário - Testes
Figura 10: Consulta de usuário pelo ID - Requisição
Figura 11: Consulta de usuário pelo ID - Testes
Figura 12: Criação de um projeto - Requisição
Figura 13: Criação de um projeto - Testes
Figura 14: Consulta de projeto pelo ID - Requisição
Figura 15: Consulta de projeto pelo ID - Testes
Figura 16: Criação de uma tarefa - Requisição
Figura 17: Criação de uma tarefa - Testes
Figura 18: Consulta de tarefa pelo ID - Requisição
Figura 19: Consulta de tarefa pelo ID - Testes
Por fim, requisições que devem retornar coleções - Usuários, Projetos e Tarefas - foram inseridas no final da coleção para uma verificação final da sua implementação. As Figuras 20 a 25 mostram os resultados dessas requisições
Figura 20: Requisição para retornar todos os usuários do banco - Banco de dados com 1 usuário inserido
Figura 21: Requisição para retornar todos os usuários do banco - Testes
Figura 22: Requisição para retornar todos os projetos do banco - Banco de dados com 1 projeto inserido
Figura 23: Requisição para retornar todos os projetos do banco - Testes
Figura 24: Requisição para retornar todas as tarefas do banco - Banco de dados com 1 tarefa inserida
Figura 25: Requisição para retornar todas as tarefas do banco - Testes
Alguns pacotes adicionais serão instalados para essa parte da atividade 3. O comando original é apresentado abaixo, junto com os resultados que apontam conflitos com os pacotes instalados anteriormente.
# Original command
# [bcrypt](https://www.npmjs.com/package/bcrypt)
# [bcrypt repository](https://github.com/kelektiv/node.bcrypt.js)
# [Type definitions for bcrypt](https://www.npmjs.com/package/@types/bcrypt)
# [Repository with types for bcrypt](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/bcrypt)
# [JWT utilities module for Nest based on the jsonwebtoken package](https://www.npmjs.com/package/@nestjs/jwt)
# [jwt repositories](https://github.com/nestjs/jwt)
# [cache-manager module for Nest originally published as part of the @nestjs/common package. This package is a drop-in replacement for the deprecated CacheModule](https://www.npmjs.com/package/@nestjs/cache-manager/v/2.3.0)
# [cache-manager module repository](https://github.com/nestjs/cache-manager#readme)
# [A cache module for nodejs that allows easy wrapping of functions in cache, tiered caches, and a consistent interface. This module is now part of the Cacheable project](https://www.npmjs.com/package/cache-manager/v/5.7.6)
# [Caching for Nodejs based on Keyv](https://github.com/jaredwray/cacheable#readme)
# [Redis cache store for node-cache-manager](https://www.npmjs.com/package/cache-manager-redis-store/v/2.0.0)
# [Redis cache store repository](https://github.com/dabroek/node-cache-manager-redis-store#readme)
# [Redis](https://www.npmjs.com/package/redis)
# [node-redis repository](https://github.com/redis/node-redis)
npm install --save bcrypt @types/bcrypt @nestjs/jwt @nestjs/cache-manager@2 cache-manager@5 cache-manager-redis-store@2 redis
# Results of original command - Redacted
npm error code ERESOLVE
npm error ERESOLVE unable to resolve dependency tree
npm error
npm error While resolving: [email protected]
npm error Found: @nestjs/[email protected]
npm error node_modules/@nestjs/common
npm error @nestjs/common@"^11.0.1" from the root project
npm error
npm error Could not resolve dependency:
npm error peer @nestjs/common@"^9.0.0 || ^10.0.0" from @nestjs/[email protected]
npm error node_modules/@nestjs/cache-manager
npm error @nestjs/cache-manager@"2" from the root project
npm error
npm error Fix the upstream dependency conflict, or retry
npm error this command with --force or --legacy-peer-deps
npm error to accept an incorrect (and potentially broken) dependency resolution.
npm error
npm error
npm error For a full report see:
npm error {REDACTED}\npm-cache\_logs\2025-09-14T19_54_12_471Z-eresolve-report.txt
npm error A complete log of this run can be found in: {REDACTED}\npm-cache\_logs\2025-09-14T19_54_12_471Z-debug-0.log
Com o objetivo de resolver o conflito, tentar-se-á forçar a resolução de dependências.
# Modified command
npm install --save bcrypt @types/bcrypt @nestjs/jwt @nestjs/cache-manager@2 cache-manager@5 cache-manager-redis-store@2 redis --legacy-peer-deps
Novos módulos serão criados conforme os comandos listados abaixo:
nest g module infrastructure/redis
nest g module infrastructure/auth # (it didn't have any impact due to commands executed before)
Um novo serviço será criado dentro da pasta auth
:
nest g service infrastructure/auth/auth --flat
Criação de arquivo com constante para uso com o jwt:
echo > src/infrastructure/auth/constants.ts
O comando a ser executado é:
nest g service domain/use-cases/users/get-user-by-email --flat
O comando para criação do guard é:
nest g service gateways/guards/auth-guard --flat
O comando para criação do controller é:
nest g controller gateways/controllers/auth/auth --flat
O comando para criação dos dtos de login via linha de comando é:
echo > src/gateways/controllers/auth/dtos/login.dto.ts
Para ilustrar o funcionamento das configurações de autenticação e autorização, uma pequena coleção (Assignment #3 - Postman collection) foi criada com 3 requisições HTTP usando o Postman. A coleção criada para a atividade 2 foi usada como base.
O tempo de expiração do token foi ajustado em 5 minutos por dois fatores: longo o suficiente para fazer duas ou mais requisições sequenciais sem necessitar obter um novo token e curto o suficiente para expirar durante os testes e permitir checar sua expiração.
A primeira requisição consistiu na criação do usuário com uma senha. Nessa atividade, a senha passou a ser encriptada para ser salva no banco de dados, conforme implementação disponível no Commit 4f4f640: Added encryption of password in creation of users.
A Figura 26 apresenta a requisição para a criação de usuários. Nota-se que essa requisição não carece de autorização nessa implementação presente. Num cenário real, a criação de usuários também é protegida para evitar abusos na criação e acessos ao sistema. Nota-se também que a senha é devolvida na resposta devidamente encriptada. Num cenário real, essa senha não seria devolvida dessa forma, pois não importa ao usuário saber o resultado da encriptação de sua senha, além de expor esse retorno a abusos.
Na Figura 27, uma requisição para a rota de login (/auth/login
) é feita para a obtenção do token de acesso. Essa também é uma requisição que dispensa autorização - sendo a senha e usuário corretos, o token de acesso será usado posteriormente para a autorização de outras rotas.
Figura 27: Obtenção do token de acesso
Para facilitar o uso dessa coleção da forma mais autônoma possível - mesmo que nesse cenário didático a coleção seja pequena e apenas uma requisição vá usar efetivamente o token de acesso - criação de projetos a partir de um usuário autenticado, foi implementado um script que é executado no retorno da requisição para coletar o token de acesso no corpo da resposta e salvar automaticamente na variável de ambiente access_token
- dessa maneira, nenhuma intervenção manual é necessária para uso do token.
O script para esse salvamento está reproduzido abaixo e na Figura 28 e está presente também no arquivo da coleção.
const response = pm.response.json();
const access_token_value = response['access_token'];
pm.environment.set('access_token', access_token_value);
console.info('New access token written to environment variable access_token');
Figura 28: Salvamento do token de acesso automaticamente
E, por fim, temos a criação do projeto. Foram feitos dois testes para simular o uso ativo do token de acesso.
Na Figura 29, mostra-se o resultado da requisição sem a presença do Bearer Token. Já a Figura 30 mostra o exmeplo de uma requisição bem sucedida. Note que o token é obtido automaticamente das variáveis de ambiente.
Figura 29: Criação de projeto não autorizada pela falta de token de acesso
Figura 30: Criação de projeto autorizada pela falta de token de acesso
Voltando ao aspecto da encriptação da senha no banco de dados, as Figuras 31 e 32 mostram o salvamento da senha não encriptada como parte da atividade #2 e a senha encriptada como parte da atividade #3
Figura 31: Senha não encriptada
Para a atividade 4, será utilizado o Redis para implementação da comunicação entre microserviços. As rotas / serviços de tarefas serão extraídos do projeto principal e será implementado como um microserviço.
Criação de arquivo docker-compose.yml
:
echo > docker-compose.yml
code docker-compose.yml
Conversão do projeto para sistema de monorepos:
nest generated app tasks
Ajustes na resolução de referências por meio da modificação do caminho no tsconfig.json
"paths": {
"@project-manager-api/*": [
"apps/project-manager-api/src/*"
]
}
Usando o recurso de busca do VS Code, a string src/
foi substituída por @project-manager-api/
em todos os arquivos na pasta ./apps/project-manager-api
Instalação de pacotes do redis
e dos microserviços do nestjs
: o parâmetro --legacy-peer-deps
foi adicionado para forçar a resolução de dependências e obter sucesso na instalação dos pacotes necessários.
# [microservices package from nestjs](https://www.npmjs.com/package/@nestjs/microservices)
# [NestJS repository](https://github.com/nestjs/nest)
# [A robust, performance-focused and full-featured Redis client for Node.js](https://www.npmjs.com/package/ioredis)
# [ioredis repository](https://github.com/redis/ioredis#readme)
# [node-redis is a modern, high performance Redis client for Node.js.](https://www.npmjs.com/package/redis)
# [node-redis repository](https://github.com/redis/node-redis)
npm i --save @nestjs/microservices@10 ioredis redis@4 --legacy-peer-deps
Criação de uma biblioteca compartilhada entre as aplicações para compartilhar arquivos e interfaces
nest generate lib common
Replicação da arquitetura clean dentro do pacote Tasks:
mkdir apps/tasks/src/gateways
echo > apps/tasks/src/gateways/.gitignore
mkdir apps/tasks/src/gateways/controllers
echo > apps/tasks/src/gateways/controllers/.gitignore
mkdir apps/tasks/src/gateways/controllers/dtos
echo > apps/tasks/src/gateways/controllers/dtos/.gitignore
mkdir apps/tasks/src/infrastructure
echo > apps/tasks/src/infrastructure/.gitignore
mkdir apps/tasks/src/infrastructure/entities
echo > apps/tasks/src/infrastructure/entities/.gitignore
mkdir apps/tasks/src/infrastructure/database
echo > apps/tasks/src/infrastructure/database/.gitignore
mkdir apps/tasks/src/infrastructure/repositories
echo > apps/tasks/src/infrastructure/repositories/.gitignore
mkdir apps/tasks/src/domain
echo > apps/tasks/src/domain/.gitignore
mkdir apps/tasks/src/domain/entities
echo > apps/tasks/src/domain/entities/.gitignore
mkdir apps/tasks/src/domain/interfaces
echo > apps/tasks/src/domain/interfaces/.gitignore
mkdir apps/tasks/src/domain/repositories
echo > apps/tasks/src/domain/repositories/.gitignore
mkdir apps/tasks/src/domain/use-cases
echo > apps/tasks/src/domain/use-cases/.gitignore
Todos os arquivos relacionados às Tasks
dentro do projecto project-manager-api
serão movidos ou terão seu conteúdo migrado para o pacote tasks
mv ./apps/project-manager-api/src/domain/entities/task.ts ./apps/tasks/src/domain/entities
mv ./apps/project-manager-api/src/domain/interfaces/task.interface.ts ./apps/tasks/src/domain
mv ./apps/project-manager-api/src/domain/repositories/tasks-repository.interface.ts ./apps/tasks/src/domain/repositories
mv -t ./apps/tasks/src/domain/use-cases ./apps/project-manager-api/src/domain/use-cases/tasks/*
mv ./apps/project-manager-api/src/infrastructure/database/entities/task.entity.ts ./apps/tasks/src/infrastructure/entities
mv ./apps/project-manager-api/src/infrastructure/database/repositories/tasks.repository.service.ts ./apps/tasks/src/infrastructure/repositories
cp ./apps/project-manager-api/src/gateways/controllers/tasks/tasks.controller.ts ./apps/tasks/src/gateways/controllers/tasks.controller.ts
mv -t ./apps/tasks/src/gateways/controllers/dtos ./apps/project-manager-api/src/gateways/controllers/tasks/dtos/*
Criar módulos no pacote tasks
:
echo > apps/tasks/src/domain/domain.module.ts
echo > apps/tasks/src/gateways/gateways.module.ts
echo > apps/tasks/src/infrastructure/infrastructure.module.ts
Uma nova coleção foi criada para a atividade 4. As primeiras requisições fazem a carga inicial do banco de dados para em seguida permitir o teste das rotas que são manipuladas pelo microserviço de Tasks
, que foi extraído - em relação à atividade 3 - do projeto project-manager-api
.
Nessa tarefa, três diferentes componentes arquiteturais são necessários:
- API de gestão de projetos - criada nas atividades 1 a 3 -
project-manager-api
, inicializada vianpm run start:dev
- Instância do Redis para manipular os eventos de tarefas enviados pelo
project-manager-api
e processado pelo microserviço deTasks
, inicializada viadocker-compose up --build
- E, por fim, o microserviço de tarefas
Tasks
que foi extraído da API de gestão de projetos e inicalizada vianest start tasks --watch
As Figuras 33 a 44 mostram os resultados dessa implementação e as legendas proveem explicação adicional sobre cada uma delas. Nas Figuras que exibem o console bipartido horizontalmente, o painel superior é a API project-manager-api
e o painel inferior é o microserviço Tasks
. Apenas as operações que envolvem as tarefas produzirão logs no painel inferior mas todas as imagens mostrarão ambos os painéis incondicionalmente.
Figura 33: Criação de usuário para popular o banco de dados e permitir as próximas operações
Figura 34: Log de criação do usuário. Note que nesse e em outras imagens nesse repositório as senhas enviadas no corpo da requisição são exibidas em texto plano nos logs a título de exemplo educativo. Essa não é uma prática segura nem recomendada para o uso em sistemas em produção.
Figura 35: Operação de login para obtenção de token de acesso
Figura 36: Detalhes da operação de login: Log exibindo os dados do corpo da requisição, data e horário de expiração do token de acesso e token propriamente dito
Figura 37: Criação de um novo projeto
Figura 38: Log da criação de novo projeto. Esse e outros logs fazem replicação da resposta enviada ao cliente da API
Figura 39: Criação de nova tarefa
Figura 40: Log da criação da nova tarefa mostrando o envio de um evento do project-manager-api
para o microserviço Tasks
. Apesar desses logs não apresentarem timestamps, a sequência de exibição é sempre no painel superior seguida pelo painel inferior, visto que o microserviço Tasks
apenas reage aos comandos solicitados.
Figura 41: Obtenção de uma tarefa por meio de seu identificador único
Figura 42: Log da consulta de tarefa pelo seu identificador