@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/src/deepMerge.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @since Last modified: 2025/12/
|
|
2
|
+
* @since Last modified: 2025/12/26 15:40:50
|
|
3
3
|
* @function deepMerge
|
|
4
4
|
* @description Deeply merges two data structures (Object, Array, Map, or Set) based on their types.
|
|
5
5
|
* This function recursively merges the properties or items of the target and source, depending on their types.
|
|
@@ -59,20 +59,42 @@ export interface DeepMergeOptions {
|
|
|
59
59
|
// 启用克隆时传递给deepClone函数的选项
|
|
60
60
|
deepClone?: Record<string, any>;
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
62
|
+
/**
|
|
63
|
+
* Interceptor function. If returns a non-null value, use it as the merging result.
|
|
64
|
+
* 拦截器函数。如果返回非null值,则将其用作合并结果。
|
|
65
|
+
*/
|
|
66
|
+
interceptor?: (params: {
|
|
67
|
+
target: any;
|
|
68
|
+
source: any;
|
|
69
|
+
parent?: any;
|
|
70
|
+
}) => any;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Callback function executed before merging each data structure
|
|
74
|
+
* 在每个数据结构合并前执行的回调函数
|
|
75
|
+
*/
|
|
76
|
+
onBeforeMerge?: (params: {
|
|
77
|
+
target: any;
|
|
78
|
+
source: any;
|
|
79
|
+
parent?: any;
|
|
80
|
+
}) => void;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Callback function executed after merging each data structure
|
|
84
|
+
* 在每个数据结构合并后执行的回调函数
|
|
85
|
+
*/
|
|
86
|
+
onAfterMerge?: (params: {
|
|
87
|
+
result: any;
|
|
88
|
+
target: any;
|
|
89
|
+
source: any;
|
|
90
|
+
parent?: any;
|
|
91
|
+
type?: '' | 'Object' | 'Array' | 'Map' | 'Set';
|
|
92
|
+
}) => void;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* 深度合并时的临时保存的父对象
|
|
96
|
+
*/
|
|
97
|
+
parent?: any;
|
|
76
98
|
}
|
|
77
99
|
export type EnableObject = {
|
|
78
100
|
enable: boolean;
|
|
@@ -122,12 +144,31 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
122
144
|
}, opts),
|
|
123
145
|
// Main helper function for recursive merging
|
|
124
146
|
// 递归合并的主辅助函数
|
|
125
|
-
|
|
147
|
+
smartMerger = (target: any, source: any, options: DeepMergeOptions): any => {
|
|
126
148
|
let targetType = getDataType(target),
|
|
127
149
|
sourceType = getDataType(source),
|
|
128
150
|
flag = true,
|
|
129
|
-
type,
|
|
151
|
+
type: any,
|
|
130
152
|
result;
|
|
153
|
+
|
|
154
|
+
// Check interceptor - if it returns a value (not null/undefined), use it directly
|
|
155
|
+
if (options.interceptor && typeof options.interceptor === 'function') {
|
|
156
|
+
let interceptorResult = options.interceptor({ target, source, parent: options.parent });
|
|
157
|
+
if ((interceptorResult ?? false)) {
|
|
158
|
+
//如果不是返回{target,source},那么直接返回interceptorResult
|
|
159
|
+
if (interceptorResult?.target === null || interceptorResult?.source === null) {
|
|
160
|
+
return interceptorResult;
|
|
161
|
+
} else {
|
|
162
|
+
//interceptorResult={target,source}
|
|
163
|
+
target = interceptorResult.target;
|
|
164
|
+
source = interceptorResult.source;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// If interceptor returns null/undefined, continue with normal cloning process
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
options?.onBeforeMerge?.({ target, source, parent: options.parent });
|
|
171
|
+
|
|
131
172
|
// Determine the type and perform appropriate merging
|
|
132
173
|
// 确定类型并执行相应的合并
|
|
133
174
|
if (targetType === 'Object' && sourceType === 'Object') {
|
|
@@ -146,6 +187,7 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
146
187
|
flag = false;
|
|
147
188
|
result = target;
|
|
148
189
|
}
|
|
190
|
+
options?.onAfterMerge?.({ result, target, source, type, parent: opts.parent });
|
|
149
191
|
return { result, flag, type };
|
|
150
192
|
},
|
|
151
193
|
// Special handling for objects with enable property
|
|
@@ -174,7 +216,6 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
174
216
|
if (targetType !== 'Object' || sourceType !== 'Object') {
|
|
175
217
|
return target;
|
|
176
218
|
}
|
|
177
|
-
opts?.onBeforeMerge?.(target, source);
|
|
178
219
|
|
|
179
220
|
const options = Object.assign({ inheritMissing: true, targetClone: false, useEnable: true }, opts);
|
|
180
221
|
let result: any = {};
|
|
@@ -185,7 +226,7 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
185
226
|
for (let k in source) {
|
|
186
227
|
if (source.hasOwnProperty(k) && result.hasOwnProperty(k)) {
|
|
187
228
|
|
|
188
|
-
let resp =
|
|
229
|
+
let resp = smartMerger((result as any)[k], source[k], { ...opts, parent: result });
|
|
189
230
|
//resp={result,flag,type}
|
|
190
231
|
//flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
|
|
191
232
|
if (!resp.flag) {
|
|
@@ -221,13 +262,12 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
221
262
|
for (let k of symbols) (result as any)[k] = source[k];
|
|
222
263
|
}
|
|
223
264
|
}
|
|
224
|
-
options?.onAfterMerge?.(result, target, source);
|
|
225
265
|
return result;
|
|
226
266
|
},
|
|
227
267
|
deepMergeArrays = (target: any[], source: any[], options: DeepMergeOptions = {}): any[] => {
|
|
228
268
|
// Ensure both target and source are arrays
|
|
229
269
|
if (!Array.isArray(target) || !Array.isArray(source)) return target;
|
|
230
|
-
|
|
270
|
+
|
|
231
271
|
// Merge options, with default values
|
|
232
272
|
const opts = Object.assign({ dataMode: 'clear', inheritMissing: true, targetClone: false }, options),
|
|
233
273
|
|
|
@@ -241,7 +281,7 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
241
281
|
// If not allowed to add beyond length
|
|
242
282
|
// 如果不允许添加超过长度
|
|
243
283
|
if (!opts.inheritMissing && i >= result.length) break;
|
|
244
|
-
let resp =
|
|
284
|
+
let resp = smartMerger(result[i], source[i], { ...opts, parent: result });
|
|
245
285
|
//resp={result,flag,type}
|
|
246
286
|
//flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
|
|
247
287
|
if (!resp.flag) {
|
|
@@ -256,13 +296,12 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
256
296
|
result.length = 0;
|
|
257
297
|
result.push(...source);
|
|
258
298
|
}
|
|
259
|
-
options?.onAfterMerge?.(result, target, source);
|
|
260
299
|
return result;
|
|
261
300
|
},
|
|
262
301
|
deepMergeMaps = (target: Map<any, any>, source: Map<any, any>, options: DeepMergeOptions = {}): Map<any, any> => {
|
|
263
302
|
// Ensure both target and source are Maps
|
|
264
303
|
if (!(target instanceof Map) || !(source instanceof Map)) return target;
|
|
265
|
-
|
|
304
|
+
|
|
266
305
|
// Merge options, with default values
|
|
267
306
|
const opts = Object.assign({ inheritMissing: true, targetClone: false, useEnable: true }, options),
|
|
268
307
|
|
|
@@ -275,7 +314,7 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
275
314
|
if (result.has(key)) {
|
|
276
315
|
const _target = result.get(key),
|
|
277
316
|
_source = value,
|
|
278
|
-
resp =
|
|
317
|
+
resp = smartMerger(_target, _source, opts);
|
|
279
318
|
//resp={result,flag,type}
|
|
280
319
|
//flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
|
|
281
320
|
if (!resp.flag) {
|
|
@@ -289,13 +328,12 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
289
328
|
// If the key doesn't exist in the target, add the entry from the source Map
|
|
290
329
|
options.inheritMissing && result.set(key, value);
|
|
291
330
|
}
|
|
292
|
-
options?.onAfterMerge?.(result, target, source);
|
|
293
331
|
return result;
|
|
294
332
|
},
|
|
295
333
|
deepMergeSets = (target: Set<any>, source: Set<any>, options: DeepMergeOptions = {}): Set<any> => {
|
|
296
334
|
// Ensure both target and source are Sets
|
|
297
335
|
if (!(target instanceof Set) || !(source instanceof Set)) return target;
|
|
298
|
-
|
|
336
|
+
|
|
299
337
|
// Merge options, with default values
|
|
300
338
|
const opts = Object.assign({ dataMode: 'clear', inheritMissing: true, targetClone: false, useEnable: true }, options),
|
|
301
339
|
|
|
@@ -307,11 +345,10 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
307
345
|
// Replace mode: recursively merge items in the Sets
|
|
308
346
|
const _result = [...result],
|
|
309
347
|
_source = [...source],
|
|
310
|
-
resp =
|
|
348
|
+
resp = smartMerger(_result, _source, opts);
|
|
311
349
|
result.clear();
|
|
312
350
|
for (let item of resp.result) result.add(item);
|
|
313
351
|
|
|
314
|
-
|
|
315
352
|
} else if (opts.dataMode === 'concat') {
|
|
316
353
|
// Concatenate mode: add all items from the source Set to the target Set
|
|
317
354
|
for (let item of source) result.add(item);
|
|
@@ -320,9 +357,11 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
320
357
|
result.clear();
|
|
321
358
|
for (let item of source) result.add(item);
|
|
322
359
|
}
|
|
323
|
-
|
|
360
|
+
|
|
324
361
|
return result;
|
|
325
362
|
};
|
|
326
|
-
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
return smartMerger(target, source, options).result;
|
|
327
366
|
}
|
|
328
367
|
export default deepMerge;
|