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/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Total.js
|
|
1
|
+
// Total.js framework
|
|
2
2
|
// The MIT License
|
|
3
3
|
// Copyright 2012-2023 (c) Peter Širka <petersirka@gmail.com>
|
|
4
4
|
|
|
@@ -20,7 +20,7 @@ Object.freeze(EMPTYOBJECT);
|
|
|
20
20
|
Object.freeze(EMPTYARRAY);
|
|
21
21
|
|
|
22
22
|
// Globals
|
|
23
|
-
global.F = {};
|
|
23
|
+
global.F = global.Total = {};
|
|
24
24
|
global.DEBUG = true;
|
|
25
25
|
global.CONF = {};
|
|
26
26
|
global.REPO = {};
|
|
@@ -38,6 +38,7 @@ global.DEF = {};
|
|
|
38
38
|
F.clusterid = '';
|
|
39
39
|
F.is5 = F.version = 5000;
|
|
40
40
|
F.isBundle = false;
|
|
41
|
+
F.isLoaded = false;
|
|
41
42
|
F.version_header = '5';
|
|
42
43
|
F.version_node = process.version + '';
|
|
43
44
|
F.EMPTYOBJECT = EMPTYOBJECT;
|
|
@@ -57,6 +58,8 @@ global.DEF = {};
|
|
|
57
58
|
F.filestorages = {};
|
|
58
59
|
F.jsonschemas = {};
|
|
59
60
|
F.querybuilders = {};
|
|
61
|
+
F.openclients = {};
|
|
62
|
+
F.nodemodules = {};
|
|
60
63
|
F.workers = {};
|
|
61
64
|
F.config = CONF;
|
|
62
65
|
F.def = DEF;
|
|
@@ -182,6 +185,7 @@ global.DEF = {};
|
|
|
182
185
|
response: {
|
|
183
186
|
ddos: 0,
|
|
184
187
|
html: 0,
|
|
188
|
+
xml: 0,
|
|
185
189
|
json: 0,
|
|
186
190
|
websocket: 0,
|
|
187
191
|
timeout: 0,
|
|
@@ -221,6 +225,9 @@ global.DEF = {};
|
|
|
221
225
|
F.path.private = path => path ? F.path.$join(F.temporary.directories.private, path) : F.temporary.directories.private;
|
|
222
226
|
F.path.databases = path => path ? F.path.$join(F.temporary.directories.databases, path) : F.temporary.directories.databases;
|
|
223
227
|
F.path.plugins = path => path ? F.path.$join(F.temporary.directories.plugins, path) : F.temporary.directories.plugins;
|
|
228
|
+
F.path.templates = path => path ? F.path.$join(F.temporary.directories.templates, path) : F.temporary.directories.templates;
|
|
229
|
+
F.path.flowstreams = path => path ? F.path.$join(F.temporary.directories.flowstreams, path) : F.temporary.directories.flowstreams;
|
|
230
|
+
F.path.modules = path => path ? F.path.$join(F.temporary.directories.modules, path) : F.temporary.directories.modules;
|
|
224
231
|
F.path.directory = (type, path) => path ? F.path.$join(F.temporary.directories[type], path) : F.temporary.directories[type];
|
|
225
232
|
F.path.tmp = F.path.temp = path => path ? F.path.$join(F.temporary.directories.tmp, path) : F.temporary.directories.tmp;
|
|
226
233
|
F.path.exists = (path, callback) => callback ? (F.Fs.lstat(path, (err, stats) => callback(err ? false : true, stats ? stats.size : 0, stats ? stats.isFile() : false))) : new Promise(resolve => F.path.exists(path, resolve));
|
|
@@ -338,15 +345,19 @@ function unlink(arr, callback) {
|
|
|
338
345
|
// New internal configuration
|
|
339
346
|
CONF.$root = '';
|
|
340
347
|
CONF.$cors = ''; // hostnames separated by comma
|
|
348
|
+
CONF.$api = '/api/'; // a default API endpoint
|
|
341
349
|
CONF.$sourcemap = true;
|
|
342
350
|
CONF.$httpreqlimit = 0; // request limit per ip
|
|
343
351
|
CONF.$httpcompress = true;
|
|
344
352
|
CONF.$httpetag = '';
|
|
345
|
-
CONF.$httpmaxsize = 256; //
|
|
353
|
+
CONF.$httpmaxsize = 256; // kB
|
|
346
354
|
CONF.$httprangebuffer = 5120; // 5 MB
|
|
347
355
|
CONF.$httptimeout = 5; // 5 seconds
|
|
348
|
-
CONF.$httpfiles = { flac: true, jpg: true, jpeg: true, png: true, gif: true, ico: true, wasm: true, js: true, mjs: true, css: true, txt: true, xml: true, woff: true, woff2: true, otf: true, ttf: true, eot: true, svg: true, zip: true, rar: true, pdf: true, docx: true, xlsx: true, doc: true, xls: true, html: true, htm: true, appcache: true, manifest: true, map: true, ogv: true, ogg: true, mp4: true, mp3: true, webp: true, webm: true, swf: true, package: true, json: true, ui: true, md: true, m4v: true, jsx: true, heif: true, heic: true, ics: true, ts: true, m3u8: true, wav: true, xsd: true, xsl: true, xslt: true };
|
|
356
|
+
CONF.$httpfiles = { flac: true, jpg: true, jpeg: true, png: true, gif: true, ico: true, wasm: true, js: true, mjs: true, css: true, txt: true, xml: true, woff: true, woff2: true, otf: true, ttf: true, eot: true, svg: true, zip: true, rar: true, pdf: true, docx: true, xlsx: true, doc: true, xls: true, html: true, htm: true, appcache: true, manifest: true, map: true, ogv: true, ogg: true, mp4: true, mp3: true, webp: true, webm: true, swf: true, package: true, json: true, ui: true, md: true, m4v: true, jsx: true, heif: true, heic: true, ics: true, ts: true, m3u8: true, wav: true, xsd: true, xsl: true, xslt: true, ipynb: true, ijsnb: true };
|
|
349
357
|
CONF.$httpchecktypes = true; // for multipart data only
|
|
358
|
+
CONF.$httpmaxage = 60; // in seconds
|
|
359
|
+
CONF.$httpmaxkeys = 33;
|
|
360
|
+
CONF.$httpmaxkey = 25;
|
|
350
361
|
CONF.$blacklist = '';
|
|
351
362
|
CONF.$xpoweredby = 'Total.js';
|
|
352
363
|
CONF.$maxopenfiles = 100;
|
|
@@ -369,15 +380,14 @@ function unlink(arr, callback) {
|
|
|
369
380
|
CONF.$imagememory = 0; // disabled because e.g. GM v1.3.32 throws some error about the memory
|
|
370
381
|
CONF.$stats = true;
|
|
371
382
|
|
|
372
|
-
CONF.$nodemodules = require.resolve('./index');
|
|
373
|
-
CONF.$nodemodules = CONF.$nodemodules.substring(0, CONF.$nodemodules.length - (8 + 7));
|
|
374
383
|
CONF.$npmcache = '/var/www/.npm';
|
|
375
384
|
CONF.$python = 'python3';
|
|
376
|
-
CONF.$wsmaxsize = 256; //
|
|
385
|
+
CONF.$wsmaxsize = 256; // kB
|
|
377
386
|
CONF.$wscompress = true;
|
|
378
387
|
CONF.$wsencodedecode = false;
|
|
379
388
|
CONF.$wsmaxlatency = 2000;
|
|
380
389
|
CONF.$proxytimeout = 5; // 5 seconds
|
|
390
|
+
// CONF.$proxyrequest = '';
|
|
381
391
|
CONF.$cookiesamesite = 'Lax';
|
|
382
392
|
CONF.$cookiesecure = false;
|
|
383
393
|
CONF.$csrfexpiration = '30 minutes';
|
|
@@ -386,9 +396,10 @@ function unlink(arr, callback) {
|
|
|
386
396
|
CONF.$tapiurl = 'eu';
|
|
387
397
|
CONF.$tapimail = false;
|
|
388
398
|
CONF.$tapilogger = false;
|
|
399
|
+
CONF.$imprint = true;
|
|
389
400
|
|
|
390
401
|
CONF.$tms = false;
|
|
391
|
-
CONF.$tmsmaxsize = 256;
|
|
402
|
+
CONF.$tmsmaxsize = 256; // kB
|
|
392
403
|
CONF.$tmsurl = '/$tms/';
|
|
393
404
|
CONF.$tmsclearblocked = 60; // in minutes
|
|
394
405
|
|
|
@@ -449,7 +460,7 @@ function unlink(arr, callback) {
|
|
|
449
460
|
} else
|
|
450
461
|
msg.to(email);
|
|
451
462
|
|
|
452
|
-
msg.from(F.config.mail_from);
|
|
463
|
+
msg.from(F.config.mail_from || F.config.smtp.from || F.config.smtp.user);
|
|
453
464
|
callback && msg.callback(callback);
|
|
454
465
|
|
|
455
466
|
if (reply)
|
|
@@ -480,7 +491,10 @@ function unlink(arr, callback) {
|
|
|
480
491
|
|
|
481
492
|
NOW = new Date();
|
|
482
493
|
|
|
483
|
-
if (
|
|
494
|
+
if (err instanceof F.TBuilders.ErrorBuilder) {
|
|
495
|
+
if (!name)
|
|
496
|
+
name = err[0].name;
|
|
497
|
+
} else if (!name && err.name)
|
|
484
498
|
name = err.name;
|
|
485
499
|
|
|
486
500
|
err = err.toString();
|
|
@@ -560,10 +574,12 @@ F.loadconfig = function(value) {
|
|
|
560
574
|
|
|
561
575
|
break;
|
|
562
576
|
case '$cryptoiv':
|
|
563
|
-
cfg[key] = val ? Buffer.from(val, 'hex') : null;
|
|
577
|
+
cfg[key] = val ? Buffer.from(val, (/[A-Z=\/+]/).test(val) ? 'base64' : 'hex') : null;
|
|
564
578
|
break;
|
|
565
|
-
case 'mail_from':
|
|
566
579
|
case '$root':
|
|
580
|
+
cfg[key] = val ? F.TUtils.normalize(val) : '';
|
|
581
|
+
break;
|
|
582
|
+
case 'mail_from':
|
|
567
583
|
break;
|
|
568
584
|
case '$port':
|
|
569
585
|
cfg[key] = +val;
|
|
@@ -596,6 +612,7 @@ F.loadconfig = function(value) {
|
|
|
596
612
|
process.env.NODE_TLS_REJECT_UNAUTHORIZED = F.config.$insecure ? '0' : '1';
|
|
597
613
|
F.logger(F.config.$logger == true);
|
|
598
614
|
F.dir();
|
|
615
|
+
F.emit('$cors');
|
|
599
616
|
F.emit('$tms');
|
|
600
617
|
F.emit('$reconfigure');
|
|
601
618
|
};
|
|
@@ -710,6 +727,9 @@ F.auth = function(fn) {
|
|
|
710
727
|
|
|
711
728
|
F.load = async function(types, callback) {
|
|
712
729
|
|
|
730
|
+
if (!types)
|
|
731
|
+
types = '';
|
|
732
|
+
|
|
713
733
|
var beg = Date.now();
|
|
714
734
|
|
|
715
735
|
F.dir();
|
|
@@ -735,10 +755,11 @@ F.load = async function(types, callback) {
|
|
|
735
755
|
return arr;
|
|
736
756
|
};
|
|
737
757
|
|
|
738
|
-
if (
|
|
758
|
+
if (types.length && !types.includes('stats')) {
|
|
739
759
|
F.config.$stats = false;
|
|
740
760
|
F.config.$sourcemap = false;
|
|
741
|
-
}
|
|
761
|
+
} else
|
|
762
|
+
F.config.$sourcemap = DEBUG;
|
|
742
763
|
|
|
743
764
|
if (!types.length || types.includes('env')) {
|
|
744
765
|
let env = await read(F.path.root('.env'));
|
|
@@ -770,7 +791,7 @@ F.load = async function(types, callback) {
|
|
|
770
791
|
}
|
|
771
792
|
}
|
|
772
793
|
|
|
773
|
-
let loader = ['modules', '
|
|
794
|
+
let loader = ['modules', 'actions', 'schemas', 'models', 'definitions', 'controllers', 'middleware', 'sources'];
|
|
774
795
|
var files = [];
|
|
775
796
|
var tmp;
|
|
776
797
|
|
|
@@ -859,7 +880,7 @@ F.load = async function(types, callback) {
|
|
|
859
880
|
F.loadservices();
|
|
860
881
|
F.stats.compilation = Date.now() - beg;
|
|
861
882
|
F.stats.compiled = files.length;
|
|
862
|
-
F.
|
|
883
|
+
F.isLoaded = true;
|
|
863
884
|
DEBUG && F.TSourceMap.refresh();
|
|
864
885
|
callback && callback();
|
|
865
886
|
|
|
@@ -868,9 +889,42 @@ F.load = async function(types, callback) {
|
|
|
868
889
|
};
|
|
869
890
|
|
|
870
891
|
F.require = function(name) {
|
|
892
|
+
|
|
871
893
|
if (name.startsWith('node:'))
|
|
872
894
|
return require(name);
|
|
873
|
-
|
|
895
|
+
|
|
896
|
+
if (NODE_MODULES[name])
|
|
897
|
+
return require('node:' + name);
|
|
898
|
+
|
|
899
|
+
let mod = null;
|
|
900
|
+
|
|
901
|
+
try {
|
|
902
|
+
mod = require(name);
|
|
903
|
+
} catch (e) {
|
|
904
|
+
mod = require(F.Path.join(F.config.$nodemodules, name));
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
if (!mod)
|
|
908
|
+
throw new Error('NPM module "' + name + '" not found');
|
|
909
|
+
|
|
910
|
+
return mod;
|
|
911
|
+
};
|
|
912
|
+
|
|
913
|
+
F.runscript = function(filename) {
|
|
914
|
+
F.Fs.readFile(filename || PATH.root('debug.js'), function(err, data) {
|
|
915
|
+
if (data) {
|
|
916
|
+
var scr = data.toString('utf8').trim();
|
|
917
|
+
var fn;
|
|
918
|
+
if (data) {
|
|
919
|
+
try {
|
|
920
|
+
fn = new Function('require', scr);
|
|
921
|
+
} catch (e) {
|
|
922
|
+
console.error(e);
|
|
923
|
+
}
|
|
924
|
+
fn && fn(require);
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
});
|
|
874
928
|
};
|
|
875
929
|
|
|
876
930
|
F.import = function(url, callback) {
|
|
@@ -977,7 +1031,7 @@ F.npminstall = function(name, callback) {
|
|
|
977
1031
|
if (!callback)
|
|
978
1032
|
return new Promise((resolve, reject) => F.npminstall(name, err => err ? reject(err) : resolve()));
|
|
979
1033
|
|
|
980
|
-
var path = F.config.$
|
|
1034
|
+
var path = F.config.$nodemodules;
|
|
981
1035
|
F.path.mkdir(path, true);
|
|
982
1036
|
|
|
983
1037
|
var index = name.lastIndexOf('@');
|
|
@@ -1033,7 +1087,13 @@ F.shell = function(cmd, callback, cwd) {
|
|
|
1033
1087
|
|
|
1034
1088
|
F.console = function() {
|
|
1035
1089
|
|
|
1090
|
+
if (!F.config.$imprint)
|
|
1091
|
+
return;
|
|
1092
|
+
|
|
1036
1093
|
var memory = process.memoryUsage();
|
|
1094
|
+
var nodemodules = require.resolve('./index');
|
|
1095
|
+
|
|
1096
|
+
nodemodules = nodemodules.substring(0, nodemodules.length - (8 + 7));
|
|
1037
1097
|
|
|
1038
1098
|
print('====================================================');
|
|
1039
1099
|
print('PID : ' + process.pid);
|
|
@@ -1054,10 +1114,10 @@ F.console = function() {
|
|
|
1054
1114
|
print('====================================================');
|
|
1055
1115
|
F.config.$root && print('Root : ' + F.config.$root);
|
|
1056
1116
|
print('Directory : ' + process.cwd());
|
|
1057
|
-
print('node_modules : ' +
|
|
1117
|
+
print('node_modules : ' + nodemodules);
|
|
1058
1118
|
print('====================================================\n');
|
|
1059
1119
|
|
|
1060
|
-
if (!F.isWorker) {
|
|
1120
|
+
if (!F.isWorker && F.server) {
|
|
1061
1121
|
|
|
1062
1122
|
var hostname = F.unixsocket ? ('Socket: ' + F.unixsocket) : '{2}://{0}:{1}/'.format(F.config.$ip, F.config.$port, F.isHTTPS ? 'https' : 'http');
|
|
1063
1123
|
|
|
@@ -1082,7 +1142,7 @@ F.console = function() {
|
|
|
1082
1142
|
|
|
1083
1143
|
F.loadservices = function() {
|
|
1084
1144
|
|
|
1085
|
-
F.internal.interval && clearInterval(F.internal.
|
|
1145
|
+
F.internal.interval && clearInterval(F.internal.interval);
|
|
1086
1146
|
|
|
1087
1147
|
// This timer solving timeouts
|
|
1088
1148
|
F.internal.interval = setInterval(function() {
|
|
@@ -1093,6 +1153,9 @@ F.loadservices = function() {
|
|
|
1093
1153
|
for (let key in F.flowstreams)
|
|
1094
1154
|
F.flowstreams[key].service(F.internal.ticks);
|
|
1095
1155
|
|
|
1156
|
+
if (F.internal.ticks == 6 || F.internal.ticks == 12)
|
|
1157
|
+
F.TWebSocket.ping();
|
|
1158
|
+
|
|
1096
1159
|
// 1 minute
|
|
1097
1160
|
if (F.internal.ticks == 12) {
|
|
1098
1161
|
F.internal.ticks = 0;
|
|
@@ -1101,9 +1164,6 @@ F.loadservices = function() {
|
|
|
1101
1164
|
F.$events.service && F.emit('service', F.internal.counter);
|
|
1102
1165
|
}
|
|
1103
1166
|
|
|
1104
|
-
if (F.internal.ticks == 6 || F.internal.ticks == 12)
|
|
1105
|
-
F.TWebSocket.ping();
|
|
1106
|
-
|
|
1107
1167
|
F.TFlow.ping();
|
|
1108
1168
|
|
|
1109
1169
|
if (!F.temporary.pending.length) {
|
|
@@ -1116,7 +1176,7 @@ F.loadservices = function() {
|
|
|
1116
1176
|
while (true) {
|
|
1117
1177
|
let ctrl = F.temporary.pending[index];
|
|
1118
1178
|
if (ctrl) {
|
|
1119
|
-
if (ctrl.destroyed) {
|
|
1179
|
+
if (ctrl.destroyed || ctrl.res.headersSent || ctrl.res.writableEnded) {
|
|
1120
1180
|
F.temporary.pending.splice(index, 1);
|
|
1121
1181
|
} else if (ctrl.timeout <= 0) {
|
|
1122
1182
|
|
|
@@ -1155,6 +1215,11 @@ F.http = function(opt) {
|
|
|
1155
1215
|
// config, env, modules, controllers, actions, schemas, models, definitions, sources, middleware, resources, plugins, stats
|
|
1156
1216
|
// none - loads only web server
|
|
1157
1217
|
|
|
1218
|
+
if (F.isLoaded) {
|
|
1219
|
+
F.httpload(opt);
|
|
1220
|
+
return;
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1158
1223
|
if (opt.config) {
|
|
1159
1224
|
let cfg = [];
|
|
1160
1225
|
for (let key in opt.config)
|
|
@@ -1162,81 +1227,90 @@ F.http = function(opt) {
|
|
|
1162
1227
|
F.loadconfig(cfg);
|
|
1163
1228
|
}
|
|
1164
1229
|
|
|
1165
|
-
F.load(opt.load || opt.type || '',
|
|
1230
|
+
F.load(opt.load || opt.type || '', () => F.httpload(opt));
|
|
1231
|
+
};
|
|
1166
1232
|
|
|
1167
|
-
|
|
1168
|
-
F.server.on('upgrade', F.TWebSocket.listen);
|
|
1233
|
+
F.httpload = function(opt) {
|
|
1169
1234
|
|
|
1170
|
-
|
|
1235
|
+
if (F.server) {
|
|
1236
|
+
F.server.close(function() {
|
|
1237
|
+
F.server = null;
|
|
1238
|
+
F.httpload(opt);
|
|
1239
|
+
});
|
|
1240
|
+
return;
|
|
1241
|
+
}
|
|
1171
1242
|
|
|
1172
|
-
|
|
1243
|
+
F.server = F.Http.createServer(F.THttp.listen);
|
|
1244
|
+
F.server.on('upgrade', F.TWebSocket.listen);
|
|
1173
1245
|
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
} catch (e) {}
|
|
1246
|
+
var unixsocket = opt.unixsocket || F.config.$unixsocket;
|
|
1247
|
+
if (unixsocket) {
|
|
1177
1248
|
|
|
1178
|
-
|
|
1179
|
-
|
|
1249
|
+
try {
|
|
1250
|
+
F.Fs.unlinkSync(unixsocket);
|
|
1251
|
+
} catch (e) {}
|
|
1180
1252
|
|
|
1181
|
-
|
|
1253
|
+
if (F.isWindows && unixsocket.indexOf(SOCKETWINDOWS) === -1)
|
|
1254
|
+
unixsocket = F.Path.join(SOCKETWINDOWS, unixsocket);
|
|
1182
1255
|
|
|
1183
|
-
|
|
1184
|
-
F.server.listen(unixsocket, function() {
|
|
1256
|
+
F.config.$unixsocket = F.unixsocket = unixsocket;
|
|
1185
1257
|
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
return;
|
|
1258
|
+
var listen = function(count) {
|
|
1259
|
+
F.server.listen(unixsocket, function() {
|
|
1189
1260
|
|
|
1190
|
-
|
|
1261
|
+
// Check if the socket exists
|
|
1262
|
+
if (F.isWindows)
|
|
1263
|
+
return;
|
|
1191
1264
|
|
|
1192
|
-
|
|
1193
|
-
throw new Error('HTTP server can not listen the path "{0}"'.format(unixsocket));
|
|
1265
|
+
F.Fs.lstat(unixsocket, function(err) {
|
|
1194
1266
|
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
else if (opt.unixsocket777)
|
|
1198
|
-
F.Fs.chmodSync(unixsocket, 0o777);
|
|
1199
|
-
});
|
|
1267
|
+
if (count > 9)
|
|
1268
|
+
throw new Error('HTTP server can not listen the path "{0}"'.format(unixsocket));
|
|
1200
1269
|
|
|
1270
|
+
if (err)
|
|
1271
|
+
setTimeout(listen, 500, count + 1);
|
|
1272
|
+
else if (opt.unixsocket777)
|
|
1273
|
+
F.Fs.chmodSync(unixsocket, 0o777);
|
|
1201
1274
|
});
|
|
1202
|
-
};
|
|
1203
1275
|
|
|
1204
|
-
|
|
1276
|
+
});
|
|
1277
|
+
};
|
|
1278
|
+
|
|
1279
|
+
listen(1);
|
|
1205
1280
|
|
|
1206
|
-
|
|
1281
|
+
} else {
|
|
1207
1282
|
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
}
|
|
1283
|
+
if (opt.port)
|
|
1284
|
+
F.config.$port = opt.port;
|
|
1285
|
+
|
|
1286
|
+
if (F.config.$port === 'auto') {
|
|
1287
|
+
let port = process.env.PORT;
|
|
1288
|
+
if (!port) {
|
|
1289
|
+
for (let arg of process.argv) {
|
|
1290
|
+
if ((/^\d{3,5}$/).test(arg)) {
|
|
1291
|
+
port = arg;
|
|
1292
|
+
break;
|
|
1219
1293
|
}
|
|
1220
1294
|
}
|
|
1221
|
-
if (port)
|
|
1222
|
-
port = +port;
|
|
1223
|
-
if (isNaN(port))
|
|
1224
|
-
port = 8000;
|
|
1225
|
-
F.config.$port = port;
|
|
1226
1295
|
}
|
|
1296
|
+
if (port)
|
|
1297
|
+
port = +port;
|
|
1298
|
+
if (isNaN(port))
|
|
1299
|
+
port = 8000;
|
|
1300
|
+
F.config.$port = port;
|
|
1301
|
+
}
|
|
1227
1302
|
|
|
1228
|
-
|
|
1229
|
-
|
|
1303
|
+
if (opt.ip)
|
|
1304
|
+
F.config.$ip = opt.ip;
|
|
1230
1305
|
|
|
1231
|
-
|
|
1232
|
-
|
|
1306
|
+
F.server.listen(F.config.$port, F.config.$ip);
|
|
1307
|
+
}
|
|
1233
1308
|
|
|
1234
|
-
|
|
1309
|
+
F.config.$performance && F.server.on('connection', httptuningperformance);
|
|
1235
1310
|
|
|
1236
|
-
|
|
1237
|
-
|
|
1311
|
+
if (!process.connected && F.console)
|
|
1312
|
+
F.console();
|
|
1238
1313
|
|
|
1239
|
-
});
|
|
1240
1314
|
};
|
|
1241
1315
|
|
|
1242
1316
|
F.logger = function(enable) {
|
|
@@ -1305,8 +1379,12 @@ F.logger = function(enable) {
|
|
|
1305
1379
|
};
|
|
1306
1380
|
};
|
|
1307
1381
|
|
|
1382
|
+
F.componentator = function(name, components, removeprev = true, attrs = '') {
|
|
1308
1383
|
|
|
1309
|
-
|
|
1384
|
+
if (typeof(removeprev) === 'string') {
|
|
1385
|
+
attrs = removeprev;
|
|
1386
|
+
removeprev = true;
|
|
1387
|
+
}
|
|
1310
1388
|
|
|
1311
1389
|
var meta = {};
|
|
1312
1390
|
|
|
@@ -1315,7 +1393,7 @@ F.componentator = function(name, components, removeprev = true) {
|
|
|
1315
1393
|
|
|
1316
1394
|
F.$events.componentator && F.emit('componentator', meta);
|
|
1317
1395
|
|
|
1318
|
-
var url = 'https://componentator.com/download.js?id=' + meta.components;
|
|
1396
|
+
var url = 'https://componentator.com/download.js?id=' + meta.components + (attrs ? ('&' + attrs) : '');
|
|
1319
1397
|
var nameid = meta.name.slug();
|
|
1320
1398
|
var relative = 'ui-' + (removeprev ? (nameid + '-') : '') + url.makeid() + '.min.js';
|
|
1321
1399
|
var filename = F.path.public(relative);
|
|
@@ -1344,13 +1422,13 @@ F.componentator = function(name, components, removeprev = true) {
|
|
|
1344
1422
|
|
|
1345
1423
|
};
|
|
1346
1424
|
|
|
1347
|
-
F.error = function(err, name,
|
|
1425
|
+
F.error = function(err, name, url) {
|
|
1348
1426
|
|
|
1349
1427
|
if (!arguments.length)
|
|
1350
1428
|
return F.errorcallback;
|
|
1351
1429
|
|
|
1352
1430
|
if (err)
|
|
1353
|
-
F.def.onError(err, name,
|
|
1431
|
+
F.def.onError(err, name, url);
|
|
1354
1432
|
};
|
|
1355
1433
|
|
|
1356
1434
|
F.errorcallback = function(err) {
|
|
@@ -1410,6 +1488,7 @@ F.merge = function(url) {
|
|
|
1410
1488
|
if (F.temporary.merged[key]) {
|
|
1411
1489
|
if (F.temporary.notfound[url]) {
|
|
1412
1490
|
ctrl.fallback(404);
|
|
1491
|
+
next();
|
|
1413
1492
|
return;
|
|
1414
1493
|
}
|
|
1415
1494
|
} else {
|
|
@@ -1520,8 +1599,12 @@ F.middleware = function(name, fn, assign) {
|
|
|
1520
1599
|
}
|
|
1521
1600
|
}
|
|
1522
1601
|
} else {
|
|
1602
|
+
|
|
1523
1603
|
if (a === 'websocket' || a === 'file' || a === 'route')
|
|
1524
1604
|
a += 's';
|
|
1605
|
+
else if (a === 'dynamic')
|
|
1606
|
+
a = 'routes';
|
|
1607
|
+
|
|
1525
1608
|
let routes = F.routes[a];
|
|
1526
1609
|
if (routes) {
|
|
1527
1610
|
for (let route of routes) {
|
|
@@ -1654,15 +1737,6 @@ F.service = function(count) {
|
|
|
1654
1737
|
}
|
|
1655
1738
|
}
|
|
1656
1739
|
|
|
1657
|
-
// Exec crons
|
|
1658
|
-
for (let cron of F.crons) {
|
|
1659
|
-
if (cron.check(NOW))
|
|
1660
|
-
cron.exec(NOW);
|
|
1661
|
-
}
|
|
1662
|
-
|
|
1663
|
-
if (count % 10 === 0 && global.gc)
|
|
1664
|
-
setTimeout(cleargc, 1000);
|
|
1665
|
-
|
|
1666
1740
|
F.temporary.service.publish = F.stats.performance.publish;
|
|
1667
1741
|
F.temporary.service.subscribe = F.stats.performance.subscribe;
|
|
1668
1742
|
F.temporary.service.call = F.stats.performance.call;
|
|
@@ -1695,6 +1769,16 @@ F.service = function(count) {
|
|
|
1695
1769
|
|
|
1696
1770
|
F.usage && F.usage();
|
|
1697
1771
|
F.temporary.service.usage = 0;
|
|
1772
|
+
|
|
1773
|
+
if (count % 10 === 0 && global.gc)
|
|
1774
|
+
setTimeout(cleargc, 1000);
|
|
1775
|
+
|
|
1776
|
+
// Exec crons
|
|
1777
|
+
for (let cron of F.crons) {
|
|
1778
|
+
if (cron.check(NOW))
|
|
1779
|
+
cron.exec(NOW);
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1698
1782
|
};
|
|
1699
1783
|
|
|
1700
1784
|
function cleargc() {
|
|
@@ -1716,8 +1800,7 @@ F.clear = function(init = true, callback) {
|
|
|
1716
1800
|
dir = dir.replaceAll('/', '\\');
|
|
1717
1801
|
|
|
1718
1802
|
if (init) {
|
|
1719
|
-
|
|
1720
|
-
if (!F.config.$cleartemp) {
|
|
1803
|
+
if (F.config.$cleartemp) {
|
|
1721
1804
|
// clears only JS and CSS files
|
|
1722
1805
|
F.TUtils.ls(dir, function(files) {
|
|
1723
1806
|
F.path.unlink(files, callback);
|
|
@@ -1839,7 +1922,7 @@ F.newjsonschema = function(name, obj) {
|
|
|
1839
1922
|
F.newtransform = function(name, action, id) {
|
|
1840
1923
|
if (action == null) {
|
|
1841
1924
|
let items = F.transformations[name];
|
|
1842
|
-
let index = items.
|
|
1925
|
+
let index = items.TfindIndex('id', id);
|
|
1843
1926
|
if (index !== -1) {
|
|
1844
1927
|
items.splice(index, 1);
|
|
1845
1928
|
if (!items.length)
|
|
@@ -1849,19 +1932,30 @@ F.newtransform = function(name, action, id) {
|
|
|
1849
1932
|
let obj = {};
|
|
1850
1933
|
obj.id = id;
|
|
1851
1934
|
obj.action = action;
|
|
1852
|
-
|
|
1935
|
+
obj.remove = function() {
|
|
1936
|
+
let arr = F.transformations[name];
|
|
1937
|
+
if (arr) {
|
|
1938
|
+
let index = arr.indexOf(obj);
|
|
1939
|
+
if (index !== -1) {
|
|
1940
|
+
arr.splice(index, 1);
|
|
1941
|
+
if (!arr.length)
|
|
1942
|
+
delete F.transformations[name];
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
};
|
|
1853
1946
|
if (F.transformations[name])
|
|
1854
1947
|
F.transformations[name].push(obj);
|
|
1855
1948
|
else
|
|
1856
1949
|
F.transformations[name] = [obj];
|
|
1950
|
+
return obj;
|
|
1857
1951
|
}
|
|
1858
1952
|
};
|
|
1859
1953
|
|
|
1860
1954
|
function transform(items, opt, index) {
|
|
1861
1955
|
var t = items[index];
|
|
1862
1956
|
if (t) {
|
|
1957
|
+
opt.next = () => transform(items, opt, index + 1);
|
|
1863
1958
|
t.action(opt, opt.value);
|
|
1864
|
-
t.next = () => transform(items, opt, index + 1);
|
|
1865
1959
|
} else
|
|
1866
1960
|
opt.$callback(opt.error.items.length ? opt.error : null, opt.value);
|
|
1867
1961
|
}
|
|
@@ -1905,11 +1999,12 @@ F.audit = function(name, $, message, type) {
|
|
|
1905
1999
|
if ($.controller) {
|
|
1906
2000
|
if ($.controller.sessionid)
|
|
1907
2001
|
data.sessionid = $.controller.sessionid;
|
|
1908
|
-
data.ua = $.ua;
|
|
1909
|
-
data.ip = $.ip;
|
|
1910
|
-
data.url = $.url;
|
|
1911
2002
|
}
|
|
1912
2003
|
|
|
2004
|
+
data.ua = $.ua;
|
|
2005
|
+
data.ip = $.ip;
|
|
2006
|
+
data.url = $.url;
|
|
2007
|
+
|
|
1913
2008
|
if (type)
|
|
1914
2009
|
data.type = type || 'info';
|
|
1915
2010
|
|
|
@@ -2130,7 +2225,7 @@ F.restore = function(filename, target, callback, filter) {
|
|
|
2130
2225
|
parser.next();
|
|
2131
2226
|
});
|
|
2132
2227
|
|
|
2133
|
-
|
|
2228
|
+
F.cleanup(stream, function() {
|
|
2134
2229
|
end = true;
|
|
2135
2230
|
parser.end();
|
|
2136
2231
|
});
|
|
@@ -2302,16 +2397,13 @@ F.restart = function() {
|
|
|
2302
2397
|
process.send && process.send('total:restart');
|
|
2303
2398
|
};
|
|
2304
2399
|
|
|
2305
|
-
F.exit = function(signal) {
|
|
2400
|
+
F.exit = function(signal = 15) {
|
|
2306
2401
|
|
|
2307
2402
|
if (F.isexited)
|
|
2308
2403
|
return;
|
|
2309
2404
|
|
|
2310
2405
|
F.isexited = true;
|
|
2311
2406
|
|
|
2312
|
-
if (!signal)
|
|
2313
|
-
signal = 'SIGTERM';
|
|
2314
|
-
|
|
2315
2407
|
for (let m in F.workers) {
|
|
2316
2408
|
let worker = F.workers[m];
|
|
2317
2409
|
try {
|
|
@@ -2329,8 +2421,8 @@ F.exit = function(signal) {
|
|
|
2329
2421
|
} catch (e) {}
|
|
2330
2422
|
}
|
|
2331
2423
|
|
|
2332
|
-
F.internal.
|
|
2333
|
-
F.internal.
|
|
2424
|
+
F.internal.interval && clearInterval(F.internal.interval);
|
|
2425
|
+
F.internal.interval = null;
|
|
2334
2426
|
|
|
2335
2427
|
if (F.server) {
|
|
2336
2428
|
F.server.setTimeout(1);
|
|
@@ -2413,10 +2505,10 @@ F.dir = function(val) {
|
|
|
2413
2505
|
if (val)
|
|
2414
2506
|
F.directory = val;
|
|
2415
2507
|
|
|
2416
|
-
var dirs = ['public', 'tmp', 'logs', 'databases', 'controllers', 'resources', 'plugins', 'views', 'definitions', 'schemas', 'models', 'flowstreams', 'bundles', 'actions', 'extensions', 'source', 'services', 'updates', 'templates'];
|
|
2508
|
+
var dirs = ['public', 'tmp', 'logs', 'databases', 'controllers', 'resources', 'plugins', 'modules', 'views', 'definitions', 'schemas', 'models', 'flowstreams', 'bundles', 'actions', 'extensions', 'source', 'services', 'updates', 'templates', 'private'];
|
|
2417
2509
|
|
|
2418
2510
|
for (let dir of dirs) {
|
|
2419
|
-
|
|
2511
|
+
let cfg = F.config['$dir' + dir];
|
|
2420
2512
|
F.temporary.directories[dir] = cfg || F.Path.join(F.directory, dir);
|
|
2421
2513
|
}
|
|
2422
2514
|
|
|
@@ -2456,7 +2548,7 @@ F.mail = function(email, subject, name, model, language, callback) {
|
|
|
2456
2548
|
// Localization
|
|
2457
2549
|
if (typeof(language) === 'string') {
|
|
2458
2550
|
if (subject.includes('@('))
|
|
2459
|
-
subject =
|
|
2551
|
+
subject = F.translate(language, subject);
|
|
2460
2552
|
}
|
|
2461
2553
|
|
|
2462
2554
|
let body = F.view(name, model, view => view.language = language || '');
|
|
@@ -2474,9 +2566,9 @@ F.htmlmail = function(email, subject, body, language, callback) {
|
|
|
2474
2566
|
// Localization
|
|
2475
2567
|
if (typeof(language) === 'string') {
|
|
2476
2568
|
if (subject.includes('@('))
|
|
2477
|
-
subject =
|
|
2569
|
+
subject = F.translate(language, subject);
|
|
2478
2570
|
if (body.includes('@('))
|
|
2479
|
-
body =
|
|
2571
|
+
body = F.translate(language, body);
|
|
2480
2572
|
}
|
|
2481
2573
|
|
|
2482
2574
|
body = body.indexOf('<body>') === -1 ? ('<!DOCTYPE html><html><head><title>' + subject + '</title><meta charset="utf-8" /></head><body style="padding:0;margin:0;font-family:Arial;font-size:14px;font-weight:normal">' + body + '</body></html>') : body;
|
|
@@ -2487,6 +2579,17 @@ F.readfile = function(path, type = null) {
|
|
|
2487
2579
|
return new Promise(resolve => F.Fs.readFile(path, type, (err, response) => err ? resolve(null) : resolve(response)));
|
|
2488
2580
|
};
|
|
2489
2581
|
|
|
2582
|
+
F.datauri = function(path) {
|
|
2583
|
+
return new Promise(resolve => F.Fs.readFile(path, 'base64', function(err, response) {
|
|
2584
|
+
if (err) {
|
|
2585
|
+
resolve(null);
|
|
2586
|
+
} else {
|
|
2587
|
+
var ext = F.TUtils.getExtension(path);
|
|
2588
|
+
resolve('data:' + F.TUtils.getContentType(ext) + ';base64,' + response);
|
|
2589
|
+
}
|
|
2590
|
+
}));
|
|
2591
|
+
};
|
|
2592
|
+
|
|
2490
2593
|
F.loadstats = function() {
|
|
2491
2594
|
|
|
2492
2595
|
var main = {};
|
|
@@ -2604,9 +2707,9 @@ process.on('message', function(msg, h) {
|
|
|
2604
2707
|
|
|
2605
2708
|
let key;
|
|
2606
2709
|
|
|
2607
|
-
if (msg === 'total:debug')
|
|
2608
|
-
F.TUtils.wait(() => F.
|
|
2609
|
-
else if (msg === 'total:ping')
|
|
2710
|
+
if (msg === 'total:debug') {
|
|
2711
|
+
F.TUtils.wait(() => F.isLoaded, F.console, 10000, 500);
|
|
2712
|
+
} else if (msg === 'total:ping')
|
|
2610
2713
|
setImmediate(ping);
|
|
2611
2714
|
else if (msg === 'total:update') {
|
|
2612
2715
|
key = '$update';
|
|
@@ -2658,11 +2761,16 @@ process.on('message', function(msg, h) {
|
|
|
2658
2761
|
F.TCluster = require('./cluster');
|
|
2659
2762
|
|
|
2660
2763
|
// Settings
|
|
2661
|
-
F.directory = F.TUtils.$normalize(require.main ? F.Path.dirname(require.main.filename) : process.cwd());
|
|
2764
|
+
// F.directory = F.TUtils.$normalize(require.main ? F.Path.dirname(require.main.filename) : process.cwd());
|
|
2765
|
+
F.directory = F.TUtils.$normalize(process.cwd());
|
|
2766
|
+
|
|
2662
2767
|
F.is = F.Os.platform().substring(0, 3).toLowerCase() === 'win';
|
|
2663
2768
|
F.isWorker = process.env.PASSENGER_APP_ENV ? false : F.Cluster.isWorker;
|
|
2664
2769
|
F.syshash = (__dirname + '-' + F.Os.hostname() + '-' + F.Os.platform() + '-' + F.Os.arch() + '-' + F.Os.release() + '-' + F.Os.tmpdir() + JSON.stringify(process.versions)).md5();
|
|
2665
2770
|
F.isLE = F.Os.endianness ? F.Os.endianness() === 'LE' : true;
|
|
2771
|
+
F.isWindows = F.Os.platform().substring(0, 3).toLowerCase() === 'win';
|
|
2772
|
+
|
|
2773
|
+
F.config.$total5 = F.Path.dirname(require.resolve('./index'));
|
|
2666
2774
|
|
|
2667
2775
|
F.cache = require('./cache');
|
|
2668
2776
|
F.TImages = require('./images');
|
|
@@ -2673,16 +2781,17 @@ process.on('message', function(msg, h) {
|
|
|
2673
2781
|
|
|
2674
2782
|
F.on2 = F.on;
|
|
2675
2783
|
F.on = function(name, fn) {
|
|
2676
|
-
if (name === 'ready' && F.
|
|
2784
|
+
if (name === 'ready' && F.isLoaded)
|
|
2677
2785
|
fn();
|
|
2678
2786
|
else
|
|
2679
2787
|
F.on2(name, fn);
|
|
2680
2788
|
};
|
|
2681
2789
|
|
|
2682
2790
|
// Configuration
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2791
|
+
F.config.secret_uid = F.syshash.substring(10);
|
|
2792
|
+
F.config.$httpexpire = NOW.add('y', 1).toUTCString(); // must be refreshed every hour
|
|
2793
|
+
F.config.$cryptoiv = Buffer.from(F.syshash).slice(0, 16);
|
|
2794
|
+
F.config.$nodemodules = F.Path.join(F.directory, 'node_modules');
|
|
2686
2795
|
|
|
2687
2796
|
// Methods
|
|
2688
2797
|
F.route = F.TRouting.route;
|
|
@@ -2719,4 +2828,24 @@ require('./markdown');
|
|
|
2719
2828
|
// Init directories
|
|
2720
2829
|
F.dir();
|
|
2721
2830
|
|
|
2831
|
+
// Init CORS
|
|
2832
|
+
F.on('$cors', function() {
|
|
2833
|
+
|
|
2834
|
+
var arr = (F.config.$cors || '').toLowerCase().split(',').trim();
|
|
2835
|
+
var wildcard = [];
|
|
2836
|
+
var strict = [];
|
|
2837
|
+
|
|
2838
|
+
for (let i = 0; i < arr.length; i++) {
|
|
2839
|
+
let val = arr[i];
|
|
2840
|
+
if (val !== '*') {
|
|
2841
|
+
if (val[0] === '*' && val.length > 1)
|
|
2842
|
+
wildcard.push(val.substring(1));
|
|
2843
|
+
else
|
|
2844
|
+
strict.push(val);
|
|
2845
|
+
}
|
|
2846
|
+
}
|
|
2847
|
+
|
|
2848
|
+
F.temporary.cors = F.config.$cors === '*' ? null : { wildcard: wildcard, strict: strict };
|
|
2849
|
+
});
|
|
2850
|
+
|
|
2722
2851
|
module.exports = F;
|