@codady/utils 0.0.14 → 0.0.16
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/CHANGELOG.md +19 -0
- package/dist/utils.cjs.js +32 -33
- package/dist/utils.cjs.min.js +3 -3
- package/dist/utils.esm.js +32 -33
- package/dist/utils.esm.min.js +3 -3
- package/dist/utils.umd.js +32 -33
- package/dist/utils.umd.min.js +3 -3
- package/dist.zip +0 -0
- package/package.json +1 -1
- package/src/deepClone.js +13 -18
- package/src/deepClone.ts +9 -15
- package/src/deepMerge.js +25 -15
- package/src/deepMerge.ts +70 -31
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
All changes to Utils including new features, updates, and removals are documented here.
|
|
4
4
|
|
|
5
|
+
## [v0.0.16] - 2025-12-26
|
|
6
|
+
|
|
7
|
+
### Distribution Files
|
|
8
|
+
* **JS**: https://unpkg.com/@codady/utils@0.0.16/dist/js/utils.js
|
|
9
|
+
* **Zip**:https://unpkg.com/@codady/utils@0.0.16/dist.zip
|
|
10
|
+
|
|
11
|
+
### Changes
|
|
12
|
+
|
|
13
|
+
#### Fixed
|
|
14
|
+
* Null
|
|
15
|
+
|
|
16
|
+
#### Added
|
|
17
|
+
* Modified the `deepMerge` function to include an `interceptor` parameter, which can be used to intercept the merging process and handle it manually when needed.修改了`deepMerge`函数,对参数增加`interceptor`属性,用来拦截合并,当需要手动处理合并时可使用该参数。
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
#### Removed
|
|
21
|
+
* Null
|
|
5
22
|
|
|
6
23
|
## [v0.0.14] - 2025-12-26
|
|
7
24
|
|
|
@@ -16,6 +33,8 @@ All changes to Utils including new features, updates, and removals are documente
|
|
|
16
33
|
|
|
17
34
|
#### Added
|
|
18
35
|
* The `onBeforeClone` and `onAfterClone` callbacks of the `deepClone` function now include a new `parent` property, which can temporarily store the parent object being cloned. deepClone函数的onBeforeClone和onAfterClone新增属性parent,可临时存储被拷贝的父对象。
|
|
36
|
+
* Modified the `deepMerge` function to include an `interceptor` parameter, which can be used to intercept the merging process and handle it manually when needed.修改了`deepMerge`函数,对参数增加`interceptor`属性,用来拦截合并,当需要手动处理合并时可使用该参数。
|
|
37
|
+
|
|
19
38
|
|
|
20
39
|
#### Removed
|
|
21
40
|
* Null
|
package/dist/utils.cjs.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
/*!
|
|
3
|
-
* @since Last modified: 2025-12-26
|
|
3
|
+
* @since Last modified: 2025-12-26 15:47:37
|
|
4
4
|
* @name Utils for web front-end.
|
|
5
|
-
* @version 0.0.
|
|
5
|
+
* @version 0.0.16
|
|
6
6
|
* @author AXUI development team <3217728223@qq.com>
|
|
7
7
|
* @description This is a set of general-purpose JavaScript utility functions developed by the AXUI team. All functions are pure and do not involve CSS or other third-party libraries. They are suitable for any web front-end environment.
|
|
8
8
|
* @see {@link https://www.axui.cn|Official website}
|
|
@@ -61,16 +61,10 @@ const deepClone = (data, options = {}) => {
|
|
|
61
61
|
}, options);
|
|
62
62
|
// Check interceptor - if it returns a value (not null/undefined), use it directly
|
|
63
63
|
if (opts.interceptor && typeof opts.interceptor === 'function') {
|
|
64
|
-
let result = opts.interceptor(data, dataType);
|
|
64
|
+
let result = opts.interceptor({ input: data, type: dataType, parent: opts.parent });
|
|
65
65
|
if ((result ?? false)) {
|
|
66
66
|
// Call onAfterClone if set
|
|
67
|
-
|
|
68
|
-
output: result,
|
|
69
|
-
input: data,
|
|
70
|
-
type: dataType,
|
|
71
|
-
cloned: result !== data,
|
|
72
|
-
parent: opts.parent
|
|
73
|
-
});
|
|
67
|
+
|
|
74
68
|
return result;
|
|
75
69
|
}
|
|
76
70
|
// If interceptor returns null/undefined, continue with normal cloning process
|
|
@@ -84,8 +78,6 @@ const deepClone = (data, options = {}) => {
|
|
|
84
78
|
let newData, cloned = true;
|
|
85
79
|
if (dataType === 'Object' && opts.cloneObject) {
|
|
86
80
|
const newObj = {}, symbols = Object.getOwnPropertySymbols(data);
|
|
87
|
-
//存储parent对象,在下一次深复制时使用
|
|
88
|
-
opts.parent = data;
|
|
89
81
|
// Clone regular properties
|
|
90
82
|
for (const key in data) {
|
|
91
83
|
//临时保存父对象
|
|
@@ -94,30 +86,27 @@ const deepClone = (data, options = {}) => {
|
|
|
94
86
|
// Clone Symbol properties
|
|
95
87
|
if (symbols.length > 0) {
|
|
96
88
|
for (const symbol of symbols) {
|
|
97
|
-
newObj[symbol] = deepClone(data[symbol], opts);
|
|
89
|
+
newObj[symbol] = deepClone(data[symbol], { ...opts, parent: data });
|
|
98
90
|
}
|
|
99
91
|
}
|
|
100
92
|
newData = newObj;
|
|
101
93
|
}
|
|
102
94
|
else if (dataType === 'Array' && opts.cloneArray) {
|
|
103
|
-
opts
|
|
104
|
-
newData = data.map(item => deepClone(item, opts));
|
|
95
|
+
newData = data.map(item => deepClone(item, { ...opts, parent: data }));
|
|
105
96
|
}
|
|
106
97
|
else if (dataType === 'Map' && opts.cloneMap) {
|
|
107
98
|
const newMap = new Map();
|
|
108
|
-
opts.parent = data;
|
|
109
99
|
for (const [key, value] of data) {
|
|
110
100
|
// Both Map keys and values need deep cloning
|
|
111
|
-
newMap.set(deepClone(key, opts), deepClone(value, opts));
|
|
101
|
+
newMap.set(deepClone(key, opts), deepClone(value, { ...opts, parent: data }));
|
|
112
102
|
}
|
|
113
103
|
newData = newMap;
|
|
114
104
|
}
|
|
115
105
|
else if (dataType === 'Set' && opts.cloneSet) {
|
|
116
106
|
const newSet = new Set();
|
|
117
|
-
opts.parent = data;
|
|
118
107
|
for (const value of data) {
|
|
119
108
|
// Set values need deep cloning
|
|
120
|
-
newSet.add(deepClone(value, opts));
|
|
109
|
+
newSet.add(deepClone(value, { ...opts, parent: data }));
|
|
121
110
|
}
|
|
122
111
|
newData = newSet;
|
|
123
112
|
}
|
|
@@ -537,8 +526,25 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
537
526
|
}, opts),
|
|
538
527
|
// Main helper function for recursive merging
|
|
539
528
|
// 递归合并的主辅助函数
|
|
540
|
-
|
|
529
|
+
smartMerger = (target, source, options) => {
|
|
541
530
|
let targetType = getDataType(target), sourceType = getDataType(source), flag = true, type, result;
|
|
531
|
+
// Check interceptor - if it returns a value (not null/undefined), use it directly
|
|
532
|
+
if (options.interceptor && typeof options.interceptor === 'function') {
|
|
533
|
+
let interceptorResult = options.interceptor({ target, source, parent: options.parent });
|
|
534
|
+
if ((interceptorResult ?? false)) {
|
|
535
|
+
//如果不是返回{target,source},那么直接返回interceptorResult
|
|
536
|
+
if (interceptorResult?.target === null || interceptorResult?.source === null) {
|
|
537
|
+
return interceptorResult;
|
|
538
|
+
}
|
|
539
|
+
else {
|
|
540
|
+
//interceptorResult={target,source}
|
|
541
|
+
target = interceptorResult.target;
|
|
542
|
+
source = interceptorResult.source;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
// If interceptor returns null/undefined, continue with normal cloning process
|
|
546
|
+
}
|
|
547
|
+
options?.onBeforeMerge?.({ target, source, parent: options.parent });
|
|
542
548
|
// Determine the type and perform appropriate merging
|
|
543
549
|
// 确定类型并执行相应的合并
|
|
544
550
|
if (targetType === 'Object' && sourceType === 'Object') {
|
|
@@ -561,6 +567,7 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
561
567
|
flag = false;
|
|
562
568
|
result = target;
|
|
563
569
|
}
|
|
570
|
+
options?.onAfterMerge?.({ result, target, source, type, parent: opts.parent });
|
|
564
571
|
return { result, flag, type };
|
|
565
572
|
},
|
|
566
573
|
// Special handling for objects with enable property
|
|
@@ -589,7 +596,6 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
589
596
|
if (targetType !== 'Object' || sourceType !== 'Object') {
|
|
590
597
|
return target;
|
|
591
598
|
}
|
|
592
|
-
opts?.onBeforeMerge?.(target, source);
|
|
593
599
|
const options = Object.assign({ inheritMissing: true, targetClone: false, useEnable: true }, opts);
|
|
594
600
|
let result = {};
|
|
595
601
|
// If cloning is enabled, clone the target first
|
|
@@ -597,7 +603,7 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
597
603
|
result = options.targetClone ? shallowCopy(target) : target;
|
|
598
604
|
for (let k in source) {
|
|
599
605
|
if (source.hasOwnProperty(k) && result.hasOwnProperty(k)) {
|
|
600
|
-
let resp =
|
|
606
|
+
let resp = smartMerger(result[k], source[k], { ...opts, parent: result });
|
|
601
607
|
//resp={result,flag,type}
|
|
602
608
|
//flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
|
|
603
609
|
if (!resp.flag) {
|
|
@@ -637,13 +643,11 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
637
643
|
result[k] = source[k];
|
|
638
644
|
}
|
|
639
645
|
}
|
|
640
|
-
options?.onAfterMerge?.(result, target, source);
|
|
641
646
|
return result;
|
|
642
647
|
}, deepMergeArrays = (target, source, options = {}) => {
|
|
643
648
|
// Ensure both target and source are arrays
|
|
644
649
|
if (!Array.isArray(target) || !Array.isArray(source))
|
|
645
650
|
return target;
|
|
646
|
-
options?.onBeforeMerge?.(target, source);
|
|
647
651
|
// Merge options, with default values
|
|
648
652
|
const opts = Object.assign({ dataMode: 'clear', inheritMissing: true, targetClone: false }, options),
|
|
649
653
|
// If cloning is enabled, create a deep copy of the target array
|
|
@@ -656,7 +660,7 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
656
660
|
// 如果不允许添加超过长度
|
|
657
661
|
if (!opts.inheritMissing && i >= result.length)
|
|
658
662
|
break;
|
|
659
|
-
let resp =
|
|
663
|
+
let resp = smartMerger(result[i], source[i], { ...opts, parent: result });
|
|
660
664
|
//resp={result,flag,type}
|
|
661
665
|
//flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
|
|
662
666
|
if (!resp.flag) {
|
|
@@ -673,13 +677,11 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
673
677
|
result.length = 0;
|
|
674
678
|
result.push(...source);
|
|
675
679
|
}
|
|
676
|
-
options?.onAfterMerge?.(result, target, source);
|
|
677
680
|
return result;
|
|
678
681
|
}, deepMergeMaps = (target, source, options = {}) => {
|
|
679
682
|
// Ensure both target and source are Maps
|
|
680
683
|
if (!(target instanceof Map) || !(source instanceof Map))
|
|
681
684
|
return target;
|
|
682
|
-
options?.onBeforeMerge?.(target, source);
|
|
683
685
|
// Merge options, with default values
|
|
684
686
|
const opts = Object.assign({ inheritMissing: true, targetClone: false, useEnable: true }, options),
|
|
685
687
|
// If cloning is enabled, create a deep copy of the target Map
|
|
@@ -688,7 +690,7 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
688
690
|
for (const [key, value] of source.entries())
|
|
689
691
|
// Check if the key already exists in the target Map
|
|
690
692
|
if (result.has(key)) {
|
|
691
|
-
const _target = result.get(key), _source = value, resp =
|
|
693
|
+
const _target = result.get(key), _source = value, resp = smartMerger(_target, _source, opts);
|
|
692
694
|
//resp={result,flag,type}
|
|
693
695
|
//flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
|
|
694
696
|
if (!resp.flag) {
|
|
@@ -704,13 +706,11 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
704
706
|
// If the key doesn't exist in the target, add the entry from the source Map
|
|
705
707
|
options.inheritMissing && result.set(key, value);
|
|
706
708
|
}
|
|
707
|
-
options?.onAfterMerge?.(result, target, source);
|
|
708
709
|
return result;
|
|
709
710
|
}, deepMergeSets = (target, source, options = {}) => {
|
|
710
711
|
// Ensure both target and source are Sets
|
|
711
712
|
if (!(target instanceof Set) || !(source instanceof Set))
|
|
712
713
|
return target;
|
|
713
|
-
options?.onBeforeMerge?.(target, source);
|
|
714
714
|
// Merge options, with default values
|
|
715
715
|
const opts = Object.assign({ dataMode: 'clear', inheritMissing: true, targetClone: false, useEnable: true }, options),
|
|
716
716
|
// If cloning is enabled, create a deep copy of the target Set
|
|
@@ -718,7 +718,7 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
718
718
|
// Handle different merge strategies based on dataMode
|
|
719
719
|
if (opts.dataMode === 'replace') {
|
|
720
720
|
// Replace mode: recursively merge items in the Sets
|
|
721
|
-
const _result = [...result], _source = [...source], resp =
|
|
721
|
+
const _result = [...result], _source = [...source], resp = smartMerger(_result, _source, opts);
|
|
722
722
|
result.clear();
|
|
723
723
|
for (let item of resp.result)
|
|
724
724
|
result.add(item);
|
|
@@ -734,10 +734,9 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
734
734
|
for (let item of source)
|
|
735
735
|
result.add(item);
|
|
736
736
|
}
|
|
737
|
-
options?.onAfterMerge?.(result, target, source);
|
|
738
737
|
return result;
|
|
739
738
|
};
|
|
740
|
-
return
|
|
739
|
+
return smartMerger(target, source, options).result;
|
|
741
740
|
};
|
|
742
741
|
|
|
743
742
|
const utils = {
|
package/dist/utils.cjs.min.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @since Last modified: 2025-12-26
|
|
2
|
+
* @since Last modified: 2025-12-26 15:47:37
|
|
3
3
|
* @name Utils for web front-end.
|
|
4
|
-
* @version 0.0.
|
|
4
|
+
* @version 0.0.16
|
|
5
5
|
* @author AXUI development team <3217728223@qq.com>
|
|
6
6
|
* @description This is a set of general-purpose JavaScript utility functions developed by the AXUI team. All functions are pure and do not involve CSS or other third-party libraries. They are suitable for any web front-end environment.
|
|
7
7
|
* @see {@link https://www.axui.cn|Official website}
|
|
@@ -12,4 +12,4 @@
|
|
|
12
12
|
* @copyright This software supports the MIT License, allowing free learning and commercial use, but please retain the terms 'ax,' 'axui,' 'AX,' and 'AXUI' within the software.
|
|
13
13
|
* @license MIT license
|
|
14
14
|
*/
|
|
15
|
-
"use strict";const getDataType=e=>{let t,r=Object.prototype.toString.call(e).slice(8,-1);return t="Function"===r&&/^\s*class\s+/.test(e.toString())?"Class":"Object"===r&&Object.getPrototypeOf(e)!==Object.prototype?"Instance":r,t},deepClone=(e,t={})=>{const r=getDataType(e),
|
|
15
|
+
"use strict";const getDataType=e=>{let t,r=Object.prototype.toString.call(e).slice(8,-1);return t="Function"===r&&/^\s*class\s+/.test(e.toString())?"Class":"Object"===r&&Object.getPrototypeOf(e)!==Object.prototype?"Instance":r,t},deepClone=(e,t={})=>{const r=getDataType(e),a=Object.assign({cloneSet:!0,cloneMap:!0,cloneObject:!0,cloneArray:!0,cloneDate:!0,cloneRegex:!0},t);if(a.interceptor&&"function"==typeof a.interceptor){let t=a.interceptor({input:e,type:r,parent:a.parent});if(t)return t}a.onBeforeClone?.({input:e,type:r,parent:a.parent});let o,n=!0;if("Object"===r&&a.cloneObject){const t={},r=Object.getOwnPropertySymbols(e);for(const r in e)t[r]=deepClone(e[r],a);if(r.length>0)for(const o of r)t[o]=deepClone(e[o],{...a,parent:e});o=t}else if("Array"===r&&a.cloneArray)o=e.map(t=>deepClone(t,{...a,parent:e}));else if("Map"===r&&a.cloneMap){const t=new Map;for(const[r,o]of e)t.set(deepClone(r,a),deepClone(o,{...a,parent:e}));o=t}else if("Set"===r&&a.cloneSet){const t=new Set;for(const r of e)t.add(deepClone(r,{...a,parent:e}));o=t}else if("Date"===r&&a.cloneDate)o=new Date(e.getTime());else if("RegExp"===r&&a.cloneRegex){const t=e;o=new RegExp(t.source,t.flags)}else o=e,n=!1;return a.onAfterClone?.({output:o,input:e,type:r,cloned:n,parent:a.parent}),o},deepCloneToJSON=e=>{const t=getDataType(e);if("Object"===t){const t={};for(const r in e)t[r]=deepCloneToJSON(e[r]);for(const e in t)void 0===t[e]&&Reflect.deleteProperty(t,e);return t}if("Array"===t){return e.map((e,t)=>deepCloneToJSON(e)).filter(e=>void 0!==e)}return["Number","String","Boolean","Null"].includes(t)?e:void 0},arrayMutableMethods=["push","pop","shift","unshift","splice","sort","reverse","copyWithin","fill"],wrapArrayMethods=({target:e,onBeforeMutate:t=()=>{},onAfterMutate:r=()=>{},allowList:a,props:o={}})=>{if(!Array.isArray(e))throw new TypeError("The 'target' parameter must be an array.");a&&!a?.length||(a=arrayMutableMethods);const n={};for(let s of a)n[s]=function(...a){const n={},l=e.length;switch(s){case"push":case"unshift":n.addedItems=[...a];break;case"pop":n.poppedItem=e[l-1];break;case"shift":n.shiftedItem=e[0];break;case"splice":const[t,r]=a,o=t<0?Math.max(l+t,0):Math.min(t,l),s=void 0===r?l-o:r;n.deletedItems=e.slice(o,o+s);break;case"sort":case"reverse":n.oldSnapshot=[...e];break;case"fill":case"copyWithin":const i=a[1]||0,p=void 0===a[2]?l:a[2];n.oldItems=e.slice(i,p),n.start=i,n.end=p}t?.(n);const i=Array.prototype[s].apply(e,a),p={value:i,key:s,args:a,context:n,target:e,...o};return r?.(p),i};return n},requireTypes=(e,t,r)=>{let a=Array.isArray(t)?t:[t],o=getDataType(e),n=o.toLowerCase(),s=a.map(e=>e.toLowerCase()),l=n.includes("html")?"element":n;if(r)try{if(!s.includes(l))throw new TypeError(`Expected data type(s): [${s.join(", ")}], but got: ${l}`)}catch(e){r(e,o)}else if(!s.includes(l))throw new TypeError(`Expected data type(s): [${s.join(", ")}], but got: ${l}`);return o},getUniqueId=(e={})=>{const t=e.prefix,r=e.suffix,a=e.base10,o=e.base36;return`${t?t+"-":""}${Date.now()}${o?"-"+Math.random().toString(36).substring(2,11):""}${a?"-"+Math.floor(1e4*Math.random()).toString().padStart(4,"0"):""}${r?"-"+r:""}`},setMutableMethods=["add","delete","clear"],mapMutableMethods=["set","delete","clear"],wrapSetMethods=({target:e,onBeforeMutate:t=()=>{},onAfterMutate:r=()=>{},allowList:a=setMutableMethods,props:o={}})=>{if(!(e instanceof Set))throw new TypeError("The 'target' parameter must be a Set.");const n={},createWrappedMethod=a=>function(...n){const s={};switch(a){case"add":{const[t]=n;s.addedItem=t,s.existed=e.has(t);break}case"delete":{const[t]=n;s.existed=e.has(t),s.deletedItem=s.existed?t:void 0;break}case"clear":s.clearedItems=Array.from(e),s.previousSize=e.size}t(s);const l=e[a].apply(e,n),i={method:a,result:l,args:n,context:s,target:e,...o};return r(i),l};for(const e of a)setMutableMethods.includes(e)&&(n[e]=createWrappedMethod(e));return Object.defineProperty(n,"target",{get:()=>e,enumerable:!1,configurable:!1}),n},wrapMapMethods=({target:e,onBeforeMutate:t=()=>{},onAfterMutate:r=()=>{},allowList:a=mapMutableMethods,props:o={}})=>{if(!(e instanceof Map))throw new TypeError("The 'target' parameter must be a Map.");const n={},createWrappedMethod=a=>function(...n){const s={};switch(a){case"set":{const[t,r]=n;s.key=t,s.newValue=r,s.existed=e.has(t),s.oldValue=s.existed?e.get(t):void 0;break}case"delete":{const[t]=n;s.key=t,s.existed=e.has(t),s.value=s.existed?e.get(t):void 0;break}case"clear":s.clearedItems=Array.from(e.entries()),s.previousSize=e.size}t(s);const l=e[a].apply(e,n),i={method:a,result:l,args:n,context:s,target:e,...o};return r(i),l};for(const e of a)mapMutableMethods.includes(e)&&(n[e]=createWrappedMethod(e));return Object.defineProperty(n,"target",{get:()=>e,enumerable:!1,configurable:!1}),n},copyObjectWithSymbol=e=>{if(!e||"object"!=typeof e)return e;const t=e,r=Object.getOwnPropertySymbols(t).reduce((e,r)=>(e[r]=t[r],e),{});return{...t,...r}},shallowCopy=(e,t={})=>{const r=getDataType(e);return"Set"===r?new Set([...e]):"Map"===r?new Map([...e]):Array.isArray(e)?[...e]:"object"===r?copyObjectWithSymbol(e):"Date"===r?new Date(e.getTime()):"RegExp"===r?new RegExp(e.source,e.flags):"Buffer"===r?Buffer.from(e):"ArrayBuffer"===r||ArrayBuffer.isView(e)?e.slice(0):"WeakSet"===r?new WeakSet([...e]):"WeakMap"===r?new WeakMap([...e]):"Error"===r?new Error(e.message):e},deepMerge=(e,t,r={})=>{const a=Object.assign({dataMode:"clear",inheritMissing:!0,targetClone:!1,useEnable:!0,useSymbol:!0,deepClone:{},onBeforeMerge:void 0,onAfterMerge:void 0},r),smartMerger=(e,t,a)=>{let o,n,s=getDataType(e),l=getDataType(t),i=!0;if(a.interceptor&&"function"==typeof a.interceptor){let r=a.interceptor({target:e,source:t,parent:a.parent});if(r){if(null===r?.target||null===r?.source)return r;e=r.target,t=r.source}}return a?.onBeforeMerge?.({target:e,source:t,parent:a.parent}),"Object"===s&&"Object"===l?(n=deepMergeObjects(e,t,a),o="Object"):"Array"===s&&"Array"===l?(n=deepMergeArrays(e,t,a),o="Array"):"Set"===s&&"Set"===l?(n=deepMergeSets(e,t,a),o="Set"):"Map"===s&&"Map"===l?(n=deepMergeMaps(e,t,a),o="Map"):(i=!1,n=e),a?.onAfterMerge?.({result:n,target:e,source:t,type:o,parent:r.parent}),{result:n,flag:i,type:o}},mergeEnableObject=(e,t)=>e?.hasOwnProperty("enable")&&"boolean"==typeof t?(e.enable=t,e):t?.hasOwnProperty("enable")&&"boolean"==typeof e?Object.assign({enable:e},t):t,deepMergeObjects=(e,t,r={})=>{let a=getDataType(e),o=getDataType(t);if("Object"!==a||"Object"!==o)return e;const n=Object.assign({inheritMissing:!0,targetClone:!1,useEnable:!0},r);let s={};s=n.targetClone?shallowCopy(e):e;for(let e in t)if(t.hasOwnProperty(e)&&s.hasOwnProperty(e)){let a=smartMerger(s[e],t[e],{...r,parent:s});a.flag?a.type?"Object"===a.type&&(s[e]=a.result):s[e]=t[e]:n.useEnable?s[e]=mergeEnableObject(s[e],t[e]):s[e]=t[e]}else t.hasOwnProperty(e)&&!s.hasOwnProperty(e)&&n.inheritMissing&&(s[e]=t[e]);if(n.useSymbol){let e=Object.getOwnPropertySymbols(t);if(e.length)for(let r of e)s[r]=t[r]}return s},deepMergeArrays=(e,t,r={})=>{if(!Array.isArray(e)||!Array.isArray(t))return e;const a=Object.assign({dataMode:"clear",inheritMissing:!0,targetClone:!1},r),o=a.targetClone?[...e]:e;if("replace"===a.dataMode)for(let e=0;e<t.length&&(a.inheritMissing||!(e>=o.length));e++){smartMerger(o[e],t[e],{...a,parent:o}).flag||(o[e]=t[e])}else"concat"===a.dataMode||(o.length=0),o.push(...t);return o},deepMergeMaps=(e,t,r={})=>{if(!(e instanceof Map&&t instanceof Map))return e;const a=Object.assign({inheritMissing:!0,targetClone:!1,useEnable:!0},r),o=a.targetClone?new Map([...e]):e;for(const[e,n]of t.entries())if(o.has(e)){const t=o.get(e),r=n,s=smartMerger(t,r,a);s.flag?"Object"===s.type&&o.set(e,s.result):o.set(e,r)}else r.inheritMissing&&o.set(e,n);return o},deepMergeSets=(e,t,r={})=>{if(!(e instanceof Set&&t instanceof Set))return e;const a=Object.assign({dataMode:"clear",inheritMissing:!0,targetClone:!1,useEnable:!0},r),o=a.targetClone?new Set(...e):e;if("replace"===a.dataMode){const e=[...o],r=[...t],n=smartMerger(e,r,a);o.clear();for(let e of n.result)o.add(e)}else if("concat"===a.dataMode)for(let e of t)o.add(e);else{o.clear();for(let e of t)o.add(e)}return o};return smartMerger(e,t,a).result},utils={getDataType:getDataType,requireTypes:requireTypes,deepClone:deepClone,deepCloneToJSON:deepCloneToJSON,wrapArrayMethods:wrapArrayMethods,arrayMutableMethods:arrayMutableMethods,setMutableMethods:setMutableMethods,mapMutableMethods:mapMutableMethods,wrapSetMethods:wrapSetMethods,wrapMapMethods:wrapMapMethods,getUniqueId:getUniqueId,deepMerge:deepMerge,shallowCopy:shallowCopy,copyObjectWithSymbol:copyObjectWithSymbol};module.exports=utils;
|
package/dist/utils.esm.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
/*!
|
|
3
|
-
* @since Last modified: 2025-12-26
|
|
3
|
+
* @since Last modified: 2025-12-26 15:47:37
|
|
4
4
|
* @name Utils for web front-end.
|
|
5
|
-
* @version 0.0.
|
|
5
|
+
* @version 0.0.16
|
|
6
6
|
* @author AXUI development team <3217728223@qq.com>
|
|
7
7
|
* @description This is a set of general-purpose JavaScript utility functions developed by the AXUI team. All functions are pure and do not involve CSS or other third-party libraries. They are suitable for any web front-end environment.
|
|
8
8
|
* @see {@link https://www.axui.cn|Official website}
|
|
@@ -59,16 +59,10 @@ const deepClone = (data, options = {}) => {
|
|
|
59
59
|
}, options);
|
|
60
60
|
// Check interceptor - if it returns a value (not null/undefined), use it directly
|
|
61
61
|
if (opts.interceptor && typeof opts.interceptor === 'function') {
|
|
62
|
-
let result = opts.interceptor(data, dataType);
|
|
62
|
+
let result = opts.interceptor({ input: data, type: dataType, parent: opts.parent });
|
|
63
63
|
if ((result ?? false)) {
|
|
64
64
|
// Call onAfterClone if set
|
|
65
|
-
|
|
66
|
-
output: result,
|
|
67
|
-
input: data,
|
|
68
|
-
type: dataType,
|
|
69
|
-
cloned: result !== data,
|
|
70
|
-
parent: opts.parent
|
|
71
|
-
});
|
|
65
|
+
|
|
72
66
|
return result;
|
|
73
67
|
}
|
|
74
68
|
// If interceptor returns null/undefined, continue with normal cloning process
|
|
@@ -82,8 +76,6 @@ const deepClone = (data, options = {}) => {
|
|
|
82
76
|
let newData, cloned = true;
|
|
83
77
|
if (dataType === 'Object' && opts.cloneObject) {
|
|
84
78
|
const newObj = {}, symbols = Object.getOwnPropertySymbols(data);
|
|
85
|
-
//存储parent对象,在下一次深复制时使用
|
|
86
|
-
opts.parent = data;
|
|
87
79
|
// Clone regular properties
|
|
88
80
|
for (const key in data) {
|
|
89
81
|
//临时保存父对象
|
|
@@ -92,30 +84,27 @@ const deepClone = (data, options = {}) => {
|
|
|
92
84
|
// Clone Symbol properties
|
|
93
85
|
if (symbols.length > 0) {
|
|
94
86
|
for (const symbol of symbols) {
|
|
95
|
-
newObj[symbol] = deepClone(data[symbol], opts);
|
|
87
|
+
newObj[symbol] = deepClone(data[symbol], { ...opts, parent: data });
|
|
96
88
|
}
|
|
97
89
|
}
|
|
98
90
|
newData = newObj;
|
|
99
91
|
}
|
|
100
92
|
else if (dataType === 'Array' && opts.cloneArray) {
|
|
101
|
-
opts
|
|
102
|
-
newData = data.map(item => deepClone(item, opts));
|
|
93
|
+
newData = data.map(item => deepClone(item, { ...opts, parent: data }));
|
|
103
94
|
}
|
|
104
95
|
else if (dataType === 'Map' && opts.cloneMap) {
|
|
105
96
|
const newMap = new Map();
|
|
106
|
-
opts.parent = data;
|
|
107
97
|
for (const [key, value] of data) {
|
|
108
98
|
// Both Map keys and values need deep cloning
|
|
109
|
-
newMap.set(deepClone(key, opts), deepClone(value, opts));
|
|
99
|
+
newMap.set(deepClone(key, opts), deepClone(value, { ...opts, parent: data }));
|
|
110
100
|
}
|
|
111
101
|
newData = newMap;
|
|
112
102
|
}
|
|
113
103
|
else if (dataType === 'Set' && opts.cloneSet) {
|
|
114
104
|
const newSet = new Set();
|
|
115
|
-
opts.parent = data;
|
|
116
105
|
for (const value of data) {
|
|
117
106
|
// Set values need deep cloning
|
|
118
|
-
newSet.add(deepClone(value, opts));
|
|
107
|
+
newSet.add(deepClone(value, { ...opts, parent: data }));
|
|
119
108
|
}
|
|
120
109
|
newData = newSet;
|
|
121
110
|
}
|
|
@@ -535,8 +524,25 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
535
524
|
}, opts),
|
|
536
525
|
// Main helper function for recursive merging
|
|
537
526
|
// 递归合并的主辅助函数
|
|
538
|
-
|
|
527
|
+
smartMerger = (target, source, options) => {
|
|
539
528
|
let targetType = getDataType(target), sourceType = getDataType(source), flag = true, type, result;
|
|
529
|
+
// Check interceptor - if it returns a value (not null/undefined), use it directly
|
|
530
|
+
if (options.interceptor && typeof options.interceptor === 'function') {
|
|
531
|
+
let interceptorResult = options.interceptor({ target, source, parent: options.parent });
|
|
532
|
+
if ((interceptorResult ?? false)) {
|
|
533
|
+
//如果不是返回{target,source},那么直接返回interceptorResult
|
|
534
|
+
if (interceptorResult?.target === null || interceptorResult?.source === null) {
|
|
535
|
+
return interceptorResult;
|
|
536
|
+
}
|
|
537
|
+
else {
|
|
538
|
+
//interceptorResult={target,source}
|
|
539
|
+
target = interceptorResult.target;
|
|
540
|
+
source = interceptorResult.source;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
// If interceptor returns null/undefined, continue with normal cloning process
|
|
544
|
+
}
|
|
545
|
+
options?.onBeforeMerge?.({ target, source, parent: options.parent });
|
|
540
546
|
// Determine the type and perform appropriate merging
|
|
541
547
|
// 确定类型并执行相应的合并
|
|
542
548
|
if (targetType === 'Object' && sourceType === 'Object') {
|
|
@@ -559,6 +565,7 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
559
565
|
flag = false;
|
|
560
566
|
result = target;
|
|
561
567
|
}
|
|
568
|
+
options?.onAfterMerge?.({ result, target, source, type, parent: opts.parent });
|
|
562
569
|
return { result, flag, type };
|
|
563
570
|
},
|
|
564
571
|
// Special handling for objects with enable property
|
|
@@ -587,7 +594,6 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
587
594
|
if (targetType !== 'Object' || sourceType !== 'Object') {
|
|
588
595
|
return target;
|
|
589
596
|
}
|
|
590
|
-
opts?.onBeforeMerge?.(target, source);
|
|
591
597
|
const options = Object.assign({ inheritMissing: true, targetClone: false, useEnable: true }, opts);
|
|
592
598
|
let result = {};
|
|
593
599
|
// If cloning is enabled, clone the target first
|
|
@@ -595,7 +601,7 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
595
601
|
result = options.targetClone ? shallowCopy(target) : target;
|
|
596
602
|
for (let k in source) {
|
|
597
603
|
if (source.hasOwnProperty(k) && result.hasOwnProperty(k)) {
|
|
598
|
-
let resp =
|
|
604
|
+
let resp = smartMerger(result[k], source[k], { ...opts, parent: result });
|
|
599
605
|
//resp={result,flag,type}
|
|
600
606
|
//flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
|
|
601
607
|
if (!resp.flag) {
|
|
@@ -635,13 +641,11 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
635
641
|
result[k] = source[k];
|
|
636
642
|
}
|
|
637
643
|
}
|
|
638
|
-
options?.onAfterMerge?.(result, target, source);
|
|
639
644
|
return result;
|
|
640
645
|
}, deepMergeArrays = (target, source, options = {}) => {
|
|
641
646
|
// Ensure both target and source are arrays
|
|
642
647
|
if (!Array.isArray(target) || !Array.isArray(source))
|
|
643
648
|
return target;
|
|
644
|
-
options?.onBeforeMerge?.(target, source);
|
|
645
649
|
// Merge options, with default values
|
|
646
650
|
const opts = Object.assign({ dataMode: 'clear', inheritMissing: true, targetClone: false }, options),
|
|
647
651
|
// If cloning is enabled, create a deep copy of the target array
|
|
@@ -654,7 +658,7 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
654
658
|
// 如果不允许添加超过长度
|
|
655
659
|
if (!opts.inheritMissing && i >= result.length)
|
|
656
660
|
break;
|
|
657
|
-
let resp =
|
|
661
|
+
let resp = smartMerger(result[i], source[i], { ...opts, parent: result });
|
|
658
662
|
//resp={result,flag,type}
|
|
659
663
|
//flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
|
|
660
664
|
if (!resp.flag) {
|
|
@@ -671,13 +675,11 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
671
675
|
result.length = 0;
|
|
672
676
|
result.push(...source);
|
|
673
677
|
}
|
|
674
|
-
options?.onAfterMerge?.(result, target, source);
|
|
675
678
|
return result;
|
|
676
679
|
}, deepMergeMaps = (target, source, options = {}) => {
|
|
677
680
|
// Ensure both target and source are Maps
|
|
678
681
|
if (!(target instanceof Map) || !(source instanceof Map))
|
|
679
682
|
return target;
|
|
680
|
-
options?.onBeforeMerge?.(target, source);
|
|
681
683
|
// Merge options, with default values
|
|
682
684
|
const opts = Object.assign({ inheritMissing: true, targetClone: false, useEnable: true }, options),
|
|
683
685
|
// If cloning is enabled, create a deep copy of the target Map
|
|
@@ -686,7 +688,7 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
686
688
|
for (const [key, value] of source.entries())
|
|
687
689
|
// Check if the key already exists in the target Map
|
|
688
690
|
if (result.has(key)) {
|
|
689
|
-
const _target = result.get(key), _source = value, resp =
|
|
691
|
+
const _target = result.get(key), _source = value, resp = smartMerger(_target, _source, opts);
|
|
690
692
|
//resp={result,flag,type}
|
|
691
693
|
//flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
|
|
692
694
|
if (!resp.flag) {
|
|
@@ -702,13 +704,11 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
702
704
|
// If the key doesn't exist in the target, add the entry from the source Map
|
|
703
705
|
options.inheritMissing && result.set(key, value);
|
|
704
706
|
}
|
|
705
|
-
options?.onAfterMerge?.(result, target, source);
|
|
706
707
|
return result;
|
|
707
708
|
}, deepMergeSets = (target, source, options = {}) => {
|
|
708
709
|
// Ensure both target and source are Sets
|
|
709
710
|
if (!(target instanceof Set) || !(source instanceof Set))
|
|
710
711
|
return target;
|
|
711
|
-
options?.onBeforeMerge?.(target, source);
|
|
712
712
|
// Merge options, with default values
|
|
713
713
|
const opts = Object.assign({ dataMode: 'clear', inheritMissing: true, targetClone: false, useEnable: true }, options),
|
|
714
714
|
// If cloning is enabled, create a deep copy of the target Set
|
|
@@ -716,7 +716,7 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
716
716
|
// Handle different merge strategies based on dataMode
|
|
717
717
|
if (opts.dataMode === 'replace') {
|
|
718
718
|
// Replace mode: recursively merge items in the Sets
|
|
719
|
-
const _result = [...result], _source = [...source], resp =
|
|
719
|
+
const _result = [...result], _source = [...source], resp = smartMerger(_result, _source, opts);
|
|
720
720
|
result.clear();
|
|
721
721
|
for (let item of resp.result)
|
|
722
722
|
result.add(item);
|
|
@@ -732,10 +732,9 @@ const deepMerge = (target, source, opts = {}) => {
|
|
|
732
732
|
for (let item of source)
|
|
733
733
|
result.add(item);
|
|
734
734
|
}
|
|
735
|
-
options?.onAfterMerge?.(result, target, source);
|
|
736
735
|
return result;
|
|
737
736
|
};
|
|
738
|
-
return
|
|
737
|
+
return smartMerger(target, source, options).result;
|
|
739
738
|
};
|
|
740
739
|
|
|
741
740
|
const utils = {
|
package/dist/utils.esm.min.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @since Last modified: 2025-12-26
|
|
2
|
+
* @since Last modified: 2025-12-26 15:47:37
|
|
3
3
|
* @name Utils for web front-end.
|
|
4
|
-
* @version 0.0.
|
|
4
|
+
* @version 0.0.16
|
|
5
5
|
* @author AXUI development team <3217728223@qq.com>
|
|
6
6
|
* @description This is a set of general-purpose JavaScript utility functions developed by the AXUI team. All functions are pure and do not involve CSS or other third-party libraries. They are suitable for any web front-end environment.
|
|
7
7
|
* @see {@link https://www.axui.cn|Official website}
|
|
@@ -12,4 +12,4 @@
|
|
|
12
12
|
* @copyright This software supports the MIT License, allowing free learning and commercial use, but please retain the terms 'ax,' 'axui,' 'AX,' and 'AXUI' within the software.
|
|
13
13
|
* @license MIT license
|
|
14
14
|
*/
|
|
15
|
-
const getDataType=e=>{let t,r=Object.prototype.toString.call(e).slice(8,-1);return t="Function"===r&&/^\s*class\s+/.test(e.toString())?"Class":"Object"===r&&Object.getPrototypeOf(e)!==Object.prototype?"Instance":r,t},deepClone=(e,t={})=>{const r=getDataType(e),a=Object.assign({cloneSet:!0,cloneMap:!0,cloneObject:!0,cloneArray:!0,cloneDate:!0,cloneRegex:!0},t);if(a.interceptor&&"function"==typeof a.interceptor){let t=a.interceptor(
|
|
15
|
+
const getDataType=e=>{let t,r=Object.prototype.toString.call(e).slice(8,-1);return t="Function"===r&&/^\s*class\s+/.test(e.toString())?"Class":"Object"===r&&Object.getPrototypeOf(e)!==Object.prototype?"Instance":r,t},deepClone=(e,t={})=>{const r=getDataType(e),a=Object.assign({cloneSet:!0,cloneMap:!0,cloneObject:!0,cloneArray:!0,cloneDate:!0,cloneRegex:!0},t);if(a.interceptor&&"function"==typeof a.interceptor){let t=a.interceptor({input:e,type:r,parent:a.parent});if(t)return t}a.onBeforeClone?.({input:e,type:r,parent:a.parent});let o,n=!0;if("Object"===r&&a.cloneObject){const t={},r=Object.getOwnPropertySymbols(e);for(const r in e)t[r]=deepClone(e[r],a);if(r.length>0)for(const o of r)t[o]=deepClone(e[o],{...a,parent:e});o=t}else if("Array"===r&&a.cloneArray)o=e.map(t=>deepClone(t,{...a,parent:e}));else if("Map"===r&&a.cloneMap){const t=new Map;for(const[r,o]of e)t.set(deepClone(r,a),deepClone(o,{...a,parent:e}));o=t}else if("Set"===r&&a.cloneSet){const t=new Set;for(const r of e)t.add(deepClone(r,{...a,parent:e}));o=t}else if("Date"===r&&a.cloneDate)o=new Date(e.getTime());else if("RegExp"===r&&a.cloneRegex){const t=e;o=new RegExp(t.source,t.flags)}else o=e,n=!1;return a.onAfterClone?.({output:o,input:e,type:r,cloned:n,parent:a.parent}),o},deepCloneToJSON=e=>{const t=getDataType(e);if("Object"===t){const t={};for(const r in e)t[r]=deepCloneToJSON(e[r]);for(const e in t)void 0===t[e]&&Reflect.deleteProperty(t,e);return t}if("Array"===t){return e.map((e,t)=>deepCloneToJSON(e)).filter(e=>void 0!==e)}return["Number","String","Boolean","Null"].includes(t)?e:void 0},arrayMutableMethods=["push","pop","shift","unshift","splice","sort","reverse","copyWithin","fill"],wrapArrayMethods=({target:e,onBeforeMutate:t=()=>{},onAfterMutate:r=()=>{},allowList:a,props:o={}})=>{if(!Array.isArray(e))throw new TypeError("The 'target' parameter must be an array.");a&&!a?.length||(a=arrayMutableMethods);const n={};for(let s of a)n[s]=function(...a){const n={},l=e.length;switch(s){case"push":case"unshift":n.addedItems=[...a];break;case"pop":n.poppedItem=e[l-1];break;case"shift":n.shiftedItem=e[0];break;case"splice":const[t,r]=a,o=t<0?Math.max(l+t,0):Math.min(t,l),s=void 0===r?l-o:r;n.deletedItems=e.slice(o,o+s);break;case"sort":case"reverse":n.oldSnapshot=[...e];break;case"fill":case"copyWithin":const i=a[1]||0,p=void 0===a[2]?l:a[2];n.oldItems=e.slice(i,p),n.start=i,n.end=p}t?.(n);const i=Array.prototype[s].apply(e,a),p={value:i,key:s,args:a,context:n,target:e,...o};return r?.(p),i};return n},requireTypes=(e,t,r)=>{let a=Array.isArray(t)?t:[t],o=getDataType(e),n=o.toLowerCase(),s=a.map(e=>e.toLowerCase()),l=n.includes("html")?"element":n;if(r)try{if(!s.includes(l))throw new TypeError(`Expected data type(s): [${s.join(", ")}], but got: ${l}`)}catch(e){r(e,o)}else if(!s.includes(l))throw new TypeError(`Expected data type(s): [${s.join(", ")}], but got: ${l}`);return o},getUniqueId=(e={})=>{const t=e.prefix,r=e.suffix,a=e.base10,o=e.base36;return`${t?t+"-":""}${Date.now()}${o?"-"+Math.random().toString(36).substring(2,11):""}${a?"-"+Math.floor(1e4*Math.random()).toString().padStart(4,"0"):""}${r?"-"+r:""}`},setMutableMethods=["add","delete","clear"],mapMutableMethods=["set","delete","clear"],wrapSetMethods=({target:e,onBeforeMutate:t=()=>{},onAfterMutate:r=()=>{},allowList:a=setMutableMethods,props:o={}})=>{if(!(e instanceof Set))throw new TypeError("The 'target' parameter must be a Set.");const n={},createWrappedMethod=a=>function(...n){const s={};switch(a){case"add":{const[t]=n;s.addedItem=t,s.existed=e.has(t);break}case"delete":{const[t]=n;s.existed=e.has(t),s.deletedItem=s.existed?t:void 0;break}case"clear":s.clearedItems=Array.from(e),s.previousSize=e.size}t(s);const l=e[a].apply(e,n),i={method:a,result:l,args:n,context:s,target:e,...o};return r(i),l};for(const e of a)setMutableMethods.includes(e)&&(n[e]=createWrappedMethod(e));return Object.defineProperty(n,"target",{get:()=>e,enumerable:!1,configurable:!1}),n},wrapMapMethods=({target:e,onBeforeMutate:t=()=>{},onAfterMutate:r=()=>{},allowList:a=mapMutableMethods,props:o={}})=>{if(!(e instanceof Map))throw new TypeError("The 'target' parameter must be a Map.");const n={},createWrappedMethod=a=>function(...n){const s={};switch(a){case"set":{const[t,r]=n;s.key=t,s.newValue=r,s.existed=e.has(t),s.oldValue=s.existed?e.get(t):void 0;break}case"delete":{const[t]=n;s.key=t,s.existed=e.has(t),s.value=s.existed?e.get(t):void 0;break}case"clear":s.clearedItems=Array.from(e.entries()),s.previousSize=e.size}t(s);const l=e[a].apply(e,n),i={method:a,result:l,args:n,context:s,target:e,...o};return r(i),l};for(const e of a)mapMutableMethods.includes(e)&&(n[e]=createWrappedMethod(e));return Object.defineProperty(n,"target",{get:()=>e,enumerable:!1,configurable:!1}),n},copyObjectWithSymbol=e=>{if(!e||"object"!=typeof e)return e;const t=e,r=Object.getOwnPropertySymbols(t).reduce((e,r)=>(e[r]=t[r],e),{});return{...t,...r}},shallowCopy=(e,t={})=>{const r=getDataType(e);return"Set"===r?new Set([...e]):"Map"===r?new Map([...e]):Array.isArray(e)?[...e]:"object"===r?copyObjectWithSymbol(e):"Date"===r?new Date(e.getTime()):"RegExp"===r?new RegExp(e.source,e.flags):"Buffer"===r?Buffer.from(e):"ArrayBuffer"===r||ArrayBuffer.isView(e)?e.slice(0):"WeakSet"===r?new WeakSet([...e]):"WeakMap"===r?new WeakMap([...e]):"Error"===r?new Error(e.message):e},deepMerge=(e,t,r={})=>{const a=Object.assign({dataMode:"clear",inheritMissing:!0,targetClone:!1,useEnable:!0,useSymbol:!0,deepClone:{},onBeforeMerge:void 0,onAfterMerge:void 0},r),smartMerger=(e,t,a)=>{let o,n,s=getDataType(e),l=getDataType(t),i=!0;if(a.interceptor&&"function"==typeof a.interceptor){let r=a.interceptor({target:e,source:t,parent:a.parent});if(r){if(null===r?.target||null===r?.source)return r;e=r.target,t=r.source}}return a?.onBeforeMerge?.({target:e,source:t,parent:a.parent}),"Object"===s&&"Object"===l?(n=deepMergeObjects(e,t,a),o="Object"):"Array"===s&&"Array"===l?(n=deepMergeArrays(e,t,a),o="Array"):"Set"===s&&"Set"===l?(n=deepMergeSets(e,t,a),o="Set"):"Map"===s&&"Map"===l?(n=deepMergeMaps(e,t,a),o="Map"):(i=!1,n=e),a?.onAfterMerge?.({result:n,target:e,source:t,type:o,parent:r.parent}),{result:n,flag:i,type:o}},mergeEnableObject=(e,t)=>e?.hasOwnProperty("enable")&&"boolean"==typeof t?(e.enable=t,e):t?.hasOwnProperty("enable")&&"boolean"==typeof e?Object.assign({enable:e},t):t,deepMergeObjects=(e,t,r={})=>{let a=getDataType(e),o=getDataType(t);if("Object"!==a||"Object"!==o)return e;const n=Object.assign({inheritMissing:!0,targetClone:!1,useEnable:!0},r);let s={};s=n.targetClone?shallowCopy(e):e;for(let e in t)if(t.hasOwnProperty(e)&&s.hasOwnProperty(e)){let a=smartMerger(s[e],t[e],{...r,parent:s});a.flag?a.type?"Object"===a.type&&(s[e]=a.result):s[e]=t[e]:n.useEnable?s[e]=mergeEnableObject(s[e],t[e]):s[e]=t[e]}else t.hasOwnProperty(e)&&!s.hasOwnProperty(e)&&n.inheritMissing&&(s[e]=t[e]);if(n.useSymbol){let e=Object.getOwnPropertySymbols(t);if(e.length)for(let r of e)s[r]=t[r]}return s},deepMergeArrays=(e,t,r={})=>{if(!Array.isArray(e)||!Array.isArray(t))return e;const a=Object.assign({dataMode:"clear",inheritMissing:!0,targetClone:!1},r),o=a.targetClone?[...e]:e;if("replace"===a.dataMode)for(let e=0;e<t.length&&(a.inheritMissing||!(e>=o.length));e++){smartMerger(o[e],t[e],{...a,parent:o}).flag||(o[e]=t[e])}else"concat"===a.dataMode||(o.length=0),o.push(...t);return o},deepMergeMaps=(e,t,r={})=>{if(!(e instanceof Map&&t instanceof Map))return e;const a=Object.assign({inheritMissing:!0,targetClone:!1,useEnable:!0},r),o=a.targetClone?new Map([...e]):e;for(const[e,n]of t.entries())if(o.has(e)){const t=o.get(e),r=n,s=smartMerger(t,r,a);s.flag?"Object"===s.type&&o.set(e,s.result):o.set(e,r)}else r.inheritMissing&&o.set(e,n);return o},deepMergeSets=(e,t,r={})=>{if(!(e instanceof Set&&t instanceof Set))return e;const a=Object.assign({dataMode:"clear",inheritMissing:!0,targetClone:!1,useEnable:!0},r),o=a.targetClone?new Set(...e):e;if("replace"===a.dataMode){const e=[...o],r=[...t],n=smartMerger(e,r,a);o.clear();for(let e of n.result)o.add(e)}else if("concat"===a.dataMode)for(let e of t)o.add(e);else{o.clear();for(let e of t)o.add(e)}return o};return smartMerger(e,t,a).result},utils={getDataType:getDataType,requireTypes:requireTypes,deepClone:deepClone,deepCloneToJSON:deepCloneToJSON,wrapArrayMethods:wrapArrayMethods,arrayMutableMethods:arrayMutableMethods,setMutableMethods:setMutableMethods,mapMutableMethods:mapMutableMethods,wrapSetMethods:wrapSetMethods,wrapMapMethods:wrapMapMethods,getUniqueId:getUniqueId,deepMerge:deepMerge,shallowCopy:shallowCopy,copyObjectWithSymbol:copyObjectWithSymbol};export{utils as default};
|