@codady/utils 0.0.15 → 0.0.17
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 +37 -33
- package/dist/utils.cjs.min.js +3 -3
- package/dist/utils.esm.js +37 -33
- package/dist/utils.esm.min.js +3 -3
- package/dist/utils.umd.js +37 -33
- package/dist/utils.umd.min.js +3 -3
- package/dist.zip +0 -0
- package/package.json +1 -1
- package/src/deepClone.js +9 -9
- package/src/deepClone.ts +5 -5
- package/src/deepMerge.js +34 -24
- package/src/deepMerge.ts +84 -39
package/src/deepMerge.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @since Last modified: 2025/12/
|
|
2
|
+
* @since Last modified: 2025/12/26 16:03:37
|
|
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,48 @@ 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
|
+
targetType: string;
|
|
71
|
+
sourceType: string;
|
|
72
|
+
}) => any;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Callback function executed before merging each data structure
|
|
76
|
+
* 在每个数据结构合并前执行的回调函数
|
|
77
|
+
*/
|
|
78
|
+
onBeforeMerge?: (params: {
|
|
79
|
+
target: any;
|
|
80
|
+
source: any;
|
|
81
|
+
parent?: any;
|
|
82
|
+
targetType: string;
|
|
83
|
+
sourceType: string;
|
|
84
|
+
}) => void;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Callback function executed after merging each data structure
|
|
88
|
+
* 在每个数据结构合并后执行的回调函数
|
|
89
|
+
*/
|
|
90
|
+
onAfterMerge?: (params: {
|
|
91
|
+
result: any;
|
|
92
|
+
target: any;
|
|
93
|
+
source: any;
|
|
94
|
+
parent?: any;
|
|
95
|
+
targetType: string;
|
|
96
|
+
sourceType: string;
|
|
97
|
+
mergeType?: '' | 'Object' | 'Array' | 'Map' | 'Set';
|
|
98
|
+
}) => void;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* 深度合并时的临时保存的父对象
|
|
102
|
+
*/
|
|
103
|
+
parent?: any;
|
|
76
104
|
}
|
|
77
105
|
export type EnableObject = {
|
|
78
106
|
enable: boolean;
|
|
@@ -122,31 +150,51 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
122
150
|
}, opts),
|
|
123
151
|
// Main helper function for recursive merging
|
|
124
152
|
// 递归合并的主辅助函数
|
|
125
|
-
|
|
153
|
+
smartMerger = (target: any, source: any, options: DeepMergeOptions): any => {
|
|
126
154
|
let targetType = getDataType(target),
|
|
127
155
|
sourceType = getDataType(source),
|
|
128
156
|
flag = true,
|
|
129
|
-
|
|
157
|
+
mergeType: any,
|
|
130
158
|
result;
|
|
159
|
+
|
|
160
|
+
// Check interceptor - if it returns a value (not null/undefined), use it directly
|
|
161
|
+
if (options.interceptor && typeof options.interceptor === 'function') {
|
|
162
|
+
let interceptorResult = options.interceptor({ target, source, targetType, sourceType, parent: options.parent });
|
|
163
|
+
if ((interceptorResult ?? false)) {
|
|
164
|
+
//如果不是返回{target,source},那么直接返回interceptorResult
|
|
165
|
+
if (interceptorResult?.target === null || interceptorResult?.source === null) {
|
|
166
|
+
return interceptorResult;
|
|
167
|
+
} else {
|
|
168
|
+
//interceptorResult={target,source}
|
|
169
|
+
target = interceptorResult.target;
|
|
170
|
+
source = interceptorResult.source;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// If interceptor returns null/undefined, continue with normal cloning process
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
options?.onBeforeMerge?.({ target, source, targetType, sourceType, parent: options.parent });
|
|
177
|
+
|
|
131
178
|
// Determine the type and perform appropriate merging
|
|
132
179
|
// 确定类型并执行相应的合并
|
|
133
180
|
if (targetType === 'Object' && sourceType === 'Object') {
|
|
134
181
|
result = deepMergeObjects(target, source, options);
|
|
135
|
-
|
|
182
|
+
mergeType = 'Object';
|
|
136
183
|
} else if (targetType === 'Array' && sourceType === 'Array') {
|
|
137
184
|
result = deepMergeArrays(target, source, options);
|
|
138
|
-
|
|
185
|
+
mergeType = 'Array';
|
|
139
186
|
} else if (targetType === 'Set' && sourceType === 'Set') {
|
|
140
187
|
result = deepMergeSets(target, source, options);
|
|
141
|
-
|
|
188
|
+
mergeType = 'Set';
|
|
142
189
|
} else if (targetType === 'Map' && sourceType === 'Map') {
|
|
143
190
|
result = deepMergeMaps(target, source, options);
|
|
144
|
-
|
|
191
|
+
mergeType = 'Map';
|
|
145
192
|
} else {
|
|
146
193
|
flag = false;
|
|
147
194
|
result = target;
|
|
148
195
|
}
|
|
149
|
-
|
|
196
|
+
options?.onAfterMerge?.({ result, target, source, targetType, sourceType, mergeType, parent: opts.parent });
|
|
197
|
+
return { result, flag, mergeType };
|
|
150
198
|
},
|
|
151
199
|
// Special handling for objects with enable property
|
|
152
200
|
// 对具有enable属性的对象进行特殊处理
|
|
@@ -174,7 +222,6 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
174
222
|
if (targetType !== 'Object' || sourceType !== 'Object') {
|
|
175
223
|
return target;
|
|
176
224
|
}
|
|
177
|
-
opts?.onBeforeMerge?.(target, source);
|
|
178
225
|
|
|
179
226
|
const options = Object.assign({ inheritMissing: true, targetClone: false, useEnable: true }, opts);
|
|
180
227
|
let result: any = {};
|
|
@@ -185,7 +232,7 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
185
232
|
for (let k in source) {
|
|
186
233
|
if (source.hasOwnProperty(k) && result.hasOwnProperty(k)) {
|
|
187
234
|
|
|
188
|
-
let resp =
|
|
235
|
+
let resp = smartMerger((result as any)[k], source[k], { ...opts, parent: result });
|
|
189
236
|
//resp={result,flag,type}
|
|
190
237
|
//flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
|
|
191
238
|
if (!resp.flag) {
|
|
@@ -198,8 +245,8 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
198
245
|
}
|
|
199
246
|
} else {
|
|
200
247
|
//类型相同
|
|
201
|
-
if (resp.
|
|
202
|
-
if (resp.
|
|
248
|
+
if (resp.mergeType) {
|
|
249
|
+
if (resp.mergeType === 'Object') {
|
|
203
250
|
//如果遇上对象则深度复制
|
|
204
251
|
(result as any)[k] = resp.result;
|
|
205
252
|
}
|
|
@@ -221,13 +268,12 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
221
268
|
for (let k of symbols) (result as any)[k] = source[k];
|
|
222
269
|
}
|
|
223
270
|
}
|
|
224
|
-
options?.onAfterMerge?.(result, target, source);
|
|
225
271
|
return result;
|
|
226
272
|
},
|
|
227
273
|
deepMergeArrays = (target: any[], source: any[], options: DeepMergeOptions = {}): any[] => {
|
|
228
274
|
// Ensure both target and source are arrays
|
|
229
275
|
if (!Array.isArray(target) || !Array.isArray(source)) return target;
|
|
230
|
-
|
|
276
|
+
|
|
231
277
|
// Merge options, with default values
|
|
232
278
|
const opts = Object.assign({ dataMode: 'clear', inheritMissing: true, targetClone: false }, options),
|
|
233
279
|
|
|
@@ -241,7 +287,7 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
241
287
|
// If not allowed to add beyond length
|
|
242
288
|
// 如果不允许添加超过长度
|
|
243
289
|
if (!opts.inheritMissing && i >= result.length) break;
|
|
244
|
-
let resp =
|
|
290
|
+
let resp = smartMerger(result[i], source[i], { ...opts, parent: result });
|
|
245
291
|
//resp={result,flag,type}
|
|
246
292
|
//flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
|
|
247
293
|
if (!resp.flag) {
|
|
@@ -256,13 +302,12 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
256
302
|
result.length = 0;
|
|
257
303
|
result.push(...source);
|
|
258
304
|
}
|
|
259
|
-
options?.onAfterMerge?.(result, target, source);
|
|
260
305
|
return result;
|
|
261
306
|
},
|
|
262
307
|
deepMergeMaps = (target: Map<any, any>, source: Map<any, any>, options: DeepMergeOptions = {}): Map<any, any> => {
|
|
263
308
|
// Ensure both target and source are Maps
|
|
264
309
|
if (!(target instanceof Map) || !(source instanceof Map)) return target;
|
|
265
|
-
|
|
310
|
+
|
|
266
311
|
// Merge options, with default values
|
|
267
312
|
const opts = Object.assign({ inheritMissing: true, targetClone: false, useEnable: true }, options),
|
|
268
313
|
|
|
@@ -275,7 +320,7 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
275
320
|
if (result.has(key)) {
|
|
276
321
|
const _target = result.get(key),
|
|
277
322
|
_source = value,
|
|
278
|
-
resp =
|
|
323
|
+
resp = smartMerger(_target, _source, opts);
|
|
279
324
|
//resp={result,flag,type}
|
|
280
325
|
//flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
|
|
281
326
|
if (!resp.flag) {
|
|
@@ -283,19 +328,18 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
283
328
|
result.set(key, _source);
|
|
284
329
|
} else {
|
|
285
330
|
// If both target and source are objects, merge them recursively
|
|
286
|
-
resp.
|
|
331
|
+
resp.mergeType === 'Object' && result.set(key, resp.result);
|
|
287
332
|
}
|
|
288
333
|
} else {
|
|
289
334
|
// If the key doesn't exist in the target, add the entry from the source Map
|
|
290
335
|
options.inheritMissing && result.set(key, value);
|
|
291
336
|
}
|
|
292
|
-
options?.onAfterMerge?.(result, target, source);
|
|
293
337
|
return result;
|
|
294
338
|
},
|
|
295
339
|
deepMergeSets = (target: Set<any>, source: Set<any>, options: DeepMergeOptions = {}): Set<any> => {
|
|
296
340
|
// Ensure both target and source are Sets
|
|
297
341
|
if (!(target instanceof Set) || !(source instanceof Set)) return target;
|
|
298
|
-
|
|
342
|
+
|
|
299
343
|
// Merge options, with default values
|
|
300
344
|
const opts = Object.assign({ dataMode: 'clear', inheritMissing: true, targetClone: false, useEnable: true }, options),
|
|
301
345
|
|
|
@@ -307,11 +351,10 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
307
351
|
// Replace mode: recursively merge items in the Sets
|
|
308
352
|
const _result = [...result],
|
|
309
353
|
_source = [...source],
|
|
310
|
-
resp =
|
|
354
|
+
resp = smartMerger(_result, _source, opts);
|
|
311
355
|
result.clear();
|
|
312
356
|
for (let item of resp.result) result.add(item);
|
|
313
357
|
|
|
314
|
-
|
|
315
358
|
} else if (opts.dataMode === 'concat') {
|
|
316
359
|
// Concatenate mode: add all items from the source Set to the target Set
|
|
317
360
|
for (let item of source) result.add(item);
|
|
@@ -320,9 +363,11 @@ const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, sourc
|
|
|
320
363
|
result.clear();
|
|
321
364
|
for (let item of source) result.add(item);
|
|
322
365
|
}
|
|
323
|
-
|
|
366
|
+
|
|
324
367
|
return result;
|
|
325
368
|
};
|
|
326
|
-
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
return smartMerger(target, source, options).result;
|
|
327
372
|
}
|
|
328
373
|
export default deepMerge;
|