Skip to content

Commit e948ca2

Browse files
committed
feat: processOperators() to execute/rturn operator value
1 parent daf7438 commit e948ca2

File tree

1 file changed

+143
-20
lines changed

1 file changed

+143
-20
lines changed

src/server.js

Lines changed: 143 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,19 @@ class CoCreateLazyLoader {
185185
}
186186
}
187187

188-
data.postmark = await method.apply(instance, params);
188+
// TODO: should run processOperators before and after in order to perform complex opertions
189+
// let execute = webhook.events[eventName];
190+
// if (execute) {
191+
// execute = await processOperators(data, execute);
192+
// }
193+
194+
data[name] = await method.apply(instance, params);
195+
196+
// let execute = webhook.events[eventName];
197+
// if (execute) {
198+
// execute = await processOperators(data, execute);
199+
// }
200+
189201
return data
190202
} catch (error) {
191203
data.error = error.message
@@ -208,22 +220,13 @@ class CoCreateLazyLoader {
208220
name = name[3] || name[2] || name[1]
209221

210222
// TODO: webhook secert could be a key pair
211-
let webhookSecret, webhookObject
212223
const webhook = data.apis[environment].webhooks[name];
213224
if (!webhook)
214225
throw new Error(`Webhook ${name} is not defined`);
215-
else if (typeof webhook === 'string')
216-
webhookSecret = webhook
217-
else if (webhook.webhookSecret) {
218-
webhookSecret = webhook.webhookSecret
219-
webhookObject = webhook.webhookObject
220-
// TODO: webhook could conatin $crud to get get webhook data
221-
} else
222-
throw new Error(`Webhook secret ${name} is not defined`);
223-
224-
// const webhookSecret = data.apis[environment].webhooks[name];
225-
if (webhookSecret !== req.headers[name])
226-
throw new Error(`Webhook secret failed for ${name}. Unauthorized access attempt.`);
226+
else if (!webhook.eventKey)
227+
throw new Error(`Webhook ${name} eventKey is not defined`);
228+
else if (!webhook.events)
229+
throw new Error(`Webhook ${name} events is not defined`);
227230

228231
let rawBody = '';
229232
await new Promise((resolve, reject) => {
@@ -238,13 +241,70 @@ class CoCreateLazyLoader {
238241
});
239242
});
240243

241-
// TODO: if decrypt and validation is builtin to service
242-
// const service = require(config.path);
243-
// const instance = new service[config.initialize](key);
244+
let parameters, method
245+
246+
if (webhook.events[webhook.eventKey].authenticate) {
247+
method = webhook.events[eventName].authenticate.method
248+
parameters = webhook.events[eventName].authenticate.parameters
249+
}
250+
251+
if (!parameters && webhook.authenticate && webhook.authenticate.parameters) {
252+
parameters = webhook.authenticate.parameters
253+
} else
254+
throw new Error(`Webhook secret ${name} is not defined`);
255+
256+
if (!method && webhook.authenticate)
257+
method = webhook.authenticate.method
258+
259+
if (!method && parameters[0] !== parameters[1])
260+
throw new Error(`Webhook secret failed for ${name}. Unauthorized access attempt.`);
261+
262+
263+
let event, eventName
264+
if (!method) {
265+
event = JSON.parse(rawBody)
266+
eventName = event[webhook.eventKey]
267+
268+
if (!eventName) {
269+
throw new Error(`Webhook ${name} eventKey: ${webhook.eventKey} could not be found in the event.`);
270+
} else if (!webhook.events[eventName]) {
271+
throw new Error(`Webhook ${name} eventName: ${webhook.eventName} is not defined.`);
272+
} else if (webhook.events[eventName].authenticate) {
273+
method = webhook.events[eventName].authenticate.method
274+
parameters = webhook.events[eventName].authenticate.parameters
275+
}
276+
277+
if (!parameters && webhook.authenticate && webhook.authenticate.parameters) {
278+
parameters = webhook.authenticate.parameters
279+
} else
280+
throw new Error(`Webhook secret ${name} is not defined`);
281+
282+
if (!method && webhook.authenticate)
283+
method = webhook.authenticate.method
284+
285+
if (!method && parameters[0] !== parameters[1])
286+
throw new Error(`Webhook secret failed for ${name}. Unauthorized access attempt.`);
287+
288+
} else {
289+
const service = require(config.path);
290+
const instance = new service[config.initialize](key);
291+
const methodPath = method.split('.')
292+
let property = instance
293+
294+
for (let i = 0; i < methodPath.length; i++) {
295+
property = property[methodPath[i]]
296+
if (property === undefined) {
297+
throw new Error(`Method ${methodPath[i]} not found using ${data.method}.`);
298+
}
299+
}
244300

245-
// TODO: event may need to be handle by a built in service function
246-
const event = JSON.parse(rawBody)
247-
// TODO: using request.method and event.type get object and send socket.onMessage for proccessing
301+
event = await property.apply(instance, parameters);
302+
}
303+
304+
let execute = webhook.events[eventName];
305+
if (execute) {
306+
execute = await processOperators(data, execute);
307+
}
248308

249309
data.res.writeHead(200, { 'Content-Type': 'application/json' });
250310
data.res.end(JSON.stringify({ message: 'Webhook received and processed' }));
@@ -270,6 +330,66 @@ class CoCreateLazyLoader {
270330

271331
}
272332

333+
async function processOperator(data, operator, context) {
334+
if (operator.startsWith('$data.')) {
335+
operator = getValueFromObject(data, operator.substring(6))
336+
} else if (operator.startsWith('$req.')) {
337+
operator = getValueFromObject(data.req, operator.substring(5))
338+
} else if (operator.startsWith('$header.')) {
339+
operator = getValueFromObject(data.req.header, operator.substring(7))
340+
} else if (operator.startsWith('$crud')) {
341+
operator = await data.crud.send(context)
342+
let name = operator.method.split('.')[0]
343+
operator = operator[name]
344+
} else if (operator.startsWith('$socket')) {
345+
operator = await data.socket.send(context)
346+
let name = operator.method.split('.')[0]
347+
operator = operator[name]
348+
} else if (operator.startsWith('$api')) {
349+
let name = context.method.split('.')[0]
350+
operator = this.executeScriptWithTimeout(name, context)
351+
} else if (operator.startsWith('$webhook')) {
352+
// TODO: would expect a data.req
353+
// let name = context.method.split('.')[0]
354+
// operator = this.executeScriptWithTimeout(name, context)
355+
}
356+
357+
// TODO: function to parse and execute object in order to broadcast/store some or all of the returned event
358+
359+
// TODO: using request.method and event.type get object and send socket.onMessage for proccessing
360+
361+
return operator; // For illustration, return the operator itself or the computed value
362+
}
363+
364+
async function processOperators(data, obj, parent = null, parentKey = null) {
365+
if (Array.isArray(obj)) {
366+
obj.forEach(async (item, index) => await processOperators(data, item, obj, index));
367+
} else if (typeof obj === 'object' && obj !== null) {
368+
for (let key of Object.keys(obj)) {
369+
// Check if key is an operator
370+
if (key.startsWith('$')) {
371+
const operatorResult = await processOperator(data, key, obj[key]);
372+
if (parent && operatorResult !== null) {
373+
if (parentKey !== null) {
374+
parent[parentKey] = operatorResult;
375+
await processOperators(data, parent[parentKey], parent, parentKey);
376+
}
377+
// else {
378+
// // Scenario 2: Replace the key (more complex, might require re-structuring the object)
379+
// delete parent[key]; // Remove the original key
380+
// parent[operatorResult] = obj[key]; // Assign the value to the new key
381+
// // Continue processing the new key if necessary
382+
// }
383+
}
384+
} else {
385+
await processOperators(data, obj[key], obj, key);
386+
}
387+
}
388+
} else {
389+
return await processOperator(data, obj);
390+
}
391+
}
392+
273393
function getModuleDependencies(modulePath) {
274394
let moduleObj = require.cache[modulePath];
275395
if (!moduleObj) {
@@ -356,4 +476,7 @@ async function fetchScriptFromDatabaseAndSave(name, moduleConfig) {
356476
return src;
357477
}
358478

479+
480+
481+
359482
module.exports = CoCreateLazyLoader;

0 commit comments

Comments
 (0)