@codady/utils 0.0.4 → 0.0.6

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 CHANGED
@@ -2,6 +2,27 @@
2
2
 
3
3
  All changes to Utils including new features, updates, and removals are documented here.
4
4
 
5
+ ## [v0.0.6] - 2025-12-19
6
+
7
+ ### Distribution Files
8
+ - **JS**: https://unpkg.com/@codady/utils@0.0.6/dist/js/utils.js
9
+ - **Zip**: https://unpkg.com/@codady/utils@0.0.6/dist.zip
10
+
11
+ ### Changes
12
+
13
+ #### Fixed
14
+ - Some problems.
15
+
16
+ #### Added
17
+ - The `mutateMethods` variable has been renamed to `mutableMethods`.`mutateMethods`变量改名为`mutableMethods`。
18
+ - Added `props` parameter to `mutateArray`.mutateArray新增参数props。
19
+ - The `method` parameter in `onAfterMutate` callback of `mutateArray` has been renamed to `key`, and `result` renamed to `value`.mutateArray的onAfterMutate的参数method改名为key,result改名为value。
20
+
21
+
22
+ #### Removed
23
+ - Null
24
+
25
+
5
26
  ## [v0.0.3] - 2025-12-18
6
27
 
7
28
  ### Distribution Files
package/dist/utils.cjs.js CHANGED
@@ -1,8 +1,8 @@
1
1
 
