New:Microsoft Teams Notifications Are Now Available in Socket.Learn more
Get Started

@fiado/gateway-adapter

Package Overview
Dependencies
Maintainers
1
Versions
112
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@fiado/gateway-adapter

Facilita la comunicación e integración entre AWS Lambda y API Gateway , sqs y Event Bridge

npmnpm
Version
3.3.2
Version published
Maintainers
1
Created
Source

Fiado Gateway Adapter

Libreria Core para Enrutamiento de Eventos en Microservicios Lambda

npm TypeScript AWS Lambda InversifyJS

Tabla de Contenidos

Descripcion General

@fiado/gateway-adapter es la libreria core del ecosistema Fiado que actua como router central para todos los eventos que recibe una funcion Lambda. Proporciona:

  • Enrutamiento automatico de eventos API Gateway, SQS y EventBridge
  • Transformacion de requests/responses con tipado fuerte
  • Sistema de autorizacion basado en decoradores y features
  • Decodificacion de tokens JWT de Cognito
  • Respuestas HTTP estandarizadas con CORS configurado
  • Encriptacion JWE opcional para datos sensibles
  • Registro de actividad de sesion automatico

Proposito

En el modelo de desarrollo Fiado, cada Lambda recibe multiples tipos de eventos:

  • API Gateway: Peticiones HTTP (publicas, privadas, backoffice)
  • SQS: Mensajes de colas para procesamiento asincrono
  • EventBridge: Eventos entre servicios

Esta libreria unifica el manejo de todos estos eventos en un unico punto de entrada.

Arquitectura

                              LAMBDA HANDLER
                                index.ts
                                   |
                                   v
                          +---------------+
                          | GatewayAdapter | <-- Router Principal
                          +-------+-------+
                                  |
              +-------------------+-------------------+
              v                   v                   v
     +-----------------+ +-----------------+ +-----------------+
     |ApiGatewayAdapter| |QueueGatewayAdapter| |EventBridgeAdapter|
     +--------+--------+ +--------+--------+ +--------+--------+
              |                   |                   |
              v                   v                   v
     +-----------------+ +-----------------+ +-----------------+
     |   Controllers   | | SQS Subscriber  | |  EB Subscriber  |
     | Public/Private/ | |IMessageSubscriber| |IEventBridgeSub |
     |   Backoffice    | |                 | |                 |
     +-----------------+ +-----------------+ +-----------------+

Flujo de Deteccion de Eventos

El GatewayAdapter detecta automaticamente el tipo de evento:

  • API Gateway: Si event.httpMethod existe
  • SQS: Si event.Records[0].eventSource === 'aws:sqs'
  • EventBridge: Si event.source === 'EVENT_BRIDGE'

Instalacion

npm install @fiado/gateway-adapter

Peer Dependencies

{
  "@fiado/logger": "^1.0.2",
  "@fiado/type-kit": "^2.1.35",
  "inversify": "^6.2.2",
  "reflect-metadata": "^0.2.2"
}

Configuracion

Registro en el Contenedor IoC

import { Container } from "inversify";
import { 
    gatewayAdapterBindings, 
    TypeQueue, 
    TypeEventBridge,
    IController,
    IMessageSubscriber,
    IEventBridgeMessageSubscriber
} from "@fiado/gateway-adapter";

const container = new Container();

// Cargar bindings del gateway adapter
container.load(gatewayAdapterBindings);

// Registrar controladores del proyecto
container.bind<IController>('PublicController').to(PublicController);
container.bind<IController>('PrivateController').to(PrivateController);
container.bind<IController>('BackofficeController').to(BackofficeController);

// Registrar subscriber de SQS (si aplica)
container.bind<IMessageSubscriber<any>>("SQSMessageSubscriber").to(MySqsSubscriber);
container.bind<() => IMessageSubscriber<any>>(TypeQueue.SQSMessageSubscriberFactory)
    .toAutoFactory("SQSMessageSubscriber");

// Registrar subscriber de EventBridge (si aplica)
container.bind<IEventBridgeMessageSubscriber<any>>("EventBridgeMessageSubscriber")
    .to(MyEventBridgeSubscriber);
container.bind<() => IEventBridgeMessageSubscriber<any>>(
    TypeEventBridge.EventBridgeMessageSubscriberFactory
).toAutoFactory("EventBridgeMessageSubscriber");

export { container };

Entry Point del Lambda

import 'reflect-metadata';
import warmer from "lambda-warmer";
import { container } from './container.config';
import { GatewayAdapter, TypeGateway } from '@fiado/gateway-adapter';
import { log } from "@fiado/logger";

