O Rentx é um projeto (API) para aluguel de carros
Como executar o projeto | Requisitos da aplicação | Anotações
Back-end
Banco de Dados
Documentação
git clone https://github.com/eliasmcastro/rocketseat-ignite-nodejs-rentx.git
1. Instalar as dependências
Instalar as dependências do projeto
yarn
2. Arquivos de configurações
Criar o arquivo ormconfig.json
utilizando o arquivo ormconfig.example.json
Criar o arquivo .env
utilizando o arquivo .env.example
3. Cria o container do banco de dados e redis utilizando o Docker
Criar e iniciar o container do banco de dados e do redis
docker-compose up -d
4. Executar as migrations
Executar as migrations
yarn typeorm migration:run
5. Criar usuário admin
Executar o comando
yarn seed:admin
Dados do usuário:
- email: [email protected]
- password: admin
6. Iniciar a aplicação
Iniciar a aplicação
yarn dev
7. Rotas da aplicação
- A aplicação começará a ser executada em http://localhost:3333
- A documentação da API pode ser acessada em http://localhost:3333/api-docs
Dica: utilizar o Insomnia para testar as rotas
- Abrir o Insomnia -> Application -> Preferences -> Data -> Import Data -> From File -> Selecionar o arquivo insomnia.json
8. Banco de dados
Você pode utilizar o DBeaver para acessar o banco de dados da aplicação, utilizando os seguintes dados de conexão:
- Host: localhost
- Database: rentx
- Username: docker
- Password: ignite
Antes de executar os testes, é necessário criarmos um banco de dados exclusivo para os testes. Podemos fazer de duas formas:
1. Utilizando alguma ferramenta (ex: DBeaver) para acesso ao banco de dados
Acessar a ferramenta que você está utilizando para acessar o banco de dados e criar o banco de dados de teste chamado rentx_test
com o comando abaixo:
Dados de conexão:
- Host: localhost
- Port: 5432
- Username: docker
- Password: ignite
create database rentx_test;
2. Acessando diretamente o container do banco de dados
Rodar o comando abaixo para obter o CONTAINER ID
docker ps
Acessar o container
docker exec -it ${CONTAINER ID} bash
Acessar o banco postgres
psql -U postgres
Criar o banco de dados de teste
create database rentx_test;
Visualizar todos os bancos de dados criados
\l
Sair do container
\q
exit
3. Executar os testes unitários e de integração
yarn test
RF
- Deve ser possível cadastrar um novo carro
RN
- Não deve ser possível cadastrar um carro com uma placa já existente
- O carro deve ser cadastrado, por padrão, com disponibilidade
- O usuário responsável pelo cadastro deve ser um usuário administrador
RF
- Deve ser possível listar apenas os carros disponíveis
- Deve ser possível listar todos os carros disponível pelo nome da categoria
- Deve ser possível listar todos os carros disponível pelo nome do carro
- Deve ser possível listar todos os carros disponível pelo nome da marca
RN
- Não é necessário está logado no sistema para listar os carros cadastrados
RF
- Deve ser possível cadastrar uma ou mais especificações para um carro
RN
- Não deve ser possível cadastrar uma especificação para um carro não cadastrado
- Não deve ser possível cadastrar especificações com nomes duplicados para um mesmo carro
- Apenas usuários administradores pode cadastrar uma nova especificação
RF
- Deve ser possível cadastrar a imagem do carro
RNF
- Utilizar o multer para upload dos arquivos
RN
- O usuário pode cadastrar mais de uma imagem para o mesmo carro
- Apenas usuários administradores pode cadastrar as imagens
RF
- Deve ser possível cadastrar um aluguel
RN
- O aluguel deve ter duração mínima de 24 horas
- Não deve ser possível cadastrar um novo aluguel caso já exista um aberto para o mesmo usuário
- Não deve ser possível cadastrar um novo aluguel caso já exista um aberto para o mesmo carro
- O usuário deve estar logado na aplicação
- Ao realizar um aluguel, o status do carro deverá ser - alterado para indisponível
RF
- Deve ser possível realizar a devolução de um carro
RN
- Se o carro for devolvido com menos de 24 horas, deverá ser cobrado diária completa
- Ao realizar a devolução, o carro deverá ser liberado para outro aluguel
- Ao realizar a devolução, o usuário deverá ser liberado para outro aluguel
- Ao realizar a devolução, deverá ser calculado o total do aluguel
- Caso o horário de devolução seja superior ao horário previsto de entrega, deverá ser cobrado multa proporcional aos dias de atraso
- Caso haja multa, deverá ser somado ao total do aluguel
- O usuário deve estar logado na aplicação
RF
- Deve ser possível realizar a busca de todos os alugueis para o usuário
RN
- O usuário deve estar logado na aplicação
RF
- Deve ser possível o usuário recuperar a senha informando o e-mail
- O usuário deve receber um e-mail com o passo a passo para a recuperação da senha
- O usuário deve conseguir inserir uma nova senha
RN
- O usuário precisa informar uma nova senha
- O link enviado para a recuperação deve expirar em 3 horas
- Node.js
- O Node.js deve ser instalado via package manager utilizando o Chocolatey no Windows
- Instalar o Chocolatey
- Executar
cinst nodejs-lts
para instalar o Node.js - Executar
node -v
enpm -v
para verificar se a instalação deu certo
- O Node.js deve ser instalado via package manager utilizando o Chocolatey no Windows
- Yarn
- Instalar o Yarn
- Executar
yarn -v
para verificar se a instalação deu certo
- Visual Studio Code
-
yarn init -y
cria o arquivo package.json -
yarn add typescript -D
para instalar o TypeScript -
yarn add express
para instalar o Express -
yarn add @types/express -D
para instalar a definição de tipo da biblioteca Express -
yarn add uuid
para instalar o UUID -
yarn add @types/uuid -D
para instalar a definição de tipo da biblioteca UUID -
yarn tsc --init
cria o arquivo de configuração do TypeScript -
yarn add ts-node-dev -D
para instalar a ferramenta que reinicia automaticamente o servidor quando alterações nos arquivos são detectadas -
Em
package.json
:"scripts": { "dev": "ts-node-dev --transpile-only --ignore-watch node_modules --respawn src/server.ts" }
-
Nota: Foi necessário adicionar essa regra
"editor.formatOnSave": false
no settings.json do VSCode para funcionar
-
Criar arquivo
launch.json
, escolher Node.js e configurá-lo conforme as configurações abaixo:{ "version": "0.2.0", "configurations": [ { "type": "node", "request": "attach", "restart": true, "name": "App Debug", "skipFiles": ["<node_internals>/**"] } ] }
-
Para que o debugger possa se conectar à nossa aplicação, é necessário que o comando dev tenha a flag
--inspect
:"scripts": { "dev": "ts-node-dev --inspect --transpile-only --ignore-watch node_modules --respawn src/server.ts" }
- S => SRP: Single Responsiblity Principle (Princípio da responsabilidade única)
- O => OCP: Open-Closed Principle (Princípio Aberto-Fechado)
- L => LSP: Liskov Substitution Principle (Princípio da substituição de Liskov)
- I => ISP: Interface Segregation Principle (Princípio da Segregação da Interface)
- D => DIP: Dependency Inversion Principle (Princípio da inversão da dependência)
yarn add multer
para instalar o multeryarn add @types/multer -D
para instalar a definição de tipo da biblioteca multer
yarn add csv-parse
para instalar a csv-parse
yarn add swagger-ui-express
para instalar o swaggeryarn add @types/swagger-ui-express -D
para instalar a definição de tipo da biblioteca swagger- Para acessar a documentação criada: http://localhost:3333/api-docs
-
docker build -t rentx .
para criar imagem da aplicação -
docker run -p 3333:3333 rentx
para criar container da imagem da aplicação -
docker ps
para visualizar apenas os containers em execução -
docker ps -a
para visualizar todos os containers (parados e em execução) -
docker exec -it ${nomeContainer} /bin/bash
para acessar um container- CTRL + D para sair
-
docker logs -f ${nomeContainer}
para ver log de um container -
docker start ${nomeContainer}
para iniciar um container -
docker stop ${nomeContainer}
para parar um container -
docker rm ${nomeContainer}
para remover um container -
docker images
para listar imagens -
docker rmi ${nomeImagen}
para remover uma imagem -
docker-compose up
para criar e iniciar um container -
docker-compose up -d
para criar e iniciar um container, mas libera o terminal -
docker-compose up --force-recreate -d
para forçar re-criar e iniciar um container, mas libera o terminal -
docker-compose start
para iniciar um container -
docker-compose stop
para parar um container -
docker-compose down
para remover um container -
docker-compose down -v --rmi local
para remover tudo (containers, volumes e imagens) -
No Windows é necessário adicionar no script de dev no
package.json
a flag--poll
para que qualquer alteração realizadas nos arquivos sejam refletidas no container"scripts": { "dev": "ts-node-dev --inspect --transpile-only --poll --ignore-watch node_modules --respawn src/server.ts" }
yarn add [email protected]
para instalar o typeormyarn add reflect-metadata
para instalar o reflect-metadatayarn add pg
para instalar o driver do PostgreSQL
yarn typeorm migration:create -n CreateCategories
para criar a migration de categoriasyarn typeorm migration:create -n CreateSpecifications
para criar a migration de categoriasyarn typeorm migration:create -n CreateUsers
para criar a migration de usuáriosyarn typeorm migration:run
para executar as migrations criadasyarn typeorm migration:revert
para reveter a execução das migrations
yarn add tsyringe
para instalar o TSyringe
yarn add bcryptjs
para instalar o bcryptyarn add @types/bcryptjs -D
para instalar a definição de tipo da biblioteca bcryptjs
-
yarn add jsonwebtoken
para instalar o jsonwebtoken -
yarn add @types/jsonwebtoken -D
para instalar a definição de tipo da biblioteca jsonwebtoken -
Explicação sobre o uso de token e refreshToken
- O usuário loga na aplicação e recebe um refreshToken e um token. O token vai ter uma expiração menor e o refreshToken uma expiração maior.
- Quando o token expirar, vamos interceptar a chamada à API que deu erro e vamos enviar o refreshToken para o backend.
- O back-end recebe o refreshToken e retorna um novo token válido para o front-end, junto com possivelmente um novo refreshToken atualizado também.
- O front-end com os novos tokens recebidos, pode refazer as requests que falharam com novos tokens válidos e que não vão dar mais erros.
- Mas também existem outras possibilidades nesse fluxo, por exemplo, caso o refreshToken seja inválido, ele retorna um erro para o front-end, então o front-end pode redirecionar o usuário para a página de login novamente para ele logar novamente.
yarn add express-async-errors
para instalar o express-async-errors
- Testes unitários
- Testes de integração
- TDD (Test Driven Development)
yarn add jest -D
para instalar o jestyarn add @types/jest -D
para instalar a definição de tipo da biblioteca jestyarn add ts-jest -D
para instalar o ts-jestyarn jest --init
cria o arquivo de configuração do jest- Would you like to use Jest when running "test" script in "package.json"? ... yes
- Would you like to use Typescript for the configuration file? ... yes
- Choose the test environment that will be used for testing » node
- Do you want Jest to add coverage reports? ... no
- Which provider should be used to instrument code for coverage? v8
- Automatically clear mock calls, instances, contexts and results before every test? ... yes
yarn add supertest
para instalar o supertest (teste de integração)yarn add @types/supertest -D
para instalar o supertest (teste de integração)
-
yarn add tsconfig-paths -D
para instalar o tsconfig-paths -
Adicionar no
tsconfig.json
"baseUrl": "./src", "paths": { "@config/*": ["config/*"], "@modules/*": ["modules/*"], "@shared/*": ["shared/*"], "@utils/*": ["utils/*"] },
-
Adicionar no script de dev e typeorm no
package.json
a flag-r tsconfig-paths/register
para realizar a tradução do uso do @ nos imports"scripts": { "dev": "ts-node-dev -r tsconfig-paths/register --inspect --transpile-only --poll --ignore-watch node_modules --respawn src/server.ts", "typeorm": "ts-node-dev -r tsconfig-paths/register ./node_modules/typeorm/cli", }
-
Adicionar no
jest.config.ts
a propriedade abaixoObs: Foi necessário remover todos os comentários do arquivo
tsconfig.json
import { pathsToModuleNameMapper } from 'ts-jest'; import { compilerOptions } from './tsconfig.json'; moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/src/', }),
yarn add dayjs
para instalar o dayjs
- Caso esteja utilizando o Windows é necessário adicionar a lib
cross-env
para utilizar por exemplo oNODE_ENV=test
yarn add cross-env -D
para instalar o cross-envyarn add dotenv
para instalar o dotenv
- Ferramenta para uso de e-mail em ambiente de Dev: Ethereal
yarn add nodemailer
para instalar o nodemaileryarn add @types/nodemailer -D
para instalar a definição de tipo da biblioteca nodemailer- Ferramenta para criar templates de e-mails: Handlebars
yarn add handlebars
para instalar o handlebars
yarn add @aws-sdk/client-s3
para instalar o sdk da AWS S3
yarn add class-transformer
para instalar o class-transformer
-
Utilização do Babel para converter o código feito em TypeScript para JavaScript
-
yarn add @babel/cli @babel/core @babel/node @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators @babel/preset-env @babel/preset-typescript babel-plugin-module-resolver babel-plugin-transform-typescript-metadata -D
para instalar as dependências necessárias do Babel -
Criação do arquivo
babel.config.js
-
Em
package.json
:"scripts": { "build": "babel src --extensions \".js,.ts\" --out-dir dist --copy-files", }
-
Para gerar o build da aplicação executar
yarn build
-
Criar o arquivo
ormconfig.json
utilizando o arquivoormconfig.example.json
- Alterar o
src
paradist
- Alterar a extensão
.ts
para.js
- Alterar o
-
Criar o arquivo
.env
utilizando o arquivo.env.example
-
Criar e iniciar o container do banco de dados e do redis
docker-compose up -d
-
Executar aplicação após o build:
node dist/shared/infra/http/server.js
- Acessar repositório do GitHub -> Actions -> set up a workflow yourself
- Cria todo o passo a passo para realização do deploy
- Um exemplo de actions encontra-se em .github/workflows/main.yml
- É necessário configurar as Keys (HOST, PORT, USER, PASS do servidor) em Settings no repositório do GitHub
- Utilizando o Nginx
- Executar
sudo apt install nginx
para instalar o nginx - Caminho para criar arquivo de configuração:
cd /etc/nginx/sites-avaliable/
-
sudo touch rentx
-
vim rentx
server { listen 80 default_server; listen [::]:80 default_server; location / { proxy_pass http://localhost:3333; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } }
-
Criar link simbólico:
sudo ln -s /etc/nginx/sites-avaliable/rentx rentx
-
Remover o default:
sudo rm -rf default
- Remover também o default do caminho anterior:
cd ../
esudo rm -rf default
- Remover também o default do caminho anterior:
-
Realizar o restart do nginx:
sudo service nginx restart
-
- Executar
- O PM2 é um gerenciador de processos do Node.js
- Realizar a instação conforme instrução presente no site
- Exemplo de start da aplicação:
pm2 start dist/shared/infra/http/server.js --name rentx
- Verificar se DNS foi propagado: https://www.whatsmydns.net/
- Auxilia na configuração do certificado: https://certbot.eff.org/
yarn add cors
para instalar o corsyarn add @types/cors -D
para instalar a definição de tipo da biblioteca cors
- O rate-limiter-flexible conta e limita o número de ações por chave e protege contra ataques DDoS e de força bruta em qualquer escala
yarn add redis
para instalar o redisyarn add @types/redis -D
para instalar a definição de tipo da biblioteca redisyarn add rate-limiter-flexible
para instalar o rate-limiter-flexible
- O Sentry serve para monitorar erros e performance da aplicação
- Você deve criar uma conta no sentry.io para gerar o DNS
yarn add @sentry/node @sentry/profiling-node
para instalar o sentry