@questwork/q-utilities 0.1.19 → 0.1.20

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.
@@ -48,6 +48,7 @@ __webpack_require__.r(__webpack_exports__);
48
48
 
49
49
  // EXPORTS
50
50
  __webpack_require__.d(__webpack_exports__, {
51
+ ActionRecord: () => (/* reexport */ ActionRecord),
51
52
  ApiResponse: () => (/* reexport */ ApiResponse),
52
53
  AwsStsS3Client: () => (/* reexport */ AwsStsS3Client),
53
54
  KeyValueObject: () => (/* reexport */ KeyValueObject),
@@ -56,6 +57,8 @@ __webpack_require__.d(__webpack_exports__, {
56
57
  QMeta: () => (/* reexport */ QMeta),
57
58
  Repo: () => (/* reexport */ Repo),
58
59
  Service: () => (/* reexport */ Service),
60
+ Status: () => (/* reexport */ Status),
61
+ StatusDocument: () => (/* reexport */ StatusDocument),
59
62
  TemplateCompiler: () => (/* reexport */ TemplateCompiler),
60
63
  TenantAwareEntity: () => (/* reexport */ TenantAwareEntity),
61
64
  TrackedEntity: () => (/* reexport */ TrackedEntity),
@@ -76,6 +79,7 @@ __webpack_require__.d(__webpack_exports__, {
76
79
  init: () => (/* reexport */ init),
77
80
  initFromArray: () => (/* reexport */ initFromArray),
78
81
  initOnlyValidFromArray: () => (/* reexport */ initOnlyValidFromArray),
82
+ isConvertibleToNumber: () => (/* reexport */ isConvertibleToNumber),
79
83
  makeApiResponse: () => (/* reexport */ makeApiResponse),
80
84
  makeService: () => (/* reexport */ makeService),
81
85
  mergeArraysByKey: () => (/* reexport */ mergeArraysByKey),
@@ -116,14 +120,14 @@ function authorize({ allowCoordinator, allowOwner, query = {}, required, user })
116
120
  if (query.registrationGroupCode && user.myManagedRegistrationGroupCodes.includes(query.registrationGroupCode)) {
117
121
  query.__ALLOW_COORDINATOR = true
118
122
  } else {
119
- if (!scopes.includes('EVENT')) {
120
- query.eventRegistrationCode = user.eventRegistrationCode
121
- }
122
- }
123
- } else {
124
123
  if (!scopes.includes('EVENT')) {
125
124
  query.eventRegistrationCode = user.eventRegistrationCode
126
125
  }
126
+ }
127
+ } else {
128
+ if (!scopes.includes('EVENT')) {
129
+ query.eventRegistrationCode = user.eventRegistrationCode
130
+ }
127
131
  }
128
132
  if (allowOwner) {
129
133
  query.__ALLOW_OWNER = true
@@ -155,14 +159,14 @@ function calculateAge(timestamp, reference) {
155
159
  }
156
160
 
157
161
  // Calculate raw difference
158
- let age = refDate.getFullYear() - birthDate.getFullYear();
159
- const monthDiff = refDate.getMonth() - birthDate.getMonth();
160
-
162
+ let age = refDate.getFullYear() - birthDate.getFullYear()
163
+ const monthDiff = refDate.getMonth() - birthDate.getMonth()
164
+
161
165
  // Adjust if birthday hasn't occurred yet this year
162
166
  if (monthDiff < 0 || (monthDiff === 0 && refDate.getDate() < birthDate.getDate())) {
163
167
  age--
164
168
  }
165
-
169
+
166
170
  return age
167
171
  }
168
172
 
@@ -192,7 +196,18 @@ function changeCreatorOwner(that, { source, target }) {
192
196
  ;// ./lib/helpers/changeCreatorOwner/index.js
193
197
 
194
198
 
199
+ ;// ./lib/helpers/isConvertibleToNumber/isConvertibleToNumber.js
200
+ function isConvertibleToNumber(value) {
201
+ return value !== null
202
+ && value !== undefined
203
+ && typeof value !== 'boolean'
204
+ && String(value).trim() !== ''
205
+ && !isNaN(Number(value))
206
+ }
207
+
195
208
  ;// ./lib/helpers/getValidation/getValidation.js
209
+
210
+
196
211
  function getValidation(rule, data, getDataByKey, KeyValueObject) {
197
212
  if (!rule) {
198
213
  return true
@@ -206,10 +221,10 @@ function getValidation(rule, data, getDataByKey, KeyValueObject) {
206
221
  if (!key && typeof placeholder === 'undefined') {
207
222
  switch (valueAttribute) {
208
223
  case '$and': {
209
- return value['$and'].reduce((acc, item) => (acc && getValidation(item, data, getDataByKey, KeyValueObject)), true)
224
+ return value.$and.reduce((acc, item) => (acc && getValidation(item, data, getDataByKey, KeyValueObject)), true)
210
225
  }
211
226
  case '$or': {
212
- return value['$or'].reduce((acc, item) => (acc || getValidation(item, data, getDataByKey, KeyValueObject)), false)
227
+ return value.$or.reduce((acc, item) => (acc || getValidation(item, data, getDataByKey, KeyValueObject)), false)
213
228
  }
214
229
  default:
215
230
  return false
@@ -224,39 +239,53 @@ function getValidation(rule, data, getDataByKey, KeyValueObject) {
224
239
  }
225
240
 
226
241
  switch (valueAttribute) {
242
+ case '$after': {
243
+ if (isConvertibleToNumber(value?.$after)) {
244
+ const _value = Number(String(value?.$after))
245
+ return Date.now() > _value
246
+ }
247
+ return false
248
+ }
249
+ case '$before': {
250
+ if (isConvertibleToNumber(value?.$before)) {
251
+ const _value = Number(String(value?.$before))
252
+ return Date.now() < _value
253
+ }
254
+ return false
255
+ }
227
256
  case '$empty': {
228
257
  const isEmpty = rowValue === null || rowValue === undefined
229
- return isEmpty === value['$empty']
258
+ return isEmpty === value.$empty
230
259
  }
231
260
  case '$eq': {
232
- return rowValue === value['$eq']
261
+ return rowValue === value.$eq
233
262
  }
234
263
  case '$gt': {
235
- return rowValue > value['$gt']
264
+ return rowValue > value.$gt
236
265
  }
237
266
  case '$gte': {
238
- return rowValue >= value['$gte']
267
+ return rowValue >= value.$gte
239
268
  }
240
269
  case '$hasOverlap': {
241
- return _hasOverlap(rowValue, value['$hasOverlap'])
270
+ return _hasOverlap(rowValue, value.$hasOverlap)
242
271
  }
243
272
  case '$lt': {
244
- return rowValue < value['$lt']
273
+ return rowValue < value.$lt
245
274
  }
246
275
  case '$lte': {
247
- return rowValue <= value['$lte']
276
+ return rowValue <= value.$lte
248
277
  }
249
278
  case '$in': {
250
279
  if (Array.isArray(rowValue)) {
251
- return !!rowValue.find((e) => (value['$in'].includes(e)))
280
+ return !!rowValue.find((e) => (value.$in.includes(e)))
252
281
  }
253
282
  if (typeof rowValue !== 'object') {
254
- return !!value['$in'].includes(rowValue)
283
+ return !!value.$in.includes(rowValue)
255
284
  }
256
285
  return false
257
286
  }
258
287
  case '$inValue': {
259
- const result = getDataByKey(value['$inValue'], data)
288
+ const result = getDataByKey(value.$inValue, data)
260
289
  const _value = Array.isArray(result) ? result : []
261
290
  if (Array.isArray(rowValue)) {
262
291
  return !!rowValue.find((e) => (_value.includes(e)))
@@ -267,36 +296,36 @@ function getValidation(rule, data, getDataByKey, KeyValueObject) {
267
296
  return false
268
297
  }
269
298
  case '$ne': {
270
- return rowValue !== value['$ne']
299
+ return rowValue !== value.$ne
271
300
  }
272
301
  case '$notIn': {
273
302
  if (Array.isArray(rowValue)) {
274
- return !rowValue.find((e) => (value['$notIn'].includes(e)))
303
+ return !rowValue.find((e) => (value.$notIn.includes(e)))
275
304
  }
276
305
  if (typeof rowValue !== 'object') {
277
- return !value['$notIn'].includes(rowValue)
306
+ return !value.$notIn.includes(rowValue)
278
307
  }
279
308
  return false
280
309
  }
281
310
  case '$intervalTimeGt': {
282
311
  const now = new Date().getTime()
283
312
  const timestamp = new Date(rowValue).getTime()
284
- return (now - timestamp) > value['$intervalTimeGt']
313
+ return (now - timestamp) > value.$intervalTimeGt
285
314
  }
286
315
  case '$intervalTimeLt': {
287
316
  const now = new Date().getTime()
288
317
  const timestamp = new Date(rowValue).getTime()
289
- return (now - timestamp) < value['$intervalTimeLt']
318
+ return (now - timestamp) < value.$intervalTimeLt
290
319
  }
291
320
  case '$isToday': {
292
321
  const currentDate = new Date()
293
- const start = currentDate.setHours(0,0,0,0)
294
- const end = currentDate.setHours(23,59,59,59)
322
+ const start = currentDate.setHours(0, 0, 0, 0)
323
+ const end = currentDate.setHours(23, 59, 59, 59)
295
324
  const dateValue = new Date(rowValue).getTime()
296
- return (start <= dateValue && end >= dateValue) === value['$isToday']
325
+ return (start <= dateValue && end >= dateValue) === value.$isToday
297
326
  }
298
327
  case '$notInValue': {
299
- const result = getDataByKey(value['$notInValue'], data)
328
+ const result = getDataByKey(value.$notInValue, data)
300
329
  const _value = Array.isArray(result) ? result : []
301
330
  if (Array.isArray(rowValue)) {
302
331
  return !rowValue.find((e) => (_value.includes(e)))
@@ -307,7 +336,7 @@ function getValidation(rule, data, getDataByKey, KeyValueObject) {
307
336
  return false
308
337
  }
309
338
  case '$range': {
310
- const [min, max] = value['$range']
339
+ const [min, max] = value.$range
311
340
  if (typeof min === 'number' && typeof max === 'number' && rowValue >= min && rowValue <= max) {
312
341
  return true
313
342
  }
@@ -316,7 +345,6 @@ function getValidation(rule, data, getDataByKey, KeyValueObject) {
316
345
  default:
317
346
  return false
318
347
  }
319
-
320
348
  }
321
349
 
322
350
  function _hasOverlap(item1, item2) {
@@ -341,12 +369,11 @@ function _hasOverlap(item1, item2) {
341
369
 
342
370
 
343
371
  ;// ./lib/helpers/formatDate/formatDate.js
344
-
345
372
  function formatDate(date, format) {
346
373
  const _date = date && date instanceof Date ? date : new Date(date)
347
- const dayMapChi = ['日','一','二','三','四','五','六']
348
- const dayMapEng = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday']
349
- const dayMapEngShort = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
374
+ const dayMapChi = ['日', '一', '二', '三', '四', '五', '六']
375
+ const dayMapEng = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
376
+ const dayMapEngShort = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
350
377
  const _format = format || 'YYYY/MM/DD hh:mm'
351
378
  const e = _date.getDay()
352
379
  const ee = dayMapEngShort[e]
@@ -381,13 +408,11 @@ function padding(m) {
381
408
  return m < 10 ? `0${m}` : m
382
409
  }
383
410
 
384
-
385
411
  /* harmony default export */ const formatDate_formatDate = ({
386
412
  formatDate
387
413
  });
388
414
 
389
415
 
390
-
391
416
  ;// ./lib/helpers/formatDate/index.js
392
417
 
393
418
 
@@ -418,7 +443,6 @@ function getValueByKeys_getValueByKeys(keys, data) {
418
443
  return _data[firstKey]
419
444
  }
420
445
  return _data
421
-
422
446
  }
423
447
  /* harmony default export */ const getValueByKeys = ({
424
448
  getValueByKeys: getValueByKeys_getValueByKeys
@@ -470,6 +494,7 @@ const _FN_NAMES = [
470
494
  'map',
471
495
  'neq',
472
496
  'removeHtml',
497
+ 'sum',
473
498
  'toLowerCase',
474
499
  'toUpperCase',
475
500
  ]
@@ -622,10 +647,12 @@ function _existObject(data, args) {
622
647
 
623
648
  function _performOperation(arg, value) {
624
649
  // the arg is undefined
625
- if (arg === undefined && value === undefined) return true
650
+ if (arg === undefined && value === undefined)
651
+ return true
626
652
 
627
653
  // the arg is null
628
- if (arg === null && value === null) return true
654
+ if (arg === null && value === null)
655
+ return true
629
656
 
630
657
  // the arg is boolean
631
658
  if (typeof arg === 'boolean') {
@@ -701,17 +728,18 @@ function _splitOperator(str) {
701
728
  const operators = ['!=', '>=', '<=', '>', '<']
702
729
 
703
730
  const matchedOp = operators.find((op) => str.startsWith(op))
704
- if (!matchedOp) return { operator: null, value: null }
731
+ if (!matchedOp)
732
+ return { operator: null, value: null }
705
733
 
706
734
  const remaining = str.slice(matchedOp.length)
707
735
 
708
736
  // '>Primary' or '<Primary' is invalid
709
- if (/^[a-zA-Z]*$/.test(remaining) && matchedOp !== '!=') {
737
+ if (/^[a-z]*$/i.test(remaining) && matchedOp !== '!=') {
710
738
  return { operator: null, value: null }
711
739
  }
712
740
 
713
741
  // if it is a number it is converted to a number
714
- const value = (!Number.isNaN(parseFloat(remaining)) && !Number.isNaN(remaining)) ? Number(remaining) : remaining
742
+ const value = (!Number.isNaN(Number.parseFloat(remaining)) && !Number.isNaN(remaining)) ? Number(remaining) : remaining
715
743
 
716
744
  return {
717
745
  operator: matchedOp,
@@ -923,11 +951,14 @@ function _isNotEmpty(data, args) {
923
951
  }
924
952
 
925
953
 
954
+
926
955
  ;// ./lib/models/templateCompiler/helpers/_join.js
927
956
  function _join(data, delimiter) {
928
957
  try {
929
- if (data.length === 0) return ''
930
- if (data.length === 1) return _stringifyObject(data[0])
958
+ if (data.length === 0)
959
+ return ''
960
+ if (data.length === 1)
961
+ return _stringifyObject(data[0])
931
962
  return data.map((item) => _stringifyObject(item)).join(delimiter)
932
963
  } catch (e) {
933
964
  throw e
@@ -1074,13 +1105,13 @@ function _removeHtml(html, args) {
1074
1105
 
1075
1106
  function _htmlToPlainText(html, delimiter = '\n') {
1076
1107
  if (typeof delimiter !== 'string') {
1077
- delimiter = '\n'; // Fallback to default if not a string
1108
+ delimiter = '\n' // Fallback to default if not a string
1078
1109
  }
1079
1110
 
1080
1111
  // First decode HTML entities and normalize whitespace
1081
1112
  const decodedHtml = html
1082
1113
  .replace(/&nbsp;/g, ' ')
1083
- .replace(/\s+/g, ' '); // Collapse all whitespace to single spaces
1114
+ .replace(/\s+/g, ' ') // Collapse all whitespace to single spaces
1084
1115
 
1085
1116
  // Process HTML tags
1086
1117
  let text = decodedHtml
@@ -1091,29 +1122,36 @@ function _htmlToPlainText(html, delimiter = '\n') {
1091
1122
  // Remove all other tags
1092
1123
  .replace(/<[^>]+>/g, '')
1093
1124
  // Convert markers to specified delimiter
1094
- .replace(/~~~+/g, delimiter)
1125
+ .replace(/~{3,}/g, delimiter)
1095
1126
  // Trim and clean whitespace
1096
- .trim();
1127
+ .trim()
1097
1128
 
1098
1129
  // Special handling for empty delimiter
1099
1130
  if (delimiter === '') {
1100
1131
  // Collapse all whitespace to single space
1101
- text = text.replace(/\s+/g, ' ');
1132
+ text = text.replace(/\s+/g, ' ')
1102
1133
  } else {
1103
-
1104
-
1105
1134
  // Collapse multiple delimiters to single
1106
- text = text.replace(new RegExp(`${escapeRegExp(delimiter)}+`, 'g'), delimiter);
1135
+ text = text.replace(new RegExp(`${escapeRegExp(delimiter)}+`, 'g'), delimiter)
1107
1136
  // Remove leading/trailing delimiters
1108
- text = text.replace(new RegExp(`^${escapeRegExp(delimiter)}|${escapeRegExp(delimiter)}$`, 'g'), '');
1137
+ text = text.replace(new RegExp(`^${escapeRegExp(delimiter)}|${escapeRegExp(delimiter)}$`, 'g'), '')
1109
1138
  }
1110
1139
 
1111
- return text;
1140
+ return text
1112
1141
  }
1113
1142
 
1114
-
1115
1143
  function escapeRegExp(string) {
1116
- return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1144
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
1145
+ }
1146
+
1147
+
1148
+
1149
+ ;// ./lib/models/templateCompiler/helpers/_sum.js
1150
+ function _sum(data, args) {
1151
+ if (Number.isNaN(data) || data === null || (typeof data === 'undefined') || data === '') {
1152
+ return data
1153
+ }
1154
+ return args.reduce((acc, e) => (acc + e), data)
1117
1155
  }
1118
1156
 
1119
1157
 
@@ -1173,6 +1211,7 @@ function _toUpperCase(data, args) {
1173
1211
 
1174
1212
 
1175
1213
 
1214
+
1176
1215
 
1177
1216
 
1178
1217
  ;// ./lib/models/templateCompiler/templateCompiler.js
@@ -1246,6 +1285,9 @@ class TemplateCompiler {
1246
1285
  static removeHtml(data, args) {
1247
1286
  return _removeHtml(data, args)
1248
1287
  }
1288
+ static sum(data, args) {
1289
+ return _sum(data, args)
1290
+ }
1249
1291
  static toLowerCase(data, args) {
1250
1292
  return _toLowerCase(data, args)
1251
1293
  }
@@ -1306,7 +1348,7 @@ function _parseFunction(expression, existFunctionNames) {
1306
1348
 
1307
1349
  function _parseParams(parameters) {
1308
1350
  const _parameters = parameters.trim()
1309
- const regExp = new RegExp(/^[^\w\d\s]+$/)
1351
+ const regExp = new RegExp(/^[^\w\s]+$/)
1310
1352
  const match = _parameters.match(regExp)
1311
1353
  if (match !== null) {
1312
1354
  return [_parameters.substring(1, _parameters.length - 1)]
@@ -1321,13 +1363,13 @@ function _parseParams(parameters) {
1321
1363
 
1322
1364
  function _splitIgnoringBrackets(input) {
1323
1365
  const regExp2 = new RegExp(/^\d+(\.\d+)?$/)
1324
- const regExp = new RegExp(/(?![^\[]*\])\s*,\s*/)
1366
+ const regExp = new RegExp(/(?![^[]*\])\s*,\s*/)
1325
1367
  const parts = input.split(regExp)
1326
1368
  return parts.map((part) => {
1327
1369
  const _part = part.trim()
1328
1370
  if (_part !== '' && !!_part.match(regExp2)) {
1329
1371
  // 如果是数字,转换为 num 类型
1330
- return Number.isNaN(_part) ? _part : parseInt(_part, 10)
1372
+ return Number.isNaN(_part) ? _part : Number.parseInt(_part, 10)
1331
1373
  }
1332
1374
  // 否则当作字符串处理
1333
1375
  return _part
@@ -1340,7 +1382,7 @@ function _parseSinglePart(input) {
1340
1382
  // 去掉双引号,返回
1341
1383
  return input.substring(1, input.length - 1)
1342
1384
  }
1343
- if (input.startsWith("'") && input.endsWith("'")) {
1385
+ if (input.startsWith('\'') && input.endsWith('\'')) {
1344
1386
  // 去掉双引号,返回
1345
1387
  return input.substring(1, input.length - 1)
1346
1388
  }
@@ -1371,7 +1413,7 @@ function _toBasicType(input) {
1371
1413
  // 去掉双引号,返回
1372
1414
  return input.substring(1, input.length - 1)
1373
1415
  }
1374
- if (input.startsWith("'") && input.endsWith("'")) {
1416
+ if (input.startsWith('\'') && input.endsWith('\'')) {
1375
1417
  // 去掉双引号,返回
1376
1418
  return input.substring(1, input.length - 1)
1377
1419
  }
@@ -1439,6 +1481,8 @@ function _callFunction(data, functionName, parameters) {
1439
1481
  return _neq(data, parameters)
1440
1482
  case 'removeHtml':
1441
1483
  return _removeHtml(data, parameters)
1484
+ case 'sum':
1485
+ return _sum(data, parameters)
1442
1486
  case 'toLowerCase':
1443
1487
  return _toLowerCase(data)
1444
1488
  case 'toUpperCase':
@@ -1468,14 +1512,14 @@ function concatStringByArray(arrTemplate, data) {
1468
1512
  return arrTemplate.reduce((acc, item) => {
1469
1513
  const { type, value = '', restriction, template, format, showMinutes } = item
1470
1514
  switch (type) {
1471
- case('array'): {
1515
+ case ('array'): {
1472
1516
  if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
1473
1517
  const _value = getValueByKeys_getValueByKeys(value.split('.'), data) || []
1474
1518
  acc += _value.reduce((_acc, item) => {
1475
1519
  return _acc += concatStringByArray(template, item)
1476
1520
  }, '')
1477
1521
  }
1478
- break
1522
+ break
1479
1523
  }
1480
1524
  case ('date'): {
1481
1525
  if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
@@ -1484,7 +1528,7 @@ function concatStringByArray(arrTemplate, data) {
1484
1528
  }
1485
1529
  break
1486
1530
  }
1487
- case('ellipsis'): {
1531
+ case ('ellipsis'): {
1488
1532
  if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
1489
1533
  const { maxLength } = item
1490
1534
  const _value = getValueByKeys_getValueByKeys(value.split('.'), data) || ''
@@ -1494,15 +1538,15 @@ function concatStringByArray(arrTemplate, data) {
1494
1538
  acc += `${_value.substr(0, maxLength)}...`
1495
1539
  }
1496
1540
  }
1497
- break
1541
+ break
1498
1542
  }
1499
- case('group'): {
1543
+ case ('group'): {
1500
1544
  if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
1501
1545
  return concatStringByArray(value, data)
1502
1546
  }
1503
1547
  break
1504
1548
  }
1505
- case('label'): {
1549
+ case ('label'): {
1506
1550
  if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
1507
1551
  acc += (value.toString())
1508
1552
  }
@@ -1515,12 +1559,12 @@ function concatStringByArray(arrTemplate, data) {
1515
1559
  }
1516
1560
  break
1517
1561
  }
1518
- case('value'): {
1562
+ case ('value'): {
1519
1563
  if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
1520
1564
  const _value = getValueByKeys_getValueByKeys(value.split('.'), data) || ''
1521
1565
  acc += (_value.toString())
1522
1566
  }
1523
- break
1567
+ break
1524
1568
  }
1525
1569
  }
1526
1570
  return acc
@@ -1531,7 +1575,6 @@ function concatStringByArray(arrTemplate, data) {
1531
1575
  });
1532
1576
 
1533
1577
 
1534
-
1535
1578
  ;// ./lib/helpers/concatStringByArray/index.js
1536
1579
 
1537
1580
 
@@ -1542,7 +1585,7 @@ function convertString(string, patternMatch = /\$\{(.+?)\}/g, value, getValueByK
1542
1585
  if (!string) {
1543
1586
  return ''
1544
1587
  }
1545
- let _getValueByKeys = typeof getValueByKeys === 'function' ? getValueByKeys : getValueByKeys_getValueByKeys
1588
+ const _getValueByKeys = typeof getValueByKeys === 'function' ? getValueByKeys : getValueByKeys_getValueByKeys
1546
1589
  const reg = new RegExp(patternMatch, 'g')
1547
1590
  return string.replace(reg, (match, key) => {
1548
1591
  const result = _getValueByKeys({ keys: key.split('.'), obj: value })
@@ -1563,7 +1606,7 @@ function convertString(string, patternMatch = /\$\{(.+?)\}/g, value, getValueByK
1563
1606
 
1564
1607
  ;// ./lib/helpers/escapeRegex/escapeRegex.js
1565
1608
  function escapeRegex(string) {
1566
- return String(string).replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')
1609
+ return String(string).replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
1567
1610
  }
1568
1611
 
1569
1612
  ;// ./lib/helpers/escapeRegex/index.js
@@ -1666,7 +1709,6 @@ function updateOneResult({ responseHelper, service }) {
1666
1709
 
1667
1710
 
1668
1711
 
1669
-
1670
1712
  const expressHelper = {
1671
1713
  customHandler: customHandler,
1672
1714
  findAllResult: findAllResult,
@@ -1682,27 +1724,29 @@ const expressHelper = {
1682
1724
  * @returns {Array} Sorted array of unique, lowercase email addresses
1683
1725
  */
1684
1726
  function extractEmails(dirtyArray) {
1685
- const emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g
1727
+ const emailRegex = /[\w.%+-]+@[a-z0-9.-]+\.[a-z]{2,}/gi
1686
1728
  const emails = new Set()
1687
1729
 
1688
1730
  // Handle null/undefined input array
1689
- if (!dirtyArray) return []
1731
+ if (!dirtyArray)
1732
+ return []
1690
1733
 
1691
- dirtyArray.forEach(entry => {
1734
+ dirtyArray.forEach((entry) => {
1692
1735
  // Skip null, undefined, empty, or whitespace-only entries
1693
- if (!entry || typeof entry !== 'string' || !entry.trim()) return
1736
+ if (!entry || typeof entry !== 'string' || !entry.trim())
1737
+ return
1694
1738
 
1695
1739
  try {
1696
1740
  const cleanEntry = entry
1697
1741
  .replace(/[\u200B-\u200D\uFEFF\u202A-\u202E]/g, '') // Remove hidden chars
1698
- .replace(/[<>]/g, ' ') // Convert email delimiters to spaces
1699
- .replace(/\s+/g, ' ') // Collapse multiple whitespace
1742
+ .replace(/[<>]/g, ' ') // Convert email delimiters to spaces
1743
+ .replace(/\s+/g, ' ') // Collapse multiple whitespace
1700
1744
  .trim()
1701
1745
 
1702
1746
  // Extract all email matches
1703
1747
  const matches = cleanEntry.match(emailRegex)
1704
1748
  if (matches) {
1705
- matches.forEach(email => emails.add(email.toLowerCase())) // Normalize to lowercase
1749
+ matches.forEach((email) => emails.add(email.toLowerCase())) // Normalize to lowercase
1706
1750
  }
1707
1751
  } catch (e) {
1708
1752
  console.warn('Failed to process entry:', entry, e)
@@ -1748,64 +1792,65 @@ const objectHelper = {
1748
1792
  },
1749
1793
  merge,
1750
1794
  set(obj, path, value) {
1751
- const parts = path.split('.');
1752
- let current = obj;
1795
+ const parts = path.split('.')
1796
+ let current = obj
1753
1797
 
1754
1798
  // 处理所有中间部分
1755
1799
  for (let i = 0; i < parts.length - 1; i++) {
1756
- const part = parts[i];
1757
- let key, index;
1800
+ const part = parts[i]
1801
+ let key, index
1758
1802
 
1759
1803
  // 检查是否是数组索引格式,如key[0]
1760
- const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/);
1804
+ const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/)
1761
1805
  if (arrayMatch) {
1762
- key = arrayMatch[1];
1763
- index = parseInt(arrayMatch[2], 10);
1806
+ key = arrayMatch[1]
1807
+ index = Number.parseInt(arrayMatch[2], 10)
1764
1808
  // 确保当前层级的数组存在
1765
1809
  if (!current[key] || !Array.isArray(current[key])) {
1766
- current[key] = [];
1810
+ current[key] = []
1767
1811
  }
1768
1812
  // 扩展数组到足够大
1769
1813
  while (current[key].length <= index) {
1770
- current[key].push(undefined);
1814
+ current[key].push(undefined)
1771
1815
  }
1772
1816
  // 如果当前位置未定义或为null,初始化为对象
1773
1817
  if (current[key][index] == null) {
1774
- current[key][index] = {};
1818
+ current[key][index] = {}
1775
1819
  }
1776
- current = current[key][index];
1820
+ current = current[key][index]
1777
1821
  } else {
1778
1822
  // 处理普通属性
1779
1823
  if (!current[part]) {
1780
- current[part] = {};
1824
+ current[part] = {}
1781
1825
  }
1782
- current = current[part];
1826
+ current = current[part]
1783
1827
  }
1784
1828
  }
1785
1829
 
1786
1830
  // 处理最后一部分
1787
- const lastPart = parts[parts.length - 1];
1788
- const arrayMatch = lastPart.match(/^(\w+)\[(\d+)\]$/);
1831
+ const lastPart = parts[parts.length - 1]
1832
+ const arrayMatch = lastPart.match(/^(\w+)\[(\d+)\]$/)
1789
1833
  if (arrayMatch) {
1790
- const key = arrayMatch[1];
1791
- const index = parseInt(arrayMatch[2], 10);
1834
+ const key = arrayMatch[1]
1835
+ const index = Number.parseInt(arrayMatch[2], 10)
1792
1836
  // 确保数组存在
1793
1837
  if (!current[key] || !Array.isArray(current[key])) {
1794
- current[key] = [];
1838
+ current[key] = []
1795
1839
  }
1796
1840
  // 扩展数组到所需索引
1797
1841
  while (current[key].length <= index) {
1798
- current[key].push(undefined);
1842
+ current[key].push(undefined)
1799
1843
  }
1800
- current[key][index] = value;
1844
+ current[key][index] = value
1801
1845
  } else {
1802
- current[lastPart] = value;
1846
+ current[lastPart] = value
1803
1847
  }
1804
1848
  }
1805
1849
  }
1806
1850
 
1807
1851
  function merge(target, ...sources) {
1808
- if (!sources.length) return target
1852
+ if (!sources.length)
1853
+ return target
1809
1854
 
1810
1855
  const source = sources.shift() // 取出第一个源对象
1811
1856
 
@@ -1842,28 +1887,28 @@ function _isObject(obj) {
1842
1887
 
1843
1888
  ;// ./lib/helpers/pReduce/pReduce.js
1844
1889
  async function pReduce(iterable, reducer, initialValue) {
1845
- return new Promise((resolve, reject) => {
1846
- const iterator = iterable[Symbol.iterator]()
1847
- let index = 0
1890
+ return new Promise((resolve, reject) => {
1891
+ const iterator = iterable[Symbol.iterator]()
1892
+ let index = 0
1848
1893
 
1849
- const next = async total => {
1850
- const element = iterator.next()
1894
+ const next = async (total) => {
1895
+ const element = iterator.next()
1851
1896
 
1852
- if (element.done) {
1853
- resolve(total)
1854
- return
1855
- }
1897
+ if (element.done) {
1898
+ resolve(total)
1899
+ return
1900
+ }
1856
1901
 
1857
- try {
1858
- const [resolvedTotal, resolvedValue] = await Promise.all([total, element.value])
1859
- next(reducer(resolvedTotal, resolvedValue, index++))
1860
- } catch (error) {
1861
- reject(error)
1862
- }
1863
- }
1902
+ try {
1903
+ const [resolvedTotal, resolvedValue] = await Promise.all([total, element.value])
1904
+ next(reducer(resolvedTotal, resolvedValue, index++))
1905
+ } catch (error) {
1906
+ reject(error)
1907
+ }
1908
+ }
1864
1909
 
1865
- next(initialValue)
1866
- })
1910
+ next(initialValue)
1911
+ })
1867
1912
  }
1868
1913
 
1869
1914
 
@@ -2010,16 +2055,17 @@ class Repo {
2010
2055
  const promise = typeof this.model.saveAll === 'function'
2011
2056
  ? this.model.saveAll({ config, docs })
2012
2057
  : Promise.all(docs.map(async (doc) => {
2013
- if (doc) {
2014
- const result = await this.saveOne({ config, doc })
2015
- isNew = result.isNew
2016
- const _data = result._data || result.data
2017
- return _data[0]
2018
- }
2019
- return null
2020
- }))
2058
+ if (doc) {
2059
+ const result = await this.saveOne({ config, doc })
2060
+ isNew = result.isNew
2061
+ const _data = result._data || result.data
2062
+ return _data[0]
2063
+ }
2064
+ return null
2065
+ }))
2021
2066
  return promise.then((savedData) => {
2022
- if (savedData.length !== 1) isNew = null
2067
+ if (savedData.length !== 1)
2068
+ isNew = null
2023
2069
  const result = {
2024
2070
  data: savedData,
2025
2071
  isNew,
@@ -2353,6 +2399,9 @@ function initOnlyValidFromArray(_class, arr) {
2353
2399
  ;// ./lib/helpers/initOnlyValidFromArray/index.js
2354
2400
 
2355
2401
 
2402
+ ;// ./lib/helpers/isConvertibleToNumber/index.js
2403
+
2404
+
2356
2405
  ;// ./lib/helpers/mergeArraysByKey/mergeArraysByKey.js
2357
2406
  function mergeArraysByKey(arr1, arr2) {
2358
2407
  // Handle undefined/null inputs by defaulting to empty arrays
@@ -2363,40 +2412,41 @@ function mergeArraysByKey(arr1, arr2) {
2363
2412
 
2364
2413
  // Helper function to merge values based on their type
2365
2414
  const mergeValues = (existingValue, newValue) => {
2366
- if (existingValue === undefined) return newValue
2367
-
2415
+ if (existingValue === undefined)
2416
+ return newValue
2417
+
2368
2418
  // Handle arrays by concatenating
2369
2419
  if (Array.isArray(existingValue) && Array.isArray(newValue)) {
2370
2420
  return [...new Set([...existingValue, ...newValue])]
2371
2421
  }
2372
-
2422
+
2373
2423
  // Handle objects by merging
2374
- if (typeof existingValue === 'object' && typeof newValue === 'object' &&
2375
- !Array.isArray(existingValue) && !Array.isArray(newValue)) {
2424
+ if (typeof existingValue === 'object' && typeof newValue === 'object'
2425
+ && !Array.isArray(existingValue) && !Array.isArray(newValue)) {
2376
2426
  return { ...existingValue, ...newValue }
2377
2427
  }
2378
-
2428
+
2379
2429
  // // Handle numbers by adding
2380
2430
  // if (typeof existingValue === 'number' && typeof newValue === 'number') {
2381
2431
  // return existingValue
2382
2432
  // }
2383
-
2433
+
2384
2434
  // // Handle strings by concatenating
2385
2435
  // if (typeof existingValue === 'string' && typeof newValue === 'string') {
2386
2436
  // return existingValue
2387
2437
  // }
2388
-
2438
+
2389
2439
  // Default: use the new value
2390
2440
  return newValue
2391
2441
  }
2392
2442
 
2393
2443
  // Process first array
2394
- safeArr1.forEach(item => {
2444
+ safeArr1.forEach((item) => {
2395
2445
  mergedMap.set(item.key, item.value)
2396
2446
  })
2397
2447
 
2398
2448
  // Process second array and merge values
2399
- safeArr2.forEach(item => {
2449
+ safeArr2.forEach((item) => {
2400
2450
  const existingValue = mergedMap.get(item.key)
2401
2451
  mergedMap.set(item.key, mergeValues(existingValue, item.value))
2402
2452
  })
@@ -2415,7 +2465,7 @@ function mergeArraysByKey(arr1, arr2) {
2415
2465
  function padZeros(num, minLength = 6) {
2416
2466
  num = num.toString()
2417
2467
  if (num.length < minLength) {
2418
- return padZeros('0' + num, minLength)
2468
+ return padZeros(`0${num}`, minLength)
2419
2469
  }
2420
2470
  return num
2421
2471
  }
@@ -2435,26 +2485,26 @@ function padZeros(num, minLength = 6) {
2435
2485
  ;// ./lib/helpers/replacePlaceholders/replacePlaceholders.js
2436
2486
  function replacePlaceholders({ content, mapping }) {
2437
2487
  let isObjectMode = false
2438
-
2488
+
2439
2489
  if (typeof content === 'object' && content !== null) {
2440
2490
  content = JSON.stringify(content)
2441
2491
  isObjectMode = true
2442
2492
  }
2443
2493
 
2444
2494
  // [[ eventRegistration.eventRegistrationCode | 0 ]]
2445
- const regex = /(\[*)\[\[\s*([\w.\-_]+)(?:\s*\|\s*([^:\]\s]+))?(?:\s*:\s*([^\]\s]+))?\s*\]\](\]*)/g;
2495
+ const regex = /(\[*)\[\[\s*([\w.\-]+)(?:\s*\|\s*([^:\]\s]+))?(?:\s*:\s*([^\]\s]+))?\s*\]\](\]*)/g
2446
2496
 
2447
2497
  const result = content.replace(regex, (match, leadingBrackets, path, defaultValue, type, trailingBrackets) => {
2448
-
2449
2498
  // Split the path into parts
2450
2499
  const keys = path.trim().split('.')
2451
-
2500
+
2452
2501
  // Traverse the nested object structure
2453
2502
  let value = mapping
2454
2503
  for (const key of keys) {
2455
2504
  // Handle empty keys (in case of double dots or leading/trailing dots)
2456
- if (!key) continue
2457
-
2505
+ if (!key)
2506
+ continue
2507
+
2458
2508
  value = value?.[key]
2459
2509
  if (value === undefined) {
2460
2510
  break
@@ -2462,10 +2512,12 @@ function replacePlaceholders({ content, mapping }) {
2462
2512
  }
2463
2513
 
2464
2514
  // Apply default if missing
2465
- if (value === undefined) value = defaultValue?.trim();
2466
- if (value === undefined) return isObjectMode ? undefined : match;
2467
-
2468
- value = value !== undefined
2515
+ if (value === undefined)
2516
+ value = defaultValue?.trim()
2517
+ if (value === undefined)
2518
+ return isObjectMode ? undefined : match
2519
+
2520
+ value = value !== undefined
2469
2521
  ? leadingBrackets + value + trailingBrackets
2470
2522
  : match
2471
2523
 
@@ -2486,10 +2538,11 @@ function replacePlaceholders({ content, mapping }) {
2486
2538
  /**
2487
2539
  * Sanitizes input by removing hidden/control characters with customizable whitespace handling.
2488
2540
  * @param {string} input - The string to sanitize.
2489
- * @param {Object} [options] - Configuration options.
2490
- * @param {boolean} [options.normalizeWhitespace=true] - Collapse multiple spaces/tabs into one space.
2491
- * @param {boolean} [options.removeNewlines=false] - If true, replaces newlines with spaces.
2492
- * @param {boolean} [options.trim=true] - If true, trims leading/trailing whitespace.
2541
+ * @param {object} [options] - Configuration options.
2542
+ * @param {boolean} [options.normalizeWhitespace] - Collapse multiple spaces/tabs into one space.
2543
+ * @param {boolean} [options.removeNewlines] - If true, replaces newlines with spaces.
2544
+ * @param {boolean} [options.trim] - If true, trims leading/trailing whitespace.
2545
+ * @param {boolean} [options.debug] - If true, logs debug information about removed characters.
2493
2546
  * @returns {string} The sanitized string.
2494
2547
  */
2495
2548
  function sanitizeText(input, options = {}) {
@@ -2497,7 +2550,8 @@ function sanitizeText(input, options = {}) {
2497
2550
  normalizeWhitespace = true,
2498
2551
  removeNewlines = false,
2499
2552
  trim = true,
2500
- preserveBasicWhitespace = true, // new option to keep tabs, newlines if removeNewlines=false
2553
+ preserveBasicWhitespace = true,
2554
+ debug = false, // new option for debugging
2501
2555
  } = options
2502
2556
 
2503
2557
  if (typeof input !== 'string') {
@@ -2506,27 +2560,106 @@ function sanitizeText(input, options = {}) {
2506
2560
 
2507
2561
  let result = input
2508
2562
 
2563
+ if (debug) {
2564
+ console.log('Original input:', JSON.stringify(input))
2565
+ console.log('Options:', { normalizeWhitespace, removeNewlines, trim, preserveBasicWhitespace })
2566
+ }
2567
+
2509
2568
  // Phase 1: Remove all control characters except basic whitespace if requested
2510
2569
  if (preserveBasicWhitespace && !removeNewlines) {
2511
- // Keep tab (\t), newline (\n), carriage return (\r)
2512
- result = result.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g, '')
2570
+ if (debug) {
2571
+ const before = result
2572
+ const matches = []
2573
+ // Use a replacer function to capture what's being removed
2574
+ result = result.replace(/[\x00-\x08\v\f\x0E-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g, (match) => {
2575
+ matches.push({
2576
+ char: match,
2577
+ code: match.charCodeAt(0),
2578
+ hex: `0x${match.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0')}`
2579
+ })
2580
+ return ''
2581
+ })
2582
+ if (matches.length > 0) {
2583
+ console.log('Phase 1 (preserve mode) - Removed characters:')
2584
+ matches.forEach((m) => {
2585
+ console.log(` - Character: ${JSON.stringify(m.char)}, Code: ${m.code}, Hex: ${m.hex}`)
2586
+ })
2587
+ console.log(`Removed ${matches.length} control character(s)`)
2588
+ } else {
2589
+ console.log('Phase 1 (preserve mode) - No control characters found')
2590
+ }
2591
+ } else {
2592
+ result = result.replace(/[\x00-\x08\v\f\x0E-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g, '')
2593
+ }
2513
2594
  } else {
2514
- // Remove all control characters including basic whitespace
2515
- result = result.replace(/[\x00-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g, '')
2595
+ if (debug) {
2596
+ const before = result
2597
+ const matches = []
2598
+ result = result.replace(/[\x00-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g, (match) => {
2599
+ matches.push({
2600
+ char: match,
2601
+ code: match.charCodeAt(0),
2602
+ hex: `0x${match.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0')}`
2603
+ })
2604
+ return ''
2605
+ })
2606
+ if (matches.length > 0) {
2607
+ console.log('Phase 1 (full removal mode) - Removed characters:')
2608
+ matches.forEach((m) => {
2609
+ console.log(` - Character: ${JSON.stringify(m.char)}, Code: ${m.code}, Hex: ${m.hex}`)
2610
+ })
2611
+ console.log(`Removed ${matches.length} control character(s)`)
2612
+ } else {
2613
+ console.log('Phase 1 (full removal mode) - No control characters found')
2614
+ }
2615
+ } else {
2616
+ result = result.replace(/[\x00-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g, '')
2617
+ }
2618
+ }
2619
+
2620
+ if (debug) {
2621
+ console.log('After Phase 1:', JSON.stringify(result))
2516
2622
  }
2517
2623
 
2518
2624
  // Phase 2: Handle whitespace transformations
2519
2625
  if (removeNewlines) {
2520
- result = result.replace(/[\r\n]+/g, ' ') // Convert newlines to spaces
2626
+ if (debug) {
2627
+ const before = result
2628
+ result = result.replace(/[\r\n]+/g, ' ')
2629
+ console.log('Phase 2 - Converted newlines to spaces')
2630
+ } else {
2631
+ result = result.replace(/[\r\n]+/g, ' ')
2632
+ }
2521
2633
  }
2522
2634
 
2523
2635
  if (normalizeWhitespace) {
2524
- result = result.replace(/[ \t]+/g, ' ') // Collapse spaces/tabs to single space
2636
+ if (debug) {
2637
+ const before = result
2638
+ result = result.replace(/[ \t]+/g, ' ')
2639
+ console.log('Phase 2 - Normalized whitespace')
2640
+ } else {
2641
+ result = result.replace(/[ \t]+/g, ' ')
2642
+ }
2643
+ }
2644
+
2645
+ if (debug) {
2646
+ console.log('After Phase 2:', JSON.stringify(result))
2525
2647
  }
2526
2648
 
2527
2649
  // Phase 3: Final trimming
2528
2650
  if (trim) {
2529
- result = result.trim()
2651
+ if (debug) {
2652
+ const before = result
2653
+ result = result.trim()
2654
+ console.log('Phase 3 - Trimmed leading/trailing whitespace')
2655
+ } else {
2656
+ result = result.trim()
2657
+ }
2658
+ }
2659
+
2660
+ if (debug) {
2661
+ console.log('Final result:', JSON.stringify(result))
2662
+ console.log('--- Sanitization complete ---')
2530
2663
  }
2531
2664
 
2532
2665
  return result
@@ -2537,12 +2670,12 @@ function sanitizeText(input, options = {}) {
2537
2670
 
2538
2671
  ;// ./lib/helpers/shuffleArray/shuffleArray.js
2539
2672
  function shuffleArray(array) {
2540
- const arr = [...array];
2541
- for (let i = arr.length - 1; i >= 0; i--) { // Changed `i > 0` to `i >= 0`
2673
+ const arr = [...array]
2674
+ for (let i = arr.length - 1; i >= 0; i--) { // Changed `i > 0` to `i >= 0`
2542
2675
  const j = Math.floor(Math.random() * (i + 1));
2543
- [arr[i], arr[j]] = [arr[j], arr[i]];
2676
+ [arr[i], arr[j]] = [arr[j], arr[i]]
2544
2677
  }
2545
- return arr;
2678
+ return arr
2546
2679
  }
2547
2680
 
2548
2681
  ;// ./lib/helpers/shuffleArray/index.js
@@ -2604,7 +2737,7 @@ function indexCharset(str) {
2604
2737
  for (let i = 0; i < length; i++) {
2605
2738
  char = str[i]
2606
2739
  byCode[i] = char
2607
- byChar[char] = i;
2740
+ byChar[char] = i
2608
2741
  }
2609
2742
  return { byCode, byChar, length }
2610
2743
  }
@@ -2635,7 +2768,7 @@ function randomString({ len = 16, pattern = 'a1' } = {}) {
2635
2768
  str += mark
2636
2769
  }
2637
2770
  const chars = [...str]
2638
- return [...Array(len)].map(i => {
2771
+ return [...new Array(len)].map((i) => {
2639
2772
  return chars[(Math.random() * chars.length) | 0]
2640
2773
  }).join``
2641
2774
  }
@@ -2659,12 +2792,14 @@ function setCode(base = 34) {
2659
2792
  }
2660
2793
 
2661
2794
  function toCamelCase(str) {
2662
- if (!str) return ''
2795
+ if (!str)
2796
+ return ''
2663
2797
  return str
2664
2798
  .trim()
2665
2799
  .split(/\s+/)
2666
2800
  .map((word, index) => {
2667
- if (!word) return ''
2801
+ if (!word)
2802
+ return ''
2668
2803
  if (index === 0) {
2669
2804
  return word.toLowerCase()
2670
2805
  }
@@ -2674,7 +2809,8 @@ function toCamelCase(str) {
2674
2809
  }
2675
2810
 
2676
2811
  function toLowerCase(str) {
2677
- if (!str) return ''
2812
+ if (!str)
2813
+ return ''
2678
2814
  return str
2679
2815
  .trim()
2680
2816
  .toLowerCase()
@@ -2709,7 +2845,7 @@ function trackingPlugin(schema, options) {
2709
2845
  })
2710
2846
 
2711
2847
  // Auto-update hook
2712
- schema.pre('save', function(next) {
2848
+ schema.pre('save', function (next) {
2713
2849
  this.meta.modified = Date.now()
2714
2850
  next()
2715
2851
  })
@@ -2721,9 +2857,9 @@ function trackingPlugin(schema, options) {
2721
2857
  }, {
2722
2858
  name: 'tracking_status_index',
2723
2859
  background: true,
2724
- partialFilterExpression: {
2860
+ partialFilterExpression: {
2725
2861
  'meta.active': true,
2726
- 'meta.deleted': false
2862
+ 'meta.deleted': false
2727
2863
  }
2728
2864
  })
2729
2865
 
@@ -2752,7 +2888,7 @@ function tenantPlugin(schema, options) {
2752
2888
 
2753
2889
  // Add core indexes
2754
2890
  schema.index({
2755
- 'tenantCode': 1
2891
+ tenantCode: 1
2756
2892
  }, {
2757
2893
  name: 'tenant_core_index',
2758
2894
  background: true
@@ -2760,15 +2896,15 @@ function tenantPlugin(schema, options) {
2760
2896
 
2761
2897
  // 1. ENHANCE EXISTING TRACKING INDEXES
2762
2898
  const existingIndexes = schema.indexes()
2763
-
2899
+
2764
2900
  // Check if tracking_status_index exists
2765
- const hasTenantStatusIndex = existingIndexes.some(idx =>
2901
+ const hasTenantStatusIndex = existingIndexes.some((idx) =>
2766
2902
  idx.name === 'tenant_status_index' // Check by name for reliability
2767
2903
  )
2768
2904
 
2769
2905
  if (!hasTenantStatusIndex) {
2770
2906
  schema.index({
2771
- 'tenantCode': 1, // Unique field first
2907
+ tenantCode: 1, // Unique field first
2772
2908
  _type: 1, // Low-cardinality field last
2773
2909
  }, {
2774
2910
  name: 'tenant_status_index',
@@ -2776,7 +2912,7 @@ function tenantPlugin(schema, options) {
2776
2912
  partialFilterExpression: {
2777
2913
  '_type': 'Tenant',
2778
2914
  'meta.active': true,
2779
- 'meta.deleted': false
2915
+ 'meta.deleted': false
2780
2916
  }
2781
2917
  })
2782
2918
  }
@@ -2815,6 +2951,7 @@ function tenantPlugin(schema, options) {
2815
2951
 
2816
2952
 
2817
2953
 
2954
+
2818
2955
 
2819
2956
 
2820
2957
  ;// ./lib/models/apiResponse/index.js
@@ -2872,10 +3009,11 @@ class AwsStsS3Client {
2872
3009
  }
2873
3010
 
2874
3011
  get isExpired() {
2875
- if (!this.expiration) return true;
2876
- const now = new Date();
2877
- const bufferMs = 1 * 60 * 1000; // 一分钟缓冲
2878
- return now >= new Date(this.expiration.getTime() - bufferMs);
3012
+ if (!this.expiration)
3013
+ return true
3014
+ const now = new Date()
3015
+ const bufferMs = 1 * 60 * 1000 // 一分钟缓冲
3016
+ return now >= new Date(this.expiration.getTime() - bufferMs)
2879
3017
  }
2880
3018
 
2881
3019
  get isValid() {
@@ -2910,7 +3048,7 @@ class AwsStsS3Client {
2910
3048
  throw new Error(`Missing ${component} in AWS awsClientS3 client configuration`)
2911
3049
  }
2912
3050
  }
2913
-
3051
+
2914
3052
  return true
2915
3053
  }
2916
3054
 
@@ -2920,9 +3058,9 @@ class AwsStsS3Client {
2920
3058
  if (!webIdentityToken) {
2921
3059
  throw new Error('getIdToken function returned empty or invalid token')
2922
3060
  }
2923
-
3061
+
2924
3062
  const stsClient = new this.awsClientSts.STSClient({ region: this.region })
2925
-
3063
+
2926
3064
  const stsResponse = await stsClient.send(
2927
3065
  new this.awsClientSts.AssumeRoleWithWebIdentityCommand({
2928
3066
  RoleArn: this.roleArn,
@@ -3229,29 +3367,30 @@ class KeyValueObject {
3229
3367
  }
3230
3368
 
3231
3369
  function _mergeValues(existingValue, newValue) {
3232
- if (existingValue === undefined) return newValue
3233
-
3370
+ if (existingValue === undefined)
3371
+ return newValue
3372
+
3234
3373
  // Handle arrays by concatenating
3235
3374
  if (Array.isArray(existingValue) && Array.isArray(newValue)) {
3236
3375
  return [...new Set([...existingValue, ...newValue])]
3237
3376
  }
3238
-
3377
+
3239
3378
  // Handle objects by merging
3240
- if (typeof existingValue === 'object' && typeof newValue === 'object' &&
3241
- !Array.isArray(existingValue) && !Array.isArray(newValue)) {
3379
+ if (typeof existingValue === 'object' && typeof newValue === 'object'
3380
+ && !Array.isArray(existingValue) && !Array.isArray(newValue)) {
3242
3381
  return { ...existingValue, ...newValue }
3243
3382
  }
3244
-
3383
+
3245
3384
  // // Handle numbers by adding
3246
3385
  // if (typeof existingValue === 'number' && typeof newValue === 'number') {
3247
3386
  // return existingValue
3248
3387
  // }
3249
-
3388
+
3250
3389
  // // Handle strings by concatenating
3251
3390
  // if (typeof existingValue === 'string' && typeof newValue === 'string') {
3252
3391
  // return existingValue
3253
3392
  // }
3254
-
3393
+
3255
3394
  // Default: use the new value
3256
3395
  return newValue
3257
3396
  }
@@ -3311,29 +3450,30 @@ function metadata_isSame(key1, key2) {
3311
3450
  }
3312
3451
 
3313
3452
  function metadata_mergeValues(existingValue, newValue) {
3314
- if (existingValue === undefined) return newValue
3315
-
3453
+ if (existingValue === undefined)
3454
+ return newValue
3455
+
3316
3456
  // Handle arrays by concatenating
3317
3457
  if (Array.isArray(existingValue) && Array.isArray(newValue)) {
3318
3458
  return [...new Set([...existingValue, ...newValue])]
3319
3459
  }
3320
-
3460
+
3321
3461
  // Handle objects by merging
3322
- if (typeof existingValue === 'object' && typeof newValue === 'object' &&
3323
- !Array.isArray(existingValue) && !Array.isArray(newValue)) {
3462
+ if (typeof existingValue === 'object' && typeof newValue === 'object'
3463
+ && !Array.isArray(existingValue) && !Array.isArray(newValue)) {
3324
3464
  return { ...existingValue, ...newValue }
3325
3465
  }
3326
-
3466
+
3327
3467
  // // Handle numbers by adding
3328
3468
  // if (typeof existingValue === 'number' && typeof newValue === 'number') {
3329
3469
  // return existingValue
3330
3470
  // }
3331
-
3471
+
3332
3472
  // // Handle strings by concatenating
3333
3473
  // if (typeof existingValue === 'string' && typeof newValue === 'string') {
3334
3474
  // return existingValue
3335
3475
  // }
3336
-
3476
+
3337
3477
  // Default: use the new value
3338
3478
  return newValue
3339
3479
  }
@@ -3354,14 +3494,14 @@ class TrackedEntity {
3354
3494
  const timestamp = Date.now()
3355
3495
  this.meta = {
3356
3496
  active: options.meta?.active ?? options.active ?? true,
3357
- created: options.meta?.created ?? (options.created
3358
- ? new Date(options.created).getTime()
3359
- : timestamp),
3497
+ created: options.meta?.created ?? (options.created
3498
+ ? new Date(options.created).getTime()
3499
+ : timestamp),
3360
3500
  creator: options.meta?.creator ?? options.creator ?? '',
3361
3501
  deleted: options.meta?.deleted ?? options.deleted ?? false,
3362
- modified: options.meta?.modified ?? (options.modified
3363
- ? new Date(options.modified).getTime()
3364
- : timestamp),
3502
+ modified: options.meta?.modified ?? (options.modified
3503
+ ? new Date(options.modified).getTime()
3504
+ : timestamp),
3365
3505
  owner: options.meta?.owner ?? options.owner ?? '',
3366
3506
  }
3367
3507
 
@@ -3528,7 +3668,6 @@ class PushEnvelope extends TrackedEntity {
3528
3668
  get isValid() {
3529
3669
  return super.isValid && this.data
3530
3670
  }
3531
-
3532
3671
  }
3533
3672
 
3534
3673
  ;// ./lib/models/pushEnvelope/index.js
@@ -3595,6 +3734,168 @@ class QMeta {
3595
3734
 
3596
3735
 
3597
3736
 
3737
+ ;// ./lib/models/status/actionRecord.js
3738
+
3739
+
3740
+ class ActionRecord {
3741
+ constructor(options) {
3742
+ options = options || {}
3743
+
3744
+ const { _Actor } = options._constructor || {}
3745
+ this._Actor = _Actor
3746
+
3747
+ this._actor = options._actor
3748
+
3749
+ this.actorCode = typeof options === 'number' ? null : (options.actorCode || null)
3750
+ this.timestamp = typeof options === 'number' ? options : (options.timestamp || null)
3751
+ }
3752
+
3753
+ static get _classname() {
3754
+ return 'ActionRecord'
3755
+ }
3756
+ static get _superclass() {
3757
+ return 'ActionRecord'
3758
+ }
3759
+ static dummyData() {
3760
+ return {
3761
+ timestamp: (new Date()).valueOf(),
3762
+ }
3763
+ }
3764
+ static init(options = {}) {
3765
+ return init(this, options)
3766
+ }
3767
+
3768
+ get _classname() {
3769
+ return 'ActionRecord'
3770
+ }
3771
+
3772
+ get _superclass() {
3773
+ return 'ActionRecord'
3774
+ }
3775
+
3776
+ get actor() {
3777
+ return this._Actor && typeof this._Actor.init === 'function' ? this._Actor.init(this._actor) : this._actor
3778
+ }
3779
+
3780
+ get isValid() {
3781
+ return !!this.timestamp
3782
+ }
3783
+
3784
+ update(update) {
3785
+ if (typeof update === 'number') {
3786
+ this.timestamp = update
3787
+ return this
3788
+ }
3789
+ Object.keys(update).forEach((key) => {
3790
+ this[key] = update[key]
3791
+ })
3792
+ return this
3793
+ }
3794
+ }
3795
+
3796
+ ;// ./lib/models/status/status.js
3797
+
3798
+
3799
+
3800
+ const notUpdateAllowedProps = [
3801
+ 'created',
3802
+ // 'statusType'
3803
+ ]
3804
+
3805
+ class Status {
3806
+ constructor(options) {
3807
+ options = options || {}
3808
+
3809
+ const { _ActionRecord } = options._constructor || {}
3810
+ this._ActionRecord = _ActionRecord && (_ActionRecord._superclass === ActionRecord._superclass) ? _ActionRecord : ActionRecord
3811
+
3812
+ this.created = this._ActionRecord.init(options.created || { timestamp: (new Date()).valueOf() })
3813
+ // this.statusType = options.statusType || 'Status'
3814
+ }
3815
+
3816
+ static get _classname() {
3817
+ return 'Status'
3818
+ }
3819
+ static get _superclass() {
3820
+ return 'Status'
3821
+ }
3822
+ static dummyData() {
3823
+ return {}
3824
+ }
3825
+ static init(options = {}) {
3826
+ return init(this, options)
3827
+ }
3828
+ static initFromArray(arr = []) {
3829
+ return initFromArray(this, arr)
3830
+ }
3831
+ static initOnlyValidFromArray(arr = []) {
3832
+ return initOnlyValidFromArray(this, arr)
3833
+ }
3834
+
3835
+ get _classname() {
3836
+ return 'Status'
3837
+ }
3838
+ get _superclass() {
3839
+ return 'Status'
3840
+ }
3841
+ get isCreated() {
3842
+ return this.created?.timestamp !== null
3843
+ }
3844
+ get isValid() {
3845
+ return !!this
3846
+ }
3847
+
3848
+ setValue(t, actorCode, key) {
3849
+ const timestamp = t || Date.now()
3850
+ this[key] = this[key] instanceof this._ActionRecord ? this[key].update({ actorCode, timestamp }) : this._ActionRecord.init({ actorCode, timestamp })
3851
+ return this
3852
+ }
3853
+
3854
+ update(update) {
3855
+ Object.keys(update).forEach((key) => {
3856
+ if (!notUpdateAllowedProps.includes(key)) {
3857
+ this[key] = this[key] instanceof this._ActionRecord ? this[key].update(update[key]) : this._ActionRecord.init(update[key])
3858
+ }
3859
+ })
3860
+ return this
3861
+ }
3862
+ }
3863
+
3864
+ ;// ./lib/models/status/statusDocument.js
3865
+
3866
+
3867
+ class StatusDocument extends Status {
3868
+ constructor(options) {
3869
+ options = options || {}
3870
+ super(options)
3871
+
3872
+ this.archived = this._ActionRecord.init(options.archived)
3873
+ this.completed = this._ActionRecord.init(options.completed)
3874
+ this.drafted = this._ActionRecord.init(options.drafted)
3875
+ this.discarded = this._ActionRecord.init(options.discarded)
3876
+ // this.statusType = 'StatusDocument'
3877
+ }
3878
+
3879
+ get isValid() {
3880
+ return super.isValid
3881
+ }
3882
+
3883
+ static get _classname() {
3884
+ return 'StatusDocument'
3885
+ }
3886
+ setArchived(value, actorCode) {
3887
+ // const timestamp = value || Date.now()
3888
+ // this.archived = this.archived instanceof this._ActionRecord ? this.archived.update({ actorCode, timestamp }) : this._ActionRecord.init({ actorCode, timestamp })
3889
+ // return this
3890
+ return this.setValue(value, actorCode, 'archived')
3891
+ }
3892
+ }
3893
+
3894
+ ;// ./lib/models/status/index.js
3895
+
3896
+
3897
+
3898
+
3598
3899
  ;// ./lib/models/tenantAwareEntity/tenantAwareEntity.js
3599
3900
 
3600
3901
 
@@ -3735,6 +4036,7 @@ function _makeSetCode(fieldName, options) {
3735
4036
 
3736
4037
 
3737
4038
 
4039
+
3738
4040
  ;// ./lib/index.js
3739
4041
 
3740
4042