{"id":21044025,"url":"https://github.com/ribeirogab/goomer-lista-rango","last_synced_at":"2025-05-15T17:32:20.880Z","repository":{"id":48526673,"uuid":"386898081","full_name":"ribeirogab/goomer-lista-rango","owner":"ribeirogab","description":"API RESTful capaz de gerenciar os restaurantes e os produtos do seu cardápio.","archived":false,"fork":false,"pushed_at":"2021-07-21T23:38:44.000Z","size":2194,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-03T12:52:01.409Z","etag":null,"topics":["jest","nodejs","pg","typescript"],"latest_commit_sha":null,"homepage":"https://goomer-lista-rango.ribeirogab.me","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ribeirogab.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-07-17T09:46:04.000Z","updated_at":"2024-02-16T23:38:34.000Z","dependencies_parsed_at":"2022-08-31T09:41:59.605Z","dependency_job_id":null,"html_url":"https://github.com/ribeirogab/goomer-lista-rango","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ribeirogab%2Fgoomer-lista-rango","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ribeirogab%2Fgoomer-lista-rango/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ribeirogab%2Fgoomer-lista-rango/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ribeirogab%2Fgoomer-lista-rango/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ribeirogab","download_url":"https://codeload.github.com/ribeirogab/goomer-lista-rango/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254388242,"owners_count":22063011,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["jest","nodejs","pg","typescript"],"created_at":"2024-11-19T14:15:02.430Z","updated_at":"2025-05-15T17:32:19.651Z","avatar_url":"https://github.com/ribeirogab.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  \u003cimg src=\"https://i.ibb.co/YPChnDc/Lista-Rango-2.png\" alt=\"Goomer Lista Rango API\" width=\"260\"/\u003e\n\u003c/h1\u003e\n\n# 🍴 Goomer Lista Rango API 🍴\n\n\u003e API RESTful capaz de gerenciar os restaurantes e os produtos do seu cardápio.\n\n- [Tecnologias](#Tecnologias)\n- [Desafios](#Desafios)\n- [Melhorias](#Melhorias)\n- [Arquitetura](#Arquitetura)\n- [Instalação](#Instalação)\n- [Testes](#Testes)\n\n**✨ Demo:** [**https://goomer-lista-rango.ribeirogab.me**](https://goomer-lista-rango.ribeirogab.me)\n\n# Tecnologias\n\n###### Linguagens e ferramentas:\n\n- [Node.js](https://nodejs.org/);\n- [TypeScript](https://www.typescriptlang.org/).\n\n###### Banco de Dados:\n\n- [PostgreSQL](https://www.postgresql.org/).\n\n###### Testes unitários:\n\n- [Jest](https://jestjs.io/).\n\n###### Cache:\n\n- [Redis](https://redis.io/).\n\n###### Ambiente\n\n- [Docker](https://docs.docker.com/);\n- [Docker Compose](https://docs.docker.com/compose/).\n\n###### Padronização de código/commits:\n\n- [ESLint](https://eslint.org/);\n- [Prettier](https://prettier.io/);\n- [Commitizen](https://github.com/commitizen/cz-cli).\n\n# Desafios\n\n**Trabalhar sem ORM:**\n\nTrabalhar sem ter um ``ORM``. Ter que relembrar e escrever SQL puro, aprender como fazer agregações no PostgreSQL e criar uma arquitetura própria de relação entre as ``entities`` do projeto com certeza foi o maior desafio.\n\n**TDD:**\n\nOutro desafio foi escrever primeiramente todos os testes unitários da aplicação com os repositórios fakes para somente após isso criar e implementar os repositórios do PostgreSQL. Está decisão foi tomada pelo fato de ter que criar toda a lógica no SQL manualmente, implementar essas lógicas primeiramente nos testes ajudaram bastante na criação dos repositórios do PostgreSQL.\n\n# Possíveis melhorias\n\n\u003c!-- **Testes de integração:** --\u003e\n\n**🟥 Tabela de indisponibilidade:**\n\nCriar uma tabela de indisponibilidade no banco de dados para que os restaurantes consigam cadastrar um horário que estarão ausentes. Por exemplo:\n\nUm restaurante trabalha das 11:00 às 17:00 de segunda à sexta, porém, em uma semana específica ele funcionará das 11:00 às 15:00 na segunda-feira (os outros dias continuam normais), por conta de algum compromisso/imprevisto ou qualquer outra coisa. Tendo uma tabela de indisponibilidade, o restaurante poderá cadastrar exatamente o período que estará indisponível, sem precisar alterar o seu horário de trabalho fixo.\n\n---\n\n**🟢 Implementar um ORM:**\n\nApesar da aplicação estar relativamente organizada, um ``ORM`` seria de grande ajuda principalmente para deixar o código mais legível e manutenível, retirando toda a complexidade do SQL dos repositórios.\n\nOpções de ORM:\n\n- Sequelize;\n- TypeORM.\n\n---\n\n**📬 API de códigos postais:**\n\nAtualmente a API possui um ``provider`` códigos postais com duas implementações:\n\n- Brasil API;\n- Postmon.\n\nPorém essas APIs fornecem apenas códigos postais (CEP) do Brasil, sendo assim, a aplicação ficaria limitada a somente o Brasil. (dependendo do objetivo da aplicação isso não é um problema)\n\nPossíveis soluções:\n\n- Criar uma implementação do [Zipcodebase](https://zipcodebase.com/):\n\n  O Zipcodebase é uma API de códigos postais **globais**, porém disponibiliza apenas 5000 requisições mensais, dependendo do tamanho da aplicação pode ser viável. (os planos pagos são bem caros $$$)\n\n---\n\n**🔑 API KEY:**\n\nComo a API não tem nenhuma forma de autenticação e todas as rotas são públicas isso a torna muito insegura e vulnerável.\n\nUm exemplo de vulnerabilidade são as rotas de envio de imagem em ambiente de produção, atualmente a aplicação está utilizando o Amazon S3 para armazenar as imagens, sendo assim, qualquer pessoa que tiver acesso a essas rotas conseguem enviar imagens para o bucket do projeto no S3, ou seja, **MUITO GRAVE**.\n\nNo momento a autenticação via ``API KEY`` não foi implementada para facilitar os testes, mas após o término do processo essas chaves de autenticação serão configuradas para aumentar a segurança da API e evitar dores de cabeça.\n\nEm ambiente de desenvolvimento a aplicação está utilizando o ``DiskProvider`` que salva as imagens diretamente no disco sendo assim, não é um problema.\n\n---\n\n**❌ Excluir promoções automaticamente:**\n\nQuando um produto é colocado em promoção temos a data/hora de início e término, ao fim da promoção o registro continua vigente no banco de dados e na listagem de produto(s).\n\nUma possível melhoria que evitaria informações desnecessárias no banco seria: após o fim da promoção deletar o registro do banco de dados e \"setar\" o campo ``promotion`` dos produtos (nas listagens) como ``null``.\n\n# Arquitetura\n\nO projeto foi construído em cima da arquitetura Domain-Driven Design ou Projeto Orientado a Domínio (famoso DDD) que é um padrão de modelagem orientado a objetos (ou módulos).\n\n**🌐 Arquitetura global:**\n\n```shell\nsrc/\n|-- config/ # Contém os arquivos de configuração, exemplo: dotenv, cache e upload\n|-- modules/ # Contém os módulos (ou objetos) da aplicação\n|-- shared/ # Arquivos compartilhados (globais), exemplo: server, errors e container de injeção de dependência\n|-- swagger.json # Apenas a documentação\n```\n\n\u003cbr\u003e\n\n**📁 Arquitetura dos módulos:**\n\n```shell\n{module}/\n|-- infra/ # Contém as rotas, controllers e implementações de repositórios\n|-- models/ # Contém o modelo (ou estrutura) de dados do módulo\n|-- providers/ # Arquivos dos repositórios e providers do módulo para serem \"injetados\" no container de injeção de dependência\n|-- repositories/ # Modelo de dados, DTOs e fakes dos repositórios do módulo\n|-- services/ # Serviços ou regra de negócio da aplicação\n|-- utils/ # Arquivo com funções/lógicas que são utilizadas em dois ou mais services\n```\n\n\u003cbr\u003e\n\n**↔️ Fluxo de requisição:**\n\nDe forma abstrata, a aplicação possuí o seguinte fluxo de requisição:\n\n\u003cimg src=\"https://i.ibb.co/yQwBJRk/Fluxo-de-requisi-o-2x-1.png\" alt=\"Fluxo de requisição\" width=\"800\"/\u003e\n\n\u003cbr\u003e\n\n# Banco de dados\n\nO banco de dados utilizado no projeto foi o PostgreSQL, mais por questão de familiaridade do que alguma outra razão específica.\n\n**💾 Modelo (DER):**\n\n\u003cimg src=\"https://i.ibb.co/4mFyy6f/Goomer-Lista-Rango-2x-8.png\" alt=\"DER\" width=\"800\"/\u003e\n\n\u003e [SQL de criação do banco](https://github.com/ribeirogab/goomer-lista-rango/blob/main/src/shared/infra/databases/postgreSQL/init.sql)\n\n# Instalação\n\n```sh\ngit clone https://github.com/ribeirogab/goomer-lista-rango\n```\n\n```sh\ncd goomer-lista-rango\n```\n\n## **Rodando o projeto**\n\nAs rotas da aplicação podem ser testadas localmente ou em pode seguir uma das três opções descritas a seguir.\n\nOpções:\n\n- [Docker Compose](#docker-compose-recomendada); (Recomendada)\n- [Manualmente](#manualmente);\n- [Docker run](#docker-run).\n\n## **Docker Compose (Recomendada)**\n\n### **Requisitos**\n\n- [Docker](https://docs.docker.com/engine/install/) versão 20.10.2 ou superior;\n- [Docker Compose](https://docs.docker.com/compose/install/) versão 1.29.2 ou superior.\n\n---\n\n### **Desenvolvimento**\n\nApós clonar o projeto e instalar as dependências, execute o seguinte comando para rodar a aplicação:\n\n```sh\ndocker-compose up\n```\n\n\u003e Após os containers subirem, a aplicação estará disponível em [http://localhost:3333/](http://localhost:3333/)\n\n---\n\n### **Produção**\n\nPara executar o projeto em produção, será necessário criar um arquivo ``.env`` na raiz do projeto e preenche-lo, caso seja apenas um teste, basta copiar os valores de ``.env.example``.\n\n```sh\ncp .env.example .env\n```\n\nCom o ``.env`` criado e preenchido, rode o seguinte comando:\n\n```sh\ndocker-compose -f docker-compose.yml up\n```\n\n---\n\n## **Manualmente**\n\nPara ver as instruções de como rodar o projeto manualmente clique [aqui](./docs/RUN.md#manualmente).\n\n## **Docker run**\n\nPara ver as instruções de como rodar o projeto utilizando ``docker run`` [aqui](./docs/RUN.md#docker-run).\n\n# Testes\n\n## **Rotas**\n\nAs rotas da aplicação podem ser testadas localmente com o repositório clonado ou em [**https://goomer-lista-rango.ribeirogab.me**](https://goomer-lista-rango.ribeirogab.me) (o servidor está espelhando o código da branch ``main``).\n\n**Requests Collections:**\n\nCaso seja preciso, as *requests collections* para testar as rotas no **Postman** e/ou **Insomnia**, o download pode ser feito clicando na opção desejada:\n\n- [Insomnia](https://drive.google.com/file/d/10A23rAAa1VWtDu7Tqm9lI9MlPqVCNbpX/view?usp=sharing);\n- [Postman](https://drive.google.com/file/d/1JcjkTyhFi9Ui0U_q92MlhqMViB0f0Zuh/view?usp=sharing).\n\n---\n\n## **Testes unitários**\n\nCom a aplicação clonada e as dependências instaladas, para rodar os testes unitários execute o seguinte comando:\n\n```sh\nyarn test\n```\n\n**🧪 Cobertura:**\n\n\u003cimg src=\"https://i.ibb.co/LJMfJtW/Screenshot-20210720-181328.png\" alt=\"Cobertura dos testes\" width=\"480\"/\u003e\n\n\nPara visualizar a cobertura dos testes de uma maneira mais intuítiva, acesse o diretório ``goomer-lista-rango/coverage/lcov-report``.\n\nEsta pasta possuí um arquivo ``index.html``, que ao ser aberto exibirá a cobertura de todos os testes em uma página web.\n\n---\n\n## Contato\n\nQualquer dúvida, sugestão ou crítica construtiva estarei à disposição! :)\n\n**Muito obrigado!** 💙\n\nE-mail: **ribeirogabx@gmail.com**\n\nLinkedIn: [**https://www.linkedin.com/in/ribeirogab/**](https://www.linkedin.com/in/ribeirogab/*)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fribeirogab%2Fgoomer-lista-rango","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fribeirogab%2Fgoomer-lista-rango","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fribeirogab%2Fgoomer-lista-rango/lists"}