UNPKG

lemon-core

Version:
220 lines 8.6 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FunctionHandler = exports.FunctionSubHandler = void 0; /** * `lambda-handler.ts` * - main lambda handler. * * * @author Ian Kim <ian@lemoncloud.io> * @date 2023-10-30 initial version * * @copyright (C) lemoncloud.io 2023 - All Rights Reserved. */ // eslint-disable-next-line @typescript-eslint/no-unused-vars const engine_1 = require("../../engine"); const test_helper_1 = require("../../common/test-helper"); const NS = engine_1.$U.NS('FUNC', 'green'); // NAMESPACE TO BE PRINTED. class FunctionSubHandler { constructor(functions, type) { if (!functions) throw new Error('@functions (functions-handler) is required!'); this.functions = functions; this.type = type; if (functions && type) functions.setHandler(type, this); } } exports.FunctionSubHandler = FunctionSubHandler; /** * build reprot-error function in safe. * * @param isReport flag to report-error via sns * @return the last error message */ const buildReportError = (isReport) => (e, ctx, req, data) => { return (isReport ? (0, engine_1.doReportError)(e, ctx, req, data) : Promise.resolve(data)) .then(() => (0, test_helper_1.GETERR)(e)) .catch(test_helper_1.GETERR); }; /** * class: `LambdaHandler` * - general lambda handler so that routes to proper target handlers. */ class FunctionHandler { //! protected constructor. constructor(config) { //! handler map. this._map = {}; //! Find Service By Event this.findService = (ctx) => { const headers = (ctx && ctx.headers) || {}; (0, engine_1._log)(NS, `> headers =`, engine_1.$U.json(headers)); //! check if AZURE SB TOPICS Notification Subscription -> notification controller. if (ctx.invocationId) { for (const binding of ctx.bindingDefinitions) { if (binding.type === 'httpTrigger') { return 'web'; } else { if (binding.type === 'serviceBusTrigger' && binding.name === 'queue') { return 'sqs'; } if (binding.type === 'serviceBusTrigger' && binding.name === 'topic') { return 'sns'; } } } } else { if (ctx.requestContext && ctx.pathParameters !== undefined) { return 'web'; } } }; this.config = config; } /** * set service lambda handler. * @param type name of type * @param handler handler of service */ setHandler(type, handler) { let key = `${type || ''}`.toLowerCase().trim(); key = key === 'dynamo-stream' ? 'dds' : key; // console.info(`! set-handler[${type}] =`, typeof handler); if (key) this._map[key] = handler; } /** * decode event to proper handler. * - NOTE! - returns promised results with `async` * * @returns boolean */ handle(ctx, req) { return __awaiter(this, void 0, void 0, function* () { if (!ctx) throw new Error('@ctx is required!'); //! Check API parameters. const main = (ctx, req, callback) => { const type = this.findService(ctx); (0, engine_1._log)(NS, `main(${type})...`); const handler = this._map[type]; if (handler && typeof handler == 'function') { //! low level handler function. return handler(ctx, req, callback); } else if (handler && typeof handler == 'object') { //! must be `LambdaHandlerService`. const $svc = handler; return $svc.handle(ctx, req); } //! raise error if not found. (0, engine_1._inf)(NS, `WARN! unknown[${type}].event =`, engine_1.$U.json(event)); callback && callback(new Error(`400 UNKNOWN - service:${type}`)); }; //! call promised. const promise = (main, ctx, req) => new Promise((resolve, reject) => { try { let resolved = false; const R = main(ctx, req, (error, result) => { error && (0, engine_1._err)(NS, '! err@cb =', error); // !error && _inf(NS, '! res@cb =', result); if (error) reject(error); else if (!resolved) resolve(result); }); if (R !== undefined) { resolved = true; resolve(R); } } catch (e) { return reject(e); } }); //! call main.. (it will return result or promised) return promise(main, ctx, req) .then(_ => { // if (_ !== undefined) _log(NS, '! res =', $U.json(_)); if (_ !== undefined) (0, engine_1._log)(NS, '! res =', engine_1.$U.S(_, 320, 64, ' .... ')); //! cut result string. // ((context && context.done) || callback)(null, _); // return true; try { ctx.res = { status: _.statusCode, body: _.body, }; } catch (error) { ctx.res = { status: 500, body: error, }; } return _; }) .catch(e => { (0, engine_1._err)(NS, '! err =', e); if (!FunctionHandler.REPORT_ERROR) { // ((context && context.done) || callback)(e, null); // return false; throw e; } //! report this error. return (0, engine_1.doReportError)(e, ctx, req) .catch(_ => _) // safe call w/o error. .then(() => { // ((context && context.done) || callback)(e, null); // return false; throw e; }); }); }); } /** * handle param via protocol-service. * - sub-service could call this method() to bypass request. * * @param param protocol parameters */ handleProtocol(param) { return __awaiter(this, void 0, void 0, function* () { //! if valid API Request, then use $web's function. const $web = this._map['web']; if (!$web || typeof $web != 'object') throw new Error(`500 NO WEB HANDLER - name:web`); return $web.handleProtocol(param); }); } /** * (default) pack the origin context to application context. * - override this function if required! * * @param event origin event * @param $ctx origin context of lambda */ packContext($ctx, req) { return __awaiter(this, void 0, void 0, function* () { const context = {}; $ctx && (0, engine_1._log)(NS, `! context[${$ctx || ''}] =`, engine_1.$U.json($ctx)); return context; }); } } exports.FunctionHandler = FunctionHandler; //! shared config. FunctionHandler.REPORT_ERROR = engine_1.$U.env('REPORT_ERROR', '1') == '1'; //# sourceMappingURL=functions-handler.js.map