export const handler = async (event: any, context: any) => {
    
    // Soporte para lambda warming
    if (await warmer(event)) {
        return 'warmed';
    }

    log.info(`Event received: ${JSON.stringify(event)}`);

    // Obtener el router y ejecutar
    const gatewayAdapter = container.get<GatewayAdapter>(TypeGateway.GatewayAdapter);
    return await gatewayAdapter.execute(event);
}

GatewayAdapter - Router Principal

El GatewayAdapter es el componente central que detecta el tipo de evento y lo enruta al adaptador correspondiente.

Tipos de Eventos Soportados

TipoDeteccionAdaptador
API Gatewayevent.httpMethod existeApiGatewayAdapter
SQSevent.Records[0].eventSource === 'aws:sqs'QueueGatewayAdapter
EventBridgeevent.source === 'EVENT_BRIDGE'EventBridgeGatewayAdapter

Uso

import { GatewayAdapter, TypeGateway } from '@fiado/gateway-adapter';

const gatewayAdapter = container.get<GatewayAdapter>(TypeGateway.GatewayAdapter);

// El adapter detecta automaticamente el tipo de evento
const result = await gatewayAdapter.execute(event);

API Gateway

ApiGatewayRequest

Interface tipada que representa una peticion HTTP transformada:

interface ApiGatewayRequest<TBody> {
    body: TBody | null;                                    // Body parseado
    headers: { [key: string]: string | undefined };        // Headers HTTP
    method: string;                                        // GET, POST, PUT, DELETE
    pathParameter: { [key: string]: string | undefined };  // Path params (/users/:id)
    queryStringParameters: { [key: string]: string };      // Query params (?key=value)
    multiValueQueryStringParameters: { [key: string]: string[] }; // Arrays
    token: TokenPayload | undefined | null;                // Token JWT decodificado
    operationName: string | null;                          // Nombre de la operacion
    base64EncodedFile?: string;                            // Archivos en base64
    requestContext: { identity?: { sourceIp?: string } };  // Contexto de request
}

Controladores

Los controladores se identifican por prefijo en el operationName:

PrefijoControladorUso
public*PublicControllerEndpoints publicos (internet)
private*PrivateControllerEndpoints privados (VPC)
backoffice*BackofficeControllerEndpoints administrativos
agent* / agents*AgentControllerEndpoints de agentes

Ejemplo de Controlador

import { injectable, inject } from 'inversify';
import { 
    IController, 
    ApiGatewayRequest, 
    ApiResponse,
    AuthorizedFeatures,
    Feature,
    Endpoint,
    HttpMethod,
    SecurityType
} from '@fiado/gateway-adapter';

@injectable()
export class PublicController implements IController {

    constructor(
        @inject("IUserManager") private userManager: IUserManager
    ) {}

    @AuthorizedFeatures(Feature.ANONIMUS)
    @Endpoint({
        method: HttpMethod.GET,
        path: '/users/:id',
        summary: 'Obtener usuario por ID',
        tags: ['PublicController'],
        security: SecurityType.CognitoAppAuthorizer
    })
    async getUser(request: ApiGatewayRequest<void>): Promise<any> {
        const userId = request.pathParameter?.id;
        const user = await this.userManager.getById(userId);
        return ApiResponse.success({ data: user });
    }

    @AuthorizedFeatures(Feature.ANONIMUS)
    @Endpoint({
        method: HttpMethod.POST,
        path: '/users',
        summary: 'Crear usuario',
        tags: ['PublicController'],
        security: SecurityType.CognitoAppAuthorizer
    })
    async createUser(request: ApiGatewayRequest<CreateUserDto>): Promise<any> {
        const user = await this.userManager.create(request.body);
        return ApiResponse.created({ data: user });
    }
}

TokenService

Servicio para decodificar tokens JWT de Cognito:

import { TokenService } from '@fiado/gateway-adapter';

const tokenService = new TokenService();
const payload = tokenService.decodeToken(bearerToken);

// payload contiene:
// - sub: ID del usuario
// - email: Email del usuario
// - permissions: Array de permisos/features
// - cognito:groups: Grupos de Cognito

Colas SQS

IMessageSubscriber

Interface para procesar mensajes de SQS:

export interface IMessageSubscriber<T> {
    handle(messageBody: T, receiptHandle: string): Promise<void>;
    deleteMessage(queueUrl: string, receiptHandle: string): Promise<void>;
}

Implementacion de Subscriber

import { injectable } from 'inversify';
import { IMessageSubscriber } from '@fiado/gateway-adapter';
import { log } from '@fiado/logger';

@injectable()
export class OrderMessageSubscriber implements IMessageSubscriber<OrderMessage> {
    
    async handle(messageBody: OrderMessage, receiptHandle: string): Promise<void> {
        log.info('Processing order message', { orderId: messageBody.orderId });
        await this.processOrder(messageBody);
    }

    async deleteMessage(queueUrl: string, receiptHandle: string): Promise<void> {
        // Implementar si se necesita borrado manual
    }

