@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.
- package/CHANGELOG.md +19 -0
- package/package.json +1 -1
- 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
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
|
|
@@ -153,7 +156,13 @@ class CoCreateLazyLoader {
|
|
|
153
156
|
const name = methodPath.shift()
|
|
154
157
|
|
|
155
158
|
const apis = await this.getApiKey(data, name)
|
|
156
|
-
|
|
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
|
-
|
|
200
|
-
|
|
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
|
-
|
|
215
|
-
|
|
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
|
-
|
|
219
|
-
|
|
220
|
-
|
|
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
|
-
|
|
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
|
-
|
|
252
|
+
|
|
253
|
+
if (webhook.authenticate && webhook.authenticate.method) {
|
|
241
254
|
method = webhook.authenticate.method
|
|
242
|
-
|
|
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 (
|
|
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
|
|
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
|
-
|
|
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,
|
|
290
|
+
let eventName = getValueFromObject(event, eventNameKey)
|
|
273
291
|
if (!eventName)
|
|
274
|
-
throw new Error(`Webhook ${name}
|
|
292
|
+
throw new Error(`Webhook ${name} eventNameKey: ${eventNameKey} could not be found in the event.`);
|
|
275
293
|
|
|
276
|
-
let eventData = getValueFromObject(event,
|
|
294
|
+
let eventData = getValueFromObject(event, eventDataKey)
|
|
277
295
|
if (!eventData)
|
|
278
|
-
throw new Error(`Webhook ${name}
|
|
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
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
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(
|
|
453
|
+
throw new Error(error);
|
|
401
454
|
}
|
|
402
455
|
}
|
|
403
456
|
|