IglanCardeal / mercafacil-test

API Back-end feita em Node.js para o desafio teste da Mercafacil.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Back-end API

Mercafacil Test


1 1 1 1 1 1 1 1

Status do Projeto

Concluído

Tabela de conteúdos

  1. Funcionalidades
  2. Outras branchs
  3. Pré-requisitos
  4. Iniciando o projeto
  5. API
  6. Como testar localmente
  7. Testes
  8. CI - GitHub Actions
  9. Scripts
  10. Tecnologias usadas
  11. Autor

Funcionalidades

Este projeto consiste em uma API para cadastro de clientes dos tipos macapá e varejâo e estes podem cadastrar contatos de telefone em bases de dados diferentes usando o mesmo endpoint.

Clientes não cadastrados:

  • Se cadastrar informando nome, email, senha e tipo (varejão ou macapá).
  • Realizar o login na aplicação informando email, senha e tipo.

Clientes cadastrados:

  • Salvar seus contatos informando nome e telefone.
  • Recuperar seus contatos.

Todos os clientes podem realizar chamadas HTTP para os mesmos endpoints da aplicação, a diferença está definida em um campo no token JWT que será descriptografado, validado e com base nos valores retornados, será executada determinada operação de acordo com o tipo do cliente.

Outras branchs

CSV

Nesta branch chamada csv, eu aplico um exemplo hipotético onde um dos clientes solicitou que os contatos fossem salvos em um arquivo CSV e não mais em um banco de dados. Neste caso eu fiz uma análise de o que eu teria que alterar e o quanto isso afetaria o restante do sistema para atender essa situação.

Quer saber mais? Então acesse esta branch e veja o README onde eu explico mais sobre.

Obs: Refatorações futuras serão feitas somente na branch main.

Pré-requisitos

Para iniciar os testes localmente com este projeto, você deve ter instalado em sua máquina o Node.js, Yarn, Docker e Git.

Iniciando o projeto

Para começar, faça o clone deste repositório:

$ git clone https://github.com/IglanCardeal/mercafacil-test.git

e acesse a pasta do projeto:

$ cd mercafacil-test

Instale as dependências usando o Yarn:

$ yarn install

Caso você não tenha o yarn instalado, instale-o usando o npm: $ npm install -g yarn

Renomeie o arquivo .env.example para .env. Para saber mais sobre este arquivo, clique aqui.

Docker compose

Este projeto possui o arquivo docker-compose.yml que deve ser usado para iniciar os servidores de banco de dados MySQL e Postgres. O arquivo tem a seguinte estrutura:

version: '3'

services:
  mysql:
    container_name: mercafacil-api-mysql
    image: mysql
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=admin
      - MYSQL_DATABASE=admin
      - MYSQL_USER=admin
      - MYSQL_PASSWORD=admin
      - MYSQL_ROOT_HOST=%
    ports:
      - '3306:3306'
    command: --default-authentication-plugin=mysql_native_password
    volumes:
      - ./docker-volumes/mercafacil-api/mysql:/data/dbc

  postgresql:
    container_name: mercafacil-api-postgres
    image: postgres
    restart: always
    ports:
      - '5432:5432'
    environment:
      POSTGRES_PASSWORD: 'admin'
      POSTGRES_USER: 'admin'
    volumes:
      - ./docker-volumes/mercafacil-api/postgres:/data/dbc

Faça os devidos ajustes de acordo com seu ambiente. Os volumes dos containers ficarão dentro da pasta docker-volumes na raiz do projeto.

Makefile

Este é um arquivo Make usado para simplificar os comandos do docker-compose, ou seja, ao invés de ter que executar o comando docker-compose logs -f para obter os logs, com Makefile basta executar make logs. O arquivo tem a seguinte estrutura:

.PHONY: up

.PHONY: logs

.PHONY: down

up:
  docker-compose up -d && yarn dev

down:
  docker-compose down

logs:
  docker-compose logs -f

Execute o comando make up para executar o docker-compose e iniciar/instalar os bancos de dados e subir os containers. Logo em seguida, ele irá executar o comando yarn dev, isto irá subir o servidor em modo development, mas pronto para receber as chamadas HTTP. Por padrão, o servidor escuta na URL http://127.0.0.1:3000 (3000 porta definida no .env).

Se os containers de banco dados já estão rodando, você pode inicializar o servidor diretamente executando o comando yarn dev no terminal.

Obs: A inicialização do servidor possui um atraso definido pela função delay no arquivo server.ts. Esta função serve para esperar até os containers de banco de dados subirem e rodarem e assim evitar erro de inicialização do servidor. Por padrão, o atraso é de 10 segundos e o máximo de tentativas de 5 com atraso de 2 segundos entre cada tentativa, antes de lançar uma exceção por causa de falha de conexão com banco de dados.

