Este projeto é uma API desenvolvida para processar documentos (PDFs e páginas web), extrair dados, armazená-los em um banco de dados e associá-los a clientes cadastrados. A aplicação foi construída utilizando NestJS e segue boas práticas de desenvolvimento, como Clean Architecture, Design Patterns, autenticação JWT, e integração com Docker.
- Linguagem: TypeScript
- Framework: NestJS
- ORM: Prisma
- Autenticação: JWT e Bcrypt
- Validação de Dados: Class Validator
- Tranformação de Dados: Class Transform
- Testes: Jest e Supertest
- Containerização: Docker
- Web Scraping: Cheerio
- Processamento de PDFs: PDF-Parse
- CI/CD: Github Actions
/src
|-- application/ # Camada de aplicação (use cases, DTOs, errors)
|-- domain/ # Camada de domínio (entidades e interfaces)
|-- infrastructure/ # Camada de infraestrutura (controllers, adapters, pipes, repositories)
|-- documentation/ # Documentação do projeto
|-- main.ts # Arquivo principal da aplicação
- Separação de Camadas: O projeto segue a Clean Architecture, separando responsabilidades em camadas (
Domain,Application,Infrastructure). - Desacoplamento: As dependências entre camadas são gerenciadas por interfaces, permitindo substituição e testes independentes.
Na pasta documentation, você encontrará o arquivo architecture.md. Ao abrir esse arquivo com o preview, será exibida uma imagem detalhada da arquitetura do projeto, o que ajuda a visualizar melhor a estrutura e o fluxo da aplicação.
- Utilizei
whitelist: truepara ignorar atributos extras no corpo da requisição, garantindo maior segurança e consistência.
- IDs únicos e difíceis de descobrir foram implementados com UUID, garantindo segurança e unicidade.
- O banco de dados foi configurado no Docker para evitar a necessidade de instalação local.
- Funcionalidades simples foram desenvolvidas primeiro, deixando as mais complexas, como JWT, para o final. Isso facilitou os testes iniciais.
- Testes automatizados e verificação de código foram configurados para feedback rápido, evitando commits com falhas.
- Variáveis sensíveis, como URL e nome do banco de dados, foram protegidas com
dotenveGitHub Secrets.
- Escolhido pelo suporte a migrations versionadas, evitando problemas de sincronização com
sync: true. - Utilizei
delete on cascadepara evitar registros órfãos e prevenir erros de remoção. - Nomeação com
camelCaseno código esnake_caseno banco de dados, utilizando o decorator@mapdo Prisma.
- Imagem Docker otimizada com multi-staged build, reduzindo o tamanho final.
- Classe abstrata para lidar com hashing de senha (
bcrypt). - Pipe para hash de senha antes de chegar ao service, aproveitando os recursos do NestJS.
- Uso de
includeecountpara consultas eficientes.
- Separação correta dos módulos, sem duplicação de providers. Tudo é gerenciado por
importseexportsno módulo responsável.
- Exceções do framework e métodos de criptografia foram desacoplados, permitindo substituição fácil.
- Erros na camada
Applicationsão usados para lógica de negócio, enquanto erros naInfrastructurelidam com detalhes técnicos. - Uso de um
Global Filterpara centralizar o tratamento de erros, evitando múltiplostry-catchnas controllers.
- Factories foram implementadas para abstrair a complexidade de instanciação dos use cases.
- Um
SignInAdapterPipefoi criado para converter DTOs antes de chegar à controller, economizando linhas de código e melhorando a legibilidade.
- Nomes genéricos foram usados para abstrações, enquanto implementações específicas utilizam o nome da biblioteca.
- Docker: Instale o Docker e o Docker Compose para rodar os serviços.
git clone https://github.com/renanjava/backend-challengecd backend-challengecode .No terminal da raiz do diretório do projeto, execute o seguinte comando para instalar todas as dependências necessárias:
npm installRenomeie o arquivo .env.example para .env com o seguinte comando:
mv .env.example .envApós renomear o .env.example para .env, preencha o conteúdo do arquivo com os valores abaixo:
PORT=3000
DATABASE_NAME=backend_challenge
DATABASE_URL=postgresql://postgres:password@localhost:5432/${DATABASE_NAME}
JWT_SECRET=cafecomleiteNo diretório do projeto, execute o seguinte comando para subir apenas o banco de dados:
npm run docker:up:postgresCom o banco de dados em execução, aplique as migrações:
npx prisma migrate deployEm seguida, gere o client Prisma:
npx prisma generateEm seguida, vá no arquivo .env e altere a URL do banco:
DATABASE_URL=postgresql://postgres:password@postgres:5432/${DATABASE_NAME}Agora, inicie o restante dos serviços:
npm run docker:upApós iniciar a aplicação, ela estará disponível em http://localhost:3000/
- POST /auth/login:
- Autentica um usuário e retorna um token JWT.
- Body:
email: E-mail do usuário.password: Senha do usuário.
- Resposta:
token: Token JWT gerado para autenticação.
-
POST /client:
- Cria um novo cliente.
- Body:
name: Nome do cliente.email: E-mail do cliente.password: Senha do cliente.
- Resposta:
client: Cliente recém-criado.
-
GET /client:
- Lista todos os clientes.
- Resposta:
clients: Lista de todos os clientes registrados no sistema.
-
GET /client/document:
- Lista todos os documentos associados ao cliente autenticado.
- Headers:
Authorization: Token JWT válido, usado para autorizar e obter o ID do cliente.
- Resposta:
documents: Lista de documentos pertencentes ao cliente autenticado.
-
GET /client/document/:id:
- Retorna um documento específico do cliente autenticado.
- Headers:
Authorization: Token JWT válido, usado para autorizar e obter o ID do cliente.
- Parâmetros:
id: ID do documento.
- Headers:
Authorization: Token JWT válido.
- Resposta:
document: Objeto do documento correspondente aoid, caso pertença ao cliente autenticado.
-
POST /document/pdf:
- Faz upload de um PDF, processa o conteúdo e associa a um cliente.
- Headers:
Authorization: Token JWT válido, usado para autorizar e obter o ID do cliente.
- Body:
file: Arquivo PDF.
- Resposta:
document: Dados processados do PDF (como título, conteúdo extraído, data de processamento, etc.).
-
POST /document/web:
- Processa uma página web a partir de uma URL e associa a um cliente.
- Headers:
Authorization: Token JWT válido, usado para autorizar e obter o ID do cliente.
- Body:
url: URL da página web a ser processada.
- Resposta:
document: Dados processados da página web (como título, conteúdo extraído, data de processamento, etc.).
A aplicação conta com testes unitários e de integração utilizando o framework Jest.
Para executar os testes unitários da aplicação, utilize o seguinte comando:
npm run test:unitPara executar os testes de integração, utilize o seguinte comando:
npm run test:intPara executar os testes com cobertura de código, utilize o seguinte comando:
npm run test:cov