@codady/utils 0.0.8 → 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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @since Last modified: 2025/12/19 10:14:03
2
+ * @since Last modified: 2025/12/22 17:14:00
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.
@@ -18,7 +18,7 @@
18
18
  * methods.push(4); // arr is now [1, 2, 3, 4]
19
19
  */
20
20
  'use strict';
21
- import mutableMethods from "./mutableMethods";
21
+ import arrayMutableMethods from "./arrayMutableMethods";
22
22
  const wrapArrayMethods = ({ target, onBeforeMutate = () => { }, onAfterMutate = () => { }, allowList, props = {}, }) => {
23
23
  // Validation: Ensure target is an array and method is allowed
24
24
  if (!Array.isArray(target)) {
@@ -26,7 +26,7 @@ const wrapArrayMethods = ({ target, onBeforeMutate = () => { }, onAfterMutate =
26
26
  }
27
27
  //使用默认
28
28
  if (!allowList || allowList?.length) {
29
- allowList = mutableMethods;
29
+ allowList = arrayMutableMethods;
30
30
  }
31
31
  const methods = {};
32
32
  for (let method of allowList) {
@@ -42,10 +42,10 @@ const wrapArrayMethods = ({ target, onBeforeMutate = () => { }, onAfterMutate =
42
42
  context.addedItems = [...args];
43
43
  break;
44
44
  case 'pop':
45
- context.poppedValue = target[len - 1];
45
+ context.poppedItem = target[len - 1];
46
46
  break;
47
47
  case 'shift':
48
- context.shiftedValue = target[0];
48
+ context.shiftedItem = target[0];
49
49
  break;
50
50
  case 'splice':
51
51
  const [s, d] = args,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @since Last modified: 2025/12/19 10:14:03
2
+ * @since Last modified: 2025/12/22 17:14:00
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.
@@ -19,7 +19,7 @@
19
19
  */
20
20
  'use strict';
21
21
 
22
- import mutableMethods, { ArrayMutationNames } from "./mutableMethods";
22
+ import arrayMutableMethods, { ArrayMutationNames } from "./arrayMutableMethods";
23
23
 
24
24
 
25
25
  /**
@@ -27,8 +27,8 @@ import mutableMethods, { ArrayMutationNames } from "./mutableMethods";
27
27
  */
28
28
  export interface MutationContextt {
29
29
  addedItems?: any[]; // Items added to the array
30
- poppedValue?: any; // Value popped from the array
31
- shiftedValue?: any; // Value shifted from the array
30
+ poppedItem?: any; // Value popped from the array
31
+ shiftedItem?: any; // Value shifted from the array
32
32
  deletedItems?: any[]; // Items removed from the array
33
33
  oldSnapshot?: any[]; // Snapshot of the array before methods like 'sort' or 'reverse'
34
34
  oldItems?: any[]; // Items overwritten (for methods like 'fill' or 'copyWithin')
@@ -87,7 +87,7 @@ const wrapArrayMethods = <T = any>({
87
87
  }
88
88
  //使用默认
89
89
  if (!allowList || allowList?.length) {
90
- allowList = mutableMethods;
90
+ allowList = arrayMutableMethods;
91
91
  }
92
92
 
93
93
  const methods: Partial<ArrayMutationMethods<T>> = {};
@@ -109,10 +109,10 @@ const wrapArrayMethods = <T = any>({
109
109
  context.addedItems = [...args];
110
110
  break;
111
111
  case 'pop':
112
- context.poppedValue = target[len - 1];
112
+ context.poppedItem = target[len - 1];
113
113
  break;
114
114
  case 'shift':
115
- context.shiftedValue = target[0];
115
+ context.shiftedItem = target[0];
116
116
  break;
117
117
  case 'splice':
118
118
  const [s, d] = args,
@@ -0,0 +1,119 @@
1
+ /**
2
+ * @since Last modified: 2025/12/22 16:37:23
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
+ * Available Map mutation methods
45
+ */
46
+ export const mapMutableMethods = ['set', 'delete', 'clear'];
47
+ /**
48
+ * Creates wrapped mutation methods for Map with tracking capabilities
49
+ *
50
+ * @param options Configuration options
51
+ * @returns Object containing wrapped Map mutation methods
52
+ * @throws TypeError if target is not a Map
53
+ */
54
+ const wrapMap = ({ target, onBeforeMutate = () => { }, onAfterMutate = () => { }, allowList = mapMutableMethods, props = {}, }) => {
55
+ // Validation: Ensure target is a Map
56
+ if (!(target instanceof Map)) {
57
+ throw new TypeError("The 'target' parameter must be a Map.");
58
+ }
59
+ // Create method wrappers
60
+ const methods = {};
61
+ // Helper to create wrapped method
62
+ const createWrappedMethod = (method) => {
63
+ return function (...args) {
64
+ const context = {};
65
+ // Capture pre-mutation context based on method
66
+ switch (method) {
67
+ case 'set': {
68
+ const [key, newValue] = args;
69
+ context.key = key;
70
+ context.newValue = newValue;
71
+ context.hadKey = target.has(key);
72
+ context.oldValue = context.hadKey ? target.get(key) : undefined;
73
+ break;
74
+ }
75
+ case 'delete': {
76
+ const [key] = args;
77
+ context.key = key;
78
+ context.existed = target.has(key);
79
+ break;
80
+ }
81
+ case 'clear': {
82
+ context.clearedEntries = Array.from(target.entries());
83
+ context.previousSize = target.size;
84
+ break;
85
+ }
86
+ }
87
+ // Execute before mutation callback
88
+ onBeforeMutate(context);
89
+ // Execute the native Map method
90
+ const result = target[method].apply(target, args);
91
+ // Construct patch object
92
+ const patch = {
93
+ method,
94
+ result,
95
+ args,
96
+ context,
97
+ target,
98
+ ...props
99
+ };
100
+ // Execute after mutation callback
101
+ onAfterMutate(patch);
102
+ return result;
103
+ };
104
+ };
105
+ // Wrap allowed methods
106
+ for (const method of allowList) {
107
+ if (mapMutableMethods.includes(method)) {
108
+ methods[method] = createWrappedMethod(method);
109
+ }
110
+ }
111
+ // Add target reference
112
+ Object.defineProperty(methods, 'target', {
113
+ get: () => target,
114
+ enumerable: false,
115
+ configurable: false
116
+ });
117
+ return methods;
118
+ };
119
+ export default wrapMap;
@@ -0,0 +1,118 @@
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
+ import mapMutableMethods from "./mapMutableMethods";
44
+ /**
45
+ * Creates wrapped mutation methods for Map with tracking capabilities
46
+ *
47
+ * @param options Configuration options
48
+ * @returns Object containing wrapped Map mutation methods
49
+ * @throws TypeError if target is not a Map
50
+ */
51
+ const wrapMapMethods = ({ target, onBeforeMutate = () => { }, onAfterMutate = () => { }, allowList = mapMutableMethods, props = {}, }) => {
52
+ // Validation: Ensure target is a Map
53
+ if (!(target instanceof Map)) {
54
+ throw new TypeError("The 'target' parameter must be a Map.");
55
+ }
56
+ // Create method wrappers
57
+ const methods = {};
58
+ // Helper to create wrapped method
59
+ const createWrappedMethod = (method) => {
60
+ return function (...args) {
61
+ const context = {};
62
+ // Capture pre-mutation context based on method
63
+ switch (method) {
64
+ case 'set': {
65
+ const [key, newValue] = args;
66
+ context.key = key;
67
+ context.newValue = newValue;
68
+ context.existed = target.has(key);
69
+ context.oldValue = context.existed ? target.get(key) : undefined;
70
+ break;
71
+ }
72
+ case 'delete': {
73
+ const [key] = args;
74
+ context.key = key;
75
+ context.existed = target.has(key);
76
+ context.value = context.existed ? target.get(key) : undefined;
77
+ break;
78
+ }
79
+ case 'clear': {
80
+ context.clearedItems = Array.from(target.entries());
81
+ //用来做验证
82
+ context.previousSize = target.size;
83
+ break;
84
+ }
85
+ }
86
+ // Execute before mutation callback
87
+ onBeforeMutate(context);
88
+ // Execute the native Map method
89
+ const result = target[method].apply(target, args);
90
+ // Construct patch object
91
+ const patch = {
92
+ method,
93
+ result,
94
+ args,
95
+ context,
96
+ target,
97
+ ...props
98
+ };
99
+ // Execute after mutation callback
100
+ onAfterMutate(patch);
101
+ return result;
102
+ };
103
+ };
104
+ // Wrap allowed methods
105
+ for (const method of allowList) {
106
+ if (mapMutableMethods.includes(method)) {
107
+ methods[method] = createWrappedMethod(method);
108
+ }
109
+ }
110
+ // Add target reference
111
+ Object.defineProperty(methods, 'target', {
112
+ get: () => target,
113
+ enumerable: false,
114
+ configurable: false
115
+ });
116
+ return methods;
117
+ };
118
+ export default wrapMapMethods;
@@ -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;