Arquivo .env

O projeto usa um arquivo do tipo .env é utilizado pela aplicação para usar as variáveis de ambiente. Neste arquivo é definido as credenciais que será utilizada pela aplicação. Na raiz do projeto, eu coloquei um arquivo .env.example para que você possa se basear para configurar sua credenciais.

Os valores informados e sua motivação são explicadas a seguir:

  • PORT -> que defini a porta a ser usada pelo servidor.
  • PRIVATE_KEY -> chave RSA privada que será usada pela classe JsonWebTokenAdapter para assinar o token de autenticação.
  • PUBLIC_KEY -> chave RSA publica usado para verificar o token de autenticação.

No mesmo, também, devem ser informadas as credenciais para acesso a banco de dados que serão acessados pela aplicação:

  1. credenciais para conexão com banco MySQL:

    MYSQL_ROOT_PASSWORD=
    MYSQL_DATABASE=
    MYSQL_USER=
    MYSQL_PASSWORD=
    MYSQL_PORT=3306 # porta padrão
    MYSQL_ROOT_HOST= 127.0.0.1 # host padrão
    
  2. credenciais para conexão com banco Postgres:

    POSTGRES_DATABASE=
    POSTGRES_PASSWORD=
    POSTGRES_USER=
    POSTGRES_PORT= 5432 # porta padrão
    POSTGRES_ROOT_HOST= 127.0.0.1 # host padrão
    

Recomendo que você use as credenciais que já estão no arquivo de exemplo, mas caso queira alterá-las, não esqueça de fazer os ajustes no arquivo do docker-compose.yml.

API

Os endpoins da API são demonstrados a seguir junto com o campos de exemplo:

URL base padrão: http://localhost:3000

  • /api/client/signup -> cadastro de cliente.

    • Método: POST

    • Corpo da requisição:

      {
        "name": "any name",
        "email": "any2@email.com",
        "password": "any_pass",
        "type": "macapa"
      }
    • Retorno:

      {
        "statusCode": 201,
        "body": {
          "uuid": "cbc2dd57-e897-4c9e-bb70-4752fdd85e2d",
          "password": "$2b$12$C82D2xKwbESoCHGU8bYyp.lVOzy1rp/CicwruV4vDqIKZgJv1a21K",
          "name": "any name",
          "type": "macapa",
          "email": "any2@email.com",
          "id": 1
        }
      }
  • /api/client/signin -> login de cliente.

    • Método: POST

    • Corpo da requisição:

      {
        "name": "any name",
        "email": "any2@email.com",
        "password": "any_pass",
        "type": "macapa"
      }
    • Retorno:

      {
        "statusCode": 200,
        "body": {
          "token": "Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1dWlkIjoiY2JjMmRkNTctZTg5Ny00YzllLWJiNzAtNDc1MmZkZDg1ZTJkIiwidHlwZSI6Im1hY2FwYSIsImlhdCI6MTYzMTk3MDA1NCwiZXhwIjoxNjMxOTczNjU0LCJpc3MiOiJNZXJjYWZhY2lsIEJhY2tlbmQgQVBJIFRlc3QifQ.t7_naCB8SirW28NX3OWbOzS5nTFghfDgimGiVgiiRibRsf8lJinErMXOhjJHHNOi49mtzoePP5eU6JruVoBU9g"
        }
      }
  • /api/contact/create -> cadastro de contatos do cliente.

    • Método: POST

    • Headers: Authorization com token Bearer <token>

    • Corpo da requisição:

      {
        "contacts": [
          {
            "name": "Marina de  Rodrigues",
            "cellphone": "5541996941922"
          }
        ]
      }
    • Retorno:

      {
        "statusCode": 201,
        "body": {
          "contacts": [
            {
              "id": null,
              "name": "MARINA DE RODRIGUES",
              "cellphone": "+55 (41) 99694-1922"
            }
          ]
        }
      }

      id pode ser null caso o cellphone já exista na base e então somente o name será atualizado.

  • /api/contact/get -> recupera os contatos do cliente.

    • Método: GET

    • Headers: Authorization com token Bearer <token>

    • Corpo da requisição:

      none
    • Retorno:

      {
        "statusCode": 200,
        "body": {
          "contacts": [
            {
              "id": 1,
              "name": "MARINA DE RODRIGUES",
              "cellphone": "+55 (41) 99694-1922"
            }
          ]
        }
      }

Como testar localmente

Insomnia

Este projeto possui o arquivo Insomnia_examples com exemplos para realizar chamadas HTTP para todas as rotas. Importe este arquivo no Insomnia e começe os testes.

Testes

Testes unitários