    private async processOrder(order: OrderMessage): Promise<void> {
        // Logica de procesamiento
    }
}

IMessagePublisher

Interface para publicar mensajes a SQS:

export interface IMessagePublisher<T> {
    publish(messageBody: T, options?: PublishOptions): Promise<void>;
}

EventBridge

IEventBridgeMessageSubscriber

Interface para procesar eventos de EventBridge:

import { EventBridgeMessageRequest } from "@fiado/type-kit";

export interface IEventBridgeMessageSubscriber<TPayload> {
    handle(message: EventBridgeMessageRequest<TPayload>): Promise<void>;
}

Implementacion de Subscriber

import { injectable } from 'inversify';
import { IEventBridgeMessageSubscriber } from '@fiado/gateway-adapter';
import { EventBridgeMessageRequest } from '@fiado/type-kit';

@injectable()
export class PaymentEventSubscriber implements IEventBridgeMessageSubscriber<PaymentEvent> {
    
    async handle(message: EventBridgeMessageRequest<PaymentEvent>): Promise<void> {
        const { payload, eventType } = message;
        
        switch (eventType) {
            case 'PAYMENT_COMPLETED':
                await this.handlePaymentCompleted(payload);
                break;
            case 'PAYMENT_FAILED':
                await this.handlePaymentFailed(payload);
                break;
        }
    }
}

Decoradores

@AuthorizedFeatures

Decorador para definir que features/permisos pueden acceder a un metodo:

import { AuthorizedFeatures, Feature } from '@fiado/gateway-adapter';

// Acceso anonimo (sin token)
@AuthorizedFeatures(Feature.ANONIMUS)
async publicEndpoint(request: ApiGatewayRequest<any>): Promise<any> { }

// Requiere feature especifico en el token
@AuthorizedFeatures(Feature.PAYROLL)
async payrollEndpoint(request: ApiGatewayRequest<any>): Promise<any> { }

// Multiples features (OR - cualquiera autoriza)
@AuthorizedFeatures(Feature.ADMIN, Feature.MANAGER)
async adminEndpoint(request: ApiGatewayRequest<any>): Promise<any> { }

Feature Enum

export enum Feature {
    ANONIMUS = "ANONIMUS",  // Acceso publico sin autenticacion
    TEST = "test",
    FEATURE1 = "feature1",
    PAYROLL = "PAYROLL"
}

@Endpoint

Decorador para definir metadata del endpoint (usado para generacion OpenAPI):

import { Endpoint, HttpMethod, SecurityType } from '@fiado/gateway-adapter';

@Endpoint({
    method: HttpMethod.POST,
    path: '/payments',
    summary: 'Procesar pago',
    tags: ['PaymentController'],
    security: SecurityType.CognitoAppAuthorizer,
    queryParams: ['currency'],
    pathParams: ['id']
})
async processPayment(request: ApiGatewayRequest<PaymentDto>): Promise<any> { }

HttpMethod Enum

export enum HttpMethod {
    GET = 'get',
    POST = 'post',
    PUT = 'put',
    DELETE = 'delete'
}

SecurityType Enum

export enum SecurityType {
    CognitoAppAuthorizer = 'CognitoAppAuthorizer',           // Usuarios de la app
    CognitoBackofficeAuthorizer = 'CognitoBackofficeAuthorizer', // Administradores
    CognitoCombinedAuthorizer = 'CognitoCombinedAuthorizer',     // Ambos pools
    CognitoAgentAuthorizer = 'CognitoAgentAuthorizer'            // Agentes
}

Sistema de Respuestas

ApiResponse

Clase estatica para construir respuestas HTTP estandarizadas:

import { ApiResponse } from '@fiado/gateway-adapter';

// 200 OK
return ApiResponse.success({ data: result, msg: 'Operacion exitosa' });

// 201 Created
return ApiResponse.created({ data: newResource });

// 400 Bad Request
return ApiResponse.badRequest({ code: 'VALIDATION_ERROR', msg: 'Campo requerido' });

// 401 Unauthorized
return ApiResponse.unauthorized({ msg: 'Token invalido' });

// 403 Forbidden
return ApiResponse.forbidden({ msg: 'Acceso denegado' });

// 404 Not Found
return ApiResponse.notFound({ msg: 'Recurso no encontrado' });

// 425 Too Early
return ApiResponse.tooEarly({ msg: 'Intente mas tarde' });

// 500 Internal Server Error
return ApiResponse.internalServerError({ msg: 'Error interno' });

// 302 Redirect
return ApiResponse.redirect({ data: { url: 'https://...' } });

// Redireccion real con header Location
return ApiResponse.redirectTo('https://example.com/callback', 302);

Estructura de Respuesta

Todas las respuestas siguen el formato estandar:

