architecture refactoring

This commit is contained in:
Cesar
2026-05-22 19:26:38 -06:00
parent 34dbfd051b
commit c2e53eb21b
20 changed files with 949 additions and 222 deletions

202
backend/CHANGES_SUMMARY.md Normal file
View File

@@ -0,0 +1,202 @@
# Resumen de Archivos - Clean Architecture
## Archivos Modificados/Creados
### 1. **config/env.ts** ✓
- Lee y valida variables de entorno
- Centraliza PORT, DATABASE_URL, JWT_SEED, BCRYPT_ROUNDS
- Se importa en toda la app para acceder a configuración
### 2. **config/jwt.ts** ✓
- JwtAdapter para generar y validar tokens
- Métodos estáticos: `generate()` y `validate()`
- Define JwtPayload interface con id y email
- Exporta los tokens y valida automáticamente expiración
### 3. **config/bcrypt.ts** ✓
- BcryptAdapter para hashear y comparar contraseñas
- Métodos estáticos: `hash()` y `compare()`
- Usa BCRYPT_ROUNDS de env para consistencia
### 4. **domain/errors/custom.error.ts** ✓
- CustomError clase base para errores personalizados
- Métodos estáticos: badRequest(), unauthorized(), notFound(), conflict(), internalServer()
- Cada error tiene statusCode para responder correctamente
### 5. **domain/dtos/auth/register-user.dto.ts** ✓
- RegisterUserDto interfaz
- RegisterUserDtoValidator con método validate()
- Valida name (no vacío), email (formato), password (mínimo 6 caracteres)
- Normaliza email a minúsculas
### 6. **domain/dtos/auth/login-user.dto.ts** ✓
- LoginUserDto interfaz
- LoginUserDtoValidator con método validate()
- Valida email (formato) y password (no vacío)
- Normaliza email a minúsculas
### 7. **domain/dtos/index.ts** ✓
- Exporta todos los DTOs en un solo lugar
- Facilita importar: `import * from '../../dtos'`
### 8. **domain/repositories/auth.repository.ts** ✓
- AuthRepository interfaz (contrato)
- Define métodos: findByEmail(), create(), findById()
- El UseCase no sabe cómo se implementa, solo el contrato
### 9. **domain/use-cases/auth/register-user.use-case.ts** ✓
- RegisterUserUseCase ejecuta el registro
- Valida DTO → Verifica email → Hashea → Crea usuario → Genera JWT
- Retorna { user, token }
- Lanza CustomError si email existe
### 10. **domain/use-cases/auth/login-user.use-case.ts** ✓
- LoginUserUseCase ejecuta el login
- Valida DTO → Busca usuario → Compara password → Genera JWT
- Retorna { user, token }
- Lanza CustomError si credenciales son inválidas
### 11. **domain/use-cases/auth/get-me.use-case.ts** ✓
- GetMeUseCase obtiene el usuario autenticado
- Recibe userId del JWT
- Busca en repositorio y retorna datos del usuario
- Lanza CustomError si no existe
### 12. **data/postgres/index.ts** ✓
- Cliente único de Prisma
- Se inicializa una vez y se reutiliza
- Se exporta para usarlo en repositorios
### 13. **data/repositories/auth.repository.impl.ts** ✓
- AuthRepositoryImpl implementa AuthRepository
- Habla directamente con Prisma (BD)
- Métodos: findByEmail(), create(), findById()
- Select solo los campos necesarios (no contraseña en getMe)
### 14. **presentation/middlewares/auth.middleware.ts** ✓
- AuthMiddleware valida JWT en rutas protegidas
- Extrae token del header: "Authorization: Bearer TOKEN"
- Valida token → Busca usuario en BD → Agrega a req.user
- Define AuthRequest extends Request con user opcional
- Retorna 401 si token inválido o usuario no existe
### 15. **presentation/auth/controller.ts** ✓
- AuthController maneja peticiones HTTP
- Métodos: register(), login(), getMe()
- Cada método recibe, llama al UseCase, responde
- handleError() maneja CustomError y error normal
### 16. **presentation/auth/routes.ts** ✓
- Define rutas de autenticación
- POST /api/auth/register → controller.register
- POST /api/auth/login → controller.login
- GET /api/auth/me → AuthMiddleware.validate → controller.getMe
### 17. **presentation/routes.ts** ✓
- Rutas principales de la app
- Integra AuthRoutes en /api/auth
### 18. **presentation/server.ts** (Sin cambios)
- Instancia Express
- Middlewares globales (json, urlencoded)
### 19. **app.ts** ✓
- Punto de entrada
- Conecta a Prisma
- Crea Server con env.PORT
- Maneja errores globales
### 20. **.env.example** ✓
- Ejemplo de variables de entorno
- El usuario debe copiar a .env y configurar valores
### 21. **ARCHITECTURE.md** ✓
- Documentación completa de la arquitectura
- Estructura de carpetas
- Flujo de datos
- Endpoints
- Variables de entorno
---
## Resumen de Cambios
### Lógica de Negocio (Domain)
- DTOs con validaciones robustas
- UseCase implementan la lógica de registrar, login, obtener usuario
- Repository interface define el contrato
- CustomError para manejo de errores consistente
### Implementación (Data)
- AuthRepositoryImpl usa Prisma para hablar con BD
- Select solo campos necesarios (seguridad)
- Reutiliza cliente de Prisma
### HTTP (Presentation)
- AuthController coordina peticiones HTTP
- AuthMiddleware valida JWT en rutas protegidas
- AuthRoutes define endpoints
### Configuración (Config)
- JwtAdapter y BcryptAdapter centralizados
- env.ts maneja todas las variables
---
## Cómo Usar
### 1. Copiar .env.example a .env
```bash
cp .env.example .env
```
### 2. Configurar variables de entorno
```bash
# .env
DATABASE_URL=postgresql://user:password@localhost:5432/optihack
JWT_SEED=mi_secreto_super_seguro
```
### 3. Instalar dependencias
```bash
npm install
```
### 4. Ejecutar migraciones de Prisma
```bash
npx prisma migrate dev
```
### 5. Iniciar el servidor
```bash
npm run dev
```
### 6. Probar endpoints
```bash
# Register
curl -X POST http://localhost:3000/api/auth/register \
-H "Content-Type: application/json" \
-d '{"name":"John","email":"john@example.com","password":"password123"}'
# Login
curl -X POST http://localhost:3000/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"john@example.com","password":"password123"}'
# GetMe (usa el token obtenido en login)
curl -X GET http://localhost:3000/api/auth/me \
-H "Authorization: Bearer <token>"
```
---
## Principios Aplicados
**Separation of Concerns**: Cada capa tiene una responsabilidad
**Dependency Inversion**: UseCase depende de interfaz, no implementación
**Single Responsibility**: Cada archivo hace una cosa bien
**Open/Closed**: Fácil agregar nuevos casos de uso
**Liskov Substitution**: AuthRepositoryImpl puede reemplazar AuthRepository
**Interface Segregation**: Interfaces pequeñas y específicas
**DRY**: No repitas código, centraliza lógica