@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.ts CHANGED
@@ -1,74 +1,9 @@
1
- /**
2
- * Interface defining the shape of the EventBus.
3
- * @template TEventMap - A record mapping event names to their respective payload types.
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
- /** The number of times the state has been successfully updated. */
87
- updateCount: number;
88
- /** The total number of listener functions executed in response to state changes. */
89
- listenerExecutions: number;
90
- /** The average time taken for a state update process to complete (in milliseconds). */
91
- averageUpdateTime: number;
92
- /** The size (e.g., number of paths changed) of the largest single state update. */
93
- largestUpdateSize: number;
94
- /** List of state paths that trigger the most listener executions. */
95
- mostActiveListenerPaths: string[];
96
- /** The total number of update attempts (including blocked ones). */
97
- totalUpdates: number;
98
- /** The number of updates that were blocked by blocking middleware. */
99
- blockedUpdates: number;
100
- /** The average duration of a state update cycle (in milliseconds). */
101
- averageUpdateDuration: number;
102
- /** The total number of middleware functions executed. */
103
- middlewareExecutions: number;
104
- /** The total number of transactions initiated. */
105
- transactionCount: number;
106
- /** The total number of store events fired. */
107
- totalEventsFired: number;
108
- /** The total number of actions dispatched. */
109
- totalActionsDispatched: number;
110
- /** The total number of actions that completed successfully. */
111
- totalActionsSucceeded: number;
112
- /** The total number of actions that failed with an error. */
113
- totalActionsFailed: number;
114
- /** The average duration of an action execution (in milliseconds). */
115
- averageActionDuration: number;
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
- /** Indicates if a state update process is currently executing. */
122
- executing: boolean;
123
- /** The changes (DeepPartial) currently being processed in the execution cycle. Null if none. */
124
- changes: DeepPartial<T> | null;
125
- /** A queue of pending state update functions/objects to be applied sequentially. */
126
- pendingChanges: Array<StateUpdater<T>>;
127
- /** Names of all currently registered middlewares. */
128
- middlewares: string[];
129
- /** Details of the middleware currently running. Null if none. */
130
- runningMiddleware: {
131
- id: string;
132
- name: string;
133
- startTime: number;
134
- } | null;
135
- /** Indicates if the store is currently within an active transaction block. */
136
- transactionActive: boolean;
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
- /** Unique identifier of the selector. */
147
- selectorId: string;
148
- /** The new computed result of the selector. */
149
- newResult: S;
150
- /** Timestamp of when the change occurred. */
151
- timestamp: number;
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
- [K in StoreEvent]: K extends "update:complete" ? {
159
- /** List of state changes (deltas) applied in the update. */
160
- deltas: StateDelta[];
161
- /** Total duration of the update process (in milliseconds). */
162
- duration: number;
163
- /** Timestamp of the update completion. */
164
- timestamp: number;
165
- /** Optional ID of the action that triggered the update. */
166
- actionId?: string;
167
- /** The resulting new state after the update (may be a partial/transformed state). */
168
- newState: any;
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
- /** Unique identifier of the selector. */
183
- selectorId: string;
184
- /** List of state paths accessed during the selector computation. */
185
- accessedPaths: string[];
186
- /** Duration of the selector computation (in milliseconds). */
187
- duration: number;
188
- /** Timestamp of the access. */
189
- timestamp: number;
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
- /** Unique identifier for the action execution. */
196
- actionId: string;
197
- /** Name of the action function. */
198
- name: string;
199
- /** The parameters passed to the action function. */
200
- params: any[];
201
- /** Timestamp of when the action execution started. */
202
- timestamp: number;
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
- /** Unique identifier for the action execution. */
209
- actionId: string;
210
- /** Name of the action function. */
211
- name: string;
212
- /** The parameters passed to the action function. */
213
- params: any[];
214
- /** Timestamp of when the action execution started. */
215
- startTime: number;
216
- /** Timestamp of when the action execution completed. */
217
- endTime: number;
218
- /** Total duration of the action execution (in milliseconds). */
219
- duration: number;
220
- /** The result returned by the action function. */
221
- result: any;
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
- /** Unique identifier for the action execution. */
228
- actionId: string;
229
- /** Name of the action function. */
230
- name: string;
231
- /** The parameters passed to the action function. */
232
- params: any[];
233
- /** Timestamp of when the action execution started. */
234
- startTime: number;
235
- /** Timestamp of when the action execution ended (with error). */
236
- endTime: number;
237
- /** Total duration of the action execution (in milliseconds). */
238
- duration: number;
239
- /** The error object. */
240
- error: any;
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
- /** Unique identifier for the middleware instance. */
253
- id: string;
254
- /** Name of the middleware. */
255
- name: string;
256
- /** Timestamp of when the middleware execution started. */
257
- startTime: number;
258
- /** Timestamp of when the middleware execution completed. */
259
- endTime: number;
260
- /** Total duration of the middleware execution (in milliseconds). */
261
- duration: number;
262
- /** True if the middleware blocked the update. */
263
- blocked: boolean;
264
- /** Error object if the middleware failed. */
265
- error?: Error;
266
- /** List of state changes (deltas) that resulted from this middleware's transformation. */
267
- deltas: StateDelta[];
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
- /** Dot-separated path to the changed property (e.g., "user.profile.name"). */
274
- path: string;
275
- /** The value of the property *before* the update. */
276
- oldValue: any;
277
- /** The value of the property *after* the update. */
278
- newValue: any;
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
- block: boolean;
307
- error?: Error;
230
+ block: boolean;
231
+ error?: Error;
308
232
  }> | boolean | {
309
- block: boolean;
310
- error?: Error;
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
- /** The middleware function (can be a transform or blocking middleware). */
317
- action: TransformMiddleware<T> | BlockingMiddleware<T>;
318
- /** An optional, human-readable name for the middleware. */
319
- name?: string;
320
- /** If true, the middleware is treated as a blocking middleware (must return a boolean or `{ block: boolean }`). */
321
- block?: boolean;
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
- /** Unique identifier for the selector. */
328
- id: string;
329
- /** Function to get the current computed value of the selector. */
330
- get: () => S;
331
- /**
332
- * Subscribes a callback function to run whenever the selector's result changes.
333
- * Returns an unsubscribe function.
334
- */
335
- subscribe: (callback: (state: S) => void) => () => void;
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
- /** Unique identifier for the action */
339
- name: string;
340
- /** Function to get the current computed value of the action. */
341
- status: () => boolean;
342
- /**
343
- * Subscribes a callback function to run whenever the action's status changes.
344
- * Returns an unsubscribe function.
345
- */
346
- subscribe: (callback: () => void) => () => void;
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
- /** If true, blocks resolution until changes are fully committed to the database row */
350
- flush?: boolean;
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
- * Gets the current state of the store.
359
- * @param clone If true, returns a deep clone of the state; otherwise, returns the internal state reference.
360
- * @returns The current state T.
361
- */
362
- get(clone?: boolean): T;
363
- /**
364
- * Gets a subset of the store.
365
- * @param paths The paths which to include in the returned object.
366
- * @param separator Optional separator for paths. Defaults to `.` .
367
- * @returns An object of the shape K mapping paths to their current values.
368
- */
369
- subset<K extends Record<string, any> = Record<string, any>>(paths: Array<string>, separator?: string): K;
370
- /**
371
- * Registers a named action function that can modify the state.
372
- * @param action The action configuration object.
373
- * @returns A function to unregister the action.
374
- */
375
- register<R extends any[]>(action: {
376
- name: string;
377
- fn: (state: T, ...args: R) => DeepPartial<T> | Promise<DeepPartial<T>>;
378
- debounce?: {
379
- delay: number;
380
- condition?: (previous: R, current: R) => boolean;
381
- };
382
- }): () => void;
383
- /**
384
- * Executes (dispatches) a previously registered action by its name.
385
- * @param name The name of the action.
386
- * @param args The parameters to pass to the action function.
387
- * @returns A promise that resolves to the final state after the action and subsequent updates are complete.
388
- */
389
- dispatch<R extends any[]>(name: string, ...args: R): Promise<T>;
390
- /**
391
- * Sets or updates the state using a StateUpdater.
392
- * @param update The new state, partial state, or a function returning a partial state.
393
- * @param options Configuration options for the set operation.
394
- * @returns A promise that resolves to the current state when the update is complete.
395
- */
396
- set(update: StateUpdater<T>, options?: {
397
- force?: boolean;
398
- actionId?: string;
399
- }): Promise<T>;
400
- /**
401
- * Creates a reactive selector that computes a derived value and tracks dependencies.
402
- * @param selector A function to compute the derived state value S from the full state T.
403
- * @returns A `ReactiveSelector<S>` object.
404
- */
405
- select<S>(selector: (state: T) => S): ReactiveSelector<S>;
406
- /**
407
- * Subscribes a callback to run when the data at the specified path(s) changes.
408
- * @param path A single path string or an array of path strings to watch.
409
- * @param callback The function to execute when a change occurs in the watched path(s).
410
- * @param options Extra options to pass to the event bus
411
- * @returns An unsubscribe function.
412
- */
413
- watch(path: string | Array<string>, callback: (state: T) => void, options?: SubscribeOptions): () => void;
414
- /**
415
- * Subscribes to execution‑status changes of a registered action.
416
- *
417
- * The provided callback is called **every time** the action transitions
418
- * between idle and running (i.e. on `action:start`, `action:complete`, or
419
- * `action:error` for the given name). The current status can also be read
420
- * synchronously with `isActionRunning(name)`.
421
- *
422
- * **Deferred listener teardown**
423
- * To avoid unnecessary churn when subscriptions are rapidly created and
424
- * destroyed, the underlying event listeners are not removed immediately
425
- * on unsubscribe. Instead, a *pending reset* is queued via `queueMicrotask`.
426
- * If a new subscription for the same action arrives before that microtask
427
- * executes, the reset is silently cancelled and the already‑established
428
- * listeners are reused. This keeps the subscription infrastructure stable
429
- * and prevents cascading notifications that could otherwise arise from
430
- * repeated subscribe‑unsubscribe‑subscribe cycles.
431
- *
432
- * @param name - The name of the action to watch.
433
- * @returns An ActionWatcher
434
- */
435
- watchAction(name: string): ActionWatcher;
436
- /**
437
- * Executes an operation function within a transaction block.
438
- * All state updates (`set` or actions) within the transaction are batched and applied atomically (all or nothing).
439
- * @param operation The function containing the state updates.
440
- * @returns A promise that resolves to the return value of the operation function.
441
- */
442
- transaction<R>(operation: () => R | Promise<R>, options?: TransactionOptions): Promise<R>;
443
- /**
444
- * Registers a middleware function to intercept state updates.
445
- * @param props The middleware configuration.
446
- * @returns A function to unregister the middleware.
447
- */
448
- use(props: MiddlewareConfig<T>): () => boolean;
449
- /**
450
- * Subscribes a listener to a specific store event type.
451
- * @param event The type of store event to listen for.
452
- * @param listener The callback function to execute when the event fires.
453
- * @returns An unsubscribe function.
454
- */
455
- on(event: StoreEvent, listener: (data: any) => void): () => void;
456
- /**
457
- * Returns the unique identifier of the store instance.
458
- */
459
- id(): string;
460
- /**
461
- * Checks whether the store is fully initialized and ready for use.
462
- */
463
- isReady(): boolean;
464
- /**
465
- * Returns a promise that resolves once the store is fully initialised.
466
- * Safe to call multiple times — all callers share the same latch.
467
- *
468
- * @param timeout - Optional maximum wait time in milliseconds.
469
- * @throws {TimeoutError} If the store does not become ready within the timeout.
470
- *
471
- * @example
472
- * await store.ready();
473
- * const state = store.get();
474
- */
475
- ready(timeout?: number): Promise<void>;
476
- /**
477
- * Returns a readonly snapshot of the current execution state of the store.
478
- */
479
- state(): Readonly<StoreExecutionState<T>>;
480
- /**
481
- * Releases all resources held by the store and renders it unusable
482
- */
483
- dispose(): Promise<void>;
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
- /** Unique ID for the persistence task. */
488
- taskId: string;
489
- /** Paths that were changed and triggered persistence. */
490
- changedPaths: string[];
491
- /** The current number of tasks waiting in the persistence queue. */
492
- queueSize: number;
493
- /** Timestamp of when the task was queued. */
494
- timestamp: number;
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
- /** Unique ID for the persistence task. */
499
- taskId: string;
500
- /** Paths that were successfully persisted. */
501
- changedPaths: string[];
502
- /** Duration of the persistence operation (in milliseconds). */
503
- duration: number;
504
- /** Timestamp of the success. */
505
- timestamp: number;
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
- /** Unique ID for the persistence task. */
510
- taskId: string;
511
- /** Current retry attempt number. */
512
- attempt: number;
513
- /** Maximum allowed retries. */
514
- maxRetries: number;
515
- /** Time until the next retry attempt (in milliseconds). */
516
- nextRetryIn: number;
517
- /** The error that triggered the retry. */
518
- error: any;
519
- /** Timestamp of the retry event. */
520
- timestamp: number;
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
- /** Unique ID for the persistence task. */
525
- taskId: string;
526
- /** Paths that failed to persist. */
527
- changedPaths: string[];
528
- /** Total number of attempts made. */
529
- attempts: number;
530
- /** The final error object. */
531
- error: any;
532
- /** Timestamp of the final failure. */
533
- timestamp: number;
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
- /** The number of persistence tasks that were cleared from the queue. */
538
- clearedTasks: number;
539
- /** Timestamp of when the queue was cleared. */
540
- timestamp: number;
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
- /** The error that occurred during persistence initialization. */
545
- error: any;
546
- /** Timestamp of the error. */
547
- timestamp: number;
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
- /** Unique identifier for the action definition. */
554
- id: string;
555
- /** Name of the action, used for dispatching. */
556
- name: string;
557
- /** The actual function that takes state and arguments, and returns a state update. */
558
- action: (state: T, ...args: R) => DeepPartial<T> | Promise<DeepPartial<T>>;
559
- /** Optional configuration for debouncing action execution. */
560
- debounce?: {
561
- /** Active timer reference, if debouncing */
562
- timer?: ReturnType<typeof setTimeout>;
563
- /** Debounce delay in milliseconds */
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
- interface SimplePersistence<T> {
576
- /**
577
- * Persists data to storage.
578
- *
579
- * @param id The **unique identifier of the *consumer instance*** making the change. This is NOT the ID of the data (`T`) itself.
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
- timeout?: number;
626
- state?: T;
627
- persistence?: SimplePersistence<T>;
628
- deleteMarker?: symbol;
629
- options?: {
630
- persistenceMaxRetries?: number;
631
- persistenceRetryDelay?: number;
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
- /** Manages the core application state. */
644
- private coreState;
645
- /** Orchestrates and executes middleware for state changes. */
646
- private middlewareEngine;
647
- /** Manages saving state changes to a persistence layer. */
648
- private persistenceHandler;
649
- /** Manages atomic state updates via transactions. */
650
- private transactionManager;
651
- /** Collects and provides performance metrics for the store. */
652
- private metricsCollector;
653
- private selectorManager;
654
- private actions;
655
- /**
656
- * Serializer enforces FIFO serial execution of all state updates.
657
- *
658
- * Replaces the bare `Promise<T | void>` chain. Benefits over the old pattern:
659
- * - Backpressure: rejects when the queue exceeds capacity rather than growing
660
- * unboundedly under write pressure.
661
- * - Clean shutdown: `close()` in dispose() immediately rejects any subsequent
662
- * `set()` calls with a clear error instead of silently enqueuing them.
663
- * - Observability: `updateSerializer.running()` and `updateSerializer.pending()`
664
- * replace the manually-managed `executionState.executing` flag.
665
- * - Error isolation: errors in one update do not corrupt the queue — the
666
- * Serializer's mutex is always released in its own `finally` block.
667
- */
668
- private updateSerializer;
669
- /**
670
- * Latch that opens once the store is fully initialised (persistence loaded).
671
- *
672
- * Replaces the poll-only `isReady(): boolean` pattern. Callers can now
673
- * `await store.ready()` with an optional timeout rather than polling or
674
- * subscribing to an internal event. `isReady()` is preserved as `latch.isOpen()`
675
- * for synchronous checks and backwards compatibility.
676
- */
677
- private readyLatch;
678
- private disposeOnce;
679
- private updateBus;
680
- private eventBus;
681
- private executionState;
682
- private instanceID;
683
- private merge;
684
- private diff;
685
- /**
686
- * Creates a new ReactiveDataStore instance.
687
- */
688
- constructor(initialData: T, persistence?: SimplePersistence<T>, deleteMarker?: symbol, options?: {
689
- persistenceMaxRetries?: number;
690
- persistenceRetryDelay?: number;
691
- broadcastChannel?: string;
692
- });
693
- /**
694
- * Returns true if the store has finished initialising (persistence loaded).
695
- * For async flows, prefer `await store.ready()` over polling this.
696
- */
697
- isReady(): boolean;
698
- /**
699
- * Returns a promise that resolves once the store is fully initialised.
700
- * Safe to call multiple times — all callers share the same latch.
701
- *
702
- * @param timeout - Optional maximum wait time in milliseconds.
703
- * @throws {TimeoutError} If the store does not become ready within the timeout.
704
- *
705
- * @example
706
- * await store.ready();
707
- * const state = store.get();
708
- */
709
- ready(timeout?: number): Promise<void>;
710
- state(): Readonly<StoreExecutionState<T>>;
711
- /**
712
- * Gets the current state. Optimized default to return reference (false) for performance.
713
- * @param clone If `true`, returns a deep clone (use sparingly).
714
- * @returns The current state object.
715
- */
716
- get(clone?: boolean): T;
717
- subset<K extends Record<string, any>>(paths: Array<string>, separator?: string): K;
718
- select<S>(selector: (state: T) => S): ReactiveSelector<S>;
719
- register<R extends any[]>(action: {
720
- name: string;
721
- fn: (state: T, ...args: R) => DeepPartial<T> | Promise<DeepPartial<T>>;
722
- debounce?: {
723
- delay: number;
724
- condition?: (previous: R | undefined, current: R) => boolean;
725
- };
726
- }): () => void;
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
- flush(): Promise<void>;
813
- /**
814
- * Discards all pending persistence tasks.
815
- * WARNING: Any queued writes not yet persisted will be lost.
816
- * Call flushPersistence() first if writes must not be lost.
817
- */
818
- discardPersistenceQueue(): void;
819
- /**
820
- * Disposes the store and all owned resources.
821
- *
822
- * Closes the update Serializer — any `set()` calls after dispose() will
823
- * reject immediately with `SerializerExecutionDone` rather than silently
824
- * enqueuing work against a dead store.
825
- */
826
- dispose(): Promise<void>;
827
- private checkDisposed;
828
- disposed(): boolean;
829
- private emit;
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
- * Optional callback fired when a store is actively garbage collected.
838
- * Highly recommended for production telemetry and memory leak debugging.
839
- */
840
- onEvict?: (storeId: string) => void;
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
- private readonly stores;
849
- private readonly storeToOnce;
850
- private readonly finalizer;
851
- private readonly onEvict?;
852
- constructor(options?: StoreRegistryOptions);
853
- /**
854
- * Get an existing store for storeId, or create a new one via an always-cached Once primitive.
855
- * Ensures only one instantiation occurs even under concurrent calls.
856
- * * @param storeId - Unique identifier for the store.
857
- * @param initialState - The initial state to seed the store if it is created.
858
- * @param timeout - Optional timeout (ms) for store initialization.
859
- */
860
- get(storeId: string, options?: ReactiveDataStoreOptions<S>): Promise<ReactiveDataStore<S>>;
861
- getSync(storeId: string, options?: ReactiveDataStoreOptions<S>): ReactiveDataStore<S>;
862
- /**
863
- * Manually remove a store registry entry, unregistering its finalizer and disposing it.
864
- * @param storeId - Unique identifier for the store.
865
- * @returns True if a store was actively removed, false otherwise.
866
- */
867
- release(storeId: string): Promise<boolean>;
868
- /**
869
- * Clears all stores from the registry, disposes them, and unregisters all finalizers.
870
- */
871
- clear(): Promise<void>;
872
- /**
873
- * Get the store if it exists and has successfully finished initialization.
874
- * Does not trigger initialization if the store is missing or pending.
875
- */
876
- has(storeId: string): boolean;
877
- /**
878
- * Returns the current number of tracked stores.
879
- * Note: This includes entries that may have lost external references but haven't been GC'd yet.
880
- */
881
- get size(): number;
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
- /** The type of store event (e.g., 'update:start', 'action:complete'). */
897
- type: string;
898
- /** The timestamp when the event occurred. */
899
- timestamp: number;
900
- /** The raw data payload associated with the event, including actionId where applicable. */
901
- data: any;
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
- /** The complete state object at the time of the snapshot. */
909
- state: T;
910
- /** The timestamp of the state change. */
911
- timestamp: number;
912
- /** The list of changes (deltas) that resulted in this state. */
913
- deltas: StateDelta[];
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
- /** The chronological history of debug events. */
921
- eventHistory: DebugEvent[];
922
- /** The chronological history of state snapshots. */
923
- stateHistory: Snapshot<T>[];
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
- /** Maximum number of events to retain in memory. Defaults to 500. */
931
- maxEvents?: number;
932
- /** Enables or disables console logging for all events (overridden by 'silent'). Defaults to false. */
933
- enableConsoleLogging?: boolean;
934
- /** Maximum number of state snapshots to retain for time-travel. Defaults to 20. */
935
- maxStateHistory?: number;
936
- /** Fine-grained control over which event types are logged to the console. */
937
- logEvents?: {
938
- updates?: boolean;
939
- middleware?: boolean;
940
- transactions?: boolean;
941
- actions?: boolean;
942
- selectors?: boolean;
943
- };
944
- /** Performance thresholds for triggering console warnings. Values are in milliseconds (ms). */
945
- performanceThresholds?: {
946
- updateTime?: number;
947
- middlewareTime?: number;
948
- };
949
- /** If true, suppresses all console output and logging regardless of other options. Defaults to false. */
950
- silent?: boolean;
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
- protected store: DataStore<T>;
959
- private eventHistory;
960
- private stateHistory;
961
- private unsubscribers;
962
- private isTimeTraveling;
963
- private devTools;
964
- private middlewareExecutions;
965
- private activeTransactionCount;
966
- private activeBatches;
967
- private maxEvents;
968
- private maxStateHistory;
969
- private enableConsoleLogging;
970
- private isSilent;
971
- private logEvents;
972
- private performanceThresholds;
973
- /**
974
- * @param store The DataStore instance to observe.
975
- * @param options Configuration options for the observer.
976
- */
977
- constructor(store: DataStore<T>, options?: ObserverOptions);
978
- /**
979
- * @private
980
- * Centralized logging method. All console output must go through here to respect the `isSilent` flag.
981
- * @param method The console method to call ('log', 'warn', 'error', 'group', 'groupEnd', 'table', 'debug').
982
- * @param args Arguments to pass to the console method.
983
- */
984
- private _consoleLog;
985
- /**
986
- * @private
987
- * Sets up listeners for all relevant store events.
988
- */
989
- private setupEventListeners;
990
- /**
991
- * @private
992
- * Records a new state snapshot and manages the state history limit.
993
- * @param deltas The state changes that led to this snapshot.
994
- */
995
- private recordStateSnapshot;
996
- /**
997
- * @private
998
- * Records a debug event and manages the event history limit.
999
- * @param type The type of event.
1000
- * @param data The data payload of the event.
1001
- */
1002
- private recordEvent;
1003
- /**
1004
- * Returns a cloned copy of the recorded event history.
1005
- * @returns Array of debug events.
1006
- */
1007
- getEventHistory(): DebugEvent[];
1008
- /**
1009
- * Returns a cloned copy of the recorded state history (snapshots).
1010
- * @returns Array of state snapshots.
1011
- */
1012
- getStateHistory(): Snapshot<T>[];
1013
- /**
1014
- * Returns middleware execution history from the state.
1015
- * @returns Array of middleware executions.
1016
- */
1017
- getMiddlewareExecutions(): MiddlewareExecution[];
1018
- /**
1019
- * Returns current transaction status.
1020
- * @returns Object with transaction status information.
1021
- */
1022
- getTransactionStatus(): {
1023
- activeTransactions: number;
1024
- activeBatches: string[];
1025
- };
1026
- /**
1027
- * Creates a standard middleware that logs all updates.
1028
- * NOTE: This is user-defined middleware and uses native console methods,
1029
- * so its output is independent of the observer's `silent` flag.
1030
- * @param options Options for the logging middleware.
1031
- * @returns A middleware function.
1032
- */
1033
- createLoggingMiddleware(options?: {
1034
- logLevel?: "debug" | "info" | "warn";
1035
- logUpdates?: boolean;
1036
- }): (state: T, update: DeepPartial<T>) => DeepPartial<T>;
1037
- /**
1038
- * Creates a middleware that validates updates against a schema.
1039
- * Uses the internal `_consoleLog` for warnings.
1040
- * @param validator Function that validates updates.
1041
- * @returns A blocking middleware function.
1042
- */
1043
- createValidationMiddleware(validator: (state: T, update: DeepPartial<T>) => boolean | {
1044
- valid: boolean;
1045
- reason?: string;
1046
- }): (state: T, update: DeepPartial<T>) => boolean;
1047
- /**
1048
- * Returns a simplified view of recent state changes.
1049
- * @param limit Maximum number of state changes to compare. Defaults to 5.
1050
- * @returns Array of state difference objects.
1051
- */
1052
- getRecentChanges(limit?: number): Array<{
1053
- timestamp: number;
1054
- changedPaths: string[];
1055
- from: Partial<T>;
1056
- to: Partial<T>;
1057
- }>;
1058
- /**
1059
- * Clears both the event and state history, preserving only the initial state snapshot.
1060
- */
1061
- clearHistory(): void;
1062
- /**
1063
- * Filters and returns events related to a specific action ID.
1064
- * @param actionId The ID of the action to filter by.
1065
- * @returns Array of debug events associated with the action.
1066
- */
1067
- getHistoryForAction(actionId: string): DebugEvent[];
1068
- /**
1069
- * Attempts to replay a state update from history using the recorded update payload.
1070
- * @param eventIndex The index of the replayable event (an "update:start" event) in the history array.
1071
- */
1072
- replay(eventIndex: number): Promise<void>;
1073
- /**
1074
- * Creates a time-travel utility object with undo/redo capabilities.
1075
- * @returns An object with methods for time-travel navigation.
1076
- */
1077
- createTimeTravel(): {
1078
- canUndo: () => boolean;
1079
- canRedo: () => boolean;
1080
- undo: () => Promise<void>;
1081
- redo: () => Promise<void>;
1082
- length: () => number;
1083
- clear: () => void;
1084
- };
1085
- /**
1086
- * Saves the current observer session (events and state history) using a persistence mechanism.
1087
- * @param persistence An object implementing the SimplePersistence interface.
1088
- * @returns A promise that resolves to true if the session was saved successfully.
1089
- */
1090
- saveSession(persistence: SimplePersistence<ObserverSessionData<T>>): Promise<boolean>;
1091
- /**
1092
- * Loads a previously saved observer session and restores the state to the latest saved snapshot.
1093
- * @param persistence An object implementing the SimplePersistence interface.
1094
- * @returns A promise that resolves to true if a session was loaded.
1095
- */
1096
- loadSession(persistence: SimplePersistence<ObserverSessionData<T>>): Promise<boolean>;
1097
- /**
1098
- * Exports the current session data as a JSON file, initiating a browser download.
1099
- */
1100
- exportSession(): void;
1101
- /**
1102
- * Imports a session from a JSON file, restoring event history and state.
1103
- * @param file The file object (e.g., from an <input type="file"> event) to import.
1104
- * @returns A promise that resolves when the import is complete.
1105
- */
1106
- importSession(file: File): Promise<void>;
1107
- /**
1108
- * Cleans up the observer by unsubscribing all event listeners and clearing history.
1109
- */
1110
- disconnect(): void;
1111
- /**
1112
- * @private
1113
- * Logs an event to the console with appropriate formatting.
1114
- * Uses `this._consoleLog` for all output.
1115
- * @param type Event type.
1116
- * @param data Event data.
1117
- */
1118
- private _log;
1119
- /**
1120
- * @private
1121
- * Checks for performance issues in the events.
1122
- * Uses `this._consoleLog` for all output.
1123
- * @param type Event type.
1124
- * @param data Event data.
1125
- */
1126
- private _checkPerformance;
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
- deleteMarker?: symbol;
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
- deleteMarker?: symbol;
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
- deleteMarker?: symbol;
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
- constructor();
1062
+ constructor();
1181
1063
  }
1182
1064
  declare class UnknownActionError extends Error {
1183
- constructor({ action }: {
1184
- action: string;
1185
- });
1065
+ constructor({
1066
+ action
1067
+ }: {
1068
+ action: string;
1069
+ });
1186
1070
  }
1187
1071
  declare class ActionManager<T extends object> {
1188
- private eventBus;
1189
- private set;
1190
- private registrations;
1191
- constructor(eventBus: EventBus<Record<StoreEvent, any>>, set: (update: StateUpdater<T>, options?: {
1192
- force?: boolean;
1193
- actionId?: string;
1194
- }) => Promise<any>);
1195
- register<R extends any[]>(action: {
1196
- name: string;
1197
- fn: (state: T, ...args: R) => DeepPartial<T> | Promise<DeepPartial<T>>;
1198
- debounce?: {
1199
- delay: number;
1200
- condition?: (previous: R | undefined, current: R) => boolean;
1201
- };
1202
- }): () => void;
1203
- dispatch<R extends any[]>(name: string, ...params: R): Promise<T>;
1204
- private executeAction;
1205
- running(name: string): boolean;
1206
- private subscribe;
1207
- watch(name: string): ActionWatcher;
1208
- private notifyStatusListeners;
1209
- private emit;
1210
- dispose(): void;
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, type ActionCompletePayload, type ActionErrorPayload, ActionManager, type ActionStartPayload, type ActionWatcher, type BlockingMiddleware, DELETE_SYMBOL, type DataStore, type DeepPartial, type DiffFunction, type MergeFunction, type Middleware, type MiddlewareConfig, type MiddlewareExecution, type ObserverOptions, type PersistenceFailedPayload, type PersistenceInitErrorPayload, type PersistenceQueueClearedPayload, type PersistenceQueuedPayload, type PersistenceRetryPayload, type PersistenceSuccessPayload, ReactiveDataStore, type ReactiveDataStoreOptions, type ReactiveSelector, type SelectorAccessedPayload, type SelectorChangedPayload, type StateDelta, type StateUpdater, type StoreAction, type StoreEvent, type StoreEvents, type StoreExecutionState, type StoreMetrics, StoreObserver, StoreRegistry, type StoreRegistryOptions, type SubscribeOptions, type TransactionOptions, type TransformMiddleware, UnknownActionError, createDerivePaths, createDiff, createMerge, derivePaths, diff, merge, shallowClone };
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 };