@questwork/q-utilities 0.1.8 → 0.1.10

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.
@@ -55,7 +55,7 @@ __webpack_require__.d(__webpack_exports__, {
55
55
  QMeta: () => (/* reexport */ QMeta),
56
56
  Repo: () => (/* reexport */ Repo),
57
57
  Service: () => (/* reexport */ Service),
58
- Template: () => (/* reexport */ Template),
58
+ TemplateCompiler: () => (/* reexport */ TemplateCompiler),
59
59
  UniqueKeyGenerator: () => (/* reexport */ UniqueKeyGenerator),
60
60
  convertString: () => (/* reexport */ convertString),
61
61
  formatDate: () => (/* reexport */ formatDate),
@@ -232,6 +232,16 @@ function getValidation(rule, data, getDataByKey, KeyValueObject) {
232
232
  }
233
233
  return false
234
234
  }
235
+ case '$intervalTimeGt': {
236
+ const now = new Date().getTime()
237
+ const timestamp = new Date(rowValue).getTime()
238
+ return (now - timestamp) > value['$intervalTimeGt']
239
+ }
240
+ case '$intervalTimeLt': {
241
+ const now = new Date().getTime()
242
+ const timestamp = new Date(rowValue).getTime()
243
+ return (now - timestamp) < value['$intervalTimeLt']
244
+ }
235
245
  case '$notInValue': {
236
246
  const result = getDataByKey(value['$notInValue'], data)
237
247
  const _value = Array.isArray(result) ? result : []
@@ -961,11 +971,11 @@ class Repo {
961
971
  reject(new Error('more than one is found'))
962
972
  }
963
973
  })
964
- .catch((err) => {
965
- log({ level: 'warn', output: err.toString() })
966
- throw err
967
- })
968
974
  })
975
+ .catch((err) => {
976
+ log({ level: 'warn', output: err.toString() })
977
+ throw err
978
+ })
969
979
  }
970
980
 
