🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
25 KiB
Patrones de Backend - GAMILIT
Documento: Analisis de Patrones de Backend Node.js + TypeScript Proyecto de Referencia: GAMILIT Fecha: 2025-11-23 Analista: Architecture-Analyst Agent
1. VISION GENERAL
GAMILIT implementa un backend modular en Node.js 18+ con Express.js y TypeScript 5+ que demuestra excelentes practicas de organizacion, separacion de responsabilidades y mantenibilidad del codigo.
Stack tecnologico:
- Runtime: Node.js 18+
- Framework: Express.js
- Lenguaje: TypeScript 5+ (strict mode)
- Database Client: node-postgres (pg)
- Testing: Jest (40 tests, 15% coverage - GAP CRITICO)
- Process Manager: PM2
- Linting: ESLint + Prettier
Metricas:
- LOC: ~45,000 lineas
- Modulos: 11 modulos funcionales
- Endpoints: 470+ API endpoints
- Controllers: ~50
- Services: ~80
- DTOs: ~100
- Entities: ~40
2. ESTRUCTURA MODULAR (11 MODULOS)
2.1 Organizacion del Backend
backend/
├── src/
│ ├── shared/ # Codigo compartido (constants SSOT, utils, types)
│ │ ├── constants/ # ⭐ Single Source of Truth
│ │ │ ├── enums.constants.ts # 687 lineas de ENUMs
│ │ │ ├── database.constants.ts # Schemas y tablas
│ │ │ ├── routes.constants.ts # 368 lineas de rutas API
│ │ │ ├── regex.ts # Expresiones regulares
│ │ │ └── index.ts # Barrel export
│ │ ├── types/ # Tipos TypeScript compartidos
│ │ ├── utils/ # Utilidades generales
│ │ └── decorators/ # Decoradores personalizados
│ │
│ ├── middleware/ # Middleware de Express
│ │ ├── auth.middleware.ts # Autenticacion JWT
│ │ ├── validation.middleware.ts # Validacion de DTOs
│ │ ├── error.middleware.ts # Manejo de errores global
│ │ └── logging.middleware.ts # Logging de requests
│ │
│ ├── config/ # Configuraciones
│ │ ├── database.config.ts # Configuracion DB
│ │ ├── jwt.config.ts # Configuracion JWT
│ │ └── cors.config.ts # Configuracion CORS
│ │
│ ├── database/ # Conexion DB, migrations, seeds
│ │ ├── connection.ts # Pool de conexiones
│ │ └── pool.ts # Singleton pool
│ │
│ ├── modules/ # ⭐ 11 MODULOS DE NEGOCIO
│ │ ├── auth/ # Autenticacion y autorizacion
│ │ ├── educational/ # Contenido educativo
│ │ ├── gamification/ # Sistema de gamificacion
│ │ ├── progress/ # Tracking de progreso
│ │ ├── social/ # Features sociales
│ │ ├── content/ # Content management
│ │ ├── admin/ # Panel de administracion
│ │ ├── teacher/ # Portal de profesor
│ │ ├── analytics/ # Analytics y reportes
│ │ ├── notifications/ # Sistema de notificaciones
│ │ └── system/ # Sistema y configuracion
│ │
│ └── main.ts # Entry point de la aplicacion
│
├── __tests__/ # Tests (40 tests, 15% coverage)
├── dist/ # Build output (compilado)
├── logs/ # Application logs
├── node_modules/ # Dependencies (95 MB)
├── package.json # NPM config
├── tsconfig.json # ⭐ TypeScript config (path aliases)
├── jest.config.js # Jest config
├── .eslintrc.js # ESLint config
└── README.md # Documentacion
2.2 Los 11 Modulos Funcionales
| Modulo | Responsabilidad | Endpoints | Aplicabilidad ERP |
|---|---|---|---|
| auth/ | Autenticacion, autorizacion, usuarios, roles | ~40 | ⭐⭐⭐⭐⭐ MAXIMA |
| educational/ | Modulos, ejercicios, recursos educativos | ~60 | ❌ No aplicable |
| gamification/ | Logros, rangos, ML Coins, comodines | ~80 | ❌ No aplicable |
| progress/ | Tracking de progreso, sesiones, attempts | ~90 | 🔧 Adaptar (avance de obra) |
| social/ | Aulas, equipos, amistades, desafios | ~70 | 🔧 Adaptar (jerarquias) |
| content/ | Plantillas, multimedia, Marie Curie | ~40 | 🔧 Adaptar (docs, plantillas) |
| admin/ | Panel de administracion, bulk operations | ~30 | ⭐⭐⭐⭐⭐ MAXIMA |
| teacher/ | Portal de profesor, grading, classrooms | ~30 | 🔧 Adaptar (supervisor) |
| analytics/ | Analytics, reportes, metricas | ~20 | ⭐⭐⭐⭐⭐ MAXIMA |
| notifications/ | Notificaciones multi-canal | ~10 | ⭐⭐⭐⭐⭐ MAXIMA |
| system/ | Configuracion, feature flags, health | ~10 | ⭐⭐⭐⭐⭐ MAXIMA |
Total endpoints: 470+
3. PATRON DE MODULO TIPICO
Cada modulo en GAMILIT sigue un patron consistente que facilita navegacion y mantenimiento:
3.1 Estructura de un Modulo (ejemplo: auth/)
modules/auth/
├── entities/ # Entidades de base de datos
│ ├── user.entity.ts
│ ├── role.entity.ts
│ ├── session.entity.ts
│ └── tenant.entity.ts
│
├── dtos/ # Data Transfer Objects (validacion)
│ ├── login.dto.ts
│ ├── register.dto.ts
│ ├── update-profile.dto.ts
│ └── change-password.dto.ts
│
├── services/ # Logica de negocio
│ ├── auth.service.ts # Servicio principal
│ ├── user.service.ts # Servicios especializados
│ ├── session.service.ts
│ └── tenant.service.ts
│
├── controllers/ # Controllers Express (rutas)
│ ├── auth.controller.ts
│ └── user.controller.ts
│
├── routes/ # Definicion de rutas
│ ├── auth.routes.ts # Rutas de autenticacion
│ └── user.routes.ts # Rutas de usuarios
│
├── middleware/ # Middleware especifico del modulo
│ ├── auth.middleware.ts # Verificacion JWT
│ └── rate-limit.middleware.ts # Rate limiting
│
├── validators/ # Validadores personalizados
│ └── user.validator.ts
│
├── types/ # Tipos TypeScript del modulo
│ └── auth.types.ts
│
└── index.ts # Barrel export (Public API)
3.2 Capas del Modulo
1. Entities (Entidades):
- Representacion de tablas de base de datos
- Mapeo 1:1 con esquema PostgreSQL
- Tipos TypeScript para type safety
Ejemplo user.entity.ts:
import { DB_SCHEMAS, DB_TABLES } from '@shared/constants';
export interface UserEntity {
id: string;
email: string;
password_hash: string;
tenant_id: string;
created_at: Date;
updated_at: Date;
}
export const USER_TABLE = `${DB_SCHEMAS.AUTH}.${DB_TABLES.AUTH.USERS}`;
2. DTOs (Data Transfer Objects):
- Validacion de datos de entrada
- Transformacion de datos
- Documentacion de contratos
Ejemplo login.dto.ts:
export interface LoginDto {
email: string; // Validacion: email valido
password: string; // Validacion: minimo 8 caracteres
tenant_id?: string; // Opcional para multi-tenancy
}
export function validateLoginDto(data: unknown): LoginDto {
// Validacion con Zod, class-validator, etc.
// ...
return data as LoginDto;
}
3. Services (Servicios):
- Logica de negocio
- Interaccion con base de datos
- Orquestacion de operaciones
Ejemplo auth.service.ts:
import { pool } from '@database/pool';
import { USER_TABLE } from './entities/user.entity';
import { DB_SCHEMAS } from '@shared/constants';
export class AuthService {
async login(dto: LoginDto): Promise<LoginResponse> {
// 1. Buscar usuario por email
const user = await this.findUserByEmail(dto.email);
// 2. Verificar password
const isValid = await bcrypt.compare(dto.password, user.password_hash);
if (!isValid) throw new UnauthorizedError();
// 3. Generar JWT
const token = jwt.sign({ userId: user.id }, JWT_SECRET);
// 4. Crear sesion
await this.createSession(user.id, token);
return { user, token };
}
private async findUserByEmail(email: string): Promise<UserEntity> {
const result = await pool.query(
`SELECT * FROM ${USER_TABLE} WHERE email = $1`,
[email]
);
return result.rows[0];
}
}
4. Controllers (Controladores):
- Manejo de requests HTTP
- Validacion de input
- Delegacion a servicios
- Manejo de responses
Ejemplo auth.controller.ts:
import { Router } from 'express';
import { AuthService } from './services/auth.service';
import { API_ROUTES } from '@shared/constants';
const router = Router();
const authService = new AuthService();
// POST /api/v1/auth/login
router.post(API_ROUTES.AUTH.LOGIN, async (req, res, next) => {
try {
const dto = validateLoginDto(req.body);
const result = await authService.login(dto);
res.json(result);
} catch (error) {
next(error);
}
});
export default router;
5. Routes (Rutas):
- Configuracion de rutas
- Aplicacion de middleware
- Documentacion de endpoints
6. Middleware:
- Autenticacion
- Autorizacion
- Validacion
- Rate limiting
7. Validators:
- Validaciones personalizadas
- Reglas de negocio
4. PATH ALIASES (IMPORTS LIMPIOS)
4.1 Configuracion en tsconfig.json
{
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"@/*": ["./*"],
"@shared/*": ["shared/*"],
"@middleware/*": ["middleware/*"],
"@config/*": ["config/*"],
"@database/*": ["database/*"],
"@modules/*": ["modules/*"]
}
}
}
4.2 Comparacion de Imports
❌ SIN PATH ALIASES (malo, fragil):
import { UserEntity } from '../../../modules/auth/entities/user.entity';
import { DB_SCHEMAS } from '../../../shared/constants/database.constants';
import { AuthService } from '../../../modules/auth/services/auth.service';
import { validateLoginDto } from '../../../modules/auth/dtos/login.dto';
✅ CON PATH ALIASES (bueno, mantenible):
import { UserEntity } from '@modules/auth/entities/user.entity';
import { DB_SCHEMAS } from '@shared/constants/database.constants';
import { AuthService } from '@modules/auth/services/auth.service';
import { validateLoginDto } from '@modules/auth/dtos/login.dto';
4.3 Beneficios
- Legibilidad: Imports semanticos y claros
- Mantenibilidad: Facil refactoring de estructura
- Prevencion de errores: No mas
../../../incorrectos - IDE Support: Autocompletado mejorado
- Consistencia: Mismo patron en todo el proyecto
4.4 Aplicabilidad a ERP Generico
⭐⭐⭐⭐⭐ (MAXIMA)
Decision: ✅ ADOPTAR COMPLETAMENTE
Aliases propuestos para ERP:
{
"paths": {
"@/*": ["./*"],
"@shared/*": ["shared/*"],
"@middleware/*": ["middleware/*"],
"@config/*": ["config/*"],
"@database/*": ["database/*"],
"@modules/*": ["modules/*"],
"@shared/*": ["modules/core/*"],
"@accounting/*": ["modules/accounting/*"],
"@budgets/*": ["modules/budgets/*"],
"@purchasing/*": ["modules/purchasing/*"]
}
}
5. MIDDLEWARE PATTERNS
5.1 Tipos de Middleware Implementados
1. Authentication Middleware:
// middleware/auth.middleware.ts
import jwt from 'jsonwebtoken';
export const authenticate = async (req, res, next) => {
try {
const token = extractToken(req.headers.authorization);
const decoded = jwt.verify(token, JWT_SECRET);
// Establecer contexto del usuario
req.user = decoded;
req.userId = decoded.userId;
req.tenantId = decoded.tenantId;
next();
} catch (error) {
res.status(401).json({ error: 'Unauthorized' });
}
};
2. Validation Middleware:
// middleware/validation.middleware.ts
export const validateDto = (schema) => {
return (req, res, next) => {
try {
req.body = schema.parse(req.body);
next();
} catch (error) {
res.status(400).json({ errors: error.errors });
}
};
};
// Uso:
router.post('/login', validateDto(loginSchema), authController.login);
3. Error Middleware:
// middleware/error.middleware.ts
export const errorHandler = (err, req, res, next) => {
console.error(err);
// Errores conocidos
if (err instanceof UnauthorizedError) {
return res.status(401).json({ error: err.message });
}
if (err instanceof ValidationError) {
return res.status(400).json({ errors: err.errors });
}
// Error generico
res.status(500).json({ error: 'Internal server error' });
};
4. Logging Middleware:
// middleware/logging.middleware.ts
export const requestLogger = (req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
console.log(`${req.method} ${req.url} ${res.statusCode} - ${duration}ms`);
});
next();
};
5.2 Aplicabilidad a ERP Generico
⭐⭐⭐⭐⭐ (MAXIMA)
Decision: ✅ ADOPTAR COMPLETAMENTE
Middleware criticos para ERP:
- Authentication (JWT con multi-tenancy)
- Authorization (permisos por rol)
- Validation (DTOs con Zod)
- Error handling (global)
- Logging (auditoria de requests)
- Rate limiting (proteccion DDoS)
6. ERROR HANDLING
6.1 Jerarquia de Errores Personalizados
// shared/errors/base.error.ts
export class AppError extends Error {
constructor(
public statusCode: number,
public message: string,
public isOperational = true
) {
super(message);
Error.captureStackTrace(this, this.constructor);
}
}
// Errores especificos
export class UnauthorizedError extends AppError {
constructor(message = 'Unauthorized') {
super(401, message);
}
}
export class NotFoundError extends AppError {
constructor(resource: string) {
super(404, `${resource} not found`);
}
}
export class ValidationError extends AppError {
constructor(public errors: any[]) {
super(400, 'Validation failed');
}
}
export class ForbiddenError extends AppError {
constructor(message = 'Forbidden') {
super(403, message);
}
}
export class ConflictError extends AppError {
constructor(message: string) {
super(409, message);
}
}
6.2 Uso en Servicios
// modules/auth/services/auth.service.ts
export class AuthService {
async findUserById(id: string): Promise<UserEntity> {
const user = await this.userRepository.findById(id);
if (!user) {
throw new NotFoundError('User');
}
return user;
}
async updateUser(id: string, dto: UpdateUserDto): Promise<UserEntity> {
// Verificar si email ya existe
const existing = await this.userRepository.findByEmail(dto.email);
if (existing && existing.id !== id) {
throw new ConflictError('Email already in use');
}
return await this.userRepository.update(id, dto);
}
}
6.3 Aplicabilidad a ERP Generico
⭐⭐⭐⭐⭐ (MAXIMA)
Decision: ✅ ADOPTAR COMPLETAMENTE
7. DATABASE PATTERNS
7.1 Connection Pool (Singleton)
// database/pool.ts
import { Pool } from 'pg';
import { DB_CONFIG } from '@config/database.config';
let pool: Pool | null = null;
export function getPool(): Pool {
if (!pool) {
pool = new Pool({
host: DB_CONFIG.host,
port: DB_CONFIG.port,
database: DB_CONFIG.database,
user: DB_CONFIG.user,
password: DB_CONFIG.password,
max: 20, // Maximo 20 conexiones
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000,
});
}
return pool;
}
export const pool = getPool();
7.2 Uso de Constants para Queries
import { pool } from '@database/pool';
import { DB_SCHEMAS, DB_TABLES, getFullTableName } from '@shared/constants';
export class UserRepository {
private readonly TABLE = getFullTableName(
DB_SCHEMAS.AUTH,
DB_TABLES.AUTH.USERS
);
async findById(id: string): Promise<UserEntity | null> {
const result = await pool.query(
`SELECT * FROM ${this.TABLE} WHERE id = $1`,
[id]
);
return result.rows[0] || null;
}
async create(user: CreateUserDto): Promise<UserEntity> {
const result = await pool.query(
`INSERT INTO ${this.TABLE} (email, password_hash, tenant_id)
VALUES ($1, $2, $3)
RETURNING *`,
[user.email, user.passwordHash, user.tenantId]
);
return result.rows[0];
}
}
7.3 Transacciones
export class OrderService {
async createOrderWithItems(dto: CreateOrderDto): Promise<Order> {
const client = await pool.connect();
try {
await client.query('BEGIN');
// 1. Crear orden
const order = await this.createOrder(client, dto);
// 2. Crear items
await this.createOrderItems(client, order.id, dto.items);
// 3. Actualizar inventario
await this.updateInventory(client, dto.items);
await client.query('COMMIT');
return order;
} catch (error) {
await client.query('ROLLBACK');
throw error;
} finally {
client.release();
}
}
}
7.4 Critica: Sin ORM
Observacion: GAMILIT usa node-postgres (pg) directamente, sin ORM.
Ventajas:
- ✅ Control total sobre queries
- ✅ Performance optimo
- ✅ Queries SQL explicitas
Desventajas:
- ❌ Sin type safety en queries
- ❌ Mapeo manual de resultados
- ❌ Migrations manuales
- ❌ Propenso a SQL injection si no se usan placeholders
Recomendacion para ERP Generico:
⭐⭐⭐⭐ (ALTA)
Decision: 🔧 CONSIDERAR TypeORM o Prisma
Justificacion:
- Type safety completo
- Migrations automaticas
- Query builder type-safe
- Reduccion de codigo boilerplate
8. TESTING PATTERNS
8.1 Metricas de Testing (GAP CRITICO)
| Metrica | Actual | Objetivo | Gap |
|---|---|---|---|
| Tests Backend | 40 | 210 | -170 (81%) |
| Coverage | 15% | 70% | -55pp |
Critica: Coverage extremadamente bajo. NO copiar este anti-patron.
8.2 Ejemplos de Tests (los pocos que existen)
Test de Servicio:
// modules/auth/__tests__/auth.service.test.ts
describe('AuthService', () => {
let authService: AuthService;
beforeEach(() => {
authService = new AuthService();
});
describe('login', () => {
it('should return token for valid credentials', async () => {
const dto = { email: 'test@example.com', password: 'password123' };
const result = await authService.login(dto);
expect(result).toHaveProperty('token');
expect(result).toHaveProperty('user');
});
it('should throw UnauthorizedError for invalid password', async () => {
const dto = { email: 'test@example.com', password: 'wrong' };
await expect(authService.login(dto)).rejects.toThrow(UnauthorizedError);
});
});
});
8.3 Recomendacion para ERP Generico
⭐⭐⭐⭐⭐ (MAXIMA - CRITICO)
Decision: ✅ IMPLEMENTAR TESTING DESDE EL INICIO
Objetivos:
- Coverage: 70%+ desde el inicio
- TDD: Test-Driven Development
- Tests por capa: Unit, Integration, E2E
- CI/CD: Tests automaticos en pipeline
Herramientas:
- Jest para unit tests
- Supertest para integration tests
- Test containers para tests con DB
9. MATRIZ DE DECISION: ADOPTAR / ADAPTAR / EVITAR
9.1 ADOPTAR COMPLETAMENTE ✅
| Patron | Descripcion | Justificacion | Prioridad |
|---|---|---|---|
| Estructura modular | 11 modulos funcionales independientes | Organizacion clara, escalable | P0 |
| Patron de modulo | entities, dtos, services, controllers, routes | Consistencia en toda la aplicacion | P0 |
| Path aliases | @shared, @modules, @config, etc. | Imports limpios y mantenibles | P0 |
| Middleware patterns | auth, validation, error, logging | Separacion de responsabilidades | P0 |
| Error handling | Jerarquia de errores personalizados | Manejo consistente de errores | P0 |
| Connection pool | Singleton pool de conexiones PostgreSQL | Performance y gestion de conexiones | P0 |
| Constants SSOT | Backend como fuente de verdad | Eliminacion de hardcoding | P0 |
9.2 ADAPTAR / MEJORAR 🔧
| Patron | Estado Actual | Mejora Propuesta | Prioridad |
|---|---|---|---|
| Database access | node-postgres directo | TypeORM o Prisma (type safety) | P1 |
| Testing | 15% coverage, 40 tests | 70%+ coverage, TDD | P0 CRITICO |
| Validation | Validacion manual | Zod o class-validator | P1 |
| Documentation | Comentarios en codigo | OpenAPI/Swagger specs | P1 |
9.3 EVITAR ❌
| Patron | Razon | Alternativa |
|---|---|---|
| Coverage bajo | 15% es inaceptable | 70%+ coverage desde el inicio |
| Sin ORM | Propenso a errores, sin type safety | TypeORM o Prisma |
| Validacion manual | Inconsistente, propenso a errores | Zod o class-validator |
10. PROPUESTA DE MODULOS PARA ERP GENERICO
Basado en el analisis de GAMILIT, se propone:
backend/src/modules/
├── core/ # Sistema core
│ ├── companies/ # Empresas (multi-tenant)
│ ├── users/ # Usuarios del sistema
│ ├── roles/ # Roles RBAC
│ └── currencies/ # Monedas
│
├── accounting/ # Contabilidad
│ ├── accounts/ # Catalogo de cuentas
│ ├── entries/ # Asientos contables
│ └── reports/ # Reportes financieros
│
├── budgets/ # Presupuestos
│ ├── budgets/ # Presupuestos maestros
│ ├── items/ # Partidas presupuestarias
│ └── tracking/ # Seguimiento de ejecucion
│
├── purchasing/ # Compras
│ ├── suppliers/ # Proveedores
│ ├── orders/ # Ordenes de compra
│ └── invoices/ # Facturas
│
├── inventory/ # Inventario
│ ├── products/ # Productos/Materiales
│ ├── warehouses/ # Almacenes
│ └── movements/ # Movimientos
│
├── projects/ # Proyectos
│ ├── projects/ # Proyectos/Obras
│ ├── phases/ # Fases de proyecto
│ └── team/ # Equipo del proyecto
│
├── hr/ # RRHH
│ ├── employees/ # Empleados
│ ├── payrolls/ # Nominas
│ └── attendance/ # Asistencia
│
├── reports/ # Reportes y Analytics
│ ├── financial/ # Reportes financieros
│ ├── operational/ # Reportes operacionales
│ └── dashboards/ # Dashboards
│
├── notifications/ # Notificaciones
│ └── multi-channel/ # Multi-canal (email, SMS, push)
│
└── admin/ # Administracion
├── audit/ # Auditoria
├── settings/ # Configuracion
└── bulk-ops/ # Operaciones bulk
Total modulos propuestos: 10 modulos
11. CONCLUSION Y RECOMENDACIONES
11.1 Hallazgos Clave
-
Estructura modular excelente: ⭐⭐⭐⭐⭐
- 11 modulos bien organizados
- Patron consistente por modulo
- Facil navegacion y mantenimiento
-
Path aliases son criticos: ⭐⭐⭐⭐⭐
- Imports limpios y semanticos
- Facil refactoring
-
Middleware patterns bien implementados: ⭐⭐⭐⭐⭐
- Auth, validation, error, logging
- Separacion de responsabilidades
-
Testing es GAP CRITICO: ❌❌❌
- 15% coverage es inaceptable
- Solo 40 tests para 45,000 LOC
- NO copiar este anti-patron
11.2 Recomendaciones Finales
ADOPTAR COMPLETAMENTE ✅ (Prioridad P0)
- Estructura modular (10 modulos para ERP)
- Patron de modulo (entities, dtos, services, controllers)
- Path aliases (@shared, @modules, @config)
- Middleware patterns (auth, validation, error)
- Error handling con jerarquia de errores
- Connection pool singleton
- Constants SSOT (Backend como fuente de verdad)
MEJORAR RESPECTO A GAMILIT 🔧 (Prioridad P0-P1)
- Testing: 70%+ coverage desde el inicio (P0 CRITICO)
- ORM: Usar TypeORM o Prisma (P1)
- Validation: Zod o class-validator (P1)
- Documentation: OpenAPI/Swagger (P1)
- DevOps: Docker, CI/CD completo (P0)
EVITAR ❌
- Coverage bajo (15%)
- Sin ORM (propenso a errores)
- Validacion manual inconsistente
Documento creado: 2025-11-23
Ultima actualizacion: 2025-11-23
Version: 1.0
Estado: Completado
Proximo documento: frontend-patterns.md