@cocreate/lazy-loader 1.18.0 → 1.19.1

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 +19 -0
  2. package/package.json +1 -1
  3. package/src/server.js +134 -81
package/CHANGELOG.md CHANGED
@@ -1,3 +1,22 @@
1
+ ## [1.19.1](https://github.com/CoCreate-app/CoCreate-lazy-loader/compare/v1.19.0...v1.19.1) (2024-04-27)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * eniroment declaration and error handling of execute method ([659d947](https://github.com/CoCreate-app/CoCreate-lazy-loader/commit/659d947af1226c77b4cbcbaaed10596ade73183f))
7
+
8
+ # [1.19.0](https://github.com/CoCreate-app/CoCreate-lazy-loader/compare/v1.18.0...v1.19.0) (2024-04-26)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * added processOperators and processOperator to lazyLoader class ([973f07a](https://github.com/CoCreate-app/CoCreate-lazy-loader/commit/973f07ac492dee348f15b6889c15e180cf4d3eb0))
14
+
15
+
16
+ ### Features
17
+
18
+ * dynamically handle webhooks using operations and objects to perform actions ([c1f17b4](https://github.com/CoCreate-app/CoCreate-lazy-loader/commit/c1f17b47304bd9c0b44ba591809dfee3c7186992))
19
+
1
20
  # [1.18.0](https://github.com/CoCreate-app/CoCreate-lazy-loader/compare/v1.17.0...v1.18.0) (2024-03-18)
2
21
 
3
22
 
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.1",
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
@@ -153,7 +156,13 @@ class CoCreateLazyLoader {
153
156
  const name = methodPath.shift()
154
157
 
155
158
  const apis = await this.getApiKey(data, name)
156
- const environment = data.environment || 'production';
159
+ let environment = 'production';
160
+
161
+ if (data.environment)
162
+ environment = data.environment
163
+ else if (data.host.startsWith('dev.') || data.host.startsWith('test.'))
164
+ environment = 'test'
165
+
157
166
  const key = apis[environment].key;
158
167
  if (!key)
159
168
  throw new Error(`Missing ${name} key in organization apis object`);
@@ -196,8 +205,9 @@ class CoCreateLazyLoader {
196
205
  async webhooks(config, data, name) {
197
206
  try {
198
207
  const apis = await this.getApiKey(data, name)
199
- let environment = data.environment || 'production';
200
- if (data.host.startsWith('dev.') || data.host.startsWith('test.'))
208
+ if (data.environment)
209
+ environment = data.environment
210
+ else if (data.host.startsWith('dev.') || data.host.startsWith('test.'))
201
211
  environment = 'test'
202
212
 
203
213
  const key = apis[environment].key;
@@ -211,21 +221,23 @@ class CoCreateLazyLoader {
211
221
  if (!webhook)
212
222
  throw new Error(`Webhook ${name} ${webhookName} is not defined`);
213
223
 
214
- let dataKey = webhook.dataKey || apis[environment].dataKey
215
- if (!dataKey)
224
+ // eventDataKey is used to access the event data
225
+ let eventDataKey = webhook.eventDataKey || apis[environment].eventDataKey
226
+ if (!eventDataKey)
216
227
  throw new Error(`Webhook ${name} eventKey is not defined`);
217
228
 
218
- let nameKey = webhook.nameKey || apis[environment].nameKey
219
- if (!nameKey)
220
- throw new Error(`Webhook ${name} eventKey is not defined`);
229
+ // eventNameKey is used to access the event the event name
230
+ let eventNameKey = webhook.eventNameKey || apis[environment].eventNameKey
231
+ if (!eventNameKey)
232
+ throw new Error(`Webhook ${name} eventNameKey is not defined`);
221
233
 
222
234
  if (!webhook.events)
223
235
  throw new Error(`Webhook ${name} events are not defined`);
224
236
 
225
- let rawBody = '';
237
+ data.rawBody = '';
226
238
  await new Promise((resolve, reject) => {
227
239
  data.req.on('data', chunk => {
228
- rawBody += chunk.toString();
240
+ data.rawBody += chunk.toString();
229
241
  });
230
242
  data.req.on('end', () => {
231
243
  resolve();
@@ -237,18 +249,20 @@ class CoCreateLazyLoader {
237
249
 
238
250
  let parameters, method
239
251
 
240
- if (webhook.authenticate) {
252
+
253
+ if (webhook.authenticate && webhook.authenticate.method) {
241
254
  method = webhook.authenticate.method
242
- parameters = webhook.authenticate.parameters
243
- }
255
+ } else if (apis[environment].authenticate && apis[environment].authenticate.method) {
256
+ method = apis[environment].authenticate.method
257
+ } else
258
+ throw new Error(`Webhook ${name} authenticate method is not defined`);
244
259
 
245
- if (!parameters && apis[environment].authenticate && apis[environment].authenticate.parameters) {
260
+ if (webhook.authenticate && webhook.authenticate.parameters) {
261
+ parameters = webhook.authenticate.parameters
262
+ } else if (apis[environment].authenticate && apis[environment].authenticate.parameters) {
246
263
  parameters = apis[environment].authenticate.parameters
247
264
  } else
248
- throw new Error(`Webhook secret ${name} is not defined`);
249
-
250
- if (!method && apis[environment].authenticate)
251
- method = apis[environment].authenticate.method
265
+ throw new Error(`Webhook ${name} authenticate parameters is not defined`);
252
266
 
253
267
  // TODO: webhook secert could be a key pair
254
268
 
@@ -257,7 +271,7 @@ class CoCreateLazyLoader {
257
271
  if (!parameters[0] !== parameters[1])
258
272
  throw new Error(`Webhook secret failed for ${name}. Unauthorized access attempt.`);
259
273
 
260
- event = JSON.parse(rawBody)
274
+ event = JSON.parse(data.rawBody)
261
275
  } else {
262
276
  const service = require(config.path);
263
277
  let instance
@@ -266,20 +280,24 @@ class CoCreateLazyLoader {
266
280
  else
267
281
  instance = new service(key);
268
282
 
269
- event = await executeMethod(name + '.' + method, methodPath, instance, parameters)
283
+ const methodPath = method.split('.')
284
+
285
+ await this.processOperators(data, '', parameters);
286
+
287
+ event = await executeMethod(method, methodPath, instance, parameters)
270
288
  }
271
289
 
272
- let eventName = getValueFromObject(event, nameKey)
290
+ let eventName = getValueFromObject(event, eventNameKey)
273
291
  if (!eventName)
274
- throw new Error(`Webhook ${name} nameKey: ${nameKey} could not be found in the event.`);
292
+ throw new Error(`Webhook ${name} eventNameKey: ${eventNameKey} could not be found in the event.`);
275
293
 
276
- let eventData = getValueFromObject(event, dataKey)
294
+ let eventData = getValueFromObject(event, eventDataKey)
277
295
  if (!eventData)
278
- throw new Error(`Webhook ${name} dataKey: ${dataKey} could not be found in the event.`);
296
+ throw new Error(`Webhook ${name} eventDataKey: ${eventDataKey} could not be found in the event.`);
279
297
 
280
298
  let execute = webhook.events[eventName];
281
299
  if (execute) {
282
- execute = await processOperators(data, event, execute);
300
+ execute = await this.processOperators(data, event, execute);
283
301
  }
284
302
 
285
303
  data.res.writeHead(200, { 'Content-Type': 'application/json' });
@@ -293,6 +311,67 @@ class CoCreateLazyLoader {
293
311
  }
294
312
  }
295
313
 
314
+ async processOperators(data, event, execute, parent = null, parentKey = null) {
315
+ if (Array.isArray(execute)) {
316
+ for (let index = 0; index < execute.length; index++) {
317
+ execute[index] = await this.processOperators(data, event, execute[index], execute, index);
318
+ }
319
+ } else if (typeof execute === 'object' && execute !== null) {
320
+ for (let key of Object.keys(execute)) {
321
+ if (key.startsWith('$')) {
322
+ const operatorResult = await this.processOperator(data, event, key, execute[key]);
323
+ if (parent && operatorResult !== null && parentKey !== null) {
324
+ parent[parentKey] = operatorResult;
325
+ await this.processOperators(data, event, parent[parentKey], parent, parentKey);
326
+ }
327
+ } else {
328
+ execute[key] = await this.processOperators(data, event, execute[key], execute, key);
329
+ }
330
+ }
331
+ } else {
332
+ return await this.processOperator(data, event, execute);
333
+ }
334
+ return execute;
335
+ }
336
+
337
+ async processOperator(data, event, operator, context) {
338
+ let result
339
+ if (operator.startsWith('$data.')) {
340
+ return getValueFromObject(data, operator.substring(6))
341
+ } else if (operator.startsWith('$req')) {
342
+ return getValueFromObject(data, operator.substring(1))
343
+ } else if (operator.startsWith('$header')) {
344
+ return getValueFromObject(data.req, operator.substring(1))
345
+ } else if (operator.startsWith('$rawBody')) {
346
+ return getValueFromObject(data, operator.substring(1))
347
+ } else if (operator.startsWith('$crud')) {
348
+ context = await this.processOperators(data, event, context);
349
+ result = await this.crud.send(context)
350
+ if (operator.startsWith('$crud.'))
351
+ result = getValueFromObject(operator, operator.substring(6))
352
+ return await this.processOperators(data, event, result);
353
+ } else if (operator.startsWith('$socket')) {
354
+ context = await this.processOperators(data, event, context);
355
+ result = await this.socket.send(context)
356
+ if (operator.startsWith('$socket.'))
357
+ result = getValueFromObject(operator, operator.substring(6))
358
+ return await this.processOperators(data, event, result);
359
+ } else if (operator.startsWith('$api')) {
360
+ context = await this.processOperators(data, event, context);
361
+ let name = context.method.split('.')[0]
362
+ result = this.executeScriptWithTimeout(name, context)
363
+ if (operator.startsWith('$api.'))
364
+ result = getValueFromObject(event, operator.substring(5))
365
+ return await this.processOperators(data, event, result);
366
+ } else if (operator.startsWith('$event')) {
367
+ if (operator.startsWith('$event.'))
368
+ result = getValueFromObject(event, operator.substring(7))
369
+ return await this.processOperators(data, event, result);
370
+ }
371
+
372
+ return operator;
373
+ }
374
+
296
375
  async getApiKey(data, name) {
297
376
  let organization = await this.crud.getOrganization(data);
298
377
  if (organization.error)
@@ -306,61 +385,35 @@ class CoCreateLazyLoader {
306
385
 
307
386
  }
308
387
 
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
388
 
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
-
362
- return operator;
363
- }
389
+ // async function processOperators(data, event, execute, parent = null, parentKey = null) {
390
+ // if (Array.isArray(execute)) {
391
+ // execute.forEach(async (item, index) => await processOperators(data, event, item, execute, index));
392
+ // } else if (typeof execute === 'object' && execute !== null) {
393
+ // for (let key of Object.keys(execute)) {
394
+ // // Check if key is an operator
395
+ // if (key.startsWith('$')) {
396
+ // const operatorResult = await processOperator(data, event, key, execute[key]);
397
+ // if (parent && operatorResult !== null) {
398
+ // if (parentKey !== null) {
399
+ // parent[parentKey] = operatorResult;
400
+ // await processOperators(data, event, parent[parentKey], parent, parentKey);
401
+ // }
402
+ // // else {
403
+ // // // Scenario 2: Replace the key (more complex, might require re-structuring the executable object)
404
+ // // delete parent[key]; // Remove the original key
405
+ // // parent[operatorResult] = execute[key]; // Assign the value to the new key
406
+ // // // Continue processing the new key if necessary
407
+ // // }
408
+ // }
409
+ // } else {
410
+ // await processOperators(data, event, execute[key], execute, key);
411
+ // }
412
+ // }
413
+ // } else {
414
+ // return await processOperator(data, event, execute);
415
+ // }
416
+ // }
364
417
 
365
418
  async function executeMethod(method, methodPath, instance, params) {
366
419
  try {
@@ -397,7 +450,7 @@ async function executeMethod(method, methodPath, instance, params) {
397
450
  return await Method[methodName](...params)
398
451
  }
399
452
  } catch (error) {
400
- throw new Error(`Method ${method} not found.`);
453
+ throw new Error(error);
401
454
  }
402
455
  }
403
456