@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 +27 -0
- package/docs/index.html +0 -4
- package/package.json +1 -1
- package/src/server.js +141 -30
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
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
|
-
|
|
53
|
-
|
|
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 (
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
else
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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 (
|
|
93
|
-
|
|
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
|
-
|
|
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(
|
|
137
|
-
let organization = await this.crud.getOrganization(
|
|
247
|
+
async getApiKey(data, name) {
|
|
248
|
+
let organization = await this.crud.getOrganization(data);
|
|
138
249
|
if (organization.error)
|
|
139
|
-
|
|
250
|
+
throw new Error(organization.error);
|
|
140
251
|
if (!organization.apis)
|
|
141
|
-
|
|
252
|
+
throw new Error('Missing apis object in organization object');
|
|
142
253
|
if (!organization.apis[name])
|
|
143
|
-
|
|
254
|
+
throw new Error(`Missing ${name} in organization apis object`);
|
|
144
255
|
return organization.apis[name]
|
|
145
256
|
}
|
|
146
257
|
|