Saltar al contenido principal

Estructura backend - NestJS

Notas sobre la Estructura​

OrganizaciΓ³n Modular​

  • /common: Cross-cutting concerns que afectan toda la aplicaciΓ³n
  • /config: ConfiguraciΓ³n centralizada y validada
  • /core: Servicios fundamentales del sistema
  • /modules: LΓ³gica de negocio organizada por dominio
  • /infrastructure: Servicios tΓ©cnicos y de infraestructura
  • /shared: CΓ³digo compartido entre mΓ³dulos

MΓ³dulos de Dominio​

Cada mΓ³dulo sigue la estructura:

  • Controllers: Manejo de HTTP requests
  • Services: LΓ³gica de negocio
  • Repositories: Acceso a datos
  • Entities: Modelos de dominio
  • DTOs: ValidaciΓ³n de entrada/salida
  • Interfaces: Contratos y tipos
  • Events: Eventos del dominio (si aplica)

Principios SOLID​

  • Single Responsibility: Cada servicio tiene una responsabilidad clara
  • Open/Closed: Extensible mediante interfaces y herencia
  • Liskov Substitution: Uso de abstracciones (providers base)
  • Interface Segregation: Interfaces especΓ­ficas por contexto
  • Dependency Inversion: InyecciΓ³n de dependencias de NestJS

Testing​

  • Tests unitarios junto al cΓ³digo o en /test/unit
  • Tests de integraciΓ³n en /test/integration
  • Tests E2E en /test/e2e
  • Fixtures y utilidades compartidas

Repositorios​

  • AbstracciΓ³n del acceso a datos
  • Facilita migraciΓ³n futura de Firebase
  • Operaciones CRUD estandarizadas

Servicios​

  • LΓ³gica de negocio pura
  • Sin dependencias directas de HTTP
  • Testeable de forma aislada

Guards y Decoradores​

  • Reutilizables en toda la aplicaciΓ³n
  • SeparaciΓ³n de concerns de seguridad
  • Metadata-driven

ConfiguraciΓ³n​

  • Variables de entorno validadas
  • ConfiguraciΓ³n tipada
  • Separada por dominios

Esta estructura permite:

  • Escalabilidad horizontal y vertical
  • FΓ‘cil testing y mantenimiento
  • Onboarding rΓ‘pido de desarrolladores
  • MigraciΓ³n gradual de componentes
  • Cumplimiento de mejores prΓ‘cticas de NestJS
