total5 0.0.1-2 → 0.0.1-21
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 +1 -1
- package/builders.js +323 -22
- package/bundles.js +2 -12
- package/cms.js +61 -11
- package/controller.js +141 -32
- package/filestorage.js +39 -19
- package/flow-flowstream.js +412 -246
- package/flow.js +62 -36
- package/flowstream.js +84 -15
- package/global.js +144 -3
- package/http.js +1 -1
- package/image.js +4 -0
- package/images.js +1 -1
- package/index.js +142 -48
- package/jsonschema.js +35 -27
- package/mail.js +9 -7
- package/markdown.js +756 -0
- package/minificators.js +1 -1
- package/nosql-builder.js +1 -1
- package/nosql.js +11 -0
- package/openclient.js +1 -1
- package/package.json +1 -1
- package/querybuilder.js +2 -3
- package/routing.js +113 -31
- package/sourcemap.js +1 -1
- package/test.js +48 -0
- package/tms.js +13 -18
- package/tmsclient.js +4 -0
- package/uibuilder.js +54 -19
- package/utils.js +72 -43
- package/viewengine.js +10 -11
- package/websocket.js +4 -3
- package/workers.js +2 -2
- package/CONTRIBUTING.md +0 -55
- package/helpers/index.js +0 -32
- package/templates.json +0 -74
- 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
|
|
|
@@ -8,7 +8,7 @@ const NODE_MODULES = { buffer: 1, child_process: 1, process: 1, fs: 1, events: 1
|
|
|
8
8
|
const EMPTYOBJECT = {};
|
|
9
9
|
const EMPTYARRAY = [];
|
|
10
10
|
|
|
11
|
-
const REG_SKIPERRORS = /epipe|invalid\sdistance/i;
|
|
11
|
+
const REG_SKIPERRORS = /epipe|invalid\sdistance|err_ipc_channel_closed/i;
|
|
12
12
|
const REG_HTTPHTTPS = /^(http|https):\/\//i;
|
|
13
13
|
const SOCKETWINDOWS = '\\\\?\\pipe';
|
|
14
14
|
const CLUSTER_STATS = { TYPE: 'stats' };
|
|
@@ -37,6 +37,7 @@ global.DEF = {};
|
|
|
37
37
|
F.id = '';
|
|
38
38
|
F.clusterid = '';
|
|
39
39
|
F.is5 = F.version = 5000;
|
|
40
|
+
F.isBundle = false;
|
|
40
41
|
F.version_header = '5';
|
|
41
42
|
F.version_node = process.version + '';
|
|
42
43
|
F.EMPTYOBJECT = EMPTYOBJECT;
|
|
@@ -214,14 +215,17 @@ global.DEF = {};
|
|
|
214
215
|
};
|
|
215
216
|
|
|
216
217
|
F.path = {};
|
|
217
|
-
|
|
218
218
|
F.path.root = path => path ? F.path.$join(F.directory, path) : F.directory;
|
|
219
219
|
F.path.logs = path => path ? F.path.$join(F.temporary.directories.logs, path) : F.temporary.directories.logs;
|
|
220
220
|
F.path.public = path => path ? F.path.$join(F.temporary.directories.public, path) : F.temporary.directories.public;
|
|
221
221
|
F.path.private = path => path ? F.path.$join(F.temporary.directories.private, path) : F.temporary.directories.private;
|
|
222
222
|
F.path.databases = path => path ? F.path.$join(F.temporary.directories.databases, path) : F.temporary.directories.databases;
|
|
223
|
+
F.path.plugins = path => path ? F.path.$join(F.temporary.directories.plugins, path) : F.temporary.directories.plugins;
|
|
224
|
+
F.path.templates = path => path ? F.path.$join(F.temporary.directories.templates, path) : F.temporary.directories.templates;
|
|
225
|
+
F.path.flowstreams = path => path ? F.path.$join(F.temporary.directories.flowstreams, path) : F.temporary.directories.flowstreams;
|
|
223
226
|
F.path.directory = (type, path) => path ? F.path.$join(F.temporary.directories[type], path) : F.temporary.directories[type];
|
|
224
227
|
F.path.tmp = F.path.temp = path => path ? F.path.$join(F.temporary.directories.tmp, path) : F.temporary.directories.tmp;
|
|
228
|
+
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));
|
|
225
229
|
|
|
226
230
|
F.path.$join = function(directory, path) {
|
|
227
231
|
var key = '$' + directory;
|
|
@@ -340,11 +344,12 @@ function unlink(arr, callback) {
|
|
|
340
344
|
CONF.$httpreqlimit = 0; // request limit per ip
|
|
341
345
|
CONF.$httpcompress = true;
|
|
342
346
|
CONF.$httpetag = '';
|
|
343
|
-
CONF.$httpmaxsize = 256; //
|
|
347
|
+
CONF.$httpmaxsize = 256; // kB
|
|
344
348
|
CONF.$httprangebuffer = 5120; // 5 MB
|
|
345
349
|
CONF.$httptimeout = 5; // 5 seconds
|
|
346
|
-
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 };
|
|
350
|
+
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 };
|
|
347
351
|
CONF.$httpchecktypes = true; // for multipart data only
|
|
352
|
+
CONF.$httpmaxage = 60; // in seconds
|
|
348
353
|
CONF.$blacklist = '';
|
|
349
354
|
CONF.$xpoweredby = 'Total.js';
|
|
350
355
|
CONF.$maxopenfiles = 100;
|
|
@@ -352,7 +357,7 @@ function unlink(arr, callback) {
|
|
|
352
357
|
CONF.$minifycss = true;
|
|
353
358
|
CONF.$minifyhtml = true;
|
|
354
359
|
CONF.$localize = true;
|
|
355
|
-
CONF.$port =
|
|
360
|
+
CONF.$port = 'auto';
|
|
356
361
|
CONF.$ip = '0.0.0.0';
|
|
357
362
|
CONF.$unixsocket = '';
|
|
358
363
|
CONF.$timezone = 'utc';
|
|
@@ -367,11 +372,9 @@ function unlink(arr, callback) {
|
|
|
367
372
|
CONF.$imagememory = 0; // disabled because e.g. GM v1.3.32 throws some error about the memory
|
|
368
373
|
CONF.$stats = true;
|
|
369
374
|
|
|
370
|
-
CONF.$nodemodules = require.resolve('./index');
|
|
371
|
-
CONF.$nodemodules = CONF.$nodemodules.substring(0, CONF.$nodemodules.length - (8 + 7));
|
|
372
375
|
CONF.$npmcache = '/var/www/.npm';
|
|
373
376
|
CONF.$python = 'python3';
|
|
374
|
-
CONF.$wsmaxsize = 256; //
|
|
377
|
+
CONF.$wsmaxsize = 256; // kB
|
|
375
378
|
CONF.$wscompress = true;
|
|
376
379
|
CONF.$wsencodedecode = false;
|
|
377
380
|
CONF.$wsmaxlatency = 2000;
|
|
@@ -386,7 +389,7 @@ function unlink(arr, callback) {
|
|
|
386
389
|
CONF.$tapilogger = false;
|
|
387
390
|
|
|
388
391
|
CONF.$tms = false;
|
|
389
|
-
CONF.$tmsmaxsize = 256;
|
|
392
|
+
CONF.$tmsmaxsize = 256; // kB
|
|
390
393
|
CONF.$tmsurl = '/$tms/';
|
|
391
394
|
CONF.$tmsclearblocked = 60; // in minutes
|
|
392
395
|
|
|
@@ -478,7 +481,10 @@ function unlink(arr, callback) {
|
|
|
478
481
|
|
|
479
482
|
NOW = new Date();
|
|
480
483
|
|
|
481
|
-
if (
|
|
484
|
+
if (err instanceof F.TBuilders.ErrorBuilder) {
|
|
485
|
+
if (!name)
|
|
486
|
+
name = err[0].name;
|
|
487
|
+
} else if (!name && err.name)
|
|
482
488
|
name = err.name;
|
|
483
489
|
|
|
484
490
|
err = err.toString();
|
|
@@ -489,7 +495,7 @@ function unlink(arr, callback) {
|
|
|
489
495
|
if (F.errors.push(obj) > 10)
|
|
490
496
|
F.errors.shift();
|
|
491
497
|
|
|
492
|
-
|
|
498
|
+
F.$events.error && F.emit('error', obj);
|
|
493
499
|
F.stats.error++;
|
|
494
500
|
};
|
|
495
501
|
|
|
@@ -591,9 +597,13 @@ F.loadconfig = function(value) {
|
|
|
591
597
|
if (smtp)
|
|
592
598
|
F.config.smtp = smtp;
|
|
593
599
|
|
|
600
|
+
if (!F.config.$nodemodules)
|
|
601
|
+
F.config.$nodemodules = PATH.root('node_modules');
|
|
602
|
+
|
|
594
603
|
process.env.NODE_TLS_REJECT_UNAUTHORIZED = F.config.$insecure ? '0' : '1';
|
|
595
604
|
F.logger(F.config.$logger == true);
|
|
596
605
|
F.dir();
|
|
606
|
+
F.emit('$cors');
|
|
597
607
|
F.emit('$tms');
|
|
598
608
|
F.emit('$reconfigure');
|
|
599
609
|
};
|
|
@@ -610,10 +620,10 @@ F.loadresource = function(name, value) {
|
|
|
610
620
|
if (response && (response instanceof Array || typeof(response) === 'object')) {
|
|
611
621
|
if (response instanceof Array) {
|
|
612
622
|
for (let item of response)
|
|
613
|
-
|
|
623
|
+
F.loadresource(item.id || item.key || item.code || item.language, item.value || item.name || item.text || item.body);
|
|
614
624
|
} else {
|
|
615
625
|
for (let key in response)
|
|
616
|
-
|
|
626
|
+
F.loadresource(key, response[key]);
|
|
617
627
|
}
|
|
618
628
|
}
|
|
619
629
|
|
|
@@ -695,8 +705,15 @@ F.resource = function(language, key) {
|
|
|
695
705
|
return language === 'default' ? '' : F.resource('default', key);
|
|
696
706
|
};
|
|
697
707
|
|
|
708
|
+
F.localize = function(fn) {
|
|
709
|
+
F.def.onLocalize = fn;
|
|
710
|
+
};
|
|
711
|
+
|
|
698
712
|
F.auth = function(fn) {
|
|
699
|
-
|
|
713
|
+
if (typeof(fn) === 'object')
|
|
714
|
+
F.TBuilders.builtinauth(fn);
|
|
715
|
+
else
|
|
716
|
+
F.def.onAuthorize = fn;
|
|
700
717
|
};
|
|
701
718
|
|
|
702
719
|
F.load = async function(types, callback) {
|
|
@@ -708,6 +725,8 @@ F.load = async function(types, callback) {
|
|
|
708
725
|
await F.TBundles.extract();
|
|
709
726
|
await F.clear(true);
|
|
710
727
|
|
|
728
|
+
process.send && process.send('total:ready');
|
|
729
|
+
|
|
711
730
|
if (typeof(types) === 'string')
|
|
712
731
|
types = types.split(',').trim();
|
|
713
732
|
|
|
@@ -730,21 +749,35 @@ F.load = async function(types, callback) {
|
|
|
730
749
|
}
|
|
731
750
|
|
|
732
751
|
if (!types.length || types.includes('env')) {
|
|
733
|
-
|
|
752
|
+
let env = await read(F.path.root('.env'));
|
|
734
753
|
env && F.loadenv(env);
|
|
735
754
|
}
|
|
736
755
|
|
|
737
756
|
if (!types.length || types.includes('config')) {
|
|
738
|
-
|
|
757
|
+
let config = await read(F.path.root('config'));
|
|
739
758
|
config && F.loadconfig(config);
|
|
740
759
|
}
|
|
741
760
|
|
|
742
761
|
if (!types.length || types.includes('resources')) {
|
|
743
|
-
|
|
762
|
+
let resources = await list(F.path.root('resources'), 'resource');
|
|
744
763
|
for (let resource of resources)
|
|
745
764
|
F.loadresource(F.TUtils.getName(resource).replace(/\.resource$/i, ''), await read(resource));
|
|
746
765
|
}
|
|
747
766
|
|
|
767
|
+
if (!types.length || types.includes('jsonschemas')) {
|
|
768
|
+
let jsonschemas = await list(F.path.root('jsonschemas'), 'json');
|
|
769
|
+
for (let jsonschema of jsonschemas) {
|
|
770
|
+
let json = await read(jsonschema);
|
|
771
|
+
json = json.parseJSON();
|
|
772
|
+
json && F.newjsonschema(F.TUtils.getName(jsonschema).replace(/\.json$/i, ''), json);
|
|
773
|
+
}
|
|
774
|
+
jsonschemas = await list(F.path.root('jsonschemas'), 'txt');
|
|
775
|
+
for (let jsonschema of jsonschemas) {
|
|
776
|
+
let txt = await read(jsonschema);
|
|
777
|
+
txt && F.newjsonschema(F.TUtils.getName(jsonschema).replace(/\.txt$/i, ''), txt);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
|
|
748
781
|
let loader = ['modules', 'controllers', 'actions', 'schemas', 'models', 'definitions', 'sources', 'middleware'];
|
|
749
782
|
var files = [];
|
|
750
783
|
var tmp;
|
|
@@ -836,7 +869,6 @@ F.load = async function(types, callback) {
|
|
|
836
869
|
F.stats.compiled = files.length;
|
|
837
870
|
F.isloaded = true;
|
|
838
871
|
DEBUG && F.TSourceMap.refresh();
|
|
839
|
-
process.send && process.send('total:ready');
|
|
840
872
|
callback && callback();
|
|
841
873
|
|
|
842
874
|
F.emit('ready');
|
|
@@ -846,7 +878,7 @@ F.load = async function(types, callback) {
|
|
|
846
878
|
F.require = function(name) {
|
|
847
879
|
if (name.startsWith('node:'))
|
|
848
880
|
return require(name);
|
|
849
|
-
return NODE_MODULES[name] ? require('node:' + name) : require(F.Path.join(F.
|
|
881
|
+
return NODE_MODULES[name] ? require('node:' + name) : require(name); // TODO: check functionality without absolute path: require(F.Path.join(F.config.$nodemodules, name))
|
|
850
882
|
};
|
|
851
883
|
|
|
852
884
|
F.import = function(url, callback) {
|
|
@@ -953,7 +985,7 @@ F.npminstall = function(name, callback) {
|
|
|
953
985
|
if (!callback)
|
|
954
986
|
return new Promise((resolve, reject) => F.npminstall(name, err => err ? reject(err) : resolve()));
|
|
955
987
|
|
|
956
|
-
var path = F.config.$
|
|
988
|
+
var path = F.config.$nodemodules;
|
|
957
989
|
F.path.mkdir(path, true);
|
|
958
990
|
|
|
959
991
|
var index = name.lastIndexOf('@');
|
|
@@ -1010,6 +1042,9 @@ F.shell = function(cmd, callback, cwd) {
|
|
|
1010
1042
|
F.console = function() {
|
|
1011
1043
|
|
|
1012
1044
|
var memory = process.memoryUsage();
|
|
1045
|
+
var nodemodules = require.resolve('./index');
|
|
1046
|
+
|
|
1047
|
+
nodemodules = nodemodules.substring(0, CONF.$nodemodules.length - (8 + 7));
|
|
1013
1048
|
|
|
1014
1049
|
print('====================================================');
|
|
1015
1050
|
print('PID : ' + process.pid);
|
|
@@ -1030,10 +1065,10 @@ F.console = function() {
|
|
|
1030
1065
|
print('====================================================');
|
|
1031
1066
|
F.config.$root && print('Root : ' + F.config.$root);
|
|
1032
1067
|
print('Directory : ' + process.cwd());
|
|
1033
|
-
print('node_modules : ' +
|
|
1068
|
+
print('node_modules : ' + nodemodules);
|
|
1034
1069
|
print('====================================================\n');
|
|
1035
1070
|
|
|
1036
|
-
if (!F.isWorker) {
|
|
1071
|
+
if (!F.isWorker && F.server) {
|
|
1037
1072
|
|
|
1038
1073
|
var hostname = F.unixsocket ? ('Socket: ' + F.unixsocket) : '{2}://{0}:{1}/'.format(F.config.$ip, F.config.$port, F.isHTTPS ? 'https' : 'http');
|
|
1039
1074
|
|
|
@@ -1147,6 +1182,10 @@ F.http = function(opt) {
|
|
|
1147
1182
|
|
|
1148
1183
|
if (unixsocket) {
|
|
1149
1184
|
|
|
1185
|
+
try {
|
|
1186
|
+
F.Fs.unlinkSync(unixsocket);
|
|
1187
|
+
} catch (e) {}
|
|
1188
|
+
|
|
1150
1189
|
if (F.isWindows && unixsocket.indexOf(SOCKETWINDOWS) === -1)
|
|
1151
1190
|
unixsocket = F.Path.join(SOCKETWINDOWS, unixsocket);
|
|
1152
1191
|
|
|
@@ -1180,6 +1219,23 @@ F.http = function(opt) {
|
|
|
1180
1219
|
if (opt.port)
|
|
1181
1220
|
F.config.$port = opt.port;
|
|
1182
1221
|
|
|
1222
|
+
if (F.config.$port === 'auto') {
|
|
1223
|
+
let port = process.env.PORT;
|
|
1224
|
+
if (!port) {
|
|
1225
|
+
for (let arg of process.argv) {
|
|
1226
|
+
if ((/^\d{3,5}$/).test(arg)) {
|
|
1227
|
+
port = arg;
|
|
1228
|
+
break;
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
if (port)
|
|
1233
|
+
port = +port;
|
|
1234
|
+
if (isNaN(port))
|
|
1235
|
+
port = 8000;
|
|
1236
|
+
F.config.$port = port;
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1183
1239
|
if (opt.ip)
|
|
1184
1240
|
F.config.$ip = opt.ip;
|
|
1185
1241
|
|
|
@@ -1294,18 +1350,18 @@ F.componentator = function(name, components, removeprev = true) {
|
|
|
1294
1350
|
|
|
1295
1351
|
F.Fs.lstat(filename, function(err) {
|
|
1296
1352
|
if (err)
|
|
1297
|
-
F.download(url, filename, F.error('COMPONENTATOR'));
|
|
1353
|
+
F.download(url, filename, err => err ? F.error(err, 'COMPONENTATOR') : null);
|
|
1298
1354
|
});
|
|
1299
1355
|
|
|
1300
1356
|
};
|
|
1301
1357
|
|
|
1302
|
-
F.error = function(err, name,
|
|
1358
|
+
F.error = function(err, name, url) {
|
|
1303
1359
|
|
|
1304
1360
|
if (!arguments.length)
|
|
1305
1361
|
return F.errorcallback;
|
|
1306
1362
|
|
|
1307
1363
|
if (err)
|
|
1308
|
-
F.def.onError(err, name,
|
|
1364
|
+
F.def.onError(err, name, url);
|
|
1309
1365
|
};
|
|
1310
1366
|
|
|
1311
1367
|
F.errorcallback = function(err) {
|
|
@@ -1475,8 +1531,12 @@ F.middleware = function(name, fn, assign) {
|
|
|
1475
1531
|
}
|
|
1476
1532
|
}
|
|
1477
1533
|
} else {
|
|
1534
|
+
|
|
1478
1535
|
if (a === 'websocket' || a === 'file' || a === 'route')
|
|
1479
1536
|
a += 's';
|
|
1537
|
+
else if (a === 'dynamic')
|
|
1538
|
+
a = 'routes';
|
|
1539
|
+
|
|
1480
1540
|
let routes = F.routes[a];
|
|
1481
1541
|
if (routes) {
|
|
1482
1542
|
for (let route of routes) {
|
|
@@ -1586,10 +1646,8 @@ F.service = function(count) {
|
|
|
1586
1646
|
}
|
|
1587
1647
|
|
|
1588
1648
|
// Update expires date
|
|
1589
|
-
if (count % 60 === 0)
|
|
1649
|
+
if (count % 60 === 0)
|
|
1590
1650
|
F.config.$httpexpire = NOW.add('y', 1).toUTCString();
|
|
1591
|
-
F.TImages.clear();
|
|
1592
|
-
}
|
|
1593
1651
|
|
|
1594
1652
|
if (count % F.config.$tmsclearblocked === 0)
|
|
1595
1653
|
F.temporary.tmsblocked = {};
|
|
@@ -1796,7 +1854,7 @@ F.newjsonschema = function(name, obj) {
|
|
|
1796
1854
|
F.newtransform = function(name, action, id) {
|
|
1797
1855
|
if (action == null) {
|
|
1798
1856
|
let items = F.transformations[name];
|
|
1799
|
-
let index = items.
|
|
1857
|
+
let index = items.TfindIndex('id', id);
|
|
1800
1858
|
if (index !== -1) {
|
|
1801
1859
|
items.splice(index, 1);
|
|
1802
1860
|
if (!items.length)
|
|
@@ -2160,7 +2218,7 @@ F.backup = function(filename, files, callback, filter) {
|
|
|
2160
2218
|
F.Fs.stat(file, function(err, stats) {
|
|
2161
2219
|
|
|
2162
2220
|
if (err) {
|
|
2163
|
-
F.error(err, '
|
|
2221
|
+
F.error(err, 'F.backup()', filename);
|
|
2164
2222
|
next();
|
|
2165
2223
|
return;
|
|
2166
2224
|
}
|
|
@@ -2246,7 +2304,7 @@ F.backup = function(filename, files, callback, filter) {
|
|
|
2246
2304
|
counter++;
|
|
2247
2305
|
setImmediate(next);
|
|
2248
2306
|
}).on('error', function(err) {
|
|
2249
|
-
F.error(err, 'F.backup', file);
|
|
2307
|
+
F.error(err, 'F.backup()', file);
|
|
2250
2308
|
setImmediate(next);
|
|
2251
2309
|
});
|
|
2252
2310
|
|
|
@@ -2255,16 +2313,17 @@ F.backup = function(filename, files, callback, filter) {
|
|
|
2255
2313
|
});
|
|
2256
2314
|
};
|
|
2257
2315
|
|
|
2258
|
-
F.
|
|
2316
|
+
F.restart = function() {
|
|
2317
|
+
process.send && process.send('total:restart');
|
|
2318
|
+
};
|
|
2319
|
+
|
|
2320
|
+
F.exit = function(signal = 15) {
|
|
2259
2321
|
|
|
2260
2322
|
if (F.isexited)
|
|
2261
2323
|
return;
|
|
2262
2324
|
|
|
2263
2325
|
F.isexited = true;
|
|
2264
2326
|
|
|
2265
|
-
if (!signal)
|
|
2266
|
-
signal = 'SIGTERM';
|
|
2267
|
-
|
|
2268
2327
|
for (let m in F.workers) {
|
|
2269
2328
|
let worker = F.workers[m];
|
|
2270
2329
|
try {
|
|
@@ -2272,7 +2331,7 @@ F.exit = function(signal) {
|
|
|
2272
2331
|
} catch (e) {}
|
|
2273
2332
|
}
|
|
2274
2333
|
|
|
2275
|
-
let key = '
|
|
2334
|
+
let key = 'exit';
|
|
2276
2335
|
|
|
2277
2336
|
F.$events[key] && F.emit(key, signal);
|
|
2278
2337
|
|
|
@@ -2366,7 +2425,7 @@ F.dir = function(val) {
|
|
|
2366
2425
|
if (val)
|
|
2367
2426
|
F.directory = val;
|
|
2368
2427
|
|
|
2369
|
-
var dirs = ['public', 'tmp', 'logs', 'databases', 'controllers', 'resources', 'plugins', 'views', 'definitions', 'schemas', 'models', 'flowstreams', 'bundles', 'actions', 'extensions', 'source', 'services', 'updates', 'templates'];
|
|
2428
|
+
var dirs = ['public', 'tmp', 'logs', 'databases', 'controllers', 'resources', 'plugins', 'views', 'definitions', 'schemas', 'models', 'flowstreams', 'bundles', 'actions', 'extensions', 'source', 'services', 'updates', 'templates', 'private'];
|
|
2370
2429
|
|
|
2371
2430
|
for (let dir of dirs) {
|
|
2372
2431
|
var cfg = F.config['$dir' + dir];
|
|
@@ -2406,6 +2465,12 @@ F.mail = function(email, subject, name, model, language, callback) {
|
|
|
2406
2465
|
callback = tmp;
|
|
2407
2466
|
}
|
|
2408
2467
|
|
|
2468
|
+
// Localization
|
|
2469
|
+
if (typeof(language) === 'string') {
|
|
2470
|
+
if (subject.includes('@('))
|
|
2471
|
+
subject = TRANSLATE(language, subject);
|
|
2472
|
+
}
|
|
2473
|
+
|
|
2409
2474
|
let body = F.view(name, model, view => view.language = language || '');
|
|
2410
2475
|
return F.def.onMail(email, subject, body, callback);
|
|
2411
2476
|
};
|
|
@@ -2418,17 +2483,22 @@ F.htmlmail = function(email, subject, body, language, callback) {
|
|
|
2418
2483
|
callback = tmp;
|
|
2419
2484
|
}
|
|
2420
2485
|
|
|
2421
|
-
//
|
|
2486
|
+
// Localization
|
|
2422
2487
|
if (typeof(language) === 'string') {
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2488
|
+
if (subject.includes('@('))
|
|
2489
|
+
subject = TRANSLATE(language, subject);
|
|
2490
|
+
if (body.includes('@('))
|
|
2491
|
+
body = TRANSLATE(language, body);
|
|
2426
2492
|
}
|
|
2427
2493
|
|
|
2428
|
-
|
|
2494
|
+
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;
|
|
2429
2495
|
return F.def.onMail(email, subject, body, callback);
|
|
2430
2496
|
};
|
|
2431
2497
|
|
|
2498
|
+
F.readfile = function(path, type = null) {
|
|
2499
|
+
return new Promise(resolve => F.Fs.readFile(path, type, (err, response) => err ? resolve(null) : resolve(response)));
|
|
2500
|
+
};
|
|
2501
|
+
|
|
2432
2502
|
F.loadstats = function() {
|
|
2433
2503
|
|
|
2434
2504
|
var main = {};
|
|
@@ -2526,13 +2596,11 @@ process.on('unhandledRejection', function(e) {
|
|
|
2526
2596
|
F.error(e.stack, '');
|
|
2527
2597
|
});
|
|
2528
2598
|
|
|
2529
|
-
// process.on('uncaughtException', function(e) {
|
|
2530
2599
|
process.on('uncaughtException', function(e) {
|
|
2531
|
-
|
|
2532
2600
|
var err = e + '';
|
|
2533
2601
|
if (err.indexOf('listen EADDRINUSE') !== -1) {
|
|
2534
|
-
process.send && process.send('total:eaddrinuse');
|
|
2535
2602
|
console.log('\nThe IP address and the PORT is already in use.\nYou must change the PORT\'s number or IP address.\n');
|
|
2603
|
+
process.send && process.send('total:eaddrinuse');
|
|
2536
2604
|
process.exit(1);
|
|
2537
2605
|
return;
|
|
2538
2606
|
} else if (F.config.$filtererrors && REG_SKIPERRORS.test(err))
|
|
@@ -2548,9 +2616,9 @@ process.on('message', function(msg, h) {
|
|
|
2548
2616
|
|
|
2549
2617
|
let key;
|
|
2550
2618
|
|
|
2551
|
-
if (msg === 'total:debug')
|
|
2619
|
+
if (msg === 'total:debug') {
|
|
2552
2620
|
F.TUtils.wait(() => F.isloaded, F.console, 10000, 500);
|
|
2553
|
-
else if (msg === 'total:ping')
|
|
2621
|
+
} else if (msg === 'total:ping')
|
|
2554
2622
|
setImmediate(ping);
|
|
2555
2623
|
else if (msg === 'total:update') {
|
|
2556
2624
|
key = '$update';
|
|
@@ -2608,6 +2676,8 @@ process.on('message', function(msg, h) {
|
|
|
2608
2676
|
F.syshash = (__dirname + '-' + F.Os.hostname() + '-' + F.Os.platform() + '-' + F.Os.arch() + '-' + F.Os.release() + '-' + F.Os.tmpdir() + JSON.stringify(process.versions)).md5();
|
|
2609
2677
|
F.isLE = F.Os.endianness ? F.Os.endianness() === 'LE' : true;
|
|
2610
2678
|
|
|
2679
|
+
CONF.$total5 = F.Path.dirname(require.resolve('./index'));
|
|
2680
|
+
|
|
2611
2681
|
F.cache = require('./cache');
|
|
2612
2682
|
F.TImages = require('./images');
|
|
2613
2683
|
F.path.fs = F.Fs;
|
|
@@ -2658,5 +2728,29 @@ process.connected && setTimeout(() => process.send('total:init'), 100);
|
|
|
2658
2728
|
|
|
2659
2729
|
require('./global');
|
|
2660
2730
|
require('./tangular');
|
|
2731
|
+
require('./markdown');
|
|
2732
|
+
|
|
2733
|
+
// Init directories
|
|
2734
|
+
F.dir();
|
|
2735
|
+
|
|
2736
|
+
// Init CORS
|
|
2737
|
+
F.on('$cors', function() {
|
|
2738
|
+
|
|
2739
|
+
var arr = (F.config.$cors || '').toLowerCase().split(',').trim();
|
|
2740
|
+
var wildcard = [];
|
|
2741
|
+
var strict = [];
|
|
2742
|
+
|
|
2743
|
+
for (let i = 0; i < arr.length; i++) {
|
|
2744
|
+
let val = arr[i];
|
|
2745
|
+
if (val !== '*') {
|
|
2746
|
+
if (val[0] === '*' && val.length > 1)
|
|
2747
|
+
wildcard.push(val.substring(1));
|
|
2748
|
+
else
|
|
2749
|
+
strict.push(val);
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2752
|
+
|
|
2753
|
+
F.temporary.cors = F.config.$cors === '*' ? null : { wildcard: wildcard, strict: strict };
|
|
2754
|
+
});
|
|
2661
2755
|
|
|
2662
2756
|
module.exports = F;
|
package/jsonschema.js
CHANGED
|
@@ -18,7 +18,7 @@ function check_string(meta, error, value, errplus, path) {
|
|
|
18
18
|
var type = typeof(value);
|
|
19
19
|
|
|
20
20
|
if (type !== 'string')
|
|
21
|
-
value = value ? (value + '') : null;
|
|
21
|
+
value = value ? (value + '') : meta.nullable ? null : '';
|
|
22
22
|
|
|
23
23
|
if (errplus == null)
|
|
24
24
|
errplus = '';
|
|
@@ -37,7 +37,7 @@ function check_string(meta, error, value, errplus, path) {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
if (value == null)
|
|
40
|
-
return;
|
|
40
|
+
return null;
|
|
41
41
|
|
|
42
42
|
var len = value.length;
|
|
43
43
|
|
|
@@ -133,6 +133,14 @@ function check_string(meta, error, value, errplus, path) {
|
|
|
133
133
|
return;
|
|
134
134
|
}
|
|
135
135
|
break;
|
|
136
|
+
case 'datauri':
|
|
137
|
+
value = value.trim();
|
|
138
|
+
if (value && !value.isBase64(true)) {
|
|
139
|
+
error.push2(errplus + meta.$$ID, path);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
value = value ? value.parseDataURI() : null;
|
|
143
|
+
break;
|
|
136
144
|
case 'color':
|
|
137
145
|
value = value.trim();
|
|
138
146
|
if (value && !REG_COLOR.test(value)) {
|
|
@@ -299,7 +307,8 @@ function check_date(meta, error, value, errplus, path) {
|
|
|
299
307
|
return value;
|
|
300
308
|
}
|
|
301
309
|
|
|
302
|
-
function
|
|
310
|
+
function readdef(ref, definitions) {
|
|
311
|
+
|
|
303
312
|
if (ref[0] === '#') {
|
|
304
313
|
var tmp = ref.substring(2).split('/');
|
|
305
314
|
var def = definitions[tmp[0]];
|
|
@@ -312,7 +321,8 @@ function read_def(ref, definitions) {
|
|
|
312
321
|
return obj;
|
|
313
322
|
}
|
|
314
323
|
}
|
|
315
|
-
}
|
|
324
|
+
} else
|
|
325
|
+
return F.jsonschemas[ref];
|
|
316
326
|
}
|
|
317
327
|
|
|
318
328
|
function check_array(meta, error, value, stop, definitions, path) {
|
|
@@ -420,13 +430,14 @@ function check_array(meta, error, value, stop, definitions, path) {
|
|
|
420
430
|
var val = value[i];
|
|
421
431
|
|
|
422
432
|
if (meta.items.$ref) {
|
|
423
|
-
var ref =
|
|
433
|
+
var ref = typeof(meta.items.$ref) === 'object' ? meta.items.$ref :readdef(meta.items.$ref, definitions);
|
|
424
434
|
if (ref) {
|
|
425
|
-
var newerror =
|
|
426
|
-
tmp = transform(ref, newerror, val);
|
|
427
|
-
if (newerror.length) {
|
|
428
|
-
for (var err of newerror)
|
|
429
|
-
error.push2(
|
|
435
|
+
var newerror = new F.ErrorBuilder();
|
|
436
|
+
tmp = transform(ref, newerror, val, false, currentpath + '[' + i + ']');
|
|
437
|
+
if (newerror.items.length) {
|
|
438
|
+
for (var err of newerror.items) {
|
|
439
|
+
error.push2(err.name, err.path, i);
|
|
440
|
+
}
|
|
430
441
|
} else if (tmp != null && (!meta.uniqueItems || response.indexOf(tmp) === -1))
|
|
431
442
|
response.push(tmp);
|
|
432
443
|
continue;
|
|
@@ -552,10 +563,8 @@ function check_object(meta, error, value, response, stop, definitions, path) {
|
|
|
552
563
|
case 'boolean':
|
|
553
564
|
case 'bool':
|
|
554
565
|
tmp = check_boolean(prop, error, val, null, currentpath);
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
count++;
|
|
558
|
-
}
|
|
566
|
+
response[key] = tmp == true;
|
|
567
|
+
count++;
|
|
559
568
|
break;
|
|
560
569
|
case 'date':
|
|
561
570
|
tmp = check_date(prop, error, val, null, currentpath);
|
|
@@ -564,16 +573,14 @@ function check_object(meta, error, value, response, stop, definitions, path) {
|
|
|
564
573
|
break;
|
|
565
574
|
case 'string':
|
|
566
575
|
tmp = check_string(prop, error, val, null, currentpath);
|
|
567
|
-
if (tmp
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
response[key] = tmp;
|
|
573
|
-
count++;
|
|
574
|
-
}
|
|
576
|
+
if (tmp == '' && prop.nullable)
|
|
577
|
+
tmp = null;
|
|
578
|
+
response[key] = tmp;
|
|
579
|
+
count++;
|
|
575
580
|
break;
|
|
581
|
+
|
|
576
582
|
case 'object':
|
|
583
|
+
|
|
577
584
|
if (prop.properties) {
|
|
578
585
|
tmp = check_object(prop, error, val, null, null, definitions, currentpath);
|
|
579
586
|
if (tmp != null) {
|
|
@@ -584,13 +591,14 @@ function check_object(meta, error, value, response, stop, definitions, path) {
|
|
|
584
591
|
|
|
585
592
|
// check ref
|
|
586
593
|
if (prop.$ref) {
|
|
587
|
-
var ref =
|
|
594
|
+
var ref = typeof(prop.$ref) === 'object' ? prop.$ref : readdef(prop.$ref, definitions);
|
|
588
595
|
if (ref) {
|
|
589
|
-
var newerror = new ErrorBuilder();
|
|
590
|
-
tmp = transform(ref, newerror, val);
|
|
596
|
+
var newerror = new F.ErrorBuilder();
|
|
597
|
+
tmp = transform(ref, newerror, val, false, currentpath);
|
|
591
598
|
if (newerror.items.length) {
|
|
592
|
-
for (var err of newerror.items)
|
|
593
|
-
error.
|
|
599
|
+
for (var err of newerror.items) {
|
|
600
|
+
error.push2(err.name, err.path);
|
|
601
|
+
}
|
|
594
602
|
} else
|
|
595
603
|
response[key] = tmp;
|
|
596
604
|
continue;
|
package/mail.js
CHANGED
|
@@ -225,10 +225,12 @@ Message.prototype.send2 = function(callback) {
|
|
|
225
225
|
Mailer.send(F.config.smtp, self, callback);
|
|
226
226
|
};
|
|
227
227
|
|
|
228
|
-
Message.prototype.send = function(smtp, options, callback) {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
228
|
+
Message.prototype.send = function(smtp, options, callback, cache) {
|
|
229
|
+
var self = this;
|
|
230
|
+
self.$callback2 = callback;
|
|
231
|
+
options.server = smtp;
|
|
232
|
+
Mailer.send(options, self, callback, cache);
|
|
233
|
+
return self;
|
|
232
234
|
};
|
|
233
235
|
|
|
234
236
|
Mailer.tls = function(obj, opt) {
|
|
@@ -396,12 +398,12 @@ function writeattachmentbytes(chunk) {
|
|
|
396
398
|
}
|
|
397
399
|
}
|
|
398
400
|
|
|
399
|
-
Mailer.try = function(
|
|
401
|
+
Mailer.try = function(options, callback) {
|
|
400
402
|
var self = this;
|
|
401
403
|
if (callback)
|
|
402
|
-
|
|
404
|
+
self.send(options, undefined, callback);
|
|
403
405
|
else
|
|
404
|
-
return new Promise((resolve, reject) => self.send(
|
|
406
|
+
return new Promise((resolve, reject) => self.send(options, undefined, err => err ? reject(err) : resolve()));
|
|
405
407
|
};
|
|
406
408
|
|
|
407
409
|
Mailer.send2 = function(messages, callback) {
|