NestJS Architect — Arquitectura y Scaffolding
Define, evalúa y valida la arquitectura de proyectos NestJS. Asegura un diseño modular robusto, desacoplado, que cumpla con Clean Architecture y DDD.
Lectura previa obligatoria
- Estructura de carpetas del proyecto (
src/, modules/, infraestructure/, common/)
package.json — dependencias (TypeORM, X-Road, etc.)
- Módulos existentes como referencia de patrones
Cuándo usar esta skill
- "creá un módulo nuevo"
- "diseñá la estructura de X feature"
- "evaluá si esta arquitectura está bien"
- "organizá las capas de este módulo"
- "planificá la integración con X-Road"
- Antes de crear un módulo nuevo o reorganizar uno existente
Cuándo NO usar esta skill
- Añadir un método o parámetro a un servicio existente → Fast-Path: implementar directo con
nestjs-developer sin redactar un nuevo plan arquitectónico.
- Implementar controladores/servicios →
nestjs-developer
- Escribir tests →
nestjs-unit-tester
- Fix de un bug concreto → buscar la causa directamente
Metodología
Paso 1 — Entender el contexto
- ¿Qué dominio de negocio cubre el módulo?
- ¿Qué entidades involucra?
- ¿Qué casos de uso necesita?
- ¿Requiere publicación X-Road?
Paso 2 — Definir la estructura de capas
La estructura del código se organiza bajo una división estricta entre infraestructura global, elementos comunes, y módulos de negocio modularizados:
src/infraestructure/: implementaciones de detalles técnicos compartidos (base de datos, almacenamiento, monitoreo).
src/common/: decoradores, filtros de excepción, interceptores, pipes, utilitarios y definiciones de error comunes.
src/modules/<feature>/: cada módulo representa un dominio de negocio auto-contenido:
<feature>.module.ts — módulo NestJS (importaciones, controladores, providers)
presentation/ — controllers, dtos, mappers
domain/ — interfaces de servicio (abstractas), interfaces de entidades
data/ — interfaces de repositorio (abstractas), implementaciones de persistencia
Paso 3 — Definir inyección de dependencias
- Desacoplamiento estricto: las capas superiores NUNCA dependen de implementaciones concretas
- Tokens: usar clases abstractas como
abstract class IDemandService (TypeScript no conserva interfaces en runtime)
- Registro en módulo:
@Module({
providers: [
{ provide: IDemandService, useClass: DemandService },
{ provide: IDemandRepository, useClass: DemandRepository },
],
controllers: [DemandController],
})
export class FeatureModule {}
Paso 3b — Manejo de Transacciones y Persistencia (Unit of Work)
Para casos de uso que requieren atomicidad sobre la base de datos (múltiples repositorios, persistencia coordinada o compensaciones):
- Contrato de Unit of Work en Dominio:
// domain/services/i-unit-of-work.service.ts
export abstract class IUnitOfWork {
abstract runInTransaction<T>(work: () => Promise<T>): Promise<T>;
}
- Implementación con TypeORM QueryRunner en Data/Infra:
// data/repositories/typeorm-unit-of-work.ts
import { Injectable } from '@nestjs/common';
import { DataSource } from 'typeorm';
import { IUnitOfWork } from '../../domain/services/i-unit-of-work.service';
@Injectable()
export class TypeOrmUnitOfWork implements IUnitOfWork {
constructor(private readonly dataSource: DataSource) {}
async runInTransaction<T>(work: () => Promise<T>): Promise<T> {
const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();
try {
const result = await work();
await queryRunner.commitTransaction();
return result;
} catch (error) {
await queryRunner.rollbackTransaction();
throw error;
} finally {
await queryRunner.release();
}
}
}
Paso 4 — Generar los archivos (scaffolding automatizado)
Ejecutar el script de scaffolding para crear la estructura de capas estandarizada con un solo comando:
bash scripts/scaffold_module.sh <nombre-modulo>
# Ejemplo: bash scripts/scaffold_module.sh payment-requests
Orden de generación respetado por el script para evitar dependencias circulares:
- Interfaz de entidad →
domain/interfaces/<singular>.interface.ts
- Contrato de servicio →
domain/services/i-<singular>.service.ts
- Contrato de repositorio →
data/repositories/i-<singular>.repository.ts
- Módulo NestJS →
<plural>.module.ts
Tras generar el scaffolding, verificar inmediatamente la ausencia de dependencias circulares:
npx madge --circular src/modules/
ℹ️ Degradación Elegante (Fallback si madge no está disponible):
Si npx madge no puede ejecutarse en el entorno, verificar manualmente la regla de capas: confirmar que domain/ no importe nada de presentation/ ni de data/, y que no existan dependencias circulares entre los *.module.ts.
Paso 5 — Entregar el diseño técnico (.agents/plans/.md)
Protocolo de Entrega Direct-to-Disk OBLIGATORIO
El entregable arquitectónico completo NUNCA se responde ni se vuelca en el hilo de chat. Debe persistirse directamente en disco utilizando la plantilla oficial:
Plantilla oficial: Utilizar la estructura definida en templates/backend-architecture-plan.template.md.
Destino del entregable: Escribir el documento de diseño arquitectónico completo en .agents/plans/<nombre>.md (crear la carpeta .agents/plans/ si no existe).
<nombre> debe ser el nombre del módulo o feature en formato kebab-case (ej. .agents/plans/solicitudes-pago.md, .agents/plans/demand-requests.md).
Prohibido volcar el diseño en el chat: No imprimir el documento técnico completo, interfaces detalladas, contratos exhaustivos ni especificaciones largas en la respuesta de la conversación. Esto previene la saturación de tokens y preserva el contexto del asistente.
Contenido obligatorio del archivo .agents/plans/<nombre>.md:
- Objetivo y Contexto de Negocio: dominio cubierto, entidades clave y casos de uso principales.
- Estructura de Carpetas y Capas: detalle de archivos a crear en
presentation/, domain/, data/ y infraestructure/.
- Inyección de Dependencias y Tokens: clases abstractas (
abstract class I...Service, abstract class I...Repository), registro de providers y desacoplamiento estricto.
- Contratos de Dominio y Datos: signaturas de métodos, DTOs con validación (
class-validator), mappers estáticos y manejo de retorno tipado con Result<T, E>.
- Persistencia, Transacciones y Unit of Work: entidades TypeORM, tablas/relaciones, migraciones y estrategia transaccional (
QueryRunner).
- Oportunidades de Mejora y Gaps Detectados: análisis proactivo de endpoints CRUD omitidos, validaciones de seguridad/roles, índices de BD o casos de error no contemplados.
- Preguntas de Negocio: dudas funcionales, reglas de negocio o decisiones de alcance que requieren validación explícita del usuario.
Respuesta en el hilo de chat (Reporte Sintético):
En la conversación de chat, el agente únicamente debe responder con un reporte sintético conciso:
- Ruta del entregable: enlace/ruta al archivo generado (
.agents/plans/<nombre>.md).
- Resumen ejecutivo: síntesis breve (1-2 párrafos) del diseño del módulo y la estrategia de capas adoptada.
- Archivos creados (scaffolding): si se ejecutó el Paso 4 generando interfaces/contratos base, listar las rutas relativas generadas en disco.
- Preguntas de Negocio y Gaps: lista de preguntas o puntos de decisión críticos para el usuario antes de proceder a la implementación.
- Siguiente paso recomendado: sugerir invocar nestjs-developer para implementar controladores, servicios, DTOs y mappers una vez aprobado el plan.
Reglas de lo que SÍ debe hacer
- Escribir obligatoriamente el entregable de diseño/arquitectura en
.agents/plans/<nombre>.md (write_to_file)
- Reportar en el chat únicamente el resumen sintético, ruta del archivo y preguntas de negocio / gaps
- Separar estrictamente las capas (presentation, domain, data)
- Usar clases abstractas como tokens de inyección
- Registrar implementaciones concretas en el módulo
- Seguir el orden de scaffolding (interfaces antes que implementaciones)
- Verificar que no haya dependencias circulares ejecutando
npx madge --circular src/modules/
Reglas de lo que NO debe hacer
- NO volcar el diseño arquitectónico completo ni especificaciones extensas en la respuesta del chat
- NO omitir la persistencia del entregable en
.agents/plans/<nombre>.md
- NO poner lógica de negocio en controladores
- NO importar implementaciones concretas de repositorios en servicios
- NO usar interfaces como tokens de DI (usar clases abstractas)
- NO crear módulos sin declarar dependencias explícitamente
- NO saltarse el orden de generación de archivos
Verificación
El diseño técnico responde todas estas preguntas:
- ¿Se escribió el archivo en
.agents/plans/<nombre>.md siguiendo el template oficial?
- ¿El chat contiene solo el reporte sintético con preguntas de negocio y gaps?
- ¿Se respetan las 3 capas estrictas (presentation, domain, data)?
- ¿Se usan clases abstractas para los tokens de inyección?
- ¿Están identificadas las entidades, servicios y repositorios?
- ¿Se contempló la integración con infraestructura (TypeORM, transacciones, X-Road)?
- ¿Se verificó la ausencia de dependencias circulares con
npx madge --circular?
Al terminar
Confirmar que el diseño arquitectónico quedó guardado en .agents/plans/<nombre>.md. Reportar en el chat el resumen sintético y las preguntas de negocio pendientes de validación. Tras la aprobación humana, sugerir al usuario: nestjs-developer para implementar controladores, servicios, DTOs y mappers del módulo creado.
1---2name: nestjs-architect3description: Define y evalúa la arquitectura del proyecto NestJS. Estructuración modular, separación de conceptos en presentación/dominio/datos (Clean Architecture / DDD) e integración de infraestructura técnica de manera desacoplada. Escribe su entregable en .agents/plans/<nombre>.md en lugar de responder en el hilo de chat.4---56# NestJS Architect — Arquitectura y Scaffolding78Define, evalúa y valida la arquitectura de proyectos NestJS. Asegura un diseño modular robusto, desacoplado, que cumpla con Clean Architecture y DDD.910## Lectura previa obligatoria1112- Estructura de carpetas del proyecto (`src/`, `modules/`, `infraestructure/`, `common/`)13- `package.json` — dependencias (TypeORM, X-Road, etc.)14- Módulos existentes como referencia de patrones1516## Cuándo usar esta skill1718- "creá un módulo nuevo"19- "diseñá la estructura de X feature"20- "evaluá si esta arquitectura está bien"21- "organizá las capas de este módulo"22- "planificá la integración con X-Road"23- Antes de crear un módulo nuevo o reorganizar uno existente2425## Cuándo NO usar esta skill2627- **Añadir un método o parámetro a un servicio existente** → Fast-Path: implementar directo con `nestjs-developer` sin redactar un nuevo plan arquitectónico.28- **Implementar controladores/servicios** → `nestjs-developer`29- **Escribir tests** → `nestjs-unit-tester`30- **Fix de un bug concreto** → buscar la causa directamente3132---3334## Metodología3536### Paso 1 — Entender el contexto3738- ¿Qué dominio de negocio cubre el módulo?39- ¿Qué entidades involucra?40- ¿Qué casos de uso necesita?41- ¿Requiere publicación X-Road?4243### Paso 2 — Definir la estructura de capas4445La estructura del código se organiza bajo una división estricta entre **infraestructura global**, **elementos comunes**, y **módulos de negocio modularizados**:46471. **`src/infraestructure/`**: implementaciones de detalles técnicos compartidos (base de datos, almacenamiento, monitoreo).482. **`src/common/`**: decoradores, filtros de excepción, interceptores, pipes, utilitarios y definiciones de error comunes.493. **`src/modules/<feature>/`**: cada módulo representa un dominio de negocio auto-contenido:50 - `<feature>.module.ts` — módulo NestJS (importaciones, controladores, providers)51 - `presentation/` — controllers, dtos, mappers52 - `domain/` — interfaces de servicio (abstractas), interfaces de entidades53 - `data/` — interfaces de repositorio (abstractas), implementaciones de persistencia5455### Paso 3 — Definir inyección de dependencias5657- **Desacoplamiento estricto**: las capas superiores NUNCA dependen de implementaciones concretas58- **Tokens**: usar clases abstractas como `abstract class IDemandService` (TypeScript no conserva interfaces en runtime)59- **Registro en módulo**:60 ```typescript61 @Module({62 providers: [63 { provide: IDemandService, useClass: DemandService },64 { provide: IDemandRepository, useClass: DemandRepository },65 ],66 controllers: [DemandController],67 })68 export class FeatureModule {}69 ```7071### Paso 3b — Manejo de Transacciones y Persistencia (Unit of Work)7273Para casos de uso que requieren atomicidad sobre la base de datos (múltiples repositorios, persistencia coordinada o compensaciones):74- **Contrato de Unit of Work en Dominio**:75 ```typescript76 // domain/services/i-unit-of-work.service.ts77 export abstract class IUnitOfWork {78 abstract runInTransaction<T>(work: () => Promise<T>): Promise<T>;79 }80 ```81- **Implementación con TypeORM QueryRunner en Data/Infra**:82 ```typescript83 // data/repositories/typeorm-unit-of-work.ts84 import { Injectable } from '@nestjs/common';85 import { DataSource } from 'typeorm';86 import { IUnitOfWork } from '../../domain/services/i-unit-of-work.service';8788 @Injectable()89 export class TypeOrmUnitOfWork implements IUnitOfWork {90 constructor(private readonly dataSource: DataSource) {}9192 async runInTransaction<T>(work: () => Promise<T>): Promise<T> {93 const queryRunner = this.dataSource.createQueryRunner();94 await queryRunner.connect();95 await queryRunner.startTransaction();96 try {97 const result = await work();98 await queryRunner.commitTransaction();99 return result;100 } catch (error) {101 await queryRunner.rollbackTransaction();102 throw error;103 } finally {104 await queryRunner.release();105 }106 }107 }108 ```109110### Paso 4 — Generar los archivos (scaffolding automatizado)111112Ejecutar el script de scaffolding para crear la estructura de capas estandarizada con un solo comando:113```bash114bash scripts/scaffold_module.sh <nombre-modulo>115# Ejemplo: bash scripts/scaffold_module.sh payment-requests116```117118Orden de generación respetado por el script para evitar dependencias circulares:1191. **Interfaz de entidad** → `domain/interfaces/<singular>.interface.ts`1202. **Contrato de servicio** → `domain/services/i-<singular>.service.ts`1213. **Contrato de repositorio** → `data/repositories/i-<singular>.repository.ts`1224. **Módulo NestJS** → `<plural>.module.ts`123124Tras generar el scaffolding, verificar inmediatamente la ausencia de dependencias circulares:125```bash126npx madge --circular src/modules/127```128> ℹ️ **Degradación Elegante (Fallback si madge no está disponible)**: 129> Si `npx madge` no puede ejecutarse en el entorno, verificar manualmente la regla de capas: confirmar que `domain/` no importe nada de `presentation/` ni de `data/`, y que no existan dependencias circulares entre los `*.module.ts`.130131### Paso 5 — Entregar el diseño técnico (.agents/plans/<nombre>.md)132133#### Protocolo de Entrega Direct-to-Disk OBLIGATORIO134135El entregable arquitectónico completo **NUNCA se responde ni se vuelca en el hilo de chat**. Debe persistirse directamente en disco utilizando la plantilla oficial:1361371. **Plantilla oficial**: Utilizar la estructura definida en [`templates/backend-architecture-plan.template.md`](./templates/backend-architecture-plan.template.md).1382. **Destino del entregable**: Escribir el documento de diseño arquitectónico completo en `.agents/plans/<nombre>.md` (crear la carpeta `.agents/plans/` si no existe).139 - `<nombre>` debe ser el nombre del módulo o feature en formato `kebab-case` (ej. `.agents/plans/solicitudes-pago.md`, `.agents/plans/demand-requests.md`).1403. **Prohibido volcar el diseño en el chat**: No imprimir el documento técnico completo, interfaces detalladas, contratos exhaustivos ni especificaciones largas en la respuesta de la conversación. Esto previene la saturación de tokens y preserva el contexto del asistente.1414. **Contenido obligatorio del archivo `.agents/plans/<nombre>.md`**:142 - **Objetivo y Contexto de Negocio**: dominio cubierto, entidades clave y casos de uso principales.143 - **Estructura de Carpetas y Capas**: detalle de archivos a crear en `presentation/`, `domain/`, `data/` y `infraestructure/`.144 - **Inyección de Dependencias y Tokens**: clases abstractas (`abstract class I...Service`, `abstract class I...Repository`), registro de providers y desacoplamiento estricto.145 - **Contratos de Dominio y Datos**: signaturas de métodos, DTOs con validación (`class-validator`), mappers estáticos y manejo de retorno tipado con `Result<T, E>`.146 - **Persistencia, Transacciones y Unit of Work**: entidades TypeORM, tablas/relaciones, migraciones y estrategia transaccional (`QueryRunner`).147 - **Oportunidades de Mejora y Gaps Detectados**: análisis proactivo de endpoints CRUD omitidos, validaciones de seguridad/roles, índices de BD o casos de error no contemplados.148 - **Preguntas de Negocio**: dudas funcionales, reglas de negocio o decisiones de alcance que requieren validación explícita del usuario.1491505. **Respuesta en el hilo de chat (Reporte Sintético)**:151 En la conversación de chat, el agente **únicamente** debe responder con un reporte sintético conciso:152 - **Ruta del entregable**: enlace/ruta al archivo generado (`.agents/plans/<nombre>.md`).153 - **Resumen ejecutivo**: síntesis breve (1-2 párrafos) del diseño del módulo y la estrategia de capas adoptada.154 - **Archivos creados (scaffolding)**: si se ejecutó el Paso 4 generando interfaces/contratos base, listar las rutas relativas generadas en disco.155 - **Preguntas de Negocio y Gaps**: lista de preguntas o puntos de decisión críticos para el usuario antes de proceder a la implementación.156 - **Siguiente paso recomendado**: sugerir invocar **nestjs-developer** para implementar controladores, servicios, DTOs y mappers una vez aprobado el plan.157158---159160## Reglas de lo que SÍ debe hacer161162- Escribir obligatoriamente el entregable de diseño/arquitectura en `.agents/plans/<nombre>.md` (`write_to_file`)163- Reportar en el chat únicamente el resumen sintético, ruta del archivo y preguntas de negocio / gaps164- Separar estrictamente las capas (presentation, domain, data)165- Usar clases abstractas como tokens de inyección166- Registrar implementaciones concretas en el módulo167- Seguir el orden de scaffolding (interfaces antes que implementaciones)168- Verificar que no haya dependencias circulares ejecutando `npx madge --circular src/modules/`169170## Reglas de lo que NO debe hacer171172- NO volcar el diseño arquitectónico completo ni especificaciones extensas en la respuesta del chat173- NO omitir la persistencia del entregable en `.agents/plans/<nombre>.md`174- NO poner lógica de negocio en controladores175- NO importar implementaciones concretas de repositorios en servicios176- NO usar interfaces como tokens de DI (usar clases abstractas)177- NO crear módulos sin declarar dependencias explícitamente178- NO saltarse el orden de generación de archivos179180---181182## Verificación183184El diseño técnico responde todas estas preguntas:185186- ¿Se escribió el archivo en `.agents/plans/<nombre>.md` siguiendo el template oficial?187- ¿El chat contiene solo el reporte sintético con preguntas de negocio y gaps?188- ¿Se respetan las 3 capas estrictas (presentation, domain, data)?189- ¿Se usan clases abstractas para los tokens de inyección?190- ¿Están identificadas las entidades, servicios y repositorios?191- ¿Se contempló la integración con infraestructura (TypeORM, transacciones, X-Road)?192- ¿Se verificó la ausencia de dependencias circulares con `npx madge --circular`?193194## Al terminar195196Confirmar que el diseño arquitectónico quedó guardado en `.agents/plans/<nombre>.md`. Reportar en el chat el resumen sintético y las preguntas de negocio pendientes de validación. Tras la aprobación humana, sugerir al usuario: **nestjs-developer** para implementar controladores, servicios, DTOs y mappers del módulo creado.