@cocreate/lazy-loader 1.17.0 → 1.18.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 +16 -0
- package/package.json +1 -1
- package/src/server.js +173 -26
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
# [1.18.0](https://github.com/CoCreate-app/CoCreate-lazy-loader/compare/v1.17.0...v1.18.0) (2024-03-18)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* handlng wbhook returned as string or object ([daf7438](https://github.com/CoCreate-app/CoCreate-lazy-loader/commit/daf7438bf8d6f049629112d056d9a598499cc23e))
|
|
7
|
+
* imporved authentication handling ([dfc9b1c](https://github.com/CoCreate-app/CoCreate-lazy-loader/commit/dfc9b1c8b9fe547ff16d441e4b31b3f0332bacb8))
|
|
8
|
+
* typo executeect updated to object ([a1b6258](https://github.com/CoCreate-app/CoCreate-lazy-loader/commit/a1b6258a7a88cd4e9847257fb552852342d9c7e3))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* authentication can be defined at envirnonemt level ([e4bf74c](https://github.com/CoCreate-app/CoCreate-lazy-loader/commit/e4bf74cdd8146bd390aec734d29e4177c3b264a7))
|
|
14
|
+
* executeMethod() to handle dotNotion method without losing context ([8ab4f84](https://github.com/CoCreate-app/CoCreate-lazy-loader/commit/8ab4f8484073891dba4c154938ae597c21962c5f))
|
|
15
|
+
* processOperators() to execute/rturn operator value ([e948ca2](https://github.com/CoCreate-app/CoCreate-lazy-loader/commit/e948ca24c1fb1ba5ae9718aaa466f0e26af78c74))
|
|
16
|
+
|
|
1
17
|
# [1.17.0](https://github.com/CoCreate-app/CoCreate-lazy-loader/compare/v1.16.0...v1.17.0) (2024-02-05)
|
|
2
18
|
|
|
3
19
|
|
package/package.json
CHANGED
package/src/server.js
CHANGED
|
@@ -76,7 +76,7 @@ class CoCreateLazyLoader {
|
|
|
76
76
|
|
|
77
77
|
async executeScriptWithTimeout(name, data) {
|
|
78
78
|
try {
|
|
79
|
-
if (this.modules[name].initialize) {
|
|
79
|
+
if (this.modules[name].initialize || this.modules[name].initialize === '') {
|
|
80
80
|
if (data.req)
|
|
81
81
|
data = await this.webhooks(this.modules[name], data, name)
|
|
82
82
|
else
|
|
@@ -159,18 +159,11 @@ class CoCreateLazyLoader {
|
|
|
159
159
|
throw new Error(`Missing ${name} key in organization apis object`);
|
|
160
160
|
|
|
161
161
|
const service = require(config.path);
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
if (method === undefined) {
|
|
168
|
-
throw new Error(`Method ${methodPath[i]} not found using ${data.method}.`);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if (typeof method !== 'function')
|
|
173
|
-
throw new Error(`Method ${data.method} is not a function.`);
|
|
162
|
+
let instance
|
|
163
|
+
if (config.initialize)
|
|
164
|
+
instance = new service[config.initialize](key);
|
|
165
|
+
else
|
|
166
|
+
instance = new service(key);
|
|
174
167
|
|
|
175
168
|
let params = [], mainParam = false
|
|
176
169
|
for (let i = 0; true; i++) {
|
|
@@ -185,7 +178,14 @@ class CoCreateLazyLoader {
|
|
|
185
178
|
}
|
|
186
179
|
}
|
|
187
180
|
|
|
188
|
-
|
|
181
|
+
// TODO: should run processOperators before in order to perform complex opertions and get data
|
|
182
|
+
// data[name] = await processOperators(data, null, data[name]);
|
|
183
|
+
|
|
184
|
+
data[name] = await executeMethod(data.method, methodPath, instance, params)
|
|
185
|
+
|
|
186
|
+
// TODO: should run processOperators after in order to perform complex opertions and get data
|
|
187
|
+
// data[name] = await processOperators(data, data[name]);
|
|
188
|
+
|
|
189
189
|
return data
|
|
190
190
|
} catch (error) {
|
|
191
191
|
data.error = error.message
|
|
@@ -204,13 +204,23 @@ class CoCreateLazyLoader {
|
|
|
204
204
|
if (!key)
|
|
205
205
|
throw new Error(`Missing ${name} key in organization apis object`);
|
|
206
206
|
|
|
207
|
-
let
|
|
208
|
-
|
|
207
|
+
let webhookName = data.req.url.split('/');
|
|
208
|
+
webhookName = webhookName[webhookName.length - 1]
|
|
209
209
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
210
|
+
const webhook = apis[environment].webhooks[webhookName];
|
|
211
|
+
if (!webhook)
|
|
212
|
+
throw new Error(`Webhook ${name} ${webhookName} is not defined`);
|
|
213
|
+
|
|
214
|
+
let dataKey = webhook.dataKey || apis[environment].dataKey
|
|
215
|
+
if (!dataKey)
|
|
216
|
+
throw new Error(`Webhook ${name} eventKey is not defined`);
|
|
217
|
+
|
|
218
|
+
let nameKey = webhook.nameKey || apis[environment].nameKey
|
|
219
|
+
if (!nameKey)
|
|
220
|
+
throw new Error(`Webhook ${name} eventKey is not defined`);
|
|
221
|
+
|
|
222
|
+
if (!webhook.events)
|
|
223
|
+
throw new Error(`Webhook ${name} events are not defined`);
|
|
214
224
|
|
|
215
225
|
let rawBody = '';
|
|
216
226
|
await new Promise((resolve, reject) => {
|
|
@@ -225,13 +235,52 @@ class CoCreateLazyLoader {
|
|
|
225
235
|
});
|
|
226
236
|
});
|
|
227
237
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
238
|
+
let parameters, method
|
|
239
|
+
|
|
240
|
+
if (webhook.authenticate) {
|
|
241
|
+
method = webhook.authenticate.method
|
|
242
|
+
parameters = webhook.authenticate.parameters
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (!parameters && apis[environment].authenticate && apis[environment].authenticate.parameters) {
|
|
246
|
+
parameters = apis[environment].authenticate.parameters
|
|
247
|
+
} else
|
|
248
|
+
throw new Error(`Webhook secret ${name} is not defined`);
|
|
249
|
+
|
|
250
|
+
if (!method && apis[environment].authenticate)
|
|
251
|
+
method = apis[environment].authenticate.method
|
|
252
|
+
|
|
253
|
+
// TODO: webhook secert could be a key pair
|
|
231
254
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
255
|
+
let event
|
|
256
|
+
if (!method) {
|
|
257
|
+
if (!parameters[0] !== parameters[1])
|
|
258
|
+
throw new Error(`Webhook secret failed for ${name}. Unauthorized access attempt.`);
|
|
259
|
+
|
|
260
|
+
event = JSON.parse(rawBody)
|
|
261
|
+
} else {
|
|
262
|
+
const service = require(config.path);
|
|
263
|
+
let instance
|
|
264
|
+
if (config.initialize)
|
|
265
|
+
instance = new service[config.initialize](key);
|
|
266
|
+
else
|
|
267
|
+
instance = new service(key);
|
|
268
|
+
|
|
269
|
+
event = await executeMethod(name + '.' + method, methodPath, instance, parameters)
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
let eventName = getValueFromObject(event, nameKey)
|
|
273
|
+
if (!eventName)
|
|
274
|
+
throw new Error(`Webhook ${name} nameKey: ${nameKey} could not be found in the event.`);
|
|
275
|
+
|
|
276
|
+
let eventData = getValueFromObject(event, dataKey)
|
|
277
|
+
if (!eventData)
|
|
278
|
+
throw new Error(`Webhook ${name} dataKey: ${dataKey} could not be found in the event.`);
|
|
279
|
+
|
|
280
|
+
let execute = webhook.events[eventName];
|
|
281
|
+
if (execute) {
|
|
282
|
+
execute = await processOperators(data, event, execute);
|
|
283
|
+
}
|
|
235
284
|
|
|
236
285
|
data.res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
237
286
|
data.res.end(JSON.stringify({ message: 'Webhook received and processed' }));
|
|
@@ -257,6 +306,101 @@ class CoCreateLazyLoader {
|
|
|
257
306
|
|
|
258
307
|
}
|
|
259
308
|
|
|
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
|
+
|
|
362
|
+
return operator;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
async function executeMethod(method, methodPath, instance, params) {
|
|
366
|
+
try {
|
|
367
|
+
switch (methodPath.length) {
|
|
368
|
+
case 1:
|
|
369
|
+
return await instance[methodPath[0]](...params)
|
|
370
|
+
case 2:
|
|
371
|
+
return await instance[methodPath[0]][methodPath[1]](...params);
|
|
372
|
+
case 3:
|
|
373
|
+
return await instance[methodPath[0]][methodPath[1]][methodPath[2]](...params);
|
|
374
|
+
case 4:
|
|
375
|
+
return await instance[methodPath[0]][methodPath[1]][methodPath[2]][methodPath[3]](...params);
|
|
376
|
+
case 5:
|
|
377
|
+
return await instance[methodPath[0]][methodPath[1]][methodPath[2]][methodPath[3]][methodPath[4]](...params);
|
|
378
|
+
case 6:
|
|
379
|
+
return await instance[methodPath[0]][methodPath[1]][methodPath[2]][methodPath[3]][methodPath[4]][methodPath[5]](...params);
|
|
380
|
+
case 7:
|
|
381
|
+
return await instance[methodPath[0]][methodPath[1]][methodPath[2]][methodPath[3]][methodPath[4]][methodPath[5]][methodPath[6]](...params);
|
|
382
|
+
case 8:
|
|
383
|
+
return await instance[methodPath[0]][methodPath[1]][methodPath[2]][methodPath[3]][methodPath[4]][methodPath[5]][methodPath[6]][methodPath[7]](...params);
|
|
384
|
+
default:
|
|
385
|
+
const methodName = methodPath.pop();
|
|
386
|
+
let Method = instance
|
|
387
|
+
for (let i = 0; i < methodPath.length; i++) {
|
|
388
|
+
Method = Method[methodPath[i]]
|
|
389
|
+
if (Method === undefined) {
|
|
390
|
+
throw new Error(`Method ${methodPath[i]} not found using ${method}.`);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
if (typeof Method[methodName] !== 'function')
|
|
395
|
+
throw new Error(`Method ${method} is not a function.`);
|
|
396
|
+
|
|
397
|
+
return await Method[methodName](...params)
|
|
398
|
+
}
|
|
399
|
+
} catch (error) {
|
|
400
|
+
throw new Error(`Method ${method} not found.`);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
260
404
|
function getModuleDependencies(modulePath) {
|
|
261
405
|
let moduleObj = require.cache[modulePath];
|
|
262
406
|
if (!moduleObj) {
|
|
@@ -343,4 +487,7 @@ async function fetchScriptFromDatabaseAndSave(name, moduleConfig) {
|
|
|
343
487
|
return src;
|
|
344
488
|
}
|
|
345
489
|
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
|
|
346
493
|
module.exports = CoCreateLazyLoader;
|