@dra2020/baseclient 1.0.142 → 1.0.144
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/dist/baseclient.js +62 -33
- package/dist/baseclient.js.map +1 -1
- package/dist/filterexpr/filterexpr.d.ts +1 -0
- package/lib/detail/detail.ts +36 -38
- package/lib/filterexpr/filterexpr.ts +39 -0
- package/package.json +1 -1
package/dist/baseclient.js
CHANGED
|
@@ -1244,12 +1244,17 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
1244
1244
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1245
1245
|
exports.FormatDetail = void 0;
|
|
1246
1246
|
const Util = __importStar(__webpack_require__(/*! ../util/all */ "./lib/util/all.ts"));
|
|
1247
|
+
//import { Util } from '@dra2020/baseclient';
|
|
1247
1248
|
const reIdentifier = /\b[a-zA-Z_$][a-zA-Z0-9_$]*\b/g;
|
|
1249
|
+
const reIdentifierOrString = /([a-zA-Z_$][a-zA-Z0-9_$]*)|(['"])(?:(?=(\\?))\3.)*?\2/g;
|
|
1248
1250
|
const reParam = /^__\d+$/;
|
|
1251
|
+
const reString = /^['"]/;
|
|
1249
1252
|
// Number format: (locale|general|integer|currency).precision
|
|
1250
1253
|
function formatNumber(n, format) {
|
|
1251
1254
|
if (!format)
|
|
1252
1255
|
format = 'locale.0';
|
|
1256
|
+
if (isNaN(n))
|
|
1257
|
+
n = 0;
|
|
1253
1258
|
let parts = format.split('.');
|
|
1254
1259
|
let fmt = parts[0];
|
|
1255
1260
|
let precision = Number(parts[1] || '0');
|
|
@@ -1258,7 +1263,8 @@ function formatNumber(n, format) {
|
|
|
1258
1263
|
}
|
|
1259
1264
|
const DefaultDetailOptions = { numberFormat: 'locale.0' };
|
|
1260
1265
|
class Evaluator {
|
|
1261
|
-
constructor(expr) {
|
|
1266
|
+
constructor(expr, options) {
|
|
1267
|
+
this.options = Util.shallowAssignImmutable(DefaultDetailOptions, options);
|
|
1262
1268
|
this.expr = expr;
|
|
1263
1269
|
this._error = false;
|
|
1264
1270
|
}
|
|
@@ -1277,15 +1283,20 @@ class Evaluator {
|
|
|
1277
1283
|
let values = Object.values(o);
|
|
1278
1284
|
let safeexpr = this.expr;
|
|
1279
1285
|
let safenames = names.map(n => namemap[n]);
|
|
1280
|
-
//
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1286
|
+
// Replace valid identifiers with safe version
|
|
1287
|
+
safeexpr = safeexpr.replace(reIdentifierOrString, (match) => {
|
|
1288
|
+
if (namemap[match])
|
|
1289
|
+
return namemap[match];
|
|
1290
|
+
else if (match === '__format' || reString.test(match))
|
|
1291
|
+
return match;
|
|
1292
|
+
else {
|
|
1293
|
+
this._error = true;
|
|
1294
|
+
return 'invalid';
|
|
1295
|
+
}
|
|
1285
1296
|
});
|
|
1286
1297
|
// Remove any identifiers that aren't the simple parameters to prevent out-of-sandbox execution
|
|
1287
|
-
safeexpr = safeexpr.replace(
|
|
1288
|
-
let valid = reParam.test(match);
|
|
1298
|
+
safeexpr = safeexpr.replace(reIdentifierOrString, (match) => {
|
|
1299
|
+
let valid = reParam.test(match) || match === '__format' || reString.test(match);
|
|
1289
1300
|
if (valid)
|
|
1290
1301
|
return match;
|
|
1291
1302
|
else {
|
|
@@ -1293,12 +1304,15 @@ class Evaluator {
|
|
|
1293
1304
|
return 'invalid';
|
|
1294
1305
|
}
|
|
1295
1306
|
});
|
|
1307
|
+
let __format = (n) => { return formatNumber(n, this.options.numberFormat); };
|
|
1308
|
+
safenames.push('__format');
|
|
1309
|
+
values.push(__format);
|
|
1296
1310
|
// Create a new function that accepts the variables as parameters
|
|
1297
1311
|
// and evaluates the expression
|
|
1298
1312
|
const func = new Function(...safenames, `return ${safeexpr};`);
|
|
1299
1313
|
// Call the function with the variable values
|
|
1300
1314
|
let r = func(...values);
|
|
1301
|
-
return isNaN(r) ? 0 : r;
|
|
1315
|
+
return typeof r === 'string' ? r : ((typeof r !== 'number' || isNaN(r)) ? 0 : r);
|
|
1302
1316
|
}
|
|
1303
1317
|
catch (err) {
|
|
1304
1318
|
this._error = true;
|
|
@@ -1315,28 +1329,8 @@ class FormatDetail {
|
|
|
1315
1329
|
this.pattern = pattern.trim();
|
|
1316
1330
|
let a = reExpr.exec(pattern);
|
|
1317
1331
|
if (a && a.length == 2) {
|
|
1318
|
-
this.items = [];
|
|
1319
1332
|
const expr = a[1];
|
|
1320
|
-
|
|
1321
|
-
let state = 'expr';
|
|
1322
|
-
parse.forEach(subexpr => {
|
|
1323
|
-
if (state === 'expr') {
|
|
1324
|
-
if (subexpr.length) {
|
|
1325
|
-
// Don't allow unsafe actions
|
|
1326
|
-
if (reInvalidChars.test(subexpr))
|
|
1327
|
-
this.items.push({ text: subexpr });
|
|
1328
|
-
else
|
|
1329
|
-
this.items.push({ expr: subexpr });
|
|
1330
|
-
}
|
|
1331
|
-
state = 'text';
|
|
1332
|
-
}
|
|
1333
|
-
else // state === 'text'
|
|
1334
|
-
{
|
|
1335
|
-
if (subexpr.length)
|
|
1336
|
-
this.items.push({ text: subexpr });
|
|
1337
|
-
state = 'expr';
|
|
1338
|
-
}
|
|
1339
|
-
});
|
|
1333
|
+
this.items = [{ expr }];
|
|
1340
1334
|
}
|
|
1341
1335
|
else {
|
|
1342
1336
|
this._error = true;
|
|
@@ -1364,16 +1358,19 @@ class FormatDetail {
|
|
|
1364
1358
|
this._error = true;
|
|
1365
1359
|
return { n: 0, v: '' };
|
|
1366
1360
|
}
|
|
1367
|
-
let n;
|
|
1361
|
+
let n = 0;
|
|
1368
1362
|
let av = this.items.map(di => {
|
|
1369
1363
|
if (di.text)
|
|
1370
1364
|
return di.text;
|
|
1371
1365
|
else {
|
|
1372
|
-
let e = new Evaluator(di.expr);
|
|
1366
|
+
let e = new Evaluator(di.expr, this.options);
|
|
1373
1367
|
n = e.eval(o);
|
|
1374
1368
|
if (!this._error)
|
|
1375
1369
|
this._error = e.error;
|
|
1376
|
-
|
|
1370
|
+
if (typeof n === 'string')
|
|
1371
|
+
return n;
|
|
1372
|
+
else
|
|
1373
|
+
return formatNumber(n, this.options.numberFormat);
|
|
1377
1374
|
}
|
|
1378
1375
|
});
|
|
1379
1376
|
return { n, v: av.join('') };
|
|
@@ -1577,6 +1574,23 @@ function tokIsUnary(tt) {
|
|
|
1577
1574
|
case TokType.And: return false;
|
|
1578
1575
|
case TokType.Or: return false;
|
|
1579
1576
|
case TokType.Colon: return false;
|
|
1577
|
+
case TokType.GreaterThan: return false;
|
|
1578
|
+
case TokType.GreaterThanEqual: return false;
|
|
1579
|
+
case TokType.Equal: return false;
|
|
1580
|
+
case TokType.LessThan: return false;
|
|
1581
|
+
case TokType.LessThanEqual: return false;
|
|
1582
|
+
case TokType.NotEqual: return false;
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
function tokIsArithmetic(tt) {
|
|
1586
|
+
switch (tt) {
|
|
1587
|
+
case TokType.Text: return false;
|
|
1588
|
+
case TokType.OpenParen: return false;
|
|
1589
|
+
case TokType.CloseParen: return false;
|
|
1590
|
+
case TokType.Not: return false;
|
|
1591
|
+
case TokType.And: return false;
|
|
1592
|
+
case TokType.Or: return false;
|
|
1593
|
+
case TokType.Colon: return false;
|
|
1580
1594
|
// Nominally binary, but written as "prop: < 3" so appears as unary operator where test is comparative to prop value
|
|
1581
1595
|
case TokType.GreaterThan: return true;
|
|
1582
1596
|
case TokType.GreaterThanEqual: return true;
|
|
@@ -1709,6 +1723,8 @@ class Parser {
|
|
|
1709
1723
|
this.clauses = clauses;
|
|
1710
1724
|
this.combineParenthetical();
|
|
1711
1725
|
this.convertOpToText();
|
|
1726
|
+
this.combineArithmetic();
|
|
1727
|
+
this.convertOpToText();
|
|
1712
1728
|
this.combineBinary(TokType.Colon);
|
|
1713
1729
|
this.convertOpToText();
|
|
1714
1730
|
this.combineUnary();
|
|
@@ -1785,6 +1801,19 @@ class Parser {
|
|
|
1785
1801
|
}
|
|
1786
1802
|
}
|
|
1787
1803
|
}
|
|
1804
|
+
combineArithmetic() {
|
|
1805
|
+
// go backwards to handle not not
|
|
1806
|
+
for (let i = this.clauses.length - 1; i >= 0; i--) {
|
|
1807
|
+
let c = this.clauses[i];
|
|
1808
|
+
if (tokIsArithmetic(c.op.tt)) {
|
|
1809
|
+
let argclause = (i < this.clauses.length - 1) ? { op: c.op, operand1: this.clauses[i + 1] } : undefined;
|
|
1810
|
+
if (argclause)
|
|
1811
|
+
this.clauses.splice(i, 2, argclause);
|
|
1812
|
+
else
|
|
1813
|
+
this.clauses.splice(i, 1);
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1788
1817
|
combineUnary() {
|
|
1789
1818
|
// go backwards to handle not not
|
|
1790
1819
|
for (let i = this.clauses.length - 1; i >= 0; i--) {
|