Skip to content

LuanVittor/CRUD-typescript

Repository files navigation

Termos e acordos

Ao iniciar este projeto, você concorda com as diretrizes do Código de Ética e Conduta e do Manual da Pessoa Estudante da Trybe.

Boas vindas ao repositório do projeto Trybesmith!

Você já usa o GitHub diariamente para desenvolver os exercícios, certo? Agora, para desenvolver os projetos, você deverá seguir as instruções a seguir. Tenha atenção a cada passo, e se tiver qualquer dúvida, nos envie por Slack! #vqv 🚀

Aqui você vai encontrar os detalhes de como estruturar o desenvolvimento do seu projeto a partir deste repositório, utilizando uma branch específica e um Pull Request para colocar seus códigos.


Sumário


Habilidades

Neste projeto, você será capaz de:

  • Declarar variáveis e funções com tipagens Typescript;

  • Construir uma API Node Express utilizando o Typescript.


Entregáveis

Para entregar o seu projeto você deverá criar um Pull Request neste repositório.

Lembre-se que você pode consultar nosso conteúdo sobre Git & GitHub sempre que precisar!


O que deverá ser desenvolvido

Para este projeto, você vai desenvolver um CRUD (Create, Read, Update e Delete) de itens medievais, no formato de uma API, utilizando Typescript.

Você irá criar alguns endpoints que irão ler e escrever em um banco de dados, utilizando o MySQL.


Desenvolvimento

Você vai desenvolver todas as camadas da aplicação (Models, Service e Controllers) em seu código e, por meio dessa aplicação, será possível realizar as operações básicas que se pode fazer em um determinado banco de dados: Criação, Leitura, Atualização e Exclusão (ou CRUD, para as pessoas mais íntimas 😜).

O código para cadastro de pessoas usuárias deve ser criado por você utilizando os conhecimentos adquiridos nesse bloco.

⚠️ Dicas Importantes ⚠️:

  • Não haverá front-end neste projeto, portanto não se preocupe com a visualização, apenas com as funcionalidades e organização do código.

  • Sua API deve ser desenvolvida dentro da pasta ./src;


Data de Entrega

  • Será X dia de projeto.
  • Data de entrega para avaliação final do projeto: 05/04/2022 14:00.

Instruções para entregar seu projeto

Antes de começar a desenvolver

  1. Clone o repositório
  • git clone https://github.com/tryber/sd-015-a-project-trybesmith.git.
  • Entre na pasta do repositório que você acabou de clonar:
    • cd sd-015-a-project-trybesmith
  1. Instale as dependências [Caso existam]
  • npm install
  1. Crie uma branch a partir da branch main
  • Verifique que você está na branch main
    • Exemplo: git branch
  • Se não estiver, mude para a branch main
    • Exemplo: git checkout main
  • Agora crie uma branch à qual você vai submeter os commits do seu projeto
    • Você deve criar uma branch no seguinte formato: nome-de-usuario-nome-do-projeto
    • Exemplo: git checkout -b joaozinho-sd-015-a-project-trybesmith
  1. Adicione as mudanças ao stage do Git e faça um commit
  • Verifique que as mudanças ainda não estão no stage
    • Exemplo: git status (deve aparecer listada a pasta joaozinho em vermelho)
  • Adicione o novo arquivo ao stage do Git
    • Exemplo:
      • git add . (adicionando todas as mudanças - que estavam em vermelho - ao stage do Git)
      • git status (deve aparecer listado o arquivo joaozinho/README.md em verde)
  • Faça o commit inicial
    • Exemplo:
      • git commit -m 'iniciando o projeto x' (fazendo o primeiro commit)
      • git status (deve aparecer uma mensagem tipo nothing to commit )
  1. Adicione a sua branch com o novo commit ao repositório remoto
  • Usando o exemplo anterior: git push -u origin joaozinho-sd-015-a-project-trybesmith
  1. Crie um novo Pull Request (PR)
  • Vá até a página de Pull Requests do repositório no GitHub
  • Clique no botão verde "New pull request"
  • Clique na caixa de seleção "Compare" e escolha a sua branch com atenção
  • Clique no botão verde "Create pull request"
  • Adicione uma descrição para o Pull Request e clique no botão verde "Create pull request"
  • Não se preocupe em preencher mais nada por enquanto!
  • Volte até a página de Pull Requests do repositório e confira que o seu Pull Request está criado

