@questwork/q-utilities 0.1.29 → 0.1.32

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.
@@ -1,4441 +0,0 @@
1
- (function webpackUniversalModuleDefinition(root, factory) {
2
- if(typeof exports === 'object' && typeof module === 'object')
3
- module.exports = factory(require("bwip-js"));
4
- else if(typeof define === 'function' && define.amd)
5
- define(["bwip-js"], factory);
6
- else if(typeof exports === 'object')
7
- exports["@questwork/q-utilities"] = factory(require("bwip-js"));
8
- else
9
- root["@questwork/q-utilities"] = factory(root["bwip-js"]);
10
- })(this, (__WEBPACK_EXTERNAL_MODULE__22__) => {
11
- return /******/ (() => { // webpackBootstrap
12
- /******/ var __webpack_modules__ = ({
13
-
14
- /***/ 22:
15
- /***/ ((module) => {
16
-
17
- module.exports = __WEBPACK_EXTERNAL_MODULE__22__;
18
-
19
- /***/ })
20
-
21
- /******/ });
22
- /************************************************************************/
23
- /******/ // The module cache
24
- /******/ var __webpack_module_cache__ = {};
25
- /******/
26
- /******/ // The require function
27
- /******/ function __webpack_require__(moduleId) {
28
- /******/ // Check if module is in cache
29
- /******/ var cachedModule = __webpack_module_cache__[moduleId];
30
- /******/ if (cachedModule !== undefined) {
31
- /******/ return cachedModule.exports;
32
- /******/ }
33
- /******/ // Create a new module (and put it into the cache)
34
- /******/ var module = __webpack_module_cache__[moduleId] = {
35
- /******/ // no module.id needed
36
- /******/ // no module.loaded needed
37
- /******/ exports: {}
38
- /******/ };
39
- /******/
40
- /******/ // Execute the module function
41
- /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
42
- /******/
43
- /******/ // Return the exports of the module
44
- /******/ return module.exports;
45
- /******/ }
46
- /******/
47
- /************************************************************************/
48
- /******/ /* webpack/runtime/define property getters */
49
- /******/ (() => {
50
- /******/ // define getter functions for harmony exports
51
- /******/ __webpack_require__.d = (exports, definition) => {
52
- /******/ for(var key in definition) {
53
- /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
54
- /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
55
- /******/ }
56
- /******/ }
57
- /******/ };
58
- /******/ })();
59
- /******/
60
- /******/ /* webpack/runtime/hasOwnProperty shorthand */
61
- /******/ (() => {
62
- /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
63
- /******/ })();
64
- /******/
65
- /******/ /* webpack/runtime/make namespace object */
66
- /******/ (() => {
67
- /******/ // define __esModule on exports
68
- /******/ __webpack_require__.r = (exports) => {
69
- /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
70
- /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
71
- /******/ }
72
- /******/ Object.defineProperty(exports, '__esModule', { value: true });
73
- /******/ };
74
- /******/ })();
75
- /******/
76
- /************************************************************************/
77
- var __webpack_exports__ = {};
78
- // ESM COMPAT FLAG
79
- __webpack_require__.r(__webpack_exports__);
80
-
81
- // EXPORTS
82
- __webpack_require__.d(__webpack_exports__, {
83
- ActionRecord: () => (/* reexport */ ActionRecord),
84
- ApiResponse: () => (/* reexport */ ApiResponse),
85
- AwsStsS3Client: () => (/* reexport */ AwsStsS3Client),
86
- KeyValueObject: () => (/* reexport */ keyValueObject_KeyValueObject),
87
- Metadata: () => (/* reexport */ Metadata),
88
- PushEnvelope: () => (/* reexport */ PushEnvelope),
89
- QMeta: () => (/* reexport */ QMeta),
90
- Repo: () => (/* reexport */ Repo),
91
- Service: () => (/* reexport */ Service),
92
- Status: () => (/* reexport */ Status),
93
- StatusDocument: () => (/* reexport */ StatusDocument),
94
- TemplateCompiler: () => (/* reexport */ TemplateCompiler),
95
- TenantAwareEntity: () => (/* reexport */ TenantAwareEntity),
96
- TrackedEntity: () => (/* reexport */ TrackedEntity),
97
- UniqueKeyGenerator: () => (/* reexport */ UniqueKeyGenerator),
98
- authorize: () => (/* reexport */ authorize),
99
- bwipJsHelper: () => (/* reexport */ bwipJsHelper),
100
- calculateAge: () => (/* reexport */ calculateAge),
101
- changeCreatorOwner: () => (/* reexport */ changeCreatorOwner),
102
- concatStringByArray: () => (/* reexport */ concatStringByArray),
103
- convertString: () => (/* reexport */ convertString),
104
- detectControlCharacters: () => (/* reexport */ detectControlCharacters),
105
- downloadFileByUrl: () => (/* reexport */ downloadFileByUrl),
106
- escapeRegex: () => (/* reexport */ escapeRegex),
107
- expressHelper: () => (/* reexport */ expressHelper),
108
- extractEmails: () => (/* reexport */ extractEmails),
109
- formatDate: () => (/* reexport */ formatDate),
110
- generalPost: () => (/* reexport */ generalPost),
111
- getObjectByArr: () => (/* reexport */ getObjectByArr),
112
- getValidation: () => (/* reexport */ getValidation),
113
- getValueByKeys: () => (/* reexport */ getValueByKeys_getValueByKeys),
114
- groupArrayByKey: () => (/* reexport */ groupArrayByKey),
115
- init: () => (/* reexport */ init),
116
- initFromArray: () => (/* reexport */ initFromArray),
117
- initOnlyValidFromArray: () => (/* reexport */ initOnlyValidFromArray),
118
- isConvertibleToNumber: () => (/* reexport */ isConvertibleToNumber),
119
- makeApiResponse: () => (/* reexport */ makeApiResponse),
120
- makeService: () => (/* reexport */ makeService),
121
- mergeArraysByKey: () => (/* reexport */ mergeArraysByKey),
122
- objectHelper: () => (/* reexport */ objectHelper),
123
- pReduce: () => (/* reexport */ pReduce),
124
- padZeros: () => (/* reexport */ padZeros),
125
- printControlCharReport: () => (/* reexport */ printControlCharReport),
126
- replacePlaceholders: () => (/* reexport */ replacePlaceholders),
127
- sanitizeText: () => (/* reexport */ sanitizeText),
128
- shuffleArray: () => (/* reexport */ shuffleArray),
129
- stringFormatter: () => (/* reexport */ stringFormatter),
130
- stringHelper: () => (/* reexport */ stringHelper),
131
- tenantPlugin: () => (/* reexport */ tenantPlugin),
132
- trackingPlugin: () => (/* reexport */ trackingPlugin)
133
- });
134
-
135
- ;// ./lib/helpers/authorize/authorize.js
136
- function authorize({ allowCoordinator, allowOwner, query = {}, required, user }) {
137
- if (!user) {
138
- throw new Error('Require login.')
139
- }
140
- if (!user.permission) {
141
- // throw new Error('You do not have any permission.')
142
- }
143
- const scopes = user.permission.getScopes(required || {}) || []
144
- if (!scopes || scopes.length === 0) {
145
- // throw new Error('You are not allowed in this scope.')
146
- }
147
- if (!scopes.includes('*')) {
148
- query.tenantCode = user.tenantCode
149
- }
150
- if (!scopes.includes('TENANT')) {
151
- query.eventShortCode = user.eventShortCode
152
- }
153
- // if (!scopes.includes('EVENT')) {
154
- // query.eventRegistrationCode = user.eventRegistrationCode
155
- // }
156
- if (allowCoordinator) {
157
- if (query.registrationGroupCode && user.myManagedRegistrationGroupCodes.includes(query.registrationGroupCode)) {
158
- query.__ALLOW_COORDINATOR = true
159
- } else {
160
- if (!scopes.includes('EVENT')) {
161
- query.eventRegistrationCode = user.eventRegistrationCode
162
- }
163
- }
164
- } else {
165
- if (!scopes.includes('EVENT')) {
166
- query.eventRegistrationCode = user.eventRegistrationCode
167
- }
168
- }
169
- if (allowOwner) {
170
- query.__ALLOW_OWNER = true
171
- }
172
- // not good, just use it as example
173
- if (user.hasExcludedFields) {
174
- query.__EXCLUDED_FIELDS = user.getExcludedFields(required)
175
- }
176
- query.__LOGIN_SUBJECT_CODE = user.loginSubjectCode
177
- return query
178
- }
179
-
180
- ;// ./lib/helpers/authorize/index.js
181
-
182
-
183
- // EXTERNAL MODULE: external "bwip-js"
184
- var external_bwip_js_ = __webpack_require__(22);
185
- ;// ./lib/helpers/bwipJsHelper/toDataUrlInBrowser.js
186
-
187
-
188
- function toDataUrlInBrowser({ config = {}, type = 'image/png' }) {
189
- const canvas = document.createElement('canvas')
190
- external_bwip_js_.toCanvas(canvas, {
191
- bcid: 'qrcode',
192
- text: '',
193
- ...config
194
- })
195
- return canvas.toDataURL(type)
196
- }
197
-
198
- /* harmony default export */ const bwipJsHelper_toDataUrlInBrowser = ({
199
- toDataUrlInBrowser
200
- });
201
-
202
-
203
- ;// ./lib/helpers/bwipJsHelper/index.js
204
-
205
-
206
- const bwipJsHelper = {
207
- toDataUrlInBrowser: toDataUrlInBrowser
208
- }
209
-
210
- ;// ./lib/helpers/calculateAge/calculateAge.js
211
- function calculateAge(timestamp, reference) {
212
- const birthDate = new Date(timestamp)
213
- const refDate = reference ? new Date(reference) : new Date()
214
- // Validate inputs
215
- if (isNaN(birthDate.getTime())) {
216
- return null
217
- }
218
- if (isNaN(refDate.getTime())) {
219
- return null
220
- }
221
- if (birthDate > refDate) {
222
- return null
223
- }
224
-
225
- // Calculate raw difference
226
- let age = refDate.getFullYear() - birthDate.getFullYear()
227
- const monthDiff = refDate.getMonth() - birthDate.getMonth()
228
-
229
- // Adjust if birthday hasn't occurred yet this year
230
- if (monthDiff < 0 || (monthDiff === 0 && refDate.getDate() < birthDate.getDate())) {
231
- age--
232
- }
233
-
234
- return age
235
- }
236
-
237
- ;// ./lib/helpers/calculateAge/index.js
238
-
239
-
240
- ;// ./lib/helpers/changeCreatorOwner/changeCreatorOwner.js
241
- function changeCreatorOwner(that, { source, target }) {
242
- if (that.meta) {
243
- if (!that.meta.creator || that.meta.creator === source.getId()) {
244
- that.meta.creator = target.getId()
245
- }
246
- if (!that.meta.owner || that.meta.owner === source.getId()) {
247
- that.meta.owner = target.getId()
248
- }
249
- } else {
250
- if (!that.creator || that.creator === source.getId()) {
251
- that.creator = target.getId()
252
- }
253
- if (!that.owner || that.owner === source.getId()) {
254
- that.owner = target.getId()
255
- }
256
- }
257
- return that
258
- }
259
-
260
- ;// ./lib/helpers/changeCreatorOwner/index.js
261
-
262
-
263
- ;// ./lib/helpers/isConvertibleToNumber/isConvertibleToNumber.js
264
- function isConvertibleToNumber(value) {
265
- return value !== null
266
- && value !== undefined
267
- && typeof value !== 'boolean'
268
- && String(value).trim() !== ''
269
- && !isNaN(Number(value))
270
- }
271
-
272
- ;// ./lib/helpers/getValueByKeys/getValueByKeys.js
273
- // keys can be array or object or string
274
- function getValueByKeys_getValueByKeys(keys, data) {
275
- let _keys = keys
276
- let _data = data
277
- if (typeof keys === 'string') {
278
- _keys = _keys.split('.')
279
- }
280
- if (!Array.isArray(keys) && typeof keys === 'object') {
281
- const { keys: keyArr, obj } = keys
282
- _keys = keyArr
283
- _data = obj
284
- }
285
- if (_keys.length === 0) {
286
- return _data
287
- }
288
- const firstKey = _keys.shift()
289
- if (_data && Object.prototype.hasOwnProperty.call(_data, firstKey)) {
290
- return getValueByKeys_getValueByKeys(_keys, _data[firstKey])
291
- }
292
- if (_data && firstKey) {
293
- if (_keys.length > 0) {
294
- return getValueByKeys_getValueByKeys(_keys, _data[firstKey])
295
- }
296
- return _data[firstKey]
297
- }
298
- return _data
299
- }
300
- /* harmony default export */ const getValueByKeys = ({
301
- getValueByKeys: getValueByKeys_getValueByKeys
302
- });
303
-
304
-
305
- ;// ./lib/helpers/getValueByKeys/index.js
306
-
307
-
308
- ;// ./lib/models/apiResponse/apiResponse.js
309
- class ApiResponse {
310
- constructor(options = {}) {
311
- options = options || {}
312
- this._data = options.data || options._data || []
313
- this.err = options.err
314
- this.isNew = options.isNew || false
315
- this.message = options.message
316
- this.total = options.total || 0
317
- this._instanceBuilder = options._instanceBuilder
318
- }
319
-
320
- static init(options = {}) {
321
- if (options instanceof this) {
322
- return options
323
- }
324
- const instance = new this(options)
325
- return instance
326
- }
327
- static get _classname() {
328
- return 'ApiResponse'
329
- }
330
- static get _superclass() {
331
- return 'ApiResponse'
332
- }
333
-
334
- // getters
335
- get data() {
336
- if (this._instanceBuilder && (typeof this._instanceBuilder === 'function')) {
337
- return this._data.map(this._instanceBuilder)
338
- }
339
- return this._data
340
- }
341
- }
342
-
343
-
344
-
345
- ;// ./lib/models/apiResponse/makeApiResponse.js
346
-
347
-
348
- function makeApiResponse({ repo, result }) {
349
- return ApiResponse.init({
350
- ...result,
351
- _instanceBuilder: (i) => {
352
- return repo.init(i)
353
- }
354
- })
355
- }
356
-
357
-
358
-
359
- ;// ./lib/models/apiResponse/index.js
360
-
361
-
362
-
363
-
364
-
365
- ;// ./lib/models/awsStsS3Client/awsStsS3Client.js
366
- class AwsStsS3Client {
367
- constructor(options) {
368
- options = options || {}
369
-
370
- this.expiration = options.expiration || null
371
- this.s3Client = options.s3Client || null
372
- this.getIdToken = options.getIdToken
373
- this.region = options.region || 'ap-east-1'
374
- this.roleArn = options.roleArn
375
- this.roleSessionName = options.roleSessionName || 'web-identity-session'
376
- this.durationSession = options.durationSession || 3600
377
- this.awsClientSts = options.awsClientSts
378
- this.awsClientS3 = options.awsClientS3
379
- }
380
-
381
- static dummyData() {
382
- return {
383
- getIdToken: () => 'mock-web-identity-token',
384
- roleArn: 'arn:aws:iam::846252828949:role/oidcS3Jccpa',
385
- awsClientSts: {
386
- STSClient: class {},
387
- AssumeRoleWithWebIdentityCommand: class {}
388
- },
389
- awsClientS3: {
390
- S3Client: class {},
391
- PutObjectCommand: class {},
392
- GetObjectCommand: class {},
393
- DeleteObjectCommand: class {}
394
- }
395
- }
396
- }
397
-
398
- static init(options = {}) {
399
- if (options instanceof this) {
400
- return options
401
- }
402
- try {
403
- const instance = new this(options)
404
- if (!instance.isValid) {
405
- return null
406
- }
407
- return instance
408
- } catch (error) {
409
- return null
410
- }
411
- }
412
-
413
- get isExpired() {
414
- if (!this.expiration)
415
- return true
416
- const now = new Date()
417
- const bufferMs = 1 * 60 * 1000 // 一分钟缓冲
418
- return now >= new Date(this.expiration.getTime() - bufferMs)
419
- }
420
-
421
- get isValid() {
422
- if (!this.getIdToken) {
423
- throw new Error('Missing required configuration: getIdToken function')
424
- }
425
- if (!this.roleArn) {
426
- throw new Error('Missing required configuration: roleArn')
427
- }
428
- if (!this.awsClientSts) {
429
- throw new Error('Missing required AWS awsClientSts client configuration')
430
- }
431
- if (!this.awsClientSts.STSClient) {
432
- throw new Error('Missing STSClient in AWS awsClientSts client configuration')
433
- }
434
- if (!this.awsClientSts.AssumeRoleWithWebIdentityCommand) {
435
- throw new Error('Missing AssumeRoleWithWebIdentityCommand in AWS awsClientSts client configuration')
436
- }
437
- if (!this.awsClientS3) {
438
- throw new Error('Missing required AWS awsClientS3 client configuration')
439
- }
440
-
441
- const requiredS3Components = [
442
- 'S3Client',
443
- 'PutObjectCommand',
444
- 'GetObjectCommand',
445
- 'DeleteObjectCommand'
446
- ]
447
-
448
- for (const component of requiredS3Components) {
449
- if (!this.awsClientS3[component]) {
450
- throw new Error(`Missing ${component} in AWS awsClientS3 client configuration`)
451
- }
452
- }
453
-
454
- return true
455
- }
456
-
457
- async refreshCredentials() {
458
- try {
459
- const webIdentityToken = await this.getIdToken()
460
- if (!webIdentityToken) {
461
- throw new Error('getIdToken function returned empty or invalid token')
462
- }
463
-
464
- const stsClient = new this.awsClientSts.STSClient({ region: this.region })
465
-
466
- const stsResponse = await stsClient.send(
467
- new this.awsClientSts.AssumeRoleWithWebIdentityCommand({
468
- RoleArn: this.roleArn,
469
- RoleSessionName: this.roleSessionName,
470
- WebIdentityToken: await this.getIdToken(),
471
- DurationSeconds: this.durationSession,
472
- })
473
- )
474
-
475
- const credentials = stsResponse.Credentials
476
- if (!credentials) {
477
- throw new Error('No credentials returned from awsClientSts')
478
- }
479
-
480
- this.expiration = credentials.Expiration
481
-
482
- this.s3Client = new this.awsClientS3.S3Client({
483
- region: this.region,
484
- credentials: {
485
- accessKeyId: credentials.AccessKeyId,
486
- secretAccessKey: credentials.SecretAccessKey,
487
- sessionToken: credentials.SessionToken,
488
- }
489
- })
490
-
491
- return this
492
- } catch (error) {
493
- throw new Error(`Failed to refresh credentials: ${error.message}`)
494
- }
495
- }
496
-
497
- async getS3Client() {
498
- if (this.isExpired || !this.s3Client) {
499
- await this.refreshCredentials()
500
- }
501
- return this.s3Client
502
- }
503
-
504
- async putObject(params) {
505
- try {
506
- const client = await this.getS3Client()
507
- const command = new this.awsClientS3.PutObjectCommand(params)
508
- await client.send(command)
509
- const fileArr = params.Key.split('/')
510
- return {
511
- url: `https://s3.${this.region}.amazonaws.com/${params.Bucket}/${params.Key}`,
512
- filename: fileArr.pop(),
513
- folder: params.Bucket,
514
- subFolders: fileArr
515
- }
516
- } catch (error) {
517
- throw new Error(`Failed to put object: ${error.message}`)
518
- }
519
- }
520
-
521
- async getObject(params) {
522
- try {
523
- const client = await this.getS3Client()
524
- const command = new this.awsClientS3.GetObjectCommand(params)
525
- const response = await client.send(command)
526
- return {
527
- body: response.Body,
528
- contentType: response.ContentType,
529
- lastModified: response.LastModified,
530
- contentLength: response.ContentLength,
531
- }
532
- } catch (error) {
533
- throw new Error(`Failed to get object: ${error.message}`)
534
- }
535
- }
536
-
537
- async deleteObject(params) {
538
- try {
539
- const client = await this.getS3Client()
540
- const command = new this.awsClientS3.DeleteObjectCommand(params)
541
- await client.send(command)
542
- return true
543
- } catch (error) {
544
- throw new Error(`Failed to delete object: ${error.message}`)
545
- }
546
- }
547
- }
548
-
549
-
550
-
551
- ;// ./lib/models/awsStsS3Client/index.js
552
-
553
-
554
-
555
-
556
- ;// ./lib/helpers/objectHelper/objectHelper.js
557
- const objectHelper = {
558
- get(obj, path) {
559
- const parts = path.split('.')
560
- return parts.reduce((acc, part) => {
561
- if (part.endsWith('[]')) {
562
- // 处理数组遍历
563
- const key = part.slice(0, -2) // 去掉 '[]' 得到属性名
564
- if (Array.isArray(acc[key])) {
565
- return acc[key] // 返回整个数组
566
- }
567
- return [] // 如果不是数组,返回空数组
568
- }
569
- if (part.includes('[') && part.includes(']')) {
570
- // 处理数组索引
571
- const arrayMatch = part.match(/(\w+)\[(\d+)\]/)
572
- if (arrayMatch) {
573
- const key = arrayMatch[1]
574
- const index = arrayMatch[2]
575
- return acc && acc[key] && acc[key][index]
576
- }
577
- } else if (acc && Array.isArray(acc)) {
578
- // 如果当前值是数组,提取每个对象的指定属性
579
- return acc.map((item) => item[part])
580
- } else {
581
- // 处理普通属性
582
- return acc && acc[part]
583
- }
584
- }, obj)
585
- },
586
- isPlainObject,
587
- merge,
588
- set(obj, path, value) {
589
- const parts = path.split('.')
590
- let current = obj
591
-
592
- // 处理所有中间部分
593
- for (let i = 0; i < parts.length - 1; i++) {
594
- const part = parts[i]
595
- let key, index
596
-
597
- // 检查是否是数组索引格式,如key[0]
598
- const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/)
599
- if (arrayMatch) {
600
- key = arrayMatch[1]
601
- index = Number.parseInt(arrayMatch[2], 10)
602
- // 确保当前层级的数组存在
603
- if (!current[key] || !Array.isArray(current[key])) {
604
- current[key] = []
605
- }
606
- // 扩展数组到足够大
607
- while (current[key].length <= index) {
608
- current[key].push(undefined)
609
- }
610
- // 如果当前位置未定义或为null,初始化为对象
611
- if (current[key][index] == null) {
612
- current[key][index] = {}
613
- }
614
- current = current[key][index]
615
- } else {
616
- // 处理普通属性
617
- if (!current[part]) {
618
- current[part] = {}
619
- }
620
- current = current[part]
621
- }
622
- }
623
-
624
- // 处理最后一部分
625
- const lastPart = parts[parts.length - 1]
626
- const arrayMatch = lastPart.match(/^(\w+)\[(\d+)\]$/)
627
- if (arrayMatch) {
628
- const key = arrayMatch[1]
629
- const index = Number.parseInt(arrayMatch[2], 10)
630
- // 确保数组存在
631
- if (!current[key] || !Array.isArray(current[key])) {
632
- current[key] = []
633
- }
634
- // 扩展数组到所需索引
635
- while (current[key].length <= index) {
636
- current[key].push(undefined)
637
- }
638
- current[key][index] = value
639
- } else {
640
- current[lastPart] = value
641
- }
642
- }
643
- }
644
-
645
- function isPlainObject(value) {
646
- return (
647
- value !== null
648
- && typeof value === 'object'
649
- && !Array.isArray(value) &&
650
- !(value instanceof Date) &&
651
- !(value instanceof RegExp) &&
652
- // Optional: exclude other built-in objects
653
- Object.prototype.toString.call(value) === '[object Object]'
654
- )
655
- }
656
-
657
- function merge(target, ...sources) {
658
- if (!sources.length)
659
- return target
660
-
661
- const source = sources.shift() // 取出第一个源对象
662
-
663
- if (_isObject(target) && _isObject(source)) {
664
- for (const key in source) {
665
- if (_isObject(source[key])) {
666
- if (!target[key]) {
667
- // 如果目标对象没有该属性,创建一个空对象
668
- target[key] = {}
669
- }
670
- // 递归合并
671
- merge(target[key], source[key])
672
- } else {
673
- // 直接覆盖
674
- target[key] = source[key]
675
- }
676
- }
677
- }
678
-
679
- // 继续合并剩余的源对象
680
- return merge(target, ...sources)
681
- }
682
-
683
- function _isObject(obj) {
684
- return obj && typeof obj === 'object' && !Array.isArray(obj)
685
- }
686
-
687
-
688
-
689
- ;// ./lib/helpers/objectHelper/index.js
690
-
691
-
692
-
693
-
694
- ;// ./lib/models/keyValueObject/keyValueObject.js
695
-
696
-
697
- class keyValueObject_KeyValueObject {
698
- constructor(options = {}) {
699
- options = options || {}
700
- this.key = options.key || null
701
- this.value = (typeof options.value !== 'undefined') ? options.value : ''
702
- }
703
-
704
- // Class methods
705
- static init(options = {}) {
706
- if (options instanceof this) {
707
- return options
708
- }
709
- const instance = new this(options)
710
- return instance.isValid ? instance : null
711
- }
712
- static initFromArray(arr = []) {
713
- if (Array.isArray(arr)) {
714
- return arr.map((a) => this.init(a))
715
- }
716
- return []
717
- }
718
- static initOnlyValidFromArray(arr = []) {
719
- return this.initFromArray(arr).filter((i) => i)
720
- }
721
- static get _classname() {
722
- return 'KeyValueObject'
723
- }
724
- static get _superclass() {
725
- return 'KeyValueObject'
726
- }
727
-
728
- static addItem(arr, key, value) {
729
- arr.push(this.init({ key, value }))
730
- }
731
- static addRecord(arr = [], key, value) {
732
- if (!this.hasKeyValue(arr, key, value)) {
733
- arr.push(this.init({ key, value }))
734
- }
735
- return arr
736
- }
737
- static appendRecord(arr = [], key, value) {
738
- return arr.map((item) => {
739
- if (this.sameKey(item, key)) {
740
- item.value = [...item.value, ...value]
741
- }
742
- return item
743
- })
744
- }
745
- static appendValueArray(arr = [], key, value) {
746
- return arr.map((item) => {
747
- if (this.sameKey(item, key)) {
748
- item.value = [...item.value, ...value]
749
- }
750
- return item
751
- })
752
- }
753
- static foundByKey(arr = [], key) {
754
- const found = arr.find((m) => {
755
- return this.sameKey(m, key)
756
- })
757
- return found || null
758
- }
759
- static foundValueByKey(arr = [], key) {
760
- const found = this.foundByKey(arr, key)
761
- return found ? found.value : null
762
- }
763
- static fromObject(options = {}) {
764
- return Object.keys(options).reduce((acc, key) => {
765
- acc.push(this.init({ key, value: options[key] }))
766
- return acc
767
- }, [])
768
- }
769
- static getValueByKey(arr = [], key) {
770
- return this.foundValueByKey(arr, key)
771
- }
772
- static getMetadataValueByKeyAsArray(arr = [], key) {
773
- const _value = this.getValueByKey(arr, key)
774
- if (!_value) {
775
- return []
776
- }
777
- if (objectHelper.isPlainObject(_value)) {
778
- return Object.keys(_value).reduce((acc, key) => {
779
- acc.push({ key, value: _value[key] })
780
- return acc
781
- }, [])
782
- }
783
- return _value
784
- }
785
- static getValueByKeyFromArray(arr = [], key) {
786
- if (arr.length === 0) {
787
- return null
788
- }
789
- const firstArr = arr.shift()
790
- const found = firstArr.find((i) => {
791
- return this.sameKey(i, key)
792
- })
793
- if (found && found.value) {
794
- return found.value
795
- }
796
- return this.getValueByKeyFromArray(arr, key)
797
- }
798
- static getValuesByKey(arr = [], key) {
799
- return arr.reduce((acc, item) => {
800
- if (this.sameKey(item, key)) {
801
- acc.push(item.value)
802
- }
803
- return acc
804
- }, [])
805
- }
806
- static hasKeyValue(arr = [], key, value) {
807
- if (typeof value === 'undefined') {
808
- return arr.filter((item) => this.sameKey(item, key)).length > 0
809
- }
810
- return arr.filter((item) => (this.sameKey(item, key) && _isSame(item.value, value))).length > 0
811
- }
812
- static insertOrUpdateRecord(arr = [], key, value) {
813
- let copy = [...arr]
814
- if (!this.hasKeyValue(arr, key)) {
815
- copy.push(this.init({ key, value }))
816
- } else {
817
- copy = this.updateRecord(arr, key, value)
818
- }
819
- return copy
820
- }
821
- static keys(arr = []) {
822
- if (Array.isArray(arr)) {
823
- return arr.reduce((acc, item) => {
824
- acc.push(item.key)
825
- return acc
826
- }, [])
827
- }
828
- return []
829
- }
830
- static merge(toArr, fromArr) {
831
- (fromArr || []).map((from) => {
832
- const found = toArr.find((to) => {
833
- return to.key === from.key
834
- })
835
- if (found) {
836
- found.value = _mergeValues(from.value, found.value)
837
- } else {
838
- toArr.push(from)
839
- }
840
- })
841
- return toArr
842
- }
843
- static removeByKey(arr, key) {
844
- return arr.reduce((acc, item) => {
845
- if (!this.sameKey(item, key)) {
846
- acc.push(item)
847
- }
848
- return acc
849
- }, [])
850
- }
851
- static sameKey(item, key) {
852
- if (item) {
853
- return _isSame(item.key, key)
854
- }
855
- return false
856
- }
857
- static toObject(arr = []) {
858
- if (Array.isArray(arr)) {
859
- return arr.reduce((acc, item) => {
860
- acc[item.key] = item.value
861
- return acc
862
- }, {})
863
- }
864
- return {}
865
- }
866
- static toString(arr = [], delimiter = '; ') {
867
- if (Array.isArray(arr)) {
868
- return arr.reduce((acc, item) => {
869
- acc.push(`${item.key}: ${item.value}`)
870
- return acc
871
- }, []).join(delimiter)
872
- }
873
- return ''
874
- }
875
- static updateRecord(arr = [], key, value) {
876
- return arr.map((item) => {
877
- if (this.sameKey(item, key)) {
878
- return {
879
- ...item,
880
- value
881
- }
882
- }
883
- return item
884
- })
885
- }
886
- static updateOrInsertRecord(arr = [], key, value) {
887
- return this.insertOrUpdateRecord(arr, key, value)
888
- }
889
- static updateRecordsFromArray(arr = [], updateArr = []) {
890
- if (Array.isArray(arr) && Array.isArray(updateArr)) {
891
- const obj1 = this.toObject(arr)
892
- const obj2 = this.toObject(updateArr)
893
- return this.fromObject({
894
- ...obj1,
895
- ...obj2
896
- })
897
- }
898
- return []
899
- }
900
- static values(arr = []) {
901
- if (Array.isArray(arr)) {
902
- return arr.reduce((acc, item) => {
903
- acc.push(item.value)
904
- return acc
905
- }, [])
906
- }
907
- return []
908
- }
909
-
910
- // getters
911
- get isValid() {
912
- return !!this.key
913
- }
914
-
915
- get toObject() {
916
- const obj = {}
917
- if (this.isValid) {
918
- obj[this.key] = this.value
919
- }
920
- return obj
921
- }
922
- }
923
-
924
- function _mergeValues(existingValue, newValue) {
925
- if (existingValue === undefined)
926
- return newValue
927
-
928
- // Handle arrays by concatenating
929
- if (Array.isArray(existingValue) && Array.isArray(newValue)) {
930
- return [...new Set([...existingValue, ...newValue])]
931
- }
932
-
933
- // Handle objects by merging
934
- if (typeof existingValue === 'object' && typeof newValue === 'object'
935
- && !Array.isArray(existingValue) && !Array.isArray(newValue)) {
936
- return { ...existingValue, ...newValue }
937
- }
938
-
939
- // // Handle numbers by adding
940
- // if (typeof existingValue === 'number' && typeof newValue === 'number') {
941
- // return existingValue
942
- // }
943
-
944
- // // Handle strings by concatenating
945
- // if (typeof existingValue === 'string' && typeof newValue === 'string') {
946
- // return existingValue
947
- // }
948
-
949
- // Default: use the new value
950
- return newValue
951
- }
952
-
953
- function _isSame(key1, key2) {
954
- return key1 === key2
955
- }
956
-
957
-
958
-
959
- ;// ./lib/models/keyValueObject/index.js
960
-
961
-
962
-
963
-
964
- ;// ./lib/helpers/stringFormatter/stringFormatter.js
965
- function stringFormatter(str, delimiter = '_') {
966
- if (str === null || typeof str === 'undefined' || typeof str.toString === 'undefined') {
967
- return null
968
- }
969
- return str.toString()
970
- .trim()
971
- .toUpperCase()
972
- .replace('-', delimiter)
973
- .replace(' ', delimiter)
974
- }
975
-
976
-
977
-
978
- ;// ./lib/models/metadata/metadata.js
979
-
980
-
981
-
982
- const DELIMITER = '_'
983
-
984
- class Metadata extends keyValueObject_KeyValueObject {
985
- static init(options = {}) {
986
- if (options instanceof this) {
987
- return options
988
- }
989
- const instance = new this({
990
- ...options,
991
- key: stringFormatter(options.key, DELIMITER),
992
- })
993
- return instance.isValid ? instance : null
994
- }
995
- static get _classname() {
996
- return 'Metadata'
997
- }
998
-
999
- static merge(toArr, fromArr) {
1000
- (fromArr || []).map((from) => {
1001
- const found = toArr.find((to) => {
1002
- return metadata_isSame(to.key, from.key)
1003
- })
1004
- if (found) {
1005
- found.value = metadata_mergeValues(from.value, found.value)
1006
- } else {
1007
- toArr.push(from)
1008
- }
1009
- })
1010
- return toArr
1011
- }
1012
- static sameKey(item, key) {
1013
- return metadata_isSame(item.key, key)
1014
- }
1015
- }
1016
-
1017
- function metadata_isSame(key1, key2) {
1018
- return stringFormatter(key1, DELIMITER) === stringFormatter(key2, DELIMITER)
1019
- }
1020
-
1021
- function metadata_mergeValues(existingValue, newValue) {
1022
- if (existingValue === undefined)
1023
- return newValue
1024
-
1025
- // Handle arrays by concatenating
1026
- if (Array.isArray(existingValue) && Array.isArray(newValue)) {
1027
- return [...new Set([...existingValue, ...newValue])]
1028
- }
1029
-
1030
- // Handle objects by merging
1031
- if (typeof existingValue === 'object' && typeof newValue === 'object'
1032
- && !Array.isArray(existingValue) && !Array.isArray(newValue)) {
1033
- return { ...existingValue, ...newValue }
1034
- }
1035
-
1036
- // // Handle numbers by adding
1037
- // if (typeof existingValue === 'number' && typeof newValue === 'number') {
1038
- // return existingValue
1039
- // }
1040
-
1041
- // // Handle strings by concatenating
1042
- // if (typeof existingValue === 'string' && typeof newValue === 'string') {
1043
- // return existingValue
1044
- // }
1045
-
1046
- // Default: use the new value
1047
- return newValue
1048
- }
1049
-
1050
-
1051
-
1052
- ;// ./lib/models/metadata/index.js
1053
-
1054
-
1055
-
1056
-
1057
- ;// ./lib/models/trackedEntity/trackedEntity.js
1058
-
1059
-
1060
- class TrackedEntity {
1061
- constructor(options = {}) {
1062
- options = options || {}
1063
- const timestamp = Date.now()
1064
- this.meta = {
1065
- active: options.meta?.active ?? options.active ?? true,
1066
- created: options.meta?.created ?? (options.created
1067
- ? new Date(options.created).getTime()
1068
- : timestamp),
1069
- creator: options.meta?.creator ?? options.creator ?? '',
1070
- deleted: options.meta?.deleted ?? options.deleted ?? false,
1071
- modified: options.meta?.modified ?? (options.modified
1072
- ? new Date(options.modified).getTime()
1073
- : timestamp),
1074
- owner: options.meta?.owner ?? options.owner ?? '',
1075
- }
1076
-
1077
- // if (trackFlat) {
1078
- // Object.assign(this, _tracking)
1079
- // } else {
1080
- // this.meta = { ..._tracking, ...options.meta }
1081
- // }
1082
- }
1083
-
1084
- // Class methods
1085
- static get _classname() {
1086
- return 'TrackedEntity'
1087
- }
1088
- static get _superclass() {
1089
- return 'TrackedEntity'
1090
- }
1091
-
1092
- static init(options = {}) {
1093
- return init(this, options)
1094
- }
1095
- static initFromArray(arr = []) {
1096
- return initFromArray(this, arr)
1097
- }
1098
- static initOnlyValidFromArray(arr = []) {
1099
- return initOnlyValidFromArray(this, arr)
1100
- }
1101
- // static nest(entity) {
1102
- // const { active, created, creator, deleted, modified, owner, ...rest } = entity
1103
- // return { ...rest, meta: { active, created, creator, deleted, modified, owner } }
1104
- // }
1105
-
1106
- // getters
1107
- get __valid() {
1108
- return {}
1109
- }
1110
- get isValid() {
1111
- return !!this
1112
- }
1113
- get active() {
1114
- return this.meta?.active ?? this.active
1115
- }
1116
- get created() {
1117
- return this.meta?.created ?? this.created
1118
- }
1119
- get creator() {
1120
- return this.meta?.creator ?? this.creator
1121
- }
1122
- get deleted() {
1123
- return this.meta?.deleted ?? this.deleted
1124
- }
1125
- get modified() {
1126
- return this.meta?.modified ?? this.modified
1127
- }
1128
- get owner() {
1129
- return this.meta?.owner ?? this.owner
1130
- }
1131
- changeCreatorOwner({ source, target }) {
1132
- return changeCreatorOwner(this, { source, target }).setModified()
1133
- }
1134
- delete() {
1135
- return this.setDeleted()
1136
- }
1137
- setActive() {
1138
- if (this.meta) {
1139
- this.meta.active = true
1140
- } else {
1141
- this.active = true
1142
- }
1143
- return this
1144
- }
1145
- setDeleted() {
1146
- if (this.meta) {
1147
- this.meta.deleted = true
1148
- } else {
1149
- this.deleted = true
1150
- }
1151
- return this
1152
- }
1153
- setModified() {
1154
- const timestamp = Date.now()
1155
- if (this.meta) {
1156
- this.meta.modified = timestamp
1157
- } else {
1158
- this.modified = timestamp
1159
- }
1160
- return this
1161
- }
1162
- setOwner(owner) {
1163
- if (!owner) {
1164
- return this
1165
- }
1166
- if (this.meta) {
1167
- this.meta.owner = owner
1168
- } else {
1169
- this.owner = owner
1170
- }
1171
- return this
1172
- }
1173
- unsetActive() {
1174
- if (this.meta) {
1175
- this.meta.active = false
1176
- } else {
1177
- this.active = false
1178
- }
1179
- return this
1180
- }
1181
- unsetDeleted() {
1182
- if (this.meta) {
1183
- this.meta.deleted = false
1184
- } else {
1185
- this.deleted = false
1186
- }
1187
- return this
1188
- }
1189
-
1190
- update(update) {
1191
- if (update.meta) {
1192
- this.meta = { ...this.meta, ...update.meta }
1193
- }
1194
- return this.setModified()
1195
- }
1196
- }
1197
-
1198
- ;// ./lib/models/trackedEntity/index.js
1199
-
1200
- // Explicit named export (optional)
1201
-
1202
- ;// ./lib/models/pushEnvelope/pushEnvelope.js
1203
-
1204
-
1205
-
1206
-
1207
-
1208
- class PushEnvelope extends TrackedEntity {
1209
- constructor(options) {
1210
- options = options || {}
1211
- super(options)
1212
-
1213
- this.id = options.id
1214
- this.body = options.body
1215
- this.data = options.data
1216
- this.dirty = options.dirty
1217
- this.metadata = Metadata.initOnlyValidFromArray(options.metadata)
1218
- this.remarks = keyValueObject_KeyValueObject.initOnlyValidFromArray(options.remarks)
1219
- this.threadID = options.threadID
1220
- this.title = options.title
1221
- }
1222
- static get _classname() {
1223
- return 'PushEnvelope'
1224
- }
1225
- static get _superclass() {
1226
- return 'PushEnvelope'
1227
- }
1228
- static init(options = {}) {
1229
- return init(this, options)
1230
- }
1231
-
1232
- get _classname() {
1233
- return 'PushEnvelope'
1234
- }
1235
-
1236
- get _superclass() {
1237
- return 'PushEnvelope'
1238
- }
1239
-
1240
- get isValid() {
1241
- return super.isValid && this.data
1242
- }
1243
- }
1244
-
1245
- ;// ./lib/models/pushEnvelope/index.js
1246
-
1247
-
1248
- ;// ./lib/models/qMeta/qMeta.js
1249
-
1250
-
1251
- const updateAllowedProps = [
1252
- 'attributes',
1253
- 'ref'
1254
- ]
1255
-
1256
- class QMeta {
1257
- constructor(options = {}) {
1258
- options = options || {}
1259
- this.attributes = keyValueObject_KeyValueObject.initOnlyValidFromArray(options.attributes)
1260
- this.ref = options.ref || {}
1261
- }
1262
-
1263
- static get _classname() {
1264
- return 'QMeta'
1265
- }
1266
- static get _superclass() {
1267
- return 'QMeta'
1268
- }
1269
-
1270
- // Class methods
1271
- static init(options = {}) {
1272
- if (options instanceof QMeta) {
1273
- return options
1274
- }
1275
- return new QMeta(options)
1276
- }
1277
-
1278
- // instance methods
1279
- addAttribute(obj) {
1280
- const kvObject = keyValueObject_KeyValueObject.init(obj)
1281
- if (!kvObject) {
1282
- throw new Error('invalid meta attribute')
1283
- }
1284
- this.attributes.push(kvObject)
1285
- return this
1286
- }
1287
-
1288
- update(obj) {
1289
- Object.keys(obj).forEach((key) => {
1290
- if (updateAllowedProps.includes(key)) {
1291
- if (key === 'attributes') {
1292
- this[key] = keyValueObject_KeyValueObject.initOnlyValidFromArray(obj[key])
1293
- } else {
1294
- this[key] = obj[key]
1295
- }
1296
- }
1297
- })
1298
- return this
1299
- }
1300
- }
1301
-
1302
-
1303
-
1304
- ;// ./lib/models/qMeta/index.js
1305
-
1306
-
1307
-
1308
-
1309
- ;// ./lib/models/repo/repo.js
1310
-
1311
-
1312
- class Repo {
1313
- constructor(options) {
1314
- options = options || {}
1315
- this.model = options.model
1316
- this._sharedOptions = options._sharedOptions // { session: this.dbTransaction }
1317
- this._queryOptions = options._queryOptions
1318
- this._saveOptions = options._saveOptions
1319
- this._Class = options._constructor && options._constructor._Class
1320
- ? options._constructor._Class
1321
- : null
1322
- }
1323
- static init(options = {}) {
1324
- return init(this, options)
1325
- }
1326
- static get _classname() {
1327
- return 'Repo'
1328
- }
1329
- static get _superclass() {
1330
- return 'Repo'
1331
- }
1332
-
1333
- get _classname() {
1334
- return 'Repo'
1335
- }
1336
-
1337
- get _superclass() {
1338
- return 'Repo'
1339
- }
1340
-
1341
- get isValid() {
1342
- return this.model
1343
- && (typeof this.model.deleteOne === 'function')
1344
- && (typeof this.model.findAll === 'function')
1345
- && (typeof this.model.saveOne === 'function')
1346
- }
1347
-
1348
- get queryOptions() {
1349
- return {
1350
- ...this._sharedOptions,
1351
- ...this._queryOptions,
1352
- }
1353
- }
1354
-
1355
- get saveOptions() {
1356
- return {
1357
- ...this._sharedOptions,
1358
- ...this._saveOptions,
1359
- }
1360
- }
1361
-
1362
- init(options) {
1363
- if (this._Class && typeof this._Class.init === 'function') {
1364
- return this._Class.init(options)
1365
- }
1366
- return options
1367
- }
1368
-
1369
- async deleteOne({ id }) {
1370
- try {
1371
- const result = await this.model.deleteOne({ _id: id })
1372
- return {
1373
- ...result, // { message: 'ok', total }
1374
- isNew: false,
1375
- data: []
1376
- }
1377
- } catch (err) {
1378
- throw err
1379
- }
1380
- }
1381
-
1382
- // systemLog is optional
1383
- findAll({ query, systemLog }) {
1384
- const log = _makeLog({
1385
- systemLog,
1386
- label: 'REPO_READ',
1387
- message: `fn ${this._classname}.prototype.findAll`,
1388
- input: [{ query: { ...query }, systemLog: { ...systemLog } }]
1389
- })
1390
- return new Promise((resolve, reject) => {
1391
- this.model.findAll(query, this.queryOptions, (err, data, total) => {
1392
- if (err) {
1393
- log({ level: 'warn', output: err.toString() })
1394
- reject(err)
1395
- } else {
1396
- const result = {
1397
- isNew: false,
1398
- data,
1399
- total: total || data.length
1400
- }
1401
- log({ level: 'info', output: { ...result } })
1402
- resolve(result)
1403
- }
1404
- })
1405
- })
1406
- }
1407
-
1408
- findOne({ query, systemLog }) {
1409
- const log = _makeLog({
1410
- systemLog,
1411
- label: 'REPO_READ',
1412
- message: `fn ${this._classname}.prototype.findOne`,
1413
- input: [{ query: { ...query }, systemLog: { ...systemLog } }]
1414
- })
1415
- return new Promise((resolve, reject) => {
1416
- this.model.findAll(query, this.queryOptions, (err, data) => {
1417
- if (err) {
1418
- reject(err)
1419
- } else if (data.length === 1) {
1420
- const result = {
1421
- isNew: false,
1422
- data,
1423
- total: 1
1424
- }
1425
- log({ level: 'info', output: { ...result } })
1426
- resolve(result)
1427
- } else if (data.length === 0) {
1428
- reject(new Error('record not found'))
1429
- } else {
1430
- reject(new Error('more than one is found'))
1431
- }
1432
- })
1433
- })
1434
- .catch((err) => {
1435
- log({ level: 'warn', output: err.toString() })
1436
- throw err
1437
- })
1438
- }
1439
-
1440
- saveAll({ config = {}, docs, systemLog }) {
1441
- let isNew
1442
- const log = _makeLog({
1443
- systemLog,
1444
- label: 'REPO_WRITE',
1445
- message: `fn ${this._classname}.prototype.saveAll`,
1446
- input: [{ config, docs: [...docs], systemLog: { ...systemLog } }]
1447
- })
1448
- const promise = typeof this.model.saveAll === 'function'
1449
- ? this.model.saveAll({ config, docs })
1450
- : Promise.all(docs.map(async (doc) => {
1451
- if (doc) {
1452
- const result = await this.saveOne({ config, doc })
1453
- isNew = result.isNew
1454
- const _data = result._data || result.data
1455
- return _data[0]
1456
- }
1457
- return null
1458
- }))
1459
- return promise.then((savedData) => {
1460
- if (savedData.length !== 1)
1461
- isNew = null
1462
- const result = {
1463
- data: savedData,
1464
- isNew,
1465
- total: savedData.length
1466
- }
1467
- log({ level: 'info', output: { ...result } })
1468
- return result
1469
- }).catch((err) => {
1470
- log({ level: 'warn', output: err.toString() })
1471
- throw err
1472
- })
1473
- }
1474
-
1475
- saveOne({ config = {}, doc, systemLog }) {
1476
- const log = _makeLog({
1477
- systemLog,
1478
- label: 'REPO_WRITE',
1479
- message: `fn ${this._classname}.prototype.saveOne`,
1480
- input: [{ config, doc: { ...doc }, systemLog: { ...systemLog } }]
1481
- })
1482
- const saveOptions = {
1483
- ...this.saveOptions,
1484
- ...config,
1485
- }
1486
- return new Promise((resolve, reject) => {
1487
- this.model.saveOne(doc, saveOptions, (err, result) => {
1488
- if (err) {
1489
- log({ level: 'warn', output: err.toString() })
1490
- reject(err)
1491
- } else {
1492
- log({ level: 'info', output: { ...result } })
1493
- resolve(result)
1494
- }
1495
- })
1496
- })
1497
- }
1498
- }
1499
-
1500
- function _makeLog({ systemLog, label, message: message1, input } = {}) {
1501
- return ({ level, messgae: massage2, output } = {}) => {
1502
- if (systemLog && systemLog.systemLogHelper) {
1503
- systemLog.systemLogHelper.log({
1504
- batchId: systemLog.batchId,
1505
- label,
1506
- level,
1507
- message: massage2 || message1,
1508
- data: {
1509
- payload: {
1510
- input,
1511
- output
1512
- }
1513
- }
1514
- })
1515
- }
1516
- }
1517
- }
1518
-
1519
-
1520
-
1521
- ;// ./lib/models/repo/index.js
1522
-
1523
-
1524
-
1525
-
1526
- ;// ./lib/models/service/service.js
1527
-
1528
-
1529
-
1530
- class Service {
1531
- constructor({ repo }) {
1532
- this.repo = repo
1533
- }
1534
-
1535
- static get _classname() {
1536
- return 'Service'
1537
- }
1538
- static get _superclass() {
1539
- return 'Service'
1540
- }
1541
-
1542
- async deleteOne({ id }) {
1543
- const result = await this.repo.deleteOne({ id })
1544
- return makeApiResponse({
1545
- repo: this.repo,
1546
- result
1547
- })
1548
- // return this.repo.delete({ id })
1549
- // .catch(() => {
1550
- // throw new Error(`Not found for query: ${id}`)
1551
- // })
1552
- }
1553
-
1554
- async findAll({ query = {}, systemLog } = {}) {
1555
- const result = await this.repo.findAll({ query, systemLog })
1556
- return makeApiResponse({
1557
- repo: this.repo,
1558
- result
1559
- })
1560
- }
1561
-
1562
- async findOne({ query = {}, systemLog } = {}) {
1563
- const result = await this.repo.findOne({ query, systemLog })
1564
- return makeApiResponse({
1565
- repo: this.repo,
1566
- result
1567
- })
1568
- }
1569
-
1570
- init(options) {
1571
- return this.repo.init(options)
1572
- }
1573
- initFromArray(arr = []) {
1574
- if (Array.isArray(arr)) {
1575
- return arr.map((a) => this.init(a))
1576
- }
1577
- return []
1578
- }
1579
- initOnlyValidFromArray(arr = []) {
1580
- return this.initFromArray(arr).filter((i) => i)
1581
- }
1582
-
1583
- async saveAll({ config = {}, docs = [], systemLog } = {}) {
1584
- const copies = docs.map((doc) => {
1585
- return config.skipInit ? doc : this.init(doc)
1586
- })
1587
- const result = await this.repo.saveAll({ config, docs: copies, systemLog })
1588
- return makeApiResponse({
1589
- repo: this.repo,
1590
- result
1591
- })
1592
- }
1593
-
1594
- // set skipInit to true if we want to use POST for query
1595
- async saveOne({ config = {}, doc = {}, systemLog } = {}) {
1596
- const copy = config.skipInit ? doc : this.init(doc)
1597
- if (copy) {
1598
- const result = await this.repo.saveOne({ config, doc: copy, systemLog })
1599
- return makeApiResponse({
1600
- repo: this.repo,
1601
- result
1602
- })
1603
- }
1604
- return {
1605
- isNew: null,
1606
- data: [],
1607
- err: new Error('doc is not a valid instance')
1608
- }
1609
- }
1610
- }
1611
-
1612
- function makeService({ repo }) {
1613
- if (repo === undefined) {
1614
- throw new Error('repo is required.')
1615
- }
1616
- if (repo._superclass !== Repo._superclass) {
1617
- throw new Error('repo is not an instance of Repo.')
1618
- }
1619
- return new Service({ repo })
1620
- }
1621
-
1622
-
1623
-
1624
- ;// ./lib/models/service/index.js
1625
-
1626
-
1627
-
1628
-
1629
- ;// ./lib/models/status/actionRecord.js
1630
-
1631
-
1632
- class ActionRecord {
1633
- constructor(options) {
1634
- options = options || {}
1635
-
1636
- const { _Actor } = options._constructor || {}
1637
- this._Actor = _Actor
1638
-
1639
- this._actor = options._actor
1640
-
1641
- this.actorCode = typeof options === 'number' ? null : (options.actorCode || null)
1642
- this.timestamp = typeof options === 'number' ? options : (options.timestamp || null)
1643
- }
1644
-
1645
- static get _classname() {
1646
- return 'ActionRecord'
1647
- }
1648
- static get _superclass() {
1649
- return 'ActionRecord'
1650
- }
1651
- static dummyData() {
1652
- return {
1653
- timestamp: (new Date()).valueOf(),
1654
- }
1655
- }
1656
- static init(options = {}) {
1657
- return init(this, options)
1658
- }
1659
-
1660
- get _classname() {
1661
- return 'ActionRecord'
1662
- }
1663
-
1664
- get _superclass() {
1665
- return 'ActionRecord'
1666
- }
1667
-
1668
- get actor() {
1669
- return this._Actor && typeof this._Actor.init === 'function' ? this._Actor.init(this._actor) : this._actor
1670
- }
1671
-
1672
- get isValid() {
1673
- return !!this.timestamp
1674
- }
1675
-
1676
- update(update) {
1677
- if (typeof update === 'number') {
1678
- this.timestamp = update
1679
- return this
1680
- }
1681
- Object.keys(update).forEach((key) => {
1682
- this[key] = update[key]
1683
- })
1684
- return this
1685
- }
1686
- }
1687
-
1688
- ;// ./lib/models/status/status.js
1689
-
1690
-
1691
-
1692
- const notUpdateAllowedProps = [
1693
- '_ActionRecord',
1694
- 'created',
1695
- // 'statusType'
1696
- ]
1697
-
1698
- class Status {
1699
- constructor(options) {
1700
- options = options || {}
1701
-
1702
- const { _ActionRecord } = options._constructor || {}
1703
- this._ActionRecord = _ActionRecord && (_ActionRecord._superclass === ActionRecord._superclass) ? _ActionRecord : ActionRecord
1704
-
1705
- this.created = this._ActionRecord.init(options.created || { timestamp: (new Date()).valueOf() })
1706
- // this.statusType = options.statusType || 'Status'
1707
- }
1708
-
1709
- static get _classname() {
1710
- return 'Status'
1711
- }
1712
- static get _superclass() {
1713
- return 'Status'
1714
- }
1715
- static dummyData() {
1716
- return {}
1717
- }
1718
- static init(options = {}) {
1719
- return init(this, options)
1720
- }
1721
- static initFromArray(arr = []) {
1722
- return initFromArray(this, arr)
1723
- }
1724
- static initOnlyValidFromArray(arr = []) {
1725
- return initOnlyValidFromArray(this, arr)
1726
- }
1727
-
1728
- get _classname() {
1729
- return 'Status'
1730
- }
1731
- get _superclass() {
1732
- return 'Status'
1733
- }
1734
- get isCreated() {
1735
- return this.created?.timestamp !== null
1736
- }
1737
- get isValid() {
1738
- return !!this
1739
- }
1740
-
1741
- setValue(t, actorCode, key) {
1742
- const timestamp = t || Date.now()
1743
- this[key] = this[key] instanceof this._ActionRecord ? this[key].update({ actorCode, timestamp }) : this._ActionRecord.init({ actorCode, timestamp })
1744
- return this
1745
- }
1746
-
1747
- update(update) {
1748
- Object.keys(update).forEach((key) => {
1749
- if (!notUpdateAllowedProps.includes(key)) {
1750
- this[key] = this[key] instanceof this._ActionRecord ? this[key].update(update[key]) : this._ActionRecord.init(update[key])
1751
- }
1752
- })
1753
- return this
1754
- }
1755
- }
1756
-
1757
- ;// ./lib/models/status/statusDocument.js
1758
-
1759
-
1760
- class StatusDocument extends Status {
1761
- constructor(options) {
1762
- options = options || {}
1763
- super(options)
1764
-
1765
- this.archived = this._ActionRecord.init(options.archived)
1766
- this.completed = this._ActionRecord.init(options.completed)
1767
- this.discarded = this._ActionRecord.init(options.discarded)
1768
- this.drafted = this._ActionRecord.init(options.drafted)
1769
- // this.statusType = 'StatusDocument'
1770
- }
1771
-
1772
- static get _classname() {
1773
- return 'StatusDocument'
1774
- }
1775
- get _classname() {
1776
- return 'StatusDocument'
1777
- }
1778
- get isArchived() {
1779
- return this.created?.timestamp !== null
1780
- }
1781
- get isCompleted() {
1782
- return this.completed?.timestamp !== null
1783
- }
1784
- get isDiscarded() {
1785
- return this.discarded?.timestamp !== null
1786
- }
1787
- get isDrafted() {
1788
- return this.drafted?.timestamp !== null
1789
- }
1790
- get isValid() {
1791
- return super.isValid
1792
- }
1793
- setArchived(value, actorCode) {
1794
- // const timestamp = value || Date.now()
1795
- // this.archived = this.archived instanceof this._ActionRecord ? this.archived.update({ actorCode, timestamp }) : this._ActionRecord.init({ actorCode, timestamp })
1796
- // return this
1797
- return this.setValue(value, actorCode, 'archived')
1798
- }
1799
- setCompleted(value, actorCode) {
1800
- return this.setValue(value, actorCode, 'completed')
1801
- }
1802
- setDiscarded(value, actorCode) {
1803
- return this.setValue(value, actorCode, 'discarded')
1804
- }
1805
- setDrafted(value, actorCode) {
1806
- return this.setValue(value, actorCode, 'drafted')
1807
- }
1808
- }
1809
-
1810
- ;// ./lib/models/status/index.js
1811
-
1812
-
1813
-
1814
-
1815
- ;// ./lib/models/templateCompiler/templateCompilerException.js
1816
- const TEMPLATE_COMPILER_EXCEPTION_TYPE = {
1817
- argumentEmptyException: 'Argument is empty',
1818
- argumentFormatException: 'Incorrect number or format of argument',
1819
- invalidFuntionException: 'Function Name is invalid',
1820
- invalidRegExpException: 'Invalid regular expression',
1821
- isNotAFunctionException: 'Is not a function',
1822
- notExistException: 'Key does not exist',
1823
- resultEmptyException: 'Result is empty',
1824
- resultMoreThanOneException: 'More than one result'
1825
- }
1826
-
1827
- class TemplateCompilerException extends Error {
1828
- constructor(message) {
1829
- super(message)
1830
- this.message = message
1831
- }
1832
- }
1833
-
1834
-
1835
-
1836
- ;// ./lib/models/templateCompiler/constants.js
1837
- const _EMPTY = '_EMPTY'
1838
- const _FN_NAMES = [
1839
- 'concatIf',
1840
- 'divide',
1841
- 'eq',
1842
- 'exec',
1843
- 'filterAll',
1844
- 'filterOne',
1845
- 'formatDate',
1846
- 'get',
1847
- 'gt',
1848
- 'gte',
1849
- 'isEmpty',
1850
- 'isNotEmpty',
1851
- 'join',
1852
- 'lt',
1853
- 'lte',
1854
- 'map',
1855
- 'neq',
1856
- 'removeHtml',
1857
- 'sum',
1858
- 'toLowerCase',
1859
- 'toUpperCase',
1860
- ]
1861
- const _HIDE = '_HIDE'
1862
- const _NOT_EMPTY = '_NOT_EMPTY'
1863
- const _SELF = '_SELF'
1864
- const TAGS_EJS = ['<%=', '%>']
1865
- const TAGS_HANDLEBAR = ['{{', '}}']
1866
-
1867
-
1868
-
1869
- ;// ./lib/models/templateCompiler/helpers/_concatIf.js
1870
-
1871
-
1872
-
1873
-
1874
- function _concatIf(data, args) {
1875
- if (typeof data !== 'string') {
1876
- throw new TemplateCompilerException(`_concatIf: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: the data must be string :${data.join(', ')}`)
1877
- }
1878
- if (args.length !== 3) {
1879
- throw new TemplateCompilerException(`_concatIf: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
1880
- }
1881
- if (data === null || (typeof data === 'undefined')) {
1882
- return null
1883
- }
1884
- const [condition, success, failover] = args
1885
- const validConditions = [_EMPTY, _NOT_EMPTY]
1886
- if (validConditions.includes(condition) || success.length !== 2) {
1887
- throw new TemplateCompilerException(`concatIf: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentEmptyException}: ${condition}, ${success}`)
1888
- }
1889
- if (data === '' && failover.includes(_HIDE)) {
1890
- return ''
1891
- }
1892
- if (data !== '' && (data !== null || data !== undefined) && failover.includes(_HIDE)) {
1893
- return `${success[0]}${data}${success[success.length - 1]}`
1894
- }
1895
- return failover
1896
- }
1897
-
1898
-
1899
-
1900
- ;// ./lib/models/templateCompiler/helpers/_divide.js
1901
- function _divide(value, divisor) {
1902
- try {
1903
- if (Number.isNaN(value)) {
1904
- return value
1905
- }
1906
- return (value / divisor)
1907
- } catch (e) {
1908
- throw e
1909
- }
1910
- }
1911
-
1912
-
1913
-
1914
- ;// ./lib/models/templateCompiler/helpers/_eq.js
1915
-
1916
-
1917
-
1918
-
1919
- function _eq(data, args) {
1920
- if (args.length !== 3) {
1921
- throw new TemplateCompilerException(`eq: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
1922
- }
1923
- if (data === null || (typeof data === 'undefined')) {
1924
- return null
1925
- }
1926
- if (args.includes(_SELF)) {
1927
- args = args.map((arg) => {
1928
- return (arg === _SELF) ? data : arg
1929
- })
1930
- }
1931
- const expected = args[0]
1932
- return data === expected ? args[1] : args[2]
1933
- }
1934
-
1935
-
1936
-
1937
- ;// ./lib/models/templateCompiler/helpers/_exec.js
1938
- function _exec(data, args) {
1939
- try {
1940
- const [methodName, ..._args] = args
1941
- return data[methodName](..._args)
1942
- } catch (e) {
1943
- throw e
1944
- }
1945
- }
1946
-
1947
-
1948
-
1949
- ;// ./lib/models/templateCompiler/helpers/_filterAll.js
1950
-
1951
-
1952
-
1953
- // const DELIMITER = '~~~'
1954
-
1955
- function _filterAll(data, args) {
1956
- try {
1957
- if (!Array.isArray(args) || args.length === 0) {
1958
- throw new TemplateCompilerException(TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentEmptyException)
1959
- }
1960
- if (!Array.isArray(data) || data.length === 0) {
1961
- return []
1962
- }
1963
- if (typeof data[0] === 'object') {
1964
- return _existObject(data, args)
1965
- }
1966
- if (typeof data[0] === 'string' || typeof data[0] === 'number') {
1967
- return _exist(data, args)
1968
- }
1969
- return []
1970
- } catch (e) {
1971
- throw e
1972
- }
1973
- }
1974
-
1975
- function _exist(data, args) {
1976
- const _args = args.flat()
1977
- return data.filter((e) => _args.some((arg) => _performOperation(arg, e)))
1978
- }
1979
-
1980
- function _existObject(data, args) {
1981
- if (args.length === 1) {
1982
- const arg = args[0]
1983
- return data.filter((e) => {
1984
- if (arg.includes('.')) {
1985
- return getValueByKeys_getValueByKeys(arg.split('.'), e)
1986
- }
1987
- return Object.prototype.hasOwnProperty.call(e, arg)
1988
- })
1989
- }
1990
-
1991
- if (args.length > 2) {
1992
- let res = data
1993
- for (let i = 0; i < args.length; i += 2) {
1994
- const group = [args[i], args[i + 1]]
1995
- res = _existObject(res, group)
1996
- }
1997
- return res
1998
- }
1999
-
2000
- const [key, ..._argsArr] = args
2001
- const _args = _argsArr.flat()
2002
- return data.filter((e) => {
2003
- const value = key.includes('.') ? getValueByKeys_getValueByKeys(key.split('.'), e) : e[key]
2004
- return _args.some((arg) => _performOperation(arg, value))
2005
- })
2006
- }
2007
-
2008
- function _performOperation(arg, value) {
2009
- // the arg is undefined
2010
- if (arg === undefined && value === undefined)
2011
- return true
2012
-
2013
- // the arg is null
2014
- if (arg === null && value === null)
2015
- return true
2016
-
2017
- // the arg is boolean
2018
- if (typeof arg === 'boolean') {
2019
- return arg === value
2020
- }
2021
-
2022
- // the arg is blank or *: Blank => Empty, * => Not Empty
2023
- if (arg === '' || arg === '*') {
2024
- // null and undefined are not included in either case
2025
- if (value === null || value === undefined) {
2026
- return false
2027
- }
2028
- if (typeof value === 'string') {
2029
- return arg === '' ? value === '' : value !== ''
2030
- }
2031
- if (Array.isArray(value)) {
2032
- return arg === '' ? value.length === 0 : value.length !== 0
2033
- }
2034
- return arg !== ''
2035
- }
2036
-
2037
- // the arg is alphabetic or number
2038
- if (_isPureStringOrNumber(arg)) {
2039
- return arg === value
2040
- }
2041
-
2042
- // the arg is array of [] or [*]: [] => Empty, [*] => Not Empty
2043
- if (arg.startsWith('[') && arg.endsWith(']')) {
2044
- if (arg === '[]') {
2045
- return Array.isArray(value) && value.length === 0
2046
- }
2047
- if (arg === '[*]') {
2048
- return Array.isArray(value) && value.length !== 0
2049
- }
2050
- return false
2051
- }
2052
-
2053
- // the arg is 'operator + string | number'
2054
- const { operator, value: argValue } = _splitOperator(arg)
2055
- if (!operator || (argValue !== 0 && !argValue)) {
2056
- return false
2057
- }
2058
- switch (operator) {
2059
- case '>':
2060
- return value > argValue
2061
- case '<':
2062
- return value < argValue
2063
- case '!=':
2064
- return value !== argValue
2065
- case '>=':
2066
- return value >= argValue
2067
- case '<=':
2068
- return value <= argValue
2069
- default:
2070
- return false
2071
- }
2072
- }
2073
-
2074
- function _isPureStringOrNumber(input) {
2075
- if (typeof input === 'string') {
2076
- if (input.startsWith('[') && input.endsWith(']')) {
2077
- return false
2078
- }
2079
- if (/!=|>=|<=|>|</.test(input)) {
2080
- return false
2081
- }
2082
- return true
2083
- }
2084
- return !Number.isNaN(input)
2085
- }
2086
-
2087
- function _splitOperator(str) {
2088
- const operators = ['!=', '>=', '<=', '>', '<']
2089
-
2090
- const matchedOp = operators.find((op) => str.startsWith(op))
2091
- if (!matchedOp)
2092
- return { operator: null, value: null }
2093
-
2094
- const remaining = str.slice(matchedOp.length)
2095
-
2096
- // '>Primary' or '<Primary' is invalid
2097
- if (/^[a-z]*$/i.test(remaining) && matchedOp !== '!=') {
2098
- return { operator: null, value: null }
2099
- }
2100
-
2101
- // if it is a number it is converted to a number
2102
- const value = (!Number.isNaN(Number.parseFloat(remaining)) && !Number.isNaN(remaining)) ? Number(remaining) : remaining
2103
-
2104
- return {
2105
- operator: matchedOp,
2106
- value
2107
- }
2108
- }
2109
-
2110
-
2111
-
2112
- ;// ./lib/models/templateCompiler/helpers/_filterOne.js
2113
-
2114
-
2115
-
2116
- function _filterOne(data, args) {
2117
- try {
2118
- const list = _filterAll(data, args)
2119
- if (list.length === 1) {
2120
- return list[0]
2121
- }
2122
- if (list.length === 0) {
2123
- return null
2124
- }
2125
- throw new TemplateCompilerException(TEMPLATE_COMPILER_EXCEPTION_TYPE.resultMoreThanOneException)
2126
- } catch (e) {
2127
- throw e
2128
- }
2129
- }
2130
-
2131
-
2132
-
2133
- ;// ./lib/models/templateCompiler/helpers/_formatDate.js
2134
-
2135
-
2136
- function _formatDate(timestamp, format) {
2137
- if (format.length === 0) {
2138
- throw new TemplateCompilerException(`_formateDate: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: format parts must be not empty array`)
2139
- }
2140
-
2141
- if (timestamp === null || timestamp === undefined) {
2142
- return null
2143
- }
2144
-
2145
- const date = new Date(timestamp)
2146
-
2147
- const partsMap = {
2148
- yyyy: String(date.getFullYear()),
2149
- mm: String(date.getMonth() + 1).padStart(2, '0'),
2150
- dd: String(date.getDate()).padStart(2, '0')
2151
- }
2152
-
2153
- // Check for invalid format tokens
2154
- const validTokens = ['yyyy', 'mm', 'dd']
2155
- const invalidTokens = format.filter((part) => part.length > 1 && !validTokens.includes(part))
2156
-
2157
- if (invalidTokens.length > 0) {
2158
- throw new TemplateCompilerException(
2159
- `_formateDate: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: the format type is not valid: ${format.join(', ')}`
2160
- )
2161
- }
2162
-
2163
- // Build the formatted string using reduce
2164
- return format.reduce((result, part) => result + (partsMap[part] || part), '')
2165
- }
2166
-
2167
-
2168
-
2169
- ;// ./lib/models/templateCompiler/helpers/_get.js
2170
-
2171
-
2172
- function _get(data, key, failover = null) {
2173
- try {
2174
- if (key === null || (typeof key === 'undefined') || key === '') {
2175
- throw new TemplateCompilerException(TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentEmptyException)
2176
- }
2177
- if (data === null) {
2178
- return null
2179
- }
2180
- if (key.includes('.')) {
2181
- const parts = key.split('.')
2182
- if (parts.length > 1) {
2183
- const first = parts.shift()
2184
- const remainingKey = parts.join('.')
2185
- if (typeof data[first] !== 'undefined') {
2186
- return _get(data[first], remainingKey, failover)
2187
- }
2188
- return _handleFailover(key, failover)
2189
- }
2190
- }
2191
- if (typeof data[key] !== 'undefined') {
2192
- return data[key]
2193
- }
2194
- return _handleFailover(key, failover)
2195
- } catch (e) {
2196
- throw e
2197
- }
2198
- }
2199
-
2200
- function _handleFailover(key, failover) {
2201
- if (failover !== null) {
2202
- return failover
2203
- }
2204
- return null
2205
- // throw new TemplateCompilerException(`Key "${key}" does not exist and no failover`)
2206
- }
2207
-
2208
-
2209
-
2210
- ;// ./lib/models/templateCompiler/helpers/_gt.js
2211
-
2212
-
2213
-
2214
-
2215
- function _gt(data, args) {
2216
- if (args.length !== 3) {
2217
- throw new TemplateCompilerException(`_gt: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
2218
- }
2219
- if (data === null || (typeof data === 'undefined')) {
2220
- return null
2221
- }
2222
- if (args.includes(_SELF)) {
2223
- args = args.map((arg) => {
2224
- return (arg === _SELF) ? data : arg
2225
- })
2226
- }
2227
- const expected = args[0]
2228
- return data > expected ? args[1] : args[2]
2229
- }
2230
-
2231
-
2232
-
2233
- ;// ./lib/models/templateCompiler/helpers/_gte.js
2234
-
2235
-
2236
-
2237
-
2238
- function _gte(data, args) {
2239
- if (args.length !== 3) {
2240
- throw new TemplateCompilerException(`_gte: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
2241
- }
2242
- if (data === null || (typeof data === 'undefined')) {
2243
- return null
2244
- }
2245
- if (args.includes(_SELF)) {
2246
- args = args.map((arg) => {
2247
- return (arg === _SELF) ? data : arg
2248
- })
2249
- }
2250
- const expected = args[0]
2251
- return data >= expected ? args[1] : args[2]
2252
- }
2253
-
2254
-
2255
-
2256
- ;// ./lib/models/templateCompiler/helpers/_isEmpty.js
2257
-
2258
-
2259
-
2260
-
2261
- function _isEmpty(data, args) {
2262
- if (args.length !== 2) {
2263
- throw new TemplateCompilerException(`_isEmpty: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
2264
- }
2265
- // if (data === null || (typeof data === 'undefined')) {
2266
- // return null
2267
- // }
2268
- if (args.includes(_SELF)) {
2269
- args = args.map((arg) => {
2270
- return (arg === _SELF) ? data : arg
2271
- })
2272
- }
2273
- if (data !== null && typeof data === 'object' && Object.keys(data).length === 0) {
2274
- return args[0]
2275
- }
2276
- return (data === '' || data === null || data === undefined || data.length === 0) ? args[0] : args[1]
2277
- }
2278
-
2279
-
2280
-
2281
- ;// ./lib/models/templateCompiler/helpers/_isNotEmpty.js
2282
-
2283
-
2284
-
2285
-
2286
- function _isNotEmpty(data, args) {
2287
- if (args.length !== 2) {
2288
- throw new TemplateCompilerException(`_isNotEmpty: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
2289
- }
2290
- // if (data === null || (typeof data === 'undefined')) {
2291
- // return null
2292
- // }
2293
- if (args.includes(_SELF)) {
2294
- args = args.map((arg) => {
2295
- return (arg === _SELF) ? data : arg
2296
- })
2297
- }
2298
- if (data !== null && typeof data === 'object' && Object.keys(data).length === 0) {
2299
- return args[1]
2300
- }
2301
- if (Array.isArray(data) && data.length === 0) {
2302
- return args[1]
2303
- }
2304
- if (typeof data === 'string' && data === '') {
2305
- return args[1]
2306
- }
2307
- if (data === null || data === undefined) {
2308
- return args[1]
2309
- }
2310
- return args[0]
2311
- }
2312
-
2313
-
2314
-
2315
- ;// ./lib/models/templateCompiler/helpers/_join.js
2316
- function _join(data, delimiter) {
2317
- try {
2318
- if (data.length === 0)
2319
- return ''
2320
- if (data.length === 1)
2321
- return _stringifyObject(data[0])
2322
- return data.map((item) => _stringifyObject(item)).join(delimiter)
2323
- } catch (e) {
2324
- throw e
2325
- }
2326
- }
2327
-
2328
- function _stringifyObject(obj) {
2329
- return JSON.stringify(obj).replace(/"([^"]+)":/g, '$1: ').replace(/"([^"]+)"/g, '$1').replace(/,/g, ', ')
2330
- }
2331
-
2332
-
2333
-
2334
- ;// ./lib/models/templateCompiler/helpers/_lt.js
2335
-
2336
-
2337
-
2338
-
2339
- function _lt(data, args) {
2340
- if (args.length !== 3) {
2341
- throw new TemplateCompilerException(`_lt: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
2342
- }
2343
- if (data === null || (typeof data === 'undefined')) {
2344
- return null
2345
- }
2346
- if (args.includes(_SELF)) {
2347
- args = args.map((arg) => {
2348
- return (arg === _SELF) ? data : arg
2349
- })
2350
- }
2351
- const expected = args[0]
2352
- return data < expected ? args[1] : args[2]
2353
- }
2354
-
2355
-
2356
-
2357
- ;// ./lib/models/templateCompiler/helpers/_lte.js
2358
-
2359
-
2360
-
2361
-
2362
- function _lte(data, args) {
2363
- if (args.length !== 3) {
2364
- throw new TemplateCompilerException(`_lte: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
2365
- }
2366
- if (data === null || (typeof data === 'undefined')) {
2367
- return null
2368
- }
2369
- if (args.includes(_SELF)) {
2370
- args = args.map((arg) => {
2371
- return (arg === _SELF) ? data : arg
2372
- })
2373
- }
2374
- const expected = args[0]
2375
- return data <= expected ? args[1] : args[2]
2376
- }
2377
-
2378
-
2379
-
2380
- ;// ./lib/models/templateCompiler/helpers/_map.js
2381
-
2382
-
2383
-
2384
- function _map(data, args) {
2385
- try {
2386
- if (args.length === 0) {
2387
- throw new TemplateCompilerException(TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentEmptyException)
2388
- }
2389
- if (data === null || (typeof data === 'undefined')) {
2390
- return null
2391
- }
2392
-
2393
- const result = data.reduce((acc, item) => {
2394
- if (args.length === 1 && Array.isArray(args[0])) {
2395
- args = args[0]
2396
- acc.hasFormat = true
2397
- }
2398
- const list = args.map((key) => {
2399
- if (key.includes('.')) {
2400
- const parts = key.split('.')
2401
- const first = parts[0]
2402
- parts.shift()
2403
- const remainingKey = parts.join('.')
2404
- return _get(item[first], remainingKey)
2405
- }
2406
- if (typeof item[key] !== 'undefined') {
2407
- return item[key]
2408
- }
2409
- return null
2410
- })
2411
- if (acc.hasFormat) {
2412
- acc.content.push(list)
2413
- } else {
2414
- acc.content = acc.content.concat(list)
2415
- }
2416
- return acc
2417
- }, {
2418
- content: [],
2419
- hasFormat: false
2420
- })
2421
- return result.content
2422
- } catch (e) {
2423
- throw e
2424
- }
2425
- }
2426
-
2427
-
2428
-
2429
- ;// ./lib/models/templateCompiler/helpers/_neq.js
2430
-
2431
-
2432
-
2433
-
2434
- function _neq(data, args) {
2435
- if (args.length !== 3) {
2436
- throw new TemplateCompilerException(`_neq: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
2437
- }
2438
- if (data === null || (typeof data === 'undefined')) {
2439
- return null
2440
- }
2441
- if (args.includes(_SELF)) {
2442
- args = args.map((arg) => {
2443
- return (arg === _SELF) ? data : arg
2444
- })
2445
- }
2446
- const expected = args[0]
2447
- return data !== expected ? args[1] : args[2]
2448
- }
2449
-
2450
-
2451
-
2452
- ;// ./lib/models/templateCompiler/helpers/_removeHtml.js
2453
-
2454
-
2455
- function _removeHtml(html, args) {
2456
- if (html === null || html === undefined) {
2457
- return null
2458
- }
2459
- if (!Array.isArray(args)) {
2460
- throw new TemplateCompilerException(`_removeHtml: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: args parts must be array`)
2461
- }
2462
-
2463
- return _htmlToPlainText(html, args[0])
2464
- }
2465
-
2466
- function _htmlToPlainText(html, delimiter = '\n') {
2467
- if (typeof delimiter !== 'string') {
2468
- delimiter = '\n' // Fallback to default if not a string
2469
- }
2470
-
2471
- // First decode HTML entities and normalize whitespace
2472
- const decodedHtml = html
2473
- .replace(/&nbsp;/g, ' ')
2474
- .replace(/\s+/g, ' ') // Collapse all whitespace to single spaces
2475
-
2476
- // Process HTML tags
2477
- let text = decodedHtml
2478
- // Replace block tags with temporary marker (~~~)
2479
- .replace(/<\/?(p|div|h[1-6]|ul|ol|li|pre|section|article|table|tr|td|th)(\s[^>]*)?>/gi, '~~~')
2480
- // Replace <br> tags with temporary marker (~~~)
2481
- .replace(/<br\s*\/?>/gi, '~~~')
2482
- // Remove all other tags
2483
- .replace(/<[^>]+>/g, '')
2484
- // Convert markers to specified delimiter
2485
- .replace(/~{3,}/g, delimiter)
2486
- // Trim and clean whitespace
2487
- .trim()
2488
-
2489
- // Special handling for empty delimiter
2490
- if (delimiter === '') {
2491
- // Collapse all whitespace to single space
2492
- text = text.replace(/\s+/g, ' ')
2493
- } else {
2494
- // Collapse multiple delimiters to single
2495
- text = text.replace(new RegExp(`${escapeRegExp(delimiter)}+`, 'g'), delimiter)
2496
- // Remove leading/trailing delimiters
2497
- text = text.replace(new RegExp(`^${escapeRegExp(delimiter)}|${escapeRegExp(delimiter)}$`, 'g'), '')
2498
- }
2499
-
2500
- return text
2501
- }
2502
-
2503
- function escapeRegExp(string) {
2504
- return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
2505
- }
2506
-
2507
-
2508
-
2509
- ;// ./lib/models/templateCompiler/helpers/_sum.js
2510
- function _sum(data, args) {
2511
- if (Number.isNaN(data) || data === null || (typeof data === 'undefined') || data === '') {
2512
- return data
2513
- }
2514
- return args.reduce((acc, e) => (acc + e), data)
2515
- }
2516
-
2517
-
2518
-
2519
- ;// ./lib/models/templateCompiler/helpers/_toLowerCase.js
2520
-
2521
-
2522
- function _toLowerCase(data, args) {
2523
- if (args !== undefined) {
2524
- throw new TemplateCompilerException(`_toLowerCase: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: ${args.join(', ')}`)
2525
- }
2526
- if (data === null || (typeof data === 'undefined') || typeof data !== 'string') {
2527
- return null
2528
- }
2529
- return String(data).toLowerCase()
2530
- }
2531
-
2532
-
2533
-
2534
- ;// ./lib/models/templateCompiler/helpers/_toUpperCase.js
2535
-
2536
-
2537
- function _toUpperCase(data, args) {
2538
- if (typeof data !== 'string') {
2539
- throw new TemplateCompilerException(`_toUpperCase: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: the data must be string: ${data}`)
2540
- }
2541
- if (args !== undefined) {
2542
- throw new TemplateCompilerException(`_toUpperCase: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException}: the argument must be empty: ${args.join(', ')}`)
2543
- }
2544
- if (data === null || (typeof data === 'undefined') || typeof data !== 'string') {
2545
- return null
2546
- }
2547
- return String(data).toUpperCase()
2548
- }
2549
-
2550
-
2551
-
2552
- ;// ./lib/models/templateCompiler/helpers/index.js
2553
-
2554
-
2555
-
2556
-
2557
-
2558
-
2559
-
2560
-
2561
-
2562
-
2563
-
2564
-
2565
-
2566
-
2567
-
2568
-
2569
-
2570
-
2571
-
2572
-
2573
-
2574
-
2575
-
2576
-
2577
- ;// ./lib/models/templateCompiler/templateCompiler.js
2578
-
2579
-
2580
-
2581
-
2582
- class TemplateCompiler {
2583
- constructor(data) {
2584
- this.data = data
2585
- }
2586
- static init(options) {
2587
- return new this(options)
2588
- }
2589
- static initFromArray(arr = []) {
2590
- if (Array.isArray(arr)) {
2591
- return arr.map((a) => this.init(a))
2592
- }
2593
- return []
2594
- }
2595
- static initOnlyValidFromArray(arr = []) {
2596
- return this.initFromArray(arr).filter((i) => i)
2597
- }
2598
- static concatIf(data, args) {
2599
- return _concatIf(data, args)
2600
- }
2601
- static divide(data, args) {
2602
- return _divide(data, args)
2603
- }
2604
- static eq(data, args) {
2605
- return _eq(data, args)
2606
- }
2607
-
2608
- static filterAll(data, args) {
2609
- return _filterAll(data, args)
2610
- }
2611
-
2612
- static formatDate(data, args) {
2613
- return _formatDate(data, args)
2614
- }
2615
- static get(data, key, failover = null) {
2616
- return _get(data, key, failover)
2617
- }
2618
- static gt(data, args) {
2619
- return _gt(data, args)
2620
- }
2621
- static gte(data, args) {
2622
- return _gte(data, args)
2623
- }
2624
- static isEmpty(data, args) {
2625
- return _isEmpty(data, args)
2626
- }
2627
- static isNotEmpty(data, args) {
2628
- return _isNotEmpty(data, args)
2629
- }
2630
- static join(data, separator = '') {
2631
- return _join(data, separator)
2632
- }
2633
- static lt(data, args) {
2634
- return _lt(data, args)
2635
- }
2636
- static lte(data, args) {
2637
- return _lte(data, args)
2638
- }
2639
- static map(data, args = []) {
2640
- return _map(data, args)
2641
- }
2642
- static neq(data, args) {
2643
- return _neq(data, args)
2644
- }
2645
- static removeHtml(data, args) {
2646
- return _removeHtml(data, args)
2647
- }
2648
- static sum(data, args) {
2649
- return _sum(data, args)
2650
- }
2651
- static toLowerCase(data, args) {
2652
- return _toLowerCase(data, args)
2653
- }
2654
- static toUpperCase(data, args) {
2655
- return _toUpperCase(data, args)
2656
- }
2657
- static parseFunction(expression) {
2658
- return _parseFunction(expression, _FN_NAMES)
2659
- }
2660
- static parseParams(parameters) {
2661
- return _parseParams(parameters)
2662
- }
2663
-
2664
- pipe(expression = '') {
2665
- this.delimiters = expression.substring(0, 2) === '{{' ? TAGS_HANDLEBAR : TAGS_EJS
2666
- const regex = new RegExp(`${this.delimiters[0]}\\s(.*?)\\s${this.delimiters[1]}`)
2667
- const match = expression.match(regex)
2668
- if (match !== null) {
2669
- try {
2670
- const functionList = _parseFunction(match[1], _FN_NAMES)
2671
- return functionList.reduce((acc, fn) => {
2672
- return _callFunction(acc, fn.name, fn.args)
2673
- }, this.data)
2674
- } catch (e) {
2675
- throw new TemplateCompilerException(`TemplateCompiler engine error: ${e.message}`)
2676
- }
2677
- }
2678
- throw new TemplateCompilerException(`TemplateCompiler engine error: ${TEMPLATE_COMPILER_EXCEPTION_TYPE.invalidRegExpException}`)
2679
- }
2680
- }
2681
-
2682
- function _parseFunction(expression, existFunctionNames) {
2683
- const regExp = new RegExp(/(\w+)\(([^)]*)\)/)
2684
- let parts
2685
- if (expression.includes('|')) {
2686
- parts = expression.split('|')
2687
- } else {
2688
- parts = [expression]
2689
- }
2690
- return parts.reduce((acc, part) => {
2691
- const match = part.match(regExp)
2692
- if (match !== null) {
2693
- const functionName = match[1]
2694
- const parameters = match[2]
2695
- const paramList = _parseParams(parameters)
2696
- if (existFunctionNames.includes(functionName)) {
2697
- acc.push({
2698
- name: functionName,
2699
- args: paramList
2700
- })
2701
- } else {
2702
- throw new TemplateCompilerException(`${functionName} is not a valid function`)
2703
- }
2704
- }
2705
- return acc
2706
- }, [])
2707
- }
2708
-
2709
- function _parseParams(parameters) {
2710
- const _parameters = parameters.trim()
2711
- const regExp = new RegExp(/^[^\w\s]+$/)
2712
- const match = _parameters.match(regExp)
2713
- if (match !== null) {
2714
- return [_parameters.substring(1, _parameters.length - 1)]
2715
- }
2716
- if (_parameters.includes(',')) {
2717
- // 用正则表达式匹配逗号,但忽略方括号中的逗号
2718
- const parts = _splitIgnoringBrackets(_parameters)
2719
- return parts.map((part) => _parseSinglePart(part))
2720
- }
2721
- return [_parseSinglePart(_parameters)]
2722
- }
2723
-
2724
- function _splitIgnoringBrackets(input) {
2725
- const regExp2 = new RegExp(/^\d+(\.\d+)?$/)
2726
- const regExp = new RegExp(/(?![^[]*\])\s*,\s*/)
2727
- const parts = input.split(regExp)
2728
- return parts.map((part) => {
2729
- const _part = part.trim()
2730
- if (_part !== '' && !!_part.match(regExp2)) {
2731
- // 如果是数字,转换为 num 类型
2732
- return Number.isNaN(_part) ? _part : Number.parseInt(_part, 10)
2733
- }
2734
- // 否则当作字符串处理
2735
- return _part
2736
- })
2737
- }
2738
-
2739
- function _parseSinglePart(input) {
2740
- if (typeof input === 'string') {
2741
- if (input.startsWith('"') && input.endsWith('"')) {
2742
- // 去掉双引号,返回
2743
- return input.substring(1, input.length - 1)
2744
- }
2745
- if (input.startsWith('\'') && input.endsWith('\'')) {
2746
- // 去掉双引号,返回
2747
- return input.substring(1, input.length - 1)
2748
- }
2749
-
2750
- const _input = _toBasicType(input)
2751
-
2752
- if (typeof _input !== 'string') {
2753
- return _input
2754
- }
2755
-
2756
- // 如果是一个列表形式(例如 ["p", "d"] 或 [p, d])
2757
- if (_input.startsWith('[') && _input.endsWith(']')) {
2758
- const listContent = _input.substring(1, _input.length - 1).trim()
2759
- if (listContent !== '') {
2760
- return listContent.split(',').map((item) => {
2761
- return _toBasicType(item.trim())
2762
- })
2763
- }
2764
- return []
2765
- }
2766
- return input
2767
- }
2768
- return input
2769
- }
2770
-
2771
- function _toBasicType(input) {
2772
- if (input.startsWith('"') && input.endsWith('"')) {
2773
- // 去掉双引号,返回
2774
- return input.substring(1, input.length - 1)
2775
- }
2776
- if (input.startsWith('\'') && input.endsWith('\'')) {
2777
- // 去掉双引号,返回
2778
- return input.substring(1, input.length - 1)
2779
- }
2780
- if (input === 'true') {
2781
- return true
2782
- }
2783
- if (input === 'false') {
2784
- return false
2785
- }
2786
- if (input === 'undefined') {
2787
- return undefined
2788
- }
2789
- if (input === 'null') {
2790
- return null
2791
- }
2792
- if (!Number.isNaN(input) && !Number.isNaN(Number.parseFloat(input))) {
2793
- return Number(input)
2794
- }
2795
- return input
2796
- }
2797
-
2798
- function _callFunction(data, functionName, parameters) {
2799
- try {
2800
- let failover
2801
- switch (functionName) {
2802
- case 'concatIf':
2803
- return _concatIf(data, parameters)
2804
- case 'divide':
2805
- return _divide(data, parameters)
2806
- case 'eq':
2807
- return _eq(data, parameters)
2808
- case 'exec':
2809
- return _exec(data, parameters)
2810
- case 'filterAll':
2811
- return _filterAll(data, parameters)
2812
- case 'filterOne':
2813
- return _filterOne(data, parameters)
2814
- case 'formatDate':
2815
- return _formatDate(data, parameters)
2816
- case 'get':
2817
- if (parameters.length > 2) {
2818
- throw new TemplateCompilerException(TEMPLATE_COMPILER_EXCEPTION_TYPE.argumentFormatException)
2819
- }
2820
- if (parameters.length === 2) {
2821
- failover = parameters[parameters.length - 1]
2822
- }
2823
- return _get(data, parameters[0], failover)
2824
- case 'gt':
2825
- return _gt(data, parameters)
2826
- case 'gte':
2827
- return _gte(data, parameters)
2828
- case 'isEmpty':
2829
- return _isEmpty(data, parameters)
2830
- case 'isNotEmpty':
2831
- return _isNotEmpty(data, parameters)
2832
- case 'join':
2833
- return _join(data, parameters[0])
2834
- case 'lt':
2835
- return _lt(data, parameters)
2836
- case 'lte':
2837
- return _lte(data, parameters)
2838
- case 'map':
2839
- return _map(data, parameters)
2840
- case 'neq':
2841
- return _neq(data, parameters)
2842
- case 'removeHtml':
2843
- return _removeHtml(data, parameters)
2844
- case 'sum':
2845
- return _sum(data, parameters)
2846
- case 'toLowerCase':
2847
- return _toLowerCase(data)
2848
- case 'toUpperCase':
2849
- return _toUpperCase(data)
2850
- default:
2851
- throw new Error(`${functionName} is not a valid function`)
2852
- }
2853
- } catch (e) {
2854
- throw e
2855
- }
2856
- }
2857
-
2858
-
2859
-
2860
- ;// ./lib/models/templateCompiler/index.js
2861
-
2862
-
2863
-
2864
-
2865
- ;// ./lib/models/tenantAwareEntity/tenantAwareEntity.js
2866
-
2867
-
2868
-
2869
-
2870
- class TenantAwareEntity extends TrackedEntity {
2871
- constructor(options = {}) {
2872
- options = options || {}
2873
-
2874
- /**
2875
- * instead of throw error, we choose to implement the isValid checking
2876
- */
2877
- // if (!options.tenantCode) {
2878
- // throw new Error('tenantCode required')
2879
- // }
2880
-
2881
- super(options)
2882
-
2883
- this._tenant = options._tenant
2884
-
2885
- this.metadata = Metadata.initOnlyValidFromArray(options.metadata)
2886
- this.remarks = keyValueObject_KeyValueObject.initOnlyValidFromArray(options.remarks)
2887
- this.tenantCode = options.tenantCode // Required for multi-tenancy
2888
- }
2889
-
2890
- // Class methods
2891
- static get _classname() {
2892
- return 'TenantAwareEntity'
2893
- }
2894
- static get _superclass() {
2895
- return 'TenantAwareEntity'
2896
- }
2897
-
2898
- // getters
2899
- get __valid() {
2900
- return {
2901
- ...super.__valid,
2902
- tenantCode: this.tenantCode
2903
- }
2904
- }
2905
- get isValid() {
2906
- return super.isValid && !!this.tenantCode // Required for multi-tenancy
2907
- }
2908
-
2909
- // instance methods
2910
- insertOrUpdateMetadata(key, value) {
2911
- this.metadata = Metadata.insertOrUpdateRecord(this.metadata, key, value)
2912
- return this
2913
- }
2914
- getMetadata() {
2915
- return this.metadata
2916
- }
2917
- getMetadataByKey(key) {
2918
- return Metadata.foundByKey(this.metadata, key)
2919
- }
2920
- getMetadataValueByKey(key) {
2921
- const found = this.getMetadataByKey(key)
2922
- return found ? found.value : null
2923
- }
2924
- getMetadataValueByKeys(keys, kv) {
2925
- if (!Array.isArray(keys)) {
2926
- return null
2927
- }
2928
- kv = kv || this.metadata
2929
- if (keys.length === 0) {
2930
- return kv
2931
- }
2932
- const key = keys.shift()
2933
- const _val = Metadata.getMetadataValueByKeyAsArray(kv, key)
2934
- return this.getMetadataValueByKeys(keys, _val)
2935
- }
2936
- getMetadataValueByKeyAsArray(key) {
2937
- return Metadata.getMetadataValueByKeyAsArray(this.metadata, key)
2938
- }
2939
- getRemarks() {
2940
- return this.remarks
2941
- }
2942
- getRemarkByKey(key) {
2943
- return keyValueObject_KeyValueObject.foundByKey(this.remarks, key)
2944
- }
2945
- getRemarksValueByKey(key) {
2946
- const found = this.getRemarkByKey(key)
2947
- return found ? found.value : null
2948
- }
2949
- getTenantCode() {
2950
- return this.tenantCode
2951
- }
2952
-
2953
- update(update) {
2954
- if (update.metadata && Array.isArray(update.metadata)) {
2955
- this.metadata = Metadata.initOnlyValidFromArray(update.metadata)
2956
- }
2957
- if (update.remarks && Array.isArray(update.remarks)) {
2958
- this.remarks = keyValueObject_KeyValueObject.initOnlyValidFromArray(update.remarks)
2959
- }
2960
- return super.update(update)
2961
- }
2962
- }
2963
-
2964
- ;// ./lib/models/tenantAwareEntity/index.js
2965
-
2966
-
2967
-
2968
- ;// ./lib/models/uniqueKeyGenerator/uniqueKeyGenerator.js
2969
-
2970
-
2971
- class UniqueKeyGenerator {
2972
- static get _classname() {
2973
- return 'UniqueKeyGenerator'
2974
- }
2975
- static get _superclass() {
2976
- return 'UniqueKeyGenerator'
2977
- }
2978
- static makeFormatter({ fieldName, format, options }) {
2979
- switch (format) {
2980
- case 'set_code':
2981
- return _makeSetCode(fieldName, options)
2982
- default:
2983
- return _makeSetCode(fieldName, options)
2984
- }
2985
- }
2986
- static makeGenerator(arr) {
2987
- const fns = arr.map((item) => this.makeFormatter(item))
2988
- return async (obj) => {
2989
- const output = await pReduce(fns, async (acc, fn) => {
2990
- const _obj = await fn(obj)
2991
- return Object.assign(acc, _obj)
2992
- }, obj)
2993
- return output
2994
- }
2995
- }
2996
- }
2997
-
2998
- function _makeSetCode(fieldName, options) {
2999
- return async (obj = {}) => {
3000
- if (obj[fieldName]) {
3001
- return {}
3002
- }
3003
- return {
3004
- [fieldName]: stringHelper.setCode()
3005
- }
3006
- }
3007
- }
3008
-
3009
-
3010
-
3011
- ;// ./lib/models/uniqueKeyGenerator/index.js
3012
-
3013
-
3014
-
3015
-
3016
- ;// ./lib/models/index.js
3017
-
3018
-
3019
-
3020
-
3021
-
3022
-
3023
-
3024
-
3025
-
3026
-
3027
-
3028
-
3029
-
3030
-
3031
- ;// ./lib/helpers/getValidation/getValidation.js
3032
-
3033
-
3034
-
3035
-
3036
- function getValidation(rule, data, getDataByKey = _getDataByKey, KeyValueObject = keyValueObject_KeyValueObject) {
3037
- if (!rule) {
3038
- return true
3039
- }
3040
- if (typeof getDataByKey !== 'function' || (KeyValueObject && typeof KeyValueObject !== 'function')) {
3041
- return false
3042
- }
3043
- const { key = '', value, placeholder, keyValuePath = '' } = rule
3044
- const [valueAttribute] = Object.keys(value)
3045
-
3046
- if (!key && typeof placeholder === 'undefined') {
3047
- switch (valueAttribute) {
3048
- case '$and': {
3049
- return value.$and.reduce((acc, item) => (acc && getValidation(item, data, getDataByKey, KeyValueObject)), true)
3050
- }
3051
- case '$or': {
3052
- return value.$or.reduce((acc, item) => (acc || getValidation(item, data, getDataByKey, KeyValueObject)), false)
3053
- }
3054
- default:
3055
- return false
3056
- }
3057
- }
3058
- let rowValue = typeof placeholder === 'undefined' ? getDataByKey(key, data) : placeholder
3059
-
3060
- // if KeyValue object
3061
- if (keyValuePath) {
3062
- const rowValueData = KeyValueObject.toObject(rowValue)
3063
- rowValue = getDataByKey(keyValuePath, rowValueData)
3064
- }
3065
-
3066
- switch (valueAttribute) {
3067
- case '$after': {
3068
- if (isConvertibleToNumber(value?.$after)) {
3069
- const _value = Number(String(value?.$after))
3070
- return Date.now() > _value
3071
- }
3072
- return false
3073
- }
3074
- case '$before': {
3075
- if (isConvertibleToNumber(value?.$before)) {
3076
- const _value = Number(String(value?.$before))
3077
- return Date.now() < _value
3078
- }
3079
- return false
3080
- }
3081
- case '$empty': {
3082
- const isEmpty = rowValue === null || rowValue === undefined
3083
- return isEmpty === value.$empty
3084
- }
3085
- case '$eq': {
3086
- return rowValue === value.$eq
3087
- }
3088
- case '$gt': {
3089
- return rowValue > value.$gt
3090
- }
3091
- case '$gte': {
3092
- return rowValue >= value.$gte
3093
- }
3094
- case '$hasOverlap': {
3095
- return _hasOverlap(rowValue, value.$hasOverlap)
3096
- }
3097
- case '$lt': {
3098
- return rowValue < value.$lt
3099
- }
3100
- case '$lte': {
3101
- return rowValue <= value.$lte
3102
- }
3103
- case '$in': {
3104
- if (Array.isArray(rowValue)) {
3105
- return !!rowValue.find((e) => (value.$in.includes(e)))
3106
- }
3107
- if (typeof rowValue !== 'object') {
3108
- return !!value.$in.includes(rowValue)
3109
- }
3110
- return false
3111
- }
3112
- case '$includes': {
3113
- if (Array.isArray(rowValue)) {
3114
- return rowValue.includes(value.$includes)
3115
- }
3116
- return false
3117
- }
3118
- case '$intervalTimeGt': {
3119
- const now = new Date().getTime()
3120
- const timestamp = new Date(rowValue).getTime()
3121
- return (now - timestamp) > value.$intervalTimeGt
3122
- }
3123
- case '$intervalTimeLt': {
3124
- const now = new Date().getTime()
3125
- const timestamp = new Date(rowValue).getTime()
3126
- return (now - timestamp) < value.$intervalTimeLt
3127
- }
3128
- case '$inValue': {
3129
- const result = getDataByKey(value.$inValue, data)
3130
- const _value = Array.isArray(result) ? result : []
3131
- if (Array.isArray(rowValue)) {
3132
- return !!rowValue.find((e) => (_value.includes(e)))
3133
- }
3134
- if (typeof rowValue === 'string') {
3135
- return !!_value.includes(rowValue)
3136
- }
3137
- return false
3138
- }
3139
- case '$isToday': {
3140
- const currentDate = new Date()
3141
- const start = currentDate.setHours(0, 0, 0, 0)
3142
- const end = currentDate.setHours(23, 59, 59, 59)
3143
- const dateValue = new Date(rowValue).getTime()
3144
- return (start <= dateValue && end >= dateValue) === value.$isToday
3145
- }
3146
- case '$ne': {
3147
- return rowValue !== value.$ne
3148
- }
3149
- case '$notIn': {
3150
- if (Array.isArray(rowValue)) {
3151
- return !rowValue.find((e) => (value.$notIn.includes(e)))
3152
- }
3153
- if (typeof rowValue !== 'object') {
3154
- return !value.$notIn.includes(rowValue)
3155
- }
3156
- return false
3157
- }
3158
- case '$notInValue': {
3159
- const result = getDataByKey(value.$notInValue, data)
3160
- const _value = Array.isArray(result) ? result : []
3161
- if (Array.isArray(rowValue)) {
3162
- return !rowValue.find((e) => (_value.includes(e)))
3163
- }
3164
- if (typeof rowValue !== 'object') {
3165
- return !_value.includes(rowValue)
3166
- }
3167
- return false
3168
- }
3169
- case '$range': {
3170
- const [min, max] = value.$range
3171
- if (typeof min === 'number' && typeof max === 'number' && rowValue >= min && rowValue <= max) {
3172
- return true
3173
- }
3174
- return false
3175
- }
3176
- default:
3177
- return false
3178
- }
3179
- }
3180
-
3181
- function _getDataByKey(key, data) {
3182
- return getValueByKeys_getValueByKeys(key.split('.'), data)
3183
- }
3184
-
3185
- function _hasOverlap(item1, item2) {
3186
- let arr1 = item1
3187
- let arr2 = item2
3188
- if (typeof arr1 === 'string') {
3189
- arr1 = arr1.split(',')
3190
- }
3191
- if (typeof arr2 === 'string') {
3192
- arr2 = arr2.split(',')
3193
- }
3194
- const set1 = new Set(arr1)
3195
- return arr2.find((i) => (set1.has(i)))
3196
- }
3197
-
3198
- /* harmony default export */ const getValidation_getValidation = ({
3199
- getValidation
3200
- });
3201
-
3202
-
3203
- ;// ./lib/helpers/getValidation/index.js
3204
-
3205
-
3206
- ;// ./lib/helpers/formatDate/formatDate.js
3207
- function formatDate(date, format) {
3208
- const _date = date && date instanceof Date ? date : new Date(date)
3209
- const dayMapChi = ['日', '一', '二', '三', '四', '五', '六']
3210
- const dayMapEng = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
3211
- const dayMapEngShort = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
3212
- const _format = format || 'YYYY/MM/DD hh:mm'
3213
- const e = _date.getDay()
3214
- const ee = dayMapEngShort[e]
3215
- const eee = dayMapChi[e]
3216
- const eeee = dayMapEng[e]
3217
- const y = _date.getFullYear()
3218
- const m = _date.getMonth() + 1
3219
- const d = _date.getDate()
3220
- const h = _date.getHours()
3221
- const mm = _date.getMinutes()
3222
- const s = _date.getSeconds()
3223
-
3224
- return _format.replace('YYYY', y)
3225
- .replace('MM', padding(m))
3226
- .replace('MM', padding(m))
3227
- .replace('DD', padding(d))
3228
- .replace('hh', padding(h))
3229
- .replace('mm', padding(mm))
3230
- .replace('ss', padding(s))
3231
- .replace('M', m)
3232
- .replace('D', d)
3233
- .replace('h', h)
3234
- .replace('m', mm)
3235
- .replace('s', s)
3236
- .replace('EEEE', padding(eeee))
3237
- .replace('EEE', padding(eee))
3238
- .replace('EE', padding(ee))
3239
- .replace('E', padding(e))
3240
- }
3241
-
3242
- function padding(m) {
3243
- return m < 10 ? `0${m}` : m
3244
- }
3245
-
3246
- /* harmony default export */ const formatDate_formatDate = ({
3247
- formatDate
3248
- });
3249
-
3250
-
3251
- ;// ./lib/helpers/formatDate/index.js
3252
-
3253
-
3254
- ;// ./lib/helpers/concatStringByArray/concatStringByArray.js
3255
-
3256
-
3257
-
3258
-
3259
-
3260
- function concatStringByArray(arrTemplate, data) {
3261
- return arrTemplate.reduce((acc, item) => {
3262
- const { type, value = '', restriction, template, format, showMinutes } = item
3263
- switch (type) {
3264
- case ('array'): {
3265
- if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
3266
- const _value = getValueByKeys_getValueByKeys(value.split('.'), data) || []
3267
- acc += _value.reduce((_acc, item) => {
3268
- return _acc += concatStringByArray(template, item)
3269
- }, '')
3270
- }
3271
- break
3272
- }
3273
- case ('date'): {
3274
- if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
3275
- const _value = getValueByKeys_getValueByKeys(value.split('.'), data) || ''
3276
- acc += (formatDate(_value, format).toString())
3277
- }
3278
- break
3279
- }
3280
- case ('ellipsis'): {
3281
- if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
3282
- const { maxLength } = item
3283
- const _value = getValueByKeys_getValueByKeys(value.split('.'), data) || ''
3284
- if (_value.length <= maxLength) {
3285
- acc += (_value.toString())
3286
- } else {
3287
- acc += `${_value.substr(0, maxLength)}...`
3288
- }
3289
- }
3290
- break
3291
- }
3292
- case ('group'): {
3293
- if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
3294
- return concatStringByArray(value, data)
3295
- }
3296
- break
3297
- }
3298
- case ('label'): {
3299
- if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
3300
- acc += (value.toString())
3301
- }
3302
- break
3303
- }
3304
- case ('templateCompiler'): {
3305
- if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
3306
- const templateCompiler = new TemplateCompiler({ data })
3307
- acc += templateCompiler.pipe(value)
3308
- }
3309
- break
3310
- }
3311
- case ('value'): {
3312
- if (getValidation(restriction, data, getValueByKeys_getValueByKeys)) {
3313
- const _value = getValueByKeys_getValueByKeys(value.split('.'), data) || ''
3314
- acc += (_value.toString())
3315
- }
3316
- break
3317
- }
3318
- }
3319
- return acc
3320
- }, '')
3321
- }
3322
- /* harmony default export */ const concatStringByArray_concatStringByArray = ({
3323
- concatStringByArray
3324
- });
3325
-
3326
-
3327
- ;// ./lib/helpers/concatStringByArray/index.js
3328
-
3329
-
3330
- ;// ./lib/helpers/convertString/convertString.js
3331
-
3332
-
3333
- function convertString(string, patternMatch = /\$\{(.+?)\}/g, value, getValueByKeys) {
3334
- if (!string) {
3335
- return ''
3336
- }
3337
- const _getValueByKeys = typeof getValueByKeys === 'function' ? getValueByKeys : getValueByKeys_getValueByKeys
3338
- const reg = new RegExp(patternMatch, 'g')
3339
- return string.replace(reg, (match, key) => {
3340
- const result = _getValueByKeys({ keys: key.split('.'), obj: value })
3341
- if (result === null || result === undefined) {
3342
- return ''
3343
- }
3344
- return typeof result === 'object' ? JSON.stringify(result) : result
3345
- })
3346
- }
3347
-
3348
- /* harmony default export */ const convertString_convertString = ({
3349
- convertString
3350
- });
3351
-
3352
-
3353
- ;// ./lib/helpers/convertString/index.js
3354
-
3355
-
3356
- ;// ./lib/helpers/detectControlCharacters/detectControlCharacters.js
3357
- /**
3358
- * Detects and reports hidden/control characters in a string without modifying it.
3359
- * @param {string} input - The string to analyze.
3360
- * @param {Object} [options] - Configuration options.
3361
- * @param {boolean} [options.preserveBasicWhitespace=true] - Whether to consider basic whitespace as valid.
3362
- * @returns {Object} Report object with detection results.
3363
- */
3364
- function detectControlCharacters(input, options = {}) {
3365
- const {
3366
- preserveBasicWhitespace = true,
3367
- removeNewlines = false
3368
- } = options
3369
-
3370
- if (typeof input !== 'string') {
3371
- return {
3372
- hasControlChars: false,
3373
- matches: [],
3374
- inputType: typeof input,
3375
- message: 'Input is not a string'
3376
- }
3377
- }
3378
-
3379
- const matches = []
3380
- let regex
3381
-
3382
- if (preserveBasicWhitespace && !removeNewlines) {
3383
- // Same regex as Phase 1 preserve mode - keep tab (\t), newline (\n), carriage return (\r)
3384
- regex = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g
3385
- } else {
3386
- // Same regex as Phase 1 full removal mode - use consistent escape sequences
3387
- regex = /[\x00-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g
3388
- }
3389
-
3390
- // Use a replacer function to capture matches without modifying the string
3391
- input.replace(regex, (match, offset) => {
3392
- matches.push({
3393
- character: match,
3394
- code: match.charCodeAt(0),
3395
- hex: '0x' + match.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0'),
3396
- position: offset,
3397
- context: getContext(input, offset, 10) // Show surrounding text
3398
- })
3399
- return '' // Return empty but we don't use the result
3400
- })
3401
-
3402
- return {
3403
- hasControlChars: matches.length > 0,
3404
- matches,
3405
- totalFound: matches.length,
3406
- inputPreview: input.length > 50 ? input.substring(0, 50) + '...' : input,
3407
- inputLength: input.length,
3408
- optionsUsed: { preserveBasicWhitespace },
3409
- regexPattern: regex.toString()
3410
- }
3411
- }
3412
-
3413
- /**
3414
- * Helper function to get context around a match
3415
- */
3416
- function getContext(str, position, contextLength = 10) {
3417
- const start = Math.max(0, position - contextLength)
3418
- const end = Math.min(str.length, position + contextLength + 1)
3419
- let context = str.substring(start, end)
3420
-
3421
- // Replace control characters with their escape sequences for readability
3422
- context = context.replace(/[\x00-\x1F\x7F-\x9F]/g, (match) => {
3423
- return '\\u' + match.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0')
3424
- })
3425
-
3426
- return context
3427
- }
3428
-
3429
- /**
3430
- * Pretty print the detection results to console
3431
- */
3432
- function printControlCharReport(report) {
3433
- console.log('=== Control Character Detection Report ===')
3434
- console.log(`Input: "${report.inputPreview}" (${report.inputLength} chars)`)
3435
- console.log(`Options: preserveBasicWhitespace = ${report.optionsUsed.preserveBasicWhitespace}`)
3436
- console.log(`Regex pattern: ${report.regexPattern}`)
3437
- console.log(`Control characters found: ${report.totalFound}`)
3438
-
3439
- if (report.hasControlChars) {
3440
- console.log('\n📋 Matches found:')
3441
- report.matches.forEach((match, index) => {
3442
- console.log(`\n${index + 1}. Character: ${JSON.stringify(match.character)}`)
3443
- console.log(` Code: ${match.code} (${match.hex})`)
3444
- console.log(` Position: ${match.position}`)
3445
- console.log(` Context: "...${match.context}..."`)
3446
- })
3447
- } else {
3448
- console.log('✅ No control characters detected in Phase 1 range')
3449
- }
3450
-
3451
- console.log('=== End Report ===')
3452
- }
3453
-
3454
- ;// ./lib/helpers/detectControlCharacters/index.js
3455
-
3456
-
3457
- ;// ./lib/helpers/downloadFileByUrl/downloadFileByUrl.js
3458
- function downloadFileByUrl({ dataUrl = '', filename = '' } = {}) {
3459
- const link = document.createElement('a')
3460
- link.download = filename
3461
- link.href = dataUrl
3462
- document.body.appendChild(link)
3463
- link.click()
3464
- document.body.removeChild(link)
3465
- }
3466
-
3467
-
3468
-
3469
- ;// ./lib/helpers/downloadFileByUrl/index.js
3470
-
3471
-
3472
-
3473
-
3474
- ;// ./lib/helpers/escapeRegex/escapeRegex.js
3475
- function escapeRegex(string) {
3476
- return String(string).replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
3477
- }
3478
-
3479
- ;// ./lib/helpers/escapeRegex/index.js
3480
-
3481
-
3482
- ;// ./lib/helpers/expressHelper/customHandler.js
3483
- function customHandler({ responseHelper, handler, ignoreError = false }) {
3484
- return async (req, res, next) => {
3485
- try {
3486
- await handler({ req, res })
3487
- await next()
3488
- } catch (err) {
3489
- if (ignoreError || !responseHelper) {
3490
- await next()
3491
- } else {
3492
- res.status(400).json(responseHelper.standardizeResponse({ err, message: err.message || err }))
3493
- }
3494
- }
3495
- }
3496
- }
3497
-
3498
- ;// ./lib/helpers/expressHelper/findAllResult.js
3499
- function findAllResult({ responseHelper, service }) {
3500
- return async (req, res, next) => {
3501
- try {
3502
- const { query } = req
3503
- const result = await service.findAll({ query })
3504
- res.locals.findAllResult = result
3505
- await next()
3506
- } catch (err) {
3507
- res.status(400).json(responseHelper.standardizeResponse({ err, message: err.message || err }))
3508
- }
3509
- }
3510
- }
3511
-
3512
- ;// ./lib/helpers/expressHelper/findOneResult.js
3513
- function findOneResult({ responseHelper, service }) {
3514
- return async (req, res, next) => {
3515
- try {
3516
- const { params, query } = req
3517
- const { id } = params
3518
- const result = await service.findOne({
3519
- query: {
3520
- ...query,
3521
- id
3522
- }
3523
- })
3524
- res.locals.findOneResult = result
3525
- await next()
3526
- } catch (err) {
3527
- res.status(400).json(responseHelper.standardizeResponse({ err, message: err.message || err }))
3528
- }
3529
- }
3530
- }
3531
-
3532
- ;// ./lib/helpers/expressHelper/postResult.js
3533
- function postResult({ responseHelper, service }) {
3534
- return async (req, res, next) => {
3535
- try {
3536
- const { body } = req
3537
- let result
3538
- if (Array.isArray(body)) {
3539
- result = await service.saveAll({ docs: body })
3540
- } else {
3541
- result = await service.saveOne({ doc: body })
3542
- }
3543
- res.locals.postResult = result
3544
- await next()
3545
- } catch (err) {
3546
- res.status(400).json(responseHelper.standardizeResponse({ err, message: err.message || err }))
3547
- }
3548
- }
3549
- }
3550
-
3551
- ;// ./lib/helpers/expressHelper/updateOneResult.js
3552
- function updateOneResult({ responseHelper, service }) {
3553
- return async (req, res, next) => {
3554
- try {
3555
- const { body, params } = req
3556
- const { id } = params
3557
- if (id !== body.id) {
3558
- throw new Error('id in params and body must be same')
3559
- }
3560
- const { data } = await service.findOne({ query: { id } })
3561
- const doc = data[0]
3562
- doc.update(body)
3563
- const result = await service.saveOne({ doc })
3564
- res.locals.updateOneResult = result
3565
- await next()
3566
- } catch (err) {
3567
- res.status(400).json(responseHelper.standardizeResponse({ err, message: err.message || err }))
3568
- }
3569
- }
3570
- }
3571
-
3572
- ;// ./lib/helpers/expressHelper/index.js
3573
-
3574
-
3575
-
3576
-
3577
-
3578
-
3579
- const expressHelper = {
3580
- customHandler: customHandler,
3581
- findAllResult: findAllResult,
3582
- findOneResult: findOneResult,
3583
- postResult: postResult,
3584
- updateOneResult: updateOneResult,
3585
- }
3586
-
3587
- ;// ./lib/helpers/extractEmails/extractEmails.js
3588
- /**
3589
- * Extracts and normalizes unique email addresses from an array containing messy entries
3590
- * @param {Array} dirtyArray - Array that may contain emails in various formats (may include null/empty entries)
3591
- * @returns {Array} Sorted array of unique, lowercase email addresses
3592
- */
3593
- function extractEmails(dirtyArray) {
3594
- const emailRegex = /[\w.%+-]+@[a-z0-9.-]+\.[a-z]{2,}/gi
3595
- const emails = new Set()
3596
-
3597
- // Handle null/undefined input array
3598
- if (!dirtyArray)
3599
- return []
3600
-
3601
- dirtyArray.forEach((entry) => {
3602
- // Skip null, undefined, empty, or whitespace-only entries
3603
- if (!entry || typeof entry !== 'string' || !entry.trim())
3604
- return
3605
-
3606
- try {
3607
- const cleanEntry = entry
3608
- .replace(/[\u200B-\u200D\uFEFF\u202A-\u202E]/g, '') // Remove hidden chars
3609
- .replace(/[<>]/g, ' ') // Convert email delimiters to spaces
3610
- .replace(/\s+/g, ' ') // Collapse multiple whitespace
3611
- .trim()
3612
-
3613
- // Extract all email matches
3614
- const matches = cleanEntry.match(emailRegex)
3615
- if (matches) {
3616
- matches.forEach((email) => emails.add(email.toLowerCase())) // Normalize to lowercase
3617
- }
3618
- } catch (e) {
3619
- console.warn('Failed to process entry:', entry, e)
3620
- }
3621
- })
3622
-
3623
- // Convert Set to array and sort alphabetically
3624
- return Array.from(emails).sort((a, b) => a.localeCompare(b))
3625
- }
3626
-
3627
- ;// ./lib/helpers/extractEmails/index.js
3628
-
3629
-
3630
- ;// ./lib/helpers/pReduce/pReduce.js
3631
- async function pReduce(iterable, reducer, initialValue) {
3632
- return new Promise((resolve, reject) => {
3633
- const iterator = iterable[Symbol.iterator]()
3634
- let index = 0
3635
-
3636
- const next = async (total) => {
3637
- const element = iterator.next()
3638
-
3639
- if (element.done) {
3640
- resolve(total)
3641
- return
3642
- }
3643
-
3644
- try {
3645
- const [resolvedTotal, resolvedValue] = await Promise.all([total, element.value])
3646
- next(reducer(resolvedTotal, resolvedValue, index++))
3647
- } catch (error) {
3648
- reject(error)
3649
- }
3650
- }
3651
-
3652
- next(initialValue)
3653
- })
3654
- }
3655
-
3656
-
3657
-
3658
- ;// ./lib/helpers/generalPost/generalPost.js
3659
-
3660
-
3661
-
3662
-
3663
-
3664
- async function generalPost({ body = {}, GeneralModel, UniqueKeyGenerator, resourceInfo }) {
3665
- const { resources, data, globalShared = {}, shared = {}, relationship = {} } = body
3666
- const _resourceInfo = resourceInfo || body.resourceInfo
3667
- _attachShared(data, globalShared, shared)
3668
- const obj = await pReduce(resources, async (acc, resource) => {
3669
- const service = _makeService(resource, _resourceInfo, UniqueKeyGenerator, GeneralModel)
3670
- _createRelationship(data, relationship[resource], acc)
3671
- const _data = data[resource]
3672
- const result = await service.saveAll({ docs: [].concat(_data) })
3673
- acc[resource] = Array.isArray(_data) ? result._data : result._data[0]
3674
- return acc
3675
- }, {})
3676
- return obj
3677
- }
3678
-
3679
- function _attachShared(data, globalShared = {}, shared = {}) {
3680
- Object.keys(shared).forEach((key) => {
3681
- const _data = data[key]
3682
- if (Array.isArray(_data)) {
3683
- data[key] = _data.map((_dataItem) => {
3684
- return objectHelper.merge({}, _dataItem, globalShared, shared[key] || {})
3685
- })
3686
- } else {
3687
- data[key] = objectHelper.merge({}, _data, globalShared, shared[key] || {})
3688
- }
3689
- })
3690
- }
3691
-
3692
- function _createRelationship(data, relationship = {}, object) {
3693
- Object.keys(relationship).forEach((key) => {
3694
- const path = relationship[key]
3695
- const val = objectHelper.get(object, path)
3696
- objectHelper.set(data, key, val)
3697
- })
3698
- }
3699
-
3700
- function _makeService(resource, resourceInfo, UniqueKeyGenerator, GeneralModel) {
3701
- const { collectionName, fields } = resourceInfo[resource]
3702
- const uniqueKeyGenerator = UniqueKeyGenerator.makeGenerator(fields)
3703
- const model = new GeneralModel({ collectionName, uniqueKeyGenerator })
3704
- return makeService({
3705
- repo: new Repo({ model })
3706
- })
3707
- }
3708
-
3709
-
3710
-
3711
- ;// ./lib/helpers/generalPost/index.js
3712
-
3713
-
3714
-
3715
-
3716
- ;// ./lib/helpers/getObjectByArr/getObjectByArr.js
3717
-
3718
-
3719
- function getObjectByArr(arr, data, getValueByKeys, getValidation, KeyValueObject) {
3720
- const _KeyValueObject = KeyValueObject || keyValueObject_KeyValueObject
3721
- if (!Array.isArray(arr) || arr.length === 0) {
3722
- return null
3723
- }
3724
- return arr.reduce((acc, e) => {
3725
- const { key, type, value, restriction } = e
3726
- const isValid = getValidation && typeof getValidation === 'function' ? getValidation({ rule: restriction, data }) : true
3727
- if (isValid) {
3728
- let _value = value
3729
- switch (type) {
3730
- case 'array': {
3731
- // _value = _getObjectByArr(value, data, getValueByKeys, getValidation)
3732
- _value = value.map((el) => {
3733
- const result = getValueByKeys({ keys: el.value.split('.'), obj: data })
3734
- return result
3735
- })
3736
- break
3737
- }
3738
- case 'fromKeyValue': {
3739
- const { dataPath, key: valueKey } = value
3740
- const keyValues = getValueByKeys({ keys: dataPath.split('.'), obj: data })
3741
- _value = _KeyValueObject.getValuesByKey(keyValues, valueKey)[0]
3742
- break
3743
- }
3744
- case 'toKeyValue': {
3745
- const keyValues = getValueByKeys({ keys: value.split('.'), obj: data })
3746
- _value = _KeyValueObject.fromObject(keyValues)
3747
- break
3748
- }
3749
- case 'nested': {
3750
- _value = getObjectByArr(value, data, getValueByKeys, getValidation)
3751
- break
3752
- }
3753
- case 'path': {
3754
- _value = getValueByKeys({ keys: value.split('.'), obj: data })
3755
- break
3756
- }
3757
- // should be deleted
3758
- case 'orgin': {
3759
- _value = value
3760
- break
3761
- }
3762
- case 'origin': {
3763
- _value = value
3764
- break
3765
- }
3766
- default: {
3767
- _value = value
3768
- break
3769
- }
3770
- }
3771
- if (key) {
3772
- return {
3773
- ...acc,
3774
- [key]: _value,
3775
- }
3776
- }
3777
- if (typeof _value === 'string') {
3778
- return _value
3779
- }
3780
- return {
3781
- ...acc,
3782
- ..._value,
3783
- }
3784
- }
3785
- return acc
3786
- }, {})
3787
- }
3788
-
3789
-
3790
- /* harmony default export */ const getObjectByArr_getObjectByArr = ({
3791
- getObjectByArr,
3792
- });
3793
-
3794
-
3795
- ;// ./lib/helpers/getObjectByArr/index.js
3796
-
3797
-
3798
- ;// ./lib/helpers/groupArrayByKey/groupArrayByKey.js
3799
- function groupArrayByKey(arr, key) {
3800
- if (!key || typeof key !== 'string') {
3801
- return {}
3802
- }
3803
- return arr.reduce((acc, curr) => {
3804
- if (!acc[curr[key]]) {
3805
- acc[curr[key]] = 0
3806
- }
3807
- acc[curr[key]]++
3808
- return acc
3809
- }, {})
3810
- }
3811
-
3812
- ;// ./lib/helpers/groupArrayByKey/index.js
3813
-
3814
-
3815
- ;// ./lib/helpers/init/init.js
3816
- function init(_class, options) {
3817
- if (options instanceof _class) {
3818
- return options
3819
- }
3820
- try {
3821
- const instance = new _class(options)
3822
- return instance.isValid !== false ? instance : null
3823
- } catch (e) {
3824
- console.log(`init failed for class: ${_class._classname || 'no _classname'}`, e)
3825
- return null
3826
- }
3827
- }
3828
-
3829
- ;// ./lib/helpers/init/index.js
3830
-
3831
-
3832
- ;// ./lib/helpers/initFromArray/initFromArray.js
3833
-
3834
-
3835
- function initFromArray(_class, arr) {
3836
- if (Array.isArray(arr)) {
3837
- return arr.map((a) => init(_class, a))
3838
- }
3839
- return []
3840
- }
3841
-
3842
- ;// ./lib/helpers/initFromArray/index.js
3843
-
3844
-
3845
- ;// ./lib/helpers/initOnlyValidFromArray/initOnlyValidFromArray.js
3846
-
3847
-
3848
- function initOnlyValidFromArray(_class, arr) {
3849
- return initFromArray(_class, arr).filter((i) => i)
3850
- }
3851
-
3852
- ;// ./lib/helpers/initOnlyValidFromArray/index.js
3853
-
3854
-
3855
- ;// ./lib/helpers/isConvertibleToNumber/index.js
3856
-
3857
-
3858
- ;// ./lib/helpers/mergeArraysByKey/mergeArraysByKey.js
3859
- function mergeArraysByKey(arr1, arr2) {
3860
- // Handle undefined/null inputs by defaulting to empty arrays
3861
- const safeArr1 = Array.isArray(arr1) ? arr1 : []
3862
- const safeArr2 = Array.isArray(arr2) ? arr2 : []
3863
-
3864
- const mergedMap = new Map()
3865
-
3866
- // Helper function to merge values based on their type
3867
- const mergeValues = (existingValue, newValue) => {
3868
- if (existingValue === undefined)
3869
- return newValue
3870
-
3871
- // Handle arrays by concatenating
3872
- if (Array.isArray(existingValue) && Array.isArray(newValue)) {
3873
- return [...new Set([...existingValue, ...newValue])]
3874
- }
3875
-
3876
- // Handle objects by merging
3877
- if (typeof existingValue === 'object' && typeof newValue === 'object'
3878
- && !Array.isArray(existingValue) && !Array.isArray(newValue)) {
3879
- return { ...existingValue, ...newValue }
3880
- }
3881
-
3882
- // // Handle numbers by adding
3883
- // if (typeof existingValue === 'number' && typeof newValue === 'number') {
3884
- // return existingValue
3885
- // }
3886
-
3887
- // // Handle strings by concatenating
3888
- // if (typeof existingValue === 'string' && typeof newValue === 'string') {
3889
- // return existingValue
3890
- // }
3891
-
3892
- // Default: use the new value
3893
- return newValue
3894
- }
3895
-
3896
- // Process first array
3897
- safeArr1.forEach((item) => {
3898
- mergedMap.set(item.key, item.value)
3899
- })
3900
-
3901
- // Process second array and merge values
3902
- safeArr2.forEach((item) => {
3903
- const existingValue = mergedMap.get(item.key)
3904
- mergedMap.set(item.key, mergeValues(existingValue, item.value))
3905
- })
3906
-
3907
- // Convert back to array format
3908
- return Array.from(mergedMap.entries()).map(([key, value]) => ({
3909
- key,
3910
- value
3911
- }))
3912
- }
3913
-
3914
- ;// ./lib/helpers/mergeArraysByKey/index.js
3915
-
3916
-
3917
- ;// ./lib/helpers/padZeros/padZeros.js
3918
- function padZeros(num, minLength = 6) {
3919
- num = num.toString()
3920
- if (num.length < minLength) {
3921
- return padZeros(`0${num}`, minLength)
3922
- }
3923
- return num
3924
- }
3925
-
3926
-
3927
-
3928
- ;// ./lib/helpers/padZeros/index.js
3929
-
3930
-
3931
-
3932
-
3933
- ;// ./lib/helpers/pReduce/index.js
3934
-
3935
-
3936
-
3937
-
3938
- ;// ./lib/helpers/replacePlaceholders/replacePlaceholders.js
3939
- function replacePlaceholders({ content, mapping }) {
3940
- let isObjectMode = false
3941
-
3942
- if (typeof content === 'object' && content !== null) {
3943
- content = JSON.stringify(content)
3944
- isObjectMode = true
3945
- }
3946
-
3947
- /**
3948
- // [[ eventRegistration.eventRegistrationCode | 0 ]]
3949
- const regex = /(\[*)\[\[\s*([\w.\-]+)(?:\s*\|\s*([^:\]\s]+))?(?:\s*:\s*([^\]\s]+))?\s*\]\](\]*)/g
3950
-
3951
- const result = content.replace(regex, (match, leadingBrackets, path, defaultValue, type, trailingBrackets) => {
3952
- // Split the path into parts
3953
- const keys = path.trim().split('.')
3954
-
3955
- // Traverse the nested object structure
3956
- let value = mapping
3957
- for (const key of keys) {
3958
- // Handle empty keys (in case of double dots or leading/trailing dots)
3959
- if (!key)
3960
- continue
3961
-
3962
- value = value?.[key]
3963
- if (value === undefined) {
3964
- break
3965
- }
3966
- }
3967
-
3968
- // Apply default if missing
3969
- if (value === undefined)
3970
- value = defaultValue?.trim()
3971
- if (value === undefined)
3972
- return isObjectMode ? undefined : match
3973
-
3974
- value = value !== undefined
3975
- ? leadingBrackets + value + trailingBrackets
3976
- : match
3977
-
3978
- // Return replacement or original if not found
3979
- return value
3980
- })
3981
- */
3982
-
3983
- // Regex to match both simple and complex expressions
3984
- const regex = /\[\[\s*([^[\]]+?)\s*\]\]/g;
3985
-
3986
- const result = content.replace(regex, (match, expression) => {
3987
- // Trim whitespace from the expression
3988
- const trimmedExpr = expression.trim();
3989
-
3990
- // Check if it's a simple path (alphanumeric, dots, hyphens only)
3991
- if (/^[\w.\-]+$/.test(trimmedExpr)) {
3992
- // Try to find this path in the mapping
3993
- const keys = trimmedExpr.split('.');
3994
- let value = mapping;
3995
-
3996
- for (const key of keys) {
3997
- if (!key) continue;
3998
- value = value?.[key];
3999
- if (value === undefined) break;
4000
- }
4001
-
4002
- // If found in mapping, return the value
4003
- if (value !== undefined) {
4004
- return value;
4005
- }
4006
- }
4007
-
4008
- // For complex expressions or unmatched simple expressions, convert to EJS syntax
4009
- return `<%= ${trimmedExpr} %>`;
4010
- })
4011
-
4012
- if (isObjectMode) {
4013
- return JSON.parse(result)
4014
- }
4015
- return result
4016
- }
4017
-
4018
- ;// ./lib/helpers/replacePlaceholders/index.js
4019
-
4020
-
4021
- ;// ./lib/helpers/sanitizeText/sanitizeText.js
4022
- /**
4023
- * Sanitizes input by removing hidden/control characters with customizable whitespace handling.
4024
- * @param {string} input - The string to sanitize.
4025
- * @param {object} [options] - Configuration options.
4026
- * @param {boolean} [options.normalizeWhitespace] - Collapse multiple spaces/tabs into one space.
4027
- * @param {boolean} [options.removeNewlines] - If true, replaces newlines with spaces.
4028
- * @param {boolean} [options.trim] - If true, trims leading/trailing whitespace.
4029
- * @param {boolean} [options.debug] - If true, logs debug information about removed characters.
4030
- * @returns {string} The sanitized string.
4031
- */
4032
- function sanitizeText(input, options = {}) {
4033
- const {
4034
- normalizeWhitespace = true,
4035
- removeNewlines = false,
4036
- trim = true,
4037
- preserveBasicWhitespace = true,
4038
- debug = false, // new option for debugging
4039
- } = options
4040
-
4041
- if (typeof input !== 'string') {
4042
- return input
4043
- }
4044
-
4045
- let result = input
4046
-
4047
- if (debug) {
4048
- console.log('Original input:', JSON.stringify(input))
4049
- console.log('Options:', { normalizeWhitespace, removeNewlines, trim, preserveBasicWhitespace })
4050
- }
4051
-
4052
- // Phase 1: Remove all control characters except basic whitespace if requested
4053
- if (preserveBasicWhitespace && !removeNewlines) {
4054
- if (debug) {
4055
- const before = result
4056
- const matches = []
4057
- // Use a replacer function to capture what's being removed
4058
- result = result.replace(/[\x00-\x08\v\f\x0E-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g, (match) => {
4059
- matches.push({
4060
- char: match,
4061
- code: match.charCodeAt(0),
4062
- hex: `0x${match.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0')}`
4063
- })
4064
- return ''
4065
- })
4066
- if (matches.length > 0) {
4067
- console.log('Phase 1 (preserve mode) - Removed characters:')
4068
- matches.forEach((m) => {
4069
- console.log(` - Character: ${JSON.stringify(m.char)}, Code: ${m.code}, Hex: ${m.hex}`)
4070
- })
4071
- console.log(`Removed ${matches.length} control character(s)`)
4072
- } else {
4073
- console.log('Phase 1 (preserve mode) - No control characters found')
4074
- }
4075
- } else {
4076
- result = result.replace(/[\x00-\x08\v\f\x0E-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g, '')
4077
- }
4078
- } else {
4079
- if (debug) {
4080
- const before = result
4081
- const matches = []
4082
- result = result.replace(/[\x00-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g, (match) => {
4083
- matches.push({
4084
- char: match,
4085
- code: match.charCodeAt(0),
4086
- hex: `0x${match.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0')}`
4087
- })
4088
- return ''
4089
- })
4090
- if (matches.length > 0) {
4091
- console.log('Phase 1 (full removal mode) - Removed characters:')
4092
- matches.forEach((m) => {
4093
- console.log(` - Character: ${JSON.stringify(m.char)}, Code: ${m.code}, Hex: ${m.hex}`)
4094
- })
4095
- console.log(`Removed ${matches.length} control character(s)`)
4096
- } else {
4097
- console.log('Phase 1 (full removal mode) - No control characters found')
4098
- }
4099
- } else {
4100
- result = result.replace(/[\x00-\x1F\x7F-\x9F\u200B-\u200D\uFEFF\u202A-\u202E]/g, '')
4101
- }
4102
- }
4103
-
4104
- if (debug) {
4105
- console.log('After Phase 1:', JSON.stringify(result))
4106
- }
4107
-
4108
- // Phase 2: Handle whitespace transformations
4109
- if (removeNewlines) {
4110
- if (debug) {
4111
- const before = result
4112
- result = result.replace(/[\r\n]+/g, ' ')
4113
- console.log('Phase 2 - Converted newlines to spaces')
4114
- } else {
4115
- result = result.replace(/[\r\n]+/g, ' ')
4116
- }
4117
- }
4118
-
4119
- if (normalizeWhitespace) {
4120
- if (debug) {
4121
- const before = result
4122
- result = result.replace(/[ \t]+/g, ' ')
4123
- console.log('Phase 2 - Normalized whitespace')
4124
- } else {
4125
- result = result.replace(/[ \t]+/g, ' ')
4126
- }
4127
- }
4128
-
4129
- if (debug) {
4130
- console.log('After Phase 2:', JSON.stringify(result))
4131
- }
4132
-
4133
- // Phase 3: Final trimming
4134
- if (trim) {
4135
- if (debug) {
4136
- const before = result
4137
- result = result.trim()
4138
- console.log('Phase 3 - Trimmed leading/trailing whitespace')
4139
- } else {
4140
- result = result.trim()
4141
- }
4142
- }
4143
-
4144
- if (debug) {
4145
- console.log('Final result:', JSON.stringify(result))
4146
- console.log('--- Sanitization complete ---')
4147
- }
4148
-
4149
- return result
4150
- }
4151
-
4152
- ;// ./lib/helpers/sanitizeText/index.js
4153
-
4154
-
4155
- ;// ./lib/helpers/shuffleArray/shuffleArray.js
4156
- function shuffleArray(array) {
4157
- const arr = [...array]
4158
- for (let i = arr.length - 1; i >= 0; i--) { // Changed `i > 0` to `i >= 0`
4159
- const j = Math.floor(Math.random() * (i + 1));
4160
- [arr[i], arr[j]] = [arr[j], arr[i]]
4161
- }
4162
- return arr
4163
- }
4164
-
4165
- ;// ./lib/helpers/shuffleArray/index.js
4166
-
4167
-
4168
- ;// ./lib/helpers/stringFormatter/index.js
4169
-
4170
-
4171
-
4172
-
4173
- ;// ./lib/helpers/stringHelper/stringHelper.js
4174
- function baseXEncode(num, base = 34) {
4175
- const charset = getBaseCharset(base)
4176
- return encode(num, charset)
4177
- }
4178
-
4179
- function encode(int, charset) {
4180
- const { byCode } = charset
4181
- if (int === 0) {
4182
- return byCode[0]
4183
- }
4184
-
4185
- let res = ''
4186
- const max = charset.length
4187
- while (int > 0) {
4188
- res = byCode[int % max] + res
4189
- int = Math.floor(int / max)
4190
- }
4191
- return res
4192
- }
4193
-
4194
- function getBaseCharset(base) {
4195
- let charset = '9876543210ABCDEFGHJKLMNPQRSTUVWXYZ'
4196
- if (base === 58) {
4197
- charset = '9876543210ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz'
4198
- }
4199
- return indexCharset(charset)
4200
- }
4201
-
4202
- function indexCharset(str) {
4203
- const byCode = {}
4204
- const byChar = {}
4205
- const { length } = str
4206
- let char
4207
- for (let i = 0; i < length; i++) {
4208
- char = str[i]
4209
- byCode[i] = char
4210
- byChar[char] = i
4211
- }
4212
- return { byCode, byChar, length }
4213
- }
4214
-
4215
- function isSame(str1, str2) {
4216
- if (typeof str1 !== 'string' || typeof str2 !== 'string') {
4217
- return false
4218
- }
4219
- return str1.trim().toUpperCase() === str2.trim().toUpperCase()
4220
- }
4221
-
4222
- function randomString({ len = 16, pattern = 'a1' } = {}) {
4223
- const A = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
4224
- const a = 'abcdefghijklmnopqrstuvwxyz'
4225
- const num = '1234567890'
4226
- const mark = '~!@#$%^&*_+-='
4227
- let str = ''
4228
- if (pattern.includes('A')) {
4229
- str += A
4230
- }
4231
- if (pattern.includes('a')) {
4232
- str += a
4233
- }
4234
- if (pattern.includes('1')) {
4235
- str += num
4236
- }
4237
- if (pattern.includes('#')) {
4238
- str += mark
4239
- }
4240
- const chars = [...str]
4241
- return [...new Array(len)].map((i) => {
4242
- return chars[(Math.random() * chars.length) | 0]
4243
- }).join``
4244
- }
4245
-
4246
- function reverse(str) {
4247
- const _str = (typeof str !== 'string') ? str.toString() : str
4248
- const splitString = _str.split('')
4249
- const reverseArray = splitString.reverse()
4250
- return reverseArray.join('')
4251
- }
4252
-
4253
- function setCode(base = 34) {
4254
- const now = (new Date()).valueOf()
4255
- const random = randomString({
4256
- len: 8,
4257
- pattern: '1'
4258
- })
4259
- const str = reverse(`${now}${random}`)
4260
- // const str = `${now}${random}`
4261
- return baseXEncode(str, base)
4262
- }
4263
-
4264
- function toCamelCase(str) {
4265
- if (!str)
4266
- return ''
4267
- return str
4268
- .trim()
4269
- .split(/\s+/)
4270
- .map((word, index) => {
4271
- if (!word)
4272
- return ''
4273
- if (index === 0) {
4274
- return word.toLowerCase()
4275
- }
4276
- return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
4277
- })
4278
- .join('')
4279
- }
4280
-
4281
- function toLowerCase(str) {
4282
- if (!str)
4283
- return ''
4284
- return str
4285
- .trim()
4286
- .toLowerCase()
4287
- }
4288
-
4289
- const stringHelper = {
4290
- isSame,
4291
- setCode,
4292
- toCamelCase,
4293
- toLowerCase,
4294
- }
4295
-
4296
-
4297
-
4298
- ;// ./lib/helpers/stringHelper/index.js
4299
-
4300
-
4301
-
4302
-
4303
- ;// ./lib/helpers/trackingPlugin/trackingPlugin.js
4304
- function trackingPlugin(schema, options) {
4305
- // Add meta fields
4306
- schema.add({
4307
- meta: {
4308
- active: { type: Boolean, default: true },
4309
- created: { type: Number },
4310
- creator: { type: String },
4311
- deleted: { type: Boolean, default: false },
4312
- modified: { type: Number },
4313
- owner: { type: String },
4314
- }
4315
- })
4316
-
4317
- // Auto-update hook
4318
- schema.pre('save', function (next) {
4319
- this.meta.modified = Date.now()
4320
- next()
4321
- })
4322
-
4323
- // Add core indexes
4324
- schema.index({
4325
- 'meta.active': 1,
4326
- 'meta.deleted': 1
4327
- }, {
4328
- name: 'tracking_status_index',
4329
- background: true,
4330
- partialFilterExpression: {
4331
- 'meta.active': true,
4332
- 'meta.deleted': false
4333
- }
4334
- })
4335
-
4336
- // Optional: Add helper methods
4337
- // schema.methods.touch = function(userId) {
4338
- // this.meta.updatedAt = new Date()
4339
- // this.meta.updatedBy = userId
4340
- // }
4341
- }
4342
-
4343
- ;// ./lib/helpers/tenantPlugin/tenantPlugin.js
4344
-
4345
-
4346
- function tenantPlugin(schema, options) {
4347
- // Apply tracking plugin first if not already present
4348
- if (!schema.path('meta')) {
4349
- trackingPlugin(schema, options)
4350
- }
4351
-
4352
- // Add tenant-specific fields
4353
- schema.add({
4354
- metadata: [{ type: Object }], // Instead of Schema.Types.Mixed
4355
- remarks: [{ type: Object }],
4356
- tenantCode: { type: String, required: true }
4357
- })
4358
-
4359
- // Add core indexes
4360
- schema.index({
4361
- tenantCode: 1
4362
- }, {
4363
- name: 'tenant_core_index',
4364
- background: true
4365
- })
4366
-
4367
- // 1. ENHANCE EXISTING TRACKING INDEXES
4368
- const existingIndexes = schema.indexes()
4369
-
4370
- // Check if tracking_status_index exists
4371
- const hasTenantStatusIndex = existingIndexes.some((idx) =>
4372
- idx.name === 'tenant_status_index' // Check by name for reliability
4373
- )
4374
-
4375
- if (!hasTenantStatusIndex) {
4376
- schema.index({
4377
- tenantCode: 1, // Unique field first
4378
- _type: 1, // Low-cardinality field last
4379
- }, {
4380
- name: 'tenant_status_index',
4381
- background: true,
4382
- partialFilterExpression: {
4383
- '_type': 'Tenant',
4384
- 'meta.active': true,
4385
- 'meta.deleted': false
4386
- }
4387
- })
4388
- }
4389
- }
4390
-
4391
- ;// ./lib/helpers/tenantPlugin/index.js
4392
-
4393
-
4394
- ;// ./lib/helpers/trackingPlugin/index.js
4395
-
4396
-
4397
- ;// ./lib/helpers/index.js
4398
-
4399
-
4400
-
4401
-
4402
-
4403
-
4404
-
4405
-
4406
-
4407
-
4408
-
4409
-
4410
-
4411
-
4412
-
4413
-
4414
-
4415
-
4416
-
4417
-
4418
-
4419
-
4420
-
4421
-
4422
-
4423
-
4424
-
4425
-
4426
-
4427
-
4428
-
4429
-
4430
-
4431
- ;// ./lib/index.js
4432
-
4433
-
4434
-
4435
- ;// ./index.js
4436
-
4437
-
4438
- /******/ return __webpack_exports__;
4439
- /******/ })()
4440
- ;
4441
- });