@codady/utils 0.0.9 → 0.0.10
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 +21 -0
- package/dist/utils.cjs.js +234 -27
- package/dist/utils.cjs.min.js +3 -3
- package/dist/utils.esm.js +234 -27
- package/dist/utils.esm.min.js +3 -3
- package/dist/utils.umd.js +234 -27
- package/dist/utils.umd.min.js +3 -3
- package/dist.zip +0 -0
- package/modules.js +11 -3
- package/modules.ts +11 -3
- package/package.json +1 -1
- package/src/arrayMutableMethods - /345/211/257/346/234/254.js" +5 -0
- package/src/arrayMutableMethods.js +5 -0
- package/src/{mutableMethods.ts → arrayMutableMethods.ts} +3 -3
- package/src/deepClone.js +151 -26
- package/src/deepClone.ts +194 -35
- package/src/deepCloneToJSON - /345/211/257/346/234/254.js" +47 -0
- package/src/getUniqueId.js +11 -7
- package/src/getUniqueId.ts +16 -9
- package/src/mapMutableMethods.js +5 -0
- package/src/mapMutableMethods.ts +15 -0
- package/src/mutableMethods.js +2 -2
- package/src/setMutableMethods - /345/211/257/346/234/254.js" +5 -0
- package/src/setMutableMethods.js +5 -0
- package/src/setMutableMethods.ts +14 -0
- package/src/wrapArrayMethods.js +5 -5
- package/src/wrapArrayMethods.ts +7 -7
- package/src/wrapMap - /345/211/257/346/234/254.js" +119 -0
- package/src/wrapMapMethods.js +118 -0
- package/src/wrapMapMethods.ts +226 -0
- package/src/wrapSetMethods.js +112 -0
- package/src/wrapSetMethods.ts +215 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,27 @@
|
|
|
3
3
|
All changes to Utils including new features, updates, and removals are documented here.
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
## [v0.0.10] - 2025-12-21
|
|
7
|
+
|
|
8
|
+
### Distribution Files
|
|
9
|
+
* **JS**: https://unpkg.com/@codady/utils@0.0.10/dist/js/utils.js
|
|
10
|
+
* **Zip**:https://unpkg.com/@codady/utils@0.0.10/dist.zip
|
|
11
|
+
|
|
12
|
+
### Changes
|
|
13
|
+
|
|
14
|
+
#### Fixed
|
|
15
|
+
* Modified the `getUniqueId` parameter structure, changing the `extra` parameter to `base10`, and adding a `base36` parameter.修改了`getUniqueId`的参数结构,extra参数改为base10,新增base36参数。
|
|
16
|
+
* Modified the `deepClone` function, adding an `options` parameter. By default, it does not copy reference types like `Date`, `Function`, `RegExp`, etc.修改了`deepClone`函数,增加options参数,默认不复制Date、Function、RegExp等引用类型数据。
|
|
17
|
+
* Changed `mutableMethods` to `arrayMutableMethods`.将`mutableMethods`改为`arrayMutableMethods`。
|
|
18
|
+
|
|
19
|
+
#### Added
|
|
20
|
+
* Added `setMutableMethods` and `mapMutableMethods` variables.新增`setMutableMethods`和`mapMutableMethods`变量。
|
|
21
|
+
* Added `wrapSetMethods` and `wrapMapMethods` functions.新增`wrapSetMethods`和`wrapMapMethods`函数。
|
|
22
|
+
|
|
23
|
+
#### Removed
|
|
24
|
+
* Null
|
|
25
|
+
|
|
26
|
+
|
|
6
27
|
## [v0.0.7] - 2025-12-19
|
|
7
28
|
|
|
8
29
|
### Distribution Files
|
package/dist/utils.cjs.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
/*!
|
|
3
|
-
* @since Last modified: 2025-12-
|
|
3
|
+
* @since Last modified: 2025-12-22 20:26:42
|
|
4
4
|
* @name Utils for web front-end.
|
|
5
|
-
* @version 0.0.
|
|
5
|
+
* @version 0.0.10
|
|
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}
|
|
@@ -41,37 +41,100 @@ const getDataType = (obj) => {
|
|
|
41
41
|
//document.createElementNS('http://www.w3.org/1998/Math/MathML', 'math'); -> MathMLElement
|
|
42
42
|
};
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
//支持原始值的复制,包括Number、String、Boolean、Null
|
|
45
|
+
//支持Date和Regex对象值复制(值转换)
|
|
46
|
+
//支持{},[],Set和Map的遍历
|
|
47
|
+
const deepClone = (data, options = {}) => {
|
|
48
|
+
const dataType = getDataType(data),
|
|
49
|
+
// Default options
|
|
50
|
+
opts = Object.assign({
|
|
51
|
+
cloneSet: true,
|
|
52
|
+
cloneMap: true,
|
|
53
|
+
cloneObject: true,
|
|
54
|
+
cloneArray: true,
|
|
55
|
+
//可重新构建
|
|
56
|
+
cloneDate: true,
|
|
57
|
+
cloneRegex: true,
|
|
58
|
+
//节点默认不复制
|
|
59
|
+
//cloneElement: false,
|
|
60
|
+
//cloneFragment: false,
|
|
61
|
+
}, options);
|
|
62
|
+
// Check interceptor - if it returns a value (not null/undefined), use it directly
|
|
63
|
+
if (opts.interceptor && typeof opts.interceptor === 'function') {
|
|
64
|
+
let result = opts.interceptor(data, dataType);
|
|
65
|
+
if ((result ?? false)) {
|
|
66
|
+
// Call onAfterClone if set
|
|
67
|
+
opts.onAfterClone?.({
|
|
68
|
+
output: result,
|
|
69
|
+
input: data,
|
|
70
|
+
type: dataType,
|
|
71
|
+
cloned: result !== data,
|
|
72
|
+
});
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
// If interceptor returns null/undefined, continue with normal cloning process
|
|
76
|
+
}
|
|
77
|
+
// Callback before cloning
|
|
78
|
+
opts.onBeforeClone?.(data, dataType);
|
|
79
|
+
let newData, cloned = true;
|
|
80
|
+
if (dataType === 'Object' && opts.cloneObject) {
|
|
81
|
+
const newObj = {}, symbols = Object.getOwnPropertySymbols(data);
|
|
49
82
|
// Clone regular properties
|
|
50
83
|
for (const key in data) {
|
|
51
|
-
newObj[key] = deepClone(data[key]);
|
|
84
|
+
newObj[key] = deepClone(data[key], opts);
|
|
52
85
|
}
|
|
53
86
|
// Clone Symbol properties
|
|
54
87
|
if (symbols.length > 0) {
|
|
55
88
|
for (const symbol of symbols) {
|
|
56
|
-
newObj[symbol] = deepClone(data[symbol]);
|
|
89
|
+
newObj[symbol] = deepClone(data[symbol], opts);
|
|
57
90
|
}
|
|
58
91
|
}
|
|
59
|
-
|
|
92
|
+
newData = newObj;
|
|
60
93
|
}
|
|
61
|
-
else if (dataType === 'Array') {
|
|
62
|
-
|
|
94
|
+
else if (dataType === 'Array' && opts.cloneArray) {
|
|
95
|
+
newData = data.map(item => deepClone(item, opts));
|
|
63
96
|
}
|
|
64
|
-
else if (dataType === '
|
|
65
|
-
|
|
97
|
+
else if (dataType === 'Map' && opts.cloneMap) {
|
|
98
|
+
const newMap = new Map();
|
|
99
|
+
for (const [key, value] of data) {
|
|
100
|
+
// Both Map keys and values need deep cloning
|
|
101
|
+
newMap.set(deepClone(key, opts), deepClone(value, opts));
|
|
102
|
+
}
|
|
103
|
+
newData = newMap;
|
|
104
|
+
}
|
|
105
|
+
else if (dataType === 'Set' && opts.cloneSet) {
|
|
106
|
+
const newSet = new Set();
|
|
107
|
+
for (const value of data) {
|
|
108
|
+
// Set values need deep cloning
|
|
109
|
+
newSet.add(deepClone(value, opts));
|
|
110
|
+
}
|
|
111
|
+
newData = newSet;
|
|
66
112
|
}
|
|
67
|
-
else if (dataType === '
|
|
113
|
+
else if (dataType === 'Date' && opts.cloneDate) {
|
|
114
|
+
newData = new Date(data.getTime());
|
|
115
|
+
}
|
|
116
|
+
else if (dataType === 'RegExp' && opts.cloneRegex) {
|
|
68
117
|
const regex = data;
|
|
69
|
-
|
|
118
|
+
newData = new RegExp(regex.source, regex.flags);
|
|
119
|
+
// } else if ((dataType.includes('HTML') && opts.cloneElement) ||
|
|
120
|
+
// (dataType === 'DocumentFragment' && opts.cloneFragment)
|
|
121
|
+
//) {
|
|
122
|
+
//Text,Comment,HTML*Element,DocumentFragment,Attr
|
|
123
|
+
// newData = (data as any).cloneNode(true) as T;
|
|
70
124
|
}
|
|
71
125
|
else {
|
|
72
|
-
// Number, String, Boolean, Symbol,
|
|
73
|
-
|
|
126
|
+
// Number, String, Boolean, Symbol, Function,Error,Promise,ArrayBuffer,Blob,File, return directly
|
|
127
|
+
newData = data;
|
|
128
|
+
cloned = false;
|
|
74
129
|
}
|
|
130
|
+
// Callback after cloning
|
|
131
|
+
opts.onAfterClone?.({
|
|
132
|
+
output: newData,
|
|
133
|
+
input: data,
|
|
134
|
+
type: dataType,
|
|
135
|
+
cloned,
|
|
136
|
+
});
|
|
137
|
+
return newData;
|
|
75
138
|
};
|
|
76
139
|
|
|
77
140
|
const deepCloneToJSON = (data) => {
|
|
@@ -102,7 +165,7 @@ const deepCloneToJSON = (data) => {
|
|
|
102
165
|
}
|
|
103
166
|
};
|
|
104
167
|
|
|
105
|
-
const
|
|
168
|
+
const arrayMutableMethods = [
|
|
106
169
|
'push', 'pop', 'shift', 'unshift', 'splice',
|
|
107
170
|
'sort', 'reverse', 'copyWithin', 'fill'
|
|
108
171
|
];
|
|
@@ -114,7 +177,7 @@ const wrapArrayMethods = ({ target, onBeforeMutate = () => { }, onAfterMutate =
|
|
|
114
177
|
}
|
|
115
178
|
//使用默认
|
|
116
179
|
if (!allowList || allowList?.length) {
|
|
117
|
-
allowList =
|
|
180
|
+
allowList = arrayMutableMethods;
|
|
118
181
|
}
|
|
119
182
|
const methods = {};
|
|
120
183
|
for (let method of allowList) {
|
|
@@ -130,10 +193,10 @@ const wrapArrayMethods = ({ target, onBeforeMutate = () => { }, onAfterMutate =
|
|
|
130
193
|
context.addedItems = [...args];
|
|
131
194
|
break;
|
|
132
195
|
case 'pop':
|
|
133
|
-
context.
|
|
196
|
+
context.poppedItem = target[len - 1];
|
|
134
197
|
break;
|
|
135
198
|
case 'shift':
|
|
136
|
-
context.
|
|
199
|
+
context.shiftedItem = target[0];
|
|
137
200
|
break;
|
|
138
201
|
case 'splice':
|
|
139
202
|
const [s, d] = args,
|
|
@@ -203,20 +266,160 @@ const requireTypes = (data, require, cb) => {
|
|
|
203
266
|
return dataType;
|
|
204
267
|
};
|
|
205
268
|
|
|
206
|
-
const getUniqueId = (
|
|
269
|
+
const getUniqueId = (options = {}) => {
|
|
270
|
+
const prefix = options.prefix, suffix = options.suffix, base10 = options.base10, base36 = options.base36;
|
|
207
271
|
// Current timestamp in milliseconds (since Unix epoch)
|
|
208
272
|
// This provides the primary uniqueness guarantee
|
|
209
273
|
const timestamp = Date.now(),
|
|
210
274
|
// Generate a base-36 random string (0-9, a-z)
|
|
211
275
|
// Math.random() returns a number in [0, 1), converting to base-36 gives a compact representation
|
|
212
276
|
// substring(2, 11) extracts 9 characters starting from index 2
|
|
213
|
-
|
|
277
|
+
//0.259854635->0.9crs03e8v2
|
|
278
|
+
base36Random = base36 ? '-' + Math.random().toString(36).substring(2, 11) : '',
|
|
214
279
|
// Additional 4-digit random number for extra randomness
|
|
215
280
|
// This helps avoid collisions in high-frequency generation scenarios
|
|
216
|
-
|
|
281
|
+
base10Random = base10 ? '-' + Math.floor(Math.random() * 10000).toString().padStart(4, '0') : '', prefixString = prefix ? prefix + '-' : '', suffixString = suffix ? '-' + suffix : '';
|
|
217
282
|
// Construct the final ID string
|
|
218
283
|
// Format: [prefix_]timestamp_randomBase36_extraRandom
|
|
219
|
-
return `${prefixString}${timestamp}
|
|
284
|
+
return `${prefixString}${timestamp}${base36Random}${base10Random}${suffixString}`;
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
const setMutableMethods = ['add', 'delete', 'clear'];
|
|
288
|
+
|
|
289
|
+
const mapMutableMethods = ['set', 'delete', 'clear'];
|
|
290
|
+
|
|
291
|
+
const wrapSetMethods = ({ target, onBeforeMutate = () => { }, onAfterMutate = () => { }, allowList = setMutableMethods, props = {}, }) => {
|
|
292
|
+
// Validation: Ensure target is a Set
|
|
293
|
+
if (!(target instanceof Set)) {
|
|
294
|
+
throw new TypeError("The 'target' parameter must be a Set.");
|
|
295
|
+
}
|
|
296
|
+
// Create method wrappers
|
|
297
|
+
const methods = {};
|
|
298
|
+
// Helper to create wrapped method
|
|
299
|
+
const createWrappedMethod = (method) => {
|
|
300
|
+
return function (...args) {
|
|
301
|
+
const context = {};
|
|
302
|
+
// Capture pre-mutation context based on method
|
|
303
|
+
switch (method) {
|
|
304
|
+
case 'add': {
|
|
305
|
+
const [value] = args;
|
|
306
|
+
context.addedItem = value;
|
|
307
|
+
//context.existed=true,说明值重复
|
|
308
|
+
context.existed = target.has(value);
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
case 'delete': {
|
|
312
|
+
const [value] = args;
|
|
313
|
+
context.existed = target.has(value);
|
|
314
|
+
context.deletedItem = context.existed ? value : undefined;
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
case 'clear': {
|
|
318
|
+
context.clearedItems = Array.from(target);
|
|
319
|
+
//用来做验证
|
|
320
|
+
context.previousSize = target.size;
|
|
321
|
+
break;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
// Execute before mutation callback
|
|
325
|
+
onBeforeMutate(context);
|
|
326
|
+
// Execute the native Set method
|
|
327
|
+
const result = target[method].apply(target, args);
|
|
328
|
+
// Construct patch object
|
|
329
|
+
const patch = {
|
|
330
|
+
method,
|
|
331
|
+
result,
|
|
332
|
+
args,
|
|
333
|
+
context,
|
|
334
|
+
target,
|
|
335
|
+
...props
|
|
336
|
+
};
|
|
337
|
+
// Execute after mutation callback
|
|
338
|
+
onAfterMutate(patch);
|
|
339
|
+
return result;
|
|
340
|
+
};
|
|
341
|
+
};
|
|
342
|
+
// Wrap allowed methods
|
|
343
|
+
for (const method of allowList) {
|
|
344
|
+
if (setMutableMethods.includes(method)) {
|
|
345
|
+
methods[method] = createWrappedMethod(method);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
// Add target reference
|
|
349
|
+
Object.defineProperty(methods, 'target', {
|
|
350
|
+
get: () => target,
|
|
351
|
+
enumerable: false,
|
|
352
|
+
configurable: false
|
|
353
|
+
});
|
|
354
|
+
return methods;
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
const wrapMapMethods = ({ target, onBeforeMutate = () => { }, onAfterMutate = () => { }, allowList = mapMutableMethods, props = {}, }) => {
|
|
358
|
+
// Validation: Ensure target is a Map
|
|
359
|
+
if (!(target instanceof Map)) {
|
|
360
|
+
throw new TypeError("The 'target' parameter must be a Map.");
|
|
361
|
+
}
|
|
362
|
+
// Create method wrappers
|
|
363
|
+
const methods = {};
|
|
364
|
+
// Helper to create wrapped method
|
|
365
|
+
const createWrappedMethod = (method) => {
|
|
366
|
+
return function (...args) {
|
|
367
|
+
const context = {};
|
|
368
|
+
// Capture pre-mutation context based on method
|
|
369
|
+
switch (method) {
|
|
370
|
+
case 'set': {
|
|
371
|
+
const [key, newValue] = args;
|
|
372
|
+
context.key = key;
|
|
373
|
+
context.newValue = newValue;
|
|
374
|
+
context.existed = target.has(key);
|
|
375
|
+
context.oldValue = context.existed ? target.get(key) : undefined;
|
|
376
|
+
break;
|
|
377
|
+
}
|
|
378
|
+
case 'delete': {
|
|
379
|
+
const [key] = args;
|
|
380
|
+
context.key = key;
|
|
381
|
+
context.existed = target.has(key);
|
|
382
|
+
context.value = context.existed ? target.get(key) : undefined;
|
|
383
|
+
break;
|
|
384
|
+
}
|
|
385
|
+
case 'clear': {
|
|
386
|
+
context.clearedItems = Array.from(target.entries());
|
|
387
|
+
//用来做验证
|
|
388
|
+
context.previousSize = target.size;
|
|
389
|
+
break;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
// Execute before mutation callback
|
|
393
|
+
onBeforeMutate(context);
|
|
394
|
+
// Execute the native Map method
|
|
395
|
+
const result = target[method].apply(target, args);
|
|
396
|
+
// Construct patch object
|
|
397
|
+
const patch = {
|
|
398
|
+
method,
|
|
399
|
+
result,
|
|
400
|
+
args,
|
|
401
|
+
context,
|
|
402
|
+
target,
|
|
403
|
+
...props
|
|
404
|
+
};
|
|
405
|
+
// Execute after mutation callback
|
|
406
|
+
onAfterMutate(patch);
|
|
407
|
+
return result;
|
|
408
|
+
};
|
|
409
|
+
};
|
|
410
|
+
// Wrap allowed methods
|
|
411
|
+
for (const method of allowList) {
|
|
412
|
+
if (mapMutableMethods.includes(method)) {
|
|
413
|
+
methods[method] = createWrappedMethod(method);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
// Add target reference
|
|
417
|
+
Object.defineProperty(methods, 'target', {
|
|
418
|
+
get: () => target,
|
|
419
|
+
enumerable: false,
|
|
420
|
+
configurable: false
|
|
421
|
+
});
|
|
422
|
+
return methods;
|
|
220
423
|
};
|
|
221
424
|
|
|
222
425
|
const utils = {
|
|
@@ -228,7 +431,11 @@ const utils = {
|
|
|
228
431
|
deepClone,
|
|
229
432
|
deepCloneToJSON,
|
|
230
433
|
wrapArrayMethods,
|
|
231
|
-
|
|
434
|
+
arrayMutableMethods,
|
|
435
|
+
setMutableMethods,
|
|
436
|
+
mapMutableMethods,
|
|
437
|
+
wrapSetMethods,
|
|
438
|
+
wrapMapMethods,
|
|
232
439
|
getUniqueId
|
|
233
440
|
};
|
|
234
441
|
|
package/dist/utils.cjs.min.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @since Last modified: 2025-12-
|
|
2
|
+
* @since Last modified: 2025-12-22 20:26:42
|
|
3
3
|
* @name Utils for web front-end.
|
|
4
|
-
* @version 0.0.
|
|
4
|
+
* @version 0.0.10
|
|
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,
|
|
15
|
+
"use strict";const getDataType=e=>{let t,o=Object.prototype.toString.call(e).slice(8,-1);return t="Function"===o&&/^\s*class\s+/.test(e.toString())?"Class":"Object"===o&&Object.getPrototypeOf(e)!==Object.prototype?"Instance":o,t},deepClone=(e,t={})=>{const o=getDataType(e),r=Object.assign({cloneSet:!0,cloneMap:!0,cloneObject:!0,cloneArray:!0,cloneDate:!0,cloneRegex:!0},t);if(r.interceptor&&"function"==typeof r.interceptor){let t=r.interceptor(e,o);if(t)return r.onAfterClone?.({output:t,input:e,type:o,cloned:t!==e}),t}r.onBeforeClone?.(e,o);let a,s=!0;if("Object"===o&&r.cloneObject){const t={},o=Object.getOwnPropertySymbols(e);for(const o in e)t[o]=deepClone(e[o],r);if(o.length>0)for(const a of o)t[a]=deepClone(e[a],r);a=t}else if("Array"===o&&r.cloneArray)a=e.map(e=>deepClone(e,r));else if("Map"===o&&r.cloneMap){const t=new Map;for(const[o,a]of e)t.set(deepClone(o,r),deepClone(a,r));a=t}else if("Set"===o&&r.cloneSet){const t=new Set;for(const o of e)t.add(deepClone(o,r));a=t}else if("Date"===o&&r.cloneDate)a=new Date(e.getTime());else if("RegExp"===o&&r.cloneRegex){const t=e;a=new RegExp(t.source,t.flags)}else a=e,s=!1;return r.onAfterClone?.({output:a,input:e,type:o,cloned:s}),a},deepCloneToJSON=e=>{const t=getDataType(e);if("Object"===t){const t={};for(const o in e)t[o]=deepCloneToJSON(e[o]);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:o=()=>{},allowList:r,props:a={}})=>{if(!Array.isArray(e))throw new TypeError("The 'target' parameter must be an array.");r&&!r?.length||(r=arrayMutableMethods);const s={};for(let n of r)s[n]=function(...r){const s={},l=e.length;switch(n){case"push":case"unshift":s.addedItems=[...r];break;case"pop":s.poppedItem=e[l-1];break;case"shift":s.shiftedItem=e[0];break;case"splice":const[t,o]=r,a=t<0?Math.max(l+t,0):Math.min(t,l),n=void 0===o?l-a:o;s.deletedItems=e.slice(a,a+n);break;case"sort":case"reverse":s.oldSnapshot=[...e];break;case"fill":case"copyWithin":const c=r[1]||0,p=void 0===r[2]?l:r[2];s.oldItems=e.slice(c,p),s.start=c,s.end=p}t?.(s);const c=Array.prototype[n].apply(e,r),p={value:c,key:n,args:r,context:s,target:e,...a};return o?.(p),c};return s},requireTypes=(e,t,o)=>{let r=Array.isArray(t)?t:[t],a=getDataType(e),s=a.toLowerCase(),n=r.map(e=>e.toLowerCase()),l=s.includes("html")?"element":s;if(o)try{if(!n.includes(l))throw new TypeError(`Expected data type(s): [${n.join(", ")}], but got: ${l}`)}catch(e){o(e,a)}else if(!n.includes(l))throw new TypeError(`Expected data type(s): [${n.join(", ")}], but got: ${l}`);return a},getUniqueId=(e={})=>{const t=e.prefix,o=e.suffix,r=e.base10,a=e.base36;return`${t?t+"-":""}${Date.now()}${a?"-"+Math.random().toString(36).substring(2,11):""}${r?"-"+Math.floor(1e4*Math.random()).toString().padStart(4,"0"):""}${o?"-"+o:""}`},setMutableMethods=["add","delete","clear"],mapMutableMethods=["set","delete","clear"],wrapSetMethods=({target:e,onBeforeMutate:t=()=>{},onAfterMutate:o=()=>{},allowList:r=setMutableMethods,props:a={}})=>{if(!(e instanceof Set))throw new TypeError("The 'target' parameter must be a Set.");const s={},createWrappedMethod=r=>function(...s){const n={};switch(r){case"add":{const[t]=s;n.addedItem=t,n.existed=e.has(t);break}case"delete":{const[t]=s;n.existed=e.has(t),n.deletedItem=n.existed?t:void 0;break}case"clear":n.clearedItems=Array.from(e),n.previousSize=e.size}t(n);const l=e[r].apply(e,s),c={method:r,result:l,args:s,context:n,target:e,...a};return o(c),l};for(const e of r)setMutableMethods.includes(e)&&(s[e]=createWrappedMethod(e));return Object.defineProperty(s,"target",{get:()=>e,enumerable:!1,configurable:!1}),s},wrapMapMethods=({target:e,onBeforeMutate:t=()=>{},onAfterMutate:o=()=>{},allowList:r=mapMutableMethods,props:a={}})=>{if(!(e instanceof Map))throw new TypeError("The 'target' parameter must be a Map.");const s={},createWrappedMethod=r=>function(...s){const n={};switch(r){case"set":{const[t,o]=s;n.key=t,n.newValue=o,n.existed=e.has(t),n.oldValue=n.existed?e.get(t):void 0;break}case"delete":{const[t]=s;n.key=t,n.existed=e.has(t),n.value=n.existed?e.get(t):void 0;break}case"clear":n.clearedItems=Array.from(e.entries()),n.previousSize=e.size}t(n);const l=e[r].apply(e,s),c={method:r,result:l,args:s,context:n,target:e,...a};return o(c),l};for(const e of r)mapMutableMethods.includes(e)&&(s[e]=createWrappedMethod(e));return Object.defineProperty(s,"target",{get:()=>e,enumerable:!1,configurable:!1}),s},utils={getDataType:getDataType,requireTypes:requireTypes,deepClone:deepClone,deepCloneToJSON:deepCloneToJSON,wrapArrayMethods:wrapArrayMethods,arrayMutableMethods:arrayMutableMethods,setMutableMethods:setMutableMethods,mapMutableMethods:mapMutableMethods,wrapSetMethods:wrapSetMethods,wrapMapMethods:wrapMapMethods,getUniqueId:getUniqueId};module.exports=utils;
|