Template NestJS
Propósito y Alcance
Este proyecto, es un Backend For Frontend (BFF) desarrollado con NestJS. Su propósito principal es servir como una capa de agregación y adaptación entre los servicios frontend y diversos servicios backend del sistema EMX_STPLANNG.
Problema que resuelve: Simplifica la comunicación para los clientes frontend al proporcionar una única interfaz que orquesta y consolida datos de múltiples microservicios backend. Esto reduce la complejidad en el lado del cliente y optimiza las peticiones de red.
Alcance del proyecto:
- Exposición de endpoints API RESTful para consumo de los frontends.
- Integración con servicios backend como
ehvypln-chain-management-be,ehvypln-journey, yehvypln-om-be. - Gestión de la lógica de presentación y agregación de datos.
- Procesamiento de mensajes de Kafka (ej. para alertas).
- Interacción con Google Cloud Firestore para almacenamiento de datos específicos (ej. alertas, mensajes de aeronaves).
- Autenticación y autorización de peticiones mediante Azure AD.
- Manejo de configuración por entorno.
- Observabilidad a través de OpenTelemetry.
Arquitectura
El proyecto sigue una arquitectura modular basada en el framework NestJS, implementando el patrón Backend For Frontend (BFF).
Componentes Principales:
- API Gateway (Cloud Endpoints): Gestiona la exposición pública de la API, autenticación, y otras políticas.
- Aplicación NestJS (ehvypln-bff):
- Controladores: Exponen los endpoints HTTP y manejan las solicitudes/respuestas.
- Servicios: Contienen la lógica de negocio, orquestación de llamadas a otros servicios, y procesamiento de datos.
- Módulos de Infraestructura:
- Kafka: Para consumir mensajes de tópicos específicos (ej. alertas).
- Firestore: Cliente para interactuar con la base de datos Firestore.
- HTTP Client (Axios): Para comunicarse con otros servicios REST.
- OpenTelemetry: Para tracing y métricas.
- Mongoose: Para interactuar con MongoDB (base de datos principal de la aplicación, inferido por
MONGO_CONNECTION_STRING).
Dependencias Externas (Servicios Backend):
Según catalog-info.yml, el BFF depende de:
api:ehvypln-chain-management-beapi:ehvypln-journeyapi:ehvypln-om-be
Flujo de Datos Típico:
- Un cliente frontend realiza una petición al endpoint expuesto por Google Cloud Endpoints.
- Cloud Endpoints valida la autenticación (ej. Azure AD token) y redirige la petición al servicio
ehvypln-bffen GKE. - Un controlador NestJS recibe la petición.
- El servicio correspondiente procesa la solicitud, posiblemente:
- Realizando llamadas HTTP a uno o más servicios backend.
- Consultando o guardando datos en Firestore.
- Consultando o guardando datos en MongoDB.
- El servicio consolida la respuesta y la devuelve al controlador.
- El controlador envía la respuesta HTTP al cliente.
Diagrama de Arquitectura:
Idealmente, aquí se enlazaría a un diagrama visual de la arquitectura.