{
    statusCode: 200,
    headers: {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Headers": "*",
        "Access-Control-Allow-Methods": "*",
        "Content-Type": "application/json"
    },
    body: {
        code: "PROCESS_OK",      // Codigo de respuesta
        date: "2024-01-15T...",  // Timestamp ISO
        data: { ... },           // Datos de respuesta
        description: null,       // Descripcion opcional
        msg: null,               // Mensaje opcional
        encrypted: false         // Flag de encriptacion (opcional)
    }
}

ResponseOptions

interface ResponseOptions<T> {
    data?: T;              // Datos a retornar
    code?: string;         // Codigo personalizado
    msg?: string;          // Mensaje
    description?: string;  // Descripcion
    encrypted?: boolean;   // Flag de encriptacion
}

Encriptacion JWE

JweEncryptionService

Servicio para encriptar respuestas sensibles usando JWE (JSON Web Encryption):

Configuracion

Variables de entorno para habilitar encriptacion:

Environment:
  Variables:
    # Encriptar TODOS los endpoints de app
    JWE_ENCRYPTION_APP: "true"
    
    # O encriptar endpoints especificos
    JWE_ENCRYPTION_APP_ENDPOINTS: "publicGetBalance,publicGetTransactions"
    
    # Para backoffice
    JWE_ENCRYPTION_BACKOFFICE: "true"
    JWE_ENCRYPTION_BACKOFFICE_ENDPOINTS: "backofficeGetUserData"

Flujo de Encriptacion

  • Cliente envia header x-session-key con session key encriptada (JWE con llave publica RSA)
  • Lambda descifra session key usando llave privada de Secrets Manager
  • Respuesta data se encripta con AES-256-GCM usando session key
  • Cliente descifra respuesta con su session key

Uso Automatico

La encriptacion se aplica automaticamente si:

  • El endpoint esta configurado para encriptar
  • El cliente envia el header x-session-key
  • El servicio puede inicializarse correctamente
// La respuesta se encripta automaticamente
return ApiResponse.success({ data: sensitiveData });

// Respuesta encriptada:
{
    code: "PROCESS_OK",
    data: "eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIn0...",  // JWE
    encrypted: true
}

Estructura del Proyecto

src/
├── index.ts                    # Exportaciones publicas
├── container.config.ts         # ContainerModule con bindings
├── GatewayAdapter.ts           # Router principal
│
├── apigateway/                 # Modulo API Gateway
│   ├── abstractions/
│   │   ├── ApiGatewayRequest.ts
│   │   ├── ApiGatewayResponse.ts
│   │   ├── FeatureEnum.ts
│   │   ├── IController.ts
│   │   ├── ResponseOptions.ts
│   │   ├── StandardResponse.ts
│   │   └── TypeGateway.ts
│   ├── decorators/
│   │   └── AuthorizedFeatures.ts
│   └── services/
│       ├── ActivitySessionService.ts
│       ├── ApiGatewayAdapter.ts
│       ├── ApiResponse.ts
│       ├── JweEncryptionService.ts
│       └── TokenService.ts
│
├── queue/                      # Modulo SQS
│   ├── abstractions/
│   │   ├── IMessagePublisher.ts
│   │   ├── IMessageSubscriber.ts
│   │   ├── IPublishOptions.ts
│   │   └── TypeQueue.ts
│   ├── decorators/
│   └── services/
│       └── QueueGatewayAdapter.ts
│
├── eventBridge/                # Modulo EventBridge
│   ├── abstractions/
│   │   ├── IEventBridgeMessageSubscriber.ts
│   │   └── TypeEventBridge.ts
│   └── service/
│       └── EventBridgeGatewayAdapter.ts
│
└── endpoint/                   # Decorador @Endpoint
    └── endpointDecorator.ts

Dependencias

Runtime

DependenciaVersionProposito
@fiado/api-invoker^1.4.6Invocacion de APIs internas
@fiado/logger^1.0.2Logging estructurado
@fiado/type-kit^2.1.35DTOs y tipos compartidos
aws-lambda^1.0.7Tipos de AWS Lambda
inversify^6.2.2Inyeccion de dependencias
jose^4.15.5Encriptacion JWE
jsonwebtoken^9.0.2Decodificacion JWT
reflect-metadata^0.2.2Metadatos para decoradores
uuid^9.0.1Generacion de UUIDs

Desarrollo

DependenciaVersionProposito
@types/jsonwebtoken^9.0.6Tipos de jsonwebtoken

Compilacion y Publicacion

Build

npm run build

Genera archivos .js y .d.ts en el directorio bin/.

Publicacion

npm version patch|minor|major
npm publish

Fiado Inc. | @fiado/gateway-adapter v1.1.59

`

FAQs

Package last updated on 17 Jun 2026

Related posts