UNPKG

@sailplane/lambda-utils

Version:

Use middleware to remove redundancy in AWS Lambda handlers.

116 lines (112 loc) 4.01 kB
// lib/handler-utils.ts import middy from "@middy/core"; import cors from "@middy/http-cors"; import httpEventNormalizer from "@middy/http-event-normalizer"; import httpHeaderNormalizer from "@middy/http-header-normalizer"; import httpJsonBodyParser from "@middy/http-json-body-parser"; import { Logger as Logger3 } from "@sailplane/logger"; // lib/resolved-promise-is-success.ts var resolvedPromiseIsSuccessMiddleware = () => ({ after: async (request) => { const response = request.response; if (!response || typeof response !== "object" || !response.statusCode && !response.body) { request.response = { statusCode: 200, body: response ? JSON.stringify(response) : "", headers: { "content-type": response ? "application/json; charset=utf-8" : "text/plain; charset=utf-8" } }; } } }); // lib/unhandled-exception.ts import { Logger } from "@sailplane/logger"; var logger = new Logger("lambda-utils"); var unhandledExceptionMiddleware = () => ({ onError: async (request) => { logger.error("Unhandled exception:", request.error); request.response = request.response || {}; if ((request.response.statusCode || 0) < 400) { const error = findRootCause(request.error); request.response.statusCode = error?.statusCode || 500; request.response.body = error?.toString() ?? ""; request.response.headers = request.response.headers ?? {}; request.response.headers["content-type"] = "text/plain; charset=utf-8"; } logger.info("Response to API Gateway: ", request.response); } }); function findRootCause(error) { const errorWithStatus = error; if (errorWithStatus?.statusCode && errorWithStatus.statusCode >= 400) { return error; } else if (errorWithStatus?.cause) { return findRootCause(errorWithStatus.cause); } else { return error; } } // lib/logger-context.ts import { Logger as Logger2 } from "@sailplane/logger"; var loggerContextMiddleware = () => { return { before: async (request) => { Logger2.setLambdaContext(request.context); const requestContext = request.event.requestContext; const claims = requestContext?.authorizer?.claims || // API v1 requestContext?.authorizer?.jwt?.claims; const context = { api_request_id: requestContext?.requestId, jwt_sub: claims?.sub }; Logger2.addAttributes(context); } }; }; // lib/handler-utils.ts var logger2 = new Logger3("lambda-utils"); function wrapApiHandler(handler) { return middy(handler).use(cors({ origin: "*" })).use(resolvedPromiseIsSuccessMiddleware()).use(unhandledExceptionMiddleware()).use(loggerContextMiddleware()).use(httpEventNormalizer()).use(httpHeaderNormalizer()).use( // Parse JSON body, but don't throw when there is no body httpJsonBodyParser({ disableContentTypeError: true }) ); } var wrapApiHandlerV1 = wrapApiHandler; function wrapApiHandlerV2(handler) { return middy(handler).use(cors({ origin: "*" })).use(resolvedPromiseIsSuccessMiddleware()).use(unhandledExceptionMiddleware()).use(loggerContextMiddleware()).use(httpEventNormalizer()).use(httpHeaderNormalizer()).use( // Parse JSON body, but don't throw when there is no body httpJsonBodyParser({ disableContentTypeError: true }) ); } function apiSuccess(result) { return { statusCode: 200, body: result ? JSON.stringify(result) : "", headers: { "content-type": result ? "application/json; charset=utf-8" : "text/plain; charset=utf-8" } }; } function apiFailure(statusCode, message) { const response = { statusCode, body: message || "", headers: { "content-type": "text/plain; charset=utf-8" } }; logger2.warn("Response to API Gateway: ", response); return response; } export { apiFailure, apiSuccess, loggerContextMiddleware, resolvedPromiseIsSuccessMiddleware, unhandledExceptionMiddleware, wrapApiHandler, wrapApiHandlerV1, wrapApiHandlerV2 }; //# sourceMappingURL=index.mjs.map