@questwork/q-utilities 0.1.10 → 0.1.12

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