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