@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 +30 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +7 -1
- package/package.json +1 -1
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>,
|
|
103
|
-
enabled: boolean
|
|
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
|
});
|