@asaidimu/utils-store 10.1.7 → 10.1.8
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 +67 -60
- package/index.d.ts +67 -60
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/package.json +2 -2
package/index.d.mts
CHANGED
|
@@ -1,3 +1,66 @@
|
|
|
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: (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: (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
|
+
* After calling clear(), the bus is fully reset and can be reused —
|
|
38
|
+
* cross-tab communication is re-established if it was previously enabled.
|
|
39
|
+
*/
|
|
40
|
+
clear: () => void;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Interface defining the metrics tracked by the EventBus.
|
|
44
|
+
*/
|
|
45
|
+
interface EventMetrics {
|
|
46
|
+
/** Total number of events emitted (both sync and deferred paths). */
|
|
47
|
+
totalEvents: number;
|
|
48
|
+
/** Number of active subscriptions across all event names. */
|
|
49
|
+
activeSubscriptions: number;
|
|
50
|
+
/** Map of event names to their emission counts. */
|
|
51
|
+
eventCounts: Map<string, number>;
|
|
52
|
+
/** Average duration of event dispatch in milliseconds. */
|
|
53
|
+
averageEmitDuration: number;
|
|
54
|
+
}
|
|
55
|
+
interface SubscribeOptions {
|
|
56
|
+
/**
|
|
57
|
+
* Debounce delay in milliseconds. When multiple events arrive in quick
|
|
58
|
+
* succession, the callback runs only after the quiet period ends, using the
|
|
59
|
+
* latest payload. Default = no debouncing.
|
|
60
|
+
*/
|
|
61
|
+
debounce?: number;
|
|
62
|
+
}
|
|
63
|
+
|
|
1
64
|
/**
|
|
2
65
|
* Utility type for representing partial updates to the state, allowing deep nesting.
|
|
3
66
|
* It makes all properties optional and applies the same transformation recursively
|
|
@@ -325,9 +388,10 @@ interface DataStore<T extends object> {
|
|
|
325
388
|
* Subscribes a callback to run when the data at the specified path(s) changes.
|
|
326
389
|
* @param path A single path string or an array of path strings to watch.
|
|
327
390
|
* @param callback The function to execute when a change occurs in the watched path(s).
|
|
391
|
+
* @param options Extra options to pass to the event bus
|
|
328
392
|
* @returns An unsubscribe function.
|
|
329
393
|
*/
|
|
330
|
-
watch(path: string | Array<string>, callback: (state: T) => void): () => void;
|
|
394
|
+
watch(path: string | Array<string>, callback: (state: T) => void, options?: SubscribeOptions): () => void;
|
|
331
395
|
/**
|
|
332
396
|
* Subscribes to execution‑status changes of a registered action.
|
|
333
397
|
*
|
|
@@ -651,7 +715,7 @@ declare class ReactiveDataStore<T extends object> implements DataStore<T> {
|
|
|
651
715
|
*/
|
|
652
716
|
private setupReadyLatch;
|
|
653
717
|
private setupPersistenceListener;
|
|
654
|
-
watch(path: string | Array<string>, callback: (state: T) => void): () => void;
|
|
718
|
+
watch(path: string | Array<string>, callback: (state: T) => void, options?: SubscribeOptions): () => void;
|
|
655
719
|
/**
|
|
656
720
|
* Subscribes to execution‑status changes of a registered action.
|
|
657
721
|
*
|
|
@@ -698,15 +762,11 @@ declare class ReactiveDataStore<T extends object> implements DataStore<T> {
|
|
|
698
762
|
force?: boolean;
|
|
699
763
|
actionId?: string;
|
|
700
764
|
}) => void;
|
|
701
|
-
/** @deprecated Use `watch()` instead. **/
|
|
702
|
-
subscribe(path: string | Array<string>, callback: (state: T) => void): () => void;
|
|
703
765
|
id(): string;
|
|
704
766
|
transaction<R>(operation: () => R | Promise<R>): Promise<R>;
|
|
705
767
|
use(props: MiddlewareConfig<T>): () => boolean;
|
|
706
768
|
metrics(): StoreMetrics;
|
|
707
769
|
on(event: StoreEvent, listener: (data: any) => void): () => void;
|
|
708
|
-
/** @deprecated Use `on()` instead. */
|
|
709
|
-
onStoreEvent(event: StoreEvent, listener: (data: any) => void): () => void;
|
|
710
770
|
getPersistenceStatus(): {
|
|
711
771
|
queueSize: number;
|
|
712
772
|
isProcessing: boolean;
|
|
@@ -1026,59 +1086,6 @@ declare function createMerge(options?: {
|
|
|
1026
1086
|
declare const merge: <T extends object>(original: T, changes: DeepPartial<T> | symbol) => T;
|
|
1027
1087
|
type MergeFunction = ReturnType<typeof createMerge>;
|
|
1028
1088
|
|
|
1029
|
-
/**
|
|
1030
|
-
* Interface defining the shape of the EventBus.
|
|
1031
|
-
* @template TEventMap - A record mapping event names to their respective payload types.
|
|
1032
|
-
*/
|
|
1033
|
-
interface EventBus<TEventMap extends Record<string, any>> {
|
|
1034
|
-
/**
|
|
1035
|
-
* Subscribes to a specific event by name.
|
|
1036
|
-
* @param eventName - The name of the event to subscribe to.
|
|
1037
|
-
* @param callback - The function to call when the event is emitted.
|
|
1038
|
-
* @returns A function to unsubscribe from the event.
|
|
1039
|
-
*/
|
|
1040
|
-
subscribe: <TEventName extends keyof TEventMap>(eventName: TEventName, callback: (payload: TEventMap[TEventName]) => void) => () => void;
|
|
1041
|
-
/**
|
|
1042
|
-
* Subscribes to an event and automatically unsubscribes after it fires once.
|
|
1043
|
-
* @param eventName - The name of the event to subscribe to.
|
|
1044
|
-
* @param callback - The function to call when the event is emitted.
|
|
1045
|
-
* @returns A function to cancel the one-shot subscription before it fires.
|
|
1046
|
-
*/
|
|
1047
|
-
once: <TEventName extends keyof TEventMap>(eventName: TEventName, callback: (payload: TEventMap[TEventName]) => void) => () => void;
|
|
1048
|
-
/**
|
|
1049
|
-
* Emits an event with a payload to all subscribed listeners.
|
|
1050
|
-
* @param event - An object containing the event name and payload.
|
|
1051
|
-
*/
|
|
1052
|
-
emit: <TEventName extends keyof TEventMap>(event: {
|
|
1053
|
-
name: TEventName;
|
|
1054
|
-
payload: TEventMap[TEventName];
|
|
1055
|
-
}) => void;
|
|
1056
|
-
/**
|
|
1057
|
-
* Retrieves metrics about event bus usage.
|
|
1058
|
-
* @returns An object containing various metrics.
|
|
1059
|
-
*/
|
|
1060
|
-
metrics: () => EventMetrics;
|
|
1061
|
-
/**
|
|
1062
|
-
* Clears all subscriptions and resets metrics.
|
|
1063
|
-
* After calling clear(), the bus is fully reset and can be reused —
|
|
1064
|
-
* cross-tab communication is re-established if it was previously enabled.
|
|
1065
|
-
*/
|
|
1066
|
-
clear: () => void;
|
|
1067
|
-
}
|
|
1068
|
-
/**
|
|
1069
|
-
* Interface defining the metrics tracked by the EventBus.
|
|
1070
|
-
*/
|
|
1071
|
-
interface EventMetrics {
|
|
1072
|
-
/** Total number of events emitted (both sync and deferred paths). */
|
|
1073
|
-
totalEvents: number;
|
|
1074
|
-
/** Number of active subscriptions across all event names. */
|
|
1075
|
-
activeSubscriptions: number;
|
|
1076
|
-
/** Map of event names to their emission counts. */
|
|
1077
|
-
eventCounts: Map<string, number>;
|
|
1078
|
-
/** Average duration of event dispatch in milliseconds. */
|
|
1079
|
-
averageEmitDuration: number;
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
1089
|
declare class ActionCancelledError extends Error {
|
|
1083
1090
|
constructor();
|
|
1084
1091
|
}
|
|
@@ -1112,4 +1119,4 @@ declare class ActionManager<T extends object> {
|
|
|
1112
1119
|
private emit;
|
|
1113
1120
|
}
|
|
1114
1121
|
|
|
1115
|
-
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 ReactiveSelector, type SelectorAccessedPayload, type SelectorChangedPayload, type StateDelta, type StateUpdater, type StoreAction, type StoreEvent, type StoreEvents, type StoreExecutionState, type StoreMetrics, StoreObserver, type TransformMiddleware, UnknownActionError, createDerivePaths, createDiff, createMerge, derivePaths, diff, merge, shallowClone };
|
|
1122
|
+
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 ReactiveSelector, type SelectorAccessedPayload, type SelectorChangedPayload, type StateDelta, type StateUpdater, type StoreAction, type StoreEvent, type StoreEvents, type StoreExecutionState, type StoreMetrics, StoreObserver, type SubscribeOptions, type TransformMiddleware, UnknownActionError, createDerivePaths, createDiff, createMerge, derivePaths, diff, merge, shallowClone };
|
package/index.d.ts
CHANGED
|
@@ -1,3 +1,66 @@
|
|
|
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: (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: (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
|
+
* After calling clear(), the bus is fully reset and can be reused —
|
|
38
|
+
* cross-tab communication is re-established if it was previously enabled.
|
|
39
|
+
*/
|
|
40
|
+
clear: () => void;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Interface defining the metrics tracked by the EventBus.
|
|
44
|
+
*/
|
|
45
|
+
interface EventMetrics {
|
|
46
|
+
/** Total number of events emitted (both sync and deferred paths). */
|
|
47
|
+
totalEvents: number;
|
|
48
|
+
/** Number of active subscriptions across all event names. */
|
|
49
|
+
activeSubscriptions: number;
|
|
50
|
+
/** Map of event names to their emission counts. */
|
|
51
|
+
eventCounts: Map<string, number>;
|
|
52
|
+
/** Average duration of event dispatch in milliseconds. */
|
|
53
|
+
averageEmitDuration: number;
|
|
54
|
+
}
|
|
55
|
+
interface SubscribeOptions {
|
|
56
|
+
/**
|
|
57
|
+
* Debounce delay in milliseconds. When multiple events arrive in quick
|
|
58
|
+
* succession, the callback runs only after the quiet period ends, using the
|
|
59
|
+
* latest payload. Default = no debouncing.
|
|
60
|
+
*/
|
|
61
|
+
debounce?: number;
|
|
62
|
+
}
|
|
63
|
+
|
|
1
64
|
/**
|
|
2
65
|
* Utility type for representing partial updates to the state, allowing deep nesting.
|
|
3
66
|
* It makes all properties optional and applies the same transformation recursively
|
|
@@ -325,9 +388,10 @@ interface DataStore<T extends object> {
|
|
|
325
388
|
* Subscribes a callback to run when the data at the specified path(s) changes.
|
|
326
389
|
* @param path A single path string or an array of path strings to watch.
|
|
327
390
|
* @param callback The function to execute when a change occurs in the watched path(s).
|
|
391
|
+
* @param options Extra options to pass to the event bus
|
|
328
392
|
* @returns An unsubscribe function.
|
|
329
393
|
*/
|
|
330
|
-
watch(path: string | Array<string>, callback: (state: T) => void): () => void;
|
|
394
|
+
watch(path: string | Array<string>, callback: (state: T) => void, options?: SubscribeOptions): () => void;
|
|
331
395
|
/**
|
|
332
396
|
* Subscribes to execution‑status changes of a registered action.
|
|
333
397
|
*
|
|
@@ -651,7 +715,7 @@ declare class ReactiveDataStore<T extends object> implements DataStore<T> {
|
|
|
651
715
|
*/
|
|
652
716
|
private setupReadyLatch;
|
|
653
717
|
private setupPersistenceListener;
|
|
654
|
-
watch(path: string | Array<string>, callback: (state: T) => void): () => void;
|
|
718
|
+
watch(path: string | Array<string>, callback: (state: T) => void, options?: SubscribeOptions): () => void;
|
|
655
719
|
/**
|
|
656
720
|
* Subscribes to execution‑status changes of a registered action.
|
|
657
721
|
*
|
|
@@ -698,15 +762,11 @@ declare class ReactiveDataStore<T extends object> implements DataStore<T> {
|
|
|
698
762
|
force?: boolean;
|
|
699
763
|
actionId?: string;
|
|
700
764
|
}) => void;
|
|
701
|
-
/** @deprecated Use `watch()` instead. **/
|
|
702
|
-
subscribe(path: string | Array<string>, callback: (state: T) => void): () => void;
|
|
703
765
|
id(): string;
|
|
704
766
|
transaction<R>(operation: () => R | Promise<R>): Promise<R>;
|
|
705
767
|
use(props: MiddlewareConfig<T>): () => boolean;
|
|
706
768
|
metrics(): StoreMetrics;
|
|
707
769
|
on(event: StoreEvent, listener: (data: any) => void): () => void;
|
|
708
|
-
/** @deprecated Use `on()` instead. */
|
|
709
|
-
onStoreEvent(event: StoreEvent, listener: (data: any) => void): () => void;
|
|
710
770
|
getPersistenceStatus(): {
|
|
711
771
|
queueSize: number;
|
|
712
772
|
isProcessing: boolean;
|
|
@@ -1026,59 +1086,6 @@ declare function createMerge(options?: {
|
|
|
1026
1086
|
declare const merge: <T extends object>(original: T, changes: DeepPartial<T> | symbol) => T;
|
|
1027
1087
|
type MergeFunction = ReturnType<typeof createMerge>;
|
|
1028
1088
|
|
|
1029
|
-
/**
|
|
1030
|
-
* Interface defining the shape of the EventBus.
|
|
1031
|
-
* @template TEventMap - A record mapping event names to their respective payload types.
|
|
1032
|
-
*/
|
|
1033
|
-
interface EventBus<TEventMap extends Record<string, any>> {
|
|
1034
|
-
/**
|
|
1035
|
-
* Subscribes to a specific event by name.
|
|
1036
|
-
* @param eventName - The name of the event to subscribe to.
|
|
1037
|
-
* @param callback - The function to call when the event is emitted.
|
|
1038
|
-
* @returns A function to unsubscribe from the event.
|
|
1039
|
-
*/
|
|
1040
|
-
subscribe: <TEventName extends keyof TEventMap>(eventName: TEventName, callback: (payload: TEventMap[TEventName]) => void) => () => void;
|
|
1041
|
-
/**
|
|
1042
|
-
* Subscribes to an event and automatically unsubscribes after it fires once.
|
|
1043
|
-
* @param eventName - The name of the event to subscribe to.
|
|
1044
|
-
* @param callback - The function to call when the event is emitted.
|
|
1045
|
-
* @returns A function to cancel the one-shot subscription before it fires.
|
|
1046
|
-
*/
|
|
1047
|
-
once: <TEventName extends keyof TEventMap>(eventName: TEventName, callback: (payload: TEventMap[TEventName]) => void) => () => void;
|
|
1048
|
-
/**
|
|
1049
|
-
* Emits an event with a payload to all subscribed listeners.
|
|
1050
|
-
* @param event - An object containing the event name and payload.
|
|
1051
|
-
*/
|
|
1052
|
-
emit: <TEventName extends keyof TEventMap>(event: {
|
|
1053
|
-
name: TEventName;
|
|
1054
|
-
payload: TEventMap[TEventName];
|
|
1055
|
-
}) => void;
|
|
1056
|
-
/**
|
|
1057
|
-
* Retrieves metrics about event bus usage.
|
|
1058
|
-
* @returns An object containing various metrics.
|
|
1059
|
-
*/
|
|
1060
|
-
metrics: () => EventMetrics;
|
|
1061
|
-
/**
|
|
1062
|
-
* Clears all subscriptions and resets metrics.
|
|
1063
|
-
* After calling clear(), the bus is fully reset and can be reused —
|
|
1064
|
-
* cross-tab communication is re-established if it was previously enabled.
|
|
1065
|
-
*/
|
|
1066
|
-
clear: () => void;
|
|
1067
|
-
}
|
|
1068
|
-
/**
|
|
1069
|
-
* Interface defining the metrics tracked by the EventBus.
|
|
1070
|
-
*/
|
|
1071
|
-
interface EventMetrics {
|
|
1072
|
-
/** Total number of events emitted (both sync and deferred paths). */
|
|
1073
|
-
totalEvents: number;
|
|
1074
|
-
/** Number of active subscriptions across all event names. */
|
|
1075
|
-
activeSubscriptions: number;
|
|
1076
|
-
/** Map of event names to their emission counts. */
|
|
1077
|
-
eventCounts: Map<string, number>;
|
|
1078
|
-
/** Average duration of event dispatch in milliseconds. */
|
|
1079
|
-
averageEmitDuration: number;
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
1089
|
declare class ActionCancelledError extends Error {
|
|
1083
1090
|
constructor();
|
|
1084
1091
|
}
|
|
@@ -1112,4 +1119,4 @@ declare class ActionManager<T extends object> {
|
|
|
1112
1119
|
private emit;
|
|
1113
1120
|
}
|
|
1114
1121
|
|
|
1115
|
-
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 ReactiveSelector, type SelectorAccessedPayload, type SelectorChangedPayload, type StateDelta, type StateUpdater, type StoreAction, type StoreEvent, type StoreEvents, type StoreExecutionState, type StoreMetrics, StoreObserver, type TransformMiddleware, UnknownActionError, createDerivePaths, createDiff, createMerge, derivePaths, diff, merge, shallowClone };
|
|
1122
|
+
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 ReactiveSelector, type SelectorAccessedPayload, type SelectorChangedPayload, type StateDelta, type StateUpdater, type StoreAction, type StoreEvent, type StoreEvents, type StoreExecutionState, type StoreMetrics, StoreObserver, type SubscribeOptions, type TransformMiddleware, UnknownActionError, createDerivePaths, createDiff, createMerge, derivePaths, diff, merge, shallowClone };
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("@asaidimu/utils-events"),t=require("uuid"),s=class{_delay;_leading;_timer;_pendingFn;_pendingResolvers=[];_leadingFired=!1;constructor(e){this._delay=e?.delay??300,this._leading=e?.leading??!1}do(e){return new Promise((t=>{this._enqueue(e,t)}))}fire(e){this._enqueue(e,void 0)}_enqueue(e,t){if(this._pendingFn=e,t&&this._pendingResolvers.push(t),this._leading&&!this._leadingFired)return this._leadingFired=!0,this._fire(),clearTimeout(this._timer),void(this._timer=setTimeout((()=>{this._leadingFired=!1,void 0!==this._pendingFn&&this._fire()}),this._delay));clearTimeout(this._timer),this._timer=setTimeout((()=>{this._leadingFired=!1,this._fire()}),this._delay)}cancel(){clearTimeout(this._timer),this._timer=void 0,this._pendingFn=void 0,this._leadingFired=!1;const e=this._pendingResolvers.splice(0);for(const t of e)t({status:"cancelled"})}async flush(){return this._pendingFn?(clearTimeout(this._timer),this._timer=void 0,this._leadingFired=!1,this._fire()):null}pending(){return void 0!==this._pendingFn}async _fire(){const e=this._pendingFn,t=this._pendingResolvers.splice(0);let s;this._pendingFn=void 0;try{s={status:"ok",value:await e()}}catch(e){s={status:"error",error:e}}for(const e of t)e(s);return s}},i=class e extends Error{constructor(t,s){super(t,{cause:s}),this.name="SyncError",Object.setPrototypeOf(this,e.prototype)}},r=class extends i{constructor(e){super(`[ArtifactContainer] Operation timed out: ${e}`)}},n=class extends i{constructor(e){super("[Serializer] The serializer has been marked as done!",e)}},a=class{_open=!1;_resolve;_promise;constructor(){this._promise=new Promise((e=>{this._resolve=e}))}open(){this._open||(this._open=!0,this._resolve())}async wait(e){if(this._open)return;if(null==e)return this._promise;let t;await Promise.race([this._promise.then((()=>clearTimeout(t))),new Promise(((s,i)=>{t=setTimeout((()=>i(new r("Latch timed out"))),e)}))])}isOpen(){return this._open}},o=class{_locked=!1;_capacity;_yieldMode;waiters=[];constructor(e){this._capacity=e?.capacity??1/0,this._yieldMode=e?.yieldMode??"macrotask"}async lock(e){if(!this._locked)return void(this._locked=!0);if(this.waiters.length>=this._capacity)throw new Error(`Mutex queue is full (capacity: ${this._capacity})`);let t;const s=new Promise((e=>t=e));if(this.waiters.push(t),null==e)return void await s;let i;await Promise.race([s.then((()=>clearTimeout(i))),new Promise(((s,n)=>{i=setTimeout((()=>{const e=this.waiters.indexOf(t);-1!==e&&this.waiters.splice(e,1),n(new r("Mutex lock timed out"))}),e)}))])}tryLock(){return!this._locked&&(this._locked=!0,!0)}unlock(){if(!this._locked)throw new Error("Mutex is not locked");const e=this.waiters.shift();e?"microtask"===this._yieldMode?queueMicrotask(e):setTimeout(e,0):this._locked=!1}locked(){return this._locked}pending(){return this.waiters.length}},c=class{mutex=new o({yieldMode:"microtask"});promise=null;_value=null;_error;_done=!1;retry;throws;constructor({retry:e,throws:t}={}){this.retry=Boolean(e),this.throws=Boolean(t)}async do(e,t){return this._done?this.peek():this.promise?this._awaitWithTimeout(this.promise,t,"Once do() timed out"):(await this.mutex.lock(),this.promise?(this.mutex.unlock(),this._awaitWithTimeout(this.promise,t,"Once do() timed out")):(this.promise=(async()=>{try{this._value=await e(),this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.retry&&!this._done&&(this.promise=null)}return this.peek()})(),this.mutex.unlock(),this._awaitWithTimeout(this.promise,t,"Once do() timed out")))}doSync(e){if(this._done){if(this.throws&&this._error)throw this._error;return this.peek()}if(this.promise){const e=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw e;return{value:null,error:e}}if(!this.mutex.tryLock()){const e=new Error("Cannot execute doSync: lock is currently held.");if(this.throws)throw e;return{value:null,error:e}}if(this.promise||this._done){if(this.mutex.unlock(),this._done){if(this.throws&&this._error)throw this._error;return this.peek()}const e=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw e;return{value:null,error:e}}try{const t=e();this._value=t,this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.mutex.unlock()}return this.peek()}running(){return null!==this.promise&&!this.done()}peek(){return{value:this._value,error:this._error}}get(){if(!this._done)throw new Error("Once operation is not yet complete");if(this._error)throw this._error;return this._value}reset(){if(this.running())throw new Error("Cannot reset Once while an operation is in progress.");this._done=!1,this.promise=null,this._value=null,this._error=void 0}done(){return this._done}current(){return this.promise}_awaitWithTimeout(e,t,s="Operation timed out"){if(null==t)return e;let i;return Promise.race([e.then((e=>(clearTimeout(i),e))),new Promise(((e,n)=>{i=setTimeout((()=>n(new r(s))),t)}))])}},h=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;_hasRun=!1;constructor(e){this.mutex=new o({capacity:e?.capacity??1e3,yieldMode:e?.yieldMode??"macrotask"})}async do(e,t){if(this._done)return{value:null,error:new n};try{await this.mutex.lock(t)}catch(e){return{value:null,error:e}}let s,i=null;try{if(this._done)throw new n;i=await e(),this._lastValue=i,this._lastError=void 0,this._hasRun=!0}catch(e){s=e,this._lastError=e,this._hasRun=!0}finally{this.mutex.unlock()}return{value:i,error:s}}peek(){return{value:this._lastValue,error:this._lastError}}hasRun(){return this._hasRun}close(){this._done=!0}pending(){return this.mutex.pending()}running(){return this.mutex.locked()}},d=class{constructor(e,t,s={}){this.factory=e,this.onCleanup=t,this.options=s}_count=0;init=new c({retry:!1,throws:!1});pendingMicrotask=!1;cleanupTimer;get subscribers(){return this._count}async acquire(){this.cancelPendingCleanup(),this._count++;const e=await this.init.do(this.factory);if(e.error)throw e.error;return e.value}release(){this._count<=0?console.warn("SharedResource.release() called, but count is already 0."):(this._count--,0===this._count&&this.scheduleCleanup())}peek(){const e=this.init.peek();return e.error?null:e.value}forceCleanup(){this.cancelPendingCleanup(),this._count=0,this.executeCleanup()}cancelPendingCleanup(){this.pendingMicrotask=!1,void 0!==this.cleanupTimer&&(clearTimeout(this.cleanupTimer),this.cleanupTimer=void 0)}scheduleCleanup(){const e=this.options.gracePeriod??"microtask";if("sync"!==e)return"microtask"===e?(this.pendingMicrotask=!0,void queueMicrotask((()=>{!this.pendingMicrotask||this._count>0||(this.pendingMicrotask=!1,this.executeCleanup())}))):void(this.cleanupTimer=setTimeout((()=>{this.cleanupTimer=void 0,this._count>0||this.executeCleanup()}),e));this.executeCleanup()}executeCleanup(){const e=this.init.peek();try{this.onCleanup(e.value)}catch(e){console.error("[SharedResource] Error during cleanup callback:",e)}this.init.running()||this.init.reset()}},l=Symbol.for("delete"),u=e=>Array.isArray(e)?[...e]:{...e};function p(e){const t=e?.deleteMarker||l;function s(e){if(null==e)return e;if(Array.isArray(e))return e.filter((e=>e!==t)).map((e=>"object"!=typeof e||null===e||Array.isArray(e)?e:s(e)));if("object"==typeof e){const i={};for(const[r,n]of Object.entries(e))if(n!==t)if("object"==typeof n&&null!==n){const e=s(n);void 0!==e&&(i[r]=e)}else i[r]=n;return i}return e===t?void 0:e}return function(e,i){if("object"!=typeof e||null===e)return"object"==typeof i&&null!==i?s(i):i===t?{}:i;if("object"!=typeof i||null===i)return e;const r=u(e),n=[{target:r,source:i}];for(;n.length>0;){const{target:e,source:s}=n.pop();for(const i of Object.keys(s)){const r=s[i];if(r!==t)if(Array.isArray(r))e[i]=r;else if("object"==typeof r&&null!==r){const t=i in e&&"object"==typeof e[i]&&null!==e[i]?e[i]:{};e[i]=u(t),n.push({target:e[i],source:r})}else e[i]=r;else delete e[i]}}return r}}var m=p(),g=["map","filter","reduce","forEach","find","findIndex","some","every","includes","flatMap","flat","slice","splice"],y=class{reactiveSelectors=new Map;pathBasedCache=new Map;dependencyMap=new Map;getState;eventBus;unsubscribeFromStore;constructor(e,t){this.getState=e,this.eventBus=t,this.unsubscribeFromStore=this.eventBus.subscribe("update:complete",this.handleStoreUpdate)}handleStoreUpdate=e=>{const t=new Set;for(const s of e.deltas){const e=s.path;for(const[s,i]of this.dependencyMap)if(s===e||s.startsWith(e+".")||e.startsWith(s+"."))for(const e of i)t.add(e)}for(const e of t){const t=this.reactiveSelectors.get(e);t&&this.evaluateEntry(t)}};evaluateEntry(e){let t;try{t=e.selector(this.getState())}catch{t=void 0}if(t!==e.lastResult){e.lastResult=t;for(const s of e.subscribers)s(t);this.eventBus.emit({name:"selector:changed",payload:{selectorId:e.id,newResult:t,timestamp:performance.now()}})}}createReactiveSelector(e){const t=function(e,t="."){const s=new Set,i=new Map,r=(e="")=>{if(i.has(e))return i.get(e);const n=new Proxy((()=>{}),{get:(i,n)=>{if("symbol"==typeof n||"then"===n)return;if("valueOf"===n||"toString"===n)throw new Error("Cannot perform logic, arithmetic, or string operations inside a selector.");if(g.includes(n))throw new Error(`Array method .${n}() is not allowed in selectors.`);const a=e?`${e}${t}${n}`:n;return e&&s.delete(e),s.add(a),r(a)},has:()=>{throw new Error("The 'in' operator is not allowed in selectors.")},apply:()=>{throw new Error("Selectors cannot call functions or methods.")}});return i.set(e,n),n};try{e(r())}catch(e){throw new Error(`Selector failed during path analysis. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}return Array.from(s)}(e),s=[...t].sort().join("|"),i=this.pathBasedCache.get(s);if(i)return void 0!==i.cleanupTimer&&(clearTimeout(i.cleanupTimer),i.cleanupTimer=void 0),i.reactiveSelectorInstance;const r=`sel-${Math.random().toString(36).slice(2,9)}`,n={id:r,selector:e,lastResult:e(this.getState()),accessedPaths:t,subscribers:new Set,count:0,cleanupTimer:void 0,pathCacheKey:s,reactiveSelectorInstance:null};for(const e of t)this.dependencyMap.has(e)||this.dependencyMap.set(e,new Set),this.dependencyMap.get(e).add(r);const a={id:r,get:()=>{try{return n.selector(this.getState())}catch{return}},subscribe:e=>(void 0!==n.cleanupTimer&&(clearTimeout(n.cleanupTimer),n.cleanupTimer=void 0),n.subscribers.add(e),n.count++,()=>{n.subscribers.delete(e),n.count--,0===n.count&&(n.cleanupTimer=setTimeout((()=>{0===n.count&&this.evictEntry(n)}),0))})};return n.reactiveSelectorInstance=a,this.reactiveSelectors.set(r,n),this.pathBasedCache.set(s,n),this.eventBus.emit({name:"selector:accessed",payload:{selectorId:r,accessedPaths:t,duration:0,timestamp:performance.now()}}),a}evictEntry(e){for(const t of e.accessedPaths){const s=this.dependencyMap.get(t);s&&(s.delete(e.id),0===s.size&&this.dependencyMap.delete(t))}this.reactiveSelectors.delete(e.id),this.pathBasedCache.delete(e.pathCacheKey)}dispose(){this.unsubscribeFromStore(),this.reactiveSelectors.clear(),this.dependencyMap.clear(),this.pathBasedCache.clear()}};function w(e,t){if(e===t)return!0;if(e&&t&&"object"==typeof e&&"object"==typeof t){if(e.constructor!==t.constructor)return!1;let s,i;if(Array.isArray(e)){if(s=e.length,s!=t.length)return!1;for(i=s;i-- >0;)if(!w(e[i],t[i]))return!1;return!0}const[r,n]=[Object.keys(e),Object.keys(t)];if(s=r.length,s!==n.length)return!1;for(i=s;i-- >0;){const s=r[i];if(!Object.prototype.hasOwnProperty.call(t,s)||!w(e[s],t[s]))return!1}return!0}return e!=e&&t!=t}function f(e){const t=e?.deleteMarker||l;return function(e,s){const i=[],r=[{pathStr:"",orig:e||{},part:s||{}}];for(;r.length>0;){const{pathStr:e,orig:s,part:n}=r.pop();if(null!=n&&!w(s,n))if("object"!=typeof n||Array.isArray(n))e&&i.push({path:e,oldValue:s,newValue:n});else for(const a of Object.keys(n)){const o=e?e+"."+a:a,c=n[a],h=s&&"object"==typeof s?s[a]:void 0;c!==t?"object"==typeof c&&null!==c?r.push({pathStr:o,orig:h,part:c}):w(h,c)||i.push({path:o,oldValue:h,newValue:c}):void 0!==h&&i.push({path:o,oldValue:h,newValue:void 0})}}return i}}function v(e){const t=e?.deleteMarker||l;return function(e){const s=new Set,i=[{obj:e,currentPath:""}];for(;i.length>0;){const{obj:e,currentPath:r}=i.pop();if(null!=e&&"object"==typeof e&&!Array.isArray(e))for(const n of Object.keys(e)){const a=r?`${r}.${n}`:n;s.add(a);const o=e[n];"object"!=typeof o||null===o||Array.isArray(o)||o===t||i.push({obj:o,currentPath:a})}}return Array.from(s)}}var b=f(),_=v(),S=class{constructor(e,t,s){this.updateBus=t,this.diff=s,this.cache=structuredClone(e)}cache;get(e){return e?structuredClone(this.cache):this.cache}applyChanges(e,t=!1,s=!1,i=[]){if(t)return this.cache=s?structuredClone(e):e,this.notifyListeners([]),[];0===i.length&&(i=[e]);const r=this.get(!1),n=new Map;for(let e=0;e<i.length;e++){const t=i[e],s=this.diff(r,t);for(let e=0;e<s.length;e++){const t=s[e];n.set(t.path,t)}}const a=n.size?[...n.values()]:[];if(a.length>0){this.cache=s?structuredClone(e):e;const t=new Set;for(let e=0;e<a.length;e++){let s=a[e].path;for(;s&&!t.has(s);){t.add(s);const e=s.lastIndexOf(".");if(e<0)break;s=s.slice(0,e)}}this.notifyListeners(t)}return a}notifyListeners(e){for(const t of e)this.updateBus.emit({name:"update",payload:t})}},x=class{constructor(e,t,s){this.eventBus=e,this.executionState=t,this.merge=s}middleware=[];blockingMiddleware=[];async executeBlocking(e,t){for(const{fn:s,name:i,id:r}of this.blockingMiddleware){const n={id:r,name:i,startTime:performance.now()};this.executionState.runningMiddleware={id:r,name:i,startTime:performance.now()},this.emitMiddlewareLifecycle("start",{id:r,name:i,type:"blocking"});try{const a=await Promise.resolve(s(e,t));if(n.endTime=performance.now(),n.duration=n.endTime-n.startTime,!1===a)return n.blocked=!0,this.emitMiddlewareLifecycle("blocked",{id:r,name:i,duration:n.duration}),this.emit(this.eventBus,{name:"middleware:executed",payload:n}),{blocked:!0};this.emitMiddlewareLifecycle("complete",{id:r,name:i,type:"blocking",duration:n.duration}),this.emit(this.eventBus,{name:"middleware:executed",payload:{...n,blocked:!1}})}catch(e){return n.endTime=performance.now(),n.duration=n.endTime-n.startTime,n.error=e instanceof Error?e:new Error(String(e)),n.blocked=!0,this.emitMiddlewareError(r,i,n.error,n.duration),this.emit(this.eventBus,{name:"middleware:executed",payload:n}),{blocked:!0,error:n.error}}finally{this.executionState.runningMiddleware=null}}return{blocked:!1}}async executeTransform(e,t){let s=e,i=t;for(const{fn:e,name:r,id:n}of this.middleware){const a={id:n,name:r,startTime:performance.now()};this.executionState.runningMiddleware={id:n,name:r,startTime:performance.now()},this.emitMiddlewareLifecycle("start",{id:n,name:r,type:"transform"});try{const o=await Promise.resolve(e(s,t));a.endTime=performance.now(),a.duration=a.endTime-a.startTime,a.blocked=!1,o&&"object"==typeof o&&(s=this.merge(s,o),i=this.merge(i,o)),this.emit(this.eventBus,{name:"middleware:executed",payload:a}),this.emitMiddlewareLifecycle("complete",{id:n,name:r,type:"transform",duration:a.duration})}catch(e){a.endTime=performance.now(),a.duration=a.endTime-a.startTime,a.error=e instanceof Error?e:new Error(String(e)),a.blocked=!1,this.emit(this.eventBus,{name:"middleware:executed",payload:a}),this.emitMiddlewareError(n,r,a.error,a.duration),console.error(`Middleware ${r} error:`,e)}finally{this.executionState.runningMiddleware=null}}return i}addMiddleware(e,t="unnamed-middleware"){const s=this.generateId();return this.middleware.push({fn:e,name:t,id:s}),this.updateExecutionState(),s}addBlockingMiddleware(e,t="unnamed-blocking-middleware"){const s=this.generateId();return this.blockingMiddleware.push({fn:e,name:t,id:s}),this.updateExecutionState(),s}removeMiddleware(e){const t=this.middleware.length+this.blockingMiddleware.length;return this.middleware=this.middleware.filter((t=>t.id!==e)),this.blockingMiddleware=this.blockingMiddleware.filter((t=>t.id!==e)),this.updateExecutionState(),this.middleware.length+this.blockingMiddleware.length<t}updateExecutionState(){this.executionState.middlewares=[...this.middleware.map((e=>e.name)),...this.blockingMiddleware.map((e=>e.name))]}emitMiddlewareLifecycle(e,t){this.emit(this.eventBus,{name:`middleware:${e}`,payload:{...t,timestamp:Date.now()}})}emitMiddlewareError(e,t,s,i){this.emit(this.eventBus,{name:"middleware:error",payload:{id:e,name:t,error:s,duration:i,timestamp:Date.now()}})}generateId(){return crypto.randomUUID?crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).substring(2,15)}`}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},k=class{constructor(e,t,s,i){this.eventBus=e,this.coreState=t,this.instanceID=s,this.maxRetries=i?.maxRetries??3,this.retryDelay=i?.retryDelay??1e3}persistence;instanceID;persistenceReady=!1;backgroundQueue=[];isProcessingQueue=!1;maxRetries=3;retryDelay=1e3;queueProcessor;pendingRetries=new Set;async initialize(e){e?await this.setPersistence(e):this.setPersistenceReady()}isReady(){return this.persistenceReady}handleStateChange(e,t){if(!this.persistence||0===e.length)return;const s={id:`${Date.now()}-${Math.random().toString(36).slice(2,11)}`,state:structuredClone(t),changedPaths:[...e],timestamp:Date.now(),retries:0};this.backgroundQueue.push(s),this.scheduleQueueProcessing(),this.emit(this.eventBus,{name:"persistence:queued",payload:{taskId:s.id,changedPaths:e,queueSize:this.backgroundQueue.length,timestamp:s.timestamp}})}getQueueStatus(){return{queueSize:this.backgroundQueue.length,isProcessing:this.isProcessingQueue,pendingRetries:this.pendingRetries.size,oldestTask:this.backgroundQueue[0]?.timestamp}}async flush(){this.isProcessingQueue&&await new Promise((e=>{const t=()=>{this.isProcessingQueue?setTimeout(t,10):e()};t()})),await this.processQueue()}discardQueue(){const e=this.backgroundQueue.length+this.pendingRetries.size;this.backgroundQueue=[],this.pendingRetries.clear(),this.queueProcessor&&(clearTimeout(this.queueProcessor),this.queueProcessor=void 0),this.emit(this.eventBus,{name:"persistence:queue_cleared",payload:{clearedTasks:e,timestamp:Date.now()}})}scheduleQueueProcessing(){this.queueProcessor||this.isProcessingQueue||(this.queueProcessor=setTimeout((()=>{this.processQueue().catch((e=>{console.error("Queue processing failed:",e)}))}),10))}async processQueue(){if(!this.isProcessingQueue&&0!==this.backgroundQueue.length){this.isProcessingQueue=!0,this.queueProcessor=void 0;try{for(;this.backgroundQueue.length>0;){const e=this.backgroundQueue.shift();await this.processTask(e)}}finally{this.isProcessingQueue=!1}}}async processTask(e){try{await this.persistence.set(this.instanceID,e.state)?this.emit(this.eventBus,{name:"persistence:success",payload:{taskId:e.id,changedPaths:e.changedPaths,duration:Date.now()-e.timestamp,timestamp:Date.now()}}):await this.handleTaskFailure(e,new Error("Persistence returned false"))}catch(t){await this.handleTaskFailure(e,t)}}async handleTaskFailure(e,t){if(e.retries++,e.retries<=this.maxRetries){const s=this.retryDelay*Math.pow(2,e.retries-1);this.emit(this.eventBus,{name:"persistence:retry",payload:{taskId:e.id,attempt:e.retries,maxRetries:this.maxRetries,nextRetryIn:s,error:t,timestamp:Date.now()}}),this.pendingRetries.add(e.id),setTimeout((()=>{this.pendingRetries.has(e.id)&&(this.pendingRetries.delete(e.id),this.backgroundQueue.unshift(e),this.scheduleQueueProcessing())}),s)}else this.emit(this.eventBus,{name:"persistence:failed",payload:{taskId:e.id,changedPaths:e.changedPaths,attempts:e.retries,error:t,timestamp:Date.now()}})}setPersistenceReady(){this.persistenceReady=!0,this.emit(this.eventBus,{name:"persistence:ready",payload:{timestamp:Date.now()}})}async setPersistence(e){this.persistence=e;try{const e=await this.persistence.get();e&&this.coreState.applyChanges(e)}catch(e){console.error("Failed to initialize persistence:",e),this.emit(this.eventBus,{name:"persistence:init_error",payload:{error:e,timestamp:Date.now()}})}finally{this.setPersistenceReady()}this.persistence.subscribe(this.instanceID,(async e=>{const t=this.coreState.applyChanges(e);t.length>0&&this.emit(this.eventBus,{name:"update:complete",payload:{changedPaths:t,source:"external",timestamp:Date.now()}})}))}dispose(){this.discardQueue(),this.isProcessingQueue=!1,this.persistenceReady=!1}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},T=class{constructor(e,t,s){this.eventBus=e,this.coreState=t,this.executionState=s}async execute(e){const t=this.coreState.get(!0);this.executionState.transactionActive=!0,this.emit(this.eventBus,{name:"transaction:start",payload:{timestamp:Date.now()}});try{const t=await Promise.resolve(e());return this.emit(this.eventBus,{name:"transaction:complete",payload:{timestamp:Date.now()}}),this.executionState.transactionActive=!1,t}catch(e){throw this.coreState.applyChanges(t,!0,!1),this.emit(this.eventBus,{name:"transaction:error",payload:{error:e instanceof Error?e:new Error(String(e)),timestamp:Date.now()}}),this.executionState.transactionActive=!1,e}}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},E=class{updateCount=0;listenerExecutions=0;averageUpdateTime=0;largestUpdateSize=0;mostActiveListenerPaths=[];totalUpdates=0;blockedUpdates=0;averageUpdateDuration=0;middlewareExecutions=0;transactionCount=0;totalEventsFired=0;totalActionsDispatched=0;totalActionsSucceeded=0;totalActionsFailed=0;averageActionDuration=0;updateTimes=[];actionTimes=[];pathExecutionCounts=new Map;constructor(e){this.setupEventListeners(e)}getMetrics(){return{updateCount:this.updateCount,listenerExecutions:this.listenerExecutions,averageUpdateTime:this.averageUpdateTime,largestUpdateSize:this.largestUpdateSize,mostActiveListenerPaths:[...this.mostActiveListenerPaths],totalUpdates:this.totalUpdates,blockedUpdates:this.blockedUpdates,averageUpdateDuration:this.averageUpdateDuration,middlewareExecutions:this.middlewareExecutions,transactionCount:this.transactionCount,totalEventsFired:this.totalEventsFired,totalActionsDispatched:this.totalActionsDispatched,totalActionsSucceeded:this.totalActionsSucceeded,totalActionsFailed:this.totalActionsFailed,averageActionDuration:this.averageActionDuration}}setupEventListeners(e){const t=e.emit;e.emit=s=>(this.totalEventsFired++,t.call(e,s)),e.subscribe("update:complete",(e=>{if(this.totalUpdates++,e.blocked)this.blockedUpdates++;else{if(e.duration){this.updateTimes.push(e.duration),this.updateTimes.length>100&&this.updateTimes.shift();const t=this.updateTimes.reduce(((e,t)=>e+t),0)/this.updateTimes.length;this.averageUpdateTime=t,this.averageUpdateDuration=t}e.deltas?.length&&(this.updateCount++,this.largestUpdateSize=Math.max(this.largestUpdateSize,e.deltas.length),e.deltas.forEach((e=>{const t=this.pathExecutionCounts.get(e.path)||0;this.pathExecutionCounts.set(e.path,t+1)})),this.mostActiveListenerPaths=Array.from(this.pathExecutionCounts.entries()).sort((([,e],[,t])=>t-e)).slice(0,5).map((([e])=>e)))}})),e.subscribe("middleware:start",(()=>{this.middlewareExecutions++})),e.subscribe("transaction:start",(()=>{this.transactionCount++})),e.subscribe("action:start",(()=>{this.totalActionsDispatched++})),e.subscribe("action:complete",(e=>{this.totalActionsSucceeded++,e.duration&&(this.actionTimes.push(e.duration),this.actionTimes.length>100&&this.actionTimes.shift(),this.averageActionDuration=this.actionTimes.reduce(((e,t)=>e+t),0)/this.actionTimes.length)})),e.subscribe("action:error",(()=>{this.totalActionsFailed++}))}reset(){this.updateCount=0,this.listenerExecutions=0,this.averageUpdateTime=0,this.largestUpdateSize=0,this.mostActiveListenerPaths=[],this.totalUpdates=0,this.blockedUpdates=0,this.averageUpdateDuration=0,this.middlewareExecutions=0,this.transactionCount=0,this.totalEventsFired=0,this.totalActionsDispatched=0,this.totalActionsSucceeded=0,this.totalActionsFailed=0,this.averageActionDuration=0,this.updateTimes=[],this.actionTimes=[],this.pathExecutionCounts.clear()}getDetailedMetrics(){return{pathExecutionCounts:new Map(this.pathExecutionCounts),recentUpdateTimes:[...this.updateTimes],successRate:this.totalUpdates>0?(this.totalUpdates-this.blockedUpdates)/this.totalUpdates:1,averagePathsPerUpdate:this.updateCount>0?Array.from(this.pathExecutionCounts.values()).reduce(((e,t)=>e+t),0)/this.updateCount:0}}dispose(){this.reset()}},M=class extends Error{constructor(){super("Action Cancelled by Debounce"),this.name="ActionCancelledError"}},C=class extends Error{constructor({action:e}){super(`Unknown action: "${e}"`),this.name="UnknownActionError"}},P=()=>{},A={name:"UNDEFINED ACTION",status:()=>!1,subscribe:e=>()=>{}},L=class{constructor(e,t){this.eventBus=e,this.set=t}registrations=new Map;register(e){const i={action:{name:e.name,id:t.v4(),action:e.fn,debounce:e.debounce?{...e.debounce,condition:e.debounce.condition??(()=>!0)}:void 0},debouncer:e.debounce&&e.debounce.delay>0?new s({delay:e.debounce.delay}):void 0,previousArgs:void 0,running:!1,subscription:{listeners:new Set,watcher:null,watchers:new d((()=>[this.eventBus.subscribe("action:start",(t=>t.name===e.name&&this.notifyStatusListeners(e.name))),this.eventBus.subscribe("action:complete",(t=>t.name===e.name&&this.notifyStatusListeners(e.name))),this.eventBus.subscribe("action:error",(t=>t.name===e.name&&this.notifyStatusListeners(e.name)))]),(e=>e?.forEach((e=>e()))),{gracePeriod:"microtask"})}};return this.registrations.set(e.name,i),()=>{const t=this.registrations.get(e.name);t&&(t.debouncer?.cancel(),this.registrations.delete(e.name))}}async dispatch(e,...t){const s=this.registrations.get(e);if(!s)throw new C({action:e});const{action:i,debouncer:r}=s,{debounce:n}=i;if(!r||!n)return this.executeAction(s,t);const a=n.condition(s.previousArgs,t);if(s.previousArgs=t,!a)return this.executeAction(s,t);const o=await r.do((()=>this.executeAction(s,t)));if("cancelled"===o.status)throw new M;if("error"===o.status&&o.error)throw o.error;return o.value}async executeAction(e,t){const s=performance.now();e.running=!0,this.emit(this.eventBus,{name:"action:start",payload:{actionId:e.action.id,name:e.action.name,params:t||[],timestamp:s}});try{const i=await this.set((s=>e.action.action(s,...t)),{actionId:e.action.id}),r=performance.now();return e.running=!1,this.emit(this.eventBus,{name:"action:complete",payload:{actionId:e.action.id,name:e.action.name,params:t,startTime:s,endTime:r,duration:r-s,result:i}}),i}catch(i){const r=performance.now();throw e.running=!1,this.emit(this.eventBus,{name:"action:error",payload:{actionId:e.action.id,name:e.action.name,params:t,startTime:s,endTime:r,duration:r-s,error:i}}),i}}running(e){const t=this.registrations.get(e);return!!t&&t.running}subscribe(e,t){const s=this.registrations.get(e);return s?(s.subscription.listeners.add(t),s.subscription.watchers.acquire(),()=>{s.subscription.listeners.delete(t),s.subscription.watchers?.release()}):P}watch(e){const t=this.registrations.get(e);return t?(t.subscription.watcher||(t.subscription.watcher={name:e,status:()=>this.running(e),subscribe:t=>this.subscribe(e,t)}),t.subscription.watcher):A}notifyStatusListeners(e){const t=this.registrations.get(e).subscription.listeners;t&&t.forEach((e=>e()))}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}};exports.ActionCancelledError=M,exports.ActionManager=L,exports.DELETE_SYMBOL=l,exports.ReactiveDataStore=class{coreState;middlewareEngine;persistenceHandler;transactionManager;metricsCollector;selectorManager;actions;updateSerializer=new h({yieldMode:"macrotask",capacity:1e3});readyLatch=new a;updateBus=e.createEventBus();eventBus;executionState;instanceID=t.v4();merge;diff;constructor(t,s,i=l,r){this.eventBus=e.createEventBus(),this.executionState={executing:!1,changes:null,pendingChanges:[],middlewares:[],runningMiddleware:null,transactionActive:!1},this.merge=p({deleteMarker:i}),this.diff=f({deleteMarker:i}),this.coreState=new S(t,this.updateBus,this.diff),this.middlewareEngine=new x(this.eventBus,this.executionState,this.merge),this.persistenceHandler=new k(this.eventBus,this.coreState,this.instanceID,{maxRetries:r?.persistenceMaxRetries,retryDelay:r?.persistenceRetryDelay}),this.transactionManager=new T(this.eventBus,this.coreState,this.executionState),this.metricsCollector=new E(this.eventBus),this.actions=new L(this.eventBus,this.set.bind(this)),this.persistenceHandler.initialize(s),this.setupPersistenceListener(),this.setupReadyLatch(),this.selectorManager=new y(this.get.bind(this),this.eventBus)}isReady(){return this.readyLatch.isOpen()}async ready(e){return this.readyLatch.wait(e)}state(){return this.executionState.executing=this.updateSerializer.running(),this.executionState}get(e){return this.coreState.get(e??!1)}select(e){return this.selectorManager.createReactiveSelector(e)}register(e){return this.actions.register(e)}async dispatch(e,...t){return this.actions.dispatch(e,...t)}async set(e,t={}){const s=await this.updateSerializer.do((()=>this._performUpdate(e,t)));if(s.error)throw s.error;return s.value}async _performUpdate(e,t){const s=performance.now();this.emit(this.eventBus,{name:"update:start",payload:{timestamp:s,actionId:t.actionId}});try{if(t.force){const i=this.get(!1),r="function"==typeof e?e(i):e;this.coreState.applyChanges(r,!0);const n=performance.now();return this.emit(this.eventBus,{name:"update:complete",payload:{deltas:[],duration:n-s,timestamp:Date.now(),actionId:t.actionId,newState:r}}),r}let i;const r=this.get(!1);if("function"==typeof e){const t=e(r);i=t instanceof Promise?await t:t}else i=e;const n=await this.middlewareEngine.executeBlocking(r,i);if(n.blocked)throw n.error||new Error("Update blocked by middleware");const a=this.merge(r,i),o=await this.middlewareEngine.executeTransform(a,i),c=this.merge(a,o),h=this.coreState.applyChanges(c,!1,!1,[i,o]),d=performance.now(),l=this.get(!1);return this.emit(this.eventBus,{name:"update:complete",payload:{deltas:h,duration:d-s,timestamp:Date.now(),actionId:t.actionId,newState:l}}),l}catch(e){throw this.emit(this.eventBus,{name:"update:complete",payload:{blocked:!0,error:e,timestamp:Date.now(),actionId:t.actionId,newState:this.get(!1)}}),e}finally{this.executionState.executing=!1,this.executionState.changes=null,this.executionState.runningMiddleware=null,this.executionState.pendingChanges=[]}}setupReadyLatch(){this.readyLatch.open(),this.persistenceHandler.isReady()?this.readyLatch.open():queueMicrotask((()=>{this.readyLatch.isOpen()||this.readyLatch.open()}))}setupPersistenceListener(){this.updateBus.subscribe("update",(e=>{e&&this.persistenceHandler.isReady()&&this.persistenceHandler.handleStateChange([e],this.get(!1))}))}watch(e,t){const s=Array.isArray(e)?e:[e],i=""===e||0===s.length;return this.updateBus.subscribe("update",(e=>{(i||s.includes(e))&&(t(this.get(!1)),this.metricsCollector.listenerExecutions++)}))}watchAction(e){return this.actions.watch(e)}debouncedSetter(e){const t=new s({delay:e.delay,leading:e.leading});return(e,s={})=>{t.fire((()=>this.set(e,s)))}}subscribe(e,t){return this.watch(e,t)}id(){return this.instanceID}async transaction(e){return this.transactionManager.execute(e)}use(e){const t=(e.block?this.middlewareEngine.addBlockingMiddleware:this.middlewareEngine.addMiddleware).bind(this.middlewareEngine)(e.action,e.name);return()=>this.middlewareEngine.removeMiddleware(t)}metrics(){return this.metricsCollector.getMetrics()}on(e,t){return this.eventBus.subscribe(e,t)}onStoreEvent(e,t){return this.eventBus.subscribe(e,t)}getPersistenceStatus(){return this.persistenceHandler.getQueueStatus()}async flushPersistence(){return this.persistenceHandler.flush()}discardPersistenceQueue(){this.persistenceHandler.discardQueue()}dispose(){this.updateSerializer.close(),this.persistenceHandler.dispose(),this.metricsCollector.dispose?.(),this.selectorManager.dispose?.()}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},exports.StoreObserver=class{store;eventHistory=[];stateHistory=[];unsubscribers=[];isTimeTraveling=!1;devTools=null;middlewareExecutions=[];activeTransactionCount=0;activeBatches=new Set;maxEvents;maxStateHistory;enableConsoleLogging;isSilent;logEvents;performanceThresholds;constructor(e,t={}){this.store=e,this.maxEvents=t.maxEvents??500,this.maxStateHistory=t.maxStateHistory??20,this.enableConsoleLogging=t.enableConsoleLogging??!1,this.isSilent=t.silent??!1,this.logEvents={updates:t.logEvents?.updates??!0,middleware:t.logEvents?.middleware??!0,transactions:t.logEvents?.transactions??!0,actions:t.logEvents?.actions??!0,selectors:t.logEvents?.selectors??!0},this.performanceThresholds={updateTime:t.performanceThresholds?.updateTime??50,middlewareTime:t.performanceThresholds?.middlewareTime??20},this.recordStateSnapshot([]),this.setupEventListeners()}_consoleLog(e,...t){this.isSilent||"function"==typeof console[e]&&console[e](...t)}setupEventListeners(){const e=["update:start","update:complete","middleware:start","middleware:complete","middleware:error","middleware:blocked","transaction:start","transaction:complete","transaction:error","middleware:executed","action:start","action:complete","action:error","selector:accessed"];for(const t of e){const e=t.startsWith("update")&&this.logEvents.updates||t.startsWith("middleware")&&this.logEvents.middleware||t.startsWith("transaction")&&this.logEvents.transactions||t.startsWith("action")&&this.logEvents.actions||t.startsWith("selector")&&this.logEvents.selectors;this.unsubscribers.push(this.store.on(t,(s=>{"update:complete"!==t||s.blocked||this.isTimeTraveling||this.recordStateSnapshot(s.deltas),"middleware:executed"===t?this.middlewareExecutions.push(s):"transaction:start"===t?this.activeTransactionCount++:"transaction:complete"!==t&&"transaction:error"!==t||(this.activeTransactionCount=Math.max(0,this.activeTransactionCount-1)),s.batchId&&(t.endsWith("start")?this.activeBatches.add(s.batchId):(t.endsWith("complete")||t.endsWith("error"))&&this.activeBatches.delete(s.batchId)),this.recordEvent(t,s),this.enableConsoleLogging&&e&&this._log(t,s),this._checkPerformance(t,s)})))}}recordStateSnapshot(e){const t={state:this.store.get(!0),timestamp:Date.now(),deltas:e};this.stateHistory.unshift(t),this.stateHistory.length>this.maxStateHistory&&this.stateHistory.pop()}recordEvent(e,t){const s={type:e,timestamp:Date.now(),data:structuredClone(t)};this.eventHistory.unshift(s),this.eventHistory.length>this.maxEvents&&this.eventHistory.pop()}getEventHistory(){return structuredClone(this.eventHistory)}getStateHistory(){return structuredClone(this.stateHistory)}getMiddlewareExecutions(){return this.middlewareExecutions}getTransactionStatus(){return{activeTransactions:this.activeTransactionCount,activeBatches:Array.from(this.activeBatches)}}createLoggingMiddleware(e={}){const{logLevel:t="debug",logUpdates:s=!0}=e;return(e,i)=>{if(s){(console[t]||console.log)("State Update:",i)}return i}}createValidationMiddleware(e){return(t,s)=>{const i=e(t,s);return"boolean"==typeof i?i:(!i.valid&&i.reason&&this._consoleLog("warn","Validation failed:",i.reason),i.valid)}}getRecentChanges(e=5){const t=[],s=Math.min(e,this.stateHistory.length);for(let e=0;e<s;e++){const s=this.stateHistory[e];if(!s.deltas||0===s.deltas.length)continue;const i={},r={},n=(e,t,s)=>{t.reduce(((e,i,r)=>(r===t.length-1?e[i]=s:e[i]=e[i]??{},e[i])),e)};for(const e of s.deltas){const t=e.path.split(".");n(i,t,e.oldValue),n(r,t,e.newValue)}t.push({timestamp:s.timestamp,changedPaths:s.deltas.map((e=>e.path)),from:i,to:r})}return t}clearHistory(){this.eventHistory=[],this.stateHistory.length>0&&(this.stateHistory=[this.stateHistory[0]])}getHistoryForAction(e){return this.eventHistory.filter((t=>t.data?.actionId===e))}async replay(e){const t=this.eventHistory.filter((e=>"update:start"===e.type))[e];t?.data.update?(this._consoleLog("log",`Replaying event at index ${e}:`,t),await this.store.set(t.data.update,{force:!0})):this._consoleLog("warn",`No replayable event found at index ${e}.`)}createTimeTravel(){let e=0,t=[];const s=this.store.on("update:complete",(s=>{this.isTimeTraveling||s.blocked||(t=[],e=0)}));this.unsubscribers.push(s);const i=()=>this.stateHistory.length,r=()=>e<i()-1,n=()=>t.length>0;return{canUndo:r,canRedo:n,undo:async()=>{if(!r())return;t.unshift(this.stateHistory[e]),e++;const s=this.stateHistory[e].state;this.isTimeTraveling=!0,await this.store.set({...s},{force:!0}),this.isTimeTraveling=!1},redo:async()=>{if(!n())return;const s=t.shift();e--,this.isTimeTraveling=!0,await this.store.set({...s.state},{force:!0}),this.isTimeTraveling=!1},length:i,clear:()=>{t=[],e=0}}}async saveSession(e){const t=this.store.id(),s={eventHistory:this.eventHistory,stateHistory:this.stateHistory};return Promise.resolve(e.set(t,s))}async loadSession(e){const t=await Promise.resolve(e.get());return!!t&&(this.eventHistory=t.eventHistory||[],this.stateHistory=t.stateHistory||[],this.stateHistory.length>0&&await this.store.set(this.stateHistory[0].state,{force:!0}),!0)}exportSession(){const e={eventHistory:this.eventHistory,stateHistory:this.stateHistory},t=new Blob([JSON.stringify(e,null,2)],{type:"application/json"}),s=URL.createObjectURL(t),i=document.createElement("a");i.href=s,i.download=`store-observer-session-${(new Date).toISOString()}.json`,i.click(),URL.revokeObjectURL(s)}importSession(e){return new Promise(((t,s)=>{const i=new FileReader;i.onload=async e=>{try{const s=JSON.parse(e.target?.result);this.eventHistory=s.eventHistory||[],this.stateHistory=s.stateHistory||[],this.stateHistory.length>0&&await this.store.set(this.stateHistory[0].state,{force:!0}),t()}catch(e){s(e)}},i.onerror=e=>s(e),i.readAsText(e)}))}disconnect(){this.unsubscribers.forEach((e=>e())),this.unsubscribers=[],this.devTools?.disconnect(),this.clearHistory()}_log(e,t){const s=new Date(t.timestamp||Date.now()).toISOString().split("T")[1].replace("Z","");if("update:start"===e)this._consoleLog("group",`%c⚡ Store Update Started [${s}]`,"color: #4a6da7");else if("update:complete"===e){if(t.blocked)this._consoleLog("warn",`%c✋ Update Blocked [${s}]`,"color: #bf8c0a",t.error);else{const e=t.deltas||[];e.length>0&&(this._consoleLog("log",`%c✅ Update Complete [${s}] - ${e.length} paths changed in ${t.duration?.toFixed(2)}ms`,"color: #2a9d8f"),this._consoleLog("table",e.map((e=>({path:e.path,oldValue:e.oldValue,newValue:e.newValue})))))}this._consoleLog("groupEnd")}else"middleware:start"===e?this._consoleLog("debug",`%c◀ Middleware "${t.name}" started [${s}] (${t.type})`,"color: #8c8c8c"):"middleware:complete"===e?this._consoleLog("debug",`%c▶ Middleware "${t.name}" completed [${s}] in ${t.duration?.toFixed(2)}ms`,"color: #7c9c7c"):"middleware:error"===e?this._consoleLog("error",`%c❌ Middleware "${t.name}" error [${s}]:`,"color: #e63946",t.error):"middleware:blocked"===e?this._consoleLog("warn",`%c🛑 Middleware "${t.name}" blocked update [${s}]`,"color: #e76f51"):"transaction:start"===e?this._consoleLog("group",`%c📦 Transaction Started [${s}]`,"color: #6d597a"):"transaction:complete"===e?(this._consoleLog("log",`%c📦 Transaction Complete [${s}]`,"color: #355070"),this._consoleLog("groupEnd")):"transaction:error"===e?(this._consoleLog("error",`%c📦 Transaction Error [${s}]:`,"color: #e56b6f",t.error),this._consoleLog("groupEnd")):"action:start"===e?this._consoleLog("group",`%c🚀 Action "${t.name}" Started [${s}]`,"color: #9b59b6",{params:t.params}):"action:complete"===e?(this._consoleLog("log",`%c✔️ Action "${t.name}" Complete [${s}] in ${t.duration?.toFixed(2)}ms`,"color: #2ecc71"),this._consoleLog("groupEnd")):"action:error"===e?(this._consoleLog("error",`%c🔥 Action "${t.name}" Error [${s}]:`,"color: #e74c3c",t.error),this._consoleLog("groupEnd")):"selector:accessed"===e&&this._consoleLog("debug",`%c👀 Selector Accessed [${s}] in ${t.duration?.toFixed(2)}ms`,"color: #f1c40f",{accessedPaths:t.accessedPaths,selectorId:t.selectorId})}_checkPerformance(e,t){this.enableConsoleLogging&&("update:complete"===e&&!t.blocked&&t.duration>this.performanceThresholds.updateTime&&this._consoleLog("warn",`%c⚠️ Slow update detected [${t.duration.toFixed(2)}ms]`,"color: #ff9f1c",{deltas:t.deltas,threshold:this.performanceThresholds.updateTime}),"middleware:complete"===e&&t.duration>this.performanceThresholds.middlewareTime&&this._consoleLog("warn",`%c⚠️ Slow middleware "${t.name}" [${t.duration.toFixed(2)}ms]`,"color: #ff9f1c",{threshold:this.performanceThresholds.middlewareTime}))}},exports.UnknownActionError=C,exports.createDerivePaths=v,exports.createDiff=f,exports.createMerge=p,exports.derivePaths=_,exports.diff=b,exports.merge=m,exports.shallowClone=u;
|
|
1
|
+
"use strict";var e=require("@asaidimu/utils-events"),t=require("uuid"),s=class{_delay;_leading;_timer;_pendingFn;_pendingResolvers=[];_leadingFired=!1;constructor(e){this._delay=e?.delay??300,this._leading=e?.leading??!1}do(e){return new Promise((t=>{this._enqueue(e,t)}))}fire(e){this._enqueue(e,void 0)}_enqueue(e,t){if(this._pendingFn=e,t&&this._pendingResolvers.push(t),this._leading&&!this._leadingFired)return this._leadingFired=!0,this._fire(),clearTimeout(this._timer),void(this._timer=setTimeout((()=>{this._leadingFired=!1,void 0!==this._pendingFn&&this._fire()}),this._delay));clearTimeout(this._timer),this._timer=setTimeout((()=>{this._leadingFired=!1,this._fire()}),this._delay)}cancel(){clearTimeout(this._timer),this._timer=void 0,this._pendingFn=void 0,this._leadingFired=!1;const e=this._pendingResolvers.splice(0);for(const t of e)t({status:"cancelled"})}async flush(){return this._pendingFn?(clearTimeout(this._timer),this._timer=void 0,this._leadingFired=!1,this._fire()):null}pending(){return void 0!==this._pendingFn}async _fire(){const e=this._pendingFn,t=this._pendingResolvers.splice(0);let s;this._pendingFn=void 0;try{s={status:"ok",value:await e()}}catch(e){s={status:"error",error:e}}for(const e of t)e(s);return s}},i=class e extends Error{constructor(t,s){super(t,{cause:s}),this.name="SyncError",Object.setPrototypeOf(this,e.prototype)}},r=class extends i{constructor(e){super(`[ArtifactContainer] Operation timed out: ${e}`)}},n=class extends i{constructor(e){super("[Serializer] The serializer has been marked as done!",e)}},a=class{_open=!1;_resolve;_promise;constructor(){this._promise=new Promise((e=>{this._resolve=e}))}open(){this._open||(this._open=!0,this._resolve())}async wait(e){if(this._open)return;if(null==e)return this._promise;let t;await Promise.race([this._promise.then((()=>clearTimeout(t))),new Promise(((s,i)=>{t=setTimeout((()=>i(new r("Latch timed out"))),e)}))])}isOpen(){return this._open}},o=class{_locked=!1;_capacity;_yieldMode;waiters=[];constructor(e){this._capacity=e?.capacity??1/0,this._yieldMode=e?.yieldMode??"macrotask"}async lock(e){if(!this._locked)return void(this._locked=!0);if(this.waiters.length>=this._capacity)throw new Error(`Mutex queue is full (capacity: ${this._capacity})`);let t;const s=new Promise((e=>t=e));if(this.waiters.push(t),null==e)return void await s;let i;await Promise.race([s.then((()=>clearTimeout(i))),new Promise(((s,n)=>{i=setTimeout((()=>{const e=this.waiters.indexOf(t);-1!==e&&this.waiters.splice(e,1),n(new r("Mutex lock timed out"))}),e)}))])}tryLock(){return!this._locked&&(this._locked=!0,!0)}unlock(){if(!this._locked)throw new Error("Mutex is not locked");const e=this.waiters.shift();e?"microtask"===this._yieldMode?queueMicrotask(e):setTimeout(e,0):this._locked=!1}locked(){return this._locked}pending(){return this.waiters.length}},c=class{mutex=new o({yieldMode:"microtask"});promise=null;_value=null;_error;_done=!1;retry;throws;constructor({retry:e,throws:t}={}){this.retry=Boolean(e),this.throws=Boolean(t)}async do(e,t){return this._done?this.peek():this.promise?this._awaitWithTimeout(this.promise,t,"Once do() timed out"):(await this.mutex.lock(),this.promise?(this.mutex.unlock(),this._awaitWithTimeout(this.promise,t,"Once do() timed out")):(this.promise=(async()=>{try{this._value=await e(),this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.retry&&!this._done&&(this.promise=null)}return this.peek()})(),this.mutex.unlock(),this._awaitWithTimeout(this.promise,t,"Once do() timed out")))}doSync(e){if(this._done){if(this.throws&&this._error)throw this._error;return this.peek()}if(this.promise){const e=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw e;return{value:null,error:e}}if(!this.mutex.tryLock()){const e=new Error("Cannot execute doSync: lock is currently held.");if(this.throws)throw e;return{value:null,error:e}}if(this.promise||this._done){if(this.mutex.unlock(),this._done){if(this.throws&&this._error)throw this._error;return this.peek()}const e=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw e;return{value:null,error:e}}try{const t=e();this._value=t,this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.mutex.unlock()}return this.peek()}running(){return null!==this.promise&&!this.done()}peek(){return{value:this._value,error:this._error}}get(){if(!this._done)throw new Error("Once operation is not yet complete");if(this._error)throw this._error;return this._value}reset(){if(this.running())throw new Error("Cannot reset Once while an operation is in progress.");this._done=!1,this.promise=null,this._value=null,this._error=void 0}done(){return this._done}current(){return this.promise}_awaitWithTimeout(e,t,s="Operation timed out"){if(null==t)return e;let i;return Promise.race([e.then((e=>(clearTimeout(i),e))),new Promise(((e,n)=>{i=setTimeout((()=>n(new r(s))),t)}))])}},h=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;_hasRun=!1;constructor(e){this.mutex=new o({capacity:e?.capacity??1e3,yieldMode:e?.yieldMode??"macrotask"})}async do(e,t){if(this._done)return{value:null,error:new n};try{await this.mutex.lock(t)}catch(e){return{value:null,error:e}}let s,i=null;try{if(this._done)throw new n;i=await e(),this._lastValue=i,this._lastError=void 0,this._hasRun=!0}catch(e){s=e,this._lastError=e,this._hasRun=!0}finally{this.mutex.unlock()}return{value:i,error:s}}peek(){return{value:this._lastValue,error:this._lastError}}hasRun(){return this._hasRun}close(){this._done=!0}pending(){return this.mutex.pending()}running(){return this.mutex.locked()}},d=class{constructor(e,t,s={}){this.factory=e,this.onCleanup=t,this.options=s}_count=0;init=new c({retry:!1,throws:!1});pendingMicrotask=!1;cleanupTimer;get subscribers(){return this._count}async acquire(){this.cancelPendingCleanup(),this._count++;const e=await this.init.do(this.factory);if(e.error)throw e.error;return e.value}release(){this._count<=0?console.warn("SharedResource.release() called, but count is already 0."):(this._count--,0===this._count&&this.scheduleCleanup())}peek(){const e=this.init.peek();return e.error?null:e.value}forceCleanup(){this.cancelPendingCleanup(),this._count=0,this.executeCleanup()}cancelPendingCleanup(){this.pendingMicrotask=!1,void 0!==this.cleanupTimer&&(clearTimeout(this.cleanupTimer),this.cleanupTimer=void 0)}scheduleCleanup(){const e=this.options.gracePeriod??"microtask";if("sync"!==e)return"microtask"===e?(this.pendingMicrotask=!0,void queueMicrotask((()=>{!this.pendingMicrotask||this._count>0||(this.pendingMicrotask=!1,this.executeCleanup())}))):void(this.cleanupTimer=setTimeout((()=>{this.cleanupTimer=void 0,this._count>0||this.executeCleanup()}),e));this.executeCleanup()}executeCleanup(){const e=this.init.peek();try{this.onCleanup(e.value)}catch(e){console.error("[SharedResource] Error during cleanup callback:",e)}this.init.running()||this.init.reset()}},l=Symbol.for("delete"),u=e=>Array.isArray(e)?[...e]:{...e};function p(e){const t=e?.deleteMarker||l;function s(e){if(null==e)return e;if(Array.isArray(e))return e.filter((e=>e!==t)).map((e=>"object"!=typeof e||null===e||Array.isArray(e)?e:s(e)));if("object"==typeof e){const i={};for(const[r,n]of Object.entries(e))if(n!==t)if("object"==typeof n&&null!==n){const e=s(n);void 0!==e&&(i[r]=e)}else i[r]=n;return i}return e===t?void 0:e}return function(e,i){if("object"!=typeof e||null===e)return"object"==typeof i&&null!==i?s(i):i===t?{}:i;if("object"!=typeof i||null===i)return e;const r=u(e),n=[{target:r,source:i}];for(;n.length>0;){const{target:e,source:s}=n.pop();for(const i of Object.keys(s)){const r=s[i];if(r!==t)if(Array.isArray(r))e[i]=r;else if("object"==typeof r&&null!==r){const t=i in e&&"object"==typeof e[i]&&null!==e[i]?e[i]:{};e[i]=u(t),n.push({target:e[i],source:r})}else e[i]=r;else delete e[i]}}return r}}var m=p(),g=["map","filter","reduce","forEach","find","findIndex","some","every","includes","flatMap","flat","slice","splice"],y=class{reactiveSelectors=new Map;pathBasedCache=new Map;dependencyMap=new Map;getState;eventBus;unsubscribeFromStore;constructor(e,t){this.getState=e,this.eventBus=t,this.unsubscribeFromStore=this.eventBus.subscribe("update:complete",this.handleStoreUpdate)}handleStoreUpdate=e=>{const t=new Set;for(const s of e.deltas){const e=s.path;for(const[s,i]of this.dependencyMap)if(s===e||s.startsWith(e+".")||e.startsWith(s+"."))for(const e of i)t.add(e)}for(const e of t){const t=this.reactiveSelectors.get(e);t&&this.evaluateEntry(t)}};evaluateEntry(e){let t;try{t=e.selector(this.getState())}catch{t=void 0}if(t!==e.lastResult){e.lastResult=t;for(const s of e.subscribers)s(t);this.eventBus.emit({name:"selector:changed",payload:{selectorId:e.id,newResult:t,timestamp:performance.now()}})}}createReactiveSelector(e){const t=function(e,t="."){const s=new Set,i=new Map,r=(e="")=>{if(i.has(e))return i.get(e);const n=new Proxy((()=>{}),{get:(i,n)=>{if("symbol"==typeof n||"then"===n)return;if("valueOf"===n||"toString"===n)throw new Error("Cannot perform logic, arithmetic, or string operations inside a selector.");if(g.includes(n))throw new Error(`Array method .${n}() is not allowed in selectors.`);const a=e?`${e}${t}${n}`:n;return e&&s.delete(e),s.add(a),r(a)},has:()=>{throw new Error("The 'in' operator is not allowed in selectors.")},apply:()=>{throw new Error("Selectors cannot call functions or methods.")}});return i.set(e,n),n};try{e(r())}catch(e){throw new Error(`Selector failed during path analysis. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}return Array.from(s)}(e),s=[...t].sort().join("|"),i=this.pathBasedCache.get(s);if(i)return void 0!==i.cleanupTimer&&(clearTimeout(i.cleanupTimer),i.cleanupTimer=void 0),i.reactiveSelectorInstance;const r=`sel-${Math.random().toString(36).slice(2,9)}`,n={id:r,selector:e,lastResult:e(this.getState()),accessedPaths:t,subscribers:new Set,count:0,cleanupTimer:void 0,pathCacheKey:s,reactiveSelectorInstance:null};for(const e of t)this.dependencyMap.has(e)||this.dependencyMap.set(e,new Set),this.dependencyMap.get(e).add(r);const a={id:r,get:()=>{try{return n.selector(this.getState())}catch{return}},subscribe:e=>(void 0!==n.cleanupTimer&&(clearTimeout(n.cleanupTimer),n.cleanupTimer=void 0),n.subscribers.add(e),n.count++,()=>{n.subscribers.delete(e),n.count--,0===n.count&&(n.cleanupTimer=setTimeout((()=>{0===n.count&&this.evictEntry(n)}),0))})};return n.reactiveSelectorInstance=a,this.reactiveSelectors.set(r,n),this.pathBasedCache.set(s,n),this.eventBus.emit({name:"selector:accessed",payload:{selectorId:r,accessedPaths:t,duration:0,timestamp:performance.now()}}),a}evictEntry(e){for(const t of e.accessedPaths){const s=this.dependencyMap.get(t);s&&(s.delete(e.id),0===s.size&&this.dependencyMap.delete(t))}this.reactiveSelectors.delete(e.id),this.pathBasedCache.delete(e.pathCacheKey)}dispose(){this.unsubscribeFromStore(),this.reactiveSelectors.clear(),this.dependencyMap.clear(),this.pathBasedCache.clear()}};function w(e,t){if(e===t)return!0;if(e&&t&&"object"==typeof e&&"object"==typeof t){if(e.constructor!==t.constructor)return!1;let s,i;if(Array.isArray(e)){if(s=e.length,s!=t.length)return!1;for(i=s;i-- >0;)if(!w(e[i],t[i]))return!1;return!0}const[r,n]=[Object.keys(e),Object.keys(t)];if(s=r.length,s!==n.length)return!1;for(i=s;i-- >0;){const s=r[i];if(!Object.prototype.hasOwnProperty.call(t,s)||!w(e[s],t[s]))return!1}return!0}return e!=e&&t!=t}function f(e){const t=e?.deleteMarker||l;return function(e,s){const i=[],r=[{pathStr:"",orig:e||{},part:s||{}}];for(;r.length>0;){const{pathStr:e,orig:s,part:n}=r.pop();if(null!=n&&!w(s,n))if("object"!=typeof n||Array.isArray(n))e&&i.push({path:e,oldValue:s,newValue:n});else for(const a of Object.keys(n)){const o=e?e+"."+a:a,c=n[a],h=s&&"object"==typeof s?s[a]:void 0;c!==t?"object"==typeof c&&null!==c?r.push({pathStr:o,orig:h,part:c}):w(h,c)||i.push({path:o,oldValue:h,newValue:c}):void 0!==h&&i.push({path:o,oldValue:h,newValue:void 0})}}return i}}function v(e){const t=e?.deleteMarker||l;return function(e){const s=new Set,i=[{obj:e,currentPath:""}];for(;i.length>0;){const{obj:e,currentPath:r}=i.pop();if(null!=e&&"object"==typeof e&&!Array.isArray(e))for(const n of Object.keys(e)){const a=r?`${r}.${n}`:n;s.add(a);const o=e[n];"object"!=typeof o||null===o||Array.isArray(o)||o===t||i.push({obj:o,currentPath:a})}}return Array.from(s)}}var b=f(),_=v(),S=class{constructor(e,t,s){this.updateBus=t,this.diff=s,this.cache=structuredClone(e)}cache;get(e){return e?structuredClone(this.cache):this.cache}applyChanges(e,t=!1,s=!1,i=[]){if(t)return this.cache=s?structuredClone(e):e,this.notifyListeners([]),[];0===i.length&&(i=[e]);const r=this.get(!1),n=new Map;for(let e=0;e<i.length;e++){const t=i[e],s=this.diff(r,t);for(let e=0;e<s.length;e++){const t=s[e];n.set(t.path,t)}}const a=n.size?[...n.values()]:[];if(a.length>0){this.cache=s?structuredClone(e):e;const t=new Set;for(let e=0;e<a.length;e++){let s=a[e].path;for(;s&&!t.has(s);){t.add(s);const e=s.lastIndexOf(".");if(e<0)break;s=s.slice(0,e)}}this.notifyListeners(t)}return a}notifyListeners(e){for(const t of e)this.updateBus.emit({name:"update",payload:t})}},x=class{constructor(e,t,s){this.eventBus=e,this.executionState=t,this.merge=s}middleware=[];blockingMiddleware=[];async executeBlocking(e,t){for(const{fn:s,name:i,id:r}of this.blockingMiddleware){const n={id:r,name:i,startTime:performance.now()};this.executionState.runningMiddleware={id:r,name:i,startTime:performance.now()},this.emitMiddlewareLifecycle("start",{id:r,name:i,type:"blocking"});try{const a=await Promise.resolve(s(e,t));if(n.endTime=performance.now(),n.duration=n.endTime-n.startTime,!1===a)return n.blocked=!0,this.emitMiddlewareLifecycle("blocked",{id:r,name:i,duration:n.duration}),this.emit(this.eventBus,{name:"middleware:executed",payload:n}),{blocked:!0};this.emitMiddlewareLifecycle("complete",{id:r,name:i,type:"blocking",duration:n.duration}),this.emit(this.eventBus,{name:"middleware:executed",payload:{...n,blocked:!1}})}catch(e){return n.endTime=performance.now(),n.duration=n.endTime-n.startTime,n.error=e instanceof Error?e:new Error(String(e)),n.blocked=!0,this.emitMiddlewareError(r,i,n.error,n.duration),this.emit(this.eventBus,{name:"middleware:executed",payload:n}),{blocked:!0,error:n.error}}finally{this.executionState.runningMiddleware=null}}return{blocked:!1}}async executeTransform(e,t){let s=e,i=t;for(const{fn:e,name:r,id:n}of this.middleware){const a={id:n,name:r,startTime:performance.now()};this.executionState.runningMiddleware={id:n,name:r,startTime:performance.now()},this.emitMiddlewareLifecycle("start",{id:n,name:r,type:"transform"});try{const o=await Promise.resolve(e(s,t));a.endTime=performance.now(),a.duration=a.endTime-a.startTime,a.blocked=!1,o&&"object"==typeof o&&(s=this.merge(s,o),i=this.merge(i,o)),this.emit(this.eventBus,{name:"middleware:executed",payload:a}),this.emitMiddlewareLifecycle("complete",{id:n,name:r,type:"transform",duration:a.duration})}catch(e){a.endTime=performance.now(),a.duration=a.endTime-a.startTime,a.error=e instanceof Error?e:new Error(String(e)),a.blocked=!1,this.emit(this.eventBus,{name:"middleware:executed",payload:a}),this.emitMiddlewareError(n,r,a.error,a.duration),console.error(`Middleware ${r} error:`,e)}finally{this.executionState.runningMiddleware=null}}return i}addMiddleware(e,t="unnamed-middleware"){const s=this.generateId();return this.middleware.push({fn:e,name:t,id:s}),this.updateExecutionState(),s}addBlockingMiddleware(e,t="unnamed-blocking-middleware"){const s=this.generateId();return this.blockingMiddleware.push({fn:e,name:t,id:s}),this.updateExecutionState(),s}removeMiddleware(e){const t=this.middleware.length+this.blockingMiddleware.length;return this.middleware=this.middleware.filter((t=>t.id!==e)),this.blockingMiddleware=this.blockingMiddleware.filter((t=>t.id!==e)),this.updateExecutionState(),this.middleware.length+this.blockingMiddleware.length<t}updateExecutionState(){this.executionState.middlewares=[...this.middleware.map((e=>e.name)),...this.blockingMiddleware.map((e=>e.name))]}emitMiddlewareLifecycle(e,t){this.emit(this.eventBus,{name:`middleware:${e}`,payload:{...t,timestamp:Date.now()}})}emitMiddlewareError(e,t,s,i){this.emit(this.eventBus,{name:"middleware:error",payload:{id:e,name:t,error:s,duration:i,timestamp:Date.now()}})}generateId(){return crypto.randomUUID?crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).substring(2,15)}`}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},k=class{constructor(e,t,s,i){this.eventBus=e,this.coreState=t,this.instanceID=s,this.maxRetries=i?.maxRetries??3,this.retryDelay=i?.retryDelay??1e3}persistence;instanceID;persistenceReady=!1;backgroundQueue=[];isProcessingQueue=!1;maxRetries=3;retryDelay=1e3;queueProcessor;pendingRetries=new Set;async initialize(e){e?await this.setPersistence(e):this.setPersistenceReady()}isReady(){return this.persistenceReady}handleStateChange(e,t){if(!this.persistence||0===e.length)return;const s={id:`${Date.now()}-${Math.random().toString(36).slice(2,11)}`,state:structuredClone(t),changedPaths:[...e],timestamp:Date.now(),retries:0};this.backgroundQueue.push(s),this.scheduleQueueProcessing(),this.emit(this.eventBus,{name:"persistence:queued",payload:{taskId:s.id,changedPaths:e,queueSize:this.backgroundQueue.length,timestamp:s.timestamp}})}getQueueStatus(){return{queueSize:this.backgroundQueue.length,isProcessing:this.isProcessingQueue,pendingRetries:this.pendingRetries.size,oldestTask:this.backgroundQueue[0]?.timestamp}}async flush(){this.isProcessingQueue&&await new Promise((e=>{const t=()=>{this.isProcessingQueue?setTimeout(t,10):e()};t()})),await this.processQueue()}discardQueue(){const e=this.backgroundQueue.length+this.pendingRetries.size;this.backgroundQueue=[],this.pendingRetries.clear(),this.queueProcessor&&(clearTimeout(this.queueProcessor),this.queueProcessor=void 0),this.emit(this.eventBus,{name:"persistence:queue_cleared",payload:{clearedTasks:e,timestamp:Date.now()}})}scheduleQueueProcessing(){this.queueProcessor||this.isProcessingQueue||(this.queueProcessor=setTimeout((()=>{this.processQueue().catch((e=>{console.error("Queue processing failed:",e)}))}),10))}async processQueue(){if(!this.isProcessingQueue&&0!==this.backgroundQueue.length){this.isProcessingQueue=!0,this.queueProcessor=void 0;try{for(;this.backgroundQueue.length>0;){const e=this.backgroundQueue.shift();await this.processTask(e)}}finally{this.isProcessingQueue=!1}}}async processTask(e){try{await this.persistence.set(this.instanceID,e.state)?this.emit(this.eventBus,{name:"persistence:success",payload:{taskId:e.id,changedPaths:e.changedPaths,duration:Date.now()-e.timestamp,timestamp:Date.now()}}):await this.handleTaskFailure(e,new Error("Persistence returned false"))}catch(t){await this.handleTaskFailure(e,t)}}async handleTaskFailure(e,t){if(e.retries++,e.retries<=this.maxRetries){const s=this.retryDelay*Math.pow(2,e.retries-1);this.emit(this.eventBus,{name:"persistence:retry",payload:{taskId:e.id,attempt:e.retries,maxRetries:this.maxRetries,nextRetryIn:s,error:t,timestamp:Date.now()}}),this.pendingRetries.add(e.id),setTimeout((()=>{this.pendingRetries.has(e.id)&&(this.pendingRetries.delete(e.id),this.backgroundQueue.unshift(e),this.scheduleQueueProcessing())}),s)}else this.emit(this.eventBus,{name:"persistence:failed",payload:{taskId:e.id,changedPaths:e.changedPaths,attempts:e.retries,error:t,timestamp:Date.now()}})}setPersistenceReady(){this.persistenceReady=!0,this.emit(this.eventBus,{name:"persistence:ready",payload:{timestamp:Date.now()}})}async setPersistence(e){this.persistence=e;try{const e=await this.persistence.get();e&&this.coreState.applyChanges(e)}catch(e){console.error("Failed to initialize persistence:",e),this.emit(this.eventBus,{name:"persistence:init_error",payload:{error:e,timestamp:Date.now()}})}finally{this.setPersistenceReady()}this.persistence.subscribe(this.instanceID,(async e=>{const t=this.coreState.applyChanges(e);t.length>0&&this.emit(this.eventBus,{name:"update:complete",payload:{changedPaths:t,source:"external",timestamp:Date.now()}})}))}dispose(){this.discardQueue(),this.isProcessingQueue=!1,this.persistenceReady=!1}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},T=class{constructor(e,t,s){this.eventBus=e,this.coreState=t,this.executionState=s}async execute(e){const t=this.coreState.get(!0);this.executionState.transactionActive=!0,this.emit(this.eventBus,{name:"transaction:start",payload:{timestamp:Date.now()}});try{const t=await Promise.resolve(e());return this.emit(this.eventBus,{name:"transaction:complete",payload:{timestamp:Date.now()}}),this.executionState.transactionActive=!1,t}catch(e){throw this.coreState.applyChanges(t,!0,!1),this.emit(this.eventBus,{name:"transaction:error",payload:{error:e instanceof Error?e:new Error(String(e)),timestamp:Date.now()}}),this.executionState.transactionActive=!1,e}}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},E=class{updateCount=0;listenerExecutions=0;averageUpdateTime=0;largestUpdateSize=0;mostActiveListenerPaths=[];totalUpdates=0;blockedUpdates=0;averageUpdateDuration=0;middlewareExecutions=0;transactionCount=0;totalEventsFired=0;totalActionsDispatched=0;totalActionsSucceeded=0;totalActionsFailed=0;averageActionDuration=0;updateTimes=[];actionTimes=[];pathExecutionCounts=new Map;constructor(e){this.setupEventListeners(e)}getMetrics(){return{updateCount:this.updateCount,listenerExecutions:this.listenerExecutions,averageUpdateTime:this.averageUpdateTime,largestUpdateSize:this.largestUpdateSize,mostActiveListenerPaths:[...this.mostActiveListenerPaths],totalUpdates:this.totalUpdates,blockedUpdates:this.blockedUpdates,averageUpdateDuration:this.averageUpdateDuration,middlewareExecutions:this.middlewareExecutions,transactionCount:this.transactionCount,totalEventsFired:this.totalEventsFired,totalActionsDispatched:this.totalActionsDispatched,totalActionsSucceeded:this.totalActionsSucceeded,totalActionsFailed:this.totalActionsFailed,averageActionDuration:this.averageActionDuration}}setupEventListeners(e){const t=e.emit;e.emit=s=>(this.totalEventsFired++,t.call(e,s)),e.subscribe("update:complete",(e=>{if(this.totalUpdates++,e.blocked)this.blockedUpdates++;else{if(e.duration){this.updateTimes.push(e.duration),this.updateTimes.length>100&&this.updateTimes.shift();const t=this.updateTimes.reduce(((e,t)=>e+t),0)/this.updateTimes.length;this.averageUpdateTime=t,this.averageUpdateDuration=t}e.deltas?.length&&(this.updateCount++,this.largestUpdateSize=Math.max(this.largestUpdateSize,e.deltas.length),e.deltas.forEach((e=>{const t=this.pathExecutionCounts.get(e.path)||0;this.pathExecutionCounts.set(e.path,t+1)})),this.mostActiveListenerPaths=Array.from(this.pathExecutionCounts.entries()).sort((([,e],[,t])=>t-e)).slice(0,5).map((([e])=>e)))}})),e.subscribe("middleware:start",(()=>{this.middlewareExecutions++})),e.subscribe("transaction:start",(()=>{this.transactionCount++})),e.subscribe("action:start",(()=>{this.totalActionsDispatched++})),e.subscribe("action:complete",(e=>{this.totalActionsSucceeded++,e.duration&&(this.actionTimes.push(e.duration),this.actionTimes.length>100&&this.actionTimes.shift(),this.averageActionDuration=this.actionTimes.reduce(((e,t)=>e+t),0)/this.actionTimes.length)})),e.subscribe("action:error",(()=>{this.totalActionsFailed++}))}reset(){this.updateCount=0,this.listenerExecutions=0,this.averageUpdateTime=0,this.largestUpdateSize=0,this.mostActiveListenerPaths=[],this.totalUpdates=0,this.blockedUpdates=0,this.averageUpdateDuration=0,this.middlewareExecutions=0,this.transactionCount=0,this.totalEventsFired=0,this.totalActionsDispatched=0,this.totalActionsSucceeded=0,this.totalActionsFailed=0,this.averageActionDuration=0,this.updateTimes=[],this.actionTimes=[],this.pathExecutionCounts.clear()}getDetailedMetrics(){return{pathExecutionCounts:new Map(this.pathExecutionCounts),recentUpdateTimes:[...this.updateTimes],successRate:this.totalUpdates>0?(this.totalUpdates-this.blockedUpdates)/this.totalUpdates:1,averagePathsPerUpdate:this.updateCount>0?Array.from(this.pathExecutionCounts.values()).reduce(((e,t)=>e+t),0)/this.updateCount:0}}dispose(){this.reset()}},M=class extends Error{constructor(){super("Action Cancelled by Debounce"),this.name="ActionCancelledError"}},C=class extends Error{constructor({action:e}){super(`Unknown action: "${e}"`),this.name="UnknownActionError"}},P=()=>{},A={name:"UNDEFINED ACTION",status:()=>!1,subscribe:e=>()=>{}},L=class{constructor(e,t){this.eventBus=e,this.set=t}registrations=new Map;register(e){const i={action:{name:e.name,id:t.v4(),action:e.fn,debounce:e.debounce?{...e.debounce,condition:e.debounce.condition??(()=>!0)}:void 0},debouncer:e.debounce&&e.debounce.delay>0?new s({delay:e.debounce.delay}):void 0,previousArgs:void 0,running:!1,subscription:{listeners:new Set,watcher:null,watchers:new d((()=>[this.eventBus.subscribe("action:start",(t=>t.name===e.name&&this.notifyStatusListeners(e.name))),this.eventBus.subscribe("action:complete",(t=>t.name===e.name&&this.notifyStatusListeners(e.name))),this.eventBus.subscribe("action:error",(t=>t.name===e.name&&this.notifyStatusListeners(e.name)))]),(e=>e?.forEach((e=>e()))),{gracePeriod:"microtask"})}};return this.registrations.set(e.name,i),()=>{const t=this.registrations.get(e.name);t&&(t.debouncer?.cancel(),this.registrations.delete(e.name))}}async dispatch(e,...t){const s=this.registrations.get(e);if(!s)throw new C({action:e});const{action:i,debouncer:r}=s,{debounce:n}=i;if(!r||!n)return this.executeAction(s,t);const a=n.condition(s.previousArgs,t);if(s.previousArgs=t,!a)return this.executeAction(s,t);const o=await r.do((()=>this.executeAction(s,t)));if("cancelled"===o.status)throw new M;if("error"===o.status&&o.error)throw o.error;return o.value}async executeAction(e,t){const s=performance.now();e.running=!0,this.emit(this.eventBus,{name:"action:start",payload:{actionId:e.action.id,name:e.action.name,params:t||[],timestamp:s}});try{const i=await this.set((s=>e.action.action(s,...t)),{actionId:e.action.id}),r=performance.now();return e.running=!1,this.emit(this.eventBus,{name:"action:complete",payload:{actionId:e.action.id,name:e.action.name,params:t,startTime:s,endTime:r,duration:r-s,result:i}}),i}catch(i){const r=performance.now();throw e.running=!1,this.emit(this.eventBus,{name:"action:error",payload:{actionId:e.action.id,name:e.action.name,params:t,startTime:s,endTime:r,duration:r-s,error:i}}),i}}running(e){const t=this.registrations.get(e);return!!t&&t.running}subscribe(e,t){const s=this.registrations.get(e);return s?(s.subscription.listeners.add(t),s.subscription.watchers.acquire(),()=>{s.subscription.listeners.delete(t),s.subscription.watchers?.release()}):P}watch(e){const t=this.registrations.get(e);return t?(t.subscription.watcher||(t.subscription.watcher={name:e,status:()=>this.running(e),subscribe:t=>this.subscribe(e,t)}),t.subscription.watcher):A}notifyStatusListeners(e){const t=this.registrations.get(e).subscription.listeners;t&&t.forEach((e=>e()))}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}};exports.ActionCancelledError=M,exports.ActionManager=L,exports.DELETE_SYMBOL=l,exports.ReactiveDataStore=class{coreState;middlewareEngine;persistenceHandler;transactionManager;metricsCollector;selectorManager;actions;updateSerializer=new h({yieldMode:"macrotask",capacity:1e3});readyLatch=new a;updateBus=e.createEventBus();eventBus;executionState;instanceID=t.v4();merge;diff;constructor(t,s,i=l,r){this.eventBus=e.createEventBus(),this.executionState={executing:!1,changes:null,pendingChanges:[],middlewares:[],runningMiddleware:null,transactionActive:!1},this.merge=p({deleteMarker:i}),this.diff=f({deleteMarker:i}),this.coreState=new S(t,this.updateBus,this.diff),this.middlewareEngine=new x(this.eventBus,this.executionState,this.merge),this.persistenceHandler=new k(this.eventBus,this.coreState,this.instanceID,{maxRetries:r?.persistenceMaxRetries,retryDelay:r?.persistenceRetryDelay}),this.transactionManager=new T(this.eventBus,this.coreState,this.executionState),this.metricsCollector=new E(this.eventBus),this.actions=new L(this.eventBus,this.set.bind(this)),this.persistenceHandler.initialize(s),this.setupPersistenceListener(),this.setupReadyLatch(),this.selectorManager=new y(this.get.bind(this),this.eventBus)}isReady(){return this.readyLatch.isOpen()}async ready(e){return this.readyLatch.wait(e)}state(){return this.executionState.executing=this.updateSerializer.running(),this.executionState}get(e){return this.coreState.get(e??!1)}select(e){return this.selectorManager.createReactiveSelector(e)}register(e){return this.actions.register(e)}async dispatch(e,...t){return this.actions.dispatch(e,...t)}async set(e,t={}){const s=await this.updateSerializer.do((()=>this._performUpdate(e,t)));if(s.error)throw s.error;return s.value}async _performUpdate(e,t){const s=performance.now();this.emit(this.eventBus,{name:"update:start",payload:{timestamp:s,actionId:t.actionId}});try{if(t.force){const i=this.get(!1),r="function"==typeof e?e(i):e;this.coreState.applyChanges(r,!0);const n=performance.now();return this.emit(this.eventBus,{name:"update:complete",payload:{deltas:[],duration:n-s,timestamp:Date.now(),actionId:t.actionId,newState:r}}),r}let i;const r=this.get(!1);if("function"==typeof e){const t=e(r);i=t instanceof Promise?await t:t}else i=e;const n=await this.middlewareEngine.executeBlocking(r,i);if(n.blocked)throw n.error||new Error("Update blocked by middleware");const a=this.merge(r,i),o=await this.middlewareEngine.executeTransform(a,i),c=this.merge(a,o),h=this.coreState.applyChanges(c,!1,!1,[i,o]),d=performance.now(),l=this.get(!1);return this.emit(this.eventBus,{name:"update:complete",payload:{deltas:h,duration:d-s,timestamp:Date.now(),actionId:t.actionId,newState:l}}),l}catch(e){throw this.emit(this.eventBus,{name:"update:complete",payload:{blocked:!0,error:e,timestamp:Date.now(),actionId:t.actionId,newState:this.get(!1)}}),e}finally{this.executionState.executing=!1,this.executionState.changes=null,this.executionState.runningMiddleware=null,this.executionState.pendingChanges=[]}}setupReadyLatch(){this.readyLatch.open(),this.persistenceHandler.isReady()?this.readyLatch.open():queueMicrotask((()=>{this.readyLatch.isOpen()||this.readyLatch.open()}))}setupPersistenceListener(){this.updateBus.subscribe("update",(e=>{e&&this.persistenceHandler.isReady()&&this.persistenceHandler.handleStateChange([e],this.get(!1))}))}watch(e,t,s){const i=Array.isArray(e)?e:[e],r=""===e||0===i.length;return this.updateBus.subscribe("update",(e=>{(r||i.includes(e))&&(t(this.get(!1)),this.metricsCollector.listenerExecutions++)}),s)}watchAction(e){return this.actions.watch(e)}debouncedSetter(e){const t=new s({delay:e.delay,leading:e.leading});return(e,s={})=>{t.fire((()=>this.set(e,s)))}}id(){return this.instanceID}async transaction(e){return this.transactionManager.execute(e)}use(e){const t=(e.block?this.middlewareEngine.addBlockingMiddleware:this.middlewareEngine.addMiddleware).bind(this.middlewareEngine)(e.action,e.name);return()=>this.middlewareEngine.removeMiddleware(t)}metrics(){return this.metricsCollector.getMetrics()}on(e,t){return this.eventBus.subscribe(e,t)}getPersistenceStatus(){return this.persistenceHandler.getQueueStatus()}async flushPersistence(){return this.persistenceHandler.flush()}discardPersistenceQueue(){this.persistenceHandler.discardQueue()}dispose(){this.updateSerializer.close(),this.persistenceHandler.dispose(),this.metricsCollector.dispose?.(),this.selectorManager.dispose?.()}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},exports.StoreObserver=class{store;eventHistory=[];stateHistory=[];unsubscribers=[];isTimeTraveling=!1;devTools=null;middlewareExecutions=[];activeTransactionCount=0;activeBatches=new Set;maxEvents;maxStateHistory;enableConsoleLogging;isSilent;logEvents;performanceThresholds;constructor(e,t={}){this.store=e,this.maxEvents=t.maxEvents??500,this.maxStateHistory=t.maxStateHistory??20,this.enableConsoleLogging=t.enableConsoleLogging??!1,this.isSilent=t.silent??!1,this.logEvents={updates:t.logEvents?.updates??!0,middleware:t.logEvents?.middleware??!0,transactions:t.logEvents?.transactions??!0,actions:t.logEvents?.actions??!0,selectors:t.logEvents?.selectors??!0},this.performanceThresholds={updateTime:t.performanceThresholds?.updateTime??50,middlewareTime:t.performanceThresholds?.middlewareTime??20},this.recordStateSnapshot([]),this.setupEventListeners()}_consoleLog(e,...t){this.isSilent||"function"==typeof console[e]&&console[e](...t)}setupEventListeners(){const e=["update:start","update:complete","middleware:start","middleware:complete","middleware:error","middleware:blocked","transaction:start","transaction:complete","transaction:error","middleware:executed","action:start","action:complete","action:error","selector:accessed"];for(const t of e){const e=t.startsWith("update")&&this.logEvents.updates||t.startsWith("middleware")&&this.logEvents.middleware||t.startsWith("transaction")&&this.logEvents.transactions||t.startsWith("action")&&this.logEvents.actions||t.startsWith("selector")&&this.logEvents.selectors;this.unsubscribers.push(this.store.on(t,(s=>{"update:complete"!==t||s.blocked||this.isTimeTraveling||this.recordStateSnapshot(s.deltas),"middleware:executed"===t?this.middlewareExecutions.push(s):"transaction:start"===t?this.activeTransactionCount++:"transaction:complete"!==t&&"transaction:error"!==t||(this.activeTransactionCount=Math.max(0,this.activeTransactionCount-1)),s.batchId&&(t.endsWith("start")?this.activeBatches.add(s.batchId):(t.endsWith("complete")||t.endsWith("error"))&&this.activeBatches.delete(s.batchId)),this.recordEvent(t,s),this.enableConsoleLogging&&e&&this._log(t,s),this._checkPerformance(t,s)})))}}recordStateSnapshot(e){const t={state:this.store.get(!0),timestamp:Date.now(),deltas:e};this.stateHistory.unshift(t),this.stateHistory.length>this.maxStateHistory&&this.stateHistory.pop()}recordEvent(e,t){const s={type:e,timestamp:Date.now(),data:structuredClone(t)};this.eventHistory.unshift(s),this.eventHistory.length>this.maxEvents&&this.eventHistory.pop()}getEventHistory(){return structuredClone(this.eventHistory)}getStateHistory(){return structuredClone(this.stateHistory)}getMiddlewareExecutions(){return this.middlewareExecutions}getTransactionStatus(){return{activeTransactions:this.activeTransactionCount,activeBatches:Array.from(this.activeBatches)}}createLoggingMiddleware(e={}){const{logLevel:t="debug",logUpdates:s=!0}=e;return(e,i)=>{if(s){(console[t]||console.log)("State Update:",i)}return i}}createValidationMiddleware(e){return(t,s)=>{const i=e(t,s);return"boolean"==typeof i?i:(!i.valid&&i.reason&&this._consoleLog("warn","Validation failed:",i.reason),i.valid)}}getRecentChanges(e=5){const t=[],s=Math.min(e,this.stateHistory.length);for(let e=0;e<s;e++){const s=this.stateHistory[e];if(!s.deltas||0===s.deltas.length)continue;const i={},r={},n=(e,t,s)=>{t.reduce(((e,i,r)=>(r===t.length-1?e[i]=s:e[i]=e[i]??{},e[i])),e)};for(const e of s.deltas){const t=e.path.split(".");n(i,t,e.oldValue),n(r,t,e.newValue)}t.push({timestamp:s.timestamp,changedPaths:s.deltas.map((e=>e.path)),from:i,to:r})}return t}clearHistory(){this.eventHistory=[],this.stateHistory.length>0&&(this.stateHistory=[this.stateHistory[0]])}getHistoryForAction(e){return this.eventHistory.filter((t=>t.data?.actionId===e))}async replay(e){const t=this.eventHistory.filter((e=>"update:start"===e.type))[e];t?.data.update?(this._consoleLog("log",`Replaying event at index ${e}:`,t),await this.store.set(t.data.update,{force:!0})):this._consoleLog("warn",`No replayable event found at index ${e}.`)}createTimeTravel(){let e=0,t=[];const s=this.store.on("update:complete",(s=>{this.isTimeTraveling||s.blocked||(t=[],e=0)}));this.unsubscribers.push(s);const i=()=>this.stateHistory.length,r=()=>e<i()-1,n=()=>t.length>0;return{canUndo:r,canRedo:n,undo:async()=>{if(!r())return;t.unshift(this.stateHistory[e]),e++;const s=this.stateHistory[e].state;this.isTimeTraveling=!0,await this.store.set({...s},{force:!0}),this.isTimeTraveling=!1},redo:async()=>{if(!n())return;const s=t.shift();e--,this.isTimeTraveling=!0,await this.store.set({...s.state},{force:!0}),this.isTimeTraveling=!1},length:i,clear:()=>{t=[],e=0}}}async saveSession(e){const t=this.store.id(),s={eventHistory:this.eventHistory,stateHistory:this.stateHistory};return Promise.resolve(e.set(t,s))}async loadSession(e){const t=await Promise.resolve(e.get());return!!t&&(this.eventHistory=t.eventHistory||[],this.stateHistory=t.stateHistory||[],this.stateHistory.length>0&&await this.store.set(this.stateHistory[0].state,{force:!0}),!0)}exportSession(){const e={eventHistory:this.eventHistory,stateHistory:this.stateHistory},t=new Blob([JSON.stringify(e,null,2)],{type:"application/json"}),s=URL.createObjectURL(t),i=document.createElement("a");i.href=s,i.download=`store-observer-session-${(new Date).toISOString()}.json`,i.click(),URL.revokeObjectURL(s)}importSession(e){return new Promise(((t,s)=>{const i=new FileReader;i.onload=async e=>{try{const s=JSON.parse(e.target?.result);this.eventHistory=s.eventHistory||[],this.stateHistory=s.stateHistory||[],this.stateHistory.length>0&&await this.store.set(this.stateHistory[0].state,{force:!0}),t()}catch(e){s(e)}},i.onerror=e=>s(e),i.readAsText(e)}))}disconnect(){this.unsubscribers.forEach((e=>e())),this.unsubscribers=[],this.devTools?.disconnect(),this.clearHistory()}_log(e,t){const s=new Date(t.timestamp||Date.now()).toISOString().split("T")[1].replace("Z","");if("update:start"===e)this._consoleLog("group",`%c⚡ Store Update Started [${s}]`,"color: #4a6da7");else if("update:complete"===e){if(t.blocked)this._consoleLog("warn",`%c✋ Update Blocked [${s}]`,"color: #bf8c0a",t.error);else{const e=t.deltas||[];e.length>0&&(this._consoleLog("log",`%c✅ Update Complete [${s}] - ${e.length} paths changed in ${t.duration?.toFixed(2)}ms`,"color: #2a9d8f"),this._consoleLog("table",e.map((e=>({path:e.path,oldValue:e.oldValue,newValue:e.newValue})))))}this._consoleLog("groupEnd")}else"middleware:start"===e?this._consoleLog("debug",`%c◀ Middleware "${t.name}" started [${s}] (${t.type})`,"color: #8c8c8c"):"middleware:complete"===e?this._consoleLog("debug",`%c▶ Middleware "${t.name}" completed [${s}] in ${t.duration?.toFixed(2)}ms`,"color: #7c9c7c"):"middleware:error"===e?this._consoleLog("error",`%c❌ Middleware "${t.name}" error [${s}]:`,"color: #e63946",t.error):"middleware:blocked"===e?this._consoleLog("warn",`%c🛑 Middleware "${t.name}" blocked update [${s}]`,"color: #e76f51"):"transaction:start"===e?this._consoleLog("group",`%c📦 Transaction Started [${s}]`,"color: #6d597a"):"transaction:complete"===e?(this._consoleLog("log",`%c📦 Transaction Complete [${s}]`,"color: #355070"),this._consoleLog("groupEnd")):"transaction:error"===e?(this._consoleLog("error",`%c📦 Transaction Error [${s}]:`,"color: #e56b6f",t.error),this._consoleLog("groupEnd")):"action:start"===e?this._consoleLog("group",`%c🚀 Action "${t.name}" Started [${s}]`,"color: #9b59b6",{params:t.params}):"action:complete"===e?(this._consoleLog("log",`%c✔️ Action "${t.name}" Complete [${s}] in ${t.duration?.toFixed(2)}ms`,"color: #2ecc71"),this._consoleLog("groupEnd")):"action:error"===e?(this._consoleLog("error",`%c🔥 Action "${t.name}" Error [${s}]:`,"color: #e74c3c",t.error),this._consoleLog("groupEnd")):"selector:accessed"===e&&this._consoleLog("debug",`%c👀 Selector Accessed [${s}] in ${t.duration?.toFixed(2)}ms`,"color: #f1c40f",{accessedPaths:t.accessedPaths,selectorId:t.selectorId})}_checkPerformance(e,t){this.enableConsoleLogging&&("update:complete"===e&&!t.blocked&&t.duration>this.performanceThresholds.updateTime&&this._consoleLog("warn",`%c⚠️ Slow update detected [${t.duration.toFixed(2)}ms]`,"color: #ff9f1c",{deltas:t.deltas,threshold:this.performanceThresholds.updateTime}),"middleware:complete"===e&&t.duration>this.performanceThresholds.middlewareTime&&this._consoleLog("warn",`%c⚠️ Slow middleware "${t.name}" [${t.duration.toFixed(2)}ms]`,"color: #ff9f1c",{threshold:this.performanceThresholds.middlewareTime}))}},exports.UnknownActionError=C,exports.createDerivePaths=v,exports.createDiff=f,exports.createMerge=p,exports.derivePaths=_,exports.diff=b,exports.merge=m,exports.shallowClone=u;
|
package/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createEventBus as e}from"@asaidimu/utils-events";import{v4 as t}from"uuid";var s=class{_delay;_leading;_timer;_pendingFn;_pendingResolvers=[];_leadingFired=!1;constructor(e){this._delay=e?.delay??300,this._leading=e?.leading??!1}do(e){return new Promise((t=>{this._enqueue(e,t)}))}fire(e){this._enqueue(e,void 0)}_enqueue(e,t){if(this._pendingFn=e,t&&this._pendingResolvers.push(t),this._leading&&!this._leadingFired)return this._leadingFired=!0,this._fire(),clearTimeout(this._timer),void(this._timer=setTimeout((()=>{this._leadingFired=!1,void 0!==this._pendingFn&&this._fire()}),this._delay));clearTimeout(this._timer),this._timer=setTimeout((()=>{this._leadingFired=!1,this._fire()}),this._delay)}cancel(){clearTimeout(this._timer),this._timer=void 0,this._pendingFn=void 0,this._leadingFired=!1;const e=this._pendingResolvers.splice(0);for(const t of e)t({status:"cancelled"})}async flush(){return this._pendingFn?(clearTimeout(this._timer),this._timer=void 0,this._leadingFired=!1,this._fire()):null}pending(){return void 0!==this._pendingFn}async _fire(){const e=this._pendingFn,t=this._pendingResolvers.splice(0);let s;this._pendingFn=void 0;try{s={status:"ok",value:await e()}}catch(e){s={status:"error",error:e}}for(const e of t)e(s);return s}},i=class e extends Error{constructor(t,s){super(t,{cause:s}),this.name="SyncError",Object.setPrototypeOf(this,e.prototype)}},r=class extends i{constructor(e){super(`[ArtifactContainer] Operation timed out: ${e}`)}},n=class extends i{constructor(e){super("[Serializer] The serializer has been marked as done!",e)}},a=class{_open=!1;_resolve;_promise;constructor(){this._promise=new Promise((e=>{this._resolve=e}))}open(){this._open||(this._open=!0,this._resolve())}async wait(e){if(this._open)return;if(null==e)return this._promise;let t;await Promise.race([this._promise.then((()=>clearTimeout(t))),new Promise(((s,i)=>{t=setTimeout((()=>i(new r("Latch timed out"))),e)}))])}isOpen(){return this._open}},o=class{_locked=!1;_capacity;_yieldMode;waiters=[];constructor(e){this._capacity=e?.capacity??1/0,this._yieldMode=e?.yieldMode??"macrotask"}async lock(e){if(!this._locked)return void(this._locked=!0);if(this.waiters.length>=this._capacity)throw new Error(`Mutex queue is full (capacity: ${this._capacity})`);let t;const s=new Promise((e=>t=e));if(this.waiters.push(t),null==e)return void await s;let i;await Promise.race([s.then((()=>clearTimeout(i))),new Promise(((s,n)=>{i=setTimeout((()=>{const e=this.waiters.indexOf(t);-1!==e&&this.waiters.splice(e,1),n(new r("Mutex lock timed out"))}),e)}))])}tryLock(){return!this._locked&&(this._locked=!0,!0)}unlock(){if(!this._locked)throw new Error("Mutex is not locked");const e=this.waiters.shift();e?"microtask"===this._yieldMode?queueMicrotask(e):setTimeout(e,0):this._locked=!1}locked(){return this._locked}pending(){return this.waiters.length}},c=class{mutex=new o({yieldMode:"microtask"});promise=null;_value=null;_error;_done=!1;retry;throws;constructor({retry:e,throws:t}={}){this.retry=Boolean(e),this.throws=Boolean(t)}async do(e,t){return this._done?this.peek():this.promise?this._awaitWithTimeout(this.promise,t,"Once do() timed out"):(await this.mutex.lock(),this.promise?(this.mutex.unlock(),this._awaitWithTimeout(this.promise,t,"Once do() timed out")):(this.promise=(async()=>{try{this._value=await e(),this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.retry&&!this._done&&(this.promise=null)}return this.peek()})(),this.mutex.unlock(),this._awaitWithTimeout(this.promise,t,"Once do() timed out")))}doSync(e){if(this._done){if(this.throws&&this._error)throw this._error;return this.peek()}if(this.promise){const e=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw e;return{value:null,error:e}}if(!this.mutex.tryLock()){const e=new Error("Cannot execute doSync: lock is currently held.");if(this.throws)throw e;return{value:null,error:e}}if(this.promise||this._done){if(this.mutex.unlock(),this._done){if(this.throws&&this._error)throw this._error;return this.peek()}const e=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw e;return{value:null,error:e}}try{const t=e();this._value=t,this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.mutex.unlock()}return this.peek()}running(){return null!==this.promise&&!this.done()}peek(){return{value:this._value,error:this._error}}get(){if(!this._done)throw new Error("Once operation is not yet complete");if(this._error)throw this._error;return this._value}reset(){if(this.running())throw new Error("Cannot reset Once while an operation is in progress.");this._done=!1,this.promise=null,this._value=null,this._error=void 0}done(){return this._done}current(){return this.promise}_awaitWithTimeout(e,t,s="Operation timed out"){if(null==t)return e;let i;return Promise.race([e.then((e=>(clearTimeout(i),e))),new Promise(((e,n)=>{i=setTimeout((()=>n(new r(s))),t)}))])}},h=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;_hasRun=!1;constructor(e){this.mutex=new o({capacity:e?.capacity??1e3,yieldMode:e?.yieldMode??"macrotask"})}async do(e,t){if(this._done)return{value:null,error:new n};try{await this.mutex.lock(t)}catch(e){return{value:null,error:e}}let s,i=null;try{if(this._done)throw new n;i=await e(),this._lastValue=i,this._lastError=void 0,this._hasRun=!0}catch(e){s=e,this._lastError=e,this._hasRun=!0}finally{this.mutex.unlock()}return{value:i,error:s}}peek(){return{value:this._lastValue,error:this._lastError}}hasRun(){return this._hasRun}close(){this._done=!0}pending(){return this.mutex.pending()}running(){return this.mutex.locked()}},d=class{constructor(e,t,s={}){this.factory=e,this.onCleanup=t,this.options=s}_count=0;init=new c({retry:!1,throws:!1});pendingMicrotask=!1;cleanupTimer;get subscribers(){return this._count}async acquire(){this.cancelPendingCleanup(),this._count++;const e=await this.init.do(this.factory);if(e.error)throw e.error;return e.value}release(){this._count<=0?console.warn("SharedResource.release() called, but count is already 0."):(this._count--,0===this._count&&this.scheduleCleanup())}peek(){const e=this.init.peek();return e.error?null:e.value}forceCleanup(){this.cancelPendingCleanup(),this._count=0,this.executeCleanup()}cancelPendingCleanup(){this.pendingMicrotask=!1,void 0!==this.cleanupTimer&&(clearTimeout(this.cleanupTimer),this.cleanupTimer=void 0)}scheduleCleanup(){const e=this.options.gracePeriod??"microtask";if("sync"!==e)return"microtask"===e?(this.pendingMicrotask=!0,void queueMicrotask((()=>{!this.pendingMicrotask||this._count>0||(this.pendingMicrotask=!1,this.executeCleanup())}))):void(this.cleanupTimer=setTimeout((()=>{this.cleanupTimer=void 0,this._count>0||this.executeCleanup()}),e));this.executeCleanup()}executeCleanup(){const e=this.init.peek();try{this.onCleanup(e.value)}catch(e){console.error("[SharedResource] Error during cleanup callback:",e)}this.init.running()||this.init.reset()}},l=Symbol.for("delete"),u=e=>Array.isArray(e)?[...e]:{...e};function p(e){const t=e?.deleteMarker||l;function s(e){if(null==e)return e;if(Array.isArray(e))return e.filter((e=>e!==t)).map((e=>"object"!=typeof e||null===e||Array.isArray(e)?e:s(e)));if("object"==typeof e){const i={};for(const[r,n]of Object.entries(e))if(n!==t)if("object"==typeof n&&null!==n){const e=s(n);void 0!==e&&(i[r]=e)}else i[r]=n;return i}return e===t?void 0:e}return function(e,i){if("object"!=typeof e||null===e)return"object"==typeof i&&null!==i?s(i):i===t?{}:i;if("object"!=typeof i||null===i)return e;const r=u(e),n=[{target:r,source:i}];for(;n.length>0;){const{target:e,source:s}=n.pop();for(const i of Object.keys(s)){const r=s[i];if(r!==t)if(Array.isArray(r))e[i]=r;else if("object"==typeof r&&null!==r){const t=i in e&&"object"==typeof e[i]&&null!==e[i]?e[i]:{};e[i]=u(t),n.push({target:e[i],source:r})}else e[i]=r;else delete e[i]}}return r}}var m=p(),g=["map","filter","reduce","forEach","find","findIndex","some","every","includes","flatMap","flat","slice","splice"],y=class{reactiveSelectors=new Map;pathBasedCache=new Map;dependencyMap=new Map;getState;eventBus;unsubscribeFromStore;constructor(e,t){this.getState=e,this.eventBus=t,this.unsubscribeFromStore=this.eventBus.subscribe("update:complete",this.handleStoreUpdate)}handleStoreUpdate=e=>{const t=new Set;for(const s of e.deltas){const e=s.path;for(const[s,i]of this.dependencyMap)if(s===e||s.startsWith(e+".")||e.startsWith(s+"."))for(const e of i)t.add(e)}for(const e of t){const t=this.reactiveSelectors.get(e);t&&this.evaluateEntry(t)}};evaluateEntry(e){let t;try{t=e.selector(this.getState())}catch{t=void 0}if(t!==e.lastResult){e.lastResult=t;for(const s of e.subscribers)s(t);this.eventBus.emit({name:"selector:changed",payload:{selectorId:e.id,newResult:t,timestamp:performance.now()}})}}createReactiveSelector(e){const t=function(e,t="."){const s=new Set,i=new Map,r=(e="")=>{if(i.has(e))return i.get(e);const n=new Proxy((()=>{}),{get:(i,n)=>{if("symbol"==typeof n||"then"===n)return;if("valueOf"===n||"toString"===n)throw new Error("Cannot perform logic, arithmetic, or string operations inside a selector.");if(g.includes(n))throw new Error(`Array method .${n}() is not allowed in selectors.`);const a=e?`${e}${t}${n}`:n;return e&&s.delete(e),s.add(a),r(a)},has:()=>{throw new Error("The 'in' operator is not allowed in selectors.")},apply:()=>{throw new Error("Selectors cannot call functions or methods.")}});return i.set(e,n),n};try{e(r())}catch(e){throw new Error(`Selector failed during path analysis. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}return Array.from(s)}(e),s=[...t].sort().join("|"),i=this.pathBasedCache.get(s);if(i)return void 0!==i.cleanupTimer&&(clearTimeout(i.cleanupTimer),i.cleanupTimer=void 0),i.reactiveSelectorInstance;const r=`sel-${Math.random().toString(36).slice(2,9)}`,n={id:r,selector:e,lastResult:e(this.getState()),accessedPaths:t,subscribers:new Set,count:0,cleanupTimer:void 0,pathCacheKey:s,reactiveSelectorInstance:null};for(const e of t)this.dependencyMap.has(e)||this.dependencyMap.set(e,new Set),this.dependencyMap.get(e).add(r);const a={id:r,get:()=>{try{return n.selector(this.getState())}catch{return}},subscribe:e=>(void 0!==n.cleanupTimer&&(clearTimeout(n.cleanupTimer),n.cleanupTimer=void 0),n.subscribers.add(e),n.count++,()=>{n.subscribers.delete(e),n.count--,0===n.count&&(n.cleanupTimer=setTimeout((()=>{0===n.count&&this.evictEntry(n)}),0))})};return n.reactiveSelectorInstance=a,this.reactiveSelectors.set(r,n),this.pathBasedCache.set(s,n),this.eventBus.emit({name:"selector:accessed",payload:{selectorId:r,accessedPaths:t,duration:0,timestamp:performance.now()}}),a}evictEntry(e){for(const t of e.accessedPaths){const s=this.dependencyMap.get(t);s&&(s.delete(e.id),0===s.size&&this.dependencyMap.delete(t))}this.reactiveSelectors.delete(e.id),this.pathBasedCache.delete(e.pathCacheKey)}dispose(){this.unsubscribeFromStore(),this.reactiveSelectors.clear(),this.dependencyMap.clear(),this.pathBasedCache.clear()}};function w(e,t){if(e===t)return!0;if(e&&t&&"object"==typeof e&&"object"==typeof t){if(e.constructor!==t.constructor)return!1;let s,i;if(Array.isArray(e)){if(s=e.length,s!=t.length)return!1;for(i=s;i-- >0;)if(!w(e[i],t[i]))return!1;return!0}const[r,n]=[Object.keys(e),Object.keys(t)];if(s=r.length,s!==n.length)return!1;for(i=s;i-- >0;){const s=r[i];if(!Object.prototype.hasOwnProperty.call(t,s)||!w(e[s],t[s]))return!1}return!0}return e!=e&&t!=t}function f(e){const t=e?.deleteMarker||l;return function(e,s){const i=[],r=[{pathStr:"",orig:e||{},part:s||{}}];for(;r.length>0;){const{pathStr:e,orig:s,part:n}=r.pop();if(null!=n&&!w(s,n))if("object"!=typeof n||Array.isArray(n))e&&i.push({path:e,oldValue:s,newValue:n});else for(const a of Object.keys(n)){const o=e?e+"."+a:a,c=n[a],h=s&&"object"==typeof s?s[a]:void 0;c!==t?"object"==typeof c&&null!==c?r.push({pathStr:o,orig:h,part:c}):w(h,c)||i.push({path:o,oldValue:h,newValue:c}):void 0!==h&&i.push({path:o,oldValue:h,newValue:void 0})}}return i}}function v(e){const t=e?.deleteMarker||l;return function(e){const s=new Set,i=[{obj:e,currentPath:""}];for(;i.length>0;){const{obj:e,currentPath:r}=i.pop();if(null!=e&&"object"==typeof e&&!Array.isArray(e))for(const n of Object.keys(e)){const a=r?`${r}.${n}`:n;s.add(a);const o=e[n];"object"!=typeof o||null===o||Array.isArray(o)||o===t||i.push({obj:o,currentPath:a})}}return Array.from(s)}}var b=f(),_=v(),S=class{constructor(e,t,s){this.updateBus=t,this.diff=s,this.cache=structuredClone(e)}cache;get(e){return e?structuredClone(this.cache):this.cache}applyChanges(e,t=!1,s=!1,i=[]){if(t)return this.cache=s?structuredClone(e):e,this.notifyListeners([]),[];0===i.length&&(i=[e]);const r=this.get(!1),n=new Map;for(let e=0;e<i.length;e++){const t=i[e],s=this.diff(r,t);for(let e=0;e<s.length;e++){const t=s[e];n.set(t.path,t)}}const a=n.size?[...n.values()]:[];if(a.length>0){this.cache=s?structuredClone(e):e;const t=new Set;for(let e=0;e<a.length;e++){let s=a[e].path;for(;s&&!t.has(s);){t.add(s);const e=s.lastIndexOf(".");if(e<0)break;s=s.slice(0,e)}}this.notifyListeners(t)}return a}notifyListeners(e){for(const t of e)this.updateBus.emit({name:"update",payload:t})}},k=class{constructor(e,t,s){this.eventBus=e,this.executionState=t,this.merge=s}middleware=[];blockingMiddleware=[];async executeBlocking(e,t){for(const{fn:s,name:i,id:r}of this.blockingMiddleware){const n={id:r,name:i,startTime:performance.now()};this.executionState.runningMiddleware={id:r,name:i,startTime:performance.now()},this.emitMiddlewareLifecycle("start",{id:r,name:i,type:"blocking"});try{const a=await Promise.resolve(s(e,t));if(n.endTime=performance.now(),n.duration=n.endTime-n.startTime,!1===a)return n.blocked=!0,this.emitMiddlewareLifecycle("blocked",{id:r,name:i,duration:n.duration}),this.emit(this.eventBus,{name:"middleware:executed",payload:n}),{blocked:!0};this.emitMiddlewareLifecycle("complete",{id:r,name:i,type:"blocking",duration:n.duration}),this.emit(this.eventBus,{name:"middleware:executed",payload:{...n,blocked:!1}})}catch(e){return n.endTime=performance.now(),n.duration=n.endTime-n.startTime,n.error=e instanceof Error?e:new Error(String(e)),n.blocked=!0,this.emitMiddlewareError(r,i,n.error,n.duration),this.emit(this.eventBus,{name:"middleware:executed",payload:n}),{blocked:!0,error:n.error}}finally{this.executionState.runningMiddleware=null}}return{blocked:!1}}async executeTransform(e,t){let s=e,i=t;for(const{fn:e,name:r,id:n}of this.middleware){const a={id:n,name:r,startTime:performance.now()};this.executionState.runningMiddleware={id:n,name:r,startTime:performance.now()},this.emitMiddlewareLifecycle("start",{id:n,name:r,type:"transform"});try{const o=await Promise.resolve(e(s,t));a.endTime=performance.now(),a.duration=a.endTime-a.startTime,a.blocked=!1,o&&"object"==typeof o&&(s=this.merge(s,o),i=this.merge(i,o)),this.emit(this.eventBus,{name:"middleware:executed",payload:a}),this.emitMiddlewareLifecycle("complete",{id:n,name:r,type:"transform",duration:a.duration})}catch(e){a.endTime=performance.now(),a.duration=a.endTime-a.startTime,a.error=e instanceof Error?e:new Error(String(e)),a.blocked=!1,this.emit(this.eventBus,{name:"middleware:executed",payload:a}),this.emitMiddlewareError(n,r,a.error,a.duration),console.error(`Middleware ${r} error:`,e)}finally{this.executionState.runningMiddleware=null}}return i}addMiddleware(e,t="unnamed-middleware"){const s=this.generateId();return this.middleware.push({fn:e,name:t,id:s}),this.updateExecutionState(),s}addBlockingMiddleware(e,t="unnamed-blocking-middleware"){const s=this.generateId();return this.blockingMiddleware.push({fn:e,name:t,id:s}),this.updateExecutionState(),s}removeMiddleware(e){const t=this.middleware.length+this.blockingMiddleware.length;return this.middleware=this.middleware.filter((t=>t.id!==e)),this.blockingMiddleware=this.blockingMiddleware.filter((t=>t.id!==e)),this.updateExecutionState(),this.middleware.length+this.blockingMiddleware.length<t}updateExecutionState(){this.executionState.middlewares=[...this.middleware.map((e=>e.name)),...this.blockingMiddleware.map((e=>e.name))]}emitMiddlewareLifecycle(e,t){this.emit(this.eventBus,{name:`middleware:${e}`,payload:{...t,timestamp:Date.now()}})}emitMiddlewareError(e,t,s,i){this.emit(this.eventBus,{name:"middleware:error",payload:{id:e,name:t,error:s,duration:i,timestamp:Date.now()}})}generateId(){return crypto.randomUUID?crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).substring(2,15)}`}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},T=class{constructor(e,t,s,i){this.eventBus=e,this.coreState=t,this.instanceID=s,this.maxRetries=i?.maxRetries??3,this.retryDelay=i?.retryDelay??1e3}persistence;instanceID;persistenceReady=!1;backgroundQueue=[];isProcessingQueue=!1;maxRetries=3;retryDelay=1e3;queueProcessor;pendingRetries=new Set;async initialize(e){e?await this.setPersistence(e):this.setPersistenceReady()}isReady(){return this.persistenceReady}handleStateChange(e,t){if(!this.persistence||0===e.length)return;const s={id:`${Date.now()}-${Math.random().toString(36).slice(2,11)}`,state:structuredClone(t),changedPaths:[...e],timestamp:Date.now(),retries:0};this.backgroundQueue.push(s),this.scheduleQueueProcessing(),this.emit(this.eventBus,{name:"persistence:queued",payload:{taskId:s.id,changedPaths:e,queueSize:this.backgroundQueue.length,timestamp:s.timestamp}})}getQueueStatus(){return{queueSize:this.backgroundQueue.length,isProcessing:this.isProcessingQueue,pendingRetries:this.pendingRetries.size,oldestTask:this.backgroundQueue[0]?.timestamp}}async flush(){this.isProcessingQueue&&await new Promise((e=>{const t=()=>{this.isProcessingQueue?setTimeout(t,10):e()};t()})),await this.processQueue()}discardQueue(){const e=this.backgroundQueue.length+this.pendingRetries.size;this.backgroundQueue=[],this.pendingRetries.clear(),this.queueProcessor&&(clearTimeout(this.queueProcessor),this.queueProcessor=void 0),this.emit(this.eventBus,{name:"persistence:queue_cleared",payload:{clearedTasks:e,timestamp:Date.now()}})}scheduleQueueProcessing(){this.queueProcessor||this.isProcessingQueue||(this.queueProcessor=setTimeout((()=>{this.processQueue().catch((e=>{console.error("Queue processing failed:",e)}))}),10))}async processQueue(){if(!this.isProcessingQueue&&0!==this.backgroundQueue.length){this.isProcessingQueue=!0,this.queueProcessor=void 0;try{for(;this.backgroundQueue.length>0;){const e=this.backgroundQueue.shift();await this.processTask(e)}}finally{this.isProcessingQueue=!1}}}async processTask(e){try{await this.persistence.set(this.instanceID,e.state)?this.emit(this.eventBus,{name:"persistence:success",payload:{taskId:e.id,changedPaths:e.changedPaths,duration:Date.now()-e.timestamp,timestamp:Date.now()}}):await this.handleTaskFailure(e,new Error("Persistence returned false"))}catch(t){await this.handleTaskFailure(e,t)}}async handleTaskFailure(e,t){if(e.retries++,e.retries<=this.maxRetries){const s=this.retryDelay*Math.pow(2,e.retries-1);this.emit(this.eventBus,{name:"persistence:retry",payload:{taskId:e.id,attempt:e.retries,maxRetries:this.maxRetries,nextRetryIn:s,error:t,timestamp:Date.now()}}),this.pendingRetries.add(e.id),setTimeout((()=>{this.pendingRetries.has(e.id)&&(this.pendingRetries.delete(e.id),this.backgroundQueue.unshift(e),this.scheduleQueueProcessing())}),s)}else this.emit(this.eventBus,{name:"persistence:failed",payload:{taskId:e.id,changedPaths:e.changedPaths,attempts:e.retries,error:t,timestamp:Date.now()}})}setPersistenceReady(){this.persistenceReady=!0,this.emit(this.eventBus,{name:"persistence:ready",payload:{timestamp:Date.now()}})}async setPersistence(e){this.persistence=e;try{const e=await this.persistence.get();e&&this.coreState.applyChanges(e)}catch(e){console.error("Failed to initialize persistence:",e),this.emit(this.eventBus,{name:"persistence:init_error",payload:{error:e,timestamp:Date.now()}})}finally{this.setPersistenceReady()}this.persistence.subscribe(this.instanceID,(async e=>{const t=this.coreState.applyChanges(e);t.length>0&&this.emit(this.eventBus,{name:"update:complete",payload:{changedPaths:t,source:"external",timestamp:Date.now()}})}))}dispose(){this.discardQueue(),this.isProcessingQueue=!1,this.persistenceReady=!1}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},x=class{constructor(e,t,s){this.eventBus=e,this.coreState=t,this.executionState=s}async execute(e){const t=this.coreState.get(!0);this.executionState.transactionActive=!0,this.emit(this.eventBus,{name:"transaction:start",payload:{timestamp:Date.now()}});try{const t=await Promise.resolve(e());return this.emit(this.eventBus,{name:"transaction:complete",payload:{timestamp:Date.now()}}),this.executionState.transactionActive=!1,t}catch(e){throw this.coreState.applyChanges(t,!0,!1),this.emit(this.eventBus,{name:"transaction:error",payload:{error:e instanceof Error?e:new Error(String(e)),timestamp:Date.now()}}),this.executionState.transactionActive=!1,e}}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},E=class{updateCount=0;listenerExecutions=0;averageUpdateTime=0;largestUpdateSize=0;mostActiveListenerPaths=[];totalUpdates=0;blockedUpdates=0;averageUpdateDuration=0;middlewareExecutions=0;transactionCount=0;totalEventsFired=0;totalActionsDispatched=0;totalActionsSucceeded=0;totalActionsFailed=0;averageActionDuration=0;updateTimes=[];actionTimes=[];pathExecutionCounts=new Map;constructor(e){this.setupEventListeners(e)}getMetrics(){return{updateCount:this.updateCount,listenerExecutions:this.listenerExecutions,averageUpdateTime:this.averageUpdateTime,largestUpdateSize:this.largestUpdateSize,mostActiveListenerPaths:[...this.mostActiveListenerPaths],totalUpdates:this.totalUpdates,blockedUpdates:this.blockedUpdates,averageUpdateDuration:this.averageUpdateDuration,middlewareExecutions:this.middlewareExecutions,transactionCount:this.transactionCount,totalEventsFired:this.totalEventsFired,totalActionsDispatched:this.totalActionsDispatched,totalActionsSucceeded:this.totalActionsSucceeded,totalActionsFailed:this.totalActionsFailed,averageActionDuration:this.averageActionDuration}}setupEventListeners(e){const t=e.emit;e.emit=s=>(this.totalEventsFired++,t.call(e,s)),e.subscribe("update:complete",(e=>{if(this.totalUpdates++,e.blocked)this.blockedUpdates++;else{if(e.duration){this.updateTimes.push(e.duration),this.updateTimes.length>100&&this.updateTimes.shift();const t=this.updateTimes.reduce(((e,t)=>e+t),0)/this.updateTimes.length;this.averageUpdateTime=t,this.averageUpdateDuration=t}e.deltas?.length&&(this.updateCount++,this.largestUpdateSize=Math.max(this.largestUpdateSize,e.deltas.length),e.deltas.forEach((e=>{const t=this.pathExecutionCounts.get(e.path)||0;this.pathExecutionCounts.set(e.path,t+1)})),this.mostActiveListenerPaths=Array.from(this.pathExecutionCounts.entries()).sort((([,e],[,t])=>t-e)).slice(0,5).map((([e])=>e)))}})),e.subscribe("middleware:start",(()=>{this.middlewareExecutions++})),e.subscribe("transaction:start",(()=>{this.transactionCount++})),e.subscribe("action:start",(()=>{this.totalActionsDispatched++})),e.subscribe("action:complete",(e=>{this.totalActionsSucceeded++,e.duration&&(this.actionTimes.push(e.duration),this.actionTimes.length>100&&this.actionTimes.shift(),this.averageActionDuration=this.actionTimes.reduce(((e,t)=>e+t),0)/this.actionTimes.length)})),e.subscribe("action:error",(()=>{this.totalActionsFailed++}))}reset(){this.updateCount=0,this.listenerExecutions=0,this.averageUpdateTime=0,this.largestUpdateSize=0,this.mostActiveListenerPaths=[],this.totalUpdates=0,this.blockedUpdates=0,this.averageUpdateDuration=0,this.middlewareExecutions=0,this.transactionCount=0,this.totalEventsFired=0,this.totalActionsDispatched=0,this.totalActionsSucceeded=0,this.totalActionsFailed=0,this.averageActionDuration=0,this.updateTimes=[],this.actionTimes=[],this.pathExecutionCounts.clear()}getDetailedMetrics(){return{pathExecutionCounts:new Map(this.pathExecutionCounts),recentUpdateTimes:[...this.updateTimes],successRate:this.totalUpdates>0?(this.totalUpdates-this.blockedUpdates)/this.totalUpdates:1,averagePathsPerUpdate:this.updateCount>0?Array.from(this.pathExecutionCounts.values()).reduce(((e,t)=>e+t),0)/this.updateCount:0}}dispose(){this.reset()}},M=class extends Error{constructor(){super("Action Cancelled by Debounce"),this.name="ActionCancelledError"}},C=class extends Error{constructor({action:e}){super(`Unknown action: "${e}"`),this.name="UnknownActionError"}},P=()=>{},L={name:"UNDEFINED ACTION",status:()=>!1,subscribe:e=>()=>{}},A=class{constructor(e,t){this.eventBus=e,this.set=t}registrations=new Map;register(e){const i={action:{name:e.name,id:t(),action:e.fn,debounce:e.debounce?{...e.debounce,condition:e.debounce.condition??(()=>!0)}:void 0},debouncer:e.debounce&&e.debounce.delay>0?new s({delay:e.debounce.delay}):void 0,previousArgs:void 0,running:!1,subscription:{listeners:new Set,watcher:null,watchers:new d((()=>[this.eventBus.subscribe("action:start",(t=>t.name===e.name&&this.notifyStatusListeners(e.name))),this.eventBus.subscribe("action:complete",(t=>t.name===e.name&&this.notifyStatusListeners(e.name))),this.eventBus.subscribe("action:error",(t=>t.name===e.name&&this.notifyStatusListeners(e.name)))]),(e=>e?.forEach((e=>e()))),{gracePeriod:"microtask"})}};return this.registrations.set(e.name,i),()=>{const t=this.registrations.get(e.name);t&&(t.debouncer?.cancel(),this.registrations.delete(e.name))}}async dispatch(e,...t){const s=this.registrations.get(e);if(!s)throw new C({action:e});const{action:i,debouncer:r}=s,{debounce:n}=i;if(!r||!n)return this.executeAction(s,t);const a=n.condition(s.previousArgs,t);if(s.previousArgs=t,!a)return this.executeAction(s,t);const o=await r.do((()=>this.executeAction(s,t)));if("cancelled"===o.status)throw new M;if("error"===o.status&&o.error)throw o.error;return o.value}async executeAction(e,t){const s=performance.now();e.running=!0,this.emit(this.eventBus,{name:"action:start",payload:{actionId:e.action.id,name:e.action.name,params:t||[],timestamp:s}});try{const i=await this.set((s=>e.action.action(s,...t)),{actionId:e.action.id}),r=performance.now();return e.running=!1,this.emit(this.eventBus,{name:"action:complete",payload:{actionId:e.action.id,name:e.action.name,params:t,startTime:s,endTime:r,duration:r-s,result:i}}),i}catch(i){const r=performance.now();throw e.running=!1,this.emit(this.eventBus,{name:"action:error",payload:{actionId:e.action.id,name:e.action.name,params:t,startTime:s,endTime:r,duration:r-s,error:i}}),i}}running(e){const t=this.registrations.get(e);return!!t&&t.running}subscribe(e,t){const s=this.registrations.get(e);return s?(s.subscription.listeners.add(t),s.subscription.watchers.acquire(),()=>{s.subscription.listeners.delete(t),s.subscription.watchers?.release()}):P}watch(e){const t=this.registrations.get(e);return t?(t.subscription.watcher||(t.subscription.watcher={name:e,status:()=>this.running(e),subscribe:t=>this.subscribe(e,t)}),t.subscription.watcher):L}notifyStatusListeners(e){const t=this.registrations.get(e).subscription.listeners;t&&t.forEach((e=>e()))}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},B=class{coreState;middlewareEngine;persistenceHandler;transactionManager;metricsCollector;selectorManager;actions;updateSerializer=new h({yieldMode:"macrotask",capacity:1e3});readyLatch=new a;updateBus=e();eventBus;executionState;instanceID=t();merge;diff;constructor(t,s,i=l,r){this.eventBus=e(),this.executionState={executing:!1,changes:null,pendingChanges:[],middlewares:[],runningMiddleware:null,transactionActive:!1},this.merge=p({deleteMarker:i}),this.diff=f({deleteMarker:i}),this.coreState=new S(t,this.updateBus,this.diff),this.middlewareEngine=new k(this.eventBus,this.executionState,this.merge),this.persistenceHandler=new T(this.eventBus,this.coreState,this.instanceID,{maxRetries:r?.persistenceMaxRetries,retryDelay:r?.persistenceRetryDelay}),this.transactionManager=new x(this.eventBus,this.coreState,this.executionState),this.metricsCollector=new E(this.eventBus),this.actions=new A(this.eventBus,this.set.bind(this)),this.persistenceHandler.initialize(s),this.setupPersistenceListener(),this.setupReadyLatch(),this.selectorManager=new y(this.get.bind(this),this.eventBus)}isReady(){return this.readyLatch.isOpen()}async ready(e){return this.readyLatch.wait(e)}state(){return this.executionState.executing=this.updateSerializer.running(),this.executionState}get(e){return this.coreState.get(e??!1)}select(e){return this.selectorManager.createReactiveSelector(e)}register(e){return this.actions.register(e)}async dispatch(e,...t){return this.actions.dispatch(e,...t)}async set(e,t={}){const s=await this.updateSerializer.do((()=>this._performUpdate(e,t)));if(s.error)throw s.error;return s.value}async _performUpdate(e,t){const s=performance.now();this.emit(this.eventBus,{name:"update:start",payload:{timestamp:s,actionId:t.actionId}});try{if(t.force){const i=this.get(!1),r="function"==typeof e?e(i):e;this.coreState.applyChanges(r,!0);const n=performance.now();return this.emit(this.eventBus,{name:"update:complete",payload:{deltas:[],duration:n-s,timestamp:Date.now(),actionId:t.actionId,newState:r}}),r}let i;const r=this.get(!1);if("function"==typeof e){const t=e(r);i=t instanceof Promise?await t:t}else i=e;const n=await this.middlewareEngine.executeBlocking(r,i);if(n.blocked)throw n.error||new Error("Update blocked by middleware");const a=this.merge(r,i),o=await this.middlewareEngine.executeTransform(a,i),c=this.merge(a,o),h=this.coreState.applyChanges(c,!1,!1,[i,o]),d=performance.now(),l=this.get(!1);return this.emit(this.eventBus,{name:"update:complete",payload:{deltas:h,duration:d-s,timestamp:Date.now(),actionId:t.actionId,newState:l}}),l}catch(e){throw this.emit(this.eventBus,{name:"update:complete",payload:{blocked:!0,error:e,timestamp:Date.now(),actionId:t.actionId,newState:this.get(!1)}}),e}finally{this.executionState.executing=!1,this.executionState.changes=null,this.executionState.runningMiddleware=null,this.executionState.pendingChanges=[]}}setupReadyLatch(){this.readyLatch.open(),this.persistenceHandler.isReady()?this.readyLatch.open():queueMicrotask((()=>{this.readyLatch.isOpen()||this.readyLatch.open()}))}setupPersistenceListener(){this.updateBus.subscribe("update",(e=>{e&&this.persistenceHandler.isReady()&&this.persistenceHandler.handleStateChange([e],this.get(!1))}))}watch(e,t){const s=Array.isArray(e)?e:[e],i=""===e||0===s.length;return this.updateBus.subscribe("update",(e=>{(i||s.includes(e))&&(t(this.get(!1)),this.metricsCollector.listenerExecutions++)}))}watchAction(e){return this.actions.watch(e)}debouncedSetter(e){const t=new s({delay:e.delay,leading:e.leading});return(e,s={})=>{t.fire((()=>this.set(e,s)))}}subscribe(e,t){return this.watch(e,t)}id(){return this.instanceID}async transaction(e){return this.transactionManager.execute(e)}use(e){const t=(e.block?this.middlewareEngine.addBlockingMiddleware:this.middlewareEngine.addMiddleware).bind(this.middlewareEngine)(e.action,e.name);return()=>this.middlewareEngine.removeMiddleware(t)}metrics(){return this.metricsCollector.getMetrics()}on(e,t){return this.eventBus.subscribe(e,t)}onStoreEvent(e,t){return this.eventBus.subscribe(e,t)}getPersistenceStatus(){return this.persistenceHandler.getQueueStatus()}async flushPersistence(){return this.persistenceHandler.flush()}discardPersistenceQueue(){this.persistenceHandler.discardQueue()}dispose(){this.updateSerializer.close(),this.persistenceHandler.dispose(),this.metricsCollector.dispose?.(),this.selectorManager.dispose?.()}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},H=class{store;eventHistory=[];stateHistory=[];unsubscribers=[];isTimeTraveling=!1;devTools=null;middlewareExecutions=[];activeTransactionCount=0;activeBatches=new Set;maxEvents;maxStateHistory;enableConsoleLogging;isSilent;logEvents;performanceThresholds;constructor(e,t={}){this.store=e,this.maxEvents=t.maxEvents??500,this.maxStateHistory=t.maxStateHistory??20,this.enableConsoleLogging=t.enableConsoleLogging??!1,this.isSilent=t.silent??!1,this.logEvents={updates:t.logEvents?.updates??!0,middleware:t.logEvents?.middleware??!0,transactions:t.logEvents?.transactions??!0,actions:t.logEvents?.actions??!0,selectors:t.logEvents?.selectors??!0},this.performanceThresholds={updateTime:t.performanceThresholds?.updateTime??50,middlewareTime:t.performanceThresholds?.middlewareTime??20},this.recordStateSnapshot([]),this.setupEventListeners()}_consoleLog(e,...t){this.isSilent||"function"==typeof console[e]&&console[e](...t)}setupEventListeners(){const e=["update:start","update:complete","middleware:start","middleware:complete","middleware:error","middleware:blocked","transaction:start","transaction:complete","transaction:error","middleware:executed","action:start","action:complete","action:error","selector:accessed"];for(const t of e){const e=t.startsWith("update")&&this.logEvents.updates||t.startsWith("middleware")&&this.logEvents.middleware||t.startsWith("transaction")&&this.logEvents.transactions||t.startsWith("action")&&this.logEvents.actions||t.startsWith("selector")&&this.logEvents.selectors;this.unsubscribers.push(this.store.on(t,(s=>{"update:complete"!==t||s.blocked||this.isTimeTraveling||this.recordStateSnapshot(s.deltas),"middleware:executed"===t?this.middlewareExecutions.push(s):"transaction:start"===t?this.activeTransactionCount++:"transaction:complete"!==t&&"transaction:error"!==t||(this.activeTransactionCount=Math.max(0,this.activeTransactionCount-1)),s.batchId&&(t.endsWith("start")?this.activeBatches.add(s.batchId):(t.endsWith("complete")||t.endsWith("error"))&&this.activeBatches.delete(s.batchId)),this.recordEvent(t,s),this.enableConsoleLogging&&e&&this._log(t,s),this._checkPerformance(t,s)})))}}recordStateSnapshot(e){const t={state:this.store.get(!0),timestamp:Date.now(),deltas:e};this.stateHistory.unshift(t),this.stateHistory.length>this.maxStateHistory&&this.stateHistory.pop()}recordEvent(e,t){const s={type:e,timestamp:Date.now(),data:structuredClone(t)};this.eventHistory.unshift(s),this.eventHistory.length>this.maxEvents&&this.eventHistory.pop()}getEventHistory(){return structuredClone(this.eventHistory)}getStateHistory(){return structuredClone(this.stateHistory)}getMiddlewareExecutions(){return this.middlewareExecutions}getTransactionStatus(){return{activeTransactions:this.activeTransactionCount,activeBatches:Array.from(this.activeBatches)}}createLoggingMiddleware(e={}){const{logLevel:t="debug",logUpdates:s=!0}=e;return(e,i)=>{if(s){(console[t]||console.log)("State Update:",i)}return i}}createValidationMiddleware(e){return(t,s)=>{const i=e(t,s);return"boolean"==typeof i?i:(!i.valid&&i.reason&&this._consoleLog("warn","Validation failed:",i.reason),i.valid)}}getRecentChanges(e=5){const t=[],s=Math.min(e,this.stateHistory.length);for(let e=0;e<s;e++){const s=this.stateHistory[e];if(!s.deltas||0===s.deltas.length)continue;const i={},r={},n=(e,t,s)=>{t.reduce(((e,i,r)=>(r===t.length-1?e[i]=s:e[i]=e[i]??{},e[i])),e)};for(const e of s.deltas){const t=e.path.split(".");n(i,t,e.oldValue),n(r,t,e.newValue)}t.push({timestamp:s.timestamp,changedPaths:s.deltas.map((e=>e.path)),from:i,to:r})}return t}clearHistory(){this.eventHistory=[],this.stateHistory.length>0&&(this.stateHistory=[this.stateHistory[0]])}getHistoryForAction(e){return this.eventHistory.filter((t=>t.data?.actionId===e))}async replay(e){const t=this.eventHistory.filter((e=>"update:start"===e.type))[e];t?.data.update?(this._consoleLog("log",`Replaying event at index ${e}:`,t),await this.store.set(t.data.update,{force:!0})):this._consoleLog("warn",`No replayable event found at index ${e}.`)}createTimeTravel(){let e=0,t=[];const s=this.store.on("update:complete",(s=>{this.isTimeTraveling||s.blocked||(t=[],e=0)}));this.unsubscribers.push(s);const i=()=>this.stateHistory.length,r=()=>e<i()-1,n=()=>t.length>0;return{canUndo:r,canRedo:n,undo:async()=>{if(!r())return;t.unshift(this.stateHistory[e]),e++;const s=this.stateHistory[e].state;this.isTimeTraveling=!0,await this.store.set({...s},{force:!0}),this.isTimeTraveling=!1},redo:async()=>{if(!n())return;const s=t.shift();e--,this.isTimeTraveling=!0,await this.store.set({...s.state},{force:!0}),this.isTimeTraveling=!1},length:i,clear:()=>{t=[],e=0}}}async saveSession(e){const t=this.store.id(),s={eventHistory:this.eventHistory,stateHistory:this.stateHistory};return Promise.resolve(e.set(t,s))}async loadSession(e){const t=await Promise.resolve(e.get());return!!t&&(this.eventHistory=t.eventHistory||[],this.stateHistory=t.stateHistory||[],this.stateHistory.length>0&&await this.store.set(this.stateHistory[0].state,{force:!0}),!0)}exportSession(){const e={eventHistory:this.eventHistory,stateHistory:this.stateHistory},t=new Blob([JSON.stringify(e,null,2)],{type:"application/json"}),s=URL.createObjectURL(t),i=document.createElement("a");i.href=s,i.download=`store-observer-session-${(new Date).toISOString()}.json`,i.click(),URL.revokeObjectURL(s)}importSession(e){return new Promise(((t,s)=>{const i=new FileReader;i.onload=async e=>{try{const s=JSON.parse(e.target?.result);this.eventHistory=s.eventHistory||[],this.stateHistory=s.stateHistory||[],this.stateHistory.length>0&&await this.store.set(this.stateHistory[0].state,{force:!0}),t()}catch(e){s(e)}},i.onerror=e=>s(e),i.readAsText(e)}))}disconnect(){this.unsubscribers.forEach((e=>e())),this.unsubscribers=[],this.devTools?.disconnect(),this.clearHistory()}_log(e,t){const s=new Date(t.timestamp||Date.now()).toISOString().split("T")[1].replace("Z","");if("update:start"===e)this._consoleLog("group",`%c⚡ Store Update Started [${s}]`,"color: #4a6da7");else if("update:complete"===e){if(t.blocked)this._consoleLog("warn",`%c✋ Update Blocked [${s}]`,"color: #bf8c0a",t.error);else{const e=t.deltas||[];e.length>0&&(this._consoleLog("log",`%c✅ Update Complete [${s}] - ${e.length} paths changed in ${t.duration?.toFixed(2)}ms`,"color: #2a9d8f"),this._consoleLog("table",e.map((e=>({path:e.path,oldValue:e.oldValue,newValue:e.newValue})))))}this._consoleLog("groupEnd")}else"middleware:start"===e?this._consoleLog("debug",`%c◀ Middleware "${t.name}" started [${s}] (${t.type})`,"color: #8c8c8c"):"middleware:complete"===e?this._consoleLog("debug",`%c▶ Middleware "${t.name}" completed [${s}] in ${t.duration?.toFixed(2)}ms`,"color: #7c9c7c"):"middleware:error"===e?this._consoleLog("error",`%c❌ Middleware "${t.name}" error [${s}]:`,"color: #e63946",t.error):"middleware:blocked"===e?this._consoleLog("warn",`%c🛑 Middleware "${t.name}" blocked update [${s}]`,"color: #e76f51"):"transaction:start"===e?this._consoleLog("group",`%c📦 Transaction Started [${s}]`,"color: #6d597a"):"transaction:complete"===e?(this._consoleLog("log",`%c📦 Transaction Complete [${s}]`,"color: #355070"),this._consoleLog("groupEnd")):"transaction:error"===e?(this._consoleLog("error",`%c📦 Transaction Error [${s}]:`,"color: #e56b6f",t.error),this._consoleLog("groupEnd")):"action:start"===e?this._consoleLog("group",`%c🚀 Action "${t.name}" Started [${s}]`,"color: #9b59b6",{params:t.params}):"action:complete"===e?(this._consoleLog("log",`%c✔️ Action "${t.name}" Complete [${s}] in ${t.duration?.toFixed(2)}ms`,"color: #2ecc71"),this._consoleLog("groupEnd")):"action:error"===e?(this._consoleLog("error",`%c🔥 Action "${t.name}" Error [${s}]:`,"color: #e74c3c",t.error),this._consoleLog("groupEnd")):"selector:accessed"===e&&this._consoleLog("debug",`%c👀 Selector Accessed [${s}] in ${t.duration?.toFixed(2)}ms`,"color: #f1c40f",{accessedPaths:t.accessedPaths,selectorId:t.selectorId})}_checkPerformance(e,t){this.enableConsoleLogging&&("update:complete"===e&&!t.blocked&&t.duration>this.performanceThresholds.updateTime&&this._consoleLog("warn",`%c⚠️ Slow update detected [${t.duration.toFixed(2)}ms]`,"color: #ff9f1c",{deltas:t.deltas,threshold:this.performanceThresholds.updateTime}),"middleware:complete"===e&&t.duration>this.performanceThresholds.middlewareTime&&this._consoleLog("warn",`%c⚠️ Slow middleware "${t.name}" [${t.duration.toFixed(2)}ms]`,"color: #ff9f1c",{threshold:this.performanceThresholds.middlewareTime}))}};export{M as ActionCancelledError,A as ActionManager,l as DELETE_SYMBOL,B as ReactiveDataStore,H as StoreObserver,C as UnknownActionError,v as createDerivePaths,f as createDiff,p as createMerge,_ as derivePaths,b as diff,m as merge,u as shallowClone};
|
|
1
|
+
import{createEventBus as e}from"@asaidimu/utils-events";import{v4 as t}from"uuid";var s=class{_delay;_leading;_timer;_pendingFn;_pendingResolvers=[];_leadingFired=!1;constructor(e){this._delay=e?.delay??300,this._leading=e?.leading??!1}do(e){return new Promise((t=>{this._enqueue(e,t)}))}fire(e){this._enqueue(e,void 0)}_enqueue(e,t){if(this._pendingFn=e,t&&this._pendingResolvers.push(t),this._leading&&!this._leadingFired)return this._leadingFired=!0,this._fire(),clearTimeout(this._timer),void(this._timer=setTimeout((()=>{this._leadingFired=!1,void 0!==this._pendingFn&&this._fire()}),this._delay));clearTimeout(this._timer),this._timer=setTimeout((()=>{this._leadingFired=!1,this._fire()}),this._delay)}cancel(){clearTimeout(this._timer),this._timer=void 0,this._pendingFn=void 0,this._leadingFired=!1;const e=this._pendingResolvers.splice(0);for(const t of e)t({status:"cancelled"})}async flush(){return this._pendingFn?(clearTimeout(this._timer),this._timer=void 0,this._leadingFired=!1,this._fire()):null}pending(){return void 0!==this._pendingFn}async _fire(){const e=this._pendingFn,t=this._pendingResolvers.splice(0);let s;this._pendingFn=void 0;try{s={status:"ok",value:await e()}}catch(e){s={status:"error",error:e}}for(const e of t)e(s);return s}},i=class e extends Error{constructor(t,s){super(t,{cause:s}),this.name="SyncError",Object.setPrototypeOf(this,e.prototype)}},r=class extends i{constructor(e){super(`[ArtifactContainer] Operation timed out: ${e}`)}},n=class extends i{constructor(e){super("[Serializer] The serializer has been marked as done!",e)}},a=class{_open=!1;_resolve;_promise;constructor(){this._promise=new Promise((e=>{this._resolve=e}))}open(){this._open||(this._open=!0,this._resolve())}async wait(e){if(this._open)return;if(null==e)return this._promise;let t;await Promise.race([this._promise.then((()=>clearTimeout(t))),new Promise(((s,i)=>{t=setTimeout((()=>i(new r("Latch timed out"))),e)}))])}isOpen(){return this._open}},o=class{_locked=!1;_capacity;_yieldMode;waiters=[];constructor(e){this._capacity=e?.capacity??1/0,this._yieldMode=e?.yieldMode??"macrotask"}async lock(e){if(!this._locked)return void(this._locked=!0);if(this.waiters.length>=this._capacity)throw new Error(`Mutex queue is full (capacity: ${this._capacity})`);let t;const s=new Promise((e=>t=e));if(this.waiters.push(t),null==e)return void await s;let i;await Promise.race([s.then((()=>clearTimeout(i))),new Promise(((s,n)=>{i=setTimeout((()=>{const e=this.waiters.indexOf(t);-1!==e&&this.waiters.splice(e,1),n(new r("Mutex lock timed out"))}),e)}))])}tryLock(){return!this._locked&&(this._locked=!0,!0)}unlock(){if(!this._locked)throw new Error("Mutex is not locked");const e=this.waiters.shift();e?"microtask"===this._yieldMode?queueMicrotask(e):setTimeout(e,0):this._locked=!1}locked(){return this._locked}pending(){return this.waiters.length}},c=class{mutex=new o({yieldMode:"microtask"});promise=null;_value=null;_error;_done=!1;retry;throws;constructor({retry:e,throws:t}={}){this.retry=Boolean(e),this.throws=Boolean(t)}async do(e,t){return this._done?this.peek():this.promise?this._awaitWithTimeout(this.promise,t,"Once do() timed out"):(await this.mutex.lock(),this.promise?(this.mutex.unlock(),this._awaitWithTimeout(this.promise,t,"Once do() timed out")):(this.promise=(async()=>{try{this._value=await e(),this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.retry&&!this._done&&(this.promise=null)}return this.peek()})(),this.mutex.unlock(),this._awaitWithTimeout(this.promise,t,"Once do() timed out")))}doSync(e){if(this._done){if(this.throws&&this._error)throw this._error;return this.peek()}if(this.promise){const e=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw e;return{value:null,error:e}}if(!this.mutex.tryLock()){const e=new Error("Cannot execute doSync: lock is currently held.");if(this.throws)throw e;return{value:null,error:e}}if(this.promise||this._done){if(this.mutex.unlock(),this._done){if(this.throws&&this._error)throw this._error;return this.peek()}const e=new Error("Cannot execute doSync while an async operation is pending.");if(this.throws)throw e;return{value:null,error:e}}try{const t=e();this._value=t,this._done=!0}catch(e){if(this._error=e,this.retry||(this._done=!0),this.throws)throw e}finally{this.mutex.unlock()}return this.peek()}running(){return null!==this.promise&&!this.done()}peek(){return{value:this._value,error:this._error}}get(){if(!this._done)throw new Error("Once operation is not yet complete");if(this._error)throw this._error;return this._value}reset(){if(this.running())throw new Error("Cannot reset Once while an operation is in progress.");this._done=!1,this.promise=null,this._value=null,this._error=void 0}done(){return this._done}current(){return this.promise}_awaitWithTimeout(e,t,s="Operation timed out"){if(null==t)return e;let i;return Promise.race([e.then((e=>(clearTimeout(i),e))),new Promise(((e,n)=>{i=setTimeout((()=>n(new r(s))),t)}))])}},h=class{mutex;_done=!1;_lastValue=null;_lastError=void 0;_hasRun=!1;constructor(e){this.mutex=new o({capacity:e?.capacity??1e3,yieldMode:e?.yieldMode??"macrotask"})}async do(e,t){if(this._done)return{value:null,error:new n};try{await this.mutex.lock(t)}catch(e){return{value:null,error:e}}let s,i=null;try{if(this._done)throw new n;i=await e(),this._lastValue=i,this._lastError=void 0,this._hasRun=!0}catch(e){s=e,this._lastError=e,this._hasRun=!0}finally{this.mutex.unlock()}return{value:i,error:s}}peek(){return{value:this._lastValue,error:this._lastError}}hasRun(){return this._hasRun}close(){this._done=!0}pending(){return this.mutex.pending()}running(){return this.mutex.locked()}},d=class{constructor(e,t,s={}){this.factory=e,this.onCleanup=t,this.options=s}_count=0;init=new c({retry:!1,throws:!1});pendingMicrotask=!1;cleanupTimer;get subscribers(){return this._count}async acquire(){this.cancelPendingCleanup(),this._count++;const e=await this.init.do(this.factory);if(e.error)throw e.error;return e.value}release(){this._count<=0?console.warn("SharedResource.release() called, but count is already 0."):(this._count--,0===this._count&&this.scheduleCleanup())}peek(){const e=this.init.peek();return e.error?null:e.value}forceCleanup(){this.cancelPendingCleanup(),this._count=0,this.executeCleanup()}cancelPendingCleanup(){this.pendingMicrotask=!1,void 0!==this.cleanupTimer&&(clearTimeout(this.cleanupTimer),this.cleanupTimer=void 0)}scheduleCleanup(){const e=this.options.gracePeriod??"microtask";if("sync"!==e)return"microtask"===e?(this.pendingMicrotask=!0,void queueMicrotask((()=>{!this.pendingMicrotask||this._count>0||(this.pendingMicrotask=!1,this.executeCleanup())}))):void(this.cleanupTimer=setTimeout((()=>{this.cleanupTimer=void 0,this._count>0||this.executeCleanup()}),e));this.executeCleanup()}executeCleanup(){const e=this.init.peek();try{this.onCleanup(e.value)}catch(e){console.error("[SharedResource] Error during cleanup callback:",e)}this.init.running()||this.init.reset()}},l=Symbol.for("delete"),u=e=>Array.isArray(e)?[...e]:{...e};function p(e){const t=e?.deleteMarker||l;function s(e){if(null==e)return e;if(Array.isArray(e))return e.filter((e=>e!==t)).map((e=>"object"!=typeof e||null===e||Array.isArray(e)?e:s(e)));if("object"==typeof e){const i={};for(const[r,n]of Object.entries(e))if(n!==t)if("object"==typeof n&&null!==n){const e=s(n);void 0!==e&&(i[r]=e)}else i[r]=n;return i}return e===t?void 0:e}return function(e,i){if("object"!=typeof e||null===e)return"object"==typeof i&&null!==i?s(i):i===t?{}:i;if("object"!=typeof i||null===i)return e;const r=u(e),n=[{target:r,source:i}];for(;n.length>0;){const{target:e,source:s}=n.pop();for(const i of Object.keys(s)){const r=s[i];if(r!==t)if(Array.isArray(r))e[i]=r;else if("object"==typeof r&&null!==r){const t=i in e&&"object"==typeof e[i]&&null!==e[i]?e[i]:{};e[i]=u(t),n.push({target:e[i],source:r})}else e[i]=r;else delete e[i]}}return r}}var m=p(),g=["map","filter","reduce","forEach","find","findIndex","some","every","includes","flatMap","flat","slice","splice"],y=class{reactiveSelectors=new Map;pathBasedCache=new Map;dependencyMap=new Map;getState;eventBus;unsubscribeFromStore;constructor(e,t){this.getState=e,this.eventBus=t,this.unsubscribeFromStore=this.eventBus.subscribe("update:complete",this.handleStoreUpdate)}handleStoreUpdate=e=>{const t=new Set;for(const s of e.deltas){const e=s.path;for(const[s,i]of this.dependencyMap)if(s===e||s.startsWith(e+".")||e.startsWith(s+"."))for(const e of i)t.add(e)}for(const e of t){const t=this.reactiveSelectors.get(e);t&&this.evaluateEntry(t)}};evaluateEntry(e){let t;try{t=e.selector(this.getState())}catch{t=void 0}if(t!==e.lastResult){e.lastResult=t;for(const s of e.subscribers)s(t);this.eventBus.emit({name:"selector:changed",payload:{selectorId:e.id,newResult:t,timestamp:performance.now()}})}}createReactiveSelector(e){const t=function(e,t="."){const s=new Set,i=new Map,r=(e="")=>{if(i.has(e))return i.get(e);const n=new Proxy((()=>{}),{get:(i,n)=>{if("symbol"==typeof n||"then"===n)return;if("valueOf"===n||"toString"===n)throw new Error("Cannot perform logic, arithmetic, or string operations inside a selector.");if(g.includes(n))throw new Error(`Array method .${n}() is not allowed in selectors.`);const a=e?`${e}${t}${n}`:n;return e&&s.delete(e),s.add(a),r(a)},has:()=>{throw new Error("The 'in' operator is not allowed in selectors.")},apply:()=>{throw new Error("Selectors cannot call functions or methods.")}});return i.set(e,n),n};try{e(r())}catch(e){throw new Error(`Selector failed during path analysis. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}return Array.from(s)}(e),s=[...t].sort().join("|"),i=this.pathBasedCache.get(s);if(i)return void 0!==i.cleanupTimer&&(clearTimeout(i.cleanupTimer),i.cleanupTimer=void 0),i.reactiveSelectorInstance;const r=`sel-${Math.random().toString(36).slice(2,9)}`,n={id:r,selector:e,lastResult:e(this.getState()),accessedPaths:t,subscribers:new Set,count:0,cleanupTimer:void 0,pathCacheKey:s,reactiveSelectorInstance:null};for(const e of t)this.dependencyMap.has(e)||this.dependencyMap.set(e,new Set),this.dependencyMap.get(e).add(r);const a={id:r,get:()=>{try{return n.selector(this.getState())}catch{return}},subscribe:e=>(void 0!==n.cleanupTimer&&(clearTimeout(n.cleanupTimer),n.cleanupTimer=void 0),n.subscribers.add(e),n.count++,()=>{n.subscribers.delete(e),n.count--,0===n.count&&(n.cleanupTimer=setTimeout((()=>{0===n.count&&this.evictEntry(n)}),0))})};return n.reactiveSelectorInstance=a,this.reactiveSelectors.set(r,n),this.pathBasedCache.set(s,n),this.eventBus.emit({name:"selector:accessed",payload:{selectorId:r,accessedPaths:t,duration:0,timestamp:performance.now()}}),a}evictEntry(e){for(const t of e.accessedPaths){const s=this.dependencyMap.get(t);s&&(s.delete(e.id),0===s.size&&this.dependencyMap.delete(t))}this.reactiveSelectors.delete(e.id),this.pathBasedCache.delete(e.pathCacheKey)}dispose(){this.unsubscribeFromStore(),this.reactiveSelectors.clear(),this.dependencyMap.clear(),this.pathBasedCache.clear()}};function w(e,t){if(e===t)return!0;if(e&&t&&"object"==typeof e&&"object"==typeof t){if(e.constructor!==t.constructor)return!1;let s,i;if(Array.isArray(e)){if(s=e.length,s!=t.length)return!1;for(i=s;i-- >0;)if(!w(e[i],t[i]))return!1;return!0}const[r,n]=[Object.keys(e),Object.keys(t)];if(s=r.length,s!==n.length)return!1;for(i=s;i-- >0;){const s=r[i];if(!Object.prototype.hasOwnProperty.call(t,s)||!w(e[s],t[s]))return!1}return!0}return e!=e&&t!=t}function f(e){const t=e?.deleteMarker||l;return function(e,s){const i=[],r=[{pathStr:"",orig:e||{},part:s||{}}];for(;r.length>0;){const{pathStr:e,orig:s,part:n}=r.pop();if(null!=n&&!w(s,n))if("object"!=typeof n||Array.isArray(n))e&&i.push({path:e,oldValue:s,newValue:n});else for(const a of Object.keys(n)){const o=e?e+"."+a:a,c=n[a],h=s&&"object"==typeof s?s[a]:void 0;c!==t?"object"==typeof c&&null!==c?r.push({pathStr:o,orig:h,part:c}):w(h,c)||i.push({path:o,oldValue:h,newValue:c}):void 0!==h&&i.push({path:o,oldValue:h,newValue:void 0})}}return i}}function v(e){const t=e?.deleteMarker||l;return function(e){const s=new Set,i=[{obj:e,currentPath:""}];for(;i.length>0;){const{obj:e,currentPath:r}=i.pop();if(null!=e&&"object"==typeof e&&!Array.isArray(e))for(const n of Object.keys(e)){const a=r?`${r}.${n}`:n;s.add(a);const o=e[n];"object"!=typeof o||null===o||Array.isArray(o)||o===t||i.push({obj:o,currentPath:a})}}return Array.from(s)}}var b=f(),_=v(),S=class{constructor(e,t,s){this.updateBus=t,this.diff=s,this.cache=structuredClone(e)}cache;get(e){return e?structuredClone(this.cache):this.cache}applyChanges(e,t=!1,s=!1,i=[]){if(t)return this.cache=s?structuredClone(e):e,this.notifyListeners([]),[];0===i.length&&(i=[e]);const r=this.get(!1),n=new Map;for(let e=0;e<i.length;e++){const t=i[e],s=this.diff(r,t);for(let e=0;e<s.length;e++){const t=s[e];n.set(t.path,t)}}const a=n.size?[...n.values()]:[];if(a.length>0){this.cache=s?structuredClone(e):e;const t=new Set;for(let e=0;e<a.length;e++){let s=a[e].path;for(;s&&!t.has(s);){t.add(s);const e=s.lastIndexOf(".");if(e<0)break;s=s.slice(0,e)}}this.notifyListeners(t)}return a}notifyListeners(e){for(const t of e)this.updateBus.emit({name:"update",payload:t})}},k=class{constructor(e,t,s){this.eventBus=e,this.executionState=t,this.merge=s}middleware=[];blockingMiddleware=[];async executeBlocking(e,t){for(const{fn:s,name:i,id:r}of this.blockingMiddleware){const n={id:r,name:i,startTime:performance.now()};this.executionState.runningMiddleware={id:r,name:i,startTime:performance.now()},this.emitMiddlewareLifecycle("start",{id:r,name:i,type:"blocking"});try{const a=await Promise.resolve(s(e,t));if(n.endTime=performance.now(),n.duration=n.endTime-n.startTime,!1===a)return n.blocked=!0,this.emitMiddlewareLifecycle("blocked",{id:r,name:i,duration:n.duration}),this.emit(this.eventBus,{name:"middleware:executed",payload:n}),{blocked:!0};this.emitMiddlewareLifecycle("complete",{id:r,name:i,type:"blocking",duration:n.duration}),this.emit(this.eventBus,{name:"middleware:executed",payload:{...n,blocked:!1}})}catch(e){return n.endTime=performance.now(),n.duration=n.endTime-n.startTime,n.error=e instanceof Error?e:new Error(String(e)),n.blocked=!0,this.emitMiddlewareError(r,i,n.error,n.duration),this.emit(this.eventBus,{name:"middleware:executed",payload:n}),{blocked:!0,error:n.error}}finally{this.executionState.runningMiddleware=null}}return{blocked:!1}}async executeTransform(e,t){let s=e,i=t;for(const{fn:e,name:r,id:n}of this.middleware){const a={id:n,name:r,startTime:performance.now()};this.executionState.runningMiddleware={id:n,name:r,startTime:performance.now()},this.emitMiddlewareLifecycle("start",{id:n,name:r,type:"transform"});try{const o=await Promise.resolve(e(s,t));a.endTime=performance.now(),a.duration=a.endTime-a.startTime,a.blocked=!1,o&&"object"==typeof o&&(s=this.merge(s,o),i=this.merge(i,o)),this.emit(this.eventBus,{name:"middleware:executed",payload:a}),this.emitMiddlewareLifecycle("complete",{id:n,name:r,type:"transform",duration:a.duration})}catch(e){a.endTime=performance.now(),a.duration=a.endTime-a.startTime,a.error=e instanceof Error?e:new Error(String(e)),a.blocked=!1,this.emit(this.eventBus,{name:"middleware:executed",payload:a}),this.emitMiddlewareError(n,r,a.error,a.duration),console.error(`Middleware ${r} error:`,e)}finally{this.executionState.runningMiddleware=null}}return i}addMiddleware(e,t="unnamed-middleware"){const s=this.generateId();return this.middleware.push({fn:e,name:t,id:s}),this.updateExecutionState(),s}addBlockingMiddleware(e,t="unnamed-blocking-middleware"){const s=this.generateId();return this.blockingMiddleware.push({fn:e,name:t,id:s}),this.updateExecutionState(),s}removeMiddleware(e){const t=this.middleware.length+this.blockingMiddleware.length;return this.middleware=this.middleware.filter((t=>t.id!==e)),this.blockingMiddleware=this.blockingMiddleware.filter((t=>t.id!==e)),this.updateExecutionState(),this.middleware.length+this.blockingMiddleware.length<t}updateExecutionState(){this.executionState.middlewares=[...this.middleware.map((e=>e.name)),...this.blockingMiddleware.map((e=>e.name))]}emitMiddlewareLifecycle(e,t){this.emit(this.eventBus,{name:`middleware:${e}`,payload:{...t,timestamp:Date.now()}})}emitMiddlewareError(e,t,s,i){this.emit(this.eventBus,{name:"middleware:error",payload:{id:e,name:t,error:s,duration:i,timestamp:Date.now()}})}generateId(){return crypto.randomUUID?crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).substring(2,15)}`}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},T=class{constructor(e,t,s,i){this.eventBus=e,this.coreState=t,this.instanceID=s,this.maxRetries=i?.maxRetries??3,this.retryDelay=i?.retryDelay??1e3}persistence;instanceID;persistenceReady=!1;backgroundQueue=[];isProcessingQueue=!1;maxRetries=3;retryDelay=1e3;queueProcessor;pendingRetries=new Set;async initialize(e){e?await this.setPersistence(e):this.setPersistenceReady()}isReady(){return this.persistenceReady}handleStateChange(e,t){if(!this.persistence||0===e.length)return;const s={id:`${Date.now()}-${Math.random().toString(36).slice(2,11)}`,state:structuredClone(t),changedPaths:[...e],timestamp:Date.now(),retries:0};this.backgroundQueue.push(s),this.scheduleQueueProcessing(),this.emit(this.eventBus,{name:"persistence:queued",payload:{taskId:s.id,changedPaths:e,queueSize:this.backgroundQueue.length,timestamp:s.timestamp}})}getQueueStatus(){return{queueSize:this.backgroundQueue.length,isProcessing:this.isProcessingQueue,pendingRetries:this.pendingRetries.size,oldestTask:this.backgroundQueue[0]?.timestamp}}async flush(){this.isProcessingQueue&&await new Promise((e=>{const t=()=>{this.isProcessingQueue?setTimeout(t,10):e()};t()})),await this.processQueue()}discardQueue(){const e=this.backgroundQueue.length+this.pendingRetries.size;this.backgroundQueue=[],this.pendingRetries.clear(),this.queueProcessor&&(clearTimeout(this.queueProcessor),this.queueProcessor=void 0),this.emit(this.eventBus,{name:"persistence:queue_cleared",payload:{clearedTasks:e,timestamp:Date.now()}})}scheduleQueueProcessing(){this.queueProcessor||this.isProcessingQueue||(this.queueProcessor=setTimeout((()=>{this.processQueue().catch((e=>{console.error("Queue processing failed:",e)}))}),10))}async processQueue(){if(!this.isProcessingQueue&&0!==this.backgroundQueue.length){this.isProcessingQueue=!0,this.queueProcessor=void 0;try{for(;this.backgroundQueue.length>0;){const e=this.backgroundQueue.shift();await this.processTask(e)}}finally{this.isProcessingQueue=!1}}}async processTask(e){try{await this.persistence.set(this.instanceID,e.state)?this.emit(this.eventBus,{name:"persistence:success",payload:{taskId:e.id,changedPaths:e.changedPaths,duration:Date.now()-e.timestamp,timestamp:Date.now()}}):await this.handleTaskFailure(e,new Error("Persistence returned false"))}catch(t){await this.handleTaskFailure(e,t)}}async handleTaskFailure(e,t){if(e.retries++,e.retries<=this.maxRetries){const s=this.retryDelay*Math.pow(2,e.retries-1);this.emit(this.eventBus,{name:"persistence:retry",payload:{taskId:e.id,attempt:e.retries,maxRetries:this.maxRetries,nextRetryIn:s,error:t,timestamp:Date.now()}}),this.pendingRetries.add(e.id),setTimeout((()=>{this.pendingRetries.has(e.id)&&(this.pendingRetries.delete(e.id),this.backgroundQueue.unshift(e),this.scheduleQueueProcessing())}),s)}else this.emit(this.eventBus,{name:"persistence:failed",payload:{taskId:e.id,changedPaths:e.changedPaths,attempts:e.retries,error:t,timestamp:Date.now()}})}setPersistenceReady(){this.persistenceReady=!0,this.emit(this.eventBus,{name:"persistence:ready",payload:{timestamp:Date.now()}})}async setPersistence(e){this.persistence=e;try{const e=await this.persistence.get();e&&this.coreState.applyChanges(e)}catch(e){console.error("Failed to initialize persistence:",e),this.emit(this.eventBus,{name:"persistence:init_error",payload:{error:e,timestamp:Date.now()}})}finally{this.setPersistenceReady()}this.persistence.subscribe(this.instanceID,(async e=>{const t=this.coreState.applyChanges(e);t.length>0&&this.emit(this.eventBus,{name:"update:complete",payload:{changedPaths:t,source:"external",timestamp:Date.now()}})}))}dispose(){this.discardQueue(),this.isProcessingQueue=!1,this.persistenceReady=!1}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},x=class{constructor(e,t,s){this.eventBus=e,this.coreState=t,this.executionState=s}async execute(e){const t=this.coreState.get(!0);this.executionState.transactionActive=!0,this.emit(this.eventBus,{name:"transaction:start",payload:{timestamp:Date.now()}});try{const t=await Promise.resolve(e());return this.emit(this.eventBus,{name:"transaction:complete",payload:{timestamp:Date.now()}}),this.executionState.transactionActive=!1,t}catch(e){throw this.coreState.applyChanges(t,!0,!1),this.emit(this.eventBus,{name:"transaction:error",payload:{error:e instanceof Error?e:new Error(String(e)),timestamp:Date.now()}}),this.executionState.transactionActive=!1,e}}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},E=class{updateCount=0;listenerExecutions=0;averageUpdateTime=0;largestUpdateSize=0;mostActiveListenerPaths=[];totalUpdates=0;blockedUpdates=0;averageUpdateDuration=0;middlewareExecutions=0;transactionCount=0;totalEventsFired=0;totalActionsDispatched=0;totalActionsSucceeded=0;totalActionsFailed=0;averageActionDuration=0;updateTimes=[];actionTimes=[];pathExecutionCounts=new Map;constructor(e){this.setupEventListeners(e)}getMetrics(){return{updateCount:this.updateCount,listenerExecutions:this.listenerExecutions,averageUpdateTime:this.averageUpdateTime,largestUpdateSize:this.largestUpdateSize,mostActiveListenerPaths:[...this.mostActiveListenerPaths],totalUpdates:this.totalUpdates,blockedUpdates:this.blockedUpdates,averageUpdateDuration:this.averageUpdateDuration,middlewareExecutions:this.middlewareExecutions,transactionCount:this.transactionCount,totalEventsFired:this.totalEventsFired,totalActionsDispatched:this.totalActionsDispatched,totalActionsSucceeded:this.totalActionsSucceeded,totalActionsFailed:this.totalActionsFailed,averageActionDuration:this.averageActionDuration}}setupEventListeners(e){const t=e.emit;e.emit=s=>(this.totalEventsFired++,t.call(e,s)),e.subscribe("update:complete",(e=>{if(this.totalUpdates++,e.blocked)this.blockedUpdates++;else{if(e.duration){this.updateTimes.push(e.duration),this.updateTimes.length>100&&this.updateTimes.shift();const t=this.updateTimes.reduce(((e,t)=>e+t),0)/this.updateTimes.length;this.averageUpdateTime=t,this.averageUpdateDuration=t}e.deltas?.length&&(this.updateCount++,this.largestUpdateSize=Math.max(this.largestUpdateSize,e.deltas.length),e.deltas.forEach((e=>{const t=this.pathExecutionCounts.get(e.path)||0;this.pathExecutionCounts.set(e.path,t+1)})),this.mostActiveListenerPaths=Array.from(this.pathExecutionCounts.entries()).sort((([,e],[,t])=>t-e)).slice(0,5).map((([e])=>e)))}})),e.subscribe("middleware:start",(()=>{this.middlewareExecutions++})),e.subscribe("transaction:start",(()=>{this.transactionCount++})),e.subscribe("action:start",(()=>{this.totalActionsDispatched++})),e.subscribe("action:complete",(e=>{this.totalActionsSucceeded++,e.duration&&(this.actionTimes.push(e.duration),this.actionTimes.length>100&&this.actionTimes.shift(),this.averageActionDuration=this.actionTimes.reduce(((e,t)=>e+t),0)/this.actionTimes.length)})),e.subscribe("action:error",(()=>{this.totalActionsFailed++}))}reset(){this.updateCount=0,this.listenerExecutions=0,this.averageUpdateTime=0,this.largestUpdateSize=0,this.mostActiveListenerPaths=[],this.totalUpdates=0,this.blockedUpdates=0,this.averageUpdateDuration=0,this.middlewareExecutions=0,this.transactionCount=0,this.totalEventsFired=0,this.totalActionsDispatched=0,this.totalActionsSucceeded=0,this.totalActionsFailed=0,this.averageActionDuration=0,this.updateTimes=[],this.actionTimes=[],this.pathExecutionCounts.clear()}getDetailedMetrics(){return{pathExecutionCounts:new Map(this.pathExecutionCounts),recentUpdateTimes:[...this.updateTimes],successRate:this.totalUpdates>0?(this.totalUpdates-this.blockedUpdates)/this.totalUpdates:1,averagePathsPerUpdate:this.updateCount>0?Array.from(this.pathExecutionCounts.values()).reduce(((e,t)=>e+t),0)/this.updateCount:0}}dispose(){this.reset()}},M=class extends Error{constructor(){super("Action Cancelled by Debounce"),this.name="ActionCancelledError"}},C=class extends Error{constructor({action:e}){super(`Unknown action: "${e}"`),this.name="UnknownActionError"}},P=()=>{},L={name:"UNDEFINED ACTION",status:()=>!1,subscribe:e=>()=>{}},A=class{constructor(e,t){this.eventBus=e,this.set=t}registrations=new Map;register(e){const i={action:{name:e.name,id:t(),action:e.fn,debounce:e.debounce?{...e.debounce,condition:e.debounce.condition??(()=>!0)}:void 0},debouncer:e.debounce&&e.debounce.delay>0?new s({delay:e.debounce.delay}):void 0,previousArgs:void 0,running:!1,subscription:{listeners:new Set,watcher:null,watchers:new d((()=>[this.eventBus.subscribe("action:start",(t=>t.name===e.name&&this.notifyStatusListeners(e.name))),this.eventBus.subscribe("action:complete",(t=>t.name===e.name&&this.notifyStatusListeners(e.name))),this.eventBus.subscribe("action:error",(t=>t.name===e.name&&this.notifyStatusListeners(e.name)))]),(e=>e?.forEach((e=>e()))),{gracePeriod:"microtask"})}};return this.registrations.set(e.name,i),()=>{const t=this.registrations.get(e.name);t&&(t.debouncer?.cancel(),this.registrations.delete(e.name))}}async dispatch(e,...t){const s=this.registrations.get(e);if(!s)throw new C({action:e});const{action:i,debouncer:r}=s,{debounce:n}=i;if(!r||!n)return this.executeAction(s,t);const a=n.condition(s.previousArgs,t);if(s.previousArgs=t,!a)return this.executeAction(s,t);const o=await r.do((()=>this.executeAction(s,t)));if("cancelled"===o.status)throw new M;if("error"===o.status&&o.error)throw o.error;return o.value}async executeAction(e,t){const s=performance.now();e.running=!0,this.emit(this.eventBus,{name:"action:start",payload:{actionId:e.action.id,name:e.action.name,params:t||[],timestamp:s}});try{const i=await this.set((s=>e.action.action(s,...t)),{actionId:e.action.id}),r=performance.now();return e.running=!1,this.emit(this.eventBus,{name:"action:complete",payload:{actionId:e.action.id,name:e.action.name,params:t,startTime:s,endTime:r,duration:r-s,result:i}}),i}catch(i){const r=performance.now();throw e.running=!1,this.emit(this.eventBus,{name:"action:error",payload:{actionId:e.action.id,name:e.action.name,params:t,startTime:s,endTime:r,duration:r-s,error:i}}),i}}running(e){const t=this.registrations.get(e);return!!t&&t.running}subscribe(e,t){const s=this.registrations.get(e);return s?(s.subscription.listeners.add(t),s.subscription.watchers.acquire(),()=>{s.subscription.listeners.delete(t),s.subscription.watchers?.release()}):P}watch(e){const t=this.registrations.get(e);return t?(t.subscription.watcher||(t.subscription.watcher={name:e,status:()=>this.running(e),subscribe:t=>this.subscribe(e,t)}),t.subscription.watcher):L}notifyStatusListeners(e){const t=this.registrations.get(e).subscription.listeners;t&&t.forEach((e=>e()))}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},B=class{coreState;middlewareEngine;persistenceHandler;transactionManager;metricsCollector;selectorManager;actions;updateSerializer=new h({yieldMode:"macrotask",capacity:1e3});readyLatch=new a;updateBus=e();eventBus;executionState;instanceID=t();merge;diff;constructor(t,s,i=l,r){this.eventBus=e(),this.executionState={executing:!1,changes:null,pendingChanges:[],middlewares:[],runningMiddleware:null,transactionActive:!1},this.merge=p({deleteMarker:i}),this.diff=f({deleteMarker:i}),this.coreState=new S(t,this.updateBus,this.diff),this.middlewareEngine=new k(this.eventBus,this.executionState,this.merge),this.persistenceHandler=new T(this.eventBus,this.coreState,this.instanceID,{maxRetries:r?.persistenceMaxRetries,retryDelay:r?.persistenceRetryDelay}),this.transactionManager=new x(this.eventBus,this.coreState,this.executionState),this.metricsCollector=new E(this.eventBus),this.actions=new A(this.eventBus,this.set.bind(this)),this.persistenceHandler.initialize(s),this.setupPersistenceListener(),this.setupReadyLatch(),this.selectorManager=new y(this.get.bind(this),this.eventBus)}isReady(){return this.readyLatch.isOpen()}async ready(e){return this.readyLatch.wait(e)}state(){return this.executionState.executing=this.updateSerializer.running(),this.executionState}get(e){return this.coreState.get(e??!1)}select(e){return this.selectorManager.createReactiveSelector(e)}register(e){return this.actions.register(e)}async dispatch(e,...t){return this.actions.dispatch(e,...t)}async set(e,t={}){const s=await this.updateSerializer.do((()=>this._performUpdate(e,t)));if(s.error)throw s.error;return s.value}async _performUpdate(e,t){const s=performance.now();this.emit(this.eventBus,{name:"update:start",payload:{timestamp:s,actionId:t.actionId}});try{if(t.force){const i=this.get(!1),r="function"==typeof e?e(i):e;this.coreState.applyChanges(r,!0);const n=performance.now();return this.emit(this.eventBus,{name:"update:complete",payload:{deltas:[],duration:n-s,timestamp:Date.now(),actionId:t.actionId,newState:r}}),r}let i;const r=this.get(!1);if("function"==typeof e){const t=e(r);i=t instanceof Promise?await t:t}else i=e;const n=await this.middlewareEngine.executeBlocking(r,i);if(n.blocked)throw n.error||new Error("Update blocked by middleware");const a=this.merge(r,i),o=await this.middlewareEngine.executeTransform(a,i),c=this.merge(a,o),h=this.coreState.applyChanges(c,!1,!1,[i,o]),d=performance.now(),l=this.get(!1);return this.emit(this.eventBus,{name:"update:complete",payload:{deltas:h,duration:d-s,timestamp:Date.now(),actionId:t.actionId,newState:l}}),l}catch(e){throw this.emit(this.eventBus,{name:"update:complete",payload:{blocked:!0,error:e,timestamp:Date.now(),actionId:t.actionId,newState:this.get(!1)}}),e}finally{this.executionState.executing=!1,this.executionState.changes=null,this.executionState.runningMiddleware=null,this.executionState.pendingChanges=[]}}setupReadyLatch(){this.readyLatch.open(),this.persistenceHandler.isReady()?this.readyLatch.open():queueMicrotask((()=>{this.readyLatch.isOpen()||this.readyLatch.open()}))}setupPersistenceListener(){this.updateBus.subscribe("update",(e=>{e&&this.persistenceHandler.isReady()&&this.persistenceHandler.handleStateChange([e],this.get(!1))}))}watch(e,t,s){const i=Array.isArray(e)?e:[e],r=""===e||0===i.length;return this.updateBus.subscribe("update",(e=>{(r||i.includes(e))&&(t(this.get(!1)),this.metricsCollector.listenerExecutions++)}),s)}watchAction(e){return this.actions.watch(e)}debouncedSetter(e){const t=new s({delay:e.delay,leading:e.leading});return(e,s={})=>{t.fire((()=>this.set(e,s)))}}id(){return this.instanceID}async transaction(e){return this.transactionManager.execute(e)}use(e){const t=(e.block?this.middlewareEngine.addBlockingMiddleware:this.middlewareEngine.addMiddleware).bind(this.middlewareEngine)(e.action,e.name);return()=>this.middlewareEngine.removeMiddleware(t)}metrics(){return this.metricsCollector.getMetrics()}on(e,t){return this.eventBus.subscribe(e,t)}getPersistenceStatus(){return this.persistenceHandler.getQueueStatus()}async flushPersistence(){return this.persistenceHandler.flush()}discardPersistenceQueue(){this.persistenceHandler.discardQueue()}dispose(){this.updateSerializer.close(),this.persistenceHandler.dispose(),this.metricsCollector.dispose?.(),this.selectorManager.dispose?.()}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},H=class{store;eventHistory=[];stateHistory=[];unsubscribers=[];isTimeTraveling=!1;devTools=null;middlewareExecutions=[];activeTransactionCount=0;activeBatches=new Set;maxEvents;maxStateHistory;enableConsoleLogging;isSilent;logEvents;performanceThresholds;constructor(e,t={}){this.store=e,this.maxEvents=t.maxEvents??500,this.maxStateHistory=t.maxStateHistory??20,this.enableConsoleLogging=t.enableConsoleLogging??!1,this.isSilent=t.silent??!1,this.logEvents={updates:t.logEvents?.updates??!0,middleware:t.logEvents?.middleware??!0,transactions:t.logEvents?.transactions??!0,actions:t.logEvents?.actions??!0,selectors:t.logEvents?.selectors??!0},this.performanceThresholds={updateTime:t.performanceThresholds?.updateTime??50,middlewareTime:t.performanceThresholds?.middlewareTime??20},this.recordStateSnapshot([]),this.setupEventListeners()}_consoleLog(e,...t){this.isSilent||"function"==typeof console[e]&&console[e](...t)}setupEventListeners(){const e=["update:start","update:complete","middleware:start","middleware:complete","middleware:error","middleware:blocked","transaction:start","transaction:complete","transaction:error","middleware:executed","action:start","action:complete","action:error","selector:accessed"];for(const t of e){const e=t.startsWith("update")&&this.logEvents.updates||t.startsWith("middleware")&&this.logEvents.middleware||t.startsWith("transaction")&&this.logEvents.transactions||t.startsWith("action")&&this.logEvents.actions||t.startsWith("selector")&&this.logEvents.selectors;this.unsubscribers.push(this.store.on(t,(s=>{"update:complete"!==t||s.blocked||this.isTimeTraveling||this.recordStateSnapshot(s.deltas),"middleware:executed"===t?this.middlewareExecutions.push(s):"transaction:start"===t?this.activeTransactionCount++:"transaction:complete"!==t&&"transaction:error"!==t||(this.activeTransactionCount=Math.max(0,this.activeTransactionCount-1)),s.batchId&&(t.endsWith("start")?this.activeBatches.add(s.batchId):(t.endsWith("complete")||t.endsWith("error"))&&this.activeBatches.delete(s.batchId)),this.recordEvent(t,s),this.enableConsoleLogging&&e&&this._log(t,s),this._checkPerformance(t,s)})))}}recordStateSnapshot(e){const t={state:this.store.get(!0),timestamp:Date.now(),deltas:e};this.stateHistory.unshift(t),this.stateHistory.length>this.maxStateHistory&&this.stateHistory.pop()}recordEvent(e,t){const s={type:e,timestamp:Date.now(),data:structuredClone(t)};this.eventHistory.unshift(s),this.eventHistory.length>this.maxEvents&&this.eventHistory.pop()}getEventHistory(){return structuredClone(this.eventHistory)}getStateHistory(){return structuredClone(this.stateHistory)}getMiddlewareExecutions(){return this.middlewareExecutions}getTransactionStatus(){return{activeTransactions:this.activeTransactionCount,activeBatches:Array.from(this.activeBatches)}}createLoggingMiddleware(e={}){const{logLevel:t="debug",logUpdates:s=!0}=e;return(e,i)=>{if(s){(console[t]||console.log)("State Update:",i)}return i}}createValidationMiddleware(e){return(t,s)=>{const i=e(t,s);return"boolean"==typeof i?i:(!i.valid&&i.reason&&this._consoleLog("warn","Validation failed:",i.reason),i.valid)}}getRecentChanges(e=5){const t=[],s=Math.min(e,this.stateHistory.length);for(let e=0;e<s;e++){const s=this.stateHistory[e];if(!s.deltas||0===s.deltas.length)continue;const i={},r={},n=(e,t,s)=>{t.reduce(((e,i,r)=>(r===t.length-1?e[i]=s:e[i]=e[i]??{},e[i])),e)};for(const e of s.deltas){const t=e.path.split(".");n(i,t,e.oldValue),n(r,t,e.newValue)}t.push({timestamp:s.timestamp,changedPaths:s.deltas.map((e=>e.path)),from:i,to:r})}return t}clearHistory(){this.eventHistory=[],this.stateHistory.length>0&&(this.stateHistory=[this.stateHistory[0]])}getHistoryForAction(e){return this.eventHistory.filter((t=>t.data?.actionId===e))}async replay(e){const t=this.eventHistory.filter((e=>"update:start"===e.type))[e];t?.data.update?(this._consoleLog("log",`Replaying event at index ${e}:`,t),await this.store.set(t.data.update,{force:!0})):this._consoleLog("warn",`No replayable event found at index ${e}.`)}createTimeTravel(){let e=0,t=[];const s=this.store.on("update:complete",(s=>{this.isTimeTraveling||s.blocked||(t=[],e=0)}));this.unsubscribers.push(s);const i=()=>this.stateHistory.length,r=()=>e<i()-1,n=()=>t.length>0;return{canUndo:r,canRedo:n,undo:async()=>{if(!r())return;t.unshift(this.stateHistory[e]),e++;const s=this.stateHistory[e].state;this.isTimeTraveling=!0,await this.store.set({...s},{force:!0}),this.isTimeTraveling=!1},redo:async()=>{if(!n())return;const s=t.shift();e--,this.isTimeTraveling=!0,await this.store.set({...s.state},{force:!0}),this.isTimeTraveling=!1},length:i,clear:()=>{t=[],e=0}}}async saveSession(e){const t=this.store.id(),s={eventHistory:this.eventHistory,stateHistory:this.stateHistory};return Promise.resolve(e.set(t,s))}async loadSession(e){const t=await Promise.resolve(e.get());return!!t&&(this.eventHistory=t.eventHistory||[],this.stateHistory=t.stateHistory||[],this.stateHistory.length>0&&await this.store.set(this.stateHistory[0].state,{force:!0}),!0)}exportSession(){const e={eventHistory:this.eventHistory,stateHistory:this.stateHistory},t=new Blob([JSON.stringify(e,null,2)],{type:"application/json"}),s=URL.createObjectURL(t),i=document.createElement("a");i.href=s,i.download=`store-observer-session-${(new Date).toISOString()}.json`,i.click(),URL.revokeObjectURL(s)}importSession(e){return new Promise(((t,s)=>{const i=new FileReader;i.onload=async e=>{try{const s=JSON.parse(e.target?.result);this.eventHistory=s.eventHistory||[],this.stateHistory=s.stateHistory||[],this.stateHistory.length>0&&await this.store.set(this.stateHistory[0].state,{force:!0}),t()}catch(e){s(e)}},i.onerror=e=>s(e),i.readAsText(e)}))}disconnect(){this.unsubscribers.forEach((e=>e())),this.unsubscribers=[],this.devTools?.disconnect(),this.clearHistory()}_log(e,t){const s=new Date(t.timestamp||Date.now()).toISOString().split("T")[1].replace("Z","");if("update:start"===e)this._consoleLog("group",`%c⚡ Store Update Started [${s}]`,"color: #4a6da7");else if("update:complete"===e){if(t.blocked)this._consoleLog("warn",`%c✋ Update Blocked [${s}]`,"color: #bf8c0a",t.error);else{const e=t.deltas||[];e.length>0&&(this._consoleLog("log",`%c✅ Update Complete [${s}] - ${e.length} paths changed in ${t.duration?.toFixed(2)}ms`,"color: #2a9d8f"),this._consoleLog("table",e.map((e=>({path:e.path,oldValue:e.oldValue,newValue:e.newValue})))))}this._consoleLog("groupEnd")}else"middleware:start"===e?this._consoleLog("debug",`%c◀ Middleware "${t.name}" started [${s}] (${t.type})`,"color: #8c8c8c"):"middleware:complete"===e?this._consoleLog("debug",`%c▶ Middleware "${t.name}" completed [${s}] in ${t.duration?.toFixed(2)}ms`,"color: #7c9c7c"):"middleware:error"===e?this._consoleLog("error",`%c❌ Middleware "${t.name}" error [${s}]:`,"color: #e63946",t.error):"middleware:blocked"===e?this._consoleLog("warn",`%c🛑 Middleware "${t.name}" blocked update [${s}]`,"color: #e76f51"):"transaction:start"===e?this._consoleLog("group",`%c📦 Transaction Started [${s}]`,"color: #6d597a"):"transaction:complete"===e?(this._consoleLog("log",`%c📦 Transaction Complete [${s}]`,"color: #355070"),this._consoleLog("groupEnd")):"transaction:error"===e?(this._consoleLog("error",`%c📦 Transaction Error [${s}]:`,"color: #e56b6f",t.error),this._consoleLog("groupEnd")):"action:start"===e?this._consoleLog("group",`%c🚀 Action "${t.name}" Started [${s}]`,"color: #9b59b6",{params:t.params}):"action:complete"===e?(this._consoleLog("log",`%c✔️ Action "${t.name}" Complete [${s}] in ${t.duration?.toFixed(2)}ms`,"color: #2ecc71"),this._consoleLog("groupEnd")):"action:error"===e?(this._consoleLog("error",`%c🔥 Action "${t.name}" Error [${s}]:`,"color: #e74c3c",t.error),this._consoleLog("groupEnd")):"selector:accessed"===e&&this._consoleLog("debug",`%c👀 Selector Accessed [${s}] in ${t.duration?.toFixed(2)}ms`,"color: #f1c40f",{accessedPaths:t.accessedPaths,selectorId:t.selectorId})}_checkPerformance(e,t){this.enableConsoleLogging&&("update:complete"===e&&!t.blocked&&t.duration>this.performanceThresholds.updateTime&&this._consoleLog("warn",`%c⚠️ Slow update detected [${t.duration.toFixed(2)}ms]`,"color: #ff9f1c",{deltas:t.deltas,threshold:this.performanceThresholds.updateTime}),"middleware:complete"===e&&t.duration>this.performanceThresholds.middlewareTime&&this._consoleLog("warn",`%c⚠️ Slow middleware "${t.name}" [${t.duration.toFixed(2)}ms]`,"color: #ff9f1c",{threshold:this.performanceThresholds.middlewareTime}))}};export{M as ActionCancelledError,A as ActionManager,l as DELETE_SYMBOL,B as ReactiveDataStore,H as StoreObserver,C as UnknownActionError,v as createDerivePaths,f as createDiff,p as createMerge,_ as derivePaths,b as diff,m as merge,u as shallowClone};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asaidimu/utils-store",
|
|
3
|
-
"version": "10.1.
|
|
3
|
+
"version": "10.1.8",
|
|
4
4
|
"description": "A reactive data store",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "index.mjs",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"uuid": "^11.1.0",
|
|
33
|
-
"@asaidimu/utils-events": "1.
|
|
33
|
+
"@asaidimu/utils-events": "^1.0.0"
|
|
34
34
|
},
|
|
35
35
|
"exports": {
|
|
36
36
|
".": {
|