@asaidimu/utils-store 5.0.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -267
- package/index.d.mts +1 -213
- package/index.d.ts +1 -213
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,7 +22,6 @@ A comprehensive, type-safe, and reactive state management library for TypeScript
|
|
|
22
22
|
- [Middleware System](#middleware-system)
|
|
23
23
|
- [Transaction Support](#transaction-support)
|
|
24
24
|
- [Artifacts (Dependency Injection)](#artifacts-dependency-injection)
|
|
25
|
-
- [React Integration](#react-integration)
|
|
26
25
|
- [Store Observer (Debugging & Observability)](#store-observer-debugging--observability)
|
|
27
26
|
- [Event System](#event-system)
|
|
28
27
|
- [Project Architecture](#project-architecture)
|
|
@@ -49,7 +48,6 @@ This library offers robust tools to handle your state with confidence, enabling
|
|
|
49
48
|
* 📦 **Atomic Transaction Support**: Group multiple state updates into a single, atomic operation. If any update within the transaction fails or an error is thrown, the entire transaction is rolled back to the state before the transaction began, guaranteeing data integrity. Supports both synchronous and asynchronous operations.
|
|
50
49
|
* 💾 **Optional Persistence Layer**: Seamlessly integrate with any `SimplePersistence<T>` implementation (e.g., for local storage, IndexedDB, or backend synchronization) to load an initial state and save subsequent changes. The store emits a `persistence:ready` event and listens for external updates, handling persistence queueing and retries.
|
|
51
50
|
* 🧩 **Artifacts (Dependency Injection)**: A flexible dependency injection system to manage services, utilities, or complex objects that your actions and other artifacts depend on. Supports `Singleton` (re-evaluated on dependencies change) and `Transient` (new instance every time) scopes, and reactive resolution using `use(({select, resolve}) => ...)` context. Handles dependency graphs and circular dependency detection.
|
|
52
|
-
* ⚛️ **React Integration**: Provides a `createStore` factory function that returns a custom React hook (`useStore`). This hook offers `select` (memoized selector hook), `actions` (bound action dispatchers), and `resolve` (reactive artifact resolver) for seamless integration with React components. It leverages React's `useSyncExternalStore` for optimal performance.
|
|
53
51
|
* 👀 **Deep Observer & Debugging (`StoreObserver`)**: An optional but highly recommended class for unparalleled runtime introspection and debugging:
|
|
54
52
|
* **Comprehensive Event History**: Captures a detailed log of all internal store events (`update:start`, `middleware:complete`, `transaction:error`, `persistence:ready`, `middleware:executed`, `action:start`, `selector:accessed`, etc.).
|
|
55
53
|
* **State Snapshots**: Maintains a configurable history of your application's state over time, allowing for easy inspection of changes between updates and post-mortem analysis.
|
|
@@ -82,7 +80,6 @@ yarn add @asaidimu/utils-store
|
|
|
82
80
|
|
|
83
81
|
* **Node.js**: (LTS version recommended) for development and compilation.
|
|
84
82
|
* **TypeScript**: (v4.0+ recommended) for full type-safety during development. Modern TS features (ES2017+ for `async/await`, ES2020+ for `Symbol.for()` and `structuredClone()`) are utilized. `moduleResolution`: `Node16` or `Bundler` is recommended in `tsconfig.json`.
|
|
85
|
-
* **React**: (v16.8+ for hooks) if using the `@asaidimu/utils-store/react` integration.
|
|
86
83
|
|
|
87
84
|
### Verification
|
|
88
85
|
|
|
@@ -698,7 +695,7 @@ console.log('State after manual action:', store.get());
|
|
|
698
695
|
const temporaryLoggerId = store.use({ name: 'TemporaryLogger', action: (s, u) => console.log('Temporary logger saw:', u) });
|
|
699
696
|
await store.set({ counter: 1 });
|
|
700
697
|
// Output: Temporary logger saw: { counter: 1 }
|
|
701
|
-
const removed =
|
|
698
|
+
const removed = temporaryLoggerId(); // Remove the temporary logger
|
|
702
699
|
console.log('Middleware removed:', removed);
|
|
703
700
|
await store.set({ counter: 1 }); // TemporaryLogger will not be called now
|
|
704
701
|
```
|
|
@@ -872,10 +869,8 @@ try {
|
|
|
872
869
|
|
|
873
870
|
The Artifact system provides a powerful way to manage external dependencies, services, or complex objects that your actions or other artifacts might need. It supports `Singleton` (created once, reactive to dependencies) and `Transient` (new instance every time) scopes, and allows artifacts to depend on state changes and other artifacts.
|
|
874
871
|
|
|
875
|
-
This example uses the `ArtifactContainer` directly for clarity, but in React applications, you'd typically use the `createStore` factory, which automatically integrates with `ArtifactContainer` and exposes resolution via `useStore().resolve()`.
|
|
876
|
-
|
|
877
872
|
```typescript
|
|
878
|
-
import { ArtifactContainer, ArtifactScope } from '@asaidimu/utils-store
|
|
873
|
+
import { ReactiveDataStore, ArtifactContainer, ArtifactScope } from '@asaidimu/utils-store';
|
|
879
874
|
|
|
880
875
|
interface AppState {
|
|
881
876
|
user: { id: string; name: string; };
|
|
@@ -883,12 +878,10 @@ interface AppState {
|
|
|
883
878
|
}
|
|
884
879
|
|
|
885
880
|
// Mock DataStore interface for standalone ArtifactContainer usage
|
|
886
|
-
|
|
881
|
+
const store = new ReactiveDataStore<AppState>({
|
|
887
882
|
user: { id: 'user-1', name: 'Alice' },
|
|
888
883
|
config: { apiUrl: '/api/v1', logLevel: 'info' }
|
|
889
|
-
};
|
|
890
|
-
|
|
891
|
-
const store = new ReactiveDataStore<AppState>(currentState);
|
|
884
|
+
});
|
|
892
885
|
|
|
893
886
|
const container = new ArtifactContainer(store);
|
|
894
887
|
|
|
@@ -911,16 +904,17 @@ const apiClientCleanup = () => console.log('API Client connection closed.');
|
|
|
911
904
|
container.register({
|
|
912
905
|
key: 'apiClient',
|
|
913
906
|
scope: ArtifactScope.Singleton,
|
|
914
|
-
factory: async ({ use, current }) => {
|
|
907
|
+
factory: async ({ use, onCleanup, current }) => {
|
|
915
908
|
const apiUrl = await use(({ select }) => select((state: AppState) => state.config.apiUrl));
|
|
916
909
|
console.log(`API Client created/re-created for URL: ${apiUrl}`);
|
|
917
910
|
if (current) {
|
|
918
911
|
console.log('Re-creating API client. Old instance:', current);
|
|
919
912
|
}
|
|
920
|
-
|
|
913
|
+
onCleanup(apiClientCleanup); // Register cleanup for this instance
|
|
914
|
+
return {
|
|
921
915
|
fetchUser: (id: string) => `Fetching ${id} from ${apiUrl}`,
|
|
922
916
|
sendData: (data: any) => `Sending ${JSON.stringify(data)} to ${apiUrl}`
|
|
923
|
-
}
|
|
917
|
+
};
|
|
924
918
|
}
|
|
925
919
|
});
|
|
926
920
|
|
|
@@ -929,17 +923,18 @@ const userServiceCleanup = () => console.log('User Service resources released.')
|
|
|
929
923
|
container.register({
|
|
930
924
|
key: 'userService',
|
|
931
925
|
scope: ArtifactScope.Singleton,
|
|
932
|
-
factory: async ({ use, current }) => {
|
|
926
|
+
factory: async ({ use, onCleanup, current }) => {
|
|
933
927
|
const apiClient = await use(({ resolve }) => resolve('apiClient'));
|
|
934
928
|
const userName = await use(({ select }) => select((state: AppState) => state.user.name));
|
|
935
929
|
console.log(`User Service created/re-created for user: ${userName}`);
|
|
936
930
|
if (current) {
|
|
937
931
|
console.log('Re-creating User Service. Old instance:', current);
|
|
938
932
|
}
|
|
939
|
-
|
|
940
|
-
|
|
933
|
+
onCleanup(userServiceCleanup); // Register cleanup for this instance
|
|
934
|
+
return {
|
|
935
|
+
getUserProfile: () => apiClient.instance!.fetchUser(store.get().user.id),
|
|
941
936
|
updateUserName: (newName: string) => `Updating user name to ${newName} via API. Current: ${userName}`
|
|
942
|
-
}
|
|
937
|
+
};
|
|
943
938
|
}
|
|
944
939
|
});
|
|
945
940
|
|
|
@@ -948,48 +943,47 @@ container.register({
|
|
|
948
943
|
async function runDemo() {
|
|
949
944
|
console.log('\n--- Initial Artifact Resolution ---');
|
|
950
945
|
const logger1 = await container.resolve('logger');
|
|
951
|
-
logger1.log('Application started.');
|
|
946
|
+
logger1.instance!.log('Application started.');
|
|
952
947
|
|
|
953
948
|
const apiClient1 = await container.resolve('apiClient');
|
|
954
|
-
console.log(apiClient1.fetchUser('123'));
|
|
949
|
+
console.log(apiClient1.instance!.fetchUser('123'));
|
|
955
950
|
|
|
956
951
|
const userService1 = await container.resolve('userService');
|
|
957
|
-
console.log(userService1.getUserProfile());
|
|
952
|
+
console.log(userService1.instance!.getUserProfile());
|
|
958
953
|
|
|
959
954
|
// Transient artifact resolves a new instance
|
|
960
955
|
const logger2 = await container.resolve('logger');
|
|
961
|
-
|
|
956
|
+
console.log('Logger instances are different:', logger1.instance !== logger2.instance);
|
|
962
957
|
|
|
963
|
-
// Singleton artifacts resolve the same instance
|
|
958
|
+
// Singleton artifacts resolve the same instance initially
|
|
964
959
|
const apiClient2 = await container.resolve('apiClient');
|
|
965
|
-
|
|
960
|
+
console.log('API Client instances are same:', apiClient1.instance === apiClient2.instance);
|
|
966
961
|
|
|
967
962
|
console.log('\n--- Simulate State Change (config.apiUrl) ---');
|
|
968
|
-
store.set({ config:{ apiUrl: '/api/v2'}})
|
|
963
|
+
await store.set({ config:{ apiUrl: '/api/v2'}})
|
|
964
|
+
// This state change invalidates 'apiClient' which depends on 'config.apiUrl'
|
|
965
|
+
// and then invalidates 'userService' which depends on 'apiClient'.
|
|
969
966
|
|
|
970
967
|
// After config.apiUrl changes, apiClient (and userService) should be re-created
|
|
971
968
|
const apiClient3 = await container.resolve('apiClient'); // This will trigger re-creation
|
|
972
|
-
console.log(apiClient3.fetchUser('123'));
|
|
973
|
-
|
|
969
|
+
console.log(apiClient3.instance!.fetchUser('123'));
|
|
970
|
+
console.log('API Client instances are different:', apiClient3.instance !== apiClient1.instance); // Should be a new instance
|
|
974
971
|
|
|
975
972
|
// userService should also be re-created because apiClient, its dependency, was re-created
|
|
976
973
|
const userService2 = await container.resolve('userService');
|
|
977
|
-
console.log(userService2.getUserProfile());
|
|
978
|
-
|
|
974
|
+
console.log(userService2.instance!.getUserProfile());
|
|
975
|
+
console.log('User Service instances are different:', userService2.instance !== userService1.instance); // Should be a new instance
|
|
979
976
|
|
|
980
977
|
console.log('\n--- Simulate State Change (user.name) ---');
|
|
981
|
-
|
|
982
|
-
{ ...currentState, user: { ...currentState.user, name: 'Bob' } },
|
|
983
|
-
['user.name']
|
|
984
|
-
);
|
|
978
|
+
await store.set({ user: { name: 'Bob' } });
|
|
985
979
|
|
|
986
980
|
// Only userService (which depends on user.name) should be re-created this time, not apiClient
|
|
987
981
|
const apiClient4 = await container.resolve('apiClient');
|
|
988
|
-
|
|
982
|
+
console.log('API Client instances are same:', apiClient4.instance === apiClient3.instance); // Still the same API client instance
|
|
989
983
|
|
|
990
984
|
const userService3 = await container.resolve('userService');
|
|
991
|
-
console.log(userService3.getUserProfile());
|
|
992
|
-
|
|
985
|
+
console.log(userService3.instance!.getUserProfile());
|
|
986
|
+
console.log('User Service instances are different:', userService3.instance !== userService2.instance); // New user service instance
|
|
993
987
|
|
|
994
988
|
console.log('\n--- Unregistering Artifacts ---');
|
|
995
989
|
await container.unregister('userService');
|
|
@@ -1000,220 +994,13 @@ async function runDemo() {
|
|
|
1000
994
|
try {
|
|
1001
995
|
await container.resolve('userService');
|
|
1002
996
|
} catch (e: any) {
|
|
1003
|
-
console.error('Expected error:', e.message);
|
|
997
|
+
console.error('Expected error:', e.message); // Artifact not found
|
|
1004
998
|
}
|
|
1005
999
|
}
|
|
1006
1000
|
|
|
1007
1001
|
runDemo();
|
|
1008
1002
|
```
|
|
1009
1003
|
|
|
1010
|
-
### React Integration
|
|
1011
|
-
|
|
1012
|
-
The `@asaidimu/utils-store/react-store` module provides a `createStore` factory function that integrates the core `ReactiveDataStore` with React's context and `useSyncExternalStore` hook. This makes it easy to consume state, dispatch actions, and resolve artifacts in your React components.
|
|
1013
|
-
|
|
1014
|
-
```typescript
|
|
1015
|
-
// store.ts (example for an E-commerce dashboard)
|
|
1016
|
-
import { ArtifactScope, createStore, ActionMap, ArtifactsMap } from '@asaidimu/utils-store';
|
|
1017
|
-
|
|
1018
|
-
export interface Product {
|
|
1019
|
-
id: number; name: string; price: number; stock: number; image: string;
|
|
1020
|
-
}
|
|
1021
|
-
export interface CartItem extends Product { quantity: number; }
|
|
1022
|
-
export interface Order { id: string; items: CartItem[]; total: number; date: Date; }
|
|
1023
|
-
|
|
1024
|
-
export interface ECommerceState extends Record<string, any> {
|
|
1025
|
-
products: Product[];
|
|
1026
|
-
cart: CartItem[];
|
|
1027
|
-
orders: Order[];
|
|
1028
|
-
topSellers: { id: number; name: string; sales: number }[];
|
|
1029
|
-
activeUsers: number;
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
const initialState: ECommerceState = {
|
|
1033
|
-
products: [
|
|
1034
|
-
{ id: 1, name: 'Wireless Mouse', price: 25.99, stock: 150, image: 'https://placehold.co/600x400/white/black?text=Mouse' },
|
|
1035
|
-
{ id: 2, name: 'Mechanical Keyboard', price: 79.99, stock: 100, image: 'https://placehold.co/600x400/white/black?text=Keyboard' },
|
|
1036
|
-
],
|
|
1037
|
-
cart: [], orders: [], topSellers: [], activeUsers: 1428,
|
|
1038
|
-
};
|
|
1039
|
-
|
|
1040
|
-
// 1. Define Artifacts
|
|
1041
|
-
export const artifacts = {
|
|
1042
|
-
logger: {
|
|
1043
|
-
scope: ArtifactScope.Singleton,
|
|
1044
|
-
factory: () => ((...args:any[]) => console.log('Artifact Logger:', ...args))
|
|
1045
|
-
},
|
|
1046
|
-
analytics: {
|
|
1047
|
-
scope: ArtifactScope.Transient,
|
|
1048
|
-
factory: () => ({
|
|
1049
|
-
trackEvent: (name: string, data: object) => console.log(`[Analytics] ${name}`, data)
|
|
1050
|
-
})
|
|
1051
|
-
}
|
|
1052
|
-
} as const satisfies ArtifactsMap<ECommerceState>
|
|
1053
|
-
|
|
1054
|
-
// 2. Define Actions
|
|
1055
|
-
export const actions = {
|
|
1056
|
-
addToCart: async ({ state, resolve }, product: Product) => {
|
|
1057
|
-
const log = await resolve("logger");
|
|
1058
|
-
const analytics = await resolve("analytics");
|
|
1059
|
-
analytics.trackEvent('add_to_cart', { product: product.name });
|
|
1060
|
-
|
|
1061
|
-
const existingItem = state.cart.find((item) => item.id === product.id);
|
|
1062
|
-
if (existingItem) {
|
|
1063
|
-
return {
|
|
1064
|
-
cart: state.cart.map((item) =>
|
|
1065
|
-
item.id === product.id ? { ...item, quantity: item.quantity + 1 } : item
|
|
1066
|
-
),
|
|
1067
|
-
};
|
|
1068
|
-
}
|
|
1069
|
-
const result = { cart: [...state.cart, { ...product, quantity: 1 }] };
|
|
1070
|
-
log("Item added:", product.name);
|
|
1071
|
-
return result
|
|
1072
|
-
},
|
|
1073
|
-
removeFromCart: ({ state }, productId: number) => ({
|
|
1074
|
-
cart: state.cart.filter((item) => item.id !== productId),
|
|
1075
|
-
}),
|
|
1076
|
-
checkout: ({ state }) => {
|
|
1077
|
-
const total = state.cart.reduce((sum, item) => sum + item.price * item.quantity, 0);
|
|
1078
|
-
const newOrder: Order = {
|
|
1079
|
-
id: crypto.randomUUID(), items: state.cart, total, date: new Date(),
|
|
1080
|
-
};
|
|
1081
|
-
return {
|
|
1082
|
-
cart: [], orders: [newOrder, ...state.orders],
|
|
1083
|
-
};
|
|
1084
|
-
},
|
|
1085
|
-
// Simulated real-time updates for the dashboard example
|
|
1086
|
-
updateStock: ({ state }) => ({
|
|
1087
|
-
products: state.products.map(p => ({
|
|
1088
|
-
...p,
|
|
1089
|
-
stock: Math.max(0, p.stock + Math.floor(Math.random() * 10) - 5)
|
|
1090
|
-
}))
|
|
1091
|
-
}),
|
|
1092
|
-
updateActiveUsers: ({ state }) => ({
|
|
1093
|
-
activeUsers: state.activeUsers + Math.floor(Math.random() * 20) - 10,
|
|
1094
|
-
}),
|
|
1095
|
-
addRandomOrder: ({ state }) => {
|
|
1096
|
-
const randomProduct = state.products[Math.floor(Math.random() * state.products.length)];
|
|
1097
|
-
const quantity = Math.floor(Math.random() * 3) + 1;
|
|
1098
|
-
const newOrder: Order = {
|
|
1099
|
-
id: crypto.randomUUID(),
|
|
1100
|
-
items: [{ ...randomProduct, quantity }],
|
|
1101
|
-
total: randomProduct.price * quantity,
|
|
1102
|
-
date: new Date(),
|
|
1103
|
-
};
|
|
1104
|
-
return {
|
|
1105
|
-
orders: [newOrder, ...state.orders],
|
|
1106
|
-
};
|
|
1107
|
-
},
|
|
1108
|
-
} as const satisfies ActionMap<ECommerceState, typeof artifacts>
|
|
1109
|
-
|
|
1110
|
-
// 3. Create the React Store Hook
|
|
1111
|
-
export const useStore = createStore(
|
|
1112
|
-
{
|
|
1113
|
-
state: initialState,
|
|
1114
|
-
artifacts,
|
|
1115
|
-
actions,
|
|
1116
|
-
},
|
|
1117
|
-
{ enableMetrics: true, enableConsoleLogging: true }
|
|
1118
|
-
);
|
|
1119
|
-
|
|
1120
|
-
// App.tsx (React Component)
|
|
1121
|
-
import { useEffect, useMemo } from 'react';
|
|
1122
|
-
import { useStore } from './store'; // Import the custom hook
|
|
1123
|
-
|
|
1124
|
-
function ProductCatalog() {
|
|
1125
|
-
const { select, actions } = useStore();
|
|
1126
|
-
const products = select((state) => state.products); // Reactive selector for products
|
|
1127
|
-
|
|
1128
|
-
return (
|
|
1129
|
-
<div>
|
|
1130
|
-
<h2>Products</h2>
|
|
1131
|
-
{products.map((product) => (
|
|
1132
|
-
<div key={product.id}>
|
|
1133
|
-
{product.name} - ${product.price} ({product.stock} in stock)
|
|
1134
|
-
<button onClick={() => actions.addToCart(product)}>Add to Cart</button>
|
|
1135
|
-
</div>
|
|
1136
|
-
))}
|
|
1137
|
-
</div>
|
|
1138
|
-
);
|
|
1139
|
-
}
|
|
1140
|
-
|
|
1141
|
-
function ShoppingCart() {
|
|
1142
|
-
const { select, actions } = useStore();
|
|
1143
|
-
const cart = select((state) => state.cart); // Reactive selector for cart
|
|
1144
|
-
const total = useMemo(() => cart.reduce((sum, item) => sum + item.price * item.quantity, 0), [cart]);
|
|
1145
|
-
|
|
1146
|
-
return (
|
|
1147
|
-
<div>
|
|
1148
|
-
<h2>Shopping Cart</h2>
|
|
1149
|
-
{cart.length === 0 ? (
|
|
1150
|
-
<p>Your cart is empty.</p>
|
|
1151
|
-
) : (
|
|
1152
|
-
<ul>
|
|
1153
|
-
{cart.map((item) => (
|
|
1154
|
-
<li key={item.id}>
|
|
1155
|
-
{item.name} x {item.quantity} - ${item.price * item.quantity}
|
|
1156
|
-
<button onClick={() => actions.removeFromCart(item.id)}>Remove</button>
|
|
1157
|
-
</li>
|
|
1158
|
-
))}
|
|
1159
|
-
</ul>
|
|
1160
|
-
)}
|
|
1161
|
-
<p>Total: ${total.toFixed(2)}</p>
|
|
1162
|
-
{cart.length > 0 && <button onClick={() => actions.checkout()}>Checkout</button>}
|
|
1163
|
-
</div>
|
|
1164
|
-
);
|
|
1165
|
-
}
|
|
1166
|
-
|
|
1167
|
-
function DebugPanel() {
|
|
1168
|
-
const { resolve, watch, state } = useStore();
|
|
1169
|
-
const [logger, loggerReady] = resolve('logger'); // Reactive artifact resolution
|
|
1170
|
-
const [analytics, analyticsReady] = resolve('analytics');
|
|
1171
|
-
|
|
1172
|
-
const isLoadingAddToCart = watch('addToCart'); // Watch specific action loading state
|
|
1173
|
-
|
|
1174
|
-
return (
|
|
1175
|
-
<div>
|
|
1176
|
-
<h3>Debug Panel</h3>
|
|
1177
|
-
<p>Add to Cart Loading: {isLoadingAddToCart ? 'Yes' : 'No'}</p>
|
|
1178
|
-
<p>Store is ready: {useStore().isReady ? 'Yes' : 'No'}</p>
|
|
1179
|
-
<button onClick={() => loggerReady && logger('Debug message from UI')}>Log via Artifact</button>
|
|
1180
|
-
<button onClick={() => analyticsReady && analytics.trackEvent('ui_event', { component: 'DebugPanel' })}>Track UI Event</button>
|
|
1181
|
-
<pre>Full State: {JSON.stringify(state(), null, 2)}</pre>
|
|
1182
|
-
</div>
|
|
1183
|
-
);
|
|
1184
|
-
}
|
|
1185
|
-
|
|
1186
|
-
function App() {
|
|
1187
|
-
const { actions } = useStore();
|
|
1188
|
-
|
|
1189
|
-
// Simulate real-time updates
|
|
1190
|
-
useEffect(() => {
|
|
1191
|
-
const stockInterval = setInterval(() => actions.updateStock(), 2000);
|
|
1192
|
-
const usersInterval = setInterval(() => actions.updateActiveUsers(), 3000);
|
|
1193
|
-
const ordersInterval = setInterval(() => actions.addRandomOrder(), 5000);
|
|
1194
|
-
|
|
1195
|
-
return () => {
|
|
1196
|
-
clearInterval(stockInterval);
|
|
1197
|
-
clearInterval(usersInterval);
|
|
1198
|
-
clearInterval(ordersInterval);
|
|
1199
|
-
};
|
|
1200
|
-
}, [actions]);
|
|
1201
|
-
|
|
1202
|
-
return (
|
|
1203
|
-
<div>
|
|
1204
|
-
<h1>E-Commerce App</h1>
|
|
1205
|
-
<ProductCatalog />
|
|
1206
|
-
<hr />
|
|
1207
|
-
<ShoppingCart />
|
|
1208
|
-
<hr />
|
|
1209
|
-
<DebugPanel />
|
|
1210
|
-
</div>
|
|
1211
|
-
);
|
|
1212
|
-
}
|
|
1213
|
-
|
|
1214
|
-
export default App;
|
|
1215
|
-
```
|
|
1216
|
-
|
|
1217
1004
|
### Store Observer (Debugging & Observability)
|
|
1218
1005
|
|
|
1219
1006
|
The `StoreObserver` class provides advanced debugging and monitoring capabilities for any `ReactiveDataStore` instance. It allows you to inspect event history, state changes, and even time-travel through your application's state. It's an invaluable tool for understanding complex state flows.
|
|
@@ -1509,29 +1296,6 @@ console.log('Final value:', store.get().value, 'Final status:', store.get().stat
|
|
|
1509
1296
|
|
|
1510
1297
|
The `@asaidimu/utils-store` library is built with a modular, component-based architecture to promote maintainability, testability, and extensibility. Each core concern is encapsulated within its own class, with `ReactiveDataStore` acting as the central coordinator.
|
|
1511
1298
|
|
|
1512
|
-
```
|
|
1513
|
-
src/store/
|
|
1514
|
-
├── index.ts # Main entry point (exports all public APIs)
|
|
1515
|
-
├── types.ts # TypeScript interfaces and types for the store
|
|
1516
|
-
├── store.ts # `ReactiveDataStore` - The main orchestrator
|
|
1517
|
-
├── state.ts # `StateManager` - Manages the immutable state and diffing
|
|
1518
|
-
├── merge.ts # `createMerge` - Deep merging utility with deletion support
|
|
1519
|
-
├── diff.ts # `createDiff`, `createDerivePaths` - Change detection utilities
|
|
1520
|
-
├── middleware.ts # `MiddlewareEngine` - Manages and executes middleware pipeline
|
|
1521
|
-
├── transactions.ts # `TransactionManager` - Handles atomic state transactions
|
|
1522
|
-
├── persistence.ts # `PersistenceHandler` - Integrates with `SimplePersistence` layer
|
|
1523
|
-
├── metrics.ts # `MetricsCollector` - Gathers runtime performance metrics
|
|
1524
|
-
├── selector.ts # `SelectorManager` - Manages reactive selectors for derived state
|
|
1525
|
-
├── observer.ts # `StoreObserver` - Debugging and introspection utilities
|
|
1526
|
-
├── artifacts.ts # `ArtifactContainer` - Dependency Injection system for services
|
|
1527
|
-
├── actions.ts # `ActionManager` - Manages registration and dispatch of named actions
|
|
1528
|
-
└── react-store/ # React integration module (hooks, context)
|
|
1529
|
-
├── index.ts
|
|
1530
|
-
├── types.ts
|
|
1531
|
-
├── store.ts # `createStore` - Factory for React hooks
|
|
1532
|
-
└── execution.ts # `ActionTracker` - Tracks action execution history for React integration
|
|
1533
|
-
```
|
|
1534
|
-
|
|
1535
1299
|
### Core Components
|
|
1536
1300
|
|
|
1537
1301
|
* **`ReactiveDataStore<T>`**: The public API and primary entry point. It orchestrates interactions between all other internal components. It manages the update queue, ensures sequential processing of `set` calls, and exposes public methods like `get`, `dispatch`, `select`, `set`, `watch`, `transaction`, `use`, and `on`.
|
package/index.d.mts
CHANGED
|
@@ -382,218 +382,6 @@ declare class ReactiveDataStore<T extends object> implements DataStore<T> {
|
|
|
382
382
|
private emit;
|
|
383
383
|
}
|
|
384
384
|
|
|
385
|
-
/**
|
|
386
|
-
* Defines the lifecycle scope of an artifact.
|
|
387
|
-
*/
|
|
388
|
-
declare enum ArtifactScope {
|
|
389
|
-
/**
|
|
390
|
-
* Created once and cached.
|
|
391
|
-
* The container tracks its dependencies and rebuilds it if they change.
|
|
392
|
-
*/
|
|
393
|
-
Singleton = "singleton",
|
|
394
|
-
/**
|
|
395
|
-
* Created every time it is resolved.
|
|
396
|
-
* Dependencies are NOT tracked, and it is never cached.
|
|
397
|
-
*/
|
|
398
|
-
Transient = "transient"
|
|
399
|
-
}
|
|
400
|
-
/**
|
|
401
|
-
* Dependency resolution context provided to the `use()` callback.
|
|
402
|
-
* Used to declare dependencies on other artifacts or state slices.
|
|
403
|
-
*/
|
|
404
|
-
interface UseDependencyContext<TState extends object> {
|
|
405
|
-
/**
|
|
406
|
-
* Resolve another artifact.
|
|
407
|
-
* This records a dependency: if the target artifact is invalidated, the caller will be too.
|
|
408
|
-
*
|
|
409
|
-
* @param key The key of the artifact to resolve.
|
|
410
|
-
*/
|
|
411
|
-
resolve<TArtifact>(key: string): Promise<ResolvedArtifact<TArtifact>>;
|
|
412
|
-
/**
|
|
413
|
-
* Select a slice of state.
|
|
414
|
-
* This records a dependency: if the selected state changes, the artifact will be invalidated.
|
|
415
|
-
*
|
|
416
|
-
* @param selector A function that selects a part of the global state.
|
|
417
|
-
*/
|
|
418
|
-
select<S>(selector: (state: TState) => S): S;
|
|
419
|
-
}
|
|
420
|
-
/**
|
|
421
|
-
* The context object provided to an artifact's factory function.
|
|
422
|
-
* Provides tools for state access, dependency injection, and lifecycle management.
|
|
423
|
-
*/
|
|
424
|
-
interface ArtifactFactoryContext<TState extends object> {
|
|
425
|
-
/**
|
|
426
|
-
* Get the current state snapshot immediately.
|
|
427
|
-
* **Note:** Calling this does NOT create a subscription. Use `ctx.use(c => c.select(...))` for reactive behavior.
|
|
428
|
-
*/
|
|
429
|
-
state(): TState;
|
|
430
|
-
/**
|
|
431
|
-
* The existing instance if the artifact is being re-evaluated/rebuilt.
|
|
432
|
-
* Useful for preserving internal state (like active connections) during hot-swaps.
|
|
433
|
-
*/
|
|
434
|
-
current?: unknown;
|
|
435
|
-
/**
|
|
436
|
-
* Execute a callback to capture dependencies.
|
|
437
|
-
* All `resolve()` and `select()` calls inside this callback are recorded
|
|
438
|
-
* to build the reactive dependency graph.
|
|
439
|
-
*
|
|
440
|
-
* @param callback The function where dependencies are declared.
|
|
441
|
-
*/
|
|
442
|
-
use<K>(callback: (ctx: UseDependencyContext<TState>) => K | Promise<K>): Promise<K>;
|
|
443
|
-
/**
|
|
444
|
-
* Register a cleanup function to be called when the artifact is disposed or rebuilt.
|
|
445
|
-
* Multiple cleanup functions can be registered; they will be called in reverse order (LIFO).
|
|
446
|
-
*
|
|
447
|
-
* @param cleanup A function to execute during teardown.
|
|
448
|
-
*/
|
|
449
|
-
onCleanup(cleanup: ArtifactCleanup): void;
|
|
450
|
-
/**
|
|
451
|
-
* Hot-swap the artifact instance without triggering a full teardown.
|
|
452
|
-
*
|
|
453
|
-
* **Behavior:**
|
|
454
|
-
* 1. Updates the internal instance **synchronously** (immediate consistency).
|
|
455
|
-
* 2. Invalidates downstream dependents **asynchronously** (graph consistency).
|
|
456
|
-
* 3. Notifies listeners (UI updates) only after the graph is consistent.
|
|
457
|
-
*
|
|
458
|
-
* @param value The new instance value to set.
|
|
459
|
-
*
|
|
460
|
-
* @example
|
|
461
|
-
* // Updating a WebSocket connection without losing the wrapping artifact
|
|
462
|
-
* factory: async (ctx) => {
|
|
463
|
-
* const ws = new WebSocket(url);
|
|
464
|
-
* ws.onmessage = (msg) => ctx.yield(JSON.parse(msg.data));
|
|
465
|
-
* return ws; // Initial value
|
|
466
|
-
* }
|
|
467
|
-
*/
|
|
468
|
-
yield(value: unknown): void;
|
|
469
|
-
}
|
|
470
|
-
/**
|
|
471
|
-
* A function to clean up resources (close sockets, remove listeners, etc.).
|
|
472
|
-
*/
|
|
473
|
-
type ArtifactCleanup = () => void | Promise<void>;
|
|
474
|
-
/**
|
|
475
|
-
* The result of resolving an artifact.
|
|
476
|
-
* Wraps the instance with metadata, error state, and control methods.
|
|
477
|
-
*/
|
|
478
|
-
interface ResolvedArtifact<TArtifact> {
|
|
479
|
-
/** The resolved artifact instance. */
|
|
480
|
-
instance: TArtifact;
|
|
481
|
-
/** A function that runs all registered cleanups for this artifact. */
|
|
482
|
-
cleanup?: ArtifactCleanup;
|
|
483
|
-
/** Any error that occurred during creation. */
|
|
484
|
-
error?: any;
|
|
485
|
-
/**
|
|
486
|
-
* Manually invalidate this artifact.
|
|
487
|
-
* @param replace If `true`, forces an immediate rebuild (Eager). If `false`, marks as stale (Lazy).
|
|
488
|
-
*/
|
|
489
|
-
invalidate(replace?: boolean): Promise<void>;
|
|
490
|
-
}
|
|
491
|
-
/**
|
|
492
|
-
* A factory function that creates an instance of an artifact.
|
|
493
|
-
*/
|
|
494
|
-
type ArtifactFactory<TState extends object, TArtifact> = (context: ArtifactFactoryContext<TState>) => TArtifact | Promise<TArtifact>;
|
|
495
|
-
/**
|
|
496
|
-
* A reactive dependency injection container.
|
|
497
|
-
* Manages the lifecycle, caching, and dependency graph of application artifacts.
|
|
498
|
-
*/
|
|
499
|
-
declare class ArtifactContainer<TState extends object> {
|
|
500
|
-
private readonly artifacts;
|
|
501
|
-
private readonly resolvingStack;
|
|
502
|
-
private readonly listeners;
|
|
503
|
-
private readonly getState;
|
|
504
|
-
private readonly subscribe;
|
|
505
|
-
/**
|
|
506
|
-
* @param props Interface to the external state store (e.g., Zustand, Redux).
|
|
507
|
-
*/
|
|
508
|
-
constructor(props: Pick<DataStore<TState>, "watch" | "get">);
|
|
509
|
-
/**
|
|
510
|
-
* Watch an artifact for changes and retrieve its current state.
|
|
511
|
-
*
|
|
512
|
-
* @param id The artifact key to watch.
|
|
513
|
-
* @returns An object containing the ID, a getter, and a subscribe method.
|
|
514
|
-
*
|
|
515
|
-
* @example
|
|
516
|
-
* const watcher = container.watch("current-user");
|
|
517
|
-
* const unsub = watcher.subscribe(() => {
|
|
518
|
-
* const user = watcher.get()?.instance;
|
|
519
|
-
* console.log("User updated:", user);
|
|
520
|
-
* });
|
|
521
|
-
*/
|
|
522
|
-
watch<TArtifact>(id: string): {
|
|
523
|
-
id: string;
|
|
524
|
-
get(): ResolvedArtifact<TArtifact> | null;
|
|
525
|
-
subscribe(callback: () => void): () => void;
|
|
526
|
-
};
|
|
527
|
-
/**
|
|
528
|
-
* Direct sync access to an artifact instance.
|
|
529
|
-
* Use this sparingly; prefer `resolve()` or `watch()`.
|
|
530
|
-
*/
|
|
531
|
-
get(id: string): any | undefined;
|
|
532
|
-
/**
|
|
533
|
-
* Registers a new artifact factory.
|
|
534
|
-
*
|
|
535
|
-
* @param options Configuration for the artifact.
|
|
536
|
-
* @returns A function to unregister the artifact.
|
|
537
|
-
*/
|
|
538
|
-
register<TArtifact>(options: {
|
|
539
|
-
key: string;
|
|
540
|
-
factory: ArtifactFactory<TState, TArtifact>;
|
|
541
|
-
scope?: ArtifactScope;
|
|
542
|
-
lazy?: boolean;
|
|
543
|
-
}): () => void;
|
|
544
|
-
/**
|
|
545
|
-
* Unregisters an artifact and cleans up its resources.
|
|
546
|
-
*/
|
|
547
|
-
unregister(key: string): Promise<void>;
|
|
548
|
-
/**
|
|
549
|
-
* Resolves an artifact, creating it if necessary.
|
|
550
|
-
* Handles dependency tracking, caching, and error states.
|
|
551
|
-
*
|
|
552
|
-
* @param key The artifact identifier.
|
|
553
|
-
*/
|
|
554
|
-
resolve<TArtifact>(key: string): Promise<ResolvedArtifact<TArtifact>>;
|
|
555
|
-
/**
|
|
556
|
-
* Helper to wrap a definition into the standard public return type.
|
|
557
|
-
*/
|
|
558
|
-
private packageArtifact;
|
|
559
|
-
/**
|
|
560
|
-
* Executes the factory and captures dependencies.
|
|
561
|
-
* Contains the "Yield" implementation.
|
|
562
|
-
*/
|
|
563
|
-
private createArtifactInstance;
|
|
564
|
-
/**
|
|
565
|
-
* Orchestrates the invalidation and notification sequence for a yield event.
|
|
566
|
-
* Ensures downstream dependents are invalidated BEFORE listeners are notified.
|
|
567
|
-
*/
|
|
568
|
-
private processYieldPropagation;
|
|
569
|
-
/**
|
|
570
|
-
* Updates the dependency graph structure after a successful build.
|
|
571
|
-
*/
|
|
572
|
-
private updateGraph;
|
|
573
|
-
/**
|
|
574
|
-
* Cascading invalidation logic.
|
|
575
|
-
* Destroys the artifact, destroys dependents, then conditionally rebuilds.
|
|
576
|
-
*
|
|
577
|
-
* @param key The artifact key to invalidate
|
|
578
|
-
* @param replace If true, eagerly rebuild after invalidation. If false, respect lazy flag.
|
|
579
|
-
*/
|
|
580
|
-
private invalidate;
|
|
581
|
-
/**
|
|
582
|
-
* Cleans up a specific artifact definition's instance and subscriptions.
|
|
583
|
-
* Keeps the definition registered but clears the instance.
|
|
584
|
-
*/
|
|
585
|
-
private disposeInstance;
|
|
586
|
-
/**
|
|
587
|
-
* Fully removes an artifact from the system.
|
|
588
|
-
*/
|
|
589
|
-
private disposeArtifact;
|
|
590
|
-
private createCompositeCleanup;
|
|
591
|
-
private notifyListeners;
|
|
592
|
-
private detectCycles;
|
|
593
|
-
dispose(): void;
|
|
594
|
-
isLoading(key: string): boolean;
|
|
595
|
-
}
|
|
596
|
-
|
|
597
385
|
/**
|
|
598
386
|
* @fileoverview Store Observer Module
|
|
599
387
|
* @description A comprehensive module to add advanced debugging, observability, and time-travel
|
|
@@ -922,4 +710,4 @@ declare class ActionManager<T extends object> {
|
|
|
922
710
|
private emit;
|
|
923
711
|
}
|
|
924
712
|
|
|
925
|
-
export { type ActionCompletePayload, type ActionErrorPayload, ActionManager, type ActionStartPayload, type
|
|
713
|
+
export { type ActionCompletePayload, type ActionErrorPayload, ActionManager, type ActionStartPayload, 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, createDerivePaths, createDiff, createMerge, derivePaths, diff, merge, shallowClone };
|
package/index.d.ts
CHANGED
|
@@ -382,218 +382,6 @@ declare class ReactiveDataStore<T extends object> implements DataStore<T> {
|
|
|
382
382
|
private emit;
|
|
383
383
|
}
|
|
384
384
|
|
|
385
|
-
/**
|
|
386
|
-
* Defines the lifecycle scope of an artifact.
|
|
387
|
-
*/
|
|
388
|
-
declare enum ArtifactScope {
|
|
389
|
-
/**
|
|
390
|
-
* Created once and cached.
|
|
391
|
-
* The container tracks its dependencies and rebuilds it if they change.
|
|
392
|
-
*/
|
|
393
|
-
Singleton = "singleton",
|
|
394
|
-
/**
|
|
395
|
-
* Created every time it is resolved.
|
|
396
|
-
* Dependencies are NOT tracked, and it is never cached.
|
|
397
|
-
*/
|
|
398
|
-
Transient = "transient"
|
|
399
|
-
}
|
|
400
|
-
/**
|
|
401
|
-
* Dependency resolution context provided to the `use()` callback.
|
|
402
|
-
* Used to declare dependencies on other artifacts or state slices.
|
|
403
|
-
*/
|
|
404
|
-
interface UseDependencyContext<TState extends object> {
|
|
405
|
-
/**
|
|
406
|
-
* Resolve another artifact.
|
|
407
|
-
* This records a dependency: if the target artifact is invalidated, the caller will be too.
|
|
408
|
-
*
|
|
409
|
-
* @param key The key of the artifact to resolve.
|
|
410
|
-
*/
|
|
411
|
-
resolve<TArtifact>(key: string): Promise<ResolvedArtifact<TArtifact>>;
|
|
412
|
-
/**
|
|
413
|
-
* Select a slice of state.
|
|
414
|
-
* This records a dependency: if the selected state changes, the artifact will be invalidated.
|
|
415
|
-
*
|
|
416
|
-
* @param selector A function that selects a part of the global state.
|
|
417
|
-
*/
|
|
418
|
-
select<S>(selector: (state: TState) => S): S;
|
|
419
|
-
}
|
|
420
|
-
/**
|
|
421
|
-
* The context object provided to an artifact's factory function.
|
|
422
|
-
* Provides tools for state access, dependency injection, and lifecycle management.
|
|
423
|
-
*/
|
|
424
|
-
interface ArtifactFactoryContext<TState extends object> {
|
|
425
|
-
/**
|
|
426
|
-
* Get the current state snapshot immediately.
|
|
427
|
-
* **Note:** Calling this does NOT create a subscription. Use `ctx.use(c => c.select(...))` for reactive behavior.
|
|
428
|
-
*/
|
|
429
|
-
state(): TState;
|
|
430
|
-
/**
|
|
431
|
-
* The existing instance if the artifact is being re-evaluated/rebuilt.
|
|
432
|
-
* Useful for preserving internal state (like active connections) during hot-swaps.
|
|
433
|
-
*/
|
|
434
|
-
current?: unknown;
|
|
435
|
-
/**
|
|
436
|
-
* Execute a callback to capture dependencies.
|
|
437
|
-
* All `resolve()` and `select()` calls inside this callback are recorded
|
|
438
|
-
* to build the reactive dependency graph.
|
|
439
|
-
*
|
|
440
|
-
* @param callback The function where dependencies are declared.
|
|
441
|
-
*/
|
|
442
|
-
use<K>(callback: (ctx: UseDependencyContext<TState>) => K | Promise<K>): Promise<K>;
|
|
443
|
-
/**
|
|
444
|
-
* Register a cleanup function to be called when the artifact is disposed or rebuilt.
|
|
445
|
-
* Multiple cleanup functions can be registered; they will be called in reverse order (LIFO).
|
|
446
|
-
*
|
|
447
|
-
* @param cleanup A function to execute during teardown.
|
|
448
|
-
*/
|
|
449
|
-
onCleanup(cleanup: ArtifactCleanup): void;
|
|
450
|
-
/**
|
|
451
|
-
* Hot-swap the artifact instance without triggering a full teardown.
|
|
452
|
-
*
|
|
453
|
-
* **Behavior:**
|
|
454
|
-
* 1. Updates the internal instance **synchronously** (immediate consistency).
|
|
455
|
-
* 2. Invalidates downstream dependents **asynchronously** (graph consistency).
|
|
456
|
-
* 3. Notifies listeners (UI updates) only after the graph is consistent.
|
|
457
|
-
*
|
|
458
|
-
* @param value The new instance value to set.
|
|
459
|
-
*
|
|
460
|
-
* @example
|
|
461
|
-
* // Updating a WebSocket connection without losing the wrapping artifact
|
|
462
|
-
* factory: async (ctx) => {
|
|
463
|
-
* const ws = new WebSocket(url);
|
|
464
|
-
* ws.onmessage = (msg) => ctx.yield(JSON.parse(msg.data));
|
|
465
|
-
* return ws; // Initial value
|
|
466
|
-
* }
|
|
467
|
-
*/
|
|
468
|
-
yield(value: unknown): void;
|
|
469
|
-
}
|
|
470
|
-
/**
|
|
471
|
-
* A function to clean up resources (close sockets, remove listeners, etc.).
|
|
472
|
-
*/
|
|
473
|
-
type ArtifactCleanup = () => void | Promise<void>;
|
|
474
|
-
/**
|
|
475
|
-
* The result of resolving an artifact.
|
|
476
|
-
* Wraps the instance with metadata, error state, and control methods.
|
|
477
|
-
*/
|
|
478
|
-
interface ResolvedArtifact<TArtifact> {
|
|
479
|
-
/** The resolved artifact instance. */
|
|
480
|
-
instance: TArtifact;
|
|
481
|
-
/** A function that runs all registered cleanups for this artifact. */
|
|
482
|
-
cleanup?: ArtifactCleanup;
|
|
483
|
-
/** Any error that occurred during creation. */
|
|
484
|
-
error?: any;
|
|
485
|
-
/**
|
|
486
|
-
* Manually invalidate this artifact.
|
|
487
|
-
* @param replace If `true`, forces an immediate rebuild (Eager). If `false`, marks as stale (Lazy).
|
|
488
|
-
*/
|
|
489
|
-
invalidate(replace?: boolean): Promise<void>;
|
|
490
|
-
}
|
|
491
|
-
/**
|
|
492
|
-
* A factory function that creates an instance of an artifact.
|
|
493
|
-
*/
|
|
494
|
-
type ArtifactFactory<TState extends object, TArtifact> = (context: ArtifactFactoryContext<TState>) => TArtifact | Promise<TArtifact>;
|
|
495
|
-
/**
|
|
496
|
-
* A reactive dependency injection container.
|
|
497
|
-
* Manages the lifecycle, caching, and dependency graph of application artifacts.
|
|
498
|
-
*/
|
|
499
|
-
declare class ArtifactContainer<TState extends object> {
|
|
500
|
-
private readonly artifacts;
|
|
501
|
-
private readonly resolvingStack;
|
|
502
|
-
private readonly listeners;
|
|
503
|
-
private readonly getState;
|
|
504
|
-
private readonly subscribe;
|
|
505
|
-
/**
|
|
506
|
-
* @param props Interface to the external state store (e.g., Zustand, Redux).
|
|
507
|
-
*/
|
|
508
|
-
constructor(props: Pick<DataStore<TState>, "watch" | "get">);
|
|
509
|
-
/**
|
|
510
|
-
* Watch an artifact for changes and retrieve its current state.
|
|
511
|
-
*
|
|
512
|
-
* @param id The artifact key to watch.
|
|
513
|
-
* @returns An object containing the ID, a getter, and a subscribe method.
|
|
514
|
-
*
|
|
515
|
-
* @example
|
|
516
|
-
* const watcher = container.watch("current-user");
|
|
517
|
-
* const unsub = watcher.subscribe(() => {
|
|
518
|
-
* const user = watcher.get()?.instance;
|
|
519
|
-
* console.log("User updated:", user);
|
|
520
|
-
* });
|
|
521
|
-
*/
|
|
522
|
-
watch<TArtifact>(id: string): {
|
|
523
|
-
id: string;
|
|
524
|
-
get(): ResolvedArtifact<TArtifact> | null;
|
|
525
|
-
subscribe(callback: () => void): () => void;
|
|
526
|
-
};
|
|
527
|
-
/**
|
|
528
|
-
* Direct sync access to an artifact instance.
|
|
529
|
-
* Use this sparingly; prefer `resolve()` or `watch()`.
|
|
530
|
-
*/
|
|
531
|
-
get(id: string): any | undefined;
|
|
532
|
-
/**
|
|
533
|
-
* Registers a new artifact factory.
|
|
534
|
-
*
|
|
535
|
-
* @param options Configuration for the artifact.
|
|
536
|
-
* @returns A function to unregister the artifact.
|
|
537
|
-
*/
|
|
538
|
-
register<TArtifact>(options: {
|
|
539
|
-
key: string;
|
|
540
|
-
factory: ArtifactFactory<TState, TArtifact>;
|
|
541
|
-
scope?: ArtifactScope;
|
|
542
|
-
lazy?: boolean;
|
|
543
|
-
}): () => void;
|
|
544
|
-
/**
|
|
545
|
-
* Unregisters an artifact and cleans up its resources.
|
|
546
|
-
*/
|
|
547
|
-
unregister(key: string): Promise<void>;
|
|
548
|
-
/**
|
|
549
|
-
* Resolves an artifact, creating it if necessary.
|
|
550
|
-
* Handles dependency tracking, caching, and error states.
|
|
551
|
-
*
|
|
552
|
-
* @param key The artifact identifier.
|
|
553
|
-
*/
|
|
554
|
-
resolve<TArtifact>(key: string): Promise<ResolvedArtifact<TArtifact>>;
|
|
555
|
-
/**
|
|
556
|
-
* Helper to wrap a definition into the standard public return type.
|
|
557
|
-
*/
|
|
558
|
-
private packageArtifact;
|
|
559
|
-
/**
|
|
560
|
-
* Executes the factory and captures dependencies.
|
|
561
|
-
* Contains the "Yield" implementation.
|
|
562
|
-
*/
|
|
563
|
-
private createArtifactInstance;
|
|
564
|
-
/**
|
|
565
|
-
* Orchestrates the invalidation and notification sequence for a yield event.
|
|
566
|
-
* Ensures downstream dependents are invalidated BEFORE listeners are notified.
|
|
567
|
-
*/
|
|
568
|
-
private processYieldPropagation;
|
|
569
|
-
/**
|
|
570
|
-
* Updates the dependency graph structure after a successful build.
|
|
571
|
-
*/
|
|
572
|
-
private updateGraph;
|
|
573
|
-
/**
|
|
574
|
-
* Cascading invalidation logic.
|
|
575
|
-
* Destroys the artifact, destroys dependents, then conditionally rebuilds.
|
|
576
|
-
*
|
|
577
|
-
* @param key The artifact key to invalidate
|
|
578
|
-
* @param replace If true, eagerly rebuild after invalidation. If false, respect lazy flag.
|
|
579
|
-
*/
|
|
580
|
-
private invalidate;
|
|
581
|
-
/**
|
|
582
|
-
* Cleans up a specific artifact definition's instance and subscriptions.
|
|
583
|
-
* Keeps the definition registered but clears the instance.
|
|
584
|
-
*/
|
|
585
|
-
private disposeInstance;
|
|
586
|
-
/**
|
|
587
|
-
* Fully removes an artifact from the system.
|
|
588
|
-
*/
|
|
589
|
-
private disposeArtifact;
|
|
590
|
-
private createCompositeCleanup;
|
|
591
|
-
private notifyListeners;
|
|
592
|
-
private detectCycles;
|
|
593
|
-
dispose(): void;
|
|
594
|
-
isLoading(key: string): boolean;
|
|
595
|
-
}
|
|
596
|
-
|
|
597
385
|
/**
|
|
598
386
|
* @fileoverview Store Observer Module
|
|
599
387
|
* @description A comprehensive module to add advanced debugging, observability, and time-travel
|
|
@@ -922,4 +710,4 @@ declare class ActionManager<T extends object> {
|
|
|
922
710
|
private emit;
|
|
923
711
|
}
|
|
924
712
|
|
|
925
|
-
export { type ActionCompletePayload, type ActionErrorPayload, ActionManager, type ActionStartPayload, type
|
|
713
|
+
export { type ActionCompletePayload, type ActionErrorPayload, ActionManager, type ActionStartPayload, 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, createDerivePaths, createDiff, createMerge, derivePaths, diff, merge, shallowClone };
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e,t,s=require("uuid"),i=Object.create,r=Object.defineProperty,a=Object.getOwnPropertyDescriptor,n=Object.getOwnPropertyNames,o=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,l=(e,t,s)=>(s=null!=e?i(o(e)):{},((e,t,s,i)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let o of n(t))c.call(e,o)||o===s||r(e,o,{get:()=>t[o],enumerable:!(i=a(t,o))||i.enumerable});return e})(e&&e.__esModule?s:r(s,"default",{value:e,enumerable:!0}),e)),d=(e={"src/store/node_modules/@asaidimu/events/index.js"(e,t){var s,i=Object.defineProperty,r=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,n=Object.prototype.hasOwnProperty,o={};((e,t)=>{for(var s in t)i(e,s,{get:t[s],enumerable:!0})})(o,{createEventBus:()=>c}),t.exports=(s=o,((e,t,s,o)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of a(t))n.call(e,c)||c===s||i(e,c,{get:()=>t[c],enumerable:!(o=r(t,c))||o.enumerable});return e})(i({},"__esModule",{value:!0}),s));var c=(e={async:!1,batchSize:1e3,batchDelay:16,errorHandler:e=>console.error("EventBus Error:",e),crossTab:!1,channelName:"event-bus-channel"})=>{const t=new Map;let s=[],i=0,r=0;const a=new Map,n=new Map;let o=null;e.crossTab&&"undefined"!=typeof BroadcastChannel?o=new BroadcastChannel(e.channelName):e.crossTab&&console.warn("BroadcastChannel is not supported in this browser. Cross-tab notifications are disabled.");const c=(e,t)=>{i++,r+=t,a.set(e,(a.get(e)||0)+1)},l=()=>{const t=s;s=[],t.forEach((({name:t,payload:s})=>{const i=performance.now();try{(n.get(t)||[]).forEach((e=>e(s)))}catch(i){e.errorHandler({...i,eventName:t,payload:s})}c(t,performance.now()-i)}))},d=(()=>{let t;return()=>{clearTimeout(t),t=setTimeout(l,e.batchDelay)}})(),h=e=>{const s=t.get(e);s?n.set(e,Array.from(s)):n.delete(e)};return o&&(o.onmessage=e=>{const{name:t,payload:s}=e.data;(n.get(t)||[]).forEach((e=>e(s)))}),{subscribe:(e,s)=>{t.has(e)||t.set(e,new Set);const i=t.get(e);return i.add(s),h(e),()=>{i.delete(s),0===i.size?(t.delete(e),n.delete(e)):h(e)}},emit:({name:t,payload:i})=>{if(e.async)return s.push({name:t,payload:i}),s.length>=e.batchSize?l():d(),void(o&&o.postMessage({name:t,payload:i}));const r=performance.now();try{(n.get(t)||[]).forEach((e=>e(i))),o&&o.postMessage({name:t,payload:i})}catch(s){e.errorHandler({...s,eventName:t,payload:i})}c(t,performance.now()-r)},getMetrics:()=>({totalEvents:i,activeSubscriptions:Array.from(t.values()).reduce(((e,t)=>e+t.size),0),eventCounts:a,averageEmitDuration:i>0?r/i:0}),clear:()=>{t.clear(),n.clear(),s=[],i=0,r=0,a.clear(),o&&(o.close(),o=null)}}}}},function(){return t||(0,e[n(e)[0]])((t={exports:{}}).exports,t),t.exports}),h=l(d()),u=Symbol.for("delete"),p=e=>Array.isArray(e)?[...e]:{...e};function m(e){const t=e?.deleteMarker||u;return function(e,s){if("object"!=typeof e||null===e)return"object"==typeof s&&null!==s?a(s):s===t?{}:s;if("object"!=typeof s||null===s)return e;const i=p(e),r=[{target:i,source:s}];for(;r.length>0;){const{target:e,source:s}=r.pop();for(const i of Object.keys(s)){if(!Object.prototype.hasOwnProperty.call(s,i))continue;const n=s[i];if(n!==t)if(Array.isArray(n))e[i]=n.map((e=>"object"!=typeof e||null===e||Array.isArray(e)?e===t?void 0:e:a(e)));else if("object"==typeof n&&null!==n){const t=i in e&&"object"==typeof e[i]&&null!==e[i]?e[i]:{};e[i]=p(t),r.push({target:e[i],source:n})}else e[i]=n;else delete e[i]}}return i;function a(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===t?void 0:e:a(e)));if("object"==typeof e){const s={};for(const[i,r]of Object.entries(e))if(r!==t)if("object"==typeof r&&null!==r){const e=a(r);void 0!==e&&(s[i]=e)}else s[i]=r;return s}return e===t?void 0:e}}}var f=m();l(d());var g=class{reactiveSelectors=new Map;reactiveSelectorCache=new WeakMap;pathBasedCache=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=e.deltas.map((e=>e.path));this.reEvaluateReactiveSelectors(t)};reEvaluateReactiveSelectors=e=>{this.reactiveSelectors.forEach((t=>{if(t.accessedPaths.some((t=>e.some((e=>e.startsWith(t)||t.startsWith(e)))))){let e;try{e=t.selector(this.getState())}catch{e=void 0}e!==t.lastResult&&(t.lastResult=e,t.subscribers.forEach((e=>e(t.lastResult))),this.eventBus.emit({name:"selector:changed",payload:{selectorId:t.id,newResult:e,timestamp:performance.now()}}))}}))};createReactiveSelector(e){const t=this.reactiveSelectorCache.get(e);if(t)return t;const s=y(e);this.validateSimpleSelector(e,s);const i=s.sort().join("|"),r=this.pathBasedCache.get(i);if(r)return this.reactiveSelectorCache.set(e,r),r;const a=`selector-${Math.random().toString(36).substring(2,9)}`,n=e(this.getState()),o={id:a,selector:e,lastResult:n,accessedPaths:s,subscribers:new Set,reactiveSelectorInstance:null},c={get:()=>o.lastResult,subscribe:t=>(o.subscribers.add(t),()=>{o.subscribers.delete(t),queueMicrotask((()=>{0===o.subscribers.size&&(this.reactiveSelectors.delete(a),this.reactiveSelectorCache.delete(e),this.pathBasedCache.delete(i))}))}),id:a};return o.reactiveSelectorInstance=c,this.reactiveSelectors.set(a,o),this.reactiveSelectorCache.set(e,c),this.pathBasedCache.set(i,c),this.eventBus.emit({name:"selector:accessed",payload:{selectorId:a,accessedPaths:s,duration:0,timestamp:performance.now()}}),c}validateSimpleSelector(e,t){const s=e.toString(),i=s.match(/=>\s*(.+)$/),r=i?i[1].trim():s,a=["map","filter","reduce","forEach","find","findIndex","some","every","includes","flatMap","flat","slice","splice"];for(const e of a)if(new RegExp(`\\.${e}\\s*\\(`).test(r))throw new Error(`Selector contains .${e}() which is not allowed. Selectors must be simple property accessors only. Use store effects for transformations.`);if(/\?[^:]*:/.test(r))throw new Error("Selector contains ternary operator (? :) which is not allowed. Selectors must be simple property accessors only. Use store effects for conditional transformations.");if(/\bif\s*\(|\bswitch\s*\(/.test(r))throw new Error("Selector contains conditional logic (if/switch) which is not allowed. Selectors must be simple property accessors only. Use store effects for conditional transformations.");if(/(?<![.\w])[a-zA-Z_$][a-zA-Z0-9_$]*\s*\(/.test(r))throw new Error("Selector contains function calls which are not allowed. Selectors must be simple property accessors only.");const n=/[+\-*/%&|^](?!=)|[<>!]=?(?!=)/.test(r),o=/\[.*\]/.test(r);if(n&&!o)throw new Error("Selector contains operations (+, -, *, /, etc.) which are not allowed. Selectors must be simple property accessors only. Use store effects for computed values.");if(0===t.length)throw new Error("Selector doesn't access any state properties. Selectors must access at least one state property.")}dispose(){this.unsubscribeFromStore(),this.reactiveSelectors.clear(),this.pathBasedCache.clear()}createMemoizedSelector(e){const t=y(e);this.validateSimpleSelector(e,t);let s,i=null;return r=>{const a=this.extractStateSubset(r,t);return i===a||(i=a,s=e(r)),s}}extractStateSubset(e,t){const s=[];for(const i of t){const t=i.split(".");let r=e;for(const e of t){if(null==r){s.push(void 0);break}r=r[e]}s.push(r)}return s}};function y(e,t="."){const s=new Set,i=(e=[])=>new Proxy({},{get:(r,a)=>{if("symbol"==typeof a)return;const n=[...e,a],o=n.join(t);return s.add(o),i(n)}});try{e(i())}catch(e){throw new Error(`Selector failed during path analysis. This usually means the selector is too complex. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}const r=Array.from(s);return r.filter((e=>!r.some((s=>s!==e&&s.startsWith(e+t)))))}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,a]=[Object.keys(e),Object.keys(t)];if(s=r.length,s!==a.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 v(e){const t=e?.deleteMarker||u;return function(e,s){const i=[],r=[{pathArray:[],pathStr:"",orig:e||{},part:s||{}}];for(;r.length>0;){const{pathArray:e,pathStr:s,orig:a,part:n}=r.pop();if(null!=n&&!w(a,n))if("object"!=typeof n||Array.isArray(n))s&&i.push({path:s,oldValue:a,newValue:n});else for(const o of Object.keys(n)){const c=[...e,o],l=s?s+"."+o:o,d=n[o],h=a&&"object"==typeof a?a[o]:void 0;d!==t?"object"==typeof d&&null!==d?r.push({pathArray:c,pathStr:l,orig:h,part:d}):w(h,d)||i.push({path:l,oldValue:h,newValue:d}):void 0===h&&a&&"object"==typeof a||i.push({path:l,oldValue:h,newValue:void 0})}}return i}}function b(e){const t=e?.deleteMarker||u;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 a of Object.keys(e)){const n=r?`${r}.${a}`:a;s.add(n);const o=n.split(".");if(o.length>1)for(let e=o.length-1;e>0;e--){const t=o.slice(0,e).join(".");if(s.has(t))break;s.add(t)}const c=e[a];"object"==typeof c&&null!==c&&c!==t&&i.push({obj:c,currentPath:n})}}return Array.from(s)}}var S=v(),E=b(),x=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),a=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];a.set(t.path,t)}}const n=a.size?[...a.values()]:[];if(n.length>0){this.cache=s?structuredClone(e):e;const t=new Set;for(let e=0;e<n.length;e++){let s=n[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 n}notifyListeners(e){for(const t of e)this.updateBus.emit({name:"update",payload:t})}};l(d());var 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 a={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 n=await Promise.resolve(s(e,t));if(a.endTime=performance.now(),a.duration=a.endTime-a.startTime,!1===n)return a.blocked=!0,this.emitMiddlewareLifecycle("blocked",{id:r,name:i,duration:a.duration}),this.emit(this.eventBus,{name:"middleware:executed",payload:a}),{blocked:!0};this.emitMiddlewareLifecycle("complete",{id:r,name:i,type:"blocking",duration:a.duration}),this.emit(this.eventBus,{name:"middleware:executed",payload:{...a,blocked:!1}})}catch(e){return a.endTime=performance.now(),a.duration=a.endTime-a.startTime,a.error=e instanceof Error?e:new Error(String(e)),a.blocked=!0,this.emitMiddlewareError(r,i,a.error,a.duration),this.emit(this.eventBus,{name:"middleware:executed",payload:a}),{blocked:!0,error:a.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:a}of this.middleware){const n={id:a,name:r,startTime:performance.now()};this.executionState.runningMiddleware={id:a,name:r,startTime:performance.now()},this.emitMiddlewareLifecycle("start",{id:a,name:r,type:"transform"});try{const o=await Promise.resolve(e(s,t));n.endTime=performance.now(),n.duration=n.endTime-n.startTime,n.blocked=!1,o&&"object"==typeof o&&(s=this.merge(s,o),i=this.merge(i,o)),this.emit(this.eventBus,{name:"middleware:executed",payload:n}),this.emitMiddlewareLifecycle("complete",{id:a,name:r,type:"transform",duration:n.duration})}catch(e){n.endTime=performance.now(),n.duration=n.endTime-n.startTime,n.error=e instanceof Error?e:new Error(String(e)),n.blocked=!1,this.emit(this.eventBus,{name:"middleware:executed",payload:n}),this.emitMiddlewareError(a,r,n.error,n.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)}))}};l(d());var 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;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).substr(2,9)}`,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,oldestTask:this.backgroundQueue[0]?.timestamp}}async flush(){this.isProcessingQueue||await this.processQueue()}clearQueue(){const e=this.backgroundQueue.length;this.backgroundQueue=[],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()}}),setTimeout((()=>{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.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.clearQueue(),this.isProcessingQueue=!1,this.persistenceReady=!1}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}};l(d());var C=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)}))}};l(d());var A=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()}};l(d());var P=class extends Error{constructor(){super("Action Cancelled by Debounce"),this.name="ActionCancelledError"}},M=class{constructor(e,t){this.eventBus=e,this.set=t}actions=new Map;register(e){const t=e.debounce,i={name:e.name,id:s.v4(),action:e.fn,debounce:t?{...t,condition:t.condition||(()=>!0)}:void 0};return this.actions.set(e.name,i),()=>{const t=this.actions.get(e.name);t?.debounce?.timer&&clearTimeout(t.debounce.timer),this.actions.delete(e.name)}}async dispatch(e,...t){const s=this.actions.get(e);if(!s)throw new Error(`unknown action ${e}`);const{id:i,action:r,debounce:a}=s;return!a||void 0===a.delay||a.delay<=0||a.condition&&!a.condition(a.args,t)?this.executeAction(e,i,r,t):(a.timer&&(clearTimeout(a.timer),a.reject?.(new P)),new Promise(((s,n)=>{a.resolve=s,a.reject=n,a.timer=setTimeout((async()=>{a.timer=void 0,a.resolve=void 0,a.reject=void 0;try{const a=await this.executeAction(e,i,r,t);s(a)}catch(e){n(e)}}),a.delay)})))}async executeAction(e,t,s,i){const r=performance.now();this.emit(this.eventBus,{name:"action:start",payload:{actionId:t,name:e,params:i||[],timestamp:r}});try{const a=await this.set((e=>s(e,...i)),{actionId:t}),n=this.actions.get(e);n?.debounce&&(n.debounce.args=i);const o=performance.now();return this.emit(this.eventBus,{name:"action:complete",payload:{actionId:t,name:e,params:i,startTime:r,endTime:o,duration:o-r,result:a}}),a}catch(s){const a=performance.now();throw this.emit(this.eventBus,{name:"action:error",payload:{actionId:t,name:e,params:i,startTime:r,endTime:a,duration:a-r,error:s}}),s}}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},B=(e=>(e.Singleton="singleton",e.Transient="transient",e))(B||{});exports.ActionManager=M,exports.ArtifactContainer=class{artifacts=new Map;resolvingStack=[];listeners=new Map;getState;subscribe;constructor(e){this.getState=(...t)=>e.get(...t),this.subscribe=(...t)=>e.watch(...t)}watch(e){return{id:e,get:()=>{const t=this.artifacts.get(e);return t&&(void 0!==t.instance||t.error)?this.packageArtifact(t):null},subscribe:t=>{this.listeners.has(e)||this.listeners.set(e,new Set);const s=this.listeners.get(e);return s.add(t),()=>s.delete(t)}}}get(e){return this.artifacts.get(e)?.instance}register(e){const{key:t,factory:s,scope:i="singleton",lazy:r=!0}=e;this.artifacts.has(t)&&(console.warn(`[ArtifactContainer] Warning: Overwriting existing artifact "${t}".`),this.disposeArtifact(t));const a={key:t,factory:s,scope:i,lazy:r,cleanupFunctions:[],stateDependencies:new Set,artifactDependencies:new Set,dependents:new Set};return this.artifacts.set(t,a),r||"singleton"!==i||this.resolve(t).catch((e=>{console.error(`[ArtifactContainer] Eager load failed for "${t}":`,e)})),async()=>{await this.unregister(t)}}async unregister(e){this.artifacts.has(e)&&(await this.disposeArtifact(e),this.artifacts.delete(e))}async resolve(e){if(this.resolvingStack.includes(e))throw new Error(`[ArtifactContainer] Circular dependency: ${this.resolvingStack.join(" -> ")} -> ${e}`);this.resolvingStack.push(e);try{const t=this.artifacts.get(e);if(!t)throw new Error(`[ArtifactContainer] Artifact with key "${e}" not found.`);if("transient"===t.scope){const e=await this.createArtifactInstance(t,new Set,new Set);return{instance:e.instance,cleanup:e.cleanup,error:e.error,invalidate:async()=>{}}}if(void 0!==t.instance||void 0!==t.error)return this.packageArtifact(t);if(t.initializationPromise)try{return await t.initializationPromise,this.packageArtifact(t)}catch(e){return this.packageArtifact(t)}const s=(async()=>{try{const e=new Set,s=new Set,i=await this.createArtifactInstance(t,e,s);return this.updateGraph(t,e,s),i.error&&(t.error=i.error),i.instance}catch(e){throw t.error=e,t.initializationPromise=void 0,e}})();t.initializationPromise=s;try{await s}catch(e){}return this.packageArtifact(t)}finally{this.resolvingStack.pop()}}packageArtifact(e){return{instance:e.instance,cleanup:this.createCompositeCleanup(e.cleanupFunctions),error:e.error,invalidate:async t=>this.invalidate(e.key,t)}}async createArtifactInstance(e,t,s){const i=[];let r=!0;i.push((()=>{r=!1}));const a={state:this.getState,current:e.instance,use:async i=>i({resolve:async s=>{if(s===e.key)throw new Error(`[ArtifactContainer] Self-dependency detected in "${e.key}"`);return t.add(s),this.resolve(s)},select:e=>(y(e).forEach((e=>s.add(e))),e(this.getState()))}),onCleanup:e=>{i.push(e)},yield:t=>{r?"transient"!==e.scope?(e.instance=t,e.error=void 0,this.processYieldPropagation(e.key)):console.warn(`[ArtifactContainer] Yield ignored on transient artifact "${e.key}"`):console.warn(`[ArtifactContainer] Ignored yield on disposed artifact "${e.key}"`)}};let n,o;try{n=await e.factory(a)}catch(e){o=e,n=void 0}"singleton"===e.scope&&(void 0!==n&&(e.instance=n),e.cleanupFunctions=i);return{instance:"singleton"===e.scope?e.instance:n,cleanup:this.createCompositeCleanup(i),error:o}}async processYieldPropagation(e){const t=this.artifacts.get(e);if(t&&(void 0!==t.instance||t.error))try{const s=Array.from(t.dependents);await Promise.all(s.map((e=>this.invalidate(e,!1)))),this.notifyListeners(e)}catch(t){console.error(`[ArtifactContainer] Yield propagation failed for "${e}":`,t)}}updateGraph(e,t,s){e.artifactDependencies.forEach((t=>{const s=this.artifacts.get(t);s&&s.dependents.delete(e.key)})),e.artifactDependencies=t,t.forEach((t=>{const s=this.artifacts.get(t);s&&s.dependents.add(e.key)}));const i=e.stateSubscriptionCleanup;e.stateDependencies=s,s.size>0?e.stateSubscriptionCleanup=this.subscribe(Array.from(s),(()=>this.invalidate(e.key))):e.stateSubscriptionCleanup=void 0,i&&i(),this.detectCycles(e.key),this.notifyListeners(e.key)}async invalidate(e,t=!1){const s=this.artifacts.get(e);if(!s)return;if(s.initializationPromise)try{await s.initializationPromise}catch(e){}if(s.rebuildPromise)return s.rebuildPromise;const i=(async()=>{try{const i=Array.from(s.dependents);await Promise.all(i.map((e=>this.invalidate(e,t)))),await this.disposeInstance(s),!t&&s.lazy||await this.resolve(e).catch((t=>{console.error(`[ArtifactContainer] Rebuild failed for "${e}":`,t)}))}finally{s.rebuildPromise=void 0}})();return s.rebuildPromise=i,i}async disposeInstance(e){if(e.stateSubscriptionCleanup&&(e.stateSubscriptionCleanup(),e.stateSubscriptionCleanup=void 0),e.cleanupFunctions.length>0)for(let t=e.cleanupFunctions.length-1;t>=0;t--)try{await e.cleanupFunctions[t]()}catch(t){console.error(`[ArtifactContainer] Cleanup error for "${e.key}":`,t)}e.instance=void 0,e.error=void 0,e.cleanupFunctions=[],e.initializationPromise=void 0,this.notifyListeners(e.key)}async disposeArtifact(e){const t=this.artifacts.get(e);t&&(t.rebuildPromise&&await t.rebuildPromise,await this.disposeInstance(t),t.artifactDependencies.forEach((t=>{const s=this.artifacts.get(t);s&&s.dependents.delete(e)})))}createCompositeCleanup(e){if(0!==e.length)return async()=>{for(let t=e.length-1;t>=0;t--)try{await e[t]()}catch(e){}}}notifyListeners(e){const t=this.listeners.get(e);t&&t.forEach((e=>e()))}detectCycles(e){const t=new Set,s=new Set,i=e=>{if(s.has(e))throw new Error(`[ArtifactContainer] Circular dependency: ${Array.from(s).join(" -> ")} -> ${e}`);if(t.has(e))return;t.add(e),s.add(e);const r=this.artifacts.get(e);r&&r.artifactDependencies.forEach((e=>i(e))),s.delete(e)};i(e)}dispose(){this.artifacts.forEach(((e,t)=>this.disposeArtifact(t))),this.artifacts.clear()}isLoading(e){return this.resolvingStack.includes(e)||void 0!==this.artifacts.get(e)?.initializationPromise}},exports.ArtifactScope=B,exports.DELETE_SYMBOL=u,exports.ReactiveDataStore=class{coreState;middlewareEngine;persistenceHandler;transactionManager;metricsCollector;selectorManager;actionManager;updateQueue=Promise.resolve();updateBus=(0,h.createEventBus)();eventBus=(0,h.createEventBus)();executionState;instanceID=s.v4();merge;diff;constructor(e,t,s=u,i){this.executionState={executing:!1,changes:null,pendingChanges:[],middlewares:[],runningMiddleware:null,transactionActive:!1},this.merge=m({deleteMarker:s}),this.diff=v({deleteMarker:s}),this.coreState=new x(e,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:i?.persistenceMaxRetries,retryDelay:i?.persistenceRetryDelay}),this.transactionManager=new C(this.eventBus,this.coreState,this.executionState),this.metricsCollector=new A(this.eventBus),this.actionManager=new M(this.eventBus,this.set.bind(this)),this.persistenceHandler.initialize(t),this.setupPersistenceListener(),this.selectorManager=new g(this.get.bind(this),this.eventBus)}isReady(){return this.persistenceHandler.isReady()}state(){return this.executionState}get(e){return this.coreState.get(e??!1)}select(e){return this.selectorManager.createReactiveSelector(e)}register(e){return this.actionManager.register(e)}async dispatch(e,...t){return this.actionManager.dispatch(e,...t)}async set(e,t={}){const s=this.updateQueue.then((()=>this._performUpdate(e,t)));return this.updateQueue=s.catch((()=>{})),s}async _performUpdate(e,t){this.executionState.executing=!0;const s=performance.now();this.emit(this.eventBus,{name:"update:start",payload:{timestamp:s,actionId:t.actionId}});try{if(t.force){const t=this.get(!1),s="function"==typeof e?e(t):e;return this.coreState.applyChanges(s,!0),s}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 a=await this.middlewareEngine.executeBlocking(r,i);if(a.blocked)throw a.error||new Error("Update blocked by middleware");const n=this.merge(r,i),o=await this.middlewareEngine.executeTransform(n,i),c=this.merge(n,o),l=this.coreState.applyChanges(c,!1,!1,[i,o]),d=performance.now(),h=this.get(!1);return this.emit(this.eventBus,{name:"update:complete",payload:{deltas:l,duration:d-s,timestamp:Date.now(),actionId:t.actionId,newState:h}}),h}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=[]}}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++)}))}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()}clearPersistenceQueue(){this.persistenceHandler.clearQueue()}dispose(){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.onStoreEvent(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={},a=(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(".");a(i,t,e.oldValue),a(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.onStoreEvent("update:complete",(s=>{this.isTimeTraveling||s.blocked||(t=[],e=0)}));this.unsubscribers.push(s);const i=()=>this.stateHistory.length,r=()=>e<i()-1,a=()=>t.length>0;return{canUndo:r,canRedo:a,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(!a())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.createDerivePaths=b,exports.createDiff=v,exports.createMerge=m,exports.derivePaths=E,exports.diff=S,exports.merge=f,exports.shallowClone=p;
|
|
1
|
+
"use strict";var e,t,s=require("uuid"),r=Object.create,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,n=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,l=(e,t,s)=>(s=null!=e?r(n(e)):{},((e,t,s,r)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let n of o(t))c.call(e,n)||n===s||i(e,n,{get:()=>t[n],enumerable:!(r=a(t,n))||r.enumerable});return e})(e&&e.__esModule?s:i(s,"default",{value:e,enumerable:!0}),e)),d=(e={"src/store/node_modules/@asaidimu/events/index.js"(e,t){var s,r=Object.defineProperty,i=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,o=Object.prototype.hasOwnProperty,n={};((e,t)=>{for(var s in t)r(e,s,{get:t[s],enumerable:!0})})(n,{createEventBus:()=>c}),t.exports=(s=n,((e,t,s,n)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of a(t))o.call(e,c)||c===s||r(e,c,{get:()=>t[c],enumerable:!(n=i(t,c))||n.enumerable});return e})(r({},"__esModule",{value:!0}),s));var c=(e={async:!1,batchSize:1e3,batchDelay:16,errorHandler:e=>console.error("EventBus Error:",e),crossTab:!1,channelName:"event-bus-channel"})=>{const t=new Map;let s=[],r=0,i=0;const a=new Map,o=new Map;let n=null;e.crossTab&&"undefined"!=typeof BroadcastChannel?n=new BroadcastChannel(e.channelName):e.crossTab&&console.warn("BroadcastChannel is not supported in this browser. Cross-tab notifications are disabled.");const c=(e,t)=>{r++,i+=t,a.set(e,(a.get(e)||0)+1)},l=()=>{const t=s;s=[],t.forEach((({name:t,payload:s})=>{const r=performance.now();try{(o.get(t)||[]).forEach((e=>e(s)))}catch(r){e.errorHandler({...r,eventName:t,payload:s})}c(t,performance.now()-r)}))},d=(()=>{let t;return()=>{clearTimeout(t),t=setTimeout(l,e.batchDelay)}})(),h=e=>{const s=t.get(e);s?o.set(e,Array.from(s)):o.delete(e)};return n&&(n.onmessage=e=>{const{name:t,payload:s}=e.data;(o.get(t)||[]).forEach((e=>e(s)))}),{subscribe:(e,s)=>{t.has(e)||t.set(e,new Set);const r=t.get(e);return r.add(s),h(e),()=>{r.delete(s),0===r.size?(t.delete(e),o.delete(e)):h(e)}},emit:({name:t,payload:r})=>{if(e.async)return s.push({name:t,payload:r}),s.length>=e.batchSize?l():d(),void(n&&n.postMessage({name:t,payload:r}));const i=performance.now();try{(o.get(t)||[]).forEach((e=>e(r))),n&&n.postMessage({name:t,payload:r})}catch(s){e.errorHandler({...s,eventName:t,payload:r})}c(t,performance.now()-i)},getMetrics:()=>({totalEvents:r,activeSubscriptions:Array.from(t.values()).reduce(((e,t)=>e+t.size),0),eventCounts:a,averageEmitDuration:r>0?i/r:0}),clear:()=>{t.clear(),o.clear(),s=[],r=0,i=0,a.clear(),n&&(n.close(),n=null)}}}}},function(){return t||(0,e[o(e)[0]])((t={exports:{}}).exports,t),t.exports}),h=l(d()),u=Symbol.for("delete"),p=e=>Array.isArray(e)?[...e]:{...e};function m(e){const t=e?.deleteMarker||u;return function(e,s){if("object"!=typeof e||null===e)return"object"==typeof s&&null!==s?a(s):s===t?{}:s;if("object"!=typeof s||null===s)return e;const r=p(e),i=[{target:r,source:s}];for(;i.length>0;){const{target:e,source:s}=i.pop();for(const r of Object.keys(s)){if(!Object.prototype.hasOwnProperty.call(s,r))continue;const o=s[r];if(o!==t)if(Array.isArray(o))e[r]=o.map((e=>"object"!=typeof e||null===e||Array.isArray(e)?e===t?void 0:e:a(e)));else if("object"==typeof o&&null!==o){const t=r in e&&"object"==typeof e[r]&&null!==e[r]?e[r]:{};e[r]=p(t),i.push({target:e[r],source:o})}else e[r]=o;else delete e[r]}}return r;function a(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===t?void 0:e:a(e)));if("object"==typeof e){const s={};for(const[r,i]of Object.entries(e))if(i!==t)if("object"==typeof i&&null!==i){const e=a(i);void 0!==e&&(s[r]=e)}else s[r]=i;return s}return e===t?void 0:e}}}var g=m();l(d());var f=class{reactiveSelectors=new Map;reactiveSelectorCache=new WeakMap;pathBasedCache=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=e.deltas.map((e=>e.path));this.reEvaluateReactiveSelectors(t)};reEvaluateReactiveSelectors=e=>{this.reactiveSelectors.forEach((t=>{if(t.accessedPaths.some((t=>e.some((e=>e.startsWith(t)||t.startsWith(e)))))){let e;try{e=t.selector(this.getState())}catch{e=void 0}e!==t.lastResult&&(t.lastResult=e,t.subscribers.forEach((e=>e(t.lastResult))),this.eventBus.emit({name:"selector:changed",payload:{selectorId:t.id,newResult:e,timestamp:performance.now()}}))}}))};createReactiveSelector(e){const t=this.reactiveSelectorCache.get(e);if(t)return t;const s=y(e);this.validateSimpleSelector(e,s);const r=s.sort().join("|"),i=this.pathBasedCache.get(r);if(i)return this.reactiveSelectorCache.set(e,i),i;const a=`selector-${Math.random().toString(36).substring(2,9)}`,o=e(this.getState()),n={id:a,selector:e,lastResult:o,accessedPaths:s,subscribers:new Set,reactiveSelectorInstance:null},c={get:()=>n.lastResult,subscribe:t=>(n.subscribers.add(t),()=>{n.subscribers.delete(t),queueMicrotask((()=>{0===n.subscribers.size&&(this.reactiveSelectors.delete(a),this.reactiveSelectorCache.delete(e),this.pathBasedCache.delete(r))}))}),id:a};return n.reactiveSelectorInstance=c,this.reactiveSelectors.set(a,n),this.reactiveSelectorCache.set(e,c),this.pathBasedCache.set(r,c),this.eventBus.emit({name:"selector:accessed",payload:{selectorId:a,accessedPaths:s,duration:0,timestamp:performance.now()}}),c}validateSimpleSelector(e,t){const s=e.toString(),r=s.match(/=>\s*(.+)$/),i=r?r[1].trim():s,a=["map","filter","reduce","forEach","find","findIndex","some","every","includes","flatMap","flat","slice","splice"];for(const e of a)if(new RegExp(`\\.${e}\\s*\\(`).test(i))throw new Error(`Selector contains .${e}() which is not allowed. Selectors must be simple property accessors only. Use store effects for transformations.`);if(/\?[^:]*:/.test(i))throw new Error("Selector contains ternary operator (? :) which is not allowed. Selectors must be simple property accessors only. Use store effects for conditional transformations.");if(/\bif\s*\(|\bswitch\s*\(/.test(i))throw new Error("Selector contains conditional logic (if/switch) which is not allowed. Selectors must be simple property accessors only. Use store effects for conditional transformations.");if(/(?<![.\w])[a-zA-Z_$][a-zA-Z0-9_$]*\s*\(/.test(i))throw new Error("Selector contains function calls which are not allowed. Selectors must be simple property accessors only.");const o=/[+\-*/%&|^](?!=)|[<>!]=?(?!=)/.test(i),n=/\[.*\]/.test(i);if(o&&!n)throw new Error("Selector contains operations (+, -, *, /, etc.) which are not allowed. Selectors must be simple property accessors only. Use store effects for computed values.");if(0===t.length)throw new Error("Selector doesn't access any state properties. Selectors must access at least one state property.")}dispose(){this.unsubscribeFromStore(),this.reactiveSelectors.clear(),this.pathBasedCache.clear()}createMemoizedSelector(e){const t=y(e);this.validateSimpleSelector(e,t);let s,r=null;return i=>{const a=this.extractStateSubset(i,t);return r===a||(r=a,s=e(i)),s}}extractStateSubset(e,t){const s=[];for(const r of t){const t=r.split(".");let i=e;for(const e of t){if(null==i){s.push(void 0);break}i=i[e]}s.push(i)}return s}};function y(e,t="."){const s=new Set,r=(e=[])=>new Proxy({},{get:(i,a)=>{if("symbol"==typeof a)return;const o=[...e,a],n=o.join(t);return s.add(n),r(o)}});try{e(r())}catch(e){throw new Error(`Selector failed during path analysis. This usually means the selector is too complex. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}const i=Array.from(s);return i.filter((e=>!i.some((s=>s!==e&&s.startsWith(e+t)))))}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,r;if(Array.isArray(e)){if(s=e.length,s!=t.length)return!1;for(r=s;r-- >0;)if(!w(e[r],t[r]))return!1;return!0}const[i,a]=[Object.keys(e),Object.keys(t)];if(s=i.length,s!==a.length)return!1;for(r=s;r-- >0;){const s=i[r];if(!Object.prototype.hasOwnProperty.call(t,s)||!w(e[s],t[s]))return!1}return!0}return e!=e&&t!=t}function v(e){const t=e?.deleteMarker||u;return function(e,s){const r=[],i=[{pathArray:[],pathStr:"",orig:e||{},part:s||{}}];for(;i.length>0;){const{pathArray:e,pathStr:s,orig:a,part:o}=i.pop();if(null!=o&&!w(a,o))if("object"!=typeof o||Array.isArray(o))s&&r.push({path:s,oldValue:a,newValue:o});else for(const n of Object.keys(o)){const c=[...e,n],l=s?s+"."+n:n,d=o[n],h=a&&"object"==typeof a?a[n]:void 0;d!==t?"object"==typeof d&&null!==d?i.push({pathArray:c,pathStr:l,orig:h,part:d}):w(h,d)||r.push({path:l,oldValue:h,newValue:d}):void 0===h&&a&&"object"==typeof a||r.push({path:l,oldValue:h,newValue:void 0})}}return r}}function b(e){const t=e?.deleteMarker||u;return function(e){const s=new Set,r=[{obj:e,currentPath:""}];for(;r.length>0;){const{obj:e,currentPath:i}=r.pop();if(null!=e&&"object"==typeof e&&!Array.isArray(e))for(const a of Object.keys(e)){const o=i?`${i}.${a}`:a;s.add(o);const n=o.split(".");if(n.length>1)for(let e=n.length-1;e>0;e--){const t=n.slice(0,e).join(".");if(s.has(t))break;s.add(t)}const c=e[a];"object"==typeof c&&null!==c&&c!==t&&r.push({obj:c,currentPath:o})}}return Array.from(s)}}var S=v(),x=b(),E=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,r=[]){if(t)return this.cache=s?structuredClone(e):e,this.notifyListeners([]),[];0===r.length&&(r=[e]);const i=this.get(!1),a=new Map;for(let e=0;e<r.length;e++){const t=r[e],s=this.diff(i,t);for(let e=0;e<s.length;e++){const t=s[e];a.set(t.path,t)}}const o=a.size?[...a.values()]:[];if(o.length>0){this.cache=s?structuredClone(e):e;const t=new Set;for(let e=0;e<o.length;e++){let s=o[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 o}notifyListeners(e){for(const t of e)this.updateBus.emit({name:"update",payload:t})}};l(d());var T=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:r,id:i}of this.blockingMiddleware){const a={id:i,name:r,startTime:performance.now()};this.executionState.runningMiddleware={id:i,name:r,startTime:performance.now()},this.emitMiddlewareLifecycle("start",{id:i,name:r,type:"blocking"});try{const o=await Promise.resolve(s(e,t));if(a.endTime=performance.now(),a.duration=a.endTime-a.startTime,!1===o)return a.blocked=!0,this.emitMiddlewareLifecycle("blocked",{id:i,name:r,duration:a.duration}),this.emit(this.eventBus,{name:"middleware:executed",payload:a}),{blocked:!0};this.emitMiddlewareLifecycle("complete",{id:i,name:r,type:"blocking",duration:a.duration}),this.emit(this.eventBus,{name:"middleware:executed",payload:{...a,blocked:!1}})}catch(e){return a.endTime=performance.now(),a.duration=a.endTime-a.startTime,a.error=e instanceof Error?e:new Error(String(e)),a.blocked=!0,this.emitMiddlewareError(i,r,a.error,a.duration),this.emit(this.eventBus,{name:"middleware:executed",payload:a}),{blocked:!0,error:a.error}}finally{this.executionState.runningMiddleware=null}}return{blocked:!1}}async executeTransform(e,t){let s=e,r=t;for(const{fn:e,name:i,id:a}of this.middleware){const o={id:a,name:i,startTime:performance.now()};this.executionState.runningMiddleware={id:a,name:i,startTime:performance.now()},this.emitMiddlewareLifecycle("start",{id:a,name:i,type:"transform"});try{const n=await Promise.resolve(e(s,t));o.endTime=performance.now(),o.duration=o.endTime-o.startTime,o.blocked=!1,n&&"object"==typeof n&&(s=this.merge(s,n),r=this.merge(r,n)),this.emit(this.eventBus,{name:"middleware:executed",payload:o}),this.emitMiddlewareLifecycle("complete",{id:a,name:i,type:"transform",duration:o.duration})}catch(e){o.endTime=performance.now(),o.duration=o.endTime-o.startTime,o.error=e instanceof Error?e:new Error(String(e)),o.blocked=!1,this.emit(this.eventBus,{name:"middleware:executed",payload:o}),this.emitMiddlewareError(a,i,o.error,o.duration),console.error(`Middleware ${i} error:`,e)}finally{this.executionState.runningMiddleware=null}}return r}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,r){this.emit(this.eventBus,{name:"middleware:error",payload:{id:e,name:t,error:s,duration:r,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)}))}};l(d());var k=class{constructor(e,t,s,r){this.eventBus=e,this.coreState=t,this.instanceID=s,this.maxRetries=r?.maxRetries??3,this.retryDelay=r?.retryDelay??1e3}persistence;instanceID;persistenceReady=!1;backgroundQueue=[];isProcessingQueue=!1;maxRetries=3;retryDelay=1e3;queueProcessor;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).substr(2,9)}`,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,oldestTask:this.backgroundQueue[0]?.timestamp}}async flush(){this.isProcessingQueue||await this.processQueue()}clearQueue(){const e=this.backgroundQueue.length;this.backgroundQueue=[],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()}}),setTimeout((()=>{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.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.clearQueue(),this.isProcessingQueue=!1,this.persistenceReady=!1}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}};l(d());var M=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)}))}};l(d());var P=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()}};l(d());var C=class extends Error{constructor(){super("Action Cancelled by Debounce"),this.name="ActionCancelledError"}},B=class{constructor(e,t){this.eventBus=e,this.set=t}actions=new Map;register(e){const t=e.debounce,r={name:e.name,id:s.v4(),action:e.fn,debounce:t?{...t,condition:t.condition||(()=>!0)}:void 0};return this.actions.set(e.name,r),()=>{const t=this.actions.get(e.name);t?.debounce?.timer&&clearTimeout(t.debounce.timer),this.actions.delete(e.name)}}async dispatch(e,...t){const s=this.actions.get(e);if(!s)throw new Error(`unknown action ${e}`);const{id:r,action:i,debounce:a}=s;return!a||void 0===a.delay||a.delay<=0||a.condition&&!a.condition(a.args,t)?this.executeAction(e,r,i,t):(a.timer&&(clearTimeout(a.timer),a.reject?.(new C)),new Promise(((s,o)=>{a.resolve=s,a.reject=o,a.timer=setTimeout((async()=>{a.timer=void 0,a.resolve=void 0,a.reject=void 0;try{const a=await this.executeAction(e,r,i,t);s(a)}catch(e){o(e)}}),a.delay)})))}async executeAction(e,t,s,r){const i=performance.now();this.emit(this.eventBus,{name:"action:start",payload:{actionId:t,name:e,params:r||[],timestamp:i}});try{const a=await this.set((e=>s(e,...r)),{actionId:t}),o=this.actions.get(e);o?.debounce&&(o.debounce.args=r);const n=performance.now();return this.emit(this.eventBus,{name:"action:complete",payload:{actionId:t,name:e,params:r,startTime:i,endTime:n,duration:n-i,result:a}}),a}catch(s){const a=performance.now();throw this.emit(this.eventBus,{name:"action:error",payload:{actionId:t,name:e,params:r,startTime:i,endTime:a,duration:a-i,error:s}}),s}}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}};exports.ActionManager=B,exports.DELETE_SYMBOL=u,exports.ReactiveDataStore=class{coreState;middlewareEngine;persistenceHandler;transactionManager;metricsCollector;selectorManager;actionManager;updateQueue=Promise.resolve();updateBus=(0,h.createEventBus)();eventBus=(0,h.createEventBus)();executionState;instanceID=s.v4();merge;diff;constructor(e,t,s=u,r){this.executionState={executing:!1,changes:null,pendingChanges:[],middlewares:[],runningMiddleware:null,transactionActive:!1},this.merge=m({deleteMarker:s}),this.diff=v({deleteMarker:s}),this.coreState=new E(e,this.updateBus,this.diff),this.middlewareEngine=new T(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 M(this.eventBus,this.coreState,this.executionState),this.metricsCollector=new P(this.eventBus),this.actionManager=new B(this.eventBus,this.set.bind(this)),this.persistenceHandler.initialize(t),this.setupPersistenceListener(),this.selectorManager=new f(this.get.bind(this),this.eventBus)}isReady(){return this.persistenceHandler.isReady()}state(){return this.executionState}get(e){return this.coreState.get(e??!1)}select(e){return this.selectorManager.createReactiveSelector(e)}register(e){return this.actionManager.register(e)}async dispatch(e,...t){return this.actionManager.dispatch(e,...t)}async set(e,t={}){const s=this.updateQueue.then((()=>this._performUpdate(e,t)));return this.updateQueue=s.catch((()=>{})),s}async _performUpdate(e,t){this.executionState.executing=!0;const s=performance.now();this.emit(this.eventBus,{name:"update:start",payload:{timestamp:s,actionId:t.actionId}});try{if(t.force){const t=this.get(!1),s="function"==typeof e?e(t):e;return this.coreState.applyChanges(s,!0),s}let r;const i=this.get(!1);if("function"==typeof e){const t=e(i);r=t instanceof Promise?await t:t}else r=e;const a=await this.middlewareEngine.executeBlocking(i,r);if(a.blocked)throw a.error||new Error("Update blocked by middleware");const o=this.merge(i,r),n=await this.middlewareEngine.executeTransform(o,r),c=this.merge(o,n),l=this.coreState.applyChanges(c,!1,!1,[r,n]),d=performance.now(),h=this.get(!1);return this.emit(this.eventBus,{name:"update:complete",payload:{deltas:l,duration:d-s,timestamp:Date.now(),actionId:t.actionId,newState:h}}),h}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=[]}}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],r=""===e||0===s.length;return this.updateBus.subscribe("update",(e=>{(r||s.includes(e))&&(t(this.get(!1)),this.metricsCollector.listenerExecutions++)}))}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()}clearPersistenceQueue(){this.persistenceHandler.clearQueue()}dispose(){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.onStoreEvent(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,r)=>{if(s){(console[t]||console.log)("State Update:",r)}return r}}createValidationMiddleware(e){return(t,s)=>{const r=e(t,s);return"boolean"==typeof r?r:(!r.valid&&r.reason&&this._consoleLog("warn","Validation failed:",r.reason),r.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 r={},i={},a=(e,t,s)=>{t.reduce(((e,r,i)=>(i===t.length-1?e[r]=s:e[r]=e[r]??{},e[r])),e)};for(const e of s.deltas){const t=e.path.split(".");a(r,t,e.oldValue),a(i,t,e.newValue)}t.push({timestamp:s.timestamp,changedPaths:s.deltas.map((e=>e.path)),from:r,to:i})}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.onStoreEvent("update:complete",(s=>{this.isTimeTraveling||s.blocked||(t=[],e=0)}));this.unsubscribers.push(s);const r=()=>this.stateHistory.length,i=()=>e<r()-1,a=()=>t.length>0;return{canUndo:i,canRedo:a,undo:async()=>{if(!i())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(!a())return;const s=t.shift();e--,this.isTimeTraveling=!0,await this.store.set({...s.state},{force:!0}),this.isTimeTraveling=!1},length:r,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),r=document.createElement("a");r.href=s,r.download=`store-observer-session-${(new Date).toISOString()}.json`,r.click(),URL.revokeObjectURL(s)}importSession(e){return new Promise(((t,s)=>{const r=new FileReader;r.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)}},r.onerror=e=>s(e),r.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.createDerivePaths=b,exports.createDiff=v,exports.createMerge=m,exports.derivePaths=x,exports.diff=S,exports.merge=g,exports.shallowClone=p;
|
package/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{v4 as e}from"uuid";var t,s,i=Object.create,r=Object.defineProperty,a=Object.getOwnPropertyDescriptor,n=Object.getOwnPropertyNames,o=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,l=(e,t,s)=>(s=null!=e?i(o(e)):{},((e,t,s,i)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let o of n(t))c.call(e,o)||o===s||r(e,o,{get:()=>t[o],enumerable:!(i=a(t,o))||i.enumerable});return e})(e&&e.__esModule?s:r(s,"default",{value:e,enumerable:!0}),e)),d=(t={"src/store/node_modules/@asaidimu/events/index.js"(e,t){var s,i=Object.defineProperty,r=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,n=Object.prototype.hasOwnProperty,o={};((e,t)=>{for(var s in t)i(e,s,{get:t[s],enumerable:!0})})(o,{createEventBus:()=>c}),t.exports=(s=o,((e,t,s,o)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of a(t))n.call(e,c)||c===s||i(e,c,{get:()=>t[c],enumerable:!(o=r(t,c))||o.enumerable});return e})(i({},"__esModule",{value:!0}),s));var c=(e={async:!1,batchSize:1e3,batchDelay:16,errorHandler:e=>console.error("EventBus Error:",e),crossTab:!1,channelName:"event-bus-channel"})=>{const t=new Map;let s=[],i=0,r=0;const a=new Map,n=new Map;let o=null;e.crossTab&&"undefined"!=typeof BroadcastChannel?o=new BroadcastChannel(e.channelName):e.crossTab&&console.warn("BroadcastChannel is not supported in this browser. Cross-tab notifications are disabled.");const c=(e,t)=>{i++,r+=t,a.set(e,(a.get(e)||0)+1)},l=()=>{const t=s;s=[],t.forEach((({name:t,payload:s})=>{const i=performance.now();try{(n.get(t)||[]).forEach((e=>e(s)))}catch(i){e.errorHandler({...i,eventName:t,payload:s})}c(t,performance.now()-i)}))},d=(()=>{let t;return()=>{clearTimeout(t),t=setTimeout(l,e.batchDelay)}})(),h=e=>{const s=t.get(e);s?n.set(e,Array.from(s)):n.delete(e)};return o&&(o.onmessage=e=>{const{name:t,payload:s}=e.data;(n.get(t)||[]).forEach((e=>e(s)))}),{subscribe:(e,s)=>{t.has(e)||t.set(e,new Set);const i=t.get(e);return i.add(s),h(e),()=>{i.delete(s),0===i.size?(t.delete(e),n.delete(e)):h(e)}},emit:({name:t,payload:i})=>{if(e.async)return s.push({name:t,payload:i}),s.length>=e.batchSize?l():d(),void(o&&o.postMessage({name:t,payload:i}));const r=performance.now();try{(n.get(t)||[]).forEach((e=>e(i))),o&&o.postMessage({name:t,payload:i})}catch(s){e.errorHandler({...s,eventName:t,payload:i})}c(t,performance.now()-r)},getMetrics:()=>({totalEvents:i,activeSubscriptions:Array.from(t.values()).reduce(((e,t)=>e+t.size),0),eventCounts:a,averageEmitDuration:i>0?r/i:0}),clear:()=>{t.clear(),n.clear(),s=[],i=0,r=0,a.clear(),o&&(o.close(),o=null)}}}}},function(){return s||(0,t[n(t)[0]])((s={exports:{}}).exports,s),s.exports}),h=l(d()),u=Symbol.for("delete"),p=e=>Array.isArray(e)?[...e]:{...e};function m(e){const t=e?.deleteMarker||u;return function(e,s){if("object"!=typeof e||null===e)return"object"==typeof s&&null!==s?a(s):s===t?{}:s;if("object"!=typeof s||null===s)return e;const i=p(e),r=[{target:i,source:s}];for(;r.length>0;){const{target:e,source:s}=r.pop();for(const i of Object.keys(s)){if(!Object.prototype.hasOwnProperty.call(s,i))continue;const n=s[i];if(n!==t)if(Array.isArray(n))e[i]=n.map((e=>"object"!=typeof e||null===e||Array.isArray(e)?e===t?void 0:e:a(e)));else if("object"==typeof n&&null!==n){const t=i in e&&"object"==typeof e[i]&&null!==e[i]?e[i]:{};e[i]=p(t),r.push({target:e[i],source:n})}else e[i]=n;else delete e[i]}}return i;function a(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===t?void 0:e:a(e)));if("object"==typeof e){const s={};for(const[i,r]of Object.entries(e))if(r!==t)if("object"==typeof r&&null!==r){const e=a(r);void 0!==e&&(s[i]=e)}else s[i]=r;return s}return e===t?void 0:e}}}var f=m();l(d());var g=class{reactiveSelectors=new Map;reactiveSelectorCache=new WeakMap;pathBasedCache=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=e.deltas.map((e=>e.path));this.reEvaluateReactiveSelectors(t)};reEvaluateReactiveSelectors=e=>{this.reactiveSelectors.forEach((t=>{if(t.accessedPaths.some((t=>e.some((e=>e.startsWith(t)||t.startsWith(e)))))){let e;try{e=t.selector(this.getState())}catch{e=void 0}e!==t.lastResult&&(t.lastResult=e,t.subscribers.forEach((e=>e(t.lastResult))),this.eventBus.emit({name:"selector:changed",payload:{selectorId:t.id,newResult:e,timestamp:performance.now()}}))}}))};createReactiveSelector(e){const t=this.reactiveSelectorCache.get(e);if(t)return t;const s=y(e);this.validateSimpleSelector(e,s);const i=s.sort().join("|"),r=this.pathBasedCache.get(i);if(r)return this.reactiveSelectorCache.set(e,r),r;const a=`selector-${Math.random().toString(36).substring(2,9)}`,n=e(this.getState()),o={id:a,selector:e,lastResult:n,accessedPaths:s,subscribers:new Set,reactiveSelectorInstance:null},c={get:()=>o.lastResult,subscribe:t=>(o.subscribers.add(t),()=>{o.subscribers.delete(t),queueMicrotask((()=>{0===o.subscribers.size&&(this.reactiveSelectors.delete(a),this.reactiveSelectorCache.delete(e),this.pathBasedCache.delete(i))}))}),id:a};return o.reactiveSelectorInstance=c,this.reactiveSelectors.set(a,o),this.reactiveSelectorCache.set(e,c),this.pathBasedCache.set(i,c),this.eventBus.emit({name:"selector:accessed",payload:{selectorId:a,accessedPaths:s,duration:0,timestamp:performance.now()}}),c}validateSimpleSelector(e,t){const s=e.toString(),i=s.match(/=>\s*(.+)$/),r=i?i[1].trim():s,a=["map","filter","reduce","forEach","find","findIndex","some","every","includes","flatMap","flat","slice","splice"];for(const e of a)if(new RegExp(`\\.${e}\\s*\\(`).test(r))throw new Error(`Selector contains .${e}() which is not allowed. Selectors must be simple property accessors only. Use store effects for transformations.`);if(/\?[^:]*:/.test(r))throw new Error("Selector contains ternary operator (? :) which is not allowed. Selectors must be simple property accessors only. Use store effects for conditional transformations.");if(/\bif\s*\(|\bswitch\s*\(/.test(r))throw new Error("Selector contains conditional logic (if/switch) which is not allowed. Selectors must be simple property accessors only. Use store effects for conditional transformations.");if(/(?<![.\w])[a-zA-Z_$][a-zA-Z0-9_$]*\s*\(/.test(r))throw new Error("Selector contains function calls which are not allowed. Selectors must be simple property accessors only.");const n=/[+\-*/%&|^](?!=)|[<>!]=?(?!=)/.test(r),o=/\[.*\]/.test(r);if(n&&!o)throw new Error("Selector contains operations (+, -, *, /, etc.) which are not allowed. Selectors must be simple property accessors only. Use store effects for computed values.");if(0===t.length)throw new Error("Selector doesn't access any state properties. Selectors must access at least one state property.")}dispose(){this.unsubscribeFromStore(),this.reactiveSelectors.clear(),this.pathBasedCache.clear()}createMemoizedSelector(e){const t=y(e);this.validateSimpleSelector(e,t);let s,i=null;return r=>{const a=this.extractStateSubset(r,t);return i===a||(i=a,s=e(r)),s}}extractStateSubset(e,t){const s=[];for(const i of t){const t=i.split(".");let r=e;for(const e of t){if(null==r){s.push(void 0);break}r=r[e]}s.push(r)}return s}};function y(e,t="."){const s=new Set,i=(e=[])=>new Proxy({},{get:(r,a)=>{if("symbol"==typeof a)return;const n=[...e,a],o=n.join(t);return s.add(o),i(n)}});try{e(i())}catch(e){throw new Error(`Selector failed during path analysis. This usually means the selector is too complex. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}const r=Array.from(s);return r.filter((e=>!r.some((s=>s!==e&&s.startsWith(e+t)))))}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,a]=[Object.keys(e),Object.keys(t)];if(s=r.length,s!==a.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 v(e){const t=e?.deleteMarker||u;return function(e,s){const i=[],r=[{pathArray:[],pathStr:"",orig:e||{},part:s||{}}];for(;r.length>0;){const{pathArray:e,pathStr:s,orig:a,part:n}=r.pop();if(null!=n&&!w(a,n))if("object"!=typeof n||Array.isArray(n))s&&i.push({path:s,oldValue:a,newValue:n});else for(const o of Object.keys(n)){const c=[...e,o],l=s?s+"."+o:o,d=n[o],h=a&&"object"==typeof a?a[o]:void 0;d!==t?"object"==typeof d&&null!==d?r.push({pathArray:c,pathStr:l,orig:h,part:d}):w(h,d)||i.push({path:l,oldValue:h,newValue:d}):void 0===h&&a&&"object"==typeof a||i.push({path:l,oldValue:h,newValue:void 0})}}return i}}function b(e){const t=e?.deleteMarker||u;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 a of Object.keys(e)){const n=r?`${r}.${a}`:a;s.add(n);const o=n.split(".");if(o.length>1)for(let e=o.length-1;e>0;e--){const t=o.slice(0,e).join(".");if(s.has(t))break;s.add(t)}const c=e[a];"object"==typeof c&&null!==c&&c!==t&&i.push({obj:c,currentPath:n})}}return Array.from(s)}}var S=v(),E=b(),k=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),a=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];a.set(t.path,t)}}const n=a.size?[...a.values()]:[];if(n.length>0){this.cache=s?structuredClone(e):e;const t=new Set;for(let e=0;e<n.length;e++){let s=n[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 n}notifyListeners(e){for(const t of e)this.updateBus.emit({name:"update",payload:t})}};l(d());var 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 a={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 n=await Promise.resolve(s(e,t));if(a.endTime=performance.now(),a.duration=a.endTime-a.startTime,!1===n)return a.blocked=!0,this.emitMiddlewareLifecycle("blocked",{id:r,name:i,duration:a.duration}),this.emit(this.eventBus,{name:"middleware:executed",payload:a}),{blocked:!0};this.emitMiddlewareLifecycle("complete",{id:r,name:i,type:"blocking",duration:a.duration}),this.emit(this.eventBus,{name:"middleware:executed",payload:{...a,blocked:!1}})}catch(e){return a.endTime=performance.now(),a.duration=a.endTime-a.startTime,a.error=e instanceof Error?e:new Error(String(e)),a.blocked=!0,this.emitMiddlewareError(r,i,a.error,a.duration),this.emit(this.eventBus,{name:"middleware:executed",payload:a}),{blocked:!0,error:a.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:a}of this.middleware){const n={id:a,name:r,startTime:performance.now()};this.executionState.runningMiddleware={id:a,name:r,startTime:performance.now()},this.emitMiddlewareLifecycle("start",{id:a,name:r,type:"transform"});try{const o=await Promise.resolve(e(s,t));n.endTime=performance.now(),n.duration=n.endTime-n.startTime,n.blocked=!1,o&&"object"==typeof o&&(s=this.merge(s,o),i=this.merge(i,o)),this.emit(this.eventBus,{name:"middleware:executed",payload:n}),this.emitMiddlewareLifecycle("complete",{id:a,name:r,type:"transform",duration:n.duration})}catch(e){n.endTime=performance.now(),n.duration=n.endTime-n.startTime,n.error=e instanceof Error?e:new Error(String(e)),n.blocked=!1,this.emit(this.eventBus,{name:"middleware:executed",payload:n}),this.emitMiddlewareError(a,r,n.error,n.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)}))}};l(d());var 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;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).substr(2,9)}`,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,oldestTask:this.backgroundQueue[0]?.timestamp}}async flush(){this.isProcessingQueue||await this.processQueue()}clearQueue(){const e=this.backgroundQueue.length;this.backgroundQueue=[],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()}}),setTimeout((()=>{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.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.clearQueue(),this.isProcessingQueue=!1,this.persistenceReady=!1}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}};l(d());var C=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)}))}};l(d());var A=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()}};l(d());var P=class extends Error{constructor(){super("Action Cancelled by Debounce"),this.name="ActionCancelledError"}},M=class{constructor(e,t){this.eventBus=e,this.set=t}actions=new Map;register(t){const s=t.debounce,i={name:t.name,id:e(),action:t.fn,debounce:s?{...s,condition:s.condition||(()=>!0)}:void 0};return this.actions.set(t.name,i),()=>{const e=this.actions.get(t.name);e?.debounce?.timer&&clearTimeout(e.debounce.timer),this.actions.delete(t.name)}}async dispatch(e,...t){const s=this.actions.get(e);if(!s)throw new Error(`unknown action ${e}`);const{id:i,action:r,debounce:a}=s;return!a||void 0===a.delay||a.delay<=0||a.condition&&!a.condition(a.args,t)?this.executeAction(e,i,r,t):(a.timer&&(clearTimeout(a.timer),a.reject?.(new P)),new Promise(((s,n)=>{a.resolve=s,a.reject=n,a.timer=setTimeout((async()=>{a.timer=void 0,a.resolve=void 0,a.reject=void 0;try{const a=await this.executeAction(e,i,r,t);s(a)}catch(e){n(e)}}),a.delay)})))}async executeAction(e,t,s,i){const r=performance.now();this.emit(this.eventBus,{name:"action:start",payload:{actionId:t,name:e,params:i||[],timestamp:r}});try{const a=await this.set((e=>s(e,...i)),{actionId:t}),n=this.actions.get(e);n?.debounce&&(n.debounce.args=i);const o=performance.now();return this.emit(this.eventBus,{name:"action:complete",payload:{actionId:t,name:e,params:i,startTime:r,endTime:o,duration:o-r,result:a}}),a}catch(s){const a=performance.now();throw this.emit(this.eventBus,{name:"action:error",payload:{actionId:t,name:e,params:i,startTime:r,endTime:a,duration:a-r,error:s}}),s}}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},B=class{coreState;middlewareEngine;persistenceHandler;transactionManager;metricsCollector;selectorManager;actionManager;updateQueue=Promise.resolve();updateBus=(0,h.createEventBus)();eventBus=(0,h.createEventBus)();executionState;instanceID=e();merge;diff;constructor(e,t,s=u,i){this.executionState={executing:!1,changes:null,pendingChanges:[],middlewares:[],runningMiddleware:null,transactionActive:!1},this.merge=m({deleteMarker:s}),this.diff=v({deleteMarker:s}),this.coreState=new k(e,this.updateBus,this.diff),this.middlewareEngine=new x(this.eventBus,this.executionState,this.merge),this.persistenceHandler=new T(this.eventBus,this.coreState,this.instanceID,{maxRetries:i?.persistenceMaxRetries,retryDelay:i?.persistenceRetryDelay}),this.transactionManager=new C(this.eventBus,this.coreState,this.executionState),this.metricsCollector=new A(this.eventBus),this.actionManager=new M(this.eventBus,this.set.bind(this)),this.persistenceHandler.initialize(t),this.setupPersistenceListener(),this.selectorManager=new g(this.get.bind(this),this.eventBus)}isReady(){return this.persistenceHandler.isReady()}state(){return this.executionState}get(e){return this.coreState.get(e??!1)}select(e){return this.selectorManager.createReactiveSelector(e)}register(e){return this.actionManager.register(e)}async dispatch(e,...t){return this.actionManager.dispatch(e,...t)}async set(e,t={}){const s=this.updateQueue.then((()=>this._performUpdate(e,t)));return this.updateQueue=s.catch((()=>{})),s}async _performUpdate(e,t){this.executionState.executing=!0;const s=performance.now();this.emit(this.eventBus,{name:"update:start",payload:{timestamp:s,actionId:t.actionId}});try{if(t.force){const t=this.get(!1),s="function"==typeof e?e(t):e;return this.coreState.applyChanges(s,!0),s}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 a=await this.middlewareEngine.executeBlocking(r,i);if(a.blocked)throw a.error||new Error("Update blocked by middleware");const n=this.merge(r,i),o=await this.middlewareEngine.executeTransform(n,i),c=this.merge(n,o),l=this.coreState.applyChanges(c,!1,!1,[i,o]),d=performance.now(),h=this.get(!1);return this.emit(this.eventBus,{name:"update:complete",payload:{deltas:l,duration:d-s,timestamp:Date.now(),actionId:t.actionId,newState:h}}),h}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=[]}}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++)}))}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()}clearPersistenceQueue(){this.persistenceHandler.clearQueue()}dispose(){this.persistenceHandler.dispose(),this.metricsCollector.dispose?.(),this.selectorManager.dispose?.()}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},D=(e=>(e.Singleton="singleton",e.Transient="transient",e))(D||{}),H=class{artifacts=new Map;resolvingStack=[];listeners=new Map;getState;subscribe;constructor(e){this.getState=(...t)=>e.get(...t),this.subscribe=(...t)=>e.watch(...t)}watch(e){return{id:e,get:()=>{const t=this.artifacts.get(e);return t&&(void 0!==t.instance||t.error)?this.packageArtifact(t):null},subscribe:t=>{this.listeners.has(e)||this.listeners.set(e,new Set);const s=this.listeners.get(e);return s.add(t),()=>s.delete(t)}}}get(e){return this.artifacts.get(e)?.instance}register(e){const{key:t,factory:s,scope:i="singleton",lazy:r=!0}=e;this.artifacts.has(t)&&(console.warn(`[ArtifactContainer] Warning: Overwriting existing artifact "${t}".`),this.disposeArtifact(t));const a={key:t,factory:s,scope:i,lazy:r,cleanupFunctions:[],stateDependencies:new Set,artifactDependencies:new Set,dependents:new Set};return this.artifacts.set(t,a),r||"singleton"!==i||this.resolve(t).catch((e=>{console.error(`[ArtifactContainer] Eager load failed for "${t}":`,e)})),async()=>{await this.unregister(t)}}async unregister(e){this.artifacts.has(e)&&(await this.disposeArtifact(e),this.artifacts.delete(e))}async resolve(e){if(this.resolvingStack.includes(e))throw new Error(`[ArtifactContainer] Circular dependency: ${this.resolvingStack.join(" -> ")} -> ${e}`);this.resolvingStack.push(e);try{const t=this.artifacts.get(e);if(!t)throw new Error(`[ArtifactContainer] Artifact with key "${e}" not found.`);if("transient"===t.scope){const e=await this.createArtifactInstance(t,new Set,new Set);return{instance:e.instance,cleanup:e.cleanup,error:e.error,invalidate:async()=>{}}}if(void 0!==t.instance||void 0!==t.error)return this.packageArtifact(t);if(t.initializationPromise)try{return await t.initializationPromise,this.packageArtifact(t)}catch(e){return this.packageArtifact(t)}const s=(async()=>{try{const e=new Set,s=new Set,i=await this.createArtifactInstance(t,e,s);return this.updateGraph(t,e,s),i.error&&(t.error=i.error),i.instance}catch(e){throw t.error=e,t.initializationPromise=void 0,e}})();t.initializationPromise=s;try{await s}catch(e){}return this.packageArtifact(t)}finally{this.resolvingStack.pop()}}packageArtifact(e){return{instance:e.instance,cleanup:this.createCompositeCleanup(e.cleanupFunctions),error:e.error,invalidate:async t=>this.invalidate(e.key,t)}}async createArtifactInstance(e,t,s){const i=[];let r=!0;i.push((()=>{r=!1}));const a={state:this.getState,current:e.instance,use:async i=>i({resolve:async s=>{if(s===e.key)throw new Error(`[ArtifactContainer] Self-dependency detected in "${e.key}"`);return t.add(s),this.resolve(s)},select:e=>(y(e).forEach((e=>s.add(e))),e(this.getState()))}),onCleanup:e=>{i.push(e)},yield:t=>{r?"transient"!==e.scope?(e.instance=t,e.error=void 0,this.processYieldPropagation(e.key)):console.warn(`[ArtifactContainer] Yield ignored on transient artifact "${e.key}"`):console.warn(`[ArtifactContainer] Ignored yield on disposed artifact "${e.key}"`)}};let n,o;try{n=await e.factory(a)}catch(e){o=e,n=void 0}"singleton"===e.scope&&(void 0!==n&&(e.instance=n),e.cleanupFunctions=i);return{instance:"singleton"===e.scope?e.instance:n,cleanup:this.createCompositeCleanup(i),error:o}}async processYieldPropagation(e){const t=this.artifacts.get(e);if(t&&(void 0!==t.instance||t.error))try{const s=Array.from(t.dependents);await Promise.all(s.map((e=>this.invalidate(e,!1)))),this.notifyListeners(e)}catch(t){console.error(`[ArtifactContainer] Yield propagation failed for "${e}":`,t)}}updateGraph(e,t,s){e.artifactDependencies.forEach((t=>{const s=this.artifacts.get(t);s&&s.dependents.delete(e.key)})),e.artifactDependencies=t,t.forEach((t=>{const s=this.artifacts.get(t);s&&s.dependents.add(e.key)}));const i=e.stateSubscriptionCleanup;e.stateDependencies=s,s.size>0?e.stateSubscriptionCleanup=this.subscribe(Array.from(s),(()=>this.invalidate(e.key))):e.stateSubscriptionCleanup=void 0,i&&i(),this.detectCycles(e.key),this.notifyListeners(e.key)}async invalidate(e,t=!1){const s=this.artifacts.get(e);if(!s)return;if(s.initializationPromise)try{await s.initializationPromise}catch(e){}if(s.rebuildPromise)return s.rebuildPromise;const i=(async()=>{try{const i=Array.from(s.dependents);await Promise.all(i.map((e=>this.invalidate(e,t)))),await this.disposeInstance(s),!t&&s.lazy||await this.resolve(e).catch((t=>{console.error(`[ArtifactContainer] Rebuild failed for "${e}":`,t)}))}finally{s.rebuildPromise=void 0}})();return s.rebuildPromise=i,i}async disposeInstance(e){if(e.stateSubscriptionCleanup&&(e.stateSubscriptionCleanup(),e.stateSubscriptionCleanup=void 0),e.cleanupFunctions.length>0)for(let t=e.cleanupFunctions.length-1;t>=0;t--)try{await e.cleanupFunctions[t]()}catch(t){console.error(`[ArtifactContainer] Cleanup error for "${e.key}":`,t)}e.instance=void 0,e.error=void 0,e.cleanupFunctions=[],e.initializationPromise=void 0,this.notifyListeners(e.key)}async disposeArtifact(e){const t=this.artifacts.get(e);t&&(t.rebuildPromise&&await t.rebuildPromise,await this.disposeInstance(t),t.artifactDependencies.forEach((t=>{const s=this.artifacts.get(t);s&&s.dependents.delete(e)})))}createCompositeCleanup(e){if(0!==e.length)return async()=>{for(let t=e.length-1;t>=0;t--)try{await e[t]()}catch(e){}}}notifyListeners(e){const t=this.listeners.get(e);t&&t.forEach((e=>e()))}detectCycles(e){const t=new Set,s=new Set,i=e=>{if(s.has(e))throw new Error(`[ArtifactContainer] Circular dependency: ${Array.from(s).join(" -> ")} -> ${e}`);if(t.has(e))return;t.add(e),s.add(e);const r=this.artifacts.get(e);r&&r.artifactDependencies.forEach((e=>i(e))),s.delete(e)};i(e)}dispose(){this.artifacts.forEach(((e,t)=>this.disposeArtifact(t))),this.artifacts.clear()}isLoading(e){return this.resolvingStack.includes(e)||void 0!==this.artifacts.get(e)?.initializationPromise}},L=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.onStoreEvent(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={},a=(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(".");a(i,t,e.oldValue),a(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.onStoreEvent("update:complete",(s=>{this.isTimeTraveling||s.blocked||(t=[],e=0)}));this.unsubscribers.push(s);const i=()=>this.stateHistory.length,r=()=>e<i()-1,a=()=>t.length>0;return{canUndo:r,canRedo:a,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(!a())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 ActionManager,H as ArtifactContainer,D as ArtifactScope,u as DELETE_SYMBOL,B as ReactiveDataStore,L as StoreObserver,b as createDerivePaths,v as createDiff,m as createMerge,E as derivePaths,S as diff,f as merge,p as shallowClone};
|
|
1
|
+
import{v4 as e}from"uuid";var t,s,r=Object.create,i=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,n=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,l=(e,t,s)=>(s=null!=e?r(n(e)):{},((e,t,s,r)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let n of o(t))c.call(e,n)||n===s||i(e,n,{get:()=>t[n],enumerable:!(r=a(t,n))||r.enumerable});return e})(e&&e.__esModule?s:i(s,"default",{value:e,enumerable:!0}),e)),d=(t={"src/store/node_modules/@asaidimu/events/index.js"(e,t){var s,r=Object.defineProperty,i=Object.getOwnPropertyDescriptor,a=Object.getOwnPropertyNames,o=Object.prototype.hasOwnProperty,n={};((e,t)=>{for(var s in t)r(e,s,{get:t[s],enumerable:!0})})(n,{createEventBus:()=>c}),t.exports=(s=n,((e,t,s,n)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let c of a(t))o.call(e,c)||c===s||r(e,c,{get:()=>t[c],enumerable:!(n=i(t,c))||n.enumerable});return e})(r({},"__esModule",{value:!0}),s));var c=(e={async:!1,batchSize:1e3,batchDelay:16,errorHandler:e=>console.error("EventBus Error:",e),crossTab:!1,channelName:"event-bus-channel"})=>{const t=new Map;let s=[],r=0,i=0;const a=new Map,o=new Map;let n=null;e.crossTab&&"undefined"!=typeof BroadcastChannel?n=new BroadcastChannel(e.channelName):e.crossTab&&console.warn("BroadcastChannel is not supported in this browser. Cross-tab notifications are disabled.");const c=(e,t)=>{r++,i+=t,a.set(e,(a.get(e)||0)+1)},l=()=>{const t=s;s=[],t.forEach((({name:t,payload:s})=>{const r=performance.now();try{(o.get(t)||[]).forEach((e=>e(s)))}catch(r){e.errorHandler({...r,eventName:t,payload:s})}c(t,performance.now()-r)}))},d=(()=>{let t;return()=>{clearTimeout(t),t=setTimeout(l,e.batchDelay)}})(),h=e=>{const s=t.get(e);s?o.set(e,Array.from(s)):o.delete(e)};return n&&(n.onmessage=e=>{const{name:t,payload:s}=e.data;(o.get(t)||[]).forEach((e=>e(s)))}),{subscribe:(e,s)=>{t.has(e)||t.set(e,new Set);const r=t.get(e);return r.add(s),h(e),()=>{r.delete(s),0===r.size?(t.delete(e),o.delete(e)):h(e)}},emit:({name:t,payload:r})=>{if(e.async)return s.push({name:t,payload:r}),s.length>=e.batchSize?l():d(),void(n&&n.postMessage({name:t,payload:r}));const i=performance.now();try{(o.get(t)||[]).forEach((e=>e(r))),n&&n.postMessage({name:t,payload:r})}catch(s){e.errorHandler({...s,eventName:t,payload:r})}c(t,performance.now()-i)},getMetrics:()=>({totalEvents:r,activeSubscriptions:Array.from(t.values()).reduce(((e,t)=>e+t.size),0),eventCounts:a,averageEmitDuration:r>0?i/r:0}),clear:()=>{t.clear(),o.clear(),s=[],r=0,i=0,a.clear(),n&&(n.close(),n=null)}}}}},function(){return s||(0,t[o(t)[0]])((s={exports:{}}).exports,s),s.exports}),h=l(d()),u=Symbol.for("delete"),p=e=>Array.isArray(e)?[...e]:{...e};function m(e){const t=e?.deleteMarker||u;return function(e,s){if("object"!=typeof e||null===e)return"object"==typeof s&&null!==s?a(s):s===t?{}:s;if("object"!=typeof s||null===s)return e;const r=p(e),i=[{target:r,source:s}];for(;i.length>0;){const{target:e,source:s}=i.pop();for(const r of Object.keys(s)){if(!Object.prototype.hasOwnProperty.call(s,r))continue;const o=s[r];if(o!==t)if(Array.isArray(o))e[r]=o.map((e=>"object"!=typeof e||null===e||Array.isArray(e)?e===t?void 0:e:a(e)));else if("object"==typeof o&&null!==o){const t=r in e&&"object"==typeof e[r]&&null!==e[r]?e[r]:{};e[r]=p(t),i.push({target:e[r],source:o})}else e[r]=o;else delete e[r]}}return r;function a(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===t?void 0:e:a(e)));if("object"==typeof e){const s={};for(const[r,i]of Object.entries(e))if(i!==t)if("object"==typeof i&&null!==i){const e=a(i);void 0!==e&&(s[r]=e)}else s[r]=i;return s}return e===t?void 0:e}}}var g=m();l(d());var f=class{reactiveSelectors=new Map;reactiveSelectorCache=new WeakMap;pathBasedCache=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=e.deltas.map((e=>e.path));this.reEvaluateReactiveSelectors(t)};reEvaluateReactiveSelectors=e=>{this.reactiveSelectors.forEach((t=>{if(t.accessedPaths.some((t=>e.some((e=>e.startsWith(t)||t.startsWith(e)))))){let e;try{e=t.selector(this.getState())}catch{e=void 0}e!==t.lastResult&&(t.lastResult=e,t.subscribers.forEach((e=>e(t.lastResult))),this.eventBus.emit({name:"selector:changed",payload:{selectorId:t.id,newResult:e,timestamp:performance.now()}}))}}))};createReactiveSelector(e){const t=this.reactiveSelectorCache.get(e);if(t)return t;const s=y(e);this.validateSimpleSelector(e,s);const r=s.sort().join("|"),i=this.pathBasedCache.get(r);if(i)return this.reactiveSelectorCache.set(e,i),i;const a=`selector-${Math.random().toString(36).substring(2,9)}`,o=e(this.getState()),n={id:a,selector:e,lastResult:o,accessedPaths:s,subscribers:new Set,reactiveSelectorInstance:null},c={get:()=>n.lastResult,subscribe:t=>(n.subscribers.add(t),()=>{n.subscribers.delete(t),queueMicrotask((()=>{0===n.subscribers.size&&(this.reactiveSelectors.delete(a),this.reactiveSelectorCache.delete(e),this.pathBasedCache.delete(r))}))}),id:a};return n.reactiveSelectorInstance=c,this.reactiveSelectors.set(a,n),this.reactiveSelectorCache.set(e,c),this.pathBasedCache.set(r,c),this.eventBus.emit({name:"selector:accessed",payload:{selectorId:a,accessedPaths:s,duration:0,timestamp:performance.now()}}),c}validateSimpleSelector(e,t){const s=e.toString(),r=s.match(/=>\s*(.+)$/),i=r?r[1].trim():s,a=["map","filter","reduce","forEach","find","findIndex","some","every","includes","flatMap","flat","slice","splice"];for(const e of a)if(new RegExp(`\\.${e}\\s*\\(`).test(i))throw new Error(`Selector contains .${e}() which is not allowed. Selectors must be simple property accessors only. Use store effects for transformations.`);if(/\?[^:]*:/.test(i))throw new Error("Selector contains ternary operator (? :) which is not allowed. Selectors must be simple property accessors only. Use store effects for conditional transformations.");if(/\bif\s*\(|\bswitch\s*\(/.test(i))throw new Error("Selector contains conditional logic (if/switch) which is not allowed. Selectors must be simple property accessors only. Use store effects for conditional transformations.");if(/(?<![.\w])[a-zA-Z_$][a-zA-Z0-9_$]*\s*\(/.test(i))throw new Error("Selector contains function calls which are not allowed. Selectors must be simple property accessors only.");const o=/[+\-*/%&|^](?!=)|[<>!]=?(?!=)/.test(i),n=/\[.*\]/.test(i);if(o&&!n)throw new Error("Selector contains operations (+, -, *, /, etc.) which are not allowed. Selectors must be simple property accessors only. Use store effects for computed values.");if(0===t.length)throw new Error("Selector doesn't access any state properties. Selectors must access at least one state property.")}dispose(){this.unsubscribeFromStore(),this.reactiveSelectors.clear(),this.pathBasedCache.clear()}createMemoizedSelector(e){const t=y(e);this.validateSimpleSelector(e,t);let s,r=null;return i=>{const a=this.extractStateSubset(i,t);return r===a||(r=a,s=e(i)),s}}extractStateSubset(e,t){const s=[];for(const r of t){const t=r.split(".");let i=e;for(const e of t){if(null==i){s.push(void 0);break}i=i[e]}s.push(i)}return s}};function y(e,t="."){const s=new Set,r=(e=[])=>new Proxy({},{get:(i,a)=>{if("symbol"==typeof a)return;const o=[...e,a],n=o.join(t);return s.add(n),r(o)}});try{e(r())}catch(e){throw new Error(`Selector failed during path analysis. This usually means the selector is too complex. Selectors must be simple property accessors only. Error: ${e instanceof Error?e.message:String(e)}`)}const i=Array.from(s);return i.filter((e=>!i.some((s=>s!==e&&s.startsWith(e+t)))))}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,r;if(Array.isArray(e)){if(s=e.length,s!=t.length)return!1;for(r=s;r-- >0;)if(!w(e[r],t[r]))return!1;return!0}const[i,a]=[Object.keys(e),Object.keys(t)];if(s=i.length,s!==a.length)return!1;for(r=s;r-- >0;){const s=i[r];if(!Object.prototype.hasOwnProperty.call(t,s)||!w(e[s],t[s]))return!1}return!0}return e!=e&&t!=t}function v(e){const t=e?.deleteMarker||u;return function(e,s){const r=[],i=[{pathArray:[],pathStr:"",orig:e||{},part:s||{}}];for(;i.length>0;){const{pathArray:e,pathStr:s,orig:a,part:o}=i.pop();if(null!=o&&!w(a,o))if("object"!=typeof o||Array.isArray(o))s&&r.push({path:s,oldValue:a,newValue:o});else for(const n of Object.keys(o)){const c=[...e,n],l=s?s+"."+n:n,d=o[n],h=a&&"object"==typeof a?a[n]:void 0;d!==t?"object"==typeof d&&null!==d?i.push({pathArray:c,pathStr:l,orig:h,part:d}):w(h,d)||r.push({path:l,oldValue:h,newValue:d}):void 0===h&&a&&"object"==typeof a||r.push({path:l,oldValue:h,newValue:void 0})}}return r}}function b(e){const t=e?.deleteMarker||u;return function(e){const s=new Set,r=[{obj:e,currentPath:""}];for(;r.length>0;){const{obj:e,currentPath:i}=r.pop();if(null!=e&&"object"==typeof e&&!Array.isArray(e))for(const a of Object.keys(e)){const o=i?`${i}.${a}`:a;s.add(o);const n=o.split(".");if(n.length>1)for(let e=n.length-1;e>0;e--){const t=n.slice(0,e).join(".");if(s.has(t))break;s.add(t)}const c=e[a];"object"==typeof c&&null!==c&&c!==t&&r.push({obj:c,currentPath:o})}}return Array.from(s)}}var S=v(),E=b(),x=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,r=[]){if(t)return this.cache=s?structuredClone(e):e,this.notifyListeners([]),[];0===r.length&&(r=[e]);const i=this.get(!1),a=new Map;for(let e=0;e<r.length;e++){const t=r[e],s=this.diff(i,t);for(let e=0;e<s.length;e++){const t=s[e];a.set(t.path,t)}}const o=a.size?[...a.values()]:[];if(o.length>0){this.cache=s?structuredClone(e):e;const t=new Set;for(let e=0;e<o.length;e++){let s=o[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 o}notifyListeners(e){for(const t of e)this.updateBus.emit({name:"update",payload:t})}};l(d());var T=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:r,id:i}of this.blockingMiddleware){const a={id:i,name:r,startTime:performance.now()};this.executionState.runningMiddleware={id:i,name:r,startTime:performance.now()},this.emitMiddlewareLifecycle("start",{id:i,name:r,type:"blocking"});try{const o=await Promise.resolve(s(e,t));if(a.endTime=performance.now(),a.duration=a.endTime-a.startTime,!1===o)return a.blocked=!0,this.emitMiddlewareLifecycle("blocked",{id:i,name:r,duration:a.duration}),this.emit(this.eventBus,{name:"middleware:executed",payload:a}),{blocked:!0};this.emitMiddlewareLifecycle("complete",{id:i,name:r,type:"blocking",duration:a.duration}),this.emit(this.eventBus,{name:"middleware:executed",payload:{...a,blocked:!1}})}catch(e){return a.endTime=performance.now(),a.duration=a.endTime-a.startTime,a.error=e instanceof Error?e:new Error(String(e)),a.blocked=!0,this.emitMiddlewareError(i,r,a.error,a.duration),this.emit(this.eventBus,{name:"middleware:executed",payload:a}),{blocked:!0,error:a.error}}finally{this.executionState.runningMiddleware=null}}return{blocked:!1}}async executeTransform(e,t){let s=e,r=t;for(const{fn:e,name:i,id:a}of this.middleware){const o={id:a,name:i,startTime:performance.now()};this.executionState.runningMiddleware={id:a,name:i,startTime:performance.now()},this.emitMiddlewareLifecycle("start",{id:a,name:i,type:"transform"});try{const n=await Promise.resolve(e(s,t));o.endTime=performance.now(),o.duration=o.endTime-o.startTime,o.blocked=!1,n&&"object"==typeof n&&(s=this.merge(s,n),r=this.merge(r,n)),this.emit(this.eventBus,{name:"middleware:executed",payload:o}),this.emitMiddlewareLifecycle("complete",{id:a,name:i,type:"transform",duration:o.duration})}catch(e){o.endTime=performance.now(),o.duration=o.endTime-o.startTime,o.error=e instanceof Error?e:new Error(String(e)),o.blocked=!1,this.emit(this.eventBus,{name:"middleware:executed",payload:o}),this.emitMiddlewareError(a,i,o.error,o.duration),console.error(`Middleware ${i} error:`,e)}finally{this.executionState.runningMiddleware=null}}return r}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,r){this.emit(this.eventBus,{name:"middleware:error",payload:{id:e,name:t,error:s,duration:r,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)}))}};l(d());var k=class{constructor(e,t,s,r){this.eventBus=e,this.coreState=t,this.instanceID=s,this.maxRetries=r?.maxRetries??3,this.retryDelay=r?.retryDelay??1e3}persistence;instanceID;persistenceReady=!1;backgroundQueue=[];isProcessingQueue=!1;maxRetries=3;retryDelay=1e3;queueProcessor;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).substr(2,9)}`,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,oldestTask:this.backgroundQueue[0]?.timestamp}}async flush(){this.isProcessingQueue||await this.processQueue()}clearQueue(){const e=this.backgroundQueue.length;this.backgroundQueue=[],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()}}),setTimeout((()=>{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.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.clearQueue(),this.isProcessingQueue=!1,this.persistenceReady=!1}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}};l(d());var M=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)}))}};l(d());var P=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()}};l(d());var C=class extends Error{constructor(){super("Action Cancelled by Debounce"),this.name="ActionCancelledError"}},B=class{constructor(e,t){this.eventBus=e,this.set=t}actions=new Map;register(t){const s=t.debounce,r={name:t.name,id:e(),action:t.fn,debounce:s?{...s,condition:s.condition||(()=>!0)}:void 0};return this.actions.set(t.name,r),()=>{const e=this.actions.get(t.name);e?.debounce?.timer&&clearTimeout(e.debounce.timer),this.actions.delete(t.name)}}async dispatch(e,...t){const s=this.actions.get(e);if(!s)throw new Error(`unknown action ${e}`);const{id:r,action:i,debounce:a}=s;return!a||void 0===a.delay||a.delay<=0||a.condition&&!a.condition(a.args,t)?this.executeAction(e,r,i,t):(a.timer&&(clearTimeout(a.timer),a.reject?.(new C)),new Promise(((s,o)=>{a.resolve=s,a.reject=o,a.timer=setTimeout((async()=>{a.timer=void 0,a.resolve=void 0,a.reject=void 0;try{const a=await this.executeAction(e,r,i,t);s(a)}catch(e){o(e)}}),a.delay)})))}async executeAction(e,t,s,r){const i=performance.now();this.emit(this.eventBus,{name:"action:start",payload:{actionId:t,name:e,params:r||[],timestamp:i}});try{const a=await this.set((e=>s(e,...r)),{actionId:t}),o=this.actions.get(e);o?.debounce&&(o.debounce.args=r);const n=performance.now();return this.emit(this.eventBus,{name:"action:complete",payload:{actionId:t,name:e,params:r,startTime:i,endTime:n,duration:n-i,result:a}}),a}catch(s){const a=performance.now();throw this.emit(this.eventBus,{name:"action:error",payload:{actionId:t,name:e,params:r,startTime:i,endTime:a,duration:a-i,error:s}}),s}}emit(e,t){queueMicrotask((()=>{e.emit(t)}))}},A=class{coreState;middlewareEngine;persistenceHandler;transactionManager;metricsCollector;selectorManager;actionManager;updateQueue=Promise.resolve();updateBus=(0,h.createEventBus)();eventBus=(0,h.createEventBus)();executionState;instanceID=e();merge;diff;constructor(e,t,s=u,r){this.executionState={executing:!1,changes:null,pendingChanges:[],middlewares:[],runningMiddleware:null,transactionActive:!1},this.merge=m({deleteMarker:s}),this.diff=v({deleteMarker:s}),this.coreState=new x(e,this.updateBus,this.diff),this.middlewareEngine=new T(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 M(this.eventBus,this.coreState,this.executionState),this.metricsCollector=new P(this.eventBus),this.actionManager=new B(this.eventBus,this.set.bind(this)),this.persistenceHandler.initialize(t),this.setupPersistenceListener(),this.selectorManager=new f(this.get.bind(this),this.eventBus)}isReady(){return this.persistenceHandler.isReady()}state(){return this.executionState}get(e){return this.coreState.get(e??!1)}select(e){return this.selectorManager.createReactiveSelector(e)}register(e){return this.actionManager.register(e)}async dispatch(e,...t){return this.actionManager.dispatch(e,...t)}async set(e,t={}){const s=this.updateQueue.then((()=>this._performUpdate(e,t)));return this.updateQueue=s.catch((()=>{})),s}async _performUpdate(e,t){this.executionState.executing=!0;const s=performance.now();this.emit(this.eventBus,{name:"update:start",payload:{timestamp:s,actionId:t.actionId}});try{if(t.force){const t=this.get(!1),s="function"==typeof e?e(t):e;return this.coreState.applyChanges(s,!0),s}let r;const i=this.get(!1);if("function"==typeof e){const t=e(i);r=t instanceof Promise?await t:t}else r=e;const a=await this.middlewareEngine.executeBlocking(i,r);if(a.blocked)throw a.error||new Error("Update blocked by middleware");const o=this.merge(i,r),n=await this.middlewareEngine.executeTransform(o,r),c=this.merge(o,n),l=this.coreState.applyChanges(c,!1,!1,[r,n]),d=performance.now(),h=this.get(!1);return this.emit(this.eventBus,{name:"update:complete",payload:{deltas:l,duration:d-s,timestamp:Date.now(),actionId:t.actionId,newState:h}}),h}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=[]}}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],r=""===e||0===s.length;return this.updateBus.subscribe("update",(e=>{(r||s.includes(e))&&(t(this.get(!1)),this.metricsCollector.listenerExecutions++)}))}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()}clearPersistenceQueue(){this.persistenceHandler.clearQueue()}dispose(){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.onStoreEvent(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,r)=>{if(s){(console[t]||console.log)("State Update:",r)}return r}}createValidationMiddleware(e){return(t,s)=>{const r=e(t,s);return"boolean"==typeof r?r:(!r.valid&&r.reason&&this._consoleLog("warn","Validation failed:",r.reason),r.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 r={},i={},a=(e,t,s)=>{t.reduce(((e,r,i)=>(i===t.length-1?e[r]=s:e[r]=e[r]??{},e[r])),e)};for(const e of s.deltas){const t=e.path.split(".");a(r,t,e.oldValue),a(i,t,e.newValue)}t.push({timestamp:s.timestamp,changedPaths:s.deltas.map((e=>e.path)),from:r,to:i})}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.onStoreEvent("update:complete",(s=>{this.isTimeTraveling||s.blocked||(t=[],e=0)}));this.unsubscribers.push(s);const r=()=>this.stateHistory.length,i=()=>e<r()-1,a=()=>t.length>0;return{canUndo:i,canRedo:a,undo:async()=>{if(!i())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(!a())return;const s=t.shift();e--,this.isTimeTraveling=!0,await this.store.set({...s.state},{force:!0}),this.isTimeTraveling=!1},length:r,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),r=document.createElement("a");r.href=s,r.download=`store-observer-session-${(new Date).toISOString()}.json`,r.click(),URL.revokeObjectURL(s)}importSession(e){return new Promise(((t,s)=>{const r=new FileReader;r.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)}},r.onerror=e=>s(e),r.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{B as ActionManager,u as DELETE_SYMBOL,A as ReactiveDataStore,H as StoreObserver,b as createDerivePaths,v as createDiff,m as createMerge,E as derivePaths,S as diff,g as merge,p as shallowClone};
|