@asaidimu/utils-store 10.2.4 → 10.2.5
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/index.d.cts +1269 -0
- package/index.d.ts +856 -968
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/package.json +2 -1
- package/index.d.mts +0 -1213
package/index.d.ts
CHANGED
|
@@ -1,74 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
interface EventBus<TEventMap extends Record<string, any>> {
|
|
6
|
-
/**
|
|
7
|
-
* Subscribes to a specific event by name.
|
|
8
|
-
* @param eventName - The name of the event to subscribe to.
|
|
9
|
-
* @param callback - The function to call when the event is emitted.
|
|
10
|
-
* @param options - Extra options to determine the behaviour of the
|
|
11
|
-
* subscription
|
|
12
|
-
* @returns A function to unsubscribe from the event.
|
|
13
|
-
*/
|
|
14
|
-
subscribe<TEventName extends keyof TEventMap | "*">(eventName: TEventName, callback: TEventName extends "*" ? (payload: TEventMap[keyof TEventMap], event: keyof TEventMap) => void : (payload: TEventMap[TEventName]) => void, options?: SubscribeOptions): () => void;
|
|
15
|
-
/**
|
|
16
|
-
* Subscribes to an event and automatically unsubscribes after it fires once.
|
|
17
|
-
* @param eventName - The name of the event to subscribe to.
|
|
18
|
-
* @param callback - The function to call when the event is emitted.
|
|
19
|
-
* @returns A function to cancel the one-shot subscription before it fires.
|
|
20
|
-
*/
|
|
21
|
-
once<TEventName extends keyof TEventMap | "*">(eventName: TEventName, callback: TEventName extends "*" ? (payload: TEventMap[keyof TEventMap], event: keyof TEventMap) => void : (payload: TEventMap[TEventName]) => void, options?: SubscribeOptions): () => void;
|
|
22
|
-
/**
|
|
23
|
-
* Emits an event with a payload to all subscribed listeners.
|
|
24
|
-
* @param event - An object containing the event name and payload.
|
|
25
|
-
*/
|
|
26
|
-
emit: <TEventName extends keyof TEventMap>(event: {
|
|
27
|
-
name: TEventName;
|
|
28
|
-
payload: TEventMap[TEventName];
|
|
29
|
-
}) => void;
|
|
30
|
-
/**
|
|
31
|
-
* Retrieves metrics about event bus usage.
|
|
32
|
-
* @returns An object containing various metrics.
|
|
33
|
-
*/
|
|
34
|
-
metrics: () => EventMetrics;
|
|
35
|
-
/**
|
|
36
|
-
* Clears all subscriptions and resets metrics.
|
|
37
|
-
*
|
|
38
|
-
* After calling `clear()`, the bus is fully reset and can be reused
|
|
39
|
-
* cross-tab communication is re-established if it was previously enabled.
|
|
40
|
-
*
|
|
41
|
-
* @param options - Optional configuration object.
|
|
42
|
-
* @param options.permanent - If `true`, the bus becomes permanently unusable after clearing.
|
|
43
|
-
* Defaults to `false`.
|
|
44
|
-
* @returns {void}
|
|
45
|
-
*/
|
|
46
|
-
clear: (options?: {
|
|
47
|
-
permanent?: boolean;
|
|
48
|
-
}) => void;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Interface defining the metrics tracked by the EventBus.
|
|
52
|
-
*/
|
|
53
|
-
interface EventMetrics {
|
|
54
|
-
/** Total number of events emitted (both sync and deferred paths). */
|
|
55
|
-
totalEvents: number;
|
|
56
|
-
/** Number of active subscriptions across all event names. */
|
|
57
|
-
activeSubscriptions: number;
|
|
58
|
-
/** Map of event names to their emission counts. */
|
|
59
|
-
eventCounts: Map<string, number>;
|
|
60
|
-
/** Average duration of event dispatch in milliseconds. */
|
|
61
|
-
averageEmitDuration: number;
|
|
62
|
-
}
|
|
63
|
-
interface SubscribeOptions {
|
|
64
|
-
/**
|
|
65
|
-
* Debounce delay in milliseconds. When multiple events arrive in quick
|
|
66
|
-
* succession, the callback runs only after the quiet period ends, using the
|
|
67
|
-
* latest payload. Default = no debouncing.
|
|
68
|
-
*/
|
|
69
|
-
debounce?: number;
|
|
70
|
-
}
|
|
1
|
+
import { EventBus, SubscribeOptions, SubscribeOptions as SubscribeOptions$1 } from "@asaidimu/utils-events";
|
|
2
|
+
import { SystemLogger } from "@asaidimu/utils-logger";
|
|
3
|
+
import { SimplePersistence } from "@asaidimu/utils-persistence";
|
|
4
|
+
import { SimplePersistence as SimplePersistence$1 } from "@asaidimu/utils-persistence/types.ts";
|
|
71
5
|
|
|
6
|
+
//#region src/store/types.d.ts
|
|
72
7
|
/**
|
|
73
8
|
* Utility type for representing partial updates to the state, allowing deep nesting.
|
|
74
9
|
* It makes all properties optional and applies the same transformation recursively
|
|
@@ -76,64 +11,62 @@ interface SubscribeOptions {
|
|
|
76
11
|
* preserving the original structure. It also includes the original type T and
|
|
77
12
|
* undefined as possibilities for the top level and nested values.
|
|
78
13
|
*/
|
|
79
|
-
type DeepPartial<T> = T extends object ? T extends readonly (infer U)[] ? readonly (DeepPartial<U> | undefined)[] | undefined | T : T extends (infer U)[] ? (DeepPartial<U> | undefined)[] | undefined | T : {
|
|
80
|
-
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> | undefined : T[K] | undefined;
|
|
81
|
-
} | undefined | T : T | undefined | symbol;
|
|
14
|
+
type DeepPartial<T> = T extends object ? T extends readonly (infer U)[] ? readonly (DeepPartial<U> | undefined)[] | undefined | T : T extends (infer U)[] ? (DeepPartial<U> | undefined)[] | undefined | T : { [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> | undefined : T[K] | undefined } | undefined | T : T | undefined | symbol;
|
|
82
15
|
/**
|
|
83
16
|
* Interface for performance and execution metrics of the state store.
|
|
84
17
|
*/
|
|
85
18
|
interface StoreMetrics {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
19
|
+
/** The number of times the state has been successfully updated. */
|
|
20
|
+
updateCount: number;
|
|
21
|
+
/** The total number of listener functions executed in response to state changes. */
|
|
22
|
+
listenerExecutions: number;
|
|
23
|
+
/** The average time taken for a state update process to complete (in milliseconds). */
|
|
24
|
+
averageUpdateTime: number;
|
|
25
|
+
/** The size (e.g., number of paths changed) of the largest single state update. */
|
|
26
|
+
largestUpdateSize: number;
|
|
27
|
+
/** List of state paths that trigger the most listener executions. */
|
|
28
|
+
mostActiveListenerPaths: string[];
|
|
29
|
+
/** The total number of update attempts (including blocked ones). */
|
|
30
|
+
totalUpdates: number;
|
|
31
|
+
/** The number of updates that were blocked by blocking middleware. */
|
|
32
|
+
blockedUpdates: number;
|
|
33
|
+
/** The average duration of a state update cycle (in milliseconds). */
|
|
34
|
+
averageUpdateDuration: number;
|
|
35
|
+
/** The total number of middleware functions executed. */
|
|
36
|
+
middlewareExecutions: number;
|
|
37
|
+
/** The total number of transactions initiated. */
|
|
38
|
+
transactionCount: number;
|
|
39
|
+
/** The total number of store events fired. */
|
|
40
|
+
totalEventsFired: number;
|
|
41
|
+
/** The total number of actions dispatched. */
|
|
42
|
+
totalActionsDispatched: number;
|
|
43
|
+
/** The total number of actions that completed successfully. */
|
|
44
|
+
totalActionsSucceeded: number;
|
|
45
|
+
/** The total number of actions that failed with an error. */
|
|
46
|
+
totalActionsFailed: number;
|
|
47
|
+
/** The average duration of an action execution (in milliseconds). */
|
|
48
|
+
averageActionDuration: number;
|
|
116
49
|
}
|
|
117
50
|
/**
|
|
118
51
|
* Extended store state for monitoring the current execution status (e.g., if an update is in progress).
|
|
119
52
|
*/
|
|
120
53
|
interface StoreExecutionState<T> {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
54
|
+
/** Indicates if a state update process is currently executing. */
|
|
55
|
+
executing: boolean;
|
|
56
|
+
/** The changes (DeepPartial) currently being processed in the execution cycle. Null if none. */
|
|
57
|
+
changes: DeepPartial<T> | null;
|
|
58
|
+
/** A queue of pending state update functions/objects to be applied sequentially. */
|
|
59
|
+
pendingChanges: Array<StateUpdater<T>>;
|
|
60
|
+
/** Names of all currently registered middlewares. */
|
|
61
|
+
middlewares: string[];
|
|
62
|
+
/** Details of the middleware currently running. Null if none. */
|
|
63
|
+
runningMiddleware: {
|
|
64
|
+
id: string;
|
|
65
|
+
name: string;
|
|
66
|
+
startTime: number;
|
|
67
|
+
} | null;
|
|
68
|
+
/** Indicates if the store is currently within an active transaction block. */
|
|
69
|
+
transactionActive: boolean;
|
|
137
70
|
}
|
|
138
71
|
/**
|
|
139
72
|
* Event types emitted by the state store for observability and debugging.
|
|
@@ -143,101 +76,92 @@ type StoreEvent = "update:start" | "update:complete" | "middleware:start" | "mid
|
|
|
143
76
|
* Payload for the 'selector:changed' event.
|
|
144
77
|
*/
|
|
145
78
|
interface SelectorChangedPayload<S> {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
79
|
+
/** Unique identifier of the selector. */
|
|
80
|
+
selectorId: string;
|
|
81
|
+
/** The new computed result of the selector. */
|
|
82
|
+
newResult: S;
|
|
83
|
+
/** Timestamp of when the change occurred. */
|
|
84
|
+
timestamp: number;
|
|
152
85
|
}
|
|
153
86
|
/**
|
|
154
87
|
* Maps each `StoreEvent` type to its corresponding event payload interface.
|
|
155
88
|
* Uses conditional types to ensure type safety for event listeners.
|
|
156
89
|
*/
|
|
157
|
-
type StoreEvents = {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
/** True if the update was blocked by a middleware. */
|
|
170
|
-
blocked?: boolean;
|
|
171
|
-
/** Any error that occurred during the update. */
|
|
172
|
-
error?: any;
|
|
173
|
-
} : K extends "selector:accessed" ? SelectorAccessedPayload : K extends "selector:changed" ? SelectorChangedPayload<any> : K extends "action:start" ? ActionStartPayload : K extends "action:complete" ? ActionCompletePayload : K extends "action:error" ? ActionErrorPayload : K extends "middleware:start" | "middleware:complete" | "middleware:error" | "middleware:blocked" | "middleware:executed" ? MiddlewareExecution : K extends "transaction:start" | "transaction:complete" | "transaction:error" ? {
|
|
174
|
-
transactionId: string;
|
|
175
|
-
timestamp: number;
|
|
176
|
-
} : K extends "persistence:queued" ? PersistenceQueuedPayload : K extends "persistence:success" ? PersistenceSuccessPayload : K extends "persistence:retry" ? PersistenceRetryPayload : K extends "persistence:failed" ? PersistenceFailedPayload : K extends "persistence:queue_cleared" ? PersistenceQueueClearedPayload : K extends "persistence:init_error" ? PersistenceInitErrorPayload : any;
|
|
177
|
-
};
|
|
90
|
+
type StoreEvents = { [K in StoreEvent]: K extends "update:complete" ? {
|
|
91
|
+
/** List of state changes (deltas) applied in the update. */deltas: StateDelta[]; /** Total duration of the update process (in milliseconds). */
|
|
92
|
+
duration: number; /** Timestamp of the update completion. */
|
|
93
|
+
timestamp: number; /** Optional ID of the action that triggered the update. */
|
|
94
|
+
actionId?: string; /** The resulting new state after the update (may be a partial/transformed state). */
|
|
95
|
+
newState: any; /** True if the update was blocked by a middleware. */
|
|
96
|
+
blocked?: boolean; /** Any error that occurred during the update. */
|
|
97
|
+
error?: any;
|
|
98
|
+
} : K extends "selector:accessed" ? SelectorAccessedPayload : K extends "selector:changed" ? SelectorChangedPayload<any> : K extends "action:start" ? ActionStartPayload : K extends "action:complete" ? ActionCompletePayload : K extends "action:error" ? ActionErrorPayload : K extends "middleware:start" | "middleware:complete" | "middleware:error" | "middleware:blocked" | "middleware:executed" ? MiddlewareExecution : K extends "transaction:start" | "transaction:complete" | "transaction:error" ? {
|
|
99
|
+
transactionId: string;
|
|
100
|
+
timestamp: number;
|
|
101
|
+
} : K extends "persistence:queued" ? PersistenceQueuedPayload : K extends "persistence:success" ? PersistenceSuccessPayload : K extends "persistence:retry" ? PersistenceRetryPayload : K extends "persistence:failed" ? PersistenceFailedPayload : K extends "persistence:queue_cleared" ? PersistenceQueueClearedPayload : K extends "persistence:init_error" ? PersistenceInitErrorPayload : any };
|
|
178
102
|
/**
|
|
179
103
|
* Payload for the 'selector:accessed' event.
|
|
180
104
|
*/
|
|
181
105
|
interface SelectorAccessedPayload {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
106
|
+
/** Unique identifier of the selector. */
|
|
107
|
+
selectorId: string;
|
|
108
|
+
/** List of state paths accessed during the selector computation. */
|
|
109
|
+
accessedPaths: string[];
|
|
110
|
+
/** Duration of the selector computation (in milliseconds). */
|
|
111
|
+
duration: number;
|
|
112
|
+
/** Timestamp of the access. */
|
|
113
|
+
timestamp: number;
|
|
190
114
|
}
|
|
191
115
|
/**
|
|
192
116
|
* Payload for the 'action:start' event.
|
|
193
117
|
*/
|
|
194
118
|
interface ActionStartPayload {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
119
|
+
/** Unique identifier for the action execution. */
|
|
120
|
+
actionId: string;
|
|
121
|
+
/** Name of the action function. */
|
|
122
|
+
name: string;
|
|
123
|
+
/** The parameters passed to the action function. */
|
|
124
|
+
params: any[];
|
|
125
|
+
/** Timestamp of when the action execution started. */
|
|
126
|
+
timestamp: number;
|
|
203
127
|
}
|
|
204
128
|
/**
|
|
205
129
|
* Payload for the 'action:complete' event (successful action execution).
|
|
206
130
|
*/
|
|
207
131
|
interface ActionCompletePayload {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
132
|
+
/** Unique identifier for the action execution. */
|
|
133
|
+
actionId: string;
|
|
134
|
+
/** Name of the action function. */
|
|
135
|
+
name: string;
|
|
136
|
+
/** The parameters passed to the action function. */
|
|
137
|
+
params: any[];
|
|
138
|
+
/** Timestamp of when the action execution started. */
|
|
139
|
+
startTime: number;
|
|
140
|
+
/** Timestamp of when the action execution completed. */
|
|
141
|
+
endTime: number;
|
|
142
|
+
/** Total duration of the action execution (in milliseconds). */
|
|
143
|
+
duration: number;
|
|
144
|
+
/** The result returned by the action function. */
|
|
145
|
+
result: any;
|
|
222
146
|
}
|
|
223
147
|
/**
|
|
224
148
|
* Payload for the 'action:error' event (failed action execution).
|
|
225
149
|
*/
|
|
226
150
|
interface ActionErrorPayload {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
151
|
+
/** Unique identifier for the action execution. */
|
|
152
|
+
actionId: string;
|
|
153
|
+
/** Name of the action function. */
|
|
154
|
+
name: string;
|
|
155
|
+
/** The parameters passed to the action function. */
|
|
156
|
+
params: any[];
|
|
157
|
+
/** Timestamp of when the action execution started. */
|
|
158
|
+
startTime: number;
|
|
159
|
+
/** Timestamp of when the action execution ended (with error). */
|
|
160
|
+
endTime: number;
|
|
161
|
+
/** Total duration of the action execution (in milliseconds). */
|
|
162
|
+
duration: number;
|
|
163
|
+
/** The error object. */
|
|
164
|
+
error: any;
|
|
241
165
|
}
|
|
242
166
|
/**
|
|
243
167
|
* Type for a generic middleware function.
|
|
@@ -249,33 +173,33 @@ type Middleware<T> = (state: T, update: DeepPartial<T>) => Promise<DeepPartial<T
|
|
|
249
173
|
* Middleware execution information for event emissions and tracking.
|
|
250
174
|
*/
|
|
251
175
|
interface MiddlewareExecution {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
176
|
+
/** Unique identifier for the middleware instance. */
|
|
177
|
+
id: string;
|
|
178
|
+
/** Name of the middleware. */
|
|
179
|
+
name: string;
|
|
180
|
+
/** Timestamp of when the middleware execution started. */
|
|
181
|
+
startTime: number;
|
|
182
|
+
/** Timestamp of when the middleware execution completed. */
|
|
183
|
+
endTime: number;
|
|
184
|
+
/** Total duration of the middleware execution (in milliseconds). */
|
|
185
|
+
duration: number;
|
|
186
|
+
/** True if the middleware blocked the update. */
|
|
187
|
+
blocked: boolean;
|
|
188
|
+
/** Error object if the middleware failed. */
|
|
189
|
+
error?: Error;
|
|
190
|
+
/** List of state changes (deltas) that resulted from this middleware's transformation. */
|
|
191
|
+
deltas: StateDelta[];
|
|
268
192
|
}
|
|
269
193
|
/**
|
|
270
194
|
* Represents a single change to the state, detailing the path, old value, and new value.
|
|
271
195
|
*/
|
|
272
196
|
interface StateDelta {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
197
|
+
/** Dot-separated path to the changed property (e.g., "user.profile.name"). */
|
|
198
|
+
path: string;
|
|
199
|
+
/** The value of the property *before* the update. */
|
|
200
|
+
oldValue: any;
|
|
201
|
+
/** The value of the property *after* the update. */
|
|
202
|
+
newValue: any;
|
|
279
203
|
}
|
|
280
204
|
/**
|
|
281
205
|
* Represents a state update, which can be:
|
|
@@ -303,333 +227,281 @@ type TransformMiddleware<T> = (state: T, changes: DeepPartial<T>) => Promise<Dee
|
|
|
303
227
|
* It returns a boolean or an object containing a `block` boolean and an optional `error`.
|
|
304
228
|
*/
|
|
305
229
|
type BlockingMiddleware<T> = (state: T, changes: DeepPartial<T>) => Promise<boolean | {
|
|
306
|
-
|
|
307
|
-
|
|
230
|
+
block: boolean;
|
|
231
|
+
error?: Error;
|
|
308
232
|
}> | boolean | {
|
|
309
|
-
|
|
310
|
-
|
|
233
|
+
block: boolean;
|
|
234
|
+
error?: Error;
|
|
311
235
|
};
|
|
312
236
|
/**
|
|
313
237
|
* Type representing the configuration object passed to the `use` method to register a middleware.
|
|
314
238
|
*/
|
|
315
239
|
interface MiddlewareConfig<T> {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
240
|
+
/** The middleware function (can be a transform or blocking middleware). */
|
|
241
|
+
action: TransformMiddleware<T> | BlockingMiddleware<T>;
|
|
242
|
+
/** An optional, human-readable name for the middleware. */
|
|
243
|
+
name?: string;
|
|
244
|
+
/** If true, the middleware is treated as a blocking middleware (must return a boolean or `{ block: boolean }`). */
|
|
245
|
+
block?: boolean;
|
|
322
246
|
}
|
|
323
247
|
/**
|
|
324
248
|
* Interface for a reactive selector result, providing access to the value and subscription capabilities.
|
|
325
249
|
*/
|
|
326
250
|
interface ReactiveSelector<S> {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
251
|
+
/** Unique identifier for the selector. */
|
|
252
|
+
id: string;
|
|
253
|
+
/** Function to get the current computed value of the selector. */
|
|
254
|
+
get: () => S;
|
|
255
|
+
/**
|
|
256
|
+
* Subscribes a callback function to run whenever the selector's result changes.
|
|
257
|
+
* Returns an unsubscribe function.
|
|
258
|
+
*/
|
|
259
|
+
subscribe: (callback: (state: S) => void) => () => void;
|
|
336
260
|
}
|
|
337
261
|
interface ActionWatcher {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
262
|
+
/** Unique identifier for the action */
|
|
263
|
+
name: string;
|
|
264
|
+
/** Function to get the current computed value of the action. */
|
|
265
|
+
status: () => boolean;
|
|
266
|
+
/**
|
|
267
|
+
* Subscribes a callback function to run whenever the action's status changes.
|
|
268
|
+
* Returns an unsubscribe function.
|
|
269
|
+
*/
|
|
270
|
+
subscribe: (callback: () => void) => () => void;
|
|
347
271
|
}
|
|
348
272
|
interface TransactionOptions {
|
|
349
|
-
|
|
350
|
-
|
|
273
|
+
/** If true, blocks resolution until changes are fully committed to the database row */
|
|
274
|
+
flush?: boolean;
|
|
351
275
|
}
|
|
352
276
|
/**
|
|
353
277
|
* Interface defining the contract for the core data state store.
|
|
354
278
|
* T must be an object type.
|
|
355
279
|
*/
|
|
356
280
|
interface DataStore<T extends object> {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
281
|
+
/**
|
|
282
|
+
* Gets the current state of the store.
|
|
283
|
+
* @param clone If true, returns a deep clone of the state; otherwise, returns the internal state reference.
|
|
284
|
+
* @returns The current state T.
|
|
285
|
+
*/
|
|
286
|
+
get(clone?: boolean): T;
|
|
287
|
+
/**
|
|
288
|
+
* Gets a subset of the store.
|
|
289
|
+
* @param paths The paths which to include in the returned object.
|
|
290
|
+
* @param separator Optional separator for paths. Defaults to `.` .
|
|
291
|
+
* @returns An object of the shape K mapping paths to their current values.
|
|
292
|
+
*/
|
|
293
|
+
subset<K extends Record<string, any> = Record<string, any>>(paths: Array<string>, separator?: string): K;
|
|
294
|
+
/**
|
|
295
|
+
* Registers a named action function that can modify the state.
|
|
296
|
+
* @param action The action configuration object.
|
|
297
|
+
* @returns A function to unregister the action.
|
|
298
|
+
*/
|
|
299
|
+
register<R extends any[]>(action: {
|
|
300
|
+
name: string;
|
|
301
|
+
fn: (state: T, ...args: R) => DeepPartial<T> | Promise<DeepPartial<T>>;
|
|
302
|
+
debounce?: {
|
|
303
|
+
delay: number;
|
|
304
|
+
condition?: (previous: R, current: R) => boolean;
|
|
305
|
+
};
|
|
306
|
+
}): () => void;
|
|
307
|
+
/**
|
|
308
|
+
* Executes (dispatches) a previously registered action by its name.
|
|
309
|
+
* @param name The name of the action.
|
|
310
|
+
* @param args The parameters to pass to the action function.
|
|
311
|
+
* @returns A promise that resolves to the final state after the action and subsequent updates are complete.
|
|
312
|
+
*/
|
|
313
|
+
dispatch<R extends any[]>(name: string, ...args: R): Promise<T>;
|
|
314
|
+
/**
|
|
315
|
+
* Sets or updates the state using a StateUpdater.
|
|
316
|
+
* @param update The new state, partial state, or a function returning a partial state.
|
|
317
|
+
* @param options Configuration options for the set operation.
|
|
318
|
+
* @returns A promise that resolves to the current state when the update is complete.
|
|
319
|
+
*/
|
|
320
|
+
set(update: StateUpdater<T>, options?: {
|
|
321
|
+
force?: boolean;
|
|
322
|
+
actionId?: string;
|
|
323
|
+
}): Promise<T>;
|
|
324
|
+
/**
|
|
325
|
+
* Creates a reactive selector that computes a derived value and tracks dependencies.
|
|
326
|
+
* @param selector A function to compute the derived state value S from the full state T.
|
|
327
|
+
* @returns A `ReactiveSelector<S>` object.
|
|
328
|
+
*/
|
|
329
|
+
select<S>(selector: (state: T) => S): ReactiveSelector<S>;
|
|
330
|
+
/**
|
|
331
|
+
* Subscribes a callback to run when the data at the specified path(s) changes.
|
|
332
|
+
* @param path A single path string or an array of path strings to watch.
|
|
333
|
+
* @param callback The function to execute when a change occurs in the watched path(s).
|
|
334
|
+
* @param options Extra options to pass to the event bus
|
|
335
|
+
* @returns An unsubscribe function.
|
|
336
|
+
*/
|
|
337
|
+
watch(path: string | Array<string>, callback: (state: T) => void, options?: SubscribeOptions$1): () => void;
|
|
338
|
+
/**
|
|
339
|
+
* Subscribes to execution‑status changes of a registered action.
|
|
340
|
+
*
|
|
341
|
+
* The provided callback is called **every time** the action transitions
|
|
342
|
+
* between idle and running (i.e. on `action:start`, `action:complete`, or
|
|
343
|
+
* `action:error` for the given name). The current status can also be read
|
|
344
|
+
* synchronously with `isActionRunning(name)`.
|
|
345
|
+
*
|
|
346
|
+
* **Deferred listener teardown**
|
|
347
|
+
* To avoid unnecessary churn when subscriptions are rapidly created and
|
|
348
|
+
* destroyed, the underlying event listeners are not removed immediately
|
|
349
|
+
* on unsubscribe. Instead, a *pending reset* is queued via `queueMicrotask`.
|
|
350
|
+
* If a new subscription for the same action arrives before that microtask
|
|
351
|
+
* executes, the reset is silently cancelled and the already‑established
|
|
352
|
+
* listeners are reused. This keeps the subscription infrastructure stable
|
|
353
|
+
* and prevents cascading notifications that could otherwise arise from
|
|
354
|
+
* repeated subscribe‑unsubscribe‑subscribe cycles.
|
|
355
|
+
*
|
|
356
|
+
* @param name - The name of the action to watch.
|
|
357
|
+
* @returns An ActionWatcher
|
|
358
|
+
*/
|
|
359
|
+
watchAction(name: string): ActionWatcher;
|
|
360
|
+
/**
|
|
361
|
+
* Executes an operation function within a transaction block.
|
|
362
|
+
* All state updates (`set` or actions) within the transaction are batched and applied atomically (all or nothing).
|
|
363
|
+
* @param operation The function containing the state updates.
|
|
364
|
+
* @returns A promise that resolves to the return value of the operation function.
|
|
365
|
+
*/
|
|
366
|
+
transaction<R>(operation: () => R | Promise<R>, options?: TransactionOptions): Promise<R>;
|
|
367
|
+
/**
|
|
368
|
+
* Registers a middleware function to intercept state updates.
|
|
369
|
+
* @param props The middleware configuration.
|
|
370
|
+
* @returns A function to unregister the middleware.
|
|
371
|
+
*/
|
|
372
|
+
use(props: MiddlewareConfig<T>): () => boolean;
|
|
373
|
+
/**
|
|
374
|
+
* Subscribes a listener to a specific store event type.
|
|
375
|
+
* @param event The type of store event to listen for.
|
|
376
|
+
* @param listener The callback function to execute when the event fires.
|
|
377
|
+
* @returns An unsubscribe function.
|
|
378
|
+
*/
|
|
379
|
+
on(event: StoreEvent, listener: (data: any) => void): () => void;
|
|
380
|
+
/**
|
|
381
|
+
* Returns the unique identifier of the store instance.
|
|
382
|
+
*/
|
|
383
|
+
id(): string;
|
|
384
|
+
/**
|
|
385
|
+
* Checks whether the store is fully initialized and ready for use.
|
|
386
|
+
*/
|
|
387
|
+
isReady(): boolean;
|
|
388
|
+
/**
|
|
389
|
+
* Returns a promise that resolves once the store is fully initialised.
|
|
390
|
+
* Safe to call multiple times — all callers share the same latch.
|
|
391
|
+
*
|
|
392
|
+
* @param timeout - Optional maximum wait time in milliseconds.
|
|
393
|
+
* @throws {TimeoutError} If the store does not become ready within the timeout.
|
|
394
|
+
*
|
|
395
|
+
* @example
|
|
396
|
+
* await store.ready();
|
|
397
|
+
* const state = store.get();
|
|
398
|
+
*/
|
|
399
|
+
ready(timeout?: number): Promise<void>;
|
|
400
|
+
/**
|
|
401
|
+
* Returns a readonly snapshot of the current execution state of the store.
|
|
402
|
+
*/
|
|
403
|
+
state(): Readonly<StoreExecutionState<T>>;
|
|
404
|
+
/**
|
|
405
|
+
* Releases all resources held by the store and renders it unusable
|
|
406
|
+
*/
|
|
407
|
+
dispose(): Promise<void>;
|
|
484
408
|
}
|
|
485
409
|
/** Payload for the 'persistence:queued' event. */
|
|
486
410
|
interface PersistenceQueuedPayload {
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
411
|
+
/** Unique ID for the persistence task. */
|
|
412
|
+
taskId: string;
|
|
413
|
+
/** Paths that were changed and triggered persistence. */
|
|
414
|
+
changedPaths: string[];
|
|
415
|
+
/** The current number of tasks waiting in the persistence queue. */
|
|
416
|
+
queueSize: number;
|
|
417
|
+
/** Timestamp of when the task was queued. */
|
|
418
|
+
timestamp: number;
|
|
495
419
|
}
|
|
496
420
|
/** Payload for the 'persistence:success' event. */
|
|
497
421
|
interface PersistenceSuccessPayload {
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
422
|
+
/** Unique ID for the persistence task. */
|
|
423
|
+
taskId: string;
|
|
424
|
+
/** Paths that were successfully persisted. */
|
|
425
|
+
changedPaths: string[];
|
|
426
|
+
/** Duration of the persistence operation (in milliseconds). */
|
|
427
|
+
duration: number;
|
|
428
|
+
/** Timestamp of the success. */
|
|
429
|
+
timestamp: number;
|
|
506
430
|
}
|
|
507
431
|
/** Payload for the 'persistence:retry' event. */
|
|
508
432
|
interface PersistenceRetryPayload {
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
433
|
+
/** Unique ID for the persistence task. */
|
|
434
|
+
taskId: string;
|
|
435
|
+
/** Current retry attempt number. */
|
|
436
|
+
attempt: number;
|
|
437
|
+
/** Maximum allowed retries. */
|
|
438
|
+
maxRetries: number;
|
|
439
|
+
/** Time until the next retry attempt (in milliseconds). */
|
|
440
|
+
nextRetryIn: number;
|
|
441
|
+
/** The error that triggered the retry. */
|
|
442
|
+
error: any;
|
|
443
|
+
/** Timestamp of the retry event. */
|
|
444
|
+
timestamp: number;
|
|
521
445
|
}
|
|
522
446
|
/** Payload for the 'persistence:failed' event. */
|
|
523
447
|
interface PersistenceFailedPayload {
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
448
|
+
/** Unique ID for the persistence task. */
|
|
449
|
+
taskId: string;
|
|
450
|
+
/** Paths that failed to persist. */
|
|
451
|
+
changedPaths: string[];
|
|
452
|
+
/** Total number of attempts made. */
|
|
453
|
+
attempts: number;
|
|
454
|
+
/** The final error object. */
|
|
455
|
+
error: any;
|
|
456
|
+
/** Timestamp of the final failure. */
|
|
457
|
+
timestamp: number;
|
|
534
458
|
}
|
|
535
459
|
/** Payload for the 'persistence:queue_cleared' event. */
|
|
536
460
|
interface PersistenceQueueClearedPayload {
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
461
|
+
/** The number of persistence tasks that were cleared from the queue. */
|
|
462
|
+
clearedTasks: number;
|
|
463
|
+
/** Timestamp of when the queue was cleared. */
|
|
464
|
+
timestamp: number;
|
|
541
465
|
}
|
|
542
466
|
/** Payload for the 'persistence:init_error' event. */
|
|
543
467
|
interface PersistenceInitErrorPayload {
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
468
|
+
/** The error that occurred during persistence initialization. */
|
|
469
|
+
error: any;
|
|
470
|
+
/** Timestamp of the error. */
|
|
471
|
+
timestamp: number;
|
|
548
472
|
}
|
|
549
473
|
/**
|
|
550
474
|
* Interface describing a registered state action, including its metadata and debounce configuration.
|
|
551
475
|
*/
|
|
552
476
|
type StoreAction<T, R extends any[] = any[]> = {
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
/**
|
|
558
|
-
|
|
559
|
-
/**
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
delay: number;
|
|
565
|
-
/** Optional condition to decide whether to debounce based on previous vs current args */
|
|
566
|
-
condition?: (previous: R | undefined, current: R) => boolean;
|
|
567
|
-
/** Last call’s arguments, used for condition checks */
|
|
568
|
-
args?: R;
|
|
569
|
-
/** Internal promise resolvers to prevent memory leaks */
|
|
570
|
-
resolve?: (value: any) => void;
|
|
571
|
-
reject?: (reason?: any) => void;
|
|
572
|
-
};
|
|
477
|
+
/** Unique identifier for the action definition. */id: string; /** Name of the action, used for dispatching. */
|
|
478
|
+
name: string; /** The actual function that takes state and arguments, and returns a state update. */
|
|
479
|
+
action: (state: T, ...args: R) => DeepPartial<T> | Promise<DeepPartial<T>>; /** Optional configuration for debouncing action execution. */
|
|
480
|
+
debounce?: {
|
|
481
|
+
/** Active timer reference, if debouncing */timer?: ReturnType<typeof setTimeout>; /** Debounce delay in milliseconds */
|
|
482
|
+
delay: number; /** Optional condition to decide whether to debounce based on previous vs current args */
|
|
483
|
+
condition?: (previous: R | undefined, current: R) => boolean; /** Last call’s arguments, used for condition checks */
|
|
484
|
+
args?: R; /** Internal promise resolvers to prevent memory leaks */
|
|
485
|
+
resolve?: (value: any) => void;
|
|
486
|
+
reject?: (reason?: any) => void;
|
|
487
|
+
};
|
|
573
488
|
};
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
* Think of it as the ID of the specific browser tab, component, or module that's currently interacting with the persistence layer.
|
|
581
|
-
* It should typically be a **UUID** generated once at the consumer instance's instantiation.
|
|
582
|
-
* This `id` is crucial for the `subscribe` method, helping to differentiate updates originating from the current instance versus other instances/tabs, thereby preventing self-triggered notification loops.
|
|
583
|
-
* @param state The state (of type T) to persist. This state is generally considered the **global or shared state** that all instances interact with.
|
|
584
|
-
* @returns `true` if the operation was successful, `false` if an error occurred. For asynchronous implementations (like `IndexedDBPersistence`), this returns a `Promise<boolean>`.
|
|
585
|
-
*/
|
|
586
|
-
set(id: string, state: T): boolean | Promise<boolean>;
|
|
587
|
-
/**
|
|
588
|
-
* Retrieves the global persisted data from storage.
|
|
589
|
-
*
|
|
590
|
-
* @returns The retrieved state of type `T`, or `null` if no data is found or if an error occurs during retrieval/parsing.
|
|
591
|
-
* For asynchronous implementations, this returns a `Promise<T | null>`.
|
|
592
|
-
*/
|
|
593
|
-
get(): (T | null) | Promise<T | null>;
|
|
594
|
-
/**
|
|
595
|
-
* Subscribes to changes in the global persisted data that originate from *other* instances of your application (e.g., other tabs or independent components using the same persistence layer).
|
|
596
|
-
*
|
|
597
|
-
* @param id The **unique identifier of the *consumer instance* subscribing**. This allows the persistence implementation to filter out notifications that were initiated by the subscribing instance itself.
|
|
598
|
-
* @param callback The function to call when the global persisted data changes from *another* source. The new state (`T`) is passed as an argument to this callback.
|
|
599
|
-
* @returns A function that, when called, will unsubscribe the provided callback from future updates. Call this when your component or instance is no longer active to prevent memory leaks.
|
|
600
|
-
*/
|
|
601
|
-
subscribe(id: string, callback: (state: T) => void): () => void;
|
|
602
|
-
/**
|
|
603
|
-
* Clears (removes) the entire global persisted data from storage.
|
|
604
|
-
*
|
|
605
|
-
* @returns `true` if the operation was successful, `false` if an error occurred. For asynchronous implementations, this returns a `Promise<boolean>`.
|
|
606
|
-
*/
|
|
607
|
-
clear(): boolean | Promise<boolean>;
|
|
608
|
-
/**
|
|
609
|
-
* Returns metadata about the persistence layer.
|
|
610
|
-
*
|
|
611
|
-
* This is useful for distinguishing between multiple apps running on the same host
|
|
612
|
-
* (e.g., several apps served at `localhost:3000` that share the same storage key).
|
|
613
|
-
*
|
|
614
|
-
* @returns An object containing:
|
|
615
|
-
* - `version`: The semantic version string of the persistence schema or application.
|
|
616
|
-
* - `id`: A unique identifier for the application using this persistence instance.
|
|
617
|
-
*/
|
|
618
|
-
stats(): {
|
|
619
|
-
version: string;
|
|
620
|
-
id: string;
|
|
621
|
-
};
|
|
622
|
-
}
|
|
623
|
-
|
|
489
|
+
//#endregion
|
|
490
|
+
//#region src/store/logger.d.ts
|
|
491
|
+
type StoreLogger = SystemLogger;
|
|
492
|
+
declare function createStoreLogger(logger?: StoreLogger): StoreLogger;
|
|
493
|
+
//#endregion
|
|
494
|
+
//#region src/store/store.d.ts
|
|
624
495
|
type ReactiveDataStoreOptions<T> = {
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
496
|
+
timeout?: number;
|
|
497
|
+
state?: T;
|
|
498
|
+
persistence?: SimplePersistence<T>;
|
|
499
|
+
deleteMarker?: symbol;
|
|
500
|
+
logger?: StoreLogger;
|
|
501
|
+
options?: {
|
|
502
|
+
persistenceMaxRetries?: number;
|
|
503
|
+
persistenceRetryDelay?: number;
|
|
504
|
+
};
|
|
633
505
|
};
|
|
634
506
|
/**
|
|
635
507
|
* Main ReactiveDataStore - a robust, type-safe state management solution.
|
|
@@ -640,204 +512,213 @@ type ReactiveDataStoreOptions<T> = {
|
|
|
640
512
|
* @template T The type of the data object managed by the store.
|
|
641
513
|
*/
|
|
642
514
|
declare class ReactiveDataStore<T extends object> implements DataStore<T> {
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
dispatch<R extends any[]>(name: string, ...params: R): Promise<T>;
|
|
728
|
-
/**
|
|
729
|
-
* Enqueues a state update for serial execution.
|
|
730
|
-
*
|
|
731
|
-
* Uses a `Serializer` internally, which guarantees:
|
|
732
|
-
* - FIFO ordering of all updates.
|
|
733
|
-
* - No concurrent execution — each update waits for the previous to complete.
|
|
734
|
-
* - Backpressure: throws if the queue exceeds capacity.
|
|
735
|
-
* - Clean rejection after `dispose()`.
|
|
736
|
-
*
|
|
737
|
-
* @returns A Promise that resolves with the new state T.
|
|
738
|
-
*/
|
|
739
|
-
set(update: StateUpdater<T>, options?: {
|
|
740
|
-
force?: boolean;
|
|
741
|
-
actionId?: string;
|
|
742
|
-
}): Promise<T>;
|
|
743
|
-
/**
|
|
744
|
-
* Internal logic for performing a single, sequential state update.
|
|
745
|
-
* Always called inside the Serializer — never call directly.
|
|
746
|
-
*/
|
|
747
|
-
private _performUpdate;
|
|
748
|
-
/**
|
|
749
|
-
* Opens the readyLatch once the persistence layer signals it is ready.
|
|
750
|
-
* The latch can only open once — subsequent `persistence:ready` events are no-ops.
|
|
751
|
-
*/
|
|
752
|
-
private setupReadyLatch;
|
|
753
|
-
private setupPersistenceListener;
|
|
754
|
-
watch(path: string | Array<string>, callback: (state: T) => void, options?: SubscribeOptions): () => void;
|
|
755
|
-
/**
|
|
756
|
-
* Subscribes to execution‑status changes of a registered action.
|
|
757
|
-
*
|
|
758
|
-
* The provided callback is called **every time** the action transitions
|
|
759
|
-
* between idle and running (i.e. on `action:start`, `action:complete`, or
|
|
760
|
-
* `action:error` for the given name). The current status can also be read
|
|
761
|
-
* synchronously with `isActionRunning(name)`.
|
|
762
|
-
*
|
|
763
|
-
* **Deferred listener teardown**
|
|
764
|
-
* To avoid unnecessary churn when subscriptions are rapidly created and
|
|
765
|
-
* destroyed, the underlying event listeners are not removed immediately
|
|
766
|
-
* on unsubscribe. Instead, a *pending reset* is queued via `queueMicrotask`.
|
|
767
|
-
* If a new subscription for the same action arrives before that microtask
|
|
768
|
-
* executes, the reset is silently cancelled and the already‑established
|
|
769
|
-
* listeners are reused. This keeps the subscription infrastructure stable
|
|
770
|
-
* and prevents cascading notifications that could otherwise arise from
|
|
771
|
-
* repeated subscribe‑unsubscribe‑subscribe cycles.
|
|
772
|
-
*
|
|
773
|
-
* @param name - The name of the action to watch.
|
|
774
|
-
* @returns ActionWatcher
|
|
775
|
-
*/
|
|
776
|
-
watchAction(name: string): ActionWatcher;
|
|
777
|
-
/**
|
|
778
|
-
* Creates a debounced version of `set()` using a `Debouncer`.
|
|
779
|
-
*
|
|
780
|
-
* Useful for high-frequency write sources (e.g. text input, scroll position)
|
|
781
|
-
* where you want to collapse rapid updates into a single state write after a
|
|
782
|
-
* quiet period.
|
|
783
|
-
*
|
|
784
|
-
* @param delay - Quiet period in milliseconds before the update is applied.
|
|
785
|
-
* @param leading - If true, also applies the first update immediately.
|
|
786
|
-
* @returns A debounced setter function with the same signature as `set()`.
|
|
787
|
-
*
|
|
788
|
-
* @example
|
|
789
|
-
* const debouncedSet = store.debouncedSetter({ delay: 200 });
|
|
790
|
-
* inputEl.addEventListener("input", (e) => {
|
|
791
|
-
* debouncedSet((s) => ({ ...s, query: e.target.value }));
|
|
792
|
-
* });
|
|
793
|
-
*/
|
|
794
|
-
debouncedSetter(options: {
|
|
795
|
-
delay: number;
|
|
796
|
-
leading?: boolean;
|
|
797
|
-
}): (update: StateUpdater<T>, setOptions?: {
|
|
798
|
-
force?: boolean;
|
|
799
|
-
actionId?: string;
|
|
800
|
-
}) => void;
|
|
801
|
-
id(): string;
|
|
802
|
-
transaction<R>(operation: () => R | Promise<R>, options?: TransactionOptions): Promise<R>;
|
|
803
|
-
use(props: MiddlewareConfig<T>): () => boolean;
|
|
804
|
-
metrics(): StoreMetrics;
|
|
805
|
-
on(event: StoreEvent, listener: (data: any) => void): () => void;
|
|
806
|
-
getPersistenceStatus(): {
|
|
807
|
-
queueSize: number;
|
|
808
|
-
isProcessing: boolean;
|
|
809
|
-
pendingRetries: number;
|
|
810
|
-
oldestTask?: number;
|
|
515
|
+
/** Manages the core application state. */
|
|
516
|
+
private coreState;
|
|
517
|
+
/** Orchestrates and executes middleware for state changes. */
|
|
518
|
+
private middlewareEngine;
|
|
519
|
+
/** Manages saving state changes to a persistence layer. */
|
|
520
|
+
private persistenceHandler;
|
|
521
|
+
/** Manages atomic state updates via transactions. */
|
|
522
|
+
private transactionManager;
|
|
523
|
+
/** Collects and provides performance metrics for the store. */
|
|
524
|
+
private metricsCollector;
|
|
525
|
+
private selectorManager;
|
|
526
|
+
private actions;
|
|
527
|
+
/**
|
|
528
|
+
* Serializer enforces FIFO serial execution of all state updates.
|
|
529
|
+
*
|
|
530
|
+
* Replaces the bare `Promise<T | void>` chain. Benefits over the old pattern:
|
|
531
|
+
* - Backpressure: rejects when the queue exceeds capacity rather than growing
|
|
532
|
+
* unboundedly under write pressure.
|
|
533
|
+
* - Clean shutdown: `close()` in dispose() immediately rejects any subsequent
|
|
534
|
+
* `set()` calls with a clear error instead of silently enqueuing them.
|
|
535
|
+
* - Observability: `updateSerializer.running()` and `updateSerializer.pending()`
|
|
536
|
+
* replace the manually-managed `executionState.executing` flag.
|
|
537
|
+
* - Error isolation: errors in one update do not corrupt the queue — the
|
|
538
|
+
* Serializer's mutex is always released in its own `finally` block.
|
|
539
|
+
*/
|
|
540
|
+
private updateSerializer;
|
|
541
|
+
/**
|
|
542
|
+
* Latch that opens once the store is fully initialised (persistence loaded).
|
|
543
|
+
*
|
|
544
|
+
* Replaces the poll-only `isReady(): boolean` pattern. Callers can now
|
|
545
|
+
* `await store.ready()` with an optional timeout rather than polling or
|
|
546
|
+
* subscribing to an internal event. `isReady()` is preserved as `latch.isOpen()`
|
|
547
|
+
* for synchronous checks and backwards compatibility.
|
|
548
|
+
*/
|
|
549
|
+
private readyLatch;
|
|
550
|
+
private disposeOnce;
|
|
551
|
+
private updateBus;
|
|
552
|
+
private eventBus;
|
|
553
|
+
private executionState;
|
|
554
|
+
private instanceID;
|
|
555
|
+
private merge;
|
|
556
|
+
private diff;
|
|
557
|
+
private logger;
|
|
558
|
+
/**
|
|
559
|
+
* Creates a new ReactiveDataStore instance.
|
|
560
|
+
*/
|
|
561
|
+
constructor(initialData: T, persistence?: SimplePersistence<T>, deleteMarker?: symbol, options?: {
|
|
562
|
+
persistenceMaxRetries?: number;
|
|
563
|
+
persistenceRetryDelay?: number;
|
|
564
|
+
broadcastChannel?: string;
|
|
565
|
+
logger?: StoreLogger;
|
|
566
|
+
});
|
|
567
|
+
/**
|
|
568
|
+
* Returns true if the store has finished initialising (persistence loaded).
|
|
569
|
+
* For async flows, prefer `await store.ready()` over polling this.
|
|
570
|
+
*/
|
|
571
|
+
isReady(): boolean;
|
|
572
|
+
/**
|
|
573
|
+
* Returns a promise that resolves once the store is fully initialised.
|
|
574
|
+
* Safe to call multiple times — all callers share the same latch.
|
|
575
|
+
*
|
|
576
|
+
* @param timeout - Optional maximum wait time in milliseconds.
|
|
577
|
+
* @throws {TimeoutError} If the store does not become ready within the timeout.
|
|
578
|
+
*
|
|
579
|
+
* @example
|
|
580
|
+
* await store.ready();
|
|
581
|
+
* const state = store.get();
|
|
582
|
+
*/
|
|
583
|
+
ready(timeout?: number): Promise<void>;
|
|
584
|
+
state(): Readonly<StoreExecutionState<T>>;
|
|
585
|
+
/**
|
|
586
|
+
* Gets the current state. Optimized default to return reference (false) for performance.
|
|
587
|
+
* @param clone If `true`, returns a deep clone (use sparingly).
|
|
588
|
+
* @returns The current state object.
|
|
589
|
+
*/
|
|
590
|
+
get(clone?: boolean): T;
|
|
591
|
+
subset<K extends Record<string, any>>(paths: Array<string>, separator?: string): K;
|
|
592
|
+
select<S>(selector: (state: T) => S): ReactiveSelector<S>;
|
|
593
|
+
register<R extends any[]>(action: {
|
|
594
|
+
name: string;
|
|
595
|
+
fn: (state: T, ...args: R) => DeepPartial<T> | Promise<DeepPartial<T>>;
|
|
596
|
+
debounce?: {
|
|
597
|
+
delay: number;
|
|
598
|
+
condition?: (previous: R | undefined, current: R) => boolean;
|
|
811
599
|
};
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
600
|
+
}): () => void;
|
|
601
|
+
dispatch<R extends any[]>(name: string, ...params: R): Promise<T>;
|
|
602
|
+
/**
|
|
603
|
+
* Enqueues a state update for serial execution.
|
|
604
|
+
*
|
|
605
|
+
* Uses a `Serializer` internally, which guarantees:
|
|
606
|
+
* - FIFO ordering of all updates.
|
|
607
|
+
* - No concurrent execution — each update waits for the previous to complete.
|
|
608
|
+
* - Backpressure: throws if the queue exceeds capacity.
|
|
609
|
+
* - Clean rejection after `dispose()`.
|
|
610
|
+
*
|
|
611
|
+
* @returns A Promise that resolves with the new state T.
|
|
612
|
+
*/
|
|
613
|
+
set(update: StateUpdater<T>, options?: {
|
|
614
|
+
force?: boolean;
|
|
615
|
+
actionId?: string;
|
|
616
|
+
}): Promise<T>;
|
|
617
|
+
/**
|
|
618
|
+
* Internal logic for performing a single, sequential state update.
|
|
619
|
+
* Always called inside the Serializer — never call directly.
|
|
620
|
+
*/
|
|
621
|
+
private _performUpdate;
|
|
622
|
+
/**
|
|
623
|
+
* Opens the readyLatch once the persistence layer signals it is ready.
|
|
624
|
+
* The latch can only open once — subsequent `persistence:ready` events are no-ops.
|
|
625
|
+
*/
|
|
626
|
+
private setupReadyLatch;
|
|
627
|
+
private setupPersistenceListener;
|
|
628
|
+
watch(path: string | Array<string>, callback: (state: T) => void, options?: SubscribeOptions): () => void;
|
|
629
|
+
/**
|
|
630
|
+
* Subscribes to execution‑status changes of a registered action.
|
|
631
|
+
*
|
|
632
|
+
* The provided callback is called **every time** the action transitions
|
|
633
|
+
* between idle and running (i.e. on `action:start`, `action:complete`, or
|
|
634
|
+
* `action:error` for the given name). The current status can also be read
|
|
635
|
+
* synchronously with `isActionRunning(name)`.
|
|
636
|
+
*
|
|
637
|
+
* **Deferred listener teardown**
|
|
638
|
+
* To avoid unnecessary churn when subscriptions are rapidly created and
|
|
639
|
+
* destroyed, the underlying event listeners are not removed immediately
|
|
640
|
+
* on unsubscribe. Instead, a *pending reset* is queued via `queueMicrotask`.
|
|
641
|
+
* If a new subscription for the same action arrives before that microtask
|
|
642
|
+
* executes, the reset is silently cancelled and the already‑established
|
|
643
|
+
* listeners are reused. This keeps the subscription infrastructure stable
|
|
644
|
+
* and prevents cascading notifications that could otherwise arise from
|
|
645
|
+
* repeated subscribe‑unsubscribe‑subscribe cycles.
|
|
646
|
+
*
|
|
647
|
+
* @param name - The name of the action to watch.
|
|
648
|
+
* @returns ActionWatcher
|
|
649
|
+
*/
|
|
650
|
+
watchAction(name: string): {
|
|
651
|
+
name: string;
|
|
652
|
+
status: () => boolean;
|
|
653
|
+
subscribe: (_: () => void) => () => void;
|
|
654
|
+
};
|
|
655
|
+
/**
|
|
656
|
+
* Creates a debounced version of `set()` using a `Debouncer`.
|
|
657
|
+
*
|
|
658
|
+
* Useful for high-frequency write sources (e.g. text input, scroll position)
|
|
659
|
+
* where you want to collapse rapid updates into a single state write after a
|
|
660
|
+
* quiet period.
|
|
661
|
+
*
|
|
662
|
+
* @param delay - Quiet period in milliseconds before the update is applied.
|
|
663
|
+
* @param leading - If true, also applies the first update immediately.
|
|
664
|
+
* @returns A debounced setter function with the same signature as `set()`.
|
|
665
|
+
*
|
|
666
|
+
* @example
|
|
667
|
+
* const debouncedSet = store.debouncedSetter({ delay: 200 });
|
|
668
|
+
* inputEl.addEventListener("input", (e) => {
|
|
669
|
+
* debouncedSet((s) => ({ ...s, query: e.target.value }));
|
|
670
|
+
* });
|
|
671
|
+
*/
|
|
672
|
+
debouncedSetter(options: {
|
|
673
|
+
delay: number;
|
|
674
|
+
leading?: boolean;
|
|
675
|
+
}): (update: StateUpdater<T>, setOptions?: {
|
|
676
|
+
force?: boolean;
|
|
677
|
+
actionId?: string;
|
|
678
|
+
}) => void;
|
|
679
|
+
id(): string;
|
|
680
|
+
transaction<R>(operation: () => R | Promise<R>, options?: TransactionOptions): Promise<R>;
|
|
681
|
+
use(props: MiddlewareConfig<T>): () => boolean;
|
|
682
|
+
metrics(): StoreMetrics;
|
|
683
|
+
on(event: StoreEvent, listener: (data: any) => void): () => void;
|
|
684
|
+
getPersistenceStatus(): {
|
|
685
|
+
queueSize: number;
|
|
686
|
+
isProcessing: boolean;
|
|
687
|
+
pendingRetries: number;
|
|
688
|
+
oldestTask?: number;
|
|
689
|
+
};
|
|
690
|
+
flush(): Promise<void>;
|
|
691
|
+
/**
|
|
692
|
+
* Discards all pending persistence tasks.
|
|
693
|
+
* WARNING: Any queued writes not yet persisted will be lost.
|
|
694
|
+
* Call flushPersistence() first if writes must not be lost.
|
|
695
|
+
*/
|
|
696
|
+
discardPersistenceQueue(): void;
|
|
697
|
+
/**
|
|
698
|
+
* Disposes the store and all owned resources.
|
|
699
|
+
*
|
|
700
|
+
* Closes the update Serializer — any `set()` calls after dispose() will
|
|
701
|
+
* reject immediately with `SerializerExecutionDone` rather than silently
|
|
702
|
+
* enqueuing work against a dead store.
|
|
703
|
+
*/
|
|
704
|
+
dispose(): Promise<void>;
|
|
705
|
+
private checkDisposed;
|
|
706
|
+
disposed(): boolean;
|
|
707
|
+
private emit;
|
|
830
708
|
}
|
|
831
|
-
|
|
709
|
+
//#endregion
|
|
710
|
+
//#region src/store/registry.d.ts
|
|
832
711
|
/**
|
|
833
712
|
* Configuration options for the StoreRegistry.
|
|
834
713
|
*/
|
|
835
714
|
interface StoreRegistryOptions {
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
715
|
+
/**
|
|
716
|
+
* Optional callback fired when a store is actively garbage collected.
|
|
717
|
+
* Highly recommended for production telemetry and memory leak debugging.
|
|
718
|
+
*/
|
|
719
|
+
onEvict?: (storeId: string) => void;
|
|
720
|
+
/** Optional logger instance. Defaults to no-op. */
|
|
721
|
+
logger?: StoreLogger;
|
|
841
722
|
}
|
|
842
723
|
/**
|
|
843
724
|
* A memory-safe, single-flight registry for ReactiveDataStores.
|
|
@@ -845,109 +726,106 @@ interface StoreRegistryOptions {
|
|
|
845
726
|
* when no longer in use, automatically cleaning up internal references.
|
|
846
727
|
*/
|
|
847
728
|
declare class StoreRegistry<S extends object> {
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
729
|
+
private readonly stores;
|
|
730
|
+
private readonly storeToOnce;
|
|
731
|
+
private readonly finalizer;
|
|
732
|
+
private readonly onEvict?;
|
|
733
|
+
private readonly logger;
|
|
734
|
+
constructor(options?: StoreRegistryOptions);
|
|
735
|
+
/**
|
|
736
|
+
* Get an existing store for storeId, or create a new one via an always-cached Once primitive.
|
|
737
|
+
* Ensures only one instantiation occurs even under concurrent calls.
|
|
738
|
+
* * @param storeId - Unique identifier for the store.
|
|
739
|
+
* @param initialState - The initial state to seed the store if it is created.
|
|
740
|
+
* @param timeout - Optional timeout (ms) for store initialization.
|
|
741
|
+
*/
|
|
742
|
+
get(storeId: string, options?: ReactiveDataStoreOptions<S>): Promise<ReactiveDataStore<S>>;
|
|
743
|
+
getSync(storeId: string, options?: ReactiveDataStoreOptions<S>): ReactiveDataStore<S>;
|
|
744
|
+
/**
|
|
745
|
+
* Manually remove a store registry entry, unregistering its finalizer and disposing it.
|
|
746
|
+
* @param storeId - Unique identifier for the store.
|
|
747
|
+
* @returns True if a store was actively removed, false otherwise.
|
|
748
|
+
*/
|
|
749
|
+
release(storeId: string): Promise<boolean>;
|
|
750
|
+
/**
|
|
751
|
+
* Clears all stores from the registry, disposes them, and unregisters all finalizers.
|
|
752
|
+
*/
|
|
753
|
+
clear(): Promise<void>;
|
|
754
|
+
/**
|
|
755
|
+
* Get the store if it exists and has successfully finished initialization.
|
|
756
|
+
* Does not trigger initialization if the store is missing or pending.
|
|
757
|
+
*/
|
|
758
|
+
has(storeId: string): boolean;
|
|
759
|
+
/**
|
|
760
|
+
* Returns the current number of tracked stores.
|
|
761
|
+
* Note: This includes entries that may have lost external references but haven't been GC'd yet.
|
|
762
|
+
*/
|
|
763
|
+
get size(): number;
|
|
882
764
|
}
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
* @fileoverview Store Observer Module
|
|
886
|
-
* @description A comprehensive module to add advanced debugging, observability, and time-travel
|
|
887
|
-
* capabilities to a ReactiveDataStore. All console logging is centralized to respect a 'silent' flag,
|
|
888
|
-
* preventing test runner output pollution.
|
|
889
|
-
*/
|
|
890
|
-
|
|
765
|
+
//#endregion
|
|
766
|
+
//#region src/store/observer.d.ts
|
|
891
767
|
/**
|
|
892
768
|
* @interface DebugEvent
|
|
893
769
|
* @description Interface for the structure of a recorded debug event.
|
|
894
770
|
*/
|
|
895
771
|
interface DebugEvent {
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
772
|
+
/** The type of store event (e.g., 'update:start', 'action:complete'). */
|
|
773
|
+
type: string;
|
|
774
|
+
/** The timestamp when the event occurred. */
|
|
775
|
+
timestamp: number;
|
|
776
|
+
/** The raw data payload associated with the event, including actionId where applicable. */
|
|
777
|
+
data: any;
|
|
902
778
|
}
|
|
903
779
|
/**
|
|
904
780
|
* @interface Snapshot
|
|
905
781
|
* @description Represents a rich snapshot of the state at a point in time for history tracking.
|
|
906
782
|
*/
|
|
907
783
|
interface Snapshot<T> {
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
784
|
+
/** The complete state object at the time of the snapshot. */
|
|
785
|
+
state: T;
|
|
786
|
+
/** The timestamp of the state change. */
|
|
787
|
+
timestamp: number;
|
|
788
|
+
/** The list of changes (deltas) that resulted in this state. */
|
|
789
|
+
deltas: StateDelta[];
|
|
914
790
|
}
|
|
915
791
|
/**
|
|
916
792
|
* @interface ObserverSessionData
|
|
917
793
|
* @description Defines the data structure for a saved observer session.
|
|
918
794
|
*/
|
|
919
795
|
interface ObserverSessionData<T extends object> {
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
796
|
+
/** The chronological history of debug events. */
|
|
797
|
+
eventHistory: DebugEvent[];
|
|
798
|
+
/** The chronological history of state snapshots. */
|
|
799
|
+
stateHistory: Snapshot<T>[];
|
|
924
800
|
}
|
|
925
801
|
/**
|
|
926
802
|
* @interface ObserverOptions
|
|
927
803
|
* @description Configuration options for the observer module.
|
|
928
804
|
*/
|
|
929
805
|
interface ObserverOptions {
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
806
|
+
/** Maximum number of events to retain in memory. Defaults to 500. */
|
|
807
|
+
maxEvents?: number;
|
|
808
|
+
/** Enables or disables console logging for all events (overridden by 'silent'). Defaults to false. */
|
|
809
|
+
enableConsoleLogging?: boolean;
|
|
810
|
+
/** Maximum number of state snapshots to retain for time-travel. Defaults to 20. */
|
|
811
|
+
maxStateHistory?: number;
|
|
812
|
+
/** Fine-grained control over which event types are logged to the console. */
|
|
813
|
+
logEvents?: {
|
|
814
|
+
updates?: boolean;
|
|
815
|
+
middleware?: boolean;
|
|
816
|
+
transactions?: boolean;
|
|
817
|
+
actions?: boolean;
|
|
818
|
+
selectors?: boolean;
|
|
819
|
+
};
|
|
820
|
+
/** Performance thresholds for triggering console warnings. Values are in milliseconds (ms). */
|
|
821
|
+
performanceThresholds?: {
|
|
822
|
+
updateTime?: number;
|
|
823
|
+
middlewareTime?: number;
|
|
824
|
+
};
|
|
825
|
+
/** If true, suppresses all console output and logging regardless of other options. Defaults to false. */
|
|
826
|
+
silent?: boolean;
|
|
827
|
+
/** Optional logger instance. Defaults to no-op. */
|
|
828
|
+
logger?: StoreLogger;
|
|
951
829
|
}
|
|
952
830
|
/**
|
|
953
831
|
* @class StoreObserver
|
|
@@ -955,177 +833,179 @@ interface ObserverOptions {
|
|
|
955
833
|
* @template T The type of the store's state object.
|
|
956
834
|
*/
|
|
957
835
|
declare class StoreObserver<T extends object> {
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
836
|
+
protected store: DataStore<T>;
|
|
837
|
+
private eventHistory;
|
|
838
|
+
private stateHistory;
|
|
839
|
+
private unsubscribers;
|
|
840
|
+
private isTimeTraveling;
|
|
841
|
+
private devTools;
|
|
842
|
+
private middlewareExecutions;
|
|
843
|
+
private activeTransactionCount;
|
|
844
|
+
private activeBatches;
|
|
845
|
+
private maxEvents;
|
|
846
|
+
private maxStateHistory;
|
|
847
|
+
private enableConsoleLogging;
|
|
848
|
+
private isSilent;
|
|
849
|
+
private logEvents;
|
|
850
|
+
private performanceThresholds;
|
|
851
|
+
private logger;
|
|
852
|
+
/**
|
|
853
|
+
* @param store The DataStore instance to observe.
|
|
854
|
+
* @param options Configuration options for the observer.
|
|
855
|
+
*/
|
|
856
|
+
constructor(store: DataStore<T>, options?: ObserverOptions);
|
|
857
|
+
/**
|
|
858
|
+
* @private
|
|
859
|
+
* Centralized logging method. Routes to the structured logger for level-based calls
|
|
860
|
+
* (log, warn, error, debug) and to raw console for group/table calls which have no
|
|
861
|
+
* logger equivalent. Respects the `isSilent` flag.
|
|
862
|
+
* @param method The console method to call ('log', 'warn', 'error', 'group', 'groupEnd', 'table', 'debug').
|
|
863
|
+
* @param args Arguments to pass to the console/log method.
|
|
864
|
+
*/
|
|
865
|
+
private _consoleLog;
|
|
866
|
+
/**
|
|
867
|
+
* @private
|
|
868
|
+
* Sets up listeners for all relevant store events.
|
|
869
|
+
*/
|
|
870
|
+
private setupEventListeners;
|
|
871
|
+
/**
|
|
872
|
+
* @private
|
|
873
|
+
* Records a new state snapshot and manages the state history limit.
|
|
874
|
+
* @param deltas The state changes that led to this snapshot.
|
|
875
|
+
*/
|
|
876
|
+
private recordStateSnapshot;
|
|
877
|
+
/**
|
|
878
|
+
* @private
|
|
879
|
+
* Records a debug event and manages the event history limit.
|
|
880
|
+
* @param type The type of event.
|
|
881
|
+
* @param data The data payload of the event.
|
|
882
|
+
*/
|
|
883
|
+
private recordEvent;
|
|
884
|
+
/**
|
|
885
|
+
* Returns a cloned copy of the recorded event history.
|
|
886
|
+
* @returns Array of debug events.
|
|
887
|
+
*/
|
|
888
|
+
getEventHistory(): DebugEvent[];
|
|
889
|
+
/**
|
|
890
|
+
* Returns a cloned copy of the recorded state history (snapshots).
|
|
891
|
+
* @returns Array of state snapshots.
|
|
892
|
+
*/
|
|
893
|
+
getStateHistory(): Snapshot<T>[];
|
|
894
|
+
/**
|
|
895
|
+
* Returns middleware execution history from the state.
|
|
896
|
+
* @returns Array of middleware executions.
|
|
897
|
+
*/
|
|
898
|
+
getMiddlewareExecutions(): MiddlewareExecution[];
|
|
899
|
+
/**
|
|
900
|
+
* Returns current transaction status.
|
|
901
|
+
* @returns Object with transaction status information.
|
|
902
|
+
*/
|
|
903
|
+
getTransactionStatus(): {
|
|
904
|
+
activeTransactions: number;
|
|
905
|
+
activeBatches: string[];
|
|
906
|
+
};
|
|
907
|
+
/**
|
|
908
|
+
* Creates a standard middleware that logs all updates.
|
|
909
|
+
* @param options Options for the logging middleware.
|
|
910
|
+
* @returns A middleware function.
|
|
911
|
+
*/
|
|
912
|
+
createLoggingMiddleware(options?: {
|
|
913
|
+
logLevel?: "debug" | "info" | "warn";
|
|
914
|
+
logUpdates?: boolean;
|
|
915
|
+
}): (state: T, update: DeepPartial<T>) => DeepPartial<T>;
|
|
916
|
+
/**
|
|
917
|
+
* Creates a middleware that validates updates against a schema.
|
|
918
|
+
* Uses the internal `_consoleLog` for warnings.
|
|
919
|
+
* @param validator Function that validates updates.
|
|
920
|
+
* @returns A blocking middleware function.
|
|
921
|
+
*/
|
|
922
|
+
createValidationMiddleware(validator: (state: T, update: DeepPartial<T>) => boolean | {
|
|
923
|
+
valid: boolean;
|
|
924
|
+
reason?: string;
|
|
925
|
+
}): (state: T, update: DeepPartial<T>) => boolean;
|
|
926
|
+
/**
|
|
927
|
+
* Returns a simplified view of recent state changes.
|
|
928
|
+
* @param limit Maximum number of state changes to compare. Defaults to 5.
|
|
929
|
+
* @returns Array of state difference objects.
|
|
930
|
+
*/
|
|
931
|
+
getRecentChanges(limit?: number): Array<{
|
|
932
|
+
timestamp: number;
|
|
933
|
+
changedPaths: string[];
|
|
934
|
+
from: Partial<T>;
|
|
935
|
+
to: Partial<T>;
|
|
936
|
+
}>;
|
|
937
|
+
/**
|
|
938
|
+
* Clears both the event and state history, preserving only the initial state snapshot.
|
|
939
|
+
*/
|
|
940
|
+
clearHistory(): void;
|
|
941
|
+
/**
|
|
942
|
+
* Filters and returns events related to a specific action ID.
|
|
943
|
+
* @param actionId The ID of the action to filter by.
|
|
944
|
+
* @returns Array of debug events associated with the action.
|
|
945
|
+
*/
|
|
946
|
+
getHistoryForAction(actionId: string): DebugEvent[];
|
|
947
|
+
/**
|
|
948
|
+
* Attempts to replay a state update from history using the recorded update payload.
|
|
949
|
+
* @param eventIndex The index of the replayable event (an "update:start" event) in the history array.
|
|
950
|
+
*/
|
|
951
|
+
replay(eventIndex: number): Promise<void>;
|
|
952
|
+
/**
|
|
953
|
+
* Creates a time-travel utility object with undo/redo capabilities.
|
|
954
|
+
* @returns An object with methods for time-travel navigation.
|
|
955
|
+
*/
|
|
956
|
+
createTimeTravel(): {
|
|
957
|
+
canUndo: () => boolean;
|
|
958
|
+
canRedo: () => boolean;
|
|
959
|
+
undo: () => Promise<void>;
|
|
960
|
+
redo: () => Promise<void>;
|
|
961
|
+
length: () => number;
|
|
962
|
+
clear: () => void;
|
|
963
|
+
};
|
|
964
|
+
/**
|
|
965
|
+
* Saves the current observer session (events and state history) using a persistence mechanism.
|
|
966
|
+
* @param persistence An object implementing the SimplePersistence interface.
|
|
967
|
+
* @returns A promise that resolves to true if the session was saved successfully.
|
|
968
|
+
*/
|
|
969
|
+
saveSession(persistence: SimplePersistence$1<ObserverSessionData<T>>): Promise<boolean>;
|
|
970
|
+
/**
|
|
971
|
+
* Loads a previously saved observer session and restores the state to the latest saved snapshot.
|
|
972
|
+
* @param persistence An object implementing the SimplePersistence interface.
|
|
973
|
+
* @returns A promise that resolves to true if a session was loaded.
|
|
974
|
+
*/
|
|
975
|
+
loadSession(persistence: SimplePersistence$1<ObserverSessionData<T>>): Promise<boolean>;
|
|
976
|
+
/**
|
|
977
|
+
* Exports the current session data as a JSON file, initiating a browser download.
|
|
978
|
+
*/
|
|
979
|
+
exportSession(): void;
|
|
980
|
+
/**
|
|
981
|
+
* Imports a session from a JSON file, restoring event history and state.
|
|
982
|
+
* @param file The file object (e.g., from an <input type="file"> event) to import.
|
|
983
|
+
* @returns A promise that resolves when the import is complete.
|
|
984
|
+
*/
|
|
985
|
+
importSession(file: File): Promise<void>;
|
|
986
|
+
/**
|
|
987
|
+
* Cleans up the observer by unsubscribing all event listeners and clearing history.
|
|
988
|
+
*/
|
|
989
|
+
disconnect(): void;
|
|
990
|
+
/**
|
|
991
|
+
* @private
|
|
992
|
+
* Logs an event to the console with appropriate formatting.
|
|
993
|
+
* Uses `this._consoleLog` for all output.
|
|
994
|
+
* @param type Event type.
|
|
995
|
+
* @param data Event data.
|
|
996
|
+
*/
|
|
997
|
+
private _log;
|
|
998
|
+
/**
|
|
999
|
+
* @private
|
|
1000
|
+
* Checks for performance issues in the events.
|
|
1001
|
+
* Uses `this._consoleLog` for all output.
|
|
1002
|
+
* @param type Event type.
|
|
1003
|
+
* @param data Event data.
|
|
1004
|
+
*/
|
|
1005
|
+
private _checkPerformance;
|
|
1127
1006
|
}
|
|
1128
|
-
|
|
1007
|
+
//#endregion
|
|
1008
|
+
//#region src/store/diff.d.ts
|
|
1129
1009
|
/**
|
|
1130
1010
|
* Creates a diff function with configurable options.
|
|
1131
1011
|
*
|
|
@@ -1133,7 +1013,7 @@ declare class StoreObserver<T extends object> {
|
|
|
1133
1013
|
* @param {symbol} [options.deleteMarker] - A custom symbol to mark properties for deletion.
|
|
1134
1014
|
*/
|
|
1135
1015
|
declare function createDiff(options?: {
|
|
1136
|
-
|
|
1016
|
+
deleteMarker?: symbol;
|
|
1137
1017
|
}): any;
|
|
1138
1018
|
/**
|
|
1139
1019
|
* Creates a derivePaths function with configurable options.
|
|
@@ -1142,7 +1022,7 @@ declare function createDiff(options?: {
|
|
|
1142
1022
|
* @param {symbol} [options.deleteMarker=Symbol.for("delete")] - A custom symbol to mark properties for deletion.
|
|
1143
1023
|
*/
|
|
1144
1024
|
declare function createDerivePaths(options?: {
|
|
1145
|
-
|
|
1025
|
+
deleteMarker?: symbol;
|
|
1146
1026
|
}): <T>(changes: DeepPartial<T>) => string[];
|
|
1147
1027
|
/**
|
|
1148
1028
|
* @deprecated Use `createDiff()` instead.
|
|
@@ -1155,7 +1035,8 @@ type DiffFunction = ReturnType<typeof createDiff>;
|
|
|
1155
1035
|
* Provided for backward compatibility with `Symbol.for("delete")` as the default delete marker.
|
|
1156
1036
|
*/
|
|
1157
1037
|
declare const derivePaths: <T>(changes: DeepPartial<T>) => string[];
|
|
1158
|
-
|
|
1038
|
+
//#endregion
|
|
1039
|
+
//#region src/store/merge.d.ts
|
|
1159
1040
|
/**
|
|
1160
1041
|
* Creates a shallow clone of an object or array.
|
|
1161
1042
|
*/
|
|
@@ -1167,7 +1048,7 @@ declare const shallowClone: (obj: any) => any;
|
|
|
1167
1048
|
* @param {symbol} [options.deleteMarker=Symbol.for("delete")] - A custom symbol to mark properties for deletion during merge.
|
|
1168
1049
|
*/
|
|
1169
1050
|
declare function createMerge(options?: {
|
|
1170
|
-
|
|
1051
|
+
deleteMarker?: symbol;
|
|
1171
1052
|
}): <T extends object>(original: T, changes: DeepPartial<T> | symbol) => T;
|
|
1172
1053
|
/**
|
|
1173
1054
|
* @deprecated Use `createMerge()` instead.
|
|
@@ -1175,39 +1056,46 @@ declare function createMerge(options?: {
|
|
|
1175
1056
|
*/
|
|
1176
1057
|
declare const merge: <T extends object>(original: T, changes: DeepPartial<T> | symbol) => T;
|
|
1177
1058
|
type MergeFunction = ReturnType<typeof createMerge>;
|
|
1178
|
-
|
|
1059
|
+
//#endregion
|
|
1060
|
+
//#region src/store/actions.d.ts
|
|
1179
1061
|
declare class ActionCancelledError extends Error {
|
|
1180
|
-
|
|
1062
|
+
constructor();
|
|
1181
1063
|
}
|
|
1182
1064
|
declare class UnknownActionError extends Error {
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1065
|
+
constructor({
|
|
1066
|
+
action
|
|
1067
|
+
}: {
|
|
1068
|
+
action: string;
|
|
1069
|
+
});
|
|
1186
1070
|
}
|
|
1187
1071
|
declare class ActionManager<T extends object> {
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1072
|
+
private eventBus;
|
|
1073
|
+
private set;
|
|
1074
|
+
private registrations;
|
|
1075
|
+
constructor(eventBus: EventBus<Record<StoreEvent, any>>, set: (update: StateUpdater<T>, options?: {
|
|
1076
|
+
force?: boolean;
|
|
1077
|
+
actionId?: string;
|
|
1078
|
+
}) => Promise<any>);
|
|
1079
|
+
register<R extends any[]>(action: {
|
|
1080
|
+
name: string;
|
|
1081
|
+
fn: (state: T, ...args: R) => DeepPartial<T> | Promise<DeepPartial<T>>;
|
|
1082
|
+
debounce?: {
|
|
1083
|
+
delay: number;
|
|
1084
|
+
condition?: (previous: R | undefined, current: R) => boolean;
|
|
1085
|
+
};
|
|
1086
|
+
}): () => void;
|
|
1087
|
+
dispatch<R extends any[]>(name: string, ...params: R): Promise<T>;
|
|
1088
|
+
private executeAction;
|
|
1089
|
+
running(name: string): boolean;
|
|
1090
|
+
private subscribe;
|
|
1091
|
+
watch(name: string): {
|
|
1092
|
+
name: string;
|
|
1093
|
+
status: () => boolean;
|
|
1094
|
+
subscribe: (_: () => void) => () => void;
|
|
1095
|
+
};
|
|
1096
|
+
private notifyStatusListeners;
|
|
1097
|
+
private emit;
|
|
1098
|
+
dispose(): void;
|
|
1211
1099
|
}
|
|
1212
|
-
|
|
1213
|
-
export { ActionCancelledError,
|
|
1100
|
+
//#endregion
|
|
1101
|
+
export { ActionCancelledError, ActionCompletePayload, ActionErrorPayload, ActionManager, ActionStartPayload, ActionWatcher, BlockingMiddleware, DELETE_SYMBOL, DataStore, DeepPartial, DiffFunction, MergeFunction, Middleware, MiddlewareConfig, MiddlewareExecution, type ObserverOptions, PersistenceFailedPayload, PersistenceInitErrorPayload, PersistenceQueueClearedPayload, PersistenceQueuedPayload, PersistenceRetryPayload, PersistenceSuccessPayload, ReactiveDataStore, ReactiveDataStoreOptions, ReactiveSelector, SelectorAccessedPayload, SelectorChangedPayload, StateDelta, StateUpdater, StoreAction, StoreEvent, StoreEvents, StoreExecutionState, StoreLogger, StoreMetrics, StoreObserver, StoreRegistry, StoreRegistryOptions, type SubscribeOptions, TransactionOptions, TransformMiddleware, UnknownActionError, createDerivePaths, createDiff, createMerge, createStoreLogger, derivePaths, diff, merge, shallowClone };
|