@questwork/q-utilities 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1154 @@
1
+ (function webpackUniversalModuleDefinition(root, factory) {
2
+ if(typeof exports === 'object' && typeof module === 'object')
3
+ module.exports = factory();
4
+ else if(typeof define === 'function' && define.amd)
5
+ define([], factory);
6
+ else {
7
+ var a = factory();
8
+ for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
9
+ }
10
+ })(this, () => {
11
+ return /******/ (() => { // webpackBootstrap
12
+ /******/ "use strict";
13
+ /******/ // The require scope
14
+ /******/ var __webpack_require__ = {};
15
+ /******/
16
+ /************************************************************************/
17
+ /******/ /* webpack/runtime/define property getters */
18
+ /******/ (() => {
19
+ /******/ // define getter functions for harmony exports
20
+ /******/ __webpack_require__.d = (exports, definition) => {
21
+ /******/ for(var key in definition) {
22
+ /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
23
+ /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
24
+ /******/ }
25
+ /******/ }
26
+ /******/ };
27
+ /******/ })();
28
+ /******/
29
+ /******/ /* webpack/runtime/hasOwnProperty shorthand */
30
+ /******/ (() => {
31
+ /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
32
+ /******/ })();
33
+ /******/
34
+ /******/ /* webpack/runtime/make namespace object */
35
+ /******/ (() => {
36
+ /******/ // define __esModule on exports
37
+ /******/ __webpack_require__.r = (exports) => {
38
+ /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
39
+ /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
40
+ /******/ }
41
+ /******/ Object.defineProperty(exports, '__esModule', { value: true });
42
+ /******/ };
43
+ /******/ })();
44
+ /******/
45
+ /************************************************************************/
46
+ var __webpack_exports__ = {};
47
+ // ESM COMPAT FLAG
48
+ __webpack_require__.r(__webpack_exports__);
49
+
50
+ // EXPORTS
51
+ __webpack_require__.d(__webpack_exports__, {
52
+ ApiResponse: () => (/* reexport */ ApiResponse),
53
+ KeyValueObject: () => (/* reexport */ KeyValueObject),
54
+ Metadata: () => (/* reexport */ Metadata),
55
+ Repo: () => (/* reexport */ Repo),
56
+ Service: () => (/* reexport */ Service),
57
+ convertString: () => (/* reexport */ convertString),
58
+ formatDate: () => (/* reexport */ formatDate),
59
+ getValidation: () => (/* reexport */ getValidation),
60
+ getValueByKeys: () => (/* reexport */ getValueByKeys),
61
+ jwtHelper: () => (/* reexport */ jwtHelper),
62
+ makeApiResponse: () => (/* reexport */ makeApiResponse),
63
+ makeService: () => (/* reexport */ makeService),
64
+ padZeros: () => (/* reexport */ padZeros),
65
+ stringFormatter: () => (/* reexport */ stringFormatter)
66
+ });
67
+
68
+ ;// ./lib/helpers/convertString/convertString.js
69
+ function convertString(string, patternMatch = /\$\{(.+?)\}/g, value, getValueByKeys) {
70
+ if (!string || typeof getValueByKeys !== 'function') {
71
+ return ''
72
+ }
73
+ const reg = new RegExp(patternMatch, 'g')
74
+ return string.replace(reg, (match, key) => {
75
+ const result = getValueByKeys({ keys: key.split('.'), obj: value })
76
+ if (result === null || result === undefined) {
77
+ return ''
78
+ }
79
+ return typeof result === 'object' ? JSON.stringify(result) : result
80
+ })
81
+ }
82
+
83
+ /* harmony default export */ const convertString_convertString = ({
84
+ convertString
85
+ });
86
+
87
+
88
+ ;// ./lib/helpers/convertString/index.js
89
+
90
+
91
+ ;// ./lib/helpers/formatDate/formatDate.js
92
+
93
+ function formatDate(date, format) {
94
+ const _date = date && date instanceof Date ? date : new Date(date)
95
+ const dayMapChi = ['日','一','二','三','四','五','六']
96
+ const dayMapEng = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday']
97
+ const dayMapEngShort = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
98
+ const _format = format || 'YYYY/MM/DD hh:mm'
99
+ const e = _date.getDay()
100
+ const ee = dayMapEngShort[e]
101
+ const eee = dayMapChi[e]
102
+ const eeee = dayMapEng[e]
103
+ const y = _date.getFullYear()
104
+ const m = _date.getMonth() + 1
105
+ const d = _date.getDate()
106
+ const h = _date.getHours()
107
+ const mm = _date.getMinutes()
108
+ const s = _date.getSeconds()
109
+
110
+ return _format.replace('YYYY', y)
111
+ .replace('MM', padding(m))
112
+ .replace('MM', padding(m))
113
+ .replace('DD', padding(d))
114
+ .replace('hh', padding(h))
115
+ .replace('mm', padding(mm))
116
+ .replace('ss', padding(s))
117
+ .replace('M', m)
118
+ .replace('D', d)
119
+ .replace('h', h)
120
+ .replace('m', mm)
121
+ .replace('s', s)
122
+ .replace('EEEE', padding(eeee))
123
+ .replace('EEE', padding(eee))
124
+ .replace('EE', padding(ee))
125
+ .replace('E', padding(e))
126
+ }
127
+
128
+ function padding(m) {
129
+ return m < 10 ? `0${m}` : m
130
+ }
131
+
132
+
133
+ /* harmony default export */ const formatDate_formatDate = ({
134
+ formatDate
135
+ });
136
+
137
+
138
+
139
+ ;// ./lib/helpers/formatDate/index.js
140
+
141
+
142
+ ;// ./lib/helpers/getValidation/getValidation.js
143
+ function getValidation(rule, data, getDataByKey, KeyValueObject) {
144
+ if (!rule) {
145
+ return true
146
+ }
147
+ if (typeof getDataByKey !== 'function' || typeof KeyValueObject !== 'function') {
148
+ return false
149
+ }
150
+ const { key = '', value, keyValuePath = '' } = rule
151
+ const [valueAttribute] = Object.keys(value)
152
+
153
+ if (!key) {
154
+ switch (valueAttribute) {
155
+ case '$and': {
156
+ return value['$and'].reduce((acc, item) => (acc && getValidation(item, data, getDataByKey, KeyValueObject)), true)
157
+ }
158
+ case '$or': {
159
+ return value['$or'].reduce((acc, item) => (acc || getValidation(item, data, getDataByKey, KeyValueObject)), false)
160
+ }
161
+ default:
162
+ return false
163
+ }
164
+ }
165
+
166
+ let rowValue = getDataByKey(key, data)
167
+
168
+ // debugger
169
+
170
+ // if KeyValue object
171
+ if (keyValuePath) {
172
+ console.log('keyValuePath', keyValuePath)
173
+ const rowValueData = KeyValueObject.toObject(rowValue)
174
+ rowValue = getDataByKey(keyValuePath, rowValueData)
175
+ }
176
+
177
+ switch (valueAttribute) {
178
+ case '$empty': {
179
+ const isEmpty = rowValue === null || rowValue === undefined
180
+ return isEmpty === value['$empty']
181
+ }
182
+ case '$eq': {
183
+ return rowValue === value['$eq']
184
+ }
185
+ case '$gt': {
186
+ return rowValue > value['$gt']
187
+ }
188
+ case '$gte': {
189
+ return rowValue >= value['$gte']
190
+ }
191
+ case '$lt': {
192
+ return rowValue < value['$lt']
193
+ }
194
+ case '$lte': {
195
+ return rowValue <= value['$lte']
196
+ }
197
+ case '$in': {
198
+ if (Array.isArray(rowValue)) {
199
+ return !!rowValue.find((e) => (value['$in'].includes(e)))
200
+ }
201
+ if (typeof rowValue !== 'object') {
202
+ return !!value['$in'].includes(rowValue)
203
+ }
204
+ return false
205
+ }
206
+ case '$inValue': {
207
+ const result = getDataByKey(value['$inValue'], data)
208
+ const _value = Array.isArray(result) ? result : []
209
+ if (Array.isArray(rowValue)) {
210
+ return !!rowValue.find((e) => (_value.includes(e)))
211
+ }
212
+ if (typeof rowValue === 'string') {
213
+ return !!_value.includes(rowValue)
214
+ }
215
+ return false
216
+ }
217
+ case '$ne': {
218
+ return rowValue !== value['$ne']
219
+ }
220
+ case '$notIn': {
221
+ if (Array.isArray(rowValue)) {
222
+ return !rowValue.find((e) => (value['$notIn'].includes(e)))
223
+ }
224
+ if (typeof rowValue !== 'object') {
225
+ return !value['$notIn'].includes(rowValue)
226
+ }
227
+ return false
228
+ }
229
+ case '$notInValue': {
230
+ const result = getDataByKey(value['$notInValue'], data)
231
+ const _value = Array.isArray(result) ? result : []
232
+ if (Array.isArray(rowValue)) {
233
+ return !rowValue.find((e) => (_value.includes(e)))
234
+ }
235
+ if (typeof rowValue !== 'object') {
236
+ return !_value.includes(rowValue)
237
+ }
238
+ return false
239
+ }
240
+ case '$range': {
241
+ const [min, max] = value['$range']
242
+ if (typeof min === 'number' && typeof max === 'number' && rowValue >= min && rowValue <= max) {
243
+ return true
244
+ }
245
+ return false
246
+ }
247
+ default:
248
+ return false
249
+ }
250
+ }
251
+
252
+ /* harmony default export */ const getValidation_getValidation = ({
253
+ getValidation
254
+ });
255
+
256
+
257
+ ;// ./lib/helpers/getValidation/index.js
258
+
259
+
260
+ ;// ./lib/helpers/getValueByKeys/getValueByKeys.js
261
+ // keys can be array or string
262
+ function getValueByKeys(keys, data) {
263
+ let _keys = keys
264
+ let _data = data
265
+ if (!Array.isArray(keys)) {
266
+ const { keys: keyArr, obj } = keys
267
+ _keys = keyArr
268
+ _data = obj
269
+ }
270
+ if (_keys.length === 0) {
271
+ return _data
272
+ }
273
+ const firstKey = _keys.shift()
274
+ if (_data && Object.prototype.hasOwnProperty.call(_data, firstKey)) {
275
+ return getValueByKeys(_keys, _data[firstKey])
276
+ }
277
+ if (_data && firstKey) {
278
+ return _data[firstKey]
279
+ }
280
+ return _data
281
+
282
+ }
283
+ /* harmony default export */ const getValueByKeys_getValueByKeys = ({
284
+ getValueByKeys
285
+ });
286
+
287
+
288
+
289
+ ;// ./lib/helpers/getValueByKeys/index.js
290
+
291
+
292
+ ;// ./lib/helpers/jwtHelper/jwtHelper.js
293
+ // 'use strict'
294
+
295
+ /* eslint-disable new-cap */
296
+ /* eslint-disable camelcase */
297
+ /* eslint-disable no-mixed-operators */
298
+ /* eslint-disable no-useless-escape */
299
+ /* eslint-disable no-param-reassign */
300
+
301
+ /* eslint func-names: 0 */
302
+
303
+ // const Buffer = require('buffer/').Buffer
304
+
305
+ const EXPIRY = 3600 // in second
306
+ const ALGORITHM = 'HS256'
307
+ const SECRET = 'ab1234cd'
308
+
309
+ const _hasBuffer = typeof Buffer === 'function'
310
+
311
+ const jwtHelper = {
312
+ create(obj, { secret, algorithm, expiry } = {}) {
313
+ const sAlgorithm = algorithm || ALGORITHM
314
+ const sSecret = secret || SECRET
315
+ const exp = expiry || getTimeInSecond() + EXPIRY
316
+ const payload = {
317
+ ...obj,
318
+ exp
319
+ }
320
+ return encode(payload, sSecret, sAlgorithm)
321
+ },
322
+ createByUser(loginAccount) {
323
+ const exp = getTimeInSecond() + EXPIRY
324
+ const payload = {
325
+ loginAccount,
326
+ exp
327
+ }
328
+ return this.encode(payload)
329
+ },
330
+ encode(payload, algorithm) {
331
+ return encode(payload, SECRET, algorithm)
332
+ },
333
+ decode(token, algorithm) {
334
+ const noVerify = !this.verify(token)
335
+ return decode(token, SECRET, noVerify, algorithm) // if noVerify = true, may skip verification
336
+ },
337
+ getPayload(token) {
338
+ const payload = getPayload(token)
339
+ return {
340
+ payload
341
+ }
342
+ },
343
+ getPayloadIdByKey(token, key) {
344
+ const payload = getPayload(token)
345
+ const id = payload[key] ? payload[key].id : null
346
+ return {
347
+ id,
348
+ jwtToken: token
349
+ }
350
+ },
351
+ resolve(token, secret, algorithm) {
352
+ const sSecret = secret || SECRET
353
+ return decode(token, sSecret, false, algorithm) // need verification
354
+ },
355
+ verify(token) {
356
+ const payload = getPayload(token)
357
+ const today = getTimeInSecond()
358
+ return (payload.exp && (today <= payload.exp)) || false
359
+ }
360
+ }
361
+
362
+ /**
363
+ * Private functions
364
+ */
365
+
366
+ const getPayload = (token) => decode(token, SECRET, true)
367
+
368
+ const getTimeInSecond = () => Math.floor(Date.now() / 1000)
369
+
370
+ /**
371
+ * Private functions, based on jwt-simple 0.2.0
372
+ */
373
+
374
+ const { cryptoHelper } = require('../cryptoHelper')
375
+
376
+ const algorithmMap = {
377
+ HS256: 'sha256',
378
+ HS384: 'sha384',
379
+ HS512: 'sha512',
380
+ RS256: 'RSA-SHA256'
381
+ }
382
+
383
+ const typeMap = {
384
+ HS256: 'hmac',
385
+ HS384: 'hmac',
386
+ HS512: 'hmac',
387
+ RS256: 'sign'
388
+ }
389
+
390
+
391
+ /**
392
+ * Decode jwt
393
+ *
394
+ * @param {Object} token
395
+ * @param {String} key
396
+ * @param {Boolean} noVerify
397
+ * @param {String} algorithm
398
+ * @return {Object} payload
399
+ * @api public
400
+ */
401
+ const decode = function jwt_decode(token, key, noVerify, algorithm) {
402
+ // check token
403
+ if (!token) {
404
+ throw new Error('No token supplied')
405
+ }
406
+ // check segments
407
+ const segments = token.split('.')
408
+ if (segments.length !== 3) {
409
+ throw new Error('Not enough or too many segments')
410
+ }
411
+
412
+ // All segment should be base64
413
+ const headerSeg = segments[0]
414
+ const payloadSeg = segments[1]
415
+ const signatureSeg = segments[2]
416
+
417
+ // base64 decode and parse JSON
418
+ const header = JSON.parse(base64urlDecode(headerSeg))
419
+
420
+ const payload = JSON.parse(base64urlDecode(payloadSeg))
421
+
422
+ if (!noVerify) {
423
+ const signingMethod = algorithmMap[algorithm || header.alg]
424
+ const signingType = typeMap[algorithm || header.alg]
425
+ if (!signingMethod || !signingType) {
426
+ throw new Error('Algorithm not supported')
427
+ }
428
+
429
+ // verify signature. `sign` will return base64 string.
430
+ const signingInput = [headerSeg, payloadSeg].join('.')
431
+ if (!verify(signingInput, key, signingMethod, signingType, signatureSeg)) {
432
+ throw new Error('Signature verification failed')
433
+ }
434
+ }
435
+
436
+ return payload
437
+ }
438
+
439
+
440
+ /**
441
+ * Encode jwt
442
+ *
443
+ * @param {Object} payload
444
+ * @param {String} key
445
+ * @param {String} algorithm
446
+ * @return {String} token
447
+ * @api public
448
+ */
449
+ const encode = function jwt_encode(payload, key, algorithm) {
450
+ // Check key
451
+ if (!key) {
452
+ throw new Error('Require key')
453
+ }
454
+
455
+ // Check algorithm, default is HS256
456
+ if (!algorithm) {
457
+ algorithm = ALGORITHM
458
+ }
459
+
460
+ const signingMethod = algorithmMap[algorithm]
461
+ const signingType = typeMap[algorithm]
462
+ if (!signingMethod || !signingType) {
463
+ throw new Error('Algorithm not supported')
464
+ }
465
+
466
+ // header, typ is fixed value.
467
+ const header = { typ: 'JWT', alg: algorithm }
468
+
469
+ // create segments, all segments should be base64 string
470
+ const segments = []
471
+ segments.push(base64urlEncode(JSON.stringify(header)))
472
+ segments.push(base64urlEncode(JSON.stringify(payload)))
473
+ segments.push(sign(segments.join('.'), key, signingMethod, signingType))
474
+
475
+ return segments.join('.')
476
+ }
477
+
478
+
479
+ /**
480
+ * private util functions
481
+ */
482
+
483
+ function verify(input, key, method, type, signature) {
484
+ if (type === 'hmac') {
485
+ return (signature === sign(input, key, method, type))
486
+ } else if (type === 'sign') {
487
+ try {
488
+ return cryptoHelper.createStringVerify({
489
+ algorithm: method,
490
+ data: input,
491
+ object: key,
492
+ signature: base64urlUnescape(signature),
493
+ signatureEncoding: 'base64'
494
+ })
495
+ } catch (error) {
496
+ throw new Error('createStringVerify failed')
497
+ }
498
+ }
499
+ throw new Error('Algorithm type not recognized')
500
+ }
501
+
502
+ function sign(input, key, method, type) {
503
+ let base64str
504
+ if (type === 'hmac') {
505
+ base64str = cryptoHelper.createStringHmac({
506
+ algorithm: method,
507
+ key,
508
+ data: input,
509
+ outputEncoding: 'base64'
510
+ })
511
+ } else if (type === 'sign') {
512
+ try {
513
+ base64str = cryptoHelper.createSignature({
514
+ algorithm: method,
515
+ data: input,
516
+ privateKey: key,
517
+ outputEncoding: 'base64'
518
+ })
519
+ } catch (error) {
520
+ throw new Error('createSignature failed')
521
+ }
522
+ } else {
523
+ throw new Error('Algorithm type not recognized')
524
+ }
525
+ return base64urlEscape(base64str)
526
+ }
527
+
528
+ function _decode(str) {
529
+ if (_hasBuffer) {
530
+ return Buffer.from(base64urlUnescape(str), 'base64').toString('utf8')
531
+ }
532
+ return atob(base64urlUnescape(str))
533
+ }
534
+
535
+ function _encode(str) {
536
+ if (_hasBuffer) {
537
+ return base64urlEscape(Buffer.from(str, 'utf8').toString('base64'))
538
+ }
539
+ return base64urlEscape(btoa(str))
540
+ }
541
+
542
+ function base64urlDecode(str) {
543
+ // fixed bug if decode string is incorrect
544
+ // return (new Buffer.from(base64urlUnescape(str), 'base64')).toString() || '{}'
545
+ return _decode(str)
546
+ }
547
+
548
+ function base64urlUnescape(str) {
549
+ str += new Array(5 - str.length % 4).join('=')
550
+ return str.replace(/\-/g, '+').replace(/_/g, '/')
551
+ }
552
+
553
+ function base64urlEncode(str) {
554
+ // return base64urlEscape(new Buffer.from((str)).toString('base64'))
555
+ return _encode(str)
556
+ }
557
+
558
+ function base64urlEscape(str) {
559
+ return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '')
560
+ }
561
+
562
+
563
+
564
+ ;// ./lib/helpers/jwtHelper/index.js
565
+
566
+
567
+
568
+
569
+
570
+ ;// ./lib/helpers/padZeros/padZeros.js
571
+ function padZeros(num, minLength = 6) {
572
+ num = num.toString()
573
+ if (num.length < minLength) {
574
+ return padZeros('0' + num, minLength)
575
+ }
576
+ return num
577
+ }
578
+
579
+
580
+
581
+ ;// ./lib/helpers/padZeros/index.js
582
+
583
+
584
+
585
+
586
+ ;// ./lib/helpers/stringFormatter/stringFormatter.js
587
+ function stringFormatter(str) {
588
+ return (str || '').toUpperCase().replace('-', '_').replace(' ', '_')
589
+ }
590
+
591
+
592
+
593
+ ;// ./lib/helpers/stringFormatter/index.js
594
+
595
+
596
+
597
+
598
+ ;// ./lib/helpers/index.js
599
+
600
+
601
+
602
+
603
+
604
+
605
+
606
+
607
+ ;// ./lib/models/apiResponse/apiResponse.js
608
+ class ApiResponse {
609
+ constructor(options = {}) {
610
+ options = options || {}
611
+ this._data = options.data || options._data || []
612
+ this.err = options.err
613
+ this.isNew = options.isNew || false
614
+ this.message = options.message
615
+ this.total = options.total || 0
616
+ this._instanceBuilder = options._instanceBuilder
617
+ }
618
+
619
+ static init(options = {}) {
620
+ if (options instanceof this) {
621
+ return options
622
+ }
623
+ const instance = new this(options)
624
+ return instance
625
+ }
626
+ static get _classname() {
627
+ return 'ApiResponse'
628
+ }
629
+ static get _superclass() {
630
+ return 'ApiResponse'
631
+ }
632
+
633
+ // getters
634
+ get data() {
635
+ if (this._instanceBuilder && (typeof this._instanceBuilder === 'function')) {
636
+ return this._data.map(this._instanceBuilder)
637
+ }
638
+ return this._data
639
+ }
640
+ }
641
+
642
+
643
+
644
+ ;// ./lib/models/apiResponse/makeApiResponse.js
645
+
646
+
647
+ function makeApiResponse({ repo, result }) {
648
+ return ApiResponse.init({
649
+ ...result,
650
+ _instanceBuilder: (i) => {
651
+ return repo.init(i)
652
+ }
653
+ })
654
+ }
655
+
656
+
657
+
658
+ ;// ./lib/models/apiResponse/index.js
659
+
660
+
661
+
662
+
663
+
664
+ ;// ./lib/models/keyValueObject/keyValueObject.js
665
+ class KeyValueObject {
666
+ constructor(options = {}) {
667
+ options = options || {}
668
+ this.key = options.key || null
669
+ this.value = (typeof options.value !== 'undefined') ? options.value : ''
670
+ }
671
+
672
+ // Class methods
673
+ static init(options = {}) {
674
+ if (options instanceof this) {
675
+ return options
676
+ }
677
+ const instance = new this(options)
678
+ return instance.isValid ? instance : null
679
+ }
680
+ static initFromArray(arr = []) {
681
+ if (Array.isArray(arr)) {
682
+ return arr.map((a) => this.init(a))
683
+ }
684
+ return []
685
+ }
686
+ static initOnlyValidFromArray(arr = []) {
687
+ return this.initFromArray(arr).filter((i) => i)
688
+ }
689
+ static get _classname() {
690
+ return 'KeyValueObject'
691
+ }
692
+ static get _superclass() {
693
+ return 'KeyValueObject'
694
+ }
695
+
696
+ static addItem(arr, key, value) {
697
+ arr.push(
698
+ { key, value }
699
+ )
700
+ }
701
+ static addRecord(arr = [], key, value) {
702
+ const self = this
703
+ if (!this.hasKeyValue(arr, key, value)) {
704
+ arr.push(self.init({ key, value }))
705
+ }
706
+ return arr
707
+ }
708
+
709
+ static appendRecord(arr = [], key, value) {
710
+ return arr.map((item) => {
711
+ if (item.key === key) {
712
+ item.value = [...item.value, ...value]
713
+ }
714
+ return item
715
+ })
716
+ }
717
+
718
+ static fromObject(options = {}) {
719
+ const self = this
720
+ return Object.keys(options).reduce((acc, key) => {
721
+ acc.push(self.init({ key, value: options[key] }))
722
+ return acc
723
+ }, [])
724
+ }
725
+
726
+ static removeByKey(arr, key) {
727
+ return arr.reduce((acc, item) => {
728
+ if (item.key !== key) {
729
+ acc.push(item)
730
+ }
731
+ return acc
732
+ }, [])
733
+ }
734
+
735
+ static foundByKey(arr = [], key) {
736
+ const found = arr.find((m) => {
737
+ return m.key === key
738
+ })
739
+ return found || null
740
+ }
741
+
742
+ static foundValueByKey(arr = [], key) {
743
+ const found = this.foundByKey(arr, key)
744
+ return found ? found.value : null
745
+ }
746
+
747
+ static getValueByKey(arr = [], key) {
748
+ const found = arr.find((i) => {
749
+ return i.key === key
750
+ })
751
+ if (found) {
752
+ return found.value
753
+ }
754
+ return null
755
+ }
756
+
757
+ static getValueByKeyFromArray(arr = [], key) {
758
+ if (arr.length === 0) {
759
+ return null
760
+ }
761
+ const firstArr = arr.shift()
762
+ const found = firstArr.find((i) => {
763
+ return i.key === key
764
+ })
765
+ if (found && found.value) {
766
+ return found.value
767
+ }
768
+ return this.getValueByKeyFromArray(arr, key)
769
+ }
770
+
771
+ static getValuesByKey(arr = [], key) {
772
+ return arr.reduce((acc, item) => {
773
+ if (item.key === key) {
774
+ acc.push(item.value)
775
+ }
776
+ return acc
777
+ }, [])
778
+ }
779
+
780
+ static hasKeyValue(arr = [], key, value) {
781
+ if (typeof value === 'undefined') {
782
+ return arr.filter((item) => item.key === key).length > 0
783
+ }
784
+ return arr.filter((item) => (item.key === key && item.value === value)).length > 0
785
+ }
786
+
787
+ static insertOrUpdateRecord(arr = [], key, value) {
788
+ const self = this
789
+ let copy = [...arr]
790
+ if (!self.hasKeyValue(arr, key)) {
791
+ copy.push(self.init({ key, value }))
792
+ } else {
793
+ copy = self.updateRecord(arr, key, value)
794
+ }
795
+ return copy
796
+ }
797
+
798
+ static keys(arr = []) {
799
+ if (Array.isArray(arr)) {
800
+ return arr.reduce((acc, item) => {
801
+ acc.push(item.key)
802
+ return acc
803
+ }, [])
804
+ }
805
+ return []
806
+ }
807
+
808
+ static merge(toArr, fromArr) {
809
+ (fromArr || []).map((from) => {
810
+ const found = toArr.find((to) => {
811
+ return to.key === from.key
812
+ })
813
+ if (found) {
814
+ found.value = (found.value || []).concat(from.value)
815
+ } else {
816
+ toArr.push(from)
817
+ }
818
+ })
819
+ return toArr
820
+ }
821
+
822
+ static toObject(arr = []) {
823
+ if (Array.isArray(arr)) {
824
+ return arr.reduce((acc, item) => {
825
+ acc[item.key] = item.value
826
+ return acc
827
+ }, {})
828
+ }
829
+ return {}
830
+ }
831
+
832
+ static toString(arr = [], delimiter = '; ') {
833
+ if (Array.isArray(arr)) {
834
+ return arr.reduce((acc, item) => {
835
+ acc.push(`${item.key}: ${item.value}`)
836
+ return acc
837
+ }, []).join(delimiter)
838
+ }
839
+ return ''
840
+ }
841
+
842
+ static updateRecord(arr = [], key, value) {
843
+ return arr.map((item) => {
844
+ if (item.key === key) {
845
+ return {
846
+ ...item,
847
+ value
848
+ }
849
+ }
850
+ return item
851
+ })
852
+ }
853
+
854
+ static updateOrInsertRecord(arr = [], key, value) {
855
+ return this.insertOrUpdateRecord(arr, key, value)
856
+ }
857
+
858
+ static updateRecordsFromArray(arr = [], updateArr = []) {
859
+ if (Array.isArray(arr) && Array.isArray(updateArr)) {
860
+ const obj1 = this.toObject(arr)
861
+ const obj2 = this.toObject(updateArr)
862
+ return this.fromObject({
863
+ ...obj1,
864
+ ...obj2
865
+ })
866
+ }
867
+ return []
868
+ }
869
+
870
+ static values(arr = []) {
871
+ if (Array.isArray(arr)) {
872
+ return arr.reduce((acc, item) => {
873
+ acc.push(item.value)
874
+ return acc
875
+ }, [])
876
+ }
877
+ return []
878
+ }
879
+
880
+ // getters
881
+ get isValid() {
882
+ return !!this.key
883
+ }
884
+
885
+ get toObject() {
886
+ const obj = {}
887
+ if (this.isValid) {
888
+ obj[this.key] = this.value
889
+ }
890
+ return obj
891
+ }
892
+ }
893
+
894
+
895
+
896
+ ;// ./lib/models/keyValueObject/index.js
897
+
898
+
899
+
900
+
901
+ ;// ./lib/models/metadata/metadata.js
902
+
903
+
904
+
905
+ class Metadata extends KeyValueObject {
906
+ static init(options = {}) {
907
+ if (options instanceof this) {
908
+ return options
909
+ }
910
+ const instance = new this({
911
+ ...options,
912
+ key: stringFormatter(options.key),
913
+ })
914
+ return instance.isValid ? instance : null
915
+ }
916
+
917
+ static foundByKey(arr = [], key) {
918
+ const found = (arr || []).find((m) => {
919
+ return m.key === stringFormatter(key)
920
+ })
921
+ return found || null
922
+ }
923
+
924
+ static get _classname() {
925
+ return 'Metadata'
926
+ }
927
+ }
928
+
929
+
930
+
931
+ ;// ./lib/models/metadata/index.js
932
+
933
+
934
+
935
+
936
+ ;// ./lib/models/repo/repo.js
937
+ class Repo {
938
+ constructor(options) {
939
+ this.model = options.model
940
+ this.dbTransaction = options.dbTransaction
941
+ }
942
+
943
+ static get _classname() {
944
+ return 'Repo'
945
+ }
946
+ static get _superclass() {
947
+ return 'Repo'
948
+ }
949
+
950
+ init(options) {
951
+ throw new Error('subclass should implement .init(options)')
952
+ }
953
+
954
+ async deleteOne({ id }) {
955
+ try {
956
+ const result = await this.model.deleteOne({ _id: id })
957
+ return {
958
+ ...result, // { message: 'ok', total }
959
+ isNew: false,
960
+ data: []
961
+ }
962
+ } catch (err) {
963
+ throw err
964
+ }
965
+ }
966
+
967
+ findAll({ query }) {
968
+ const options = {}
969
+ return new Promise((resolve, reject) => {
970
+ this.model.findAll(query, options, (err, data, total) => {
971
+ if (err) {
972
+ reject(err)
973
+ } else {
974
+ resolve({
975
+ isNew: false,
976
+ data,
977
+ total: total || data.length
978
+ })
979
+ }
980
+ })
981
+ })
982
+ }
983
+
984
+ findOne({ query }) {
985
+ const options = { session: this.dbTransaction }
986
+ return new Promise((resolve, reject) => {
987
+ this.model.findAll(query, options, (err, data) => {
988
+ if (err) {
989
+ reject(err)
990
+ } else if (data.length === 1) {
991
+ resolve({
992
+ isNew: false,
993
+ data,
994
+ total: 1
995
+ })
996
+ } else if (data.length === 0) {
997
+ reject(new Error('record not found'))
998
+ } else {
999
+ reject(new Error('more than one is found'))
1000
+ }
1001
+ })
1002
+ })
1003
+ }
1004
+
1005
+ saveAll({ docs }) {
1006
+ const self = this
1007
+ let isNew
1008
+ return Promise.all(docs.map(async (doc) => {
1009
+ if (doc) {
1010
+ const result = await self.saveOne({ doc })
1011
+ isNew = result.isNew
1012
+ return result.data[0]
1013
+ }
1014
+ return null
1015
+ })).then((savedData) => {
1016
+ if (savedData.length !== 1) isNew = null
1017
+ return {
1018
+ data: savedData,
1019
+ isNew,
1020
+ total: savedData.length
1021
+ }
1022
+ })
1023
+ }
1024
+
1025
+ saveOne({ doc }) {
1026
+ const options = { session: this.dbTransaction }
1027
+ return new Promise((resolve, reject) => {
1028
+ this.model.saveOne(doc, options, (err, result) => {
1029
+ if (err) {
1030
+ reject(err)
1031
+ } else {
1032
+ resolve(result)
1033
+ }
1034
+ })
1035
+ })
1036
+ }
1037
+ }
1038
+
1039
+
1040
+
1041
+ ;// ./lib/models/repo/index.js
1042
+
1043
+
1044
+
1045
+
1046
+ ;// ./lib/models/service/service.js
1047
+
1048
+
1049
+
1050
+ class Service {
1051
+ constructor({ repo }) {
1052
+ this.repo = repo
1053
+ }
1054
+
1055
+ static get _classname() {
1056
+ return 'Service'
1057
+ }
1058
+ static get _superclass() {
1059
+ return 'Service'
1060
+ }
1061
+
1062
+ deleteOne({ id }) {
1063
+ return this.repo.deleteOne({ id })
1064
+ .catch(() => {
1065
+ throw new Error(`Not found for query: ${id}`)
1066
+ })
1067
+ }
1068
+
1069
+ async findAll({ query = {} } = {}) {
1070
+ const result = await this.repo.findAll({ query })
1071
+ return makeApiResponse({
1072
+ repo: this.repo,
1073
+ result
1074
+ })
1075
+ }
1076
+
1077
+ async findOne({ query = {} } = {}) {
1078
+ const result = await this.repo.findOne({ query })
1079
+ return makeApiResponse({
1080
+ repo: this.repo,
1081
+ result
1082
+ })
1083
+ }
1084
+
1085
+ init(options) {
1086
+ return this.repo.init(options)
1087
+ }
1088
+ initFromArray(arr = []) {
1089
+ return arr.map((i) => this.init(i))
1090
+ }
1091
+
1092
+ async saveAll({ docs = [] } = {}) {
1093
+ const copies = docs.map((doc) => {
1094
+ return this.init(doc)
1095
+ })
1096
+ const result = await this.repo.saveAll({ docs: copies })
1097
+ return makeApiResponse({
1098
+ repo: this.repo,
1099
+ result
1100
+ })
1101
+ }
1102
+
1103
+ async saveOne({ doc = {} } = {}) {
1104
+ const copy = this.init(doc)
1105
+ if (copy) {
1106
+ const result = await this.repo.saveOne({ doc: copy })
1107
+ return makeApiResponse({
1108
+ repo: this.repo,
1109
+ result
1110
+ })
1111
+ }
1112
+ return {
1113
+ isNew: null,
1114
+ data: [],
1115
+ err: new Error('doc is not a valid instance')
1116
+ }
1117
+ }
1118
+ }
1119
+
1120
+ function makeService({ repo }) {
1121
+ if (repo === undefined) {
1122
+ throw new Error('repo is required.')
1123
+ }
1124
+ // if (!(repo instanceof Repo)) {
1125
+ // throw new Error('repo is not an instance of Repo.')
1126
+ // }
1127
+ return new Service({ repo })
1128
+ }
1129
+
1130
+
1131
+
1132
+ ;// ./lib/models/service/index.js
1133
+
1134
+
1135
+
1136
+
1137
+ ;// ./lib/models/index.js
1138
+
1139
+
1140
+
1141
+
1142
+
1143
+
1144
+ ;// ./lib/index.js
1145
+
1146
+
1147
+
1148
+ ;// ./index.js
1149
+
1150
+
1151
+ /******/ return __webpack_exports__;
1152
+ /******/ })()
1153
+ ;
1154
+ });