@cocreate/lazy-loader 1.18.0 → 1.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/package.json +1 -1
  3. package/src/server.js +123 -77
package/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ # [1.19.0](https://github.com/CoCreate-app/CoCreate-lazy-loader/compare/v1.18.0...v1.19.0) (2024-04-26)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * added processOperators and processOperator to lazyLoader class ([973f07a](https://github.com/CoCreate-app/CoCreate-lazy-loader/commit/973f07ac492dee348f15b6889c15e180cf4d3eb0))
7
+
8
+
9
+ ### Features
10
+
11
+ * dynamically handle webhooks using operations and objects to perform actions ([c1f17b4](https://github.com/CoCreate-app/CoCreate-lazy-loader/commit/c1f17b47304bd9c0b44ba591809dfee3c7186992))
12
+
1
13
  # [1.18.0](https://github.com/CoCreate-app/CoCreate-lazy-loader/compare/v1.17.0...v1.18.0) (2024-03-18)
2
14
 
3
15
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/lazy-loader",
3
- "version": "1.18.0",
3
+ "version": "1.19.0",
4
4
  "description": "A simple lazy-loader component in vanilla javascript. Easily configured using HTML5 data-attributes and/or JavaScript API.",
5
5
  "keywords": [
6
6
  "lazy-loader",
package/src/server.js CHANGED
@@ -1,8 +1,10 @@
1
1
  const fs = require('fs').promises;
2
2
  const path = require('path');
3
+ const { URL } = require('url');
3
4
  const vm = require('vm');
4
5
  const Config = require("@cocreate/config");
5
- const { URL } = require('url');
6
+ const { getValueFromObject } = require('@cocreate/utils');
7
+
6
8
 
7
9
  class CoCreateLazyLoader {
8
10
  constructor(server, crud, files) {
@@ -44,6 +46,7 @@ class CoCreateLazyLoader {
44
46
 
45
47
  async request(req, res) {
46
48
  try {
49
+ // TODO: track usage
47
50
  const valideUrl = new URL(`http://${req.headers.host}${req.url}`);
48
51
  const hostname = valideUrl.hostname;
49
52
  let organization
@@ -211,21 +214,23 @@ class CoCreateLazyLoader {
211
214
  if (!webhook)
212
215
  throw new Error(`Webhook ${name} ${webhookName} is not defined`);
213
216
 
214
- let dataKey = webhook.dataKey || apis[environment].dataKey
215
- if (!dataKey)
217
+ // eventDataKey is used to access the event data
218
+ let eventDataKey = webhook.eventDataKey || apis[environment].eventDataKey
219
+ if (!eventDataKey)
216
220
  throw new Error(`Webhook ${name} eventKey is not defined`);
217
221
 
218
- let nameKey = webhook.nameKey || apis[environment].nameKey
219
- if (!nameKey)
220
- throw new Error(`Webhook ${name} eventKey is not defined`);
222
+ // eventNameKey is used to access the event the event name
223
+ let eventNameKey = webhook.eventNameKey || apis[environment].eventNameKey
224
+ if (!eventNameKey)
225
+ throw new Error(`Webhook ${name} eventNameKey is not defined`);
221
226
 
222
227
  if (!webhook.events)
223
228
  throw new Error(`Webhook ${name} events are not defined`);
224
229
 
225
- let rawBody = '';
230
+ data.rawBody = '';
226
231
  await new Promise((resolve, reject) => {
227
232
  data.req.on('data', chunk => {
228
- rawBody += chunk.toString();
233
+ data.rawBody += chunk.toString();
229
234
  });
230
235
  data.req.on('end', () => {
231
236
  resolve();
@@ -237,18 +242,20 @@ class CoCreateLazyLoader {
237
242
 
238
243
  let parameters, method
239
244
 
240
- if (webhook.authenticate) {
245
+
246
+ if (webhook.authenticate && webhook.authenticate.method) {
241
247
  method = webhook.authenticate.method
242
- parameters = webhook.authenticate.parameters
243
- }
248
+ } else if (apis[environment].authenticate && apis[environment].authenticate.method) {
249
+ method = apis[environment].authenticate.method
250
+ } else
251
+ throw new Error(`Webhook ${name} authenticate method is not defined`);
244
252
 
245
- if (!parameters && apis[environment].authenticate && apis[environment].authenticate.parameters) {
253
+ if (webhook.authenticate && webhook.authenticate.parameters) {
254
+ parameters = webhook.authenticate.parameters
255
+ } else if (apis[environment].authenticate && apis[environment].authenticate.parameters) {
246
256
  parameters = apis[environment].authenticate.parameters
247
257
  } else
248
- throw new Error(`Webhook secret ${name} is not defined`);
249
-
250
- if (!method && apis[environment].authenticate)
251
- method = apis[environment].authenticate.method
258
+ throw new Error(`Webhook ${name} authenticate parameters is not defined`);
252
259
 
253
260
  // TODO: webhook secert could be a key pair
254
261
 
@@ -257,7 +264,7 @@ class CoCreateLazyLoader {
257
264
  if (!parameters[0] !== parameters[1])
258
265
  throw new Error(`Webhook secret failed for ${name}. Unauthorized access attempt.`);
259
266
 
260
- event = JSON.parse(rawBody)
267
+ event = JSON.parse(data.rawBody)
261
268
  } else {
262
269
  const service = require(config.path);
263
270
  let instance
@@ -266,20 +273,24 @@ class CoCreateLazyLoader {
266
273
  else
267
274
  instance = new service(key);
268
275
 
269
- event = await executeMethod(name + '.' + method, methodPath, instance, parameters)
276
+ const methodPath = method.split('.')
277
+
278
+ await this.processOperators(data, '', parameters);
279
+
280
+ event = await executeMethod(method, methodPath, instance, parameters)
270
281
  }
271
282
 
272
- let eventName = getValueFromObject(event, nameKey)
283
+ let eventName = getValueFromObject(event, eventNameKey)
273
284
  if (!eventName)
274
- throw new Error(`Webhook ${name} nameKey: ${nameKey} could not be found in the event.`);
285
+ throw new Error(`Webhook ${name} eventNameKey: ${eventNameKey} could not be found in the event.`);
275
286
 
276
- let eventData = getValueFromObject(event, dataKey)
287
+ let eventData = getValueFromObject(event, eventDataKey)
277
288
  if (!eventData)
278
- throw new Error(`Webhook ${name} dataKey: ${dataKey} could not be found in the event.`);
289
+ throw new Error(`Webhook ${name} eventDataKey: ${eventDataKey} could not be found in the event.`);
279
290
 
280
291
  let execute = webhook.events[eventName];
281
292
  if (execute) {
282
- execute = await processOperators(data, event, execute);
293
+ execute = await this.processOperators(data, event, execute);
283
294
  }
284
295
 
285
296
  data.res.writeHead(200, { 'Content-Type': 'application/json' });
@@ -293,6 +304,67 @@ class CoCreateLazyLoader {
293
304
  }
294
305
  }
295
306
 
307
+ async processOperators(data, event, execute, parent = null, parentKey = null) {
308
+ if (Array.isArray(execute)) {
309
+ for (let index = 0; index < execute.length; index++) {
310
+ execute[index] = await this.processOperators(data, event, execute[index], execute, index);
311
+ }
312
+ } else if (typeof execute === 'object' && execute !== null) {
313
+ for (let key of Object.keys(execute)) {
314
+ if (key.startsWith('$')) {
315
+ const operatorResult = await this.processOperator(data, event, key, execute[key]);
316
+ if (parent && operatorResult !== null && parentKey !== null) {
317
+ parent[parentKey] = operatorResult;
318
+ await this.processOperators(data, event, parent[parentKey], parent, parentKey);
319
+ }
320
+ } else {
321
+ execute[key] = await this.processOperators(data, event, execute[key], execute, key);
322
+ }
323
+ }
324
+ } else {
325
+ return await this.processOperator(data, event, execute);
326
+ }
327
+ return execute;
328
+ }
329
+
330
+ async processOperator(data, event, operator, context) {
331
+ let result
332
+ if (operator.startsWith('$data.')) {
333
+ return getValueFromObject(data, operator.substring(6))
334
+ } else if (operator.startsWith('$req')) {
335
+ return getValueFromObject(data, operator.substring(1))
336
+ } else if (operator.startsWith('$header')) {
337
+ return getValueFromObject(data.req, operator.substring(1))
338
+ } else if (operator.startsWith('$rawBody')) {
339
+ return getValueFromObject(data, operator.substring(1))
340
+ } else if (operator.startsWith('$crud')) {
341
+ context = await this.processOperators(data, event, context);
342
+ result = await this.crud.send(context)
343
+ if (operator.startsWith('$crud.'))
344
+ result = getValueFromObject(operator, operator.substring(6))
345
+ return await this.processOperators(data, event, result);
346
+ } else if (operator.startsWith('$socket')) {
347
+ context = await this.processOperators(data, event, context);
348
+ result = await this.socket.send(context)
349
+ if (operator.startsWith('$socket.'))
350
+ result = getValueFromObject(operator, operator.substring(6))
351
+ return await this.processOperators(data, event, result);
352
+ } else if (operator.startsWith('$api')) {
353
+ context = await this.processOperators(data, event, context);
354
+ let name = context.method.split('.')[0]
355
+ result = this.executeScriptWithTimeout(name, context)
356
+ if (operator.startsWith('$api.'))
357
+ result = getValueFromObject(event, operator.substring(5))
358
+ return await this.processOperators(data, event, result);
359
+ } else if (operator.startsWith('$event')) {
360
+ if (operator.startsWith('$event.'))
361
+ result = getValueFromObject(event, operator.substring(7))
362
+ return await this.processOperators(data, event, result);
363
+ }
364
+
365
+ return operator;
366
+ }
367
+
296
368
  async getApiKey(data, name) {
297
369
  let organization = await this.crud.getOrganization(data);
298
370
  if (organization.error)
@@ -306,61 +378,35 @@ class CoCreateLazyLoader {
306
378
 
307
379
  }
308
380
 
309
- async function processOperators(data, event, execute, parent = null, parentKey = null) {
310
- if (Array.isArray(execute)) {
311
- execute.forEach(async (item, index) => await processOperators(data, event, item, execute, index));
312
- } else if (typeof execute === 'object' && execute !== null) {
313
- for (let key of Object.keys(execute)) {
314
- // Check if key is an operator
315
- if (key.startsWith('$')) {
316
- const operatorResult = await processOperator(data, event, key, execute[key]);
317
- if (parent && operatorResult !== null) {
318
- if (parentKey !== null) {
319
- parent[parentKey] = operatorResult;
320
- await processOperators(data, event, parent[parentKey], parent, parentKey);
321
- }
322
- // else {
323
- // // Scenario 2: Replace the key (more complex, might require re-structuring the executable object)
324
- // delete parent[key]; // Remove the original key
325
- // parent[operatorResult] = execute[key]; // Assign the value to the new key
326
- // // Continue processing the new key if necessary
327
- // }
328
- }
329
- } else {
330
- await processOperators(data, event, execute[key], execute, key);
331
- }
332
- }
333
- } else {
334
- return await processOperator(data, event, execute);
335
- }
336
- }
337
-
338
- async function processOperator(data, event, operator, context) {
339
- if (operator.startsWith('$data.')) {
340
- operator = getValueFromObject(data, operator.substring(6))
341
- } else if (operator.startsWith('$req.')) {
342
- operator = getValueFromObject(data.req, operator.substring(5))
343
- } else if (operator.startsWith('$header.')) {
344
- operator = getValueFromObject(data.req.header, operator.substring(7))
345
- } else if (operator.startsWith('$crud')) {
346
- operator = await data.crud.send(context)
347
- let name = operator.method.split('.')[0]
348
- operator = operator[name]
349
- } else if (operator.startsWith('$socket')) {
350
- operator = await data.socket.send(context)
351
- let name = operator.method.split('.')[0]
352
- operator = operator[name]
353
- } else if (operator.startsWith('$api')) {
354
- let name = context.method.split('.')[0]
355
- operator = this.executeScriptWithTimeout(name, context)
356
- } else if (operator.startsWith('$webhook.')) {
357
- operator = getValueFromObject(webhook, operator.substring(9))
358
- } else if (operator.startsWith('$event.')) {
359
- operator = getValueFromObject(event, operator.substring(7))
360
- }
361
381
 
362
- return operator;
363
- }
382
+ // async function processOperators(data, event, execute, parent = null, parentKey = null) {
383
+ // if (Array.isArray(execute)) {
384
+ // execute.forEach(async (item, index) => await processOperators(data, event, item, execute, index));
385
+ // } else if (typeof execute === 'object' && execute !== null) {
386
+ // for (let key of Object.keys(execute)) {
387
+ // // Check if key is an operator
388
+ // if (key.startsWith('$')) {
389
+ // const operatorResult = await processOperator(data, event, key, execute[key]);
390
+ // if (parent && operatorResult !== null) {
391
+ // if (parentKey !== null) {
392
+ // parent[parentKey] = operatorResult;
393
+ // await processOperators(data, event, parent[parentKey], parent, parentKey);
394
+ // }
395
+ // // else {
396
+ // // // Scenario 2: Replace the key (more complex, might require re-structuring the executable object)
397
+ // // delete parent[key]; // Remove the original key
398
+ // // parent[operatorResult] = execute[key]; // Assign the value to the new key
399
+ // // // Continue processing the new key if necessary
400
+ // // }
401
+ // }
402
+ // } else {
403
+ // await processOperators(data, event, execute[key], execute, key);
404
+ // }
405
+ // }
406
+ // } else {
407
+ // return await processOperator(data, event, execute);
408
+ // }
409
+ // }
364
410
 
365
411
  async function executeMethod(method, methodPath, instance, params) {
366
412
  try {