Skip to content

Commit b1b8404

Browse files
authored
Feature/backend docs openapi (#101)
2 parents 70305c5 + fdb1fe6 commit b1b8404

8 files changed

Lines changed: 1069 additions & 59 deletions

File tree

.cspell/custom-dictionary-workspace.txt

Lines changed: 140 additions & 0 deletions
Large diffs are not rendered by default.

BACKEND.md

Lines changed: 344 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,344 @@
1+
# Backend - Documentação
2+
3+
Este documento descreve as principais funcionalidades, rotas, módulos e variáveis de ambiente do backend do projeto.
4+
5+
**Localização do código**: [backend](backend)
6+
7+
## Visão geral
8+
9+
- API REST em Express (TypeScript).
10+
- Scraper externo em Go integrado via HTTP (`GO_SCRAPER_URL`).
11+
- Banco de dados gerenciado com Drizzle (Postgres).
12+
- Autenticação via OAuth (Google/GitHub/LinkedIn) e credenciais (email/senha) com `iron-session`.
13+
- Cache/índices em memória (Redis) e integração com sistema Valkey para pesquisa rápida.
14+
- Documentação OpenAPI/Swagger disponível em `/docs` (quando habilitado).
15+
16+
## Como executar (rápido)
17+
18+
Requisitos: Node.js >= 22, PostgreSQL, Redis (opcional para cache), Go scraper (opcional)
19+
20+
Instalar dependências e rodar API:
21+
22+
```bash
23+
cd backend
24+
npm install
25+
npm run dev # inicia em modo de desenvolvimento
26+
# ou
27+
npm start # inicia a API
28+
```
29+
30+
Rodar scraper (local):
31+
32+
```bash
33+
npm run scraper
34+
```
35+
36+
Testes:
37+
38+
```bash
39+
npm test
40+
npm run test:watch
41+
```
42+
43+
Scripts relevantes em `package.json`:
44+
45+
- `start`, `dev`, `api` — iniciar servidor
46+
- `scraper`, `scraper:watch` — executar scraper (index.ts / Go)
47+
- `test`, `test:coverage`, `test:watch` — testes com Vitest
48+
- `db:generate`, `db:migrate`, `db:push` — comandos Drizzle
49+
50+
## Arquitetura e módulos principais
51+
52+
- `src/app.ts` — monta a aplicação Express, middlewares e rotas.
53+
- `src/server.ts` — inicia o servidor e registra Swagger (`/docs`).
54+
- `src/config.ts` — leitura e validação das variáveis de ambiente.
55+
- `src/swagger.ts` — gera especificação OpenAPI via `swagger-jsdoc`.
56+
57+
Módulos principais:
58+
59+
- `src/modules/auth` — OAuth providers, `AuthController`, `AuthService`, `credentials` (registro/login/logout).
60+
- `src/modules/users` — perfis e preferências do usuário (`UsersController`, `UsersService`).
61+
- `src/modules/savedJobs` — CRUD de vagas salvas (`SavedJobsController`, `SavedJobsService`).
62+
- `src/modules/*` — outros módulos relacionados a credenciais, buscas e integrações.
63+
64+
Adaptadores externos:
65+
66+
- `src/adapters/goScraper.ts` — envia requisições para o serviço Go que faz o scraping (`/scrape`).
67+
- `src/adapters/goKeywords.ts` — carrega e envia keywords do/para o serviço Go.
68+
69+
Database / Schemas (Drizzle):
70+
71+
- `src/db/schema/users.ts` — tabela `users`.
72+
- `src/db/schema/credentials.ts` — credenciais (email, hash).
73+
- `src/db/schema/keywords.ts` — palavras-chave (fonte `user|scraper`).
74+
- `src/db/schema/savedJobs.ts` — vagas salvas (`saved_jobs`) e enum `status`.
75+
- Migrações e snapshots em `drizzle/`.
76+
77+
Cache & Indexes:
78+
79+
- `src/lib/cache.ts` — helpers para Redis/Valkey; usado por `jobs.routes` para obter ids e buscar vagas em memória.
80+
- Busca por palavras-chave usa índices invertidos e interseção para eficiência.
81+
82+
## Middlewares
83+
84+
- `withSession` — integra `iron-session` (sessões + cookie `vagas_session`).
85+
- `requireAuth` — valida autenticação nas rotas que exigem usuário.
86+
- `securityHeaders` — cabeçalhos de segurança.
87+
- `cors` — configuração de CORS (opções em `src/middleware/cors.ts`).
88+
- `errorHandler` — tratamento centralizado de erros.
89+
90+
## Endpoints principais
91+
92+
Base: `/api`
93+
94+
- Sistema
95+
- `GET /api/health` — verifica disponibilidade (retorna `{ ok: true }`).
96+
- `GET /docs` — UI do Swagger (quando habilitado).
97+
98+
- Auth / OAuth
99+
- `GET /api/auth/:provider/url` — retorna URL de autenticação (ex: `google`, `github`, `linkedin`).
100+
- `GET /api/auth/:provider/callback` — callback OAuth — processa código/state e cria sessão.
101+
102+
- Credenciais (email/senha)
103+
- `POST /api/auth/register` — registra usuário (cria `users`, `credentials`, `userPreferences`) e inicia sessão.
104+
- `POST /api/auth/login` — autentica e inicia sessão.
105+
- `POST /api/auth/logout` — destroi sessão.
106+
- `GET /api/auth/me` — retorna id do usuário autenticado.
107+
108+
- Usuários
109+
- `GET /api/users/profile` — retorna perfil do usuário autenticado.
110+
- `PATCH /api/users/profile` — atualiza campos do perfil.
111+
- `GET /api/users/preferences` — obtém preferências do usuário.
112+
- `POST /api/users/preferences` — cria preferências (caso não existam).
113+
- `PATCH /api/users/preferences` — atualiza preferências.
114+
115+
- Jobs
116+
- `GET /api/jobs/search?keywords=...` — busca vagas utilizando índices/Valkey/Redis. Retorna paginação e fonte (`source`).
117+
118+
- Keywords
119+
- `GET /api/keywords` — lista keywords persistidas no banco.
120+
- `POST /api/keywords` — enfileira uma keyword para processamento pelo serviço Go (retorna 202).
121+
122+
- Vagas salvas (Saved Jobs)
123+
- `GET /api/saved-jobs` — lista vagas salvas do usuário.
124+
- `GET /api/saved-jobs/:id` — obtém vaga salva por id.
125+
- `POST /api/saved-jobs` — cria nova vaga salva.
126+
- `PATCH /api/saved-jobs/:id` — atualiza vaga salva.
127+
- `DELETE /api/saved-jobs/:id` — remove vaga salva.
128+
129+
Observações de segurança nas rotas:
130+
131+
- Rotas sob `/api/users`, `/api/jobs`, `/api/keywords` e `/api/saved-jobs` usam `withSession` + `requireAuth` (quando aplicável).
132+
- `auth` usa `withSession` para armazenar OAuth state e criar sessão.
133+
134+
## Variáveis de ambiente importantes
135+
136+
Definidas/consumidas em `src/config.ts` e outros módulos:
137+
138+
- `HEADLESS` — modo headless do scraper (bool).
139+
- `WAIT_BETWEEN_SEARCHES_MS` — intervalo entre buscas (ms).
140+
- `PAGE_TIMEOUT_MS` — timeout de página (ms).
141+
- `MAX_PAGES_PER_KEYWORD` — limite de páginas por keyword.
142+
- `VIEWPORT_WIDTH`, `VIEWPORT_HEIGHT` — dimensões do browser.
143+
- `SEARCH_LOCATION`, `SEARCH_GEO_ID`, `SEARCH_LANGUAGE` — parâmetros de busca.
144+
- `REMOTE_ONLY` — filtrar vagas remotas.
145+
- `JOB_TYPES` — filtros de tipo de vaga.
146+
- `TIME_FILTER` — filtro temporal (ex: `r604800`).
147+
- `DATABASE_URL` — conexão com Postgres.
148+
- `VALKEY_URL` — endpoint do Valkey (se usado).
149+
- `GO_SCRAPER_URL` — URL do serviço Go que realiza scraping.
150+
- `SESSION_SECRET` — senha para `iron-session` (obrigatória em produção).
151+
- `PORT` — porta do servidor (padrão 3001).
152+
153+
## Segurança e criptografia
154+
155+
- Senhas armazenadas usando Argon2 (`argon2`), com opções configuradas no serviço de credenciais.
156+
- Cookies de sessão `httpOnly` e `secure` quando NODE_ENV=production.
157+
- Índices únicos e constraints no DB (ex: email/username/keyword uniques) definidos nas tabelas Drizzle.
158+
159+
## Integração com serviço Go
160+
161+
- `goScraper.ts` faz POST em `${GO_SCRAPER_URL}/scrape` com `ScrapeParams` e valida `ScrapeResponse`.
162+
- `goKeywords.ts` consulta e publica keywords via endpoints do serviço Go (`/api/keywords`).
163+
164+
## Banco de dados
165+
166+
- Uso de Drizzle ORM com tipos gerados em `src/db/schema`.
167+
- Tabelas: `users`, `credentials`, `keywords`, `saved_jobs`, `user_preferences`, etc.
168+
- Migrations em `drizzle/`.
169+
170+
## Logs e observabilidade
171+
172+
- `src/logger.ts` exporta `logInfo`, `logWarn`, etc.
173+
- Erros críticos são logados; rotas tratam respostas e retornam mensagens amigáveis.
174+
175+
## Testes
176+
177+
- Testes unitários e de integração com `vitest` em `tests/`.
178+
- Cobertura configurada em `test:coverage`.
179+
180+
## Docker / Infra
181+
182+
- `Dockerfile` presente no diretório `backend`.
183+
- `docker-compose.yml` no projeto raiz orquestra serviços (possivelmente `scraper-go`, `postgres`, `redis`).
184+
185+
## Pontos de atenção / Próximos passos sugeridos
186+
187+
- Garantir `SESSION_SECRET` seguro em produção.
188+
- Documentar contrato do Valkey (se for serviço externo) e endpoints do Go scraper com exemplos de payload.
189+
- Adicionar exemplos de requests/responses no Swagger para endpoints críticos (auth, jobs/search).
190+
191+
---
192+
193+
Para editar ou complementar esta documentação, abra [backend/BACKEND.md](backend/BACKEND.md).
194+
195+
## Exemplos de Request / Response
196+
197+
Seguem exemplos práticos para os endpoints mais usados. Ajuste `HOST` para seu ambiente (ex: `http://localhost:3001`).
198+
199+
- Registrar (credentials)
200+
201+
Request:
202+
203+
POST /api/auth/register
204+
205+
```json
206+
{
207+
"email": "user@example.com",
208+
"password": "StrongP@ssw0rd",
209+
"name": "Fulano"
210+
}
211+
```
212+
213+
Response (201):
214+
215+
```json
216+
{
217+
"user": {
218+
"id": "uuid",
219+
"email": "user@example.com",
220+
"displayName": "Fulano",
221+
"username": "fulano",
222+
"emailVerified": false
223+
},
224+
"session": { "userId": "uuid" }
225+
}
226+
```
227+
228+
- Login (credentials)
229+
230+
Request:
231+
232+
POST /api/auth/login
233+
234+
```json
235+
{
236+
"email": "user@example.com",
237+
"password": "StrongP@ssw0rd"
238+
}
239+
```
240+
241+
Response (200):
242+
243+
```json
244+
{
245+
"user": { "id": "uuid", "email": "user@example.com", "username": "fulano" },
246+
"session": { "userId": "uuid" }
247+
}
248+
```
249+
250+
- Buscar vagas (Jobs search)
251+
252+
Request:
253+
254+
GET /api/jobs/search?keywords=react,node&page=1&limit=10
255+
256+
Response (200):
257+
258+
```json
259+
{
260+
"total": 123,
261+
"page": 1,
262+
"limit": 10,
263+
"totalPages": 13,
264+
"hasNext": true,
265+
"hasPrev": false,
266+
"jobs": [ { "id": "job-id", "title": "Frontend Developer", "company": "ACME" } ],
267+
"source": "valkey_filtered_by_keywords:react+node"
268+
}
269+
```
270+
271+
- Enfileirar keyword
272+
273+
Request:
274+
275+
POST /api/keywords
276+
277+
```json
278+
{
279+
"keyword": "typescript"
280+
}
281+
```
282+
283+
Response (202):
284+
285+
```json
286+
{
287+
"ok": true,
288+
"message": "Keyword enfileirada para processamento."
289+
}
290+
```
291+
292+
- Vagas salvas (Saved Jobs) — criar
293+
294+
Request:
295+
296+
POST /api/saved-jobs
297+
298+
```json
299+
{
300+
"jobLink": "https://www.linkedin.com/jobs/view/123",
301+
"jobTitle": "Backend Developer",
302+
"company": "ACME",
303+
"location": "São Paulo",
304+
"source": "linkedin",
305+
"keyword": "node"
306+
}
307+
```
308+
309+
Response (201):
310+
311+
```json
312+
{
313+
"id": "uuid",
314+
"userId": "uuid",
315+
"jobLink": "https://...",
316+
"jobTitle": "Backend Developer",
317+
"company": "ACME",
318+
"location": "São Paulo",
319+
"status": "saved",
320+
"createdAt": "2026-05-26T..."
321+
}
322+
```
323+
324+
- Perfil do usuário
325+
326+
Request:
327+
328+
GET /api/users/profile
329+
330+
Response (200):
331+
332+
```json
333+
{
334+
"id": "uuid",
335+
"displayName": "Fulano",
336+
"username": "fulano",
337+
"email": "user@example.com",
338+
"avatarUrl": null
339+
}
340+
```
341+
342+
---
343+
344+
Os exemplos acima são intencionais e servem como referência rápida para integrar o frontend ou scripts que consomem a API.

0 commit comments

Comments
 (0)