@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/src/deepMerge.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @since Last modified: 2025/12/25 12:10:30
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
- // Callback function executed before merging each data structure
63
- // 在每个数据结构合并前执行的回调函数
64
- onBeforeMerge?: (
65
- target: Object | Array<any> | Map<any, any> | Set<any>,
66
- source: Object | Array<any> | Map<any, any> | Set<any> | any
67
- ) => void;
68
-
69
- // Callback function executed after merging each data structure
70
- // 在每个数据结构合并后执行的回调函数
71
- onAfterMerge?: (
72
- result: Object | Array<any> | Map<any, any> | Set<any>,
73
- originalTarget: Object | Array<any> | Map<any, any> | Set<any>,
74
- source: Object | Array<any> | Map<any, any> | Set<any> | any
75
- ) => void;
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
- deepMergeHelper = (target: any, source: any, options: DeepMergeOptions): any => {
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
- type,
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
- type = 'Object';
182
+ mergeType = 'Object';
136
183
  } else if (targetType === 'Array' && sourceType === 'Array') {
137
184
  result = deepMergeArrays(target, source, options);
138
- type = 'Array';
185
+ mergeType = 'Array';
139
186
  } else if (targetType === 'Set' && sourceType === 'Set') {
140
187
  result = deepMergeSets(target, source, options);
141
- type = 'Set';
188
+ mergeType = 'Set';
142
189
  } else if (targetType === 'Map' && sourceType === 'Map') {
143
190
  result = deepMergeMaps(target, source, options);
144
- type = 'Map';
191
+ mergeType = 'Map';
145
192
  } else {
146
193
  flag = false;
147
194
  result = target;
148
195
  }
149
- return { result, flag, type };
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 = deepMergeHelper((result as any)[k], source[k], opts);
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.type) {
202
- if (resp.type === 'Object') {
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
- options?.onBeforeMerge?.(target, source);
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 = deepMergeHelper(result[i], source[i], opts);
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
- options?.onBeforeMerge?.(target, source);
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 = deepMergeHelper(_target, _source, opts);
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.type === 'Object' && result.set(key, resp.result);
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
- options?.onBeforeMerge?.(target, source);
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 = deepMergeHelper(_result, _source, opts);
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
- options?.onAfterMerge?.(result, target, source);
366
+
324
367
  return result;
325
368
  };
326
- return deepMergeHelper(target, source, options).result;
369
+
370
+
371
+ return smartMerger(target, source, options).result;
327
372
  }
328
373
  export default deepMerge;