@questwork/q-utilities 0.1.9 → 0.1.11

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.
Files changed (3) hide show
  1. package/dist/index.min.cjs +1656 -1071
  2. package/dist/index.min.js +1659 -1073
  3. package/package.json +8 -7
@@ -55,8 +55,9 @@ __webpack_require__.d(__webpack_exports__, {
55
55
  QMeta: () => (/* reexport */ QMeta),
56
56
  Repo: () => (/* reexport */ Repo),
57
57
  Service: () => (/* reexport */ Service),
58
- Template: () => (/* reexport */ Template),
58
+ TemplateCompiler: () => (/* reexport */ TemplateCompiler),
59
59
  UniqueKeyGenerator: () => (/* reexport */ UniqueKeyGenerator),
60
+ concatStringByArray: () => (/* reexport */ concatStringByArray),
60
61
  convertString: () => (/* reexport */ convertString),
61
62
  formatDate: () => (/* reexport */ formatDate),
62
63
  generalPost: () => (/* reexport */ generalPost),
@@ -71,86 +72,12 @@ __webpack_require__.d(__webpack_exports__, {
71
72
  stringHelper: () => (/* reexport */ stringHelper)
72
73
  });
73
74
 
74
- ;// ./lib/helpers/convertString/convertString.js
75
- function convertString(string, patternMatch = /\$\{(.+?)\}/g, value, getValueByKeys) {
76
- if (!string || typeof getValueByKeys !== 'function') {
77
- return ''
78
- }
79
- const reg = new RegExp(patternMatch, 'g')
80
- return string.replace(reg, (match, key) => {
81
- const result = getValueByKeys({ keys: key.split('.'), obj: value })
82
- if (result === null || result === undefined) {
83
- return ''
84
- }
85
- return typeof result === 'object' ? JSON.stringify(result) : result
86
- })
87
- }
88
-
89
- /* harmony default export */ const convertString_convertString = ({
90
- convertString
91
- });
92
-
93
-
94
- ;// ./lib/helpers/convertString/index.js
95
-
96
-
97
- ;// ./lib/helpers/formatDate/formatDate.js
98
-
99
- function formatDate(date, format) {
100
- const _date = date && date instanceof Date ? date : new Date(date)
101
- const dayMapChi = ['日','一','二','三','四','五','六']
102
- const dayMapEng = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday']
103
- const dayMapEngShort = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
104
- const _format = format || 'YYYY/MM/DD hh:mm'
105
- const e = _date.getDay()
106
- const ee = dayMapEngShort[e]
107
- const eee = dayMapChi[e]
108
- const eeee = dayMapEng[e]
109
- const y = _date.getFullYear()
110
- const m = _date.getMonth() + 1
111
- const d = _date.getDate()
112
- const h = _date.getHours()
113
- const mm = _date.getMinutes()
114
- const s = _date.getSeconds()
115
-
116
- return _format.replace('YYYY', y)
117
- .replace('MM', padding(m))
118
- .replace('MM', padding(m))
119
- .replace('DD', padding(d))
120
- .replace('hh', padding(h))
121
- .replace('mm', padding(mm))
122
- .replace('ss', padding(s))
123
- .replace('M', m)
124
- .replace('D', d)
125
- .replace('h', h)
126
- .replace('m', mm)
127
- .replace('s', s)
128
- .replace('EEEE', padding(eeee))
129
- .replace('EEE', padding(eee))
130
- .replace('EE', padding(ee))
131
- .replace('E', padding(e))
132
- }
133
-
134
- function padding(m) {
135
- return m < 10 ? `0${m}` : m
136
- }
137
-
138
-
139
- /* harmony default export */ const formatDate_formatDate = ({
140
- formatDate
141
- });
142
-
143
-
144
-
145
- ;// ./lib/helpers/formatDate/index.js
146
-
147
-
148
75
  ;// ./lib/helpers/getValidation/getValidation.js
149
76
  function getValidation(rule, data, getDataByKey, KeyValueObject) {
150
77
  if (!rule) {
151
78
  return true
152
79
  }
153
- if (typeof getDataByKey !== 'function' || typeof KeyValueObject !== 'function') {
80
+ if (typeof getDataByKey !== 'function' || (KeyValueObject && typeof KeyValueObject !== 'function')) {
154
81
  return false
155
82
  }
156
83
  const { key = '', value, keyValuePath = '' } = rule
@@ -232,6 +159,23 @@ function getValidation(rule, data, getDataByKey, KeyValueObject) {
232
159
  }
233
160
  return false
234
161
  }
162
+ case '$intervalTimeGt': {
163
+ const now = new Date().getTime()
164
+ const timestamp = new Date(rowValue).getTime()
165
+ return (now - timestamp) > value['$intervalTimeGt']
166
+ }
167
+ case '$intervalTimeLt': {
168
+ const now = new Date().getTime()
169
+ const timestamp = new Date(rowValue).getTime()
170
+ return (now - timestamp) < value['$intervalTimeLt']
171
+ }
172
+ case '$isToday': {
173
+ const currentDate = new Date()
174
+ const start = currentDate.setHours(0,0,0,0)
175
+ const end = currentDate.setHours(23,59,59,59)
176
+ const dateValue = new Date(rowValue).getTime()
177
+ return (start <= dateValue && end >= dateValue) === value['$isToday']
178
+ }
235
179
  case '$notInValue': {
236
180
  const result = getDataByKey(value['$notInValue'], data)
237
181
  const _value = Array.isArray(result) ? result : []
@@ -263,12 +207,66 @@ function getValidation(rule, data, getDataByKey, KeyValueObject) {
263
207
  ;// ./lib/helpers/getValidation/index.js
264
208
 
265
209
 
210
+ ;// ./lib/helpers/formatDate/formatDate.js
211
+
212
+ function formatDate(date, format) {
213
+ const _date = date && date instanceof Date ? date : new Date(date)
214
+ const dayMapChi = ['日','一','二','三','四','五','六']
215
+ const dayMapEng = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday']
216
+ const dayMapEngShort = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
217
+ const _format = format || 'YYYY/MM/DD hh:mm'
218
+ const e = _date.getDay()
219
+ const ee = dayMapEngShort[e]
220
+ const eee = dayMapChi[e]
221
+ const eeee = dayMapEng[e]
222
+ const y = _date.getFullYear()
223
+ const m = _date.getMonth() + 1
224
+ const d = _date.getDate()
225
+ const h = _date.getHours()
226
+ const mm = _date.getMinutes()
227
+ const s = _date.getSeconds()
228
+
229
+ return _format.replace('YYYY', y)
230
+ .replace('MM', padding(m))
231
+ .replace('MM', padding(m))
232
+ .replace('DD', padding(d))
233
+ .replace('hh', padding(h))
234
+ .replace('mm', padding(mm))
235
+ .replace('ss', padding(s))
236
+ .replace('M', m)
237
+ .replace('D', d)
238
+ .replace('h', h)
239
+ .replace('m', mm)
240
+ .replace('s', s)
241
+ .replace('EEEE', padding(eeee))
242
+ .replace('EEE', padding(eee))
243
+ .replace('EE', padding(ee))
244
+ .replace('E', padding(e))
245
+ }
246
+
247
+ function padding(m) {
248
+ return m < 10 ? `0${m}` : m
249
+ }
250
+
251
+
252
+ /* harmony default export */ const formatDate_formatDate = ({
253
+ formatDate
254
+ });
255
+
256
+
257
+
258
+ ;// ./lib/helpers/formatDate/index.js
259
+
260
+
266
261
  ;// ./lib/helpers/getValueByKeys/getValueByKeys.js
267
- // keys can be array or string
262
+ // keys can be array or object or string
268
263
  function getValueByKeys(keys, data) {
269
264
  let _keys = keys
270
265
  let _data = data
271
- if (!Array.isArray(keys)) {
266
+ if (typeof keys === 'string') {
267
+ _keys = _keys.split('.')
268
+ }
269
+ if (!Array.isArray(keys) && typeof keys === 'object') {
272
270
  const { keys: keyArr, obj } = keys
273
271
  _keys = keyArr
274
272
  _data = obj
@@ -295,1276 +293,1862 @@ function getValueByKeys(keys, data) {
295
293
  ;// ./lib/helpers/getValueByKeys/index.js
296
294
 
297
295
 
298
- ;// ./lib/helpers/objectHelper/objectHelper.js
299
- const objectHelper = {
300
- get(obj, path) {
301
- const parts = path.split('.')
302
- return parts.reduce((acc, part) => {
303
- if (part.endsWith('[]')) {
304
- // 处理数组遍历
305
- const key = part.slice(0, -2) // 去掉 '[]' 得到属性名
306
- if (Array.isArray(acc[key])) {
307
- return acc[key] // 返回整个数组
308
- }
309
- return [] // 如果不是数组,返回空数组
310
- }
311
- if (part.includes('[') && part.includes(']')) {
312
- // 处理数组索引
313
- const arrayMatch = part.match(/(\w+)\[(\d+)\]/)
314
- if (arrayMatch) {
315
- const key = arrayMatch[1]
316
- const index = arrayMatch[2]
317
- return acc && acc[key] && acc[key][index]
318
- }
319
- } else if (acc && Array.isArray(acc)) {
320
- // 如果当前值是数组,提取每个对象的指定属性
321
- return acc.map((item) => item[part])
322
- } else {
323
- // 处理普通属性
324
- return acc && acc[part]
325
- }
326
- }, obj)
327
- },
328
- merge,
329
- set(obj, path, value) {
330
- const parts = path.split('.')
331
- let current = obj
332
- for (let i = 0; i < parts.length - 1; i++) {
333
- const part = parts[i]
334
- if (part.endsWith('[]')) {
335
- // 处理数组遍历
336
- const key = part.slice(0, -2) // 去掉 '[]' 得到属性名
337
- if (Array.isArray(current[key])) {
338
- current[key].forEach((item) => set(item, parts.slice(i + 1).join('.'), value))
339
- }
340
- return // 处理完数组后直接返回
341
- }
342
- if (part.includes('[') && part.includes(']')) {
343
- // 处理数组索引
344
- const arrayMatch = part.match(/(\w+)\[(\d+)\]/)
345
- if (arrayMatch) {
346
- const key = arrayMatch[1]
347
- const index = arrayMatch[2]
348
- if (Array.isArray(current[key]) && current[key][index]) {
349
- current = current[key][index]
350
- } else {
351
- return // 如果数组或索引不存在,直接返回
352
- }
353
- }
354
- } else {
355
- // 处理普通属性
356
- if (!current[part]) {
357
- current[part] = {} // 如果属性不存在,创建一个空对象
358
- }
359
- current = current[part]
360
- }
361
- }
362
-
363
- // 设置最终属性值
364
- const lastPart = parts[parts.length - 1]
365
- current[lastPart] = value
366
- }
296
+ ;// ./lib/models/templateCompiler/templateCompilerException.js
297
+ const TEMPLATE_COMPILER_EXCEPTION_TYPE = {
298
+ argumentEmptyException: 'Argument is empty',
299
+ argumentFormatException: 'Incorrect number or format of argument',
300
+ invalidFuntionException: 'Function Name is invalid',
301
+ invalidRegExpException: 'Invalid regular expression',
302
+ isNotAFunctionException: 'Is not a function',
303
+ notExistException: 'Key does not exist',
304
+ resultEmptyException: 'Result is empty',
305
+ resultMoreThanOneException: 'More than one result'
367
306
  }
368
307
 
369
- function merge(target, ...sources) {
370
- if (!sources.length) return target
371
-
372
- const source = sources.shift() // 取出第一个源对象
373
-
374
- if (_isObject(target) && _isObject(source)) {
375
- for (const key in source) {
376
- if (_isObject(source[key])) {
377
- if (!target[key]) {
378
- // 如果目标对象没有该属性,创建一个空对象
379
- target[key] = {}
380
- }
381
- // 递归合并
382
- merge(target[key], source[key])
383
- } else {
384
- // 直接覆盖
385
- target[key] = source[key]
386
- }
387
- }
308
+ class TemplateCompilerException extends Error {
309
+ constructor(message) {
310
+ super(message)
311
+ this.message = message
388
312
  }
389
-
390
- // 继续合并剩余的源对象
391
- return merge(target, ...sources)
392
- }
393
-
394
- function _isObject(obj) {
395
- return obj && typeof obj === 'object' && !Array.isArray(obj)
396
313
  }
397
314
 
398
315
 
399
316
 
400
- ;// ./lib/helpers/objectHelper/index.js
317
+ ;// ./lib/models/templateCompiler/constants.js
318
+ const _EMPTY = '_EMPTY'
319
+ const _FN_NAMES = [
320
+ 'get', 'map', 'join', 'concatIf', 'exec', 'filterOne', 'filterAll', 'formatDate', 'eq', 'neq', 'gt', 'lt', 'gte', 'lte', 'isEmpty', 'isNotEmpty', 'toLowerCase', 'toUpperCase'
321
+ ]
322
+ const _HIDE = '_HIDE'
323
+ const _NOT_EMPTY = '_NOT_EMPTY'
324
+ const _SELF = '_SELF'
325
+ const TAGS_EJS = ['<%=', '%>']
326
+ const TAGS_HANDLEBAR = ['{{', '}}']
401
327
 
402
328
 
403
329
 
330
+ ;// ./lib/models/templateCompiler/helpers/_concatIf.js
404
331
 
405
- ;// ./lib/helpers/pReduce/pReduce.js
406
- async function pReduce(iterable, reducer, initialValue) {
407
- return new Promise((resolve, reject) => {
408
- const iterator = iterable[Symbol.iterator]()
409
- let index = 0
410
332
 
411
- const next = async total => {
412
- const element = iterator.next()
413
333
 
414
- if (element.done) {
415
- resolve(total)
416
- return
417
- }
418
334
 
419
- try {
420
- const [resolvedTotal, resolvedValue] = await Promise.all([total, element.value])
421
- next(reducer(resolvedTotal, resolvedValue, index++))
422
- } catch (error) {
423
- reject(error)
424
- }
425
- }
426
-
427
- next(initialValue)
428
- })
335
+ function _concatIf(data, args) {
336
+ if (typeof data !== 'string') {
337
+ throw new TemplateCompilerException(`_concatIf: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: the data must be string :${data.join(', ')}`)
338
+ }
339
+ if (args.length !== 3) {
340
+ throw new TemplateCompilerException(`_concatIf: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
341
+ }
342
+ if (data === null || (typeof data === 'undefined')) {
343
+ return null
344
+ }
345
+ const [condition, success, failover] = args
346
+ const validConditions = [_EMPTY, _NOT_EMPTY]
347
+ if (validConditions.includes(condition) || success.length !== 2) {
348
+ throw new TemplateCompilerException(`concatIf: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentEmptyException}: ${condition}, ${success}`)
349
+ }
350
+ if (data === '' && failover.includes(_HIDE)) {
351
+ return ''
352
+ }
353
+ if (data !== '' && (data !== null || data !== undefined) && failover.includes(_HIDE)) {
354
+ return `${success[0]}${data}${success[success.length - 1]}`
355
+ }
356
+ return failover
429
357
  }
430
358
 
431
359
 
432
360
 
433
- ;// ./lib/models/apiResponse/apiResponse.js
434
- class ApiResponse {
435
- constructor(options = {}) {
436
- options = options || {}
437
- this._data = options.data || options._data || []
438
- this.err = options.err
439
- this.isNew = options.isNew || false
440
- this.message = options.message
441
- this.total = options.total || 0
442
- this._instanceBuilder = options._instanceBuilder
443
- }
361
+ ;// ./lib/models/templateCompiler/helpers/_eq.js
444
362
 
445
- static init(options = {}) {
446
- if (options instanceof this) {
447
- return options
448
- }
449
- const instance = new this(options)
450
- return instance
363
+
364
+
365
+
366
+ function _eq(data, args) {
367
+ if (args.length !== 3) {
368
+ throw new TemplateCompilerException(`eq: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
451
369
  }
452
- static get _classname() {
453
- return 'ApiResponse'
370
+ if (data === null || (typeof data === 'undefined')) {
371
+ return null
454
372
  }
455
- static get _superclass() {
456
- return 'ApiResponse'
373
+ if (args.includes(_SELF)) {
374
+ args = args.map((arg) => {
375
+ return (arg === _SELF) ? data : arg
376
+ })
457
377
  }
378
+ const expected = args[0]
379
+ return data === expected ? args[1] : args[2]
380
+ }
458
381
 
459
- // getters
460
- get data() {
461
- if (this._instanceBuilder && (typeof this._instanceBuilder === 'function')) {
462
- return this._data.map(this._instanceBuilder)
463
- }
464
- return this._data
382
+
383
+
384
+ ;// ./lib/models/templateCompiler/helpers/_exec.js
385
+ function _exec(data, args) {
386
+ try {
387
+ const [methodName, ..._args] = args
388
+ return data[methodName](..._args)
389
+ } catch (e) {
390
+ throw e
465
391
  }
466
392
  }
467
393
 
468
394
 
469
395
 
470
- ;// ./lib/models/apiResponse/makeApiResponse.js
396
+ ;// ./lib/models/templateCompiler/helpers/_filterAll.js
471
397
 
472
398
 
473
- function makeApiResponse({ repo, result }) {
474
- return ApiResponse.init({
475
- ...result,
476
- _instanceBuilder: (i) => {
477
- return repo.init(i)
399
+
400
+ // const DELIMITER = '~~~'
401
+
402
+ function _filterAll(data, args) {
403
+ try {
404
+ if (!Array.isArray(args) || args.length === 0) {
405
+ throw new TemplateCompilerException(TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentEmptyException)
478
406
  }
479
- })
407
+ if (!Array.isArray(data) || data.length === 0) {
408
+ return []
409
+ }
410
+ if (typeof data[0] === 'object') {
411
+ return _existObject(data, args)
412
+ }
413
+ if (typeof data[0] === 'string' || typeof data[0] === 'number') {
414
+ return _exist(data, args)
415
+ }
416
+ return []
417
+ } catch (e) {
418
+ throw e
419
+ }
480
420
  }
481
421
 
422
+ function _exist(data, args) {
423
+ const _args = args.flat()
424
+ return data.filter((e) => _args.some((arg) => _performOperation(arg, e)))
425
+ }
482
426
 
427
+ function _existObject(data, args) {
428
+ if (args.length === 1) {
429
+ const arg = args[0]
430
+ return data.filter((e) => {
431
+ if (arg.includes('.')) {
432
+ return getValueByKeys(arg.split('.'), e)
433
+ }
434
+ return Object.prototype.hasOwnProperty.call(e, arg)
435
+ })
436
+ }
483
437
 
484
- ;// ./lib/models/apiResponse/index.js
485
-
438
+ if (args.length > 2) {
439
+ let res = data
440
+ for (let i = 0; i < args.length; i += 2) {
441
+ const group = [args[i], args[i + 1]]
442
+ res = _existObject(res, group)
443
+ }
444
+ return res
445
+ }
486
446
 
447
+ const [key, ..._argsArr] = args
448
+ const _args = _argsArr.flat()
449
+ return data.filter((e) => {
450
+ const value = key.includes('.') ? getValueByKeys(key.split('.'), e) : e[key]
451
+ return _args.some((arg) => _performOperation(arg, value))
452
+ })
453
+ }
487
454
 
455
+ function _performOperation(arg, value) {
456
+ // the arg is undefined
457
+ if (arg === undefined && value === undefined) return true
488
458
 
459
+ // the arg is null
460
+ if (arg === null && value === null) return true
489
461
 
490
- ;// ./lib/models/keyValueObject/keyValueObject.js
491
- class KeyValueObject {
492
- constructor(options = {}) {
493
- options = options || {}
494
- this.key = options.key || null
495
- this.value = (typeof options.value !== 'undefined') ? options.value : ''
462
+ // the arg is boolean
463
+ if (typeof arg === 'boolean') {
464
+ return arg === value
496
465
  }
497
466
 
498
- // Class methods
499
- static init(options = {}) {
500
- if (options instanceof this) {
501
- return options
467
+ // the arg is blank or *: Blank => Empty, * => Not Empty
468
+ if (arg === '' || arg === '*') {
469
+ // null and undefined are not included in either case
470
+ if (value === null || value === undefined) {
471
+ return false
502
472
  }
503
- const instance = new this(options)
504
- return instance.isValid ? instance : null
505
- }
506
- static initFromArray(arr = []) {
507
- if (Array.isArray(arr)) {
508
- return arr.map((a) => this.init(a))
473
+ if (typeof value === 'string') {
474
+ return arg === '' ? value === '' : value !== ''
509
475
  }
510
- return []
511
- }
512
- static initOnlyValidFromArray(arr = []) {
513
- return this.initFromArray(arr).filter((i) => i)
514
- }
515
- static get _classname() {
516
- return 'KeyValueObject'
517
- }
518
- static get _superclass() {
519
- return 'KeyValueObject'
476
+ if (Array.isArray(value)) {
477
+ return arg === '' ? value.length === 0 : value.length !== 0
478
+ }
479
+ return arg !== ''
520
480
  }
521
481
 
522
- static addItem(arr, key, value) {
523
- arr.push(this.init({ key, value }))
482
+ // the arg is alphabetic or number
483
+ if (_isPureStringOrNumber(arg)) {
484
+ return arg === value
524
485
  }
525
- static addRecord(arr = [], key, value) {
526
- if (!this.hasKeyValue(arr, key, value)) {
527
- arr.push(this.init({ key, value }))
486
+
487
+ // the arg is array of [] or [*]: [] => Empty, [*] => Not Empty
488
+ if (arg.startsWith('[') && arg.endsWith(']')) {
489
+ if (arg === '[]') {
490
+ return Array.isArray(value) && value.length === 0
528
491
  }
529
- return arr
530
- }
531
- static appendRecord(arr = [], key, value) {
532
- return arr.map((item) => {
533
- if (this.sameKey(item, key)) {
534
- item.value = [...item.value, ...value]
535
- }
536
- return item
537
- })
492
+ if (arg === '[*]') {
493
+ return Array.isArray(value) && value.length !== 0
494
+ }
495
+ return false
538
496
  }
539
- static appendValueArray(arr = [], key, value) {
540
- return arr.map((item) => {
541
- if (this.sameKey(item, key)) {
542
- item.value = [...item.value, ...value]
543
- }
544
- return item
545
- })
497
+
498
+ // the arg is 'operator + string | number'
499
+ const { operator, value: argValue } = _splitOperator(arg)
500
+ if (!operator || (argValue !== 0 && !argValue)) {
501
+ return false
546
502
  }
547
- static foundByKey(arr = [], key) {
548
- const found = arr.find((m) => {
549
- return this.sameKey(m, key)
550
- })
551
- return found || null
503
+ switch (operator) {
504
+ case '>':
505
+ return value > argValue
506
+ case '<':
507
+ return value < argValue
508
+ case '!=':
509
+ return value !== argValue
510
+ case '>=':
511
+ return value >= argValue
512
+ case '<=':
513
+ return value <= argValue
514
+ default:
515
+ return false
552
516
  }
553
- static foundValueByKey(arr = [], key) {
554
- const found = this.foundByKey(arr, key)
555
- return found ? found.value : null
517
+ }
518
+
519
+ function _isPureStringOrNumber(input) {
520
+ if (typeof input === 'string') {
521
+ if (input.startsWith('[') && input.endsWith(']')) {
522
+ return false
523
+ }
524
+ if (/!=|>=|<=|>|</.test(input)) {
525
+ return false
526
+ }
527
+ return true
556
528
  }
557
- static fromObject(options = {}) {
558
- return Object.keys(options).reduce((acc, key) => {
559
- acc.push(this.init({ key, value: options[key] }))
560
- return acc
561
- }, [])
529
+ return !Number.isNaN(input)
530
+ }
531
+
532
+ function _splitOperator(str) {
533
+ const operators = ['!=', '>=', '<=', '>', '<']
534
+
535
+ const matchedOp = operators.find((op) => str.startsWith(op))
536
+ if (!matchedOp) return { operator: null, value: null }
537
+
538
+ const remaining = str.slice(matchedOp.length)
539
+
540
+ // '>Primary' or '<Primary' is invalid
541
+ if (/^[a-zA-Z]*$/.test(remaining) && matchedOp !== '!=') {
542
+ return { operator: null, value: null }
562
543
  }
563
- static getValueByKey(arr = [], key) {
564
- return this.foundValueByKey(arr, key)
544
+
545
+ // if it is a number it is converted to a number
546
+ const value = (!Number.isNaN(parseFloat(remaining)) && !Number.isNaN(remaining)) ? Number(remaining) : remaining
547
+
548
+ return {
549
+ operator: matchedOp,
550
+ value
565
551
  }
566
- static getValueByKeyFromArray(arr = [], key) {
567
- if (arr.length === 0) {
568
- return null
552
+ }
553
+
554
+
555
+
556
+ ;// ./lib/models/templateCompiler/helpers/_filterOne.js
557
+
558
+
559
+
560
+ function _filterOne(data, args) {
561
+ try {
562
+ const list = _filterAll(data, args)
563
+ if (list.length === 1) {
564
+ return list[0]
569
565
  }
570
- const firstArr = arr.shift()
571
- const found = firstArr.find((i) => {
572
- return this.sameKey(i, key)
573
- })
574
- if (found && found.value) {
575
- return found.value
566
+ if (list.length === 0) {
567
+ return null
576
568
  }
577
- return this.getValueByKeyFromArray(arr, key)
569
+ throw new TemplateCompilerException(TEMPLATE_COMPILER_EXCEPTION_TYPE.resultMoreThanOneException)
570
+ } catch (e) {
571
+ throw e
578
572
  }
579
- static getValuesByKey(arr = [], key) {
580
- return arr.reduce((acc, item) => {
581
- if (this.sameKey(item, key)) {
582
- acc.push(item.value)
583
- }
584
- return acc
585
- }, [])
573
+ }
574
+
575
+
576
+
577
+ ;// ./lib/models/templateCompiler/helpers/_formatDate.js
578
+
579
+
580
+ function _formatDate(timestamp, format) {
581
+ if (format.length === 0) {
582
+ throw new TemplateCompilerException(`_formateDate: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: format parts must be not empty array`)
586
583
  }
587
- static hasKeyValue(arr = [], key, value) {
588
- if (typeof value === 'undefined') {
589
- return arr.filter((item) => this.sameKey(item, key)).length > 0
590
- }
591
- return arr.filter((item) => (this.sameKey(item, key) && _isSame(item.value, value))).length > 0
584
+
585
+ if (timestamp === null || timestamp === undefined) {
586
+ return null
592
587
  }
593
- static insertOrUpdateRecord(arr = [], key, value) {
594
- let copy = [...arr]
595
- if (!this.hasKeyValue(arr, key)) {
596
- copy.push(this.init({ key, value }))
597
- } else {
598
- copy = this.updateRecord(arr, key, value)
599
- }
600
- return copy
588
+
589
+ const date = new Date(timestamp)
590
+
591
+ const partsMap = {
592
+ yyyy: String(date.getFullYear()),
593
+ mm: String(date.getMonth() + 1).padStart(2, '0'),
594
+ dd: String(date.getDate()).padStart(2, '0')
601
595
  }
602
- static keys(arr = []) {
603
- if (Array.isArray(arr)) {
604
- return arr.reduce((acc, item) => {
605
- acc.push(item.key)
606
- return acc
607
- }, [])
608
- }
609
- return []
596
+
597
+ // Check for invalid format tokens
598
+ const validTokens = ['yyyy', 'mm', 'dd']
599
+ const invalidTokens = format.filter((part) => part.length > 1 && !validTokens.includes(part))
600
+
601
+ if (invalidTokens.length > 0) {
602
+ throw new TemplateCompilerException(
603
+ `_formateDate: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: the format type is not valid: ${format.join(', ')}`
604
+ )
610
605
  }
611
- static merge(toArr, fromArr) {
612
- (fromArr || []).map((from) => {
613
- const found = toArr.find((to) => {
614
- return to.key === from.key
615
- })
616
- if (found) {
617
- found.value = (found.value || []).concat(from.value)
618
- } else {
619
- toArr.push(from)
620
- }
621
- })
622
- return toArr
623
- }
624
- static removeByKey(arr, key) {
625
- return arr.reduce((acc, item) => {
626
- if (!this.sameKey(item, key)) {
627
- acc.push(item)
628
- }
629
- return acc
630
- }, [])
631
- }
632
- static sameKey(item, key) {
633
- return _isSame(item.key, key)
634
- }
635
- static toObject(arr = []) {
636
- if (Array.isArray(arr)) {
637
- return arr.reduce((acc, item) => {
638
- acc[item.key] = item.value
639
- return acc
640
- }, {})
606
+
607
+ // Build the formatted string using reduce
608
+ return format.reduce((result, part) => result + (partsMap[part] || part), '')
609
+ }
610
+
611
+
612
+
613
+ ;// ./lib/models/templateCompiler/helpers/_get.js
614
+
615
+
616
+ function _get(data, key, failover = null) {
617
+ try {
618
+ if (key === null || (typeof key === 'undefined') || key === '') {
619
+ throw new TemplateCompilerException(TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentEmptyException)
641
620
  }
642
- return {}
643
- }
644
- static toString(arr = [], delimiter = '; ') {
645
- if (Array.isArray(arr)) {
646
- return arr.reduce((acc, item) => {
647
- acc.push(`${item.key}: ${item.value}`)
648
- return acc
649
- }, []).join(delimiter)
621
+ if (data === null) {
622
+ return null
650
623
  }
651
- return ''
652
- }
653
- static updateRecord(arr = [], key, value) {
654
- return arr.map((item) => {
655
- if (this.sameKey(item, key)) {
656
- return {
657
- ...item,
658
- value
624
+ if (key.includes('.')) {
625
+ const parts = key.split('.')
626
+ if (parts.length > 1) {
627
+ const first = parts.shift()
628
+ const remainingKey = parts.join('.')
629
+ if (typeof data[first] !== 'undefined') {
630
+ return _get(data[first], remainingKey, failover)
659
631
  }
632
+ return _handleFailover(key, failover)
660
633
  }
661
- return item
662
- })
663
- }
664
- static updateOrInsertRecord(arr = [], key, value) {
665
- return this.insertOrUpdateRecord(arr, key, value)
666
- }
667
- static updateRecordsFromArray(arr = [], updateArr = []) {
668
- if (Array.isArray(arr) && Array.isArray(updateArr)) {
669
- const obj1 = this.toObject(arr)
670
- const obj2 = this.toObject(updateArr)
671
- return this.fromObject({
672
- ...obj1,
673
- ...obj2
674
- })
675
634
  }
676
- return []
677
- }
678
- static values(arr = []) {
679
- if (Array.isArray(arr)) {
680
- return arr.reduce((acc, item) => {
681
- acc.push(item.value)
682
- return acc
683
- }, [])
684
- }
685
- return []
686
- }
687
-
688
- // getters
689
- get isValid() {
690
- return !!this.key
691
- }
692
-
693
- get toObject() {
694
- const obj = {}
695
- if (this.isValid) {
696
- obj[this.key] = this.value
635
+ if (typeof data[key] !== 'undefined') {
636
+ return data[key]
697
637
  }
698
- return obj
638
+ return _handleFailover(key, failover)
639
+ } catch (e) {
640
+ throw e
699
641
  }
700
642
  }
701
643
 
702
- function _isSame(key1, key2) {
703
- return key1 === key2
644
+ function _handleFailover(key, failover) {
645
+ if (failover !== null) {
646
+ return failover
647
+ }
648
+ return null
649
+ // throw new TemplateCompilerException(`Key "${key}" does not exist and no failover`)
704
650
  }
705
651
 
706
652
 
707
653
 
708
- ;// ./lib/models/keyValueObject/index.js
654
+ ;// ./lib/models/templateCompiler/helpers/_gt.js
709
655
 
710
656
 
711
657
 
712
658
 
713
- ;// ./lib/helpers/stringFormatter/stringFormatter.js
714
- function stringFormatter(str, delimiter = '_') {
715
- if (str === null || typeof str === 'undefined' || typeof str.toString === 'undefined') {
659
+ function _gt(data, args) {
660
+ if (args.length !== 3) {
661
+ throw new TemplateCompilerException(`_gt: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
662
+ }
663
+ if (data === null || (typeof data === 'undefined')) {
716
664
  return null
717
665
  }
718
- return str.toString()
719
- .trim()
720
- .toUpperCase()
721
- .replace('-', delimiter)
722
- .replace(' ', delimiter)
666
+ if (args.includes(_SELF)) {
667
+ args = args.map((arg) => {
668
+ return (arg === _SELF) ? data : arg
669
+ })
670
+ }
671
+ const expected = args[0]
672
+ return data > expected ? args[1] : args[2]
723
673
  }
724
674
 
725
675
 
726
676
 
727
- ;// ./lib/models/metadata/metadata.js
677
+ ;// ./lib/models/templateCompiler/helpers/_gte.js
728
678
 
729
679
 
730
680
 
731
- const DELIMITER = '_'
732
681
 
733
- class Metadata extends KeyValueObject {
734
- static init(options = {}) {
735
- if (options instanceof this) {
736
- return options
737
- }
738
- const instance = new this({
739
- ...options,
740
- key: stringFormatter(options.key, DELIMITER),
741
- })
742
- return instance.isValid ? instance : null
682
+ function _gte(data, args) {
683
+ if (args.length !== 3) {
684
+ throw new TemplateCompilerException(`_gte: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
743
685
  }
744
- static get _classname() {
745
- return 'Metadata'
686
+ if (data === null || (typeof data === 'undefined')) {
687
+ return null
746
688
  }
747
-
748
- static merge(toArr, fromArr) {
749
- (fromArr || []).map((from) => {
750
- const found = toArr.find((to) => {
751
- return metadata_isSame(to.key, from.key)
752
- })
753
- if (found) {
754
- found.value = (found.value || []).concat(from.value)
755
- } else {
756
- toArr.push(from)
757
- }
689
+ if (args.includes(_SELF)) {
690
+ args = args.map((arg) => {
691
+ return (arg === _SELF) ? data : arg
758
692
  })
759
- return toArr
760
- }
761
- static sameKey(item, key) {
762
- return metadata_isSame(item.key, key)
763
693
  }
694
+ const expected = args[0]
695
+ return data >= expected ? args[1] : args[2]
764
696
  }
765
697
 
766
- function metadata_isSame(key1, key2) {
767
- return stringFormatter(key1, DELIMITER) === stringFormatter(key2, DELIMITER)
768
- }
769
698
 
770
699
 
700
+ ;// ./lib/models/templateCompiler/helpers/_isEmpty.js
771
701
 
772
- ;// ./lib/models/metadata/index.js
773
702
 
774
703
 
775
704
 
705
+ function _isEmpty(data, args) {
706
+ if (args.length !== 2) {
707
+ throw new TemplateCompilerException(`_isEmpty: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
708
+ }
709
+ // if (data === null || (typeof data === 'undefined')) {
710
+ // return null
711
+ // }
712
+ if (args.includes(_SELF)) {
713
+ args = args.map((arg) => {
714
+ return (arg === _SELF) ? data : arg
715
+ })
716
+ }
717
+ if (data !== null && typeof data === 'object' && Object.keys(data).length === 0) {
718
+ return args[0]
719
+ }
720
+ return (data === '' || data === null || data === undefined || data.length === 0) ? args[0] : args[1]
721
+ }
776
722
 
777
- ;// ./lib/models/qMeta/qMeta.js
778
723
 
779
724
 
780
- const updateAllowedProps = [
781
- 'attributes',
782
- 'ref'
783
- ]
725
+ ;// ./lib/models/templateCompiler/helpers/_isNotEmpty.js
784
726
 
785
- class QMeta {
786
- constructor(options = {}) {
787
- options = options || {}
788
- this.attributes = KeyValueObject.initOnlyValidFromArray(options.attributes)
789
- this.ref = options.ref || {}
790
- }
791
727
 
792
- static get _classname() {
793
- return 'QMeta'
728
+
729
+
730
+ function _isNotEmpty(data, args) {
731
+ if (args.length !== 2) {
732
+ throw new TemplateCompilerException(`_isNotEmpty: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
794
733
  }
795
- static get _superclass() {
796
- return 'QMeta'
734
+ // if (data === null || (typeof data === 'undefined')) {
735
+ // return null
736
+ // }
737
+ if (args.includes(_SELF)) {
738
+ args = args.map((arg) => {
739
+ return (arg === _SELF) ? data : arg
740
+ })
797
741
  }
798
-
799
- // Class methods
800
- static init(options = {}) {
801
- if (options instanceof QMeta) {
802
- return options
803
- }
804
- return new QMeta(options)
742
+ if (data !== null && typeof data === 'object' && Object.keys(data).length === 0) {
743
+ return args[1]
744
+ }
745
+ if (Array.isArray(data) && data.length === 0) {
746
+ return args[1]
747
+ }
748
+ if (typeof data === 'string' && data === '') {
749
+ return args[1]
805
750
  }
751
+ if (data === null || data === undefined) {
752
+ return args[1]
753
+ }
754
+ return args[0]
755
+ }
806
756
 
807
- // instance methods
808
- addAttribute(obj) {
809
- const kvObject = KeyValueObject.init(obj)
810
- if (!kvObject) {
811
- throw new Error('invalid meta attribute')
812
- }
813
- this.attributes.push(kvObject)
814
- return this
757
+
758
+ ;// ./lib/models/templateCompiler/helpers/_join.js
759
+ function _join(data, delimiter) {
760
+ try {
761
+ if (data.length === 0) return ''
762
+ if (data.length === 1) return _stringifyObject(data[0])
763
+ return data.map((item) => _stringifyObject(item)).join(delimiter)
764
+ } catch (e) {
765
+ throw e
815
766
  }
767
+ }
816
768
 
817
- update(obj) {
818
- Object.keys(obj).forEach((key) => {
819
- if (updateAllowedProps.includes(key)) {
820
- if (key === 'attributes') {
821
- this[key] = KeyValueObject.initOnlyValidFromArray(obj[key])
822
- } else {
823
- this[key] = obj[key]
824
- }
825
- }
769
+ function _stringifyObject(obj) {
770
+ return JSON.stringify(obj).replace(/"([^"]+)":/g, '$1: ').replace(/"([^"]+)"/g, '$1').replace(/,/g, ', ')
771
+ }
772
+
773
+
774
+
775
+ ;// ./lib/models/templateCompiler/helpers/_lt.js
776
+
777
+
778
+
779
+
780
+ function _lt(data, args) {
781
+ if (args.length !== 3) {
782
+ throw new TemplateCompilerException(`_lt: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
783
+ }
784
+ if (data === null || (typeof data === 'undefined')) {
785
+ return null
786
+ }
787
+ if (args.includes(_SELF)) {
788
+ args = args.map((arg) => {
789
+ return (arg === _SELF) ? data : arg
826
790
  })
827
- return this
828
791
  }
792
+ const expected = args[0]
793
+ return data < expected ? args[1] : args[2]
829
794
  }
830
795
 
831
796
 
832
797
 
833
- ;// ./lib/models/qMeta/index.js
798
+ ;// ./lib/models/templateCompiler/helpers/_lte.js
834
799
 
835
800
 
836
801
 
837
802
 
838
- ;// ./lib/models/repo/repo.js
839
- class Repo {
840
- constructor(options) {
841
- options = options || {}
842
- this.model = options.model
843
- this._sharedOptions = options._sharedOptions // { session: this.dbTransaction }
844
- this._queryOptions = options._queryOptions
845
- this._saveOptions = options._saveOptions
846
- this._Class = options._constructor && options._constructor._Class
847
- ? options._constructor._Class
848
- : null
849
- }
850
- static init(options = {}) {
851
- if (options instanceof this) {
852
- return options
853
- }
854
- const instance = new this(options)
855
- return instance.isValid ? instance : null
803
+ function _lte(data, args) {
804
+ if (args.length !== 3) {
805
+ throw new TemplateCompilerException(`_lte: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
856
806
  }
857
- static get _classname() {
858
- return 'Repo'
807
+ if (data === null || (typeof data === 'undefined')) {
808
+ return null
859
809
  }
860
- static get _superclass() {
861
- return 'Repo'
810
+ if (args.includes(_SELF)) {
811
+ args = args.map((arg) => {
812
+ return (arg === _SELF) ? data : arg
813
+ })
862
814
  }
815
+ const expected = args[0]
816
+ return data <= expected ? args[1] : args[2]
817
+ }
863
818
 
864
- get _classname() {
865
- return 'Repo'
866
- }
867
819
 
868
- get _superclass() {
869
- return 'Repo'
870
- }
871
820
 
872
- get isValid() {
873
- return this.model
874
- && (typeof this.model.deleteOne === 'function')
875
- && (typeof this.model.findAll === 'function')
876
- && (typeof this.model.saveOne === 'function')
877
- }
821
+ ;// ./lib/models/templateCompiler/helpers/_map.js
878
822
 
879
- get queryOptions() {
880
- return {
881
- ...this._sharedOptions,
882
- ...this._queryOptions,
883
- }
884
- }
885
823
 
886
- get saveOptions() {
887
- return {
888
- ...this._sharedOptions,
889
- ...this._saveOptions,
890
- }
891
- }
892
824
 
893
- init(options) {
894
- if (this._Class && typeof this._Class.init === 'function') {
895
- return this._Class.init(options)
825
+ function _map(data, args) {
826
+ try {
827
+ if (args.length === 0) {
828
+ throw new TemplateCompilerException(TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentEmptyException)
896
829
  }
897
- return options
898
- }
899
-
900
- async deleteOne({ id }) {
901
- try {
902
- const result = await this.model.deleteOne({ _id: id })
903
- return {
904
- ...result, // { message: 'ok', total }
905
- isNew: false,
906
- data: []
907
- }
908
- } catch (err) {
909
- throw err
830
+ if (data === null || (typeof data === 'undefined')) {
831
+ return null
910
832
  }
911
- }
912
833
 
913
- // systemLog is optional
914
- findAll({ query, systemLog }) {
915
- const log = _makeLog({
916
- systemLog,
917
- label: 'REPO_READ',
918
- message: `fn ${this._classname}.prototype.findAll`,
919
- input: [{ query: { ...query }, systemLog: { ...systemLog } }]
920
- })
921
- return new Promise((resolve, reject) => {
922
- this.model.findAll(query, this.queryOptions, (err, data, total) => {
923
- if (err) {
924
- log({ level: 'warn', output: err.toString() })
925
- reject(err)
926
- } else {
927
- const result = {
928
- isNew: false,
929
- data,
930
- total: total || data.length
931
- }
932
- log({ level: 'info', output: { ...result } })
933
- resolve(result)
834
+ const result = data.reduce((acc, item) => {
835
+ if (args.length === 1 && Array.isArray(args[0])) {
836
+ args = args[0]
837
+ acc.hasFormat = true
838
+ }
839
+ const list = args.map((key) => {
840
+ if (key.includes('.')) {
841
+ const parts = key.split('.')
842
+ const first = parts[0]
843
+ parts.shift()
844
+ const remainingKey = parts.join('.')
845
+ return _get(item[first], remainingKey)
934
846
  }
935
- })
936
- })
937
- }
938
-
939
- findOne({ query, systemLog }) {
940
- const log = _makeLog({
941
- systemLog,
942
- label: 'REPO_READ',
943
- message: `fn ${this._classname}.prototype.findOne`,
944
- input: [{ query: { ...query }, systemLog: { ...systemLog } }]
945
- })
946
- return new Promise((resolve, reject) => {
947
- this.model.findAll(query, this.queryOptions, (err, data) => {
948
- if (err) {
949
- reject(err)
950
- } else if (data.length === 1) {
951
- const result = {
952
- isNew: false,
953
- data,
954
- total: 1
955
- }
956
- log({ level: 'info', output: { ...result } })
957
- resolve(result)
958
- } else if (data.length === 0) {
959
- reject(new Error('record not found'))
960
- } else {
961
- reject(new Error('more than one is found'))
847
+ if (typeof item[key] !== 'undefined') {
848
+ return item[key]
962
849
  }
850
+ return null
963
851
  })
852
+ if (acc.hasFormat) {
853
+ acc.content.push(list)
854
+ } else {
855
+ acc.content = acc.content.concat(list)
856
+ }
857
+ return acc
858
+ }, {
859
+ content: [],
860
+ hasFormat: false
964
861
  })
965
- .catch((err) => {
966
- log({ level: 'warn', output: err.toString() })
967
- throw err
968
- })
862
+ return result.content
863
+ } catch (e) {
864
+ throw e
969
865
  }
866
+ }
970
867
 
971
- saveAll({ docs, systemLog }) {
972
- let isNew
973
- const log = _makeLog({
974
- systemLog,
975
- label: 'REPO_WRITE',
976
- message: `fn ${this._classname}.prototype.saveAll`,
977
- input: [{ docs: [...docs], systemLog: { ...systemLog } }]
978
- })
979
- const promise = typeof this.model.saveAll === 'function'
980
- ? this.model.saveAll({ docs })
981
- : Promise.all(docs.map(async (doc) => {
982
- if (doc) {
983
- const result = await this.saveOne({ doc })
984
- isNew = result.isNew
985
- const _data = result._data || result.data
986
- return _data[0]
987
- }
988
- return null
989
- }))
990
- return promise.then((savedData) => {
991
- if (savedData.length !== 1) isNew = null
992
- const result = {
993
- data: savedData,
994
- isNew,
995
- total: savedData.length
996
- }
997
- log({ level: 'info', output: { ...result } })
998
- return result
999
- }).catch((err) => {
1000
- log({ level: 'warn', output: err.toString() })
1001
- throw err
868
+
869
+
870
+ ;// ./lib/models/templateCompiler/helpers/_neq.js
871
+
872
+
873
+
874
+
875
+ function _neq(data, args) {
876
+ if (args.length !== 3) {
877
+ throw new TemplateCompilerException(`_neq: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
878
+ }
879
+ if (data === null || (typeof data === 'undefined')) {
880
+ return null
881
+ }
882
+ if (args.includes(_SELF)) {
883
+ args = args.map((arg) => {
884
+ return (arg === _SELF) ? data : arg
1002
885
  })
1003
886
  }
887
+ const expected = args[0]
888
+ return data !== expected ? args[1] : args[2]
889
+ }
1004
890
 
1005
- saveOne({ doc, systemLog }) {
1006
- const log = _makeLog({
1007
- systemLog,
1008
- label: 'REPO_WRITE',
1009
- message: `fn ${this._classname}.prototype.saveOne`,
1010
- input: [{ doc: { ...doc }, systemLog: { ...systemLog } }]
1011
- })
1012
- return new Promise((resolve, reject) => {
1013
- this.model.saveOne(doc, this.saveOptions, (err, result) => {
1014
- if (err) {
1015
- log({ level: 'warn', output: err.toString() })
1016
- reject(err)
1017
- } else {
1018
- log({ level: 'info', output: { ...result } })
1019
- resolve(result)
1020
- }
1021
- })
1022
- })
891
+
892
+
893
+ ;// ./lib/models/templateCompiler/helpers/_toLowerCase.js
894
+
895
+
896
+ function _toLowerCase(data, args) {
897
+ if (args !== undefined) {
898
+ throw new TemplateCompilerException(`_toLowerCase: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
899
+ }
900
+ if (data === null || (typeof data === 'undefined') || typeof data !== 'string') {
901
+ return null
1023
902
  }
903
+ return String(data).toLowerCase()
1024
904
  }
1025
905
 
1026
- function _makeLog({ systemLog, label, message: message1, input } = {}) {
1027
- return ({ level, messgae: massage2, output } = {}) => {
1028
- if (systemLog && systemLog.systemLogHelper) {
1029
- systemLog.systemLogHelper.log({
1030
- batchId: systemLog.batchId,
1031
- label,
1032
- level,
1033
- message: massage2 || message1,
1034
- data: {
1035
- payload: {
1036
- input,
1037
- output
1038
- }
1039
- }
1040
- })
1041
- }
906
+
907
+
908
+ ;// ./lib/models/templateCompiler/helpers/_toUpperCase.js
909
+
910
+
911
+ function _toUpperCase(data, args) {
912
+ if (typeof data !== 'string') {
913
+ throw new TemplateCompilerException(`_toUpperCase: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: the data must be string: ${data}`)
1042
914
  }
915
+ if (args !== undefined) {
916
+ throw new TemplateCompilerException(`_toUpperCase: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: the argument must be empty: ${args.join(', ')}`)
917
+ }
918
+ if (data === null || (typeof data === 'undefined') || typeof data !== 'string') {
919
+ return null
920
+ }
921
+ return String(data).toUpperCase()
1043
922
  }
1044
923
 
1045
924
 
1046
925
 
1047
- ;// ./lib/models/repo/index.js
926
+ ;// ./lib/models/templateCompiler/helpers/index.js
1048
927
 
1049
928
 
1050
929
 
1051
930
 
1052
- ;// ./lib/models/service/service.js
1053
931
 
1054
932
 
1055
933
 
1056
- class Service {
1057
- constructor({ repo }) {
1058
- this.repo = repo
934
+
935
+
936
+
937
+
938
+
939
+
940
+
941
+
942
+
943
+
944
+
945
+
946
+
947
+
948
+ ;// ./lib/models/templateCompiler/templateCompiler.js
949
+
950
+
951
+
952
+
953
+ class TemplateCompiler {
954
+ constructor(data) {
955
+ this.data = data
956
+ }
957
+ static init(options) {
958
+ return new this(options)
959
+ }
960
+ static initFromArray(arr = []) {
961
+ if (Array.isArray(arr)) {
962
+ return arr.map((a) => this.init(a))
963
+ }
964
+ return []
965
+ }
966
+ static initOnlyValidFromArray(arr = []) {
967
+ return this.initFromArray(arr).filter((i) => i)
968
+ }
969
+ static concatIf(data, args) {
970
+ return _concatIf(data, args)
971
+ }
972
+ static eq(data, args) {
973
+ return _eq(data, args)
974
+ }
975
+
976
+ static filterAll(data, args) {
977
+ return _filterAll(data, args)
978
+ }
979
+
980
+ static formatDate(data, args) {
981
+ return _formatDate(data, args)
982
+ }
983
+
984
+ static get(data, key, failover = null) {
985
+ return _get(data, key, failover)
986
+ }
987
+ static gt(data, args) {
988
+ return _gt(data, args)
989
+ }
990
+ static gte(data, args) {
991
+ return _gte(data, args)
992
+ }
993
+ static isEmpty(data, args) {
994
+ return _isEmpty(data, args)
995
+ }
996
+ static isNotEmpty(data, args) {
997
+ return _isNotEmpty(data, args)
998
+ }
999
+ static join(data, separator = '') {
1000
+ return _join(data, separator)
1001
+ }
1002
+ static lt(data, args) {
1003
+ return _lt(data, args)
1004
+ }
1005
+ static lte(data, args) {
1006
+ return _lte(data, args)
1007
+ }
1008
+ static map(data, args = []) {
1009
+ return _map(data, args)
1010
+ }
1011
+ static neq(data, args) {
1012
+ return _neq(data, args)
1013
+ }
1014
+ static toLowerCase(data, args) {
1015
+ return _toLowerCase(data, args)
1016
+ }
1017
+ static toUpperCase(data, args) {
1018
+ return _toUpperCase(data, args)
1019
+ }
1020
+ static parseFunction(expression) {
1021
+ return _parseFunction(expression, _FN_NAMES)
1022
+ }
1023
+
1024
+ pipe(expression = '') {
1025
+ this.delimiters = expression.substring(0, 2) === '{{' ? TAGS_HANDLEBAR : TAGS_EJS
1026
+ const regex = new RegExp(`${this.delimiters[0]}\\s(.*?)\\s${this.delimiters[1]}`)
1027
+ const match = expression.match(regex)
1028
+ if (match !== null) {
1029
+ try {
1030
+ const functionList = _parseFunction(match[1], _FN_NAMES)
1031
+ return functionList.reduce((acc, fn) => {
1032
+ return _callFunction(acc, fn.name, fn.args)
1033
+ }, this.data)
1034
+ } catch (e) {
1035
+ throw new TemplateCompilerException(`TemplateCompiler engine error: ${e.message}`)
1036
+ }
1037
+ }
1038
+ throw new TemplateCompilerException(`TemplateCompiler engine error: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.invalidRegExpException}`)
1039
+ }
1040
+ }
1041
+
1042
+ function _parseFunction(expression, existFunctionNames) {
1043
+ const regExp = new RegExp(/(\w+)\(([^)]*)\)/)
1044
+ let parts
1045
+ if (expression.includes('|')) {
1046
+ parts = expression.split('|')
1047
+ } else {
1048
+ parts = [expression]
1049
+ }
1050
+ return parts.reduce((acc, part) => {
1051
+ const match = part.match(regExp)
1052
+ if (match !== null) {
1053
+ const functionName = match[1]
1054
+ const parameters = match[2]
1055
+ const paramList = _parseParams(parameters)
1056
+ if (existFunctionNames.includes(functionName)) {
1057
+ acc.push({
1058
+ name: functionName,
1059
+ args: paramList
1060
+ })
1061
+ } else {
1062
+ throw new TemplateCompilerException(`${functionName} is not a valid function`)
1063
+ }
1064
+ }
1065
+ return acc
1066
+ }, [])
1067
+ }
1068
+
1069
+ function _parseParams(parameters) {
1070
+ const _parameters = parameters.trim()
1071
+ const regExp = new RegExp(/^[^\w\d\s]+$/)
1072
+ const match = _parameters.match(regExp)
1073
+ if (match !== null) {
1074
+ return [_parameters.substring(1, _parameters.length - 1)]
1075
+ }
1076
+ if (_parameters.includes(',')) {
1077
+ // 用正则表达式匹配逗号,但忽略方括号中的逗号
1078
+ const parts = _splitIgnoringBrackets(_parameters)
1079
+ return parts.map((part) => _parseSinglePart(part))
1080
+ }
1081
+ return [_parseSinglePart(_parameters)]
1082
+ }
1083
+
1084
+ function _splitIgnoringBrackets(input) {
1085
+ const regExp2 = new RegExp(/^\d+(\.\d+)?$/)
1086
+ const regExp = new RegExp(/(?![^\[]*\])\s*,\s*/)
1087
+ const parts = input.split(regExp)
1088
+ return parts.map((part) => {
1089
+ const _part = part.trim()
1090
+ if (_part !== '' && !!_part.match(regExp2)) {
1091
+ // 如果是数字,转换为 num 类型
1092
+ return Number.isNaN(_part) ? _part : parseInt(_part, 10)
1093
+ }
1094
+ // 否则当作字符串处理
1095
+ return _part
1096
+ })
1097
+ }
1098
+
1099
+ function _parseSinglePart(input) {
1100
+ if (typeof input === 'string') {
1101
+ if (input.startsWith('"') && input.endsWith('"')) {
1102
+ // 去掉双引号,返回
1103
+ return input.substring(1, input.length - 1)
1104
+ }
1105
+
1106
+ const _input = _toBasicType(input)
1107
+
1108
+ if (typeof _input !== 'string') {
1109
+ return _input
1110
+ }
1111
+
1112
+ // 如果是一个列表形式(例如 ["p", "d"] 或 [p, d])
1113
+ if (_input.startsWith('[') && _input.endsWith(']')) {
1114
+ const listContent = _input.substring(1, _input.length - 1).trim()
1115
+ if (listContent !== '') {
1116
+ return listContent.split(',').map((item) => {
1117
+ return _toBasicType(item.trim())
1118
+ })
1119
+ }
1120
+ return []
1121
+ }
1122
+ return input
1123
+ }
1124
+ return input
1125
+ }
1126
+
1127
+ function _toBasicType(input) {
1128
+ if (input.startsWith('"') && input.endsWith('"')) {
1129
+ // 去掉双引号,返回
1130
+ return input.substring(1, input.length - 1)
1131
+ }
1132
+ if (input === 'true') {
1133
+ return true
1134
+ }
1135
+ if (input === 'false') {
1136
+ return false
1137
+ }
1138
+ if (input === 'undefined') {
1139
+ return undefined
1140
+ }
1141
+ if (input === 'null') {
1142
+ return null
1143
+ }
1144
+ if (!Number.isNaN(input) && !Number.isNaN(Number.parseFloat(input))) {
1145
+ return Number(input)
1146
+ }
1147
+ return input
1148
+ }
1149
+
1150
+ function _callFunction(data, functionName, parameters) {
1151
+ try {
1152
+ let failover
1153
+ switch (functionName) {
1154
+ case 'exec':
1155
+ return _exec(data, parameters)
1156
+ case 'get':
1157
+ if (parameters.length > 2) {
1158
+ throw new TemplateCompilerException(TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException)
1159
+ }
1160
+ if (parameters.length === 2) {
1161
+ failover = parameters[parameters.length - 1]
1162
+ }
1163
+ return _get(data, parameters[0], failover)
1164
+ case 'join':
1165
+ return _join(data, parameters[0])
1166
+ case 'map':
1167
+ return _map(data, parameters)
1168
+ case 'concatIf':
1169
+ return _concatIf(data, parameters)
1170
+ case 'filterOne':
1171
+ return _filterOne(data, parameters)
1172
+ case 'filterAll':
1173
+ return _filterAll(data, parameters)
1174
+ case 'formatDate':
1175
+ return _formatDate(data, parameters)
1176
+ case 'eq':
1177
+ return _eq(data, parameters)
1178
+ case 'neq':
1179
+ return _neq(data, parameters)
1180
+ case 'gt':
1181
+ return _gt(data, parameters)
1182
+ case 'gte':
1183
+ return _gte(data, parameters)
1184
+ case 'lt':
1185
+ return _lt(data, parameters)
1186
+ case 'lte':
1187
+ return _lte(data, parameters)
1188
+ case 'isEmpty':
1189
+ return _isEmpty(data, parameters)
1190
+ case 'isNotEmpty':
1191
+ return _isNotEmpty(data, parameters)
1192
+ case 'toLowerCase':
1193
+ return _toLowerCase(data)
1194
+ case 'toUpperCase':
1195
+ return _toUpperCase(data)
1196
+ default:
1197
+ throw new Error(`${functionName} is not a valid function`)
1198
+ }
1199
+ } catch (e) {
1200
+ throw e
1201
+ }
1202
+ }
1203
+
1204
+
1205
+
1206
+ ;// ./lib/models/templateCompiler/index.js
1207
+
1208
+
1209
+
1210
+
1211
+ ;// ./lib/helpers/concatStringByArray/concatStringByArray.js
1212
+
1213
+
1214
+
1215
+
1216
+
1217
+ function concatStringByArray(arrTemplate, data) {
1218
+ return arrTemplate.reduce((acc, item) => {
1219
+ const { type, value = '', restriction, template, format, showMinutes } = item
1220
+ switch (type) {
1221
+ case('label'): {
1222
+ if (getValidation(restriction, data, getValueByKeys)) {
1223
+ acc += (value.toString())
1224
+ }
1225
+ break
1226
+ }
1227
+ case('value'): {
1228
+ if (getValidation(restriction, data, getValueByKeys)) {
1229
+ const _value = getValueByKeys(value.split('.'), data) || ''
1230
+ acc += (_value.toString())
1231
+ }
1232
+ break
1233
+ }
1234
+ case('array'): {
1235
+ if (getValidation(restriction, data, getValueByKeys)) {
1236
+ const _value = getValueByKeys(value.split('.'), data) || []
1237
+ acc += _value.reduce((_acc, item) => {
1238
+ return _acc += concatStringByArray(template, item)
1239
+ }, '')
1240
+ }
1241
+ break
1242
+ }
1243
+ case('ellipsis'): {
1244
+ if (getValidation(restriction, data, getValueByKeys)) {
1245
+ const { maxLength } = item
1246
+ const _value = getValueByKeys(value.split('.'), data) || ''
1247
+ if (_value.length <= maxLength) {
1248
+ acc += (_value.toString())
1249
+ } else {
1250
+ acc += `${_value.substr(0, maxLength)}...`
1251
+ }
1252
+ }
1253
+ break
1254
+ }
1255
+ case ('date'): {
1256
+ if (getValidation(restriction, data, getValueByKeys)) {
1257
+ const _value = getValueByKeys(value.split('.'), data) || ''
1258
+ acc += (formatDate(_value, format).toString())
1259
+ }
1260
+ break
1261
+ }
1262
+ case ('templateCompiler'): {
1263
+ if (getValidation(restriction, data, getValueByKeys)) {
1264
+ const templateCompiler = new TemplateCompiler({ data })
1265
+ acc += templateCompiler.pipe(value)
1266
+ }
1267
+ break
1268
+ }
1269
+ }
1270
+ return acc
1271
+ }, '')
1272
+ }
1273
+ /* harmony default export */ const concatStringByArray_concatStringByArray = ({
1274
+ concatStringByArray
1275
+ });
1276
+
1277
+
1278
+
1279
+ ;// ./lib/helpers/concatStringByArray/index.js
1280
+
1281
+
1282
+ ;// ./lib/helpers/convertString/convertString.js
1283
+ function convertString(string, patternMatch = /\$\{(.+?)\}/g, value, getValueByKeys) {
1284
+ if (!string || typeof getValueByKeys !== 'function') {
1285
+ return ''
1286
+ }
1287
+ const reg = new RegExp(patternMatch, 'g')
1288
+ return string.replace(reg, (match, key) => {
1289
+ const result = getValueByKeys({ keys: key.split('.'), obj: value })
1290
+ if (result === null || result === undefined) {
1291
+ return ''
1292
+ }
1293
+ return typeof result === 'object' ? JSON.stringify(result) : result
1294
+ })
1295
+ }
1296
+
1297
+ /* harmony default export */ const convertString_convertString = ({
1298
+ convertString
1299
+ });
1300
+
1301
+
1302
+ ;// ./lib/helpers/convertString/index.js
1303
+
1304
+
1305
+ ;// ./lib/helpers/objectHelper/objectHelper.js
1306
+ const objectHelper = {
1307
+ get(obj, path) {
1308
+ const parts = path.split('.')
1309
+ return parts.reduce((acc, part) => {
1310
+ if (part.endsWith('[]')) {
1311
+ // 处理数组遍历
1312
+ const key = part.slice(0, -2) // 去掉 '[]' 得到属性名
1313
+ if (Array.isArray(acc[key])) {
1314
+ return acc[key] // 返回整个数组
1315
+ }
1316
+ return [] // 如果不是数组,返回空数组
1317
+ }
1318
+ if (part.includes('[') && part.includes(']')) {
1319
+ // 处理数组索引
1320
+ const arrayMatch = part.match(/(\w+)\[(\d+)\]/)
1321
+ if (arrayMatch) {
1322
+ const key = arrayMatch[1]
1323
+ const index = arrayMatch[2]
1324
+ return acc && acc[key] && acc[key][index]
1325
+ }
1326
+ } else if (acc && Array.isArray(acc)) {
1327
+ // 如果当前值是数组,提取每个对象的指定属性
1328
+ return acc.map((item) => item[part])
1329
+ } else {
1330
+ // 处理普通属性
1331
+ return acc && acc[part]
1332
+ }
1333
+ }, obj)
1334
+ },
1335
+ merge,
1336
+ set(obj, path, value) {
1337
+ const parts = path.split('.')
1338
+ let current = obj
1339
+ for (let i = 0; i < parts.length - 1; i++) {
1340
+ const part = parts[i]
1341
+ if (part.endsWith('[]')) {
1342
+ // 处理数组遍历
1343
+ const key = part.slice(0, -2) // 去掉 '[]' 得到属性名
1344
+ if (Array.isArray(current[key])) {
1345
+ current[key].forEach((item) => set(item, parts.slice(i + 1).join('.'), value))
1346
+ }
1347
+ return // 处理完数组后直接返回
1348
+ }
1349
+ if (part.includes('[') && part.includes(']')) {
1350
+ // 处理数组索引
1351
+ const arrayMatch = part.match(/(\w+)\[(\d+)\]/)
1352
+ if (arrayMatch) {
1353
+ const key = arrayMatch[1]
1354
+ const index = arrayMatch[2]
1355
+ if (Array.isArray(current[key]) && current[key][index]) {
1356
+ current = current[key][index]
1357
+ } else {
1358
+ return // 如果数组或索引不存在,直接返回
1359
+ }
1360
+ }
1361
+ } else {
1362
+ // 处理普通属性
1363
+ if (!current[part]) {
1364
+ current[part] = {} // 如果属性不存在,创建一个空对象
1365
+ }
1366
+ current = current[part]
1367
+ }
1368
+ }
1369
+
1370
+ // 设置最终属性值
1371
+ const lastPart = parts[parts.length - 1]
1372
+ current[lastPart] = value
1373
+ }
1374
+ }
1375
+
1376
+ function merge(target, ...sources) {
1377
+ if (!sources.length) return target
1378
+
1379
+ const source = sources.shift() // 取出第一个源对象
1380
+
1381
+ if (_isObject(target) && _isObject(source)) {
1382
+ for (const key in source) {
1383
+ if (_isObject(source[key])) {
1384
+ if (!target[key]) {
1385
+ // 如果目标对象没有该属性,创建一个空对象
1386
+ target[key] = {}
1387
+ }
1388
+ // 递归合并
1389
+ merge(target[key], source[key])
1390
+ } else {
1391
+ // 直接覆盖
1392
+ target[key] = source[key]
1393
+ }
1394
+ }
1395
+ }
1396
+
1397
+ // 继续合并剩余的源对象
1398
+ return merge(target, ...sources)
1399
+ }
1400
+
1401
+ function _isObject(obj) {
1402
+ return obj && typeof obj === 'object' && !Array.isArray(obj)
1403
+ }
1404
+
1405
+
1406
+
1407
+ ;// ./lib/helpers/objectHelper/index.js
1408
+
1409
+
1410
+
1411
+
1412
+ ;// ./lib/helpers/pReduce/pReduce.js
1413
+ async function pReduce(iterable, reducer, initialValue) {
1414
+ return new Promise((resolve, reject) => {
1415
+ const iterator = iterable[Symbol.iterator]()
1416
+ let index = 0
1417
+
1418
+ const next = async total => {
1419
+ const element = iterator.next()
1420
+
1421
+ if (element.done) {
1422
+ resolve(total)
1423
+ return
1424
+ }
1425
+
1426
+ try {
1427
+ const [resolvedTotal, resolvedValue] = await Promise.all([total, element.value])
1428
+ next(reducer(resolvedTotal, resolvedValue, index++))
1429
+ } catch (error) {
1430
+ reject(error)
1431
+ }
1432
+ }
1433
+
1434
+ next(initialValue)
1435
+ })
1436
+ }
1437
+
1438
+
1439
+
1440
+ ;// ./lib/models/apiResponse/apiResponse.js
1441
+ class ApiResponse {
1442
+ constructor(options = {}) {
1443
+ options = options || {}
1444
+ this._data = options.data || options._data || []
1445
+ this.err = options.err
1446
+ this.isNew = options.isNew || false
1447
+ this.message = options.message
1448
+ this.total = options.total || 0
1449
+ this._instanceBuilder = options._instanceBuilder
1450
+ }
1451
+
1452
+ static init(options = {}) {
1453
+ if (options instanceof this) {
1454
+ return options
1455
+ }
1456
+ const instance = new this(options)
1457
+ return instance
1458
+ }
1459
+ static get _classname() {
1460
+ return 'ApiResponse'
1461
+ }
1462
+ static get _superclass() {
1463
+ return 'ApiResponse'
1464
+ }
1465
+
1466
+ // getters
1467
+ get data() {
1468
+ if (this._instanceBuilder && (typeof this._instanceBuilder === 'function')) {
1469
+ return this._data.map(this._instanceBuilder)
1470
+ }
1471
+ return this._data
1472
+ }
1473
+ }
1474
+
1475
+
1476
+
1477
+ ;// ./lib/models/apiResponse/makeApiResponse.js
1478
+
1479
+
1480
+ function makeApiResponse({ repo, result }) {
1481
+ return ApiResponse.init({
1482
+ ...result,
1483
+ _instanceBuilder: (i) => {
1484
+ return repo.init(i)
1485
+ }
1486
+ })
1487
+ }
1488
+
1489
+
1490
+
1491
+ ;// ./lib/models/apiResponse/index.js
1492
+
1493
+
1494
+
1495
+
1496
+
1497
+ ;// ./lib/models/keyValueObject/keyValueObject.js
1498
+ class KeyValueObject {
1499
+ constructor(options = {}) {
1500
+ options = options || {}
1501
+ this.key = options.key || null
1502
+ this.value = (typeof options.value !== 'undefined') ? options.value : ''
1503
+ }
1504
+
1505
+ // Class methods
1506
+ static init(options = {}) {
1507
+ if (options instanceof this) {
1508
+ return options
1509
+ }
1510
+ const instance = new this(options)
1511
+ return instance.isValid ? instance : null
1512
+ }
1513
+ static initFromArray(arr = []) {
1514
+ if (Array.isArray(arr)) {
1515
+ return arr.map((a) => this.init(a))
1516
+ }
1517
+ return []
1518
+ }
1519
+ static initOnlyValidFromArray(arr = []) {
1520
+ return this.initFromArray(arr).filter((i) => i)
1521
+ }
1522
+ static get _classname() {
1523
+ return 'KeyValueObject'
1524
+ }
1525
+ static get _superclass() {
1526
+ return 'KeyValueObject'
1527
+ }
1528
+
1529
+ static addItem(arr, key, value) {
1530
+ arr.push(this.init({ key, value }))
1531
+ }
1532
+ static addRecord(arr = [], key, value) {
1533
+ if (!this.hasKeyValue(arr, key, value)) {
1534
+ arr.push(this.init({ key, value }))
1535
+ }
1536
+ return arr
1537
+ }
1538
+ static appendRecord(arr = [], key, value) {
1539
+ return arr.map((item) => {
1540
+ if (this.sameKey(item, key)) {
1541
+ item.value = [...item.value, ...value]
1542
+ }
1543
+ return item
1544
+ })
1545
+ }
1546
+ static appendValueArray(arr = [], key, value) {
1547
+ return arr.map((item) => {
1548
+ if (this.sameKey(item, key)) {
1549
+ item.value = [...item.value, ...value]
1550
+ }
1551
+ return item
1552
+ })
1553
+ }
1554
+ static foundByKey(arr = [], key) {
1555
+ const found = arr.find((m) => {
1556
+ return this.sameKey(m, key)
1557
+ })
1558
+ return found || null
1559
+ }
1560
+ static foundValueByKey(arr = [], key) {
1561
+ const found = this.foundByKey(arr, key)
1562
+ return found ? found.value : null
1563
+ }
1564
+ static fromObject(options = {}) {
1565
+ return Object.keys(options).reduce((acc, key) => {
1566
+ acc.push(this.init({ key, value: options[key] }))
1567
+ return acc
1568
+ }, [])
1569
+ }
1570
+ static getValueByKey(arr = [], key) {
1571
+ return this.foundValueByKey(arr, key)
1572
+ }
1573
+ static getValueByKeyFromArray(arr = [], key) {
1574
+ if (arr.length === 0) {
1575
+ return null
1576
+ }
1577
+ const firstArr = arr.shift()
1578
+ const found = firstArr.find((i) => {
1579
+ return this.sameKey(i, key)
1580
+ })
1581
+ if (found && found.value) {
1582
+ return found.value
1583
+ }
1584
+ return this.getValueByKeyFromArray(arr, key)
1585
+ }
1586
+ static getValuesByKey(arr = [], key) {
1587
+ return arr.reduce((acc, item) => {
1588
+ if (this.sameKey(item, key)) {
1589
+ acc.push(item.value)
1590
+ }
1591
+ return acc
1592
+ }, [])
1059
1593
  }
1060
-
1061
- static get _classname() {
1062
- return 'Service'
1594
+ static hasKeyValue(arr = [], key, value) {
1595
+ if (typeof value === 'undefined') {
1596
+ return arr.filter((item) => this.sameKey(item, key)).length > 0
1597
+ }
1598
+ return arr.filter((item) => (this.sameKey(item, key) && _isSame(item.value, value))).length > 0
1063
1599
  }
1064
- static get _superclass() {
1065
- return 'Service'
1600
+ static insertOrUpdateRecord(arr = [], key, value) {
1601
+ let copy = [...arr]
1602
+ if (!this.hasKeyValue(arr, key)) {
1603
+ copy.push(this.init({ key, value }))
1604
+ } else {
1605
+ copy = this.updateRecord(arr, key, value)
1606
+ }
1607
+ return copy
1066
1608
  }
1067
-
1068
- deleteOne({ id }) {
1069
- return this.repo.deleteOne({ id })
1070
- .catch(() => {
1071
- throw new Error(`Not found for query: ${id}`)
1072
- })
1609
+ static keys(arr = []) {
1610
+ if (Array.isArray(arr)) {
1611
+ return arr.reduce((acc, item) => {
1612
+ acc.push(item.key)
1613
+ return acc
1614
+ }, [])
1615
+ }
1616
+ return []
1073
1617
  }
1074
-
1075
- async findAll({ query = {}, systemLog } = {}) {
1076
- const result = await this.repo.findAll({ query, systemLog })
1077
- return makeApiResponse({
1078
- repo: this.repo,
1079
- result
1618
+ static merge(toArr, fromArr) {
1619
+ (fromArr || []).map((from) => {
1620
+ const found = toArr.find((to) => {
1621
+ return to.key === from.key
1622
+ })
1623
+ if (found) {
1624
+ found.value = (found.value || []).concat(from.value)
1625
+ } else {
1626
+ toArr.push(from)
1627
+ }
1080
1628
  })
1629
+ return toArr
1081
1630
  }
1082
-
1083
- async findOne({ query = {}, systemLog } = {}) {
1084
- const result = await this.repo.findOne({ query, systemLog })
1085
- return makeApiResponse({
1086
- repo: this.repo,
1087
- result
1088
- })
1631
+ static removeByKey(arr, key) {
1632
+ return arr.reduce((acc, item) => {
1633
+ if (!this.sameKey(item, key)) {
1634
+ acc.push(item)
1635
+ }
1636
+ return acc
1637
+ }, [])
1089
1638
  }
1090
-
1091
- init(options) {
1092
- return this.repo.init(options)
1639
+ static sameKey(item, key) {
1640
+ return _isSame(item.key, key)
1093
1641
  }
1094
- initFromArray(arr = []) {
1642
+ static toObject(arr = []) {
1095
1643
  if (Array.isArray(arr)) {
1096
- return arr.map((a) => this.init(a))
1644
+ return arr.reduce((acc, item) => {
1645
+ acc[item.key] = item.value
1646
+ return acc
1647
+ }, {})
1097
1648
  }
1098
- return []
1649
+ return {}
1099
1650
  }
1100
- initOnlyValidFromArray(arr = []) {
1101
- return this.initFromArray(arr).filter((i) => i)
1651
+ static toString(arr = [], delimiter = '; ') {
1652
+ if (Array.isArray(arr)) {
1653
+ return arr.reduce((acc, item) => {
1654
+ acc.push(`${item.key}: ${item.value}`)
1655
+ return acc
1656
+ }, []).join(delimiter)
1657
+ }
1658
+ return ''
1102
1659
  }
1103
-
1104
- async saveAll({ docs = [], systemLog } = {}) {
1105
- const copies = docs.map((doc) => {
1106
- return this.init(doc)
1107
- })
1108
- const result = await this.repo.saveAll({ docs: copies, systemLog })
1109
- return makeApiResponse({
1110
- repo: this.repo,
1111
- result
1660
+ static updateRecord(arr = [], key, value) {
1661
+ return arr.map((item) => {
1662
+ if (this.sameKey(item, key)) {
1663
+ return {
1664
+ ...item,
1665
+ value
1666
+ }
1667
+ }
1668
+ return item
1112
1669
  })
1113
1670
  }
1114
-
1115
- async saveOne({ doc = {}, systemLog } = {}) {
1116
- const copy = this.init(doc)
1117
- if (copy) {
1118
- const result = await this.repo.saveOne({ doc: copy, systemLog })
1119
- return makeApiResponse({
1120
- repo: this.repo,
1121
- result
1671
+ static updateOrInsertRecord(arr = [], key, value) {
1672
+ return this.insertOrUpdateRecord(arr, key, value)
1673
+ }
1674
+ static updateRecordsFromArray(arr = [], updateArr = []) {
1675
+ if (Array.isArray(arr) && Array.isArray(updateArr)) {
1676
+ const obj1 = this.toObject(arr)
1677
+ const obj2 = this.toObject(updateArr)
1678
+ return this.fromObject({
1679
+ ...obj1,
1680
+ ...obj2
1122
1681
  })
1123
1682
  }
1124
- return {
1125
- isNew: null,
1126
- data: [],
1127
- err: new Error('doc is not a valid instance')
1683
+ return []
1684
+ }
1685
+ static values(arr = []) {
1686
+ if (Array.isArray(arr)) {
1687
+ return arr.reduce((acc, item) => {
1688
+ acc.push(item.value)
1689
+ return acc
1690
+ }, [])
1128
1691
  }
1692
+ return []
1129
1693
  }
1130
- }
1131
1694
 
1132
- function makeService({ repo }) {
1133
- if (repo === undefined) {
1134
- throw new Error('repo is required.')
1695
+ // getters
1696
+ get isValid() {
1697
+ return !!this.key
1135
1698
  }
1136
- if (repo._superclass !== Repo._superclass) {
1137
- throw new Error('repo is not an instance of Repo.')
1699
+
1700
+ get toObject() {
1701
+ const obj = {}
1702
+ if (this.isValid) {
1703
+ obj[this.key] = this.value
1704
+ }
1705
+ return obj
1138
1706
  }
1139
- return new Service({ repo })
1140
1707
  }
1141
1708
 
1709
+ function _isSame(key1, key2) {
1710
+ return key1 === key2
1711
+ }
1142
1712
 
1143
1713
 
1144
- ;// ./lib/models/service/index.js
1145
1714
 
1715
+ ;// ./lib/models/keyValueObject/index.js
1146
1716
 
1147
1717
 
1148
1718
 
1149
- ;// ./lib/models/template/templateException.js
1150
- const TEMPLATE_EXCEPTION_TYPE = {
1151
- argumentEmptyException: 'Argument is empty',
1152
- argumentFormatException: 'Incorrect number or format of argument',
1153
- invalidFuntionException: 'Function Name is invalid',
1154
- invalidRegExpException: 'Invalid regular expression',
1155
- isNotAFunctionException: 'Is not a function',
1156
- notExistException: 'Key does not exist',
1157
- resultEmptyException: 'Result is empty',
1158
- resultMoreThanOneException: 'More than one result'
1159
- }
1160
1719
 
1161
- class TemplateException extends Error {
1162
- constructor(message) {
1163
- super(message)
1164
- this.message = message
1720
+ ;// ./lib/helpers/stringFormatter/stringFormatter.js
1721
+ function stringFormatter(str, delimiter = '_') {
1722
+ if (str === null || typeof str === 'undefined' || typeof str.toString === 'undefined') {
1723
+ return null
1165
1724
  }
1725
+ return str.toString()
1726
+ .trim()
1727
+ .toUpperCase()
1728
+ .replace('-', delimiter)
1729
+ .replace(' ', delimiter)
1166
1730
  }
1167
1731
 
1168
1732
 
1169
1733
 
1170
- ;// ./lib/models/template/constants.js
1171
- const _EMPTY = '_EMPTY'
1172
- const _FN_NAMES = [
1173
- 'get', 'map', 'join', 'concatIf', 'filterOne', 'filterAll', 'formatDate', 'eq', 'neq', 'gt', 'lt', 'gte', 'lte', 'isEmpty', 'isNotEmpty', 'toLowerCase', 'toUpperCase'
1174
- ]
1175
- const _HIDE = '_HIDE'
1176
- const _NOT_EMPTY = '_NOT_EMPTY'
1177
- const _SELF = '_SELF'
1178
- const TAGS_EJS = ['<%=', '%>']
1179
- const TAGS_HANDLEBAR = ['{{', '}}']
1180
-
1181
-
1182
-
1183
- ;// ./lib/models/template/helpers/_eq.js
1734
+ ;// ./lib/models/metadata/metadata.js
1184
1735
 
1185
1736
 
1186
1737
 
1738
+ const DELIMITER = '_'
1187
1739
 
1188
- function _eq(data, args) {
1189
- if (args.length !== 3) {
1190
- throw new TemplateException(TEMPLATE_EXCEPTION_TYPE.argumentFormatException)
1740
+ class Metadata extends KeyValueObject {
1741
+ static init(options = {}) {
1742
+ if (options instanceof this) {
1743
+ return options
1744
+ }
1745
+ const instance = new this({
1746
+ ...options,
1747
+ key: stringFormatter(options.key, DELIMITER),
1748
+ })
1749
+ return instance.isValid ? instance : null
1191
1750
  }
1192
- if (data === null || (typeof data === 'undefined')) {
1193
- return null
1751
+ static get _classname() {
1752
+ return 'Metadata'
1194
1753
  }
1195
- if (args.includes(_SELF)) {
1196
- args = args.map((arg) => {
1197
- return (arg === _SELF) ? data : arg
1754
+
1755
+ static merge(toArr, fromArr) {
1756
+ (fromArr || []).map((from) => {
1757
+ const found = toArr.find((to) => {
1758
+ return metadata_isSame(to.key, from.key)
1759
+ })
1760
+ if (found) {
1761
+ found.value = (found.value || []).concat(from.value)
1762
+ } else {
1763
+ toArr.push(from)
1764
+ }
1198
1765
  })
1766
+ return toArr
1199
1767
  }
1200
- const expected = args[0]
1201
- return data === expected ? args[1] : args[2]
1202
- }
1203
-
1204
-
1205
-
1206
- ;// ./lib/models/template/helpers/_filterAll.js
1207
-
1208
-
1209
- const _filterAll_DELIMITER = '~~~'
1210
-
1211
- function _filterAll(data, args) {
1212
- try {
1213
- if (!Array.isArray(args) || args.length === 0) {
1214
- throw new TemplateException(TEMPLATE_EXCEPTION_TYPE.argumentEmptyException)
1215
- }
1216
- if (!Array.isArray(data) || data.length === 0) {
1217
- return []
1218
- }
1219
- if (typeof data[0] === 'object') {
1220
- return _existObject(data, args)
1221
- }
1222
- if (typeof data[0] === 'string' || typeof data[0] === 'number') {
1223
- return _exist(data, args)
1224
- }
1225
- return []
1226
- } catch (e) {
1227
- throw e
1768
+ static sameKey(item, key) {
1769
+ return metadata_isSame(item.key, key)
1228
1770
  }
1229
1771
  }
1230
1772
 
1231
- function _exist(data, args) {
1232
- const _str = `${_filterAll_DELIMITER}${args.join(_filterAll_DELIMITER)}${_filterAll_DELIMITER}`
1233
- return data.filter((e) => {
1234
- return _str.includes(`${_filterAll_DELIMITER}${e}${_filterAll_DELIMITER}`) && args.includes(e)
1235
- })
1773
+ function metadata_isSame(key1, key2) {
1774
+ return stringFormatter(key1, DELIMITER) === stringFormatter(key2, DELIMITER)
1236
1775
  }
1237
1776
 
1238
- function _existObject(data, args) {
1239
- if (args.length !== 2) {
1240
- return []
1241
- }
1242
- const [key, _args] = args
1243
- return data.filter((e) => {
1244
- return _args.includes(e[key])
1245
- })
1246
- }
1247
1777
 
1248
1778
 
1779
+ ;// ./lib/models/metadata/index.js
1249
1780
 
1250
- ;// ./lib/models/template/helpers/_filterOne.js
1251
1781
 
1252
1782
 
1253
1783
 
1254
- function _filterOne(data, args) {
1255
- try {
1256
- const list = _filterAll(data, args)
1257
- if (list.length === 1) {
1258
- return list[0]
1259
- }
1260
- if (list.length === 0) {
1261
- return null
1262
- }
1263
- throw new TemplateException(TEMPLATE_EXCEPTION_TYPE.resultMoreThanOneException)
1264
- } catch (e) {
1265
- throw e
1266
- }
1267
- }
1784
+ ;// ./lib/models/qMeta/qMeta.js
1268
1785
 
1269
1786
 
1787
+ const updateAllowedProps = [
1788
+ 'attributes',
1789
+ 'ref'
1790
+ ]
1270
1791
 
1271
- ;// ./lib/models/template/helpers/_get.js
1792
+ class QMeta {
1793
+ constructor(options = {}) {
1794
+ options = options || {}
1795
+ this.attributes = KeyValueObject.initOnlyValidFromArray(options.attributes)
1796
+ this.ref = options.ref || {}
1797
+ }
1272
1798
 
1799
+ static get _classname() {
1800
+ return 'QMeta'
1801
+ }
1802
+ static get _superclass() {
1803
+ return 'QMeta'
1804
+ }
1273
1805
 
1274
- function _get(data, key, failover = null) {
1275
- try {
1276
- if (key === null || (typeof key === 'undefined') || key === '') {
1277
- throw new TemplateException(TEMPLATE_EXCEPTION_TYPE.argumentEmptyException)
1806
+ // Class methods
1807
+ static init(options = {}) {
1808
+ if (options instanceof QMeta) {
1809
+ return options
1278
1810
  }
1279
- if (data === null) {
1280
- return null
1811
+ return new QMeta(options)
1812
+ }
1813
+
1814
+ // instance methods
1815
+ addAttribute(obj) {
1816
+ const kvObject = KeyValueObject.init(obj)
1817
+ if (!kvObject) {
1818
+ throw new Error('invalid meta attribute')
1281
1819
  }
1282
- if (key.includes('.')) {
1283
- const parts = key.split('.')
1284
- if (parts.length > 1) {
1285
- const first = parts.shift()
1286
- const remainingKey = parts.join('.')
1287
- if (typeof data[first] !== 'undefined') {
1288
- return _get(data[first], remainingKey, failover)
1820
+ this.attributes.push(kvObject)
1821
+ return this
1822
+ }
1823
+
1824
+ update(obj) {
1825
+ Object.keys(obj).forEach((key) => {
1826
+ if (updateAllowedProps.includes(key)) {
1827
+ if (key === 'attributes') {
1828
+ this[key] = KeyValueObject.initOnlyValidFromArray(obj[key])
1829
+ } else {
1830
+ this[key] = obj[key]
1289
1831
  }
1290
- return _handleFailover(key, failover)
1291
1832
  }
1292
- }
1293
- if (typeof data[key] !== 'undefined') {
1294
- return data[key]
1295
- }
1296
- return _handleFailover(key, failover)
1297
- } catch (e) {
1298
- throw e
1833
+ })
1834
+ return this
1299
1835
  }
1300
1836
  }
1301
1837
 
1302
- function _handleFailover(key, failover) {
1303
- if (failover !== null) {
1304
- return failover
1305
- }
1306
- return null
1307
- // throw new TemplateException(`Key "${key}" does not exist and no failover`)
1308
- }
1838
+
1839
+
1840
+ ;// ./lib/models/qMeta/index.js
1309
1841
 
1310
1842
 
1311
1843
 
1312
- ;// ./lib/models/template/helpers/_join.js
1313
- function _join(data, delimiter) {
1314
- try {
1315
- return data.join(delimiter)
1316
- } catch (e) {
1317
- throw e
1318
- }
1319
- }
1320
1844
 
1845
+ ;// ./lib/models/repo/repo.js
1846
+ class Repo {
1847
+ constructor(options) {
1848
+ options = options || {}
1849
+ this.model = options.model
1850
+ this._sharedOptions = options._sharedOptions // { session: this.dbTransaction }
1851
+ this._queryOptions = options._queryOptions
1852
+ this._saveOptions = options._saveOptions
1853
+ this._Class = options._constructor && options._constructor._Class
1854
+ ? options._constructor._Class
1855
+ : null
1856
+ }
1857
+ static init(options = {}) {
1858
+ if (options instanceof this) {
1859
+ return options
1860
+ }
1861
+ const instance = new this(options)
1862
+ return instance.isValid ? instance : null
1863
+ }
1864
+ static get _classname() {
1865
+ return 'Repo'
1866
+ }
1867
+ static get _superclass() {
1868
+ return 'Repo'
1869
+ }
1321
1870
 
1871
+ get _classname() {
1872
+ return 'Repo'
1873
+ }
1322
1874
 
1323
- ;// ./lib/models/template/helpers/_map.js
1875
+ get _superclass() {
1876
+ return 'Repo'
1877
+ }
1324
1878
 
1879
+ get isValid() {
1880
+ return this.model
1881
+ && (typeof this.model.deleteOne === 'function')
1882
+ && (typeof this.model.findAll === 'function')
1883
+ && (typeof this.model.saveOne === 'function')
1884
+ }
1325
1885
 
1886
+ get queryOptions() {
1887
+ return {
1888
+ ...this._sharedOptions,
1889
+ ...this._queryOptions,
1890
+ }
1891
+ }
1326
1892
 
1327
- function _map(data, args) {
1328
- try {
1329
- if (args.length === 0) {
1330
- throw new TemplateException(TEMPLATE_EXCEPTION_TYPE.argumentEmptyException)
1893
+ get saveOptions() {
1894
+ return {
1895
+ ...this._sharedOptions,
1896
+ ...this._saveOptions,
1331
1897
  }
1332
- if (data === null || (typeof data === 'undefined')) {
1333
- return null
1898
+ }
1899
+
1900
+ init(options) {
1901
+ if (this._Class && typeof this._Class.init === 'function') {
1902
+ return this._Class.init(options)
1334
1903
  }
1904
+ return options
1905
+ }
1335
1906
 
1336
- const result = data.reduce((acc, item) => {
1337
- if (args.length === 1 && Array.isArray(args[0])) {
1338
- args = args[0]
1339
- acc.hasFormat = true
1907
+ async deleteOne({ id }) {
1908
+ try {
1909
+ const result = await this.model.deleteOne({ _id: id })
1910
+ return {
1911
+ ...result, // { message: 'ok', total }
1912
+ isNew: false,
1913
+ data: []
1340
1914
  }
1341
- const list = args.map((key) => {
1342
- if (key.includes('.')) {
1343
- const parts = key.split('.')
1344
- const first = parts[0]
1345
- parts.shift()
1346
- const remainingKey = parts.join('.')
1347
- return _get(item[first], remainingKey)
1915
+ } catch (err) {
1916
+ throw err
1917
+ }
1918
+ }
1919
+
1920
+ // systemLog is optional
1921
+ findAll({ query, systemLog }) {
1922
+ const log = _makeLog({
1923
+ systemLog,
1924
+ label: 'REPO_READ',
1925
+ message: `fn ${this._classname}.prototype.findAll`,
1926
+ input: [{ query: { ...query }, systemLog: { ...systemLog } }]
1927
+ })
1928
+ return new Promise((resolve, reject) => {
1929
+ this.model.findAll(query, this.queryOptions, (err, data, total) => {
1930
+ if (err) {
1931
+ log({ level: 'warn', output: err.toString() })
1932
+ reject(err)
1933
+ } else {
1934
+ const result = {
1935
+ isNew: false,
1936
+ data,
1937
+ total: total || data.length
1938
+ }
1939
+ log({ level: 'info', output: { ...result } })
1940
+ resolve(result)
1348
1941
  }
1349
- if (typeof item[key] !== 'undefined') {
1350
- return item[key]
1942
+ })
1943
+ })
1944
+ }
1945
+
1946
+ findOne({ query, systemLog }) {
1947
+ const log = _makeLog({
1948
+ systemLog,
1949
+ label: 'REPO_READ',
1950
+ message: `fn ${this._classname}.prototype.findOne`,
1951
+ input: [{ query: { ...query }, systemLog: { ...systemLog } }]
1952
+ })
1953
+ return new Promise((resolve, reject) => {
1954
+ this.model.findAll(query, this.queryOptions, (err, data) => {
1955
+ if (err) {
1956
+ reject(err)
1957
+ } else if (data.length === 1) {
1958
+ const result = {
1959
+ isNew: false,
1960
+ data,
1961
+ total: 1
1962
+ }
1963
+ log({ level: 'info', output: { ...result } })
1964
+ resolve(result)
1965
+ } else if (data.length === 0) {
1966
+ reject(new Error('record not found'))
1967
+ } else {
1968
+ reject(new Error('more than one is found'))
1969
+ }
1970
+ })
1971
+ })
1972
+ .catch((err) => {
1973
+ log({ level: 'warn', output: err.toString() })
1974
+ throw err
1975
+ })
1976
+ }
1977
+
1978
+ saveAll({ docs, systemLog }) {
1979
+ let isNew
1980
+ const log = _makeLog({
1981
+ systemLog,
1982
+ label: 'REPO_WRITE',
1983
+ message: `fn ${this._classname}.prototype.saveAll`,
1984
+ input: [{ docs: [...docs], systemLog: { ...systemLog } }]
1985
+ })
1986
+ const promise = typeof this.model.saveAll === 'function'
1987
+ ? this.model.saveAll({ docs })
1988
+ : Promise.all(docs.map(async (doc) => {
1989
+ if (doc) {
1990
+ const result = await this.saveOne({ doc })
1991
+ isNew = result.isNew
1992
+ const _data = result._data || result.data
1993
+ return _data[0]
1351
1994
  }
1352
1995
  return null
1353
- })
1354
- if (acc.hasFormat) {
1355
- acc.content.push(list)
1356
- } else {
1357
- acc.content = acc.content.concat(list)
1996
+ }))
1997
+ return promise.then((savedData) => {
1998
+ if (savedData.length !== 1) isNew = null
1999
+ const result = {
2000
+ data: savedData,
2001
+ isNew,
2002
+ total: savedData.length
1358
2003
  }
1359
- return acc
1360
- }, {
1361
- content: [],
1362
- hasFormat: false
2004
+ log({ level: 'info', output: { ...result } })
2005
+ return result
2006
+ }).catch((err) => {
2007
+ log({ level: 'warn', output: err.toString() })
2008
+ throw err
1363
2009
  })
1364
- return result.content
1365
- } catch (e) {
1366
- throw e
1367
2010
  }
1368
- }
1369
-
1370
-
1371
-
1372
- ;// ./lib/models/template/helpers/index.js
1373
-
1374
2011
 
2012
+ saveOne({ doc, systemLog }) {
2013
+ const log = _makeLog({
2014
+ systemLog,
2015
+ label: 'REPO_WRITE',
2016
+ message: `fn ${this._classname}.prototype.saveOne`,
2017
+ input: [{ doc: { ...doc }, systemLog: { ...systemLog } }]
2018
+ })
2019
+ return new Promise((resolve, reject) => {
2020
+ this.model.saveOne(doc, this.saveOptions, (err, result) => {
2021
+ if (err) {
2022
+ log({ level: 'warn', output: err.toString() })
2023
+ reject(err)
2024
+ } else {
2025
+ log({ level: 'info', output: { ...result } })
2026
+ resolve(result)
2027
+ }
2028
+ })
2029
+ })
2030
+ }
2031
+ }
1375
2032
 
2033
+ function _makeLog({ systemLog, label, message: message1, input } = {}) {
2034
+ return ({ level, messgae: massage2, output } = {}) => {
2035
+ if (systemLog && systemLog.systemLogHelper) {
2036
+ systemLog.systemLogHelper.log({
2037
+ batchId: systemLog.batchId,
2038
+ label,
2039
+ level,
2040
+ message: massage2 || message1,
2041
+ data: {
2042
+ payload: {
2043
+ input,
2044
+ output
2045
+ }
2046
+ }
2047
+ })
2048
+ }
2049
+ }
2050
+ }
1376
2051
 
1377
2052
 
1378
2053
 
2054
+ ;// ./lib/models/repo/index.js
1379
2055
 
1380
2056
 
1381
2057
 
1382
- ;// ./lib/models/template/template.js
1383
2058
 
2059
+ ;// ./lib/models/service/service.js
1384
2060
 
1385
2061
 
1386
2062
 
1387
- class Template {
1388
- constructor({ data }) {
1389
- this.data = data
1390
- }
1391
- static eq(data, args) {
1392
- return _eq(data, args)
2063
+ class Service {
2064
+ constructor({ repo }) {
2065
+ this.repo = repo
1393
2066
  }
1394
- static get(data, key, failover = null) {
1395
- return _get(data, key, failover)
2067
+
2068
+ static get _classname() {
2069
+ return 'Service'
1396
2070
  }
1397
- static join(data, separator = '') {
1398
- return _join(data, separator)
2071
+ static get _superclass() {
2072
+ return 'Service'
1399
2073
  }
1400
- static map(data, args = []) {
1401
- return _map(data, args)
2074
+
2075
+ deleteOne({ id }) {
2076
+ return this.repo.deleteOne({ id })
2077
+ .catch(() => {
2078
+ throw new Error(`Not found for query: ${id}`)
2079
+ })
1402
2080
  }
1403
- static parseFunction(expression) {
1404
- return _parseFunction(expression, _FN_NAMES)
2081
+
2082
+ async findAll({ query = {}, systemLog } = {}) {
2083
+ const result = await this.repo.findAll({ query, systemLog })
2084
+ return makeApiResponse({
2085
+ repo: this.repo,
2086
+ result
2087
+ })
1405
2088
  }
1406
2089
 
1407
- pipe(expression = '') {
1408
- this.delimiters = expression.substring(0,2) === '<%' ? TAGS_EJS : TAGS_HANDLEBAR
1409
- const regex = new RegExp(`${this.delimiters[0]}\\s(.*?)\\s${this.delimiters[1]}`)
1410
- const match = expression.match(regex)
1411
- if (match !== null) {
1412
- try {
1413
- const functionList = _parseFunction(match[1], _FN_NAMES)
1414
- return functionList.reduce((acc, fn) => {
1415
- return _callFunction(acc, fn.name, fn.args)
1416
- }, this.data)
1417
- } catch (e) {
1418
- throw new TemplateException(`Template engine error: ${e.message}`)
1419
- }
1420
- }
1421
- throw new TemplateException(TEMPLATE_EXCEPTION_TYPE.invalidRegExpException)
2090
+ async findOne({ query = {}, systemLog } = {}) {
2091
+ const result = await this.repo.findOne({ query, systemLog })
2092
+ return makeApiResponse({
2093
+ repo: this.repo,
2094
+ result
2095
+ })
1422
2096
  }
1423
- }
1424
2097
 
1425
- function _parseFunction(expression, existFunctionNames) {
1426
- const regExp = new RegExp(/(\w+)\(([^)]*)\)/)
1427
- let parts
1428
- if (expression.includes('|')) {
1429
- parts = expression.split('|')
1430
- } else {
1431
- parts = [expression]
2098
+ init(options) {
2099
+ return this.repo.init(options)
1432
2100
  }
1433
- return parts.reduce((acc, part) => {
1434
- const match = part.match(regExp)
1435
- if (match !== null) {
1436
- const functionName = match[1]
1437
- const parameters = match[2]
1438
- const paramList = _parseParams(parameters)
1439
- if (existFunctionNames.includes(functionName)) {
1440
- acc.push({
1441
- name: functionName,
1442
- args: paramList
1443
- })
1444
- } else {
1445
- throw new TemplateException(`${functionName} is not a valid function`)
1446
- }
2101
+ initFromArray(arr = []) {
2102
+ if (Array.isArray(arr)) {
2103
+ return arr.map((a) => this.init(a))
1447
2104
  }
1448
- return acc
1449
- }, [])
1450
- }
1451
-
1452
- function _parseParams(parameters) {
1453
- const _parameters = parameters.trim()
1454
- const regExp = new RegExp(/^[^\w\d\s]+$/)
1455
- const match = _parameters.match(regExp)
1456
- if (match !== null) {
1457
- return [_parameters.substring(1, _parameters.length - 1)]
2105
+ return []
1458
2106
  }
1459
- if (_parameters.includes(',')) {
1460
- // 用正则表达式匹配逗号,但忽略方括号中的逗号
1461
- const parts = _splitIgnoringBrackets(_parameters)
1462
- return parts.map((part) => _parseSinglePart(part))
2107
+ initOnlyValidFromArray(arr = []) {
2108
+ return this.initFromArray(arr).filter((i) => i)
1463
2109
  }
1464
- return [_parseSinglePart(_parameters)]
1465
- }
1466
2110
 
1467
- function _splitIgnoringBrackets(input) {
1468
- const regExp2 = new RegExp(/^\d+(\.\d+)?$/)
1469
- const regExp = new RegExp(/(?![^\[]*\])\s*,\s*/)
1470
- const parts = input.split(regExp)
1471
- return parts.map((part) => {
1472
- const _part = part.trim()
1473
- if (_part !== '' && !!_part.match(regExp2)) {
1474
- // 如果是数字,转换为 num 类型
1475
- return Number.isNaN(_part) ? _part : parseInt(_part, 10)
1476
- }
1477
- // 否则当作字符串处理
1478
- return _part
1479
- })
1480
- }
2111
+ async saveAll({ docs = [], systemLog } = {}) {
2112
+ const copies = docs.map((doc) => {
2113
+ return this.init(doc)
2114
+ })
2115
+ const result = await this.repo.saveAll({ docs: copies, systemLog })
2116
+ return makeApiResponse({
2117
+ repo: this.repo,
2118
+ result
2119
+ })
2120
+ }
1481
2121
 
1482
- function _parseSinglePart(input) {
1483
- if (typeof input === 'string') {
1484
- if (input.startsWith('"') && input.endsWith('"')) {
1485
- // 去掉双引号,返回
1486
- return input.substring(1, input.length - 1)
2122
+ async saveOne({ doc = {}, systemLog } = {}) {
2123
+ const copy = this.init(doc)
2124
+ if (copy) {
2125
+ const result = await this.repo.saveOne({ doc: copy, systemLog })
2126
+ return makeApiResponse({
2127
+ repo: this.repo,
2128
+ result
2129
+ })
1487
2130
  }
1488
-
1489
- // 如果是一个列表形式(例如 ["p", "d"] 或 [p, d])
1490
- if (input.startsWith('[') && input.endsWith(']')) {
1491
- const listContent = input.substring(1, input.length - 1).trim()
1492
- if (listContent !== '') {
1493
- return listContent.split(',').map((item) => {
1494
- return item.trim().replaceAll('"', '') // 去除可能的双引号
1495
- })
1496
- }
1497
- return []
2131
+ return {
2132
+ isNew: null,
2133
+ data: [],
2134
+ err: new Error('doc is not a valid instance')
1498
2135
  }
1499
- return input
1500
2136
  }
1501
- return input
1502
2137
  }
1503
2138
 
1504
- function _callFunction(data, functionName, parameters) {
1505
- try {
1506
- let failover
1507
- switch (functionName) {
1508
- case 'get':
1509
- if (parameters.length > 2) {
1510
- throw new TemplateException(TEMPLATE_EXCEPTION_TYPE.argumentFormatException)
1511
- }
1512
- if (parameters.length === 2) {
1513
- failover = parameters[parameters.length - 1]
1514
- }
1515
- return _get(data, parameters[0], failover)
1516
- case 'map':
1517
- return _map(data, parameters)
1518
- case 'join':
1519
- return _join(data, parameters[0])
1520
- // case 'concatIf':
1521
- // if (parameters.length != 3) {
1522
- // throw const TemplateException(TemplateExceptionType.argumentFormatException);
1523
- // }
1524
- // var condition = parameters.first;
1525
- // var success = parameters[1];
1526
- // var failover = parameters[2];
1527
- // return _concatIf(data, condition, success, failover);
1528
- case 'filterOne':
1529
- return _filterOne(data, parameters)
1530
- case 'filterAll':
1531
- return _filterAll(data, parameters)
1532
- // case 'formatDate':
1533
- // if (parameters is List<String>) {
1534
- // return _formatDate(data, parameters);
1535
- // }
1536
- // throw const TemplateException(TemplateExceptionType.argumentFormatException);
1537
- case 'eq':
1538
- return _eq(data, parameters)
1539
- // case 'neq':
1540
- // return _neq(data, parameters);
1541
- // case 'gt':
1542
- // return _gt(data, parameters);
1543
- // case 'gte':
1544
- // return _gte(data, parameters);
1545
- // case 'lt':
1546
- // return _lt(data, parameters);
1547
- // case 'lte':
1548
- // return _lte(data, parameters);
1549
- // case 'isEmpty':
1550
- // return _isEmpty(data, parameters);
1551
- // case 'isNotEmpty':
1552
- // return _isNotEmpty(data, parameters);
1553
- // case 'toLowerCase':
1554
- // return _toLowerCase(data);
1555
- // case 'toUpperCase':
1556
- // return _toUpperCase(data);
1557
- default:
1558
- throw new Error(`${functionName} is not a valid function`)
1559
- }
1560
- } catch (e) {
1561
- throw e
2139
+ function makeService({ repo }) {
2140
+ if (repo === undefined) {
2141
+ throw new Error('repo is required.')
2142
+ }
2143
+ if (repo._superclass !== Repo._superclass) {
2144
+ throw new Error('repo is not an instance of Repo.')
1562
2145
  }
2146
+ return new Service({ repo })
1563
2147
  }
1564
2148
 
1565
2149
 
1566
2150
 
1567
- ;// ./lib/models/template/index.js
2151
+ ;// ./lib/models/service/index.js
1568
2152
 
1569
2153
 
1570
2154
 
@@ -1813,6 +2397,7 @@ const stringHelper = {
1813
2397
 
1814
2398
 
1815
2399
 
2400
+
1816
2401
  ;// ./lib/index.js
1817
2402
 
1818
2403