total5 0.0.1 → 0.0.2
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/LICENSE +211 -0
- package/README.md +32 -0
- package/api.js +297 -0
- package/bin/flow5 +142 -0
- package/bin/total5 +245 -0
- package/builders.js +1770 -0
- package/bundles.js +447 -0
- package/cache.js +58 -0
- package/changelog.txt +5 -0
- package/cluster.js +320 -0
- package/cms.js +759 -0
- package/controller.js +1640 -0
- package/cron.js +99 -0
- package/debug.js +546 -0
- package/edit.js +462 -0
- package/error.html +49 -0
- package/filestorage.js +1109 -0
- package/flow-flowstream.js +3352 -0
- package/flow.js +238 -0
- package/flowstream.js +2061 -0
- package/global.js +274 -0
- package/htmlparser.js +662 -0
- package/http.js +83 -0
- package/image.js +777 -0
- package/images.js +747 -0
- package/index.js +2851 -0
- package/jsonschema.js +699 -0
- package/ldap.js +792 -0
- package/macros.js +222 -0
- package/mail.js +922 -0
- package/markdown.js +762 -0
- package/minificators.js +858 -0
- package/nosql-builder.js +440 -0
- package/nosql-querybuilder.js +320 -0
- package/nosql-reader.js +353 -0
- package/nosql-stream.js +617 -0
- package/nosql.js +782 -0
- package/openclient.js +219 -0
- package/package.json +14 -5
- package/pause.html +67 -0
- package/querybuilder.js +1220 -0
- package/release.js +167 -0
- package/routing.js +1028 -0
- package/sourcemap.js +163 -0
- package/tangular.js +409 -0
- package/templates.js +145 -0
- package/test.js +51 -0
- package/tms.js +380 -0
- package/uibuilder.js +242 -0
- package/utils.js +6432 -0
- package/viewengine.js +891 -0
- package/websocket.js +1944 -0
- package/workers.js +129 -0
package/test.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Total.js Tests
|
|
2
|
+
// The MIT License
|
|
3
|
+
// Copyright 2023 (c) Peter Širka <petersirka@gmail.com>
|
|
4
|
+
|
|
5
|
+
var Test = { items: [], count: 0 };
|
|
6
|
+
|
|
7
|
+
Test.start = function(message) {
|
|
8
|
+
var divider = '------------------------------------------------';
|
|
9
|
+
|
|
10
|
+
if (Test.count)
|
|
11
|
+
console.log('');
|
|
12
|
+
|
|
13
|
+
console.log(divider);
|
|
14
|
+
console.log('> ' + message.padRight(divider.length - 4) + ' <');
|
|
15
|
+
console.log(divider);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
Test.print = function(message, err) {
|
|
19
|
+
console.log('[' + (err ? 'FAIL' : 'OK') + ']', message);
|
|
20
|
+
Test.count++;
|
|
21
|
+
if (err) {
|
|
22
|
+
setTimeout(() => process.exit(1), 1);
|
|
23
|
+
if (err instanceof Error)
|
|
24
|
+
throw err;
|
|
25
|
+
else
|
|
26
|
+
throw new Error(err.toString());
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
Test.push = function(name, fn) {
|
|
31
|
+
Test.items.push({ name: name, fn: fn });
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
Test.run = function(callback) {
|
|
35
|
+
console.time('Time');
|
|
36
|
+
Test.items.wait(function(item, next) {
|
|
37
|
+
Test.start(item.name);
|
|
38
|
+
item.fn(next);
|
|
39
|
+
}, function() {
|
|
40
|
+
console.log('');
|
|
41
|
+
console.log('Tests:', Test.count);
|
|
42
|
+
console.timeEnd('Time');
|
|
43
|
+
console.log('');
|
|
44
|
+
if (callback)
|
|
45
|
+
callback();
|
|
46
|
+
else
|
|
47
|
+
process.exit(0);
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
global.Test = Test;
|
package/tms.js
ADDED
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
// Total.js TMS
|
|
2
|
+
// The MIT License
|
|
3
|
+
// Copyright 2022-2023 (c) Peter Širka <petersirka@gmail.com>
|
|
4
|
+
|
|
5
|
+
const ErrorBuilder = F.TBuilders.ErrorBuilder;
|
|
6
|
+
|
|
7
|
+
var Cache = {
|
|
8
|
+
subscribers: {},
|
|
9
|
+
swatchers: {}, // watchers for subscribers
|
|
10
|
+
scache: {}, // cache for subscribers
|
|
11
|
+
pcache: {}, // cache for publishers
|
|
12
|
+
calls: {},
|
|
13
|
+
socket: null,
|
|
14
|
+
timeout: null,
|
|
15
|
+
url: ''
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
exports.cache = Cache;
|
|
19
|
+
|
|
20
|
+
function tmscontroller($) {
|
|
21
|
+
|
|
22
|
+
var temporary = F.temporary;
|
|
23
|
+
|
|
24
|
+
Cache.socket = $;
|
|
25
|
+
|
|
26
|
+
$.autodestroy(() => Cache.socket = null);
|
|
27
|
+
|
|
28
|
+
$.on('open', function(client) {
|
|
29
|
+
|
|
30
|
+
if (temporary.tmsblocked[client.ip] > 5) {
|
|
31
|
+
client.close(4001);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (F.config.secret_tms) {
|
|
36
|
+
var token = client.headers['x-token']; // || client.query.token;
|
|
37
|
+
if (token != F.config.secret_tms) {
|
|
38
|
+
if (temporary.tmsblocked[client.ip])
|
|
39
|
+
temporary.tmsblocked[client.ip]++;
|
|
40
|
+
else
|
|
41
|
+
temporary.tmsblocked[client.ip] = 1;
|
|
42
|
+
client.close(4001);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
delete temporary.tmsblocked[client.ip];
|
|
48
|
+
client.$subscribers = {};
|
|
49
|
+
client.tmsready = true;
|
|
50
|
+
refresh(client);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
$.on('message', function(client, msg) {
|
|
54
|
+
|
|
55
|
+
// msg.type {String}
|
|
56
|
+
// msg.data {Object}
|
|
57
|
+
|
|
58
|
+
var response;
|
|
59
|
+
|
|
60
|
+
if (client.tmsready) {
|
|
61
|
+
if (msg.type === 'ping') {
|
|
62
|
+
msg.type = 'pong';
|
|
63
|
+
client.send(msg);
|
|
64
|
+
} else if (msg.type === 'subscribe' && msg.id) {
|
|
65
|
+
F.stats.performance.subscribe++;
|
|
66
|
+
var schema = Cache.scache[msg.id];
|
|
67
|
+
if (schema) {
|
|
68
|
+
response = schema.transform(msg.data);
|
|
69
|
+
if (!response.error)
|
|
70
|
+
F.TTMS.subscribe(msg.id, response, client);
|
|
71
|
+
}
|
|
72
|
+
} else if (msg.type === 'subscribers' && msg.subscribers instanceof Array) {
|
|
73
|
+
client.$subscribers = {};
|
|
74
|
+
for (let sub of msg.subscribers)
|
|
75
|
+
client.$subscribers[sub] = true;
|
|
76
|
+
} else if (msg.type === 'call' && msg.id) {
|
|
77
|
+
var tmp = Cache.calls[msg.id];
|
|
78
|
+
if (tmp) {
|
|
79
|
+
F.stats.performance.call++;
|
|
80
|
+
response = tmp.schema.transform(msg.data);
|
|
81
|
+
if (response.error) {
|
|
82
|
+
msg.data = response.error instanceof ErrorBuilder ? response.error.output() : response.response.toString();
|
|
83
|
+
msg.error = true;
|
|
84
|
+
client.send(msg);
|
|
85
|
+
} else {
|
|
86
|
+
tmp.callback(response.response, function(err, response) {
|
|
87
|
+
if (err) {
|
|
88
|
+
msg.error = true;
|
|
89
|
+
if (err instanceof ErrorBuilder)
|
|
90
|
+
msg.data = err.output();
|
|
91
|
+
else
|
|
92
|
+
msg.data = [{ error: err + '' }];
|
|
93
|
+
} else {
|
|
94
|
+
msg.success = true;
|
|
95
|
+
msg.data = response;
|
|
96
|
+
}
|
|
97
|
+
if (client && !client.isClosed)
|
|
98
|
+
client.send(msg);
|
|
99
|
+
}, client);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
msg.error = true;
|
|
104
|
+
msg.data = new ErrorBuilder.push(404).output();
|
|
105
|
+
client.send(msg);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
exports.client = function(url, token, callback) {
|
|
112
|
+
|
|
113
|
+
if (typeof(token) === 'function') {
|
|
114
|
+
callback = token;
|
|
115
|
+
token = undefined;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
var client = F.TWebSocket.createclient();
|
|
119
|
+
var publishers = {};
|
|
120
|
+
var subscribers = {};
|
|
121
|
+
var callbacks = {};
|
|
122
|
+
var isopen = false;
|
|
123
|
+
var callbackid = 0;
|
|
124
|
+
var timeout;
|
|
125
|
+
|
|
126
|
+
if (token)
|
|
127
|
+
client.headers['x-token'] = token;
|
|
128
|
+
|
|
129
|
+
client.options.reconnectserver = true;
|
|
130
|
+
client.connect(url.replace(/^http/, 'ws'));
|
|
131
|
+
client.ready = false;
|
|
132
|
+
|
|
133
|
+
client.on('destroy', function() {
|
|
134
|
+
|
|
135
|
+
publishers = null;
|
|
136
|
+
subscribers = null;
|
|
137
|
+
|
|
138
|
+
for (let key in callbacks) {
|
|
139
|
+
let item = callbacks[key];
|
|
140
|
+
clearTimeout(item.timeout);
|
|
141
|
+
item.callback && item.callback('TMS has been destroyed');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
callbacks = null;
|
|
145
|
+
|
|
146
|
+
timeout && clearTimeout(timeout);
|
|
147
|
+
timeout = null;
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
client.on('close', function() {
|
|
151
|
+
isopen = false;
|
|
152
|
+
client.ready = false;
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
client.on('message', function(msg) {
|
|
156
|
+
if (msg.type === 'call') {
|
|
157
|
+
if (callbacks[msg.callbackid]) {
|
|
158
|
+
let tmp = callbacks[msg.callbackid];
|
|
159
|
+
tmp.callback(msg.error ? ErrorBuilder.assign(msg.data) : null, msg.success ? msg.data : null);
|
|
160
|
+
tmp.timeout && clearTimeout(tmp.timeout);
|
|
161
|
+
delete callbacks[msg.callbackid];
|
|
162
|
+
}
|
|
163
|
+
} else if (msg.type === 'publish' && subscribers[msg.id] && publishers[msg.id]) {
|
|
164
|
+
var err = new ErrorBuilder();
|
|
165
|
+
var data = F.TJSONSchema.transform(publishers[msg.id], err, msg.data, true);
|
|
166
|
+
if (data) {
|
|
167
|
+
for (let fn of subscribers[msg.id])
|
|
168
|
+
fn(data);
|
|
169
|
+
}
|
|
170
|
+
} else if (msg.type === 'meta') {
|
|
171
|
+
publishers = {};
|
|
172
|
+
for (let item of msg.publish)
|
|
173
|
+
publishers[item.id] = item.schema;
|
|
174
|
+
sync_subscribers();
|
|
175
|
+
isopen = true;
|
|
176
|
+
client.ready = true;
|
|
177
|
+
client.meta = msg;
|
|
178
|
+
if (callback) {
|
|
179
|
+
setImmediate(callback, null, client, client.meta);
|
|
180
|
+
callback = null;
|
|
181
|
+
}
|
|
182
|
+
client.emit('meta', msg);
|
|
183
|
+
client.emit('ready');
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
var timeouthandler = function(id) {
|
|
188
|
+
let obj = callbacks[id];
|
|
189
|
+
obj.callback && obj.callback('408: Timeout');
|
|
190
|
+
delete callbacks[id];
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
client.call = function(name, data, callback, timeout) {
|
|
194
|
+
if (callback)
|
|
195
|
+
client.$call(name, data, callback, timeout);
|
|
196
|
+
else
|
|
197
|
+
return new Promise((resolve, reject) => client.$call(name, data, (err, res) => err ? reject(err) : resolve(res), timeout));
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
client.$call = function(name, data, callback, timeout) {
|
|
201
|
+
if (isopen) {
|
|
202
|
+
let key = (callbackid++) + '';
|
|
203
|
+
let obj = {};
|
|
204
|
+
obj.callback = callback;
|
|
205
|
+
obj.timeout = setTimeout(timeouthandler, timeout || 10000, key);
|
|
206
|
+
callbacks[key] = obj;
|
|
207
|
+
client.send({ type: 'call', id: name, data: data, callbackid: key });
|
|
208
|
+
} else
|
|
209
|
+
callback('TMS is offline');
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
client.subscribe = function(name, callback) {
|
|
213
|
+
timeout && clearTimeout(timeout);
|
|
214
|
+
timeout = setTimeout(sync_subscribers, 30, true);
|
|
215
|
+
if (subscribers[name])
|
|
216
|
+
subscribers[name].push(callback);
|
|
217
|
+
else
|
|
218
|
+
subscribers[name] = [callback];
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
client.publish = function(name, data) {
|
|
222
|
+
isopen && client.send({ type: 'subscribe', id: name, data: data });
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
var sync_subscribers = function(force) {
|
|
226
|
+
timeout && clearTimeout(timeout);
|
|
227
|
+
timeout = null;
|
|
228
|
+
let keys = Object.keys(subscribers);
|
|
229
|
+
if (force || keys.length)
|
|
230
|
+
client.send({ type: 'subscribers', subscribers: keys });
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
return client;
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
function refresh(client) {
|
|
237
|
+
|
|
238
|
+
if (Cache.socket) {
|
|
239
|
+
|
|
240
|
+
var subscribed = [];
|
|
241
|
+
var published = [];
|
|
242
|
+
|
|
243
|
+
for (let key in Cache.pcache)
|
|
244
|
+
published.push({ id: key, schema: Cache.pcache[key] });
|
|
245
|
+
|
|
246
|
+
for (let key in Cache.scache)
|
|
247
|
+
subscribed.push({ id: key, schema: Cache.scache[key] });
|
|
248
|
+
|
|
249
|
+
var calls = [];
|
|
250
|
+
for (let key in Cache.calls)
|
|
251
|
+
calls.push({ id: key, schema: Cache.calls[key].schema });
|
|
252
|
+
|
|
253
|
+
var msg = { type: 'meta', name: F.config.name, subscribe: subscribed, publish: published, subscribers: Object.keys(Cache.subscribers), call: calls };
|
|
254
|
+
if (client)
|
|
255
|
+
client.send(msg);
|
|
256
|
+
else
|
|
257
|
+
Cache.socket.send(msg);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
exports.refresh = function() {
|
|
262
|
+
Cache.timeout && clearTimeout(Cache.timeout);
|
|
263
|
+
Cache.timeout = setTimeout(refresh, 500);
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
exports.newpublish = function(name, schema) {
|
|
267
|
+
|
|
268
|
+
if (schema == null) {
|
|
269
|
+
delete Cache.pcache[name];
|
|
270
|
+
exports.refresh();
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
Cache.pcache[name] = F.TUtils.jsonschema(schema);
|
|
275
|
+
exports.refresh();
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
exports.newcall = function(name, schema, callback) {
|
|
279
|
+
|
|
280
|
+
if (schema == null) {
|
|
281
|
+
delete Cache.calls[name];
|
|
282
|
+
exports.refresh();
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (!callback)
|
|
287
|
+
callback = (data, callback, client) => F.action(schema, data, client).callback(callback);
|
|
288
|
+
|
|
289
|
+
let obj = {};
|
|
290
|
+
obj.schema = F.TUtils.jsonschema(schema);
|
|
291
|
+
obj.callback = callback;
|
|
292
|
+
Cache.calls[name] = obj;
|
|
293
|
+
exports.refresh();
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
exports.newsubscribe = function(name, schema, callback) {
|
|
297
|
+
|
|
298
|
+
if (typeof(schema) === 'function') {
|
|
299
|
+
callback = schema;
|
|
300
|
+
schema = null;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (schema)
|
|
304
|
+
Cache.scache[name] = F.TUtils.jsonschema(schema);
|
|
305
|
+
else
|
|
306
|
+
delete Cache.scache[name];
|
|
307
|
+
|
|
308
|
+
callback && exports.subscribe(name, callback);
|
|
309
|
+
exports.refresh();
|
|
310
|
+
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
exports.publish = function(name, value) {
|
|
314
|
+
if (Cache.socket && Cache.pcache[name]) {
|
|
315
|
+
F.stats.performance.publish++;
|
|
316
|
+
Cache.socket.send({ type: 'publish', id: name, data: value }, client => client.tmsready && client.$subscribers[name]);
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
exports.subscribe = function(name, callback, client) {
|
|
321
|
+
if (client) {
|
|
322
|
+
var arr = Cache.swatchers[name];
|
|
323
|
+
if (arr) {
|
|
324
|
+
for (let fn of arr)
|
|
325
|
+
fn(callback, client);
|
|
326
|
+
}
|
|
327
|
+
} else {
|
|
328
|
+
if (Cache.swatchers[name])
|
|
329
|
+
Cache.swatchers[name].push(callback);
|
|
330
|
+
else
|
|
331
|
+
Cache.swatchers[name] = [callback];
|
|
332
|
+
Cache.subscribers[name] = 1;
|
|
333
|
+
exports.refresh();
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
exports.unsubscribe = function(name, callback) {
|
|
338
|
+
if (Cache.swatchers[name]) {
|
|
339
|
+
exports.refresh();
|
|
340
|
+
if (callback) {
|
|
341
|
+
let index = Cache.swatchers[name].indexOf(callback);
|
|
342
|
+
if (index !== -1)
|
|
343
|
+
Cache.swatchers[name].splice(index, 1);
|
|
344
|
+
if (!Cache.swatchers[name].length)
|
|
345
|
+
delete Cache.swatchers[name];
|
|
346
|
+
if (Cache.swatchers[name])
|
|
347
|
+
Cache.subscribers[name] = 1;
|
|
348
|
+
else
|
|
349
|
+
delete Cache.subscribers[name];
|
|
350
|
+
return index !== -1;
|
|
351
|
+
} else {
|
|
352
|
+
delete Cache.swatchers[name];
|
|
353
|
+
delete Cache.subscribers[name];
|
|
354
|
+
return true;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return false;
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
F.on('$tms', function() {
|
|
361
|
+
|
|
362
|
+
var endpoint = F.config.$tmsurl;
|
|
363
|
+
var is = Cache.url !== endpoint;
|
|
364
|
+
|
|
365
|
+
if (is && Cache.route) {
|
|
366
|
+
Cache.route.remove();
|
|
367
|
+
Cache.route = null;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if ((is && endpoint && F.config.$tms) || (endpoint && F.config.$tms && !Cache.route))
|
|
371
|
+
Cache.route = F.route('SOCKET ' + endpoint, tmscontroller, F.config.$tmsmaxsize * 1024);
|
|
372
|
+
|
|
373
|
+
Cache.url = endpoint;
|
|
374
|
+
|
|
375
|
+
if (endpoint && Cache.token !== F.config.secret_tms) {
|
|
376
|
+
Cache.token = F.config.secret_tms;
|
|
377
|
+
Cache.socket && Cache.socket.close(1000, 'Changed TMS secret');
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
});
|
package/uibuilder.js
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
// UIBuilder compiler | https://uibuilder.totaljs.com
|
|
2
|
+
// The MIT License
|
|
3
|
+
// Copyright 2023 (c) Peter Širka <petersirka@gmail.com>
|
|
4
|
+
|
|
5
|
+
const REG_END = /;|\n/;
|
|
6
|
+
const REG_STRING = /'|"/g;
|
|
7
|
+
|
|
8
|
+
exports.compile = async function(opt, callback) {
|
|
9
|
+
|
|
10
|
+
// opt.schema {String/Object}
|
|
11
|
+
// |--- opt.schema.origin {String}
|
|
12
|
+
// opt.local {Boolean}
|
|
13
|
+
// opt.download {Boolean}
|
|
14
|
+
// opt.origin {String}
|
|
15
|
+
// opt.filesystem {Boolean} enables loading components from HDD (default: false)
|
|
16
|
+
|
|
17
|
+
if (!callback)
|
|
18
|
+
return new Promise((resolve, reject) => exports.compile(opt, (err, response) => err ? reject(err) : resolve(response)));
|
|
19
|
+
|
|
20
|
+
if (typeof(opt.schema) === 'string')
|
|
21
|
+
opt.schema = opt.schema.parseJSON();
|
|
22
|
+
|
|
23
|
+
var schema = opt.schema;
|
|
24
|
+
var instances = getInstances(schema);
|
|
25
|
+
var used = {};
|
|
26
|
+
var response = {};
|
|
27
|
+
|
|
28
|
+
for (let instance of instances)
|
|
29
|
+
used[instance.component] = '#';
|
|
30
|
+
|
|
31
|
+
if (opt.local) {
|
|
32
|
+
response.components = used;
|
|
33
|
+
} else {
|
|
34
|
+
let components = await getComponents(opt, used);
|
|
35
|
+
response.components = components;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
for (let key in schema) {
|
|
39
|
+
if (key !== 'components')
|
|
40
|
+
response[key] = schema[key];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
response.inputs = schema.inputs;
|
|
44
|
+
response.outputs = schema.outputs;
|
|
45
|
+
response.children = schema.children;
|
|
46
|
+
response.compiled = true;
|
|
47
|
+
|
|
48
|
+
if (response.cssoutput)
|
|
49
|
+
response.css = response.cssoutput;
|
|
50
|
+
|
|
51
|
+
delete response.editor;
|
|
52
|
+
delete response.cssoutput;
|
|
53
|
+
delete response.csseditor;
|
|
54
|
+
delete response.csspreview;
|
|
55
|
+
|
|
56
|
+
callback(null, response);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
exports.download = async function(opt, callback) {
|
|
60
|
+
|
|
61
|
+
if (!callback)
|
|
62
|
+
return new Promise((resolve, reject) => exports.download(opt, (err, response) => err ? reject(err) : resolve(response)));
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
let response = await getComponents2(opt);
|
|
66
|
+
callback(null, response);
|
|
67
|
+
} catch (e) {
|
|
68
|
+
callback(e);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
function getInstances(schema) {
|
|
74
|
+
var response = [];
|
|
75
|
+
var browse = function(parent) {
|
|
76
|
+
|
|
77
|
+
for (let arr of parent.children) {
|
|
78
|
+
for (let child of arr) {
|
|
79
|
+
let cloned = F.TUtils.clone(child);
|
|
80
|
+
cloned.children = undefined;
|
|
81
|
+
response.push(cloned);
|
|
82
|
+
browse(child);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
browse(schema);
|
|
88
|
+
return response;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function Download(url, local = false) {
|
|
92
|
+
return new Promise(function(resolve) {
|
|
93
|
+
|
|
94
|
+
if (local && url[0] === '~') {
|
|
95
|
+
// File on HDD (potential dangerous)
|
|
96
|
+
F.Fs.readFile(url.substring(1), 'utf8', function(err, response) {
|
|
97
|
+
resolve(err ? '' : (response.isJSON() ? response.parseJSON(true) : response));
|
|
98
|
+
});
|
|
99
|
+
} else {
|
|
100
|
+
let opt = {};
|
|
101
|
+
opt.url = url;
|
|
102
|
+
opt.method = 'GET';
|
|
103
|
+
opt.keepalive = true;
|
|
104
|
+
opt.insecure = true;
|
|
105
|
+
opt.callback = function(err, response) {
|
|
106
|
+
resolve(response.status === 200 ? (response.body.isJSON() ? response.body.parseJSON(true) : response.body) : '');
|
|
107
|
+
};
|
|
108
|
+
REQUEST(opt);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function parseorigin(url) {
|
|
114
|
+
|
|
115
|
+
var origin = '';
|
|
116
|
+
|
|
117
|
+
if (url.charAt(0) !== '/') {
|
|
118
|
+
var index = url.indexOf('/', 9);
|
|
119
|
+
origin = index === -1 ? url : url.substring(0, index);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return origin;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async function getComponents(opt, used) {
|
|
126
|
+
|
|
127
|
+
var schema = opt.schema;
|
|
128
|
+
var download = opt.download;
|
|
129
|
+
var components = {};
|
|
130
|
+
var arr = [];
|
|
131
|
+
|
|
132
|
+
for (let key in schema.components)
|
|
133
|
+
arr.push({ id: key, value: schema.components[key] });
|
|
134
|
+
|
|
135
|
+
for (let com of arr) {
|
|
136
|
+
|
|
137
|
+
if (com.value.indexOf('.json') === -1 && !used[com.id])
|
|
138
|
+
continue;
|
|
139
|
+
|
|
140
|
+
let url = com.value;
|
|
141
|
+
let origin = opt.origin || schema.origin;
|
|
142
|
+
|
|
143
|
+
if (url[0] === '/') {
|
|
144
|
+
url = origin + url;
|
|
145
|
+
} else
|
|
146
|
+
origin = parseorigin(url);
|
|
147
|
+
|
|
148
|
+
let body = await Download(url.format(com.id), opt.filesystem);
|
|
149
|
+
|
|
150
|
+
if (typeof(body) === 'string') {
|
|
151
|
+
|
|
152
|
+
let index = body.indexOf('exports.render');
|
|
153
|
+
if (index === -1) {
|
|
154
|
+
// without render
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
index += 14;
|
|
159
|
+
|
|
160
|
+
let end = body.substring(index).match(REG_END);
|
|
161
|
+
if (!end) {
|
|
162
|
+
// without end
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
let render = body.substring(body.indexOf('=', index) + 1, index + end.index).trim().replace(REG_STRING, '').format(com.id);
|
|
167
|
+
|
|
168
|
+
if (render[0] === '/')
|
|
169
|
+
render = (origin || schema.origin || '') + render;
|
|
170
|
+
|
|
171
|
+
if (download) {
|
|
172
|
+
if (render.substring(0, 7) === 'base64 ') {
|
|
173
|
+
components[com.id] = render;
|
|
174
|
+
} else {
|
|
175
|
+
let html = await Download(render, opt.filesystem);
|
|
176
|
+
if (html)
|
|
177
|
+
components[com.id] = 'base64 ' + Buffer.from(encodeURIComponent(html), 'utf8').toString('base64');
|
|
178
|
+
}
|
|
179
|
+
} else
|
|
180
|
+
components[com.id] = render;
|
|
181
|
+
} else {
|
|
182
|
+
for (let key in body)
|
|
183
|
+
arr.push({ id: key, value: body[key] });
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return components;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
async function getComponents2(opt) {
|
|
191
|
+
|
|
192
|
+
var list = opt.components;
|
|
193
|
+
var origin = opt.origin;
|
|
194
|
+
var components = {};
|
|
195
|
+
var arr = [];
|
|
196
|
+
|
|
197
|
+
for (let key in list)
|
|
198
|
+
arr.push({ id: key, value: list[key] });
|
|
199
|
+
|
|
200
|
+
for (let com of arr) {
|
|
201
|
+
|
|
202
|
+
let url = com.value;
|
|
203
|
+
if (url[0] === '/')
|
|
204
|
+
url = origin + url;
|
|
205
|
+
|
|
206
|
+
let body = await Download(url.format(com.id), opt.filesystem);
|
|
207
|
+
|
|
208
|
+
if (typeof(body) === 'string') {
|
|
209
|
+
|
|
210
|
+
let index = body.indexOf('exports.render');
|
|
211
|
+
if (index === -1) {
|
|
212
|
+
// without render
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
index += 14;
|
|
217
|
+
|
|
218
|
+
let end = body.substring(index).match(REG_END);
|
|
219
|
+
if (!end) {
|
|
220
|
+
// without end
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
let render = body.substring(body.indexOf('=', index) + 1, index + end.index).trim().replace(REG_STRING, '').format(com.id);
|
|
225
|
+
|
|
226
|
+
if (render.substring(0, 7) === 'base64 ') {
|
|
227
|
+
components[com.id] = render;
|
|
228
|
+
} else {
|
|
229
|
+
if (render[0] === '/')
|
|
230
|
+
render = origin + render;
|
|
231
|
+
let html = await Download(render, opt.filesystem);
|
|
232
|
+
if (html)
|
|
233
|
+
components[com.id] = 'base64 ' + Buffer.from(encodeURIComponent(html), 'utf8').toString('base64');
|
|
234
|
+
}
|
|
235
|
+
} else {
|
|
236
|
+
for (let key in body)
|
|
237
|
+
arr.push({ id: key, value: body[key] });
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return components;
|
|
242
|
+
}
|