UNPKG

convert-lambda-to-express

Version:

Wrapper to run lambda on express. Works great for running lambdas as an express server during development but is production ready. Developed to work in conjunction with matthewkeil/full-stack-pattern cdk construct.

172 lines (171 loc) 8.59 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Context = void 0; const os_1 = __importDefault(require("os")); const path_1 = require("path"); const utils_1 = require("./utils"); class Context { constructor(options) { var _a, _b, _c, _d, _e, _f, _g, _h; this.options = options; this._finalized = false; // setup time management this._startTime = options.startTime; this._timeout = (options === null || options === void 0 ? void 0 : options.timeoutInSeconds) ? options.timeoutInSeconds * 1000 : 3000; // default lambda timeout this.__timeout = setTimeout(() => { this.fail(new utils_1.TimeoutError('Task timed out after ' + (this._timeout / 1000).toFixed(0) + ' second(s)')); }, this._timeout); // setup Context internals this._region = (_a = this.options.region) !== null && _a !== void 0 ? _a : 'us-east-1'; this._accountId = (_b = this.options.accountId) !== null && _b !== void 0 ? _b : '123456789012'; this.__finalize = (_c = options.finalize) !== null && _c !== void 0 ? _c : function () { }; // eslint-disable-line @typescript-eslint/no-empty-function // setup properties of IContext this.callbackWaitsForEmptyEventLoop = false; // not supported by this package this.functionName = (_d = options.functionName) !== null && _d !== void 0 ? _d : 'convert-lambda-to-express'; this.functionVersion = (_e = options.functionVersion) !== null && _e !== void 0 ? _e : '$LATEST'; this.memoryLimitInMB = `${(_f = options.memorySize) !== null && _f !== void 0 ? _f : 128}`; this.logGroupName = (_g = options.logGroupName) !== null && _g !== void 0 ? _g : `/aws/lambda/${this.functionName}`; this.logStreamName = (_h = options.logStreamName) !== null && _h !== void 0 ? _h : 'aws-log-stream'; this.identity = options.identity; this.clientContext = options.clientContext; this.invokedFunctionArn = Context.createInvokeFunctionArn(this._region, this._accountId, this.functionName); this.awsRequestId = Context.getAwsRequestId(); for (const [key, value] of Object.entries(this._buildExecutionEnv())) { process.env[key] = value; } } static createInvokeFunctionArn(region, accountId, functionName) { return ['arn', 'aws', 'lambda', region, accountId, 'function', functionName].join(':'); } static getAwsRequestId() { /* * create random invokeid. * Assuming that invokeid follows the format: * 8hex-4hex-4hex-4hex-12hex */ return [ (0, utils_1.generateRandomHex)(8), (0, utils_1.generateRandomHex)(4), (0, utils_1.generateRandomHex)(4), (0, utils_1.generateRandomHex)(4), (0, utils_1.generateRandomHex)(12) ].join('-'); } done(err, messageOrObject) { let error; if (typeof err === 'string') { error = new Error(err); } else if (err) { error = err; } if (error) { if (this._reject) { return this._reject(error); } throw error; } return this._resolve ? this._resolve(messageOrObject) : messageOrObject; } fail(err) { this.done(err); } succeed(messageOrObject) { this.done(undefined, messageOrObject); } getRemainingTimeInMillis() { const now = new Date().getTime(); return this._timeout + this._startTime - now; } _clearTimeout() { if (this.__timeout) { clearTimeout(this.__timeout); this.__timeout = undefined; } } _finalize() { if (!this._finalized) { this.__finalize(); this._finalized = true; } } _buildExecutionEnv() { var _a, _b, _c, _d; const env = {}; const pwd = process.cwd(); /** * Example env from lambda. * * // provided by code below * AWS_LAMBDA_FUNCTION_NAME: 'testing', * AWS_LAMBDA_FUNCTION_MEMORY_SIZE: '128', * AWS_LAMBDA_FUNCTION_VERSION: '$LATEST', * AWS_LAMBDA_INITIALIZATION_TYPE: 'on-demand', * TZ: ':UTC', * AWS_LAMBDA_LOG_GROUP_NAME: '/aws/lambda/testing', * AWS_LAMBDA_LOG_STREAM_NAME: '2021/11/22/[$LATEST]de828bd7f9c24c7eb7785595c8986d57', * AWS_REGION: 'us-east-1', * AWS_DEFAULT_REGION: 'us-east-1', * AWS_ACCESS_KEY_ID: 'ASIAZCOEDDHJLKBSTXHC', * AWS_SECRET_ACCESS_KEY: 'p9J3AUnM6Xq/FWC1gbjZYQNPQ5dcrssKFE5O5KuX', * AWS_SESSION_TOKEN: 'IQoJb3JpZ2luX2VjEG0aCXVzLWVhc3QtMSJHMEUCIQDE+QJWdu2ObTnT9tX2LwciiBgtztLCIatoB3SAuf+pXQIgODR1wCU8X0IWyZGWQNcs6gT/fscXr994bg9/PXfW8/8qjAIINhAAGgw2MjM3MTgzNzM4NDIiDDPpPESUXC4fMbct4CrpAc5qgMybO6icB79pLiOw5wysZJJIYRXiB0Je8OAQXrHwNaV8hxyZ8bnLVeSA0K4LSea4htMaKUpL5f88lqmFrIJMYRnKD4V3xVmLX65oFh7wl8WkF2gJ91Hl8x8keEriRdRyD69h1nhcCzM2UsQvZykDw7BTjwBYu74E4JUaTgtdZscG1/W2B9I4ooPWzOwjuCdcY6NFsUC/LBAZojS5UqQkI3Uhj1y4Fj/KtpaGBjR07EaeuRJKEDj7Urw2v4CpmyJIQObu0qqU7nWFAbSiAXyfgEWwJ4F/8sJeDD5rVE9S7aqOj4HSK/nQMJWI8IwGOpoBYbUVUr5d+H4aC4/fJR8oTotYqXqCzwit+KvnShgTLTeOnzxKVIs/h/mAXETBKoSLTSBC5Fhap9+8GJ2Oh+MLRiJ2N2I/JlbT05R9M5J3iL/OlRzxMNj8BLheEit6E23LvmIv+O3AtvDu0N+DDG2++KxlPpmfrC9DiE//i57xfLd/g+arsBnCHw1fK1Jw+6FXovJXVzLloB/DPA==', * AWS_EXECUTION_ENV: 'AWS_Lambda_nodejs14.x', * AWS_LAMBDA_RUNTIME_API: '127.0.0.1:9001', * _HANDLER: 'index.handler', * PWD: '/var/task', * LAMBDA_TASK_ROOT: '/var/task', * LAMBDA_RUNTIME_DIR: '/var/runtime', * NODE_PATH: '/opt/nodejs/node14/node_modules:/opt/nodejs/node_modules:/var/runtime/node_modules:/var/runtime:/var/task', * * // provided by node env * LANG: 'en_US.UTF-8', * PATH: '/var/lang/bin:/usr/local/bin:/usr/bin/:/bin:/opt/bin', * SHLVL: '0', * * // no provided * NODE_EXTRA_CA_CERTS: '/etc/pki/tls/certs/ca-bundle.crt', * LD_LIBRARY_PATH: '/var/lang/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib:/opt/lib', * AWS_XRAY_DAEMON_ADDRESS: '169.254.79.129:2000', * _AWS_XRAY_DAEMON_ADDRESS: '169.254.79.129', * _AWS_XRAY_DAEMON_PORT: '2000', * AWS_XRAY_CONTEXT_MISSING: 'LOG_ERROR', * _X_AMZN_TRACE_ID: 'Root=1-619c0415-0114f3884674422b7ee957a1;Parent=4a9245f561fc8965;Sampled=0' */ // base configuration env.AWS_LAMBDA_FUNCTION_NAME = this.functionName; env.AWS_LAMBDA_FUNCTION_MEMORY_SIZE = Math.floor(os_1.default.freemem() / 1048576).toString(); env.AWS_LAMBDA_FUNCTION_VERSION = '$LATEST'; env.AWS_LAMBDA_INITIALIZATION_TYPE = 'on-demand'; env.TZ = Intl.DateTimeFormat().resolvedOptions().timeZone; // logging information env.AWS_LAMBDA_LOG_GROUP_NAME = this.logGroupName; env.AWS_LAMBDA_LOG_STREAM_NAME = this.logStreamName; // information so aws-sdk can run as it would normally env.AWS_REGION = this._region; env.AWS_DEFAULT_REGION = this._region; if ((_a = this.options.credentials) === null || _a === void 0 ? void 0 : _a.accessKeyId) { env.AWS_ACCESS_KEY_ID = this.options.credentials.accessKeyId; } if ((_b = this.options.credentials) === null || _b === void 0 ? void 0 : _b.secretAccessKey) { env.AWS_SECRET_ACCESS_KEY = this.options.credentials.secretAccessKey; } if ((_c = this.options.credentials) === null || _c === void 0 ? void 0 : _c.sessionToken) { env.AWS_SESSION_TOKEN = this.options.credentials.sessionToken; } // runtime information env.AWS_EXECUTION_ENV = `AWS_Lambda_nodejs${process.version.split('.')[0]}.x`; env.AWS_LAMBDA_RUNTIME_API = '127.0.0.1:9001'; env._HANDLER = (_d = this.options.handler) !== null && _d !== void 0 ? _d : 'index.handler'; env.PWD = pwd; env.LAMBDA_TASK_ROOT = pwd; env.LAMBDA_RUNTIME_DIR = process.execPath; env.NODE_PATH = this.options.nodeModulesPath ? this.options.nodeModulesPath : (0, path_1.resolve)(require.resolve('express'), '..', '..'); return env; } } exports.Context = Context;