@h4ad/serverless-adapter
Version:
Run REST APIs and other web applications using your existing Node.js application framework (NestJS, Express, Koa, Hapi, Fastify and many others), on top of AWS, Azure, Digital Ocean and many other clouds.
443 lines (431 loc) • 16.3 kB
text/typescript
import { B as BinarySettings, H as HandlerContract, S as ServerlessHandler } from './handler.contract-D9QyTfDX.cjs';
export { b as BinarySettingsContentHeaders, a as BinarySettingsFunction } from './handler.contract-D9QyTfDX.cjs';
import { B as BothValueHeaders } from './headers-DjfGHDmI.cjs';
export { M as MultiValueHeaders, S as SingleValueHeaders } from './headers-DjfGHDmI.cjs';
export { C as Concrete, S as StripBasePathFn, b as buildStripBasePath, g as getPathWithQueryStringParams, a as getQueryParamsStringFromRecord } from './path-BrSXm7S6.cjs';
import { A as AdapterContract, R as ResolverContract } from './adapter.contract-Cp2Jsh5V.cjs';
export { a as AdapterRequest, D as DelegatedResolver, G as GetResponseAdapterProps, O as OnErrorProps, c as Resolver, b as ResolverProps, S as ServerlessResponse, d as ServerlessResponseProps } from './adapter.contract-Cp2Jsh5V.cjs';
import { F as FrameworkContract } from './framework.contract-td-lRvq6.cjs';
export { B as BaseHandler } from './base-handler-B6soYcRl.cjs';
export { a as DEFAULT_BINARY_CONTENT_TYPES, D as DEFAULT_BINARY_ENCODINGS, E as EmptyResponse, I as IEmptyResponse } from './constants-DVTIV7Xu.cjs';
import { I as ILogger } from './logger-F8qccesk.cjs';
export { L as LogLevels, b as LoggerFN, a as LoggerOptions, c as createDefaultLogger, i as isInternalLogger } from './logger-F8qccesk.cjs';
import { Writable, Readable } from 'node:stream';
export { S as ServerlessRequest, a as ServerlessRequestProps } from './request-DsBcr1WD.cjs';
import { ServerResponse } from 'node:http';
import 'http';
/**
* The properties to create a {@link ServerlessStreamResponse}.
*
* @breadcrumb Network / ServerlessStreamResponse
* @public
*/
interface ServerlessStreamResponseProps {
/**
* The HTTP Method from request
*/
method?: string;
/**
* The callback to receive the headers when they are written to the stream
* You need to return a writable stream be able to continue writing the response
*
* @param statusCode - The status code of the response
* @param headers - The headers of the response
*/
onReceiveHeaders: (statusCode: number, headers: BothValueHeaders) => Writable;
/**
* Instance of the logger
*/
log: ILogger;
}
/**
* The class that represents a response instance used to send to the framework and wait until the framework finishes processing the request.
* This response is specially built to deal with transfer-encoding: chunked
*
* @breadcrumb Network / ServerlessStreamResponse
* @public
*/
declare class ServerlessStreamResponse extends ServerResponse {
constructor({ method, onReceiveHeaders, log, }: ServerlessStreamResponseProps);
}
/**
* Get the data from a buffer, string, or Uint8Array
*
* @breadcrumb Network
* @param data - The data that was written inside the stream
*/
declare function getString(data: Buffer | string | unknown): string;
/**
* The type that represents the object that handles the references to the event created by the serverless trigger or context created by the serverless environment.
*
* @breadcrumb Core / Current Invoke
* @public
*/
type CurrentInvoke<TEvent, TContext> = {
/**
* The event created by the serverless trigger
*
* @remarks It's only null when you call {@link getCurrentInvoke} outside this library's pipeline.
*/
event: TEvent | null;
/**
* The context created by the serverless environment
*
* @remarks It's only null when you call {@link getCurrentInvoke} outside this library's pipeline.
*/
context: TContext | null;
};
/**
* Get the reference to the event created by the serverless trigger or context created by the serverless environment.
*
* @example
* ```typescript
* import type { ALBEvent, Context } from 'aws-lambda';
*
* // inside the method that handles the aws alb request.
* const { event, context } = getCurrentInvoke<ALBEvent, Context>();
* ```
*
* @breadcrumb Core / Current Invoke
* @public
*/
declare function getCurrentInvoke<TEvent = any, TContext = any>(): CurrentInvoke<TEvent, TContext>;
/**
* Method that saves to the event created by the serverless trigger or context created by the serverless environment.
*
* @remarks This method MUST NOT be called by you, this method MUST only be used internally in this library.
*
* @param event - The event created by the serverless trigger
* @param context - The context created by the serverless environment
*
* @breadcrumb Core / Current Invoke
* @public
*/
declare function setCurrentInvoke<TEvent = any, TContext = any>({ event, context, }: CurrentInvoke<TEvent, TContext>): void;
/**
* Get the event body as buffer from body string with content length
*
* @example
* ```typescript
* const body = '{}';
* const [buffer, contentLength] = getEventBodyAsBuffer(body, false);
* console.log(buffer);
* // <Buffer 7b 7d>
* console.log(contentLength);
* // 2
* ```
*
* @param body - The body string that can be encoded or not
* @param isBase64Encoded - Tells if body string is encoded in base64
*
* @breadcrumb Core
* @public
*/
declare function getEventBodyAsBuffer(body: string, isBase64Encoded: boolean): [body: Buffer, contentLength: number];
/**
* Transform a header map and make sure the value is not an array
*
* @example
* ```typescript
* const headers = { 'accept-encoding': 'gzip', 'accept-language': ['en-US', 'en;q=0.9'] };
* const flattenedHeaders = getFlattenedHeadersMap(headers, ',', true);
* console.log(flattenedHeaders);
* // { 'accept-encoding': 'gzip', 'accept-language': 'en-US,en;q=0.9' }
* ```
*
* @param headersMap - The initial headers
* @param separator - The separator used when we join the array of header's value
* @param lowerCaseKey - Should put all keys in lowercase
*
* @breadcrumb Core / Headers
* @public
*/
declare function getFlattenedHeadersMap(headersMap: BothValueHeaders, separator?: string, lowerCaseKey?: boolean): Record<string, string>;
/**
* Transforms a header map into a multi-value map header.
*
* @example
* ```typescript
* const headers = { 'accept-encoding': 'gzip', 'connection': ['keep-alive'] };
* const multiValueHeaders = getMultiValueHeadersMap(headers);
* console.log(multiValueHeaders);
* // { 'accept-encoding': ['gzip'], 'connection': ['keep-alive'] }
* ```
*
* @param headersMap - The initial headers
*
* @breadcrumb Core / Headers
* @public
*/
declare function getMultiValueHeadersMap(headersMap: BothValueHeaders): Record<string, string[]>;
/**
* The wrapper that holds the information about single value headers and cookies
*
* @breadcrumb Core / Headers
* @public
*/
type FlattenedHeadersAndCookies = {
/**
* Just the single value headers
*/
headers: Record<string, string>;
/**
* The list of cookies
*/
cookies: string[];
};
/**
* Transforms a header map into a single value headers and cookies
*
* @param headersMap - The initial headers
*
* @breadcrumb Core / Headers
* @public
*/
declare function getFlattenedHeadersMapAndCookies(headersMap: BothValueHeaders): FlattenedHeadersAndCookies;
/**
* Parse HTTP Raw Headers
* Attribution to {@link https://github.com/kesla/parse-headers/blob/master/parse-headers.js}
*
* @param headers - The raw headers
*
* @breadcrumb Core / Headers
* @public
*/
declare function parseHeaders(headers: string): Record<string, string | string[]>;
declare function keysToLowercase<T extends Record<string, unknown>>(obj: T): {
[K in keyof T as Lowercase<string & K>]: T[K];
};
/**
* The function that determines by the content encoding whether the response should be treated as binary
*
* @example
* ```typescript
* const headers = { 'content-encoding': 'gzip' };
* const isBinary = isContentEncodingBinary(headers, ['gzip']);
* console.log(isBinary);
* // true
* ```
*
* @param headers - The headers of the response
* @param binaryEncodingTypes - The list of content encodings that will be treated as binary
*
* @breadcrumb Core / isBinary
* @public
*/
declare function isContentEncodingBinary(headers: BothValueHeaders, binaryEncodingTypes: string[]): boolean;
/**
* The function that returns the content type of headers
*
* @example
* ```typescript
* const headers = { 'content-type': 'application/json' };
* const contentType = getContentType(headers);
* console.log(contentType);
* // application/json
* ```
*
* @param headers - The headers of the response
*
* @breadcrumb Core / isBinary
* @public
*/
declare function getContentType(headers: BothValueHeaders): string;
/**
* The function that determines by the content type whether the response should be treated as binary
*
* @example
* ```typescript
* const headers = { 'content-type': 'image/png' };
* const isBinary = isContentTypeBinary(headers, new Map([['image/png', true]]));
* console.log(isBinary);
* // true
* ```
*
* @param headers - The headers of the response
* @param binaryContentTypes - The list of content types that will be treated as binary
*
* @breadcrumb Core / isBinary
* @public
*/
declare function isContentTypeBinary(headers: BothValueHeaders, binaryContentTypes: string[]): boolean;
/**
* The function used to determine from the headers and the binary settings if a response should be encoded or not
*
* @example
* ```typescript
* const headers = { 'content-type': 'image/png', 'content-encoding': 'gzip' };
* const isContentBinary = isBinary(headers, { contentEncodings: ['gzip'], contentTypes: ['image/png'] });
* console.log(isContentBinary);
* // true
* ```
*
* @param headers - The headers of the response
* @param binarySettings - The settings for the validation
*
* @breadcrumb Core / isBinary
* @public
*/
declare function isBinary(headers: BothValueHeaders, binarySettings: BinarySettings): boolean;
/**
* No operation function is used when we need to pass a function, but we don't want to specify any behavior.
*
* @breadcrumb Core
* @public
*/
declare const NO_OP: (...args: any[]) => any;
/**
* Return the defaultValue whether the value is undefined, otherwise, return the value.
*
* @example
* ```typescript
* const value1 = getDefaultIfUndefined(undefined, true);
* const value2 = getDefaultIfUndefined(false, true);
*
* console.log(value1);
* // true
* console.log(value2);
* // false
* ```
*
* @param value - The value to be checked
* @param defaultValue - The default value when value is undefined
*
* @breadcrumb Core
* @public
*/
declare function getDefaultIfUndefined<T>(value: T | undefined, defaultValue: T): T;
/**
* Check if stream already ended
*
* @param stream - The stream
*
* @breadcrumb Core / Stream
* @public
*/
declare function isStreamEnded(stream: Readable | Writable): boolean;
/**
* Wait asynchronous the stream to complete
*
* @param stream - The stream
*
* @breadcrumb Core / Stream
* @public
*/
declare function waitForStreamComplete<TStream extends Readable | Writable>(stream: TStream): Promise<TStream>;
/**
* The class used to build the serverless handler.
*
* @example
* ```typescript
* const app = express();
* export const handler = ServerlessAdapter.new(app)
* .setFramework(new ExpressFramework())
* .setHandler(new DefaultHandler())
* .setResolver(new PromiseResolver())
* .setRespondWithErrors(true)
* .addAdapter(new AlbAdapter())
* .addAdapter(new SQSAdapter())
* .addAdapter(new SNSAdapter())
* .build();
* ```
*
* @breadcrumb ServerlessAdapter
* @public
*/
declare class ServerlessAdapter<TApp, TEvent, TContext, TCallback, TResponse, TReturn> {
/**
* Default constructor
*/
private constructor();
/**
* The instance of the app (express, hapi, koa, etc...)
*/
protected app: TApp;
/**
* Settings for whether the response should be treated as binary or not
*
* @defaultValue `contentEncodings` and `contentTypes` are set with {@link DEFAULT_BINARY_ENCODINGS} and {@link DEFAULT_BINARY_CONTENT_TYPES}, respectively.
*/
protected binarySettings: BinarySettings;
/**
* Indicates whether the error stack should be included in the response or not
*
* @remarks These errors will only be included when an error occurs while forwarding the event to the framework
* @defaultValue True when NODE_ENV is equal to `development`
*/
protected respondWithErrors: boolean;
/**
* The instance of the logger service
*/
protected log: ILogger;
/**
* The list of adapters used to handle an event's request and response
*/
protected adapters: AdapterContract<TEvent, TContext, TResponse>[];
/**
* The framework that will process requests
*/
protected framework?: FrameworkContract<TApp>;
/**
* The resolver that aims to resolve the response to serverless and stop its execution when the request ends
*/
protected resolver?: ResolverContract<TEvent, TContext, TCallback, TResponse, TReturn>;
/**
* The handler that will get the event, context and callback and pass it to the adapter and framework
*/
protected handler?: HandlerContract<TApp, TEvent, TContext, TCallback, TResponse, TReturn>;
/**
* Creates a new instance of the builder with app (express, hapi, koa, etc...)
*
* @param app - The instance of the app
*/
static new<TApp, TEvent, TContext = any, TCallback = any, TResponse = any, TReturn = any>(app: TApp): ServerlessAdapter<TApp, TEvent, TContext, TCallback, TResponse, TReturn>;
/**
* Defines the handler that will get the event, context and callback and pass it to the adapter and framework
*
* @param handler - The implementation of the handler contract
*/
setHandler(handler: HandlerContract<TApp, TEvent, TContext, TCallback, TResponse, TReturn>): Omit<this, 'setHandler'>;
/**
* Defines the resolver that aims to resolve the response to serverless and stop its execution when the request ends
*
* @param resolver - The implementation of the resolver contract
*/
setResolver(resolver: ResolverContract<TEvent, TContext, TCallback, TResponse, TReturn>): Omit<this, 'setResolver'>;
/**
* Defines the framework that will process requests
*
* @param framework - The implementation of the framework contract
*/
setFramework(framework: FrameworkContract<TApp>): Omit<this, 'setFramework'>;
/**
* Defines the logger service used during the execution of the handler
*
* @param logger - The implementation of the logger
*/
setLogger(logger: ILogger): Omit<this, 'setLogger'>;
/**
* Defines the binary settings for whether the response should be treated as binary or not
*
* @param binarySettings - The binary settings
*/
setBinarySettings(binarySettings: BinarySettings): Omit<this, 'setBinarySettings'>;
/**
* Defines the responseWithErrors, a property that indicates whether the error stack should be included in the response or not
*
* @param respondWithErrors - Should include or not the errors in response
*/
setRespondWithErrors(respondWithErrors: boolean): Omit<this, 'setRespondWithErrors'>;
/**
* Add an adapter to the adapters list to handle the event coming from any serverless event source
*
* @param adapter - The implementation of the adapter contract
*/
addAdapter(adapter: AdapterContract<TEvent, TContext, TResponse>): Pick<this, 'addAdapter' | 'build'>;
/**
* The builder method that returns the handler function to be exported for serverless consumption
*/
build(): ServerlessHandler<TReturn>;
}
export { AdapterContract, BinarySettings, BothValueHeaders, type CurrentInvoke, type FlattenedHeadersAndCookies, FrameworkContract, HandlerContract, ILogger, NO_OP, ResolverContract, ServerlessAdapter, ServerlessHandler, ServerlessStreamResponse, type ServerlessStreamResponseProps, getContentType, getCurrentInvoke, getDefaultIfUndefined, getEventBodyAsBuffer, getFlattenedHeadersMap, getFlattenedHeadersMapAndCookies, getMultiValueHeadersMap, getString, isBinary, isContentEncodingBinary, isContentTypeBinary, isStreamEnded, keysToLowercase, parseHeaders, setCurrentInvoke, waitForStreamComplete };