@cocreate/lazy-loader 1.16.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 CHANGED
@@ -1,3 +1,32 @@
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
+
17
+ # [1.17.0](https://github.com/CoCreate-app/CoCreate-lazy-loader/compare/v1.16.0...v1.17.0) (2024-02-05)
18
+
19
+
20
+ ### Bug Fixes
21
+
22
+ * $param handeling ([4f1cafc](https://github.com/CoCreate-app/CoCreate-lazy-loader/commit/4f1cafc6c598aad0b3e09c794d2a08874560538f))
23
+ * Removed https://cdn.cocreate.app/latest/CoCreate.min.css ([538dd6a](https://github.com/CoCreate-app/CoCreate-lazy-loader/commit/538dd6a41df1d32fa71b46c3b2d0da7158c46d74))
24
+
25
+
26
+ ### Features
27
+
28
+ * operate $param[] ([61181ad](https://github.com/CoCreate-app/CoCreate-lazy-loader/commit/61181ad37545b186336bb1a361aff1602ae6868f))
29
+
1
30
  # [1.16.0](https://github.com/CoCreate-app/CoCreate-lazy-loader/compare/v1.15.2...v1.16.0) (2024-01-30)
2
31
 
3
32
 
package/docs/index.html CHANGED
@@ -19,10 +19,6 @@
19
19
  <meta name="robots" content="index,follow" />
20
20
 
21
21
  <!-- CoCreate CSS CDN -->
22
- <link
23
- rel="stylesheet"
24
- href="https://cdn.cocreate.app/latest/CoCreate.min.css"
25
- type="text/css" />
26
22
 
27
23
  <link rel="manifest" href="/manifest.webmanifest" />
28
24
  </head>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/lazy-loader",
3
- "version": "1.16.0",
3
+ "version": "1.18.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
@@ -47,6 +47,7 @@ class CoCreateLazyLoader {
47
47
  const valideUrl = new URL(`http://${req.headers.host}${req.url}`);
48
48
  const hostname = valideUrl.hostname;
49
49
  let organization
50
+
50
51
  try {
51
52
  organization = await this.crud.getOrganization({ host: hostname });
52
53
  } catch {
@@ -75,7 +76,7 @@ class CoCreateLazyLoader {
75
76
 
76
77
  async executeScriptWithTimeout(name, data) {
77
78
  try {
78
- if (this.modules[name].initialize) {
79
+ if (this.modules[name].initialize || this.modules[name].initialize === '') {
79
80
  if (data.req)
80
81
  data = await this.webhooks(this.modules[name], data, name)
81
82
  else
@@ -158,21 +159,33 @@ class CoCreateLazyLoader {
158
159
  throw new Error(`Missing ${name} key in organization apis object`);
159
160
 
160
161
  const service = require(config.path);
161
- const instance = new service[config.initialize](key);
162
-
163
- let method = instance
164
- for (let i = 0; i < methodPath.length; i++) {
165
- method = method[methodPath[i]]
166
- if (method === undefined) {
167
- throw new Error(`Method ${methodPath[i]} not found using ${data.method}.`);
162
+ let instance
163
+ if (config.initialize)
164
+ instance = new service[config.initialize](key);
165
+ else
166
+ instance = new service(key);
167
+
168
+ let params = [], mainParam = false
169
+ for (let i = 0; true; i++) {
170
+ if (`$param[${i}]` in data[name]) {
171
+ params.push(data[name][`$param[${i}]`])
172
+ delete data[name][`$param[${i}]`]
173
+ } else if (!mainParam) {
174
+ params.push(data[name])
175
+ mainParam = true
176
+ } else {
177
+ break;
168
178
  }
169
179
  }
170
180
 
171
- if (typeof method !== 'function')
172
- throw new Error(`Method ${data.method} is not a function.`);
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]);
173
188
 
174
- let params = data.$params || [data[name]]
175
- data.postmark = await method.apply(instance, params);
176
189
  return data
177
190
  } catch (error) {
178
191
  data.error = error.message
@@ -191,13 +204,23 @@ class CoCreateLazyLoader {
191
204
  if (!key)
192
205
  throw new Error(`Missing ${name} key in organization apis object`);
193
206
 
194
- let name = data.req.url.split('/');
195
- name = name[3] || name[2] || name[1]
207
+ let webhookName = data.req.url.split('/');
208
+ webhookName = webhookName[webhookName.length - 1]
196
209
 
197
- // TODO: webhook secert could be a key pair
198
- const webhookSecret = data.apis[environment].webhooks[name];
199
- if (webhookSecret !== req.headers[name])
200
- throw new Error(`Webhook secret failed for ${name}. Unauthorized access attempt.`);
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`);
201
224
 
202
225
  let rawBody = '';
203
226
  await new Promise((resolve, reject) => {
@@ -212,13 +235,52 @@ class CoCreateLazyLoader {
212
235
  });
213
236
  });
214
237
 
215
- // TODO: if decrypt and validation is builtin to service
216
- // const service = require(config.path);
217
- // const instance = new service[config.initialize](key);
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`);
218
249
 
219
- // TODO: event may need to be handle by a built in service function
220
- const event = JSON.parse(rawBody)
221
- // TODO: using request.method and event.type get object and send socket.onMessage for proccessing
250
+ if (!method && apis[environment].authenticate)
251
+ method = apis[environment].authenticate.method
252
+
253
+ // TODO: webhook secert could be a key pair
254
+
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
+ }
222
284
 
223
285
  data.res.writeHead(200, { 'Content-Type': 'application/json' });
224
286
  data.res.end(JSON.stringify({ message: 'Webhook received and processed' }));
@@ -244,6 +306,101 @@ class CoCreateLazyLoader {
244
306
 
245
307
  }
246
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
+
247
404
  function getModuleDependencies(modulePath) {
248
405
  let moduleObj = require.cache[modulePath];
249
406
  if (!moduleObj) {
@@ -330,4 +487,7 @@ async function fetchScriptFromDatabaseAndSave(name, moduleConfig) {
330
487
  return src;
331
488
  }
332
489
 
490
+
491
+
492
+
333
493
  module.exports = CoCreateLazyLoader;