@codady/utils 0.0.11 → 0.0.13

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.
@@ -1,7 +1,7 @@
1
1
  /*!
2
- * @since Last modified: 2025-12-24 17:50:8
2
+ * @since Last modified: 2025-12-25 14:33:12
3
3
  * @name Utils for web front-end.
4
- * @version 0.0.11
4
+ * @version 0.0.13
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";var assert=require("assert");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(e,r);if(t)return a.onAfterClone?.({output:t,input:e,type:r,cloned:t!==e}),t}a.onBeforeClone?.(e,r);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);o=t}else if("Array"===r&&a.cloneArray)o=e.map(e=>deepClone(e,a));else if("Map"===r&&a.cloneMap){const t=new Map;for(const[r,o]of e)t.set(deepClone(r,a),deepClone(o,a));o=t}else if("Set"===r&&a.cloneSet){const t=new Set;for(const r of e)t.add(deepClone(r,a));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}),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={},p=e.length;switch(s){case"push":case"unshift":n.addedItems=[...a];break;case"pop":n.poppedItem=e[p-1];break;case"shift":n.shiftedItem=e[0];break;case"splice":const[t,r]=a,o=t<0?Math.max(p+t,0):Math.min(t,p),s=void 0===r?p-o:r;n.deletedItems=e.slice(o,o+s);break;case"sort":case"reverse":n.oldSnapshot=[...e];break;case"fill":case"copyWithin":const l=a[1]||0,c=void 0===a[2]?p:a[2];n.oldItems=e.slice(l,c),n.start=l,n.end=c}t?.(n);const l=Array.prototype[s].apply(e,a),c={value:l,key:s,args:a,context:n,target:e,...o};return r?.(c),l};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()),p=n.includes("html")?"element":n;if(r)try{if(!s.includes(p))throw new TypeError(`Expected data type(s): [${s.join(", ")}], but got: ${p}`)}catch(e){r(e,o)}else if(!s.includes(p))throw new TypeError(`Expected data type(s): [${s.join(", ")}], but got: ${p}`);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 p=e[a].apply(e,n),l={method:a,result:p,args:n,context:s,target:e,...o};return r(l),p};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 p=e[a].apply(e,n),l={method:a,result:p,args:n,context:s,target:e,...o};return r(l),p};for(const e of a)mapMutableMethods.includes(e)&&(n[e]=createWrappedMethod(e));return Object.defineProperty(n,"target",{get:()=>e,enumerable:!1,configurable:!1}),n},deepMergeObjects=(e,t,r={})=>{let a=getDataType(e),o=getDataType(t);if("Object"!==a||"Object"!==o)return e;const n=Object.assign({itemMode:"merge",propAppend:!0,targetClone:!1,useEnable:!0},r),s=n.targetClone?deepClone(e):e;for(let e in t)if(t.hasOwnProperty(e)&&s.hasOwnProperty(e)){let a=deepMergeHelper(s[e],t[e],r);a.flag?"Object"===a.type&&(s[e]=a.result):n.useEnable&&s.hasOwnProperty(e)&&s[e]?.hasOwnProperty("enable")&&"boolean"==typeof t[e]?s[e]?.hasOwnProperty("enable")&&"boolean"==typeof t[e]?s[e].enable=t[e]:t[e]?.hasOwnProperty("enable")&&"boolean"==typeof s[e]?s=Object.assign({enable:s[e]},t[e]):s[e]=t[e]:s[e]=t[e]}else t.hasOwnProperty(e)&&!s.hasOwnProperty(e)&&n.propAppend&&(s[e]=t[e]);if(n.useSymbol){let e=Object.getOwnPropertySymbols(t);if(e.length>0)for(let r of e)s[r]=t[r]}return s},deepMergeArrays=(e,t,r={itemMode:"merge",propAppend:!0,targetClone:!1,useEnable:!0})=>{if(!Array.isArray(e)||!Array.isArray(t))return e;const a=Object.assign({itemMode:"merge",propAppend:!0,targetClone:!1},r),o=a.targetClone?[...e]:e;if("replace"===a.itemMode)return o.length=0,o.push(...t),o;if("concat"===a.itemMode)return o.push(...t),o;for(let e=0;e<t.length;e++){deepMergeHelper(o[e],t[e],a).flag||(o[e]=t[e])}return o},deepMergeMaps=(e,t,r={itemMode:"merge",propAppend:!0,targetClone:!1,useEnable:!0})=>{if(!(e instanceof Map&&t instanceof Map))return e;const a=Object.assign({itemMode:"merge",propAppend:!0,targetClone:!1,useEnable:!0},r),o=a.targetClone?new Map(e):e;return"replace"===a.itemMode?(o.clear(),t.forEach((e,t)=>o.set(t,e)),o):"concat"===a.itemMode?(t.forEach((e,t)=>o.set(t,e)),o):(t.forEach((e,t)=>{if(o.has(t)){const r=o.get(t),n=e,s=deepMergeHelper(r,n,a);s.flag?"Object"===s.type&&o.set(t,s.result):o.set(t,n)}else o.set(t,e)}),o)},deepEqual=(e,t)=>{if(e===t)return!0;if(Array.isArray(e)&&Array.isArray(t)){if(e.length!==t.length)return!1;for(let r=0;r<e.length;r++)if(!deepEqual(e[r],t[r]))return!1;return!0}if("object"==typeof e&&"object"==typeof t){const r=Object.keys(e),a=Object.keys(t);if(r.length!==a.length)return!1;for(let o of r)if(!a.includes(o)||!deepEqual(e[o],t[o]))return!1;return!0}return e===t},deepMergeSets=(e,t,r={itemMode:"merge",propAppend:!0,targetClone:!1,useEnable:!0})=>{if(!(e instanceof Set&&t instanceof Set))return e;const a=Object.assign({itemMode:"merge",propAppend:!0,targetClone:!1,useEnable:!0},r),o=a.targetClone?new Set(e):e;if("replace"===a.itemMode){o.clear();for(let e of t)o.add(e);return o}if("concat"===a.itemMode){for(let e of t)o.add(e);return o}for(let e of t){let t=[...o].find(t=>deepEqual(t,e));!deepMergeHelper(t,e,a).flag&&o.add(e)}return o},deepMergeHelper=(e,t,r)=>{let a,o,n=getDataType(e),s=getDataType(t),p=!0;return"Object"===n&&"Object"===s?(o=deepMergeObjects(e,t,r),a="Object"):"Array"===n&&"Array"===s?(o=deepMergeArrays(e,t,r),a="Array"):"Set"===n&&"Set"===s?(o=deepMergeSets(e,t,r),a="Set"):"Map"===n&&"Map"===s?(o=deepMergeMaps(e,t,r),a="Map"):(p=!1,o=e),{result:o,flag:p,type:a}},deepMerge=(e,t,r={})=>{let a=Object.assign({itemMode:"merge",propAppend:!0,targetClone:!1,useEnable:!0},r);return deepMergeHelper(e,t,a)},utils={getDataType:getDataType,requireTypes:requireTypes,deepClone:deepClone,deepCloneToJSON:deepCloneToJSON,wrapArrayMethods:wrapArrayMethods,arrayMutableMethods:arrayMutableMethods,setMutableMethods:setMutableMethods,mapMutableMethods:mapMutableMethods,wrapSetMethods:wrapSetMethods,wrapMapMethods:wrapMapMethods,getUniqueId:getUniqueId,deepEqual:assert.deepEqual,deepMerge:deepMerge,deepMergeArrays:deepMergeArrays,deepMergeMaps:deepMergeMaps,deepMergeObjects:deepMergeObjects,deepMergeSets:deepMergeSets};module.exports=utils;
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),o=Object.assign({cloneSet:!0,cloneMap:!0,cloneObject:!0,cloneArray:!0,cloneDate:!0,cloneRegex:!0},t);if(o.interceptor&&"function"==typeof o.interceptor){let t=o.interceptor(e,r);if(t)return o.onAfterClone?.({output:t,input:e,type:r,cloned:t!==e}),t}o.onBeforeClone?.(e,r);let a,n=!0;if("Object"===r&&o.cloneObject){const t={},r=Object.getOwnPropertySymbols(e);for(const r in e)t[r]=deepClone(e[r],o);if(r.length>0)for(const a of r)t[a]=deepClone(e[a],o);a=t}else if("Array"===r&&o.cloneArray)a=e.map(e=>deepClone(e,o));else if("Map"===r&&o.cloneMap){const t=new Map;for(const[r,a]of e)t.set(deepClone(r,o),deepClone(a,o));a=t}else if("Set"===r&&o.cloneSet){const t=new Set;for(const r of e)t.add(deepClone(r,o));a=t}else if("Date"===r&&o.cloneDate)a=new Date(e.getTime());else if("RegExp"===r&&o.cloneRegex){const t=e;a=new RegExp(t.source,t.flags)}else a=e,n=!1;return o.onAfterClone?.({output:a,input:e,type:r,cloned:n}),a},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:o,props:a={}})=>{if(!Array.isArray(e))throw new TypeError("The 'target' parameter must be an array.");o&&!o?.length||(o=arrayMutableMethods);const n={};for(let s of o)n[s]=function(...o){const n={},l=e.length;switch(s){case"push":case"unshift":n.addedItems=[...o];break;case"pop":n.poppedItem=e[l-1];break;case"shift":n.shiftedItem=e[0];break;case"splice":const[t,r]=o,a=t<0?Math.max(l+t,0):Math.min(t,l),s=void 0===r?l-a:r;n.deletedItems=e.slice(a,a+s);break;case"sort":case"reverse":n.oldSnapshot=[...e];break;case"fill":case"copyWithin":const i=o[1]||0,c=void 0===o[2]?l:o[2];n.oldItems=e.slice(i,c),n.start=i,n.end=c}t?.(n);const i=Array.prototype[s].apply(e,o),c={value:i,key:s,args:o,context:n,target:e,...a};return r?.(c),i};return n},requireTypes=(e,t,r)=>{let o=Array.isArray(t)?t:[t],a=getDataType(e),n=a.toLowerCase(),s=o.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,a)}else if(!s.includes(l))throw new TypeError(`Expected data type(s): [${s.join(", ")}], but got: ${l}`);return a},getUniqueId=(e={})=>{const t=e.prefix,r=e.suffix,o=e.base10,a=e.base36;return`${t?t+"-":""}${Date.now()}${a?"-"+Math.random().toString(36).substring(2,11):""}${o?"-"+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:o=setMutableMethods,props:a={}})=>{if(!(e instanceof Set))throw new TypeError("The 'target' parameter must be a Set.");const n={},createWrappedMethod=o=>function(...n){const s={};switch(o){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[o].apply(e,n),i={method:o,result:l,args:n,context:s,target:e,...a};return r(i),l};for(const e of o)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:o=mapMutableMethods,props:a={}})=>{if(!(e instanceof Map))throw new TypeError("The 'target' parameter must be a Map.");const n={},createWrappedMethod=o=>function(...n){const s={};switch(o){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[o].apply(e,n),i={method:o,result:l,args:n,context:s,target:e,...a};return r(i),l};for(const e of o)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 o=Object.assign({dataMode:"clear",inheritMissing:!0,targetClone:!1,useEnable:!0,useSymbol:!0,deepClone:{},onBeforeMerge:void 0,onAfterMerge:void 0},r),deepMergeHelper=(e,t,r)=>{let o,a,n=getDataType(e),s=getDataType(t),l=!0;return"Object"===n&&"Object"===s?(a=deepMergeObjects(e,t,r),o="Object"):"Array"===n&&"Array"===s?(a=deepMergeArrays(e,t,r),o="Array"):"Set"===n&&"Set"===s?(a=deepMergeSets(e,t,r),o="Set"):"Map"===n&&"Map"===s?(a=deepMergeMaps(e,t,r),o="Map"):(l=!1,a=e),{result:a,flag:l,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 o=getDataType(e),a=getDataType(t);if("Object"!==o||"Object"!==a)return e;r?.onBeforeMerge?.(e,t);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 o=deepMergeHelper(s[e],t[e],r);o.flag?o.type?"Object"===o.type&&(s[e]=o.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 n?.onAfterMerge?.(s,e,t),s},deepMergeArrays=(e,t,r={})=>{if(!Array.isArray(e)||!Array.isArray(t))return e;r?.onBeforeMerge?.(e,t);const o=Object.assign({dataMode:"clear",inheritMissing:!0,targetClone:!1},r),a=o.targetClone?[...e]:e;if("replace"===o.dataMode)for(let e=0;e<t.length&&(o.inheritMissing||!(e>=a.length));e++){deepMergeHelper(a[e],t[e],o).flag||(a[e]=t[e])}else"concat"===o.dataMode||(a.length=0),a.push(...t);return r?.onAfterMerge?.(a,e,t),a},deepMergeMaps=(e,t,r={})=>{if(!(e instanceof Map&&t instanceof Map))return e;r?.onBeforeMerge?.(e,t);const o=Object.assign({inheritMissing:!0,targetClone:!1,useEnable:!0},r),a=o.targetClone?new Map([...e]):e;for(const[e,n]of t.entries())if(a.has(e)){const t=a.get(e),r=n,s=deepMergeHelper(t,r,o);s.flag?"Object"===s.type&&a.set(e,s.result):a.set(e,r)}else r.inheritMissing&&a.set(e,n);return r?.onAfterMerge?.(a,e,t),a},deepMergeSets=(e,t,r={})=>{if(!(e instanceof Set&&t instanceof Set))return e;r?.onBeforeMerge?.(e,t);const o=Object.assign({dataMode:"clear",inheritMissing:!0,targetClone:!1,useEnable:!0},r),a=o.targetClone?new Set(...e):e;if("replace"===o.dataMode){const e=[...a],r=[...t],n=deepMergeHelper(e,r,o);a.clear();for(let e of n.result)a.add(e)}else if("concat"===o.dataMode)for(let e of t)a.add(e);else{a.clear();for(let e of t)a.add(e)}return r?.onAfterMerge?.(a,e,t),a};return deepMergeHelper(e,t,o).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-24 17:50:8
3
+ * @since Last modified: 2025-12-25 14:33:12
4
4
  * @name Utils for web front-end.
5
- * @version 0.0.11
5
+ * @version 0.0.13
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}
@@ -14,8 +14,6 @@
14
14
  * @license MIT license
15
15
  */
