Files
hackathon-opti-1a67c9077937…/backend/ARCHITECTURE.md
2026-05-22 19:26:38 -06:00

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

  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