total5 0.0.1-9 → 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/api.js +18 -10
- package/bin/flow5 +142 -0
- package/bin/total5 +166 -905
- package/builders.js +90 -35
- package/changelog.txt +3 -1
- package/cluster.js +1 -1
- package/cms.js +185 -51
- package/controller.js +233 -70
- package/cron.js +1 -1
- package/debug.js +12 -5
- package/edit.js +26 -33
- package/filestorage.js +38 -17
- package/flow-flowstream.js +199 -68
- package/flow.js +16 -10
- package/flowstream.js +4 -3
- package/global.js +84 -1
- package/htmlparser.js +41 -29
- package/http.js +3 -1
- package/image.js +4 -0
- package/images.js +1 -1
- package/index.js +246 -117
- package/jsonschema.js +21 -17
- package/macros.js +222 -0
- package/mail.js +11 -27
- package/markdown.js +21 -11
- package/minificators.js +1 -1
- package/nosql-querybuilder.js +4 -0
- package/nosql.js +8 -0
- package/openclient.js +1 -1
- package/package.json +4 -3
- package/pause.html +1 -1
- package/release.js +1 -1
- package/routing.js +118 -35
- package/sourcemap.js +6 -3
- package/test.js +9 -2
- package/tms.js +11 -14
- package/uibuilder.js +59 -23
- package/utils.js +147 -102
- package/viewengine.js +19 -8
- package/websocket.js +10 -6
- package/503.html +0 -65
- package/CONTRIBUTING.md +0 -55
- package/helpers/index.js +0 -32
- package/templates.json +0 -74
- package/tests/bundles/index.js +0 -25
- package/tests/cron.js +0 -0
- package/tests/htmlparser.js +0 -0
- package/tests/minifactors.js +0 -17
- package/tests/nosql.js +0 -18
- package/tests/proxy/index.js +0 -21
- package/tests/routing/index.js +0 -27
- package/tests/schemas.js +0 -17
- package/tests/server/index.js +0 -24
- package/tests/staticfiles/index.js +0 -24
- package/tests/utils.js +0 -17
- package/tmsclient.js +0 -125
- package/todo.txt +0 -11
- package/tools/beta.sh +0 -6
- package/tools/release.sh +0 -6
package/routing.js
CHANGED
|
@@ -19,26 +19,38 @@ function parseSizeTimeout(route, value) {
|
|
|
19
19
|
|
|
20
20
|
switch (type) {
|
|
21
21
|
case 's':
|
|
22
|
-
route.timeout
|
|
22
|
+
if (route.timeout < number)
|
|
23
|
+
route.timeout = number;
|
|
23
24
|
break;
|
|
24
25
|
case 'm':
|
|
25
|
-
|
|
26
|
+
number = number * 60;
|
|
27
|
+
if (route.timeout < number)
|
|
28
|
+
route.timeout = number;
|
|
26
29
|
break;
|
|
27
30
|
case 'h':
|
|
28
|
-
|
|
31
|
+
number = number * 60 * 60;
|
|
32
|
+
if (route.timeout < number)
|
|
33
|
+
route.timeout = number;
|
|
29
34
|
break;
|
|
30
35
|
case 'b':
|
|
31
|
-
route.size
|
|
36
|
+
if (route.size < number)
|
|
37
|
+
route.size = number;
|
|
32
38
|
break;
|
|
33
39
|
case 'kb':
|
|
34
|
-
|
|
40
|
+
number = number / 1024;
|
|
41
|
+
if (route.size < number)
|
|
42
|
+
route.size = number;
|
|
35
43
|
break;
|
|
36
44
|
case 'gb':
|
|
37
|
-
|
|
45
|
+
number = (number * 1024 * 1024) * 1000;
|
|
46
|
+
if (route.size < number)
|
|
47
|
+
route.size = number;
|
|
38
48
|
break;
|
|
39
49
|
case 'mb':
|
|
40
50
|
default:
|
|
41
|
-
|
|
51
|
+
number = number * 1024 * 1024;
|
|
52
|
+
if (route.size < number)
|
|
53
|
+
route.size = number;
|
|
42
54
|
break;
|
|
43
55
|
}
|
|
44
56
|
}
|
|
@@ -51,17 +63,24 @@ function Route(url, action, size) {
|
|
|
51
63
|
action = null;
|
|
52
64
|
}
|
|
53
65
|
|
|
66
|
+
// Apply a default API endpoint
|
|
67
|
+
url = url.replace(/\?/g, F.config.$api).replace(/\/{2,}/g, '/');
|
|
68
|
+
|
|
54
69
|
var t = this;
|
|
55
70
|
|
|
56
71
|
if (url[0] === '#') {
|
|
57
72
|
// internal routing
|
|
58
|
-
t.url = [url
|
|
73
|
+
t.url = [url.substring(1)];
|
|
59
74
|
t.action = action;
|
|
60
75
|
t.fallback = true;
|
|
61
|
-
F.routes.fallback[t.url
|
|
76
|
+
F.routes.fallback[t.url] = t;
|
|
62
77
|
return;
|
|
63
78
|
}
|
|
64
79
|
|
|
80
|
+
t.timeout = 0;
|
|
81
|
+
t.size = 0;
|
|
82
|
+
t.flags = {};
|
|
83
|
+
|
|
65
84
|
var index = url.indexOf(' ');
|
|
66
85
|
|
|
67
86
|
t.method = url.substring(0, index).toUpperCase();
|
|
@@ -77,7 +96,7 @@ function Route(url, action, size) {
|
|
|
77
96
|
if (t.url2[0] === '@') {
|
|
78
97
|
// @TODO: missing WAPI implementation
|
|
79
98
|
t.skip = true;
|
|
80
|
-
console.log('This "{0}" kind of routes are not supported yet'.
|
|
99
|
+
console.log('This "{0}" kind of routes are not supported yet'.format(t.url2));
|
|
81
100
|
return;
|
|
82
101
|
}
|
|
83
102
|
|
|
@@ -100,6 +119,7 @@ function Route(url, action, size) {
|
|
|
100
119
|
}
|
|
101
120
|
|
|
102
121
|
if (t.method === 'FILE') {
|
|
122
|
+
|
|
103
123
|
let types = t.url[t.url.length - 1];
|
|
104
124
|
|
|
105
125
|
// fixed filename
|
|
@@ -117,6 +137,7 @@ function Route(url, action, size) {
|
|
|
117
137
|
for (let type of types)
|
|
118
138
|
t.ext[type] = 1;
|
|
119
139
|
}
|
|
140
|
+
|
|
120
141
|
} else {
|
|
121
142
|
t.params = [];
|
|
122
143
|
index = 0;
|
|
@@ -130,7 +151,6 @@ function Route(url, action, size) {
|
|
|
130
151
|
t.size = size || 0;
|
|
131
152
|
}
|
|
132
153
|
|
|
133
|
-
t.flags = {};
|
|
134
154
|
t.middleware = [];
|
|
135
155
|
|
|
136
156
|
index = t.url.indexOf('*');
|
|
@@ -152,13 +172,16 @@ function Route(url, action, size) {
|
|
|
152
172
|
t.partial = t.method === 'PATCH';
|
|
153
173
|
|
|
154
174
|
var endpoint = '';
|
|
175
|
+
var isapi = false;
|
|
155
176
|
|
|
156
177
|
if (t.method === 'API') {
|
|
157
178
|
t.method = 'POST';
|
|
179
|
+
isapi = true;
|
|
158
180
|
t.id = t.id.replace(/^(\+|-)/, '');
|
|
159
181
|
url = url.replace(/(\*|\+|-|%)?[a-z0-9-_/{}]+/i, function(text) {
|
|
160
182
|
let tmp = text.trim();
|
|
161
|
-
|
|
183
|
+
let c = tmp[0];
|
|
184
|
+
endpoint = c === '%' || c === '+' || c === '*' || c === '-' ? tmp.substring(1) : tmp;
|
|
162
185
|
t.partial = tmp[0] === '%';
|
|
163
186
|
return text;
|
|
164
187
|
});
|
|
@@ -185,8 +208,12 @@ function Route(url, action, size) {
|
|
|
185
208
|
t.actions.push(text.trim());
|
|
186
209
|
return '';
|
|
187
210
|
}).trim();
|
|
188
|
-
} else
|
|
189
|
-
|
|
211
|
+
} else {
|
|
212
|
+
if (isapi)
|
|
213
|
+
t.actions = [url.replace(/\+|-|%|#/g, '').trim()];
|
|
214
|
+
else
|
|
215
|
+
t.actions = url.substring(0, index + 3).replace(/\s{2,}/g, ' ').split(/\s|,/);
|
|
216
|
+
}
|
|
190
217
|
|
|
191
218
|
var parent = null;
|
|
192
219
|
|
|
@@ -202,9 +229,10 @@ function Route(url, action, size) {
|
|
|
202
229
|
|
|
203
230
|
parent = F.routes.routes.findItem('id', t.id);
|
|
204
231
|
|
|
205
|
-
var apiroute = { auth: t.auth, params: params, actions: t.actions.join(',') };
|
|
232
|
+
var apiroute = { auth: t.auth, params: params, actions: t.actions.join(','), action: action, timeout: t.timeout };
|
|
206
233
|
|
|
207
234
|
t.apiendpoint = arr[0];
|
|
235
|
+
|
|
208
236
|
if (parent) {
|
|
209
237
|
parent.api[arr[0]] = apiroute;
|
|
210
238
|
t.skip = true;
|
|
@@ -227,11 +255,11 @@ function Route(url, action, size) {
|
|
|
227
255
|
if (!t.size) {
|
|
228
256
|
switch (t.type) {
|
|
229
257
|
case 'websocket':
|
|
230
|
-
t.size = F.config.$wsmaxsize;
|
|
258
|
+
t.size = F.config.$wsmaxsize * 1024;
|
|
231
259
|
t.connections = [];
|
|
232
260
|
break;
|
|
233
261
|
case 'route':
|
|
234
|
-
t.size = F.config.$httpmaxsize;
|
|
262
|
+
t.size = F.config.$httpmaxsize * 1024;
|
|
235
263
|
break;
|
|
236
264
|
}
|
|
237
265
|
}
|
|
@@ -244,8 +272,12 @@ function Route(url, action, size) {
|
|
|
244
272
|
t.action = null;
|
|
245
273
|
}
|
|
246
274
|
|
|
275
|
+
if (!t.view && !t.action && t.method !== 'FILE' && t.method !== 'SOCKET')
|
|
276
|
+
t.view = t.url[0] && t.url[0] !== '/' ? t.url[0] : 'index';
|
|
277
|
+
|
|
247
278
|
if (t.wildcard)
|
|
248
279
|
t.priority -= 50;
|
|
280
|
+
|
|
249
281
|
}
|
|
250
282
|
|
|
251
283
|
Route.prototype.compare = function(ctrl) {
|
|
@@ -270,7 +302,7 @@ Route.prototype.remove = function() {
|
|
|
270
302
|
F.routes.websockets.splice(index);
|
|
271
303
|
for (let conn of self.connections)
|
|
272
304
|
conn.destroy();
|
|
273
|
-
break;
|
|
305
|
+
break;
|
|
274
306
|
case 'file':
|
|
275
307
|
index = F.routes.files.indexOf(self);
|
|
276
308
|
if (index !== -1)
|
|
@@ -401,6 +433,10 @@ exports.sort = function() {
|
|
|
401
433
|
|
|
402
434
|
tmp = cache;
|
|
403
435
|
let key = route.url.join('/');
|
|
436
|
+
|
|
437
|
+
if (route.wildcard)
|
|
438
|
+
key += '/*';
|
|
439
|
+
|
|
404
440
|
if (cache[key])
|
|
405
441
|
cache[key].push(route);
|
|
406
442
|
else
|
|
@@ -482,8 +518,7 @@ exports.lookup = function(ctrl, auth = 0, skip = false) {
|
|
|
482
518
|
|
|
483
519
|
// Dynamic routes
|
|
484
520
|
if (tmp.D && !(length === 1 && arr[0] === '/')) {
|
|
485
|
-
for (
|
|
486
|
-
var r = tmp.D[i];
|
|
521
|
+
for (let r of tmp.D) {
|
|
487
522
|
if (r.url.length === length || r.wildcard) {
|
|
488
523
|
if (r.compare(ctrl)) {
|
|
489
524
|
if (!routes)
|
|
@@ -575,11 +610,30 @@ exports.lookupcors = function(ctrl) {
|
|
|
575
610
|
return false;
|
|
576
611
|
}
|
|
577
612
|
|
|
578
|
-
|
|
613
|
+
let origin = ctrl.headers.origin;
|
|
579
614
|
|
|
580
|
-
if (
|
|
581
|
-
|
|
582
|
-
|
|
615
|
+
if (F.config.$cors !== '*' && !origin.endsWith(ctrl.headers.host)) {
|
|
616
|
+
|
|
617
|
+
let resume = false;
|
|
618
|
+
let cors = F.temporary.cors;
|
|
619
|
+
|
|
620
|
+
if (cors) {
|
|
621
|
+
if (cors.strict.length && cors.strict.includes(origin)) {
|
|
622
|
+
resume = true;
|
|
623
|
+
} else if (cors.wildcard.length) {
|
|
624
|
+
for (let m of cors.wildcard) {
|
|
625
|
+
if (origin.includes(m)) {
|
|
626
|
+
resume = true;
|
|
627
|
+
break;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
if (!resume) {
|
|
634
|
+
ctrl.fallback(400, 'Invalid origin (CORS)');
|
|
635
|
+
return false;
|
|
636
|
+
}
|
|
583
637
|
}
|
|
584
638
|
|
|
585
639
|
ctrl.response.headers['access-control-allow-origin'] = origin;
|
|
@@ -609,10 +663,20 @@ exports.lookupfile = function(ctrl, auth = 0) {
|
|
|
609
663
|
let key = '';
|
|
610
664
|
for (let i = 0; i < ctrl.split2.length - 1; i++)
|
|
611
665
|
key += (i ? '/' : '') + ctrl.split2[i];
|
|
612
|
-
|
|
613
666
|
let routes = F.routes.filescache[key];
|
|
614
667
|
if (routes)
|
|
615
668
|
return compareflags(ctrl, routes, auth);
|
|
669
|
+
|
|
670
|
+
// Wildcard
|
|
671
|
+
let length = ctrl.split2.length;
|
|
672
|
+
routes = [];
|
|
673
|
+
|
|
674
|
+
for (let i = 0; i < length; i++) {
|
|
675
|
+
let url = ctrl.split2.slice(0, length - i).join('/') + '/*';
|
|
676
|
+
let item = F.routes.filescache[url];
|
|
677
|
+
if (item)
|
|
678
|
+
return item[0];
|
|
679
|
+
}
|
|
616
680
|
}
|
|
617
681
|
};
|
|
618
682
|
|
|
@@ -712,14 +776,31 @@ Proxy.prototype.copy = function(type) {
|
|
|
712
776
|
|
|
713
777
|
// @type {String} none|replace|extend
|
|
714
778
|
|
|
779
|
+
// "none":
|
|
780
|
+
// PROXY('/cl/', 'https://yourdomain.com');
|
|
781
|
+
// GET /cl/?q=search --> https://yourdomain.com/?q=search');
|
|
782
|
+
// GET /cl/something/?q=search --> https://yourdomain.com/?q=search');
|
|
783
|
+
|
|
784
|
+
// "replace":
|
|
785
|
+
// PROXY('/cl/', 'https://yourdomain.com');
|
|
786
|
+
// GET /cl/?q=search --> https://yourdomain.com/');
|
|
787
|
+
// GET /cl/something/?q=search --> https://yourdomain.com/something/');
|
|
788
|
+
|
|
789
|
+
// "extend":
|
|
790
|
+
// PROXY('/cl/', 'https://yourdomain.com');
|
|
791
|
+
// GET /cl/?q=search --> https://yourdomain.com/?q=search');
|
|
792
|
+
// GET /cl/something/?q=search --> https://yourdomain.com/something/?q=search');
|
|
793
|
+
|
|
715
794
|
var t = this;
|
|
716
795
|
if (type === 'replace' && t.target.pathname.length > 1)
|
|
717
796
|
type = 'extend';
|
|
797
|
+
|
|
718
798
|
t.copypath = type;
|
|
719
799
|
return t;
|
|
720
800
|
};
|
|
721
801
|
|
|
722
802
|
Proxy.prototype.after = function(callback) {
|
|
803
|
+
// callback(response)
|
|
723
804
|
var t = this;
|
|
724
805
|
t.$after = callback;
|
|
725
806
|
return t;
|
|
@@ -733,11 +814,13 @@ Proxy.prototype.timeout = function(timeout) {
|
|
|
733
814
|
|
|
734
815
|
Proxy.prototype.check = function(callback) {
|
|
735
816
|
var t = this;
|
|
817
|
+
// callback(ctrl)
|
|
736
818
|
t.$check = callback;
|
|
737
819
|
return t;
|
|
738
820
|
};
|
|
739
821
|
|
|
740
822
|
Proxy.prototype.before = function(callback) {
|
|
823
|
+
// callback(uri, ctrl)
|
|
741
824
|
var t = this;
|
|
742
825
|
t.$before = callback;
|
|
743
826
|
return t;
|
|
@@ -753,7 +836,7 @@ Proxy.prototype.remove = function() {
|
|
|
753
836
|
exports.proxy = function(url, target) {
|
|
754
837
|
|
|
755
838
|
if (!target) {
|
|
756
|
-
let index = F.routes.proxies.
|
|
839
|
+
let index = F.routes.proxies.TfindIndex('url', url.toLowerCase());
|
|
757
840
|
if (index !== -1)
|
|
758
841
|
F.routes.proxies.splice(index, 1);
|
|
759
842
|
return;
|
|
@@ -769,7 +852,7 @@ exports.lookupproxy = function(ctrl) {
|
|
|
769
852
|
var u = ctrl.uri.key.substring(0, proxy.url.length);
|
|
770
853
|
if (u[u.length - 1] !== '/')
|
|
771
854
|
u += '/';
|
|
772
|
-
if (u === proxy.url && (!proxy
|
|
855
|
+
if (u === proxy.url && (!proxy.$check || proxy.$check(ctrl))) {
|
|
773
856
|
F.stats.response.proxy++;
|
|
774
857
|
proxycreate(proxy, ctrl);
|
|
775
858
|
return true;
|
|
@@ -807,19 +890,19 @@ function proxycreate(proxy, ctrl) {
|
|
|
807
890
|
|
|
808
891
|
var tmp;
|
|
809
892
|
|
|
810
|
-
uri.method = ctrl.method;
|
|
893
|
+
uri.method = ctrl.method === 'SOCKET' ? 'GET' : ctrl.method;
|
|
811
894
|
uri.headers = ctrl.headers;
|
|
812
895
|
ctrl.$proxy = proxy;
|
|
813
896
|
|
|
814
897
|
if (uri.socketPath) {
|
|
815
|
-
uri.path = proxy.copypath == 'none' || proxy.copypath === 'replace' ? ctrl.url.substring(proxy.url.length - 1) : ctrl.uri.pathname;
|
|
898
|
+
uri.path = (proxy.copypath == 'none' || proxy.copypath === 'replace' ? ctrl.url.substring(proxy.url.length - 1) : ctrl.uri.pathname) + (ctrl.uri.search ? ((proxy.uri.search && proxy.uri.search.length > 1 ? '&' : '?') + ctrl.uri.search) : '');
|
|
816
899
|
} else {
|
|
817
900
|
|
|
818
901
|
if (proxy.copypath === 'none') {
|
|
819
|
-
uri.path = proxy.uri.path;
|
|
820
|
-
} else if (proxy.copypath === 'replace')
|
|
902
|
+
uri.path = proxy.uri.path + (ctrl.uri.search ? ((proxy.uri.search && proxy.uri.search.length > 1 ? '&' : '?') + ctrl.uri.search) : '');
|
|
903
|
+
} else if (proxy.copypath === 'replace') {
|
|
821
904
|
uri.path = ctrl.url.substring(proxy.url.length - 1);
|
|
822
|
-
else if (proxy.copypath === 'extend') {
|
|
905
|
+
} else if (proxy.copypath === 'extend') {
|
|
823
906
|
tmp = ctrl.uri.pathname.substring(proxy.url.length) + (ctrl.uri.search ? ('?' + ctrl.uri.search) : '');
|
|
824
907
|
uri.path = proxy.path + (tmp ? ((tmp[0] === '/' ? '' : '/') + tmp) : '') + (proxy.query ? (ctrl.uri.search ? ('&' + proxy.query) : ('?' + proxy.query)) : '');
|
|
825
908
|
} else {
|
|
@@ -841,7 +924,7 @@ function proxycreate(proxy, ctrl) {
|
|
|
841
924
|
|
|
842
925
|
delete uri.headers.host;
|
|
843
926
|
|
|
844
|
-
proxy
|
|
927
|
+
proxy.$before && proxy.$before(uri, ctrl);
|
|
845
928
|
F.stats.performance.external++;
|
|
846
929
|
F.stats.request.external++;
|
|
847
930
|
|
|
@@ -849,7 +932,7 @@ function proxycreate(proxy, ctrl) {
|
|
|
849
932
|
if (ctrl.res.headersSent || ctrl.destroyed)
|
|
850
933
|
return;
|
|
851
934
|
|
|
852
|
-
var get =
|
|
935
|
+
var get = (ctrl.method === 'GET' || ctrl.method === 'HEAD' || ctrl.method === 'OPTIONS');
|
|
853
936
|
var kind = secured ? F.Https : F.Http;
|
|
854
937
|
var request = get && !ctrl.iswebsocket ? kind.get(uri, proxycreatecallback) : kind.request(uri, proxycreatecallback);
|
|
855
938
|
|
|
@@ -938,7 +1021,7 @@ function proxycreatecallback(response) {
|
|
|
938
1021
|
let ctrl = self.$controller;
|
|
939
1022
|
ctrl.released = true;
|
|
940
1023
|
ctrl.destroyed = true;
|
|
941
|
-
ctrl.$proxy
|
|
1024
|
+
ctrl.$proxy.$after && self.$proxy.$after(response);
|
|
942
1025
|
ctrl.res.writeHead && ctrl.res.writeHead(response.statusCode, response.headers);
|
|
943
1026
|
response.pipe(ctrl.res, PROXY_OPTIONS);
|
|
944
1027
|
}
|
package/sourcemap.js
CHANGED
|
@@ -64,9 +64,9 @@ exports.create = function() {
|
|
|
64
64
|
if (route.timeout)
|
|
65
65
|
m.timeout = route.timeout;
|
|
66
66
|
|
|
67
|
-
if (route.flags.upload) {
|
|
67
|
+
if (route.flags && route.flags.upload) {
|
|
68
68
|
m.upload = true;
|
|
69
|
-
m.limit = route.size
|
|
69
|
+
m.limit = route.size;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
if (route.api) {
|
|
@@ -86,6 +86,9 @@ exports.create = function() {
|
|
|
86
86
|
let action = F.actions[name];
|
|
87
87
|
if (action) {
|
|
88
88
|
tmp.input = action.input;
|
|
89
|
+
tmp.name = action.name;
|
|
90
|
+
tmp.summary = action.summary;
|
|
91
|
+
tmp.public = action.public;
|
|
89
92
|
|
|
90
93
|
if (tmp.input && tmp.input[0] === '@')
|
|
91
94
|
tmp.input = stringify(F.jsonschemas[tmp.input.substring(1)]);
|
|
@@ -152,7 +155,7 @@ exports.create = function() {
|
|
|
152
155
|
|
|
153
156
|
exports.refresh = function() {
|
|
154
157
|
|
|
155
|
-
if (!F.
|
|
158
|
+
if (!F.isLoaded || !F.config.$sourcemap || F.id)
|
|
156
159
|
return;
|
|
157
160
|
|
|
158
161
|
timeout && clearTimeout(timeout);
|
package/test.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
// Total.js Tests
|
|
2
|
+
// The MIT License
|
|
3
|
+
// Copyright 2023 (c) Peter Širka <petersirka@gmail.com>
|
|
4
|
+
|
|
1
5
|
var Test = { items: [], count: 0 };
|
|
2
6
|
|
|
3
7
|
Test.start = function(message) {
|
|
@@ -7,7 +11,7 @@ Test.start = function(message) {
|
|
|
7
11
|
console.log('');
|
|
8
12
|
|
|
9
13
|
console.log(divider);
|
|
10
|
-
console.log('
|
|
14
|
+
console.log('> ' + message.padRight(divider.length - 4) + ' <');
|
|
11
15
|
console.log(divider);
|
|
12
16
|
};
|
|
13
17
|
|
|
@@ -37,7 +41,10 @@ Test.run = function(callback) {
|
|
|
37
41
|
console.log('Tests:', Test.count);
|
|
38
42
|
console.timeEnd('Time');
|
|
39
43
|
console.log('');
|
|
40
|
-
|
|
44
|
+
if (callback)
|
|
45
|
+
callback();
|
|
46
|
+
else
|
|
47
|
+
process.exit(0);
|
|
41
48
|
});
|
|
42
49
|
};
|
|
43
50
|
|
package/tms.js
CHANGED
|
@@ -115,7 +115,7 @@ exports.client = function(url, token, callback) {
|
|
|
115
115
|
token = undefined;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
var client =
|
|
118
|
+
var client = F.TWebSocket.createclient();
|
|
119
119
|
var publishers = {};
|
|
120
120
|
var subscribers = {};
|
|
121
121
|
var callbacks = {};
|
|
@@ -211,7 +211,7 @@ exports.client = function(url, token, callback) {
|
|
|
211
211
|
|
|
212
212
|
client.subscribe = function(name, callback) {
|
|
213
213
|
timeout && clearTimeout(timeout);
|
|
214
|
-
timeout = setTimeout(sync_subscribers,
|
|
214
|
+
timeout = setTimeout(sync_subscribers, 30, true);
|
|
215
215
|
if (subscribers[name])
|
|
216
216
|
subscribers[name].push(callback);
|
|
217
217
|
else
|
|
@@ -230,6 +230,7 @@ exports.client = function(url, token, callback) {
|
|
|
230
230
|
client.send({ type: 'subscribers', subscribers: keys });
|
|
231
231
|
};
|
|
232
232
|
|
|
233
|
+
return client;
|
|
233
234
|
};
|
|
234
235
|
|
|
235
236
|
function refresh(client) {
|
|
@@ -239,19 +240,15 @@ function refresh(client) {
|
|
|
239
240
|
var subscribed = [];
|
|
240
241
|
var published = [];
|
|
241
242
|
|
|
242
|
-
for (let key in Cache.pcache)
|
|
243
|
-
|
|
244
|
-
published.push({ id: key, schema: schema });
|
|
245
|
-
}
|
|
243
|
+
for (let key in Cache.pcache)
|
|
244
|
+
published.push({ id: key, schema: Cache.pcache[key] });
|
|
246
245
|
|
|
247
|
-
for (let key in Cache.scache)
|
|
248
|
-
|
|
249
|
-
subscribed.push({ id: key, schema: schema });
|
|
250
|
-
}
|
|
246
|
+
for (let key in Cache.scache)
|
|
247
|
+
subscribed.push({ id: key, schema: Cache.scache[key] });
|
|
251
248
|
|
|
252
249
|
var calls = [];
|
|
253
250
|
for (let key in Cache.calls)
|
|
254
|
-
calls.push({ id: key, schema:
|
|
251
|
+
calls.push({ id: key, schema: Cache.calls[key].schema });
|
|
255
252
|
|
|
256
253
|
var msg = { type: 'meta', name: F.config.name, subscribe: subscribed, publish: published, subscribers: Object.keys(Cache.subscribers), call: calls };
|
|
257
254
|
if (client)
|
|
@@ -308,7 +305,7 @@ exports.newsubscribe = function(name, schema, callback) {
|
|
|
308
305
|
else
|
|
309
306
|
delete Cache.scache[name];
|
|
310
307
|
|
|
311
|
-
exports.subscribe(name, callback);
|
|
308
|
+
callback && exports.subscribe(name, callback);
|
|
312
309
|
exports.refresh();
|
|
313
310
|
|
|
314
311
|
};
|
|
@@ -324,7 +321,7 @@ exports.subscribe = function(name, callback, client) {
|
|
|
324
321
|
if (client) {
|
|
325
322
|
var arr = Cache.swatchers[name];
|
|
326
323
|
if (arr) {
|
|
327
|
-
for (let fn of
|
|
324
|
+
for (let fn of arr)
|
|
328
325
|
fn(callback, client);
|
|
329
326
|
}
|
|
330
327
|
} else {
|
|
@@ -371,7 +368,7 @@ F.on('$tms', function() {
|
|
|
371
368
|
}
|
|
372
369
|
|
|
373
370
|
if ((is && endpoint && F.config.$tms) || (endpoint && F.config.$tms && !Cache.route))
|
|
374
|
-
Cache.route = F.route('SOCKET ' + endpoint, tmscontroller, F.config.$tmsmaxsize);
|
|
371
|
+
Cache.route = F.route('SOCKET ' + endpoint, tmscontroller, F.config.$tmsmaxsize * 1024);
|
|
375
372
|
|
|
376
373
|
Cache.url = endpoint;
|
|
377
374
|
|
package/uibuilder.js
CHANGED
|
@@ -7,6 +7,13 @@ const REG_STRING = /'|"/g;
|
|
|
7
7
|
|
|
8
8
|
exports.compile = async function(opt, callback) {
|
|
9
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
|
+
|
|
10
17
|
if (!callback)
|
|
11
18
|
return new Promise((resolve, reject) => exports.compile(opt, (err, response) => err ? reject(err) : resolve(response)));
|
|
12
19
|
|
|
@@ -24,7 +31,7 @@ exports.compile = async function(opt, callback) {
|
|
|
24
31
|
if (opt.local) {
|
|
25
32
|
response.components = used;
|
|
26
33
|
} else {
|
|
27
|
-
let components = await getComponents(
|
|
34
|
+
let components = await getComponents(opt, used);
|
|
28
35
|
response.components = components;
|
|
29
36
|
}
|
|
30
37
|
|
|
@@ -55,7 +62,7 @@ exports.download = async function(opt, callback) {
|
|
|
55
62
|
return new Promise((resolve, reject) => exports.download(opt, (err, response) => err ? reject(err) : resolve(response)));
|
|
56
63
|
|
|
57
64
|
try {
|
|
58
|
-
let response = await getComponents2(opt
|
|
65
|
+
let response = await getComponents2(opt);
|
|
59
66
|
callback(null, response);
|
|
60
67
|
} catch (e) {
|
|
61
68
|
callback(e);
|
|
@@ -81,22 +88,44 @@ function getInstances(schema) {
|
|
|
81
88
|
return response;
|
|
82
89
|
}
|
|
83
90
|
|
|
84
|
-
async function Download(url) {
|
|
91
|
+
async function Download(url, local = false) {
|
|
85
92
|
return new Promise(function(resolve) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
+
}
|
|
95
110
|
});
|
|
96
111
|
}
|
|
97
112
|
|
|
98
|
-
|
|
113
|
+
function parseorigin(url) {
|
|
99
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;
|
|
100
129
|
var components = {};
|
|
101
130
|
var arr = [];
|
|
102
131
|
|
|
@@ -105,14 +134,18 @@ async function getComponents(schema, used, download) {
|
|
|
105
134
|
|
|
106
135
|
for (let com of arr) {
|
|
107
136
|
|
|
108
|
-
if (com.value.indexOf('.json') === -1
|
|
137
|
+
if (com.value.indexOf('.json') === -1 && !used[com.id])
|
|
109
138
|
continue;
|
|
110
139
|
|
|
111
140
|
let url = com.value;
|
|
112
|
-
|
|
113
|
-
url = schema.origin + url;
|
|
141
|
+
let origin = opt.origin || schema.origin;
|
|
114
142
|
|
|
115
|
-
|
|
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);
|
|
116
149
|
|
|
117
150
|
if (typeof(body) === 'string') {
|
|
118
151
|
|
|
@@ -132,13 +165,14 @@ async function getComponents(schema, used, download) {
|
|
|
132
165
|
|
|
133
166
|
let render = body.substring(body.indexOf('=', index) + 1, index + end.index).trim().replace(REG_STRING, '').format(com.id);
|
|
134
167
|
|
|
168
|
+
if (render[0] === '/')
|
|
169
|
+
render = (origin || schema.origin || '') + render;
|
|
170
|
+
|
|
135
171
|
if (download) {
|
|
136
172
|
if (render.substring(0, 7) === 'base64 ') {
|
|
137
173
|
components[com.id] = render;
|
|
138
174
|
} else {
|
|
139
|
-
|
|
140
|
-
render = schema.origin + render;
|
|
141
|
-
let html = await Download(render);
|
|
175
|
+
let html = await Download(render, opt.filesystem);
|
|
142
176
|
if (html)
|
|
143
177
|
components[com.id] = 'base64 ' + Buffer.from(encodeURIComponent(html), 'utf8').toString('base64');
|
|
144
178
|
}
|
|
@@ -153,8 +187,10 @@ async function getComponents(schema, used, download) {
|
|
|
153
187
|
return components;
|
|
154
188
|
}
|
|
155
189
|
|
|
156
|
-
async function getComponents2(
|
|
190
|
+
async function getComponents2(opt) {
|
|
157
191
|
|
|
192
|
+
var list = opt.components;
|
|
193
|
+
var origin = opt.origin;
|
|
158
194
|
var components = {};
|
|
159
195
|
var arr = [];
|
|
160
196
|
|
|
@@ -167,7 +203,7 @@ async function getComponents2(list, origin) {
|
|
|
167
203
|
if (url[0] === '/')
|
|
168
204
|
url = origin + url;
|
|
169
205
|
|
|
170
|
-
let body = await Download(url.format(com.id));
|
|
206
|
+
let body = await Download(url.format(com.id), opt.filesystem);
|
|
171
207
|
|
|
172
208
|
if (typeof(body) === 'string') {
|
|
173
209
|
|
|
@@ -192,7 +228,7 @@ async function getComponents2(list, origin) {
|
|
|
192
228
|
} else {
|
|
193
229
|
if (render[0] === '/')
|
|
194
230
|
render = origin + render;
|
|
195
|
-
let html = await Download(render);
|
|
231
|
+
let html = await Download(render, opt.filesystem);
|
|
196
232
|
if (html)
|
|
197
233
|
components[com.id] = 'base64 ' + Buffer.from(encodeURIComponent(html), 'utf8').toString('base64');
|
|
198
234
|
}
|