@questwork/q-utilities 0.1.22 → 0.1.29
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.
- package/.github/workflows/publish.yml +19 -5
- package/dist/index.min.cjs +174 -126
- package/dist/q-utilities.esm.js +174 -126
- package/dist/q-utilities.min.js +174 -126
- package/package.json +9 -9
|
@@ -4,12 +4,13 @@ on:
|
|
|
4
4
|
tags:
|
|
5
5
|
- 'v*'
|
|
6
6
|
workflow_dispatch:
|
|
7
|
+
|
|
7
8
|
jobs:
|
|
8
9
|
publish:
|
|
9
10
|
runs-on: ubuntu-latest
|
|
10
11
|
permissions:
|
|
11
12
|
contents: read
|
|
12
|
-
|
|
13
|
+
id-token: write # OIDC
|
|
13
14
|
# environment: production
|
|
14
15
|
steps:
|
|
15
16
|
- uses: actions/checkout@v4
|
|
@@ -39,8 +40,21 @@ jobs:
|
|
|
39
40
|
pnpm run build
|
|
40
41
|
fi
|
|
41
42
|
|
|
43
|
+
# - name: Publish to npm
|
|
44
|
+
# # if: steps.version-check.outputs.should_publish == 'true'
|
|
45
|
+
# run: pnpm publish --no-git-checks --access public
|
|
46
|
+
# env:
|
|
47
|
+
# NODE_AUTH_TOKEN: ${{ secrets.QW_NPM_TOKEN }}
|
|
48
|
+
|
|
49
|
+
- name: Update npm
|
|
50
|
+
run: |
|
|
51
|
+
NPM_VERSION=$(npm -v)
|
|
52
|
+
echo "Current npm version: $NPM_VERSION"
|
|
53
|
+
if ! npx semver -r ">=11.5.1" "$NPM_VERSION"; then
|
|
54
|
+
echo "npm version $NPM_VERSION is too old. Installing latest npm..."
|
|
55
|
+
npm install -g npm@latest
|
|
56
|
+
echo "Updated npm version: $(npm -v)"
|
|
57
|
+
fi
|
|
58
|
+
|
|
42
59
|
- name: Publish to npm
|
|
43
|
-
|
|
44
|
-
run: pnpm publish --no-git-checks --access public
|
|
45
|
-
env:
|
|
46
|
-
NODE_AUTH_TOKEN: ${{ secrets.QW_NPM_TOKEN }}
|
|
60
|
+
run: npm publish --no-git-checks --access public
|
package/dist/index.min.cjs
CHANGED
|
@@ -522,7 +522,147 @@ class AwsStsS3Client {
|
|
|
522
522
|
|
|
523
523
|
|
|
524
524
|
|
|
525
|
+
;// ./lib/helpers/objectHelper/objectHelper.js
|
|
526
|
+
const objectHelper = {
|
|
527
|
+
get(obj, path) {
|
|
528
|
+
const parts = path.split('.')
|
|
529
|
+
return parts.reduce((acc, part) => {
|
|
530
|
+
if (part.endsWith('[]')) {
|
|
531
|
+
// 处理数组遍历
|
|
532
|
+
const key = part.slice(0, -2) // 去掉 '[]' 得到属性名
|
|
533
|
+
if (Array.isArray(acc[key])) {
|
|
534
|
+
return acc[key] // 返回整个数组
|
|
535
|
+
}
|
|
536
|
+
return [] // 如果不是数组,返回空数组
|
|
537
|
+
}
|
|
538
|
+
if (part.includes('[') && part.includes(']')) {
|
|
539
|
+
// 处理数组索引
|
|
540
|
+
const arrayMatch = part.match(/(\w+)\[(\d+)\]/)
|
|
541
|
+
if (arrayMatch) {
|
|
542
|
+
const key = arrayMatch[1]
|
|
543
|
+
const index = arrayMatch[2]
|
|
544
|
+
return acc && acc[key] && acc[key][index]
|
|
545
|
+
}
|
|
546
|
+
} else if (acc && Array.isArray(acc)) {
|
|
547
|
+
// 如果当前值是数组,提取每个对象的指定属性
|
|
548
|
+
return acc.map((item) => item[part])
|
|
549
|
+
} else {
|
|
550
|
+
// 处理普通属性
|
|
551
|
+
return acc && acc[part]
|
|
552
|
+
}
|
|
553
|
+
}, obj)
|
|
554
|
+
},
|
|
555
|
+
isPlainObject,
|
|
556
|
+
merge,
|
|
557
|
+
set(obj, path, value) {
|
|
558
|
+
const parts = path.split('.')
|
|
559
|
+
let current = obj
|
|
560
|
+
|
|
561
|
+
// 处理所有中间部分
|
|
562
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
563
|
+
const part = parts[i]
|
|
564
|
+
let key, index
|
|
565
|
+
|
|
566
|
+
// 检查是否是数组索引格式,如key[0]
|
|
567
|
+
const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/)
|
|
568
|
+
if (arrayMatch) {
|
|
569
|
+
key = arrayMatch[1]
|
|
570
|
+
index = Number.parseInt(arrayMatch[2], 10)
|
|
571
|
+
// 确保当前层级的数组存在
|
|
572
|
+
if (!current[key] || !Array.isArray(current[key])) {
|
|
573
|
+
current[key] = []
|
|
574
|
+
}
|
|
575
|
+
// 扩展数组到足够大
|
|
576
|
+
while (current[key].length <= index) {
|
|
577
|
+
current[key].push(undefined)
|
|
578
|
+
}
|
|
579
|
+
// 如果当前位置未定义或为null,初始化为对象
|
|
580
|
+
if (current[key][index] == null) {
|
|
581
|
+
current[key][index] = {}
|
|
582
|
+
}
|
|
583
|
+
current = current[key][index]
|
|
584
|
+
} else {
|
|
585
|
+
// 处理普通属性
|
|
586
|
+
if (!current[part]) {
|
|
587
|
+
current[part] = {}
|
|
588
|
+
}
|
|
589
|
+
current = current[part]
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// 处理最后一部分
|
|
594
|
+
const lastPart = parts[parts.length - 1]
|
|
595
|
+
const arrayMatch = lastPart.match(/^(\w+)\[(\d+)\]$/)
|
|
596
|
+
if (arrayMatch) {
|
|
597
|
+
const key = arrayMatch[1]
|
|
598
|
+
const index = Number.parseInt(arrayMatch[2], 10)
|
|
599
|
+
// 确保数组存在
|
|
600
|
+
if (!current[key] || !Array.isArray(current[key])) {
|
|
601
|
+
current[key] = []
|
|
602
|
+
}
|
|
603
|
+
// 扩展数组到所需索引
|
|
604
|
+
while (current[key].length <= index) {
|
|
605
|
+
current[key].push(undefined)
|
|
606
|
+
}
|
|
607
|
+
current[key][index] = value
|
|
608
|
+
} else {
|
|
609
|
+
current[lastPart] = value
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
function isPlainObject(value) {
|
|
615
|
+
return (
|
|
616
|
+
value !== null
|
|
617
|
+
&& typeof value === 'object'
|
|
618
|
+
&& !Array.isArray(value) &&
|
|
619
|
+
!(value instanceof Date) &&
|
|
620
|
+
!(value instanceof RegExp) &&
|
|
621
|
+
// Optional: exclude other built-in objects
|
|
622
|
+
Object.prototype.toString.call(value) === '[object Object]'
|
|
623
|
+
)
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
function merge(target, ...sources) {
|
|
627
|
+
if (!sources.length)
|
|
628
|
+
return target
|
|
629
|
+
|
|
630
|
+
const source = sources.shift() // 取出第一个源对象
|
|
631
|
+
|
|
632
|
+
if (_isObject(target) && _isObject(source)) {
|
|
633
|
+
for (const key in source) {
|
|
634
|
+
if (_isObject(source[key])) {
|
|
635
|
+
if (!target[key]) {
|
|
636
|
+
// 如果目标对象没有该属性,创建一个空对象
|
|
637
|
+
target[key] = {}
|
|
638
|
+
}
|
|
639
|
+
// 递归合并
|
|
640
|
+
merge(target[key], source[key])
|
|
641
|
+
} else {
|
|
642
|
+
// 直接覆盖
|
|
643
|
+
target[key] = source[key]
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
// 继续合并剩余的源对象
|
|
649
|
+
return merge(target, ...sources)
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
function _isObject(obj) {
|
|
653
|
+
return obj && typeof obj === 'object' && !Array.isArray(obj)
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
|
|
658
|
+
;// ./lib/helpers/objectHelper/index.js
|
|
659
|
+
|
|
660
|
+
|
|
661
|
+
|
|
662
|
+
|
|
525
663
|
;// ./lib/models/keyValueObject/keyValueObject.js
|
|
664
|
+
|
|
665
|
+
|
|
526
666
|
class keyValueObject_KeyValueObject {
|
|
527
667
|
constructor(options = {}) {
|
|
528
668
|
options = options || {}
|
|
@@ -598,6 +738,19 @@ class keyValueObject_KeyValueObject {
|
|
|
598
738
|
static getValueByKey(arr = [], key) {
|
|
599
739
|
return this.foundValueByKey(arr, key)
|
|
600
740
|
}
|
|
741
|
+
static getMetadataValueByKeyAsArray(arr = [], key) {
|
|
742
|
+
const _value = this.getValueByKey(arr, key)
|
|
743
|
+
if (!_value) {
|
|
744
|
+
return []
|
|
745
|
+
}
|
|
746
|
+
if (objectHelper.isPlainObject(_value)) {
|
|
747
|
+
return Object.keys(_value).reduce((acc, key) => {
|
|
748
|
+
acc.push({ key, value: _value[key] })
|
|
749
|
+
return acc
|
|
750
|
+
}, [])
|
|
751
|
+
}
|
|
752
|
+
return _value
|
|
753
|
+
}
|
|
601
754
|
static getValueByKeyFromArray(arr = [], key) {
|
|
602
755
|
if (arr.length === 0) {
|
|
603
756
|
return null
|
|
@@ -1506,6 +1659,7 @@ class ActionRecord {
|
|
|
1506
1659
|
|
|
1507
1660
|
|
|
1508
1661
|
const notUpdateAllowedProps = [
|
|
1662
|
+
'_ActionRecord',
|
|
1509
1663
|
'created',
|
|
1510
1664
|
// 'statusType'
|
|
1511
1665
|
]
|
|
@@ -2722,6 +2876,10 @@ class TenantAwareEntity extends TrackedEntity {
|
|
|
2722
2876
|
}
|
|
2723
2877
|
|
|
2724
2878
|
// instance methods
|
|
2879
|
+
insertOrUpdateMetadata(key, value) {
|
|
2880
|
+
this.metadata = Metadata.insertOrUpdateRecord(this.metadata, key, value)
|
|
2881
|
+
return this
|
|
2882
|
+
}
|
|
2725
2883
|
getMetadata() {
|
|
2726
2884
|
return this.metadata
|
|
2727
2885
|
}
|
|
@@ -2732,6 +2890,21 @@ class TenantAwareEntity extends TrackedEntity {
|
|
|
2732
2890
|
const found = this.getMetadataByKey(key)
|
|
2733
2891
|
return found ? found.value : null
|
|
2734
2892
|
}
|
|
2893
|
+
getMetadataValueByKeys(keys, kv) {
|
|
2894
|
+
if (!Array.isArray(keys)) {
|
|
2895
|
+
return null
|
|
2896
|
+
}
|
|
2897
|
+
kv = kv || this.metadata
|
|
2898
|
+
if (keys.length === 0) {
|
|
2899
|
+
return kv
|
|
2900
|
+
}
|
|
2901
|
+
const key = keys.shift()
|
|
2902
|
+
const _val = Metadata.getMetadataValueByKeyAsArray(kv, key)
|
|
2903
|
+
return this.getMetadataValueByKeys(keys, _val)
|
|
2904
|
+
}
|
|
2905
|
+
getMetadataValueByKeyAsArray(key) {
|
|
2906
|
+
return Metadata.getMetadataValueByKeyAsArray(this.metadata, key)
|
|
2907
|
+
}
|
|
2735
2908
|
getRemarks() {
|
|
2736
2909
|
return this.remarks
|
|
2737
2910
|
}
|
|
@@ -3197,7 +3370,7 @@ function detectControlCharacters(input, options = {}) {
|
|
|
3197
3370
|
|
|
3198
3371
|
return {
|
|
3199
3372
|
hasControlChars: matches.length > 0,
|
|
3200
|
-
matches
|
|
3373
|
+
matches,
|
|
3201
3374
|
totalFound: matches.length,
|
|
3202
3375
|
inputPreview: input.length > 50 ? input.substring(0, 50) + '...' : input,
|
|
3203
3376
|
inputLength: input.length,
|
|
@@ -3423,131 +3596,6 @@ function extractEmails(dirtyArray) {
|
|
|
3423
3596
|
;// ./lib/helpers/extractEmails/index.js
|
|
3424
3597
|
|
|
3425
3598
|
|
|
3426
|
-
;// ./lib/helpers/objectHelper/objectHelper.js
|
|
3427
|
-
const objectHelper = {
|
|
3428
|
-
get(obj, path) {
|
|
3429
|
-
const parts = path.split('.')
|
|
3430
|
-
return parts.reduce((acc, part) => {
|
|
3431
|
-
if (part.endsWith('[]')) {
|
|
3432
|
-
// 处理数组遍历
|
|
3433
|
-
const key = part.slice(0, -2) // 去掉 '[]' 得到属性名
|
|
3434
|
-
if (Array.isArray(acc[key])) {
|
|
3435
|
-
return acc[key] // 返回整个数组
|
|
3436
|
-
}
|
|
3437
|
-
return [] // 如果不是数组,返回空数组
|
|
3438
|
-
}
|
|
3439
|
-
if (part.includes('[') && part.includes(']')) {
|
|
3440
|
-
// 处理数组索引
|
|
3441
|
-
const arrayMatch = part.match(/(\w+)\[(\d+)\]/)
|
|
3442
|
-
if (arrayMatch) {
|
|
3443
|
-
const key = arrayMatch[1]
|
|
3444
|
-
const index = arrayMatch[2]
|
|
3445
|
-
return acc && acc[key] && acc[key][index]
|
|
3446
|
-
}
|
|
3447
|
-
} else if (acc && Array.isArray(acc)) {
|
|
3448
|
-
// 如果当前值是数组,提取每个对象的指定属性
|
|
3449
|
-
return acc.map((item) => item[part])
|
|
3450
|
-
} else {
|
|
3451
|
-
// 处理普通属性
|
|
3452
|
-
return acc && acc[part]
|
|
3453
|
-
}
|
|
3454
|
-
}, obj)
|
|
3455
|
-
},
|
|
3456
|
-
merge,
|
|
3457
|
-
set(obj, path, value) {
|
|
3458
|
-
const parts = path.split('.')
|
|
3459
|
-
let current = obj
|
|
3460
|
-
|
|
3461
|
-
// 处理所有中间部分
|
|
3462
|
-
for (let i = 0; i < parts.length - 1; i++) {
|
|
3463
|
-
const part = parts[i]
|
|
3464
|
-
let key, index
|
|
3465
|
-
|
|
3466
|
-
// 检查是否是数组索引格式,如key[0]
|
|
3467
|
-
const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/)
|
|
3468
|
-
if (arrayMatch) {
|
|
3469
|
-
key = arrayMatch[1]
|
|
3470
|
-
index = Number.parseInt(arrayMatch[2], 10)
|
|
3471
|
-
// 确保当前层级的数组存在
|
|
3472
|
-
if (!current[key] || !Array.isArray(current[key])) {
|
|
3473
|
-
current[key] = []
|
|
3474
|
-
}
|
|
3475
|
-
// 扩展数组到足够大
|
|
3476
|
-
while (current[key].length <= index) {
|
|
3477
|
-
current[key].push(undefined)
|
|
3478
|
-
}
|
|
3479
|
-
// 如果当前位置未定义或为null,初始化为对象
|
|
3480
|
-
if (current[key][index] == null) {
|
|
3481
|
-
current[key][index] = {}
|
|
3482
|
-
}
|
|
3483
|
-
current = current[key][index]
|
|
3484
|
-
} else {
|
|
3485
|
-
// 处理普通属性
|
|
3486
|
-
if (!current[part]) {
|
|
3487
|
-
current[part] = {}
|
|
3488
|
-
}
|
|
3489
|
-
current = current[part]
|
|
3490
|
-
}
|
|
3491
|
-
}
|
|
3492
|
-
|
|
3493
|
-
// 处理最后一部分
|
|
3494
|
-
const lastPart = parts[parts.length - 1]
|
|
3495
|
-
const arrayMatch = lastPart.match(/^(\w+)\[(\d+)\]$/)
|
|
3496
|
-
if (arrayMatch) {
|
|
3497
|
-
const key = arrayMatch[1]
|
|
3498
|
-
const index = Number.parseInt(arrayMatch[2], 10)
|
|
3499
|
-
// 确保数组存在
|
|
3500
|
-
if (!current[key] || !Array.isArray(current[key])) {
|
|
3501
|
-
current[key] = []
|
|
3502
|
-
}
|
|
3503
|
-
// 扩展数组到所需索引
|
|
3504
|
-
while (current[key].length <= index) {
|
|
3505
|
-
current[key].push(undefined)
|
|
3506
|
-
}
|
|
3507
|
-
current[key][index] = value
|
|
3508
|
-
} else {
|
|
3509
|
-
current[lastPart] = value
|
|
3510
|
-
}
|
|
3511
|
-
}
|
|
3512
|
-
}
|
|
3513
|
-
|
|
3514
|
-
function merge(target, ...sources) {
|
|
3515
|
-
if (!sources.length)
|
|
3516
|
-
return target
|
|
3517
|
-
|
|
3518
|
-
const source = sources.shift() // 取出第一个源对象
|
|
3519
|
-
|
|
3520
|
-
if (_isObject(target) && _isObject(source)) {
|
|
3521
|
-
for (const key in source) {
|
|
3522
|
-
if (_isObject(source[key])) {
|
|
3523
|
-
if (!target[key]) {
|
|
3524
|
-
// 如果目标对象没有该属性,创建一个空对象
|
|
3525
|
-
target[key] = {}
|
|
3526
|
-
}
|
|
3527
|
-
// 递归合并
|
|
3528
|
-
merge(target[key], source[key])
|
|
3529
|
-
} else {
|
|
3530
|
-
// 直接覆盖
|
|
3531
|
-
target[key] = source[key]
|
|
3532
|
-
}
|
|
3533
|
-
}
|
|
3534
|
-
}
|
|
3535
|
-
|
|
3536
|
-
// 继续合并剩余的源对象
|
|
3537
|
-
return merge(target, ...sources)
|
|
3538
|
-
}
|
|
3539
|
-
|
|
3540
|
-
function _isObject(obj) {
|
|
3541
|
-
return obj && typeof obj === 'object' && !Array.isArray(obj)
|
|
3542
|
-
}
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
;// ./lib/helpers/objectHelper/index.js
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
3599
|
;// ./lib/helpers/pReduce/pReduce.js
|
|
3552
3600
|
async function pReduce(iterable, reducer, initialValue) {
|
|
3553
3601
|
return new Promise((resolve, reject) => {
|
package/dist/q-utilities.esm.js
CHANGED
|
@@ -447,7 +447,147 @@ class AwsStsS3Client {
|
|
|
447
447
|
|
|
448
448
|
|
|
449
449
|
|
|
450
|
+
;// ./lib/helpers/objectHelper/objectHelper.js
|
|
451
|
+
const objectHelper = {
|
|
452
|
+
get(obj, path) {
|
|
453
|
+
const parts = path.split('.')
|
|
454
|
+
return parts.reduce((acc, part) => {
|
|
455
|
+
if (part.endsWith('[]')) {
|
|
456
|
+
// 处理数组遍历
|
|
457
|
+
const key = part.slice(0, -2) // 去掉 '[]' 得到属性名
|
|
458
|
+
if (Array.isArray(acc[key])) {
|
|
459
|
+
return acc[key] // 返回整个数组
|
|
460
|
+
}
|
|
461
|
+
return [] // 如果不是数组,返回空数组
|
|
462
|
+
}
|
|
463
|
+
if (part.includes('[') && part.includes(']')) {
|
|
464
|
+
// 处理数组索引
|
|
465
|
+
const arrayMatch = part.match(/(\w+)\[(\d+)\]/)
|
|
466
|
+
if (arrayMatch) {
|
|
467
|
+
const key = arrayMatch[1]
|
|
468
|
+
const index = arrayMatch[2]
|
|
469
|
+
return acc && acc[key] && acc[key][index]
|
|
470
|
+
}
|
|
471
|
+
} else if (acc && Array.isArray(acc)) {
|
|
472
|
+
// 如果当前值是数组,提取每个对象的指定属性
|
|
473
|
+
return acc.map((item) => item[part])
|
|
474
|
+
} else {
|
|
475
|
+
// 处理普通属性
|
|
476
|
+
return acc && acc[part]
|
|
477
|
+
}
|
|
478
|
+
}, obj)
|
|
479
|
+
},
|
|
480
|
+
isPlainObject,
|
|
481
|
+
merge,
|
|
482
|
+
set(obj, path, value) {
|
|
483
|
+
const parts = path.split('.')
|
|
484
|
+
let current = obj
|
|
485
|
+
|
|
486
|
+
// 处理所有中间部分
|
|
487
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
488
|
+
const part = parts[i]
|
|
489
|
+
let key, index
|
|
490
|
+
|
|
491
|
+
// 检查是否是数组索引格式,如key[0]
|
|
492
|
+
const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/)
|
|
493
|
+
if (arrayMatch) {
|
|
494
|
+
key = arrayMatch[1]
|
|
495
|
+
index = Number.parseInt(arrayMatch[2], 10)
|
|
496
|
+
// 确保当前层级的数组存在
|
|
497
|
+
if (!current[key] || !Array.isArray(current[key])) {
|
|
498
|
+
current[key] = []
|
|
499
|
+
}
|
|
500
|
+
// 扩展数组到足够大
|
|
501
|
+
while (current[key].length <= index) {
|
|
502
|
+
current[key].push(undefined)
|
|
503
|
+
}
|
|
504
|
+
// 如果当前位置未定义或为null,初始化为对象
|
|
505
|
+
if (current[key][index] == null) {
|
|
506
|
+
current[key][index] = {}
|
|
507
|
+
}
|
|
508
|
+
current = current[key][index]
|
|
509
|
+
} else {
|
|
510
|
+
// 处理普通属性
|
|
511
|
+
if (!current[part]) {
|
|
512
|
+
current[part] = {}
|
|
513
|
+
}
|
|
514
|
+
current = current[part]
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// 处理最后一部分
|
|
519
|
+
const lastPart = parts[parts.length - 1]
|
|
520
|
+
const arrayMatch = lastPart.match(/^(\w+)\[(\d+)\]$/)
|
|
521
|
+
if (arrayMatch) {
|
|
522
|
+
const key = arrayMatch[1]
|
|
523
|
+
const index = Number.parseInt(arrayMatch[2], 10)
|
|
524
|
+
// 确保数组存在
|
|
525
|
+
if (!current[key] || !Array.isArray(current[key])) {
|
|
526
|
+
current[key] = []
|
|
527
|
+
}
|
|
528
|
+
// 扩展数组到所需索引
|
|
529
|
+
while (current[key].length <= index) {
|
|
530
|
+
current[key].push(undefined)
|
|
531
|
+
}
|
|
532
|
+
current[key][index] = value
|
|
533
|
+
} else {
|
|
534
|
+
current[lastPart] = value
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
function isPlainObject(value) {
|
|
540
|
+
return (
|
|
541
|
+
value !== null
|
|
542
|
+
&& typeof value === 'object'
|
|
543
|
+
&& !Array.isArray(value) &&
|
|
544
|
+
!(value instanceof Date) &&
|
|
545
|
+
!(value instanceof RegExp) &&
|
|
546
|
+
// Optional: exclude other built-in objects
|
|
547
|
+
Object.prototype.toString.call(value) === '[object Object]'
|
|
548
|
+
)
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
function merge(target, ...sources) {
|
|
552
|
+
if (!sources.length)
|
|
553
|
+
return target
|
|
554
|
+
|
|
555
|
+
const source = sources.shift() // 取出第一个源对象
|
|
556
|
+
|
|
557
|
+
if (_isObject(target) && _isObject(source)) {
|
|
558
|
+
for (const key in source) {
|
|
559
|
+
if (_isObject(source[key])) {
|
|
560
|
+
if (!target[key]) {
|
|
561
|
+
// 如果目标对象没有该属性,创建一个空对象
|
|
562
|
+
target[key] = {}
|
|
563
|
+
}
|
|
564
|
+
// 递归合并
|
|
565
|
+
merge(target[key], source[key])
|
|
566
|
+
} else {
|
|
567
|
+
// 直接覆盖
|
|
568
|
+
target[key] = source[key]
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// 继续合并剩余的源对象
|
|
574
|
+
return merge(target, ...sources)
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
function _isObject(obj) {
|
|
578
|
+
return obj && typeof obj === 'object' && !Array.isArray(obj)
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
|
|
582
|
+
|
|
583
|
+
;// ./lib/helpers/objectHelper/index.js
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
|
|
450
588
|
;// ./lib/models/keyValueObject/keyValueObject.js
|
|
589
|
+
|
|
590
|
+
|
|
451
591
|
class keyValueObject_KeyValueObject {
|
|
452
592
|
constructor(options = {}) {
|
|
453
593
|
options = options || {}
|
|
@@ -523,6 +663,19 @@ class keyValueObject_KeyValueObject {
|
|
|
523
663
|
static getValueByKey(arr = [], key) {
|
|
524
664
|
return this.foundValueByKey(arr, key)
|
|
525
665
|
}
|
|
666
|
+
static getMetadataValueByKeyAsArray(arr = [], key) {
|
|
667
|
+
const _value = this.getValueByKey(arr, key)
|
|
668
|
+
if (!_value) {
|
|
669
|
+
return []
|
|
670
|
+
}
|
|
671
|
+
if (objectHelper.isPlainObject(_value)) {
|
|
672
|
+
return Object.keys(_value).reduce((acc, key) => {
|
|
673
|
+
acc.push({ key, value: _value[key] })
|
|
674
|
+
return acc
|
|
675
|
+
}, [])
|
|
676
|
+
}
|
|
677
|
+
return _value
|
|
678
|
+
}
|
|
526
679
|
static getValueByKeyFromArray(arr = [], key) {
|
|
527
680
|
if (arr.length === 0) {
|
|
528
681
|
return null
|
|
@@ -1431,6 +1584,7 @@ class ActionRecord {
|
|
|
1431
1584
|
|
|
1432
1585
|
|
|
1433
1586
|
const notUpdateAllowedProps = [
|
|
1587
|
+
'_ActionRecord',
|
|
1434
1588
|
'created',
|
|
1435
1589
|
// 'statusType'
|
|
1436
1590
|
]
|
|
@@ -2647,6 +2801,10 @@ class TenantAwareEntity extends TrackedEntity {
|
|
|
2647
2801
|
}
|
|
2648
2802
|
|
|
2649
2803
|
// instance methods
|
|
2804
|
+
insertOrUpdateMetadata(key, value) {
|
|
2805
|
+
this.metadata = Metadata.insertOrUpdateRecord(this.metadata, key, value)
|
|
2806
|
+
return this
|
|
2807
|
+
}
|
|
2650
2808
|
getMetadata() {
|
|
2651
2809
|
return this.metadata
|
|
2652
2810
|
}
|
|
@@ -2657,6 +2815,21 @@ class TenantAwareEntity extends TrackedEntity {
|
|
|
2657
2815
|
const found = this.getMetadataByKey(key)
|
|
2658
2816
|
return found ? found.value : null
|
|
2659
2817
|
}
|
|
2818
|
+
getMetadataValueByKeys(keys, kv) {
|
|
2819
|
+
if (!Array.isArray(keys)) {
|
|
2820
|
+
return null
|
|
2821
|
+
}
|
|
2822
|
+
kv = kv || this.metadata
|
|
2823
|
+
if (keys.length === 0) {
|
|
2824
|
+
return kv
|
|
2825
|
+
}
|
|
2826
|
+
const key = keys.shift()
|
|
2827
|
+
const _val = Metadata.getMetadataValueByKeyAsArray(kv, key)
|
|
2828
|
+
return this.getMetadataValueByKeys(keys, _val)
|
|
2829
|
+
}
|
|
2830
|
+
getMetadataValueByKeyAsArray(key) {
|
|
2831
|
+
return Metadata.getMetadataValueByKeyAsArray(this.metadata, key)
|
|
2832
|
+
}
|
|
2660
2833
|
getRemarks() {
|
|
2661
2834
|
return this.remarks
|
|
2662
2835
|
}
|
|
@@ -3122,7 +3295,7 @@ function detectControlCharacters(input, options = {}) {
|
|
|
3122
3295
|
|
|
3123
3296
|
return {
|
|
3124
3297
|
hasControlChars: matches.length > 0,
|
|
3125
|
-
matches
|
|
3298
|
+
matches,
|
|
3126
3299
|
totalFound: matches.length,
|
|
3127
3300
|
inputPreview: input.length > 50 ? input.substring(0, 50) + '...' : input,
|
|
3128
3301
|
inputLength: input.length,
|
|
@@ -3348,131 +3521,6 @@ function extractEmails(dirtyArray) {
|
|
|
3348
3521
|
;// ./lib/helpers/extractEmails/index.js
|
|
3349
3522
|
|
|
3350
3523
|
|
|
3351
|
-
;// ./lib/helpers/objectHelper/objectHelper.js
|
|
3352
|
-
const objectHelper = {
|
|
3353
|
-
get(obj, path) {
|
|
3354
|
-
const parts = path.split('.')
|
|
3355
|
-
return parts.reduce((acc, part) => {
|
|
3356
|
-
if (part.endsWith('[]')) {
|
|
3357
|
-
// 处理数组遍历
|
|
3358
|
-
const key = part.slice(0, -2) // 去掉 '[]' 得到属性名
|
|
3359
|
-
if (Array.isArray(acc[key])) {
|
|
3360
|
-
return acc[key] // 返回整个数组
|
|
3361
|
-
}
|
|
3362
|
-
return [] // 如果不是数组,返回空数组
|
|
3363
|
-
}
|
|
3364
|
-
if (part.includes('[') && part.includes(']')) {
|
|
3365
|
-
// 处理数组索引
|
|
3366
|
-
const arrayMatch = part.match(/(\w+)\[(\d+)\]/)
|
|
3367
|
-
if (arrayMatch) {
|
|
3368
|
-
const key = arrayMatch[1]
|
|
3369
|
-
const index = arrayMatch[2]
|
|
3370
|
-
return acc && acc[key] && acc[key][index]
|
|
3371
|
-
}
|
|
3372
|
-
} else if (acc && Array.isArray(acc)) {
|
|
3373
|
-
// 如果当前值是数组,提取每个对象的指定属性
|
|
3374
|
-
return acc.map((item) => item[part])
|
|
3375
|
-
} else {
|
|
3376
|
-
// 处理普通属性
|
|
3377
|
-
return acc && acc[part]
|
|
3378
|
-
}
|
|
3379
|
-
}, obj)
|
|
3380
|
-
},
|
|
3381
|
-
merge,
|
|
3382
|
-
set(obj, path, value) {
|
|
3383
|
-
const parts = path.split('.')
|
|
3384
|
-
let current = obj
|
|
3385
|
-
|
|
3386
|
-
// 处理所有中间部分
|
|
3387
|
-
for (let i = 0; i < parts.length - 1; i++) {
|
|
3388
|
-
const part = parts[i]
|
|
3389
|
-
let key, index
|
|
3390
|
-
|
|
3391
|
-
// 检查是否是数组索引格式,如key[0]
|
|
3392
|
-
const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/)
|
|
3393
|
-
if (arrayMatch) {
|
|
3394
|
-
key = arrayMatch[1]
|
|
3395
|
-
index = Number.parseInt(arrayMatch[2], 10)
|
|
3396
|
-
// 确保当前层级的数组存在
|
|
3397
|
-
if (!current[key] || !Array.isArray(current[key])) {
|
|
3398
|
-
current[key] = []
|
|
3399
|
-
}
|
|
3400
|
-
// 扩展数组到足够大
|
|
3401
|
-
while (current[key].length <= index) {
|
|
3402
|
-
current[key].push(undefined)
|
|
3403
|
-
}
|
|
3404
|
-
// 如果当前位置未定义或为null,初始化为对象
|
|
3405
|
-
if (current[key][index] == null) {
|
|
3406
|
-
current[key][index] = {}
|
|
3407
|
-
}
|
|
3408
|
-
current = current[key][index]
|
|
3409
|
-
} else {
|
|
3410
|
-
// 处理普通属性
|
|
3411
|
-
if (!current[part]) {
|
|
3412
|
-
current[part] = {}
|
|
3413
|
-
}
|
|
3414
|
-
current = current[part]
|
|
3415
|
-
}
|
|
3416
|
-
}
|
|
3417
|
-
|
|
3418
|
-
// 处理最后一部分
|
|
3419
|
-
const lastPart = parts[parts.length - 1]
|
|
3420
|
-
const arrayMatch = lastPart.match(/^(\w+)\[(\d+)\]$/)
|
|
3421
|
-
if (arrayMatch) {
|
|
3422
|
-
const key = arrayMatch[1]
|
|
3423
|
-
const index = Number.parseInt(arrayMatch[2], 10)
|
|
3424
|
-
// 确保数组存在
|
|
3425
|
-
if (!current[key] || !Array.isArray(current[key])) {
|
|
3426
|
-
current[key] = []
|
|
3427
|
-
}
|
|
3428
|
-
// 扩展数组到所需索引
|
|
3429
|
-
while (current[key].length <= index) {
|
|
3430
|
-
current[key].push(undefined)
|
|
3431
|
-
}
|
|
3432
|
-
current[key][index] = value
|
|
3433
|
-
} else {
|
|
3434
|
-
current[lastPart] = value
|
|
3435
|
-
}
|
|
3436
|
-
}
|
|
3437
|
-
}
|
|
3438
|
-
|
|
3439
|
-
function merge(target, ...sources) {
|
|
3440
|
-
if (!sources.length)
|
|
3441
|
-
return target
|
|
3442
|
-
|
|
3443
|
-
const source = sources.shift() // 取出第一个源对象
|
|
3444
|
-
|
|
3445
|
-
if (_isObject(target) && _isObject(source)) {
|
|
3446
|
-
for (const key in source) {
|
|
3447
|
-
if (_isObject(source[key])) {
|
|
3448
|
-
if (!target[key]) {
|
|
3449
|
-
// 如果目标对象没有该属性,创建一个空对象
|
|
3450
|
-
target[key] = {}
|
|
3451
|
-
}
|
|
3452
|
-
// 递归合并
|
|
3453
|
-
merge(target[key], source[key])
|
|
3454
|
-
} else {
|
|
3455
|
-
// 直接覆盖
|
|
3456
|
-
target[key] = source[key]
|
|
3457
|
-
}
|
|
3458
|
-
}
|
|
3459
|
-
}
|
|
3460
|
-
|
|
3461
|
-
// 继续合并剩余的源对象
|
|
3462
|
-
return merge(target, ...sources)
|
|
3463
|
-
}
|
|
3464
|
-
|
|
3465
|
-
function _isObject(obj) {
|
|
3466
|
-
return obj && typeof obj === 'object' && !Array.isArray(obj)
|
|
3467
|
-
}
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
;// ./lib/helpers/objectHelper/index.js
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
3524
|
;// ./lib/helpers/pReduce/pReduce.js
|
|
3477
3525
|
async function pReduce(iterable, reducer, initialValue) {
|
|
3478
3526
|
return new Promise((resolve, reject) => {
|
package/dist/q-utilities.min.js
CHANGED
|
@@ -553,7 +553,147 @@ class AwsStsS3Client {
|
|
|
553
553
|
|
|
554
554
|
|
|
555
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
|
+
|
|
556
694
|
;// ./lib/models/keyValueObject/keyValueObject.js
|
|
695
|
+
|
|
696
|
+
|
|
557
697
|
class keyValueObject_KeyValueObject {
|
|
558
698
|
constructor(options = {}) {
|
|
559
699
|
options = options || {}
|
|
@@ -629,6 +769,19 @@ class keyValueObject_KeyValueObject {
|
|
|
629
769
|
static getValueByKey(arr = [], key) {
|
|
630
770
|
return this.foundValueByKey(arr, key)
|
|
631
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
|
+
}
|
|
632
785
|
static getValueByKeyFromArray(arr = [], key) {
|
|
633
786
|
if (arr.length === 0) {
|
|
634
787
|
return null
|
|
@@ -1537,6 +1690,7 @@ class ActionRecord {
|
|
|
1537
1690
|
|
|
1538
1691
|
|
|
1539
1692
|
const notUpdateAllowedProps = [
|
|
1693
|
+
'_ActionRecord',
|
|
1540
1694
|
'created',
|
|
1541
1695
|
// 'statusType'
|
|
1542
1696
|
]
|
|
@@ -2753,6 +2907,10 @@ class TenantAwareEntity extends TrackedEntity {
|
|
|
2753
2907
|
}
|
|
2754
2908
|
|
|
2755
2909
|
// instance methods
|
|
2910
|
+
insertOrUpdateMetadata(key, value) {
|
|
2911
|
+
this.metadata = Metadata.insertOrUpdateRecord(this.metadata, key, value)
|
|
2912
|
+
return this
|
|
2913
|
+
}
|
|
2756
2914
|
getMetadata() {
|
|
2757
2915
|
return this.metadata
|
|
2758
2916
|
}
|
|
@@ -2763,6 +2921,21 @@ class TenantAwareEntity extends TrackedEntity {
|
|
|
2763
2921
|
const found = this.getMetadataByKey(key)
|
|
2764
2922
|
return found ? found.value : null
|
|
2765
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
|
+
}
|
|
2766
2939
|
getRemarks() {
|
|
2767
2940
|
return this.remarks
|
|
2768
2941
|
}
|
|
@@ -3228,7 +3401,7 @@ function detectControlCharacters(input, options = {}) {
|
|
|
3228
3401
|
|
|
3229
3402
|
return {
|
|
3230
3403
|
hasControlChars: matches.length > 0,
|
|
3231
|
-
matches
|
|
3404
|
+
matches,
|
|
3232
3405
|
totalFound: matches.length,
|
|
3233
3406
|
inputPreview: input.length > 50 ? input.substring(0, 50) + '...' : input,
|
|
3234
3407
|
inputLength: input.length,
|
|
@@ -3454,131 +3627,6 @@ function extractEmails(dirtyArray) {
|
|
|
3454
3627
|
;// ./lib/helpers/extractEmails/index.js
|
|
3455
3628
|
|
|
3456
3629
|
|
|
3457
|
-
;// ./lib/helpers/objectHelper/objectHelper.js
|
|
3458
|
-
const objectHelper = {
|
|
3459
|
-
get(obj, path) {
|
|
3460
|
-
const parts = path.split('.')
|
|
3461
|
-
return parts.reduce((acc, part) => {
|
|
3462
|
-
if (part.endsWith('[]')) {
|
|
3463
|
-
// 处理数组遍历
|
|
3464
|
-
const key = part.slice(0, -2) // 去掉 '[]' 得到属性名
|
|
3465
|
-
if (Array.isArray(acc[key])) {
|
|
3466
|
-
return acc[key] // 返回整个数组
|
|
3467
|
-
}
|
|
3468
|
-
return [] // 如果不是数组,返回空数组
|
|
3469
|
-
}
|
|
3470
|
-
if (part.includes('[') && part.includes(']')) {
|
|
3471
|
-
// 处理数组索引
|
|
3472
|
-
const arrayMatch = part.match(/(\w+)\[(\d+)\]/)
|
|
3473
|
-
if (arrayMatch) {
|
|
3474
|
-
const key = arrayMatch[1]
|
|
3475
|
-
const index = arrayMatch[2]
|
|
3476
|
-
return acc && acc[key] && acc[key][index]
|
|
3477
|
-
}
|
|
3478
|
-
} else if (acc && Array.isArray(acc)) {
|
|
3479
|
-
// 如果当前值是数组,提取每个对象的指定属性
|
|
3480
|
-
return acc.map((item) => item[part])
|
|
3481
|
-
} else {
|
|
3482
|
-
// 处理普通属性
|
|
3483
|
-
return acc && acc[part]
|
|
3484
|
-
}
|
|
3485
|
-
}, obj)
|
|
3486
|
-
},
|
|
3487
|
-
merge,
|
|
3488
|
-
set(obj, path, value) {
|
|
3489
|
-
const parts = path.split('.')
|
|
3490
|
-
let current = obj
|
|
3491
|
-
|
|
3492
|
-
// 处理所有中间部分
|
|
3493
|
-
for (let i = 0; i < parts.length - 1; i++) {
|
|
3494
|
-
const part = parts[i]
|
|
3495
|
-
let key, index
|
|
3496
|
-
|
|
3497
|
-
// 检查是否是数组索引格式,如key[0]
|
|
3498
|
-
const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/)
|
|
3499
|
-
if (arrayMatch) {
|
|
3500
|
-
key = arrayMatch[1]
|
|
3501
|
-
index = Number.parseInt(arrayMatch[2], 10)
|
|
3502
|
-
// 确保当前层级的数组存在
|
|
3503
|
-
if (!current[key] || !Array.isArray(current[key])) {
|
|
3504
|
-
current[key] = []
|
|
3505
|
-
}
|
|
3506
|
-
// 扩展数组到足够大
|
|
3507
|
-
while (current[key].length <= index) {
|
|
3508
|
-
current[key].push(undefined)
|
|
3509
|
-
}
|
|
3510
|
-
// 如果当前位置未定义或为null,初始化为对象
|
|
3511
|
-
if (current[key][index] == null) {
|
|
3512
|
-
current[key][index] = {}
|
|
3513
|
-
}
|
|
3514
|
-
current = current[key][index]
|
|
3515
|
-
} else {
|
|
3516
|
-
// 处理普通属性
|
|
3517
|
-
if (!current[part]) {
|
|
3518
|
-
current[part] = {}
|
|
3519
|
-
}
|
|
3520
|
-
current = current[part]
|
|
3521
|
-
}
|
|
3522
|
-
}
|
|
3523
|
-
|
|
3524
|
-
// 处理最后一部分
|
|
3525
|
-
const lastPart = parts[parts.length - 1]
|
|
3526
|
-
const arrayMatch = lastPart.match(/^(\w+)\[(\d+)\]$/)
|
|
3527
|
-
if (arrayMatch) {
|
|
3528
|
-
const key = arrayMatch[1]
|
|
3529
|
-
const index = Number.parseInt(arrayMatch[2], 10)
|
|
3530
|
-
// 确保数组存在
|
|
3531
|
-
if (!current[key] || !Array.isArray(current[key])) {
|
|
3532
|
-
current[key] = []
|
|
3533
|
-
}
|
|
3534
|
-
// 扩展数组到所需索引
|
|
3535
|
-
while (current[key].length <= index) {
|
|
3536
|
-
current[key].push(undefined)
|
|
3537
|
-
}
|
|
3538
|
-
current[key][index] = value
|
|
3539
|
-
} else {
|
|
3540
|
-
current[lastPart] = value
|
|
3541
|
-
}
|
|
3542
|
-
}
|
|
3543
|
-
}
|
|
3544
|
-
|
|
3545
|
-
function merge(target, ...sources) {
|
|
3546
|
-
if (!sources.length)
|
|
3547
|
-
return target
|
|
3548
|
-
|
|
3549
|
-
const source = sources.shift() // 取出第一个源对象
|
|
3550
|
-
|
|
3551
|
-
if (_isObject(target) && _isObject(source)) {
|
|
3552
|
-
for (const key in source) {
|
|
3553
|
-
if (_isObject(source[key])) {
|
|
3554
|
-
if (!target[key]) {
|
|
3555
|
-
// 如果目标对象没有该属性,创建一个空对象
|
|
3556
|
-
target[key] = {}
|
|
3557
|
-
}
|
|
3558
|
-
// 递归合并
|
|
3559
|
-
merge(target[key], source[key])
|
|
3560
|
-
} else {
|
|
3561
|
-
// 直接覆盖
|
|
3562
|
-
target[key] = source[key]
|
|
3563
|
-
}
|
|
3564
|
-
}
|
|
3565
|
-
}
|
|
3566
|
-
|
|
3567
|
-
// 继续合并剩余的源对象
|
|
3568
|
-
return merge(target, ...sources)
|
|
3569
|
-
}
|
|
3570
|
-
|
|
3571
|
-
function _isObject(obj) {
|
|
3572
|
-
return obj && typeof obj === 'object' && !Array.isArray(obj)
|
|
3573
|
-
}
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
;// ./lib/helpers/objectHelper/index.js
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
3630
|
;// ./lib/helpers/pReduce/pReduce.js
|
|
3583
3631
|
async function pReduce(iterable, reducer, initialValue) {
|
|
3584
3632
|
return new Promise((resolve, reject) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@questwork/q-utilities",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.29",
|
|
4
4
|
"description": "Questwork QUtilities",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Questwork Consulting Limited",
|
|
@@ -8,6 +8,13 @@
|
|
|
8
8
|
"url": "https://questwork.com/"
|
|
9
9
|
},
|
|
10
10
|
"license": "MIT",
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "cross-env NODE_ENV=production minimize=false gulp",
|
|
13
|
+
"build:wp": "cross-env NODE_ENV=production minimize=false gulp wp",
|
|
14
|
+
"lint": "eslint .",
|
|
15
|
+
"test:helpers": "NODE_ENV=test mocha --exit 'lib/helpers/test.setup.js' 'lib/helpers/**/*.spec.js'",
|
|
16
|
+
"test:models": "NODE_ENV=test mocha --exit 'lib/test.setup.js' 'lib/**/*.spec.js'"
|
|
17
|
+
},
|
|
11
18
|
"type": "module",
|
|
12
19
|
"exports": {
|
|
13
20
|
".": {
|
|
@@ -43,12 +50,5 @@
|
|
|
43
50
|
},
|
|
44
51
|
"engines": {
|
|
45
52
|
"node": ">=10.0.0"
|
|
46
|
-
},
|
|
47
|
-
"scripts": {
|
|
48
|
-
"build": "cross-env NODE_ENV=production minimize=false gulp",
|
|
49
|
-
"build:wp": "cross-env NODE_ENV=production minimize=false gulp wp",
|
|
50
|
-
"lint": "eslint .",
|
|
51
|
-
"test:helpers": "NODE_ENV=test mocha --exit 'lib/helpers/test.setup.js' 'lib/helpers/**/*.spec.js'",
|
|
52
|
-
"test:models": "NODE_ENV=test mocha --exit 'lib/test.setup.js' 'lib/**/*.spec.js'"
|
|
53
53
|
}
|
|
54
|
-
}
|
|
54
|
+
}
|