2
2
  /*!
3
- * @since Last modified: 2025-12-18 21:8:4
3
+ * @since Last modified: 2025-12-19 9:4:44
4
4
  * @name Utils for web front-end.
5
- * @version 0.0.2
5
+ * @version 0.0.6
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}
@@ -102,6 +102,78 @@ const deepCloneToJSON = (data) => {
102
102
  }
103
103
  };
104
104
 
105
+ const mutableMethods = [
106
+ 'push', 'pop', 'shift', 'unshift', 'splice',
107
+ 'sort', 'reverse', 'copyWithin', 'fill'
108
+ ];
109
+
110
+ const mutateArray = ({ target, method, args = [], onBeforeMutate = () => { }, onAfterMutate = () => { }, allowList, props = {}, }) => {
111
+ // Validation: Ensure target is an array and method is allowed
112
+ if (!Array.isArray(target)) {
113
+ throw new TypeError("The 'target' parameter must be an array.");
114
+ }
115
+ //使用默认
116
+ if (!allowList || allowList?.length) {
117
+ allowList = mutableMethods;
118
+ }
119
+ if (!allowList?.includes(method)) {
120
+ throw new Error(`Method "${method}" is not in the allowList or is not a mutation method.`);
121
+ }
122
+ const context = {}, len = target.length;
123
+ // Capture "Pre-mutation" context for Undo/Redo/Tracking purposes
124
+ switch (method) {
125
+ // 'push' and 'unshift' are add operations, in undo/redo,
126
+ // we can determine the original data structure from result.length and args.length
127
+ // but methods that involve deletion need to record the deleted items to ensure the patch can restore the data structure during undo
128
+ case 'push':
129
+ case 'unshift':
130
+ context.addedItems = [...args];
131
+ break;
132
+ case 'pop':
133
+ context.poppedValue = target[len - 1];
134
+ break;
135
+ case 'shift':
136
+ context.shiftedValue = target[0];
137
+ break;
138
+ case 'splice':
139
+ const [s, d] = args,
140
+ // Calculate actual start index (handling negative values)
141
+ start = s < 0 ? Math.max(len + s, 0) : Math.min(s, len),
142
+ // Handle deleteCount defaults
143
+ deleteCount = d === undefined ? len - start : d;
144
+ context.deletedItems = target.slice(start, start + deleteCount);
145
+ break;
146
+ case 'sort':
147
+ case 'reverse':
148
+ // These methods reorder the whole array; requires a full shallow copy
149
+ context.oldSnapshot = [...target];
150
+ break;
151
+ case 'fill':
152
+ case 'copyWithin':
153
+ const startIdx = args[1] || 0, endIdx = args[2] === undefined ? len : args[2];
154
+ // Overwritten values
155
+ context.oldItems = target.slice(startIdx, endIdx);
156
+ context.start = startIdx;
157
+ context.end = endIdx;
158
+ break;
159
+ }
160
+ // Execute the "onBeforeMutate" callback before mutation
161
+ onBeforeMutate?.(context);
162
+ // Execute the native array mutation
163
+ const value = Array.prototype[method].apply(target, args), patch = {
164
+ value,
165
+ key: method,
166
+ args,
167
+ context,
168
+ target,
169
+ timestamp: Date.now(),
170
+ ...props
171
+ };
172
+ // Construct and trigger the patch callback
173
+ onAfterMutate?.(patch);
174
+ return value;
175
+ };
176
+
105
177
  const requireTypes = (data, require, cb) => {
106
178
  // Normalize the input types (convert to array if it's a single type)
107
179
  let requiredTypes = Array.isArray(require) ? require : [require], dataType = getDataType(data), typeLower = dataType.toLowerCase(),
@@ -136,7 +208,9 @@ const utils = {
136
208
  //renderTpl,
137
209
  //parseStr,
138
210
  deepClone,
139
- deepCloneToJSON
211
+ deepCloneToJSON,
212
+ mutateArray,
213
+ mutableMethods
140
214
  };
141
215
 
142
216
  module.exports = utils;
@@ -1,7 +1,7 @@
1
1
  /*!
2
- * @since Last modified: 2025-12-18 21:8:4
2
+ * @since Last modified: 2025-12-19 9:4:44
3
3
  * @name Utils for web front-end.
4
- * @version 0.0.2
4
+ * @version 0.0.6
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=>{const t=getDataType(e);if("Object"===t){const t={},r=Object.getOwnPropertySymbols(e);for(const r in e)t[r]=deepClone(e[r]);if(r.length>0)for(const o of r)t[o]=deepClone(e[o]);return t}if("Array"===t)return e.map(e=>deepClone(e));if("Date"===t)return new Date(e.getTime());if("RegExp"===t){const t=e;return new RegExp(t.source,t.flags)}return e},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},requireTypes=(e,t,r)=>{let o=Array.isArray(t)?t:[t],n=getDataType(e),s=n.toLowerCase(),p=o.map(e=>e.toLowerCase()),l=s.includes("html")?"element":s;if(r)try{if(!p.includes(l))throw new TypeError(`Expected data type(s): [${p.join(", ")}], but got: ${l}`)}catch(e){r(e,n)}else if(!p.includes(l))throw new TypeError(`Expected data type(s): [${p.join(", ")}], but got: ${l}`);return n},utils={getDataType:getDataType,requireTypes:requireTypes,deepClone:deepClone,deepCloneToJSON:deepCloneToJSON};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=>{const t=getDataType(e);if("Object"===t){const t={},r=Object.getOwnPropertySymbols(e);for(const r in e)t[r]=deepClone(e[r]);if(r.length>0)for(const o of r)t[o]=deepClone(e[o]);return t}if("Array"===t)return e.map(e=>deepClone(e));if("Date"===t)return new Date(e.getTime());if("RegExp"===t){const t=e;return new RegExp(t.source,t.flags)}return e},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},mutableMethods=["push","pop","shift","unshift","splice","sort","reverse","copyWithin","fill"],mutateArray=({target:e,method:t,args:r=[],onBeforeMutate:o=()=>{},onAfterMutate:a=()=>{},allowList:s,props:n={}})=>{if(!Array.isArray(e))throw new TypeError("The 'target' parameter must be an array.");if(s&&!s?.length||(s=mutableMethods),!s?.includes(t))throw new Error(`Method "${t}" is not in the allowList or is not a mutation method.`);const i={},l=e.length;switch(t){case"push":case"unshift":i.addedItems=[...r];break;case"pop":i.poppedValue=e[l-1];break;case"shift":i.shiftedValue=e[0];break;case"splice":const[t,o]=r,a=t<0?Math.max(l+t,0):Math.min(t,l),s=void 0===o?l-a:o;i.deletedItems=e.slice(a,a+s);break;case"sort":case"reverse":i.oldSnapshot=[...e];break;case"fill":case"copyWithin":const n=r[1]||0,p=void 0===r[2]?l:r[2];i.oldItems=e.slice(n,p),i.start=n,i.end=p}o?.(i);const p=Array.prototype[t].apply(e,r),c={value:p,key:t,args:r,context:i,target:e,timestamp:Date.now(),...n};return a?.(c),p},requireTypes=(e,t,r)=>{let o=Array.isArray(t)?t:[t],a=getDataType(e),s=a.toLowerCase(),n=o.map(e=>e.toLowerCase()),i=s.includes("html")?"element":s;if(r)try{if(!n.includes(i))throw new TypeError(`Expected data type(s): [${n.join(", ")}], but got: ${i}`)}catch(e){r(e,a)}else if(!n.includes(i))throw new TypeError(`Expected data type(s): [${n.join(", ")}], but got: ${i}`);return a},utils={getDataType:getDataType,requireTypes:requireTypes,deepClone:deepClone,deepCloneToJSON:deepCloneToJSON,mutateArray:mutateArray,mutableMethods:mutableMethods};module.exports=utils;
package/dist/utils.esm.js CHANGED
@@ -1,8 +1,8 @@
1
1
 
2
2
  /*!
3
- * @since Last modified: 2025-12-18 21:8:4
3
+ * @since Last modified: 2025-12-19 9:4:44
4
4
  * @name Utils for web front-end.
5
- * @version 0.0.2
5
+ * @version 0.0.6
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}
@@ -100,6 +100,78 @@ const deepCloneToJSON = (data) => {
100
100
  }
101
101
  };
102
102
 
103
+ const mutableMethods = [
104
+ 'push', 'pop', 'shift', 'unshift', 'splice',
105
+ 'sort', 'reverse', 'copyWithin', 'fill'
106
+ ];
107
+
108
+ const mutateArray = ({ target, method, args = [], onBeforeMutate = () => { }, onAfterMutate = () => { }, allowList, props = {}, }) => {
109
+ // Validation: Ensure target is an array and method is allowed
110
+ if (!Array.isArray(target)) {
111
+ throw new TypeError("The 'target' parameter must be an array.");
112
+ }
113
+ //使用默认
114
+ if (!allowList || allowList?.length) {
115
+ allowList = mutableMethods;
116
+ }
117
+ if (!allowList?.includes(method)) {
118
+ throw new Error(`Method "${method}" is not in the allowList or is not a mutation method.`);
119
+ }
120
+ const context = {}, len = target.length;
121
+ // Capture "Pre-mutation" context for Undo/Redo/Tracking purposes
122
+ switch (method) {
123
+ // 'push' and 'unshift' are add operations, in undo/redo,
124
+ // we can determine the original data structure from result.length and args.length
125
+ // but methods that involve deletion need to record the deleted items to ensure the patch can restore the data structure during undo
126
+ case 'push':
127
+ case 'unshift':
128
+ context.addedItems = [...args];
129
+ break;
130
+ case 'pop':
131
+ context.poppedValue = target[len - 1];
132
+ break;
133
+ case 'shift':
134
+ context.shiftedValue = target[0];
135
+ break;
136
+ case 'splice':
137
+ const [s, d] = args,
138
+ // Calculate actual start index (handling negative values)
139
+ start = s < 0 ? Math.max(len + s, 0) : Math.min(s, len),
140
+ // Handle deleteCount defaults
141
+ deleteCount = d === undefined ? len - start : d;
142
+ context.deletedItems = target.slice(start, start + deleteCount);
143
+ break;
144
+ case 'sort':
145
+ case 'reverse':
146
+ // These methods reorder the whole array; requires a full shallow copy
147
+ context.oldSnapshot = [...target];
148
+ break;
149
+ case 'fill':
150
+ case 'copyWithin':
151
+ const startIdx = args[1] || 0, endIdx = args[2] === undefined ? len : args[2];
152
+ // Overwritten values
153
+ context.oldItems = target.slice(startIdx, endIdx);
154
+ context.start = startIdx;
155
+ context.end = endIdx;
156
+ break;
157
+ }
158
+ // Execute the "onBeforeMutate" callback before mutation
159
+ onBeforeMutate?.(context);
160
+ // Execute the native array mutation
161
+ const value = Array.prototype[method].apply(target, args), patch = {
162
+ value,
163
+ key: method,
164
+ args,
165
+ context,
166
+ target,
167
+ timestamp: Date.now(),
168
+ ...props
169
+ };
170
+ // Construct and trigger the patch callback
171
+ onAfterMutate?.(patch);
172
+ return value;
173
+ };
174
+
103
175
  const requireTypes = (data, require, cb) => {
104
176
  // Normalize the input types (convert to array if it's a single type)
105
177
  let requiredTypes = Array.isArray(require) ? require : [require], dataType = getDataType(data), typeLower = dataType.toLowerCase(),
@@ -134,7 +206,9 @@ const utils = {
134
206
  //renderTpl,
135
207
  //parseStr,
136
208
  deepClone,
137
- deepCloneToJSON
209
+ deepCloneToJSON,
210
+ mutateArray,
211
+ mutableMethods
138
212
  };
139
213
 
140
214
  export { utils as default };
@@ -1,7 +1,7 @@
1
1
  /*!
2
- * @since Last modified: 2025-12-18 21:8:4
2
+ * @since Last modified: 2025-12-19 9:4:44
3
3
  * @name Utils for web front-end.
4
- * @version 0.0.2
4
+ * @version 0.0.6
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=>{const t=getDataType(e);if("Object"===t){const t={},r=Object.getOwnPropertySymbols(e);for(const r in e)t[r]=deepClone(e[r]);if(r.length>0)for(const o of r)t[o]=deepClone(e[o]);return t}if("Array"===t)return e.map(e=>deepClone(e));if("Date"===t)return new Date(e.getTime());if("RegExp"===t){const t=e;return new RegExp(t.source,t.flags)}return e},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},requireTypes=(e,t,r)=>{let o=Array.isArray(t)?t:[t],n=getDataType(e),p=n.toLowerCase(),s=o.map(e=>e.toLowerCase()),l=p.includes("html")?"element":p;if(r)try{if(!s.includes(l))throw new TypeError(`Expected data type(s): [${s.join(", ")}], but got: ${l}`)}catch(e){r(e,n)}else if(!s.includes(l))throw new TypeError(`Expected data type(s): [${s.join(", ")}], but got: ${l}`);return n},utils={getDataType:getDataType,requireTypes:requireTypes,deepClone:deepClone,deepCloneToJSON:deepCloneToJSON};export{utils as default};
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=>{const t=getDataType(e);if("Object"===t){const t={},r=Object.getOwnPropertySymbols(e);for(const r in e)t[r]=deepClone(e[r]);if(r.length>0)for(const o of r)t[o]=deepClone(e[o]);return t}if("Array"===t)return e.map(e=>deepClone(e));if("Date"===t)return new Date(e.getTime());if("RegExp"===t){const t=e;return new RegExp(t.source,t.flags)}return e},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},mutableMethods=["push","pop","shift","unshift","splice","sort","reverse","copyWithin","fill"],mutateArray=({target:e,method:t,args:r=[],onBeforeMutate:o=()=>{},onAfterMutate:a=()=>{},allowList:s,props:n={}})=>{if(!Array.isArray(e))throw new TypeError("The 'target' parameter must be an array.");if(s&&!s?.length||(s=mutableMethods),!s?.includes(t))throw new Error(`Method "${t}" is not in the allowList or is not a mutation method.`);const i={},l=e.length;switch(t){case"push":case"unshift":i.addedItems=[...r];break;case"pop":i.poppedValue=e[l-1];break;case"shift":i.shiftedValue=e[0];break;case"splice":const[t,o]=r,a=t<0?Math.max(l+t,0):Math.min(t,l),s=void 0===o?l-a:o;i.deletedItems=e.slice(a,a+s);break;case"sort":case"reverse":i.oldSnapshot=[...e];break;case"fill":case"copyWithin":const n=r[1]||0,p=void 0===r[2]?l:r[2];i.oldItems=e.slice(n,p),i.start=n,i.end=p}o?.(i);const p=Array.prototype[t].apply(e,r),c={value:p,key:t,args:r,context:i,target:e,timestamp:Date.now(),...n};return a?.(c),p},requireTypes=(e,t,r)=>{let o=Array.isArray(t)?t:[t],a=getDataType(e),s=a.toLowerCase(),n=o.map(e=>e.toLowerCase()),i=s.includes("html")?"element":s;if(r)try{if(!n.includes(i))throw new TypeError(`Expected data type(s): [${n.join(", ")}], but got: ${i}`)}catch(e){r(e,a)}else if(!n.includes(i))throw new TypeError(`Expected data type(s): [${n.join(", ")}], but got: ${i}`);return a},utils={getDataType:getDataType,requireTypes:requireTypes,deepClone:deepClone,deepCloneToJSON:deepCloneToJSON,mutateArray:mutateArray,mutableMethods:mutableMethods};export{utils as default};
package/dist/utils.umd.js CHANGED
@@ -1,8 +1,8 @@
1
1
 
2
2
  /*!
3
- * @since Last modified: 2025-12-18 21:8:4
3
+ * @since Last modified: 2025-12-19 9:4:44
4
4
  * @name Utils for web front-end.
5
- * @version 0.0.2
5
+ * @version 0.0.6
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}
@@ -106,6 +106,78 @@
106
106
  }
107
107
  };
108
108
 
109
+ const mutableMethods = [
110
+ 'push', 'pop', 'shift', 'unshift', 'splice',
111
+ 'sort', 'reverse', 'copyWithin', 'fill'
112
+ ];
113
+
114
+ const mutateArray = ({ target, method, args = [], onBeforeMutate = () => { }, onAfterMutate = () => { }, allowList, props = {}, }) => {
115
+ // Validation: Ensure target is an array and method is allowed
116
+ if (!Array.isArray(target)) {
117
+ throw new TypeError("The 'target' parameter must be an array.");
118
+ }
119
+ //使用默认
120
+ if (!allowList || allowList?.length) {
121
+ allowList = mutableMethods;
122
+ }
123
+ if (!allowList?.includes(method)) {
124
+ throw new Error(`Method "${method}" is not in the allowList or is not a mutation method.`);
125
+ }
126
+ const context = {}, len = target.length;
127
+ // Capture "Pre-mutation" context for Undo/Redo/Tracking purposes
128
+ switch (method) {
129
+ // 'push' and 'unshift' are add operations, in undo/redo,
130
+ // we can determine the original data structure from result.length and args.length
131
+ // but methods that involve deletion need to record the deleted items to ensure the patch can restore the data structure during undo
132
+ case 'push':
133
+ case 'unshift':
134
+ context.addedItems = [...args];
135
+ break;
136
+ case 'pop':
137
+ context.poppedValue = target[len - 1];
138
+ break;
139
+ case 'shift':
140
+ context.shiftedValue = target[0];
141
+ break;
142
+ case 'splice':
143
+ const [s, d] = args,
144
+ // Calculate actual start index (handling negative values)
145
+ start = s < 0 ? Math.max(len + s, 0) : Math.min(s, len),
146
+ // Handle deleteCount defaults
147
+ deleteCount = d === undefined ? len - start : d;
148
+ context.deletedItems = target.slice(start, start + deleteCount);
149
+ break;
150
+ case 'sort':
151
+ case 'reverse':
152
+ // These methods reorder the whole array; requires a full shallow copy
153
+ context.oldSnapshot = [...target];
154
+ break;
155
+ case 'fill':
156
+ case 'copyWithin':
157
+ const startIdx = args[1] || 0, endIdx = args[2] === undefined ? len : args[2];
158
+ // Overwritten values
159
+ context.oldItems = target.slice(startIdx, endIdx);
160
+ context.start = startIdx;
161
+ context.end = endIdx;
162
+ break;
163
+ }
164
+ // Execute the "onBeforeMutate" callback before mutation
165
+ onBeforeMutate?.(context);
166
+ // Execute the native array mutation
167
+ const value = Array.prototype[method].apply(target, args), patch = {
168
+ value,
169
+ key: method,
170
+ args,
171
+ context,
172
+ target,
173
+ timestamp: Date.now(),
174
+ ...props
175
+ };
176
+ // Construct and trigger the patch callback
177
+ onAfterMutate?.(patch);
178
+ return value;
179
+ };
180
+
109
181
  const requireTypes = (data, require, cb) => {
110
182
  // Normalize the input types (convert to array if it's a single type)
111
183
  let requiredTypes = Array.isArray(require) ? require : [require], dataType = getDataType(data), typeLower = dataType.toLowerCase(),
@@ -140,7 +212,9 @@
140
212
  //renderTpl,
141
213
  //parseStr,
142
214
  deepClone,
143
- deepCloneToJSON
215
+ deepCloneToJSON,
216
+ mutateArray,
217
+ mutableMethods
144
218
  };
145
219
 
146
220
  return utils;
@@ -1,7 +1,7 @@
1
1
  /*!
2
- * @since Last modified: 2025-12-18 21:8:4
2
+ * @since Last modified: 2025-12-19 9:4:44
3
3
  * @name Utils for web front-end.
4
- * @version 0.0.2
4
+ * @version 0.0.6
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
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).utils=t()}(this,function(){"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=>{const t=getDataType(e);if("Object"===t){const t={},r=Object.getOwnPropertySymbols(e);for(const r in e)t[r]=deepClone(e[r]);if(r.length>0)for(const o of r)t[o]=deepClone(e[o]);return t}if("Array"===t)return e.map(e=>deepClone(e));if("Date"===t)return new Date(e.getTime());if("RegExp"===t){const t=e;return new RegExp(t.source,t.flags)}return e},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};return{getDataType:getDataType,requireTypes:(e,t,r)=>{let o=Array.isArray(t)?t:[t],n=getDataType(e),i=n.toLowerCase(),s=o.map(e=>e.toLowerCase()),c=i.includes("html")?"element":i;if(r)try{if(!s.includes(c))throw new TypeError(`Expected data type(s): [${s.join(", ")}], but got: ${c}`)}catch(e){r(e,n)}else if(!s.includes(c))throw new TypeError(`Expected data type(s): [${s.join(", ")}], but got: ${c}`);return n},deepClone:deepClone,deepCloneToJSON:deepCloneToJSON}});
15
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).utils=t()}(this,function(){"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=>{const t=getDataType(e);if("Object"===t){const t={},r=Object.getOwnPropertySymbols(e);for(const r in e)t[r]=deepClone(e[r]);if(r.length>0)for(const o of r)t[o]=deepClone(e[o]);return t}if("Array"===t)return e.map(e=>deepClone(e));if("Date"===t)return new Date(e.getTime());if("RegExp"===t){const t=e;return new RegExp(t.source,t.flags)}return e},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},e=["push","pop","shift","unshift","splice","sort","reverse","copyWithin","fill"];return{getDataType:getDataType,requireTypes:(e,t,r)=>{let o=Array.isArray(t)?t:[t],s=getDataType(e),n=s.toLowerCase(),a=o.map(e=>e.toLowerCase()),i=n.includes("html")?"element":n;if(r)try{if(!a.includes(i))throw new TypeError(`Expected data type(s): [${a.join(", ")}], but got: ${i}`)}catch(e){r(e,s)}else if(!a.includes(i))throw new TypeError(`Expected data type(s): [${a.join(", ")}], but got: ${i}`);return s},deepClone:deepClone,deepCloneToJSON:deepCloneToJSON,mutateArray:({target:t,method:r,args:o=[],onBeforeMutate:s=()=>{},onAfterMutate:n=()=>{},allowList:a,props:i={}})=>{if(!Array.isArray(t))throw new TypeError("The 'target' parameter must be an array.");if(a&&!a?.length||(a=e),!a?.includes(r))throw new Error(`Method "${r}" is not in the allowList or is not a mutation method.`);const c={},l=t.length;switch(r){case"push":case"unshift":c.addedItems=[...o];break;case"pop":c.poppedValue=t[l-1];break;case"shift":c.shiftedValue=t[0];break;case"splice":const[e,r]=o,s=e<0?Math.max(l+e,0):Math.min(e,l),n=void 0===r?l-s:r;c.deletedItems=t.slice(s,s+n);break;case"sort":case"reverse":c.oldSnapshot=[...t];break;case"fill":case"copyWithin":const a=o[1]||0,i=void 0===o[2]?l:o[2];c.oldItems=t.slice(a,i),c.start=a,c.end=i}s?.(c);const p=Array.prototype[r].apply(t,o),u={value:p,key:r,args:o,context:c,target:t,timestamp:Date.now(),...i};return n?.(u),p},mutableMethods:e}});
package/dist.zip CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codady/utils",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "author": "AXUI Development Team",
5
5
  "license": "MIT",
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.",
@@ -0,0 +1,5 @@
1
+ const mutableMethods = [
2
+ 'push', 'pop', 'shift', 'unshift', 'splice',
3
+ 'sort', 'reverse', 'copyWithin', 'fill'
4
+ ];
5
+ export default mutableMethods;
@@ -1,15 +1,15 @@
1
1
  /**
2
- * @since Last modified: 2025/12/18 21:04:34
2
+ * @since Last modified: 2025/12/19 08:59:38
3
3
  * A list of supported array mutation methods.
4
4
  * These methods are commonly used to modify the contents of an array.
5
5
  * These methods can be tracked and handled in various use cases, such as undo/redo functionality,
6
6
  * or when applying certain transformations to arrays.
7
7
  *
8
8
  */
