# Clean Architecture - Backend OptiHack ## Estructura del Proyecto ``` src/ ├── config/ # Configuración e integración con librerías │ ├── env.ts # Variables de entorno │ ├── jwt.ts # JwtAdapter - genera y valida tokens │ └── bcrypt.ts # BcryptAdapter - hashea y compara contraseñas │ ├── domain/ # Lógica de negocio (sin dependencias externas) │ ├── dtos/ # Data Transfer Objects con validación │ │ ├── auth/ │ │ │ ├── register-user.dto.ts │ │ │ └── login-user.dto.ts │ │ └── index.ts │ │ │ ├── repositories/ # Interfaces de repositorios (contratos) │ │ └── auth.repository.ts │ │ │ ├── use-cases/ # Lógica de negocio (casos de uso) │ │ └── auth/ │ │ ├── register-user.use-case.ts │ │ ├── login-user.use-case.ts │ │ └── get-me.use-case.ts │ │ │ └── errors/ # Errores personalizados │ └── custom.error.ts │ ├── data/ # Implementación de datos (Prisma, BD) │ ├── postgres/ # Cliente de Prisma │ │ └── index.ts │ └── repositories/ # Implementación de repositorios │ └── auth.repository.impl.ts │ ├── presentation/ # HTTP (Express, controladores, middlewares) │ ├── auth/ │ │ ├── controller.ts │ │ └── routes.ts │ ├── middlewares/ │ │ └── auth.middleware.ts │ ├── routes.ts # Rutas principales │ └── server.ts # Instancia de Express │ ├── app.ts # Punto de entrada └── ... ``` ## Flujo de Datos (Regla Principal) ``` HTTP Request ↓ Controller recibe los datos ↓ Controller llama al UseCase ↓ UseCase hace la lógica de negocio ↓ UseCase llama al Repository ↓ Repository implementación habla con Prisma ↓ Prisma ejecuta queries en la BD ↓ Response va hacia arriba ↓ HTTP Response ``` ### Ejemplo: Register 1. **Cliente** envía POST `/api/auth/register` con `{ name, email, password }` 2. **Controller** recibe la request 3. **Controller** llama a `RegisterUserUseCase.execute()` 4. **UseCase** valida el DTO 5. **UseCase** verifica si el email existe (llama al Repository) 6. **Repository** busca en la BD 7. **UseCase** hashea la contraseña 8. **UseCase** crea el usuario (llama al Repository) 9. **Repository** inserta en la BD 10. **UseCase** genera el JWT 11. **Controller** responde con user + token ## Responsabilidades por Capa ### **Config** - Variables de entorno - Adapters (JWT, Bcrypt) - Configuraciones globales ### **Domain** (Sin dependencias externas) - DTOs con validación - Interfaces de repositorios (contratos) - Casos de uso (lógica de negocio) - Errores personalizados ### **Data** - Implementación de repositorios - Cliente de Prisma - Queries a la base de datos ### **Presentation** - Controladores (Express handlers) - Rutas - Middlewares - Validación HTTP ## Endpoints de Autenticación ### 1. Register ``` POST /api/auth/register Content-Type: application/json { "name": "John Doe", "email": "john@example.com", "password": "password123" } Response 201: { "user": { "id": 1, "email": "john@example.com", "name": "John Doe" }, "token": "eyJhbGc..." } ``` ### 2. Login ``` POST /api/auth/login Content-Type: application/json { "email": "john@example.com", "password": "password123" } Response 200: { "user": { "id": 1, "email": "john@example.com", "name": "John Doe" }, "token": "eyJhbGc..." } ``` ### 3. GetMe (Protegida) ``` GET /api/auth/me Authorization: Bearer eyJhbGc... Response 200: { "id": 1, "email": "john@example.com", "name": "John Doe", "role": "USER" } ``` ## Validaciones ### DTOs - **name**: string no vacío - **email**: email válido (regex) - **password**: mínimo 6 caracteres ### Errores - **400 Bad Request**: Datos inválidos - **401 Unauthorized**: Token inválido, usuario no autenticado - **404 Not Found**: Usuario no encontrado - **409 Conflict**: Email ya en uso - **500 Internal Server Error**: Error del servidor ## Variables de Entorno (.env) ``` PORT=3000 # Puerto del servidor NODE_ENV=development # Entorno DATABASE_URL=postgresql://user:pass@host:5432/db # URL de BD JWT_SEED=tu_secreto_super_seguro # Seed para JWT JWT_EXPIRES_IN=7d # Expiración del token BCRYPT_ROUNDS=10 # Rondas de bcrypt ``` ## Cómo Agregar un Nuevo UseCase 1. **Crear el UseCase** en `domain/use-cases/auth/new-feature.use-case.ts` 2. **Agregar método al Repository** en `domain/repositories/auth.repository.ts` 3. **Implementar en** `data/repositories/auth.repository.impl.ts` 4. **Crear método en Controller** en `presentation/auth/controller.ts` 5. **Agregar ruta** en `presentation/auth/routes.ts` ## Ventajas de Esta Arquitectura ✓ **Separación de responsabilidades**: Cada capa hace una cosa ✓ **Fácil de testear**: UseCase no conoce HTTP ni BD ✓ **Mantenible**: Cambios en BD no afectan lógica de negocio ✓ **Escalable**: Fácil agregar nuevos módulos ✓ **Simple**: No over-engineered, ideal para MVP/Hackathon ✓ **Limpio**: Código organizado y fácil de entender