@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.
@@ -24,14 +24,14 @@ function authorize({ allowCoordinator, allowOwner, query = {}, required, user })
24
24
  if (query.registrationGroupCode && user.myManagedRegistrationGroupCodes.includes(query.registrationGroupCode)) {
25
25
  query.__ALLOW_COORDINATOR = true
26
26
  } else {
27
- if (!scopes.includes('EVENT')) {
28
- query.eventRegistrationCode = user.eventRegistrationCode
29
- }
30
- }
31
- } else {
32
27
  if (!scopes.includes('EVENT')) {
33
28
  query.eventRegistrationCode = user.eventRegistrationCode
34
29
  }
30
+ }
31
+ } else {
32
+ if (!scopes.includes('EVENT')) {
33
+ query.eventRegistrationCode = user.eventRegistrationCode
34
+ }
35
35
  }
36
36
  if (allowOwner) {
37
37
  query.__ALLOW_OWNER = true
@@ -63,14 +63,14 @@ function calculateAge(timestamp, reference) {
63
63
  }
64
64
 
65
65
  // Calculate raw difference
66
- let age = refDate.getFullYear() - birthDate.getFullYear();
67
- const monthDiff = refDate.getMonth() - birthDate.getMonth();
68
-
66
+ let age = refDate.getFullYear() - birthDate.getFullYear()
67
+ const monthDiff = refDate.getMonth() - birthDate.getMonth()
68
+
69
69
  // Adjust if birthday hasn't occurred yet this year
70
70
  if (monthDiff < 0 || (monthDiff === 0 && refDate.getDate() < birthDate.getDate())) {
71
71
  age--
72
72
  }
73
-
73
+
74
74
  return age
75
75
  }
76
76
 