prompts-backend/
β”œβ”€β”€ .cursorrules # (Opcional - especΓ­fico para Cursor IDE)
β”œβ”€β”€ .env # Variables de entorno
β”œβ”€β”€ .env.example # Plantilla de variables de entorno
β”œβ”€β”€ .eslintrc.js # ConfiguraciΓ³n ESLint
β”œβ”€β”€ .gitignore # Archivos ignorados por Git
β”œβ”€β”€ .prettierrc # ConfiguraciΓ³n Prettier
β”œβ”€β”€ nest-cli.json # ConfiguraciΓ³n NestJS CLI
β”œβ”€β”€ package.json # Dependencias y scripts
β”œβ”€β”€ tsconfig.json # ConfiguraciΓ³n TypeScript
β”œβ”€β”€ tsconfig.build.json # ConfiguraciΓ³n TypeScript para build
β”œβ”€β”€ docker/
β”‚ β”œβ”€β”€ Dockerfile # Dockerfile para producciΓ³n
β”‚ β”œβ”€β”€ Dockerfile.dev # Dockerfile para desarrollo
β”‚ └── docker-compose.yml # ComposiciΓ³n de servicios
β”œβ”€β”€ src/
β”‚ β”œβ”€β”€ main.ts # Punto de entrada de la aplicaciΓ³n
β”‚ β”œβ”€β”€ app.module.ts # MΓ³dulo principal
β”‚ β”œβ”€β”€ common/ # Elementos comunes compartidos (cross-cutting concerns)
β”‚ β”‚ β”œβ”€β”€ constants/
β”‚ β”‚ β”‚ β”œβ”€β”€ api.constants.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ error-codes.constants.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ messages.constants.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ decorators/
β”‚ β”‚ β”‚ β”œβ”€β”€ api-key.decorator.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ current-user.decorator.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ rate-limit.decorator.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ roles.decorator.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ public.decorator.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ dto/
β”‚ β”‚ β”‚ β”œβ”€β”€ pagination.dto.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ response.dto.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ base-query.dto.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ exceptions/
β”‚ β”‚ β”‚ β”œβ”€β”€ business.exception.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ validation.exception.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ unauthorized.exception.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ not-found.exception.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ filters/
β”‚ β”‚ β”‚ β”œβ”€β”€ http-exception.filter.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ all-exceptions.filter.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ validation-exception.filter.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ guards/
β”‚ β”‚ β”‚ β”œβ”€β”€ jwt-auth.guard.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ api-key.guard.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ plan.guard.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ roles.guard.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ rate-limit.guard.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ interceptors/
β”‚ β”‚ β”‚ β”œβ”€β”€ logging.interceptor.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ transform.interceptor.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ timeout.interceptor.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ cache.interceptor.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ interfaces/
β”‚ β”‚ β”‚ β”œβ”€β”€ request.interface.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ response.interface.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ pagination.interface.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ middlewares/
β”‚ β”‚ β”‚ β”œβ”€β”€ logger.middleware.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ cors.middleware.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ security.middleware.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ pipes/
β”‚ β”‚ β”‚ β”œβ”€β”€ validation.pipe.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ parse-object-id.pipe.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ transform.pipe.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ types/
β”‚ β”‚ β”‚ β”œβ”€β”€ express.d.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ common.types.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ └── utils/
β”‚ β”‚ β”œβ”€β”€ pagination.util.ts
β”‚ β”‚ β”œβ”€β”€ response.util.ts
β”‚ β”‚ └── index.ts
β”‚ β”œβ”€β”€ config/ # ConfiguraciΓ³n modular
β”‚ β”‚ β”œβ”€β”€ config.module.ts
β”‚ β”‚ β”œβ”€β”€ configurations/
β”‚ β”‚ β”‚ β”œβ”€β”€ app.config.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ database.config.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ auth.config.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ redis.config.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ llm.config.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ storage.config.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ queue.config.ts
β”‚ β”‚ β”‚ └── monitoring.config.ts
β”‚ β”‚ β”œβ”€β”€ validation/
β”‚ β”‚ β”‚ β”œβ”€β”€ env.validation.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ └── index.ts
β”‚ β”œβ”€β”€ core/ # Funcionalidad central del sistema
β”‚ β”‚ β”œβ”€β”€ database/
β”‚ β”‚ β”‚ β”œβ”€β”€ database.module.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ database.service.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ logger/
β”‚ β”‚ β”‚ β”œβ”€β”€ logger.module.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ logger.service.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ cache/
β”‚ β”‚ β”‚ β”œβ”€β”€ cache.module.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ cache.service.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ └── health/
β”‚ β”‚ β”œβ”€β”€ health.module.ts
β”‚ β”‚ β”œβ”€β”€ health.controller.ts
β”‚ β”‚ └── index.ts
β”‚ β”œβ”€β”€ modules/ # MΓ³dulos de dominio de negocio
β”‚ β”‚ β”œβ”€β”€ auth/
β”‚ β”‚ β”‚ β”œβ”€β”€ auth.module.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ controllers/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ auth.controller.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ auth.controller.spec.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ auth.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ auth.service.spec.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ token.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ password.service.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ strategies/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ jwt.strategy.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ local.strategy.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ api-key.strategy.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ dto/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ login.dto.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ register.dto.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ reset-password.dto.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ change-password.dto.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ refresh-token.dto.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ entities/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ session.entity.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ interfaces/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ jwt-payload.interface.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ auth-response.interface.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ guards/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ local-auth.guard.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ users/
β”‚ β”‚ β”‚ β”œβ”€β”€ users.module.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ controllers/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ users.controller.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ profile.controller.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ users.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ profile.service.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ repositories/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ users.repository.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ entities/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ user.entity.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ profile.entity.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ dto/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ create-user.dto.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ update-user.dto.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ update-profile.dto.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ user-query.dto.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ interfaces/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ user.interface.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ prompts/
β”‚ β”‚ β”‚ β”œβ”€β”€ prompts.module.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ controllers/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompts.controller.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-templates.controller.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-execution.controller.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompts.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-optimization.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-validation.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-execution.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-templates.service.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ repositories/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompts.repository.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-templates.repository.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-history.repository.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ entities/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt.entity.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-template.entity.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-execution.entity.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ dto/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ create-prompt.dto.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ update-prompt.dto.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ execute-prompt.dto.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ optimize-prompt.dto.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-query.dto.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ interfaces/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt.interface.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ optimization.interface.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ events/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-created.event.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-executed.event.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ flows/
β”‚ β”‚ β”‚ β”œβ”€β”€ flows.module.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ controllers/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flows.controller.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flow-execution.controller.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flow-templates.controller.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flows.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flow-executor.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flow-validator.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ block-factory.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flow-engine.service.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ repositories/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flows.repository.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flow-executions.repository.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ entities/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flow.entity.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ block.entity.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ connection.entity.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flow-execution.entity.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ dto/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ create-flow.dto.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ update-flow.dto.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ execute-flow.dto.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flow-query.dto.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ block.dto.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ interfaces/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flow.interface.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ block.interface.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ execution-context.interface.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ blocks/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ base-block.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt-block.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ conditional-block.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ loop-block.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ input-block.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ output-block.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ credits/
β”‚ β”‚ β”‚ β”œβ”€β”€ credits.module.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ controllers/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ credits.controller.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ transactions.controller.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ credits.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ transaction.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ credit-calculator.service.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ repositories/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ credits.repository.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ transactions.repository.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ entities/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ credit-balance.entity.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ transaction.entity.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ dto/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ purchase-credits.dto.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ transfer-credits.dto.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ transaction-query.dto.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ interfaces/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ credit.interface.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ transaction.interface.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ api-keys/
β”‚ β”‚ β”‚ β”œβ”€β”€ api-keys.module.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ controllers/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ api-keys.controller.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ api-key-usage.controller.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ api-keys.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ api-key-validation.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ api-key-usage.service.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ repositories/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ api-keys.repository.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ api-key-usage.repository.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ entities/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ api-key.entity.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ api-key-usage.entity.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ dto/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ create-api-key.dto.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ update-api-key.dto.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ api-key-query.dto.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ interfaces/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ api-key.interface.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ llm/
β”‚ β”‚ β”‚ β”œβ”€β”€ llm.module.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ llm.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ llm-router.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ llm-health.service.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ providers/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ base-provider.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ openai.provider.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ google.provider.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ amazon.provider.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ azure.provider.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ adapters/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ vercel-sdk.adapter.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ response-normalizer.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ interfaces/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ provider.interface.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ llm-response.interface.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ multimodal/
β”‚ β”‚ β”‚ β”œβ”€β”€ multimodal.module.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ controllers/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ media.controller.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ media.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ file-processor.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ media-validator.service.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ processors/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ image.processor.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ audio.processor.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ document.processor.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ dto/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ upload-media.dto.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ interfaces/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ media.interface.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ subscriptions/
β”‚ β”‚ β”‚ β”œβ”€β”€ subscriptions.module.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ controllers/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ subscriptions.controller.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ plans.controller.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ subscriptions.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ plan-validator.service.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ billing.service.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ repositories/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ subscriptions.repository.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ plans.repository.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ entities/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ subscription.entity.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ plan.entity.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ dto/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ create-subscription.dto.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ update-subscription.dto.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ interfaces/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ subscription.interface.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ plan.interface.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ └── webhooks/
β”‚ β”‚ β”œβ”€β”€ webhooks.module.ts
β”‚ β”‚ β”œβ”€β”€ controllers/
β”‚ β”‚ β”‚ β”œβ”€β”€ stripe-webhook.controller.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”‚ β”œβ”€β”€ webhook-processor.service.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ └── index.ts
β”‚ β”œβ”€β”€ infrastructure/ # Servicios de infraestructura
β”‚ β”‚ β”œβ”€β”€ infrastructure.module.ts
β”‚ β”‚ β”œβ”€β”€ firebase/
β”‚ β”‚ β”‚ β”œβ”€β”€ firebase.module.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ firebase.service.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ firestore.service.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ firebase-auth.service.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ redis/
β”‚ β”‚ β”‚ β”œβ”€β”€ redis.module.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ redis.service.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ redis-cache.service.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ queue/
β”‚ β”‚ β”‚ β”œβ”€β”€ queue.module.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ queue.service.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ processors/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ base.processor.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ prompt.processor.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ flow.processor.ts
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ media.processor.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ storage/
β”‚ β”‚ β”‚ β”œβ”€β”€ storage.module.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ storage.service.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ providers/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ firebase-storage.provider.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ monitoring/
β”‚ β”‚ β”‚ β”œβ”€β”€ monitoring.module.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ monitoring.service.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ providers/
β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ new-relic.provider.ts
β”‚ β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ └── email/
β”‚ β”‚ β”œβ”€β”€ email.module.ts
β”‚ β”‚ β”œβ”€β”€ email.service.ts
β”‚ β”‚ β”œβ”€β”€ templates/
β”‚ β”‚ β”‚ β”œβ”€β”€ welcome.template.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ reset-password.template.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ └── index.ts
β”‚ β”œβ”€β”€ shared/ # Servicios y utilidades compartidas
β”‚ β”‚ β”œβ”€β”€ shared.module.ts
β”‚ β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”‚ β”œβ”€β”€ encryption.service.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ validation.service.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ transformation.service.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ β”œβ”€β”€ utils/
β”‚ β”‚ β”‚ β”œβ”€β”€ crypto.util.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ date.util.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ string.util.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ validation.util.ts
β”‚ β”‚ β”‚ └── index.ts
β”‚ β”‚ └── index.ts
β”‚ └── database/ # Capa de base de datos (si se migra de Firebase)
β”‚ β”œβ”€β”€ migrations/
β”‚ β”œβ”€β”€ seeds/
β”‚ └── schemas/
β”œβ”€β”€ test/ # Tests organizados por tipo
β”‚ β”œβ”€β”€ unit/
β”‚ β”‚ β”œβ”€β”€ services/
β”‚ β”‚ β”‚ β”œβ”€β”€ auth.service.spec.ts
β”‚ β”‚ β”‚ β”œβ”€β”€ prompts.service.spec.ts
β”‚ β”‚ β”‚ └── flows.service.spec.ts
β”‚ β”‚ β”œβ”€β”€ controllers/
β”‚ β”‚ β”‚ β”œβ”€β”€ auth.controller.spec.ts
β”‚ β”‚ β”‚ └── prompts.controller.spec.ts
β”‚ β”‚ └── utils/
β”‚ β”‚ └── crypto.util.spec.ts
β”‚ β”œβ”€β”€ integration/
β”‚ β”‚ β”œβ”€β”€ auth/
β”‚ β”‚ β”‚ └── auth.integration.spec.ts
β”‚ β”‚ β”œβ”€β”€ prompts/
β”‚ β”‚ β”‚ └── prompts.integration.spec.ts
β”‚ β”‚ └── flows/
β”‚ β”‚ └── flows.integration.spec.ts
β”‚ β”œβ”€β”€ e2e/
β”‚ β”‚ β”œβ”€β”€ app.e2e-spec.ts
β”‚ β”‚ β”œβ”€β”€ auth.e2e-spec.ts
β”‚ β”‚ └── prompts.e2e-spec.ts
β”‚ β”œβ”€β”€ fixtures/
β”‚ β”‚ β”œβ”€β”€ users.fixture.ts
β”‚ β”‚ β”œβ”€β”€ prompts.fixture.ts
β”‚ β”‚ └── flows.fixture.ts
β”‚ └── utils/
β”‚ β”œβ”€β”€ test-setup.ts
β”‚ └── test-helpers.ts
β”œβ”€β”€ scripts/ # Scripts de utilidad
β”‚ β”œβ”€β”€ seed.ts # Seed de base de datos
β”‚ β”œβ”€β”€ generate-api-docs.ts
β”‚ β”œβ”€β”€ check-env.ts
β”‚ └── migrate.ts
└── docs/ # DocumentaciΓ³n
β”œβ”€β”€ api/
β”‚ β”œβ”€β”€ swagger.yaml
β”‚ └── postman-collection.json
β”œβ”€β”€ architecture/
β”‚ β”œβ”€β”€ diagrams/
β”‚ └── decisions/
└── guides/
β”œβ”€β”€ development.md
└── deployment.md