@@ -185,7 +185,19 @@ class CoCreateLazyLoader {
185
185
}
186
186
}
187
187
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
+
189
201
return data
190
202
} catch ( error ) {
191
203
data . error = error . message
@@ -208,22 +220,13 @@ class CoCreateLazyLoader {
208
220
name = name [ 3 ] || name [ 2 ] || name [ 1 ]
209
221
210
222
// TODO: webhook secert could be a key pair
211
- let webhookSecret , webhookObject
212
223
const webhook = data . apis [ environment ] . webhooks [ name ] ;
213
224
if ( ! webhook )
214
225
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` ) ;
227
230
228
231
let rawBody = '' ;
229
232
await new Promise ( ( resolve , reject ) => {
@@ -238,13 +241,70 @@ class CoCreateLazyLoader {
238
241
} ) ;
239
242
} ) ;
240
243
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
+ }
244
300
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
+ }
248
308
249
309
data . res . writeHead ( 200 , { 'Content-Type' : 'application/json' } ) ;
250
310
data . res . end ( JSON . stringify ( { message : 'Webhook received and processed' } ) ) ;
@@ -270,6 +330,66 @@ class CoCreateLazyLoader {
270
330
271
331
}
272
332
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
+
273
393
function getModuleDependencies ( modulePath ) {
274
394
let moduleObj = require . cache [ modulePath ] ;
275
395
if ( ! moduleObj ) {
@@ -356,4 +476,7 @@ async function fetchScriptFromDatabaseAndSave(name, moduleConfig) {
356
476
return src ;
357
477
}
358
478
479
+
480
+
481
+
359
482
module . exports = CoCreateLazyLoader ;
0 commit comments