971
981
  saveAll({ docs, systemLog }) {
@@ -979,14 +989,14 @@ class Repo {
979
989
  const promise = typeof this.model.saveAll === 'function'
980
990
  ? this.model.saveAll({ docs })
981
991
  : Promise.all(docs.map(async (doc) => {
982
- if (doc) {
983
- const result = await this.saveOne({ doc })
984
- isNew = result.isNew
985
- const _data = result._data || result.data
986
- return _data[0]
987
- }
988
- return null
989
- }))
992
+ if (doc) {
993
+ const result = await this.saveOne({ doc })
994
+ isNew = result.isNew
995
+ const _data = result._data || result.data
996
+ return _data[0]
997
+ }
998
+ return null
999
+ }))
990
1000
  return promise.then((savedData) => {
991
1001
  if (savedData.length !== 1) isNew = null
992
1002
  const result = {
@@ -1146,10 +1156,31 @@ function makeService({ repo }) {
1146
1156
 
1147
1157
 
1148
1158
 
1149
- ;// ./lib/models/template/constants.js
1159
+ ;// ./lib/models/templateCompiler/templateCompilerException.js
1160
+ const TEMPLATE_COMPILER_EXCEPTION_TYPE = {
1161
+ argumentEmptyException: 'Argument is empty',
1162
+ argumentFormatException: 'Incorrect number or format of argument',
1163
+ invalidFuntionException: 'Function Name is invalid',
1164
+ invalidRegExpException: 'Invalid regular expression',
1165
+ isNotAFunctionException: 'Is not a function',
1166
+ notExistException: 'Key does not exist',
1167
+ resultEmptyException: 'Result is empty',
1168
+ resultMoreThanOneException: 'More than one result'
1169
+ }
1170
+
1171
+ class TemplateCompilerException extends Error {
1172
+ constructor(message) {
1173
+ super(message)
1174
+ this.message = message
1175
+ }
1176
+ }
1177
+
1178
+
1179
+
1180
+ ;// ./lib/models/templateCompiler/constants.js
1150
1181
  const _EMPTY = '_EMPTY'
1151
1182
  const _FN_NAMES = [
1152
- 'get', 'map', 'join', 'concatIf', 'filterOne', 'filterAll', 'formatDate', 'eq', 'neq', 'gt', 'lt', 'gte', 'lte', 'isEmpty', 'isNotEmpty', 'toLowerCase', 'toUpperCase'
1183
+ 'get', 'map', 'join', 'concatIf', 'exec', 'filterOne', 'filterAll', 'formatDate', 'eq', 'neq', 'gt', 'lt', 'gte', 'lte', 'isEmpty', 'isNotEmpty', 'toLowerCase', 'toUpperCase'
1153
1184
  ]
1154
1185
  const _HIDE = '_HIDE'
1155
1186
  const _NOT_EMPTY = '_NOT_EMPTY'
@@ -1159,11 +1190,47 @@ const TAGS_HANDLEBAR = ['{{', '}}']
1159
1190
 
1160
1191
 
1161
1192
 
1162
- ;// ./lib/models/template/helpers/_eq.js
1193
+ ;// ./lib/models/templateCompiler/helpers/_concatIf.js
1194
+
1195
+
1196
+
1197
+
1198
+ function _concatIf(data, args) {
1199
+ if (typeof data !== 'string') {
1200
+ throw new TemplateCompilerException(`_concatIf: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: the data must be string :${data.join(', ')}`)
1201
+ }
1202
+ if (args.length !== 3) {
1203
+ throw new TemplateCompilerException(`_concatIf: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
1204
+ }
1205
+ if (data === null || (typeof data === 'undefined')) {
1206
+ return null
1207
+ }
1208
+ const [condition, success, failover] = args
1209
+ const validConditions = [_EMPTY, _NOT_EMPTY]
1210
+ if (validConditions.includes(condition) || success.length !== 2) {
1211
+ throw new TemplateCompilerException(`concatIf: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentEmptyException}: ${condition}, ${success}`)
1212
+ }
1213
+ if (data === '' && failover.includes(_HIDE)) {
1214
+ return ''
1215
+ }
1216
+ if (data !== '' && (data !== null || data !== undefined) && failover.includes(_HIDE)) {
1217
+ return `${success[0]}${data}${success[success.length - 1]}`
1218
+ }
1219
+ return failover
1220
+ }
1221
+
1222
+
1223
+
1224
+ ;// ./lib/models/templateCompiler/helpers/_eq.js
1225
+
1226
+
1163
1227
 
1164
1228
 
1165
1229
  function _eq(data, args) {
1166
- if (data === null || (typeof data === 'undefined') || args.length !== 3) {
1230
+ if (args.length !== 3) {
1231
+ throw new TemplateCompilerException(`eq: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
1232
+ }
1233
+ if (data === null || (typeof data === 'undefined')) {
1167
1234
  return null
1168
1235
  }
1169
1236
  if (args.includes(_SELF)) {
@@ -1177,107 +1244,264 @@ function _eq(data, args) {
1177
1244
 
1178
1245
 
1179
1246
 
1180
- ;// ./lib/models/template/templateException.js
1181
- const TEMPLATE_EXCEPTION_TYPE = {
1182
- argumentEmptyException: 'Argument is empty',
1183
- argumentFormatException: 'Incorrect number or format of argument',
1184
- invalidFuntionException: 'Function Name is invalid',
1185
- invalidRegExpException: 'Invalid regular expression',
1186
- isNotAFunctionException: 'Is not a function',
1187
- notExistException: 'Key does not exist',
1188
- resultEmptyException: 'Result is empty',
1189
- resultMoreThanOneException: 'More than one result'
1190
- }
1191
-
1192
- class TemplateException extends Error {
1193
- constructor(message) {
1194
- super(message)
1195
- this.message = message
1247
+ ;// ./lib/models/templateCompiler/helpers/_exec.js
1248
+ function _exec(data, args) {
1249
+ try {
1250
+ const [methodName, ..._args] = args
1251
+ return data[methodName](..._args)
1252
+ } catch (e) {
1253
+ throw e
1196
1254
  }
1197
1255
  }
1198
1256
 
1199
1257
 
1200
1258
 
1201
- ;// ./lib/models/template/helpers/_filterAll.js
1259
+ ;// ./lib/models/templateCompiler/helpers/_filterAll.js
1260
+
1202
1261
 
1203
1262
 
1204
- const _filterAll_DELIMITER = '~~~'
1263
+ // const DELIMITER = '~~~'
1205
1264
 
1206
1265
  function _filterAll(data, args) {
1207
- if (!Array.isArray(data) || data.length === 0 || !Array.isArray(args) || args.length === 0) {
1266
+ try {
1267
+ if (!Array.isArray(args) || args.length === 0) {
1268
+ throw new TemplateCompilerException(TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentEmptyException)
1269
+ }
1270
+ if (!Array.isArray(data) || data.length === 0) {
1271
+ return []
1272
+ }
1273
+ if (typeof data[0] === 'object') {
1274
+ return _existObject(data, args)
1275
+ }
1276
+ if (typeof data[0] === 'string' || typeof data[0] === 'number') {
1277
+ return _exist(data, args)
1278
+ }
1208
1279
  return []
1280
+ } catch (e) {
1281
+ throw e
1209
1282
  }
1283
+ }
1210
1284
 
1211
- if (typeof data[0] === 'object') {
1212
- return _existObject(data, args)
1213
- }
1285
+ function _exist(data, args) {
1286
+ const _args = args.flat()
1287
+ return data.filter((e) => _args.some((arg) => _performOperation(arg, e)))
1288
+ }
1214
1289
 
1215
- if (typeof data[0] === 'string' || typeof data[0] === 'number') {
1216
- return _exist(data, args)
1290
+ function _existObject(data, args) {
1291
+ if (args.length === 1) {
1292
+ const arg = args[0]
1293
+ return data.filter((e) => {
1294
+ if (arg.includes('.')) {
1295
+ return getValueByKeys(arg.split('.'), e)
1296
+ }
1297
+ return Object.prototype.hasOwnProperty.call(e, arg)
1298
+ })
1217
1299
  }
1218
1300
 
1219
- return []
1220
- }
1301
+ if (args.length > 2) {
1302
+ let res = data
1303
+ for (let i = 0; i < args.length; i += 2) {
1304
+ const group = [args[i], args[i + 1]]
1305
+ res = _existObject(res, group)
1306
+ }
1307
+ return res
1308
+ }
1221
1309
 
1222
- function _exist(data, args) {
1223
- const _str = `${_filterAll_DELIMITER}${args.join(_filterAll_DELIMITER)}${_filterAll_DELIMITER}`
1310
+ const [key, ..._argsArr] = args
1311
+ const _args = _argsArr.flat()
1224
1312
  return data.filter((e) => {
1225
- return _str.includes(`${_filterAll_DELIMITER}${e}${_filterAll_DELIMITER}`) && args.includes(e)
1313
+ const value = key.includes('.') ? getValueByKeys(key.split('.'), e) : e[key]
1314
+ return _args.some((arg) => _performOperation(arg, value))
1226
1315
  })
1227
1316
  }
1228
1317
 
1229
- function _existObject(data, args) {
1230
- if (args.length !== 2) {
1231
- return []
1318
+ function _performOperation(arg, value) {
1319
+ // the arg is undefined
1320
+ if (arg === undefined && value === undefined) return true
1321
+
1322
+ // the arg is null
1323
+ if (arg === null && value === null) return true
1324
+
1325
+ // the arg is boolean
1326
+ if (typeof arg === 'boolean') {
1327
+ return arg === value
1328
+ }
1329
+
1330
+ // the arg is blank or *: Blank => Empty, * => Not Empty
1331
+ if (arg === '' || arg === '*') {
1332
+ // null and undefined are not included in either case
1333
+ if (value === null || value === undefined) {
1334
+ return false
1335
+ }
1336
+ if (typeof value === 'string') {
1337
+ return arg === '' ? value === '' : value !== ''
1338
+ }
1339
+ if (Array.isArray(value)) {
1340
+ return arg === '' ? value.length === 0 : value.length !== 0
1341
+ }
1342
+ return arg !== ''
1343
+ }
1344
+
1345
+ // the arg is alphabetic or number
1346
+ if (_isPureStringOrNumber(arg)) {
1347
+ return arg === value
1348
+ }
1349
+
1350
+ // the arg is array of [] or [*]: [] => Empty, [*] => Not Empty
1351
+ if (arg.startsWith('[') && arg.endsWith(']')) {
1352
+ if (arg === '[]') {
1353
+ return Array.isArray(value) && value.length === 0
1354
+ }
1355
+ if (arg === '[*]') {
1356
+ return Array.isArray(value) && value.length !== 0
1357
+ }
1358
+ return false
1359
+ }
1360
+
1361
+ // the arg is 'operator + string | number'
1362
+ const { operator, value: argValue } = _splitOperator(arg)
1363
+ if (!operator || (argValue !== 0 && !argValue)) {
1364
+ return false
1365
+ }
1366
+ switch (operator) {
1367
+ case '>':
1368
+ return value > argValue
1369
+ case '<':
1370
+ return value < argValue
1371
+ case '!=':
1372
+ return value !== argValue
1373
+ case '>=':
1374
+ return value >= argValue
1375
+ case '<=':
1376
+ return value <= argValue
1377
+ default:
1378
+ return false
1232
1379
  }
1233
- const [key, _args] = args
1234
- return data.filter((e) => {
1235
- return _args.includes(e[key])
1236
- })
1237
1380
  }
1238
1381
 
1382
+ function _isPureStringOrNumber(input) {
1383
+ if (typeof input === 'string') {
1384
+ if (input.startsWith('[') && input.endsWith(']')) {
1385
+ return false
1386
+ }
1387
+ if (/!=|>=|<=|>|</.test(input)) {
1388
+ return false
1389
+ }
1390
+ return true
1391
+ }
1392
+ return !Number.isNaN(input)
1393
+ }
1239
1394
 
1395
+ function _splitOperator(str) {
1396
+ const operators = ['!=', '>=', '<=', '>', '<']
1240
1397
 
1241
- ;// ./lib/models/template/helpers/_filterOne.js
1398
+ const matchedOp = operators.find((op) => str.startsWith(op))
1399
+ if (!matchedOp) return { operator: null, value: null }
1400
+
1401
+ const remaining = str.slice(matchedOp.length)
1402
+
1403
+ // '>Primary' or '<Primary' is invalid
1404
+ if (/^[a-zA-Z]*$/.test(remaining) && matchedOp !== '!=') {
1405
+ return { operator: null, value: null }
1406
+ }
1407
+
1408
+ // if it is a number it is converted to a number
1409
+ const value = (!Number.isNaN(parseFloat(remaining)) && !Number.isNaN(remaining)) ? Number(remaining) : remaining
1410
+
1411
+ return {
1412
+ operator: matchedOp,
1413
+ value
1414
+ }
1415
+ }
1416
+
1417
+
1418
+
1419
+ ;// ./lib/models/templateCompiler/helpers/_filterOne.js
1242
1420
 
1243
1421
 
1244
1422
 
1245
1423
  function _filterOne(data, args) {
1246
- const list = _filterAll(data, args)
1247
- if (list.length > 0) {
1248
- return list[0]
1424
+ try {
1425
+ const list = _filterAll(data, args)
1426
+ if (list.length === 1) {
1427
+ return list[0]
1428
+ }
1429
+ if (list.length === 0) {
1430
+ return null
1431
+ }
1432
+ throw new TemplateCompilerException(TEMPLATE_COMPILER_EXCEPTION_TYPE.resultMoreThanOneException)
1433
+ } catch (e) {
1434
+ throw e
1249
1435
  }
1250
- return null
1251
1436
  }
1252
1437
 
1253
1438
 
1254
1439
 
1255
- ;// ./lib/models/template/helpers/_get.js
1440
+ ;// ./lib/models/templateCompiler/helpers/_formatDate.js
1256
1441
 
1257
1442
 
1258
- function _get(data, key, failover = null) {
1259
- if (data === null || (typeof data === 'undefined') || key === '') {
1443
+ function _formatDate(timestamp, format) {
1444
+ if (format.length === 0) {
1445
+ throw new TemplateCompilerException(`_formateDate: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: format parts must be not empty array`)
1446
+ }
1447
+
1448
+ if (timestamp === null || timestamp === undefined) {
1260
1449
  return null
1261
- // throw new TemplateException(TEMPLATE_EXCEPTION_TYPE.argumentEmptyException)
1262
1450
  }
1263
1451
 
1264
- if (key.includes('.')) {
1265
- const parts = key.split('.')
1266
- if (parts.length > 1) {
1267
- const first = parts.shift()
1268
- const remainingKey = parts.join('.')
1269
- if (typeof data[first] !== 'undefined') {
1270
- return _get(data[first], remainingKey, failover)
1271
- }
1272
- return _handleFailover(key, failover)
1273
- }
1452
+ const date = new Date(timestamp)
1453
+
1454
+ const partsMap = {
1455
+ yyyy: String(date.getFullYear()),
1456
+ mm: String(date.getMonth() + 1).padStart(2, '0'),
1457
+ dd: String(date.getDate()).padStart(2, '0')
1274
1458
  }
1275
1459
 
1276
- if (typeof data[key] !== 'undefined') {
1277
- return data[key]
1460
+ // Check for invalid format tokens
1461
+ const validTokens = ['yyyy', 'mm', 'dd']
1462
+ const invalidTokens = format.filter((part) => part.length > 1 && !validTokens.includes(part))
1463
+
1464
+ if (invalidTokens.length > 0) {
1465
+ throw new TemplateCompilerException(
1466
+ `_formateDate: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: the format type is not valid: ${format.join(', ')}`
1467
+ )
1278
1468
  }
1279
1469
 
1280
- return _handleFailover(key, failover)
1470
+ // Build the formatted string using reduce
1471
+ return format.reduce((result, part) => result + (partsMap[part] || part), '')
1472
+ }
1473
+
1474
+
1475
+
1476
+ ;// ./lib/models/templateCompiler/helpers/_get.js
1477
+
1478
+
1479
+ function _get(data, key, failover = null) {
1480
+ try {
1481
+ if (key === null || (typeof key === 'undefined') || key === '') {
1482
+ throw new TemplateCompilerException(TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentEmptyException)
1483
+ }
1484
+ if (data === null) {
1485
+ return null
1486
+ }
1487
+ if (key.includes('.')) {
1488
+ const parts = key.split('.')
1489
+ if (parts.length > 1) {
1490
+ const first = parts.shift()
1491
+ const remainingKey = parts.join('.')
1492
+ if (typeof data[first] !== 'undefined') {
1493
+ return _get(data[first], remainingKey, failover)
1494
+ }
1495
+ return _handleFailover(key, failover)
1496
+ }
1497
+ }
1498
+ if (typeof data[key] !== 'undefined') {
1499
+ return data[key]
1500
+ }
1501
+ return _handleFailover(key, failover)
1502
+ } catch (e) {
1503
+ throw e
1504
+ }
1281
1505
  }
1282
1506
 
1283
1507
  function _handleFailover(key, failover) {
@@ -1285,108 +1509,396 @@ function _handleFailover(key, failover) {
1285
1509
  return failover
1286
1510
  }
1287
1511
  return null
1288
- // throw new TemplateException(`Key "${key}" does not exist and no failover`)
1512
+ // throw new TemplateCompilerException(`Key "${key}" does not exist and no failover`)
1513
+ }
1514
+
1515
+
1516
+
1517
+ ;// ./lib/models/templateCompiler/helpers/_gt.js
1518
+
1519
+
1520
+
1521
+
1522
+ function _gt(data, args) {
1523
+ if (args.length !== 3) {
1524
+ throw new TemplateCompilerException(`_gt: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
1525
+ }
1526
+ if (data === null || (typeof data === 'undefined')) {
1527
+ return null
1528
+ }
1529
+ if (args.includes(_SELF)) {
1530
+ args = args.map((arg) => {
1531
+ return (arg === _SELF) ? data : arg
1532
+ })
1533
+ }
1534
+ const expected = args[0]
1535
+ return data > expected ? args[1] : args[2]
1536
+ }
1537
+
1538
+
1539
+
1540
+ ;// ./lib/models/templateCompiler/helpers/_gte.js
1541
+
1542
+
1543
+
1544
+
1545
+ function _gte(data, args) {
1546
+ if (args.length !== 3) {
1547
+ throw new TemplateCompilerException(`_gte: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
1548
+ }
1549
+ if (data === null || (typeof data === 'undefined')) {
1550
+ return null
1551
+ }
1552
+ if (args.includes(_SELF)) {
1553
+ args = args.map((arg) => {
1554
+ return (arg === _SELF) ? data : arg
1555
+ })
1556
+ }
1557
+ const expected = args[0]
1558
+ return data >= expected ? args[1] : args[2]
1559
+ }
1560
+
1561
+
1562
+
1563
+ ;// ./lib/models/templateCompiler/helpers/_isEmpty.js
1564
+
1565
+
1566
+
1567
+
1568
+ function _isEmpty(data, args) {
1569
+ if (args.length !== 2) {
1570
+ throw new TemplateCompilerException(`_isEmpty: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
1571
+ }
1572
+ // if (data === null || (typeof data === 'undefined')) {
1573
+ // return null
1574
+ // }
1575
+ if (args.includes(_SELF)) {
1576
+ args = args.map((arg) => {
1577
+ return (arg === _SELF) ? data : arg
1578
+ })
1579
+ }
1580
+ if (data !== null && typeof data === 'object' && Object.keys(data).length === 0) {
1581
+ return args[0]
1582
+ }
1583
+ return (data === '' || data === null || data === undefined || data.length === 0) ? args[0] : args[1]
1289
1584
  }
1290
1585
 
1291
1586
 
1292
1587
 
1293
- ;// ./lib/models/template/helpers/_join.js
1588
+ ;// ./lib/models/templateCompiler/helpers/_isNotEmpty.js
1589
+
1590
+
1591
+
1592
+
1593
+ function _isNotEmpty(data, args) {
1594
+ if (args.length !== 2) {
1595
+ throw new TemplateCompilerException(`_isNotEmpty: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
1596
+ }
1597
+ // if (data === null || (typeof data === 'undefined')) {
1598
+ // return null
1599
+ // }
1600
+ if (args.includes(_SELF)) {
1601
+ args = args.map((arg) => {
1602
+ return (arg === _SELF) ? data : arg
1603
+ })
1604
+ }
1605
+ if (data !== null && typeof data === 'object' && Object.keys(data).length === 0) {
1606
+ return args[1]
1607
+ }
1608
+ if (Array.isArray(data) && data.length === 0) {
1609
+ return args[1]
1610
+ }
1611
+ if (typeof data === 'string' && data === '') {
1612
+ return args[1]
1613
+ }
1614
+ if (data === null || data === undefined) {
1615
+ return args[1]
1616
+ }
1617
+ return args[0]
1618
+ }
1619
+
1620
+
1621
+ ;// ./lib/models/templateCompiler/helpers/_join.js
1294
1622
  function _join(data, delimiter) {
1295
- return data.join(delimiter)
1623
+ try {
1624
+ if (data.length === 0) return ''
1625
+ if (data.length === 1) return _stringifyObject(data[0])
1626
+ return data.map((item) => _stringifyObject(item)).join(delimiter)
1627
+ } catch (e) {
1628
+ throw e
1629
+ }
1296
1630
  }
1297
1631
 
1632
+ function _stringifyObject(obj) {
1633
+ return JSON.stringify(obj).replace(/"([^"]+)":/g, '$1: ').replace(/"([^"]+)"/g, '$1').replace(/,/g, ', ')
1634
+ }
1298
1635
 
1299
1636
 
1300
- ;// ./lib/models/template/helpers/_map.js
1301
1637
 
1638
+ ;// ./lib/models/templateCompiler/helpers/_lt.js
1302
1639
 
1303
1640
 
1304
- function _map(data, args) {
1305
- if (data === null || (typeof data === 'undefined') || args.length === 0) {
1641
+
1642
+
1643
+ function _lt(data, args) {
1644
+ if (args.length !== 3) {
1645
+ throw new TemplateCompilerException(`_lt: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
1646
+ }
1647
+ if (data === null || (typeof data === 'undefined')) {
1306
1648
  return null
1307
- // throw new TemplateException(TEMPLATE_EXCEPTION_TYPE.argumentEmptyException)
1308
1649
  }
1650
+ if (args.includes(_SELF)) {
1651
+ args = args.map((arg) => {
1652
+ return (arg === _SELF) ? data : arg
1653
+ })
1654
+ }
1655
+ const expected = args[0]
1656
+ return data < expected ? args[1] : args[2]
1657
+ }
1309
1658
 
1310
- const result = data.reduce((acc, item) => {
1311
- if (args.length === 1 && Array.isArray(args[0])) {
1312
- args = args[0]
1313
- acc.hasFormat = true
1659
+
1660
+
1661
+ ;// ./lib/models/templateCompiler/helpers/_lte.js
1662
+
1663
+
1664
+
1665
+
1666
+ function _lte(data, args) {
1667
+ if (args.length !== 3) {
1668
+ throw new TemplateCompilerException(`_lte: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
1669
+ }
1670
+ if (data === null || (typeof data === 'undefined')) {
1671
+ return null
1672
+ }
1673
+ if (args.includes(_SELF)) {
1674
+ args = args.map((arg) => {
1675
+ return (arg === _SELF) ? data : arg
1676
+ })
1677
+ }
1678
+ const expected = args[0]
1679
+ return data <= expected ? args[1] : args[2]
1680
+ }
1681
+
1682
+
1683
+
1684
+ ;// ./lib/models/templateCompiler/helpers/_map.js
1685
+
1686
+
1687
+
1688
+ function _map(data, args) {
1689
+ try {
1690
+ if (args.length === 0) {
1691
+ throw new TemplateCompilerException(TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentEmptyException)
1314
1692
  }
1315
- const list = args.map((key) => {
1316
- if (key.includes('.')) {
1317
- const parts = key.split('.')
1318
- const first = parts[0]
1319
- parts.shift()
1320
- const remainingKey = parts.join('.')
1321
- return _get(item[first], remainingKey)
1693
+ if (data === null || (typeof data === 'undefined')) {
1694
+ return null
1695
+ }
1696
+
1697
+ const result = data.reduce((acc, item) => {
1698
+ if (args.length === 1 && Array.isArray(args[0])) {
1699
+ args = args[0]
1700
+ acc.hasFormat = true
1322
1701
  }
1323
- if (typeof item[key] !== 'undefined') {
1324
- return item[key]
1702
+ const list = args.map((key) => {
1703
+ if (key.includes('.')) {
1704
+ const parts = key.split('.')
1705
+ const first = parts[0]
1706
+ parts.shift()
1707
+ const remainingKey = parts.join('.')
1708
+ return _get(item[first], remainingKey)
1709
+ }
1710
+ if (typeof item[key] !== 'undefined') {
1711
+ return item[key]
1712
+ }
1713
+ return null
1714
+ })
1715
+ if (acc.hasFormat) {
1716
+ acc.content.push(list)
1717
+ } else {
1718
+ acc.content = acc.content.concat(list)
1325
1719
  }
1326
- return null
1327
- // throw new TemplateException('Key "$key" does not exist')
1720
+ return acc
1721
+ }, {
1722
+ content: [],
1723
+ hasFormat: false
1328
1724
  })
1329
- if (acc.hasFormat) {
1330
- acc.content.push(list)
1331
- } else {
1332
- acc.content = acc.content.concat(list)
1333
- }
1334
- return acc
1335
- }, {
1336
- content: [],
1337
- hasFormat: false
1338
- })
1339
- return result.content
1725
+ return result.content
1726
+ } catch (e) {
1727
+ throw e
1728
+ }
1340
1729
  }
1341
1730
 
1342
1731
 
1343
1732
 
1344
- ;// ./lib/models/template/helpers/index.js
1733
+ ;// ./lib/models/templateCompiler/helpers/_neq.js
1345
1734
 
1346
1735
 
1347
1736
 
1348
1737
 
1738
+ function _neq(data, args) {
1739
+ if (args.length !== 3) {
1740
+ throw new TemplateCompilerException(`_neq: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
1741
+ }
1742
+ if (data === null || (typeof data === 'undefined')) {
1743
+ return null
1744
+ }
1745
+ if (args.includes(_SELF)) {
1746
+ args = args.map((arg) => {
1747
+ return (arg === _SELF) ? data : arg
1748
+ })
1749
+ }
1750
+ const expected = args[0]
1751
+ return data !== expected ? args[1] : args[2]
1752
+ }
1753
+
1754
+
1755
+
1756
+ ;// ./lib/models/templateCompiler/helpers/_toLowerCase.js
1757
+
1758
+
1759
+ function _toLowerCase(data, args) {
1760
+ if (args !== undefined) {
1761
+ throw new TemplateCompilerException(`_toLowerCase: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
1762
+ }
1763
+ if (data === null || (typeof data === 'undefined') || typeof data !== 'string') {
1764
+ return null
1765
+ }
1766
+ return String(data).toLowerCase()
1767
+ }
1768
+
1769
+
1770
+
1771
+ ;// ./lib/models/templateCompiler/helpers/_toUpperCase.js
1772
+
1773
+
1774
+ function _toUpperCase(data, args) {
1775
+ if (typeof data !== 'string') {
1776
+ throw new TemplateCompilerException(`_toUpperCase: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: the data must be string: ${data}`)
1777
+ }
1778
+ if (args !== undefined) {
1779
+ throw new TemplateCompilerException(`_toUpperCase: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: the argument must be empty: ${args.join(', ')}`)
1780
+ }
1781
+ if (data === null || (typeof data === 'undefined') || typeof data !== 'string') {
1782
+ return null
1783
+ }
1784
+ return String(data).toUpperCase()
1785
+ }
1786
+
1349
1787
 
1350
1788
 
1789
+ ;// ./lib/models/templateCompiler/helpers/index.js
1351
1790
 
1352
1791
 
1353
1792
 
1354
- ;// ./lib/models/template/template.js
1355
1793
 
1356
1794
 
1357
1795
 
1358
1796
 
1359
- class Template {
1360
- constructor({ data }) {
1797
+
1798
+
1799
+
1800
+
1801
+
1802
+
1803
+
1804
+
1805
+
1806
+
1807
+
1808
+
1809
+
1810
+
1811
+ ;// ./lib/models/templateCompiler/templateCompiler.js
1812
+
1813
+
1814
+
1815
+
1816
+ class TemplateCompiler {
1817
+ constructor(data) {
1361
1818
  this.data = data
1362
1819
  }
1820
+ static init(options) {
1821
+ return new this(options)
1822
+ }
1823
+ static initFromArray(arr = []) {
1824
+ if (Array.isArray(arr)) {
1825
+ return arr.map((a) => this.init(a))
1826
+ }
1827
+ return []
1828
+ }
1829
+ static initOnlyValidFromArray(arr = []) {
1830
+ return this.initFromArray(arr).filter((i) => i)
1831
+ }
1832
+ static concatIf(data, args) {
1833
+ return _concatIf(data, args)
1834
+ }
1363
1835
  static eq(data, args) {
1364
1836
  return _eq(data, args)
1365
1837
  }
1838
+
1839
+ static filterAll(data, args) {
1840
+ return _filterAll(data, args)
1841
+ }
1842
+
1843
+ static formatDate(data, args) {
1844
+ return _formatDate(data, args)
1845
+ }
1846
+
1366
1847
  static get(data, key, failover = null) {
1367
1848
  return _get(data, key, failover)
1368
1849
  }
1850
+ static gt(data, args) {
1851
+ return _gt(data, args)
1852
+ }
1853
+ static gte(data, args) {
1854
+ return _gte(data, args)
1855
+ }
1856
+ static isEmpty(data, args) {
1857
+ return _isEmpty(data, args)
1858
+ }
1859
+ static isNotEmpty(data, args) {
1860
+ return _isNotEmpty(data, args)
1861
+ }
1369
1862
  static join(data, separator = '') {
1370
1863
  return _join(data, separator)
1371
1864
  }
1865
+ static lt(data, args) {
1866
+ return _lt(data, args)
1867
+ }
1868
+ static lte(data, args) {
1869
+ return _lte(data, args)
1870
+ }
1372
1871
  static map(data, args = []) {
1373
1872
  return _map(data, args)
1374
1873
  }
1874
+ static neq(data, args) {
1875
+ return _neq(data, args)
1876
+ }
1877
+ static toLowerCase(data, args) {
1878
+ return _toLowerCase(data, args)
1879
+ }
1880
+ static toUpperCase(data, args) {
1881
+ return _toUpperCase(data, args)
1882
+ }
1375
1883
  static parseFunction(expression) {
1376
1884
  return _parseFunction(expression, _FN_NAMES)
1377
1885
  }
1378
1886
 
1379
1887
  pipe(expression = '') {
1380
- this.delimiters = expression.substring(0,2) === '<%' ? TAGS_EJS : TAGS_HANDLEBAR
1888
+ this.delimiters = expression.substring(0, 2) === '{{' ? TAGS_HANDLEBAR : TAGS_EJS
1381
1889
  const regex = new RegExp(`${this.delimiters[0]}\\s(.*?)\\s${this.delimiters[1]}`)
1382
1890
  const match = expression.match(regex)
1383
1891
  if (match !== null) {
1384
- const functionList = _parseFunction(match[1], _FN_NAMES)
1385
- return functionList.reduce((acc, fn) => {
1386
- return _callFunction(acc, fn.name, fn.args)
1387
- }, this.data)
1892
+ try {
1893
+ const functionList = _parseFunction(match[1], _FN_NAMES)
1894
+ return functionList.reduce((acc, fn) => {
1895
+ return _callFunction(acc, fn.name, fn.args)
1896
+ }, this.data)
1897
+ } catch (e) {
1898
+ throw new TemplateCompilerException(`TemplateCompiler engine error: ${e.message}`)
1899
+ }
1388
1900
  }
1389
- throw new TemplateException(TEMPLATE_EXCEPTION_TYPE.invalu)
1901
+ throw new TemplateCompilerException(`TemplateCompiler engine error: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.invalidRegExpException}`)
1390
1902
  }
1391
1903
  }
1392
1904
 
@@ -1410,7 +1922,7 @@ function _parseFunction(expression, existFunctionNames) {
1410
1922
  args: paramList
1411
1923
  })
1412
1924
  } else {
1413
- throw new TemplateException(`${functionName} is not a valid function`)
1925
+ throw new TemplateCompilerException(`${functionName} is not a valid function`)
1414
1926
  }
1415
1927
  }
1416
1928
  return acc
@@ -1454,12 +1966,18 @@ function _parseSinglePart(input) {
1454
1966
  return input.substring(1, input.length - 1)
1455
1967
  }
1456
1968
 
1969
+ const _input = _toBasicType(input)
1970
+
1971
+ if (typeof _input !== 'string') {
1972
+ return _input
1973
+ }
1974
+
1457
1975
  // 如果是一个列表形式(例如 ["p", "d"] 或 [p, d])
1458
- if (input.startsWith('[') && input.endsWith(']')) {
1459
- const listContent = input.substring(1, input.length - 1).trim()
1976
+ if (_input.startsWith('[') && _input.endsWith(']')) {
1977
+ const listContent = _input.substring(1, _input.length - 1).trim()
1460
1978
  if (listContent !== '') {
1461
1979
  return listContent.split(',').map((item) => {
1462
- return item.trim().replaceAll('"', '') // 去除可能的双引号
1980
+ return _toBasicType(item.trim())
1463
1981
  })
1464
1982
  }
1465
1983
  return []
@@ -1469,66 +1987,86 @@ function _parseSinglePart(input) {
1469
1987
  return input
1470
1988
  }
1471
1989
 
1990
+ function _toBasicType(input) {
1991
+ if (input.startsWith('"') && input.endsWith('"')) {
1992
+ // 去掉双引号,返回
1993
+ return input.substring(1, input.length - 1)
1994
+ }
1995
+ if (input === 'true') {
1996
+ return true
1997
+ }
1998
+ if (input === 'false') {
1999
+ return false
2000
+ }
2001
+ if (input === 'undefined') {
2002
+ return undefined
2003
+ }
2004
+ if (input === 'null') {
2005
+ return null
2006
+ }
2007
+ if (!Number.isNaN(input) && !Number.isNaN(Number.parseFloat(input))) {
2008
+ return Number(input)
2009
+ }
2010
+ return input
2011
+ }
2012
+
1472
2013
  function _callFunction(data, functionName, parameters) {
1473
- let failover
1474
- switch (functionName) {
1475
- case 'get':
1476
- if (parameters.length > 2) {
1477
- throw new TemplateException(TEMPLATE_EXCEPTION_TYPE.argumentFormatException)
1478
- }
1479
- if (parameters.length === 2) {
1480
- failover = parameters[parameters.length - 1]
1481
- }
1482
- return _get(data, parameters[0], failover)
1483
- case 'map':
1484
- return _map(data, parameters)
1485
- case 'join':
1486
- return _join(data, parameters[0])
1487
- // case 'concatIf':
1488
- // if (parameters.length != 3) {
1489
- // throw const TemplateException(TemplateExceptionType.argumentFormatException);
1490
- // }
1491
- // var condition = parameters.first;
1492
- // var success = parameters[1];
1493
- // var failover = parameters[2];
1494
- // return _concatIf(data, condition, success, failover);
1495
- case 'filterOne':
1496
- return _filterOne(data, parameters)
1497
- case 'filterAll':
1498
- return _filterAll(data, parameters)
1499
- // case 'formatDate':
1500
- // if (parameters is List<String>) {
1501
- // return _formatDate(data, parameters);
1502
- // }
1503
- // throw const TemplateException(TemplateExceptionType.argumentFormatException);
1504
- case 'eq':
1505
- return _eq(data, parameters)
1506
- // case 'neq':
1507
- // return _neq(data, parameters);
1508
- // case 'gt':
1509
- // return _gt(data, parameters);
1510
- // case 'gte':
1511
- // return _gte(data, parameters);
1512
- // case 'lt':
1513
- // return _lt(data, parameters);
1514
- // case 'lte':
1515
- // return _lte(data, parameters);
1516
- // case 'isEmpty':
1517
- // return _isEmpty(data, parameters);
1518
- // case 'isNotEmpty':
1519
- // return _isNotEmpty(data, parameters);
1520
- // case 'toLowerCase':
1521
- // return _toLowerCase(data);
1522
- // case 'toUpperCase':
1523
- // return _toUpperCase(data);
1524
- default:
1525
- throw new Error(`${functionName} is not a valid function`)
2014
+ try {
2015
+ let failover
2016
+ switch (functionName) {
2017
+ case 'exec':
2018
+ return _exec(data, parameters)
2019
+ case 'get':
2020
+ if (parameters.length > 2) {
2021
+ throw new TemplateCompilerException(TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException)
2022
+ }
2023
+ if (parameters.length === 2) {
2024
+ failover = parameters[parameters.length - 1]
2025
+ }
2026
+ return _get(data, parameters[0], failover)
2027
+ case 'join':
2028
+ return _join(data, parameters[0])
2029
+ case 'map':
2030
+ return _map(data, parameters)
2031
+ case 'concatIf':
2032
+ return _concatIf(data, parameters)
2033
+ case 'filterOne':
2034
+ return _filterOne(data, parameters)
2035
+ case 'filterAll':
2036
+ return _filterAll(data, parameters)
2037
+ case 'formatDate':
2038
+ return _formatDate(data, parameters)
2039
+ case 'eq':
2040
+ return _eq(data, parameters)
2041
+ case 'neq':
2042
+ return _neq(data, parameters)
2043
+ case 'gt':
2044
+ return _gt(data, parameters)
2045
+ case 'gte':
2046
+ return _gte(data, parameters)
2047
+ case 'lt':
2048
+ return _lt(data, parameters)
2049
+ case 'lte':
2050
+ return _lte(data, parameters)
2051
+ case 'isEmpty':
2052
+ return _isEmpty(data, parameters)
2053
+ case 'isNotEmpty':
2054
+ return _isNotEmpty(data, parameters)
2055
+ case 'toLowerCase':
2056
+ return _toLowerCase(data)
2057
+ case 'toUpperCase':
2058
+ return _toUpperCase(data)
2059
+ default:
2060
+ throw new Error(`${functionName} is not a valid function`)
2061
+ }
2062
+ } catch (e) {
2063
+ throw e
1526
2064
  }
1527
2065
  }
1528
2066
 
1529
2067
 
1530
2068
 
1531
- ;// ./lib/models/template/index.js
2069
+ ;// ./lib/models/templateCompiler/index.js
1532
2070
 
1533
2071
 
1534
2072