9
- export type mutateMethods = ('push' | 'pop' | 'shift' | 'unshift' | 'splice' | 'sort' | 'reverse' | 'copyWithin' | 'fill')[];
10
- const mutateMethods: mutateMethods = [
9
+ export type mutableMethods = ('push' | 'pop' | 'shift' | 'unshift' | 'splice' | 'sort' | 'reverse' | 'copyWithin' | 'fill')[];
10
+ const mutableMethods: mutableMethods = [
11
11
  'push', 'pop', 'shift', 'unshift', 'splice',
12
12
  'sort', 'reverse', 'copyWithin', 'fill'
13
13
  ];
14
14
 
15
- export default mutateMethods;
15
+ export default mutableMethods;
@@ -1,11 +1,11 @@
1
1
  /**
2
- * @since Last modified: 2025/12/18 20:54:23
2
+ * @since Last modified: 2025/12/19 09:00:04
3
3
  * Mutates an array by applying one of the allowed mutation methods such as push, pop, shift, unshift, splice, etc.
4
4
  * Supports tracking of added, removed, and updated items for undo/redo or tracking purposes.
5
5
  * The mutation methods that can be tracked include push, pop, shift, unshift, splice, sort, reverse, fill, and copyWithin.
6
6
  *
7
7
  * @template T
8
- * @param {MutateOptions} options - Configuration object containing the target array, method to apply, arguments for the method, and an optional patch callback.
8
+ * @param {MutationOptions} options - Configuration object containing the target array, method to apply, arguments for the method, and an optional patch callback.
9
9
  * @returns {any} - The result of the array mutation.
10
10
  *
11
11
  * @example
@@ -30,17 +30,15 @@
30
30
  * // The patch callback logs the mutation details including deleted items and added items.
31
31
  */
32
32
  'use strict';
33
- const mutateArray = ({ target, method, args = [], onBeforeMutate = () => { }, onAfterMutate = () => { }, allowList }) => {
33
+ import mutableMethods from "./mutableMethods";
34
+ const mutateArray = ({ target, method, args = [], onBeforeMutate = () => { }, onAfterMutate = () => { }, allowList, props = {}, }) => {
34
35
  // Validation: Ensure target is an array and method is allowed
35
36
  if (!Array.isArray(target)) {
36
37
  throw new TypeError("The 'target' parameter must be an array.");
37
38
  }
38
39
  //使用默认
39
40
  if (!allowList || allowList?.length) {
40
- allowList = [
41
- 'push', 'pop', 'shift', 'unshift', 'splice',
42
- 'sort', 'reverse', 'copyWithin', 'fill'
43
- ];
41
+ allowList = mutableMethods;
44
42
  }
45
43
  if (!allowList?.includes(method)) {
46
44
  throw new Error(`Method "${method}" is not in the allowList or is not a mutation method.`);
@@ -84,17 +82,19 @@ const mutateArray = ({ target, method, args = [], onBeforeMutate = () => { }, on
84
82
  break;
85
83
  }
86
84
  // Execute the "onBeforeMutate" callback before mutation
87
- onBeforeMutate && onBeforeMutate(context);
85
+ onBeforeMutate?.(context);
88
86
  // Execute the native array mutation
89
- const result = Array.prototype[method].apply(target, args);
90
- // Construct and trigger the patch callback
91
- onAfterMutate && onAfterMutate({
92
- method,
87
+ const value = Array.prototype[method].apply(target, args), patch = {
88
+ value,
89
+ key: method,
93
90
  args,
94
91
  context,
95
- result,
96
- timestamp: Date.now()
97
- });
98
- return result;
92
+ target,
93
+ timestamp: Date.now(),
94
+ ...props
95
+ };
96
+ // Construct and trigger the patch callback
97
+ onAfterMutate?.(patch);
98
+ return value;
99
99
  };
100
100
  export default mutateArray;
@@ -1,11 +1,11 @@
1
1
  /**
2
- * @since Last modified: 2025/12/18 21:20:26
2
+ * @since Last modified: 2025/12/19 09:00:04
3
3
  * Mutates an array by applying one of the allowed mutation methods such as push, pop, shift, unshift, splice, etc.
4
4
  * Supports tracking of added, removed, and updated items for undo/redo or tracking purposes.
5
5
  * The mutation methods that can be tracked include push, pop, shift, unshift, splice, sort, reverse, fill, and copyWithin.
6
6
  *
7
7
  * @template T
8
- * @param {MutateOptions} options - Configuration object containing the target array, method to apply, arguments for the method, and an optional patch callback.
8
+ * @param {MutationOptions} options - Configuration object containing the target array, method to apply, arguments for the method, and an optional patch callback.
9
9
  * @returns {any} - The result of the array mutation.
10
10
  *
11
11
  * @example
@@ -31,13 +31,13 @@
31
31
  */
32
32
  'use strict';
33
33
 
34
- import mutateMethods from "./mutateMethods";
34
+ import mutableMethods from "./mutableMethods";
35
35
 
36
36
 
37
37
  /**
38
38
  * Defines the structure of the captured state before mutation.
39
39
  */
40
- export interface MutateContext {
40
+ export interface MutationContextt {
41
41
  addedItems?: any[]; // Items added to the array
42
42
  poppedValue?: any; // Value popped from the array
43
43
  shiftedValue?: any; // Value shifted from the array
@@ -51,24 +51,27 @@ export interface MutateContext {
51
51
  /**
52
52
  * The data object passed to the callback after mutation.
53
53
  */
54
- export interface MutatePatch {
55
- method: string; // The mutation method (e.g., 'push', 'pop', 'splice', etc.)
54
+ export interface MutationPatch<T = any> {
55
+ key: string; // The mutation method (e.g., 'push', 'pop', 'splice', etc.)
56
+ value: any; // The result of the mutation (the modified array)
56
57
  args: any[]; // Arguments passed to the mutation method
57
- context: MutateContext; // The state before mutation
58
- result: any; // The result of the mutation (the modified array)
58
+ context: MutationContextt; // The state before mutation
59
+ target: T[]; // Reference to the mutated array
59
60
  timestamp: number; // The timestamp of the mutation
61
+ [key: string]: any; // Additional properties from props
60
62
  }
61
63
 
62
64
  /**
63
65
  * Configuration options for the mutateArray function.
64
66
  */
65
- export interface MutateOptions {
67
+ export interface MutationOptions {
66
68
  target: any[]; // The array to mutate
67
69
  method: string; // The mutation method to apply (e.g., 'push', 'splice', etc.)
68
70
  args?: any[]; // Optional arguments to pass to the mutation method
69
- onBeforeMutate?: (context: MutateContext) => void; // Callback triggered before the mutation
70
- onAfterMutate?: (patch: MutatePatch) => void; // Callback triggered after the mutation
71
+ onBeforeMutate?: (context: MutationContextt) => void; // Callback triggered before the mutation
72
+ onAfterMutate?: (patch: MutationPatch) => void; // Callback triggered after the mutation
71
73
  allowList?: string[]; // Optional list of allowed mutation methods
74
+ props?: Record<string, any>; // Additional properties to attach to the patch
72
75
  }
73
76
 
74
77
  const mutateArray = ({
@@ -77,8 +80,9 @@ const mutateArray = ({
77
80
  args = [],
78
81
  onBeforeMutate = () => { },
79
82
  onAfterMutate = () => { },
80
- allowList
81
- }: MutateOptions): any => {
83
+ allowList,
84
+ props = {},
85
+ }: MutationOptions): any => {
82
86
 
83
87
  // Validation: Ensure target is an array and method is allowed
84
88
  if (!Array.isArray(target)) {
@@ -86,13 +90,13 @@ const mutateArray = ({
86
90
  }
87
91
  //使用默认
88
92
  if (!allowList || allowList?.length) {
89
- allowList = mutateMethods;
93
+ allowList = mutableMethods;
90
94
  }
91
95
  if (!allowList?.includes(method)) {
92
96
  throw new Error(`Method "${method}" is not in the allowList or is not a mutation method.`);
93
97
  }
94
98
 
95
- const context: MutateContext = {},
99
+ const context: MutationContextt = {},
96
100
  len = target.length;
97
101
 
98
102
  // Capture "Pre-mutation" context for Undo/Redo/Tracking purposes
@@ -135,21 +139,24 @@ const mutateArray = ({
135
139
  }
136
140
 
137
141
  // Execute the "onBeforeMutate" callback before mutation
138
- onBeforeMutate && onBeforeMutate(context);
142
+ onBeforeMutate?.(context);
139
143
 
140
144
  // Execute the native array mutation
141
- const result = (Array.prototype as any)[method].apply(target, args);
145
+ const value = (Array.prototype as any)[method].apply(target, args),
146
+ patch: MutationPatch = {
147
+ value,
148
+ key: method,
149
+ args,
150
+ context,
151
+ target,
152
+ timestamp: Date.now(),
153
+ ...props
154
+ };
142
155
 
143
156
  // Construct and trigger the patch callback
144
- onAfterMutate && onAfterMutate({
145
- method,
146
- args,
147
- context,
148
- result,
149
- timestamp: Date.now()
150
- });
157
+ onAfterMutate?.(patch);
151
158
 
152
- return result;
159
+ return value;
153
160
  }
154
161
 
155
162
  export default mutateArray;