@asaidimu/utils-store 2.3.2 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.mts CHANGED
@@ -1,3 +1,6 @@
1
+ import { EventBus } from '@asaidimu/events';
2
+ import { SimplePersistence as SimplePersistence$1 } from '@asaidimu/utils-persistence';
3
+
1
4
  interface SimplePersistence<T> {
2
5
  /**
3
6
  * Persists data to storage.
@@ -53,6 +56,26 @@ interface SimplePersistence<T> {
53
56
  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 : {
54
57
  [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> | undefined : T[K] | undefined;
55
58
  } | undefined | T : T | undefined;
59
+ /**
60
+ * Interface for performance metrics of the state.
61
+ */
62
+ interface StoreMetrics {
63
+ updateCount: number;
64
+ listenerExecutions: number;
65
+ averageUpdateTime: number;
66
+ largestUpdateSize: number;
67
+ mostActiveListenerPaths: string[];
68
+ totalUpdates: number;
69
+ blockedUpdates: number;
70
+ averageUpdateDuration: number;
71
+ middlewareExecutions: number;
72
+ transactionCount: number;
73
+ totalEventsFired: number;
74
+ totalActionsDispatched: number;
75
+ totalActionsSucceeded: number;
76
+ totalActionsFailed: number;
77
+ averageActionDuration: number;
78
+ }
56
79
  /**
57
80
  * Extended store state for monitoring execution status
58
81
  */
@@ -71,7 +94,56 @@ interface StoreExecutionState<T> {
71
94
  /**
72
95
  * Event types emitted by the state for observability
73
96
  */
74
- type StoreEvent = "update:start" | "update:complete" | "middleware:start" | "middleware:complete" | "middleware:error" | "middleware:blocked" | "middleware:executed" | "transaction:start" | "transaction:complete" | "transaction:error" | "persistence:ready" | "persistence:queued" | "persistence:success" | "persistence:retry" | "persistence:failed" | "persistence:queue_cleared" | "persistence:init_error";
97
+ type StoreEvent = "update:start" | "update:complete" | "middleware:start" | "middleware:complete" | "middleware:error" | "middleware:blocked" | "middleware:executed" | "transaction:start" | "transaction:complete" | "transaction:error" | "persistence:ready" | "persistence:queued" | "persistence:success" | "persistence:retry" | "persistence:failed" | "persistence:queue_cleared" | "persistence:init_error" | "action:start" | "action:complete" | "action:error" | "selector:accessed" | "selector:changed";
98
+ interface SelectorChangedPayload<S> {
99
+ selectorId: string;
100
+ newResult: S;
101
+ timestamp: number;
102
+ }
103
+ type StoreEvents = {
104
+ [K in StoreEvent]: K extends "update:complete" ? {
105
+ deltas: StateDelta[];
106
+ duration: number;
107
+ timestamp: number;
108
+ actionId?: string;
109
+ newState: any;
110
+ blocked?: boolean;
111
+ error?: any;
112
+ } : 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" ? {
113
+ transactionId: string;
114
+ timestamp: number;
115
+ } : 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;
116
+ };
117
+ interface SelectorAccessedPayload {
118
+ selectorId: string;
119
+ accessedPaths: string[];
120
+ duration: number;
121
+ timestamp: number;
122
+ }
123
+ interface ActionStartPayload {
124
+ actionId: string;
125
+ name: string;
126
+ params: any[];
127
+ timestamp: number;
128
+ }
129
+ interface ActionCompletePayload {
130
+ actionId: string;
131
+ name: string;
132
+ params: any[];
133
+ startTime: number;
134
+ endTime: number;
135
+ duration: number;
136
+ result: any;
137
+ }
138
+ interface ActionErrorPayload {
139
+ actionId: string;
140
+ name: string;
141
+ params: any[];
142
+ startTime: number;
143
+ endTime: number;
144
+ duration: number;
145
+ error: any;
146
+ }
75
147
  /**
76
148
  * Type for middleware functions. Return a partial state to transform the update.
77
149
  */
@@ -87,7 +159,12 @@ interface MiddlewareExecution {
87
159
  duration: number;
88
160
  blocked: boolean;
89
161
  error?: Error;
90
- changedPaths: string[];
162
+ deltas: StateDelta[];
163
+ }
164
+ interface StateDelta {
165
+ path: string;
166
+ oldValue: any;
167
+ newValue: any;
91
168
  }
92
169
  /**
93
170
  * Represents a state update, which can be either a partial state object or a function.
@@ -116,44 +193,42 @@ interface MiddlewareConfig<T> {
116
193
  name?: string;
117
194
  block?: boolean;
118
195
  }
119
- /**
120
- * Interface for performance metrics of the state.
121
- */
122
- interface StoreMetrics {
123
- updateCount: number;
124
- listenerExecutions: number;
125
- averageUpdateTime: number;
126
- largestUpdateSize: number;
127
- mostActiveListenerPaths: string[];
128
- }
129
- interface StoreMetrics {
130
- totalUpdates: number;
131
- blockedUpdates: number;
132
- listenerExecutions: number;
133
- averageUpdateDuration: number;
134
- middlewareExecutions: number;
135
- transactionCount: number;
136
- totalEventsFired: number;
137
- }
138
- interface DataStore<T extends object> {
139
- get(clone?: boolean): T;
140
- set(update: StateUpdater<T>): Promise<void>;
141
- subscribe(path: string, listener: (state: T) => void): () => void;
142
- transaction<R>(operation: () => R | Promise<R>): Promise<R>;
143
- metrics(): StoreMetrics;
144
- onStoreEvent(event: StoreEvent, listener: (data: any) => void): () => void;
196
+ interface ReactiveSelector<S> {
197
+ id: string;
198
+ get: () => S;
199
+ subscribe: (callback: (state: S) => void) => () => void;
145
200
  }
146
201
  /**
147
202
  * Interface defining the contract for the data state.
148
203
  */
149
204
  interface DataStore<T extends object> {
150
205
  get(clone?: boolean): T;
151
- set(update: StateUpdater<T>): Promise<void>;
206
+ register<R extends any[]>(action: {
207
+ name: string;
208
+ fn: (state: T, ...args: R) => DeepPartial<T> | Promise<DeepPartial<T>>;
209
+ debounce?: {
210
+ delay: number;
211
+ condition?: (previous: R, current: R) => boolean;
212
+ };
213
+ }): () => void;
214
+ dispatch<R extends any[]>(name: string, ...args: R): Promise<T>;
215
+ set(update: StateUpdater<T>, options?: {
216
+ force?: boolean;
217
+ actionId?: string;
218
+ }): Promise<any>;
219
+ select<S>(selector: (state: T) => S): ReactiveSelector<S>;
220
+ /** @deprecated
221
+ * Use watch instead will be removed in next major version
222
+ * **/
152
223
  subscribe(path: string | Array<string>, callback: (state: T) => void): () => void;
224
+ watch(path: string | Array<string>, callback: (state: T) => void): () => void;
153
225
  transaction<R>(operation: () => R | Promise<R>): Promise<R>;
154
- use(props: MiddlewareConfig<T>): string;
155
- unuse(id: string): boolean;
226
+ use(props: MiddlewareConfig<T>): () => boolean;
227
+ /** @deprecated
228
+ * Use on instead will be removed in next majow version
229
+ * **/
156
230
  onStoreEvent(event: StoreEvent, listener: (data: any) => void): () => void;
231
+ on(event: StoreEvent, listener: (data: any) => void): () => void;
157
232
  id(): string;
158
233
  isReady(): boolean;
159
234
  state(): Readonly<StoreExecutionState<T>>;
@@ -193,18 +268,34 @@ interface PersistenceInitErrorPayload {
193
268
  error: any;
194
269
  timestamp: number;
195
270
  }
196
- declare const author = "https://github.com/asaidimu";
271
+ type StoreAction<T, R extends any[] = any[]> = {
272
+ id: string;
273
+ name: string;
274
+ action: (state: T, ...args: R) => DeepPartial<T> | Promise<DeepPartial<T>>;
275
+ debounce?: {
276
+ /** Active timer reference, if debouncing */
277
+ timer?: ReturnType<typeof setTimeout>;
278
+ /** Debounce delay in milliseconds */
279
+ delay: number;
280
+ /** Optional condition to decide whether to debounce based on previous vs current args */
281
+ condition?: (previous: R | undefined, current: R) => boolean;
282
+ /** Last call’s arguments, used for condition checks */
283
+ args?: R;
284
+ /** Internal promise resolvers to prevent memory leaks */
285
+ resolve?: (value: any) => void;
286
+ reject?: (reason?: any) => void;
287
+ };
288
+ };
197
289
 
198
290
  /**
199
- * Reactive Data Store Implementation
200
- * A type-safe reactive data state for managing complex application state.
201
- * Arrays are treated as primitive values (stored and updated as whole units).
291
+ * Reactive Data Store Implementation - Updated for Concurrency and Performance
292
+ * The public API is preserved for test compatibility.
202
293
  */
203
294
 
204
295
  /**
205
296
  * Main ReactiveDataStore - a robust, type-safe state management solution.
206
- * It features optimistic updates for a responsive user experience and
207
- * handles data persistence in the background.
297
+ * It features optimistic updates, a promise-based update queue for serial execution,
298
+ * and decoupled persistence.
208
299
  *
209
300
  * @template T The type of the data object managed by the store.
210
301
  */
@@ -219,278 +310,359 @@ declare class ReactiveDataStore<T extends object> implements DataStore<T> {
219
310
  private transactionManager;
220
311
  /** Collects and provides performance metrics for the store. */
221
312
  private metricsCollector;
222
- /** Queue for pending state updates when the store is busy. */
223
- private pendingUpdates;
224
- /** Flag to prevent concurrent updates. */
225
- private isUpdating;
226
- /** Event bus for notifying subscribers of state updates. */
313
+ private selectorManager;
314
+ private actionManager;
315
+ /**
316
+ * Promise chain to enforce serial, non-recursive execution
317
+ * of all state updates.
318
+ */
319
+ private updateQueue;
227
320
  private updateBus;
228
- /** General event bus for broadcasting internal store events. */
229
321
  private eventBus;
230
- /** Represents the current execution state of the store. */
231
322
  private executionState;
232
- /** A unique identifier for this store instance. */
233
323
  private instanceID;
234
- /** Function to deeply merge partial state updates. */
235
324
  private merge;
236
- /** Function to calculate the difference between two state objects. */
237
325
  private diff;
238
326
  /**
239
327
  * Creates a new ReactiveDataStore instance.
240
- *
241
- * @param initialData The initial state of the data store.
242
- * @param persistence An optional persistence handler for saving state.
243
- * @param deleteMarker A symbol used to mark properties for deletion.
244
- * @param options Configuration options for the store.
245
328
  */
246
329
  constructor(initialData: T, persistence?: SimplePersistence<T>, deleteMarker?: symbol, options?: {
247
330
  persistenceMaxRetries?: number;
248
331
  persistenceRetryDelay?: number;
249
332
  });
250
- /**
251
- * Checks if the persistence layer is ready to save data.
252
- *
253
- * @returns `true` if ready, otherwise `false`.
254
- */
255
333
  isReady(): boolean;
256
- /**
257
- * Returns the current read-only execution state of the store.
258
- */
259
334
  state(): Readonly<StoreExecutionState<T>>;
260
335
  /**
261
- * Gets the current state of the data store.
262
- *
263
- * @param clone If `true`, returns a deep clone of the state to prevent direct modification.
336
+ * Gets the current state. Optimized default to return reference (false) for performance.
337
+ * @param clone If `true`, returns a deep clone (use sparingly).
264
338
  * @returns The current state object.
265
339
  */
266
340
  get(clone?: boolean): T;
341
+ select<S>(selector: (state: T) => S): ReactiveSelector<S>;
342
+ register<R extends any[]>(action: {
343
+ name: string;
344
+ fn: (state: T, ...args: R) => DeepPartial<T> | Promise<DeepPartial<T>>;
345
+ debounce?: {
346
+ delay: number;
347
+ condition?: (previous: R | undefined, current: R) => boolean;
348
+ };
349
+ }): () => void;
350
+ dispatch<R extends any[]>(name: string, ...params: R): Promise<T>;
351
+ /**
352
+ * Optimized method to update the state.
353
+ * Uses the Promise Queue to guarantee sequential execution.
354
+ * @returns A Promise that resolves with the new state T.
355
+ */
356
+ set(update: StateUpdater<T>, options?: {
357
+ force?: boolean;
358
+ actionId?: string;
359
+ }): Promise<any>;
360
+ /**
361
+ * Internal logic for performing a single, sequential state update.
362
+ */
363
+ private _performUpdate;
364
+ private setupPersistenceListener;
365
+ watch(path: string | Array<string>, callback: (state: T) => void): () => void;
366
+ /** @deprecated **/
367
+ subscribe(path: string | Array<string>, callback: (state: T) => void): () => void;
368
+ id(): string;
369
+ transaction<R>(operation: () => R | Promise<R>): Promise<R>;
370
+ use(props: MiddlewareConfig<T>): () => boolean;
371
+ metrics(): StoreMetrics;
372
+ on(event: StoreEvent, listener: (data: any) => void): () => void;
373
+ /** @deprecated */
374
+ onStoreEvent(event: StoreEvent, listener: (data: any) => void): () => void;
375
+ getPersistenceStatus(): {
376
+ queueSize: number;
377
+ isProcessing: boolean;
378
+ oldestTask?: number;
379
+ };
380
+ flushPersistence(): Promise<void>;
381
+ clearPersistenceQueue(): void;
382
+ dispose(): void;
383
+ private emit;
384
+ }
385
+
386
+ /**
387
+ * Defines the lifecycle scope of an artifact.
388
+ */
389
+ declare enum ArtifactScope {
390
+ Singleton = "singleton",// Created once, cached, tracks dependencies
391
+ Transient = "transient"
392
+ }
393
+ /**
394
+ * Dependency resolution context provided to the use() callback.
395
+ */
396
+ interface UseDependencyContext<TState extends object> {
267
397
  /**
268
- * Optimized method to update the state. It handles optimistic updates by
269
- * applying changes immediately and persisting them in the background.
270
- * Middleware is executed before and after the update.
271
- *
272
- * If another update is in progress, the new update is queued.
273
- *
274
- * @param update A partial state object or a function that returns a partial state object.
398
+ * Resolve another artifact.
399
+ * This records a dependency between the caller and the requested artifact.
275
400
  */
276
- set(update: StateUpdater<T>): Promise<void>;
401
+ resolve<TArtifact>(key: string): Promise<TArtifact>;
277
402
  /**
278
- * Subscribes a callback function to state changes at a specific path.
279
- * The callback is triggered only when the specified path changes.
280
- *
281
- * @param path The path or array of paths to subscribe to.
282
- * @param callback The function to call when the state at the path changes.
283
- * @returns A function to unsubscribe the callback.
403
+ * Select a slice of state.
404
+ * This records a dependency between the artifact and the specific state paths.
284
405
  */
285
- subscribe(path: string | Array<string>, callback: (state: T) => void): () => void;
406
+ select<S>(selector: (state: TState) => S): S;
407
+ }
408
+ /**
409
+ * The context object provided to an artifact's factory function.
410
+ */
411
+ interface ArtifactFactoryContext<TState extends object> {
286
412
  /**
287
- * Gets the unique identifier for this store instance.
288
- *
289
- * @returns The instance ID as a string.
413
+ * Get the current state snapshot immediately.
414
+ * WARNING: Calling this does NOT create a subscription.
415
+ * Use ctx.use(c => c.select(...)) for reactive behavior.
290
416
  */
291
- id(): string;
417
+ state(): TState;
292
418
  /**
293
- * Executes a series of state updates atomically within a single transaction.
294
- *
295
- * @param operation A function containing the state updates to be performed.
296
- * @returns The result of the operation.
419
+ * The existing instance if being re-evaluated.
420
+ * Useful for preserving internal state (like connections) during hot-swaps.
297
421
  */
298
- transaction<R>(operation: () => R | Promise<R>): Promise<R>;
422
+ current?: unknown;
299
423
  /**
300
- * Adds a middleware function to the store.
301
- *
302
- * @param props The middleware configuration.
303
- * @returns A unique ID for the added middleware.
424
+ * Execute a callback to capture dependencies.
425
+ * All resolve() and select() calls inside this callback are recorded
426
+ * to build the dependency graph for this artifact.
304
427
  */
305
- use(props: MiddlewareConfig<T>): string;
428
+ use<K>(callback: (ctx: UseDependencyContext<TState>) => K | Promise<K>): Promise<K>;
429
+ }
430
+ /**
431
+ * Cleanup function type.
432
+ */
433
+ type ArtifactCleanup = () => void | Promise<void>;
434
+ /**
435
+ * Represents the output of an artifact factory:
436
+ * either the artifact instance itself, or a tuple [instance, cleanup].
437
+ */
438
+ type ArtifactResult<T> = T | [T, ArtifactCleanup];
439
+ /**
440
+ * A factory function that creates an instance of an artifact.
441
+ */
442
+ type ArtifactFactory<TState extends object, TArtifact> = (context: ArtifactFactoryContext<TState>) => ArtifactResult<TArtifact> | Promise<ArtifactResult<TArtifact>>;
443
+ declare class ArtifactContainer<TState extends object> {
444
+ private readonly artifacts;
445
+ private readonly resolvingStack;
446
+ private readonly listeners;
447
+ private readonly getState;
448
+ private readonly subscribe;
306
449
  /**
307
- * Removes a middleware function by its unique ID.
308
- *
309
- * @param id The ID of the middleware to remove.
310
- * @returns `true` if the middleware was successfully removed, `false` otherwise.
450
+ * @param getState Function to retrieve current state snapshot
451
+ * @param subscribe Function to subscribe to path changes. Must return an unsubscribe function.
311
452
  */
312
- unuse(id: string): boolean;
453
+ constructor(props: Pick<DataStore<TState>, "watch" | "get">);
454
+ subscribeToArtifact(key: string, callback: () => void): () => void;
455
+ get(key: string): any | undefined;
456
+ private notifyListeners;
313
457
  /**
314
- * Get the performance metrics for the store.
315
- * @deprecated WILL BE REMOVED in a future version.
458
+ * Registers an artifact.
459
+ * @returns A function to unregister the artifact.
316
460
  */
317
- metrics(): StoreMetrics;
461
+ register<TArtifact>(options: {
462
+ key: string;
463
+ factory: ArtifactFactory<TState, TArtifact>;
464
+ scope?: ArtifactScope;
465
+ lazy?: boolean;
466
+ }): () => void;
467
+ unregister(key: string): Promise<void>;
318
468
  /**
319
- * Subscribes a listener to a specific store event.
320
- *
321
- * @param event The name of the event to listen for.
322
- * @param listener The callback function to execute when the event is emitted.
323
- * @returns A function to unsubscribe the listener.
469
+ * Resolves an artifact instance.
324
470
  */
325
- onStoreEvent(event: StoreEvent, listener: (data: any) => void): () => void;
471
+ resolve<TArtifact>(key: string): Promise<TArtifact>;
326
472
  /**
327
- * Get the current status of the persistence queue.
328
- *
329
- * @returns An object containing the queue size, processing status, and the age of the oldest task.
473
+ * Internal: Executes the factory and captures dependencies into provided Sets.
330
474
  */
331
- getPersistenceStatus(): {
332
- queueSize: number;
333
- isProcessing: boolean;
334
- oldestTask?: number;
335
- };
475
+ private createArtifactInstance;
336
476
  /**
337
- * Forces immediate processing of any pending persistence operations.
477
+ * Updates the dependency graph and state subscriptions after a successful creation.
338
478
  */
339
- flushPersistence(): Promise<void>;
479
+ private updateGraph;
340
480
  /**
341
- * Clears all pending persistence operations from the queue.
481
+ * Cascading invalidation logic.
482
+ * Destroys the artifact, destroys dependents, then rebuilds eager artifacts.
342
483
  */
343
- clearPersistenceQueue(): void;
484
+ private invalidate;
344
485
  /**
345
- * Cleans up resources, such as event listeners, to prevent memory leaks.
486
+ * Cleans up a specific artifact definition's instance and subscriptions.
487
+ * Keeps the definition registered.
346
488
  */
347
- dispose(): void;
489
+ private disposeInstance;
348
490
  /**
349
- * A private utility method to emit an event on a given event bus.
350
- * Uses `queueMicrotask` to ensure events are emitted asynchronously after the current call stack clears.
351
- *
352
- * @param bus The event bus to emit the event on.
353
- * @param event The event object to emit.
491
+ * Fully removes an artifact from the system.
354
492
  */
355
- private emit;
493
+ private disposeArtifact;
494
+ private detectCycles;
495
+ dispose(): void;
496
+ isLoading(key: string): boolean;
356
497
  }
357
498
 
358
499
  /**
359
- * Store Observability Module
360
- * A separate module to add debugging and observability capabilities to the ReactiveDataStore.
500
+ * @fileoverview Store Observer Module
501
+ * @description A comprehensive module to add advanced debugging, observability, and time-travel
502
+ * capabilities to a ReactiveDataStore. All console logging is centralized to respect a 'silent' flag,
503
+ * preventing test runner output pollution.
361
504
  */
362
505
 
363
506
  /**
364
- * Interface for debug event structure
507
+ * @interface DebugEvent
508
+ * @description Interface for the structure of a recorded debug event.
365
509
  */
366
510
  interface DebugEvent {
511
+ /** The type of store event (e.g., 'update:start', 'action:complete'). */
367
512
  type: string;
513
+ /** The timestamp when the event occurred. */
368
514
  timestamp: number;
515
+ /** The raw data payload associated with the event, including actionId where applicable. */
369
516
  data: any;
370
517
  }
371
518
  /**
372
- * Configuration options for the observability module
519
+ * @interface Snapshot
520
+ * @description Represents a rich snapshot of the state at a point in time for history tracking.
373
521
  */
374
- interface ObservabilityOptions {
375
- /** Maximum number of events to keep in history */
522
+ interface Snapshot<T> {
523
+ /** The complete state object at the time of the snapshot. */
524
+ state: T;
525
+ /** The timestamp of the state change. */
526
+ timestamp: number;
527
+ /** The list of changes (deltas) that resulted in this state. */
528
+ deltas: StateDelta[];
529
+ }
530
+ /**
531
+ * @interface ObserverSessionData
532
+ * @description Defines the data structure for a saved observer session.
533
+ */
534
+ interface ObserverSessionData<T extends object> {
535
+ /** The chronological history of debug events. */
536
+ eventHistory: DebugEvent[];
537
+ /** The chronological history of state snapshots. */
538
+ stateHistory: Snapshot<T>[];
539
+ }
540
+ /**
541
+ * @interface ObserverOptions
542
+ * @description Configuration options for the observer module.
543
+ */
544
+ interface ObserverOptions {
545
+ /** Maximum number of events to retain in memory. Defaults to 500. */
376
546
  maxEvents?: number;
377
- /** Whether to enable console logging */
547
+ /** Enables or disables console logging for all events (overridden by 'silent'). Defaults to false. */
378
548
  enableConsoleLogging?: boolean;
549
+ /** Maximum number of state snapshots to retain for time-travel. Defaults to 20. */
379
550
  maxStateHistory?: number;
380
- /** Options for specific event types to log */
551
+ /** Fine-grained control over which event types are logged to the console. */
381
552
  logEvents?: {
382
553
  updates?: boolean;
383
554
  middleware?: boolean;
384
555
  transactions?: boolean;
556
+ actions?: boolean;
557
+ selectors?: boolean;
385
558
  };
386
- /** Time threshold in ms to highlight slow operations */
559
+ /** Performance thresholds for triggering console warnings. Values are in milliseconds (ms). */
387
560
  performanceThresholds?: {
388
561
  updateTime?: number;
389
562
  middlewareTime?: number;
390
563
  };
564
+ /** If true, suppresses all console output and logging regardless of other options. Defaults to false. */
565
+ silent?: boolean;
391
566
  }
392
567
  /**
393
- * Class for observing and debugging a ReactiveDataStore instance
568
+ * @class StoreObserver
569
+ * @description Connects to a DataStore to capture state changes, events, and performance data.
570
+ * @template T The type of the store's state object.
394
571
  */
395
572
  declare class StoreObserver<T extends object> {
396
573
  protected store: DataStore<T>;
397
574
  private eventHistory;
575
+ private stateHistory;
576
+ private unsubscribers;
577
+ private isTimeTraveling;
578
+ private devTools;
579
+ private middlewareExecutions;
580
+ private activeTransactionCount;
581
+ private activeBatches;
398
582
  private maxEvents;
583
+ private maxStateHistory;
399
584
  private enableConsoleLogging;
585
+ private isSilent;
400
586
  private logEvents;
401
587
  private performanceThresholds;
402
- private unsubscribers;
403
- private stateHistory;
404
- private maxStateHistory;
405
- private activeTransactionCount;
406
- private activeBatches;
407
- private middlewareExecutions;
408
588
  /**
409
- * Creates a new StoreObservability instance
410
- * @param store The ReactiveDataStore to observe
411
- * @param options Configuration options
589
+ * @param store The DataStore instance to observe.
590
+ * @param options Configuration options for the observer.
412
591
  */
413
- constructor(store: DataStore<T>, options?: ObservabilityOptions);
592
+ constructor(store: DataStore<T>, options?: ObserverOptions);
414
593
  /**
415
- * Sets up all event listeners
594
+ * @private
595
+ * Centralized logging method. All console output must go through here to respect the `isSilent` flag.
596
+ * @param method The console method to call ('log', 'warn', 'error', 'group', 'groupEnd', 'table', 'debug').
597
+ * @param args Arguments to pass to the console method.
598
+ */
599
+ private _consoleLog;
600
+ /**
601
+ * @private
602
+ * Sets up listeners for all relevant store events.
416
603
  */
417
604
  private setupEventListeners;
418
605
  /**
419
- * Records a state snapshot
606
+ * @private
607
+ * Records a new state snapshot and manages the state history limit.
608
+ * @param deltas The state changes that led to this snapshot.
420
609
  */
421
610
  private recordStateSnapshot;
422
611
  /**
423
- * Records an event to the history
424
- * @param type Event type
425
- * @param data Event data
612
+ * @private
613
+ * Records a debug event and manages the event history limit.
614
+ * @param type The type of event.
615
+ * @param data The data payload of the event.
426
616
  */
427
617
  private recordEvent;
428
618
  /**
429
- * Logs an event to the console with appropriate formatting
430
- * @param type Event type
431
- * @param data Event data
432
- */
433
- private logEventToConsole;
434
- /**
435
- * Checks for performance issues in the events
436
- * @param type Event type
437
- * @param data Event data
438
- */
439
- private checkPerformance;
440
- /**
441
- * Returns the event history
442
- * @returns Array of debug events
619
+ * Returns a cloned copy of the recorded event history.
620
+ * @returns Array of debug events.
443
621
  */
444
622
  getEventHistory(): DebugEvent[];
445
623
  /**
446
- * Returns the state history
447
- * @returns Array of state snapshots
624
+ * Returns a cloned copy of the recorded state history (snapshots).
625
+ * @returns Array of state snapshots.
448
626
  */
449
- getStateHistory(): T[];
627
+ getStateHistory(): Snapshot<T>[];
450
628
  /**
451
- * Returns middleware execution history from the state
452
- * @returns Array of middleware executions
629
+ * Returns middleware execution history from the state.
630
+ * @returns Array of middleware executions.
453
631
  */
454
632
  getMiddlewareExecutions(): MiddlewareExecution[];
455
633
  /**
456
- * Returns state performance metrics
457
- * @returns Store metrics object
458
- */
459
- getPerformanceMetrics(): StoreMetrics;
460
- /**
461
- * Returns current transaction status
462
- * @returns Object with transaction status information
634
+ * Returns current transaction status.
635
+ * @returns Object with transaction status information.
463
636
  */
464
637
  getTransactionStatus(): {
465
638
  activeTransactions: number;
466
639
  activeBatches: string[];
467
640
  };
468
641
  /**
469
- * Creates a middleware that logs all updates
470
- * @param options Options for the logging middleware
471
- * @returns A middleware function
642
+ * Creates a standard middleware that logs all updates.
643
+ * NOTE: This is user-defined middleware and uses native console methods,
644
+ * so its output is independent of the observer's `silent` flag.
645
+ * @param options Options for the logging middleware.
646
+ * @returns A middleware function.
472
647
  */
473
648
  createLoggingMiddleware(options?: {
474
649
  logLevel?: "debug" | "info" | "warn";
475
650
  logUpdates?: boolean;
476
651
  }): (state: T, update: DeepPartial<T>) => DeepPartial<T>;
477
652
  /**
478
- * Creates a middleware that validates updates against a schema
479
- * @param validator Function that validates updates
480
- * @returns A blocking middleware function
653
+ * Creates a middleware that validates updates against a schema.
654
+ * Uses the internal `_consoleLog` for warnings.
655
+ * @param validator Function that validates updates.
656
+ * @returns A blocking middleware function.
481
657
  */
482
658
  createValidationMiddleware(validator: (state: T, update: DeepPartial<T>) => boolean | {
483
659
  valid: boolean;
484
660
  reason?: string;
485
661
  }): (state: T, update: DeepPartial<T>) => boolean;
486
662
  /**
487
- * Clears all event and state history
488
- */
489
- clearHistory(): void;
490
- /**
491
- * Returns a simplified view of recent state changes
492
- * @param limit Maximum number of state changes to compare
493
- * @returns Array of state difference objects
663
+ * Returns a simplified view of recent state changes.
664
+ * @param limit Maximum number of state changes to compare. Defaults to 5.
665
+ * @returns Array of state difference objects.
494
666
  */
495
667
  getRecentChanges(limit?: number): Array<{
496
668
  timestamp: number;
@@ -499,21 +671,218 @@ declare class StoreObserver<T extends object> {
499
671
  to: Partial<T>;
500
672
  }>;
501
673
  /**
502
- * Creates a time-travel debug middleware that lets you undo/redo state changes
503
- * @returns An object with undo/redo methods and state info
674
+ * Clears both the event and state history, preserving only the initial state snapshot.
675
+ */
676
+ clearHistory(): void;
677
+ /**
678
+ * Filters and returns events related to a specific action ID.
679
+ * @param actionId The ID of the action to filter by.
680
+ * @returns Array of debug events associated with the action.
681
+ */
682
+ getHistoryForAction(actionId: string): DebugEvent[];
683
+ /**
684
+ * Attempts to replay a state update from history using the recorded update payload.
685
+ * @param eventIndex The index of the replayable event (an "update:start" event) in the history array.
686
+ */
687
+ replay(eventIndex: number): Promise<void>;
688
+ /**
689
+ * Creates a time-travel utility object with undo/redo capabilities.
690
+ * @returns An object with methods for time-travel navigation.
504
691
  */
505
692
  createTimeTravel(): {
506
693
  canUndo: () => boolean;
507
694
  canRedo: () => boolean;
508
- undo: () => void;
509
- redo: () => void;
510
- getHistoryLength: () => number;
695
+ undo: () => Promise<void>;
696
+ redo: () => Promise<void>;
697
+ length: () => number;
511
698
  clear: () => void;
512
699
  };
513
700
  /**
514
- * Disconnects all event listeners and cleans up resources
701
+ * Saves the current observer session (events and state history) using a persistence mechanism.
702
+ * @param persistence An object implementing the SimplePersistence interface.
703
+ * @returns A promise that resolves to true if the session was saved successfully.
704
+ */
705
+ saveSession(persistence: SimplePersistence<ObserverSessionData<T>>): Promise<boolean>;
706
+ /**
707
+ * Loads a previously saved observer session and restores the state to the latest saved snapshot.
708
+ * @param persistence An object implementing the SimplePersistence interface.
709
+ * @returns A promise that resolves to true if a session was loaded.
710
+ */
711
+ loadSession(persistence: SimplePersistence<ObserverSessionData<T>>): Promise<boolean>;
712
+ /**
713
+ * Exports the current session data as a JSON file, initiating a browser download.
714
+ */
715
+ exportSession(): void;
716
+ /**
717
+ * Imports a session from a JSON file, restoring event history and state.
718
+ * @param file The file object (e.g., from an <input type="file"> event) to import.
719
+ * @returns A promise that resolves when the import is complete.
720
+ */
721
+ importSession(file: File): Promise<void>;
722
+ /**
723
+ * Cleans up the observer by unsubscribing all event listeners and clearing history.
515
724
  */
516
725
  disconnect(): void;
726
+ /**
727
+ * @private
728
+ * Logs an event to the console with appropriate formatting.
729
+ * Uses `this._consoleLog` for all output.
730
+ * @param type Event type.
731
+ * @param data Event data.
732
+ */
733
+ private _log;
734
+ /**
735
+ * @private
736
+ * Checks for performance issues in the events.
737
+ * Uses `this._consoleLog` for all output.
738
+ * @param type Event type.
739
+ * @param data Event data.
740
+ */
741
+ private _checkPerformance;
742
+ }
743
+
744
+ /**
745
+ * Creates a diff function with configurable options.
746
+ *
747
+ * @param {object} options - Configuration options for the diff function.
748
+ * @param {symbol} [options.deleteMarker] - A custom symbol to mark properties for deletion.
749
+ */
750
+ declare function createDiff(options?: {
751
+ deleteMarker?: symbol;
752
+ }): any;
753
+ /**
754
+ * Creates a derivePaths function with configurable options.
755
+ *
756
+ * @param {object} options - Configuration options for the derivePaths function.
757
+ * @param {symbol} [options.deleteMarker=Symbol.for("delete")] - A custom symbol to mark properties for deletion.
758
+ */
759
+ declare function createDerivePaths(options?: {
760
+ deleteMarker?: symbol;
761
+ }): <T>(changes: DeepPartial<T>) => string[];
762
+ /**
763
+ * @deprecated This function is deprecated. Use `createDiff()` to get a diff function,
764
+ * or `createDiff({ deleteMarker: yourSymbol })` for custom delete markers.
765
+ * Example: `import { createDiff } from 'your-module'; const diff = createDiff();`
766
+ *
767
+ * Identifies paths that differ between original and partial objects, using `Symbol.for("delete")` as the default delete marker.
768
+ * This is provided for backward compatibility.
769
+ */
770
+ declare const diff: any;
771
+ type DiffFunction = ReturnType<typeof createDiff>;
772
+ /**
773
+ * @deprecated This function is deprecated. Use `createDerivePaths()` to get a derivePaths function,
774
+ * or `createDerivePaths({ deleteMarker: yourSymbol })` for custom delete markers.
775
+ * Example: `import { createDerivePaths } from 'your-module'; const derivePaths = createDerivePaths();`
776
+ *
777
+ * Efficiently computes paths from changes, using `Symbol.for("delete")` as the default delete marker.
778
+ * This is provided for backward compatibility.
779
+ */
780
+ declare const derivePaths: <T>(changes: DeepPartial<T>) => string[];
781
+
782
+ /**
783
+ * Creates a shallow clone of an object or array.
784
+ */
785
+ declare const shallowClone: (obj: any) => any;
786
+ /**
787
+ * Creates a deep merge function with configurable options.
788
+ *
789
+ * @param {object} options - Configuration options for the merge function.
790
+ * @param {symbol} [options.deleteMarker=Symbol.for("delete")] - A custom symbol to mark properties for deletion during merge.
791
+ */
792
+ declare function createMerge(options?: {
793
+ deleteMarker?: symbol;
794
+ }): <T extends object>(original: T, changes: DeepPartial<T> | symbol) => T;
795
+ /**
796
+ * @deprecated This function is deprecated. Use `createMerge()` to get a merge function,
797
+ * or `createMerge({ deleteMarker: yourSymbol })` for custom delete markers.
798
+ * Example: `import { createMerge } from 'your-module'; const merge = createMerge();`
799
+ *
800
+ * Deep merges changes into an original object immutably, using `Symbol.for("delete")` as the default delete marker.
801
+ * This is provided for backward compatibility.
802
+ */
803
+ declare const merge: <T extends object>(original: T, changes: DeepPartial<T> | symbol) => T;
804
+ type MergeFunction = ReturnType<typeof createMerge>;
805
+
806
+ declare class ActionManager<T extends object> {
807
+ private eventBus;
808
+ private set;
809
+ private actions;
810
+ constructor(eventBus: EventBus<Record<StoreEvent, any>>, set: (update: StateUpdater<T>, options?: {
811
+ force?: boolean;
812
+ actionId?: string;
813
+ }) => Promise<any>);
814
+ register<R extends any[]>(action: {
815
+ name: string;
816
+ fn: (state: T, ...args: R) => DeepPartial<T> | Promise<DeepPartial<T>>;
817
+ debounce?: {
818
+ delay: number;
819
+ condition?: (previous: R | undefined, current: R) => boolean;
820
+ };
821
+ }): () => void;
822
+ dispatch<R extends any[]>(name: string, ...params: R): Promise<T>;
823
+ private executeAction;
824
+ private emit;
825
+ }
826
+
827
+ interface ActionContext<TState extends object, TResolvedArtifacts extends object> {
828
+ /**
829
+ * Resolve an artifact.
830
+ * This records a dependency between the caller and the requested artifact.
831
+ */
832
+ resolve<K extends keyof TResolvedArtifacts>(key: K): Promise<TResolvedArtifacts[K]>;
833
+ state: TState;
834
+ }
835
+ type ActionImplementation<TState extends object, TResolvedArtifacts extends object, TArgs extends any[]> = (ctx: ActionContext<TState, TResolvedArtifacts>, ...args: TArgs) => DeepPartial<TState> | Promise<DeepPartial<TState>>;
836
+ type ArtifactDefinition<TState extends Object, R> = {
837
+ factory: ArtifactFactory<TState, R>;
838
+ scope?: ArtifactScope;
839
+ lazy?: boolean;
840
+ };
841
+ type ArtifactsMap<TState extends object> = Record<string, ArtifactDefinition<TState, any>>;
842
+ type ExtractArtifactInstanceFromConfig<T> = T extends {
843
+ factory: ArtifactFactory<any, infer I>;
844
+ } ? I : never;
845
+ type ExtractInstanceFromMap<TMap extends ArtifactsMap<any>, TKey extends keyof TMap> = ExtractArtifactInstanceFromConfig<TMap[TKey]>;
846
+ type ResolvedArtifactsMap<TArtifactsMap extends ArtifactsMap<any>> = {
847
+ [K in keyof TArtifactsMap]: ExtractInstanceFromMap<TArtifactsMap, K>;
848
+ };
849
+ type ActionMap<TState extends object, TArtifactsMap extends ArtifactsMap<TState>> = Record<string, ActionImplementation<TState, ResolvedArtifactsMap<TArtifactsMap>, any[]>>;
850
+ /**
851
+ * Bounds the actions for the resulting store hook, removing the context argument.
852
+ */
853
+ type BoundActions<TState extends object, TArtifactsMap extends ArtifactsMap<TState>, TActions extends ActionMap<TState, TArtifactsMap>> = {
854
+ [K in keyof TActions]: (...args: Parameters<TActions[K]> extends [ActionContext<any, any>, ...infer R] ? R : never) => Promise<TState>;
855
+ };
856
+ type LoadingState<TActions> = Partial<Record<keyof TActions, boolean>>;
857
+ type StoreOptions<T> = ObserverOptions & {
858
+ enableMetrics?: boolean;
859
+ persistence?: SimplePersistence$1<T>;
860
+ };
861
+ interface StoreDefinition<TState extends object, TArtifactsMap extends ArtifactsMap<TState>, TActions extends ActionMap<TState, TArtifactsMap>> {
862
+ state: TState;
863
+ actions: TActions;
864
+ artifacts?: TArtifactsMap;
865
+ loading?: LoadingState<TActions>;
866
+ sync?: (args: TState) => void;
867
+ blockingMiddleware?: Record<string, BlockingMiddleware<TState>>;
868
+ middleware?: Record<string, Middleware<TState>>;
517
869
  }
870
+ type StoreHook<TState extends object, TArtifactsMap extends ArtifactsMap<TState>, TActions extends ActionMap<TState, TArtifactsMap>> = () => {
871
+ store: any;
872
+ observer: any;
873
+ select: <S>(selector: (state: TState) => S) => S;
874
+ actions: BoundActions<TState, TArtifactsMap, TActions>;
875
+ /**
876
+ * Reactive Artifact Resolver.
877
+ * Returns [instance, isReady].
878
+ */
879
+ resolve: <K extends keyof TArtifactsMap>(key: K) => readonly [ExtractInstanceFromMap<TArtifactsMap, K>, true] | readonly [ExtractInstanceFromMap<TArtifactsMap, K> | undefined, false];
880
+ isReady: boolean;
881
+ actionTracker: any;
882
+ watch: (action: keyof TActions) => boolean;
883
+ state: () => TState;
884
+ };
885
+
886
+ declare function createStore<TState extends Record<string, unknown>, TArtifactsMap extends ArtifactsMap<TState>, TActions extends ActionMap<TState, TArtifactsMap>>(definition: StoreDefinition<TState, TArtifactsMap, TActions>, { enableMetrics, ...options }?: StoreOptions<TState>): StoreHook<TState, TArtifactsMap, TActions>;
518
887
 
519
- export { type BlockingMiddleware, DELETE_SYMBOL, type DataStore, type DebugEvent, type DeepPartial, type Middleware, type MiddlewareConfig, type MiddlewareExecution, type ObservabilityOptions, type PersistenceFailedPayload, type PersistenceInitErrorPayload, type PersistenceQueueClearedPayload, type PersistenceQueuedPayload, type PersistenceRetryPayload, type PersistenceSuccessPayload, ReactiveDataStore, type StateUpdater, type StoreEvent, type StoreExecutionState, type StoreMetrics, StoreObserver, type TransformMiddleware, author };
888
+ export { type ActionCompletePayload, type ActionContext, type ActionErrorPayload, type ActionImplementation, ActionManager, type ActionMap, type ActionStartPayload, type ArtifactCleanup, ArtifactContainer, type ArtifactDefinition, type ArtifactFactory, type ArtifactFactoryContext, type ArtifactResult, ArtifactScope, type ArtifactsMap, type BlockingMiddleware, type BoundActions, DELETE_SYMBOL, type DataStore, type DeepPartial, type DiffFunction, type ExtractArtifactInstanceFromConfig, type ExtractInstanceFromMap, type LoadingState, type MergeFunction, type Middleware, type MiddlewareConfig, type MiddlewareExecution, type ObserverOptions, type PersistenceFailedPayload, type PersistenceInitErrorPayload, type PersistenceQueueClearedPayload, type PersistenceQueuedPayload, type PersistenceRetryPayload, type PersistenceSuccessPayload, ReactiveDataStore, type ReactiveSelector, type ResolvedArtifactsMap, type SelectorAccessedPayload, type SelectorChangedPayload, type StateDelta, type StateUpdater, type StoreAction, type StoreDefinition, type StoreEvent, type StoreEvents, type StoreExecutionState, type StoreHook, type StoreMetrics, StoreObserver, type StoreOptions, type TransformMiddleware, type UseDependencyContext, createDerivePaths, createDiff, createMerge, createStore, derivePaths, diff, merge, shallowClone };