@questwork/q-utilities 0.1.13 → 0.1.14

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.
@@ -0,0 +1,2824 @@
1
+
2
+ ;// ./lib/helpers/authorize/authorize.js
3
+ function authorize({ allowOwner, query = {}, required, user }) {
4
+ if (!user) {
5
+ throw new Error('Require login.')
6
+ }
7
+ if (!user.permission) {
8
+ throw new Error('You do not have any permission.')
9
+ }
10
+ const scopes = user.permission.getScopes(required || {})
11
+ if (!scopes || scopes.length === 0) {
12
+ throw new Error('You are not allowed in this scope.')
13
+ }
14
+ if (!scopes.includes('*')) {
15
+ query.tenantCode = user.tenantCode
16
+ }
17
+ if (!scopes.includes('TENANT')) {
18
+ query.eventShortCode = user.eventShortCode
19
+ }
20
+ if (!scopes.includes('EVENT')) {
21
+ query.eventRegistrationCode = user.eventRegistrationCode
22
+ }
23
+ if (allowOwner) {
24
+ query.__ALLOW_OWNER = true
25
+ }
26
+ // not good, just use it as example
27
+ if (user.hasExcludedFields) {
28
+ query.__EXCLUDED_FIELDS = user.getExcludedFields(required)
29
+ }
30
+ query.__LOGIN_SUBJECT_CODE = user.loginSubjectCode
31
+ return query
32
+ }
33
+
34
+ ;// ./lib/helpers/authorize/index.js
35
+
36
+
37
+ ;// ./lib/helpers/getValidation/getValidation.js
38
+ function getValidation(rule, data, getDataByKey, KeyValueObject) {
39
+ if (!rule) {
40
+ return true
41
+ }
42
+ if (typeof getDataByKey !== 'function' || (KeyValueObject && typeof KeyValueObject !== 'function')) {
43
+ return false
44
+ }
45
+ const { key = '', value, keyValuePath = '' } = rule
46
+ const [valueAttribute] = Object.keys(value)
47
+
48
+ if (!key) {
49
+ switch (valueAttribute) {
50
+ case '$and': {
51
+ return value['$and'].reduce((acc, item) => (acc && getValidation(item, data, getDataByKey, KeyValueObject)), true)
52
+ }
53
+ case '$or': {
54
+ return value['$or'].reduce((acc, item) => (acc || getValidation(item, data, getDataByKey, KeyValueObject)), false)
55
+ }
56
+ default:
57
+ return false
58
+ }
59
+ }
60
+
61
+ let rowValue = getDataByKey(key, data)
62
+
63
+ // debugger
64
+
65
+ // if KeyValue object
66
+ if (keyValuePath) {
67
+ console.log('keyValuePath', keyValuePath)
68
+ const rowValueData = KeyValueObject.toObject(rowValue)
69
+ rowValue = getDataByKey(keyValuePath, rowValueData)
70
+ }
71
+
72
+ switch (valueAttribute) {
73
+ case '$empty': {
74
+ const isEmpty = rowValue === null || rowValue === undefined
75
+ return isEmpty === value['$empty']
76
+ }
77
+ case '$eq': {
78
+ return rowValue === value['$eq']
79
+ }
80
+ case '$gt': {
81
+ return rowValue > value['$gt']
82
+ }
83
+ case '$gte': {
84
+ return rowValue >= value['$gte']
85
+ }
86
+ case '$lt': {
87
+ return rowValue < value['$lt']
88
+ }
89
+ case '$lte': {
90
+ return rowValue <= value['$lte']
91
+ }
92
+ case '$in': {
93
+ if (Array.isArray(rowValue)) {
94
+ return !!rowValue.find((e) => (value['$in'].includes(e)))
95
+ }
96
+ if (typeof rowValue !== 'object') {
97
+ return !!value['$in'].includes(rowValue)
98
+ }
99
+ return false
100
+ }
101
+ case '$inValue': {
102
+ const result = getDataByKey(value['$inValue'], data)
103
+ const _value = Array.isArray(result) ? result : []
104
+ if (Array.isArray(rowValue)) {
105
+ return !!rowValue.find((e) => (_value.includes(e)))
106
+ }
107
+ if (typeof rowValue === 'string') {
108
+ return !!_value.includes(rowValue)
109
+ }
110
+ return false
111
+ }
112
+ case '$ne': {
113
+ return rowValue !== value['$ne']
114
+ }
115
+ case '$notIn': {
116
+ if (Array.isArray(rowValue)) {
117
+ return !rowValue.find((e) => (value['$notIn'].includes(e)))
118
+ }
119
+ if (typeof rowValue !== 'object') {
120
+ return !value['$notIn'].includes(rowValue)
121
+ }
122
+ return false
123
+ }
124
+ case '$intervalTimeGt': {
125
+ const now = new Date().getTime()
126
+ const timestamp = new Date(rowValue).getTime()
127
+ return (now - timestamp) > value['$intervalTimeGt']
128
+ }
129
+ case '$intervalTimeLt': {
130
+ const now = new Date().getTime()
131
+ const timestamp = new Date(rowValue).getTime()
132
+ return (now - timestamp) < value['$intervalTimeLt']
133
+ }
134
+ case '$isToday': {
135
+ const currentDate = new Date()
136
+ const start = currentDate.setHours(0,0,0,0)
137
+ const end = currentDate.setHours(23,59,59,59)
138
+ const dateValue = new Date(rowValue).getTime()
139
+ return (start <= dateValue && end >= dateValue) === value['$isToday']
140
+ }
141
+ case '$notInValue': {
142
+ const result = getDataByKey(value['$notInValue'], data)
143
+ const _value = Array.isArray(result) ? result : []
144
+ if (Array.isArray(rowValue)) {
145
+ return !rowValue.find((e) => (_value.includes(e)))
146
+ }
147
+ if (typeof rowValue !== 'object') {
148
+ return !_value.includes(rowValue)
149
+ }
150
+ return false
151
+ }
152
+ case '$range': {
153
+ const [min, max] = value['$range']
154
+ if (typeof min === 'number' && typeof max === 'number' && rowValue >= min && rowValue <= max) {
155
+ return true
156
+ }
157
+ return false
158
+ }
159
+ default:
160
+ return false
161
+ }
162
+ }
163
+
164
+ /* harmony default export */ const getValidation_getValidation = ({
165
+ getValidation
166
+ });
167
+
168
+
169
+ ;// ./lib/helpers/getValidation/index.js
170
+
171
+
172
+ ;// ./lib/helpers/formatDate/formatDate.js
173
+
174
+ function formatDate(date, format) {
175
+ const _date = date && date instanceof Date ? date : new Date(date)
176
+ const dayMapChi = ['日','一','二','三','四','五','六']
177
+ const dayMapEng = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday']
178
+ const dayMapEngShort = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
179
+ const _format = format || 'YYYY/MM/DD hh:mm'
180
+ const e = _date.getDay()
181
+ const ee = dayMapEngShort[e]
182
+ const eee = dayMapChi[e]
183
+ const eeee = dayMapEng[e]
184
+ const y = _date.getFullYear()
185
+ const m = _date.getMonth() + 1
186
+ const d = _date.getDate()
187
+ const h = _date.getHours()
188
+ const mm = _date.getMinutes()
189
+ const s = _date.getSeconds()
190
+
191
+ return _format.replace('YYYY', y)
192
+ .replace('MM', padding(m))
193
+ .replace('MM', padding(m))
194
+ .replace('DD', padding(d))
195
+ .replace('hh', padding(h))
196
+ .replace('mm', padding(mm))
197
+ .replace('ss', padding(s))
198
+ .replace('M', m)
199
+ .replace('D', d)
200
+ .replace('h', h)
201
+ .replace('m', mm)
202
+ .replace('s', s)
203
+ .replace('EEEE', padding(eeee))
204
+ .replace('EEE', padding(eee))
205
+ .replace('EE', padding(ee))
206
+ .replace('E', padding(e))
207
+ }
208
+
209
+ function padding(m) {
210
+ return m < 10 ? `0${m}` : m
211
+ }
212
+
213
+
214
+ /* harmony default export */ const formatDate_formatDate = ({
215
+ formatDate
216
+ });
217
+
218
+
219
+
220
+ ;// ./lib/helpers/formatDate/index.js
221
+
222
+
223
+ ;// ./lib/helpers/getValueByKeys/getValueByKeys.js
224
+ // keys can be array or object or string
225
+ function getValueByKeys_getValueByKeys(keys, data) {
226
+ let _keys = keys
227
+ let _data = data
228
+ if (typeof keys === 'string') {
229
+ _keys = _keys.split('.')
230
+ }
231
+ if (!Array.isArray(keys) && typeof keys === 'object') {
232
+ const { keys: keyArr, obj } = keys
233
+ _keys = keyArr
234
+ _data = obj
235
+ }
236
+ if (_keys.length === 0) {
237
+ return _data
238
+ }
239
+ const firstKey = _keys.shift()
240
+ if (_data && Object.prototype.hasOwnProperty.call(_data, firstKey)) {
241
+ return getValueByKeys_getValueByKeys(_keys, _data[firstKey])
242
+ }
243
+ if (_data && firstKey) {
244
+ return _data[firstKey]
245
+ }
246
+ return _data
247
+
248
+ }
249
+ /* harmony default export */ const getValueByKeys = ({
250
+ getValueByKeys: getValueByKeys_getValueByKeys
251
+ });
252
+
253
+
254
+ ;// ./lib/helpers/getValueByKeys/index.js
255
+
256
+
257
+ ;// ./lib/models/templateCompiler/templateCompilerException.js
258
+ const TEMPLATE_COMPILER_EXCEPTION_TYPE = {
259
+ argumentEmptyException: 'Argument is empty',
260
+ argumentFormatException: 'Incorrect number or format of argument',
261
+ invalidFuntionException: 'Function Name is invalid',
262
+ invalidRegExpException: 'Invalid regular expression',
263
+ isNotAFunctionException: 'Is not a function',
264
+ notExistException: 'Key does not exist',
265
+ resultEmptyException: 'Result is empty',
266
+ resultMoreThanOneException: 'More than one result'
267
+ }
268
+
269
+ class TemplateCompilerException extends Error {
270
+ constructor(message) {
271
+ super(message)
272
+ this.message = message
273
+ }
274
+ }
275
+
276
+
277
+
278
+ ;// ./lib/models/templateCompiler/constants.js
279
+ const _EMPTY = '_EMPTY'
280
+ const _FN_NAMES = [
281
+ 'concatIf',
282
+ 'divide',
283
+ 'eq',
284
+ 'exec',
285
+ 'filterAll',
286
+ 'filterOne',
287
+ 'formatDate',
288
+ 'get',
289
+ 'gt',
290
+ 'gte',
291
+ 'isEmpty',
292
+ 'isNotEmpty',
293
+ 'join',
294
+ 'lt',
295
+ 'lte',
296
+ 'map',
297
+ 'neq',
298
+ 'removeHtml',
299
+ 'toLowerCase',
300
+ 'toUpperCase',
301
+ ]
302
+ const _HIDE = '_HIDE'
303
+ const _NOT_EMPTY = '_NOT_EMPTY'
304
+ const _SELF = '_SELF'
305
+ const TAGS_EJS = ['<%=', '%>']
306
+ const TAGS_HANDLEBAR = ['{{', '}}']
307
+
308
+
309
+
310
+ ;// ./lib/models/templateCompiler/helpers/_concatIf.js
311
+
312
+
313
+
314
+
315
+ function _concatIf(data, args) {
316
+ if (typeof data !== 'string') {
317
+ throw new TemplateCompilerException(`_concatIf: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: the data must be string :${data.join(', ')}`)
318
+ }
319
+ if (args.length !== 3) {
320
+ throw new TemplateCompilerException(`_concatIf: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
321
+ }
322
+ if (data === null || (typeof data === 'undefined')) {
323
+ return null
324
+ }
325
+ const [condition, success, failover] = args
326
+ const validConditions = [_EMPTY, _NOT_EMPTY]
327
+ if (validConditions.includes(condition) || success.length !== 2) {
328
+ throw new TemplateCompilerException(`concatIf: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentEmptyException}: ${condition}, ${success}`)
329
+ }
330
+ if (data === '' && failover.includes(_HIDE)) {
331
+ return ''
332
+ }
333
+ if (data !== '' && (data !== null || data !== undefined) && failover.includes(_HIDE)) {
334
+ return `${success[0]}${data}${success[success.length - 1]}`
335
+ }
336
+ return failover
337
+ }
338
+
339
+
340
+
341
+ ;// ./lib/models/templateCompiler/helpers/_divide.js
342
+ function _divide(value, divisor) {
343
+ try {
344
+ if (Number.isNaN(value)) {
345
+ return value
346
+ }
347
+ return (value / divisor)
348
+ } catch (e) {
349
+ throw e
350
+ }
351
+ }
352
+
353
+
354
+
355
+ ;// ./lib/models/templateCompiler/helpers/_eq.js
356
+
357
+
358
+
359
+
360
+ function _eq(data, args) {
361
+ if (args.length !== 3) {
362
+ throw new TemplateCompilerException(`eq: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
363
+ }
364
+ if (data === null || (typeof data === 'undefined')) {
365
+ return null
366
+ }
367
+ if (args.includes(_SELF)) {
368
+ args = args.map((arg) => {
369
+ return (arg === _SELF) ? data : arg
370
+ })
371
+ }
372
+ const expected = args[0]
373
+ return data === expected ? args[1] : args[2]
374
+ }
375
+
376
+
377
+
378
+ ;// ./lib/models/templateCompiler/helpers/_exec.js
379
+ function _exec(data, args) {
380
+ try {
381
+ const [methodName, ..._args] = args
382
+ return data[methodName](..._args)
383
+ } catch (e) {
384
+ throw e
385
+ }
386
+ }
387
+
388
+
389
+
390
+ ;// ./lib/models/templateCompiler/helpers/_filterAll.js
391
+
392
+
393
+
394
+ // const DELIMITER = '~~~'
395
+
396
+ function _filterAll(data, args) {
397
+ try {
398
+ if (!Array.isArray(args) || args.length === 0) {
399
+ throw new TemplateCompilerException(TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentEmptyException)
400
+ }
401
+ if (!Array.isArray(data) || data.length === 0) {
402
+ return []
403
+ }
404
+ if (typeof data[0] === 'object') {
405
+ return _existObject(data, args)
406
+ }
407
+ if (typeof data[0] === 'string' || typeof data[0] === 'number') {
408
+ return _exist(data, args)
409
+ }
410
+ return []
411
+ } catch (e) {
412
+ throw e
413
+ }
414
+ }
415
+
416
+ function _exist(data, args) {
417
+ const _args = args.flat()
418
+ return data.filter((e) => _args.some((arg) => _performOperation(arg, e)))
419
+ }
420
+
421
+ function _existObject(data, args) {
422
+ if (args.length === 1) {
423
+ const arg = args[0]
424
+ return data.filter((e) => {
425
+ if (arg.includes('.')) {
426
+ return getValueByKeys_getValueByKeys(arg.split('.'), e)
427
+ }
428
+ return Object.prototype.hasOwnProperty.call(e, arg)
429
+ })
430
+ }
431
+
432
+ if (args.length > 2) {
433
+ let res = data
434
+ for (let i = 0; i < args.length; i += 2) {
435
+ const group = [args[i], args[i + 1]]
436
+ res = _existObject(res, group)
437
+ }
438
+ return res
439
+ }
440
+
441
+ const [key, ..._argsArr] = args
442
+ const _args = _argsArr.flat()
443
+ return data.filter((e) => {
444
+ const value = key.includes('.') ? getValueByKeys_getValueByKeys(key.split('.'), e) : e[key]
445
+ return _args.some((arg) => _performOperation(arg, value))
446
+ })
447
+ }
448
+
449
+ function _performOperation(arg, value) {
450
+ // the arg is undefined
451
+ if (arg === undefined && value === undefined) return true
452
+
453
+ // the arg is null
454
+ if (arg === null && value === null) return true
455
+
456
+ // the arg is boolean
457
+ if (typeof arg === 'boolean') {
458
+ return arg === value
459
+ }
460
+
461
+ // the arg is blank or *: Blank => Empty, * => Not Empty
462
+ if (arg === '' || arg === '*') {
463
+ // null and undefined are not included in either case
464
+ if (value === null || value === undefined) {
465
+ return false
466
+ }
467
+ if (typeof value === 'string') {
468
+ return arg === '' ? value === '' : value !== ''
469
+ }
470
+ if (Array.isArray(value)) {
471
+ return arg === '' ? value.length === 0 : value.length !== 0
472
+ }
473
+ return arg !== ''
474
+ }
475
+
476
+ // the arg is alphabetic or number
477
+ if (_isPureStringOrNumber(arg)) {
478
+ return arg === value
479
+ }
480
+
481
+ // the arg is array of [] or [*]: [] => Empty, [*] => Not Empty
482
+ if (arg.startsWith('[') && arg.endsWith(']')) {
483
+ if (arg === '[]') {
484
+ return Array.isArray(value) && value.length === 0
485
+ }
486
+ if (arg === '[*]') {
487
+ return Array.isArray(value) && value.length !== 0
488
+ }
489
+ return false
490
+ }
491
+
492
+ // the arg is 'operator + string | number'
493
+ const { operator, value: argValue } = _splitOperator(arg)
494
+ if (!operator || (argValue !== 0 && !argValue)) {
495
+ return false
496
+ }
497
+ switch (operator) {
498
+ case '>':
499
+ return value > argValue
500
+ case '<':
501
+ return value < argValue
502
+ case '!=':
503
+ return value !== argValue
504
+ case '>=':
505
+ return value >= argValue
506
+ case '<=':
507
+ return value <= argValue
508
+ default:
509
+ return false
510
+ }
511
+ }
512
+
513
+ function _isPureStringOrNumber(input) {
514
+ if (typeof input === 'string') {
515
+ if (input.startsWith('[') && input.endsWith(']')) {
516
+ return false
517
+ }
518
+ if (/!=|>=|<=|>|</.test(input)) {
519
+ return false
520
+ }
521
+ return true
522
+ }
523
+ return !Number.isNaN(input)
524
+ }
525
+
526
+ function _splitOperator(str) {
527
+ const operators = ['!=', '>=', '<=', '>', '<']
528
+
529
+ const matchedOp = operators.find((op) => str.startsWith(op))
530
+ if (!matchedOp) return { operator: null, value: null }
531
+
532
+ const remaining = str.slice(matchedOp.length)
533
+
534
+ // '>Primary' or '<Primary' is invalid
535
+ if (/^[a-zA-Z]*$/.test(remaining) && matchedOp !== '!=') {
536
+ return { operator: null, value: null }
537
+ }
538
+
539
+ // if it is a number it is converted to a number
540
+ const value = (!Number.isNaN(parseFloat(remaining)) && !Number.isNaN(remaining)) ? Number(remaining) : remaining
541
+
542
+ return {
543
+ operator: matchedOp,
544
+ value
545
+ }
546
+ }
547
+
548
+
549
+
550
+ ;// ./lib/models/templateCompiler/helpers/_filterOne.js
551
+
552
+
553
+
554
+ function _filterOne(data, args) {
555
+ try {
556
+ const list = _filterAll(data, args)
557
+ if (list.length === 1) {
558
+ return list[0]
559
+ }
560
+ if (list.length === 0) {
561
+ return null
562
+ }
563
+ throw new TemplateCompilerException(TEMPLATE_COMPILER_EXCEPTION_TYPE.resultMoreThanOneException)
564
+ } catch (e) {
565
+ throw e
566
+ }
567
+ }
568
+
569
+
570
+
571
+ ;// ./lib/models/templateCompiler/helpers/_formatDate.js
572
+
573
+
574
+ function _formatDate(timestamp, format) {
575
+ if (format.length === 0) {
576
+ throw new TemplateCompilerException(`_formateDate: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: format parts must be not empty array`)
577
+ }
578
+
579
+ if (timestamp === null || timestamp === undefined) {
580
+ return null
581
+ }
582
+
583
+ const date = new Date(timestamp)
584
+
585
+ const partsMap = {
586
+ yyyy: String(date.getFullYear()),
587
+ mm: String(date.getMonth() + 1).padStart(2, '0'),
588
+ dd: String(date.getDate()).padStart(2, '0')
589
+ }
590
+
591
+ // Check for invalid format tokens
592
+ const validTokens = ['yyyy', 'mm', 'dd']
593
+ const invalidTokens = format.filter((part) => part.length > 1 && !validTokens.includes(part))
594
+
595
+ if (invalidTokens.length > 0) {
596
+ throw new TemplateCompilerException(
597
+ `_formateDate: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: the format type is not valid: ${format.join(', ')}`
598
+ )
599
+ }
600
+
601
+ // Build the formatted string using reduce
602
+ return format.reduce((result, part) => result + (partsMap[part] || part), '')
603
+ }
604
+
605
+
606
+
607
+ ;// ./lib/models/templateCompiler/helpers/_get.js
608
+
609
+
610
+ function _get(data, key, failover = null) {
611
+ try {
612
+ if (key === null || (typeof key === 'undefined') || key === '') {
613
+ throw new TemplateCompilerException(TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentEmptyException)
614
+ }
615
+ if (data === null) {
616
+ return null
617
+ }
618
+ if (key.includes('.')) {
619
+ const parts = key.split('.')
620
+ if (parts.length > 1) {
621
+ const first = parts.shift()
622
+ const remainingKey = parts.join('.')
623
+ if (typeof data[first] !== 'undefined') {
624
+ return _get(data[first], remainingKey, failover)
625
+ }
626
+ return _handleFailover(key, failover)
627
+ }
628
+ }
629
+ if (typeof data[key] !== 'undefined') {
630
+ return data[key]
631
+ }
632
+ return _handleFailover(key, failover)
633
+ } catch (e) {
634
+ throw e
635
+ }
636
+ }
637
+
638
+ function _handleFailover(key, failover) {
639
+ if (failover !== null) {
640
+ return failover
641
+ }
642
+ return null
643
+ // throw new TemplateCompilerException(`Key "${key}" does not exist and no failover`)
644
+ }
645
+
646
+
647
+
648
+ ;// ./lib/models/templateCompiler/helpers/_gt.js
649
+
650
+
651
+
652
+
653
+ function _gt(data, args) {
654
+ if (args.length !== 3) {
655
+ throw new TemplateCompilerException(`_gt: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
656
+ }
657
+ if (data === null || (typeof data === 'undefined')) {
658
+ return null
659
+ }
660
+ if (args.includes(_SELF)) {
661
+ args = args.map((arg) => {
662
+ return (arg === _SELF) ? data : arg
663
+ })
664
+ }
665
+ const expected = args[0]
666
+ return data > expected ? args[1] : args[2]
667
+ }
668
+
669
+
670
+
671
+ ;// ./lib/models/templateCompiler/helpers/_gte.js
672
+
673
+
674
+
675
+
676
+ function _gte(data, args) {
677
+ if (args.length !== 3) {
678
+ throw new TemplateCompilerException(`_gte: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
679
+ }
680
+ if (data === null || (typeof data === 'undefined')) {
681
+ return null
682
+ }
683
+ if (args.includes(_SELF)) {
684
+ args = args.map((arg) => {
685
+ return (arg === _SELF) ? data : arg
686
+ })
687
+ }
688
+ const expected = args[0]
689
+ return data >= expected ? args[1] : args[2]
690
+ }
691
+
692
+
693
+
694
+ ;// ./lib/models/templateCompiler/helpers/_isEmpty.js
695
+
696
+
697
+
698
+
699
+ function _isEmpty(data, args) {
700
+ if (args.length !== 2) {
701
+ throw new TemplateCompilerException(`_isEmpty: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
702
+ }
703
+ // if (data === null || (typeof data === 'undefined')) {
704
+ // return null
705
+ // }
706
+ if (args.includes(_SELF)) {
707
+ args = args.map((arg) => {
708
+ return (arg === _SELF) ? data : arg
709
+ })
710
+ }
711
+ if (data !== null && typeof data === 'object' && Object.keys(data).length === 0) {
712
+ return args[0]
713
+ }
714
+ return (data === '' || data === null || data === undefined || data.length === 0) ? args[0] : args[1]
715
+ }
716
+
717
+
718
+
719
+ ;// ./lib/models/templateCompiler/helpers/_isNotEmpty.js
720
+
721
+
722
+
723
+
724
+ function _isNotEmpty(data, args) {
725
+ if (args.length !== 2) {
726
+ throw new TemplateCompilerException(`_isNotEmpty: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
727
+ }
728
+ // if (data === null || (typeof data === 'undefined')) {
729
+ // return null
730
+ // }
731
+ if (args.includes(_SELF)) {
732
+ args = args.map((arg) => {
733
+ return (arg === _SELF) ? data : arg
734
+ })
735
+ }
736
+ if (data !== null && typeof data === 'object' && Object.keys(data).length === 0) {
737
+ return args[1]
738
+ }
739
+ if (Array.isArray(data) && data.length === 0) {
740
+ return args[1]
741
+ }
742
+ if (typeof data === 'string' && data === '') {
743
+ return args[1]
744
+ }
745
+ if (data === null || data === undefined) {
746
+ return args[1]
747
+ }
748
+ return args[0]
749
+ }
750
+
751
+
752
+ ;// ./lib/models/templateCompiler/helpers/_join.js
753
+ function _join(data, delimiter) {
754
+ try {
755
+ if (data.length === 0) return ''
756
+ if (data.length === 1) return _stringifyObject(data[0])
757
+ return data.map((item) => _stringifyObject(item)).join(delimiter)
758
+ } catch (e) {
759
+ throw e
760
+ }
761
+ }
762
+
763
+ function _stringifyObject(obj) {
764
+ return JSON.stringify(obj).replace(/"([^"]+)":/g, '$1: ').replace(/"([^"]+)"/g, '$1').replace(/,/g, ', ')
765
+ }
766
+
767
+
768
+
769
+ ;// ./lib/models/templateCompiler/helpers/_lt.js
770
+
771
+
772
+
773
+
774
+ function _lt(data, args) {
775
+ if (args.length !== 3) {
776
+ throw new TemplateCompilerException(`_lt: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
777
+ }
778
+ if (data === null || (typeof data === 'undefined')) {
779
+ return null
780
+ }
781
+ if (args.includes(_SELF)) {
782
+ args = args.map((arg) => {
783
+ return (arg === _SELF) ? data : arg
784
+ })
785
+ }
786
+ const expected = args[0]
787
+ return data < expected ? args[1] : args[2]
788
+ }
789
+
790
+
791
+
792
+ ;// ./lib/models/templateCompiler/helpers/_lte.js
793
+
794
+
795
+
796
+
797
+ function _lte(data, args) {
798
+ if (args.length !== 3) {
799
+ throw new TemplateCompilerException(`_lte: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
800
+ }
801
+ if (data === null || (typeof data === 'undefined')) {
802
+ return null
803
+ }
804
+ if (args.includes(_SELF)) {
805
+ args = args.map((arg) => {
806
+ return (arg === _SELF) ? data : arg
807
+ })
808
+ }
809
+ const expected = args[0]
810
+ return data <= expected ? args[1] : args[2]
811
+ }
812
+
813
+
814
+
815
+ ;// ./lib/models/templateCompiler/helpers/_map.js
816
+
817
+
818
+
819
+ function _map(data, args) {
820
+ try {
821
+ if (args.length === 0) {
822
+ throw new TemplateCompilerException(TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentEmptyException)
823
+ }
824
+ if (data === null || (typeof data === 'undefined')) {
825
+ return null
826
+ }
827
+
828
+ const result = data.reduce((acc, item) => {
829
+ if (args.length === 1 && Array.isArray(args[0])) {
830
+ args = args[0]
831
+ acc.hasFormat = true
832
+ }
833
+ const list = args.map((key) => {
834
+ if (key.includes('.')) {
835
+ const parts = key.split('.')
836
+ const first = parts[0]
837
+ parts.shift()
838
+ const remainingKey = parts.join('.')
839
+ return _get(item[first], remainingKey)
840
+ }
841
+ if (typeof item[key] !== 'undefined') {
842
+ return item[key]
843
+ }
844
+ return null
845
+ })
846
+ if (acc.hasFormat) {
847
+ acc.content.push(list)
848
+ } else {
849
+ acc.content = acc.content.concat(list)
850
+ }
851
+ return acc
852
+ }, {
853
+ content: [],
854
+ hasFormat: false
855
+ })
856
+ return result.content
857
+ } catch (e) {
858
+ throw e
859
+ }
860
+ }
861
+
862
+
863
+
864
+ ;// ./lib/models/templateCompiler/helpers/_neq.js
865
+
866
+
867
+
868
+
869
+ function _neq(data, args) {
870
+ if (args.length !== 3) {
871
+ throw new TemplateCompilerException(`_neq: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
872
+ }
873
+ if (data === null || (typeof data === 'undefined')) {
874
+ return null
875
+ }
876
+ if (args.includes(_SELF)) {
877
+ args = args.map((arg) => {
878
+ return (arg === _SELF) ? data : arg
879
+ })
880
+ }
881
+ const expected = args[0]
882
+ return data !== expected ? args[1] : args[2]
883
+ }
884
+
885
+
886
+
887
+ ;// ./lib/models/templateCompiler/helpers/_removeHtml.js
888
+
889
+
890
+ function _removeHtml(html, args) {
891
+ if (html === null || html === undefined) {
892
+ return null
893
+ }
894
+ if (!Array.isArray(args)) {
895
+ throw new TemplateCompilerException(`_removeHtml: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: args parts must be array`)
896
+ }
897
+
898
+ return _htmlToPlainText(html, args[0])
899
+ }
900
+
901
+ function _htmlToPlainText(html, delimiter = '\n') {
902
+ if (typeof delimiter !== 'string') {
903
+ delimiter = '\n'; // Fallback to default if not a string
904
+ }
905
+
906
+ // First decode HTML entities and normalize whitespace
907
+ const decodedHtml = html
908
+ .replace(/&nbsp;/g, ' ')
909
+ .replace(/\s+/g, ' '); // Collapse all whitespace to single spaces
910
+
911
+ // Process HTML tags
912
+ let text = decodedHtml
913
+ // Replace block tags with temporary marker (~~~)
914
+ .replace(/<\/?(p|div|h[1-6]|ul|ol|li|pre|section|article|table|tr|td|th)(\s[^>]*)?>/gi, '~~~')
915
+ // Replace <br> tags with temporary marker (~~~)
916
+ .replace(/<br\s*\/?>/gi, '~~~')
917
+ // Remove all other tags
918
+ .replace(/<[^>]+>/g, '')
919
+ // Convert markers to specified delimiter
920
+ .replace(/~~~+/g, delimiter)
921
+ // Trim and clean whitespace
922
+ .trim();
923
+
924
+ // Special handling for empty delimiter
925
+ if (delimiter === '') {
926
+ // Collapse all whitespace to single space
927
+ text = text.replace(/\s+/g, ' ');
928
+ } else {
929
+
930
+
931
+ // Collapse multiple delimiters to single
932
+ text = text.replace(new RegExp(`${escapeRegExp(delimiter)}+`, 'g'), delimiter);
933
+ // Remove leading/trailing delimiters
934
+ text = text.replace(new RegExp(`^${escapeRegExp(delimiter)}|${escapeRegExp(delimiter)}$`, 'g'), '');
935
+ }
936
+
937
+ return text;
938
+ }
939
+
940
+
941
+ function escapeRegExp(string) {
942
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
943
+ }
944
+
945
+
946
+
947
+ ;// ./lib/models/templateCompiler/helpers/_toLowerCase.js
948
+
949
+
950
+ function _toLowerCase(data, args) {
951
+ if (args !== undefined) {
952
+ throw new TemplateCompilerException(`_toLowerCase: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
953
+ }
954
+ if (data === null || (typeof data === 'undefined') || typeof data !== 'string') {
955
+ return null
956
+ }
957
+ return String(data).toLowerCase()
958
+ }
959
+
960
+
961
+
962
+ ;// ./lib/models/templateCompiler/helpers/_toUpperCase.js
963
+
964
+
965
+ function _toUpperCase(data, args) {
966
+ if (typeof data !== 'string') {
967
+ throw new TemplateCompilerException(`_toUpperCase: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: the data must be string: ${data}`)
968
+ }
969
+ if (args !== undefined) {
970
+ throw new TemplateCompilerException(`_toUpperCase: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: the argument must be empty: ${args.join(', ')}`)
971
+ }
972
+ if (data === null || (typeof data === 'undefined') || typeof data !== 'string') {
973
+ return null
974
+ }
975
+ return String(data).toUpperCase()
976
+ }
977
+
978
+
979
+
980
+ ;// ./lib/models/templateCompiler/helpers/index.js
981
+
982
+
983
+
984
+
985
+
986
+
987
+
988
+
989
+
990
+
991
+
992
+
993
+
994
+
995
+
996
+
997
+
998
+
999
+
1000
+
1001
+
1002
+
1003
+
1004
+ ;// ./lib/models/templateCompiler/templateCompiler.js
1005
+
1006
+
1007
+
1008
+
1009
+ class TemplateCompiler {
1010
+ constructor(data) {
1011
+ this.data = data
1012
+ }
1013
+ static init(options) {
1014
+ return new this(options)
1015
+ }
1016
+ static initFromArray(arr = []) {
1017
+ if (Array.isArray(arr)) {
1018
+ return arr.map((a) => this.init(a))
1019
+ }
1020
+ return []
1021
+ }
1022
+ static initOnlyValidFromArray(arr = []) {
1023
+ return this.initFromArray(arr).filter((i) => i)
1024
+ }
1025
+ static concatIf(data, args) {
1026
+ return _concatIf(data, args)
1027
+ }
1028
+ static divide(data, args) {
1029
+ return _divide(data, args)
1030
+ }
1031
+ static eq(data, args) {
1032
+ return _eq(data, args)
1033
+ }
1034
+
1035
+ static filterAll(data, args) {
1036
+ return _filterAll(data, args)
1037
+ }
1038
+
1039
+ static formatDate(data, args) {
1040
+ return _formatDate(data, args)
1041
+ }
1042
+ static get(data, key, failover = null) {
1043
+ return _get(data, key, failover)
1044
+ }
1045
+ static gt(data, args) {
1046
+ return _gt(data, args)
1047
+ }
1048
+ static gte(data, args) {
1049
+ return _gte(data, args)
1050
+ }
1051
+ static isEmpty(data, args) {
1052
+ return _isEmpty(data, args)
1053
+ }
1054
+ static isNotEmpty(data, args) {
1055
+ return _isNotEmpty(data, args)
1056
+ }
1057
+ static join(data, separator = '') {
1058
+ return _join(data, separator)
1059
+ }
1060
+ static lt(data, args) {
1061
+ return _lt(data, args)
1062
+ }
1063
+ static lte(data, args) {
1064
+ return _lte(data, args)
1065
+ }
1066
+ static map(data, args = []) {
1067
+ return _map(data, args)
1068
+ }
1069
+ static neq(data, args) {
1070
+ return _neq(data, args)
1071
+ }
1072
+ static removeHtml(data, args) {
1073
+ return _removeHtml(data, args)
1074
+ }
1075
+ static toLowerCase(data, args) {
1076
+ return _toLowerCase(data, args)
1077
+ }
1078
+ static toUpperCase(data, args) {
1079
+ return _toUpperCase(data, args)
1080
+ }
1081
+ static parseFunction(expression) {
1082
+ return _parseFunction(expression, _FN_NAMES)
1083
+ }
1084
+ static parseParams(parameters) {
1085
+ return _parseParams(parameters)
1086
+ }
1087
+
1088
+ pipe(expression = '') {
1089
+ this.delimiters = expression.substring(0, 2) === '{{' ? TAGS_HANDLEBAR : TAGS_EJS
1090
+ const regex = new RegExp(`${this.delimiters[0]}\\s(.*?)\\s${this.delimiters[1]}`)
1091
+ const match = expression.match(regex)
1092
+ if (match !== null) {
1093
+ try {
1094
+ const functionList = _parseFunction(match[1], _FN_NAMES)
1095
+ return functionList.reduce((acc, fn) => {
1096
+ return _callFunction(acc, fn.name, fn.args)
1097
+ }, this.data)
1098
+ } catch (e) {
1099
+ throw new TemplateCompilerException(`TemplateCompiler engine error: ${e.message}`)
1100
+ }
1101
+ }
1102
+ throw new TemplateCompilerException(`TemplateCompiler engine error: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.invalidRegExpException}`)
1103
+ }
1104
+ }
1105
+
1106
+ function _parseFunction(expression, existFunctionNames) {
1107
+ const regExp = new RegExp(/(\w+)\(([^)]*)\)/)
1108
+ let parts
1109
+ if (expression.includes('|')) {
1110
+ parts = expression.split('|')
1111
+ } else {
1112
+ parts = [expression]
1113
+ }
1114
+ return parts.reduce((acc, part) => {
1115
+ const match = part.match(regExp)
1116
+ if (match !== null) {
1117
+ const functionName = match[1]
1118
+ const parameters = match[2]
1119
+ const paramList = _parseParams(parameters)
1120
+ if (existFunctionNames.includes(functionName)) {
1121
+ acc.push({
1122
+ name: functionName,
1123
+ args: paramList
1124
+ })
1125
+ } else {
1126
+ throw new TemplateCompilerException(`${functionName} is not a valid function`)
1127
+ }
1128
+ }
1129
+ return acc
1130
+ }, [])
1131
+ }
1132
+
1133
+ function _parseParams(parameters) {
1134
+ const _parameters = parameters.trim()
1135
+ const regExp = new RegExp(/^[^\w\d\s]+$/)
1136
+ const match = _parameters.match(regExp)
1137
+ if (match !== null) {
1138
+ return [_parameters.substring(1, _parameters.length - 1)]
1139
+ }
1140
+ if (_parameters.includes(',')) {
1141
+ // 用正则表达式匹配逗号,但忽略方括号中的逗号
1142
+ const parts = _splitIgnoringBrackets(_parameters)
1143
+ return parts.map((part) => _parseSinglePart(part))
1144
+ }
1145
+ return [_parseSinglePart(_parameters)]
1146
+ }
1147
+
1148
+ function _splitIgnoringBrackets(input) {
1149
+ const regExp2 = new RegExp(/^\d+(\.\d+)?$/)
1150
+ const regExp = new RegExp(/(?![^\[]*\])\s*,\s*/)
1151
+ const parts = input.split(regExp)
1152
+ return parts.map((part) => {
1153
+ const _part = part.trim()
1154
+ if (_part !== '' && !!_part.match(regExp2)) {
1155
+ // 如果是数字,转换为 num 类型
1156
+ return Number.isNaN(_part) ? _part : parseInt(_part, 10)
1157
+ }
1158
+ // 否则当作字符串处理
1159
+ return _part
1160
+ })
1161
+ }
1162
+
1163
+ function _parseSinglePart(input) {
1164
+ if (typeof input === 'string') {
1165
+ if (input.startsWith('"') && input.endsWith('"')) {
1166
+ // 去掉双引号,返回
1167
+ return input.substring(1, input.length - 1)
1168
+ }
1169
+ if (input.startsWith("'") && input.endsWith("'")) {
1170
+ // 去掉双引号,返回
1171
+ return input.substring(1, input.length - 1)
1172
+ }
1173
+
1174
+ const _input = _toBasicType(input)
1175
+
1176
+ if (typeof _input !== 'string') {
1177
+ return _input
1178
+ }
1179
+
1180
+ // 如果是一个列表形式(例如 ["p", "d"] 或 [p, d])
1181
+ if (_input.startsWith('[') && _input.endsWith(']')) {
1182
+ const listContent = _input.substring(1, _input.length - 1).trim()
1183
+ if (listContent !== '') {
1184
+ return listContent.split(',').map((item) => {
1185
+ return _toBasicType(item.trim())
1186
+ })
1187
+ }
1188
+ return []
1189
+ }
1190
+ return input
1191
+ }
1192
+ return input
1193
+ }
1194
+
1195
+ function _toBasicType(input) {
1196
+ if (input.startsWith('"') && input.endsWith('"')) {
1197
+ // 去掉双引号,返回
1198
+ return input.substring(1, input.length - 1)
1199
+ }
1200
+ if (input.startsWith("'") && input.endsWith("'")) {
1201
+ // 去掉双引号,返回
1202
+ return input.substring(1, input.length - 1)
1203
+ }
1204
+ if (input === 'true') {
1205
+ return true
1206
+ }
1207
+ if (input === 'false') {
1208
+ return false
1209
+ }
1210
+ if (input === 'undefined') {
1211
+ return undefined
1212
+ }
1213
+ if (input === 'null') {
1214
+ return null
1215
+ }
1216
+ if (!Number.isNaN(input) && !Number.isNaN(Number.parseFloat(input))) {
1217
+ return Number(input)
1218
+ }
1219
+ return input
1220
+ }
1221
+
1222
+ function _callFunction(data, functionName, parameters) {
1223
+ try {
1224
+ let failover
1225
+ switch (functionName) {
1226
+ case 'concatIf':
1227
+ return _concatIf(data, parameters)
1228
+ case 'divide':
1229
+ return _divide(data, parameters)
1230
+ case 'eq':
1231
+ return _eq(data, parameters)
1232
+ case 'exec':
1233
+ return _exec(data, parameters)
1234
+ case 'filterAll':
1235
+ return _filterAll(data, parameters)
1236
+ case 'filterOne':
1237
+ return _filterOne(data, parameters)
1238
+ case 'formatDate':
1239
+ return _formatDate(data, parameters)
1240
+ case 'get':
1241
+ if (parameters.length > 2) {
1242
+ throw new TemplateCompilerException(TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException)
1243
+ }
1244
+ if (parameters.length === 2) {
1245
+ failover = parameters[parameters.length - 1]
1246
+ }
1247
+ return _get(data, parameters[0], failover)
1248
+ case 'gt':
1249
+ return _gt(data, parameters)
1250
+ case 'gte':
1251
+ return _gte(data, parameters)
1252
+ case 'isEmpty':
1253
+ return _isEmpty(data, parameters)
1254
+ case 'isNotEmpty':
1255
+ return _isNotEmpty(data, parameters)
1256
+ case 'join':
1257
+ return _join(data, parameters[0])
1258
+ case 'lt':
1259
+ return _lt(data, parameters)
1260
+ case 'lte':
1261
+ return _lte(data, parameters)
1262
+ case 'map':
1263
+ return _map(data, parameters)
1264
+ case 'neq':
1265
+ return _neq(data, parameters)
1266
+ case 'removeHtml':
1267
+ return _removeHtml(data, parameters)
1268
+ case 'toLowerCase':
1269
+ return _toLowerCase(data)
1270
+ case 'toUpperCase':
1271
+ return _toUpperCase(data)
1272
+ default:
1273
+ throw new Error(`${functionName} is not a valid function`)
1274
+ }
1275
+ } catch (e) {
1276
+ throw e
1277
+ }
1278
+ }
1279
+
1280
+
1281
+
1282
+ ;// ./lib/models/templateCompiler/index.js
1283
+
1284
+
1285
+
1286
+
1287
+ ;// ./lib/helpers/concatStringByArray/concatStringByArray.js
1288
+
1289
+
1290
+
1291
+
1292
+
1293
+ function concatStringByArray(arrTemplate, data) {
1294
+ return arrTemplate.reduce((acc, item) => {
1295
+ const { type, value = '', restriction, template, format, showMinutes } = item
1296
+ switch (type) {
1297
+ case('label'): {
1298
+ if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
1299
+ acc += (value.toString())
1300
+ }
1301
+ break
1302
+ }
1303
+ case('value'): {
1304
+ if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
1305
+ const _value = getValueByKeys_getValueByKeys(value.split('.'), data) || ''
1306
+ acc += (_value.toString())
1307
+ }
1308
+ break
1309
+ }
1310
+ case('array'): {
1311
+ if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
1312
+ const _value = getValueByKeys_getValueByKeys(value.split('.'), data) || []
1313
+ acc += _value.reduce((_acc, item) => {
1314
+ return _acc += concatStringByArray(template, item)
1315
+ }, '')
1316
+ }
1317
+ break
1318
+ }
1319
+ case('ellipsis'): {
1320
+ if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
1321
+ const { maxLength } = item
1322
+ const _value = getValueByKeys_getValueByKeys(value.split('.'), data) || ''
1323
+ if (_value.length <= maxLength) {
1324
+ acc += (_value.toString())
1325
+ } else {
1326
+ acc += `${_value.substr(0, maxLength)}...`
1327
+ }
1328
+ }
1329
+ break
1330
+ }
1331
+ case ('date'): {
1332
+ if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
1333
+ const _value = getValueByKeys_getValueByKeys(value.split('.'), data) || ''
1334
+ acc += (formatDate(_value, format).toString())
1335
+ }
1336
+ break
1337
+ }
1338
+ case ('templateCompiler'): {
1339
+ if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
1340
+ const templateCompiler = new TemplateCompiler({ data })
1341
+ acc += templateCompiler.pipe(value)
1342
+ }
1343
+ break
1344
+ }
1345
+ }
1346
+ return acc
1347
+ }, '')
1348
+ }
1349
+ /* harmony default export */ const concatStringByArray_concatStringByArray = ({
1350
+ concatStringByArray
1351
+ });
1352
+
1353
+
1354
+
1355
+ ;// ./lib/helpers/concatStringByArray/index.js
1356
+
1357
+
1358
+ ;// ./lib/helpers/convertString/convertString.js
1359
+
1360
+
1361
+ function convertString(string, patternMatch = /\$\{(.+?)\}/g, value, getValueByKeys) {
1362
+ if (!string) {
1363
+ return ''
1364
+ }
1365
+ let _getValueByKeys = typeof getValueByKeys !== 'function' ? getValueByKeys : getValueByKeys_getValueByKeys
1366
+ const reg = new RegExp(patternMatch, 'g')
1367
+ return string.replace(reg, (match, key) => {
1368
+ const result = _getValueByKeys({ keys: key.split('.'), obj: value })
1369
+ if (result === null || result === undefined) {
1370
+ return ''
1371
+ }
1372
+ return typeof result === 'object' ? JSON.stringify(result) : result
1373
+ })
1374
+ }
1375
+
1376
+ /* harmony default export */ const convertString_convertString = ({
1377
+ convertString
1378
+ });
1379
+
1380
+
1381
+ ;// ./lib/helpers/convertString/index.js
1382
+
1383
+
1384
+ ;// ./lib/helpers/objectHelper/objectHelper.js
1385
+ const objectHelper = {
1386
+ get(obj, path) {
1387
+ const parts = path.split('.')
1388
+ return parts.reduce((acc, part) => {
1389
+ if (part.endsWith('[]')) {
1390
+ // 处理数组遍历
1391
+ const key = part.slice(0, -2) // 去掉 '[]' 得到属性名
1392
+ if (Array.isArray(acc[key])) {
1393
+ return acc[key] // 返回整个数组
1394
+ }
1395
+ return [] // 如果不是数组,返回空数组
1396
+ }
1397
+ if (part.includes('[') && part.includes(']')) {
1398
+ // 处理数组索引
1399
+ const arrayMatch = part.match(/(\w+)\[(\d+)\]/)
1400
+ if (arrayMatch) {
1401
+ const key = arrayMatch[1]
1402
+ const index = arrayMatch[2]
1403
+ return acc && acc[key] && acc[key][index]
1404
+ }
1405
+ } else if (acc && Array.isArray(acc)) {
1406
+ // 如果当前值是数组,提取每个对象的指定属性
1407
+ return acc.map((item) => item[part])
1408
+ } else {
1409
+ // 处理普通属性
1410
+ return acc && acc[part]
1411
+ }
1412
+ }, obj)
1413
+ },
1414
+ merge,
1415
+ set(obj, path, value) {
1416
+ const parts = path.split('.');
1417
+ let current = obj;
1418
+
1419
+ // 处理所有中间部分
1420
+ for (let i = 0; i < parts.length - 1; i++) {
1421
+ const part = parts[i];
1422
+ let key, index;
1423
+
1424
+ // 检查是否是数组索引格式,如key[0]
1425
+ const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/);
1426
+ if (arrayMatch) {
1427
+ key = arrayMatch[1];
1428
+ index = parseInt(arrayMatch[2], 10);
1429
+ // 确保当前层级的数组存在
1430
+ if (!current[key] || !Array.isArray(current[key])) {
1431
+ current[key] = [];
1432
+ }
1433
+ // 扩展数组到足够大
1434
+ while (current[key].length <= index) {
1435
+ current[key].push(undefined);
1436
+ }
1437
+ // 如果当前位置未定义或为null,初始化为对象
1438
+ if (current[key][index] == null) {
1439
+ current[key][index] = {};
1440
+ }
1441
+ current = current[key][index];
1442
+ } else {
1443
+ // 处理普通属性
1444
+ if (!current[part]) {
1445
+ current[part] = {};
1446
+ }
1447
+ current = current[part];
1448
+ }
1449
+ }
1450
+
1451
+ // 处理最后一部分
1452
+ const lastPart = parts[parts.length - 1];
1453
+ const arrayMatch = lastPart.match(/^(\w+)\[(\d+)\]$/);
1454
+ if (arrayMatch) {
1455
+ const key = arrayMatch[1];
1456
+ const index = parseInt(arrayMatch[2], 10);
1457
+ // 确保数组存在
1458
+ if (!current[key] || !Array.isArray(current[key])) {
1459
+ current[key] = [];
1460
+ }
1461
+ // 扩展数组到所需索引
1462
+ while (current[key].length <= index) {
1463
+ current[key].push(undefined);
1464
+ }
1465
+ current[key][index] = value;
1466
+ } else {
1467
+ current[lastPart] = value;
1468
+ }
1469
+ }
1470
+ }
1471
+
1472
+ function merge(target, ...sources) {
1473
+ if (!sources.length) return target
1474
+
1475
+ const source = sources.shift() // 取出第一个源对象
1476
+
1477
+ if (_isObject(target) && _isObject(source)) {
1478
+ for (const key in source) {
1479
+ if (_isObject(source[key])) {
1480
+ if (!target[key]) {
1481
+ // 如果目标对象没有该属性,创建一个空对象
1482
+ target[key] = {}
1483
+ }
1484
+ // 递归合并
1485
+ merge(target[key], source[key])
1486
+ } else {
1487
+ // 直接覆盖
1488
+ target[key] = source[key]
1489
+ }
1490
+ }
1491
+ }
1492
+
1493
+ // 继续合并剩余的源对象
1494
+ return merge(target, ...sources)
1495
+ }
1496
+
1497
+ function _isObject(obj) {
1498
+ return obj && typeof obj === 'object' && !Array.isArray(obj)
1499
+ }
1500
+
1501
+
1502
+
1503
+ ;// ./lib/helpers/objectHelper/index.js
1504
+
1505
+
1506
+
1507
+
1508
+ ;// ./lib/helpers/pReduce/pReduce.js
1509
+ async function pReduce(iterable, reducer, initialValue) {
1510
+ return new Promise((resolve, reject) => {
1511
+ const iterator = iterable[Symbol.iterator]()
1512
+ let index = 0
1513
+
1514
+ const next = async total => {
1515
+ const element = iterator.next()
1516
+
1517
+ if (element.done) {
1518
+ resolve(total)
1519
+ return
1520
+ }
1521
+
1522
+ try {
1523
+ const [resolvedTotal, resolvedValue] = await Promise.all([total, element.value])
1524
+ next(reducer(resolvedTotal, resolvedValue, index++))
1525
+ } catch (error) {
1526
+ reject(error)
1527
+ }
1528
+ }
1529
+
1530
+ next(initialValue)
1531
+ })
1532
+ }
1533
+
1534
+
1535
+
1536
+ ;// ./lib/models/repo/repo.js
1537
+
1538
+
1539
+ class Repo {
1540
+ constructor(options) {
1541
+ options = options || {}
1542
+ this.model = options.model
1543
+ this._sharedOptions = options._sharedOptions // { session: this.dbTransaction }
1544
+ this._queryOptions = options._queryOptions
1545
+ this._saveOptions = options._saveOptions
1546
+ this._Class = options._constructor && options._constructor._Class
1547
+ ? options._constructor._Class
1548
+ : null
1549
+ }
1550
+ static init(options = {}) {
1551
+ return init(this, options)
1552
+ }
1553
+ static get _classname() {
1554
+ return 'Repo'
1555
+ }
1556
+ static get _superclass() {
1557
+ return 'Repo'
1558
+ }
1559
+
1560
+ get _classname() {
1561
+ return 'Repo'
1562
+ }
1563
+
1564
+ get _superclass() {
1565
+ return 'Repo'
1566
+ }
1567
+
1568
+ get isValid() {
1569
+ return this.model
1570
+ && (typeof this.model.deleteOne === 'function')
1571
+ && (typeof this.model.findAll === 'function')
1572
+ && (typeof this.model.saveOne === 'function')
1573
+ }
1574
+
1575
+ get queryOptions() {
1576
+ return {
1577
+ ...this._sharedOptions,
1578
+ ...this._queryOptions,
1579
+ }
1580
+ }
1581
+
1582
+ get saveOptions() {
1583
+ return {
1584
+ ...this._sharedOptions,
1585
+ ...this._saveOptions,
1586
+ }
1587
+ }
1588
+
1589
+ init(options) {
1590
+ if (this._Class && typeof this._Class.init === 'function') {
1591
+ return this._Class.init(options)
1592
+ }
1593
+ return options
1594
+ }
1595
+
1596
+ async deleteOne({ id }) {
1597
+ try {
1598
+ const result = await this.model.deleteOne({ _id: id })
1599
+ return {
1600
+ ...result, // { message: 'ok', total }
1601
+ isNew: false,
1602
+ data: []
1603
+ }
1604
+ } catch (err) {
1605
+ throw err
1606
+ }
1607
+ }
1608
+
1609
+ // systemLog is optional
1610
+ findAll({ query, systemLog }) {
1611
+ const log = _makeLog({
1612
+ systemLog,
1613
+ label: 'REPO_READ',
1614
+ message: `fn ${this._classname}.prototype.findAll`,
1615
+ input: [{ query: { ...query }, systemLog: { ...systemLog } }]
1616
+ })
1617
+ return new Promise((resolve, reject) => {
1618
+ this.model.findAll(query, this.queryOptions, (err, data, total) => {
1619
+ if (err) {
1620
+ log({ level: 'warn', output: err.toString() })
1621
+ reject(err)
1622
+ } else {
1623
+ const result = {
1624
+ isNew: false,
1625
+ data,
1626
+ total: total || data.length
1627
+ }
1628
+ log({ level: 'info', output: { ...result } })
1629
+ resolve(result)
1630
+ }
1631
+ })
1632
+ })
1633
+ }
1634
+
1635
+ findOne({ query, systemLog }) {
1636
+ const log = _makeLog({
1637
+ systemLog,
1638
+ label: 'REPO_READ',
1639
+ message: `fn ${this._classname}.prototype.findOne`,
1640
+ input: [{ query: { ...query }, systemLog: { ...systemLog } }]
1641
+ })
1642
+ return new Promise((resolve, reject) => {
1643
+ this.model.findAll(query, this.queryOptions, (err, data) => {
1644
+ if (err) {
1645
+ reject(err)
1646
+ } else if (data.length === 1) {
1647
+ const result = {
1648
+ isNew: false,
1649
+ data,
1650
+ total: 1
1651
+ }
1652
+ log({ level: 'info', output: { ...result } })
1653
+ resolve(result)
1654
+ } else if (data.length === 0) {
1655
+ reject(new Error('record not found'))
1656
+ } else {
1657
+ reject(new Error('more than one is found'))
1658
+ }
1659
+ })
1660
+ })
1661
+ .catch((err) => {
1662
+ log({ level: 'warn', output: err.toString() })
1663
+ throw err
1664
+ })
1665
+ }
1666
+
1667
+ saveAll({ docs, systemLog }) {
1668
+ let isNew
1669
+ const log = _makeLog({
1670
+ systemLog,
1671
+ label: 'REPO_WRITE',
1672
+ message: `fn ${this._classname}.prototype.saveAll`,
1673
+ input: [{ docs: [...docs], systemLog: { ...systemLog } }]
1674
+ })
1675
+ const promise = typeof this.model.saveAll === 'function'
1676
+ ? this.model.saveAll({ docs })
1677
+ : Promise.all(docs.map(async (doc) => {
1678
+ if (doc) {
1679
+ const result = await this.saveOne({ doc })
1680
+ isNew = result.isNew
1681
+ const _data = result._data || result.data
1682
+ return _data[0]
1683
+ }
1684
+ return null
1685
+ }))
1686
+ return promise.then((savedData) => {
1687
+ if (savedData.length !== 1) isNew = null
1688
+ const result = {
1689
+ data: savedData,
1690
+ isNew,
1691
+ total: savedData.length
1692
+ }
1693
+ log({ level: 'info', output: { ...result } })
1694
+ return result
1695
+ }).catch((err) => {
1696
+ log({ level: 'warn', output: err.toString() })
1697
+ throw err
1698
+ })
1699
+ }
1700
+
1701
+ saveOne({ doc, systemLog }) {
1702
+ const log = _makeLog({
1703
+ systemLog,
1704
+ label: 'REPO_WRITE',
1705
+ message: `fn ${this._classname}.prototype.saveOne`,
1706
+ input: [{ doc: { ...doc }, systemLog: { ...systemLog } }]
1707
+ })
1708
+ return new Promise((resolve, reject) => {
1709
+ this.model.saveOne(doc, this.saveOptions, (err, result) => {
1710
+ if (err) {
1711
+ log({ level: 'warn', output: err.toString() })
1712
+ reject(err)
1713
+ } else {
1714
+ log({ level: 'info', output: { ...result } })
1715
+ resolve(result)
1716
+ }
1717
+ })
1718
+ })
1719
+ }
1720
+ }
1721
+
1722
+ function _makeLog({ systemLog, label, message: message1, input } = {}) {
1723
+ return ({ level, messgae: massage2, output } = {}) => {
1724
+ if (systemLog && systemLog.systemLogHelper) {
1725
+ systemLog.systemLogHelper.log({
1726
+ batchId: systemLog.batchId,
1727
+ label,
1728
+ level,
1729
+ message: massage2 || message1,
1730
+ data: {
1731
+ payload: {
1732
+ input,
1733
+ output
1734
+ }
1735
+ }
1736
+ })
1737
+ }
1738
+ }
1739
+ }
1740
+
1741
+
1742
+
1743
+ ;// ./lib/models/repo/index.js
1744
+
1745
+
1746
+
1747
+
1748
+ ;// ./lib/models/apiResponse/apiResponse.js
1749
+ class ApiResponse {
1750
+ constructor(options = {}) {
1751
+ options = options || {}
1752
+ this._data = options.data || options._data || []
1753
+ this.err = options.err
1754
+ this.isNew = options.isNew || false
1755
+ this.message = options.message
1756
+ this.total = options.total || 0
1757
+ this._instanceBuilder = options._instanceBuilder
1758
+ }
1759
+
1760
+ static init(options = {}) {
1761
+ if (options instanceof this) {
1762
+ return options
1763
+ }
1764
+ const instance = new this(options)
1765
+ return instance
1766
+ }
1767
+ static get _classname() {
1768
+ return 'ApiResponse'
1769
+ }
1770
+ static get _superclass() {
1771
+ return 'ApiResponse'
1772
+ }
1773
+
1774
+ // getters
1775
+ get data() {
1776
+ if (this._instanceBuilder && (typeof this._instanceBuilder === 'function')) {
1777
+ return this._data.map(this._instanceBuilder)
1778
+ }
1779
+ return this._data
1780
+ }
1781
+ }
1782
+
1783
+
1784
+
1785
+ ;// ./lib/models/apiResponse/makeApiResponse.js
1786
+
1787
+
1788
+ function makeApiResponse({ repo, result }) {
1789
+ return ApiResponse.init({
1790
+ ...result,
1791
+ _instanceBuilder: (i) => {
1792
+ return repo.init(i)
1793
+ }
1794
+ })
1795
+ }
1796
+
1797
+
1798
+
1799
+ ;// ./lib/models/service/service.js
1800
+
1801
+
1802
+
1803
+ class Service {
1804
+ constructor({ repo }) {
1805
+ this.repo = repo
1806
+ }
1807
+
1808
+ static get _classname() {
1809
+ return 'Service'
1810
+ }
1811
+ static get _superclass() {
1812
+ return 'Service'
1813
+ }
1814
+
1815
+ deleteOne({ id }) {
1816
+ return this.repo.deleteOne({ id })
1817
+ .catch(() => {
1818
+ throw new Error(`Not found for query: ${id}`)
1819
+ })
1820
+ }
1821
+
1822
+ async findAll({ query = {}, systemLog } = {}) {
1823
+ const result = await this.repo.findAll({ query, systemLog })
1824
+ return makeApiResponse({
1825
+ repo: this.repo,
1826
+ result
1827
+ })
1828
+ }
1829
+
1830
+ async findOne({ query = {}, systemLog } = {}) {
1831
+ const result = await this.repo.findOne({ query, systemLog })
1832
+ return makeApiResponse({
1833
+ repo: this.repo,
1834
+ result
1835
+ })
1836
+ }
1837
+
1838
+ init(options) {
1839
+ return this.repo.init(options)
1840
+ }
1841
+ initFromArray(arr = []) {
1842
+ if (Array.isArray(arr)) {
1843
+ return arr.map((a) => this.init(a))
1844
+ }
1845
+ return []
1846
+ }
1847
+ initOnlyValidFromArray(arr = []) {
1848
+ return this.initFromArray(arr).filter((i) => i)
1849
+ }
1850
+
1851
+ async saveAll({ docs = [], config = {}, systemLog } = {}) {
1852
+ const copies = docs.map((doc) => {
1853
+ return config.skipInit ? doc : this.init(doc)
1854
+ })
1855
+ const result = await this.repo.saveAll({ docs: copies, systemLog })
1856
+ return makeApiResponse({
1857
+ repo: this.repo,
1858
+ result
1859
+ })
1860
+ }
1861
+
1862
+ // set skipInit to true if we want to use POST for query
1863
+ async saveOne({ doc = {}, config = {}, systemLog } = {}) {
1864
+ const copy = config.skipInit ? doc : this.init(doc)
1865
+ if (copy) {
1866
+ const result = await this.repo.saveOne({ doc: copy, systemLog })
1867
+ return makeApiResponse({
1868
+ repo: this.repo,
1869
+ result
1870
+ })
1871
+ }
1872
+ return {
1873
+ isNew: null,
1874
+ data: [],
1875
+ err: new Error('doc is not a valid instance')
1876
+ }
1877
+ }
1878
+ }
1879
+
1880
+ function makeService({ repo }) {
1881
+ if (repo === undefined) {
1882
+ throw new Error('repo is required.')
1883
+ }
1884
+ if (repo._superclass !== Repo._superclass) {
1885
+ throw new Error('repo is not an instance of Repo.')
1886
+ }
1887
+ return new Service({ repo })
1888
+ }
1889
+
1890
+
1891
+
1892
+ ;// ./lib/models/service/index.js
1893
+
1894
+
1895
+
1896
+
1897
+ ;// ./lib/helpers/generalPost/generalPost.js
1898
+
1899
+
1900
+
1901
+
1902
+
1903
+ async function generalPost({ body = {}, GeneralModel, UniqueKeyGenerator, resourceInfo }) {
1904
+ const { resources, data, globalShared = {}, shared = {}, relationship = {} } = body
1905
+ const _resourceInfo = resourceInfo || body.resourceInfo
1906
+ _attachShared(data, globalShared, shared)
1907
+ const obj = await pReduce(resources, async (acc, resource) => {
1908
+ const service = _makeService(resource, _resourceInfo, UniqueKeyGenerator, GeneralModel)
1909
+ _createRelationship(data, relationship[resource], acc)
1910
+ const _data = data[resource]
1911
+ const result = await service.saveAll({ docs: [].concat(_data) })
1912
+ acc[resource] = Array.isArray(_data) ? result._data : result._data[0]
1913
+ return acc
1914
+ }, {})
1915
+ return obj
1916
+ }
1917
+
1918
+ function _attachShared(data, globalShared = {}, shared = {}) {
1919
+ Object.keys(shared).forEach((key) => {
1920
+ const _data = data[key]
1921
+ if (Array.isArray(_data)) {
1922
+ data[key] = _data.map((_dataItem) => {
1923
+ return objectHelper.merge({}, _dataItem, globalShared, shared[key] || {})
1924
+ })
1925
+ } else {
1926
+ data[key] = objectHelper.merge({}, _data, globalShared, shared[key] || {})
1927
+ }
1928
+ })
1929
+ }
1930
+
1931
+ function _createRelationship(data, relationship = {}, object) {
1932
+ Object.keys(relationship).forEach((key) => {
1933
+ const path = relationship[key]
1934
+ const val = objectHelper.get(object, path)
1935
+ objectHelper.set(data, key, val)
1936
+ })
1937
+ }
1938
+
1939
+ function _makeService(resource, resourceInfo, UniqueKeyGenerator, GeneralModel) {
1940
+ const { collectionName, fields } = resourceInfo[resource]
1941
+ const uniqueKeyGenerator = UniqueKeyGenerator.makeGenerator(fields)
1942
+ const model = new GeneralModel({ collectionName, uniqueKeyGenerator })
1943
+ return makeService({
1944
+ repo: new Repo({ model })
1945
+ })
1946
+ }
1947
+
1948
+
1949
+
1950
+ ;// ./lib/helpers/generalPost/index.js
1951
+
1952
+
1953
+
1954
+
1955
+ ;// ./lib/helpers/init/init.js
1956
+ function init(_class, options) {
1957
+ if (options instanceof _class) {
1958
+ return options
1959
+ }
1960
+ try {
1961
+ const instance = new _class(options)
1962
+ return instance.isValid !== false ? instance : null
1963
+ } catch (e) {
1964
+ console.log(`init failed for class: ${_class._classname || 'no _classname'}`, e)
1965
+ return null
1966
+ }
1967
+ }
1968
+
1969
+ ;// ./lib/helpers/init/index.js
1970
+
1971
+
1972
+ ;// ./lib/helpers/initFromArray/initFromArray.js
1973
+
1974
+
1975
+ function initFromArray(_class, arr) {
1976
+ if (Array.isArray(arr)) {
1977
+ return arr.map((a) => init(_class, a))
1978
+ }
1979
+ return []
1980
+ }
1981
+
1982
+ ;// ./lib/helpers/initFromArray/index.js
1983
+
1984
+
1985
+ ;// ./lib/helpers/initOnlyValidFromArray/initOnlyValidFromArray.js
1986
+
1987
+
1988
+ function initOnlyValidFromArray(_class, arr) {
1989
+ return initFromArray(_class, arr).filter((i) => i)
1990
+ }
1991
+
1992
+ ;// ./lib/helpers/initOnlyValidFromArray/index.js
1993
+
1994
+
1995
+ ;// ./lib/helpers/padZeros/padZeros.js
1996
+ function padZeros(num, minLength = 6) {
1997
+ num = num.toString()
1998
+ if (num.length < minLength) {
1999
+ return padZeros('0' + num, minLength)
2000
+ }
2001
+ return num
2002
+ }
2003
+
2004
+
2005
+
2006
+ ;// ./lib/helpers/padZeros/index.js
2007
+
2008
+
2009
+
2010
+
2011
+ ;// ./lib/helpers/pReduce/index.js
2012
+
2013
+
2014
+
2015
+
2016
+ ;// ./lib/helpers/stringFormatter/stringFormatter.js
2017
+ function stringFormatter(str, delimiter = '_') {
2018
+ if (str === null || typeof str === 'undefined' || typeof str.toString === 'undefined') {
2019
+ return null
2020
+ }
2021
+ return str.toString()
2022
+ .trim()
2023
+ .toUpperCase()
2024
+ .replace('-', delimiter)
2025
+ .replace(' ', delimiter)
2026
+ }
2027
+
2028
+
2029
+
2030
+ ;// ./lib/helpers/stringFormatter/index.js
2031
+
2032
+
2033
+
2034
+
2035
+ ;// ./lib/helpers/stringHelper/stringHelper.js
2036
+ function baseXEncode(num, base = 34) {
2037
+ const charset = getBaseCharset(base)
2038
+ return encode(num, charset)
2039
+ }
2040
+
2041
+ function encode(int, charset) {
2042
+ const { byCode } = charset
2043
+ if (int === 0) {
2044
+ return byCode[0]
2045
+ }
2046
+
2047
+ let res = ''
2048
+ const max = charset.length
2049
+ while (int > 0) {
2050
+ res = byCode[int % max] + res
2051
+ int = Math.floor(int / max)
2052
+ }
2053
+ return res
2054
+ }
2055
+
2056
+ function getBaseCharset(base) {
2057
+ let charset = '9876543210ABCDEFGHJKLMNPQRSTUVWXYZ'
2058
+ if (base === 58) {
2059
+ charset = '9876543210ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz'
2060
+ }
2061
+ return indexCharset(charset)
2062
+ }
2063
+
2064
+ function indexCharset(str) {
2065
+ const byCode = {}
2066
+ const byChar = {}
2067
+ const { length } = str
2068
+ let char
2069
+ for (let i = 0; i < length; i++) {
2070
+ char = str[i]
2071
+ byCode[i] = char
2072
+ byChar[char] = i;
2073
+ }
2074
+ return { byCode, byChar, length }
2075
+ }
2076
+
2077
+ function isSame(str1, str2) {
2078
+ if (typeof str1 !== 'string' || typeof str2 !== 'string') {
2079
+ return false
2080
+ }
2081
+ return str1.trim().toUpperCase() === str2.trim().toUpperCase()
2082
+ }
2083
+
2084
+ function randomString({ len = 16, pattern = 'a1' } = {}) {
2085
+ const A = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
2086
+ const a = 'abcdefghijklmnopqrstuvwxyz'
2087
+ const num = '1234567890'
2088
+ const mark = '~!@#$%^&*_+-='
2089
+ let str = ''
2090
+ if (pattern.includes('A')) {
2091
+ str += A
2092
+ }
2093
+ if (pattern.includes('a')) {
2094
+ str += a
2095
+ }
2096
+ if (pattern.includes('1')) {
2097
+ str += num
2098
+ }
2099
+ if (pattern.includes('#')) {
2100
+ str += mark
2101
+ }
2102
+ const chars = [...str]
2103
+ return [...Array(len)].map(i => {
2104
+ return chars[(Math.random() * chars.length) | 0]
2105
+ }).join``
2106
+ }
2107
+
2108
+ function reverse(str) {
2109
+ const _str = (typeof str !== 'string') ? str.toString() : str
2110
+ const splitString = _str.split('')
2111
+ const reverseArray = splitString.reverse()
2112
+ return reverseArray.join('')
2113
+ }
2114
+
2115
+ function setCode(base = 34) {
2116
+ const now = (new Date()).valueOf()
2117
+ const random = randomString({
2118
+ len: 8,
2119
+ pattern: '1'
2120
+ })
2121
+ const str = reverse(`${now}${random}`)
2122
+ // const str = `${now}${random}`
2123
+ return baseXEncode(str, base)
2124
+ }
2125
+
2126
+ function toCamelCase(str) {
2127
+ if (!str) return ''
2128
+ return str
2129
+ .trim()
2130
+ .split(/\s+/)
2131
+ .map((word, index) => {
2132
+ if (!word) return ''
2133
+ if (index === 0) {
2134
+ return word.toLowerCase()
2135
+ }
2136
+ return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
2137
+ })
2138
+ .join('')
2139
+ }
2140
+
2141
+ const stringHelper = {
2142
+ isSame,
2143
+ setCode,
2144
+ toCamelCase,
2145
+ }
2146
+
2147
+
2148
+
2149
+ ;// ./lib/helpers/stringHelper/index.js
2150
+
2151
+
2152
+
2153
+
2154
+ ;// ./lib/helpers/trackingPlugin/trackingPlugin.js
2155
+ function trackingPlugin(schema, options) {
2156
+ // Add meta fields
2157
+ schema.add({
2158
+ meta: {
2159
+ active: { type: Boolean, default: true },
2160
+ created: { type: Number },
2161
+ creator: { type: String },
2162
+ deleted: { type: Boolean, default: false },
2163
+ modified: { type: Number },
2164
+ owner: { type: String },
2165
+ }
2166
+ })
2167
+
2168
+ // Auto-update hook
2169
+ schema.pre('save', function(next) {
2170
+ this.meta.modified = Date.now()
2171
+ next()
2172
+ })
2173
+
2174
+ // Optional: Add helper methods
2175
+ // schema.methods.touch = function(userId) {
2176
+ // this.meta.updatedAt = new Date()
2177
+ // this.meta.updatedBy = userId
2178
+ // }
2179
+ }
2180
+
2181
+ ;// ./lib/helpers/trackingPlugin/index.js
2182
+
2183
+
2184
+ ;// ./lib/helpers/index.js
2185
+
2186
+
2187
+
2188
+
2189
+
2190
+
2191
+
2192
+
2193
+
2194
+
2195
+
2196
+
2197
+
2198
+
2199
+
2200
+
2201
+
2202
+ ;// ./lib/models/apiResponse/index.js
2203
+
2204
+
2205
+
2206
+
2207
+
2208
+ ;// ./lib/models/keyValueObject/keyValueObject.js
2209
+ class KeyValueObject {
2210
+ constructor(options = {}) {
2211
+ options = options || {}
2212
+ this.key = options.key || null
2213
+ this.value = (typeof options.value !== 'undefined') ? options.value : ''
2214
+ }
2215
+
2216
+ // Class methods
2217
+ static init(options = {}) {
2218
+ if (options instanceof this) {
2219
+ return options
2220
+ }
2221
+ const instance = new this(options)
2222
+ return instance.isValid ? instance : null
2223
+ }
2224
+ static initFromArray(arr = []) {
2225
+ if (Array.isArray(arr)) {
2226
+ return arr.map((a) => this.init(a))
2227
+ }
2228
+ return []
2229
+ }
2230
+ static initOnlyValidFromArray(arr = []) {
2231
+ return this.initFromArray(arr).filter((i) => i)
2232
+ }
2233
+ static get _classname() {
2234
+ return 'KeyValueObject'
2235
+ }
2236
+ static get _superclass() {
2237
+ return 'KeyValueObject'
2238
+ }
2239
+
2240
+ static addItem(arr, key, value) {
2241
+ arr.push(this.init({ key, value }))
2242
+ }
2243
+ static addRecord(arr = [], key, value) {
2244
+ if (!this.hasKeyValue(arr, key, value)) {
2245
+ arr.push(this.init({ key, value }))
2246
+ }
2247
+ return arr
2248
+ }
2249
+ static appendRecord(arr = [], key, value) {
2250
+ return arr.map((item) => {
2251
+ if (this.sameKey(item, key)) {
2252
+ item.value = [...item.value, ...value]
2253
+ }
2254
+ return item
2255
+ })
2256
+ }
2257
+ static appendValueArray(arr = [], key, value) {
2258
+ return arr.map((item) => {
2259
+ if (this.sameKey(item, key)) {
2260
+ item.value = [...item.value, ...value]
2261
+ }
2262
+ return item
2263
+ })
2264
+ }
2265
+ static foundByKey(arr = [], key) {
2266
+ const found = arr.find((m) => {
2267
+ return this.sameKey(m, key)
2268
+ })
2269
+ return found || null
2270
+ }
2271
+ static foundValueByKey(arr = [], key) {
2272
+ const found = this.foundByKey(arr, key)
2273
+ return found ? found.value : null
2274
+ }
2275
+ static fromObject(options = {}) {
2276
+ return Object.keys(options).reduce((acc, key) => {
2277
+ acc.push(this.init({ key, value: options[key] }))
2278
+ return acc
2279
+ }, [])
2280
+ }
2281
+ static getValueByKey(arr = [], key) {
2282
+ return this.foundValueByKey(arr, key)
2283
+ }
2284
+ static getValueByKeyFromArray(arr = [], key) {
2285
+ if (arr.length === 0) {
2286
+ return null
2287
+ }
2288
+ const firstArr = arr.shift()
2289
+ const found = firstArr.find((i) => {
2290
+ return this.sameKey(i, key)
2291
+ })
2292
+ if (found && found.value) {
2293
+ return found.value
2294
+ }
2295
+ return this.getValueByKeyFromArray(arr, key)
2296
+ }
2297
+ static getValuesByKey(arr = [], key) {
2298
+ return arr.reduce((acc, item) => {
2299
+ if (this.sameKey(item, key)) {
2300
+ acc.push(item.value)
2301
+ }
2302
+ return acc
2303
+ }, [])
2304
+ }
2305
+ static hasKeyValue(arr = [], key, value) {
2306
+ if (typeof value === 'undefined') {
2307
+ return arr.filter((item) => this.sameKey(item, key)).length > 0
2308
+ }
2309
+ return arr.filter((item) => (this.sameKey(item, key) && _isSame(item.value, value))).length > 0
2310
+ }
2311
+ static insertOrUpdateRecord(arr = [], key, value) {
2312
+ let copy = [...arr]
2313
+ if (!this.hasKeyValue(arr, key)) {
2314
+ copy.push(this.init({ key, value }))
2315
+ } else {
2316
+ copy = this.updateRecord(arr, key, value)
2317
+ }
2318
+ return copy
2319
+ }
2320
+ static keys(arr = []) {
2321
+ if (Array.isArray(arr)) {
2322
+ return arr.reduce((acc, item) => {
2323
+ acc.push(item.key)
2324
+ return acc
2325
+ }, [])
2326
+ }
2327
+ return []
2328
+ }
2329
+ static merge(toArr, fromArr) {
2330
+ (fromArr || []).map((from) => {
2331
+ const found = toArr.find((to) => {
2332
+ return to.key === from.key
2333
+ })
2334
+ if (found) {
2335
+ found.value = (found.value || []).concat(from.value)
2336
+ } else {
2337
+ toArr.push(from)
2338
+ }
2339
+ })
2340
+ return toArr
2341
+ }
2342
+ static removeByKey(arr, key) {
2343
+ return arr.reduce((acc, item) => {
2344
+ if (!this.sameKey(item, key)) {
2345
+ acc.push(item)
2346
+ }
2347
+ return acc
2348
+ }, [])
2349
+ }
2350
+ static sameKey(item, key) {
2351
+ return _isSame(item.key, key)
2352
+ }
2353
+ static toObject(arr = []) {
2354
+ if (Array.isArray(arr)) {
2355
+ return arr.reduce((acc, item) => {
2356
+ acc[item.key] = item.value
2357
+ return acc
2358
+ }, {})
2359
+ }
2360
+ return {}
2361
+ }
2362
+ static toString(arr = [], delimiter = '; ') {
2363
+ if (Array.isArray(arr)) {
2364
+ return arr.reduce((acc, item) => {
2365
+ acc.push(`${item.key}: ${item.value}`)
2366
+ return acc
2367
+ }, []).join(delimiter)
2368
+ }
2369
+ return ''
2370
+ }
2371
+ static updateRecord(arr = [], key, value) {
2372
+ return arr.map((item) => {
2373
+ if (this.sameKey(item, key)) {
2374
+ return {
2375
+ ...item,
2376
+ value
2377
+ }
2378
+ }
2379
+ return item
2380
+ })
2381
+ }
2382
+ static updateOrInsertRecord(arr = [], key, value) {
2383
+ return this.insertOrUpdateRecord(arr, key, value)
2384
+ }
2385
+ static updateRecordsFromArray(arr = [], updateArr = []) {
2386
+ if (Array.isArray(arr) && Array.isArray(updateArr)) {
2387
+ const obj1 = this.toObject(arr)
2388
+ const obj2 = this.toObject(updateArr)
2389
+ return this.fromObject({
2390
+ ...obj1,
2391
+ ...obj2
2392
+ })
2393
+ }
2394
+ return []
2395
+ }
2396
+ static values(arr = []) {
2397
+ if (Array.isArray(arr)) {
2398
+ return arr.reduce((acc, item) => {
2399
+ acc.push(item.value)
2400
+ return acc
2401
+ }, [])
2402
+ }
2403
+ return []
2404
+ }
2405
+
2406
+ // getters
2407
+ get isValid() {
2408
+ return !!this.key
2409
+ }
2410
+
2411
+ get toObject() {
2412
+ const obj = {}
2413
+ if (this.isValid) {
2414
+ obj[this.key] = this.value
2415
+ }
2416
+ return obj
2417
+ }
2418
+ }
2419
+
2420
+ function _isSame(key1, key2) {
2421
+ return key1 === key2
2422
+ }
2423
+
2424
+
2425
+
2426
+ ;// ./lib/models/keyValueObject/index.js
2427
+
2428
+
2429
+
2430
+
2431
+ ;// ./lib/models/metadata/metadata.js
2432
+
2433
+
2434
+
2435
+ const DELIMITER = '_'
2436
+
2437
+ class Metadata extends KeyValueObject {
2438
+ static init(options = {}) {
2439
+ if (options instanceof this) {
2440
+ return options
2441
+ }
2442
+ const instance = new this({
2443
+ ...options,
2444
+ key: stringFormatter(options.key, DELIMITER),
2445
+ })
2446
+ return instance.isValid ? instance : null
2447
+ }
2448
+ static get _classname() {
2449
+ return 'Metadata'
2450
+ }
2451
+
2452
+ static merge(toArr, fromArr) {
2453
+ (fromArr || []).map((from) => {
2454
+ const found = toArr.find((to) => {
2455
+ return metadata_isSame(to.key, from.key)
2456
+ })
2457
+ if (found) {
2458
+ found.value = (found.value || []).concat(from.value)
2459
+ } else {
2460
+ toArr.push(from)
2461
+ }
2462
+ })
2463
+ return toArr
2464
+ }
2465
+ static sameKey(item, key) {
2466
+ return metadata_isSame(item.key, key)
2467
+ }
2468
+ }
2469
+
2470
+ function metadata_isSame(key1, key2) {
2471
+ return stringFormatter(key1, DELIMITER) === stringFormatter(key2, DELIMITER)
2472
+ }
2473
+
2474
+
2475
+
2476
+ ;// ./lib/models/metadata/index.js
2477
+
2478
+
2479
+
2480
+
2481
+ ;// ./lib/models/qMeta/qMeta.js
2482
+
2483
+
2484
+ const updateAllowedProps = [
2485
+ 'attributes',
2486
+ 'ref'
2487
+ ]
2488
+
2489
+ class QMeta {
2490
+ constructor(options = {}) {
2491
+ options = options || {}
2492
+ this.attributes = KeyValueObject.initOnlyValidFromArray(options.attributes)
2493
+ this.ref = options.ref || {}
2494
+ }
2495
+
2496
+ static get _classname() {
2497
+ return 'QMeta'
2498
+ }
2499
+ static get _superclass() {
2500
+ return 'QMeta'
2501
+ }
2502
+
2503
+ // Class methods
2504
+ static init(options = {}) {
2505
+ if (options instanceof QMeta) {
2506
+ return options
2507
+ }
2508
+ return new QMeta(options)
2509
+ }
2510
+
2511
+ // instance methods
2512
+ addAttribute(obj) {
2513
+ const kvObject = KeyValueObject.init(obj)
2514
+ if (!kvObject) {
2515
+ throw new Error('invalid meta attribute')
2516
+ }
2517
+ this.attributes.push(kvObject)
2518
+ return this
2519
+ }
2520
+
2521
+ update(obj) {
2522
+ Object.keys(obj).forEach((key) => {
2523
+ if (updateAllowedProps.includes(key)) {
2524
+ if (key === 'attributes') {
2525
+ this[key] = KeyValueObject.initOnlyValidFromArray(obj[key])
2526
+ } else {
2527
+ this[key] = obj[key]
2528
+ }
2529
+ }
2530
+ })
2531
+ return this
2532
+ }
2533
+ }
2534
+
2535
+
2536
+
2537
+ ;// ./lib/models/qMeta/index.js
2538
+
2539
+
2540
+
2541
+
2542
+ ;// ./lib/models/trackedEntity/trackedEntity.js
2543
+
2544
+
2545
+ class TrackedEntity {
2546
+ constructor(options = {}) {
2547
+ options = options || {}
2548
+ const timestamp = Date.now()
2549
+ const _tracking = {
2550
+ active: options.active ?? true,
2551
+ created: options.created ?? timestamp,
2552
+ creator: options.creator ?? '',
2553
+ deleted: options.deleted ?? false,
2554
+ modified: options.modified ?? timestamp,
2555
+ owner: options.owner ?? '',
2556
+ }
2557
+
2558
+ this.meta = { ..._tracking, ...options.meta }
2559
+
2560
+ // if (trackFlat) {
2561
+ // Object.assign(this, _tracking)
2562
+ // } else {
2563
+ // this.meta = { ..._tracking, ...options.meta }
2564
+ // }
2565
+ }
2566
+
2567
+ // Class methods
2568
+ static get _classname() {
2569
+ return 'TrackedEntity'
2570
+ }
2571
+ static get _superclass() {
2572
+ return 'TrackedEntity'
2573
+ }
2574
+
2575
+ static init(options = {}) {
2576
+ return init(this, options)
2577
+ }
2578
+ static initFromArray(arr = []) {
2579
+ return initFromArray(this, arr)
2580
+ }
2581
+ static initOnlyValidFromArray(arr = []) {
2582
+ return initOnlyValidFromArray(this, arr)
2583
+ }
2584
+ // static nest(entity) {
2585
+ // const { active, created, creator, deleted, modified, owner, ...rest } = entity
2586
+ // return { ...rest, meta: { active, created, creator, deleted, modified, owner } }
2587
+ // }
2588
+
2589
+ // getters
2590
+ get isValid() {
2591
+ return !!this
2592
+ }
2593
+ get active() {
2594
+ return this.meta?.active ?? this.active
2595
+ }
2596
+ get created() {
2597
+ return this.meta?.created ?? this.created
2598
+ }
2599
+ get creator() {
2600
+ return this.meta?.creator ?? this.creator
2601
+ }
2602
+ get deleted() {
2603
+ return this.meta?.deleted ?? this.deleted
2604
+ }
2605
+ get modified() {
2606
+ return this.meta?.modified ?? this.modified
2607
+ }
2608
+ get owner() {
2609
+ return this.meta?.owner ?? this.owner
2610
+ }
2611
+ delete() {
2612
+ return this.setDeleted()
2613
+ }
2614
+ setActive() {
2615
+ if (this.meta) {
2616
+ this.meta.active = true
2617
+ } else {
2618
+ this.active = true
2619
+ }
2620
+ return this
2621
+ }
2622
+ setDeleted() {
2623
+ if (this.meta) {
2624
+ this.meta.deleted = true
2625
+ } else {
2626
+ this.deleted = true
2627
+ }
2628
+ return this
2629
+ }
2630
+ setModified() {
2631
+ const timestamp = Date.now()
2632
+ if (this.meta) {
2633
+ this.meta.modified = timestamp
2634
+ } else {
2635
+ this.modified = timestamp
2636
+ }
2637
+ return this
2638
+ }
2639
+ setOwner(owner) {
2640
+ if (!owner) {
2641
+ return this
2642
+ }
2643
+ if (this.meta) {
2644
+ this.meta.owner = owner
2645
+ } else {
2646
+ this.owner = owner
2647
+ }
2648
+ return this
2649
+ }
2650
+ unsetActive() {
2651
+ if (this.meta) {
2652
+ this.meta.active = false
2653
+ } else {
2654
+ this.active = false
2655
+ }
2656
+ return this
2657
+ }
2658
+ unsetDeleted() {
2659
+ if (this.meta) {
2660
+ this.meta.deleted = false
2661
+ } else {
2662
+ this.deleted = false
2663
+ }
2664
+ return this
2665
+ }
2666
+
2667
+ update(update) {
2668
+ if (update.meta) {
2669
+ this.meta = { ...this.meta, ...update.meta }
2670
+ }
2671
+ return this.setModified()
2672
+ }
2673
+ }
2674
+
2675
+ ;// ./lib/models/trackedEntity/index.js
2676
+
2677
+ // Explicit named export (optional)
2678
+
2679
+ ;// ./lib/models/tenantAwareEntity/tenantAwareEntity.js
2680
+
2681
+
2682
+
2683
+
2684
+ class TenantAwareEntity extends TrackedEntity {
2685
+ constructor(options = {}) {
2686
+ options = options || {}
2687
+
2688
+ /**
2689
+ * instead of throw error, we choose to implement the isValid checking
2690
+ */
2691
+ // if (!options.tenantCode) {
2692
+ // throw new Error('tenantCode required')
2693
+ // }
2694
+
2695
+ super(options)
2696
+
2697
+ this._tenant = options._tenant
2698
+
2699
+ this.metadata = Metadata.initOnlyValidFromArray(options.metadata)
2700
+ this.remarks = KeyValueObject.initOnlyValidFromArray(options.remarks)
2701
+ this.tenantCode = options.tenantCode // Required for multi-tenancy
2702
+ }
2703
+
2704
+ // Class methods
2705
+ static get _classname() {
2706
+ return 'TenantAwareEntity'
2707
+ }
2708
+ static get _superclass() {
2709
+ return 'TenantAwareEntity'
2710
+ }
2711
+
2712
+ // getters
2713
+ get isValid() {
2714
+ return super.isValid && !!this.tenantCode // Required for multi-tenancy
2715
+ }
2716
+
2717
+ // instance methods
2718
+ getMetadata() {
2719
+ return this.metadata
2720
+ }
2721
+ getMetadataByKey(key) {
2722
+ return Metadata.foundByKey(this.metadata, key)
2723
+ }
2724
+ getMetadataValueByKey(key) {
2725
+ const found = this.getMetadataByKey(key)
2726
+ return found ? found.value : null
2727
+ }
2728
+ getRemarks() {
2729
+ return this.remarks
2730
+ }
2731
+ getRemarkByKey(key) {
2732
+ return KeyValueObject.foundByKey(this.remarks, key)
2733
+ }
2734
+ getRemarksValueByKey(key) {
2735
+ const found = this.getRemarkByKey(key)
2736
+ return found ? found.value : null
2737
+ }
2738
+ getTenantCode() {
2739
+ return this.tenantCode
2740
+ }
2741
+
2742
+ update(update) {
2743
+ if (update.metadata && Array.isArray(update.metadata)) {
2744
+ this.metadata = Metadata.initOnlyValidFromArray(update.metadata)
2745
+ }
2746
+ if (update.remarks && Array.isArray(update.remarks)) {
2747
+ this.remarks = KeyValueObject.initOnlyValidFromArray(update.remarks)
2748
+ }
2749
+ return super.update(update)
2750
+ }
2751
+ }
2752
+
2753
+ ;// ./lib/models/tenantAwareEntity/index.js
2754
+
2755
+
2756
+
2757
+ ;// ./lib/models/uniqueKeyGenerator/uniqueKeyGenerator.js
2758
+
2759
+
2760
+ class UniqueKeyGenerator {
2761
+ static get _classname() {
2762
+ return 'UniqueKeyGenerator'
2763
+ }
2764
+ static get _superclass() {
2765
+ return 'UniqueKeyGenerator'
2766
+ }
2767
+ static makeFormatter({ fieldName, format, options }) {
2768
+ switch (format) {
2769
+ case 'set_code':
2770
+ return _makeSetCode(fieldName, options)
2771
+ default:
2772
+ return _makeSetCode(fieldName, options)
2773
+ }
2774
+ }
2775
+ static makeGenerator(arr) {
2776
+ const fns = arr.map((item) => this.makeFormatter(item))
2777
+ return async (obj) => {
2778
+ const output = await pReduce(fns, async (acc, fn) => {
2779
+ const _obj = await fn(obj)
2780
+ return Object.assign(acc, _obj)
2781
+ }, obj)
2782
+ return output
2783
+ }
2784
+ }
2785
+ }
2786
+
2787
+ function _makeSetCode(fieldName, options) {
2788
+ return async (obj = {}) => {
2789
+ if (obj[fieldName]) {
2790
+ return {}
2791
+ }
2792
+ return {
2793
+ [fieldName]: stringHelper.setCode()
2794
+ }
2795
+ }
2796
+ }
2797
+
2798
+
2799
+
2800
+ ;// ./lib/models/uniqueKeyGenerator/index.js
2801
+
2802
+
2803
+
2804
+
2805
+ ;// ./lib/models/index.js
2806
+
2807
+
2808
+
2809
+
2810
+
2811
+
2812
+
2813
+
2814
+
2815
+
2816
+
2817
+ ;// ./lib/index.js
2818
+
2819
+
2820
+
2821
+ ;// ./index.js
2822
+
2823
+
2824
+ export { ApiResponse, KeyValueObject, Metadata, QMeta, Repo, Service, TemplateCompiler, TenantAwareEntity, TrackedEntity, UniqueKeyGenerator, authorize, concatStringByArray, convertString, formatDate, generalPost, getValidation, getValueByKeys_getValueByKeys as getValueByKeys, init, initFromArray, initOnlyValidFromArray, makeApiResponse, makeService, objectHelper, pReduce, padZeros, stringFormatter, stringHelper, trackingPlugin };