Delete backend/ARCHITECTURE.md
This commit is contained in:
@@ -1,209 +0,0 @@
|
|||||||
# 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
|
|
||||||
Reference in New Issue
Block a user