@@ -58,7 +58,7 @@ export class StateStore<T extends Record<string, unknown>> {
58
58
public getLatestValue ( ) : T {
59
59
return this . value ;
60
60
}
61
-
61
+
62
62
public subscribe ( handler : Handler < T > ) : Unsubscribe {
63
63
handler ( this . value , undefined ) ;
64
64
this . handlers . add ( handler ) ;
@@ -107,6 +107,19 @@ export class StateStore<T extends Record<string, unknown>> {
107
107
}
108
108
}
109
109
110
+ /**
111
+ * Represents a merged state store that combines two separate state stores into one.
112
+ *
113
+ * The MergedStateStore allows combining two stores with non-overlapping keys.
114
+ * It extends StateStore with the combined type of both source stores.
115
+ * Changes to either the original or merged store will propagate to the combined store.
116
+ *
117
+ * Note: Direct mutations (next, partialNext, registerModifier) are disabled on the merged store.
118
+ * You should instead call these methods on the original or merged stores.
119
+ *
120
+ * @template O The type of the original state store
121
+ * @template M The type of the merged state store
122
+ */
110
123
class MergedStateStore <
111
124
O extends Record < string , unknown > ,
112
125
M extends Record < string , unknown > ,
@@ -132,6 +145,21 @@ class MergedStateStore<
132
145
this . merged = merged ;
133
146
}
134
147
148
+ /**
149
+ * Subscribes to changes in the merged state store.
150
+ *
151
+ * This method extends the base subscribe functionality to handle the merged nature of this store:
152
+ * 1. The first subscriber triggers registration of helper subscribers that listen to both source stores
153
+ * 2. Changes from either source store are propagated to this merged store
154
+ * 3. Source store values are cached to prevent unnecessary updates
155
+ *
156
+ * When the first subscriber is added, the method sets up listeners on both original and merged stores.
157
+ * These listeners update the combined store value whenever either source store changes.
158
+ * All subscriptions (helpers and the actual handler) are tracked so they can be properly cleaned up.
159
+ *
160
+ * @param handler - The callback function that will be executed when the state changes
161
+ * @returns An unsubscribe function that, when called, removes the subscription and any helper subscriptions
162
+ */
135
163
public subscribe ( handler : Handler < O & M > ) {
136
164
const unsubscribeFunctions : Unsubscribe [ ] = [ ] ;
137
165
@@ -169,6 +197,24 @@ class MergedStateStore<
169
197
} ;
170
198
}
171
199
200
+ /**
201
+ * Retrieves the latest combined state from both original and merged stores.
202
+ *
203
+ * This method extends the base getLatestValue functionality to ensure the merged store
204
+ * remains in sync with its source stores even when there are no active subscribers.
205
+ *
206
+ * When there are no handlers registered, the method:
207
+ * 1. Fetches the latest values from both source stores
208
+ * 2. Compares them with the cached values to detect changes
209
+ * 3. If changes are detected, updates the internal value and caches
210
+ * the new source values to maintain consistency
211
+ *
212
+ * This approach ensures that calling getLatestValue() always returns the most
213
+ * up-to-date combined state, even if the merged store hasn't been actively
214
+ * receiving updates through subscriptions.
215
+ *
216
+ * @returns The latest combined state from both original and merged stores
217
+ */
172
218
public getLatestValue ( ) {
173
219
// if there are no handlers registered to MergedStore then the local value might be out-of-sync
174
220
// pull latest and compare against cached - if they differ, cache latest and produce new combined
0 commit comments