total5 0.0.1-7 → 0.0.1-8

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/builders.js CHANGED
@@ -5,6 +5,7 @@
5
5
  'use strict';
6
6
 
7
7
  const REG_ARGS = /\{{1,2}[a-z0-9_.-\s]+\}{1,2}/gi;
8
+ const SESSIONSEPARATOR = '\0';
8
9
 
9
10
  var transforms = { error: {}, restbuilder: {} };
10
11
  var restbuilderupgrades = [];
@@ -98,7 +99,7 @@ Options.prototype.action = function(schema, payload) {
98
99
  Options.prototype.publish = function(value) {
99
100
  var self = this;
100
101
  var name = self.id;
101
- if (F.TMS.cache.socket && F.TMS.cache.pcache[name] && F.TMS.cache.publishers[name]) {
102
+ if (F.TTMS.cache.socket && F.TTMS.cache.pcache[name]) {
102
103
 
103
104
  var tmp = {};
104
105
  if (tmp) {
@@ -109,7 +110,7 @@ Options.prototype.publish = function(value) {
109
110
  }
110
111
 
111
112
  F.stats.performance.publish++;
112
- F.TMS.cache.socket.send({ type: 'publish', id: name, data: tmp }, client => client.tmsready);
113
+ F.TTMS.cache.socket.send({ type: 'publish', id: name, data: tmp }, client => client.tmsready && client.$subscribers[name]);
113
114
  }
114
115
  return self;
115
116
  };
@@ -1154,7 +1155,7 @@ exports.newaction = function(name, obj) {
1154
1155
  }
1155
1156
  }
1156
1157
 
1157
- F.TMS.newpublish(name, tmsschema);
1158
+ F.TTMS.newpublish(name, tmsschema);
1158
1159
  }
1159
1160
 
1160
1161
  F.makesourcemap && F.makesourcemap();
@@ -1277,7 +1278,6 @@ ActionCaller.prototype.exec = function() {
1277
1278
  if (action.jsquery) {
1278
1279
  self.error.prefix = 'query.';
1279
1280
  response = action.jsquery.transform(query, false, self.error);
1280
- console.log(query, response, action);
1281
1281
  self.error.prefix = '';
1282
1282
  if (response.error) {
1283
1283
  self.cancel();
@@ -1300,7 +1300,7 @@ ActionCaller.prototype.exec = function() {
1300
1300
  $.params = params;
1301
1301
 
1302
1302
  if (action.jsinput && type !== '-') {
1303
- response = action.jsinput.transform(payload, type === '%', self.error);
1303
+ response = action.jsinput.transform(payload, action.partial, self.error);
1304
1304
  if (response.error) {
1305
1305
  self.cancel();
1306
1306
  return;
@@ -1436,6 +1436,15 @@ exports.action = function(name, payload, controller) {
1436
1436
  };
1437
1437
 
1438
1438
  exports.newschema = function(name, callback) {
1439
+
1440
+ if (name[0] === '@')
1441
+ name = name.substring(1);
1442
+
1443
+ if (typeof(callback) === 'string') {
1444
+ F.jsonschemas[name] = F.TUtils.jsonschema(callback, true);
1445
+ return;
1446
+ }
1447
+
1439
1448
  var $ = {};
1440
1449
  $.name = name;
1441
1450
  $.actions = {};
@@ -1445,6 +1454,262 @@ exports.newschema = function(name, callback) {
1445
1454
  callback($);
1446
1455
  };
1447
1456
 
1457
+ exports.builtinauth = function(opt) {
1458
+
1459
+ // opt.secret {String}
1460
+ // opt.ddos {Number}
1461
+ // opt.expire {String}
1462
+ // opt.cookie {String} A cookie name
1463
+ // opt.header {String} A header name
1464
+ // opt.options {Object} A cookie options
1465
+ // opt.strict {Boolean}
1466
+
1467
+ if (opt.strict == null)
1468
+ opt.strict = true;
1469
+
1470
+ // Delegates
1471
+ // opt.onddos = function($)
1472
+ // opt.onread = function({ sessionid: String, userid: String, ua: String }, callback(USER_DATA), $)
1473
+ // opt.onfree = function({ sessions: Array, users: Array })
1474
+ // opt.onlogout = function(sessionid, userid)
1475
+ // opt.onauthorize = function($) must return true for canceling of processing
1476
+
1477
+ opt.sessions = {};
1478
+ opt.blocked = {};
1479
+ opt.pending = {};
1480
+
1481
+ if (!opt.cleaner)
1482
+ opt.cleaner = 5;
1483
+
1484
+ if (!opt.secret)
1485
+ opt.secret = F.secret;
1486
+
1487
+ opt.logout = function($) {
1488
+
1489
+ var id = $;
1490
+
1491
+ if (typeof(id) === 'object')
1492
+ id = $.sessionid;
1493
+
1494
+ if (id) {
1495
+ for (var key in opt.sessions) {
1496
+ var session = opt.sessions[key];
1497
+ if (session.sessionid === id) {
1498
+ delete opt.sessions[key];
1499
+ opt.onlogout && opt.onlogout(session);
1500
+ opt.cookie && !$.controller.parent && $.controller.cookie && $.controller.cookie(opt.cookie, '', '-1 year', opt.options);
1501
+ return true;
1502
+ }
1503
+ }
1504
+ }
1505
+ };
1506
+
1507
+ opt.update = function(userid, fn) {
1508
+ var count = 0;
1509
+ for (var key in opt.sessions) {
1510
+ var session = opt.sessions[key];
1511
+ if (session.userid === userid) {
1512
+ count++;
1513
+ fn(session.data, session);
1514
+ }
1515
+ }
1516
+ return count;
1517
+ };
1518
+
1519
+ opt.refresh = function(userid, exceptsessionid) {
1520
+ var count = 0;
1521
+ for (var key in opt.sessions) {
1522
+ var session = opt.sessions[key];
1523
+ if (session.userid === userid && session.sessionid !== exceptsessionid) {
1524
+ count++;
1525
+ delete opt.sessions[key];
1526
+ }
1527
+ }
1528
+ return count;
1529
+ };
1530
+
1531
+ opt.sign = function(sessionid, userid) {
1532
+ return (sessionid + SESSIONSEPARATOR + userid + SESSIONSEPARATOR + Date.now().toString(36)).encrypt(opt.secret);
1533
+ };
1534
+
1535
+ opt.authcookie = function($, sessionid, userid, expiration, options) {
1536
+ if (!options)
1537
+ options = opt.options;
1538
+ var ctrl = $.controller ? $.controller : $;
1539
+ ctrl.cookie && !ctrl.parent && $.cookie(opt.cookie, opt.sign(sessionid, userid), expiration, options);
1540
+ };
1541
+
1542
+ if (!opt.expire)
1543
+ opt.expire = '5 minutes';
1544
+
1545
+ var callpending = function(pending, data) {
1546
+ for (var i = 0; i < pending.length; i++) {
1547
+ if (data)
1548
+ pending[i].success(data);
1549
+ else
1550
+ pending[i].invalid();
1551
+ }
1552
+ };
1553
+
1554
+ opt.auth = function($) {
1555
+
1556
+ if (opt.onauthorize && opt.onauthorize($))
1557
+ return;
1558
+
1559
+ var sessionid = opt.cookie ? $.cookie(opt.cookie) : null;
1560
+ if (!sessionid && opt.header)
1561
+ sessionid = $.controller.headers[opt.header];
1562
+
1563
+ if (!sessionid) {
1564
+
1565
+ if (opt.locale)
1566
+ $.controller.language = opt.locale(null, $.controller);
1567
+
1568
+ $.invalid();
1569
+ return;
1570
+ }
1571
+
1572
+ var id = sessionid.decrypt(opt.secret);
1573
+ if (id) {
1574
+
1575
+ id = id.split(SESSIONSEPARATOR);
1576
+
1577
+ if (!id[0] || !id[1] || !id[2])
1578
+ id = null;
1579
+
1580
+ if (id) {
1581
+ var session = opt.sessions[id[0]];
1582
+ if (session && session.data) {
1583
+ if (!opt.strict || session.ua === $.controller.ua) {
1584
+ $.controller.session = session;
1585
+ $.controller.sessionid = session.sessionid;
1586
+ if (!opt.onsession || !opt.onsession(session, $)) {
1587
+ if (opt.locale)
1588
+ $.controller.language = opt.locale(session.data, $.controller);
1589
+ $.success(session.data);
1590
+ }
1591
+ } else {
1592
+
1593
+ if (opt.locale)
1594
+ $.controller.language = opt.locale(null, $.controller);
1595
+
1596
+ $.invalid();
1597
+ sessionid = null;
1598
+ }
1599
+ return;
1600
+ }
1601
+ }
1602
+ }
1603
+
1604
+ if (opt.ddos && opt.blocked[$.controller.ip] > opt.ddos) {
1605
+ opt.onddos && opt.onddos($);
1606
+ $.invalid();
1607
+ return;
1608
+ }
1609
+
1610
+ if (!id) {
1611
+
1612
+ if (opt.ddos) {
1613
+ if (opt.blocked[$.controller.ip])
1614
+ opt.blocked[$.controller.ip]++;
1615
+ else
1616
+ opt.blocked[$.controller.ip] = 1;
1617
+ }
1618
+
1619
+ opt.cookie && $.controller && !$.controller.parent && $.controller.cookie && $.controller.cookie(opt.cookie, '', '-1 year', opt.options);
1620
+ $.invalid();
1621
+ return;
1622
+ }
1623
+
1624
+ var meta = { ip: $.controller.ip, ua: $.controller.ua, sessionid: id[0], userid: id[1] };
1625
+
1626
+ if (opt.pending[meta.sessionid]) {
1627
+ opt.pending[meta.sessionid].push($);
1628
+ return;
1629
+ }
1630
+
1631
+ opt.pending[meta.sessionid] = [];
1632
+ opt.onread(meta, function(err, data) {
1633
+
1634
+ var pending = opt.pending[meta.sessionid];
1635
+ delete opt.pending[meta.sessionid];
1636
+
1637
+ if (!err && data) {
1638
+
1639
+ $.controller.session = opt.sessions[meta.sessionid] = { sessionid: meta.sessionid, userid: meta.userid, data: data, ua: $.controller.ua, expire: NOW.add(opt.expire) };
1640
+ $.controller.sessionid = meta.sessionid;
1641
+
1642
+ if (opt.locale)
1643
+ $.controller.language = opt.locale(data, $.controller);
1644
+
1645
+ if (!opt.onsession || !opt.onsession($.controller.session, $, true))
1646
+ $.success(data);
1647
+
1648
+ if (pending.length)
1649
+ setImmediate(callpending, pending, data);
1650
+
1651
+ } else {
1652
+
1653
+ if (opt.ddos) {
1654
+ if (opt.blocked[$.controller.ip])
1655
+ opt.blocked[$.controller.ip]++;
1656
+ else
1657
+ opt.blocked[$.controller.ip] = 1;
1658
+ }
1659
+
1660
+ opt.cookie && !$.controller.parent && $.controller.cookie && $.controller.cookie(opt.cookie, '', '-1 year', opt.options);
1661
+ $.invalid();
1662
+
1663
+ if (pending.length)
1664
+ setImmediate(callpending, pending);
1665
+ }
1666
+
1667
+ }, $);
1668
+
1669
+ };
1670
+
1671
+ F.def.onAuthorize = opt.auth;
1672
+
1673
+ F.on('service', function(counter) {
1674
+
1675
+ if (counter % opt.cleaner)
1676
+ return;
1677
+
1678
+ var expired = [];
1679
+ var users_expired = {};
1680
+ var users_live = {};
1681
+
1682
+ for (var key in opt.sessions) {
1683
+ var session = opt.sessions[key];
1684
+ if (session.expire < NOW) {
1685
+ expired.push(key);
1686
+ delete opt.sessions[key];
1687
+ users_expired[session.userid] = 1;
1688
+ } else
1689
+ users_live[session.userid] = 1;
1690
+ }
1691
+
1692
+ if (expired.length) {
1693
+ for (var key in users_expired) {
1694
+ if (users_live[key])
1695
+ delete users_expired[key];
1696
+ }
1697
+ }
1698
+
1699
+ if (expired.length && opt.onfree) {
1700
+ var meta = {};
1701
+ meta.sessions = expired;
1702
+ meta.users = expired.length ? Object.keys(users_expired) : null;
1703
+ opt.onfree && opt.onfree(meta);
1704
+ }
1705
+
1706
+ opt.blocked = {};
1707
+
1708
+ });
1709
+
1710
+ return opt;
1711
+ };
1712
+
1448
1713
  exports.RESTBuilder = RESTBuilder;
1449
1714
  exports.ErrorBuilder = ErrorBuilder;
1450
1715
  exports.Options = Options;
package/cms.js CHANGED
@@ -577,7 +577,7 @@ CMSRender.prototype._render = function(meta, layout, callback) {
577
577
  }
578
578
 
579
579
  render(opt, function(response, replace, cache) {
580
- widgets[item.indexer] = replace === true ? response == null ? '' : (response + '').replace(/~(BEG|END)~/g, '') : (item.beg + (response || '') + item.end);
580
+ widgets[item.indexer] = replace === true ? (response == null || response == '' ? '' : (response + '').replace(/~(BEG|END)~/g, '')) : (item.beg + (response || '') + item.end);
581
581
  if (cache)
582
582
  self.cache[opt.cacheid] = widgets[item.indexer];
583
583
  next();
package/controller.js CHANGED
@@ -36,6 +36,7 @@ function Controller(req, res) {
36
36
  ctrl.url = ctrl.uri.key;
37
37
  ctrl.released = false;
38
38
  ctrl.downloaded = false;
39
+ ctrl.protocol = req.connection.encrypted || (req.headers['x-forwarded-protocol'] || req.headers['x-forwarded-proto']) === 'https' ? 'https' : 'http';
39
40
 
40
41
  for (let path of ctrl.split)
41
42
  ctrl.split2.push(path.toLowerCase());
@@ -120,6 +121,10 @@ Controller.prototype = {
120
121
  return this.headers['x-requested-with'] === 'XMLHttpRequest';
121
122
  },
122
123
 
124
+ get extension() {
125
+ return this.ext;
126
+ },
127
+
123
128
  get ua() {
124
129
  if (this.$ua != null)
125
130
  return this.$ua;
@@ -772,7 +777,7 @@ Controller.prototype.free = function() {
772
777
 
773
778
  Controller.prototype.hostname = function(path) {
774
779
  var ctrl = this;
775
- return ctrl.headers.host + ctrl.uri.pathname + (path ? path : '');
780
+ return ctrl.protocol + '://' + ctrl.headers.host + (path ? path : '');
776
781
  };
777
782
 
778
783
  Controller.prototype.$route = function() {
@@ -915,7 +920,7 @@ function multipart(ctrl) {
915
920
  }
916
921
 
917
922
  var boundary = type.substring(index + 9, end);
918
- var parser = F.TUtils.multipartparser(boundary, ctrl, function(err, meta) {
923
+ var parser = F.TUtils.multipartparser(boundary, ctrl.req, function(err, meta) {
919
924
 
920
925
  F.stats.performance.download += meta.size / 1024 / 1024;
921
926
 
@@ -957,13 +962,14 @@ function multipart(ctrl) {
957
962
  });
958
963
 
959
964
  parser.skipcheck = !F.config.$httpchecktypes;
960
- parser.limits.total = ctrl.route.size;
965
+ parser.limits.total = ctrl.route.size * 1024; // to bytes
961
966
  }
962
967
 
963
968
  function authorize(ctrl) {
964
969
  if (F.def.onAuthorize) {
965
970
  var opt = new F.TBuilders.Options(ctrl);
966
971
  opt.TYPE = 'auth'; // important
972
+ opt.query = ctrl.query;
967
973
  opt.next = opt.callback;
968
974
  opt.$callback = function(err, user) {
969
975
  let auth = user ? 1 : 2;
@@ -992,6 +998,9 @@ function execute(ctrl) {
992
998
  ctrl.params[param.name] = value;
993
999
  }
994
1000
 
1001
+ if (!ctrl.language && F.def.onLocalize)
1002
+ ctrl.language = F.def.onLocalize(ctrl);
1003
+
995
1004
  if (ctrl.route.middleware.length) {
996
1005
  middleware(ctrl);
997
1006
  } else {
@@ -1029,6 +1038,10 @@ function execute(ctrl) {
1029
1038
  if (ctrl.route.actions) {
1030
1039
  F.action(ctrl.route.actions, ctrl.body, ctrl).autorespond();
1031
1040
  } else {
1041
+ if (ctrl.route.view) {
1042
+ ctrl.view(ctrl.route.view);
1043
+ return;
1044
+ }
1032
1045
  let action = ctrl.route.action;
1033
1046
  if (!action)
1034
1047
  action = auto_view;
@@ -1039,7 +1052,7 @@ function execute(ctrl) {
1039
1052
  }
1040
1053
 
1041
1054
  function auto_view(ctrl) {
1042
- ctrl.view(ctrl.split[0] || 'index', ctrl.body);
1055
+ ctrl.view(ctrl.split[0] || 'index');
1043
1056
  }
1044
1057
 
1045
1058
  function send_html(ctrl, path) {
@@ -1063,6 +1076,9 @@ function send_html(ctrl, path) {
1063
1076
  return;
1064
1077
  }
1065
1078
 
1079
+ if (!ctrl.language && F.def.onLocalize)
1080
+ ctrl.language = F.def.onLocalize(ctrl);
1081
+
1066
1082
  output.body = F.translate(ctrl.language, output.body);
1067
1083
 
1068
1084
  if (ctrl.response.minify && F.config.$minifyhtml)
@@ -1308,6 +1324,9 @@ function HttpFile(meta) {
1308
1324
  }
1309
1325
 
1310
1326
  HttpFile.prototype = {
1327
+ get extension() {
1328
+ return this.ext;
1329
+ },
1311
1330
  get isImage() {
1312
1331
  return this.type.indexOf('image/') !== -1;
1313
1332
  },
package/filestorage.js CHANGED
@@ -94,14 +94,14 @@ FP.readjson = function(id, callback) {
94
94
  });
95
95
  };
96
96
 
97
- FP.save = FP.insert = function(id, name, filename, callback, custom, expire, headers) {
97
+ FP.save = FP.insert = function(id, name, filename, custom, callback, expire, headers) {
98
98
  var self = this;
99
99
 
100
- if (callback && typeof(callback) !== 'function') {
100
+ if (typeof(custom) === 'function') {
101
101
  headers = expire;
102
- expire = custom;
103
- custom = callback;
104
- callback = null;
102
+ expire = callback;
103
+ callback = custom;
104
+ custom = null;
105
105
  }
106
106
 
107
107
  if (callback)
@@ -945,7 +945,7 @@ function httprequest(self, opt, callback) {
945
945
  }
946
946
 
947
947
  function killprocess() {
948
- console.error('Main process doesn\'t respond');
948
+ // console.error('Main process doesn\'t respond');
949
949
  process.exit(1);
950
950
  }
951
951
 
@@ -3164,32 +3164,6 @@ TMS.refresh2 = function(fs) {
3164
3164
  setTimeout2('tms_refresh_' + fs.name, fs => TMS.refresh(fs), 500, null, fs);
3165
3165
  };
3166
3166
 
3167
- isFLOWSTREAMWORKER = W.workerData || process.argv.indexOf('--fork') !== -1;
3168
-
3169
- // Runs the worker
3170
- if (W.workerData) {
3171
- F.dir(F.path.join(__dirname, '../'));
3172
- exports.init(W.workerData);
3173
- }
3174
-
3175
- if (process.argv.includes('--fork')) {
3176
-
3177
- process.once('message', function(msg) {
3178
- if (msg.TYPE === 'init') {
3179
- Parent = process;
3180
- if (!Parent.postMessage)
3181
- Parent.postMessage = process.send;
3182
- F.dir(process.argv[2]);
3183
- exports.init(msg.data);
3184
- }
3185
- });
3186
-
3187
- F.on('error', function(obj) {
3188
- if (obj.error.indexOf('ERR_IPC_CHANNEL_CLOSED') !== -1)
3189
- process.exit(1);
3190
- });
3191
- }
3192
-
3193
3167
  function initrunning() {
3194
3168
 
3195
3169
  if (isrunning)
@@ -3214,4 +3188,34 @@ function initrunning() {
3214
3188
  }
3215
3189
  });
3216
3190
 
3191
+ }
3192
+
3193
+ if (process.argv[1].endsWith('flow-flowstream.js')) {
3194
+
3195
+ isFLOWSTREAMWORKER = W.workerData || process.argv.indexOf('--fork') !== -1;
3196
+
3197
+ // Runs the worker
3198
+ if (W.workerData) {
3199
+ F.dir(F.path.join(__dirname, '../'));
3200
+ exports.init(W.workerData);
3201
+ }
3202
+
3203
+ if (process.argv.includes('--fork')) {
3204
+
3205
+ process.once('message', function(msg) {
3206
+ if (msg.TYPE === 'init') {
3207
+ Parent = process;
3208
+ if (!Parent.postMessage)
3209
+ Parent.postMessage = process.send;
3210
+ F.dir(process.argv[2]);
3211
+ exports.init(msg.data);
3212
+ }
3213
+ });
3214
+
3215
+ F.on('error', function(obj) {
3216
+ if (obj.error.indexOf('ERR_IPC_CHANNEL_CLOSED') !== -1)
3217
+ process.exit(1);
3218
+ });
3219
+ }
3220
+
3217
3221
  }
package/flow.js CHANGED
@@ -8,7 +8,7 @@ const REG_BK = /-bk|_bk/i;
8
8
  var FS = exports;
9
9
 
10
10
  FS.module = require('./flow-flowstream');
11
- FS.version = 1;
11
+ FS.version = 40;
12
12
  FS.db = {};
13
13
  FS.worker = false;
14
14
  FS.instances = {};
package/global.js CHANGED
@@ -17,6 +17,7 @@ global.NPMINSTALL = F.npminstall;
17
17
  global.COMPONENTATOR = F.componentator;
18
18
  global.MERGE = F.merge;
19
19
  global.TOUCH = F.touch;
20
+ global.LOCALIZE = F.localize;
20
21
  global.AUTH = F.auth;
21
22
  global.CLEANUP = F.cleanup;
22
23
  global.NEWDB = F.newdb;
@@ -27,12 +28,14 @@ global.SUCCESS = value => DEF.onSuccess(value);
27
28
  global.MEMORIZE = F.memorize;
28
29
  global.AUDIT = F.audit;
29
30
  global.TRANSLATE = F.translate;
31
+ global.TRANSFORM = F.transform;
32
+ global.NEWTRANSFORM = F.newtransform;
30
33
  global.DATA = new F.TQueryBuilder.Controller(true);
31
34
  global.DB = () => new F.TQueryBuilder.Controller();
32
35
  global.CACHE = F.cache;
33
36
  global.NEWACTION = F.TBuilders.newaction;
34
37
  global.NEWSCHEMA = F.TBuilders.newschema;
35
- global.ACTION = F.TBuilders.action;
38
+ global.ACTION = global.EXEC = F.TBuilders.action;
36
39
  global.TEMPLATE = F.template;
37
40
  global.FILESTORAGE = F.filestorage;
38
41
  global.WEBSOCKETCLIENT = F.websocketclient;
@@ -51,6 +54,7 @@ global.MAIL = F.mail;
51
54
  global.Mail = F.TMail.Mailer;
52
55
  global.RESTBuilder = F.TBuilders.RESTBuilder;
53
56
  global.ErrorBuilder = F.TBuilders.ErrorBuilder;
57
+ global.DOWNLOAD = F.download;
54
58
 
55
59
  global.BLOCKED = function($, limit, expire) {
56
60
 
package/index.js CHANGED
@@ -223,6 +223,7 @@ global.DEF = {};
223
223
  F.path.plugins = path => path ? F.path.$join(F.temporary.directories.plugins, path) : F.temporary.directories.plugins;
224
224
  F.path.directory = (type, path) => path ? F.path.$join(F.temporary.directories[type], path) : F.temporary.directories[type];
225
225
  F.path.tmp = F.path.temp = path => path ? F.path.$join(F.temporary.directories.tmp, path) : F.temporary.directories.tmp;
226
+ 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));
226
227
 
227
228
  F.path.$join = function(directory, path) {
228
229
  var key = '$' + directory;
@@ -611,10 +612,10 @@ F.loadresource = function(name, value) {
611
612
  if (response && (response instanceof Array || typeof(response) === 'object')) {
612
613
  if (response instanceof Array) {
613
614
  for (let item of response)
614
- LOADRESOURCE(item.id || item.key || item.code || item.language, item.value || item.name || item.text || item.body);
615
+ F.loadresource(item.id || item.key || item.code || item.language, item.value || item.name || item.text || item.body);
615
616
  } else {
616
617
  for (let key in response)
617
- LOADRESOURCE(key, response[key]);
618
+ F.loadresource(key, response[key]);
618
619
  }
619
620
  }
620
621
 
@@ -696,8 +697,15 @@ F.resource = function(language, key) {
696
697
  return language === 'default' ? '' : F.resource('default', key);
697
698
  };
698
699
 
700
+ F.localize = function(fn) {
701
+ F.def.onLocalize = fn;
702
+ };
703
+
699
704
  F.auth = function(fn) {
700
- F.def.onAuthorize = fn;
705
+ if (typeof(fn) === 'object')
706
+ F.TBuilders.builtinauth(fn);
707
+ else
708
+ F.def.onAuthorize = fn;
701
709
  };
702
710
 
703
711
  F.load = async function(types, callback) {
@@ -709,6 +717,8 @@ F.load = async function(types, callback) {
709
717
  await F.TBundles.extract();
710
718
  await F.clear(true);
711
719
 
720
+ process.send && process.send('total:ready');
721
+
712
722
  if (typeof(types) === 'string')
713
723
  types = types.split(',').trim();
714
724
 
@@ -851,7 +861,6 @@ F.load = async function(types, callback) {
851
861
  F.stats.compiled = files.length;
852
862
  F.isloaded = true;
853
863
  DEBUG && F.TSourceMap.refresh();
854
- process.send && process.send('total:ready');
855
864
  callback && callback();
856
865
 
857
866
  F.emit('ready');
package/jsonschema.js CHANGED
@@ -312,7 +312,8 @@ function read_def(ref, definitions) {
312
312
  return obj;
313
313
  }
314
314
  }
315
- }
315
+ } else
316
+ return F.jsonschemas[ref];
316
317
  }
317
318
 
318
319
  function check_array(meta, error, value, stop, definitions, path) {
@@ -422,11 +423,12 @@ function check_array(meta, error, value, stop, definitions, path) {
422
423
  if (meta.items.$ref) {
423
424
  var ref = read_def(meta.items.$ref, definitions);
424
425
  if (ref) {
425
- var newerror = [];
426
- tmp = transform(ref, newerror, val);
427
- if (newerror.length) {
428
- for (var err of newerror)
429
- error.push2(ref.$$ID + '.' + err, path, i);
426
+ var newerror = new F.ErrorBuilder();
427
+ tmp = transform(ref, newerror, val, false, currentpath + '[' + i + ']');
428
+ if (newerror.items.length) {
429
+ for (var err of newerror.items) {
430
+ error.push2(err.name, err.path, i);
431
+ }
430
432
  } else if (tmp != null && (!meta.uniqueItems || response.indexOf(tmp) === -1))
431
433
  response.push(tmp);
432
434
  continue;
@@ -574,6 +576,7 @@ function check_object(meta, error, value, response, stop, definitions, path) {
574
576
  }
575
577
  break;
576
578
  case 'object':
579
+
577
580
  if (prop.properties) {
578
581
  tmp = check_object(prop, error, val, null, null, definitions, currentpath);
579
582
  if (tmp != null) {
@@ -586,11 +589,12 @@ function check_object(meta, error, value, response, stop, definitions, path) {
586
589
  if (prop.$ref) {
587
590
  var ref = read_def(prop.$ref, definitions);
588
591
  if (ref) {
589
- var newerror = new ErrorBuilder();
590
- tmp = transform(ref, newerror, val);
592
+ var newerror = new F.ErrorBuilder();
593
+ tmp = transform(ref, newerror, val, false, currentpath);
591
594
  if (newerror.items.length) {
592
- for (var err of newerror.items)
593
- error.push(ref.$$ID + '.' + err, '@');
595
+ for (var err of newerror.items) {
596
+ error.push2(err.name, err.path);
597
+ }
594
598
  } else
595
599
  response[key] = tmp;
596
600
  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
- this.$callback2 = callback;
230
- Mailer.send(smtp, options, this);
231
- return this;
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(smtp, options, callback) {
401
+ Mailer.try = function(options, callback) {
400
402
  var self = this;
401
403
  if (callback)
402
- return self.send(smtp, options, undefined, callback);
404
+ self.send(options, undefined, callback);
403
405
  else
404
- return new Promise((resolve, reject) => self.send(smtp, options, undefined, err => err ? reject(err) : resolve()));
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) {
package/nosql-builder.js CHANGED
@@ -253,7 +253,7 @@ NoSQLQueryBuilder.prototype.sort = function(sort) {
253
253
 
254
254
  if (self.$fields && self.$fields.length) {
255
255
  // Internal hack
256
- var meta = F.temporary.other['sort_' + sort];
256
+ var meta = F.temporary.utils['sort_' + sort];
257
257
  for (var i = 0; i < meta.length; i++) {
258
258
  var sort = meta[i];
259
259
  if (!self.$fieldsall[sort.name]) {
package/nosql.js CHANGED
@@ -93,6 +93,17 @@ NoSQL.prototype.find = function(builder) {
93
93
  return builder;
94
94
  };
95
95
 
96
+ NoSQL.prototype.update = function(builder) {
97
+ var self = this;
98
+ if (builder instanceof NoSQLQueryBuilder)
99
+ builder.db = self;
100
+ else
101
+ builder = new NoSQLQueryBuilder(self);
102
+ self.pending_update.push(builder);
103
+ setImmediate(next_operation, self, 2);
104
+ return builder;
105
+ };
106
+
96
107
  NoSQL.prototype.find2 = function(builder) {
97
108
  var self = this;
98
109
  if (builder instanceof NoSQLQueryBuilder)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "total5",
3
- "version": "0.0.1-7",
3
+ "version": "0.0.1-8",
4
4
  "description": "Total.js framework v5",
5
5
  "main": "index.js",
6
6
  "directories": {
package/routing.js CHANGED
@@ -149,13 +149,16 @@ function Route(url, action, size) {
149
149
 
150
150
  t.priority = 100;
151
151
  t.type = t.method === 'WEBSOCKET' || t.method === 'SOCKET' ? 'websocket' : t.method === 'FILE' ? 'file' : 'route';
152
+ t.partial = t.method === 'PATCH';
152
153
 
153
154
  var endpoint = '';
154
155
 
155
156
  if (t.method === 'API') {
156
157
  t.method = 'POST';
157
- url = url.replace(/(\*|\+|-)?[a-z0-9-_/{}]+/i, function(text) {
158
- endpoint = text.trim().substring(1);
158
+ url = url.replace(/(\*|\+|-|%)?[a-z0-9-_/{}]+/i, function(text) {
159
+ let tmp = text.trim();
160
+ endpoint = tmp.substring(1);
161
+ t.partial = tmp[0] === '%';
159
162
  return text;
160
163
  });
161
164
  }
@@ -199,9 +202,12 @@ function Route(url, action, size) {
199
202
  parent = F.routes.routes.findItem('id', t.id);
200
203
 
201
204
  var apiroute = { auth: t.auth, params: params, actions: t.actions.join(',') };
205
+
206
+ t.apiendpoint = arr[0];
202
207
  if (parent) {
203
208
  parent.api[arr[0]] = apiroute;
204
209
  t.skip = true;
210
+ t.parent = parent;
205
211
  } else {
206
212
  if (!t.api)
207
213
  t.api = {};
@@ -228,6 +234,11 @@ function Route(url, action, size) {
228
234
  if (parent && parent.size < t.size)
229
235
  parent.size = t.size;
230
236
 
237
+ if (typeof(t.action) === 'string') {
238
+ t.view = t.action;
239
+ t.action = null;
240
+ }
241
+
231
242
  if (t.wildcard)
232
243
  t.priority -= 50;
233
244
  }
@@ -261,10 +272,27 @@ Route.prototype.remove = function() {
261
272
  F.routes.files.splice(index);
262
273
  break;
263
274
  default:
264
- index = F.routes.routes.indexOf(self);
265
- if (index !== -1)
266
- F.routes.routes.splice(index);
267
- delete F.routes.api[self.url.join('/')];
275
+ if (self.apiendpoint) {
276
+ if (self.parent) {
277
+ delete self.parent.api[self.apiendpoint];
278
+ if (Object.keys(self.parent.api).length == 0) {
279
+ index = F.routes.routes.indexOf(self.parent);
280
+ if (index !== -1)
281
+ F.routes.routes.splice(index);
282
+ }
283
+ } else {
284
+ delete self.api[self.apiendpoint];
285
+ if (Object.keys(self.api).length == 0) {
286
+ index = F.routes.routes.indexOf(self);
287
+ if (index !== -1)
288
+ F.routes.routes.splice(index);
289
+ }
290
+ }
291
+ } else {
292
+ index = F.routes.routes.indexOf(self);
293
+ if (index !== -1)
294
+ F.routes.routes.splice(index, 1);
295
+ }
268
296
  break;
269
297
  }
270
298
 
@@ -405,7 +433,7 @@ function compareflags(ctrl, routes, auth) {
405
433
  if (route.flags.xhr && !ctrl.xhr)
406
434
  continue;
407
435
 
408
- if (route.flags.upload && ctrl.datatype !== 'upload')
436
+ if (route.flags.upload && ctrl.datatype !== 'multipart')
409
437
  continue;
410
438
 
411
439
  if (route.flags.mobile && !ctrl.mobile)
package/utils.js CHANGED
@@ -3958,6 +3958,12 @@ SP.base64ToBuffer = function() {
3958
3958
  return Buffer.from(self.substring(index), 'base64');
3959
3959
  };
3960
3960
 
3961
+ SP.parseDataURI = function() {
3962
+ var self = this;
3963
+ var index = self.indexOf(';');
3964
+ return index == -1 ? null : { type: self.substring(5, index), buffer: Buffer.from(self.substring(self.indexOf(',', index) + 1), 'base64') };
3965
+ };
3966
+
3961
3967
  SP.base64ContentType = function() {
3962
3968
  var self = this;
3963
3969
  var index = self.indexOf(';');
@@ -5864,7 +5870,7 @@ exports.connect = function(opt, callback) {
5864
5870
  meta.socket1.on('clientError', error);
5865
5871
  };
5866
5872
 
5867
- String.prototype.toJSONSchema = function(name, url) {
5873
+ String.prototype.toJSONSchema = String.prototype.parseSchema = function(name, url) {
5868
5874
 
5869
5875
  var obj = {};
5870
5876
  var p = (url || CONF.url || 'https://schemas.totaljs.com/');
@@ -5906,7 +5912,8 @@ String.prototype.toJSONSchema = function(name, url) {
5906
5912
  required.push(arr[0]);
5907
5913
  }
5908
5914
 
5909
- var type = (arr[1] || 'string').toLowerCase().trim();
5915
+ var type = (arr[1] || 'string').trim();
5916
+ // var type = typename.toLowerCase().trim();
5910
5917
  var size = 0;
5911
5918
  var isarr = type[0] === '[';
5912
5919
  if (isarr)
@@ -5960,20 +5967,11 @@ String.prototype.toJSONSchema = function(name, url) {
5960
5967
  type = type.toLowerCase();
5961
5968
 
5962
5969
  } else if (type[0] === '@') {
5963
-
5964
- // other schema
5965
- var subname = type.substring(1);
5966
- var schema = F.jsonschemas[subname];
5967
-
5968
- if (schema)
5969
- nestedschema = schema;
5970
- else
5971
- throw new Error('Schema "' + subname + '" not found');
5972
-
5970
+ nestedschema = type.substring(1);
5973
5971
  type = 'object';
5974
5972
  }
5975
5973
 
5976
- switch (type) {
5974
+ switch (type.toLowerCase()) {
5977
5975
  case 'string':
5978
5976
  case 'uid':
5979
5977
  case 'guid':
@@ -6053,11 +6051,11 @@ String.prototype.toJSONSchema = function(name, url) {
6053
6051
 
6054
6052
  if (isarr) {
6055
6053
  tmp.type = 'array';
6056
- tmp.items = nestedschema || { type: 'object' };
6057
- } else if (nestedschema)
6058
- tmp = nestedschema;
6059
- else
6054
+ tmp.items = { type: 'object', $ref: nestedschema };
6055
+ } else {
6060
6056
  tmp.type = 'object';
6057
+ tmp.$ref = nestedschema;
6058
+ }
6061
6059
 
6062
6060
  break;
6063
6061
  case 'enum':
package/viewengine.js CHANGED
@@ -796,12 +796,12 @@ View.prototype.import = function() {
796
796
  }
797
797
 
798
798
  if (m.indexOf('+') === -1) {
799
- let key = '/' + m;
799
+ let absolute = m[0] === '/';
800
+ let key = absolute ? m : ('/' + m);
800
801
  if (REG_CHECKCSS.test(m)) {
801
- tmp = '<link rel="stylesheet" href="/' + (F.routes.virtual[key] ? '' : 'css/') + m + '" />';
802
+ tmp = '<link rel="stylesheet" href="' + (absolute ? m : ('/' + (F.routes.virtual[key] ? '' : 'css/') + m)) + '" />';
802
803
  } else {
803
-
804
- tmp = '<scri' + 'pt src="/' + (F.routes.virtual[key] ? '' : 'js/') + m + '"></scr' + 'ipt>';
804
+ tmp = '<scri' + 'pt src="' + (absolute ? m : ('/' + (F.routes.virtual[key] ? '' : 'js/') + m)) + '"></scr' + 'ipt>';
805
805
  }
806
806
  } else {
807
807
  let iscss = REG_CHECKCSS.test(m);
package/websocket.js CHANGED
@@ -836,6 +836,7 @@ function authorize(ctrl) {
836
836
  if (F.def.onAuthorize) {
837
837
  var opt = new F.TBuilders.Options(ctrl);
838
838
  opt.TYPE = 'auth'; // important
839
+ opt.query = ctrl.query;
839
840
  opt.iswebsocket = true;
840
841
  opt.next = opt.callback;
841
842
  opt.$callback = function(err, user) {
@@ -960,8 +961,8 @@ function execute(ctrl) {
960
961
  ctrl.params[param.name] = value;
961
962
  }
962
963
 
963
- if (F.def.onLocale)
964
- ctrl.language = F.def.onLocale(ctrl);
964
+ if (F.def.onLocalize)
965
+ ctrl.language = F.def.onLocalize(ctrl);
965
966
 
966
967
  if (ctrl.route.flags.binary)
967
968
  ctrl.datatype = 'binary';
package/workers.js CHANGED
@@ -49,7 +49,7 @@ function process_thread() {
49
49
  exports.createthread = function(name, data) {
50
50
  if (!name)
51
51
  return process_thread();
52
- var filename = name === '~' ? name.substring(1) : F.path.root('workers/' + name + '.js');
52
+ var filename = name[0] === '~' ? name.substring(1) : F.path.root('workers/' + name + '.js');
53
53
  var worker = new F.Worker.Worker(filename, { workerData: data, cwd: HEADER, argv: ['--worker'] });
54
54
  worker.kill = worker.exit = () => worker.terminate();
55
55
  return worker;
@@ -60,7 +60,7 @@ exports.createfork = function(name) {
60
60
  if (!name)
61
61
  return process_thread();
62
62
 
63
- var filename = name === '~' ? name.substring(1) : F.path.root('workers/' + name + '.js');
63
+ var filename = name[0] === '~' ? name.substring(1) : F.path.root('workers/' + name + '.js');
64
64
  var fork = new F.Child.fork(filename, { cwd: HEADER, argv: ['--worker'] });
65
65
  fork.postMessage = fork.send;
66
66
  fork.terminate = () => fork.kill('SIGTERM');