Durante o desenvolvimento

  • Faça commits das alterações que você fizer no código regularmente.

  • Lembre-se de sempre após um (ou alguns) commits atualizar o repositório remoto.

  • Os comandos que você utilizará com mais frequência são:

    1. git status (para verificar o que está em vermelho - fora do stage - e o que está em verde - no stage)
    2. git add (para adicionar arquivos ao stage do Git)
    3. git commit (para criar um commit com os arquivos que estão no stage do Git)
    4. git push -u nome-da-branch (para enviar o commit para o repositório remoto na primeira vez que fizer o push de uma nova branch)
    5. git push (para enviar o commit para o repositório remoto após o passo anterior)

Como desenvolver

⚠️ Leia-os atentamente e siga à risca o que for pedido. ⚠️

👀 Observações importantes:

  • O não cumprimento de um requisito, total ou parcialmente, impactará em sua avaliação;
  • O projeto deve rodar na porta 3000;
  • O arquivo index.ts existe para rodar corretamente os testes. Todo o projeto (incluindo as rotas) deverá ser feito dentro do arquivo app.ts;
  • Você pode utilizar as funções json.parse e json.stringify nos models;

Todos os seus endpoints devem estar no padrão REST

  • Use os verbos HTTP adequados para cada operação.

  • Agrupe e padronize suas URL em cada recurso.

  • Garanta que seus endpoints sempre retornem uma resposta, havendo sucesso nas operações ou não.

  • Retorne os códigos de status corretos (recurso criado, erro de validação, etc).


Há dois arquivos no diretório ./src/: index.ts e app.ts, ambos não devem ser renomeados ou apagados.

Você poderá fazer modificações em ambos os arquivos, porém no arquivo app.ts o seguinte trecho de código não deve ser removido:

import express from 'express';

const app = express();

app.use(express.json());

export default app;

Isso está configurado para o avaliador funcionar corretamente.

Conexão com o Banco

A conexão do banco local deverá conter os seguintes parâmetros:

import dotenv from 'dotenv';
import mysql from 'mysql2/promise';

dotenv.config();

const connection = mysql.createPool({
  host: process.env.MYSQL_HOST,
  user: process.env.MYSQL_USER,
  password: process.env.MYSQL_PASSWORD,
});

export default connection;

⚠️ É essencial configurar essas 3 variáveis de ambiente para testar o projeto localmente: ⚠️

  host: process.env.MYSQL_HOST
  user: process.env.MYSQL_USER
  password: process.env.MYSQL_PASSWORD

⚠️ É essencial que seu arquivo tenha o nome de connection.ts e esteja no diretório src/models ⚠️

Tabelas

O banco terá três tabelas: pessoas usuárias, produtos e pedidos.

DROP SCHEMA IF EXISTS Trybesmith;
CREATE SCHEMA Trybesmith;

CREATE TABLE Trybesmith.Users (
  id INTEGER AUTO_INCREMENT PRIMARY KEY NOT NULL,
  username TEXT NOT NULL,
  classe TEXT NOT NULL,
  level INTEGER NOT NULL,
  password TEXT NOT NULL
);

CREATE TABLE Trybesmith.Orders (
  id INTEGER AUTO_INCREMENT PRIMARY KEY NOT NULL,
  userId INTEGER,
  FOREIGN KEY (userId) REFERENCES Trybesmith.Users (id)
);

CREATE TABLE Trybesmith.Products (
  id INTEGER AUTO_INCREMENT PRIMARY KEY NOT NULL,
  name TEXT NOT NULL,
  amount TEXT NOT NULL,
  orderId INTEGER,
  FOREIGN KEY (orderId) REFERENCES Trybesmith.Orders (id)
);

Linter

Usaremos o ESLint para fazer a análise estática do seu código.

Este projeto já vem com as dependências relacionadas ao linter configuradas no arquivos package.json.

Para poder rodar os ESLint em um projeto, basta executar o comando npm install dentro do projeto e depois npm run lint. Se a análise do ESLint encontrar problemas no seu código, tais problemas serão mostrados no seu terminal. Se não houver problema no seu código, nada será impresso no seu terminal.

⚠ PULL REQUESTS COM ISSUES DE LINTER NÃO SERÃO AVALIADAS. ATENTE-SE PARA RESOLVÊ-LAS ANTES DE FINALIZAR O DESENVOLVIMENTO! ⚠

