From 81eadfd9e5dab5767f3e0c6b93abc2d6308cd260 Mon Sep 17 00:00:00 2001 From: Ganesh S Acharya Date: Sat, 29 Jul 2023 19:15:42 +0530 Subject: [PATCH 01/17] Enhancement Added factory method to find key props in the incoming request. --- base/executor.class.js | 10 ++++++++-- helper/baseHelper.class.js | 16 ++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/base/executor.class.js b/base/executor.class.js index 542714d..7f2169d 100644 --- a/base/executor.class.js +++ b/base/executor.class.js @@ -21,9 +21,15 @@ class executor { try { this.setResponse('UNKNOWN_ERROR'); - + + // Property finding factory + const findPropInRequest = deepFindPropMaker(request) + + // Find the basic variables from the incoming request // Initializng basic variables - const { lng_key: lngKey, access_token: accessToken, enc_state: encState } = request.headers; + const lngKey = findPropInRequest("lng_key") + const encState = findPropInRequest("enc_state") + const accessToken = findPropInRequest("access_token") // Decide encryption mode. And enforce enc_state to be true if encryption is Strict const { ENCRYPTION_MODE } = JSON.parse(process.env.ENCRYPTION); diff --git a/helper/baseHelper.class.js b/helper/baseHelper.class.js index edd8d26..55378c4 100644 --- a/helper/baseHelper.class.js +++ b/helper/baseHelper.class.js @@ -120,6 +120,22 @@ class baseHelper { return requestData ? requestData : {}; } + + static deepFindPropMaker(obj) { + return (prop) => { + if (!obj || typeof obj !== 'object') return null; + if (obj.hasOwnProperty(prop) && obj[prop] !== null && obj[prop] !== undefined) { + return obj[prop]; + } + for (let key in obj) { + if (obj.hasOwnProperty(key)) { + let found = deepFindPropMaker(obj[key])(prop); + if (found) return found; + } + } + return null; + } + } } module.exports = baseHelper; From b85ee95513bc6f7c31ac5cf9e5cfb6c4679b0271 Mon Sep 17 00:00:00 2001 From: rishjs Date: Wed, 16 Aug 2023 18:01:36 +0530 Subject: [PATCH 02/17] initial commit --- base/executor.class.js | 99 +++++++++++++++++++++++++++--------------- 1 file changed, 63 insertions(+), 36 deletions(-) diff --git a/base/executor.class.js b/base/executor.class.js index 542714d..11fa0f9 100644 --- a/base/executor.class.js +++ b/base/executor.class.js @@ -11,6 +11,8 @@ const ParameterProcessor = require('./parameterProcessor.class'); const { encrypt, decrypt } = require('../helper/encryption'); const { ENC_MODE, DEFAULT_LNG_KEY, ENC_ENABLED } = require('../helper/globalConstants'); const jwt = require('../helper/jwt'); +const _ = require("lodash"); +const multiReplace = require('string-multiple-replace'); class executor { constructor() { @@ -18,23 +20,21 @@ class executor { } async executeRequest(request) { - try { this.setResponse('UNKNOWN_ERROR'); // Initializng basic variables const { lng_key: lngKey, access_token: accessToken, enc_state: encState } = request.headers; - // Decide encryption mode. And enforce enc_state to be true if encryption is Strict const { ENCRYPTION_MODE } = JSON.parse(process.env.ENCRYPTION); if (ENCRYPTION_MODE == ENC_MODE.STRICT && encState != ENC_ENABLED) { this.setResponse('ENCRYPTION_STATE_STRICTLY_ENABLED'); throw new Error(); } - const encryptionState = (ENCRYPTION_MODE == ENC_MODE.STRICT || (ENCRYPTION_MODE == ENC_MODE.OPTIONAL && encState == ENC_ENABLED)); - + this.encryptionState = (ENCRYPTION_MODE == ENC_MODE.STRICT || (ENCRYPTION_MODE == ENC_MODE.OPTIONAL && encState == ENC_ENABLED)); + // Set member variables - this.setMemberVariable('encryptionState', encryptionState); + this.setMemberVariable('encryptionState', this.encryptionState); if (lngKey) this.setMemberVariable('lng_key', lngKey); // Finalize methodName including custom route @@ -87,7 +87,7 @@ class executor { let requestData = baseHelper.parseRequestData(request, isFileExpected); // If encyption is enabled, then decrypt the request data - if (!isFileExpected && encryptionState) { + if (!isFileExpected &&this.encryptionState) { requestData = decrypt(requestData.data); if (typeof requestData === 'string') requestData = JSON.parse(requestData); @@ -111,28 +111,14 @@ class executor { // Initiate and Execute method this.responseData = await actionInstance.executeMethod(); const { responseString, responseOptions, packageName } = actionInstance.getResponseString(); - const { responseCode, responseMessage } = this.getResponse(responseString, responseOptions, packageName); - - // If encryption mode is enabled then encrypt the response data - if (encryptionState) { - // this.responseData = new URLSearchParams({data: encrypt(this.responseData)}).toString().replace("data=",''); - this.responseData = encrypt(this.responseData); - } + const response = this.getResponse(responseString, responseOptions, packageName); + return response; - return { - responseCode, - responseMessage, - responseData: this.responseData - }; } catch (e) { console.log("Exception caught", e); - const { responseCode, responseMessage } = this.getResponse(); + const response = this.getResponse(e === "NODE_VERSION_ERROR" ? e : ""); if (process.env.MODE == "DEV" && e.message) this.setDebugMessage(e.message); - return { - responseCode, - responseMessage, - responseData: {} - }; + return response; } } @@ -191,13 +177,14 @@ class executor { } const BASE_RESPONSE = require(path.resolve(process.cwd(), `src/global/i18n/response.js`)).RESPONSE; const PROJECT_RESPONSE = require(`../i18n/response.js`).RESPONSE; + const CUSTOM_RESPONSE_STRUCTURE = require(path.resolve(process.cwd(), `src/config/customResponseStructure.json`)); let RESP = { ...PROJECT_RESPONSE, ...BASE_RESPONSE }; - + //let CUSTOM_RESPONSE_STRUCTURE = {...custom_response}; if (packageName) { try { let packageVals = packageName.split('/'); - const PACKAGE_RESPONSE = require(path.resolve(process.cwd(), `njs2_modules/${[...packageVals.slice(0, packageVals.length - 1)].join('/')}/contract/response.json`)); + const PACKAGE_RESPONSE = require(path.resolve(process.cwd(), `node_modules/${[...packageVals.slice(0, packageVals.length - 1)].join('/')}/contract/response.json`)); RESP = { ...RESP, ...PACKAGE_RESPONSE }; } catch { } @@ -206,24 +193,64 @@ class executor { if (!RESP[this.responseString]) { RESP = RESP["RESPONSE_CODE_NOT_FOUND"]; } else { - RESP = RESP[this.responseString]; + RESP = {...RESP[this.responseString]}; } this.responseCode = RESP.responseCode; this.responseMessage = this.lng_key && RESP.responseMessage[this.lng_key] ? RESP.responseMessage[this.lng_key] : RESP.responseMessage[DEFAULT_LNG_KEY]; + RESP.responseMessage = this.lng_key && RESP.responseMessage[this.lng_key] + ? RESP.responseMessage[this.lng_key] + : RESP.responseMessage[DEFAULT_LNG_KEY]; + if(this.responseOptions) + Object.keys(this.responseOptions).map(keyName => { + this.responseMessage = this.responseMessage.replace(keyName, this.responseOptions[keyName]); + }) + ; + + RESP.responseData = this.responseData; + + //If no response structure specified or response structure is invalid then return default response + if(!CUSTOM_RESPONSE_STRUCTURE) { + return { + responseCode: this.responseCode, + responseMessage: this.responseMessage, + responseData: this.encryptionCheck(this.responseData) + }; + } + return this.parseResponseData(CUSTOM_RESPONSE_STRUCTURE,RESP); + + } - if (this.responseOptions) - Object.keys(this.responseOptions).map(keyName => { - this.responseMessage = this.responseMessage.replace(keyName, this.responseOptions[keyName]); - }); + parseResponseData(CUSTOM_RESPONSE_STRUCTURE,RESP){ + Object.entries(RESP).forEach(array => { + const [key,value] = array; + if(typeof value === 'object'){ + RESP[key] = JSON.stringify(value); + } + }); + + let compiled = _.template(typeof CUSTOM_RESPONSE_STRUCTURE === 'string' ? CUSTOM_RESPONSE_STRUCTURE : JSON.stringify(CUSTOM_RESPONSE_STRUCTURE))(RESP); - return { - responseCode: this.responseCode, - responseMessage: this.responseMessage, - responseData: this.responseData - }; + const matcherObj = { + '"{': '{', + '}"': '}', + } + + const replacedString =multiReplace(compiled, matcherObj); + console.log(replacedString); + return typeof CUSTOM_RESPONSE_STRUCTURE === 'string' ? replacedString : JSON.parse(replacedString); + + } + + // If encryption mode is enabled then encrypt the response data + encryptionCheck(value){ + if (value && this.encryptionState) { + // this.responseData = new URLSearchParams({data: encrypt(this.responseData)}).toString().replace("data=",''); + value = encrypt(value); + } + return value; } } From 7e438ec2dd370aed634e3b3e40373b2670fd6a67 Mon Sep 17 00:00:00 2001 From: Ganesh S Acharya Date: Thu, 17 Aug 2023 13:12:32 +0530 Subject: [PATCH 03/17] Added Serverless Wrapper for Express --- package.json | 1 + template/frameworkStructure/lambda.js | 82 +++++++++++++++++++++------ 2 files changed, 67 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 85cc4da..447cbc5 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "node-cron": "^3.0.2", "query-string": "^7.0.1", "require-dir": "^1.2.0", + "serverless-http": "^3.2.0", "socket.io": "^4.1.2" }, "njs2-type": "base", diff --git a/template/frameworkStructure/lambda.js b/template/frameworkStructure/lambda.js index 1b19159..1958c58 100644 --- a/template/frameworkStructure/lambda.js +++ b/template/frameworkStructure/lambda.js @@ -1,26 +1,76 @@ -const serverless = require('./serverless'); +const serverlessExpress = require('serverless-http') +const express = require('express') +const multer = require('multer'); +const app = express() +const upload = multer(); + const websockets = require('./websockets'); -//const init = require('./src/library/roomHandler/init'); // Make sure to create this file and add defualt content. +const { Executor } = require("@njs2/base"); + +app.use(express.json()); +app.use(express.urlencoded({ extended: true })); +app.use(upload.any()); + + +app.all('*', async function (req, res) { + + console.log("INSIDE LAMBDA BODY") + + const {event} = req.apiGateway + let result = "All Ok!" -module.exports.handler = async (event) => { try { const requestType = event.stageVariables.requestType; + console.log("INSIDE LAMBDA requestType: ", requestType) + if (requestType === 'API') { - return await serverless.execute(event); + result = await lambdaExecutor(event) } else if (requestType === 'Socket') { - return await websockets.handler(event); - } else if (requestType === 'mCron') { - // get the taskName + result = await websockets.handler(event); + } else if (requestType === 'scheduler') { const taskName = event.stageVariables.taskName; - // require the file by taskName - const mCron = require(`./src/tasks/${taskName}.task.js`); - // call default of taskName - mCron(); - } else if (requestType === 'cron') { - const cron = require(`./cron`); - cron(); + const task = require(`./src/tasks/${taskName}.task.js`); + task(); + } + res.send({...result}) + } catch(error) { + console.error(error) + res.send({ + responseCode: 200, + responseMessage: "Something went wrong!", + responseData: {} + }) + } +}) + +exports.handler = serverlessExpress(app) + +async function lambdaExecutor(eventObject) { + try { + const { httpMethod, queryStringParameters, path, files, body, headers } = eventObject + // Neutralize input parameter received from express for Executor.executeRequest + let executorReq = {}; + executorReq.httpMethod = httpMethod; + executorReq.queryStringParameters = queryStringParameters; + executorReq.body = body; + executorReq.pathParameters = { + proxy: path.length ? path.slice(1) : path + }; + executorReq.headers = headers; + if (files && files.length) { + if (files.length > 1) throw new Error("Only one file upload at a time is allowed") + files.forEach(file => { + executorReq.body[file.fieldname] = { + type: 'file', + filename: file.originalname, + contentType: file.mimetype, + content: file.buffer + }; + }); } + const executor = new Executor(); + return await executor.executeRequest(executorReq); } catch (error) { - console.error(error); + throw error } -}; \ No newline at end of file +} \ No newline at end of file From 990fe48e42b447193ccf645381012a0d8b399418 Mon Sep 17 00:00:00 2001 From: rishjs Date: Thu, 17 Aug 2023 13:49:56 +0530 Subject: [PATCH 04/17] enabled encryption state for response structure --- base/executor.class.js | 50 +++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 32 deletions(-) diff --git a/base/executor.class.js b/base/executor.class.js index 11fa0f9..43c8cb3 100644 --- a/base/executor.class.js +++ b/base/executor.class.js @@ -31,7 +31,7 @@ class executor { this.setResponse('ENCRYPTION_STATE_STRICTLY_ENABLED'); throw new Error(); } - this.encryptionState = (ENCRYPTION_MODE == ENC_MODE.STRICT || (ENCRYPTION_MODE == ENC_MODE.OPTIONAL && encState == ENC_ENABLED)); + const encryptionState = (ENCRYPTION_MODE == ENC_MODE.STRICT || (ENCRYPTION_MODE == ENC_MODE.OPTIONAL && encState == ENC_ENABLED)); // Set member variables this.setMemberVariable('encryptionState', this.encryptionState); @@ -111,6 +111,13 @@ class executor { // Initiate and Execute method this.responseData = await actionInstance.executeMethod(); const { responseString, responseOptions, packageName } = actionInstance.getResponseString(); + + // If encryption mode is enabled then encrypt the response data + if (encryptionState) { + // this.responseData = new URLSearchParams({data: encrypt(this.responseData)}).toString().replace("data=",''); + this.responseData = encrypt(this.responseData); + } + const response = this.getResponse(responseString, responseOptions, packageName); return response; @@ -177,10 +184,10 @@ class executor { } const BASE_RESPONSE = require(path.resolve(process.cwd(), `src/global/i18n/response.js`)).RESPONSE; const PROJECT_RESPONSE = require(`../i18n/response.js`).RESPONSE; - const CUSTOM_RESPONSE_STRUCTURE = require(path.resolve(process.cwd(), `src/config/customResponseStructure.json`)); + const CUSTOM_RESPONSE_STRUCTURE = require(path.resolve(process.cwd(), `src/config/responseTemplate.json`)); let RESP = { ...PROJECT_RESPONSE, ...BASE_RESPONSE }; - //let CUSTOM_RESPONSE_STRUCTURE = {...custom_response}; + if (packageName) { try { let packageVals = packageName.split('/'); @@ -196,29 +203,17 @@ class executor { RESP = {...RESP[this.responseString]}; } - this.responseCode = RESP.responseCode; - this.responseMessage = this.lng_key && RESP.responseMessage[this.lng_key] - ? RESP.responseMessage[this.lng_key] - : RESP.responseMessage[DEFAULT_LNG_KEY]; RESP.responseMessage = this.lng_key && RESP.responseMessage[this.lng_key] ? RESP.responseMessage[this.lng_key] : RESP.responseMessage[DEFAULT_LNG_KEY]; - if(this.responseOptions) - Object.keys(this.responseOptions).map(keyName => { - this.responseMessage = this.responseMessage.replace(keyName, this.responseOptions[keyName]); - }) - ; RESP.responseData = this.responseData; - - //If no response structure specified or response structure is invalid then return default response - if(!CUSTOM_RESPONSE_STRUCTURE) { - return { - responseCode: this.responseCode, - responseMessage: this.responseMessage, - responseData: this.encryptionCheck(this.responseData) - }; - } + + if(this.responseOptions) + Object.keys(this.responseOptions).map(keyName => { + RESP.responseMessage = RESP.responseMessage.replace(keyName, this.responseOptions[keyName]); + }); + return this.parseResponseData(CUSTOM_RESPONSE_STRUCTURE,RESP); } @@ -230,7 +225,7 @@ class executor { RESP[key] = JSON.stringify(value); } }); - + let compiled = _.template(typeof CUSTOM_RESPONSE_STRUCTURE === 'string' ? CUSTOM_RESPONSE_STRUCTURE : JSON.stringify(CUSTOM_RESPONSE_STRUCTURE))(RESP); const matcherObj = { @@ -239,18 +234,9 @@ class executor { } const replacedString =multiReplace(compiled, matcherObj); - console.log(replacedString); - return typeof CUSTOM_RESPONSE_STRUCTURE === 'string' ? replacedString : JSON.parse(replacedString); - } + return typeof CUSTOM_RESPONSE_STRUCTURE === 'string' ? replacedString : JSON.parse(replacedString); - // If encryption mode is enabled then encrypt the response data - encryptionCheck(value){ - if (value && this.encryptionState) { - // this.responseData = new URLSearchParams({data: encrypt(this.responseData)}).toString().replace("data=",''); - value = encrypt(value); - } - return value; } } From 42996f68b0a256a023afcfc34d4065bafffa7f5c Mon Sep 17 00:00:00 2001 From: rishjs Date: Thu, 17 Aug 2023 15:17:17 +0530 Subject: [PATCH 05/17] updates in responsestructure --- base/executor.class.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/base/executor.class.js b/base/executor.class.js index 43c8cb3..37022de 100644 --- a/base/executor.class.js +++ b/base/executor.class.js @@ -207,8 +207,8 @@ class executor { ? RESP.responseMessage[this.lng_key] : RESP.responseMessage[DEFAULT_LNG_KEY]; - RESP.responseData = this.responseData; - + typeof this.responseData === 'object' ? RESP = {...RESP, ...this.responseData} : RESP.responseData = this.responseData; + if(this.responseOptions) Object.keys(this.responseOptions).map(keyName => { RESP.responseMessage = RESP.responseMessage.replace(keyName, this.responseOptions[keyName]); From 8a883d5fbeed9f76327771f2d6c342820d55300b Mon Sep 17 00:00:00 2001 From: rishjs Date: Thu, 17 Aug 2023 16:08:29 +0530 Subject: [PATCH 06/17] bug fix : custom response structure --- base/executor.class.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/executor.class.js b/base/executor.class.js index 37022de..8bc842c 100644 --- a/base/executor.class.js +++ b/base/executor.class.js @@ -207,7 +207,7 @@ class executor { ? RESP.responseMessage[this.lng_key] : RESP.responseMessage[DEFAULT_LNG_KEY]; - typeof this.responseData === 'object' ? RESP = {...RESP, ...this.responseData} : RESP.responseData = this.responseData; + (typeof this.responseData === 'object' && Object.keys(this.responseData).length) ? RESP = {...RESP, ...this.responseData} : RESP.responseData = this.responseData; if(this.responseOptions) Object.keys(this.responseOptions).map(keyName => { From 34ba790664c85b9a22f13f63afdc9867ea2929ed Mon Sep 17 00:00:00 2001 From: rishjs Date: Thu, 17 Aug 2023 17:40:22 +0530 Subject: [PATCH 07/17] bug fix:handled array responses --- base/executor.class.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/base/executor.class.js b/base/executor.class.js index 8bc842c..3c9b36e 100644 --- a/base/executor.class.js +++ b/base/executor.class.js @@ -207,7 +207,7 @@ class executor { ? RESP.responseMessage[this.lng_key] : RESP.responseMessage[DEFAULT_LNG_KEY]; - (typeof this.responseData === 'object' && Object.keys(this.responseData).length) ? RESP = {...RESP, ...this.responseData} : RESP.responseData = this.responseData; + RESP.responseData = this.responseData; if(this.responseOptions) Object.keys(this.responseOptions).map(keyName => { @@ -231,6 +231,8 @@ class executor { const matcherObj = { '"{': '{', '}"': '}', + '"[': '[', + ']"': ']' } const replacedString =multiReplace(compiled, matcherObj); From af2275b157e70d46d68d17543b793b4d2dca6586 Mon Sep 17 00:00:00 2001 From: rishjs Date: Tue, 29 Aug 2023 10:00:17 +0530 Subject: [PATCH 08/17] responseTemplate Feedback changes --- base/executor.class.js | 72 +++++++++++++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 19 deletions(-) mode change 100644 => 100755 base/executor.class.js diff --git a/base/executor.class.js b/base/executor.class.js old mode 100644 new mode 100755 index 3c9b36e..df6d8d1 --- a/base/executor.class.js +++ b/base/executor.class.js @@ -13,6 +13,7 @@ const { ENC_MODE, DEFAULT_LNG_KEY, ENC_ENABLED } = require('../helper/globalCons const jwt = require('../helper/jwt'); const _ = require("lodash"); const multiReplace = require('string-multiple-replace'); +const fs = require("fs"); class executor { constructor() { @@ -184,7 +185,14 @@ class executor { } const BASE_RESPONSE = require(path.resolve(process.cwd(), `src/global/i18n/response.js`)).RESPONSE; const PROJECT_RESPONSE = require(`../i18n/response.js`).RESPONSE; - const CUSTOM_RESPONSE_STRUCTURE = require(path.resolve(process.cwd(), `src/config/responseTemplate.json`)); + + let CUSTOM_RESPONSE_TEMPLATE,responseTemplate; + try{ + CUSTOM_RESPONSE_TEMPLATE = require(path.resolve(process.cwd(), `src/config/responseTemplate.json`)); + responseTemplate = this.isValidResponseStructure(CUSTOM_RESPONSE_TEMPLATE); + }catch(error){ + responseTemplate = this.isValidResponseStructure(""); + } let RESP = { ...PROJECT_RESPONSE, ...BASE_RESPONSE }; @@ -214,32 +222,58 @@ class executor { RESP.responseMessage = RESP.responseMessage.replace(keyName, this.responseOptions[keyName]); }); - return this.parseResponseData(CUSTOM_RESPONSE_STRUCTURE,RESP); + return this.parseResponseData(responseTemplate,RESP); } - parseResponseData(CUSTOM_RESPONSE_STRUCTURE,RESP){ - Object.entries(RESP).forEach(array => { - const [key,value] = array; - if(typeof value === 'object'){ - RESP[key] = JSON.stringify(value); + parseResponseData(responseTemplate,RESP){ + try{ + Object.entries(RESP).forEach(array => { + const [key,value] = array; + if(typeof value === 'object'){ + RESP[key] = JSON.stringify(value); + } + }); + + const compiled = _.template(typeof responseTemplate === 'string' ? responseTemplate : JSON.stringify(responseTemplate)); + + const resultTemplate = compiled(RESP); + + const matcherObj = { + '"{': '{', + '}"': '}', + '"[': '[', + ']"': ']' } - }); - - let compiled = _.template(typeof CUSTOM_RESPONSE_STRUCTURE === 'string' ? CUSTOM_RESPONSE_STRUCTURE : JSON.stringify(CUSTOM_RESPONSE_STRUCTURE))(RESP); - - const matcherObj = { - '"{': '{', - '}"': '}', - '"[': '[', - ']"': ']' - } - const replacedString =multiReplace(compiled, matcherObj); + const replacedString =multiReplace(resultTemplate, matcherObj); - return typeof CUSTOM_RESPONSE_STRUCTURE === 'string' ? replacedString : JSON.parse(replacedString); + return typeof responseTemplate === 'string' ? replacedString : JSON.parse(replacedString); + }catch(error){ + throw new Error("parseResponseData Error:"+error); + } + } + isValidResponseStructure(CUSTOM_RESPONSE_TEMPLATE){ + // Check if type Object and object is empty or Check if type Array and array is not empty + if( + CUSTOM_RESPONSE_TEMPLATE && + Object.prototype.toString.call(CUSTOM_RESPONSE_TEMPLATE) === '[object Object]' && + Object.keys(CUSTOM_RESPONSE_TEMPLATE).length === 0 || + Array.isArray(CUSTOM_RESPONSE_TEMPLATE) && + CUSTOM_RESPONSE_TEMPLATE.length === 0 || + CUSTOM_RESPONSE_TEMPLATE === "" + ) { + CUSTOM_RESPONSE_TEMPLATE={ + "responseCode":"<%=responseCode%>", + "responseMessage":"<%=responseMessage%>", + "responseData":"<%=responseData%>" + } + } + fs.writeFileSync(path.resolve(process.cwd(), `src/config/responseTemplate.json`), JSON.stringify(CUSTOM_RESPONSE_TEMPLATE), 'utf8'); + return CUSTOM_RESPONSE_TEMPLATE; } + } module.exports = executor; \ No newline at end of file From 6f7e54e51ca46994f6577e205ea0f07a7c802dd3 Mon Sep 17 00:00:00 2001 From: rishjs Date: Mon, 4 Sep 2023 17:43:09 +0530 Subject: [PATCH 09/17] feedback changes --- base/executor.class.js | 36 +++++------------------------------- 1 file changed, 5 insertions(+), 31 deletions(-) diff --git a/base/executor.class.js b/base/executor.class.js index df6d8d1..043927a 100755 --- a/base/executor.class.js +++ b/base/executor.class.js @@ -186,13 +186,7 @@ class executor { const BASE_RESPONSE = require(path.resolve(process.cwd(), `src/global/i18n/response.js`)).RESPONSE; const PROJECT_RESPONSE = require(`../i18n/response.js`).RESPONSE; - let CUSTOM_RESPONSE_TEMPLATE,responseTemplate; - try{ - CUSTOM_RESPONSE_TEMPLATE = require(path.resolve(process.cwd(), `src/config/responseTemplate.json`)); - responseTemplate = this.isValidResponseStructure(CUSTOM_RESPONSE_TEMPLATE); - }catch(error){ - responseTemplate = this.isValidResponseStructure(""); - } + const CUSTOM_RESPONSE_TEMPLATE = require(path.resolve(process.cwd(), `src/config/responseTemplate.json`)); let RESP = { ...PROJECT_RESPONSE, ...BASE_RESPONSE }; @@ -222,11 +216,11 @@ class executor { RESP.responseMessage = RESP.responseMessage.replace(keyName, this.responseOptions[keyName]); }); - return this.parseResponseData(responseTemplate,RESP); + return this.parseResponseData(CUSTOM_RESPONSE_TEMPLATE,RESP); } - parseResponseData(responseTemplate,RESP){ + parseResponseData(CUSTOM_RESPONSE_TEMPLATE,RESP){ try{ Object.entries(RESP).forEach(array => { const [key,value] = array; @@ -235,7 +229,7 @@ class executor { } }); - const compiled = _.template(typeof responseTemplate === 'string' ? responseTemplate : JSON.stringify(responseTemplate)); + const compiled = _.template(typeof CUSTOM_RESPONSE_TEMPLATE === 'string' ? CUSTOM_RESPONSE_TEMPLATE : JSON.stringify(CUSTOM_RESPONSE_TEMPLATE)); const resultTemplate = compiled(RESP); @@ -248,31 +242,11 @@ class executor { const replacedString =multiReplace(resultTemplate, matcherObj); - return typeof responseTemplate === 'string' ? replacedString : JSON.parse(replacedString); + return typeof CUSTOM_RESPONSE_TEMPLATE === 'string' ? replacedString : JSON.parse(replacedString); }catch(error){ throw new Error("parseResponseData Error:"+error); } } - - isValidResponseStructure(CUSTOM_RESPONSE_TEMPLATE){ - // Check if type Object and object is empty or Check if type Array and array is not empty - if( - CUSTOM_RESPONSE_TEMPLATE && - Object.prototype.toString.call(CUSTOM_RESPONSE_TEMPLATE) === '[object Object]' && - Object.keys(CUSTOM_RESPONSE_TEMPLATE).length === 0 || - Array.isArray(CUSTOM_RESPONSE_TEMPLATE) && - CUSTOM_RESPONSE_TEMPLATE.length === 0 || - CUSTOM_RESPONSE_TEMPLATE === "" - ) { - CUSTOM_RESPONSE_TEMPLATE={ - "responseCode":"<%=responseCode%>", - "responseMessage":"<%=responseMessage%>", - "responseData":"<%=responseData%>" - } - } - fs.writeFileSync(path.resolve(process.cwd(), `src/config/responseTemplate.json`), JSON.stringify(CUSTOM_RESPONSE_TEMPLATE), 'utf8'); - return CUSTOM_RESPONSE_TEMPLATE; - } } From 02a8b7bbd43bd0685b609cb682139cbe092e58fa Mon Sep 17 00:00:00 2001 From: rishjs Date: Mon, 4 Sep 2023 17:48:14 +0530 Subject: [PATCH 10/17] added responseTemplate.json file in template folder --- template/frameworkStructure/src/config/responseTemplate.json | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 template/frameworkStructure/src/config/responseTemplate.json diff --git a/template/frameworkStructure/src/config/responseTemplate.json b/template/frameworkStructure/src/config/responseTemplate.json new file mode 100644 index 0000000..9b698f2 --- /dev/null +++ b/template/frameworkStructure/src/config/responseTemplate.json @@ -0,0 +1,5 @@ +{ + "responseCode":"<%=responseCode%>", + "responseMessage":"<%=responseMessage%>", + "responseData":"<%=message%>" +} \ No newline at end of file From 60409bbb05e961ac53e54354459620078658898a Mon Sep 17 00:00:00 2001 From: rishjs Date: Mon, 4 Sep 2023 18:25:02 +0530 Subject: [PATCH 11/17] updated responseTemplate.json file --- template/frameworkStructure/src/config/responseTemplate.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/frameworkStructure/src/config/responseTemplate.json b/template/frameworkStructure/src/config/responseTemplate.json index 9b698f2..4e90d83 100644 --- a/template/frameworkStructure/src/config/responseTemplate.json +++ b/template/frameworkStructure/src/config/responseTemplate.json @@ -1,5 +1,5 @@ { "responseCode":"<%=responseCode%>", "responseMessage":"<%=responseMessage%>", - "responseData":"<%=message%>" + "responseData":"<%=responseData%>" } \ No newline at end of file From d443ef91cf8192043a151c8655e220e7fb092e2e Mon Sep 17 00:00:00 2001 From: rishjs Date: Mon, 4 Sep 2023 18:32:13 +0530 Subject: [PATCH 12/17] minor bug fix --- base/executor.class.js | 1 - 1 file changed, 1 deletion(-) diff --git a/base/executor.class.js b/base/executor.class.js index 043927a..dbb0872 100755 --- a/base/executor.class.js +++ b/base/executor.class.js @@ -13,7 +13,6 @@ const { ENC_MODE, DEFAULT_LNG_KEY, ENC_ENABLED } = require('../helper/globalCons const jwt = require('../helper/jwt'); const _ = require("lodash"); const multiReplace = require('string-multiple-replace'); -const fs = require("fs"); class executor { constructor() { From a4e99a93aa83cd142250dfc5769405e02ecb765a Mon Sep 17 00:00:00 2001 From: rishjs Date: Wed, 6 Sep 2023 10:21:11 +0530 Subject: [PATCH 13/17] updated feedback changes --- base/executor.class.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/base/executor.class.js b/base/executor.class.js index dbb0872..88a18f5 100755 --- a/base/executor.class.js +++ b/base/executor.class.js @@ -224,7 +224,7 @@ class executor { Object.entries(RESP).forEach(array => { const [key,value] = array; if(typeof value === 'object'){ - RESP[key] = JSON.stringify(value); + RESP[key] = "{" + JSON.stringify(value) + "}"; } }); @@ -233,13 +233,13 @@ class executor { const resultTemplate = compiled(RESP); const matcherObj = { - '"{': '{', - '}"': '}', - '"[': '[', - ']"': ']' + '"{{': '{', + '}}"': '}', + '"{[': '[', + ']}"': ']' } - const replacedString =multiReplace(resultTemplate, matcherObj); + const replacedString = multiReplace(resultTemplate, matcherObj); return typeof CUSTOM_RESPONSE_TEMPLATE === 'string' ? replacedString : JSON.parse(replacedString); }catch(error){ From cffc7217f11ddf8c8a32bf282ed66c404f258781 Mon Sep 17 00:00:00 2001 From: Ganesh S Acharya Date: Wed, 20 Sep 2023 14:40:08 +0530 Subject: [PATCH 14/17] FEATURE: Added metadata append to actionInstance based on configs --- base/executor.class.js | 8 +++++ helper/baseHelper.class.js | 29 +++++++++++++++++++ .../frameworkStructure/src/config/config.json | 1 + 3 files changed, 38 insertions(+) diff --git a/base/executor.class.js b/base/executor.class.js index 7f2169d..3668fae 100644 --- a/base/executor.class.js +++ b/base/executor.class.js @@ -86,6 +86,14 @@ class executor { actionInstance.setMemberVariable('userObj', data); } + // Parse the incoming request object and find if the metadata configs are present + // if present, group them under metadata key and make it action instance member + const metaConfig = process.env["METADATA"]; + if(metaConfig && baseHelper.isJSON(metaConfig)) { + const metadata = baseHelper.populateMetadata(request, JSON.parse(metaConfig)); + actionInstance.setMemberVariable('metadata', metadata); + } + // validate & process request parameters const parameterProcessor = new ParameterProcessor(); const params = initInstance.getParameter(); diff --git a/helper/baseHelper.class.js b/helper/baseHelper.class.js index 55378c4..3ec6e41 100644 --- a/helper/baseHelper.class.js +++ b/helper/baseHelper.class.js @@ -136,6 +136,35 @@ class baseHelper { return null; } } + + static populateMetadata(request, configs) { + + if(configs.length == 0) return {} + + const deepFindPropInRequestObject = this.deepFindPropMaker(request) + + const keys = configs.map(key => key.trim()); + + let resultObj = {}; + + for (const key of keys) { + const value = deepFindPropInRequestObject(key); + if (value !== undefined) { + resultObj[key] = value; + } + } + return resultObj + } + + static isJSON(str) { + try { + JSON.parse(str); + return true; + } catch (e) { + return false; + } + } + } module.exports = baseHelper; diff --git a/template/frameworkStructure/src/config/config.json b/template/frameworkStructure/src/config/config.json index 60361a0..f01453c 100644 --- a/template/frameworkStructure/src/config/config.json +++ b/template/frameworkStructure/src/config/config.json @@ -16,6 +16,7 @@ "END_POINT": "", "LAMBDA_FUNCTION_NAME": "" }, + "METADATA": [], "AUTH": { "AUTH_MODE": "JWT", "JWT_SECRET": "123", From 86a8193655d58897d42e1056901cb982b2d21290 Mon Sep 17 00:00:00 2001 From: Ganesh S Acharya Date: Thu, 21 Sep 2023 14:36:16 +0530 Subject: [PATCH 15/17] BUGFIX: deepFindPropMaker call is not done properly --- helper/baseHelper.class.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helper/baseHelper.class.js b/helper/baseHelper.class.js index 3ec6e41..baaca65 100644 --- a/helper/baseHelper.class.js +++ b/helper/baseHelper.class.js @@ -129,7 +129,7 @@ class baseHelper { } for (let key in obj) { if (obj.hasOwnProperty(key)) { - let found = deepFindPropMaker(obj[key])(prop); + let found = this.deepFindPropMaker(obj[key])(prop); if (found) return found; } } From 917e617ee79ae19a44a1e9556ce6ed3d6a9b79be Mon Sep 17 00:00:00 2001 From: Ganesh S Acharya Date: Thu, 21 Sep 2023 14:39:44 +0530 Subject: [PATCH 16/17] BUGFIX: deepFindPropMaker call is not done properly --- base/executor.class.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/executor.class.js b/base/executor.class.js index 3668fae..139f5a0 100644 --- a/base/executor.class.js +++ b/base/executor.class.js @@ -23,7 +23,7 @@ class executor { this.setResponse('UNKNOWN_ERROR'); // Property finding factory - const findPropInRequest = deepFindPropMaker(request) + const findPropInRequest = baseHelper.deepFindPropMaker(request) // Find the basic variables from the incoming request // Initializng basic variables From 0b6f5a41905ae7e51bf673e53ca3fb3a9d209eef Mon Sep 17 00:00:00 2001 From: Ganesh A Date: Tue, 26 Sep 2023 23:29:01 +0530 Subject: [PATCH 17/17] debug logs removed BUGFIX: queryString.parse Null Prototype issue --- template/frameworkStructure/lambda.js | 10 ++-------- template/frameworkStructure/serverless.js | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/template/frameworkStructure/lambda.js b/template/frameworkStructure/lambda.js index 1958c58..cd96eb0 100644 --- a/template/frameworkStructure/lambda.js +++ b/template/frameworkStructure/lambda.js @@ -13,16 +13,10 @@ app.use(upload.any()); app.all('*', async function (req, res) { - - console.log("INSIDE LAMBDA BODY") - const {event} = req.apiGateway - let result = "All Ok!" - + let result = {} try { const requestType = event.stageVariables.requestType; - console.log("INSIDE LAMBDA requestType: ", requestType) - if (requestType === 'API') { result = await lambdaExecutor(event) } else if (requestType === 'Socket') { @@ -36,7 +30,7 @@ app.all('*', async function (req, res) { } catch(error) { console.error(error) res.send({ - responseCode: 200, + responseCode: 100011, responseMessage: "Something went wrong!", responseData: {} }) diff --git a/template/frameworkStructure/serverless.js b/template/frameworkStructure/serverless.js index 1a26559..f0fbe10 100644 --- a/template/frameworkStructure/serverless.js +++ b/template/frameworkStructure/serverless.js @@ -11,7 +11,7 @@ module.exports.execute = async (event) => { let fileCount = 0; if (event.headers["Content-Type"] === "application/x-www-form-urlencoded") { const querystring = require("querystring"); - event.body = querystring.parse(event.body); + event.body = Object.assign({}, querystring.parse(event.body)); } if (