5.5 KiB
5.5 KiB
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
- Cliente envía POST
/api/auth/registercon{ name, email, password } - Controller recibe la request
- Controller llama a
RegisterUserUseCase.execute() - UseCase valida el DTO
- UseCase verifica si el email existe (llama al Repository)
- Repository busca en la BD
- UseCase hashea la contraseña
- UseCase crea el usuario (llama al Repository)
- Repository inserta en la BD
- UseCase genera el JWT
- 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
- Crear el UseCase en
domain/use-cases/auth/new-feature.use-case.ts - Agregar método al Repository en
domain/repositories/auth.repository.ts - Implementar en
data/repositories/auth.repository.impl.ts - Crear método en Controller en
presentation/auth/controller.ts - 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