From cf6d1525066855c94e8f575b6d4bd7799268fb60 Mon Sep 17 00:00:00 2001 From: ppastorf Date: Fri, 10 May 2024 14:42:20 -0300 Subject: [PATCH 01/29] Makefile --- Makefile | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..653e164e --- /dev/null +++ b/Makefile @@ -0,0 +1,73 @@ +.PHONY: * + +TAG_OR_COMMIT := $(shell git describe --tags --always) +DOCKER_REGISTRY = ghcr.io +IMAGE_NAME = $(DOCKER_REGISTRY)/sos-rs/backend + +install: + @npm install + +prisma: + @npx prisma generate + @npx run migrations:dev + +setup: + @$(MAKE) install + @$(MAKE) prisma + +local-start: + @$(MAKE) setup + @npm run start:dev + +local-start-debug: + @$(MAKE) setup + @npm run start:debug + +build: + @npm run build + +clean: + @rm -rf dist + +format: + @npm run format + +lint: + @npm run lint + +test: + @npm run test + +test-coverage: + @npm run test:cov + +test-debug: + @npm run test:debug + +test-e2e: + @npm run test:e2e + +dev-up: + @docker compose -f docker-compose.dev.yml up -d --build + +dev-down: + @docker compose -f docker-compose.dev.yml down + +dev-logs: + @docker compose -f docker-compose.dev.yml logs -f + +# Para ser usado no workflow de build +docker-build: + @docker build . -t sos-rs-backend + +docker-tag: + @docker tag sos-rs-backend $(IMAGE_NAME):$(TAG_OR_COMMIT) + @docker tag sos-rs-backend $(IMAGE_NAME):latest + +# Para ser usado no workflow de deploy +prod-up: + @docker compose -f docker-compose.yml up -d --build --force-recreate + +prod-down: + @docker compose -f docker-compose.yml down --rmi all + From eed5cb3e2dc0a4bc4342c6a5511deaacce9f3c4b Mon Sep 17 00:00:00 2001 From: ppastorf Date: Fri, 10 May 2024 14:42:49 -0300 Subject: [PATCH 02/29] usando diretivas de Makefile no workflow de deploy --- .github/workflows/deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index f2806b81..ff0a19b3 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -28,7 +28,7 @@ jobs: cat .env - name: Remove old docker image - run: echo ${{ secrets.SERVER_USER_PASSWORD }} | sudo -S docker compose down --rmi all + run: echo ${{ secrets.SERVER_USER_PASSWORD }} | sudo -S make prod-down - name: Create new docker image - run: echo ${{ secrets.SERVER_USER_PASSWORD }} | sudo -S docker compose up -d --force-recreate + run: echo ${{ secrets.SERVER_USER_PASSWORD }} | sudo -S make prod-up From df1909b4cddca8e0738c364d64a0ef19afe115c1 Mon Sep 17 00:00:00 2001 From: ppastorf Date: Sat, 11 May 2024 12:41:49 -0300 Subject: [PATCH 03/29] Makefile: rebase com alteracoes no readme --- Makefile | 8 ++++++-- README.md | 29 ++++++++--------------------- docker-compose.dev.yml | 1 + 3 files changed, 15 insertions(+), 23 deletions(-) diff --git a/Makefile b/Makefile index 653e164e..a37e20f1 100644 --- a/Makefile +++ b/Makefile @@ -15,11 +15,11 @@ setup: @$(MAKE) install @$(MAKE) prisma -local-start: +start: @$(MAKE) setup @npm run start:dev -local-start-debug: +start-debug: @$(MAKE) setup @npm run start:debug @@ -56,6 +56,10 @@ dev-down: dev-logs: @docker compose -f docker-compose.dev.yml logs -f +dev-db-load-dump: + @docker compose -f docker-compose.dev.yml cp prisma/dev_dump.sql db:/tmp/backup.sql + @docker compose -f docker-compose.dev.yml exec db psql -U root -d sos_rs -f /tmp/backup.sql + # Para ser usado no workflow de build docker-build: @docker build . -t sos-rs-backend diff --git a/README.md b/README.md index 6a231353..963a696c 100644 --- a/README.md +++ b/README.md @@ -14,14 +14,7 @@ Este repositório contém o backend de um aplicativo projetado para ajudar na or Para iniciar com dados de exemplo, utilize o dump do banco disponível em `prisma/migration/dev_dump.sql`. Este arquivo pode ser executado após as migrations estarem aplicadas. -Se estiver usando Docker, os comandos para carregar o dump são: - -```bash -# Copiar o dump para a pasta temporária do Docker -docker exec -it cp backup.sql POSTGRES_CONTAINER_ID:/tmp/backup.sql -# Importar o dump para o banco -docker exec -i POSTGRES_CONTAINER_ID psql -U root -d DATABASE_NAME -f /tmp/backup.sql -``` +Se estiver usando Docker, você pode usar o comando `make dev-db-load-dump` para carregar automaticamente. ## 🐳 Configuração com Docker @@ -37,15 +30,11 @@ Para desenvolvedores de frontend que não precisam executar localmente a API e o docker-compose -f docker-compose.dev.yml up ``` -Adicione a porta do serviço de banco no `docker-compose.dev.yml` para acessos externos: - -```yaml -ports: - - '5432:5432' - - '4000:4000' -``` - ## 🚀 Configuração Inicial Local +Se você estiver recebendo algum erro relacionado a PORT da DATABASE_URL, tem uma linha comentada no .env que pode ser +descomentada para resolver o problema. + +## Configuração inicial para rodar localmente 1. Clone o repositório: ```bash @@ -53,14 +42,11 @@ ports: ``` 2. Instale as dependências: ```bash - npm install - npx prisma generate - npx prisma migrate dev - npm run start:dev + make install ``` 3. Inicie o servidor: ```bash - npm start + make start ``` A API estará disponível em `http://localhost:4000`. @@ -99,3 +85,4 @@ ports: Contribuições são muito bem-vindas! Se deseja ajudar, faça um fork do repositório, crie uma branch com suas modificações, e envie um pull request. Sua ajuda é crucial para apoiar a comunidade afetada pelas enchentes no Rio Grande do Sul! + diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index ba40eebc..f46200de 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -34,3 +34,4 @@ services: environment: - POSTGRES_PASSWORD=${DB_PASSWORD} - POSTGRES_USER=${DB_USER} + From 33c16aebca850670f2feacd342e108cbcbdb42b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9lio=20Dantas?= Date: Wed, 15 May 2024 17:57:05 -0300 Subject: [PATCH 04/29] =?UTF-8?q?doc:=20adicionando=20make=20para=20inclui?= =?UTF-8?q?=20comandos=20para=20facilitar=20o=20setup=20da=20aplica=C3=A7?= =?UTF-8?q?=C3=A3o.=20criados=20alguns=20comandos=20e=20incluido=20do=20re?= =?UTF-8?q?adme=20da=20aplica=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 2 ++ README.md | 37 +++++++++++++++++++++++++++++++++++++ makefile | 42 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 makefile diff --git a/Dockerfile b/Dockerfile index a98af1c5..4306b753 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,7 @@ FROM node:18.18-alpine as node +RUN apk add --no-cache make + WORKDIR /usr/app COPY package.json package-lock.json ./ diff --git a/README.md b/README.md index 99e4c850..acdffd4c 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,17 @@ autenticação de usuários, gerenciamento de abrigos e suprimentos, e muito mai Se você quiser discutir ideias, problemas ou contribuições, sinta-se à vontade para se juntar ao nosso servidor do Discord [aqui](https://discord.gg/vjZS6BQXvM). +## Workspace Dependencies +- [Node 18.18](https://nodejs.org/) +- [Docker](https://www.docker.com/get-started/) +- Make + - [Windows](https://gnuwin32.sourceforge.net/packages/make.htm) + - Linux + ```bash + sudo apt update + sudo apt install make + ``` + ## 🛠 Tecnologias Utilizadas - **🟢 Node.js**: Ambiente de execução para JavaScript. @@ -33,6 +44,10 @@ docker exec -i POSTGRES_CONTAINER_ID psql -U root -d DATABASE_NAME -f /tmp/backu Para desenvolvedores de frontend que não precisam executar localmente a API e o banco, siga estes passos: + ```bash + cp .env.local .env + ``` + 1. Clone o arquivo `.env` de exemplo: ```bash cp .env.local .env @@ -50,6 +65,11 @@ ports: - '5432:5432' - '4000:4000' ``` +Usando make: + + ```bash + make setupDocker +``` ## 🚀 Configuração Inicial Local @@ -58,7 +78,12 @@ ports: git clone https://github.com/seuusuario/projeto-enchentes-backend.git ``` 2. Instale as dependências: + ```bash + make setup + + # ou sem make + npm install npx prisma generate npx prisma migrate dev @@ -66,6 +91,10 @@ ports: ``` 3. Inicie o servidor: ```bash + make up + + # ou sem make + npm start ``` A API estará disponível em `http://localhost:4000`. @@ -100,6 +129,14 @@ ports: - **📝 POST /supply-categories** - Registra uma nova categoria de suprimentos. - **🔧 PUT /supply-categories/:categoryId** - Atualiza uma categoria. +## Make commands +### Using Docker +- Inicia Projeto sem docker: `make setup`. +- Inicia Projeto com docker: `make setupDocker`. +- Start Projeto sem docker: `make up` +- Start Projeto com docker: `make upDockerDev` +- Acessar container bash: `make bash` + ## 🤝 Contribuição Contribuições são muito bem-vindas! Se deseja ajudar, faça um fork do repositório, crie uma branch com suas diff --git a/makefile b/makefile new file mode 100644 index 00000000..cf1d4ae0 --- /dev/null +++ b/makefile @@ -0,0 +1,42 @@ +#!/bin/bash + +CONTAINER_BACKEND = sos-rs-api + +fileMode: + @echo "Configuring git fileMode to false" + git config core.fileMode false + +create.env.file: + if [ ! -f .env ]; then \ + cp .env.local .env; \ + fi + +upDockerDev: + docker-compose -f docker-compose.dev.yml up + +setupDocker: + make fileMode + make create.env.file + make upDockerDev + +settingsWithoutDocker: + make fileMode + make create.env.file + npm install + npx prisma generate + npx prisma migrate dev + +upDev: + npm run start:dev + +setup: + make settingsWithoutDocker + make upDev + +bash: + docker exec -it ${CONTAINER_BACKEND} sh + +.PHONY: up +up: + npm start + From f6eed883f8ac8cd5af48c804ba6b22ec9413e01e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9lio=20Dantas?= Date: Wed, 15 May 2024 18:24:14 -0300 Subject: [PATCH 05/29] build: add-makefile - instalar makefile para usos dentro do container em dev --- docker-compose.dev.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index ba40eebc..d8222d76 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -23,6 +23,7 @@ services: - PORT=${PORT} command: > sh -c "npm install && + apk add --no-cache make && npx prisma generate && npx prisma migrate dev && npm run start:dev -- --preserveWatchOutput" From fc75fd2e284e2509e51b4287111c922a820b7370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9lio=20Dantas?= Date: Wed, 15 May 2024 19:02:32 -0300 Subject: [PATCH 06/29] =?UTF-8?q?doc:=20removendo=20descri=C3=A7=C3=A3o=20?= =?UTF-8?q?duplicada?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index acdffd4c..4ee77072 100644 --- a/README.md +++ b/README.md @@ -44,10 +44,6 @@ docker exec -i POSTGRES_CONTAINER_ID psql -U root -d DATABASE_NAME -f /tmp/backu Para desenvolvedores de frontend que não precisam executar localmente a API e o banco, siga estes passos: - ```bash - cp .env.local .env - ``` - 1. Clone o arquivo `.env` de exemplo: ```bash cp .env.local .env From 5e72d2f30e2f07c9b93f934ed3aca65c4f336dff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rog=C3=A9rio=20Piatek?= <74259272+RogerioPiatek@users.noreply.github.com> Date: Sun, 12 May 2024 02:45:36 -0300 Subject: [PATCH 07/29] docs: improve readme file with discord link --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 963a696c..a14a8f95 100644 --- a/README.md +++ b/README.md @@ -84,5 +84,7 @@ descomentada para resolver o problema. Contribuições são muito bem-vindas! Se deseja ajudar, faça um fork do repositório, crie uma branch com suas modificações, e envie um pull request. +Se você quiser discutir ideias, problemas ou contribuições, sinta-se à vontade para se juntar ao nosso servidor do Discord [aqui](https://discord.gg/ZtkMVmSF). + Sua ajuda é crucial para apoiar a comunidade afetada pelas enchentes no Rio Grande do Sul! From e5148ff96b8839866d1f5aa2fb9fa7f69b1fc6d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rog=C3=A9rio=20Piatek?= <74259272+RogerioPiatek@users.noreply.github.com> Date: Sun, 12 May 2024 21:14:57 -0300 Subject: [PATCH 08/29] docs: updated to the link 'discord.gg/sosrs' --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a14a8f95..ddfd2f26 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ descomentada para resolver o problema. Contribuições são muito bem-vindas! Se deseja ajudar, faça um fork do repositório, crie uma branch com suas modificações, e envie um pull request. -Se você quiser discutir ideias, problemas ou contribuições, sinta-se à vontade para se juntar ao nosso servidor do Discord [aqui](https://discord.gg/ZtkMVmSF). +Se você quiser discutir ideias, problemas ou contribuições, sinta-se à vontade para se juntar ao nosso servidor do Discord [aqui](https://discord.gg/sosrs). Sua ajuda é crucial para apoiar a comunidade afetada pelas enchentes no Rio Grande do Sul! From 9380c9ca6147f1986807a73e5e105ce2346e8d52 Mon Sep 17 00:00:00 2001 From: Lipe Date: Mon, 13 May 2024 00:23:25 -0300 Subject: [PATCH 09/29] docs: changed discord link position --- README.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ddfd2f26..38ee69c7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,11 @@ # 🌊 Backend para App de Ajuda em Enchentes 🌊 -Este repositório contém o backend de um aplicativo projetado para ajudar na organização e distribuição de suprimentos, bem como na coordenação de voluntários durante enchentes no Rio Grande do Sul. Ele fornece APIs essenciais para a autenticação de usuários, gerenciamento de abrigos e suprimentos, e muito mais. +Este repositório contém o backend de um aplicativo projetado para ajudar na organização e distribuição de suprimentos, +bem como na coordenação de voluntários durante enchentes no Rio Grande do Sul. Ele fornece APIs essenciais para a +autenticação de usuários, gerenciamento de abrigos e suprimentos, e muito mais. + +Se você quiser discutir ideias, problemas ou contribuições, sinta-se à vontade para se juntar ao nosso servidor do +Discord [aqui](https://discord.gg/sosrs). ## 🛠 Tecnologias Utilizadas @@ -12,7 +17,8 @@ Este repositório contém o backend de um aplicativo projetado para ajudar na or ## 🗂 Dump do Banco de Dados -Para iniciar com dados de exemplo, utilize o dump do banco disponível em `prisma/migration/dev_dump.sql`. Este arquivo pode ser executado após as migrations estarem aplicadas. +Para iniciar com dados de exemplo, utilize o dump do banco disponível em `prisma/migration/dev_dump.sql`. Este arquivo +pode ser executado após as migrations estarem aplicadas. Se estiver usando Docker, você pode usar o comando `make dev-db-load-dump` para carregar automaticamente. @@ -82,9 +88,8 @@ descomentada para resolver o problema. ## 🤝 Contribuição -Contribuições são muito bem-vindas! Se deseja ajudar, faça um fork do repositório, crie uma branch com suas modificações, e envie um pull request. - -Se você quiser discutir ideias, problemas ou contribuições, sinta-se à vontade para se juntar ao nosso servidor do Discord [aqui](https://discord.gg/sosrs). +Contribuições são muito bem-vindas! Se deseja ajudar, faça um fork do repositório, crie uma branch com suas +modificações, e envie um pull request. Sua ajuda é crucial para apoiar a comunidade afetada pelas enchentes no Rio Grande do Sul! From 1210f82f5ee361d6b3b1ad540d4146da502b9936 Mon Sep 17 00:00:00 2001 From: LeoFC97 Date: Sat, 11 May 2024 10:44:27 -0300 Subject: [PATCH 10/29] docs: add templeate for PR --- .github/workflows/pull_request_template.md | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/workflows/pull_request_template.md diff --git a/.github/workflows/pull_request_template.md b/.github/workflows/pull_request_template.md new file mode 100644 index 00000000..d9d9ffd2 --- /dev/null +++ b/.github/workflows/pull_request_template.md @@ -0,0 +1,24 @@ +### 🔨 Tenho uma nova PR para vocês revisarem + +- 🤔 O que foi feito? +> Digite aqui... + + +### 📗 Checklist do desenvolvedor + +- [ ] Foi testado localmente? +- [ ] Foi adicionado documentação necessária (swagger, testes e etc)? + +### 👀 Checklist do revisor + +#### Revisor 1️⃣ + +- [ ] Você entendeu o propósito desse PR? +- [ ] Você entendeu o fluxo de negócio? +- [ ] Você entendeu o que e como foi desenvolvido tecnicamente a solução? +- [ ] Você analisou se os testes estão cobrindo a maioria dos casos? + + +### 🔗 Referênia + +[Issue XX](https://github.com/SOS-RS/backend/issues/XX) From f1416e5a1681efa5cf6bafb684bfd4d83b09a4cf Mon Sep 17 00:00:00 2001 From: kelvinsb Date: Sat, 11 May 2024 20:44:49 -0300 Subject: [PATCH 11/29] feat: only show contact on shelter public routes on authorized roles --- src/decorators/UserDecorator/index.ts | 3 ++ .../UserDecorator/user.decorator.ts | 8 ++++ src/guards/apply-user.guard.ts | 10 +++++ src/guards/utils.ts | 40 ++++++++++++------- src/shelter/shelter.controller.ts | 7 +++- src/shelter/shelter.service.ts | 13 ++++-- 6 files changed, 62 insertions(+), 19 deletions(-) create mode 100644 src/decorators/UserDecorator/index.ts create mode 100644 src/decorators/UserDecorator/user.decorator.ts create mode 100644 src/guards/apply-user.guard.ts diff --git a/src/decorators/UserDecorator/index.ts b/src/decorators/UserDecorator/index.ts new file mode 100644 index 00000000..b85696de --- /dev/null +++ b/src/decorators/UserDecorator/index.ts @@ -0,0 +1,3 @@ +import { UserDecorator } from './user.decorator'; + +export { UserDecorator }; diff --git a/src/decorators/UserDecorator/user.decorator.ts b/src/decorators/UserDecorator/user.decorator.ts new file mode 100644 index 00000000..67e5edcd --- /dev/null +++ b/src/decorators/UserDecorator/user.decorator.ts @@ -0,0 +1,8 @@ +import { createParamDecorator, ExecutionContext } from '@nestjs/common'; + +export const UserDecorator = createParamDecorator( + (data: unknown, ctx: ExecutionContext) => { + const request = ctx.switchToHttp().getRequest(); + return request?.user; + }, +); diff --git a/src/guards/apply-user.guard.ts b/src/guards/apply-user.guard.ts new file mode 100644 index 00000000..07e7a6de --- /dev/null +++ b/src/guards/apply-user.guard.ts @@ -0,0 +1,10 @@ +import { Injectable } from '@nestjs/common'; +import { AuthGuard } from '@nestjs/passport'; + +@Injectable() +export class ApplyUser extends AuthGuard('jwt') { + handleRequest(err: any, user: any) { + if (user) return user; + return null; + } +} diff --git a/src/guards/utils.ts b/src/guards/utils.ts index 1e385a4c..10a8c680 100644 --- a/src/guards/utils.ts +++ b/src/guards/utils.ts @@ -11,22 +11,34 @@ async function canActivate(context: ExecutionContext, allowed: AccessLevel[]) { if (request.user) { const { userId, sessionId } = request.user; - const session = await service.session.findUnique({ - where: { id: sessionId, active: true, user: { id: userId } }, - include: { - user: true, - }, - }); - - if ( - session && - allowed.some((permission) => permission === session.user.accessLevel) - ) { - return true; - } + return isRightSessionRole(allowed, sessionId, userId); } return false; } -export { canActivate }; +async function isRightSessionRole( + allowed: AccessLevel[], + sessionId?: string, + userId?: string, +) { + if (!sessionId) return false; + if (!userId) return false; + + const session = await service.session.findUnique({ + where: { id: sessionId, active: true, user: { id: userId } }, + include: { + user: true, + }, + }); + + if ( + session && + allowed.some((permission) => permission === session.user.accessLevel) + ) { + return true; + } + return false; +} + +export { canActivate, isRightSessionRole }; diff --git a/src/shelter/shelter.controller.ts b/src/shelter/shelter.controller.ts index 097285e4..f0963f89 100644 --- a/src/shelter/shelter.controller.ts +++ b/src/shelter/shelter.controller.ts @@ -15,6 +15,8 @@ import { ApiTags } from '@nestjs/swagger'; import { ShelterService } from './shelter.service'; import { ServerResponse } from '../utils'; import { StaffGuard } from '@/guards/staff.guard'; +import { ApplyUser } from '@/guards/apply-user.guard'; +import { UserDecorator } from '@/decorators/UserDecorator'; @ApiTags('Abrigos') @Controller('shelters') @@ -35,9 +37,10 @@ export class ShelterController { } @Get(':id') - async show(@Param('id') id: string) { + @UseGuards(ApplyUser) + async show(@UserDecorator() user: any, @Param('id') id: string) { try { - const data = await this.shelterService.show(id); + const data = await this.shelterService.show(id, user); return new ServerResponse(200, 'Successfully get shelter', data); } catch (err: any) { this.logger.error(`Failed to get shelter: ${err}`); diff --git a/src/shelter/shelter.service.ts b/src/shelter/shelter.service.ts index a24aa7ab..7da86b61 100644 --- a/src/shelter/shelter.service.ts +++ b/src/shelter/shelter.service.ts @@ -1,7 +1,7 @@ import { z } from 'zod'; import { Injectable } from '@nestjs/common'; import * as qs from 'qs'; -import { Prisma } from '@prisma/client'; +import { Prisma, AccessLevel } from '@prisma/client'; import { DefaultArgs } from '@prisma/client/runtime/library'; import { PrismaService } from '../prisma/prisma.service'; @@ -14,6 +14,7 @@ import { SearchSchema } from '../types'; import { ShelterSearch, parseTagResponse } from './ShelterSearch'; import { SupplyPriority } from '../supply/types'; import { IFilterFormProps } from './types/search.types'; +import { isRightSessionRole } from '@/guards/utils'; @Injectable() export class ShelterService { @@ -60,7 +61,13 @@ export class ShelterService { }); } - async show(id: string) { + async show(id: string, user: any) { + const isLogged = await isRightSessionRole( + [AccessLevel.User, AccessLevel.Staff], + user?.sessionId, + user?.userId, + ); + const data = await this.prismaService.shelter.findFirst({ where: { id, @@ -72,7 +79,7 @@ export class ShelterService { pix: true, shelteredPeople: true, capacity: true, - contact: true, + contact: isLogged, petFriendly: true, prioritySum: true, latitude: true, From e2c6242c858d8b7d4925fbeb09f5d00aa5cc3839 Mon Sep 17 00:00:00 2001 From: kelvinsb Date: Sat, 11 May 2024 20:46:19 -0300 Subject: [PATCH 12/29] fix: remove unused and unauthorized contact field on list route --- src/shelter/shelter.service.ts | 1 - src/shelter/types/search.types.ts | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/shelter/shelter.service.ts b/src/shelter/shelter.service.ts index 7da86b61..0bb8f9b4 100644 --- a/src/shelter/shelter.service.ts +++ b/src/shelter/shelter.service.ts @@ -144,7 +144,6 @@ export class ShelterService { pix: true, address: true, capacity: true, - contact: true, petFriendly: true, shelteredPeople: true, prioritySum: true, diff --git a/src/shelter/types/search.types.ts b/src/shelter/types/search.types.ts index b80ca59d..680ae487 100644 --- a/src/shelter/types/search.types.ts +++ b/src/shelter/types/search.types.ts @@ -12,7 +12,9 @@ export interface IFilterFormProps { tags: ShelterTagInfo | null; } -export type SearchShelterTagResponse = Shelter & { +type AllowedShelterFields = Omit; + +export type SearchShelterTagResponse = AllowedShelterFields & { shelterSupplies: (ShelterSupply & { supply: Supply })[]; }; From e23440c1d4cb0380852ebef4a19676bf1625de96 Mon Sep 17 00:00:00 2001 From: kelvinsb Date: Sun, 12 May 2024 18:46:11 -0300 Subject: [PATCH 13/29] feat: return contact when user logged, instead of some Roles --- src/shelter/shelter.service.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/shelter/shelter.service.ts b/src/shelter/shelter.service.ts index 0bb8f9b4..968f0c07 100644 --- a/src/shelter/shelter.service.ts +++ b/src/shelter/shelter.service.ts @@ -1,7 +1,7 @@ import { z } from 'zod'; import { Injectable } from '@nestjs/common'; import * as qs from 'qs'; -import { Prisma, AccessLevel } from '@prisma/client'; +import { Prisma } from '@prisma/client'; import { DefaultArgs } from '@prisma/client/runtime/library'; import { PrismaService } from '../prisma/prisma.service'; @@ -14,7 +14,6 @@ import { SearchSchema } from '../types'; import { ShelterSearch, parseTagResponse } from './ShelterSearch'; import { SupplyPriority } from '../supply/types'; import { IFilterFormProps } from './types/search.types'; -import { isRightSessionRole } from '@/guards/utils'; @Injectable() export class ShelterService { @@ -62,11 +61,8 @@ export class ShelterService { } async show(id: string, user: any) { - const isLogged = await isRightSessionRole( - [AccessLevel.User, AccessLevel.Staff], - user?.sessionId, - user?.userId, - ); + const isLogged = + Boolean(user) && Boolean(user?.sessionId) && Boolean(user?.userId); const data = await this.prismaService.shelter.findFirst({ where: { From 1bd35da049e0e60e66b637b988bdbe47d524684e Mon Sep 17 00:00:00 2001 From: kelvinsb Date: Sun, 12 May 2024 21:09:19 -0300 Subject: [PATCH 14/29] fix: suggestions about separation --- src/decorators/UserDecorator/index.ts | 3 --- src/guards/utils.ts | 2 +- src/shelter/shelter.controller.ts | 6 ++++-- src/shelter/shelter.service.ts | 7 ++----- 4 files changed, 7 insertions(+), 11 deletions(-) delete mode 100644 src/decorators/UserDecorator/index.ts diff --git a/src/decorators/UserDecorator/index.ts b/src/decorators/UserDecorator/index.ts deleted file mode 100644 index b85696de..00000000 --- a/src/decorators/UserDecorator/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { UserDecorator } from './user.decorator'; - -export { UserDecorator }; diff --git a/src/guards/utils.ts b/src/guards/utils.ts index 10a8c680..f36066e3 100644 --- a/src/guards/utils.ts +++ b/src/guards/utils.ts @@ -41,4 +41,4 @@ async function isRightSessionRole( return false; } -export { canActivate, isRightSessionRole }; +export { canActivate }; diff --git a/src/shelter/shelter.controller.ts b/src/shelter/shelter.controller.ts index f0963f89..ab14d2ec 100644 --- a/src/shelter/shelter.controller.ts +++ b/src/shelter/shelter.controller.ts @@ -16,7 +16,7 @@ import { ShelterService } from './shelter.service'; import { ServerResponse } from '../utils'; import { StaffGuard } from '@/guards/staff.guard'; import { ApplyUser } from '@/guards/apply-user.guard'; -import { UserDecorator } from '@/decorators/UserDecorator'; +import { UserDecorator } from '@/decorators/UserDecorator/user.decorator'; @ApiTags('Abrigos') @Controller('shelters') @@ -40,7 +40,9 @@ export class ShelterController { @UseGuards(ApplyUser) async show(@UserDecorator() user: any, @Param('id') id: string) { try { - const data = await this.shelterService.show(id, user); + const isLogged = + Boolean(user) && Boolean(user?.sessionId) && Boolean(user?.userId); + const data = await this.shelterService.show(id, isLogged); return new ServerResponse(200, 'Successfully get shelter', data); } catch (err: any) { this.logger.error(`Failed to get shelter: ${err}`); diff --git a/src/shelter/shelter.service.ts b/src/shelter/shelter.service.ts index 968f0c07..a320db35 100644 --- a/src/shelter/shelter.service.ts +++ b/src/shelter/shelter.service.ts @@ -60,10 +60,7 @@ export class ShelterService { }); } - async show(id: string, user: any) { - const isLogged = - Boolean(user) && Boolean(user?.sessionId) && Boolean(user?.userId); - + async show(id: string, shouldShowContact: boolean) { const data = await this.prismaService.shelter.findFirst({ where: { id, @@ -75,7 +72,7 @@ export class ShelterService { pix: true, shelteredPeople: true, capacity: true, - contact: isLogged, + contact: shouldShowContact, petFriendly: true, prioritySum: true, latitude: true, From 6f8b860845ddb082baaa5281091e13c1641c2342 Mon Sep 17 00:00:00 2001 From: Anderson Rocha <59173445+AndersonCRocha@users.noreply.github.com> Date: Mon, 13 May 2024 20:14:20 -0300 Subject: [PATCH 15/29] =?UTF-8?q?Cria=C3=A7=C3=A3o=20do=20endpoint=20para?= =?UTF-8?q?=20busca=20de=20cidades=20dos=20abrigos=20(#82)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Pedro Perrone --- .../migrations/20240512005246_/migration.sql | 6 + prisma/schema.prisma | 5 + src/prisma/hooks/shelter/index.ts | 0 src/prisma/hooks/shelter/shelter-hooks.ts | 0 src/prisma/hooks/user/index.ts | 0 src/prisma/hooks/user/user-hooks.ts | 0 src/shelter/ShelterSearch.ts | 113 ++++++++++-------- src/shelter/shelter.controller.ts | 11 ++ src/shelter/shelter.service.ts | 45 +++++-- src/shelter/types/search.types.ts | 51 +++++--- src/shelter/types/types.ts | 5 + 11 files changed, 158 insertions(+), 78 deletions(-) create mode 100644 prisma/migrations/20240512005246_/migration.sql delete mode 100644 src/prisma/hooks/shelter/index.ts delete mode 100644 src/prisma/hooks/shelter/shelter-hooks.ts delete mode 100644 src/prisma/hooks/user/index.ts delete mode 100644 src/prisma/hooks/user/user-hooks.ts diff --git a/prisma/migrations/20240512005246_/migration.sql b/prisma/migrations/20240512005246_/migration.sql new file mode 100644 index 00000000..c57b86cf --- /dev/null +++ b/prisma/migrations/20240512005246_/migration.sql @@ -0,0 +1,6 @@ +-- AlterTable +ALTER TABLE "shelters" ADD COLUMN "city" TEXT, +ADD COLUMN "neighbourhood" TEXT, +ADD COLUMN "street" TEXT, +ADD COLUMN "street_number" TEXT, +ADD COLUMN "zip_code" TEXT; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 792b1f65..b853d2b4 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -89,6 +89,11 @@ model Shelter { name String @unique pix String? @unique address String + street String? + neighbourhood String? + city String? + streetNumber String? @map("street_number") + zipCode String? @map("zip_code") petFriendly Boolean? @map("pet_friendly") shelteredPeople Int? @map("sheltered_people") capacity Int? diff --git a/src/prisma/hooks/shelter/index.ts b/src/prisma/hooks/shelter/index.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/src/prisma/hooks/shelter/shelter-hooks.ts b/src/prisma/hooks/shelter/shelter-hooks.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/src/prisma/hooks/user/index.ts b/src/prisma/hooks/user/index.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/src/prisma/hooks/user/user-hooks.ts b/src/prisma/hooks/user/user-hooks.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/src/shelter/ShelterSearch.ts b/src/shelter/ShelterSearch.ts index 7598b8e0..205f97e8 100644 --- a/src/shelter/ShelterSearch.ts +++ b/src/shelter/ShelterSearch.ts @@ -1,10 +1,11 @@ import { Prisma } from '@prisma/client'; -import { PrismaService } from '../prisma/prisma.service'; import { SupplyPriority } from 'src/supply/types'; +import { PrismaService } from '../prisma/prisma.service'; import { - IFilterFormProps, SearchShelterTagResponse, + ShelterSearchProps, + ShelterStatus, ShelterTagInfo, ShelterTagType, } from './types/search.types'; @@ -16,57 +17,54 @@ const defaultTagsData: ShelterTagInfo = { }; class ShelterSearch { - private formProps: Partial; + private formProps: Partial; private prismaService: PrismaService; constructor( prismaService: PrismaService, - props: Partial = {}, + props: Partial = {}, ) { this.prismaService = prismaService; this.formProps = { ...props }; } priority(supplyIds: string[] = []): Prisma.ShelterWhereInput { - if (this.formProps.priority) { - return { - shelterSupplies: { - some: { - priority: +this.formProps.priority, - supplyId: - supplyIds.length > 0 - ? { - in: supplyIds, - } - : undefined, - }, + if (!this.formProps.priority) return {}; + + return { + shelterSupplies: { + some: { + priority: +this.formProps.priority, + supplyId: + supplyIds.length > 0 + ? { + in: supplyIds, + } + : undefined, }, - }; - } else return {}; + }, + }; } get shelterStatus(): Prisma.ShelterWhereInput[] { if (!this.formProps.shelterStatus) return []; - else { - return this.formProps.shelterStatus.map((status) => { - if (status === 'waiting') - return { - capacity: null, - }; - else if (status === 'available') - return { - capacity: { - gt: this.prismaService.shelter.fields.shelteredPeople, - }, - }; - else - return { - capacity: { - lte: this.prismaService.shelter.fields.shelteredPeople, - }, - }; - }); - } + + const clausesFromStatus: Record< + ShelterStatus, + Prisma.ShelterWhereInput['capacity'] | null + > = { + waiting: null, + available: { + gt: this.prismaService.shelter.fields.shelteredPeople, + }, + unavailable: { + lte: this.prismaService.shelter.fields.shelteredPeople, + }, + }; + + return this.formProps.shelterStatus.map((status) => ({ + capacity: clausesFromStatus[status], + })); } supplyCategoryIds( @@ -104,27 +102,38 @@ class ShelterSearch { get search(): Prisma.ShelterWhereInput[] { if (!this.formProps.search) return []; - else - return [ - { - address: { - contains: this.formProps.search, - mode: 'insensitive', - }, + + return [ + { + address: { + contains: this.formProps.search, + mode: 'insensitive', }, - { - name: { - contains: this.formProps.search, - mode: 'insensitive', - }, + }, + { + name: { + contains: this.formProps.search, + mode: 'insensitive', }, - ]; + }, + ]; + } + + get cities(): Prisma.ShelterWhereInput { + if (!this.formProps.cities) return {}; + + return { + city: { + in: this.formProps.cities, + }, + }; } get query(): Prisma.ShelterWhereInput { if (Object.keys(this.formProps).length === 0) return {}; const queryData = { AND: [ + this.cities, { OR: this.search }, { OR: this.shelterStatus }, this.priority(this.formProps.supplyIds), @@ -144,7 +153,7 @@ class ShelterSearch { * @returns Retorna a lista de resultados, adicionando o campo tags em cada supply para assim categoriza-los corretamente e limitar a quantidade de cada retornada respeitando os parametros em formProps */ function parseTagResponse( - tagProps: Partial> = {}, + tagProps: Partial> = {}, results: SearchShelterTagResponse[], voluntaryIds: string[], ): SearchShelterTagResponse[] { diff --git a/src/shelter/shelter.controller.ts b/src/shelter/shelter.controller.ts index ab14d2ec..24603857 100644 --- a/src/shelter/shelter.controller.ts +++ b/src/shelter/shelter.controller.ts @@ -36,6 +36,17 @@ export class ShelterController { } } + @Get('cities') + async cities() { + try { + const data = await this.shelterService.getCities(); + return new ServerResponse(200, 'Successfully get shelters cities', data); + } catch (err: any) { + this.logger.error(`Failed to get shelters cities: ${err}`); + throw new HttpException(err?.code ?? err?.name ?? `${err}`, 400); + } + } + @Get(':id') @UseGuards(ApplyUser) async show(@UserDecorator() user: any, @Param('id') id: string) { diff --git a/src/shelter/shelter.service.ts b/src/shelter/shelter.service.ts index a320db35..e3883215 100644 --- a/src/shelter/shelter.service.ts +++ b/src/shelter/shelter.service.ts @@ -1,19 +1,19 @@ -import { z } from 'zod'; import { Injectable } from '@nestjs/common'; -import * as qs from 'qs'; import { Prisma } from '@prisma/client'; import { DefaultArgs } from '@prisma/client/runtime/library'; +import * as qs from 'qs'; +import { z } from 'zod'; import { PrismaService } from '../prisma/prisma.service'; +import { SupplyPriority } from '../supply/types'; +import { SearchSchema } from '../types'; +import { ShelterSearch, parseTagResponse } from './ShelterSearch'; +import { ShelterSearchPropsSchema } from './types/search.types'; import { CreateShelterSchema, FullUpdateShelterSchema, UpdateShelterSchema, } from './types/types'; -import { SearchSchema } from '../types'; -import { ShelterSearch, parseTagResponse } from './ShelterSearch'; -import { SupplyPriority } from '../supply/types'; -import { IFilterFormProps } from './types/search.types'; @Injectable() export class ShelterService { @@ -69,6 +69,11 @@ export class ShelterService { id: true, name: true, address: true, + street: true, + neighbourhood: true, + city: true, + streetNumber: true, + zipCode: true, pix: true, shelteredPeople: true, capacity: true, @@ -115,7 +120,7 @@ export class ShelterService { perPage, search: searchQuery, } = SearchSchema.parse(query); - const queryData = qs.parse(searchQuery) as unknown as IFilterFormProps; + const queryData = ShelterSearchPropsSchema.parse(qs.parse(searchQuery)); const { query: where } = new ShelterSearch(this.prismaService, queryData); const count = await this.prismaService.shelter.count({ where }); @@ -136,6 +141,11 @@ export class ShelterService { name: true, pix: true, address: true, + street: true, + neighbourhood: true, + city: true, + streetNumber: true, + zipCode: true, capacity: true, petFriendly: true, shelteredPeople: true, @@ -171,7 +181,26 @@ export class ShelterService { }; } - loadVoluntaryIds() { + async getCities() { + const cities = await this.prismaService.shelter.groupBy({ + by: ['city'], + _count: { + id: true, + }, + orderBy: { + _count: { + id: 'desc', + }, + }, + }); + + return cities.map(({ city, _count: { id: sheltersCount } }) => ({ + city: city || 'Cidade não informada', + sheltersCount, + })); + } + + private loadVoluntaryIds() { this.prismaService.supplyCategory .findMany({ where: { diff --git a/src/shelter/types/search.types.ts b/src/shelter/types/search.types.ts index 680ae487..88ed410e 100644 --- a/src/shelter/types/search.types.ts +++ b/src/shelter/types/search.types.ts @@ -1,28 +1,43 @@ import { Shelter, ShelterSupply, Supply } from '@prisma/client'; +import { z } from 'zod'; import { SupplyPriority } from '../../supply/types'; -export type ShelterAvailabilityStatus = 'available' | 'unavailable' | 'waiting'; +const ShelterStatusSchema = z.enum(['available', 'unavailable', 'waiting']); -export interface IFilterFormProps { - search: string; - priority: SupplyPriority | null; - supplyCategoryIds: string[]; - supplyIds: string[]; - shelterStatus: ShelterAvailabilityStatus[]; - tags: ShelterTagInfo | null; -} +export type ShelterStatus = z.infer; + +const ShelterTagTypeSchema = z.enum([ + 'NeedVolunteers', + 'NeedDonations', + 'RemainingSupplies', +]); + +const ShelterTagInfoSchema = z.record( + ShelterTagTypeSchema, + z.number().optional(), +); + +export type ShelterTagType = z.infer; + +export type ShelterTagInfo = z.infer; + +export const ShelterSearchPropsSchema = z.object({ + search: z.string().optional(), + priority: z.preprocess( + (value) => Number(value) || undefined, + z.nativeEnum(SupplyPriority).optional(), + ), + supplyCategoryIds: z.array(z.string()).optional(), + supplyIds: z.array(z.string()).optional(), + shelterStatus: z.array(ShelterStatusSchema).optional(), + tags: ShelterTagInfoSchema.nullable().optional(), + cities: z.array(z.string()).optional(), +}); + +export type ShelterSearchProps = z.infer; type AllowedShelterFields = Omit; export type SearchShelterTagResponse = AllowedShelterFields & { shelterSupplies: (ShelterSupply & { supply: Supply })[]; }; - -export type ShelterTagType = - | 'NeedVolunteers' - | 'NeedDonations' - | 'RemainingSupplies'; - -export type ShelterTagInfo = { - [key in ShelterTagType]?: number; -}; diff --git a/src/shelter/types/types.ts b/src/shelter/types/types.ts index b3911c96..0dc21bac 100644 --- a/src/shelter/types/types.ts +++ b/src/shelter/types/types.ts @@ -12,6 +12,11 @@ const ShelterSchema = z.object({ name: z.string().transform(capitalize), pix: z.string().nullable().optional(), address: z.string().transform(capitalize), + city: z.string().transform(capitalize).nullable().optional(), + neighbourhood: z.string().transform(capitalize).nullable().optional(), + street: z.string().transform(capitalize).nullable().optional(), + streetNumber: z.string().nullable().optional(), + zipCode: z.string().nullable().optional(), petFriendly: z.boolean().nullable().optional(), shelteredPeople: z.number().min(0).nullable().optional(), latitude: z.number().nullable().optional(), From 391607ad9162305bc7be61d5dec32f91e11d4ade Mon Sep 17 00:00:00 2001 From: Anderson Rocha <59173445+AndersonCRocha@users.noreply.github.com> Date: Mon, 13 May 2024 21:28:26 -0300 Subject: [PATCH 16/29] feat: add shelter filter by geolocation radius (#93) --- src/shelter/ShelterSearch.ts | 21 ++++++++++++++++ src/shelter/types/search.types.ts | 9 +++++++ src/utils/utils.ts | 42 ++++++++++++++++++++++++++++--- 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/src/shelter/ShelterSearch.ts b/src/shelter/ShelterSearch.ts index 205f97e8..5215d37c 100644 --- a/src/shelter/ShelterSearch.ts +++ b/src/shelter/ShelterSearch.ts @@ -1,5 +1,6 @@ import { Prisma } from '@prisma/client'; +import { calculateGeolocationBounds } from '@/utils/utils'; import { SupplyPriority } from 'src/supply/types'; import { PrismaService } from '../prisma/prisma.service'; import { @@ -129,11 +130,31 @@ class ShelterSearch { }; } + get geolocation(): Prisma.ShelterWhereInput { + if (!this.formProps.geolocation) return {}; + + const { minLat, maxLat, minLong, maxLong } = calculateGeolocationBounds( + this.formProps.geolocation, + ); + + return { + latitude: { + gte: minLat, + lte: maxLat, + }, + longitude: { + gte: minLong, + lte: maxLong, + }, + }; + } + get query(): Prisma.ShelterWhereInput { if (Object.keys(this.formProps).length === 0) return {}; const queryData = { AND: [ this.cities, + this.geolocation, { OR: this.search }, { OR: this.shelterStatus }, this.priority(this.formProps.supplyIds), diff --git a/src/shelter/types/search.types.ts b/src/shelter/types/search.types.ts index 88ed410e..b87e653a 100644 --- a/src/shelter/types/search.types.ts +++ b/src/shelter/types/search.types.ts @@ -21,6 +21,14 @@ export type ShelterTagType = z.infer; export type ShelterTagInfo = z.infer; +export const GeolocationFilterSchema = z.object({ + latitude: z.coerce.number(), + longitude: z.coerce.number(), + radiusInMeters: z.coerce.number(), +}); + +export type GeolocationFilter = z.infer; + export const ShelterSearchPropsSchema = z.object({ search: z.string().optional(), priority: z.preprocess( @@ -32,6 +40,7 @@ export const ShelterSearchPropsSchema = z.object({ shelterStatus: z.array(ShelterStatusSchema).optional(), tags: ShelterTagInfoSchema.nullable().optional(), cities: z.array(z.string()).optional(), + geolocation: GeolocationFilterSchema.optional(), }); export type ShelterSearchProps = z.infer; diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 772b3e12..dfcbc70f 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -1,4 +1,5 @@ import { Logger } from '@nestjs/common'; +import { GeolocationFilter } from 'src/shelter/types/search.types'; class ServerResponse { readonly message: string; @@ -75,10 +76,45 @@ function deepMerge(target: Record, source: Record) { } } +interface Coordinates { + maxLat: number; + minLat: number; + maxLong: number; + minLong: number; +} + +function calculateGeolocationBounds({ + latitude, + longitude, + radiusInMeters, +}: GeolocationFilter): Coordinates { + const earthRadius = 6371000; + + const latRad = (latitude * Math.PI) / 180; + + const radiusRad = radiusInMeters / earthRadius; + + const maxLat = latitude + radiusRad * (180 / Math.PI); + const minLat = latitude - radiusRad * (180 / Math.PI); + + const deltaLong = Math.asin(Math.sin(radiusRad) / Math.cos(latRad)); + + const maxLong = longitude + deltaLong * (180 / Math.PI); + const minLong = longitude - deltaLong * (180 / Math.PI); + + return { + maxLat, + minLat, + maxLong, + minLong, + }; +} + export { ServerResponse, - removeNotNumbers, - getSessionData, - deepMerge, + calculateGeolocationBounds, capitalize, + deepMerge, + getSessionData, + removeNotNumbers, }; From e8e3607239b05f365d3b69c65796290dc23994dc Mon Sep 17 00:00:00 2001 From: Filipe Pacheco de Fraga Date: Mon, 13 May 2024 22:08:23 -0300 Subject: [PATCH 17/29] Fixing discord link on Readme (#95) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 38ee69c7..b7bc9e44 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ bem como na coordenação de voluntários durante enchentes no Rio Grande do Sul autenticação de usuários, gerenciamento de abrigos e suprimentos, e muito mais. Se você quiser discutir ideias, problemas ou contribuições, sinta-se à vontade para se juntar ao nosso servidor do -Discord [aqui](https://discord.gg/sosrs). +Discord [aqui](https://discord.gg/vjZS6BQXvM). ## 🛠 Tecnologias Utilizadas From a81c9b60297f287bb680c4f48f6207e8e6dfae8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Geraldo=20D=2E=20F?= Date: Tue, 14 May 2024 01:16:15 -0300 Subject: [PATCH 18/29] =?UTF-8?q?feat:=20added=20default=20updated=20at=20?= =?UTF-8?q?in=20new=20shelter=20to=20avoid=20null=20field=20in=20=E2=80=A6?= =?UTF-8?q?=20(#100)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/shelter/shelter.service.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/shelter/shelter.service.ts b/src/shelter/shelter.service.ts index e3883215..74d03860 100644 --- a/src/shelter/shelter.service.ts +++ b/src/shelter/shelter.service.ts @@ -14,6 +14,7 @@ import { FullUpdateShelterSchema, UpdateShelterSchema, } from './types/types'; +import { subDays } from 'date-fns'; @Injectable() export class ShelterService { @@ -30,6 +31,7 @@ export class ShelterService { data: { ...payload, createdAt: new Date().toISOString(), + updatedAt: subDays(new Date(), 1).toISOString(), }, }); } From ce67813026d80bad9d114524c7a71aeb6b418260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Fagundes?= Date: Tue, 14 May 2024 11:35:47 -0300 Subject: [PATCH 19/29] hotfix: login issue --- src/sessions/sessions.service.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sessions/sessions.service.ts b/src/sessions/sessions.service.ts index 235d7f0d..200104b6 100644 --- a/src/sessions/sessions.service.ts +++ b/src/sessions/sessions.service.ts @@ -23,6 +23,9 @@ export class SessionsService { await this.prismaService.session.updateMany({ where: { + user: { + login, + }, active: true, }, data: { From 97327908e72fb036a3a42e5c563a2cdcf7704986 Mon Sep 17 00:00:00 2001 From: Giovanni Bassi <334958+giggio@users.noreply.github.com> Date: Tue, 14 May 2024 19:43:22 -0300 Subject: [PATCH 20/29] Fix tests (#78) --- .eslintrc.js | 15 ++++++++--- .github/workflows/ci.yml | 13 ++++++++-- jest.config.ts | 20 ++++++++++++++ package-lock.json | 26 +++++++++++++++++++ package.json | 20 ++------------ src/sessions/sessions.controller.spec.ts | 12 ++++++++- src/sessions/sessions.service.spec.ts | 12 +++++++-- .../shelter-managers.controller.spec.ts | 11 +++++++- .../shelter-managers.service.spec.ts | 9 ++++++- .../shelter-supply.controller.spec.ts | 11 +++++++- .../shelter-supply.service.spec.ts | 9 ++++++- src/shelter/shelter.controller.spec.ts | 13 +++++++++- src/shelter/shelter.service.spec.ts | 13 +++++++++- src/shelter/shelter.service.ts | 8 +++--- .../supply-categories.controller.spec.ts | 11 +++++++- .../supply-categories.service.spec.ts | 9 ++++++- src/supply/supply.controller.spec.ts | 11 +++++++- src/supply/supply.service.spec.ts | 9 ++++++- src/users/users.controller.spec.ts | 11 +++++++- src/users/users.service.spec.ts | 9 ++++++- test/app.e2e-spec.ts | 7 ++--- test/jest-e2e.json | 9 ------- test/jest.e2e.config.ts | 15 +++++++++++ 23 files changed, 227 insertions(+), 56 deletions(-) create mode 100644 jest.config.ts delete mode 100644 test/jest-e2e.json create mode 100644 test/jest.e2e.config.ts diff --git a/.eslintrc.js b/.eslintrc.js index d8bc3457..437379bd 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -5,10 +5,11 @@ module.exports = { tsconfigRootDir: __dirname, sourceType: 'module', }, - plugins: ['@typescript-eslint/eslint-plugin'], + plugins: ['@typescript-eslint/eslint-plugin', 'jest'], extends: [ 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended', + 'plugin:jest/recommended' ], root: true, env: { @@ -21,10 +22,16 @@ module.exports = { '@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off', '@typescript-eslint/no-explicit-any': 'off', - "prettier/prettier": [ - "error", + 'jest/expect-expect': [ + 'warn', { - "endOfLine": "auto" + 'assertFunctionNames': ['expect', 'request.**.expect'], + } + ], + 'prettier/prettier': [ + 'error', + { + 'endOfLine': 'auto' } ] }, diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f03015e0..b3714aaa 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,9 +1,15 @@ name: CI on: + workflow_dispatch: + push: + branches: + - main + tags: + - "*" pull_request: branches: - - master + - main - develop jobs: @@ -29,4 +35,7 @@ jobs: run: npm run lint:ci # Build App - name: Build App - run: npm run build \ No newline at end of file + run: npm run build + + - name: Test + run: npm test \ No newline at end of file diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 00000000..6bc3f4c4 --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,20 @@ +import type { Config } from 'jest'; + +const config: Config = { + moduleFileExtensions: ['js', 'json', 'ts'], + rootDir: 'src', + testRegex: '.*\\.spec\\.ts$', + transform: { + '^.+\\.(t|j)s$': 'ts-jest', + }, + collectCoverageFrom: ['**/*.(t|j)s'], + coverageDirectory: '../coverage', + moduleNameMapper: { + '^src/(.*)$': '/$1', + '^@/(.*)$': '/$1', + '^test/(.*)$': '/../$1', + }, + testEnvironment: 'node', +}; + +export default config; diff --git a/package-lock.json b/package-lock.json index 6c3ae692..455fac11 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,6 +38,7 @@ "@typescript-eslint/parser": "^6.0.0", "eslint": "^8.42.0", "eslint-config-prettier": "^9.0.0", + "eslint-plugin-jest": "^28.5.0", "eslint-plugin-prettier": "^5.0.0", "jest": "^29.5.0", "prettier": "^3.0.0", @@ -4517,6 +4518,31 @@ "eslint": ">=7.0.0" } }, + "node_modules/eslint-plugin-jest": { + "version": "28.5.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.5.0.tgz", + "integrity": "sha512-6np6DGdmNq/eBbA7HOUNV8fkfL86PYwBfwyb8n23FXgJNTR8+ot3smRHjza9LGsBBZRypK3qyF79vMjohIL8eQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "^6.0.0 || ^7.0.0" + }, + "engines": { + "node": "^16.10.0 || ^18.12.0 || >=20.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^6.0.0 || ^7.0.0", + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0", + "jest": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, "node_modules/eslint-plugin-prettier": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", diff --git a/package.json b/package.json index 3212f2fd..b20634cd 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "test:watch": "jest --watch", "test:cov": "jest --coverage", "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", - "test:e2e": "jest --config ./test/jest-e2e.json", + "test:e2e": "jest --config ./test/jest.e2e.config.ts", "migrations:run": "npx prisma migrate deploy", "migrations:dev": "npx prisma migrate dev", "docker:compose": "docker-compose -f docker-compose.dev.yml up" @@ -53,6 +53,7 @@ "@typescript-eslint/parser": "^6.0.0", "eslint": "^8.42.0", "eslint-config-prettier": "^9.0.0", + "eslint-plugin-jest": "^28.5.0", "eslint-plugin-prettier": "^5.0.0", "jest": "^29.5.0", "prettier": "^3.0.0", @@ -64,22 +65,5 @@ "ts-node": "^10.9.1", "tsconfig-paths": "^4.2.0", "typescript": "^5.1.3" - }, - "jest": { - "moduleFileExtensions": [ - "js", - "json", - "ts" - ], - "rootDir": "src", - "testRegex": ".*\\.spec\\.ts$", - "transform": { - "^.+\\.(t|j)s$": "ts-jest" - }, - "collectCoverageFrom": [ - "**/*.(t|j)s" - ], - "coverageDirectory": "../coverage", - "testEnvironment": "node" } } diff --git a/src/sessions/sessions.controller.spec.ts b/src/sessions/sessions.controller.spec.ts index 118ad549..a2d145e2 100644 --- a/src/sessions/sessions.controller.spec.ts +++ b/src/sessions/sessions.controller.spec.ts @@ -1,5 +1,8 @@ import { Test, TestingModule } from '@nestjs/testing'; import { SessionsController } from './sessions.controller'; +import { SessionsService } from './sessions.service'; +import { PrismaService } from 'src/prisma/prisma.service'; +import { JwtService } from '@nestjs/jwt'; describe('SessionsController', () => { let controller: SessionsController; @@ -7,7 +10,14 @@ describe('SessionsController', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [SessionsController], - }).compile(); + providers: [SessionsService, JwtService], + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); controller = module.get(SessionsController); }); diff --git a/src/sessions/sessions.service.spec.ts b/src/sessions/sessions.service.spec.ts index 923df18b..4115d43b 100644 --- a/src/sessions/sessions.service.spec.ts +++ b/src/sessions/sessions.service.spec.ts @@ -1,13 +1,21 @@ import { Test, TestingModule } from '@nestjs/testing'; import { SessionsService } from './sessions.service'; +import { JwtService } from '@nestjs/jwt'; +import { PrismaService } from 'src/prisma/prisma.service'; describe('SessionsService', () => { let service: SessionsService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - providers: [SessionsService], - }).compile(); + providers: [SessionsService, JwtService], + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); service = module.get(SessionsService); }); diff --git a/src/shelter-managers/shelter-managers.controller.spec.ts b/src/shelter-managers/shelter-managers.controller.spec.ts index 5bc76a94..01b41779 100644 --- a/src/shelter-managers/shelter-managers.controller.spec.ts +++ b/src/shelter-managers/shelter-managers.controller.spec.ts @@ -1,5 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { ShelterManagersController } from './shelter-managers.controller'; +import { PrismaService } from 'src/prisma/prisma.service'; +import { ShelterManagersService } from './shelter-managers.service'; describe('ShelterManagersController', () => { let controller: ShelterManagersController; @@ -7,7 +9,14 @@ describe('ShelterManagersController', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [ShelterManagersController], - }).compile(); + providers: [ShelterManagersService], + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); controller = module.get( ShelterManagersController, diff --git a/src/shelter-managers/shelter-managers.service.spec.ts b/src/shelter-managers/shelter-managers.service.spec.ts index 9d1878c6..51834fc4 100644 --- a/src/shelter-managers/shelter-managers.service.spec.ts +++ b/src/shelter-managers/shelter-managers.service.spec.ts @@ -1,5 +1,6 @@ import { Test, TestingModule } from '@nestjs/testing'; import { ShelterManagersService } from './shelter-managers.service'; +import { PrismaService } from 'src/prisma/prisma.service'; describe('ShelterManagersService', () => { let service: ShelterManagersService; @@ -7,7 +8,13 @@ describe('ShelterManagersService', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ShelterManagersService], - }).compile(); + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); service = module.get(ShelterManagersService); }); diff --git a/src/shelter-supply/shelter-supply.controller.spec.ts b/src/shelter-supply/shelter-supply.controller.spec.ts index 73f1a18d..04c0f885 100644 --- a/src/shelter-supply/shelter-supply.controller.spec.ts +++ b/src/shelter-supply/shelter-supply.controller.spec.ts @@ -1,5 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { ShelterSupplyController } from './shelter-supply.controller'; +import { PrismaService } from 'src/prisma/prisma.service'; +import { ShelterSupplyService } from './shelter-supply.service'; describe('ShelterSupplyController', () => { let controller: ShelterSupplyController; @@ -7,7 +9,14 @@ describe('ShelterSupplyController', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [ShelterSupplyController], - }).compile(); + providers: [ShelterSupplyService], + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); controller = module.get(ShelterSupplyController); }); diff --git a/src/shelter-supply/shelter-supply.service.spec.ts b/src/shelter-supply/shelter-supply.service.spec.ts index 2a4678ba..b3e3cae9 100644 --- a/src/shelter-supply/shelter-supply.service.spec.ts +++ b/src/shelter-supply/shelter-supply.service.spec.ts @@ -1,5 +1,6 @@ import { Test, TestingModule } from '@nestjs/testing'; import { ShelterSupplyService } from './shelter-supply.service'; +import { PrismaService } from 'src/prisma/prisma.service'; describe('ShelterSupplyService', () => { let service: ShelterSupplyService; @@ -7,7 +8,13 @@ describe('ShelterSupplyService', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ShelterSupplyService], - }).compile(); + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); service = module.get(ShelterSupplyService); }); diff --git a/src/shelter/shelter.controller.spec.ts b/src/shelter/shelter.controller.spec.ts index 6774fccb..eab66b66 100644 --- a/src/shelter/shelter.controller.spec.ts +++ b/src/shelter/shelter.controller.spec.ts @@ -1,5 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; +import { PrismaService } from 'src/prisma/prisma.service'; import { ShelterController } from './shelter.controller'; +import { ShelterService } from './shelter.service'; describe('ShelterController', () => { let controller: ShelterController; @@ -7,7 +9,16 @@ describe('ShelterController', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [ShelterController], - }).compile(); + providers: [ShelterService], + }) + .useMocker((token) => { + if (token === PrismaService) { + return { + supplyCategory: { findMany: jest.fn().mockResolvedValue(0) }, + }; + } + }) + .compile(); controller = module.get(ShelterController); }); diff --git a/src/shelter/shelter.service.spec.ts b/src/shelter/shelter.service.spec.ts index ac7cf4e0..1ce3198b 100644 --- a/src/shelter/shelter.service.spec.ts +++ b/src/shelter/shelter.service.spec.ts @@ -1,5 +1,6 @@ import { Test, TestingModule } from '@nestjs/testing'; import { ShelterService } from './shelter.service'; +import { PrismaService } from 'src/prisma/prisma.service'; describe('ShelterService', () => { let service: ShelterService; @@ -7,7 +8,17 @@ describe('ShelterService', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ShelterService], - }).compile(); + }) + .useMocker((token) => { + if (token === PrismaService) { + return { + supplyCategory: { + findMany: jest.fn().mockResolvedValue([]), + }, + }; + } + }) + .compile(); service = module.get(ShelterService); }); diff --git a/src/shelter/shelter.service.ts b/src/shelter/shelter.service.ts index 74d03860..190aedaa 100644 --- a/src/shelter/shelter.service.ts +++ b/src/shelter/shelter.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, OnModuleInit } from '@nestjs/common'; import { Prisma } from '@prisma/client'; import { DefaultArgs } from '@prisma/client/runtime/library'; import * as qs from 'qs'; @@ -17,10 +17,12 @@ import { import { subDays } from 'date-fns'; @Injectable() -export class ShelterService { +export class ShelterService implements OnModuleInit { private voluntaryIds: string[] = []; - constructor(private readonly prismaService: PrismaService) { + constructor(private readonly prismaService: PrismaService) {} + + onModuleInit() { this.loadVoluntaryIds(); } diff --git a/src/supply-categories/supply-categories.controller.spec.ts b/src/supply-categories/supply-categories.controller.spec.ts index e9e287a5..4e92c769 100644 --- a/src/supply-categories/supply-categories.controller.spec.ts +++ b/src/supply-categories/supply-categories.controller.spec.ts @@ -1,5 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { SupplyCategoriesController } from './supply-categories.controller'; +import { PrismaService } from 'src/prisma/prisma.service'; +import { SupplyCategoriesService } from './supply-categories.service'; describe('SupplyCategoriesController', () => { let controller: SupplyCategoriesController; @@ -7,7 +9,14 @@ describe('SupplyCategoriesController', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [SupplyCategoriesController], - }).compile(); + providers: [SupplyCategoriesService], + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); controller = module.get( SupplyCategoriesController, diff --git a/src/supply-categories/supply-categories.service.spec.ts b/src/supply-categories/supply-categories.service.spec.ts index 52a3e572..80f980c8 100644 --- a/src/supply-categories/supply-categories.service.spec.ts +++ b/src/supply-categories/supply-categories.service.spec.ts @@ -1,4 +1,5 @@ import { Test, TestingModule } from '@nestjs/testing'; +import { PrismaService } from 'src/prisma/prisma.service'; import { SupplyCategoriesService } from './supply-categories.service'; describe('SupplyCategoriesService', () => { @@ -7,7 +8,13 @@ describe('SupplyCategoriesService', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [SupplyCategoriesService], - }).compile(); + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); service = module.get(SupplyCategoriesService); }); diff --git a/src/supply/supply.controller.spec.ts b/src/supply/supply.controller.spec.ts index 60c2f5a4..0fb33288 100644 --- a/src/supply/supply.controller.spec.ts +++ b/src/supply/supply.controller.spec.ts @@ -1,5 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { SupplyController } from './supply.controller'; +import { SupplyService } from './supply.service'; +import { PrismaService } from 'src/prisma/prisma.service'; describe('SupplyController', () => { let controller: SupplyController; @@ -7,7 +9,14 @@ describe('SupplyController', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [SupplyController], - }).compile(); + providers: [SupplyService], + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); controller = module.get(SupplyController); }); diff --git a/src/supply/supply.service.spec.ts b/src/supply/supply.service.spec.ts index f9034a62..7868d160 100644 --- a/src/supply/supply.service.spec.ts +++ b/src/supply/supply.service.spec.ts @@ -1,5 +1,6 @@ import { Test, TestingModule } from '@nestjs/testing'; import { SupplyService } from './supply.service'; +import { PrismaService } from 'src/prisma/prisma.service'; describe('SupplyService', () => { let service: SupplyService; @@ -7,7 +8,13 @@ describe('SupplyService', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [SupplyService], - }).compile(); + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); service = module.get(SupplyService); }); diff --git a/src/users/users.controller.spec.ts b/src/users/users.controller.spec.ts index 3e27c395..e2bcecdc 100644 --- a/src/users/users.controller.spec.ts +++ b/src/users/users.controller.spec.ts @@ -1,5 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { UsersController } from './users.controller'; +import { UsersService } from './users.service'; +import { PrismaService } from 'src/prisma/prisma.service'; describe('UsersController', () => { let controller: UsersController; @@ -7,7 +9,14 @@ describe('UsersController', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ controllers: [UsersController], - }).compile(); + providers: [UsersService], + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); controller = module.get(UsersController); }); diff --git a/src/users/users.service.spec.ts b/src/users/users.service.spec.ts index 62815ba6..05a1f82b 100644 --- a/src/users/users.service.spec.ts +++ b/src/users/users.service.spec.ts @@ -1,5 +1,6 @@ import { Test, TestingModule } from '@nestjs/testing'; import { UsersService } from './users.service'; +import { PrismaService } from 'src/prisma/prisma.service'; describe('UsersService', () => { let service: UsersService; @@ -7,7 +8,13 @@ describe('UsersService', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [UsersService], - }).compile(); + }) + .useMocker((token) => { + if (token === PrismaService) { + return {}; + } + }) + .compile(); service = module.get(UsersService); }); diff --git a/test/app.e2e-spec.ts b/test/app.e2e-spec.ts index 50cda623..4bcbd9bb 100644 --- a/test/app.e2e-spec.ts +++ b/test/app.e2e-spec.ts @@ -1,7 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { INestApplication } from '@nestjs/common'; import * as request from 'supertest'; -import { AppModule } from './../src/app.module'; +import { AppModule } from 'src/app.module'; describe('AppController (e2e)', () => { let app: INestApplication; @@ -16,9 +16,6 @@ describe('AppController (e2e)', () => { }); it('/ (GET)', () => { - return request(app.getHttpServer()) - .get('/') - .expect(200) - .expect('Hello World!'); + return request(app.getHttpServer()).get('/').expect(404); }); }); diff --git a/test/jest-e2e.json b/test/jest-e2e.json deleted file mode 100644 index e9d912f3..00000000 --- a/test/jest-e2e.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "moduleFileExtensions": ["js", "json", "ts"], - "rootDir": ".", - "testEnvironment": "node", - "testRegex": ".e2e-spec.ts$", - "transform": { - "^.+\\.(t|j)s$": "ts-jest" - } -} diff --git a/test/jest.e2e.config.ts b/test/jest.e2e.config.ts new file mode 100644 index 00000000..d680f170 --- /dev/null +++ b/test/jest.e2e.config.ts @@ -0,0 +1,15 @@ +import type { Config } from 'jest'; +import { default as projectConfig } from '../jest.config'; + +const config: Config = { + ...projectConfig, + rootDir: '.', + moduleNameMapper: { + '^src/(.*)$': '/../src/$1', + '^@/(.*)$': '/../src/$1', + '^test/(.*)$': '/$1', + }, + testRegex: '.e2e-spec.ts$', +}; + +export default config; From 0e1a7a1d46c0f8bab3d3dade5045b088e250b3c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Geraldo=20D=2E=20F?= Date: Tue, 14 May 2024 22:04:02 -0300 Subject: [PATCH 21/29] feat: added partners endpoint (#106) --- .../migrations/20240514211840_/migration.sql | 14 +++++++++ .../migrations/20240515003750_/migration.sql | 8 +++++ prisma/schema.prisma | 10 +++++++ src/app.module.ts | 2 ++ src/partners/partners.controller.spec.ts | 29 +++++++++++++++++++ src/partners/partners.controller.ts | 21 ++++++++++++++ src/partners/partners.module.ts | 12 ++++++++ src/partners/partners.service.spec.ts | 28 ++++++++++++++++++ src/partners/partners.service.ts | 14 +++++++++ src/shelter/shelter.service.ts | 2 +- 10 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 prisma/migrations/20240514211840_/migration.sql create mode 100644 prisma/migrations/20240515003750_/migration.sql create mode 100644 src/partners/partners.controller.spec.ts create mode 100644 src/partners/partners.controller.ts create mode 100644 src/partners/partners.module.ts create mode 100644 src/partners/partners.service.spec.ts create mode 100644 src/partners/partners.service.ts diff --git a/prisma/migrations/20240514211840_/migration.sql b/prisma/migrations/20240514211840_/migration.sql new file mode 100644 index 00000000..d0e1f1e2 --- /dev/null +++ b/prisma/migrations/20240514211840_/migration.sql @@ -0,0 +1,14 @@ +-- CreateTable +CREATE TABLE "partners" ( + "id" TEXT NOT NULL, + "name" TEXT NOT NULL, + "link" TEXT NOT NULL, + "iconName" TEXT NOT NULL DEFAULT 'Handshake', + "created_at" VARCHAR(32) NOT NULL, + "updated_at" VARCHAR(32), + + CONSTRAINT "partners_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "partners_name_key" ON "partners"("name"); diff --git a/prisma/migrations/20240515003750_/migration.sql b/prisma/migrations/20240515003750_/migration.sql new file mode 100644 index 00000000..5e1e2a63 --- /dev/null +++ b/prisma/migrations/20240515003750_/migration.sql @@ -0,0 +1,8 @@ +/* + Warnings: + + - You are about to drop the column `iconName` on the `partners` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "partners" DROP COLUMN "iconName"; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index b853d2b4..a43b535a 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -123,3 +123,13 @@ model ShelterManagers { @@id([shelterId, userId]) @@map("shelter_managers") } + +model Partners { + id String @id @default(uuid()) + name String @unique + link String + createdAt String @map("created_at") @db.VarChar(32) + updatedAt String? @map("updated_at") @db.VarChar(32) + + @@map("partners") +} diff --git a/src/app.module.ts b/src/app.module.ts index 8b528767..c08ea99f 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -11,6 +11,7 @@ import { SessionsModule } from './sessions/sessions.module'; import { SupplyCategoriesModule } from './supply-categories/supply-categories.module'; import { ShelterManagersModule } from './shelter-managers/shelter-managers.module'; import { ShelterSupplyModule } from './shelter-supply/shelter-supply.module'; +import { PartnersModule } from './partners/partners.module'; @Module({ imports: [ @@ -22,6 +23,7 @@ import { ShelterSupplyModule } from './shelter-supply/shelter-supply.module'; SupplyCategoriesModule, ShelterManagersModule, ShelterSupplyModule, + PartnersModule, ], controllers: [], providers: [ diff --git a/src/partners/partners.controller.spec.ts b/src/partners/partners.controller.spec.ts new file mode 100644 index 00000000..3d7226e8 --- /dev/null +++ b/src/partners/partners.controller.spec.ts @@ -0,0 +1,29 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { PartnersController } from './partners.controller'; +import { PartnersService } from './partners.service'; +import { PrismaService } from '../prisma/prisma.service'; + +describe('PartnersController', () => { + let controller: PartnersController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [PartnersController], + providers: [PartnersService], + }) + .useMocker((token) => { + if (token === PrismaService) { + return { + supplyCategory: { findMany: jest.fn().mockResolvedValue(0) }, + }; + } + }) + .compile(); + + controller = module.get(PartnersController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/partners/partners.controller.ts b/src/partners/partners.controller.ts new file mode 100644 index 00000000..f1829171 --- /dev/null +++ b/src/partners/partners.controller.ts @@ -0,0 +1,21 @@ +import { Controller, Get, HttpException, Logger } from '@nestjs/common'; +import { PartnersService } from './partners.service'; +import { ServerResponse } from '../utils'; + +@Controller('partners') +export class PartnersController { + private logger = new Logger(PartnersController.name); + + constructor(private readonly partnersService: PartnersService) {} + + @Get('') + async index() { + try { + const data = await this.partnersService.index(); + return new ServerResponse(200, 'Successfully get partners', data); + } catch (err: any) { + this.logger.error(`Failed to get partners: ${err}`); + throw new HttpException(err?.code ?? err?.name ?? `${err}`, 400); + } + } +} diff --git a/src/partners/partners.module.ts b/src/partners/partners.module.ts new file mode 100644 index 00000000..04ea8c41 --- /dev/null +++ b/src/partners/partners.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; + +import { PartnersService } from './partners.service'; +import { PartnersController } from './partners.controller'; +import { PrismaModule } from '../prisma/prisma.module'; + +@Module({ + imports: [PrismaModule], + providers: [PartnersService], + controllers: [PartnersController], +}) +export class PartnersModule {} diff --git a/src/partners/partners.service.spec.ts b/src/partners/partners.service.spec.ts new file mode 100644 index 00000000..f34d51e9 --- /dev/null +++ b/src/partners/partners.service.spec.ts @@ -0,0 +1,28 @@ +import { Test, TestingModule } from '@nestjs/testing'; + +import { PartnersService } from './partners.service'; +import { PrismaService } from '../prisma/prisma.service'; + +describe('PartnersService', () => { + let service: PartnersService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [PartnersService], + }) + .useMocker((token) => { + if (token === PrismaService) { + return { + supplyCategory: { findMany: jest.fn().mockResolvedValue(0) }, + }; + } + }) + .compile(); + + service = module.get(PartnersService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/partners/partners.service.ts b/src/partners/partners.service.ts new file mode 100644 index 00000000..6b3f6c8a --- /dev/null +++ b/src/partners/partners.service.ts @@ -0,0 +1,14 @@ +import { Injectable } from '@nestjs/common'; +import { ApiTags } from '@nestjs/swagger'; + +import { PrismaService } from '../prisma/prisma.service'; + +@ApiTags('Parceiros') +@Injectable() +export class PartnersService { + constructor(private readonly prismaService: PrismaService) {} + + async index() { + return await this.prismaService.partners.findMany({}); + } +} diff --git a/src/shelter/shelter.service.ts b/src/shelter/shelter.service.ts index 190aedaa..35bfbc11 100644 --- a/src/shelter/shelter.service.ts +++ b/src/shelter/shelter.service.ts @@ -1,6 +1,7 @@ import { Injectable, OnModuleInit } from '@nestjs/common'; import { Prisma } from '@prisma/client'; import { DefaultArgs } from '@prisma/client/runtime/library'; +import { subDays } from 'date-fns'; import * as qs from 'qs'; import { z } from 'zod'; @@ -14,7 +15,6 @@ import { FullUpdateShelterSchema, UpdateShelterSchema, } from './types/types'; -import { subDays } from 'date-fns'; @Injectable() export class ShelterService implements OnModuleInit { From b62302d2154e88e5990b2f01c79d0026786853d7 Mon Sep 17 00:00:00 2001 From: Kevin Eduard Piske Date: Wed, 15 May 2024 10:26:30 -0300 Subject: [PATCH 22/29] =?UTF-8?q?fix:=20Corre=C3=A7=C3=A3o=20da=20issue=20?= =?UTF-8?q?#146=20do=20frontend.=20(#105)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Kevin Eduard Piske Co-authored-by: José Geraldo D. F --- src/shelter/ShelterSearch.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shelter/ShelterSearch.ts b/src/shelter/ShelterSearch.ts index 5215d37c..3d1367e5 100644 --- a/src/shelter/ShelterSearch.ts +++ b/src/shelter/ShelterSearch.ts @@ -60,6 +60,7 @@ class ShelterSearch { }, unavailable: { lte: this.prismaService.shelter.fields.shelteredPeople, + not: 0, }, }; From 591eca26fada89799f3b4e6c57d64eef2cc3437f Mon Sep 17 00:00:00 2001 From: Wesley Araujo <52975177+w-araujo@users.noreply.github.com> Date: Wed, 15 May 2024 10:29:18 -0300 Subject: [PATCH 23/29] feat: Add description and including a bearer token in swagger in users routes (#63) --- src/main.ts | 1 + src/users/users.controller.ts | 76 ++++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/src/main.ts b/src/main.ts index eaf3c678..649e75d4 100644 --- a/src/main.ts +++ b/src/main.ts @@ -18,6 +18,7 @@ async function bootstrap() { .setTitle('SOS - Rio Grande do Sul') .setDescription('...') .setVersion('1.0') + .addBearerAuth() .build(); const document = SwaggerModule.createDocument(app, config); SwaggerModule.setup('api', app, document); diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts index 5d4a0dc2..8bbcb6f1 100644 --- a/src/users/users.controller.ts +++ b/src/users/users.controller.ts @@ -9,7 +9,7 @@ import { Req, UseGuards, } from '@nestjs/common'; -import { ApiTags } from '@nestjs/swagger'; +import { ApiTags, ApiBody, ApiOperation, ApiBearerAuth } from '@nestjs/swagger'; import { UserGuard } from '@/guards/user.guard'; import { ServerResponse } from '../utils'; @@ -25,6 +25,28 @@ export class UsersController { @Post('') @UseGuards(AdminGuard) + @ApiBearerAuth() + @ApiOperation({ summary: 'Cria um novo usuário', description: 'Esta rota é usada para criar um novo usuário no sistema.' }) + @ApiBody({ + schema: { + type: 'object', + properties: { + name: { type: 'string' }, + lastName: { type: 'string' }, + phone: { type: 'string' }, + }, + required: ['name', 'lastName', 'phone'], + }, + examples: { + 'Exemplo 1': { + value: { + name: 'Dinho', + lastName: 'Duarte', + phone: '(31) 996675945', + }, + }, + }, + }) async store(@Body() body) { try { await this.userServices.store(body); @@ -37,6 +59,32 @@ export class UsersController { @Put(':id') @UseGuards(AdminGuard) + @ApiBearerAuth() + @ApiOperation({ summary: 'Atualiza um usuário pelo ID', description: 'Esta rota é usada para atualizar um usuário específico no sistema, podendo ser informado um ou mais campos.' }) + @ApiBody({ + schema: { + type: 'object', + properties: { + name: { type: 'string' }, + lastName: { type: 'string' }, + phone: { type: 'string' }, + login: { type: 'string' }, + password: { type: 'string' }, + }, + required: [], + }, + examples: { + 'Exemplo 1': { + value: { + name: 'Dinho', + lastName: 'Duarte', + phone: '(31) 996675945', + login: 'dinho duarte', + password: '123456', + }, + }, + }, + }) async update(@Body() body, @Param('id') id: string) { try { await this.userServices.update(id, body); @@ -49,6 +97,32 @@ export class UsersController { @Put('') @UseGuards(UserGuard) + @ApiBearerAuth() + @ApiOperation({ summary: 'Atualiza o seu próprio usuário', description: 'Esta rota é usada para atualizar o próprio usuário no sistema, podendo ser informado um ou mais campos.' }) + @ApiBody({ + schema: { + type: 'object', + properties: { + name: { type: 'string' }, + lastName: { type: 'string' }, + phone: { type: 'string' }, + login: { type: 'string' }, + password: { type: 'string' }, + }, + required: [], + }, + examples: { + 'Exemplo 1': { + value: { + name: 'Dinho', + lastName: 'Duarte', + phone: '(31) 996675945', + login: 'dinho duarte', + password: '123456', + }, + }, + }, + }) async selfUpdate(@Body() body, @Req() req) { try { const { userId } = req.user; From 037479cfcf03332501a29d50a96c8bffa7799913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Geraldo=20D=2E=20F?= Date: Wed, 15 May 2024 16:46:13 -0300 Subject: [PATCH 24/29] fix: city filter (#116) --- src/shelter/shelter.service.ts | 7 ++++++- src/users/users.controller.ts | 17 ++++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/shelter/shelter.service.ts b/src/shelter/shelter.service.ts index 35bfbc11..f9c853d8 100644 --- a/src/shelter/shelter.service.ts +++ b/src/shelter/shelter.service.ts @@ -187,6 +187,11 @@ export class ShelterService implements OnModuleInit { async getCities() { const cities = await this.prismaService.shelter.groupBy({ + where: { + city: { + not: null, + }, + }, by: ['city'], _count: { id: true, @@ -199,7 +204,7 @@ export class ShelterService implements OnModuleInit { }); return cities.map(({ city, _count: { id: sheltersCount } }) => ({ - city: city || 'Cidade não informada', + city, sheltersCount, })); } diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts index 8bbcb6f1..18baf4b6 100644 --- a/src/users/users.controller.ts +++ b/src/users/users.controller.ts @@ -26,7 +26,10 @@ export class UsersController { @Post('') @UseGuards(AdminGuard) @ApiBearerAuth() - @ApiOperation({ summary: 'Cria um novo usuário', description: 'Esta rota é usada para criar um novo usuário no sistema.' }) + @ApiOperation({ + summary: 'Cria um novo usuário', + description: 'Esta rota é usada para criar um novo usuário no sistema.', + }) @ApiBody({ schema: { type: 'object', @@ -60,7 +63,11 @@ export class UsersController { @Put(':id') @UseGuards(AdminGuard) @ApiBearerAuth() - @ApiOperation({ summary: 'Atualiza um usuário pelo ID', description: 'Esta rota é usada para atualizar um usuário específico no sistema, podendo ser informado um ou mais campos.' }) + @ApiOperation({ + summary: 'Atualiza um usuário pelo ID', + description: + 'Esta rota é usada para atualizar um usuário específico no sistema, podendo ser informado um ou mais campos.', + }) @ApiBody({ schema: { type: 'object', @@ -98,7 +105,11 @@ export class UsersController { @Put('') @UseGuards(UserGuard) @ApiBearerAuth() - @ApiOperation({ summary: 'Atualiza o seu próprio usuário', description: 'Esta rota é usada para atualizar o próprio usuário no sistema, podendo ser informado um ou mais campos.' }) + @ApiOperation({ + summary: 'Atualiza o seu próprio usuário', + description: + 'Esta rota é usada para atualizar o próprio usuário no sistema, podendo ser informado um ou mais campos.', + }) @ApiBody({ schema: { type: 'object', From e18bbfaf9b11eaea1f43314404c9bb5a2d0c912e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9lio=20Dantas?= Date: Wed, 15 May 2024 17:57:05 -0300 Subject: [PATCH 25/29] =?UTF-8?q?doc:=20adicionando=20make=20para=20inclui?= =?UTF-8?q?=20comandos=20para=20facilitar=20o=20setup=20da=20aplica=C3=A7?= =?UTF-8?q?=C3=A3o.=20criados=20alguns=20comandos=20e=20incluido=20do=20re?= =?UTF-8?q?adme=20da=20aplica=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 2 + Makefile | 34 ++++++++++--- README.md | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 169 insertions(+), 8 deletions(-) diff --git a/Dockerfile b/Dockerfile index a98af1c5..4306b753 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,7 @@ FROM node:18.18-alpine as node +RUN apk add --no-cache make + WORKDIR /usr/app COPY package.json package-lock.json ./ diff --git a/Makefile b/Makefile index a37e20f1..f7a7c53b 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ TAG_OR_COMMIT := $(shell git describe --tags --always) DOCKER_REGISTRY = ghcr.io IMAGE_NAME = $(DOCKER_REGISTRY)/sos-rs/backend +CONTAINER_BACKEND = sos-rs-api install: @npm install @@ -12,9 +13,20 @@ prisma: @npx run migrations:dev setup: + make file-mode + make create.env.file @$(MAKE) install @$(MAKE) prisma +file-mode: + @echo "Configuring git fileMode to false" + git config core.fileMode false + +create.env.file: + if [ ! -f .env ]; then \ + cp .env.local .env; \ + fi + start: @$(MAKE) setup @npm run start:dev @@ -48,17 +60,25 @@ test-e2e: @npm run test:e2e dev-up: - @docker compose -f docker-compose.dev.yml up -d --build + @docker-compose -f docker-compose.dev.yml up -d --build +setup-docker: + make file-mode + make create.env.file + make dev-up + dev-down: - @docker compose -f docker-compose.dev.yml down + @docker-compose -f docker-compose.dev.yml down + +bash: + docker exec -it ${CONTAINER_BACKEND} sh dev-logs: - @docker compose -f docker-compose.dev.yml logs -f + docker-compose -f docker-compose.dev.yml logs -f dev-db-load-dump: - @docker compose -f docker-compose.dev.yml cp prisma/dev_dump.sql db:/tmp/backup.sql - @docker compose -f docker-compose.dev.yml exec db psql -U root -d sos_rs -f /tmp/backup.sql + @docker-compose -f docker-compose.dev.yml cp prisma/dev_dump.sql db:/tmp/backup.sql + @docker-compose -f docker-compose.dev.yml exec db psql -U root -d sos_rs -f /tmp/backup.sql # Para ser usado no workflow de build docker-build: @@ -70,8 +90,8 @@ docker-tag: # Para ser usado no workflow de deploy prod-up: - @docker compose -f docker-compose.yml up -d --build --force-recreate + @docker-compose -f docker-compose.yml up -d --build --force-recreate prod-down: - @docker compose -f docker-compose.yml down --rmi all + @docker-compose -f docker-compose.yml down --rmi all diff --git a/README.md b/README.md index b7bc9e44..2db7695c 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,17 @@ autenticação de usuários, gerenciamento de abrigos e suprimentos, e muito mai Se você quiser discutir ideias, problemas ou contribuições, sinta-se à vontade para se juntar ao nosso servidor do Discord [aqui](https://discord.gg/vjZS6BQXvM). +## Workspace Dependencies +- [Node 18.18](https://nodejs.org/) +- [Docker](https://www.docker.com/get-started/) +- Make + - [Windows](https://gnuwin32.sourceforge.net/packages/make.htm) + - Linux + ```bash + sudo apt update + sudo apt install make + ``` + ## 🛠 Tecnologias Utilizadas - **🟢 Node.js**: Ambiente de execução para JavaScript. @@ -26,6 +37,7 @@ Se estiver usando Docker, você pode usar o comando `make dev-db-load-dump` para Para desenvolvedores de frontend que não precisam executar localmente a API e o banco, siga estes passos: + 1. Clone o arquivo `.env` de exemplo: ```bash cp .env.local .env @@ -35,6 +47,11 @@ Para desenvolvedores de frontend que não precisam executar localmente a API e o ```bash docker-compose -f docker-compose.dev.yml up ``` +Usando make: + + ```bash + make setup-docker +``` ## 🚀 Configuração Inicial Local Se você estiver recebendo algum erro relacionado a PORT da DATABASE_URL, tem uma linha comentada no .env que pode ser @@ -47,12 +64,25 @@ descomentada para resolver o problema. git clone https://github.com/seuusuario/projeto-enchentes-backend.git ``` 2. Instale as dependências: + ```bash - make install + make setup + + # ou sem make + + npm install + npx prisma generate + npx prisma migrate dev + npm run start:dev + ``` 3. Inicie o servidor: + ```bash make start + + # ou sem make + npm start ``` A API estará disponível em `http://localhost:4000`. @@ -86,6 +116,115 @@ descomentada para resolver o problema. - **📝 POST /supply-categories** - Registra uma nova categoria de suprimentos. - **🔧 PUT /supply-categories/:categoryId** - Atualiza uma categoria. +Claro, aqui está a documentação para esses comandos: + +--- + +### Comandos Make + +#### Instalação e Configuração do Projeto + +- **install:** + - `make install` + - Instala as dependências do projeto usando o npm. + +- **prisma:** + - `make prisma` + - Gera os artefatos do Prisma executando `npx prisma generate` e aplica as migrações do banco de dados executando `npx run migrations:dev`. + +- **setup:** + - `make setup` + - Configura o ambiente de desenvolvimento, desativando o `fileMode` do Git, criando um arquivo `.env` se ele não existir e executando os comandos `install` e `prisma`. + +- **file-mode:** + - `make file-mode` + - Configura o Git para desativar o `fileMode`. + +- **create.env.file:** + - `make create.env.file` + - Cria um arquivo `.env` a partir de `.env.local` se o arquivo `.env` ainda não existir. + +#### Inicialização e Execução do Projeto + +- **start:** + - `make start` + - Inicia o projeto em modo de desenvolvimento executando `npm run start:dev`, após configurar o ambiente com `setup`. + +- **start-debug:** + - `make start-debug` + - Inicia o projeto em modo de depuração executando `npm run start:debug`, após configurar o ambiente com `setup`. + +- **build:** + - `make build` + - Compila o projeto executando `npm run build`. + +#### Testes e Verificação + +- **test:** + - `make test` + - Executa os testes do projeto. + +- **test-coverage:** + - `make test-coverage` + - Executa os testes com cobertura. + +- **test-debug:** + - `make test-debug` + - Executa os testes em modo de depuração. + +- **test-e2e:** + - `make test-e2e` + - Executa os testes end-to-end. + +#### Docker e Ambiente de Desenvolvimento + +- **dev-up:** + - `make dev-up` + - Inicia os serviços de desenvolvimento usando Docker Compose (`docker-compose.dev.yml`). + +- **setup-docker:** + - `make setup-docker` + - Configura o ambiente de desenvolvimento com Docker, desativando o `fileMode` do Git, criando um arquivo `.env` se ele não existir e iniciando os serviços de desenvolvimento. + +- **dev-down:** + - `make dev-down` + - Desliga os serviços de desenvolvimento iniciados com Docker Compose. + +- **bash:** + - `make bash` + - Acessa o terminal do contêiner específico `sos-rs-api` para execução de comandos específicos. + +- **dev-logs:** + - `make dev-logs` + - Exibe os logs dos serviços de desenvolvimento iniciados com Docker Compose. + +- **dev-db-load-dump:** + - `make dev-db-load-dump` + - Carrega um dump no banco de dados de desenvolvimento. + +#### Docker Builds e Tags + +- **docker-build:** + - `make docker-build` + - Constrói a imagem Docker do projeto. + +- **docker-tag:** + - `make docker-tag` + - Adiciona tags à imagem Docker para identificação. + +#### Produção + +- **prod-up:** + - `make prod-up` + - Inicia os serviços de produção usando Docker Compose. + +- **prod-down:** + - `make prod-down` + - Desliga os serviços de produção e remove as imagens Docker. + +--- + + ## 🤝 Contribuição Contribuições são muito bem-vindas! Se deseja ajudar, faça um fork do repositório, crie uma branch com suas From d418b275afdd8bfca0a5e6d5e5b128a27fe74974 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9lio=20Dantas?= Date: Wed, 15 May 2024 18:24:14 -0300 Subject: [PATCH 26/29] build: add-makefile - instalar makefile para usos dentro do container em dev --- docker-compose.dev.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index f46200de..50f1a349 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -23,6 +23,7 @@ services: - PORT=${PORT} command: > sh -c "npm install && + apk add --no-cache make && npx prisma generate && npx prisma migrate dev && npm run start:dev -- --preserveWatchOutput" From 9d2c144773ad5958d02dfc3f4709ab5aa313bce5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9lio=20Dantas?= Date: Wed, 15 May 2024 19:02:32 -0300 Subject: [PATCH 27/29] =?UTF-8?q?doc:=20removendo=20descri=C3=A7=C3=A3o=20?= =?UTF-8?q?duplicada?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 2db7695c..378bce22 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,6 @@ Se estiver usando Docker, você pode usar o comando `make dev-db-load-dump` para Para desenvolvedores de frontend que não precisam executar localmente a API e o banco, siga estes passos: - 1. Clone o arquivo `.env` de exemplo: ```bash cp .env.local .env From c743a8c7136344b0a561059c11181d0872350e2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9lio=20Dantas?= Date: Sat, 18 May 2024 11:38:22 -0300 Subject: [PATCH 28/29] doc: colocando comandos makes no formato de tabela --- README.md | 120 ++++++++++++------------------------------------------ 1 file changed, 25 insertions(+), 95 deletions(-) diff --git a/README.md b/README.md index a42cf046..19da1a99 100644 --- a/README.md +++ b/README.md @@ -126,105 +126,35 @@ Claro, aqui está a documentação para esses comandos: ### Comandos Make -#### Instalação e Configuração do Projeto -- **install:** - - `make install` - - Instala as dependências do projeto usando o npm. -- **prisma:** - - `make prisma` - - Gera os artefatos do Prisma executando `npx prisma generate` e aplica as migrações do banco de dados executando `npx run migrations:dev`. - -- **setup:** - - `make setup` - - Configura o ambiente de desenvolvimento, desativando o `fileMode` do Git, criando um arquivo `.env` se ele não existir e executando os comandos `install` e `prisma`. - -- **file-mode:** - - `make file-mode` - - Configura o Git para desativar o `fileMode`. - -- **create.env.file:** - - `make create.env.file` - - Cria um arquivo `.env` a partir de `.env.local` se o arquivo `.env` ainda não existir. - -#### Inicialização e Execução do Projeto - -- **start:** - - `make start` - - Inicia o projeto em modo de desenvolvimento executando `npm run start:dev`, após configurar o ambiente com `setup`. - -- **start-debug:** - - `make start-debug` - - Inicia o projeto em modo de depuração executando `npm run start:debug`, após configurar o ambiente com `setup`. - -- **build:** - - `make build` - - Compila o projeto executando `npm run build`. - -#### Testes e Verificação - -- **test:** - - `make test` - - Executa os testes do projeto. - -- **test-coverage:** - - `make test-coverage` - - Executa os testes com cobertura. - -- **test-debug:** - - `make test-debug` - - Executa os testes em modo de depuração. - -- **test-e2e:** - - `make test-e2e` - - Executa os testes end-to-end. - -#### Docker e Ambiente de Desenvolvimento - -- **dev-up:** - - `make dev-up` - - Inicia os serviços de desenvolvimento usando Docker Compose (`docker-compose.dev.yml`). - -- **setup-docker:** - - `make setup-docker` - - Configura o ambiente de desenvolvimento com Docker, desativando o `fileMode` do Git, criando um arquivo `.env` se ele não existir e iniciando os serviços de desenvolvimento. - -- **dev-down:** - - `make dev-down` - - Desliga os serviços de desenvolvimento iniciados com Docker Compose. - -- **bash:** - - `make bash` - - Acessa o terminal do contêiner específico `sos-rs-api` para execução de comandos específicos. - -- **dev-logs:** - - `make dev-logs` - - Exibe os logs dos serviços de desenvolvimento iniciados com Docker Compose. - -- **dev-db-load-dump:** - - `make dev-db-load-dump` - - Carrega um dump no banco de dados de desenvolvimento. - -#### Docker Builds e Tags - -- **docker-build:** - - `make docker-build` - - Constrói a imagem Docker do projeto. - -- **docker-tag:** - - `make docker-tag` - - Adiciona tags à imagem Docker para identificação. - -#### Produção + +### Comandos Make -- **prod-up:** - - `make prod-up` - - Inicia os serviços de produção usando Docker Compose. +Command | Docker | Locally | Description +---- | ------- | ------- | ------- +install | - | `make install` | Instala as dependências do projeto usando o npm. +prisma | - | `make prisma` | Gera os artefatos do Prisma executando `npx prisma generate` e aplica as migrações do banco de dados executando `npx run migrations:dev`. +setup | `make setup-docker` | `make setup` | Configura o ambiente de desenvolvimento, desativando o `fileMode` do Git, criando um arquivo `.env` se ele não existir e executando os comandos `install` e `prisma`. +file-mode | - | `make file-mode` | Configura o Git para desativar o `fileMode`. +create.env.file | - | `make create.env.file` | Cria um arquivo `.env` a partir de `.env.local` se o arquivo `.env` ainda não existir. +start | - | `make start` | Inicia o projeto em modo de desenvolvimento executando `npm run start:dev`, após configurar o ambiente com `setup`. +start-debug | - | `make start-debug` | Inicia o projeto em modo de depuração executando `npm run start:debug`, após configurar o ambiente com `setup`. +build | - | `make build` | Compila o projeto executando `npm run build`. +test | - | `make test` | Executa os testes do projeto. +test-coverage | - | `make test-coverage` | Executa os testes com cobertura. +test-debug | - | `make test-debug` | Executa os testes em modo de depuração. +test-e2e | - | `make test-e2e` | Executa os testes end-to-end. +dev-up | `make dev-up` | - | Inicia os serviços de desenvolvimento usando Docker Compose (`docker-compose.dev.yml`). +dev-down | `make dev-down` | - | Desliga os serviços de desenvolvimento iniciados com Docker Compose. +bash | `make bash` | - | Acessa o terminal do contêiner específico `sos-rs-api` para execução de comandos específicos. +dev-logs | `make dev-logs` | - | Exibe os logs dos serviços de desenvolvimento iniciados com Docker Compose. +dev-db-load-dump | `make dev-db-load-dump` | - | Carrega um dump no banco de dados de desenvolvimento. +docker-build | `make docker-build` | - | Constrói a imagem Docker do projeto. +docker-tag | `make docker-tag` | - | Adiciona tags à imagem Docker para identificação. +prod-up | `make prod-up` | - | Inicia os serviços de produção usando Docker Compose. +prod-down | `make prod-down` | - | Desliga os serviços de produção e remove as imagens Docker. -- **prod-down:** - - `make prod-down` - - Desliga os serviços de produção e remove as imagens Docker. --- From fe4816b32377eb7e69c67cd507d97d9b688fad51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9lio=20Dantas?= Date: Sat, 18 May 2024 11:59:06 -0300 Subject: [PATCH 29/29] fix: corrigindo comando make para rodar as migrations --- Makefile | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f7a7c53b..06397390 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ install: prisma: @npx prisma generate - @npx run migrations:dev + @npm run migrations:dev setup: make file-mode diff --git a/README.md b/README.md index 19da1a99..d3a17eb7 100644 --- a/README.md +++ b/README.md @@ -152,7 +152,7 @@ dev-logs | `make dev-logs` | - | Exibe os logs dos serviços de desenvolvimento dev-db-load-dump | `make dev-db-load-dump` | - | Carrega um dump no banco de dados de desenvolvimento. docker-build | `make docker-build` | - | Constrói a imagem Docker do projeto. docker-tag | `make docker-tag` | - | Adiciona tags à imagem Docker para identificação. -prod-up | `make prod-up` | - | Inicia os serviços de produção usando Docker Compose. +prod-up | `make prod-up` | - | Inicia os serviços de produção usando Docker Compose.make prod-down | `make prod-down` | - | Desliga os serviços de produção e remove as imagens Docker.