# 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`: ```typescript 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`: ```typescript 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`: ```typescript 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 { // 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 { 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`: ```typescript 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 ```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):** ```typescript 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):** ```typescript 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 1. **Legibilidad:** Imports semanticos y claros 2. **Mantenibilidad:** Facil refactoring de estructura 3. **Prevencion de errores:** No mas `../../../` incorrectos 4. **IDE Support:** Autocompletado mejorado 5. **Consistencia:** Mismo patron en todo el proyecto ### 4.4 Aplicabilidad a ERP Generico ⭐⭐⭐⭐⭐ (MAXIMA) **Decision:** ✅ **ADOPTAR COMPLETAMENTE** **Aliases propuestos para ERP:** ```json { "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:** ```typescript // 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:** ```typescript // 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:** ```typescript // 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:** ```typescript // 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 ```typescript // 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 ```typescript // modules/auth/services/auth.service.ts export class AuthService { async findUserById(id: string): Promise { const user = await this.userRepository.findById(id); if (!user) { throw new NotFoundError('User'); } return user; } async updateUser(id: string, dto: UpdateUserDto): Promise { // 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) ```typescript // 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 ```typescript 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 { const result = await pool.query( `SELECT * FROM ${this.TABLE} WHERE id = $1`, [id] ); return result.rows[0] || null; } async create(user: CreateUserDto): Promise { 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 ```typescript export class OrderService { async createOrderWithItems(dto: CreateOrderDto): Promise { 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:** ```typescript // 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 1. **Estructura modular excelente:** ⭐⭐⭐⭐⭐ - 11 modulos bien organizados - Patron consistente por modulo - Facil navegacion y mantenimiento 2. **Path aliases son criticos:** ⭐⭐⭐⭐⭐ - Imports limpios y semanticos - Facil refactoring 3. **Middleware patterns bien implementados:** ⭐⭐⭐⭐⭐ - Auth, validation, error, logging - Separacion de responsabilidades 4. **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) 1. Estructura modular (10 modulos para ERP) 2. Patron de modulo (entities, dtos, services, controllers) 3. Path aliases (@shared, @modules, @config) 4. Middleware patterns (auth, validation, error) 5. Error handling con jerarquia de errores 6. Connection pool singleton 7. Constants SSOT (Backend como fuente de verdad) #### MEJORAR RESPECTO A GAMILIT 🔧 (Prioridad P0-P1) 1. **Testing:** 70%+ coverage desde el inicio (P0 CRITICO) 2. **ORM:** Usar TypeORM o Prisma (P1) 3. **Validation:** Zod o class-validator (P1) 4. **Documentation:** OpenAPI/Swagger (P1) 5. **DevOps:** Docker, CI/CD completo (P0) #### EVITAR ❌ 1. Coverage bajo (15%) 2. Sin ORM (propenso a errores) 3. Validacion manual inconsistente --- **Documento creado:** 2025-11-23 **Ultima actualizacion:** 2025-11-23 **Version:** 1.0 **Estado:** Completado **Proximo documento:** `frontend-patterns.md`