Tecnologías y Dependencias
- Lenguaje: TypeScript
- Runtime: Node.js 18 (basado en
Dockerfileypackage.json) - Framework: NestJS (
@nestjs/core,@nestjs/common, etc.) - Gestor de Paquetes: npm
- Base de Datos (Principal): MongoDB (a través de Mongoose, según
.env.exampley dependencias) - Base de Datos (Secundaria/Almacenamiento específico): Google Cloud Firestore (
@google-cloud/firestore) - Mensajería Asíncrona: Apache Kafka (
kafkajs,@nestjs/microservices) - Cache: Redis (
cache-manager-redis-yet,@nestjs/cache-manager) - Cliente HTTP: Axios (
@nestjs/axios) - Autenticación: Azure AD (
passport-azure-ad,@nestjs/passport) - Documentación API: Swagger (
@nestjs/swagger) - Gestión de Configuración:
@nestjs/config,dotenv,envalid - Seguridad HTTP: Helmet
- Observabilidad: OpenTelemetry (
@opentelemetry/*) - Feature Flags: Unleash (
unleash-client) - Containerización: Docker
- Orquestación (Despliegue): Google Kubernetes Engine (GKE) mediante Helm (basado en
deploy/) - CI/CD: Jenkins (basado en
Jenkinsfile) - Testing: Jest, Supertest, ts-jest, Testcontainers
- Linting/Formatting: ESLint, Prettier
Configuración Local
Prerrequisitos
- Node.js v18.15.0 o superior
- npm (generalmente incluido con Node.js)
- NestJS CLI global:
npm i -g @nestjs/cli - Docker y Docker Compose
Pasos de Configuración
-
Clonar el repositorio: Sigue los siguientes pasos
-
Instalar dependencias del proyecto:
npm install -
Configurar variables de entorno locales: Copiar el archivo de ejemplo y, si es necesario, ajustar los valores para el entorno local.
cp .env.example ./environments/local.envValores importantes en
environments/local.envpara desarrollo local (los valores por defecto en.env.examplesuelen ser adecuados para el setup con Docker Compose):FIRESTORE_EMULATOR_HOST=[::1]:8200PROJECT_ID=dummy-project-idKAFKA_BROKER=localhost:9092MONGO_CONNECTION_STRING="mongodb://localhost"DB_HOST=127.0.0.1DB_USERNAME=adminDB_PASSWORD=1234DB_NAME=test# ... entre otros. -
Iniciar servicios dependientes (Kafka, Firestore Emulator, Redis, etc.): Desde la raíz del proyecto, ejecutar:
docker-compose up -dEsto levantará los servicios definidos en
docker-compose.yml. -
Ejecutar la aplicación en modo local con auto-recarga:
npm run start:localLa aplicación BFF estará disponible en
http://localhost:5000(o el puerto definido enprocess.env.PORT). El global prefix es/bff.
Despliegue
El despliegue de ehvypln-bff se realiza en Google Kubernetes Engine (GKE) y es gestionado por pipelines de Jenkins.
Pipeline de Jenkins
El Jenkinsfile utiliza la pipeline pipelineLatamEMX("gke-krane-nestjs") para orquestar el build y despliegue.
Configuración por Entorno
El proyecto utiliza Helm para los despliegues en Kubernetes. La configuración específica para cada entorno (dev, intg,
cert, prod) se encuentra en los archivos values.yaml.erb dentro de las carpetas deploy/helm/<entorno>/.
Estos archivos definen:
- Número de réplicas.
- Recursos (CPU, memoria).
- Variables de entorno específicas del ambiente.
- Configuración de Google Cloud Endpoints (nombre del servicio, imagen del ESPv2).
- Conexión a Cloud SQL Proxy (aunque la app usa Mongo, el template de deployment incluye CloudSQL Proxy).
- Si se usan nodos spot o GKE Autopilot Compute Class.
Proceso General de Despliegue
- Construcción de Imagen Docker: El pipeline de Jenkins construye la imagen Docker utilizando el
Dockerfiledel proyecto. - Publicación de Imagen: La imagen se etiqueta y se publica en un registro de contenedores (ej. Google Container Registry - GCR).
- Despliegue con Helm: Krane (herramienta interna) o Helm directamente utiliza las plantillas de Helm (ubicadas
en
deploy/helm/emx-helm-chart/- inferido) y el archivovalues.yaml.erbdel entorno destino para generar los manifiestos de Kubernetes. - Aplicación en GKE: Los manifiestos se aplican al clúster de GKE correspondiente.
- Configuración de Cloud Endpoints: El servicio de Google Cloud Endpoints se configura utilizando la definición
OpenAPI en
deploy/endpoints/openapi.yaml.erbpara exponer la API.
Endpoints de la API
La API se expone con un prefijo global /bff. La documentación Swagger UI está disponible en la ruta
/bff/api/description (relativa al host del servicio desplegado).
| Método | Ruta (después de /bff) | Descripción | Autenticación Sugerida |
|---|---|---|---|
| GET | /api/healthz | Endpoint de chequeo de salud de la aplicación. | Ninguna o API Key |
| GET | /crf/bff/get/{id} | Busca una "chain" (cadena) basada en el ID proporcionado. | Azure AD Token |
| GET | /test | Endpoint de prueba sin parámetros. | Azure AD Token |
| GET | /test/{id} | Endpoint de prueba que recibe un ID. | Azure AD Token |
Autenticación
El servicio soporta varios mecanismos de autenticación definidos en deploy/endpoints/openapi.yaml.erb y gestionados
por Google Cloud Endpoints:
- API Key (
api_key): Para identificación del proyecto llamante. - Google ID Token (
google_id_token): Para usuarios autenticados con cuentas Google. - Service Account JWT (
serviceaccount_jwt): Para autenticación entre servicios. - Azure AD Token (
azure_id_token): Mecanismo principal utilizado por la aplicación para autenticar usuarios mediante tokens emitidos por Azure AD.
El backend (NestJS) utiliza passport-azure-ad para validar los tokens de Azure AD.
Componentes Específicos
MongoDB (con Mongoose)
- Propósito: Persistencia principal de datos para la aplicación.
- Configuración: A través de la variable de entorno
MONGO_CONNECTION_STRING. Para desarrollo local condocker-compose.yml(si el serviciopostgreses en realidad un MongoDB o si se añade un servicio MongoDB), se usaría algo comomongodb://localhost:27017/ehvypln-bff-db. El template.env.examplesugiereMONGO_CONNECTION_STRING="mongodb://localhost". - Módulos NestJS:
@nestjs/mongoose,MongooseModule. - Implementación: Definición de Schemas y Models de Mongoose para las entidades de la aplicación (ej.
Test).
Kafka
- Propósito: Consumo de mensajes de tópicos para procesamiento asíncrono (ej. recepción de alertas).
- Configuración:
- Variables de entorno principales:
KAFKA_BROKER,KAFKA_ALERT_CLIENT_ID,KAFKA_ALERT_CONSUMER_GROUP,ALERTS_TOPIC. - Para entornos productivos, se configura SSL y SASL (PLAIN) mediante
KAFKA_USERNAMEyKAFKA_PASSWORD. - Localmente, el broker Kafka (
kafka0) y Kafka UI están definidos endocker-compose.yml.
- Variables de entorno principales:
- Módulos NestJS:
KafkaModule(customizado ensrc/infra/kafka/),ClientsModulede@nestjs/microservices,kafkajs. - Implementación:
src/infra/kafka/kafka.utils.tsprovee la lógica para generar la configuración del cliente Kafka.src/infra/kafka/kafka-decorator-processor.service.tspermite el uso del decorador@KafkaTopicpara vincular métodos de controladores a tópicos de Kafka dinámicamente.- Ejemplo de uso en
src/alerts/controller/alerts.controller.tsque consume del tópicoALERTS_TOPIC.
Google Cloud Firestore
- Propósito: Almacenamiento NoSQL para datos específicos como alertas y mensajes de aeronaves.
- Configuración:
- Variables de entorno:
PROJECT_ID,FIRESTORE_EMULATOR_HOST(para desarrollo local). - Localmente, se utiliza el emulador de Firestore definido en
docker-compose.yml(serviciofirestore_emulatoren[::1]:8200). - Colecciones usadas:
ALERTS_FIRESTORE_COLLECTION,AIRCRAFT_MESSAGES_FIRESTORE_COLLECTION.
- Variables de entorno:
- Implementación:
src/infra/firestore/firestore.client.tsprovee un cliente customizado para interactuar con Firestore.- Este cliente se inyecta y utiliza en servicios como
AlertsService.
Redis (Cache)
- Propósito: Almacenamiento en caché para mejorar el rendimiento de la aplicación.
- Configuración:
- Localmente, el servicio Redis es levantado por
docker-compose.ymly accesible enlocalhost:6379.
- Localmente, el servicio Redis es levantado por
- Módulos NestJS:
@nestjs/cache-manager,CacheModule. - Implementación: Se utiliza el
CacheModulede NestJS, configurado concache-manager-redis-yet, para operaciones de caching estándar (get, set, delete).
OpenTelemetry (Observabilidad)
- Propósito: Recopilación y exportación de trazas y métricas para monitoreo y debugging.
- Configuración:
- Variables de entorno para exportación (ej. a Honeycomb):
HONEYCOMB_URL,HONEYCOMB_API_KEY.
- Variables de entorno para exportación (ej. a Honeycomb):
- Implementación:
- Inicialización y configuración en
src/infra/telemetry/opentelemetry/open-telemetry.ts. - Instrumenta automáticamente HTTP, Express y NestJS.
- Utiliza
OTLPTraceExporterpara enviar datos de trazas.
- Inicialización y configuración en
Pruebas
El proyecto utiliza Jest como framework de pruebas.
Tipos de Pruebas
- Pruebas Unitarias (
*.spec.ts): Prueban unidades aisladas de código (clases, funciones). - Pruebas End-to-End (
*.e2e-spec.ts): Prueban el flujo completo de la aplicación a través de sus endpoints HTTP. UsansupertestyTestcontainerspara un entorno de prueba más realista.
Comandos para Ejecutar Pruebas
- Ejecutar todas las pruebas (unitarias y de integración):
npm run test
- Ejecutar pruebas en modo observador (watch mode):
npm run test:watch
- Generar reporte de cobertura de pruebas:
El reporte se genera en el directorionpm run test:cov
coverage/. - Ejecutar pruebas E2E:
La configuración específica para E2E se encuentra ennpm run test:e2e
test/jest-e2e.json. - Debuggear pruebas:
npm run test:debug
Configuración de Pruebas
- Configuración general de Jest en
package.json(secciónjest). - Configuración E2E en
test/jest-e2e.json. - Setup adicional para Jest (mocks, etc.) en
src/test/setup-jest.ts.
Linting y Formato
El proyecto utiliza ESLint y Prettier para mantener la calidad y consistencia del código. Estos se ejecutan como un
hook pre-commit configurado con Husky y lint-staged (.husky/pre-commit).
- Lint:
npm run lint - Format:
npm run format
Consideraciones de Seguridad
- Helmet: Se utiliza para configurar varias cabeceras HTTP que ayudan a proteger la aplicación de vulnerabilidades web comunes.
- Autenticación Azure AD: La autenticación de usuarios se maneja principalmente mediante tokens JWT emitidos por
Azure AD, validados usando
passport-azure-ad(versrc/auth/azure-ad.strategy.tsyAzureADGuard). - CORS (Cross-Origin Resource Sharing): Configurado en
src/main.tspara permitir solicitudes desde orígenes específicos, previniendo CSRF y otros ataques relacionados con el origen. - Gestión de Secretos:
- Las credenciales y claves API (ej.
KAFKA_PASSWORD,HONEYCOMB_API_KEY) se gestionan como secretos. - En desarrollo local, se cargan desde
environments/local.env(que no debe ser comiteado si contiene secretos reales). - En entornos desplegados (GKE), los secretos son gestionados por Kubernetes Secrets, referenciados en los
values.yaml.erbde Helm.
- Las credenciales y claves API (ej.
- Validación de Entradas: Se utiliza
class-validatoryValidationPipede NestJS para validar los DTOs y payloads de entrada, previniendo ataques basados en datos malformados. - Google Cloud Endpoints: Actúa como una capa de API Gateway, pudiendo aplicar políticas de seguridad adicionales, cuotas y autenticación antes de que las solicitudes lleguen al backend.