Skip to main content

Módulos de feature

Cuándo usarlo: para toda área de feature nueva del backend. Preferilo siempre sobre agregar archivos al árbol plano controllers/v1 + services/v1.

Estructura

Copiá src/modules/health-center/, que es el ejemplo chico y limpio:

src/modules/<feature>/
├── controllers/ # extienden SecuredController
├── services/ # extienden Service, export default new X()
├── dtos/ # class-validator
├── entities/ # entidades TypeORM propias (si tiene)
├── module.config.ts # el manifiesto
├── module.ts # singleton con initialize() / getControllers() / getEntities() / getMetadata()
└── index.ts # barrel: re-exporta módulo, config, entities, dtos, services, controllers

module.config.ts — el manifiesto, sin lógica:

export const HEALTH_CENTER_MODULE_CONFIG: ModuleConfig = {
name: 'HealthCenterModule', version: '1.0.0', description: '…',
controllers: [HealthCenterController],
entities: [HealthCenter, HealthCenterServiceLine],
providers: [HealthCenterService, HealthCenterServiceLineService],
};

module.ts — un singleton estilo NestJS con getInstance(), un initialize() idempotente (avisa por logger.warn si ya estaba inicializado) y los getters que leen la config.

Enchufarlo a Express

// src/controllers/v1/ControllerImportsV1.ts
export const controllers = [
/* ...los de v1... */
...AppointmentsModule.getControllers(),
...HealthCenterModule.getControllers(),
];
Sin esto, las rutas no existen

Si el controller no está en esa lista —directo o vía módulo— la ruta no existe y no hay ningún error. Es el error más común al agregar un endpoint.

Los cuatro módulos que existen

rules-engine — motor de reglas por financiador

El módulo más grande: core/ (contratos), entities/ (11), services/ (22, más validators/ con 42 validadores, context/ y practice-sources/), controllers/ (6), dtos/, docs/.

Anticipa los débitos de PAMI antes de facturar. Ver Motor de reglas.

health-center — centros médicos

ABM de centros médicos y sus líneas de atención, más el vínculo con usuarios. Es la base del scoping por centro (Centro médico activo) y el molde canónico del patrón: chico y limpio, copiá este.

authorizations — autorizaciones por afiliado

AuthorizationAdapterRegistry + services/adapters/ con un adapter por origen de datos, y AuthorizationByAfiliadoController. No tiene entidades propias: reusa finances.Authorization. Ver Autorizaciones.

appointments — turnos

Módulo de agenda y turnos. Tiene alias de path propio: @appointments.

Gotchas

  • Las entidades del módulo las auto-descubre el glob de la conexión. Declararlas en entities[] es documentación / manifiesto, no el mecanismo de registro.
  • initialize() no crea tablas. El schema se aplica a mano: ver DDL y ops.
  • No importes cruzado entre módulos por ruta profunda: usá el barrel index.ts del otro módulo.
  • Los módulos se alcanzan con @modules/<feature>/.... Todo alias nuevo se declara en tres lugares (ver Arquitectura).