@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.
- package/CHANGELOG.md +12 -0
- package/package.json +1 -1
- 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
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 {
|
|
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
|
-
|
|
215
|
-
|
|
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
|
-
|
|
219
|
-
|
|
220
|
-
|
|
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
|
-
|
|
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
|
-
|
|
245
|
+
|
|
246
|
+
if (webhook.authenticate && webhook.authenticate.method) {
|
|
241
247
|
method = webhook.authenticate.method
|
|
242
|
-
|
|
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 (
|
|
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
|
|
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
|
-
|
|
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,
|
|
283
|
+
let eventName = getValueFromObject(event, eventNameKey)
|
|
273
284
|
if (!eventName)
|
|
274
|
-
throw new Error(`Webhook ${name}
|
|
285
|
+
throw new Error(`Webhook ${name} eventNameKey: ${eventNameKey} could not be found in the event.`);
|
|
275
286
|
|
|
276
|
-
let eventData = getValueFromObject(event,
|
|
287
|
+
let eventData = getValueFromObject(event, eventDataKey)
|
|
277
288
|
if (!eventData)
|
|
278
|
-
throw new Error(`Webhook ${name}
|
|
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
|
-
|
|
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 {
|