@@ -100,7 +100,18 @@ function changeCreatorOwner(that, { source, target }) {
100
100
  ;// ./lib/helpers/changeCreatorOwner/index.js
101
101
 
102
102
 
103
+ ;// ./lib/helpers/isConvertibleToNumber/isConvertibleToNumber.js
104
+ function isConvertibleToNumber(value) {
105
+ return value !== null
106
+ && value !== undefined
107
+ && typeof value !== 'boolean'
108
+ && String(value).trim() !== ''
109
+ && !isNaN(Number(value))
110
+ }
111
+
103
112
  ;// ./lib/helpers/getValidation/getValidation.js
113
+
114
+
104
115
  function getValidation(rule, data, getDataByKey, KeyValueObject) {
105
116
  if (!rule) {
106
117
  return true
@@ -114,10 +125,10 @@ function getValidation(rule, data, getDataByKey, KeyValueObject) {
114
125
  if (!key && typeof placeholder === 'undefined') {
115
126
  switch (valueAttribute) {
116
127
  case '$and': {
117
- return value['$and'].reduce((acc, item) => (acc && getValidation(item, data, getDataByKey, KeyValueObject)), true)
128
+ return value.$and.reduce((acc, item) => (acc && getValidation(item, data, getDataByKey, KeyValueObject)), true)
118
129
  }
119
130
  case '$or': {
120
- return value['$or'].reduce((acc, item) => (acc || getValidation(item, data, getDataByKey, KeyValueObject)), false)
131
+ return value.$or.reduce((acc, item) => (acc || getValidation(item, data, getDataByKey, KeyValueObject)), false)
121
132
  }
122
133
  default:
123
134
  return false
@@ -132,39 +143,53 @@ function getValidation(rule, data, getDataByKey, KeyValueObject) {
132
143
  }
133
144
 
134
145
  switch (valueAttribute) {
146
+ case '$after': {
147
+ if (isConvertibleToNumber(value?.$after)) {
148
+ const _value = Number(String(value?.$after))
149
+ return Date.now() > _value
150
+ }
151
+ return false
152
+ }
153
+ case '$before': {
154
+ if (isConvertibleToNumber(value?.$before)) {
155
+ const _value = Number(String(value?.$before))
156
+ return Date.now() < _value
157
+ }
158
+ return false
159
+ }
135
160
  case '$empty': {
136
161
  const isEmpty = rowValue === null || rowValue === undefined
137
- return isEmpty === value['$empty']
162
+ return isEmpty === value.$empty
138
163
  }
139
164
  case '$eq': {
140
- return rowValue === value['$eq']
165
+ return rowValue === value.$eq
141
166
  }
142
167
  case '$gt': {
143
- return rowValue > value['$gt']
168
+ return rowValue > value.$gt
144
169
  }
145
170
  case '$gte': {
146
- return rowValue >= value['$gte']
171
+ return rowValue >= value.$gte
147
172
  }
148
173
  case '$hasOverlap': {
149
- return _hasOverlap(rowValue, value['$hasOverlap'])
174
+ return _hasOverlap(rowValue, value.$hasOverlap)
150
175
  }
151
176
  case '$lt': {
152
- return rowValue < value['$lt']
177
+ return rowValue < value.$lt
153
178
  }
154
179
  case '$lte': {
155
- return rowValue <= value['$lte']
180
+ return rowValue <= value.$lte
156
181
  }
157
182
  case '$in': {
158
183
  if (Array.isArray(rowValue)) {
159
- return !!rowValue.find((e) => (value['$in'].includes(e)))
184
+ return !!rowValue.find((e) => (value.$in.includes(e)))
160
185
  }
161
186
  if (typeof rowValue !== 'object') {
162
- return !!value['$in'].includes(rowValue)
187
+ return !!value.$in.includes(rowValue)
163
188
  }
164
189
  return false
165
190
  }
166
191
  case '$inValue': {
167
- const result = getDataByKey(value['$inValue'], data)
192
+ const result = getDataByKey(value.$inValue, data)
168
193
  const _value = Array.isArray(result) ? result : []
169
194
  if (Array.isArray(rowValue)) {
170
195
  return !!rowValue.find((e) => (_value.includes(e)))
@@ -175,36 +200,36 @@ function getValidation(rule, data, getDataByKey, KeyValueObject) {
175
200
  return false
176
201
  }
177
202
  case '$ne': {
178
- return rowValue !== value['$ne']
203
+ return rowValue !== value.$ne
179
204
  }
180
205
  case '$notIn': {
181
206
  if (Array.isArray(rowValue)) {
182
- return !rowValue.find((e) => (value['$notIn'].includes(e)))
207
+ return !rowValue.find((e) => (value.$notIn.includes(e)))
183
208
  }
184
209
  if (typeof rowValue !== 'object') {
185
- return !value['$notIn'].includes(rowValue)
210
+ return !value.$notIn.includes(rowValue)
186
211
  }
187
212
  return false
188
213
  }
189
214
  case '$intervalTimeGt': {
190
215
  const now = new Date().getTime()
191
216
  const timestamp = new Date(rowValue).getTime()
192
- return (now - timestamp) > value['$intervalTimeGt']
217
+ return (now - timestamp) > value.$intervalTimeGt
193
218
  }
194
219
  case '$intervalTimeLt': {
195
220
  const now = new Date().getTime()
196
221
  const timestamp = new Date(rowValue).getTime()
197
- return (now - timestamp) < value['$intervalTimeLt']
222
+ return (now - timestamp) < value.$intervalTimeLt
198
223
  }
199
224
  case '$isToday': {
200
225
  const currentDate = new Date()
201
- const start = currentDate.setHours(0,0,0,0)
202
- const end = currentDate.setHours(23,59,59,59)
226
+ const start = currentDate.setHours(0, 0, 0, 0)
227
+ const end = currentDate.setHours(23, 59, 59, 59)
203
228
  const dateValue = new Date(rowValue).getTime()
204
- return (start <= dateValue && end >= dateValue) === value['$isToday']
229
+ return (start <= dateValue && end >= dateValue) === value.$isToday
205
230
  }
206
231
  case '$notInValue': {
207
- const result = getDataByKey(value['$notInValue'], data)
232
+ const result = getDataByKey(value.$notInValue, data)
208
233
  const _value = Array.isArray(result) ? result : []
209
234
  if (Array.isArray(rowValue)) {
210
235
  return !rowValue.find((e) => (_value.includes(e)))
@@ -215,7 +240,7 @@ function getValidation(rule, data, getDataByKey, KeyValueObject) {
215
240
  return false
216
241
  }
217
242
  case '$range': {
218
- const [min, max] = value['$range']
243
+ const [min, max] = value.$range
219
244
  if (typeof min === 'number' && typeof max === 'number' && rowValue >= min && rowValue <= max) {
220
245
  return true
221
246
  }
@@ -224,7 +249,6 @@ function getValidation(rule, data, getDataByKey, KeyValueObject) {
224
249
  default:
225
250
  return false
226
251
  }
227
-
228
252
  }
229
253
 
230
254
  function _hasOverlap(item1, item2) {
@@ -249,12 +273,11 @@ function _hasOverlap(item1, item2) {
249
273
 
250
274
 
251
275
  ;// ./lib/helpers/formatDate/formatDate.js
252
-
253
276
  function formatDate(date, format) {
254
277
  const _date = date && date instanceof Date ? date : new Date(date)
255
- const dayMapChi = ['日','一','二','三','四','五','六']
256
- const dayMapEng = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday']
257
- const dayMapEngShort = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
278
+ const dayMapChi = ['日', '一', '二', '三', '四', '五', '六']
279
+ const dayMapEng = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
280
+ const dayMapEngShort = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
258
281
  const _format = format || 'YYYY/MM/DD hh:mm'
259
282
  const e = _date.getDay()
260
283
  const ee = dayMapEngShort[e]
@@ -289,13 +312,11 @@ function padding(m) {
289
312
  return m < 10 ? `0${m}` : m
290
313
  }
291
314
 
292
-
293
315
  /* harmony default export */ const formatDate_formatDate = ({
294
316
  formatDate
295
317
  });
296
318
 
297
319
 
298
-
299
320
  ;// ./lib/helpers/formatDate/index.js
300
321
 
301
322
 
@@ -326,7 +347,6 @@ function getValueByKeys_getValueByKeys(keys, data) {
326
347
  return _data[firstKey]
327
348
  }
328
349
  return _data
329
-
330
350
  }
331
351
  /* harmony default export */ const getValueByKeys = ({
332
352
  getValueByKeys: getValueByKeys_getValueByKeys
@@ -378,6 +398,7 @@ const _FN_NAMES = [
378
398
  'map',
379
399
  'neq',
380
400
  'removeHtml',
401
+ 'sum',
381
402
  'toLowerCase',
382
403
  'toUpperCase',
383
404
  ]
@@ -530,10 +551,12 @@ function _existObject(data, args) {
530
551
 
531
552
  function _performOperation(arg, value) {
532
553
  // the arg is undefined
533
- if (arg === undefined && value === undefined) return true
554
+ if (arg === undefined && value === undefined)
555
+ return true
534
556
 
535
557
  // the arg is null
536
- if (arg === null && value === null) return true
558
+ if (arg === null && value === null)
559
+ return true
537
560
 
538
561
  // the arg is boolean
539
562
  if (typeof arg === 'boolean') {
@@ -609,17 +632,18 @@ function _splitOperator(str) {
609
632
  const operators = ['!=', '>=', '<=', '>', '<']
610
633
 
611
634
  const matchedOp = operators.find((op) => str.startsWith(op))
612
- if (!matchedOp) return { operator: null, value: null }
635
+ if (!matchedOp)
636
+ return { operator: null, value: null }
613
637
 
614
638
  const remaining = str.slice(matchedOp.length)
615
639
 
616
640
  // '>Primary' or '<Primary' is invalid
617
- if (/^[a-zA-Z]*$/.test(remaining) && matchedOp !== '!=') {
641
+ if (/^[a-z]*$/i.test(remaining) && matchedOp !== '!=') {
618
642
  return { operator: null, value: null }
619
643
  }
620
644
 
621
645
  // if it is a number it is converted to a number
622
- const value = (!Number.isNaN(parseFloat(remaining)) && !Number.isNaN(remaining)) ? Number(remaining) : remaining
646
+ const value = (!Number.isNaN(Number.parseFloat(remaining)) && !Number.isNaN(remaining)) ? Number(remaining) : remaining
623
647
 
624
648
  return {
625
649
  operator: matchedOp,
@@ -831,11 +855,14 @@ function _isNotEmpty(data, args) {
831
855
  }
832
856
 
833
857
 
858
+
834
859
  ;// ./lib/models/templateCompiler/helpers/_join.js
835
860
  function _join(data, delimiter) {
836
861
  try {
837
- if (data.length === 0) return ''
838
- if (data.length === 1) return _stringifyObject(data[0])
862
+ if (data.length === 0)
863
+ return ''
864
+ if (data.length === 1)
865
+ return _stringifyObject(data[0])
839
866
  return data.map((item) => _stringifyObject(item)).join(delimiter)
840
867
  } catch (e) {
841
868
  throw e
@@ -982,13 +1009,13 @@ function _removeHtml(html, args) {
982
1009
 
983
1010
  function _htmlToPlainText(html, delimiter = '\n') {
984
1011
  if (typeof delimiter !== 'string') {
985
- delimiter = '\n'; // Fallback to default if not a string
1012
+ delimiter = '\n' // Fallback to default if not a string
986
1013
  }
987
1014
 
988
1015
  // First decode HTML entities and normalize whitespace
989
1016
  const decodedHtml = html
990
1017
  .replace(/&nbsp;/g, ' ')
991
- .replace(/\s+/g, ' '); // Collapse all whitespace to single spaces
1018
+ .replace(/\s+/g, ' ') // Collapse all whitespace to single spaces
992
1019
 
993
1020
  // Process HTML tags
994
1021
  let text = decodedHtml
@@ -999,29 +1026,36 @@ function _htmlToPlainText(html, delimiter = '\n') {
999
1026
  // Remove all other tags
1000
1027
  .replace(/<[^>]+>/g, '')
1001
1028
  // Convert markers to specified delimiter
1002
- .replace(/~~~+/g, delimiter)
1029
+ .replace(/~{3,}/g, delimiter)
1003
1030
  // Trim and clean whitespace
1004
- .trim();
1031
+ .trim()
1005
1032
 
1006
1033
  // Special handling for empty delimiter
1007
1034
  if (delimiter === '') {
1008
1035
  // Collapse all whitespace to single space
1009
- text = text.replace(/\s+/g, ' ');
1036
+ text = text.replace(/\s+/g, ' ')
1010
1037
  } else {
1011
-
1012
-
1013
1038
  // Collapse multiple delimiters to single
1014
- text = text.replace(new RegExp(`${escapeRegExp(delimiter)}+`, 'g'), delimiter);
1039
+ text = text.replace(new RegExp(`${escapeRegExp(delimiter)}+`, 'g'), delimiter)
1015
1040
  // Remove leading/trailing delimiters
1016
- text = text.replace(new RegExp(`^${escapeRegExp(delimiter)}|${escapeRegExp(delimiter)}$`, 'g'), '');
1041
+ text = text.replace(new RegExp(`^${escapeRegExp(delimiter)}|${escapeRegExp(delimiter)}$`, 'g'), '')
1017
1042
  }
1018
1043
 
1019
- return text;
1044
+ return text
1020
1045
  }
1021
1046
 
1022
-
1023
1047
  function escapeRegExp(string) {
1024
- return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1048
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
1049
+ }
1050
+
1051
+
1052
+
1053
+ ;// ./lib/models/templateCompiler/helpers/_sum.js
1054
+ function _sum(data, args) {
1055
+ if (Number.isNaN(data) || data === null || (typeof data === 'undefined') || data === '') {
1056
+ return data
1057
+ }
1058
+ return args.reduce((acc, e) => (acc + e), data)
1025
1059
  }
1026
1060
 
1027
1061
 
@@ -1081,6 +1115,7 @@ function _toUpperCase(data, args) {
1081
1115
 
1082
1116
 
1083
1117
 
1118
+
1084
1119
 
1085
1120
 
1086
1121
  ;// ./lib/models/templateCompiler/templateCompiler.js
@@ -1154,6 +1189,9 @@ class TemplateCompiler {
1154
1189
  static removeHtml(data, args) {
1155
1190
  return _removeHtml(data, args)
1156
1191
  }
1192
+ static sum(data, args) {
1193
+ return _sum(data, args)
1194
+ }
1157
1195
  static toLowerCase(data, args) {
1158
1196
  return _toLowerCase(data, args)
1159
1197
  }
@@ -1214,7 +1252,7 @@ function _parseFunction(expression, existFunctionNames) {
1214
1252
 
1215
1253
  function _parseParams(parameters) {
1216
1254
  const _parameters = parameters.trim()
1217
- const regExp = new RegExp(/^[^\w\d\s]+$/)
1255
+ const regExp = new RegExp(/^[^\w\s]+$/)
1218
1256
  const match = _parameters.match(regExp)
1219
1257
  if (match !== null) {
1220
1258
  return [_parameters.substring(1, _parameters.length - 1)]
@@ -1229,13 +1267,13 @@ function _parseParams(parameters) {
1229
1267
 
1230
1268
  function _splitIgnoringBrackets(input) {
1231
1269
  const regExp2 = new RegExp(/^\d+(\.\d+)?$/)
1232
- const regExp = new RegExp(/(?![^\[]*\])\s*,\s*/)
1270
+ const regExp = new RegExp(/(?![^[]*\])\s*,\s*/)
1233
1271
  const parts = input.split(regExp)
1234
1272
  return parts.map((part) => {
1235
1273
  const _part = part.trim()
1236
1274
  if (_part !== '' && !!_part.match(regExp2)) {
1237
1275
  // 如果是数字,转换为 num 类型
1238
- return Number.isNaN(_part) ? _part : parseInt(_part, 10)
1276
+ return Number.isNaN(_part) ? _part : Number.parseInt(_part, 10)
1239
1277
  }
1240
1278
  // 否则当作字符串处理
1241
1279
  return _part
@@ -1248,7 +1286,7 @@ function _parseSinglePart(input) {
1248
1286
  // 去掉双引号,返回
1249
1287
  return input.substring(1, input.length - 1)
1250
1288
  }
1251
- if (input.startsWith("'") && input.endsWith("'")) {
1289
+ if (input.startsWith('\'') && input.endsWith('\'')) {
1252
1290
  // 去掉双引号,返回
1253
1291
  return input.substring(1, input.length - 1)
1254
1292
  }
@@ -1279,7 +1317,7 @@ function _toBasicType(input) {
1279
1317
  // 去掉双引号,返回
1280
1318
  return input.substring(1, input.length - 1)
1281
1319
  }
1282
- if (input.startsWith("'") && input.endsWith("'")) {
1320
+ if (input.startsWith('\'') && input.endsWith('\'')) {
1283
1321
  // 去掉双引号,返回
1284
1322
  return input.substring(1, input.length - 1)
1285
1323
  }
@@ -1347,6 +1385,8 @@ function _callFunction(data, functionName, parameters) {
1347
1385
  return _neq(data, parameters)
1348
1386
  case 'removeHtml':
1349
1387
  return _removeHtml(data, parameters)
1388
+ case 'sum':
1389
+ return _sum(data, parameters)
1350
1390
  case 'toLowerCase':
1351
1391
  return _toLowerCase(data)
1352
1392
  case 'toUpperCase':
@@ -1376,14 +1416,14 @@ function concatStringByArray(arrTemplate, data) {
1376
1416
  return arrTemplate.reduce((acc, item) => {
1377
1417
  const { type, value = '', restriction, template, format, showMinutes } = item
1378
1418
  switch (type) {
1379
- case('array'): {
1419
+ case ('array'): {
1380
1420
  if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
1381
1421
  const _value = getValueByKeys_getValueByKeys(value.split('.'), data) || []
1382
1422
  acc += _value.reduce((_acc, item) => {
1383
1423
  return _acc += concatStringByArray(template, item)
1384
1424
  }, '')
1385
1425
  }
1386
- break
1426
+ break
1387
1427
  }
1388
1428
  case ('date'): {
1389
1429
  if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
@@ -1392,7 +1432,7 @@ function concatStringByArray(arrTemplate, data) {
1392
1432
  }
1393
1433
  break
1394
1434
  }
1395
- case('ellipsis'): {
1435
+ case ('ellipsis'): {
1396
1436
  if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
1397
1437
  const { maxLength } = item
1398
1438
  const _value = getValueByKeys_getValueByKeys(value.split('.'), data) || ''
@@ -1402,15 +1442,15 @@ function concatStringByArray(arrTemplate, data) {
1402
1442
  acc += `${_value.substr(0, maxLength)}...`
1403
1443
  }
1404
1444
  }
1405
- break
1445
+ break
1406
1446
  }
1407
- case('group'): {
1447
+ case ('group'): {
1408
1448
  if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
1409
1449
  return concatStringByArray(value, data)
1410
1450
  }
1411
1451
  break
1412
1452
  }
1413
- case('label'): {
1453
+ case ('label'): {
1414
1454
  if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
1415
1455
  acc += (value.toString())
1416
1456
  }
@@ -1423,12 +1463,12 @@ function concatStringByArray(arrTemplate, data) {
1423
1463
  }
1424
1464
  break
1425
1465
  }
1426
- case('value'): {
1466
+ case ('value'): {
1427
1467
  if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
1428
1468
  const _value = getValueByKeys_getValueByKeys(value.split('.'), data) || ''
1429
1469
  acc += (_value.toString())
1430
1470
  }
1431
- break
1471
+ break
1432
1472
  }
1433
1473
  }
1434
1474
  return acc
@@ -1439,7 +1479,6 @@ function concatStringByArray(arrTemplate, data) {
1439
1479
  });
1440
1480
 
1441
1481
 
1442
-
1443
1482
  ;// ./lib/helpers/concatStringByArray/index.js
1444
1483
 
1445
1484
 
@@ -1450,7 +1489,7 @@ function convertString(string, patternMatch = /\$\{(.+?)\}/g, value, getValueByK
1450
1489
  if (!string) {
1451
1490
  return ''
1452
1491
  }
1453
- let _getValueByKeys = typeof getValueByKeys === 'function' ? getValueByKeys : getValueByKeys_getValueByKeys
1492
+ const _getValueByKeys = typeof getValueByKeys === 'function' ? getValueByKeys : getValueByKeys_getValueByKeys
1454
1493
  const reg = new RegExp(patternMatch, 'g')
1455
1494
  return string.replace(reg, (match, key) => {
1456
1495
  const result = _getValueByKeys({ keys: key.split('.'), obj: value })
@@ -1471,7 +1510,7 @@ function convertString(string, patternMatch = /\$\{(.+?)\}/g, value, getValueByK
1471
1510
 
1472
1511
  ;// ./lib/helpers/escapeRegex/escapeRegex.js
1473
1512
  function escapeRegex(string) {
1474
- return String(string).replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')
1513
+ return String(string).replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
1475
1514
  }
1476
1515
 
1477
1516
  ;// ./lib/helpers/escapeRegex/index.js
@@ -1574,7 +1613,6 @@ function updateOneResult({ responseHelper, service }) {
1574
1613
 
1575
1614
 
1576
1615
 
1577
-
1578
1616
  const expressHelper = {
1579
1617
  customHandler: customHandler,
1580
1618
  findAllResult: findAllResult,
@@ -1590,27 +1628,29 @@ const expressHelper = {
1590
1628
  * @returns {Array} Sorted array of unique, lowercase email addresses
1591
1629
  */
1592
1630
  function extractEmails(dirtyArray) {
1593
- const emailRegex = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g
1631
+ const emailRegex = /[\w.%+-]+@[a-z0-9.-]+\.[a-z]{2,}/gi
1594
1632
  const emails = new Set()
1595
1633
 
1596
1634
  // Handle null/undefined input array
1597
- if (!dirtyArray) return []
1635
+ if (!dirtyArray)
1636
+ return []
1598
1637
 
1599
- dirtyArray.forEach(entry => {
1638
+ dirtyArray.forEach((entry) => {
1600
1639
  // Skip null, undefined, empty, or whitespace-only entries
1601
- if (!entry || typeof entry !== 'string' || !entry.trim()) return
1640
+ if (!entry || typeof entry !== 'string' || !entry.trim())
1641
+ return
1602
1642
 
1603
1643
  try {
1604
1644
  const cleanEntry = entry
1605
1645
  .replace(/[\u200B-\u200D\uFEFF\u202A-\u202E]/g, '') // Remove hidden chars
1606
- .replace(/[<>]/g, ' ') // Convert email delimiters to spaces
1607
- .replace(/\s+/g, ' ') // Collapse multiple whitespace
1646
+ .replace(/[<>]/g, ' ') // Convert email delimiters to spaces
1647
+ .replace(/\s+/g, ' ') // Collapse multiple whitespace
1608
1648
  .trim()
1609
1649
 
1610
1650
  // Extract all email matches
1611
1651
  const matches = cleanEntry.match(emailRegex)
1612
1652
  if (matches) {
1613
- matches.forEach(email => emails.add(email.toLowerCase())) // Normalize to lowercase
1653
+ matches.forEach((email) => emails.add(email.toLowerCase())) // Normalize to lowercase
1614
1654
  }
1615
1655
  } catch (e) {
1616
1656
  console.warn('Failed to process entry:', entry, e)
@@ -1656,64 +1696,65 @@ const objectHelper = {
1656
1696
  },
1657
1697
  merge,
1658
1698
  set(obj, path, value) {
1659
- const parts = path.split('.');
1660
- let current = obj;
1699
+ const parts = path.split('.')
1700
+ let current = obj
1661
1701
 
1662
1702
  // 处理所有中间部分
1663
1703
  for (let i = 0; i < parts.length - 1; i++) {
1664
- const part = parts[i];
1665
- let key, index;
1704
+ const part = parts[i]
1705
+ let key, index
1666
1706
 
1667
1707
  // 检查是否是数组索引格式,如key[0]
1668
- const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/);
1708
+ const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/)
1669
1709
  if (arrayMatch) {
1670
- key = arrayMatch[1];
1671
- index = parseInt(arrayMatch[2], 10);
1710
+ key = arrayMatch[1]
1711
+ index = Number.parseInt(arrayMatch[2], 10)
1672
1712
  // 确保当前层级的数组存在
1673
1713
  if (!current[key] || !Array.isArray(current[key])) {
1674
- current[key] = [];
1714
+ current[key] = []
1675
1715
  }
1676
1716
  // 扩展数组到足够大
1677
1717
  while (current[key].length <= index) {
1678
- current[key].push(undefined);
1718
+ current[key].push(undefined)
1679
1719
  }
1680
1720
  // 如果当前位置未定义或为null,初始化为对象
1681
1721
  if (current[key][index] == null) {
1682
- current[key][index] = {};
1722
+ current[key][index] = {}
1683
1723
  }
1684
- current = current[key][index];
1724
+ current = current[key][index]
1685
1725
  } else {
1686
1726
  // 处理普通属性
1687
1727
  if (!current[part]) {
1688
- current[part] = {};
1728
+ current[part] = {}
1689
1729
  }
1690
- current = current[part];
1730
+ current = current[part]
1691
1731
  }
1692
1732
  }
1693
1733
 
1694
1734
  // 处理最后一部分
1695
- const lastPart = parts[parts.length - 1];
1696
- const arrayMatch = lastPart.match(/^(\w+)\[(\d+)\]$/);
1735
+ const lastPart = parts[parts.length - 1]
1736
+ const arrayMatch = lastPart.match(/^(\w+)\[(\d+)\]$/)
1697
1737
  if (arrayMatch) {
1698
- const key = arrayMatch[1];
1699
- const index = parseInt(arrayMatch[2], 10);
1738
+ const key = arrayMatch[1]
1739
+ const index = Number.parseInt(arrayMatch[2], 10)
1700
1740
  // 确保数组存在
1701
1741
  if (!current[key] || !Array.isArray(current[key])) {
1702
- current[key] = [];
1742
+ current[key] = []
1703
1743
  }
1704
1744
  // 扩展数组到所需索引
1705
1745
  while (current[key].length <= index) {
1706
- current[key].push(undefined);
1746
+ current[key].push(undefined)
1707
1747
  }
1708
- current[key][index] = value;
1748
+ current[key][index] = value
1709
1749
  } else {
1710
- current[lastPart] = value;
1750
+ current[lastPart] = value
1711
1751
  }
1712
1752
  }
1713
1753
  }
1714
1754
 
1715
1755
  function merge(target, ...sources) {
1716
- if (!sources.length) return target
1756
+ if (!sources.length)
1757
+ return target
1717
1758
 
1718
1759
  const source = sources.shift() // 取出第一个源对象
1719
1760
 
@@ -1750,28 +1791,28 @@ function _isObject(obj) {
1750
1791
 
1751
1792
  ;// ./lib/helpers/pReduce/pReduce.js
1752
1793
  async function pReduce(iterable, reducer, initialValue) {
1753
- return new Promise((resolve, reject) => {
1754
- const iterator = iterable[Symbol.iterator]()
1755
- let index = 0
1794
+ return new Promise((resolve, reject) => {
1795
+ const iterator = iterable[Symbol.iterator]()
1796
+ let index = 0
1756
1797
 
1757
- const next = async total => {
1758
- const element = iterator.next()
1798
+ const next = async (total) => {
1799
+ const element = iterator.next()
1759
1800
 
1760
- if (element.done) {
1761
- resolve(total)
1762
- return
1763
- }
1801
+ if (element.done) {
1802
+ resolve(total)
1803
+ return
1804
+ }
1764
1805
 
1765
- try {
1766
- const [resolvedTotal, resolvedValue] = await Promise.all([total, element.value])
1767
- next(reducer(resolvedTotal, resolvedValue, index++))
1768
- } catch (error) {
1769
- reject(error)
1770
- }
1771
- }
1806
+ try {
1807
+ const [resolvedTotal, resolvedValue] = await Promise.all([total, element.value])
1808
+ next(reducer(resolvedTotal, resolvedValue, index++))
1809
+ } catch (error) {
1810
+ reject(error)
1811
+ }
1812
+ }
1772
1813
 
1773
- next(initialValue)
1774
- })
1814
+ next(initialValue)
1815
+ })
1775
1816
  }
1776
1817
 
1777
1818
 
@@ -1918,16 +1959,17 @@ class Repo {
1918
1959
  const promise = typeof this.model.saveAll === 'function'
1919
1960
  ? this.model.saveAll({ config, docs })
1920
1961
  : Promise.all(docs.map(async (doc) => {
1921
- if (doc) {
1922
- const result = await this.saveOne({ config, doc })
1923
- isNew = result.isNew
1924
- const _data = result._data || result.data
1925
- return _data[0]
1926
- }
1927
- return null
1928
- }))
1962
+ if (doc) {
1963
+ const result = await this.saveOne({ config, doc })
1964
+ isNew = result.isNew
1965
+ const _data = result._data || result.data
1966
+ return _data[0]
1967
+ }
1968
+ return null
1969
+ }))
1929
1970
  return promise.then((savedData) => {
1930
- if (savedData.length !== 1) isNew = null
1971
+ if (savedData.length !== 1)
1972
+ isNew = null
1931
1973
  const result = {
1932
1974
  data: savedData,
1933
1975
  isNew,
@@ -2261,6 +2303,9 @@ function initOnlyValidFromArray(_class, arr) {
2261
2303
  ;// ./lib/helpers/initOnlyValidFromArray/index.js
2262
2304
 
2263
2305
 
2306
+ ;// ./lib/helpers/isConvertibleToNumber/index.js
2307
+
2308
+
2264
2309
  ;// ./lib/helpers/mergeArraysByKey/mergeArraysByKey.js
2265
2310
  function mergeArraysByKey(arr1, arr2) {
2266
2311
  // Handle undefined/null inputs by defaulting to empty arrays
@@ -2271,40 +2316,41 @@ function mergeArraysByKey(arr1, arr2) {
2271
2316
 
2272
2317
  // Helper function to merge values based on their type
2273
2318
  const mergeValues = (existingValue, newValue) => {
2274
- if (existingValue === undefined) return newValue
2275
-
2319
+ if (existingValue === undefined)
2320
+ return newValue
2321
+
2276
2322
  // Handle arrays by concatenating
2277
2323
  if (Array.isArray(existingValue) && Array.isArray(newValue)) {
2278
2324
  return [...new Set([...existingValue, ...newValue])]
2279
2325
  }
2280
-
2326
+
2281
2327
  // Handle objects by merging
2282
- if (typeof existingValue === 'object' && typeof newValue === 'object' &&
2283
- !Array.isArray(existingValue) && !Array.isArray(newValue)) {
2328
+ if (typeof existingValue === 'object' && typeof newValue === 'object'
2329
+ && !Array.isArray(existingValue) && !Array.isArray(newValue)) {
2284
2330
  return { ...existingValue, ...newValue }
2285
2331
  }
2286
-
2332
+
2287
2333
  // // Handle numbers by adding
2288
2334
  // if (typeof existingValue === 'number' && typeof newValue === 'number') {
2289
2335
  // return existingValue
2290
2336
  // }
2291
-
2337
+
2292
2338
  // // Handle strings by concatenating
2293
2339
  // if (typeof existingValue === 'string' && typeof newValue === 'string') {
2294
2340
  // return existingValue
2295
2341
  // }
2296
-
2342
+
2297
2343
  // Default: use the new value
2298
2344
  return newValue
2299
2345
  }
2300
2346
 
2301
2347
  // Process first array
2302
- safeArr1.forEach(item => {
2348
+ safeArr1.forEach((item) => {
2303
2349
  mergedMap.set(item.key, item.value)
2304
2350
  })
2305
2351
 
2306
2352
  // Process second array and merge values
2307
- safeArr2.forEach(item => {
2353
+ safeArr2.forEach((item) => {
2308
2354
  const existingValue = mergedMap.get(item.key)
2309
2355
  mergedMap.set(item.key, mergeValues(existingValue, item.value))
2310
2356
  })
@@ -2323,7 +2369,7 @@ function mergeArraysByKey(arr1, arr2) {
2323
2369
  function padZeros(num, minLength = 6) {
2324
2370
  num = num.toString()
2325
2371
  if (num.length < minLength) {
2326
- return padZeros('0' + num, minLength)
2372
+ return padZeros(`0${num}`, minLength)
2327
2373
  }
2328
2374
  return num
2329
2375
  }
@@ -2343,26 +2389,26 @@ function padZeros(num, minLength = 6) {
2343
2389
  ;// ./lib/helpers/replacePlaceholders/replacePlaceholders.js
2344
2390
  function replacePlaceholders({ content, mapping }) {
2345
2391
  let isObjectMode = false
2346
-
2392
+
2347
2393
  if (typeof content === 'object' && content !== null) {
2348
2394
  content = JSON.stringify(content)
2349
2395
  isObjectMode = true
2350
2396
  }
2351
2397
 
2352
2398
  // [[ eventRegistration.eventRegistrationCode | 0 ]]
2353
- const regex = /(\[*)\[\[\s*([\w.\-_]+)(?:\s*\|\s*([^:\]\s]+))?(?:\s*:\s*([^\]\s]+))?\s*\]\](\]*)/g;
2399
+ const regex = /(\[*)\[\[\s*([\w.\-]+)(?:\s*\|\s*([^:\]\s]+))?(?:\s*:\s*([^\]\s]+))?\s*\]\](\]*)/g
2354
2400
 
2355
2401
  const result = content.replace(regex, (match, leadingBrackets, path, defaultValue, type, trailingBrackets) => {
2356
-
2357
2402
  // Split the path into parts
2358
2403
  const keys = path.trim().split('.')
2359
-
2404
+
2360
2405
  // Traverse the nested object structure
2361
2406
  let value = mapping
2362
2407
  for (const key of keys) {
2363
2408
  // Handle empty keys (in case of double dots or leading/trailing dots)
2364
- if (!key) continue
2365
-
2409
+ if (!key)
2410
+ continue
2411
+
2366
2412
  value = value?.[key]
2367
2413
  if (value === undefined) {
2368
2414
  break
@@ -2370,10 +2416,12 @@ function replacePlaceholders({ content, mapping }) {
2370
2416
  }
2371
2417
 
2372
2418
  // Apply default if missing
2373
- if (value === undefined) value = defaultValue?.trim();
2374
- if (value === undefined) return isObjectMode ? undefined : match;
2375
-
2376
- value = value !== undefined
2419
+ if (value === undefined)
2420
+ value = defaultValue?.trim()
2421
+ if (value === undefined)
2422
+ return isObjectMode ? undefined : match
2423
+
2424
+ value = value !== undefined
2377
2425
  ? leadingBrackets + value + trailingBrackets
2378
2426
  : match
2379
2427
 
@@ -2394,10 +2442,11 @@ function replacePlaceholders({ content, mapping }) {
2394
2442
  /**
2395
2443
  * Sanitizes input by removing hidden/control characters with customizable whitespace handling.
2396
2444
  * @param {string} input - The string to sanitize.
2397
- * @param {Object} [options] - Configuration options.
2398
- * @param {boolean} [options.normalizeWhitespace=true] - Collapse multiple spaces/tabs into one space.
2399
- * @param {boolean} [options.removeNewlines=false] - If true, replaces newlines with spaces.
2400
- * @param {boolean} [options.trim=true] - If true, trims leading/trailing whitespace.
2445
+ * @param {object} [options] - Configuration options.
2446
+ * @param {boolean} [options.normalizeWhitespace] - Collapse multiple spaces/tabs into one space.
2447
+ * @param {boolean} [options.removeNewlines] - If true, replaces newlines with spaces.
2448
+ * @param {boolean} [options.trim] - If true, trims leading/trailing whitespace.
2449
+ * @param {boolean} [options.debug] - If true, logs debug information about removed characters.
2401
2450
  * @returns {string} The sanitized string.
2402
2451
  */
2403
2452
  function sanitizeText(input, options = {}) {
@@ -2405,7 +2454,8 @@ function sanitizeText(input, options = {}) {
2405
2454
  normalizeWhitespace = true,
2406
2455
  removeNewlines = false,
2407
2456
  trim = true,
2408
- preserveBasicWhitespace = true, // new option to keep tabs, newlines if removeNewlines=false
2457
+ preserveBasicWhitespace = true,
2458
+ debug = false, // new option for debugging
2409
2459
  } = options
2410
2460
 
2411
2461
  if (typeof input !== 'string') {
@@ -2414,27 +2464,106 @@ function sanitizeText(input, options = {}) {
2414
2464
 
2415
2465
  let result = input
2416
2466
 
2467
+ if (debug) {
2468
+ console.log('Original input:', JSON.stringify(input))
2469
+ console.log('Options:', { normalizeWhitespace, removeNewlines, trim, preserveBasicWhitespace })
2470
+ }
2471
+
2417
2472
  // Phase 1: Remove all control characters except basic whitespace if requested
2418
2473
  if (preserveBasicWhitespace && !removeNewlines) {
2419
- // Keep tab (\t), newline (\n), carriage return (\r)
2420
- result = result.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g, '')
2474
+ if (debug) {
2475
+ const before = result
2476
+ const matches = []
2477
+ // Use a replacer function to capture what's being removed
2478
+ result = result.replace(/[\x00-\x08\v\f\x0E-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g, (match) => {
2479
+ matches.push({
2480
+ char: match,
2481
+ code: match.charCodeAt(0),
2482
+ hex: `0x${match.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0')}`
2483
+ })
2484
+ return ''
2485
+ })
2486
+ if (matches.length > 0) {
2487
+ console.log('Phase 1 (preserve mode) - Removed characters:')
2488
+ matches.forEach((m) => {
2489
+ console.log(` - Character: ${JSON.stringify(m.char)}, Code: ${m.code}, Hex: ${m.hex}`)
2490
+ })
2491
+ console.log(`Removed ${matches.length} control character(s)`)
2492
+ } else {
2493
+ console.log('Phase 1 (preserve mode) - No control characters found')
2494
+ }
2495
+ } else {
2496
+ result = result.replace(/[\x00-\x08\v\f\x0E-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g, '')
2497
+ }
2421
2498
  } else {
2422
- // Remove all control characters including basic whitespace
2423
- result = result.replace(/[\x00-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g, '')
2499
+ if (debug) {
2500
+ const before = result
2501
+ const matches = []
2502
+ result = result.replace(/[\x00-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g, (match) => {
2503
+ matches.push({
2504
+ char: match,
2505
+ code: match.charCodeAt(0),
2506
+ hex: `0x${match.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0')}`
2507
+ })
2508
+ return ''
2509
+ })
2510
+ if (matches.length > 0) {
2511
+ console.log('Phase 1 (full removal mode) - Removed characters:')
2512
+ matches.forEach((m) => {
2513
+ console.log(` - Character: ${JSON.stringify(m.char)}, Code: ${m.code}, Hex: ${m.hex}`)
2514
+ })
2515
+ console.log(`Removed ${matches.length} control character(s)`)
2516
+ } else {
2517
+ console.log('Phase 1 (full removal mode) - No control characters found')
2518
+ }
2519
+ } else {
2520
+ result = result.replace(/[\x00-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g, '')
2521
+ }
2522
+ }
2523
+
2524
+ if (debug) {
2525
+ console.log('After Phase 1:', JSON.stringify(result))
2424
2526
  }
2425
2527
 
2426
2528
  // Phase 2: Handle whitespace transformations
2427
2529
  if (removeNewlines) {
2428
- result = result.replace(/[\r\n]+/g, ' ') // Convert newlines to spaces
2530
+ if (debug) {
2531
+ const before = result
2532
+ result = result.replace(/[\r\n]+/g, ' ')
2533
+ console.log('Phase 2 - Converted newlines to spaces')
2534
+ } else {
2535
+ result = result.replace(/[\r\n]+/g, ' ')
2536
+ }
2429
2537
  }
2430
2538
 
2431
2539
  if (normalizeWhitespace) {
2432
- result = result.replace(/[ \t]+/g, ' ') // Collapse spaces/tabs to single space
2540
+ if (debug) {
2541
+ const before = result
2542
+ result = result.replace(/[ \t]+/g, ' ')
2543
+ console.log('Phase 2 - Normalized whitespace')
2544
+ } else {
2545
+ result = result.replace(/[ \t]+/g, ' ')
2546
+ }
2547
+ }
2548
+
2549
+ if (debug) {
2550
+ console.log('After Phase 2:', JSON.stringify(result))
2433
2551
  }
2434
2552
 
2435
2553
  // Phase 3: Final trimming
2436
2554
  if (trim) {
2437
- result = result.trim()
2555
+ if (debug) {
2556
+ const before = result
2557
+ result = result.trim()
2558
+ console.log('Phase 3 - Trimmed leading/trailing whitespace')
2559
+ } else {
2560
+ result = result.trim()
2561
+ }
2562
+ }
2563
+
2564
+ if (debug) {
2565
+ console.log('Final result:', JSON.stringify(result))
2566
+ console.log('--- Sanitization complete ---')
2438
2567
  }
2439
2568
 
2440
2569
  return result
@@ -2445,12 +2574,12 @@ function sanitizeText(input, options = {}) {
2445
2574
 
2446
2575
  ;// ./lib/helpers/shuffleArray/shuffleArray.js
2447
2576
  function shuffleArray(array) {
2448
- const arr = [...array];
2449
- for (let i = arr.length - 1; i >= 0; i--) { // Changed `i > 0` to `i >= 0`
2577
+ const arr = [...array]
2578
+ for (let i = arr.length - 1; i >= 0; i--) { // Changed `i > 0` to `i >= 0`
2450
2579
  const j = Math.floor(Math.random() * (i + 1));
2451
- [arr[i], arr[j]] = [arr[j], arr[i]];
2580
+ [arr[i], arr[j]] = [arr[j], arr[i]]
2452
2581
  }
2453
- return arr;
2582
+ return arr
2454
2583
  }
2455
2584
 
2456
2585
  ;// ./lib/helpers/shuffleArray/index.js
@@ -2512,7 +2641,7 @@ function indexCharset(str) {
2512
2641
  for (let i = 0; i < length; i++) {
2513
2642
  char = str[i]
2514
2643
  byCode[i] = char
2515
- byChar[char] = i;
2644
+ byChar[char] = i
2516
2645
  }
2517
2646
  return { byCode, byChar, length }
2518
2647
  }
@@ -2543,7 +2672,7 @@ function randomString({ len = 16, pattern = 'a1' } = {}) {
2543
2672
  str += mark
2544
2673
  }
2545
2674
  const chars = [...str]
2546
- return [...Array(len)].map(i => {
2675
+ return [...new Array(len)].map((i) => {
2547
2676
  return chars[(Math.random() * chars.length) | 0]
2548
2677
  }).join``
2549
2678
  }
@@ -2567,12 +2696,14 @@ function setCode(base = 34) {
2567
2696
  }
2568
2697
 
2569
2698
  function toCamelCase(str) {
2570
- if (!str) return ''
2699
+ if (!str)
2700
+ return ''
2571
2701
  return str
2572
2702
  .trim()
2573
2703
  .split(/\s+/)
2574
2704
  .map((word, index) => {
2575
- if (!word) return ''
2705
+ if (!word)
2706
+ return ''
2576
2707
  if (index === 0) {
2577
2708
  return word.toLowerCase()
2578
2709
  }
@@ -2582,7 +2713,8 @@ function toCamelCase(str) {
2582
2713
  }
2583
2714
 
2584
2715
  function toLowerCase(str) {
2585
- if (!str) return ''
2716
+ if (!str)
2717
+ return ''
2586
2718
  return str
2587
2719
  .trim()
2588
2720
  .toLowerCase()
@@ -2617,7 +2749,7 @@ function trackingPlugin(schema, options) {
2617
2749
  })
2618
2750
 
2619
2751
  // Auto-update hook
2620
- schema.pre('save', function(next) {
2752
+ schema.pre('save', function (next) {
2621
2753
  this.meta.modified = Date.now()
2622
2754
  next()
2623
2755
  })
@@ -2629,9 +2761,9 @@ function trackingPlugin(schema, options) {
2629
2761
  }, {
2630
2762
  name: 'tracking_status_index',
2631
2763
  background: true,
2632
- partialFilterExpression: {
2764
+ partialFilterExpression: {
2633
2765
  'meta.active': true,
2634
- 'meta.deleted': false
2766
+ 'meta.deleted': false
2635
2767
  }
2636
2768
  })
2637
2769
 
@@ -2660,7 +2792,7 @@ function tenantPlugin(schema, options) {
2660
2792
 
2661
2793
  // Add core indexes
2662
2794
  schema.index({
2663
- 'tenantCode': 1
2795
+ tenantCode: 1
2664
2796
  }, {
2665
2797
  name: 'tenant_core_index',
2666
2798
  background: true
@@ -2668,15 +2800,15 @@ function tenantPlugin(schema, options) {
2668
2800
 
2669
2801
  // 1. ENHANCE EXISTING TRACKING INDEXES
2670
2802
  const existingIndexes = schema.indexes()
2671
-
2803
+
2672
2804
  // Check if tracking_status_index exists
2673
- const hasTenantStatusIndex = existingIndexes.some(idx =>
2805
+ const hasTenantStatusIndex = existingIndexes.some((idx) =>
2674
2806
  idx.name === 'tenant_status_index' // Check by name for reliability
2675
2807
  )
2676
2808
 
2677
2809
  if (!hasTenantStatusIndex) {
2678
2810
  schema.index({
2679
- 'tenantCode': 1, // Unique field first
2811
+ tenantCode: 1, // Unique field first
2680
2812
  _type: 1, // Low-cardinality field last
2681
2813
  }, {
2682
2814
  name: 'tenant_status_index',
@@ -2684,7 +2816,7 @@ function tenantPlugin(schema, options) {
2684
2816
  partialFilterExpression: {
2685
2817
  '_type': 'Tenant',
2686
2818
  'meta.active': true,
2687
- 'meta.deleted': false
2819
+ 'meta.deleted': false
2688
2820
  }
2689
2821
  })
2690
2822
  }
@@ -2723,6 +2855,7 @@ function tenantPlugin(schema, options) {
2723
2855
 
2724
2856
 
2725
2857
 
2858
+
2726
2859
 
2727
2860
 
2728
2861
  ;// ./lib/models/apiResponse/index.js
@@ -2780,10 +2913,11 @@ class AwsStsS3Client {
2780
2913
  }
2781
2914
 
2782
2915
  get isExpired() {
2783
- if (!this.expiration) return true;
2784
- const now = new Date();
2785
- const bufferMs = 1 * 60 * 1000; // 一分钟缓冲
2786
- return now >= new Date(this.expiration.getTime() - bufferMs);
2916
+ if (!this.expiration)
2917
+ return true
2918
+ const now = new Date()
2919
+ const bufferMs = 1 * 60 * 1000 // 一分钟缓冲
2920
+ return now >= new Date(this.expiration.getTime() - bufferMs)
2787
2921
  }
2788
2922
 
2789
2923
  get isValid() {
@@ -2818,7 +2952,7 @@ class AwsStsS3Client {
2818
2952
  throw new Error(`Missing ${component} in AWS awsClientS3 client configuration`)
2819
2953
  }
2820
2954
  }
2821
-
2955
+
2822
2956
  return true
2823
2957
  }
2824
2958
 
@@ -2828,9 +2962,9 @@ class AwsStsS3Client {
2828
2962
  if (!webIdentityToken) {
2829
2963
  throw new Error('getIdToken function returned empty or invalid token')
2830
2964
  }
2831
-
2965
+
2832
2966
  const stsClient = new this.awsClientSts.STSClient({ region: this.region })
2833
-
2967
+
2834
2968
  const stsResponse = await stsClient.send(
2835
2969
  new this.awsClientSts.AssumeRoleWithWebIdentityCommand({
2836
2970
  RoleArn: this.roleArn,
@@ -3137,29 +3271,30 @@ class KeyValueObject {
3137
3271
  }
3138
3272
 
3139
3273
  function _mergeValues(existingValue, newValue) {
3140
- if (existingValue === undefined) return newValue
3141
-
3274
+ if (existingValue === undefined)
3275
+ return newValue
3276
+
3142
3277
  // Handle arrays by concatenating
3143
3278
  if (Array.isArray(existingValue) && Array.isArray(newValue)) {
3144
3279
  return [...new Set([...existingValue, ...newValue])]
3145
3280
  }
3146
-
3281
+
3147
3282
  // Handle objects by merging
3148
- if (typeof existingValue === 'object' && typeof newValue === 'object' &&
3149
- !Array.isArray(existingValue) && !Array.isArray(newValue)) {
3283
+ if (typeof existingValue === 'object' && typeof newValue === 'object'
3284
+ && !Array.isArray(existingValue) && !Array.isArray(newValue)) {
3150
3285
  return { ...existingValue, ...newValue }
3151
3286
  }
3152
-
3287
+
3153
3288
  // // Handle numbers by adding
3154
3289
  // if (typeof existingValue === 'number' && typeof newValue === 'number') {
3155
3290
  // return existingValue
3156
3291
  // }
3157
-
3292
+
3158
3293
  // // Handle strings by concatenating
3159
3294
  // if (typeof existingValue === 'string' && typeof newValue === 'string') {
3160
3295
  // return existingValue
3161
3296
  // }
3162
-
3297
+
3163
3298
  // Default: use the new value
3164
3299
  return newValue
3165
3300
  }
@@ -3219,29 +3354,30 @@ function metadata_isSame(key1, key2) {
3219
3354
  }
3220
3355
 
3221
3356
  function metadata_mergeValues(existingValue, newValue) {
3222
- if (existingValue === undefined) return newValue
3223
-
3357
+ if (existingValue === undefined)
3358
+ return newValue
3359
+
3224
3360
  // Handle arrays by concatenating
3225
3361
  if (Array.isArray(existingValue) && Array.isArray(newValue)) {
3226
3362
  return [...new Set([...existingValue, ...newValue])]
3227
3363
  }
3228
-
3364
+
3229
3365
  // Handle objects by merging
3230
- if (typeof existingValue === 'object' && typeof newValue === 'object' &&
3231
- !Array.isArray(existingValue) && !Array.isArray(newValue)) {
3366
+ if (typeof existingValue === 'object' && typeof newValue === 'object'
3367
+ && !Array.isArray(existingValue) && !Array.isArray(newValue)) {
3232
3368
  return { ...existingValue, ...newValue }
3233
3369
  }
3234
-
3370
+
3235
3371
  // // Handle numbers by adding
3236
3372
  // if (typeof existingValue === 'number' && typeof newValue === 'number') {
3237
3373
  // return existingValue
3238
3374
  // }
3239
-
3375
+
3240
3376
  // // Handle strings by concatenating
3241
3377
  // if (typeof existingValue === 'string' && typeof newValue === 'string') {
3242
3378
  // return existingValue
3243
3379
  // }
3244
-
3380
+
3245
3381
  // Default: use the new value
3246
3382
  return newValue
3247
3383
  }
@@ -3262,14 +3398,14 @@ class TrackedEntity {
3262
3398
  const timestamp = Date.now()
3263
3399
  this.meta = {
3264
3400
  active: options.meta?.active ?? options.active ?? true,
3265
- created: options.meta?.created ?? (options.created
3266
- ? new Date(options.created).getTime()
3267
- : timestamp),
3401
+ created: options.meta?.created ?? (options.created
3402
+ ? new Date(options.created).getTime()
3403
+ : timestamp),
3268
3404
  creator: options.meta?.creator ?? options.creator ?? '',
3269
3405
  deleted: options.meta?.deleted ?? options.deleted ?? false,
3270
- modified: options.meta?.modified ?? (options.modified
3271
- ? new Date(options.modified).getTime()
3272
- : timestamp),
3406
+ modified: options.meta?.modified ?? (options.modified
3407
+ ? new Date(options.modified).getTime()
3408
+ : timestamp),
3273
3409
  owner: options.meta?.owner ?? options.owner ?? '',
3274
3410
  }
3275
3411
 
@@ -3436,7 +3572,6 @@ class PushEnvelope extends TrackedEntity {
3436
3572
  get isValid() {
3437
3573
  return super.isValid && this.data
3438
3574
  }
3439
-
3440
3575
  }
3441
3576
 
3442
3577
  ;// ./lib/models/pushEnvelope/index.js
@@ -3503,6 +3638,168 @@ class QMeta {
3503
3638
 
3504
3639
 
3505
3640
 
3641
+ ;// ./lib/models/status/actionRecord.js
3642
+
3643
+
3644
+ class ActionRecord {
3645
+ constructor(options) {
3646
+ options = options || {}
3647
+
3648
+ const { _Actor } = options._constructor || {}
3649
+ this._Actor = _Actor
3650
+
3651
+ this._actor = options._actor
3652
+
3653
+ this.actorCode = typeof options === 'number' ? null : (options.actorCode || null)
3654
+ this.timestamp = typeof options === 'number' ? options : (options.timestamp || null)
3655
+ }
3656
+
3657
+ static get _classname() {
3658
+ return 'ActionRecord'
3659
+ }
3660
+ static get _superclass() {
3661
+ return 'ActionRecord'
3662
+ }
3663
+ static dummyData() {
3664
+ return {
3665
+ timestamp: (new Date()).valueOf(),
3666
+ }
3667
+ }
3668
+ static init(options = {}) {
3669
+ return init(this, options)
3670
+ }
3671
+
3672
+ get _classname() {
3673
+ return 'ActionRecord'
3674
+ }
3675
+
3676
+ get _superclass() {
3677
+ return 'ActionRecord'
3678
+ }
3679
+
3680
+ get actor() {
3681
+ return this._Actor && typeof this._Actor.init === 'function' ? this._Actor.init(this._actor) : this._actor
3682
+ }
3683
+
3684
+ get isValid() {
3685
+ return !!this.timestamp
3686
+ }
3687
+
3688
+ update(update) {
3689
+ if (typeof update === 'number') {
3690
+ this.timestamp = update
3691
+ return this
3692
+ }
3693
+ Object.keys(update).forEach((key) => {
3694
+ this[key] = update[key]
3695
+ })
3696
+ return this
3697
+ }
3698
+ }
3699
+
3700
+ ;// ./lib/models/status/status.js
3701
+
3702
+
3703
+
3704
+ const notUpdateAllowedProps = [
3705
+ 'created',
3706
+ // 'statusType'
3707
+ ]
3708
+
3709
+ class Status {
3710
+ constructor(options) {
3711
+ options = options || {}
3712
+
3713
+ const { _ActionRecord } = options._constructor || {}
3714
+ this._ActionRecord = _ActionRecord && (_ActionRecord._superclass === ActionRecord._superclass) ? _ActionRecord : ActionRecord
3715
+
3716
+ this.created = this._ActionRecord.init(options.created || { timestamp: (new Date()).valueOf() })
3717
+ // this.statusType = options.statusType || 'Status'
3718
+ }
3719
+
3720
+ static get _classname() {
3721
+ return 'Status'
3722
+ }
3723
+ static get _superclass() {
3724
+ return 'Status'
3725
+ }
3726
+ static dummyData() {
3727
+ return {}
3728
+ }
3729
+ static init(options = {}) {
3730
+ return init(this, options)
3731
+ }
3732
+ static initFromArray(arr = []) {
3733
+ return initFromArray(this, arr)
3734
+ }
3735
+ static initOnlyValidFromArray(arr = []) {
3736
+ return initOnlyValidFromArray(this, arr)
3737
+ }
3738
+
3739
+ get _classname() {
3740
+ return 'Status'
3741
+ }
3742
+ get _superclass() {
3743
+ return 'Status'
3744
+ }
3745
+ get isCreated() {
3746
+ return this.created?.timestamp !== null
3747
+ }
3748
+ get isValid() {
3749
+ return !!this
3750
+ }
3751
+
3752
+ setValue(t, actorCode, key) {
3753
+ const timestamp = t || Date.now()
3754
+ this[key] = this[key] instanceof this._ActionRecord ? this[key].update({ actorCode, timestamp }) : this._ActionRecord.init({ actorCode, timestamp })
3755
+ return this
3756
+ }
3757
+
3758
+ update(update) {
3759
+ Object.keys(update).forEach((key) => {
3760
+ if (!notUpdateAllowedProps.includes(key)) {
3761
+ this[key] = this[key] instanceof this._ActionRecord ? this[key].update(update[key]) : this._ActionRecord.init(update[key])
3762
+ }
3763
+ })
3764
+ return this
3765
+ }
3766
+ }
3767
+
3768
+ ;// ./lib/models/status/statusDocument.js
3769
+
3770
+
3771
+ class StatusDocument extends Status {
3772
+ constructor(options) {
3773
+ options = options || {}
3774
+ super(options)
3775
+
3776
+ this.archived = this._ActionRecord.init(options.archived)
3777
+ this.completed = this._ActionRecord.init(options.completed)
3778
+ this.drafted = this._ActionRecord.init(options.drafted)
3779
+ this.discarded = this._ActionRecord.init(options.discarded)
3780
+ // this.statusType = 'StatusDocument'
3781
+ }
3782
+
3783
+ get isValid() {
3784
+ return super.isValid
3785
+ }
3786
+
3787
+ static get _classname() {
3788
+ return 'StatusDocument'
3789
+ }
3790
+ setArchived(value, actorCode) {
3791
+ // const timestamp = value || Date.now()
3792
+ // this.archived = this.archived instanceof this._ActionRecord ? this.archived.update({ actorCode, timestamp }) : this._ActionRecord.init({ actorCode, timestamp })
3793
+ // return this
3794
+ return this.setValue(value, actorCode, 'archived')
3795
+ }
3796
+ }
3797
+
3798
+ ;// ./lib/models/status/index.js
3799
+
3800
+
3801
+
3802
+
3506
3803
  ;// ./lib/models/tenantAwareEntity/tenantAwareEntity.js
3507
3804
 
3508
3805
 
@@ -3643,6 +3940,7 @@ function _makeSetCode(fieldName, options) {
3643
3940
 
3644
3941
 
3645
3942
 
3943
+
3646
3944
  ;// ./lib/index.js
3647
3945
 
3648
3946
 
@@ -3650,4 +3948,4 @@ function _makeSetCode(fieldName, options) {
3650
3948
  ;// ./index.js
3651
3949
 
3652
3950
 
3653
- export { ApiResponse, AwsStsS3Client, KeyValueObject, Metadata, PushEnvelope, QMeta, Repo, Service, TemplateCompiler, TenantAwareEntity, TrackedEntity, UniqueKeyGenerator, authorize, calculateAge, changeCreatorOwner, concatStringByArray, convertString, escapeRegex, expressHelper, extractEmails, formatDate, generalPost, getValidation, getValueByKeys_getValueByKeys as getValueByKeys, groupArrayByKey, init, initFromArray, initOnlyValidFromArray, makeApiResponse, makeService, mergeArraysByKey, objectHelper, pReduce, padZeros, replacePlaceholders, sanitizeText, shuffleArray, stringFormatter, stringHelper, tenantPlugin, trackingPlugin };
3951
+ export { ActionRecord, ApiResponse, AwsStsS3Client, KeyValueObject, Metadata, PushEnvelope, QMeta, Repo, Service, Status, StatusDocument, TemplateCompiler, TenantAwareEntity, TrackedEntity, UniqueKeyGenerator, authorize, calculateAge, changeCreatorOwner, concatStringByArray, convertString, escapeRegex, expressHelper, extractEmails, formatDate, generalPost, getValidation, getValueByKeys_getValueByKeys as getValueByKeys, groupArrayByKey, init, initFromArray, initOnlyValidFromArray, isConvertibleToNumber, makeApiResponse, makeService, mergeArraysByKey, objectHelper, pReduce, padZeros, replacePlaceholders, sanitizeText, shuffleArray, stringFormatter, stringHelper, tenantPlugin, trackingPlugin };