@ptolemy2002/immutability-utils 1.0.0 → 1.1.0

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/README.md CHANGED
@@ -9,6 +9,7 @@ A TypeScript library that wraps mutable classes and makes them immutable using p
9
9
  - **Type-Safe**: Full TypeScript support with proper type inference
10
10
  - **Efficient**: Groups multiple mutations within a single method call into one clone operation
11
11
  - **Toggle Support**: Can temporarily disable immutability when needed
12
+ - **Clone Listeners**: Register callbacks that execute whenever a clone operation occurs
12
13
 
13
14
  ## Installation
14
15
 
@@ -81,6 +82,29 @@ dataRef.current.someProperty = "mutated in place"; // No clone created
81
82
  dataRef.enabled = true;
82
83
  ```
83
84
 
85
+ #### Clone Listeners
86
+
87
+ You can register listeners that will be called whenever a clone operation occurs. This is useful for tracking changes, updating UI, or triggering side effects.
88
+
89
+ ```typescript
90
+ const counterRef = immutable(new Counter(0));
91
+
92
+ // Add a listener that logs whenever a clone occurs
93
+ counterRef.cloneListeners.push((imRef) => {
94
+ console.log('Clone occurred! New value:', imRef.current.value);
95
+ });
96
+
97
+ // This will trigger the listener
98
+ counterRef.current.increment(5); // Logs: "Clone occurred! New value: 5"
99
+ counterRef.current.increment(3); // Logs: "Clone occurred! New value: 8"
100
+ ```
101
+
102
+ **Use Cases for Clone Listeners:**
103
+ - Triggering React state updates when working with immutable data structures
104
+ - Logging or debugging mutation operations
105
+ - Synchronizing changes to external systems
106
+ - Implementing undo/redo functionality
107
+
84
108
  ## API Reference
85
109
 
86
110
  ### Types
@@ -99,8 +123,9 @@ A reference object containing the current immutable instance and an enabled flag
99
123
 
100
124
  ```typescript
101
125
  type ImmutableRef<T=object> = {
102
- current: Cloneable<T>, // The current instance
103
- enabled: boolean // Whether immutability is enabled
126
+ current: Cloneable<T>, // The current instance
127
+ enabled: boolean, // Whether immutability is enabled
128
+ cloneListeners: Array<(imRef: ImmutableRef<T>) => void> // Callbacks invoked on clone
104
129
  };
105
130
  ```
106
131
 
@@ -117,6 +142,7 @@ Creates an immutable reference wrapper around the provided object.
117
142
  - An `ImmutableRef<T>` object containing:
118
143
  - `current`: The proxied instance (initially the object you passed in)
119
144
  - `enabled`: A boolean flag (initially `true`) that controls whether immutability is active
145
+ - `cloneListeners`: An empty array (initially `[]`) where you can register listener callbacks
120
146
 
121
147
  **Example:**
122
148
  ```typescript
@@ -133,6 +159,7 @@ console.log(ref.enabled); // true
133
159
  - Sets the property on the clone
134
160
  - Re-enables immutability
135
161
  - Updates `current` to point to the new clone
162
+ - Invokes all registered clone listeners
136
163
 
137
164
  2. **Method Calls**: When you call a method (except `clone()`), the library:
138
165
  - Clones the object
@@ -140,6 +167,7 @@ console.log(ref.enabled); // true
140
167
  - Calls the method on the clone
141
168
  - Re-enables immutability
142
169
  - Updates `current` to point to the new clone
170
+ - Invokes all registered clone listeners
143
171
  - Returns the method's result
144
172
 
145
173
  3. **Read Operations**: Property reads and getters do not trigger cloning and return the value directly.
package/dist/index.d.ts CHANGED
@@ -5,5 +5,6 @@ export type Cloneable<T = object> = Override<T, {
5
5
  export type ImmutableRef<T = object> = {
6
6
  current: Cloneable<T>;
7
7
  enabled: boolean;
8
+ cloneListeners: Array<(imRef: ImmutableRef<T>) => void>;
8
9
  };
9
10
  export declare function immutable<T>(obj: Cloneable<T>): ImmutableRef<T>;
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.immutable = immutable;
7
7
  const is_callable_1 = __importDefault(require("is-callable"));
8
8
  function immutable(obj) {
9
- const imRef = { current: obj, enabled: true };
9
+ const imRef = { current: obj, enabled: true, cloneListeners: [] };
10
10
  // Wrap in a Proxy to override mutations
11
11
  function applyProxy(target) {
12
12
  return new Proxy(target, {
@@ -28,6 +28,9 @@ function immutable(obj) {
28
28
  // Sync the reference to the new cloned object
29
29
  // and reapply the proxy
30
30
  imRef.current = applyProxy(cloned);
31
+ for (const listener of imRef.cloneListeners) {
32
+ listener(imRef);
33
+ }
31
34
  return result;
32
35
  };
33
36
  }
@@ -47,6 +50,9 @@ function immutable(obj) {
47
50
  // Sync the reference to the new cloned object
48
51
  // and reapply the proxy
49
52
  imRef.current = applyProxy(cloned);
53
+ for (const listener of imRef.cloneListeners) {
54
+ listener(imRef);
55
+ }
50
56
  return result;
51
57
  }
52
58
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ptolemy2002/immutability-utils",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "private": false,
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",