As configuraçôes de testes unitários estão no arquivo jest.config.js e durante a execuçâo destes testes, será exibido o prefixo unit-tests, destacando que tipo de teste está sendo executado.

A minha iniciativa de criar um sistema com módulos desacoplados (controllers,services, repositories e adapters) perimitiu a criaçâo de testes unitários dos principais módulos da aplicaçâo. Eu segui o TDD durante a criação dos principais módulos do sistemas. Cada um desses módulos possuem o seu respectivo teste unitário no próprio arquivo de produçâo ou dentro da pasta test no mesmo diretório. Exemplo:

  |
  |-- services
      |
      |--first-service
      |     first-service.test.ts # arquivo de teste
      |     first-service.ts      # arquivo de produçâo
      |
      |--second-service
      |     second-service.test.ts # arquivo de teste
      |     second-service.ts      # arquivo de produçâo

Ou:

  |
  |-- services
      |
      |--first-service
      |     test
      |       first-service.test.ts # arquivo de teste
      |     first-service.ts        # arquivo de produçâo
      |
      |--second-service
      |     test
      |       second-service.test.ts # arquivo de teste
      |     second-service.ts        # arquivo de produçâo

Caso queira saber os scripts de teste unitário, consulte a secão Scripts. um script exemplo de destaque é o test:coverage (execute yarn test:coverage) que irá executar os testes e ainda mostrar no terminal a cobertura de testes unitários da aplicação. Será mostrado algo como:

test-coverage

Scripts

Dentro do arquivo package.json, temos os scripts que podem ser executados no projeto. Os principais serão destacados a seguir com o comando de execução, utilizando o gerenciador yarn:

  • dev -> yarn dev - inicia o servidor do projeto em modo de desenvolvimento.
  • lint -> yarn lint - usa as regras do arquivo .eslintrc para análise de estilo do código.
  • test:unit -> yarn test:unit - (Alias: test:u) executa os testes unitários.
  • test:unit:watch -> yarn test:unit:watch - (Alias: test:u:w) executa os testes unitários em modo --watch, ou seja, cada alteração em arquivo de teste/produção irá executar os testes novamentes automaticamentes.
  • test:verbose -> yarn test:verbose - (Alias: test:v) executa os testes unitários em modo --verbose, ou seja, irá exibir todas as informações dos testes executados.

CI GitHub Actions

Este projeto faz o uso do GitHub Actions para garantir a qualidade de código do projeto devido ao fato de eu gerar muitos commits e integrá-los frequentementes a este repositório. Durante a esteira de CI, os teste unitário são executados com o comando yarn test:ci. Caso tenha interesse, consulte o arquivo node.js.yml.

Tecnologias usadas

Para criar este projeto, além das tecnologias mencionadas nos requisitos, foi usado as ferramentas/bibliotecas/frameworks:

  • Fastify -> framework web com logger pino integrado por padrão, usado para tratar as chamadas e rotas HTTP.
  • JEST -> para criação de testes unitários.
  • Bcrypt -> para criptografia de senhas.
  • JsonWebToken -> para criação de tokens de autenticação.
  • UUID -> para criação de identificadores únicos.
  • Sequelize -> ORM para executar query/commands nos bancos de dados.
  • TypeScript -> JavaScript equipado com um foguete, ou seja, superset do JavaScript.
  • eslint -> para definição de regras de estilos de códigos.
  • prettier -> formatador de código.
  • husky -> para executar script de acordo com os hooks do Git.
  • git-commit-msg-linter -> forçar commits semânticos.
  • ts-node-dev -> executar o servidor em TS sem precisar gerar build do projeto.

Sobre mim

Eu sou Iglan Cardeal, desenvolvedor Node.js, apaixonado por programação, café e aviação. Atualmente meus estudos e práticas estão focados mais em Node.js, mas estou estudando Python (menos do que gostaria) e em breve vou retornar meus estudos para React Native.

Estou na busca por desafios e resolvê-los através dos meus conhecimentos e teimosia. Procuro ajudar os outros e com isso me ajudar a aprender mais, a conhecer pessoas, suas histórias e um pouco mais... Não acredita? Então veja meu perfil no StackOverflowPT. Sempre que posso, tentou ajudar e ensinar outros desenvolvedores com suas dúvidas e problemas. Pergunte alguma coisa lá, quem sabe eu consiga ajudar você :D... Ou me chame no Discord: Cardeal#0563 e vamos bater um papo por lá ;).


Projeto feito com ❤️ e dedicação por Iglan Cardeal. Gostou? então deixe uma ⭐ neste repositório :).

About

API Back-end feita em Node.js para o desafio teste da Mercafacil.


Languages

Language:TypeScript 97.7%Language:Shell 1.5%Language:JavaScript 0.7%Language:Makefile 0.2%