@cocreate/lazy-loader 1.15.2 → 1.17.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,30 @@
1
+ # [1.17.0](https://github.com/CoCreate-app/CoCreate-lazy-loader/compare/v1.16.0...v1.17.0) (2024-02-05)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * $param handeling ([4f1cafc](https://github.com/CoCreate-app/CoCreate-lazy-loader/commit/4f1cafc6c598aad0b3e09c794d2a08874560538f))
7
+ * Removed https://cdn.cocreate.app/latest/CoCreate.min.css ([538dd6a](https://github.com/CoCreate-app/CoCreate-lazy-loader/commit/538dd6a41df1d32fa71b46c3b2d0da7158c46d74))
8
+
9
+
10
+ ### Features
11
+
12
+ * operate $param[] ([61181ad](https://github.com/CoCreate-app/CoCreate-lazy-loader/commit/61181ad37545b186336bb1a361aff1602ae6868f))
13
+
14
+ # [1.16.0](https://github.com/CoCreate-app/CoCreate-lazy-loader/compare/v1.15.2...v1.16.0) (2024-01-30)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * error handling ([6bde772](https://github.com/CoCreate-app/CoCreate-lazy-loader/commit/6bde772156c95487a7c7abba494ee508c631fd99))
20
+ * getOrganization accepts one param ([bd2336a](https://github.com/CoCreate-app/CoCreate-lazy-loader/commit/bd2336a32033cd631199995cf4e4878451524010))
21
+
22
+
23
+ ### Features
24
+
25
+ * dynamically handles any third paty api and webhooks ([6ac3c2d](https://github.com/CoCreate-app/CoCreate-lazy-loader/commit/6ac3c2dce8786315ca9daaaa375e9ea480ecdf51))
26
+ * operator $params to define an array of params and their data/values. ([31b6ec7](https://github.com/CoCreate-app/CoCreate-lazy-loader/commit/31b6ec728a7330410447229376a776d23011fc55))
27
+
1
28
  ## [1.15.2](https://github.com/CoCreate-app/CoCreate-lazy-loader/compare/v1.15.1...v1.15.2) (2024-01-17)
2
29
 
3
30
 
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.15.2",
3
+ "version": "1.17.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
@@ -4,8 +4,6 @@ const vm = require('vm');
4
4
  const Config = require("@cocreate/config");
5
5
  const { URL } = require('url');
6
6
 
7
- // const organizations = {};
8
-
9
7
  class CoCreateLazyLoader {
10
8
  constructor(server, crud, files) {
11
9
  this.server = server
@@ -48,10 +46,13 @@ class CoCreateLazyLoader {
48
46
  try {
49
47
  const valideUrl = new URL(`http://${req.headers.host}${req.url}`);
50
48
  const hostname = valideUrl.hostname;
49
+ let organization
51
50
 
52
- let organization = await this.crud.getHost(hostname);
53
- if (organization.error)
51
+ try {
52
+ organization = await this.crud.getOrganization({ host: hostname });
53
+ } catch {
54
54
  return this.files.send(req, res, this.crud, organization, valideUrl)
55
+ }
55
56
 
56
57
  if (valideUrl.pathname.startsWith('/webhooks/')) {
57
58
  let name = req.url.split('/')[2]; // Assuming URL structure is /webhook/name/...
@@ -75,30 +76,38 @@ class CoCreateLazyLoader {
75
76
 
76
77
  async executeScriptWithTimeout(name, data) {
77
78
  try {
78
- if (!this.modules[name].content) {
79
- if (this.modules[name].path)
80
- this.modules[name].content = await require(this.modules[name].path)
81
- else {
82
- try {
83
- const scriptPath = path.join(scriptsDirectory, `${name}.js`);
84
- await fs.access(scriptPath);
85
- this.modules[name].content = await fs.readFile(scriptPath, 'utf8');
86
- } catch {
87
- this.modules[name].content = await fetchScriptFromDatabaseAndSave(name, this.modules[name], data);
79
+ if (this.modules[name].initialize) {
80
+ if (data.req)
81
+ data = await this.webhooks(this.modules[name], data, name)
82
+ else
83
+ data = await this.api(this.modules[name], data)
84
+ } else {
85
+ if (!this.modules[name].content) {
86
+ if (this.modules[name].path)
87
+ this.modules[name].content = await require(this.modules[name].path)
88
+ else {
89
+ try {
90
+ const scriptPath = path.join(scriptsDirectory, `${name}.js`);
91
+ await fs.access(scriptPath);
92
+ this.modules[name].content = await fs.readFile(scriptPath, 'utf8');
93
+ } catch {
94
+ this.modules[name].content = await fetchScriptFromDatabaseAndSave(name, this.modules[name], data);
95
+ }
88
96
  }
89
97
  }
98
+
99
+ if (this.modules[name].content) {
100
+ data.apis = await this.getApiKey(data, name)
101
+ data.crud = this.crud
102
+ data = await this.modules[name].content.send(data)
103
+ delete data.apis
104
+ delete data.crud
105
+ } else
106
+ return
90
107
  }
91
108
 
92
- if (this.modules[name].content) {
93
- data.apis = await this.getApiKey(data.organization_id, name)
94
- data.crud = this.crud
95
- data = await this.modules[name].content.send(data)
96
- delete data.apis
97
- delete data.crud
98
- if (data.socket)
99
- this.wsManager.send(data)
100
- } else
101
- return
109
+ if (data.socket)
110
+ this.wsManager.send(data)
102
111
 
103
112
  if (this.modules[name].unload === false || this.modules[name].unload === 'false')
104
113
  return
@@ -129,18 +138,120 @@ class CoCreateLazyLoader {
129
138
  this.modules[name].timeout = timeout
130
139
  }
131
140
  } catch (error) {
132
- console.log(error)
141
+ data.error = error.message
142
+ if (data.req) {
143
+ data.res.writeHead(400, { 'Content-Type': 'text/plain' });
144
+ data.res.end(`Lazyload Error: ${error.message}`);
145
+ } if (data.socket)
146
+ this.wsManager.send(data)
147
+ }
148
+ }
149
+
150
+ async api(config, data) {
151
+ try {
152
+ const methodPath = data.method.split('.')
153
+ const name = methodPath.shift()
154
+
155
+ const apis = await this.getApiKey(data, name)
156
+ const environment = data.environment || 'production';
157
+ const key = apis[environment].key;
158
+ if (!key)
159
+ throw new Error(`Missing ${name} key in organization apis object`);
160
+
161
+ const service = require(config.path);
162
+ const instance = new service[config.initialize](key);
163
+
164
+ let method = instance
165
+ for (let i = 0; i < methodPath.length; i++) {
166
+ method = method[methodPath[i]]
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.`);
174
+
175
+ let params = [], mainParam = false
176
+ for (let i = 0; true; i++) {
177
+ if (`$param[${i}]` in data[name]) {
178
+ params.push(data[name][`$param[${i}]`])
179
+ delete data[name][`$param[${i}]`]
180
+ } else if (!mainParam) {
181
+ params.push(data[name])
182
+ mainParam = true
183
+ } else {
184
+ break;
185
+ }
186
+ }
187
+
188
+ data.postmark = await method.apply(instance, params);
189
+ return data
190
+ } catch (error) {
191
+ data.error = error.message
192
+ return data
193
+ }
194
+ }
195
+
196
+ async webhooks(config, data, name) {
197
+ try {
198
+ const apis = await this.getApiKey(data, name)
199
+ let environment = data.environment || 'production';
200
+ if (data.host.startsWith('dev.') || data.host.startsWith('test.'))
201
+ environment = 'test'
202
+
203
+ const key = apis[environment].key;
204
+ if (!key)
205
+ throw new Error(`Missing ${name} key in organization apis object`);
206
+
207
+ let name = data.req.url.split('/');
208
+ name = name[3] || name[2] || name[1]
209
+
210
+ // TODO: webhook secert could be a key pair
211
+ const webhookSecret = data.apis[environment].webhooks[name];
212
+ if (webhookSecret !== req.headers[name])
213
+ throw new Error(`Webhook secret failed for ${name}. Unauthorized access attempt.`);
214
+
215
+ let rawBody = '';
216
+ await new Promise((resolve, reject) => {
217
+ data.req.on('data', chunk => {
218
+ rawBody += chunk.toString();
219
+ });
220
+ data.req.on('end', () => {
221
+ resolve();
222
+ });
223
+ data.req.on('error', (err) => {
224
+ reject(err);
225
+ });
226
+ });
227
+
228
+ // TODO: if decrypt and validation is builtin to service
229
+ // const service = require(config.path);
230
+ // const instance = new service[config.initialize](key);
231
+
232
+ // TODO: event may need to be handle by a built in service function
233
+ const event = JSON.parse(rawBody)
234
+ // TODO: using request.method and event.type get object and send socket.onMessage for proccessing
235
+
236
+ data.res.writeHead(200, { 'Content-Type': 'application/json' });
237
+ data.res.end(JSON.stringify({ message: 'Webhook received and processed' }));
238
+ return data
239
+ } catch (error) {
240
+ data.error = error.message
241
+ data.res.writeHead(400, { 'Content-Type': 'text/plain' });
242
+ data.res.end(error.message);
243
+ return data
133
244
  }
134
245
  }
135
246
 
136
- async getApiKey(organization_id, name) {
137
- let organization = await this.crud.getOrganization(organization_id, false);
247
+ async getApiKey(data, name) {
248
+ let organization = await this.crud.getOrganization(data);
138
249
  if (organization.error)
139
- return organization.error
250
+ throw new Error(organization.error);
140
251
  if (!organization.apis)
141
- return { error: 'Missing apis object in organization object' }
252
+ throw new Error('Missing apis object in organization object');
142
253
  if (!organization.apis[name])
143
- return { error: `Missing ${name} in organization apis object` }
254
+ throw new Error(`Missing ${name} in organization apis object`);
144
255
  return organization.apis[name]
145
256
  }
146
257