@codady/utils 0.0.9 → 0.0.11

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.
Files changed (48) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/utils.cjs.js +488 -28
  3. package/dist/utils.cjs.min.js +3 -3
  4. package/dist/utils.esm.js +488 -28
  5. package/dist/utils.esm.min.js +3 -3
  6. package/dist/utils.umd - /345/211/257/346/234/254.js" +749 -0
  7. package/dist/utils.umd.js +490 -32
  8. package/dist/utils.umd.min.js +3 -3
  9. package/dist.zip +0 -0
  10. package/modules.js +24 -4
  11. package/modules.ts +24 -4
  12. package/package.json +1 -1
  13. package/src/arrayMutableMethods - /345/211/257/346/234/254.js" +5 -0
  14. package/src/arrayMutableMethods.js +5 -0
  15. package/src/{mutableMethods.ts → arrayMutableMethods.ts} +3 -3
  16. package/src/deepClone.js +151 -26
  17. package/src/deepClone.ts +194 -35
  18. package/src/deepCloneToJSON - /345/211/257/346/234/254.js" +47 -0
  19. package/src/deepEqual.js +48 -0
  20. package/src/deepEqual.ts +46 -0
  21. package/src/deepMerge.js +34 -0
  22. package/src/deepMerge.ts +40 -0
  23. package/src/deepMergeArrays.js +45 -0
  24. package/src/deepMergeArrays.ts +62 -0
  25. package/src/deepMergeHelper.js +40 -0
  26. package/src/deepMergeHelper.ts +45 -0
  27. package/src/deepMergeMaps - /345/211/257/346/234/254.js" +78 -0
  28. package/src/deepMergeMaps.js +57 -0
  29. package/src/deepMergeMaps.ts +67 -0
  30. package/src/deepMergeObjects.js +82 -0
  31. package/src/deepMergeObjects.ts +85 -0
  32. package/src/deepMergeSets.js +48 -0
  33. package/src/deepMergeSets.ts +55 -0
  34. package/src/getUniqueId.js +11 -7
  35. package/src/getUniqueId.ts +16 -9
  36. package/src/mapMutableMethods.js +5 -0
  37. package/src/mapMutableMethods.ts +15 -0
  38. package/src/mutableMethods.js +2 -2
  39. package/src/setMutableMethods - /345/211/257/346/234/254.js" +5 -0
  40. package/src/setMutableMethods.js +5 -0
  41. package/src/setMutableMethods.ts +14 -0
  42. package/src/wrapArrayMethods.js +5 -5
  43. package/src/wrapArrayMethods.ts +7 -7
  44. package/src/wrapMap - /345/211/257/346/234/254.js" +119 -0
  45. package/src/wrapMapMethods.js +118 -0
  46. package/src/wrapMapMethods.ts +226 -0
  47. package/src/wrapSetMethods.js +112 -0
  48. package/src/wrapSetMethods.ts +215 -0