Você pode também instalar o plugin do ESLint no VSCode, bastar ir em extensions e baixar o plugin ESLint.

Testes

Todos os requisitos do projeto serão testados automaticamente. Cada endpoint possui vários requisitos e os testes para cada requisito de um endpoint estão no arquivo de teste.

Para executar os testes localmente, digite no terminal o comando npm test.

Dica: desativando testes

Especialmente no início, quando a maioria dos testes está falhando, a saída após executar os testes é bastante poluída. Você pode desabilitar temporariamente um teste utilizando a função skip junto à função it. Como o nome indica, esta função "pula" um teste:

  it.skip('Será validado que o campo "username" é obrigatório', async () => {
    const result = await request(app).post("/users").send({
      level: 2,
      classe: "classe",
      password: "senha",
    });
    expect(result.statusCode).toEqual(400);
    expect(result.body.error).toEqual("Username is required");
  });

Uma estratégia é pular todos os testes no início e ir implementando um teste de cada vez, removendo dele a função skip.

Testando um arquivo específico

⚠️ Lembre-se de não entregar o projeto com nenhum teste ignorado. Testes ignorados serão tratados como testes falhando. ⚠️

⚠️ Não apague, em hipótese alguma, qualquer teste ou arquivo deste repositório. ⚠️


Requisitos do projeto

Requisitos Obrigatórios

1 - Crie um endpoint para a listagem de produtos

  • O endpoint deve ser acessível através do caminho (/products);
Além disso, as seguintes verificações serão feitas:

👉 Para caso os dados sejam enviados corretamente

  • [Será validado que é possível listar todos os produtos com sucesso]
    • O resultado retornado para listar produtos com sucesso deverá ser conforme exibido abaixo, com um status http 200:
    [
      {
        "id": 1,
        "name": "Poção de cura",
        "amount": "20 gold",
        "orderId": null
      },
      {
        "id": 2,
        "name": "Escudo do Herói",
        "amount": "100 diamond",
        "orderId": 1
      }
    ]

2 - Crie um endpoint para o cadastro de produtos

  • O endpoint deve ser acessível através do caminho (/products).

  • Os produtos enviados devem ser salvos na tabela Products do banco de dados;

  • O endpoint deve receber a seguinte estrutura:

  {
    "name": "Espada longa",
    "amount": "30 peças de ouro"
  }
Além disso, as seguintes verificações serão feitas:

👉 Para name

  • [Será validado que o campo "name" é obrigatório]

    • Se o campo "name" não for informado, o resultado retornado deverá ser um status http 400 e
      { "error": "Name is required" }
  • [Será validado que o campo "name" tem o tipo string]

    • Se o campo "name" não for do tipo string, o resultado retornado deverá ser um status http 422 e
      { "error": "Name must be a string" }
  • [Será validado que o campo "name" é uma string com mais de 2 caracteres]

    • Se o campo "name" não for uma string com mais de 2 caracteres, o resultado retornado deverá ser um status http 422 e
      { "error": "Name must be longer than 2 characters" }

👉 Para amount

  • [Será validado que o campo "amount" é obrigatório]

    • Se o campo "amount" não for informado, o resultado retornado deverá ser um status http 400 e
      { "error": "Amount is required" }
  • [Será validado que o campo "amount" tem o tipo string]

    • Se o campo "amount" não for do tipo string, o resultado retornado deverá ser um status http 422 e
      { "error": "Amount must be a string" }
  • [Será validado que o campo "amount" é uma string com mais de 2 caracteres]

    • Se o campo "amount" não for uma string com mais de 2 caracteres, o resultado retornado deverá ser um status http 422 e
      { "error": "Amount must be longer than 2 characters" }

👉 Para caso os dados sejam enviados corretamente

  • [Será validado que é possível cadastrar um produto com sucesso]
    • O resultado retornado para cadastrar o produto com sucesso deverá ser conforme exibido abaixo, com um status http 201:
      {
        "item": {
          "id": 1,
          "name": "Poção de cura",
          "amount": "20 gold",
        }
      }

3 - Crie um endpoint para o cadastro de pessoas usuárias

  • O endpoint deve ser acessível através do caminho (/users);

  • As informações de pessoas usuárias cadastradas devem ser salvas na tabela Users do banco de dados;

  • O endpoint deve receber a seguinte estrutura:

{
  "username": "string",
  "classe": "string",
  "level": 1,
  "password": "string"
}
Além disso, as seguintes verificações serão feitas:

👉 Para username

  • [Será validado que o campo "username" é obrigatório]

    • Se a requisição não tiver o campo "username", o resultado retornado deverá ser um status http 400 e
      { "error": "Username is required" }
  • [Será validado que o campo "username" tem o tipo string]

    • Se o campo "username" não for do tipo string, o resultado retornado deverá ser um status http 422 e
      { "error": "Username must be a string" }
  • [Será validado que o campo "username" é uma string com mais de 2 caracteres]

    • Se o campo "username" não for do tipo string com mais de 2 caracteres, o resultado retornado deverá ser um status http 422 e
      { "error": "Username must be longer than 2 characters" }

👉 Para classe

  • [Será validado que o campo "classe" é obrigatório]

    • Se a requisição não tiver o campo "classe", o resultado retornado deverá ser um status http 400 e
      { "error": "classe is required" }
  • [Será validado que o campo "classe" tem o tipo string]

    • Se o campo "classe" não for do tipo string, o resultado retornado deverá ser um status http 422 e
      { "error": "Classe must be a string" }
  • [Será validado que o campo "classe" é uma string com mais de 2 caracteres]

    • Se o campo "classe" não for do tipo string com mais de 2 caracteres, o resultado retornado deverá ser um status http 422 e
      { "error": "Classe must be longer than 2 characters" }

👉 Para level

  • [Será validado que o campo "level" é obrigatório]

    • Se a pessoa usuária não tiver o campo "level", o resultado retornado deverá ser um status http 400 e
      { "error": "Level is required" }
  • [Será validado que o campo "level" tem o tipo number]

    • Se o campo "level" não for do tipo number, o resultado retornado deverá ser um status http 422 e
      { "error": "Level must be a number" }
  • [Será validado que o campo "level" deve ser um número maior que 0]

    • Se o campo "level" não for do tipo number maior que 0, o resultado retornado deverá ser um status http 422 e
      { "error": "Level must be greater than 0" }

👉 Para password

  • [Será validado que o campo "password" é obrigatório]

    • Se a requisição não tiver o campo "password", o resultado retornado deverá ser um status http 400 e
      { "error": "Password is required" }
  • [Será validado que o campo "password" tem o tipo string]

    • Se o campo "password" não for do tipo string, o resultado retornado deverá ser um status http 422 e
      { "error": "Password must be a string" }
  • [Será validado que o campo "password" é uma string com 8 ou mais caracteres]

    • Se o campo "password" não for do tipo string com mais de 8 caracteres, o resultado retornado deverá ser um status http 422 e
      { "error": "Password must be longer than 7 characters" }

👉 Para caso os dados sejam enviados corretamente

  • [Será validado que é possível cadastrar a pessoa usuária com sucesso]
    • Se a pessoa usuária for cadastrada com sucesso, o resultado deverá ser conforme o exibido abaixo, com um status http 201 e retornando um token:
    {
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
    }

4 - Crie um endpoint para listar todos os pedidos

  • O endpoint deve ser acessível através do caminho (/orders).
Além disso, as seguintes verificações serão feitas:

👉 Para orders

  • [Será validado que é possível listar todos os pedidos com sucesso]
    • Quando houver mais de um pedido, o resultado retornado para listar pedidos com sucesso deverá ser conforme exibido abaixo, com um status http 200:
      [
        {
          "id": 1,
          "userId": 2,
          "products": [1, 2]
        },
        {
          "id": 2,
          "userId": 2,
          "products": [3, 4]
        }
      ]

Requisito Bônus

5 - Crie um endpoint para o login de pessoas usuárias

  • O endpoint deve ser acessível através do caminho (/login).

  • A rota deve receber os campos username e password, e esses campos devem ser validados no banco de dados.

  • Um token JWT deve ser gerado e retornado caso haja sucesso no login. No seu payload deve estar presente o id e username.

  • O endpoint deve receber a seguinte estrutura:

  {
    "username": "string",
    "password": "string"
  }

⚠️ Na configuração do JWT não use variáveis de ambientes para não ter conflito com o avaliador.

Além disso, as seguintes verificações serão feitas:

