@@ -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+
273393function 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+
359482module . exports = CoCreateLazyLoader ;
0 commit comments