@@ -0,0 +1,226 @@
1
+ /**
2
+ * @since Last modified: 2025/12/22 17:19:32
3
+ * Wraps Map objects with mutation tracking capabilities.
4
+ * Provides hooks for before/after mutation events and captures detailed context
5
+ * for undo/redo or change tracking purposes.
6
+ *
7
+ * @template K - Map key type
8
+ * @template V - Map value type
9
+ * @param {MapMutationOptions<K, V>} options - Configuration object containing target Map and callbacks
10
+ * @returns {MapMutationMethods<K, V>} - Object containing wrapped Map mutation methods
11
+ *
12
+ * @example
13
+ * // Basic usage with tracking
14
+ * const map = new Map([['key1', 'value1']]);
15
+ * const methods = wrapMap({
16
+ * target: map,
17
+ * onAfterMutate: (patch) => {
18
+ * console.log(`Map ${patch.method} called`, patch.context);
19
+ * }
20
+ * });
21
+ *
22
+ * methods.set('key2', 'value2'); // Tracked
23
+ * methods.delete('key1'); // Tracked
24
+ * methods.clear(); // Tracked
25
+ *
26
+ * @example
27
+ * // With undo/redo support
28
+ * const history: MapMutationPatch<any, any>[] = [];
29
+ * const map = new Map<string, number>();
30
+ *
31
+ * const methods = wrapMap({
32
+ * target: map,
33
+ * onBeforeMutate: (context) => {
34
+ * console.log('Before mutation:', context);
35
+ * },
36
+ * onAfterMutate: (patch) => {
37
+ * history.push(patch);
38
+ * console.log('Mutation recorded:', patch.method, 'History size:', history.length);
39
+ * }
40
+ * });
41
+ */
42
+ 'use strict';
43
+
44
+ import mapMutableMethods, { MapMutationNames } from "./mapMutableMethods";
45
+
46
+ /**
47
+ * Context captured before Map mutation for tracking purposes
48
+ */
49
+ export interface MapMutationContext<K = any, V = any> {
50
+ /** For set method: the key being set */
51
+ key?: K;
52
+ /** For delete method: the deleted value */
53
+ value?: V;
54
+ /** For set method: the new value being set */
55
+ newValue?: V;
56
+ /** For set method: the old value if key existed */
57
+ oldValue?: V;
58
+ /** For set / delete method: whether the key existed */
59
+ existed?: boolean;
60
+ /** For clear method: snapshot of all entries before clearing */
61
+ clearedItems?: [K, V][];
62
+ /** For clear method: size of the Map before clearing */
63
+ previousSize?: number;
64
+ }
65
+
66
+ /**
67
+ * Data object passed to callback after Map mutation
68
+ */
69
+ export interface MapMutationPatch<K = any, V = any> {
70
+ /** The mutation method called */
71
+ method: MapMutationNames;
72
+ /** The result returned by the mutation method */
73
+ result: any;
74
+ /** Arguments passed to the mutation method */
75
+ args: any[];
76
+ /** Context captured before mutation */
77
+ context: MapMutationContext<K, V>;
78
+ /** Reference to the mutated Map */
79
+ target: Map<K, V>;
80
+ /** Additional custom properties */
81
+ [key: string]: any;
82
+ }
83
+
84
+ /**
85
+ * Configuration options for wrapMap function
86
+ */
87
+ export interface MapMutationOptions<K = any, V = any> {
88
+ /** The Map to wrap with mutation tracking */
89
+ target: Map<K, V>;
90
+ /** Callback triggered before mutation */
91
+ onBeforeMutate?: (context: MapMutationContext<K, V>) => void;
92
+ /** Callback triggered after mutation */
93
+ onAfterMutate?: (patch: MapMutationPatch<K, V>) => void;
94
+ /** Optional list of allowed mutation methods (default: all Map methods) */
95
+ allowList?: MapMutationNames[];
96
+ /** Additional properties to attach to the patch */
97
+ props?: Record<string, any>;
98
+ }
99
+
100
+ /**
101
+ * Wrapped mutation methods for Map
102
+ */
103
+ export interface MapMutationMethods<K = any, V = any> {
104
+ /**
105
+ * Sets the value for the key in the Map.
106
+ * @param key The key to set
107
+ * @param value The value to set
108
+ * @returns The Map object
109
+ */
110
+ set: (key: K, value: V) => Map<K, V>;
111
+
112
+ /**
113
+ * Deletes the key from the Map.
114
+ * @param key The key to delete
115
+ * @returns true if the key existed and has been removed, false otherwise
116
+ */
117
+ delete: (key: K) => boolean;
118
+
119
+ /**
120
+ * Clears all entries from the Map.
121
+ * @returns void
122
+ */
123
+ clear: () => void;
124
+
125
+ /**
126
+ * Gets the original Map instance for direct access
127
+ */
128
+ readonly target: Map<K, V>;
129
+ }
130
+
131
+ /**
132
+ * Creates wrapped mutation methods for Map with tracking capabilities
133
+ *
134
+ * @param options Configuration options
135
+ * @returns Object containing wrapped Map mutation methods
136
+ * @throws TypeError if target is not a Map
137
+ */
138
+ const wrapMapMethods = <K = any, V = any>({
139
+ target,
140
+ onBeforeMutate = () => { },
141
+ onAfterMutate = () => { },
142
+ allowList = mapMutableMethods,
143
+ props = {},
144
+ }: MapMutationOptions<K, V>): MapMutationMethods<K, V> => {
145
+
146
+ // Validation: Ensure target is a Map
147
+ if (!(target instanceof Map)) {
148
+ throw new TypeError("The 'target' parameter must be a Map.");
149
+ }
150
+
151
+ // Create method wrappers
152
+ const methods: Partial<MapMutationMethods<K, V>> = {};
153
+
154
+ // Helper to create wrapped method
155
+ const createWrappedMethod = (method: MapMutationNames) => {
156
+ return function (...args: any[]) {
157
+ const context: MapMutationContext<K, V> = {};
158
+
159
+ // Capture pre-mutation context based on method
160
+ switch (method) {
161
+ case 'set': {
162
+ const [key, newValue] = args as [K, V];
163
+ context.key = key;
164
+ context.newValue = newValue;
165
+ context.existed = target.has(key);
166
+ context.oldValue = context.existed ? target.get(key) : undefined;
167
+ break;
168
+ }
169
+
170
+ case 'delete': {
171
+ const [key] = args as [K];
172
+ context.key = key;
173
+ context.existed = target.has(key);
174
+ context.value = context.existed ? target.get(key) : undefined;
175
+ break;
176
+ }
177
+
178
+ case 'clear': {
179
+ context.clearedItems = Array.from(target.entries());
180
+ //用来做验证
181
+ context.previousSize = target.size;
182
+ break;
183
+ }
184
+ }
185
+
186
+ // Execute before mutation callback
187
+ onBeforeMutate(context);
188
+
189
+ // Execute the native Map method
190
+ const result = (target as any)[method].apply(target, args);
191
+
192
+ // Construct patch object
193
+ const patch: MapMutationPatch<K, V> = {
194
+ method,
195
+ result,
196
+ args,
197
+ context,
198
+ target,
199
+ ...props
200
+ };
201
+
202
+ // Execute after mutation callback
203
+ onAfterMutate(patch);
204
+
205
+ return result;
206
+ };
207
+ };
208
+
209
+ // Wrap allowed methods
210
+ for (const method of allowList) {
211
+ if (mapMutableMethods.includes(method)) {
212
+ (methods as any)[method] = createWrappedMethod(method);
213
+ }
214
+ }
215
+
216
+ // Add target reference
217
+ Object.defineProperty(methods, 'target', {
218
+ get: () => target,
219
+ enumerable: false,
220
+ configurable: false
221
+ });
222
+
223
+ return methods as MapMutationMethods<K, V>;
224
+ };
225
+
226
+ export default wrapMapMethods;
@@ -0,0 +1,112 @@
1
+ /**
2
+ * @since Last modified: 2025/12/22 17:19:21
3
+ * Wraps Set objects with mutation tracking capabilities.
4
+ * Provides hooks for before/after mutation events and captures detailed context
5
+ * for undo/redo or change tracking purposes.
6
+ *
7
+ * @template T - Set element type
8
+ * @param {SetMutationOptions<T>} options - Configuration object containing target Set and callbacks
9
+ * @returns {SetMutationMethods<T>} - Object containing wrapped Set mutation methods
10
+ *
11
+ * @example
12
+ * // Basic usage with tracking
13
+ * const set = new Set([1, 2, 3]);
14
+ * const methods = wrapSet({
15
+ * target: set,
16
+ * onAfterMutate: (patch) => {
17
+ * console.log(`Set ${patch.method} called`, patch.context);
18
+ * }
19
+ * });
20
+ *
21
+ * methods.add(4); // Tracked
22
+ * methods.delete(2); // Tracked
23
+ * methods.clear(); // Tracked
24
+ *
25
+ * @example
26
+ * // With change detection for UI updates
27
+ * const set = new Set<string>();
28
+ * const methods = wrapSet({
29
+ * target: set,
30
+ * onAfterMutate: (patch) => {
31
+ * // Trigger UI update when Set changes
32
+ * if (patch.method === 'add' || patch.method === 'delete') {
33
+ * updateUI(Array.from(patch.target));
34
+ * }
35
+ * }
36
+ * });
37
+ */
38
+ 'use strict';
39
+ import setMutableMethods from "./setMutableMethods";
40
+ /**
41
+ * Creates wrapped mutation methods for Set with tracking capabilities
42
+ *
43
+ * @param options Configuration options
44
+ * @returns Object containing wrapped Set mutation methods
45
+ * @throws TypeError if target is not a Set
46
+ */
47
+ const wrapSetMethods = ({ target, onBeforeMutate = () => { }, onAfterMutate = () => { }, allowList = setMutableMethods, props = {}, }) => {
48
+ // Validation: Ensure target is a Set
49
+ if (!(target instanceof Set)) {
50
+ throw new TypeError("The 'target' parameter must be a Set.");
51
+ }
52
+ // Create method wrappers
53
+ const methods = {};
54
+ // Helper to create wrapped method
55
+ const createWrappedMethod = (method) => {
56
+ return function (...args) {
57
+ const context = {};
58
+ // Capture pre-mutation context based on method
59
+ switch (method) {
60
+ case 'add': {
61
+ const [value] = args;
62
+ context.addedItem = value;
63
+ //context.existed=true,说明值重复
64
+ context.existed = target.has(value);
65
+ break;
66
+ }
67
+ case 'delete': {
68
+ const [value] = args;
69
+ context.existed = target.has(value);
70
+ context.deletedItem = context.existed ? value : undefined;
71
+ break;
72
+ }
73
+ case 'clear': {
74
+ context.clearedItems = Array.from(target);
75
+ //用来做验证
76
+ context.previousSize = target.size;
77
+ break;
78
+ }
79
+ }
80
+ // Execute before mutation callback
81
+ onBeforeMutate(context);
82
+ // Execute the native Set method
83
+ const result = target[method].apply(target, args);
84
+ // Construct patch object
85
+ const patch = {
86
+ method,
87
+ result,
88
+ args,
89
+ context,
90
+ target,
91
+ ...props
92
+ };
93
+ // Execute after mutation callback
94
+ onAfterMutate(patch);
95
+ return result;
96
+ };
97
+ };
98
+ // Wrap allowed methods
99
+ for (const method of allowList) {
100
+ if (setMutableMethods.includes(method)) {
101
+ methods[method] = createWrappedMethod(method);
102
+ }
103
+ }
104
+ // Add target reference
105
+ Object.defineProperty(methods, 'target', {
106
+ get: () => target,
107
+ enumerable: false,
108
+ configurable: false
109
+ });
110
+ return methods;
111
+ };
112
+ export default wrapSetMethods;
@@ -0,0 +1,215 @@
1
+ /**
2
+ * @since Last modified: 2025/12/22 17:19:21
3
+ * Wraps Set objects with mutation tracking capabilities.
4
+ * Provides hooks for before/after mutation events and captures detailed context
5
+ * for undo/redo or change tracking purposes.
6
+ *
7
+ * @template T - Set element type
8
+ * @param {SetMutationOptions<T>} options - Configuration object containing target Set and callbacks
9
+ * @returns {SetMutationMethods<T>} - Object containing wrapped Set mutation methods
10
+ *
11
+ * @example
12
+ * // Basic usage with tracking
13
+ * const set = new Set([1, 2, 3]);
14
+ * const methods = wrapSet({
15
+ * target: set,
16
+ * onAfterMutate: (patch) => {
17
+ * console.log(`Set ${patch.method} called`, patch.context);
18
+ * }
19
+ * });
20
+ *
21
+ * methods.add(4); // Tracked
22
+ * methods.delete(2); // Tracked
23
+ * methods.clear(); // Tracked
24
+ *
25
+ * @example
26
+ * // With change detection for UI updates
27
+ * const set = new Set<string>();
28
+ * const methods = wrapSet({
29
+ * target: set,
30
+ * onAfterMutate: (patch) => {
31
+ * // Trigger UI update when Set changes
32
+ * if (patch.method === 'add' || patch.method === 'delete') {
33
+ * updateUI(Array.from(patch.target));
34
+ * }
35
+ * }
36
+ * });
37
+ */
38
+ 'use strict';
39
+
40
+ import setMutableMethods, { SetMutationNames } from "./setMutableMethods";
41
+
42
+ /**
43
+ * Context captured before Set mutation for tracking purposes
44
+ */
45
+ export interface SetMutationContext<T = any> {
46
+ /** For add method: the value being added */
47
+ addedItem?: T;
48
+ /** For add / delete method: whether the value already existed */
49
+ existed?: boolean;
50
+ /** For delete method: the value being deleted */
51
+ deletedItem?: T;
52
+ /** For clear method: snapshot of all values before clearing */
53
+ clearedItems?: T[];
54
+ /** For clear method: size of the Set before clearing */
55
+ previousSize?: number;
56
+ }
57
+
58
+ /**
59
+ * Data object passed to callback after Set mutation
60
+ */
61
+ export interface SetMutationPatch<T = any> {
62
+ /** The mutation method called */
63
+ method: SetMutationNames;
64
+ /** The result returned by the mutation method */
65
+ result: any;
66
+ /** Arguments passed to the mutation method */
67
+ args: any[];
68
+ /** Context captured before mutation */
69
+ context: SetMutationContext<T>;
70
+ /** Reference to the mutated Set */
71
+ target: Set<T>;
72
+ /** Additional custom properties */
73
+ [key: string]: any;
74
+ }
75
+
76
+ /**
77
+ * Configuration options for wrapSet function
78
+ */
79
+ export interface SetMutationOptions<T = any> {
80
+ /** The Set to wrap with mutation tracking */
81
+ target: Set<T>;
82
+ /** Callback triggered before mutation */
83
+ onBeforeMutate?: (context: SetMutationContext<T>) => void;
84
+ /** Callback triggered after mutation */
85
+ onAfterMutate?: (patch: SetMutationPatch<T>) => void;
86
+ /** Optional list of allowed mutation methods (default: all Set methods) */
87
+ allowList?: SetMutationNames[];
88
+ /** Additional properties to attach to the patch */
89
+ props?: Record<string, any>;
90
+ }
91
+
92
+ /**
93
+ * Wrapped mutation methods for Set
94
+ */
95
+ export interface SetMutationMethods<T = any> {
96
+ /**
97
+ * Adds a value to the Set.
98
+ * @param value The value to add
99
+ * @returns The Set object
100
+ */
101
+ add: (value: T) => Set<T>;
102
+
103
+ /**
104
+ * Deletes a value from the Set.
105
+ * @param value The value to delete
106
+ * @returns true if the value existed and has been removed, false otherwise
107
+ */
108
+ delete: (value: T) => boolean;
109
+
110
+ /**
111
+ * Clears all values from the Set.
112
+ * @returns void
113
+ */
114
+ clear: () => void;
115
+
116
+ /**
117
+ * Gets the original Set instance for direct access
118
+ */
119
+ readonly target: Set<T>;
120
+ }
121
+
122
+ /**
123
+ * Creates wrapped mutation methods for Set with tracking capabilities
124
+ *
125
+ * @param options Configuration options
126
+ * @returns Object containing wrapped Set mutation methods
127
+ * @throws TypeError if target is not a Set
128
+ */
129
+ const wrapSetMethods = <T = any>({
130
+ target,
131
+ onBeforeMutate = () => { },
132
+ onAfterMutate = () => { },
133
+ allowList = setMutableMethods,
134
+ props = {},
135
+ }: SetMutationOptions<T>): SetMutationMethods<T> => {
136
+
137
+ // Validation: Ensure target is a Set
138
+ if (!(target instanceof Set)) {
139
+ throw new TypeError("The 'target' parameter must be a Set.");
140
+ }
141
+
142
+ // Create method wrappers
143
+ const methods: Partial<SetMutationMethods<T>> = {};
144
+
145
+ // Helper to create wrapped method
146
+ const createWrappedMethod = (method: SetMutationNames) => {
147
+ return function (...args: any[]) {
148
+ const context: SetMutationContext<T> = {};
149
+
150
+ // Capture pre-mutation context based on method
151
+ switch (method) {
152
+ case 'add': {
153
+ const [value] = args as [T];
154
+ context.addedItem = value;
155
+ //context.existed=true,说明值重复
156
+ context.existed = target.has(value);
157
+ break;
158
+ }
159
+
160
+ case 'delete': {
161
+ const [value] = args as [T];
162
+ context.existed = target.has(value);
163
+ context.deletedItem = context.existed ? value : undefined;
164
+ break;
165
+ }
166
+
167
+ case 'clear': {
168
+ context.clearedItems = Array.from(target);
169
+ //用来做验证
170
+ context.previousSize = target.size;
171
+ break;
172
+ }
173
+ }
174
+
175
+ // Execute before mutation callback
176
+ onBeforeMutate(context);
177
+
178
+ // Execute the native Set method
179
+ const result = (target as any)[method].apply(target, args);
180
+
181
+ // Construct patch object
182
+ const patch: SetMutationPatch<T> = {
183
+ method,
184
+ result,
185
+ args,
186
+ context,
187
+ target,
188
+ ...props
189
+ };
190
+
191
+ // Execute after mutation callback
192
+ onAfterMutate(patch);
193
+
194
+ return result;
195
+ };
196
+ };
197
+
198
+ // Wrap allowed methods
199
+ for (const method of allowList) {
200
+ if (setMutableMethods.includes(method)) {
201
+ (methods as any)[method] = createWrappedMethod(method);
202
+ }
203
+ }
204
+
205
+ // Add target reference
206
+ Object.defineProperty(methods, 'target', {
207
+ get: () => target,
208
+ enumerable: false,
209
+ configurable: false
210
+ });
211
+
212
+ return methods as SetMutationMethods<T>;
213
+ };
214
+
215
+ export default wrapSetMethods;