16
16
 
17
- import { deepEqual as deepEqual$1 } from 'assert';
18
-
19
17
  const getDataType = (obj) => {
20
18
  let tmp = Object.prototype.toString.call(obj).slice(8, -1), result;
21
19
  if (tmp === 'Function' && /^\s*class\s+/.test(obj.toString())) {
@@ -422,31 +420,176 @@ const wrapMapMethods = ({ target, onBeforeMutate = () => { }, onAfterMutate = ()
422
420
  return methods;
423
421
  };
424
422
 
425
- const deepMergeObjects = (target, source, opts = {}) => {
426
- let targetType = getDataType(target), sourceType = getDataType(source);
427
- //target不是对象或者source为空则直接返回
428
- if (targetType !== 'Object' || sourceType !== 'Object') {
429
- return target;
430
- }
431
- const options = Object.assign({ itemMode: 'merge', propAppend: true, targetClone: false, useEnable: true }, opts),
432
- //如果是复制方法,则先复制target
433
- result = options.targetClone ? deepClone(target) : target;
434
- for (let k in source) {
435
- if (source.hasOwnProperty(k) && result.hasOwnProperty(k)) {
436
- let resp = deepMergeHelper(result[k], source[k], opts);
437
- //resp={result,flag,type}
438
- //flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
439
- if (!resp.flag) {
440
- //类型不同则直接覆盖
441
- if (options.useEnable && result.hasOwnProperty(k) && result[k]?.hasOwnProperty('enable') && typeof source[k] === 'boolean') {
442
- //部分替换,仅针对result={enable:true/false,a:''},source=false/true这种情况和相反的情况,因为这种情况再笨框架比较多见
443
- if (result[k]?.hasOwnProperty('enable') && typeof source[k] === 'boolean') {
444
- //result={enable:true,a:'',b:''},source[k]=false=>result={enable:false,a:'',b:''}
445
- result[k].enable = source[k];
446
- }
447
- else if (source[k]?.hasOwnProperty('enable') && typeof result[k] === 'boolean') {
448
- //source={enable:true,a:'',b:''},(result as any)[k]=false=>result={enable:false,a:'',b:''}
449
- result = Object.assign({ enable: result[k] }, source[k]);
423
+ const copyObjectWithSymbol = (data) => {
424
+ if (!data || typeof data !== 'object') {
425
+ return data;
426
+ }
427
+ // Ensure the object type includes string and symbol keys
428
+ const obj = data, symbolProperties = Object.getOwnPropertySymbols(obj).reduce((acc, sym) => {
429
+ acc[sym] = obj[sym];
430
+ return acc;
431
+ }, {});
432
+ // Shallow copy the object and include the Symbol properties
433
+ return { ...obj, ...symbolProperties };
434
+ };
435
+
436
+ const shallowCopy = (data, options = {}) => {
437
+ const dataType = getDataType(data);
438
+ // Check if data is a Set
439
+ if (dataType === 'Set') {
440
+ // Shallow copy Set
441
+ return new Set([...data]);
442
+ }
443
+ // Check if data is a Map
444
+ if (dataType === 'Map') {
445
+ // Shallow copy Map
446
+ return new Map([...data]);
447
+ }
448
+ // Check if data is an Array
449
+ if (Array.isArray(data)) {
450
+ // Shallow copy Array
451
+ return [...data];
452
+ }
453
+ // Check if data is a Plain Object (including Symbol keys)
454
+ if (dataType === 'object') {
455
+ // Ensure the object type includes string and symbol keys
456
+ // Shallow copy the object and include the Symbol properties
457
+ return copyObjectWithSymbol(data);
458
+ }
459
+ // Check if data is a Date
460
+ if (dataType === 'Date') {
461
+ return new Date(data.getTime());
462
+ }
463
+ // Check if data is a RegExp
464
+ if (dataType === 'RegExp') {
465
+ return new RegExp(data.source, data.flags);
466
+ }
467
+ // Check if data is a Buffer (for Node.js)
468
+ if (dataType === 'Buffer') {
469
+ return Buffer.from(data);
470
+ }
471
+ // Check if data is an ArrayBuffer or TypedArray
472
+ if (dataType === 'ArrayBuffer' || ArrayBuffer.isView(data)) {
473
+ return data.slice(0);
474
+ }
475
+ // Check if data is a WeakSet
476
+ if (dataType === 'WeakSet') {
477
+ return new WeakSet([...data]);
478
+ }
479
+ // Check if data is a WeakMap
480
+ if (dataType === 'WeakMap') {
481
+ return new WeakMap([...data]);
482
+ }
483
+ // Check if data is an Error
484
+ if (dataType === 'Error') {
485
+ return new Error(data.message);
486
+ }
487
+ // For other types (such as numbers, strings, booleans, etc.), return the original value
488
+ return data;
489
+ };
490
+
491
+ const deepMerge = (target, source, opts = {}) => {
492
+ // Set default options
493
+ // 设置默认选项
494
+ const options = Object.assign({
495
+ // Merging mode for array and set collections:
496
+ // 'clear' means clear first then append; 'concat' means append directly at the end;
497
+ // 'replace' means merge sequentially (deep merging)
498
+ // 对于array和set合集的合并方式:'clear'表示先清空再追加;'concat'表示直接在尾部追加;
499
+ // 'replace'表示按顺序进行合并(深度合并)
500
+ dataMode: 'clear',
501
+ // Whether to directly append properties/items from source that target doesn't have.
502
+ // true: append; false: discard
503
+ // source对象如果有target对象没有的item或prop属性,是否直接新追加。true则追加;false则丢弃
504
+ inheritMissing: true,
505
+ // Whether to clone the target object, generating a brand new object. Default false.
506
+ // 是否克隆target对象,生成全新对象,默认false。
507
+ targetClone: false,
508
+ // How to merge when target or source has enable property and boolean value into {enable:boolean}
509
+ // 当target或source有enable属性(prop)和boolean值时,如何合并为{enable:boolean}
510
+ useEnable: true,
511
+ // Whether to allow merging key=symbol key-value pairs when target is {} type.
512
+ // target是{}类型时,是否允许合并key=symbol的键值对。
513
+ useSymbol: true,
514
+ // Options passed to the deepClone function when targetClone is true
515
+ // 当targetClone为true时传递给deepClone函数的选项
516
+ deepClone: {},
517
+ // Callback function executed before merging each data structure
518
+ // 在每个数据结构合并前执行的回调函数
519
+ onBeforeMerge: undefined,
520
+ // Callback function executed after merging each data structure
521
+ // 在每个数据结构合并后执行的回调函数
522
+ onAfterMerge: undefined,
523
+ }, opts),
524
+ // Main helper function for recursive merging
525
+ // 递归合并的主辅助函数
526
+ deepMergeHelper = (target, source, options) => {
527
+ let targetType = getDataType(target), sourceType = getDataType(source), flag = true, type, result;
528
+ // Determine the type and perform appropriate merging
529
+ // 确定类型并执行相应的合并
530
+ if (targetType === 'Object' && sourceType === 'Object') {
531
+ result = deepMergeObjects(target, source, options);
532
+ type = 'Object';
533
+ }
534
+ else if (targetType === 'Array' && sourceType === 'Array') {
535
+ result = deepMergeArrays(target, source, options);
536
+ type = 'Array';
537
+ }
538
+ else if (targetType === 'Set' && sourceType === 'Set') {
539
+ result = deepMergeSets(target, source, options);
540
+ type = 'Set';
541
+ }
542
+ else if (targetType === 'Map' && sourceType === 'Map') {
543
+ result = deepMergeMaps(target, source, options);
544
+ type = 'Map';
545
+ }
546
+ else {
547
+ flag = false;
548
+ result = target;
549
+ }
550
+ return { result, flag, type };
551
+ },
552
+ // Special handling for objects with enable property
553
+ // 对具有enable属性的对象进行特殊处理
554
+ mergeEnableObject = (target, source) => {
555
+ if (target?.hasOwnProperty('enable') && typeof source === 'boolean') {
556
+ //result={enable:true,a:'',b:''},source[k]=false=>result={enable:false,a:'',b:''}
557
+ //仅设置enable属性
558
+ target.enable = source;
559
+ //返回target原对象
560
+ return target;
561
+ }
562
+ else if (source?.hasOwnProperty('enable') && typeof target === 'boolean') {
563
+ //source={enable:true,a:'',b:''},(result as any)[k]=false=>result={enable:false,a:'',b:''}
564
+ //返回新值,新值包含enable属性
565
+ return Object.assign({ enable: target }, source);
566
+ }
567
+ return source;
568
+ },
569
+ // Deep merge for objects
570
+ // 对象的深度合并
571
+ deepMergeObjects = (target, source, opts = {}) => {
572
+ let targetType = getDataType(target), sourceType = getDataType(source);
573
+ // If target is not an object or source is empty, return target directly
574
+ // 如果target不是对象或者source为空则直接返回
575
+ if (targetType !== 'Object' || sourceType !== 'Object') {
576
+ return target;
577
+ }
578
+ opts?.onBeforeMerge?.(target, source);
579
+ const options = Object.assign({ inheritMissing: true, targetClone: false, useEnable: true }, opts);
580
+ let result = {};
581
+ // If cloning is enabled, clone the target first
582
+ // 如果是复制方法,则先复制target
583
+ result = options.targetClone ? shallowCopy(target) : target;
584
+ for (let k in source) {
585
+ if (source.hasOwnProperty(k) && result.hasOwnProperty(k)) {
586
+ let resp = deepMergeHelper(result[k], source[k], opts);
587
+ //resp={result,flag,type}
588
+ //flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
589
+ if (!resp.flag) {
590
+ //类型不同则直接覆盖
591
+ if (options.useEnable) {
592
+ result[k] = mergeEnableObject(result[k], source[k]);
450
593
  }
451
594
  else {
452
595
  //完全替换
@@ -454,99 +597,89 @@ const deepMergeObjects = (target, source, opts = {}) => {
454
597
  }
455
598
  }
456
599
  else {
457
- //完全替换
458
- result[k] = source[k];
600
+ //类型相同
601
+ if (resp.type) {
602
+ if (resp.type === 'Object') {
603
+ //如果遇上对象则深度复制
604
+ result[k] = resp.result;
605
+ }
606
+ }
607
+ else {
608
+ //其他类型则直接覆盖
609
+ result[k] = source[k];
610
+ }
459
611
  }
460
612
  }
461
- else {
462
- // If both target and source are objects, merge them recursively
463
- if (resp.type === 'Object') {
464
- result[k] = resp.result;
465
- }
613
+ else if (source.hasOwnProperty(k) && !result.hasOwnProperty(k) && options.inheritMissing) {
614
+ //如果source有属性,result没有该属性,但是options允许追加属性则直接赋值
615
+ result[k] = source[k];
466
616
  }
467
617
  }
468
- else if (source.hasOwnProperty(k) && !result.hasOwnProperty(k) && options.propAppend) {
469
- //如果source有属性,result没有该属性,但是options允许追加属性则直接赋值
470
- result[k] = source[k];
471
- }
472
- }
473
- //Symbol键直接追加,因为Symbol是唯一,结果同Object.assign
474
- if (options.useSymbol) {
475
- let symbols = Object.getOwnPropertySymbols(source);
476
- if (symbols.length > 0) {
477
- for (let k of symbols) {
478
- result[k] = source[k];
618
+ //Symbol键直接追加,因为Symbol是唯一,结果同Object.assign
619
+ if (options.useSymbol) {
620
+ let symbols = Object.getOwnPropertySymbols(source);
621
+ if (symbols.length) {
622
+ for (let k of symbols)
623
+ result[k] = source[k];
479
624
  }
480
625
  }
481
- }
482
- return result;
483
- };
484
-
485
- const deepMergeArrays = (target, source, options = { itemMode: 'merge', propAppend: true, targetClone: false, useEnable: true }) => {
486
- // Ensure both target and source are arrays
487
- if (!Array.isArray(target) || !Array.isArray(source))
488
- return target;
489
- // Merge options, with default values
490
- const opts = Object.assign({ itemMode: 'merge', propAppend: true, targetClone: false }, options),
491
- // If cloning is enabled, create a deep copy of the target array
492
- result = opts.targetClone ? [...target] : target;
493
- // Handle different merge strategies based on itemMode
494
- if (opts.itemMode === 'replace') {
495
- // Replace mode: clear the target array and push all items from the source array
496
- result.length = 0;
497
- result.push(...source);
626
+ options?.onAfterMerge?.(result, target, source);
498
627
  return result;
499
- }
500
- else if (opts.itemMode === 'concat') {
501
- // Concatenate mode: append all items from the source array to the target array
502
- result.push(...source);
503
- return result;
504
- }
505
- else {
506
- // Default "merge" mode: recursively merge items in the arrays
507
- for (let i = 0; i < source.length; i++) {
508
- let resp = deepMergeHelper(result[i], source[i], opts);
509
- //resp={result,flag,type}
510
- //flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
511
- if (!resp.flag) {
512
- result[i] = source[i];
628
+ }, deepMergeArrays = (target, source, options = {}) => {
629
+ // Ensure both target and source are arrays
630
+ if (!Array.isArray(target) || !Array.isArray(source))
631
+ return target;
632
+ options?.onBeforeMerge?.(target, source);
633
+ // Merge options, with default values
634
+ const opts = Object.assign({ dataMode: 'clear', inheritMissing: true, targetClone: false }, options),
635
+ // If cloning is enabled, create a deep copy of the target array
636
+ result = opts.targetClone ? [...target] : target;
637
+ // Handle different merge strategies based on dataMode
638
+ if (opts.dataMode === 'replace') {
639
+ // "replace" mode: recursively merge items in the arrays
640
+ for (let i = 0; i < source.length; i++) {
641
+ // If not allowed to add beyond length
642
+ // 如果不允许添加超过长度
643
+ if (!opts.inheritMissing && i >= result.length)
644
+ break;
645
+ let resp = deepMergeHelper(result[i], source[i], opts);
646
+ //resp={result,flag,type}
647
+ //flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
648
+ if (!resp.flag) {
649
+ result[i] = source[i];
650
+ }
513
651
  }
514
652
  }
653
+ else if (opts.dataMode === 'concat') {
654
+ // Concatenate mode: append all items from the source array to the target array
655
+ result.push(...source);
656
+ }
657
+ else {
658
+ //Default replace mode: clear the target array and push all items from the source array
659
+ result.length = 0;
660
+ result.push(...source);
661
+ }
662
+ options?.onAfterMerge?.(result, target, source);
515
663
  return result;
516
- }
517
- };
518
-
519
- const deepMergeMaps = (target, source, options = { itemMode: 'merge', propAppend: true, targetClone: false, useEnable: true }) => {
520
- // Ensure both target and source are Maps
521
- if (!(target instanceof Map) || !(source instanceof Map))
522
- return target;
523
- // Merge options, with default values
524
- const opts = Object.assign({ itemMode: 'merge', propAppend: true, targetClone: false, useEnable: true }, options),
525
- // If cloning is enabled, create a deep copy of the target Map
526
- result = opts.targetClone ? new Map(target) : target;
527
- // Handle different merge strategies based on itemMode
528
- if (opts.itemMode === 'replace') {
529
- // Replace mode: clear the target Map and add all entries from the source Map
530
- result.clear();
531
- source.forEach((value, key) => result.set(key, value));
532
- return result;
533
- }
534
- else if (opts.itemMode === 'concat') {
535
- // Concatenate mode: add all entries from the source Map to the target Map
536
- source.forEach((value, key) => result.set(key, value));
537
- return result;
538
- }
539
- else {
664
+ }, deepMergeMaps = (target, source, options = {}) => {
665
+ // Ensure both target and source are Maps
666
+ if (!(target instanceof Map) || !(source instanceof Map))
667
+ return target;
668
+ options?.onBeforeMerge?.(target, source);
669
+ // Merge options, with default values
670
+ const opts = Object.assign({ inheritMissing: true, targetClone: false, useEnable: true }, options),
671
+ // If cloning is enabled, create a deep copy of the target Map
672
+ result = opts.targetClone ? new Map([...target]) : target;
540
673
  // Default "merge" mode: recursively merge entries in the Maps
541
- source.forEach((value, key) => {
674
+ for (const [key, value] of source.entries())
542
675
  // Check if the key already exists in the target Map
543
676
  if (result.has(key)) {
544
- const targetValue = result.get(key), sourceValue = value, resp = deepMergeHelper(targetValue, sourceValue, opts);
677
+ const _target = result.get(key), _source = value, resp = deepMergeHelper(_target, _source, opts);
545
678
  //resp={result,flag,type}
546
679
  //flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
547
680
  if (!resp.flag) {
548
681
  // For simple values, overwrite the target value with the source value
549
- result.set(key, sourceValue);
682
+ result.set(key, _source);
550
683
  }
551
684
  else {
552
685
  // If both target and source are objects, merge them recursively
@@ -555,116 +688,42 @@ const deepMergeMaps = (target, source, options = { itemMode: 'merge', propAppend
555
688
  }
556
689
  else {
557
690
  // If the key doesn't exist in the target, add the entry from the source Map
558
- result.set(key, value);
691
+ options.inheritMissing && result.set(key, value);
559
692
  }
560
- });
693
+ options?.onAfterMerge?.(result, target, source);
561
694
  return result;
562
- }
563
- };
564
-
565
- const deepEqual = (a, b) => {
566
- // If both are equal by reference
567
- if (a === b)
568
- return true;
569
- // If both are arrays, check equality recursively
570
- if (Array.isArray(a) && Array.isArray(b)) {
571
- if (a.length !== b.length)
572
- return false;
573
- for (let i = 0; i < a.length; i++) {
574
- if (!deepEqual(a[i], b[i]))
575
- return false;
695
+ }, deepMergeSets = (target, source, options = {}) => {
696
+ // Ensure both target and source are Sets
697
+ if (!(target instanceof Set) || !(source instanceof Set))
698
+ return target;
699
+ options?.onBeforeMerge?.(target, source);
700
+ // Merge options, with default values
701
+ const opts = Object.assign({ dataMode: 'clear', inheritMissing: true, targetClone: false, useEnable: true }, options),
702
+ // If cloning is enabled, create a deep copy of the target Set
703
+ result = opts.targetClone ? new Set(...target) : target;
704
+ // Handle different merge strategies based on dataMode
705
+ if (opts.dataMode === 'replace') {
706
+ // Replace mode: recursively merge items in the Sets
707
+ const _result = [...result], _source = [...source], resp = deepMergeHelper(_result, _source, opts);
708
+ result.clear();
709
+ for (let item of resp.result)
710
+ result.add(item);
576
711
  }
577
- return true;
578
- }
579
- // If both are objects, check equality recursively
580
- if (typeof a === 'object' && typeof b === 'object') {
581
- const keysA = Object.keys(a), keysB = Object.keys(b);
582
- if (keysA.length !== keysB.length)
583
- return false;
584
- for (let key of keysA) {
585
- if (!keysB.includes(key) || !deepEqual(a[key], b[key]))
586
- return false;
712
+ else if (opts.dataMode === 'concat') {
713
+ // Concatenate mode: add all items from the source Set to the target Set
714
+ for (let item of source)
715
+ result.add(item);
587
716
  }
588
- return true;
589
- }
590
- // For other types, direct comparison
591
- return a === b;
592
- };
593
-
594
- const deepMergeSets = (target, source, options = { itemMode: 'merge', propAppend: true, targetClone: false, useEnable: true }) => {
595
- // Ensure both target and source are Sets
596
- if (!(target instanceof Set) || !(source instanceof Set))
597
- return target;
598
- // Merge options, with default values
599
- const opts = Object.assign({ itemMode: 'merge', propAppend: true, targetClone: false, useEnable: true }, options),
600
- // If cloning is enabled, create a deep copy of the target Set
601
- result = opts.targetClone ? new Set(target) : target;
602
- // Handle different merge strategies based on itemMode
603
- if (opts.itemMode === 'replace') {
604
- // Replace mode: clear the target Set and add all items from the source Set
605
- result.clear();
606
- for (let item of source)
607
- result.add(item);
608
- return result;
609
- }
610
- else if (opts.itemMode === 'concat') {
611
- // Concatenate mode: add all items from the source Set to the target Set
612
- for (let item of source)
613
- result.add(item);
614
- return result;
615
- }
616
- else {
617
- // Default "merge" mode: recursively merge items in the Sets
618
- for (let item of source) {
619
- // Check the type of the target and source items
620
- let _target = [...result].find(val => deepEqual(val, item)), resp = deepMergeHelper(_target, item, opts);
621
- //resp={result,flag}
622
- //flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
623
- !resp.flag && result.add(item);
717
+ else {
718
+ //Default "clear" mode: clear the target Set and add all items from the source Set
719
+ result.clear();
720
+ for (let item of source)
721
+ result.add(item);
624
722
  }
723
+ options?.onAfterMerge?.(result, target, source);
625
724
  return result;
626
- }
627
- };
628
-
629
- // deepMergeHelper.ts
630
-
631
-
632
- const deepMergeHelper = (target, source, options) => {
633
- let targetType = getDataType(target), sourceType = getDataType(source), flag = true, type, result;
634
- if (targetType === 'Object' && sourceType === 'Object') {
635
- result = deepMergeObjects(target, source, options);
636
- type = 'Object';
637
- }
638
- else if (targetType === 'Array' && sourceType === 'Array') {
639
- result = deepMergeArrays(target, source, options);
640
- type = 'Array';
641
- }
642
- else if (targetType === 'Set' && sourceType === 'Set') {
643
- result = deepMergeSets(target, source, options);
644
- type = 'Set';
645
- }
646
- else if (targetType === 'Map' && sourceType === 'Map') {
647
- result = deepMergeMaps(target, source, options);
648
- type = 'Map';
649
- }
650
- else {
651
- flag = false;
652
- result = target; // Default case, replace primitive values
653
- }
654
- return {
655
- result, flag, type
656
725
  };
657
- };
658
-
659
- const deepMerge = (target, source, opts = {}) => {
660
- // Get the data types of the target and source
661
- let options = Object.assign({
662
- itemMode: 'merge', // Default merge mode
663
- propAppend: true, // Default to appending properties from source to target
664
- targetClone: false, // Do not clone target by default
665
- useEnable: true // Enable special handling for objects with an `enable` property
666
- }, opts);
667
- return deepMergeHelper(target, source, options);
726
+ return deepMergeHelper(target, source, options).result;
668
727
  };
669
728
 
670
729
  const utils = {
@@ -682,12 +741,9 @@ const utils = {
682
741
  wrapSetMethods,
683
742
  wrapMapMethods,
684
743
  getUniqueId,
685
- deepEqual: deepEqual$1,
686
744
  deepMerge,
687
- deepMergeArrays,
688
- deepMergeMaps,
689
- deepMergeObjects,
690
- deepMergeSets,
745
+ shallowCopy,
746
+ copyObjectWithSymbol,
691
747
  };
692
748
 
693
749
  export { utils as default };