@questwork/q-utilities 0.1.19 → 0.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/publish.yml +6 -6
- package/dist/index.min.cjs +640 -211
- package/dist/q-utilities.esm.js +635 -212
- package/dist/q-utilities.min.js +640 -211
- package/eslint.config.js +3 -0
- package/package.json +3 -2
package/dist/q-utilities.esm.js
CHANGED
|
@@ -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
|
|
128
|
+
return value.$and.reduce((acc, item) => (acc && getValidation(item, data, getDataByKey, KeyValueObject)), true)
|
|
118
129
|
}
|
|
119
130
|
case '$or': {
|
|
120
|
-
return value
|
|
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
|
|
162
|
+
return isEmpty === value.$empty
|
|
138
163
|
}
|
|
139
164
|
case '$eq': {
|
|
140
|
-
return rowValue === value
|
|
165
|
+
return rowValue === value.$eq
|
|
141
166
|
}
|
|
142
167
|
case '$gt': {
|
|
143
|
-
return rowValue > value
|
|
168
|
+
return rowValue > value.$gt
|
|
144
169
|
}
|
|
145
170
|
case '$gte': {
|
|
146
|
-
return rowValue >= value
|
|
171
|
+
return rowValue >= value.$gte
|
|
147
172
|
}
|
|
148
173
|
case '$hasOverlap': {
|
|
149
|
-
return _hasOverlap(rowValue, value
|
|
174
|
+
return _hasOverlap(rowValue, value.$hasOverlap)
|
|
150
175
|
}
|
|
151
176
|
case '$lt': {
|
|
152
|
-
return rowValue < value
|
|
177
|
+
return rowValue < value.$lt
|
|
153
178
|
}
|
|
154
179
|
case '$lte': {
|
|
155
|
-
return rowValue <= value
|
|
180
|
+
return rowValue <= value.$lte
|
|
156
181
|
}
|
|
157
182
|
case '$in': {
|
|
158
183
|
if (Array.isArray(rowValue)) {
|
|
159
|
-
return !!rowValue.find((e) => (value
|
|
184
|
+
return !!rowValue.find((e) => (value.$in.includes(e)))
|
|
160
185
|
}
|
|
161
186
|
if (typeof rowValue !== 'object') {
|
|
162
|
-
return !!value
|
|
187
|
+
return !!value.$in.includes(rowValue)
|
|
163
188
|
}
|
|
164
189
|
return false
|
|
165
190
|
}
|
|
166
191
|
case '$inValue': {
|
|
167
|
-
const result = getDataByKey(value
|
|
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
|
|
203
|
+
return rowValue !== value.$ne
|
|
179
204
|
}
|
|
180
205
|
case '$notIn': {
|
|
181
206
|
if (Array.isArray(rowValue)) {
|
|
182
|
-
return !rowValue.find((e) => (value
|
|
207
|
+
return !rowValue.find((e) => (value.$notIn.includes(e)))
|
|
183
208
|
}
|
|
184
209
|
if (typeof rowValue !== 'object') {
|
|
185
|
-
return !value
|
|
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
|
|
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
|
|
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
|
|
229
|
+
return (start <= dateValue && end >= dateValue) === value.$isToday
|
|
205
230
|
}
|
|
206
231
|
case '$notInValue': {
|
|
207
|
-
const result = getDataByKey(value
|
|
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
|
|
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)
|
|
554
|
+
if (arg === undefined && value === undefined)
|
|
555
|
+
return true
|
|
534
556
|
|
|
535
557
|
// the arg is null
|
|
536
|
-
if (arg === null && value === null)
|
|
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)
|
|
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-
|
|
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)
|
|
838
|
-
|
|
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'
|
|
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(/ /g, ' ')
|
|
991
|
-
.replace(/\s+/g, ' ')
|
|
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(
|
|
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\
|
|
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(/(?![
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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 })
|
|
@@ -1469,9 +1508,110 @@ function convertString(string, patternMatch = /\$\{(.+?)\}/g, value, getValueByK
|
|
|
1469
1508
|
;// ./lib/helpers/convertString/index.js
|
|
1470
1509
|
|
|
1471
1510
|
|
|
1511
|
+
;// ./lib/helpers/detectControlCharacters/detectControlCharacters.js
|
|
1512
|
+
/**
|
|
1513
|
+
* Detects and reports hidden/control characters in a string without modifying it.
|
|
1514
|
+
* @param {string} input - The string to analyze.
|
|
1515
|
+
* @param {Object} [options] - Configuration options.
|
|
1516
|
+
* @param {boolean} [options.preserveBasicWhitespace=true] - Whether to consider basic whitespace as valid.
|
|
1517
|
+
* @returns {Object} Report object with detection results.
|
|
1518
|
+
*/
|
|
1519
|
+
function detectControlCharacters(input, options = {}) {
|
|
1520
|
+
const {
|
|
1521
|
+
preserveBasicWhitespace = true,
|
|
1522
|
+
removeNewlines = false
|
|
1523
|
+
} = options
|
|
1524
|
+
|
|
1525
|
+
if (typeof input !== 'string') {
|
|
1526
|
+
return {
|
|
1527
|
+
hasControlChars: false,
|
|
1528
|
+
matches: [],
|
|
1529
|
+
inputType: typeof input,
|
|
1530
|
+
message: 'Input is not a string'
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
const matches = []
|
|
1535
|
+
let regex
|
|
1536
|
+
|
|
1537
|
+
if (preserveBasicWhitespace && !removeNewlines) {
|
|
1538
|
+
// Same regex as Phase 1 preserve mode - keep tab (\t), newline (\n), carriage return (\r)
|
|
1539
|
+
regex = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g
|
|
1540
|
+
} else {
|
|
1541
|
+
// Same regex as Phase 1 full removal mode - use consistent escape sequences
|
|
1542
|
+
regex = /[\x00-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
// Use a replacer function to capture matches without modifying the string
|
|
1546
|
+
input.replace(regex, (match, offset) => {
|
|
1547
|
+
matches.push({
|
|
1548
|
+
character: match,
|
|
1549
|
+
code: match.charCodeAt(0),
|
|
1550
|
+
hex: '0x' + match.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0'),
|
|
1551
|
+
position: offset,
|
|
1552
|
+
context: getContext(input, offset, 10) // Show surrounding text
|
|
1553
|
+
})
|
|
1554
|
+
return '' // Return empty but we don't use the result
|
|
1555
|
+
})
|
|
1556
|
+
|
|
1557
|
+
return {
|
|
1558
|
+
hasControlChars: matches.length > 0,
|
|
1559
|
+
matches: matches,
|
|
1560
|
+
totalFound: matches.length,
|
|
1561
|
+
inputPreview: input.length > 50 ? input.substring(0, 50) + '...' : input,
|
|
1562
|
+
inputLength: input.length,
|
|
1563
|
+
optionsUsed: { preserveBasicWhitespace },
|
|
1564
|
+
regexPattern: regex.toString()
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
/**
|
|
1569
|
+
* Helper function to get context around a match
|
|
1570
|
+
*/
|
|
1571
|
+
function getContext(str, position, contextLength = 10) {
|
|
1572
|
+
const start = Math.max(0, position - contextLength)
|
|
1573
|
+
const end = Math.min(str.length, position + contextLength + 1)
|
|
1574
|
+
let context = str.substring(start, end)
|
|
1575
|
+
|
|
1576
|
+
// Replace control characters with their escape sequences for readability
|
|
1577
|
+
context = context.replace(/[\x00-\x1F\x7F-\x9F]/g, (match) => {
|
|
1578
|
+
return '\\u' + match.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0')
|
|
1579
|
+
})
|
|
1580
|
+
|
|
1581
|
+
return context
|
|
1582
|
+
}
|
|
1583
|
+
|
|
1584
|
+
/**
|
|
1585
|
+
* Pretty print the detection results to console
|
|
1586
|
+
*/
|
|
1587
|
+
function printControlCharReport(report) {
|
|
1588
|
+
console.log('=== Control Character Detection Report ===')
|
|
1589
|
+
console.log(`Input: "${report.inputPreview}" (${report.inputLength} chars)`)
|
|
1590
|
+
console.log(`Options: preserveBasicWhitespace = ${report.optionsUsed.preserveBasicWhitespace}`)
|
|
1591
|
+
console.log(`Regex pattern: ${report.regexPattern}`)
|
|
1592
|
+
console.log(`Control characters found: ${report.totalFound}`)
|
|
1593
|
+
|
|
1594
|
+
if (report.hasControlChars) {
|
|
1595
|
+
console.log('\n📋 Matches found:')
|
|
1596
|
+
report.matches.forEach((match, index) => {
|
|
1597
|
+
console.log(`\n${index + 1}. Character: ${JSON.stringify(match.character)}`)
|
|
1598
|
+
console.log(` Code: ${match.code} (${match.hex})`)
|
|
1599
|
+
console.log(` Position: ${match.position}`)
|
|
1600
|
+
console.log(` Context: "...${match.context}..."`)
|
|
1601
|
+
})
|
|
1602
|
+
} else {
|
|
1603
|
+
console.log('✅ No control characters detected in Phase 1 range')
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
console.log('=== End Report ===')
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
;// ./lib/helpers/detectControlCharacters/index.js
|
|
1610
|
+
|
|
1611
|
+
|
|
1472
1612
|
;// ./lib/helpers/escapeRegex/escapeRegex.js
|
|
1473
1613
|
function escapeRegex(string) {
|
|
1474
|
-
return String(string).replace(/[
|
|
1614
|
+
return String(string).replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
|
|
1475
1615
|
}
|
|
1476
1616
|
|
|
1477
1617
|
;// ./lib/helpers/escapeRegex/index.js
|
|
@@ -1574,7 +1714,6 @@ function updateOneResult({ responseHelper, service }) {
|
|
|
1574
1714
|
|
|
1575
1715
|
|
|
1576
1716
|
|
|
1577
|
-
|
|
1578
1717
|
const expressHelper = {
|
|
1579
1718
|
customHandler: customHandler,
|
|
1580
1719
|
findAllResult: findAllResult,
|
|
@@ -1590,27 +1729,29 @@ const expressHelper = {
|
|
|
1590
1729
|
* @returns {Array} Sorted array of unique, lowercase email addresses
|
|
1591
1730
|
*/
|
|
1592
1731
|
function extractEmails(dirtyArray) {
|
|
1593
|
-
const emailRegex = /[
|
|
1732
|
+
const emailRegex = /[\w.%+-]+@[a-z0-9.-]+\.[a-z]{2,}/gi
|
|
1594
1733
|
const emails = new Set()
|
|
1595
1734
|
|
|
1596
1735
|
// Handle null/undefined input array
|
|
1597
|
-
if (!dirtyArray)
|
|
1736
|
+
if (!dirtyArray)
|
|
1737
|
+
return []
|
|
1598
1738
|
|
|
1599
|
-
dirtyArray.forEach(entry => {
|
|
1739
|
+
dirtyArray.forEach((entry) => {
|
|
1600
1740
|
// Skip null, undefined, empty, or whitespace-only entries
|
|
1601
|
-
if (!entry || typeof entry !== 'string' || !entry.trim())
|
|
1741
|
+
if (!entry || typeof entry !== 'string' || !entry.trim())
|
|
1742
|
+
return
|
|
1602
1743
|
|
|
1603
1744
|
try {
|
|
1604
1745
|
const cleanEntry = entry
|
|
1605
1746
|
.replace(/[\u200B-\u200D\uFEFF\u202A-\u202E]/g, '') // Remove hidden chars
|
|
1606
|
-
.replace(/[<>]/g, ' ')
|
|
1607
|
-
.replace(/\s+/g, ' ')
|
|
1747
|
+
.replace(/[<>]/g, ' ') // Convert email delimiters to spaces
|
|
1748
|
+
.replace(/\s+/g, ' ') // Collapse multiple whitespace
|
|
1608
1749
|
.trim()
|
|
1609
1750
|
|
|
1610
1751
|
// Extract all email matches
|
|
1611
1752
|
const matches = cleanEntry.match(emailRegex)
|
|
1612
1753
|
if (matches) {
|
|
1613
|
-
matches.forEach(email => emails.add(email.toLowerCase())) // Normalize to lowercase
|
|
1754
|
+
matches.forEach((email) => emails.add(email.toLowerCase())) // Normalize to lowercase
|
|
1614
1755
|
}
|
|
1615
1756
|
} catch (e) {
|
|
1616
1757
|
console.warn('Failed to process entry:', entry, e)
|
|
@@ -1656,64 +1797,65 @@ const objectHelper = {
|
|
|
1656
1797
|
},
|
|
1657
1798
|
merge,
|
|
1658
1799
|
set(obj, path, value) {
|
|
1659
|
-
const parts = path.split('.')
|
|
1660
|
-
let current = obj
|
|
1800
|
+
const parts = path.split('.')
|
|
1801
|
+
let current = obj
|
|
1661
1802
|
|
|
1662
1803
|
// 处理所有中间部分
|
|
1663
1804
|
for (let i = 0; i < parts.length - 1; i++) {
|
|
1664
|
-
const part = parts[i]
|
|
1665
|
-
let key, index
|
|
1805
|
+
const part = parts[i]
|
|
1806
|
+
let key, index
|
|
1666
1807
|
|
|
1667
1808
|
// 检查是否是数组索引格式,如key[0]
|
|
1668
|
-
const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/)
|
|
1809
|
+
const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/)
|
|
1669
1810
|
if (arrayMatch) {
|
|
1670
|
-
key = arrayMatch[1]
|
|
1671
|
-
index = parseInt(arrayMatch[2], 10)
|
|
1811
|
+
key = arrayMatch[1]
|
|
1812
|
+
index = Number.parseInt(arrayMatch[2], 10)
|
|
1672
1813
|
// 确保当前层级的数组存在
|
|
1673
1814
|
if (!current[key] || !Array.isArray(current[key])) {
|
|
1674
|
-
current[key] = []
|
|
1815
|
+
current[key] = []
|
|
1675
1816
|
}
|
|
1676
1817
|
// 扩展数组到足够大
|
|
1677
1818
|
while (current[key].length <= index) {
|
|
1678
|
-
current[key].push(undefined)
|
|
1819
|
+
current[key].push(undefined)
|
|
1679
1820
|
}
|
|
1680
1821
|
// 如果当前位置未定义或为null,初始化为对象
|
|
1681
1822
|
if (current[key][index] == null) {
|
|
1682
|
-
current[key][index] = {}
|
|
1823
|
+
current[key][index] = {}
|
|
1683
1824
|
}
|
|
1684
|
-
current = current[key][index]
|
|
1825
|
+
current = current[key][index]
|
|
1685
1826
|
} else {
|
|
1686
1827
|
// 处理普通属性
|
|
1687
1828
|
if (!current[part]) {
|
|
1688
|
-
current[part] = {}
|
|
1829
|
+
current[part] = {}
|
|
1689
1830
|
}
|
|
1690
|
-
current = current[part]
|
|
1831
|
+
current = current[part]
|
|
1691
1832
|
}
|
|
1692
1833
|
}
|
|
1693
1834
|
|
|
1694
1835
|
// 处理最后一部分
|
|
1695
|
-
const lastPart = parts[parts.length - 1]
|
|
1696
|
-
const arrayMatch = lastPart.match(/^(\w+)\[(\d+)\]$/)
|
|
1836
|
+
const lastPart = parts[parts.length - 1]
|
|
1837
|
+
const arrayMatch = lastPart.match(/^(\w+)\[(\d+)\]$/)
|
|
1697
1838
|
if (arrayMatch) {
|
|
1698
|
-
const key = arrayMatch[1]
|
|
1699
|
-
const index = parseInt(arrayMatch[2], 10)
|
|
1839
|
+
const key = arrayMatch[1]
|
|
1840
|
+
const index = Number.parseInt(arrayMatch[2], 10)
|
|
1700
1841
|
// 确保数组存在
|
|
1701
1842
|
if (!current[key] || !Array.isArray(current[key])) {
|
|
1702
|
-
current[key] = []
|
|
1843
|
+
current[key] = []
|
|
1703
1844
|
}
|
|
1704
1845
|
// 扩展数组到所需索引
|
|
1705
1846
|
while (current[key].length <= index) {
|
|
1706
|
-
current[key].push(undefined)
|
|
1847
|
+
current[key].push(undefined)
|
|
1707
1848
|
}
|
|
1708
|
-
current[key][index] = value
|
|
1849
|
+
current[key][index] = value
|
|
1709
1850
|
} else {
|
|
1710
|
-
current[lastPart] = value
|
|
1851
|
+
current[lastPart] = value
|
|
1711
1852
|
}
|
|
1712
1853
|
}
|
|
1713
1854
|
}
|
|
1714
1855
|
|
|
1715
1856
|
function merge(target, ...sources) {
|
|
1716
|
-
if (!sources.length)
|
|
1857
|
+
if (!sources.length)
|
|
1858
|
+
return target
|
|
1717
1859
|
|
|
1718
1860
|
const source = sources.shift() // 取出第一个源对象
|
|
1719
1861
|
|
|
@@ -1750,28 +1892,28 @@ function _isObject(obj) {
|
|
|
1750
1892
|
|
|
1751
1893
|
;// ./lib/helpers/pReduce/pReduce.js
|
|
1752
1894
|
async function pReduce(iterable, reducer, initialValue) {
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1895
|
+
return new Promise((resolve, reject) => {
|
|
1896
|
+
const iterator = iterable[Symbol.iterator]()
|
|
1897
|
+
let index = 0
|
|
1756
1898
|
|
|
1757
|
-
|
|
1758
|
-
|
|
1899
|
+
const next = async (total) => {
|
|
1900
|
+
const element = iterator.next()
|
|
1759
1901
|
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1902
|
+
if (element.done) {
|
|
1903
|
+
resolve(total)
|
|
1904
|
+
return
|
|
1905
|
+
}
|
|
1764
1906
|
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1907
|
+
try {
|
|
1908
|
+
const [resolvedTotal, resolvedValue] = await Promise.all([total, element.value])
|
|
1909
|
+
next(reducer(resolvedTotal, resolvedValue, index++))
|
|
1910
|
+
} catch (error) {
|
|
1911
|
+
reject(error)
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1772
1914
|
|
|
1773
|
-
|
|
1774
|
-
|
|
1915
|
+
next(initialValue)
|
|
1916
|
+
})
|
|
1775
1917
|
}
|
|
1776
1918
|
|
|
1777
1919
|
|
|
@@ -1918,16 +2060,17 @@ class Repo {
|
|
|
1918
2060
|
const promise = typeof this.model.saveAll === 'function'
|
|
1919
2061
|
? this.model.saveAll({ config, docs })
|
|
1920
2062
|
: Promise.all(docs.map(async (doc) => {
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
2063
|
+
if (doc) {
|
|
2064
|
+
const result = await this.saveOne({ config, doc })
|
|
2065
|
+
isNew = result.isNew
|
|
2066
|
+
const _data = result._data || result.data
|
|
2067
|
+
return _data[0]
|
|
2068
|
+
}
|
|
2069
|
+
return null
|
|
2070
|
+
}))
|
|
1929
2071
|
return promise.then((savedData) => {
|
|
1930
|
-
if (savedData.length !== 1)
|
|
2072
|
+
if (savedData.length !== 1)
|
|
2073
|
+
isNew = null
|
|
1931
2074
|
const result = {
|
|
1932
2075
|
data: savedData,
|
|
1933
2076
|
isNew,
|
|
@@ -2261,6 +2404,9 @@ function initOnlyValidFromArray(_class, arr) {
|
|
|
2261
2404
|
;// ./lib/helpers/initOnlyValidFromArray/index.js
|
|
2262
2405
|
|
|
2263
2406
|
|
|
2407
|
+
;// ./lib/helpers/isConvertibleToNumber/index.js
|
|
2408
|
+
|
|
2409
|
+
|
|
2264
2410
|
;// ./lib/helpers/mergeArraysByKey/mergeArraysByKey.js
|
|
2265
2411
|
function mergeArraysByKey(arr1, arr2) {
|
|
2266
2412
|
// Handle undefined/null inputs by defaulting to empty arrays
|
|
@@ -2271,40 +2417,41 @@ function mergeArraysByKey(arr1, arr2) {
|
|
|
2271
2417
|
|
|
2272
2418
|
// Helper function to merge values based on their type
|
|
2273
2419
|
const mergeValues = (existingValue, newValue) => {
|
|
2274
|
-
if (existingValue === undefined)
|
|
2275
|
-
|
|
2420
|
+
if (existingValue === undefined)
|
|
2421
|
+
return newValue
|
|
2422
|
+
|
|
2276
2423
|
// Handle arrays by concatenating
|
|
2277
2424
|
if (Array.isArray(existingValue) && Array.isArray(newValue)) {
|
|
2278
2425
|
return [...new Set([...existingValue, ...newValue])]
|
|
2279
2426
|
}
|
|
2280
|
-
|
|
2427
|
+
|
|
2281
2428
|
// Handle objects by merging
|
|
2282
|
-
if (typeof existingValue === 'object' && typeof newValue === 'object'
|
|
2283
|
-
|
|
2429
|
+
if (typeof existingValue === 'object' && typeof newValue === 'object'
|
|
2430
|
+
&& !Array.isArray(existingValue) && !Array.isArray(newValue)) {
|
|
2284
2431
|
return { ...existingValue, ...newValue }
|
|
2285
2432
|
}
|
|
2286
|
-
|
|
2433
|
+
|
|
2287
2434
|
// // Handle numbers by adding
|
|
2288
2435
|
// if (typeof existingValue === 'number' && typeof newValue === 'number') {
|
|
2289
2436
|
// return existingValue
|
|
2290
2437
|
// }
|
|
2291
|
-
|
|
2438
|
+
|
|
2292
2439
|
// // Handle strings by concatenating
|
|
2293
2440
|
// if (typeof existingValue === 'string' && typeof newValue === 'string') {
|
|
2294
2441
|
// return existingValue
|
|
2295
2442
|
// }
|
|
2296
|
-
|
|
2443
|
+
|
|
2297
2444
|
// Default: use the new value
|
|
2298
2445
|
return newValue
|
|
2299
2446
|
}
|
|
2300
2447
|
|
|
2301
2448
|
// Process first array
|
|
2302
|
-
safeArr1.forEach(item => {
|
|
2449
|
+
safeArr1.forEach((item) => {
|
|
2303
2450
|
mergedMap.set(item.key, item.value)
|
|
2304
2451
|
})
|
|
2305
2452
|
|
|
2306
2453
|
// Process second array and merge values
|
|
2307
|
-
safeArr2.forEach(item => {
|
|
2454
|
+
safeArr2.forEach((item) => {
|
|
2308
2455
|
const existingValue = mergedMap.get(item.key)
|
|
2309
2456
|
mergedMap.set(item.key, mergeValues(existingValue, item.value))
|
|
2310
2457
|
})
|
|
@@ -2323,7 +2470,7 @@ function mergeArraysByKey(arr1, arr2) {
|
|
|
2323
2470
|
function padZeros(num, minLength = 6) {
|
|
2324
2471
|
num = num.toString()
|
|
2325
2472
|
if (num.length < minLength) {
|
|
2326
|
-
return padZeros(
|
|
2473
|
+
return padZeros(`0${num}`, minLength)
|
|
2327
2474
|
}
|
|
2328
2475
|
return num
|
|
2329
2476
|
}
|
|
@@ -2343,26 +2490,26 @@ function padZeros(num, minLength = 6) {
|
|
|
2343
2490
|
;// ./lib/helpers/replacePlaceholders/replacePlaceholders.js
|
|
2344
2491
|
function replacePlaceholders({ content, mapping }) {
|
|
2345
2492
|
let isObjectMode = false
|
|
2346
|
-
|
|
2493
|
+
|
|
2347
2494
|
if (typeof content === 'object' && content !== null) {
|
|
2348
2495
|
content = JSON.stringify(content)
|
|
2349
2496
|
isObjectMode = true
|
|
2350
2497
|
}
|
|
2351
2498
|
|
|
2352
2499
|
// [[ eventRegistration.eventRegistrationCode | 0 ]]
|
|
2353
|
-
const regex = /(\[*)\[\[\s*([\w.\-
|
|
2500
|
+
const regex = /(\[*)\[\[\s*([\w.\-]+)(?:\s*\|\s*([^:\]\s]+))?(?:\s*:\s*([^\]\s]+))?\s*\]\](\]*)/g
|
|
2354
2501
|
|
|
2355
2502
|
const result = content.replace(regex, (match, leadingBrackets, path, defaultValue, type, trailingBrackets) => {
|
|
2356
|
-
|
|
2357
2503
|
// Split the path into parts
|
|
2358
2504
|
const keys = path.trim().split('.')
|
|
2359
|
-
|
|
2505
|
+
|
|
2360
2506
|
// Traverse the nested object structure
|
|
2361
2507
|
let value = mapping
|
|
2362
2508
|
for (const key of keys) {
|
|
2363
2509
|
// Handle empty keys (in case of double dots or leading/trailing dots)
|
|
2364
|
-
if (!key)
|
|
2365
|
-
|
|
2510
|
+
if (!key)
|
|
2511
|
+
continue
|
|
2512
|
+
|
|
2366
2513
|
value = value?.[key]
|
|
2367
2514
|
if (value === undefined) {
|
|
2368
2515
|
break
|
|
@@ -2370,10 +2517,12 @@ function replacePlaceholders({ content, mapping }) {
|
|
|
2370
2517
|
}
|
|
2371
2518
|
|
|
2372
2519
|
// Apply default if missing
|
|
2373
|
-
if (value === undefined)
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2520
|
+
if (value === undefined)
|
|
2521
|
+
value = defaultValue?.trim()
|
|
2522
|
+
if (value === undefined)
|
|
2523
|
+
return isObjectMode ? undefined : match
|
|
2524
|
+
|
|
2525
|
+
value = value !== undefined
|
|
2377
2526
|
? leadingBrackets + value + trailingBrackets
|
|
2378
2527
|
: match
|
|
2379
2528
|
|
|
@@ -2394,10 +2543,11 @@ function replacePlaceholders({ content, mapping }) {
|
|
|
2394
2543
|
/**
|
|
2395
2544
|
* Sanitizes input by removing hidden/control characters with customizable whitespace handling.
|
|
2396
2545
|
* @param {string} input - The string to sanitize.
|
|
2397
|
-
* @param {
|
|
2398
|
-
* @param {boolean} [options.normalizeWhitespace
|
|
2399
|
-
* @param {boolean} [options.removeNewlines
|
|
2400
|
-
* @param {boolean} [options.trim
|
|
2546
|
+
* @param {object} [options] - Configuration options.
|
|
2547
|
+
* @param {boolean} [options.normalizeWhitespace] - Collapse multiple spaces/tabs into one space.
|
|
2548
|
+
* @param {boolean} [options.removeNewlines] - If true, replaces newlines with spaces.
|
|
2549
|
+
* @param {boolean} [options.trim] - If true, trims leading/trailing whitespace.
|
|
2550
|
+
* @param {boolean} [options.debug] - If true, logs debug information about removed characters.
|
|
2401
2551
|
* @returns {string} The sanitized string.
|
|
2402
2552
|
*/
|
|
2403
2553
|
function sanitizeText(input, options = {}) {
|
|
@@ -2405,7 +2555,8 @@ function sanitizeText(input, options = {}) {
|
|
|
2405
2555
|
normalizeWhitespace = true,
|
|
2406
2556
|
removeNewlines = false,
|
|
2407
2557
|
trim = true,
|
|
2408
|
-
preserveBasicWhitespace = true,
|
|
2558
|
+
preserveBasicWhitespace = true,
|
|
2559
|
+
debug = false, // new option for debugging
|
|
2409
2560
|
} = options
|
|
2410
2561
|
|
|
2411
2562
|
if (typeof input !== 'string') {
|
|
@@ -2414,27 +2565,106 @@ function sanitizeText(input, options = {}) {
|
|
|
2414
2565
|
|
|
2415
2566
|
let result = input
|
|
2416
2567
|
|
|
2568
|
+
if (debug) {
|
|
2569
|
+
console.log('Original input:', JSON.stringify(input))
|
|
2570
|
+
console.log('Options:', { normalizeWhitespace, removeNewlines, trim, preserveBasicWhitespace })
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2417
2573
|
// Phase 1: Remove all control characters except basic whitespace if requested
|
|
2418
2574
|
if (preserveBasicWhitespace && !removeNewlines) {
|
|
2419
|
-
|
|
2420
|
-
|
|
2575
|
+
if (debug) {
|
|
2576
|
+
const before = result
|
|
2577
|
+
const matches = []
|
|
2578
|
+
// Use a replacer function to capture what's being removed
|
|
2579
|
+
result = result.replace(/[\x00-\x08\v\f\x0E-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g, (match) => {
|
|
2580
|
+
matches.push({
|
|
2581
|
+
char: match,
|
|
2582
|
+
code: match.charCodeAt(0),
|
|
2583
|
+
hex: `0x${match.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0')}`
|
|
2584
|
+
})
|
|
2585
|
+
return ''
|
|
2586
|
+
})
|
|
2587
|
+
if (matches.length > 0) {
|
|
2588
|
+
console.log('Phase 1 (preserve mode) - Removed characters:')
|
|
2589
|
+
matches.forEach((m) => {
|
|
2590
|
+
console.log(` - Character: ${JSON.stringify(m.char)}, Code: ${m.code}, Hex: ${m.hex}`)
|
|
2591
|
+
})
|
|
2592
|
+
console.log(`Removed ${matches.length} control character(s)`)
|
|
2593
|
+
} else {
|
|
2594
|
+
console.log('Phase 1 (preserve mode) - No control characters found')
|
|
2595
|
+
}
|
|
2596
|
+
} else {
|
|
2597
|
+
result = result.replace(/[\x00-\x08\v\f\x0E-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g, '')
|
|
2598
|
+
}
|
|
2421
2599
|
} else {
|
|
2422
|
-
|
|
2423
|
-
|
|
2600
|
+
if (debug) {
|
|
2601
|
+
const before = result
|
|
2602
|
+
const matches = []
|
|
2603
|
+
result = result.replace(/[\x00-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g, (match) => {
|
|
2604
|
+
matches.push({
|
|
2605
|
+
char: match,
|
|
2606
|
+
code: match.charCodeAt(0),
|
|
2607
|
+
hex: `0x${match.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0')}`
|
|
2608
|
+
})
|
|
2609
|
+
return ''
|
|
2610
|
+
})
|
|
2611
|
+
if (matches.length > 0) {
|
|
2612
|
+
console.log('Phase 1 (full removal mode) - Removed characters:')
|
|
2613
|
+
matches.forEach((m) => {
|
|
2614
|
+
console.log(` - Character: ${JSON.stringify(m.char)}, Code: ${m.code}, Hex: ${m.hex}`)
|
|
2615
|
+
})
|
|
2616
|
+
console.log(`Removed ${matches.length} control character(s)`)
|
|
2617
|
+
} else {
|
|
2618
|
+
console.log('Phase 1 (full removal mode) - No control characters found')
|
|
2619
|
+
}
|
|
2620
|
+
} else {
|
|
2621
|
+
result = result.replace(/[\x00-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g, '')
|
|
2622
|
+
}
|
|
2623
|
+
}
|
|
2624
|
+
|
|
2625
|
+
if (debug) {
|
|
2626
|
+
console.log('After Phase 1:', JSON.stringify(result))
|
|
2424
2627
|
}
|
|
2425
2628
|
|
|
2426
2629
|
// Phase 2: Handle whitespace transformations
|
|
2427
2630
|
if (removeNewlines) {
|
|
2428
|
-
|
|
2631
|
+
if (debug) {
|
|
2632
|
+
const before = result
|
|
2633
|
+
result = result.replace(/[\r\n]+/g, ' ')
|
|
2634
|
+
console.log('Phase 2 - Converted newlines to spaces')
|
|
2635
|
+
} else {
|
|
2636
|
+
result = result.replace(/[\r\n]+/g, ' ')
|
|
2637
|
+
}
|
|
2429
2638
|
}
|
|
2430
2639
|
|
|
2431
2640
|
if (normalizeWhitespace) {
|
|
2432
|
-
|
|
2641
|
+
if (debug) {
|
|
2642
|
+
const before = result
|
|
2643
|
+
result = result.replace(/[ \t]+/g, ' ')
|
|
2644
|
+
console.log('Phase 2 - Normalized whitespace')
|
|
2645
|
+
} else {
|
|
2646
|
+
result = result.replace(/[ \t]+/g, ' ')
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2649
|
+
|
|
2650
|
+
if (debug) {
|
|
2651
|
+
console.log('After Phase 2:', JSON.stringify(result))
|
|
2433
2652
|
}
|
|
2434
2653
|
|
|
2435
2654
|
// Phase 3: Final trimming
|
|
2436
2655
|
if (trim) {
|
|
2437
|
-
|
|
2656
|
+
if (debug) {
|
|
2657
|
+
const before = result
|
|
2658
|
+
result = result.trim()
|
|
2659
|
+
console.log('Phase 3 - Trimmed leading/trailing whitespace')
|
|
2660
|
+
} else {
|
|
2661
|
+
result = result.trim()
|
|
2662
|
+
}
|
|
2663
|
+
}
|
|
2664
|
+
|
|
2665
|
+
if (debug) {
|
|
2666
|
+
console.log('Final result:', JSON.stringify(result))
|
|
2667
|
+
console.log('--- Sanitization complete ---')
|
|
2438
2668
|
}
|
|
2439
2669
|
|
|
2440
2670
|
return result
|
|
@@ -2445,12 +2675,12 @@ function sanitizeText(input, options = {}) {
|
|
|
2445
2675
|
|
|
2446
2676
|
;// ./lib/helpers/shuffleArray/shuffleArray.js
|
|
2447
2677
|
function shuffleArray(array) {
|
|
2448
|
-
const arr = [...array]
|
|
2449
|
-
for (let i = arr.length - 1; i >= 0; i--) {
|
|
2678
|
+
const arr = [...array]
|
|
2679
|
+
for (let i = arr.length - 1; i >= 0; i--) { // Changed `i > 0` to `i >= 0`
|
|
2450
2680
|
const j = Math.floor(Math.random() * (i + 1));
|
|
2451
|
-
[arr[i], arr[j]] = [arr[j], arr[i]]
|
|
2681
|
+
[arr[i], arr[j]] = [arr[j], arr[i]]
|
|
2452
2682
|
}
|
|
2453
|
-
return arr
|
|
2683
|
+
return arr
|
|
2454
2684
|
}
|
|
2455
2685
|
|
|
2456
2686
|
;// ./lib/helpers/shuffleArray/index.js
|
|
@@ -2512,7 +2742,7 @@ function indexCharset(str) {
|
|
|
2512
2742
|
for (let i = 0; i < length; i++) {
|
|
2513
2743
|
char = str[i]
|
|
2514
2744
|
byCode[i] = char
|
|
2515
|
-
byChar[char] = i
|
|
2745
|
+
byChar[char] = i
|
|
2516
2746
|
}
|
|
2517
2747
|
return { byCode, byChar, length }
|
|
2518
2748
|
}
|
|
@@ -2543,7 +2773,7 @@ function randomString({ len = 16, pattern = 'a1' } = {}) {
|
|
|
2543
2773
|
str += mark
|
|
2544
2774
|
}
|
|
2545
2775
|
const chars = [...str]
|
|
2546
|
-
return [...Array(len)].map(i => {
|
|
2776
|
+
return [...new Array(len)].map((i) => {
|
|
2547
2777
|
return chars[(Math.random() * chars.length) | 0]
|
|
2548
2778
|
}).join``
|
|
2549
2779
|
}
|
|
@@ -2567,12 +2797,14 @@ function setCode(base = 34) {
|
|
|
2567
2797
|
}
|
|
2568
2798
|
|
|
2569
2799
|
function toCamelCase(str) {
|
|
2570
|
-
if (!str)
|
|
2800
|
+
if (!str)
|
|
2801
|
+
return ''
|
|
2571
2802
|
return str
|
|
2572
2803
|
.trim()
|
|
2573
2804
|
.split(/\s+/)
|
|
2574
2805
|
.map((word, index) => {
|
|
2575
|
-
if (!word)
|
|
2806
|
+
if (!word)
|
|
2807
|
+
return ''
|
|
2576
2808
|
if (index === 0) {
|
|
2577
2809
|
return word.toLowerCase()
|
|
2578
2810
|
}
|
|
@@ -2582,7 +2814,8 @@ function toCamelCase(str) {
|
|
|
2582
2814
|
}
|
|
2583
2815
|
|
|
2584
2816
|
function toLowerCase(str) {
|
|
2585
|
-
if (!str)
|
|
2817
|
+
if (!str)
|
|
2818
|
+
return ''
|
|
2586
2819
|
return str
|
|
2587
2820
|
.trim()
|
|
2588
2821
|
.toLowerCase()
|
|
@@ -2617,7 +2850,7 @@ function trackingPlugin(schema, options) {
|
|
|
2617
2850
|
})
|
|
2618
2851
|
|
|
2619
2852
|
// Auto-update hook
|
|
2620
|
-
schema.pre('save', function(next) {
|
|
2853
|
+
schema.pre('save', function (next) {
|
|
2621
2854
|
this.meta.modified = Date.now()
|
|
2622
2855
|
next()
|
|
2623
2856
|
})
|
|
@@ -2629,9 +2862,9 @@ function trackingPlugin(schema, options) {
|
|
|
2629
2862
|
}, {
|
|
2630
2863
|
name: 'tracking_status_index',
|
|
2631
2864
|
background: true,
|
|
2632
|
-
partialFilterExpression: {
|
|
2865
|
+
partialFilterExpression: {
|
|
2633
2866
|
'meta.active': true,
|
|
2634
|
-
'meta.deleted': false
|
|
2867
|
+
'meta.deleted': false
|
|
2635
2868
|
}
|
|
2636
2869
|
})
|
|
2637
2870
|
|
|
@@ -2660,7 +2893,7 @@ function tenantPlugin(schema, options) {
|
|
|
2660
2893
|
|
|
2661
2894
|
// Add core indexes
|
|
2662
2895
|
schema.index({
|
|
2663
|
-
|
|
2896
|
+
tenantCode: 1
|
|
2664
2897
|
}, {
|
|
2665
2898
|
name: 'tenant_core_index',
|
|
2666
2899
|
background: true
|
|
@@ -2668,15 +2901,15 @@ function tenantPlugin(schema, options) {
|
|
|
2668
2901
|
|
|
2669
2902
|
// 1. ENHANCE EXISTING TRACKING INDEXES
|
|
2670
2903
|
const existingIndexes = schema.indexes()
|
|
2671
|
-
|
|
2904
|
+
|
|
2672
2905
|
// Check if tracking_status_index exists
|
|
2673
|
-
const hasTenantStatusIndex = existingIndexes.some(idx =>
|
|
2906
|
+
const hasTenantStatusIndex = existingIndexes.some((idx) =>
|
|
2674
2907
|
idx.name === 'tenant_status_index' // Check by name for reliability
|
|
2675
2908
|
)
|
|
2676
2909
|
|
|
2677
2910
|
if (!hasTenantStatusIndex) {
|
|
2678
2911
|
schema.index({
|
|
2679
|
-
|
|
2912
|
+
tenantCode: 1, // Unique field first
|
|
2680
2913
|
_type: 1, // Low-cardinality field last
|
|
2681
2914
|
}, {
|
|
2682
2915
|
name: 'tenant_status_index',
|
|
@@ -2684,7 +2917,7 @@ function tenantPlugin(schema, options) {
|
|
|
2684
2917
|
partialFilterExpression: {
|
|
2685
2918
|
'_type': 'Tenant',
|
|
2686
2919
|
'meta.active': true,
|
|
2687
|
-
'meta.deleted': false
|
|
2920
|
+
'meta.deleted': false
|
|
2688
2921
|
}
|
|
2689
2922
|
})
|
|
2690
2923
|
}
|
|
@@ -2722,6 +2955,8 @@ function tenantPlugin(schema, options) {
|
|
|
2722
2955
|
|
|
2723
2956
|
|
|
2724
2957
|
|
|
2958
|
+
|
|
2959
|
+
|
|
2725
2960
|
|
|
2726
2961
|
|
|
2727
2962
|
|
|
@@ -2780,10 +3015,11 @@ class AwsStsS3Client {
|
|
|
2780
3015
|
}
|
|
2781
3016
|
|
|
2782
3017
|
get isExpired() {
|
|
2783
|
-
if (!this.expiration)
|
|
2784
|
-
|
|
2785
|
-
const
|
|
2786
|
-
|
|
3018
|
+
if (!this.expiration)
|
|
3019
|
+
return true
|
|
3020
|
+
const now = new Date()
|
|
3021
|
+
const bufferMs = 1 * 60 * 1000 // 一分钟缓冲
|
|
3022
|
+
return now >= new Date(this.expiration.getTime() - bufferMs)
|
|
2787
3023
|
}
|
|
2788
3024
|
|
|
2789
3025
|
get isValid() {
|
|
@@ -2818,7 +3054,7 @@ class AwsStsS3Client {
|
|
|
2818
3054
|
throw new Error(`Missing ${component} in AWS awsClientS3 client configuration`)
|
|
2819
3055
|
}
|
|
2820
3056
|
}
|
|
2821
|
-
|
|
3057
|
+
|
|
2822
3058
|
return true
|
|
2823
3059
|
}
|
|
2824
3060
|
|
|
@@ -2828,9 +3064,9 @@ class AwsStsS3Client {
|
|
|
2828
3064
|
if (!webIdentityToken) {
|
|
2829
3065
|
throw new Error('getIdToken function returned empty or invalid token')
|
|
2830
3066
|
}
|
|
2831
|
-
|
|
3067
|
+
|
|
2832
3068
|
const stsClient = new this.awsClientSts.STSClient({ region: this.region })
|
|
2833
|
-
|
|
3069
|
+
|
|
2834
3070
|
const stsResponse = await stsClient.send(
|
|
2835
3071
|
new this.awsClientSts.AssumeRoleWithWebIdentityCommand({
|
|
2836
3072
|
RoleArn: this.roleArn,
|
|
@@ -3137,29 +3373,30 @@ class KeyValueObject {
|
|
|
3137
3373
|
}
|
|
3138
3374
|
|
|
3139
3375
|
function _mergeValues(existingValue, newValue) {
|
|
3140
|
-
if (existingValue === undefined)
|
|
3141
|
-
|
|
3376
|
+
if (existingValue === undefined)
|
|
3377
|
+
return newValue
|
|
3378
|
+
|
|
3142
3379
|
// Handle arrays by concatenating
|
|
3143
3380
|
if (Array.isArray(existingValue) && Array.isArray(newValue)) {
|
|
3144
3381
|
return [...new Set([...existingValue, ...newValue])]
|
|
3145
3382
|
}
|
|
3146
|
-
|
|
3383
|
+
|
|
3147
3384
|
// Handle objects by merging
|
|
3148
|
-
if (typeof existingValue === 'object' && typeof newValue === 'object'
|
|
3149
|
-
|
|
3385
|
+
if (typeof existingValue === 'object' && typeof newValue === 'object'
|
|
3386
|
+
&& !Array.isArray(existingValue) && !Array.isArray(newValue)) {
|
|
3150
3387
|
return { ...existingValue, ...newValue }
|
|
3151
3388
|
}
|
|
3152
|
-
|
|
3389
|
+
|
|
3153
3390
|
// // Handle numbers by adding
|
|
3154
3391
|
// if (typeof existingValue === 'number' && typeof newValue === 'number') {
|
|
3155
3392
|
// return existingValue
|
|
3156
3393
|
// }
|
|
3157
|
-
|
|
3394
|
+
|
|
3158
3395
|
// // Handle strings by concatenating
|
|
3159
3396
|
// if (typeof existingValue === 'string' && typeof newValue === 'string') {
|
|
3160
3397
|
// return existingValue
|
|
3161
3398
|
// }
|
|
3162
|
-
|
|
3399
|
+
|
|
3163
3400
|
// Default: use the new value
|
|
3164
3401
|
return newValue
|
|
3165
3402
|
}
|
|
@@ -3219,29 +3456,30 @@ function metadata_isSame(key1, key2) {
|
|
|
3219
3456
|
}
|
|
3220
3457
|
|
|
3221
3458
|
function metadata_mergeValues(existingValue, newValue) {
|
|
3222
|
-
if (existingValue === undefined)
|
|
3223
|
-
|
|
3459
|
+
if (existingValue === undefined)
|
|
3460
|
+
return newValue
|
|
3461
|
+
|
|
3224
3462
|
// Handle arrays by concatenating
|
|
3225
3463
|
if (Array.isArray(existingValue) && Array.isArray(newValue)) {
|
|
3226
3464
|
return [...new Set([...existingValue, ...newValue])]
|
|
3227
3465
|
}
|
|
3228
|
-
|
|
3466
|
+
|
|
3229
3467
|
// Handle objects by merging
|
|
3230
|
-
if (typeof existingValue === 'object' && typeof newValue === 'object'
|
|
3231
|
-
|
|
3468
|
+
if (typeof existingValue === 'object' && typeof newValue === 'object'
|
|
3469
|
+
&& !Array.isArray(existingValue) && !Array.isArray(newValue)) {
|
|
3232
3470
|
return { ...existingValue, ...newValue }
|
|
3233
3471
|
}
|
|
3234
|
-
|
|
3472
|
+
|
|
3235
3473
|
// // Handle numbers by adding
|
|
3236
3474
|
// if (typeof existingValue === 'number' && typeof newValue === 'number') {
|
|
3237
3475
|
// return existingValue
|
|
3238
3476
|
// }
|
|
3239
|
-
|
|
3477
|
+
|
|
3240
3478
|
// // Handle strings by concatenating
|
|
3241
3479
|
// if (typeof existingValue === 'string' && typeof newValue === 'string') {
|
|
3242
3480
|
// return existingValue
|
|
3243
3481
|
// }
|
|
3244
|
-
|
|
3482
|
+
|
|
3245
3483
|
// Default: use the new value
|
|
3246
3484
|
return newValue
|
|
3247
3485
|
}
|
|
@@ -3262,14 +3500,14 @@ class TrackedEntity {
|
|
|
3262
3500
|
const timestamp = Date.now()
|
|
3263
3501
|
this.meta = {
|
|
3264
3502
|
active: options.meta?.active ?? options.active ?? true,
|
|
3265
|
-
created: options.meta?.created ?? (options.created
|
|
3266
|
-
|
|
3267
|
-
|
|
3503
|
+
created: options.meta?.created ?? (options.created
|
|
3504
|
+
? new Date(options.created).getTime()
|
|
3505
|
+
: timestamp),
|
|
3268
3506
|
creator: options.meta?.creator ?? options.creator ?? '',
|
|
3269
3507
|
deleted: options.meta?.deleted ?? options.deleted ?? false,
|
|
3270
|
-
modified: options.meta?.modified ?? (options.modified
|
|
3271
|
-
|
|
3272
|
-
|
|
3508
|
+
modified: options.meta?.modified ?? (options.modified
|
|
3509
|
+
? new Date(options.modified).getTime()
|
|
3510
|
+
: timestamp),
|
|
3273
3511
|
owner: options.meta?.owner ?? options.owner ?? '',
|
|
3274
3512
|
}
|
|
3275
3513
|
|
|
@@ -3436,7 +3674,6 @@ class PushEnvelope extends TrackedEntity {
|
|
|
3436
3674
|
get isValid() {
|
|
3437
3675
|
return super.isValid && this.data
|
|
3438
3676
|
}
|
|
3439
|
-
|
|
3440
3677
|
}
|
|
3441
3678
|
|
|
3442
3679
|
;// ./lib/models/pushEnvelope/index.js
|
|
@@ -3503,6 +3740,191 @@ class QMeta {
|
|
|
3503
3740
|
|
|
3504
3741
|
|
|
3505
3742
|
|
|
3743
|
+
;// ./lib/models/status/actionRecord.js
|
|
3744
|
+
|
|
3745
|
+
|
|
3746
|
+
class ActionRecord {
|
|
3747
|
+
constructor(options) {
|
|
3748
|
+
options = options || {}
|
|
3749
|
+
|
|
3750
|
+
const { _Actor } = options._constructor || {}
|
|
3751
|
+
this._Actor = _Actor
|
|
3752
|
+
|
|
3753
|
+
this._actor = options._actor
|
|
3754
|
+
|
|
3755
|
+
this.actorCode = typeof options === 'number' ? null : (options.actorCode || null)
|
|
3756
|
+
this.timestamp = typeof options === 'number' ? options : (options.timestamp || null)
|
|
3757
|
+
}
|
|
3758
|
+
|
|
3759
|
+
static get _classname() {
|
|
3760
|
+
return 'ActionRecord'
|
|
3761
|
+
}
|
|
3762
|
+
static get _superclass() {
|
|
3763
|
+
return 'ActionRecord'
|
|
3764
|
+
}
|
|
3765
|
+
static dummyData() {
|
|
3766
|
+
return {
|
|
3767
|
+
timestamp: (new Date()).valueOf(),
|
|
3768
|
+
}
|
|
3769
|
+
}
|
|
3770
|
+
static init(options = {}) {
|
|
3771
|
+
return init(this, options)
|
|
3772
|
+
}
|
|
3773
|
+
|
|
3774
|
+
get _classname() {
|
|
3775
|
+
return 'ActionRecord'
|
|
3776
|
+
}
|
|
3777
|
+
|
|
3778
|
+
get _superclass() {
|
|
3779
|
+
return 'ActionRecord'
|
|
3780
|
+
}
|
|
3781
|
+
|
|
3782
|
+
get actor() {
|
|
3783
|
+
return this._Actor && typeof this._Actor.init === 'function' ? this._Actor.init(this._actor) : this._actor
|
|
3784
|
+
}
|
|
3785
|
+
|
|
3786
|
+
get isValid() {
|
|
3787
|
+
return !!this.timestamp
|
|
3788
|
+
}
|
|
3789
|
+
|
|
3790
|
+
update(update) {
|
|
3791
|
+
if (typeof update === 'number') {
|
|
3792
|
+
this.timestamp = update
|
|
3793
|
+
return this
|
|
3794
|
+
}
|
|
3795
|
+
Object.keys(update).forEach((key) => {
|
|
3796
|
+
this[key] = update[key]
|
|
3797
|
+
})
|
|
3798
|
+
return this
|
|
3799
|
+
}
|
|
3800
|
+
}
|
|
3801
|
+
|
|
3802
|
+
;// ./lib/models/status/status.js
|
|
3803
|
+
|
|
3804
|
+
|
|
3805
|
+
|
|
3806
|
+
const notUpdateAllowedProps = [
|
|
3807
|
+
'created',
|
|
3808
|
+
// 'statusType'
|
|
3809
|
+
]
|
|
3810
|
+
|
|
3811
|
+
class Status {
|
|
3812
|
+
constructor(options) {
|
|
3813
|
+
options = options || {}
|
|
3814
|
+
|
|
3815
|
+
const { _ActionRecord } = options._constructor || {}
|
|
3816
|
+
this._ActionRecord = _ActionRecord && (_ActionRecord._superclass === ActionRecord._superclass) ? _ActionRecord : ActionRecord
|
|
3817
|
+
|
|
3818
|
+
this.created = this._ActionRecord.init(options.created || { timestamp: (new Date()).valueOf() })
|
|
3819
|
+
// this.statusType = options.statusType || 'Status'
|
|
3820
|
+
}
|
|
3821
|
+
|
|
3822
|
+
static get _classname() {
|
|
3823
|
+
return 'Status'
|
|
3824
|
+
}
|
|
3825
|
+
static get _superclass() {
|
|
3826
|
+
return 'Status'
|
|
3827
|
+
}
|
|
3828
|
+
static dummyData() {
|
|
3829
|
+
return {}
|
|
3830
|
+
}
|
|
3831
|
+
static init(options = {}) {
|
|
3832
|
+
return init(this, options)
|
|
3833
|
+
}
|
|
3834
|
+
static initFromArray(arr = []) {
|
|
3835
|
+
return initFromArray(this, arr)
|
|
3836
|
+
}
|
|
3837
|
+
static initOnlyValidFromArray(arr = []) {
|
|
3838
|
+
return initOnlyValidFromArray(this, arr)
|
|
3839
|
+
}
|
|
3840
|
+
|
|
3841
|
+
get _classname() {
|
|
3842
|
+
return 'Status'
|
|
3843
|
+
}
|
|
3844
|
+
get _superclass() {
|
|
3845
|
+
return 'Status'
|
|
3846
|
+
}
|
|
3847
|
+
get isCreated() {
|
|
3848
|
+
return this.created?.timestamp !== null
|
|
3849
|
+
}
|
|
3850
|
+
get isValid() {
|
|
3851
|
+
return !!this
|
|
3852
|
+
}
|
|
3853
|
+
|
|
3854
|
+
setValue(t, actorCode, key) {
|
|
3855
|
+
const timestamp = t || Date.now()
|
|
3856
|
+
this[key] = this[key] instanceof this._ActionRecord ? this[key].update({ actorCode, timestamp }) : this._ActionRecord.init({ actorCode, timestamp })
|
|
3857
|
+
return this
|
|
3858
|
+
}
|
|
3859
|
+
|
|
3860
|
+
update(update) {
|
|
3861
|
+
Object.keys(update).forEach((key) => {
|
|
3862
|
+
if (!notUpdateAllowedProps.includes(key)) {
|
|
3863
|
+
this[key] = this[key] instanceof this._ActionRecord ? this[key].update(update[key]) : this._ActionRecord.init(update[key])
|
|
3864
|
+
}
|
|
3865
|
+
})
|
|
3866
|
+
return this
|
|
3867
|
+
}
|
|
3868
|
+
}
|
|
3869
|
+
|
|
3870
|
+
;// ./lib/models/status/statusDocument.js
|
|
3871
|
+
|
|
3872
|
+
|
|
3873
|
+
class StatusDocument extends Status {
|
|
3874
|
+
constructor(options) {
|
|
3875
|
+
options = options || {}
|
|
3876
|
+
super(options)
|
|
3877
|
+
|
|
3878
|
+
this.archived = this._ActionRecord.init(options.archived)
|
|
3879
|
+
this.completed = this._ActionRecord.init(options.completed)
|
|
3880
|
+
this.discarded = this._ActionRecord.init(options.discarded)
|
|
3881
|
+
this.drafted = this._ActionRecord.init(options.drafted)
|
|
3882
|
+
// this.statusType = 'StatusDocument'
|
|
3883
|
+
}
|
|
3884
|
+
|
|
3885
|
+
static get _classname() {
|
|
3886
|
+
return 'StatusDocument'
|
|
3887
|
+
}
|
|
3888
|
+
get _classname() {
|
|
3889
|
+
return 'StatusDocument'
|
|
3890
|
+
}
|
|
3891
|
+
get isArchived() {
|
|
3892
|
+
return this.created?.timestamp !== null
|
|
3893
|
+
}
|
|
3894
|
+
get isCompleted() {
|
|
3895
|
+
return this.completed?.timestamp !== null
|
|
3896
|
+
}
|
|
3897
|
+
get isDiscarded() {
|
|
3898
|
+
return this.discarded?.timestamp !== null
|
|
3899
|
+
}
|
|
3900
|
+
get isDrafted() {
|
|
3901
|
+
return this.drafted?.timestamp !== null
|
|
3902
|
+
}
|
|
3903
|
+
get isValid() {
|
|
3904
|
+
return super.isValid
|
|
3905
|
+
}
|
|
3906
|
+
setArchived(value, actorCode) {
|
|
3907
|
+
// const timestamp = value || Date.now()
|
|
3908
|
+
// this.archived = this.archived instanceof this._ActionRecord ? this.archived.update({ actorCode, timestamp }) : this._ActionRecord.init({ actorCode, timestamp })
|
|
3909
|
+
// return this
|
|
3910
|
+
return this.setValue(value, actorCode, 'archived')
|
|
3911
|
+
}
|
|
3912
|
+
setCompleted(value, actorCode) {
|
|
3913
|
+
return this.setValue(value, actorCode, 'completed')
|
|
3914
|
+
}
|
|
3915
|
+
setDiscarded(value, actorCode) {
|
|
3916
|
+
return this.setValue(value, actorCode, 'discarded')
|
|
3917
|
+
}
|
|
3918
|
+
setDrafted(value, actorCode) {
|
|
3919
|
+
return this.setValue(value, actorCode, 'drafted')
|
|
3920
|
+
}
|
|
3921
|
+
}
|
|
3922
|
+
|
|
3923
|
+
;// ./lib/models/status/index.js
|
|
3924
|
+
|
|
3925
|
+
|
|
3926
|
+
|
|
3927
|
+
|
|
3506
3928
|
;// ./lib/models/tenantAwareEntity/tenantAwareEntity.js
|
|
3507
3929
|
|
|
3508
3930
|
|
|
@@ -3643,6 +4065,7 @@ function _makeSetCode(fieldName, options) {
|
|
|
3643
4065
|
|
|
3644
4066
|
|
|
3645
4067
|
|
|
4068
|
+
|
|
3646
4069
|
;// ./lib/index.js
|
|
3647
4070
|
|
|
3648
4071
|
|
|
@@ -3650,4 +4073,4 @@ function _makeSetCode(fieldName, options) {
|
|
|
3650
4073
|
;// ./index.js
|
|
3651
4074
|
|
|
3652
4075
|
|
|
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 };
|
|
4076
|
+
export { ActionRecord, ApiResponse, AwsStsS3Client, KeyValueObject, Metadata, PushEnvelope, QMeta, Repo, Service, Status, StatusDocument, TemplateCompiler, TenantAwareEntity, TrackedEntity, UniqueKeyGenerator, authorize, calculateAge, changeCreatorOwner, concatStringByArray, convertString, detectControlCharacters, escapeRegex, expressHelper, extractEmails, formatDate, generalPost, getValidation, getValueByKeys_getValueByKeys as getValueByKeys, groupArrayByKey, init, initFromArray, initOnlyValidFromArray, isConvertibleToNumber, makeApiResponse, makeService, mergeArraysByKey, objectHelper, pReduce, padZeros, printControlCharReport, replacePlaceholders, sanitizeText, shuffleArray, stringFormatter, stringHelper, tenantPlugin, trackingPlugin };
|