👉 Para caso haja problemas no login

  • [Será validado que o campo "username" é enviado]

    • Se o login não tiver o campo "username", o resultado retornado deverá ser um status http 400 e
      { "error": "Username is required" }
  • [Será validado que o campo "password" é enviado]

    • Se o login não tiver o campo "password", o resultado retornado deverá ser um status http 400
      { "error": "Password is required" }
  • [Será validado que não é possível fazer login com um username inválido]

    • Se o login tiver o username inválido, o resultado retornado deverá ser um status http 401 e
      { "error": "Username or password invalid" }
  • [Será validado que não é possível fazer login com uma senha inválida]

    • Se o login tiver a senha inválida, o resultado retornado deverá ser um status http 401 e
      { "error": "Username or password invalid" }

👉 Para caso os dados sejam enviados corretamente

  • [Será validado que é possível fazer login com sucesso]
    • Se o login foi feito com sucesso, o resultado deverá ser um status http 200 e deverá retornar um token:
    {
      "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
    }

6 - Crie um endpoint para o cadastro de um pedido

  • O endpoint deve ser acessível através do caminho (/orders).

  • Um pedido só pode ser criado caso a pessoa usuária esteja logada e o token JWT validado.

  • Os pedidos enviados devem ser salvos na tabela Orders do banco de dados. A tabela Products também deve ser alterada;

  • O endpoint deve receber a seguinte estrutura:

  {
    "products": [1, 2]
  }

⚠️ Ao cadastrar um pedido, lembre-se de atualizar os respectivos produtos no banco de dados, incluindo neles o número do pedido criado.

Além disso, as seguintes verificações serão feitas:

👉 Para token

  • [Será validado que não é possível cadastrar pedidos sem token]

    • Se o token não for informado, o resultado retornado deverá ser um status http 401 e
      { "error": "Token not found" }
  • [Será validado que não é possível cadastrar um pedido com token inválido]

    • Se o token informado não for válido, o resultado retornado deverá ser um status http 401 e
      { "error": "Invalid token" }

👉 Para products

  • [Será validado que o campo "products" é obrigatório]

    • Se o corpo da requisição não possuir o campo "products", o resultado retornado deverá ser um status http 400 e
      { "error": "Products is required" }
  • [Será validado que não é possível criar um pedido com o campo "products" não sendo um array]

    • Se o valor do campo "products" não for um array, o resultado retornado deverá ser um status http 422 e
      { "error": "Products must be an array of numbers" }
  • [Será validado que não é possível cadastrar um pedido se o campo "products" for um array vazio]

    • Se o campo "products" possuir um array vazio, o resultado retornado deverá ser um status http 422 e
      { "error": "Products can't be empty" }

👉 Para caso os dados sejam enviados corretamente

  • [Será validado que é possível criar um pedido com sucesso com 1 item]

    • O resultado retornado para cadastrar um pedido com sucesso deverá ser conforme exibido abaixo, com um status http 201:
      {
        "order": {
          "userId": 1,
          "products": [1],
        }
      }
  • [Será validado que é possível criar um pedido com sucesso com vários itens]

    • O resultado retornado para cadastrar um pedido com sucesso deverá ser conforme exibido abaixo, com um status http 201:
      {
        "order": {
          "userId": 1,
          "products": [1, 2]
        }
      }

Depois de terminar o desenvolvimento (opcional)

Para sinalizar que o seu projeto está pronto para o "Code Review" dos seus colegas, faça o seguinte:

  • Vá até a página DO SEU Pull Request, adicione a label de "code-review" e marque seus colegas:

    • No menu à direita, clique no link "Labels" e escolha a label code-review;

    • No menu à direita, clique no link "Assignees" e escolha o seu usuário;

    • No menu à direita, clique no link "Reviewers" e digite students, selecione o time tryber/students-sd-00.

Caso tenha alguma dúvida, aqui tem um video explicativo.


Revisando um pull request

Use o conteúdo sobre Code Review para te ajudar a revisar os Pull Requests.

#VQV


Avisos finais

Ao finalizar e submeter o projeto, não se esqueça de avaliar sua experiência preenchendo o formulário. Leva menos de 3 minutos!

Link: FORMULÁRIO DE AVALIAÇÃO DE PROJETO

O avaliador automático não necessariamente avalia seu projeto na ordem em que os requisitos aparecem no README. Isso acontece para deixar o processo de avaliação mais rápido. Então, não se assuste se isso acontecer, ok?

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published