# Boas vindas ao repositório Games Store (Backend) Esse projeto é Uma API RESTfull de um sistema de gerenciamento de uma loja de games, onde é possível criar, visualizar, deletar e atualizar os produtos e as vendas. Usado Node.js, Express e MongoDB. Ainda em fase de desenvolvimento, porém é possível já utilizar. --- ### Tem FRONT ? Aqui está o [link](https://github.com/becauro/games-store-front) do repositório **frontend** que também fiz para usar com essa API. Desenvolvi algumas interfaces para interagir com essa API. Então, corre lá pra dá uma olhada e aproveite para sentar aquele dedo nos botões de `Code Review` pra ajudar o projeto. ## Sumário - [Habilidades](#habilidades) - [Descrição](#descrição) - [Requisitos de usuário](#requisitos-de-usuário) - Arquitetura e padrões - Tecnologias utilizadas - Futuras implementações - Requisitos para execução da API - [Como executar](#como-executar) - [Endpoints](#endpoints) - [Linter](#linter) - [Observações](#observações) - [Requisitos funcionais](#requisitos-funcionais) ## Habilidades Esse projeto teve como objetivo praticar as seguintes hardskills: - Estruturação de uma aplicação em camadas (Arquitetura MSC); - Delegação de responsabilidades específicas para cada parte do app; - Melhora da manutenibilidade e reusabilidade do código; - Aplicação dos padrões REST; - Implementação de uma API intuitiva e facilmente entendível. --- ## Descrição Se trata de uma API de gerenciamento de vendas que manipula **produtos** e **vendas**. Basicamente é um modesto controle de estoque em forma de CRUD para lidar tanto com produtos como com as vendas . Seguindo os princípios REST foi desenvolvido alguns ENDPOINTS que se conectam a um banco de dados NÃO relacional (NoSQL), MongoDB. Há uma Collection para **produtos** (products) serem cadastrados na aplicação, afim de ser possível fazer vendas com esses produtos. Da mesma forma, uma Collection para **vendas** (sales) também foi criada. Essas vendas são realizadas conforme a quantidade de produtos disponíveis em estoque. ## Requisitos de Usuário * Deve ser possível que a pessoa usuária, independente de cadastramento ou login, possa adicionar, ler, deletar e atualizar produtos no seu estoque. (Mas irei implantar Login e autorizações de usuários também brevemente) * O usuário deve poder também enviar vendas para o sistema. Essas vendas devem validar se o produto em questão existe. * Deve, também, ser possível ler, deletar e atualizar vendas. ## Arquitetura e Padrões Sumário * Arquitetura MSC * API RESTfull ## Tecnologias utilizadas Sumário * Node.js * Express * MongoDB * ESLinter (Para auxiliar na análise de erros no código e também para ajudar manter algumas boas práticas) ## Futuras implementações Sumário * Autenticação de Usuários (Login) * Autorizações de usuários com uso de tokens (JWT). * Implantar a aplicação via Cloud ou VPS, para que possa ser consumida e testada externamente. * Implantar o Banco de Dados em nuvem do [MongoDB Atlas](https://www.mongodb.com/atlas) ou algo do tipo. ## Requisitos para execução da API Sumário Você pode rodar esse projeto de duas maneiras: 1 - Via Docker 🐳 ou 2 - Manualmente 🖐️ ### Opção 1 - Via Docker Se não tiver, baixe-o no [site oficial](https://docs.docker.com/engine/install/) ### Opção 2 - Manualmente (Via Host) 1. **Node.js** Nodejs é um framework que tem um engine do Chrome modificada o qual permite que exista, no lado servidor, uma aplicação Web desenvolvida em JavaScript. Portanto é o primeiro sofware que permite esse projeto acontecer. Já testei com Node nas versões 14 à 18. Acredito que funcione nas outras versões. Para instalar , configurar e gerenciar Nodejs de forma produtiva, recomendo uso da ferramenta [NVM](https://github.com/nvm-sh/nvm#intro). Com NVM você consegue, "com um dedo", instalar várias versões do Nodejs e escolher qual usá-las quando precisar. Mas, se quiser ter mais trabalho, baixe o Nodejs do [site oficial](https://nodejs.org/en/). 2. **MongoDB** Essa API se comunica com um banco de dados não relacional (noSQL) implementado em MongoDB. Então precisa ter em _*algum lugar*_ (local ou remotamente) o software gerenciador de servidor de banco dados, MongoDB, que se possa usar aqui. Caso não o tenha, faça download e instale-o. [Site oficial](https://www.mongodb.com/try/download/community) para download do _*MongoDB Comunnity Edition*_. 3. **Software cliente** para requição de API (ex.: Postman, Insomnia e etc) Para testar todos os métodos de requição à essa API, se faz necessário um Software específico para isso. Dentre os mais conhecidos até o momento são [Postman](https://www.postman.com/downloads) e [Insomnia](https://insomnia.rest/download). Se for apenas testar o método GET no endpoint, apenas com um browser comum é possível. Por exemplo. Fazendo uma requisição GET a partir de um Browser (Firefox, Chrome e etc) para a URL **http://localhost:3000** , funciona. ## Como Executar Sumário ### Opção 1 - Via Docker **1. Verifique o arquivo compose.yml** Pode ser que tenha algo a ser mudado nesse aqruivo que atenda as tuas especificidades. Acredito que as únicas coisas relevantes que possa ter alguma possiblidade de mudança seria: _*1 - Porta exposta*_ e _*2 - Nome da rede*_ - Se porta padrão exposta (3000) já esteja em uso por outra aplicação, então mude isso, se for o caso. Quanto ao nome da rede, acho pouquíssimo provável que já exista outra como o mesmo nome. Todavia, mude se julgar necessário. - Se mudar valor da variável DB_NAME no arquivo *_compose.yml*_ , tambem terá que mudar nos arquivos **Dockerfile** e **models/Dockerfile**, E VICE-VERSA. Referente as outras opções, acredito não haver muita necessidade de alteração mesmo. Mas, se for alterar algo nesses arquivos, LEIA os comentários ali para não ficar batendo cabeça à toa, uma vez que alterações incorretas inviabilizam o correto funcionamento da aplicação. **2. Execute o docker compose** Basta usar o arquivo compose.yml e ajustar o que achar necessário antes Estando na pasta do arquivo, via CLI, basta digitar: ` docker compose up -d ` ### Opção 2 - Manualmente (Via Host) Instalado os requisitos e as dependências necessárias, basta seguir as seguintes etapas: **1. Variáveis de ambiente** Existe um arquivo na raiz do projeto chamado `.env.model`. Apesar de já explicado no tópico "Requisitos para execução da API", não custa ratificar aqui. As configurações do projeto também podem ser alteradas nesse arquivo, adicionando o valor desejado após o sinal de igual (=) em cada variável. **Lógico que não é obrigado essa alteração**, desde que não exista problemas com as configurações padrões do projeto. Se for usar o arquivo, terá que renomea-lo parar `.env`. As variáveis do arquivo .env.model são as seguintes: _*PORT*_, _*DB_NAME*_, _*DB_HOST*_ e _*DB_PORT*_. **PORT** diz respeito a porta em que o servidor irá rodar. Se nada for atribuido a essa variável, o servidor rodará na porta `3000`. **DB_NAME** refere-se ao nome do banco de dados que será criado. Se nada for atribuido, o nome do banco será `GamesStore`. **DB_HOST** refere-se ao local (hostname ou IP) do Banco de Dados. Se nada for atribuído, será considerado `localhost`. **DB_PORT** poderá receber a porta onde se encontra o Banco de Dados. Se nada for atribuído, será considerado a porta `27017`. **2. Banco de Dados MongoDB** Coloque em execução o software servidor de banco de dados MongoDB. **3. Execute o script para importar dados para o banco de dados** Para que essa API retorne dados na rota _*products*_, precisa, obviamente, ter dados no banco chamado _*GamesStore*_ (ou no banco com nome que você definiu na variável DB_NAME no arquivo .env) na coleção ("tabela") _*products*_. Por isso criei um shell script `models/db-import-for-host.sh` para automatizar a importação de dados, o qual cria o banco, a collection e importa dados que estão em outro script (arquivo `models/dataTestForDb.js`) para o banco criado. Assim, quando requisitado com GET no ENDPOINT _*products*_ será retornado esses dados previamente importados no banco, isentando a necessidade de criá-los manualmente para testar a API. **Se não quiser usar esse script, ok, a API funciona**, mas sem retornar dados; a menos que, alternativamente, cadastre-os, manualmente, usando a rota de POST, por exemplo. **Note**: Não criei script (importador de dados) para a rota _*sales*_. Se requisitares algo para esse ENDPOINT, sem ter dados na collection _*sales*_ no banco, não terás retorno de dados. **Note 2**: Os dados que se encontram no arquivo `models/dataTestForDb.js`, foram obtidos do [ENDPOINT de produtos para gamers, de uma API pública do Mercado Livre](https://api.mercadolibre.com/sites/MLB/search?category=MLB1144). Apenas modifiquei alguns pontos e parâmetros para se adaptar ao meu projeto. **4. Instale as dependências** Estando com acesso a internet e dentro da pasta raíz do projeto, execute o comando: `npm install` **5. Execute o projeto** Estando com acesso a internet e dentro da pasta raíz do projeto, execute o comando: `npm start` Se tudo ocorreu bem, após executar esse comando o servidor da API do projeto estará disponível para uso. Faça as requisições. **6. Fazendo requisições** Use algum software cliente de API (ex.: Postman, Insomnia e etc) e faça as requisições para os ENDPOINTs usando a URL **http://localhost:3000** Se for o caso, não esqueça de substituir `porta 3000` pela porta que você definiu na variável PORT do arquivo `.env`. ## Endpoints Sumário ### Produtos * GET: /products * GET: /products/:id * POST: /products * PUT: /products/:id * DELETE: /products/:id ### Vendas * GET: /sales * GET: /sales/:id * POST: /sales * PUT: /sales/:id * DELETE: /sales/:id ## Linter Sumário Foi usado [ESLint](https://eslint.org/) para fazer a análise estática do código, afim de manter padrões de indentação e espaçamento dos trechos de códigos. No entanto, para usá-lo de forma mais manual, o projeto já vem com as dependências relacionadas ao ESLint configuradas no arquivos `package.json`. Para executá-lo basta usar --- dentro da pasta do projeto --- o comando `npm run lint`. Se a análise do `ESLint` encontrar problemas no 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. ### ESLint de forma automática Particulamente eu preferi utilizar o [plugin `ESLint`](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) pela extensão do `VSCode`, em favor da produtividade. --- ## Observações Sumário ### Estrutura da lista de requisitos funcionais ### Estrutura do banco de dados: * **Observação:** O `_id` é gerado automaticamente. * O banco deve ter duas `collections`: uma para os _produtos_ e outra para as _vendas_ * A tabela de **produtos** terá o seguinte nome: `products` * Os campos da collection `products` terão esse formato: ```json { "name": "Sony Playstation 5 825gb Digital Edition Cor Branco E Preto", "price": 6499, "thumbnail": "http://http2.mlstatic.com/D_799755-MLA47058389754_082021-I.jpg", "description": "", "quantity": 7 } ``` * A tabela de **vendas** terá o seguinte nome: `sales` * Os campos da tabela `sales` terão esse formato: ```json { "itensSold": [{ "productId": "5f43cbf4c45ff5104986e81d", "quantity": 2 }] } ``` ### Shape de retorno após "insert" no banco: * A tabela de **produtos** * A resposta retornada após um `insert` (criação) no banco precisa ter o seguinte shape: ```json { "_id": ObjectId("5f43cbf4c45ff5104986e81d"), "name": "Produto tal", "quantity": 10 } ``` * A tabela de **vendas** * A resposta retornada após um `insert` (criação) no banco precisa ter o seguinte shape: ```json { "_id": ObjectId("5f43cc53c45ff5104986e81e"), "itensSold": [{ "productId": "5f43cbf4c45ff5104986e81d", "quantity": 2 }] } ``` ## Requisitos funcionais Sumário Para entender melhor a lógica por trás do código de desenvolvimento da API, é interessante olhar a _Requisitos funcionais_ do projeto. Acesse [aqui](Functional-Requirements.md) o **readme** desses _Requisitos Funcionais_.