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