@asaidimu/utils-store 7.0.0 → 7.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.mts +225 -20
- package/index.d.ts +225 -20
- package/index.js +1 -1
- package/index.mjs +1 -1
- package/package.json +1 -1
package/index.d.mts
CHANGED
|
@@ -50,132 +50,237 @@ interface SimplePersistence<T> {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
|
-
* Utility type for representing partial updates to the state.
|
|
53
|
+
* Utility type for representing partial updates to the state, allowing deep nesting.
|
|
54
|
+
* It makes all properties optional and applies the same transformation recursively
|
|
55
|
+
* to nested objects and array elements, allowing for selective updates while
|
|
56
|
+
* preserving the original structure. It also includes the original type T and
|
|
57
|
+
* undefined as possibilities for the top level and nested values.
|
|
54
58
|
*/
|
|
55
59
|
type DeepPartial<T> = T extends object ? T extends readonly (infer U)[] ? readonly (DeepPartial<U> | undefined)[] | undefined | T : T extends (infer U)[] ? (DeepPartial<U> | undefined)[] | undefined | T : {
|
|
56
60
|
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> | undefined : T[K] | undefined;
|
|
57
61
|
} | undefined | T : T | undefined;
|
|
58
62
|
/**
|
|
59
|
-
* Interface for performance metrics of the state.
|
|
63
|
+
* Interface for performance and execution metrics of the state store.
|
|
60
64
|
*/
|
|
61
65
|
interface StoreMetrics {
|
|
66
|
+
/** The number of times the state has been successfully updated. */
|
|
62
67
|
updateCount: number;
|
|
68
|
+
/** The total number of listener functions executed in response to state changes. */
|
|
63
69
|
listenerExecutions: number;
|
|
70
|
+
/** The average time taken for a state update process to complete (in milliseconds). */
|
|
64
71
|
averageUpdateTime: number;
|
|
72
|
+
/** The size (e.g., number of paths changed) of the largest single state update. */
|
|
65
73
|
largestUpdateSize: number;
|
|
74
|
+
/** List of state paths that trigger the most listener executions. */
|
|
66
75
|
mostActiveListenerPaths: string[];
|
|
76
|
+
/** The total number of update attempts (including blocked ones). */
|
|
67
77
|
totalUpdates: number;
|
|
78
|
+
/** The number of updates that were blocked by blocking middleware. */
|
|
68
79
|
blockedUpdates: number;
|
|
80
|
+
/** The average duration of a state update cycle (in milliseconds). */
|
|
69
81
|
averageUpdateDuration: number;
|
|
82
|
+
/** The total number of middleware functions executed. */
|
|
70
83
|
middlewareExecutions: number;
|
|
84
|
+
/** The total number of transactions initiated. */
|
|
71
85
|
transactionCount: number;
|
|
86
|
+
/** The total number of store events fired. */
|
|
72
87
|
totalEventsFired: number;
|
|
88
|
+
/** The total number of actions dispatched. */
|
|
73
89
|
totalActionsDispatched: number;
|
|
90
|
+
/** The total number of actions that completed successfully. */
|
|
74
91
|
totalActionsSucceeded: number;
|
|
92
|
+
/** The total number of actions that failed with an error. */
|
|
75
93
|
totalActionsFailed: number;
|
|
94
|
+
/** The average duration of an action execution (in milliseconds). */
|
|
76
95
|
averageActionDuration: number;
|
|
77
96
|
}
|
|
78
97
|
/**
|
|
79
|
-
* Extended store state for monitoring execution status
|
|
98
|
+
* Extended store state for monitoring the current execution status (e.g., if an update is in progress).
|
|
80
99
|
*/
|
|
81
100
|
interface StoreExecutionState<T> {
|
|
101
|
+
/** Indicates if a state update process is currently executing. */
|
|
82
102
|
executing: boolean;
|
|
103
|
+
/** The changes (DeepPartial) currently being processed in the execution cycle. Null if none. */
|
|
83
104
|
changes: DeepPartial<T> | null;
|
|
105
|
+
/** A queue of pending state update functions/objects to be applied sequentially. */
|
|
84
106
|
pendingChanges: Array<StateUpdater<T>>;
|
|
107
|
+
/** Names of all currently registered middlewares. */
|
|
85
108
|
middlewares: string[];
|
|
109
|
+
/** Details of the middleware currently running. Null if none. */
|
|
86
110
|
runningMiddleware: {
|
|
87
111
|
id: string;
|
|
88
112
|
name: string;
|
|
89
113
|
startTime: number;
|
|
90
114
|
} | null;
|
|
115
|
+
/** Indicates if the store is currently within an active transaction block. */
|
|
91
116
|
transactionActive: boolean;
|
|
92
117
|
}
|
|
93
118
|
/**
|
|
94
|
-
* Event types emitted by the state for observability
|
|
119
|
+
* Event types emitted by the state store for observability and debugging.
|
|
95
120
|
*/
|
|
96
121
|
type StoreEvent = "update:start" | "update:complete" | "middleware:start" | "middleware:complete" | "middleware:error" | "middleware:blocked" | "middleware:executed" | "transaction:start" | "transaction:complete" | "transaction:error" | "persistence:ready" | "persistence:queued" | "persistence:success" | "persistence:retry" | "persistence:failed" | "persistence:queue_cleared" | "persistence:init_error" | "action:start" | "action:complete" | "action:error" | "selector:accessed" | "selector:changed";
|
|
122
|
+
/**
|
|
123
|
+
* Payload for the 'selector:changed' event.
|
|
124
|
+
*/
|
|
97
125
|
interface SelectorChangedPayload<S> {
|
|
126
|
+
/** Unique identifier of the selector. */
|
|
98
127
|
selectorId: string;
|
|
128
|
+
/** The new computed result of the selector. */
|
|
99
129
|
newResult: S;
|
|
130
|
+
/** Timestamp of when the change occurred. */
|
|
100
131
|
timestamp: number;
|
|
101
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Maps each `StoreEvent` type to its corresponding event payload interface.
|
|
135
|
+
* Uses conditional types to ensure type safety for event listeners.
|
|
136
|
+
*/
|
|
102
137
|
type StoreEvents = {
|
|
103
138
|
[K in StoreEvent]: K extends "update:complete" ? {
|
|
139
|
+
/** List of state changes (deltas) applied in the update. */
|
|
104
140
|
deltas: StateDelta[];
|
|
141
|
+
/** Total duration of the update process (in milliseconds). */
|
|
105
142
|
duration: number;
|
|
143
|
+
/** Timestamp of the update completion. */
|
|
106
144
|
timestamp: number;
|
|
145
|
+
/** Optional ID of the action that triggered the update. */
|
|
107
146
|
actionId?: string;
|
|
147
|
+
/** The resulting new state after the update (may be a partial/transformed state). */
|
|
108
148
|
newState: any;
|
|
149
|
+
/** True if the update was blocked by a middleware. */
|
|
109
150
|
blocked?: boolean;
|
|
151
|
+
/** Any error that occurred during the update. */
|
|
110
152
|
error?: any;
|
|
111
153
|
} : K extends "selector:accessed" ? SelectorAccessedPayload : K extends "selector:changed" ? SelectorChangedPayload<any> : K extends "action:start" ? ActionStartPayload : K extends "action:complete" ? ActionCompletePayload : K extends "action:error" ? ActionErrorPayload : K extends "middleware:start" | "middleware:complete" | "middleware:error" | "middleware:blocked" | "middleware:executed" ? MiddlewareExecution : K extends "transaction:start" | "transaction:complete" | "transaction:error" ? {
|
|
112
154
|
transactionId: string;
|
|
113
155
|
timestamp: number;
|
|
114
156
|
} : K extends "persistence:queued" ? PersistenceQueuedPayload : K extends "persistence:success" ? PersistenceSuccessPayload : K extends "persistence:retry" ? PersistenceRetryPayload : K extends "persistence:failed" ? PersistenceFailedPayload : K extends "persistence:queue_cleared" ? PersistenceQueueClearedPayload : K extends "persistence:init_error" ? PersistenceInitErrorPayload : any;
|
|
115
157
|
};
|
|
158
|
+
/**
|
|
159
|
+
* Payload for the 'selector:accessed' event.
|
|
160
|
+
*/
|
|
116
161
|
interface SelectorAccessedPayload {
|
|
162
|
+
/** Unique identifier of the selector. */
|
|
117
163
|
selectorId: string;
|
|
164
|
+
/** List of state paths accessed during the selector computation. */
|
|
118
165
|
accessedPaths: string[];
|
|
166
|
+
/** Duration of the selector computation (in milliseconds). */
|
|
119
167
|
duration: number;
|
|
168
|
+
/** Timestamp of the access. */
|
|
120
169
|
timestamp: number;
|
|
121
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Payload for the 'action:start' event.
|
|
173
|
+
*/
|
|
122
174
|
interface ActionStartPayload {
|
|
175
|
+
/** Unique identifier for the action execution. */
|
|
123
176
|
actionId: string;
|
|
177
|
+
/** Name of the action function. */
|
|
124
178
|
name: string;
|
|
179
|
+
/** The parameters passed to the action function. */
|
|
125
180
|
params: any[];
|
|
181
|
+
/** Timestamp of when the action execution started. */
|
|
126
182
|
timestamp: number;
|
|
127
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Payload for the 'action:complete' event (successful action execution).
|
|
186
|
+
*/
|
|
128
187
|
interface ActionCompletePayload {
|
|
188
|
+
/** Unique identifier for the action execution. */
|
|
129
189
|
actionId: string;
|
|
190
|
+
/** Name of the action function. */
|
|
130
191
|
name: string;
|
|
192
|
+
/** The parameters passed to the action function. */
|
|
131
193
|
params: any[];
|
|
194
|
+
/** Timestamp of when the action execution started. */
|
|
132
195
|
startTime: number;
|
|
196
|
+
/** Timestamp of when the action execution completed. */
|
|
133
197
|
endTime: number;
|
|
198
|
+
/** Total duration of the action execution (in milliseconds). */
|
|
134
199
|
duration: number;
|
|
200
|
+
/** The result returned by the action function. */
|
|
135
201
|
result: any;
|
|
136
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* Payload for the 'action:error' event (failed action execution).
|
|
205
|
+
*/
|
|
137
206
|
interface ActionErrorPayload {
|
|
207
|
+
/** Unique identifier for the action execution. */
|
|
138
208
|
actionId: string;
|
|
209
|
+
/** Name of the action function. */
|
|
139
210
|
name: string;
|
|
211
|
+
/** The parameters passed to the action function. */
|
|
140
212
|
params: any[];
|
|
213
|
+
/** Timestamp of when the action execution started. */
|
|
141
214
|
startTime: number;
|
|
215
|
+
/** Timestamp of when the action execution ended (with error). */
|
|
142
216
|
endTime: number;
|
|
217
|
+
/** Total duration of the action execution (in milliseconds). */
|
|
143
218
|
duration: number;
|
|
219
|
+
/** The error object. */
|
|
144
220
|
error: any;
|
|
145
221
|
}
|
|
146
222
|
/**
|
|
147
|
-
* Type for
|
|
223
|
+
* Type for a generic middleware function.
|
|
224
|
+
* It receives the current state and the incoming update, and can return
|
|
225
|
+
* a modified `DeepPartial<T>` (transforming the update) or `void`.
|
|
148
226
|
*/
|
|
149
227
|
type Middleware<T> = (state: T, update: DeepPartial<T>) => Promise<DeepPartial<T>> | Promise<void> | DeepPartial<T> | void;
|
|
150
228
|
/**
|
|
151
|
-
* Middleware execution information for event emissions
|
|
229
|
+
* Middleware execution information for event emissions and tracking.
|
|
152
230
|
*/
|
|
153
231
|
interface MiddlewareExecution {
|
|
232
|
+
/** Unique identifier for the middleware instance. */
|
|
154
233
|
id: string;
|
|
234
|
+
/** Name of the middleware. */
|
|
155
235
|
name: string;
|
|
236
|
+
/** Timestamp of when the middleware execution started. */
|
|
156
237
|
startTime: number;
|
|
238
|
+
/** Timestamp of when the middleware execution completed. */
|
|
157
239
|
endTime: number;
|
|
240
|
+
/** Total duration of the middleware execution (in milliseconds). */
|
|
158
241
|
duration: number;
|
|
242
|
+
/** True if the middleware blocked the update. */
|
|
159
243
|
blocked: boolean;
|
|
244
|
+
/** Error object if the middleware failed. */
|
|
160
245
|
error?: Error;
|
|
246
|
+
/** List of state changes (deltas) that resulted from this middleware's transformation. */
|
|
161
247
|
deltas: StateDelta[];
|
|
162
248
|
}
|
|
249
|
+
/**
|
|
250
|
+
* Represents a single change to the state, detailing the path, old value, and new value.
|
|
251
|
+
*/
|
|
163
252
|
interface StateDelta {
|
|
253
|
+
/** Dot-separated path to the changed property (e.g., "user.profile.name"). */
|
|
164
254
|
path: string;
|
|
255
|
+
/** The value of the property *before* the update. */
|
|
165
256
|
oldValue: any;
|
|
257
|
+
/** The value of the property *after* the update. */
|
|
166
258
|
newValue: any;
|
|
167
259
|
}
|
|
168
260
|
/**
|
|
169
|
-
* Represents a state update, which can be
|
|
261
|
+
* Represents a state update, which can be:
|
|
262
|
+
* 1. The full new state (`T`).
|
|
263
|
+
* 2. A partial update object (`DeepPartial<T>`).
|
|
264
|
+
* 3. A function that receives the current state and returns a partial update (sync or async).
|
|
170
265
|
*/
|
|
171
266
|
type StateUpdater<T> = T | DeepPartial<T> | ((state: T) => DeepPartial<T> | Promise<DeepPartial<T>>);
|
|
267
|
+
/**
|
|
268
|
+
* A unique symbol used within DeepPartial objects to explicitly signal that a property
|
|
269
|
+
* should be deleted from the state object.
|
|
270
|
+
*/
|
|
172
271
|
declare const DELETE_SYMBOL: unique symbol;
|
|
173
272
|
/**
|
|
174
273
|
* Core types for the reactive data store
|
|
175
274
|
*/
|
|
275
|
+
/**
|
|
276
|
+
* Type for a Transform Middleware function.
|
|
277
|
+
* It modifies (transforms) the incoming changes and must return a `DeepPartial<T>`.
|
|
278
|
+
*/
|
|
176
279
|
type TransformMiddleware<T> = (state: T, changes: DeepPartial<T>) => Promise<DeepPartial<T>> | DeepPartial<T>;
|
|
177
280
|
/**
|
|
178
|
-
* Type for
|
|
281
|
+
* Type for a Blocking Middleware function.
|
|
282
|
+
* It determines whether the state update should proceed or be blocked.
|
|
283
|
+
* It returns a boolean or an object containing a `block` boolean and an optional `error`.
|
|
179
284
|
*/
|
|
180
285
|
type BlockingMiddleware<T> = (state: T, changes: DeepPartial<T>) => Promise<boolean | {
|
|
181
286
|
block: boolean;
|
|
@@ -185,23 +290,46 @@ type BlockingMiddleware<T> = (state: T, changes: DeepPartial<T>) => Promise<bool
|
|
|
185
290
|
error?: Error;
|
|
186
291
|
};
|
|
187
292
|
/**
|
|
188
|
-
* Type representing the configuration object passed to `use
|
|
293
|
+
* Type representing the configuration object passed to the `use` method to register a middleware.
|
|
189
294
|
*/
|
|
190
295
|
interface MiddlewareConfig<T> {
|
|
296
|
+
/** The middleware function (can be a transform or blocking middleware). */
|
|
191
297
|
action: TransformMiddleware<T> | BlockingMiddleware<T>;
|
|
298
|
+
/** An optional, human-readable name for the middleware. */
|
|
192
299
|
name?: string;
|
|
300
|
+
/** If true, the middleware is treated as a blocking middleware (must return a boolean or `{ block: boolean }`). */
|
|
193
301
|
block?: boolean;
|
|
194
302
|
}
|
|
303
|
+
/**
|
|
304
|
+
* Interface for a reactive selector result, providing access to the value and subscription capabilities.
|
|
305
|
+
*/
|
|
195
306
|
interface ReactiveSelector<S> {
|
|
307
|
+
/** Unique identifier for the selector. */
|
|
196
308
|
id: string;
|
|
309
|
+
/** Function to get the current computed value of the selector. */
|
|
197
310
|
get: () => S;
|
|
311
|
+
/**
|
|
312
|
+
* Subscribes a callback function to run whenever the selector's result changes.
|
|
313
|
+
* Returns an unsubscribe function.
|
|
314
|
+
*/
|
|
198
315
|
subscribe: (callback: (state: S) => void) => () => void;
|
|
199
316
|
}
|
|
200
317
|
/**
|
|
201
|
-
* Interface defining the contract for the data state.
|
|
318
|
+
* Interface defining the contract for the core data state store.
|
|
319
|
+
* T must be an object type.
|
|
202
320
|
*/
|
|
203
321
|
interface DataStore<T extends object> {
|
|
322
|
+
/**
|
|
323
|
+
* Gets the current state of the store.
|
|
324
|
+
* @param clone If true, returns a deep clone of the state; otherwise, returns the internal state reference.
|
|
325
|
+
* @returns The current state T.
|
|
326
|
+
*/
|
|
204
327
|
get(clone?: boolean): T;
|
|
328
|
+
/**
|
|
329
|
+
* Registers a named action function that can modify the state.
|
|
330
|
+
* @param action The action configuration object.
|
|
331
|
+
* @returns A function to unregister the action.
|
|
332
|
+
*/
|
|
205
333
|
register<R extends any[]>(action: {
|
|
206
334
|
name: string;
|
|
207
335
|
fn: (state: T, ...args: R) => DeepPartial<T> | Promise<DeepPartial<T>>;
|
|
@@ -210,67 +338,144 @@ interface DataStore<T extends object> {
|
|
|
210
338
|
condition?: (previous: R, current: R) => boolean;
|
|
211
339
|
};
|
|
212
340
|
}): () => void;
|
|
341
|
+
/**
|
|
342
|
+
* Executes (dispatches) a previously registered action by its name.
|
|
343
|
+
* @param name The name of the action.
|
|
344
|
+
* @param args The parameters to pass to the action function.
|
|
345
|
+
* @returns A promise that resolves to the final state after the action and subsequent updates are complete.
|
|
346
|
+
*/
|
|
213
347
|
dispatch<R extends any[]>(name: string, ...args: R): Promise<T>;
|
|
348
|
+
/**
|
|
349
|
+
* Sets or updates the state using a StateUpdater.
|
|
350
|
+
* @param update The new state, partial state, or a function returning a partial state.
|
|
351
|
+
* @param options Configuration options for the set operation.
|
|
352
|
+
* @returns A promise that resolves to the current state when the update is complete.
|
|
353
|
+
*/
|
|
214
354
|
set(update: StateUpdater<T>, options?: {
|
|
215
355
|
force?: boolean;
|
|
216
356
|
actionId?: string;
|
|
217
|
-
}): Promise<
|
|
357
|
+
}): Promise<T>;
|
|
358
|
+
/**
|
|
359
|
+
* Creates a reactive selector that computes a derived value and tracks dependencies.
|
|
360
|
+
* @param selector A function to compute the derived state value S from the full state T.
|
|
361
|
+
* @returns A `ReactiveSelector<S>` object.
|
|
362
|
+
*/
|
|
218
363
|
select<S>(selector: (state: T) => S): ReactiveSelector<S>;
|
|
219
|
-
/**
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
|
|
364
|
+
/**
|
|
365
|
+
* Subscribes a callback to run when the data at the specified path(s) changes.
|
|
366
|
+
* @param path A single path string or an array of path strings to watch.
|
|
367
|
+
* @param callback The function to execute when a change occurs in the watched path(s).
|
|
368
|
+
* @returns An unsubscribe function.
|
|
369
|
+
*/
|
|
223
370
|
watch(path: string | Array<string>, callback: (state: T) => void): () => void;
|
|
371
|
+
/**
|
|
372
|
+
* Executes an operation function within a transaction block.
|
|
373
|
+
* All state updates (`set` or actions) within the transaction are batched and applied atomically (all or nothing).
|
|
374
|
+
* @param operation The function containing the state updates.
|
|
375
|
+
* @returns A promise that resolves to the return value of the operation function.
|
|
376
|
+
*/
|
|
224
377
|
transaction<R>(operation: () => R | Promise<R>): Promise<R>;
|
|
378
|
+
/**
|
|
379
|
+
* Registers a middleware function to intercept state updates.
|
|
380
|
+
* @param props The middleware configuration.
|
|
381
|
+
* @returns A function to unregister the middleware.
|
|
382
|
+
*/
|
|
225
383
|
use(props: MiddlewareConfig<T>): () => boolean;
|
|
226
|
-
/**
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
|
|
384
|
+
/**
|
|
385
|
+
* Subscribes a listener to a specific store event type.
|
|
386
|
+
* @param event The type of store event to listen for.
|
|
387
|
+
* @param listener The callback function to execute when the event fires.
|
|
388
|
+
* @returns An unsubscribe function.
|
|
389
|
+
*/
|
|
230
390
|
on(event: StoreEvent, listener: (data: any) => void): () => void;
|
|
391
|
+
/**
|
|
392
|
+
* Returns the unique identifier of the store instance.
|
|
393
|
+
*/
|
|
231
394
|
id(): string;
|
|
395
|
+
/**
|
|
396
|
+
* Checks whether the store is fully initialized and ready for use.
|
|
397
|
+
*/
|
|
232
398
|
isReady(): boolean;
|
|
399
|
+
/**
|
|
400
|
+
* Returns a readonly snapshot of the current execution state of the store.
|
|
401
|
+
*/
|
|
233
402
|
state(): Readonly<StoreExecutionState<T>>;
|
|
234
403
|
}
|
|
404
|
+
/** Payload for the 'persistence:queued' event. */
|
|
235
405
|
interface PersistenceQueuedPayload {
|
|
406
|
+
/** Unique ID for the persistence task. */
|
|
236
407
|
taskId: string;
|
|
408
|
+
/** Paths that were changed and triggered persistence. */
|
|
237
409
|
changedPaths: string[];
|
|
410
|
+
/** The current number of tasks waiting in the persistence queue. */
|
|
238
411
|
queueSize: number;
|
|
412
|
+
/** Timestamp of when the task was queued. */
|
|
239
413
|
timestamp: number;
|
|
240
414
|
}
|
|
415
|
+
/** Payload for the 'persistence:success' event. */
|
|
241
416
|
interface PersistenceSuccessPayload {
|
|
417
|
+
/** Unique ID for the persistence task. */
|
|
242
418
|
taskId: string;
|
|
419
|
+
/** Paths that were successfully persisted. */
|
|
243
420
|
changedPaths: string[];
|
|
421
|
+
/** Duration of the persistence operation (in milliseconds). */
|
|
244
422
|
duration: number;
|
|
423
|
+
/** Timestamp of the success. */
|
|
245
424
|
timestamp: number;
|
|
246
425
|
}
|
|
426
|
+
/** Payload for the 'persistence:retry' event. */
|
|
247
427
|
interface PersistenceRetryPayload {
|
|
428
|
+
/** Unique ID for the persistence task. */
|
|
248
429
|
taskId: string;
|
|
430
|
+
/** Current retry attempt number. */
|
|
249
431
|
attempt: number;
|
|
432
|
+
/** Maximum allowed retries. */
|
|
250
433
|
maxRetries: number;
|
|
434
|
+
/** Time until the next retry attempt (in milliseconds). */
|
|
251
435
|
nextRetryIn: number;
|
|
436
|
+
/** The error that triggered the retry. */
|
|
252
437
|
error: any;
|
|
438
|
+
/** Timestamp of the retry event. */
|
|
253
439
|
timestamp: number;
|
|
254
440
|
}
|
|
441
|
+
/** Payload for the 'persistence:failed' event. */
|
|
255
442
|
interface PersistenceFailedPayload {
|
|
443
|
+
/** Unique ID for the persistence task. */
|
|
256
444
|
taskId: string;
|
|
445
|
+
/** Paths that failed to persist. */
|
|
257
446
|
changedPaths: string[];
|
|
447
|
+
/** Total number of attempts made. */
|
|
258
448
|
attempts: number;
|
|
449
|
+
/** The final error object. */
|
|
259
450
|
error: any;
|
|
451
|
+
/** Timestamp of the final failure. */
|
|
260
452
|
timestamp: number;
|
|
261
453
|
}
|
|
454
|
+
/** Payload for the 'persistence:queue_cleared' event. */
|
|
262
455
|
interface PersistenceQueueClearedPayload {
|
|
456
|
+
/** The number of persistence tasks that were cleared from the queue. */
|
|
263
457
|
clearedTasks: number;
|
|
458
|
+
/** Timestamp of when the queue was cleared. */
|
|
264
459
|
timestamp: number;
|
|
265
460
|
}
|
|
461
|
+
/** Payload for the 'persistence:init_error' event. */
|
|
266
462
|
interface PersistenceInitErrorPayload {
|
|
463
|
+
/** The error that occurred during persistence initialization. */
|
|
267
464
|
error: any;
|
|
465
|
+
/** Timestamp of the error. */
|
|
268
466
|
timestamp: number;
|
|
269
467
|
}
|
|
468
|
+
/**
|
|
469
|
+
* Interface describing a registered state action, including its metadata and debounce configuration.
|
|
470
|
+
*/
|
|
270
471
|
type StoreAction<T, R extends any[] = any[]> = {
|
|
472
|
+
/** Unique identifier for the action definition. */
|
|
271
473
|
id: string;
|
|
474
|
+
/** Name of the action, used for dispatching. */
|
|
272
475
|
name: string;
|
|
476
|
+
/** The actual function that takes state and arguments, and returns a state update. */
|
|
273
477
|
action: (state: T, ...args: R) => DeepPartial<T> | Promise<DeepPartial<T>>;
|
|
478
|
+
/** Optional configuration for debouncing action execution. */
|
|
274
479
|
debounce?: {
|
|
275
480
|
/** Active timer reference, if debouncing */
|
|
276
481
|
timer?: ReturnType<typeof setTimeout>;
|
|
@@ -355,7 +560,7 @@ declare class ReactiveDataStore<T extends object> implements DataStore<T> {
|
|
|
355
560
|
set(update: StateUpdater<T>, options?: {
|
|
356
561
|
force?: boolean;
|
|
357
562
|
actionId?: string;
|
|
358
|
-
}): Promise<
|
|
563
|
+
}): Promise<T>;
|
|
359
564
|
/**
|
|
360
565
|
* Internal logic for performing a single, sequential state update.
|
|
361
566
|
*/
|
package/index.d.ts
CHANGED
|
@@ -50,132 +50,237 @@ interface SimplePersistence<T> {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
|
-
* Utility type for representing partial updates to the state.
|
|
53
|
+
* Utility type for representing partial updates to the state, allowing deep nesting.
|
|
54
|
+
* It makes all properties optional and applies the same transformation recursively
|
|
55
|
+
* to nested objects and array elements, allowing for selective updates while
|
|
56
|
+
* preserving the original structure. It also includes the original type T and
|
|
57
|
+
* undefined as possibilities for the top level and nested values.
|
|
54
58
|
*/
|
|
55
59
|
type DeepPartial<T> = T extends object ? T extends readonly (infer U)[] ? readonly (DeepPartial<U> | undefined)[] | undefined | T : T extends (infer U)[] ? (DeepPartial<U> | undefined)[] | undefined | T : {
|
|
56
60
|
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> | undefined : T[K] | undefined;
|
|
57
61
|
} | undefined | T : T | undefined;
|
|
58
62
|
/**
|
|
59
|
-
* Interface for performance metrics of the state.
|
|
63
|
+
* Interface for performance and execution metrics of the state store.
|
|
60
64
|
*/
|
|
61
65
|
interface StoreMetrics {
|
|
66
|
+
/** The number of times the state has been successfully updated. */
|
|
62
67
|
updateCount: number;
|
|
68
|
+
/** The total number of listener functions executed in response to state changes. */
|
|
63
69
|
listenerExecutions: number;
|
|
70
|
+
/** The average time taken for a state update process to complete (in milliseconds). */
|
|
64
71
|
averageUpdateTime: number;
|
|
72
|
+
/** The size (e.g., number of paths changed) of the largest single state update. */
|
|
65
73
|
largestUpdateSize: number;
|
|
74
|
+
/** List of state paths that trigger the most listener executions. */
|
|
66
75
|
mostActiveListenerPaths: string[];
|
|
76
|
+
/** The total number of update attempts (including blocked ones). */
|
|
67
77
|
totalUpdates: number;
|
|
78
|
+
/** The number of updates that were blocked by blocking middleware. */
|
|
68
79
|
blockedUpdates: number;
|
|
80
|
+
/** The average duration of a state update cycle (in milliseconds). */
|
|
69
81
|
averageUpdateDuration: number;
|
|
82
|
+
/** The total number of middleware functions executed. */
|
|
70
83
|
middlewareExecutions: number;
|
|
84
|
+
/** The total number of transactions initiated. */
|
|
71
85
|
transactionCount: number;
|
|
86
|
+
/** The total number of store events fired. */
|
|
72
87
|
totalEventsFired: number;
|
|
88
|
+
/** The total number of actions dispatched. */
|
|
73
89
|
totalActionsDispatched: number;
|
|
90
|
+
/** The total number of actions that completed successfully. */
|
|
74
91
|
totalActionsSucceeded: number;
|
|
92
|
+
/** The total number of actions that failed with an error. */
|
|
75
93
|
totalActionsFailed: number;
|
|
94
|
+
/** The average duration of an action execution (in milliseconds). */
|
|
76
95
|
averageActionDuration: number;
|
|
77
96
|
}
|
|
78
97
|
/**
|
|
79
|
-
* Extended store state for monitoring execution status
|
|
98
|
+
* Extended store state for monitoring the current execution status (e.g., if an update is in progress).
|
|
80
99
|
*/
|
|
81
100
|
interface StoreExecutionState<T> {
|
|
101
|
+
/** Indicates if a state update process is currently executing. */
|
|
82
102
|
executing: boolean;
|
|
103
|
+
/** The changes (DeepPartial) currently being processed in the execution cycle. Null if none. */
|
|
83
104
|
changes: DeepPartial<T> | null;
|
|
105
|
+
/** A queue of pending state update functions/objects to be applied sequentially. */
|
|
84
106
|
pendingChanges: Array<StateUpdater<T>>;
|
|
107
|
+
/** Names of all currently registered middlewares. */
|
|
85
108
|
middlewares: string[];
|
|
109
|
+
/** Details of the middleware currently running. Null if none. */
|
|
86
110
|
runningMiddleware: {
|
|
87
111
|
id: string;
|
|
88
112
|
name: string;
|
|
89
113
|
startTime: number;
|
|
90
114
|
} | null;
|
|
115
|
+
/** Indicates if the store is currently within an active transaction block. */
|
|
91
116
|
transactionActive: boolean;
|
|
92
117
|
}
|
|
93
118
|
/**
|
|
94
|
-
* Event types emitted by the state for observability
|
|
119
|
+
* Event types emitted by the state store for observability and debugging.
|
|
95
120
|
*/
|
|
96
121
|
type StoreEvent = "update:start" | "update:complete" | "middleware:start" | "middleware:complete" | "middleware:error" | "middleware:blocked" | "middleware:executed" | "transaction:start" | "transaction:complete" | "transaction:error" | "persistence:ready" | "persistence:queued" | "persistence:success" | "persistence:retry" | "persistence:failed" | "persistence:queue_cleared" | "persistence:init_error" | "action:start" | "action:complete" | "action:error" | "selector:accessed" | "selector:changed";
|
|
122
|
+
/**
|
|
123
|
+
* Payload for the 'selector:changed' event.
|
|
124
|
+
*/
|
|
97
125
|
interface SelectorChangedPayload<S> {
|
|
126
|
+
/** Unique identifier of the selector. */
|
|
98
127
|
selectorId: string;
|
|
128
|
+
/** The new computed result of the selector. */
|
|
99
129
|
newResult: S;
|
|
130
|
+
/** Timestamp of when the change occurred. */
|
|
100
131
|
timestamp: number;
|
|
101
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* Maps each `StoreEvent` type to its corresponding event payload interface.
|
|
135
|
+
* Uses conditional types to ensure type safety for event listeners.
|
|
136
|
+
*/
|
|
102
137
|
type StoreEvents = {
|
|
103
138
|
[K in StoreEvent]: K extends "update:complete" ? {
|
|
139
|
+
/** List of state changes (deltas) applied in the update. */
|
|
104
140
|
deltas: StateDelta[];
|
|
141
|
+
/** Total duration of the update process (in milliseconds). */
|
|
105
142
|
duration: number;
|
|
143
|
+
/** Timestamp of the update completion. */
|
|
106
144
|
timestamp: number;
|
|
145
|
+
/** Optional ID of the action that triggered the update. */
|
|
107
146
|
actionId?: string;
|
|
147
|
+
/** The resulting new state after the update (may be a partial/transformed state). */
|
|
108
148
|
newState: any;
|
|
149
|
+
/** True if the update was blocked by a middleware. */
|
|
109
150
|
blocked?: boolean;
|
|
151
|
+
/** Any error that occurred during the update. */
|
|
110
152
|
error?: any;
|
|
111
153
|
} : K extends "selector:accessed" ? SelectorAccessedPayload : K extends "selector:changed" ? SelectorChangedPayload<any> : K extends "action:start" ? ActionStartPayload : K extends "action:complete" ? ActionCompletePayload : K extends "action:error" ? ActionErrorPayload : K extends "middleware:start" | "middleware:complete" | "middleware:error" | "middleware:blocked" | "middleware:executed" ? MiddlewareExecution : K extends "transaction:start" | "transaction:complete" | "transaction:error" ? {
|
|
112
154
|
transactionId: string;
|
|
113
155
|
timestamp: number;
|
|
114
156
|
} : K extends "persistence:queued" ? PersistenceQueuedPayload : K extends "persistence:success" ? PersistenceSuccessPayload : K extends "persistence:retry" ? PersistenceRetryPayload : K extends "persistence:failed" ? PersistenceFailedPayload : K extends "persistence:queue_cleared" ? PersistenceQueueClearedPayload : K extends "persistence:init_error" ? PersistenceInitErrorPayload : any;
|
|
115
157
|
};
|
|
158
|
+
/**
|
|
159
|
+
* Payload for the 'selector:accessed' event.
|
|
160
|
+
*/
|
|
116
161
|
interface SelectorAccessedPayload {
|
|
162
|
+
/** Unique identifier of the selector. */
|
|
117
163
|
selectorId: string;
|
|
164
|
+
/** List of state paths accessed during the selector computation. */
|
|
118
165
|
accessedPaths: string[];
|
|
166
|
+
/** Duration of the selector computation (in milliseconds). */
|
|
119
167
|
duration: number;
|
|
168
|
+
/** Timestamp of the access. */
|
|
120
169
|
timestamp: number;
|
|
121
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Payload for the 'action:start' event.
|
|
173
|
+
*/
|
|
122
174
|
interface ActionStartPayload {
|
|
175
|
+
/** Unique identifier for the action execution. */
|
|
123
176
|
actionId: string;
|
|
177
|
+
/** Name of the action function. */
|
|
124
178
|
name: string;
|
|
179
|
+
/** The parameters passed to the action function. */
|
|
125
180
|
params: any[];
|
|
181
|
+
/** Timestamp of when the action execution started. */
|
|
126
182
|
timestamp: number;
|
|
127
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Payload for the 'action:complete' event (successful action execution).
|
|
186
|
+
*/
|
|
128
187
|
interface ActionCompletePayload {
|
|
188
|
+
/** Unique identifier for the action execution. */
|
|
129
189
|
actionId: string;
|
|
190
|
+
/** Name of the action function. */
|
|
130
191
|
name: string;
|
|
192
|
+
/** The parameters passed to the action function. */
|
|
131
193
|
params: any[];
|
|
194
|
+
/** Timestamp of when the action execution started. */
|
|
132
195
|
startTime: number;
|
|
196
|
+
/** Timestamp of when the action execution completed. */
|
|
133
197
|
endTime: number;
|
|
198
|
+
/** Total duration of the action execution (in milliseconds). */
|
|
134
199
|
duration: number;
|
|
200
|
+
/** The result returned by the action function. */
|
|
135
201
|
result: any;
|
|
136
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* Payload for the 'action:error' event (failed action execution).
|
|
205
|
+
*/
|
|
137
206
|
interface ActionErrorPayload {
|
|
207
|
+
/** Unique identifier for the action execution. */
|
|
138
208
|
actionId: string;
|
|
209
|
+
/** Name of the action function. */
|
|
139
210
|
name: string;
|
|
211
|
+
/** The parameters passed to the action function. */
|
|
140
212
|
params: any[];
|
|
213
|
+
/** Timestamp of when the action execution started. */
|
|
141
214
|
startTime: number;
|
|
215
|
+
/** Timestamp of when the action execution ended (with error). */
|
|
142
216
|
endTime: number;
|
|
217
|
+
/** Total duration of the action execution (in milliseconds). */
|
|
143
218
|
duration: number;
|
|
219
|
+
/** The error object. */
|
|
144
220
|
error: any;
|
|
145
221
|
}
|
|
146
222
|
/**
|
|
147
|
-
* Type for
|
|
223
|
+
* Type for a generic middleware function.
|
|
224
|
+
* It receives the current state and the incoming update, and can return
|
|
225
|
+
* a modified `DeepPartial<T>` (transforming the update) or `void`.
|
|
148
226
|
*/
|
|
149
227
|
type Middleware<T> = (state: T, update: DeepPartial<T>) => Promise<DeepPartial<T>> | Promise<void> | DeepPartial<T> | void;
|
|
150
228
|
/**
|
|
151
|
-
* Middleware execution information for event emissions
|
|
229
|
+
* Middleware execution information for event emissions and tracking.
|
|
152
230
|
*/
|
|
153
231
|
interface MiddlewareExecution {
|
|
232
|
+
/** Unique identifier for the middleware instance. */
|
|
154
233
|
id: string;
|
|
234
|
+
/** Name of the middleware. */
|
|
155
235
|
name: string;
|
|
236
|
+
/** Timestamp of when the middleware execution started. */
|
|
156
237
|
startTime: number;
|
|
238
|
+
/** Timestamp of when the middleware execution completed. */
|
|
157
239
|
endTime: number;
|
|
240
|
+
/** Total duration of the middleware execution (in milliseconds). */
|
|
158
241
|
duration: number;
|
|
242
|
+
/** True if the middleware blocked the update. */
|
|
159
243
|
blocked: boolean;
|
|
244
|
+
/** Error object if the middleware failed. */
|
|
160
245
|
error?: Error;
|
|
246
|
+
/** List of state changes (deltas) that resulted from this middleware's transformation. */
|
|
161
247
|
deltas: StateDelta[];
|
|
162
248
|
}
|
|
249
|
+
/**
|
|
250
|
+
* Represents a single change to the state, detailing the path, old value, and new value.
|
|
251
|
+
*/
|
|
163
252
|
interface StateDelta {
|
|
253
|
+
/** Dot-separated path to the changed property (e.g., "user.profile.name"). */
|
|
164
254
|
path: string;
|
|
255
|
+
/** The value of the property *before* the update. */
|
|
165
256
|
oldValue: any;
|
|
257
|
+
/** The value of the property *after* the update. */
|
|
166
258
|
newValue: any;
|
|
167
259
|
}
|
|
168
260
|
/**
|
|
169
|
-
* Represents a state update, which can be
|
|
261
|
+
* Represents a state update, which can be:
|
|
262
|
+
* 1. The full new state (`T`).
|
|
263
|
+
* 2. A partial update object (`DeepPartial<T>`).
|
|
264
|
+
* 3. A function that receives the current state and returns a partial update (sync or async).
|
|
170
265
|
*/
|
|
171
266
|
type StateUpdater<T> = T | DeepPartial<T> | ((state: T) => DeepPartial<T> | Promise<DeepPartial<T>>);
|
|
267
|
+
/**
|
|
268
|
+
* A unique symbol used within DeepPartial objects to explicitly signal that a property
|
|
269
|
+
* should be deleted from the state object.
|
|
270
|
+
*/
|
|
172
271
|
declare const DELETE_SYMBOL: unique symbol;
|
|
173
272
|
/**
|
|
174
273
|
* Core types for the reactive data store
|
|
175
274
|
*/
|
|
275
|
+
/**
|
|
276
|
+
* Type for a Transform Middleware function.
|
|
277
|
+
* It modifies (transforms) the incoming changes and must return a `DeepPartial<T>`.
|
|
278
|
+
*/
|
|
176
279
|
type TransformMiddleware<T> = (state: T, changes: DeepPartial<T>) => Promise<DeepPartial<T>> | DeepPartial<T>;
|
|
177
280
|
/**
|
|
178
|
-
* Type for
|
|
281
|
+
* Type for a Blocking Middleware function.
|
|
282
|
+
* It determines whether the state update should proceed or be blocked.
|
|
283
|
+
* It returns a boolean or an object containing a `block` boolean and an optional `error`.
|
|
179
284
|
*/
|
|
180
285
|
type BlockingMiddleware<T> = (state: T, changes: DeepPartial<T>) => Promise<boolean | {
|
|
181
286
|
block: boolean;
|
|
@@ -185,23 +290,46 @@ type BlockingMiddleware<T> = (state: T, changes: DeepPartial<T>) => Promise<bool
|
|
|
185
290
|
error?: Error;
|
|
186
291
|
};
|
|
187
292
|
/**
|
|
188
|
-
* Type representing the configuration object passed to `use
|
|
293
|
+
* Type representing the configuration object passed to the `use` method to register a middleware.
|
|
189
294
|
*/
|
|
190
295
|
interface MiddlewareConfig<T> {
|
|
296
|
+
/** The middleware function (can be a transform or blocking middleware). */
|
|
191
297
|
action: TransformMiddleware<T> | BlockingMiddleware<T>;
|
|
298
|
+
/** An optional, human-readable name for the middleware. */
|
|
192
299
|
name?: string;
|
|
300
|
+
/** If true, the middleware is treated as a blocking middleware (must return a boolean or `{ block: boolean }`). */
|
|
193
301
|
block?: boolean;
|
|
194
302
|
}
|
|
303
|
+
/**
|
|
304
|
+
* Interface for a reactive selector result, providing access to the value and subscription capabilities.
|
|
305
|
+
*/
|
|
195
306
|
interface ReactiveSelector<S> {
|
|
307
|
+
/** Unique identifier for the selector. */
|
|
196
308
|
id: string;
|
|
309
|
+
/** Function to get the current computed value of the selector. */
|
|
197
310
|
get: () => S;
|
|
311
|
+
/**
|
|
312
|
+
* Subscribes a callback function to run whenever the selector's result changes.
|
|
313
|
+
* Returns an unsubscribe function.
|
|
314
|
+
*/
|
|
198
315
|
subscribe: (callback: (state: S) => void) => () => void;
|
|
199
316
|
}
|
|
200
317
|
/**
|
|
201
|
-
* Interface defining the contract for the data state.
|
|
318
|
+
* Interface defining the contract for the core data state store.
|
|
319
|
+
* T must be an object type.
|
|
202
320
|
*/
|
|
203
321
|
interface DataStore<T extends object> {
|
|
322
|
+
/**
|
|
323
|
+
* Gets the current state of the store.
|
|
324
|
+
* @param clone If true, returns a deep clone of the state; otherwise, returns the internal state reference.
|
|
325
|
+
* @returns The current state T.
|
|
326
|
+
*/
|
|
204
327
|
get(clone?: boolean): T;
|
|
328
|
+
/**
|
|
329
|
+
* Registers a named action function that can modify the state.
|
|
330
|
+
* @param action The action configuration object.
|
|
331
|
+
* @returns A function to unregister the action.
|
|
332
|
+
*/
|
|
205
333
|
register<R extends any[]>(action: {
|
|
206
334
|
name: string;
|
|
207
335
|
fn: (state: T, ...args: R) => DeepPartial<T> | Promise<DeepPartial<T>>;
|
|
@@ -210,67 +338,144 @@ interface DataStore<T extends object> {
|
|
|
210
338
|
condition?: (previous: R, current: R) => boolean;
|
|
211
339
|
};
|
|
212
340
|
}): () => void;
|
|
341
|
+
/**
|
|
342
|
+
* Executes (dispatches) a previously registered action by its name.
|
|
343
|
+
* @param name The name of the action.
|
|
344
|
+
* @param args The parameters to pass to the action function.
|
|
345
|
+
* @returns A promise that resolves to the final state after the action and subsequent updates are complete.
|
|
346
|
+
*/
|
|
213
347
|
dispatch<R extends any[]>(name: string, ...args: R): Promise<T>;
|
|
348
|
+
/**
|
|
349
|
+
* Sets or updates the state using a StateUpdater.
|
|
350
|
+
* @param update The new state, partial state, or a function returning a partial state.
|
|
351
|
+
* @param options Configuration options for the set operation.
|
|
352
|
+
* @returns A promise that resolves to the current state when the update is complete.
|
|
353
|
+
*/
|
|
214
354
|
set(update: StateUpdater<T>, options?: {
|
|
215
355
|
force?: boolean;
|
|
216
356
|
actionId?: string;
|
|
217
|
-
}): Promise<
|
|
357
|
+
}): Promise<T>;
|
|
358
|
+
/**
|
|
359
|
+
* Creates a reactive selector that computes a derived value and tracks dependencies.
|
|
360
|
+
* @param selector A function to compute the derived state value S from the full state T.
|
|
361
|
+
* @returns A `ReactiveSelector<S>` object.
|
|
362
|
+
*/
|
|
218
363
|
select<S>(selector: (state: T) => S): ReactiveSelector<S>;
|
|
219
|
-
/**
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
|
|
364
|
+
/**
|
|
365
|
+
* Subscribes a callback to run when the data at the specified path(s) changes.
|
|
366
|
+
* @param path A single path string or an array of path strings to watch.
|
|
367
|
+
* @param callback The function to execute when a change occurs in the watched path(s).
|
|
368
|
+
* @returns An unsubscribe function.
|
|
369
|
+
*/
|
|
223
370
|
watch(path: string | Array<string>, callback: (state: T) => void): () => void;
|
|
371
|
+
/**
|
|
372
|
+
* Executes an operation function within a transaction block.
|
|
373
|
+
* All state updates (`set` or actions) within the transaction are batched and applied atomically (all or nothing).
|
|
374
|
+
* @param operation The function containing the state updates.
|
|
375
|
+
* @returns A promise that resolves to the return value of the operation function.
|
|
376
|
+
*/
|
|
224
377
|
transaction<R>(operation: () => R | Promise<R>): Promise<R>;
|
|
378
|
+
/**
|
|
379
|
+
* Registers a middleware function to intercept state updates.
|
|
380
|
+
* @param props The middleware configuration.
|
|
381
|
+
* @returns A function to unregister the middleware.
|
|
382
|
+
*/
|
|
225
383
|
use(props: MiddlewareConfig<T>): () => boolean;
|
|
226
|
-
/**
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
|
|
384
|
+
/**
|
|
385
|
+
* Subscribes a listener to a specific store event type.
|
|
386
|
+
* @param event The type of store event to listen for.
|
|
387
|
+
* @param listener The callback function to execute when the event fires.
|
|
388
|
+
* @returns An unsubscribe function.
|
|
389
|
+
*/
|
|
230
390
|
on(event: StoreEvent, listener: (data: any) => void): () => void;
|
|
391
|
+
/**
|
|
392
|
+
* Returns the unique identifier of the store instance.
|
|
393
|
+
*/
|
|
231
394
|
id(): string;
|
|
395
|
+
/**
|
|
396
|
+
* Checks whether the store is fully initialized and ready for use.
|
|
397
|
+
*/
|
|
232
398
|
isReady(): boolean;
|
|
399
|
+
/**
|
|
400
|
+
* Returns a readonly snapshot of the current execution state of the store.
|
|
401
|
+
*/
|
|
233
402
|
state(): Readonly<StoreExecutionState<T>>;
|
|
234
403
|
}
|
|
404
|
+
/** Payload for the 'persistence:queued' event. */
|
|
235
405
|
interface PersistenceQueuedPayload {
|
|
406
|
+
/** Unique ID for the persistence task. */
|
|
236
407
|
taskId: string;
|
|
408
|
+
/** Paths that were changed and triggered persistence. */
|
|
237
409
|
changedPaths: string[];
|
|
410
|
+
/** The current number of tasks waiting in the persistence queue. */
|
|
238
411
|
queueSize: number;
|
|
412
|
+
/** Timestamp of when the task was queued. */
|
|
239
413
|
timestamp: number;
|
|
240
414
|
}
|
|
415
|
+
/** Payload for the 'persistence:success' event. */
|
|
241
416
|
interface PersistenceSuccessPayload {
|
|
417
|
+
/** Unique ID for the persistence task. */
|
|
242
418
|
taskId: string;
|
|
419
|
+
/** Paths that were successfully persisted. */
|
|
243
420
|
changedPaths: string[];
|
|
421
|
+
/** Duration of the persistence operation (in milliseconds). */
|
|
244
422
|
duration: number;
|
|
423
|
+
/** Timestamp of the success. */
|
|
245
424
|
timestamp: number;
|
|
246
425
|
}
|
|
426
|
+
/** Payload for the 'persistence:retry' event. */
|
|
247
427
|
interface PersistenceRetryPayload {
|
|
428
|
+
/** Unique ID for the persistence task. */
|
|
248
429
|
taskId: string;
|
|
430
|
+
/** Current retry attempt number. */
|
|
249
431
|
attempt: number;
|
|
432
|
+
/** Maximum allowed retries. */
|
|
250
433
|
maxRetries: number;
|
|
434
|
+
/** Time until the next retry attempt (in milliseconds). */
|
|
251
435
|
nextRetryIn: number;
|
|
436
|
+
/** The error that triggered the retry. */
|
|
252
437
|
error: any;
|
|
438
|
+
/** Timestamp of the retry event. */
|
|
253
439
|
timestamp: number;
|
|
254
440
|
}
|
|
441
|
+
/** Payload for the 'persistence:failed' event. */
|
|
255
442
|
interface PersistenceFailedPayload {
|
|
443
|
+
/** Unique ID for the persistence task. */
|
|
256
444
|
taskId: string;
|
|
445
|
+
/** Paths that failed to persist. */
|
|
257
446
|
changedPaths: string[];
|
|
447
|
+
/** Total number of attempts made. */
|
|
258
448
|
attempts: number;
|
|
449
|
+
/** The final error object. */
|
|
259
450
|
error: any;
|
|
451
|
+
/** Timestamp of the final failure. */
|
|
260
452
|
timestamp: number;
|
|
261
453
|
}
|
|
454
|
+
/** Payload for the 'persistence:queue_cleared' event. */
|
|
262
455
|
interface PersistenceQueueClearedPayload {
|
|
456
|
+
/** The number of persistence tasks that were cleared from the queue. */
|
|
263
457
|
clearedTasks: number;
|
|
458
|
+
/** Timestamp of when the queue was cleared. */
|
|
264
459
|
timestamp: number;
|
|
265
460
|
}
|
|
461
|
+
/** Payload for the 'persistence:init_error' event. */
|
|
266
462
|
interface PersistenceInitErrorPayload {
|
|
463
|
+
/** The error that occurred during persistence initialization. */
|
|
267
464
|
error: any;
|
|
465
|
+
/** Timestamp of the error. */
|
|
268
466
|
timestamp: number;
|
|
269
467
|
}
|
|
468
|
+
/**
|
|
469
|
+
* Interface describing a registered state action, including its metadata and debounce configuration.
|
|
470
|
+
*/
|
|
270
471
|
type StoreAction<T, R extends any[] = any[]> = {
|
|
472
|
+
/** Unique identifier for the action definition. */
|
|
271
473
|
id: string;
|
|
474
|
+
/** Name of the action, used for dispatching. */
|
|
272
475
|
name: string;
|
|
476
|
+
/** The actual function that takes state and arguments, and returns a state update. */
|
|
273
477
|
action: (state: T, ...args: R) => DeepPartial<T> | Promise<DeepPartial<T>>;
|
|
478
|
+
/** Optional configuration for debouncing action execution. */
|
|
274
479
|
debounce?: {
|
|
275
480
|
/** Active timer reference, if debouncing */
|
|
276
481
|
timer?: ReturnType<typeof setTimeout>;
|
|
@@ -355,7 +560,7 @@ declare class ReactiveDataStore<T extends object> implements DataStore<T> {
|
|
|
355
560
|
set(update: StateUpdater<T>, options?: {
|
|
356
561
|
force?: boolean;
|
|
357
562
|
actionId?: string;
|
|
358
|
-
}): Promise<
|
|
563
|
+
}): Promise<T>;
|
|
359
564
|
/**
|
|
360
565
|
* Internal logic for performing a single, sequential state update.
|
|
361
566
|
*/
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
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;
|
|
1
|
+
"use strict";var e,t,s=require("uuid"),i=Object.create,r=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,n=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,l=(e,t,s)=>(s=null!=e?i(n(e)):{},((e,t,s,i)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let n of o(t))c.call(e,n)||n===s||r(e,n,{get:()=>t[n],enumerable:!(i=a(t,n))||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,o=Object.prototype.hasOwnProperty,n={};((e,t)=>{for(var s in t)i(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||i(e,c,{get:()=>t[c],enumerable:!(n=r(t,c))||n.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,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)=>{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{(o.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?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 i=t.get(e);return i.add(s),h(e),()=>{i.delete(s),0===i.size?(t.delete(e),o.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(n&&n.postMessage({name:t,payload:i}));const r=performance.now();try{(o.get(t)||[]).forEach((e=>e(i))),n&&n.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(),o.clear(),s=[],i=0,r=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 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 o=s[i];if(o!==t)if(Array.isArray(o))e[i]=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=i in e&&"object"==typeof e[i]&&null!==e[i]?e[i]:{};e[i]=p(t),r.push({target:e[i],source:o})}else e[i]=o;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 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 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)}`,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(i))}))}),id:a};return n.reactiveSelectorInstance=c,this.reactiveSelectors.set(a,n),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*([\s\S]+)$/);if(!i)throw new Error("Selector format not recognized.");let r=i[1].trim();if(r.startsWith("(")&&r.endsWith(")")&&(r=r.slice(1,-1).trim()),r.startsWith("{")&&r.endsWith("}")){const e=r.match(/return\s+([\s\S]+?);?\s*}/);r=e?e[1].trim():r.slice(1,-1).trim()}const 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 only combine simple property accessors.`);if(/\?[^:]*:/.test(r))throw new Error("Selector contains ternary operator (? :) which is not allowed. Use store effects for conditional transformations.");if(/\bif\s*\(|\bswitch\s*\(/.test(s))throw new Error("Selector contains conditional logic (if/switch) which is not allowed.");if(/(?<![.\w])[a-zA-Z_$][a-zA-Z0-9_$]*\s*\(/.test(r))throw new Error("Selector contains function calls which are not allowed.");const o=/[+\-*/%&|^](?!=)|[<>!]=?(?!=)/.test(r),n=/\[.*\]/.test(r);if(o&&!n)throw new Error("Selector contains operations (+, -, *, /, etc.) which are not allowed. Use store effects for computed values.");if(0===t.length)throw new Error("Selector doesn't access any state properties.")}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 o=[...e,a],n=o.join(t);return s.add(n),i(o)}});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:o}=r.pop();if(null!=o&&!w(a,o))if("object"!=typeof o||Array.isArray(o))s&&i.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?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 o=r?`${r}.${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&&i.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,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 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: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 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: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 o={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 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),i=this.merge(i,n)),this.emit(this.eventBus,{name:"middleware:executed",payload:o}),this.emitMiddlewareLifecycle("complete",{id:a,name:r,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,r,o.error,o.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 k=class{constructor(e,t,s,i){this.eventBus=e,this.coreState=t,this.instanceID=s,this.maxRetries=i?.maxRetries??3,this.retryDelay=i?.retryDelay??1e3}persistence;instanceID;persistenceReady=!1;backgroundQueue=[];isProcessingQueue=!1;maxRetries=3;retryDelay=1e3;queueProcessor;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,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 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,i,r,t);s(a)}catch(e){o(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}),o=this.actions.get(e);o?.debounce&&(o.debounce.args=i);const n=performance.now();return this.emit(this.eventBus,{name:"action:complete",payload:{actionId:t,name:e,params:i,startTime:r,endTime:n,duration:n-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)}))}};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,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 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:i?.persistenceMaxRetries,retryDelay:i?.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 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 o=this.merge(r,i),n=await this.middlewareEngine.executeTransform(o,i),c=this.merge(o,n),l=this.coreState.applyChanges(c,!1,!1,[i,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],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.on(t,(s=>{"update:complete"!==t||s.blocked||this.isTimeTraveling||this.recordStateSnapshot(s.deltas),"middleware:executed"===t?this.middlewareExecutions.push(s):"transaction:start"===t?this.activeTransactionCount++:"transaction:complete"!==t&&"transaction:error"!==t||(this.activeTransactionCount=Math.max(0,this.activeTransactionCount-1)),s.batchId&&(t.endsWith("start")?this.activeBatches.add(s.batchId):(t.endsWith("complete")||t.endsWith("error"))&&this.activeBatches.delete(s.batchId)),this.recordEvent(t,s),this.enableConsoleLogging&&e&&this._log(t,s),this._checkPerformance(t,s)})))}}recordStateSnapshot(e){const t={state:this.store.get(!0),timestamp:Date.now(),deltas:e};this.stateHistory.unshift(t),this.stateHistory.length>this.maxStateHistory&&this.stateHistory.pop()}recordEvent(e,t){const s={type:e,timestamp:Date.now(),data:structuredClone(t)};this.eventHistory.unshift(s),this.eventHistory.length>this.maxEvents&&this.eventHistory.pop()}getEventHistory(){return structuredClone(this.eventHistory)}getStateHistory(){return structuredClone(this.stateHistory)}getMiddlewareExecutions(){return this.middlewareExecutions}getTransactionStatus(){return{activeTransactions:this.activeTransactionCount,activeBatches:Array.from(this.activeBatches)}}createLoggingMiddleware(e={}){const{logLevel:t="debug",logUpdates:s=!0}=e;return(e,i)=>{if(s){(console[t]||console.log)("State Update:",i)}return i}}createValidationMiddleware(e){return(t,s)=>{const i=e(t,s);return"boolean"==typeof i?i:(!i.valid&&i.reason&&this._consoleLog("warn","Validation failed:",i.reason),i.valid)}}getRecentChanges(e=5){const t=[],s=Math.min(e,this.stateHistory.length);for(let e=0;e<s;e++){const s=this.stateHistory[e];if(!s.deltas||0===s.deltas.length)continue;const i={},r={},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.on("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=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,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};
|
|
1
|
+
import{v4 as e}from"uuid";var t,s,i=Object.create,r=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=Object.getOwnPropertyNames,n=Object.getPrototypeOf,c=Object.prototype.hasOwnProperty,l=(e,t,s)=>(s=null!=e?i(n(e)):{},((e,t,s,i)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let n of o(t))c.call(e,n)||n===s||r(e,n,{get:()=>t[n],enumerable:!(i=a(t,n))||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,o=Object.prototype.hasOwnProperty,n={};((e,t)=>{for(var s in t)i(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||i(e,c,{get:()=>t[c],enumerable:!(n=r(t,c))||n.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,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)=>{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{(o.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?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 i=t.get(e);return i.add(s),h(e),()=>{i.delete(s),0===i.size?(t.delete(e),o.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(n&&n.postMessage({name:t,payload:i}));const r=performance.now();try{(o.get(t)||[]).forEach((e=>e(i))),n&&n.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(),o.clear(),s=[],i=0,r=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"),m=e=>Array.isArray(e)?[...e]:{...e};function p(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=m(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 o=s[i];if(o!==t)if(Array.isArray(o))e[i]=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=i in e&&"object"==typeof e[i]&&null!==e[i]?e[i]:{};e[i]=m(t),r.push({target:e[i],source:o})}else e[i]=o;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 g=p();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 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)}`,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(i))}))}),id:a};return n.reactiveSelectorInstance=c,this.reactiveSelectors.set(a,n),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*([\s\S]+)$/);if(!i)throw new Error("Selector format not recognized.");let r=i[1].trim();if(r.startsWith("(")&&r.endsWith(")")&&(r=r.slice(1,-1).trim()),r.startsWith("{")&&r.endsWith("}")){const e=r.match(/return\s+([\s\S]+?);?\s*}/);r=e?e[1].trim():r.slice(1,-1).trim()}const 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 only combine simple property accessors.`);if(/\?[^:]*:/.test(r))throw new Error("Selector contains ternary operator (? :) which is not allowed. Use store effects for conditional transformations.");if(/\bif\s*\(|\bswitch\s*\(/.test(s))throw new Error("Selector contains conditional logic (if/switch) which is not allowed.");if(/(?<![.\w])[a-zA-Z_$][a-zA-Z0-9_$]*\s*\(/.test(r))throw new Error("Selector contains function calls which are not allowed.");const o=/[+\-*/%&|^](?!=)|[<>!]=?(?!=)/.test(r),n=/\[.*\]/.test(r);if(o&&!n)throw new Error("Selector contains operations (+, -, *, /, etc.) which are not allowed. Use store effects for computed values.");if(0===t.length)throw new Error("Selector doesn't access any state properties.")}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 o=[...e,a],n=o.join(t);return s.add(n),i(o)}});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:o}=r.pop();if(null!=o&&!w(a,o))if("object"!=typeof o||Array.isArray(o))s&&i.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?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 o=r?`${r}.${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&&i.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,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 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: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 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: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 o={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 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),i=this.merge(i,n)),this.emit(this.eventBus,{name:"middleware:executed",payload:o}),this.emitMiddlewareLifecycle("complete",{id:a,name:r,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,r,o.error,o.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 k=class{constructor(e,t,s,i){this.eventBus=e,this.coreState=t,this.instanceID=s,this.maxRetries=i?.maxRetries??3,this.retryDelay=i?.retryDelay??1e3}persistence;instanceID;persistenceReady=!1;backgroundQueue=[];isProcessingQueue=!1;maxRetries=3;retryDelay=1e3;queueProcessor;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,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 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,i,r,t);s(a)}catch(e){o(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}),o=this.actions.get(e);o?.debounce&&(o.debounce.args=i);const n=performance.now();return this.emit(this.eventBus,{name:"action:complete",payload:{actionId:t,name:e,params:i,startTime:r,endTime:n,duration:n-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)}))}},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,i){this.executionState={executing:!1,changes:null,pendingChanges:[],middlewares:[],runningMiddleware:null,transactionActive:!1},this.merge=p({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:i?.persistenceMaxRetries,retryDelay:i?.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 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 o=this.merge(r,i),n=await this.middlewareEngine.executeTransform(o,i),c=this.merge(o,n),l=this.coreState.applyChanges(c,!1,!1,[i,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],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)}))}},H=class{store;eventHistory=[];stateHistory=[];unsubscribers=[];isTimeTraveling=!1;devTools=null;middlewareExecutions=[];activeTransactionCount=0;activeBatches=new Set;maxEvents;maxStateHistory;enableConsoleLogging;isSilent;logEvents;performanceThresholds;constructor(e,t={}){this.store=e,this.maxEvents=t.maxEvents??500,this.maxStateHistory=t.maxStateHistory??20,this.enableConsoleLogging=t.enableConsoleLogging??!1,this.isSilent=t.silent??!1,this.logEvents={updates:t.logEvents?.updates??!0,middleware:t.logEvents?.middleware??!0,transactions:t.logEvents?.transactions??!0,actions:t.logEvents?.actions??!0,selectors:t.logEvents?.selectors??!0},this.performanceThresholds={updateTime:t.performanceThresholds?.updateTime??50,middlewareTime:t.performanceThresholds?.middlewareTime??20},this.recordStateSnapshot([]),this.setupEventListeners()}_consoleLog(e,...t){this.isSilent||"function"==typeof console[e]&&console[e](...t)}setupEventListeners(){const e=["update:start","update:complete","middleware:start","middleware:complete","middleware:error","middleware:blocked","transaction:start","transaction:complete","transaction:error","middleware:executed","action:start","action:complete","action:error","selector:accessed"];for(const t of e){const e=t.startsWith("update")&&this.logEvents.updates||t.startsWith("middleware")&&this.logEvents.middleware||t.startsWith("transaction")&&this.logEvents.transactions||t.startsWith("action")&&this.logEvents.actions||t.startsWith("selector")&&this.logEvents.selectors;this.unsubscribers.push(this.store.on(t,(s=>{"update:complete"!==t||s.blocked||this.isTimeTraveling||this.recordStateSnapshot(s.deltas),"middleware:executed"===t?this.middlewareExecutions.push(s):"transaction:start"===t?this.activeTransactionCount++:"transaction:complete"!==t&&"transaction:error"!==t||(this.activeTransactionCount=Math.max(0,this.activeTransactionCount-1)),s.batchId&&(t.endsWith("start")?this.activeBatches.add(s.batchId):(t.endsWith("complete")||t.endsWith("error"))&&this.activeBatches.delete(s.batchId)),this.recordEvent(t,s),this.enableConsoleLogging&&e&&this._log(t,s),this._checkPerformance(t,s)})))}}recordStateSnapshot(e){const t={state:this.store.get(!0),timestamp:Date.now(),deltas:e};this.stateHistory.unshift(t),this.stateHistory.length>this.maxStateHistory&&this.stateHistory.pop()}recordEvent(e,t){const s={type:e,timestamp:Date.now(),data:structuredClone(t)};this.eventHistory.unshift(s),this.eventHistory.length>this.maxEvents&&this.eventHistory.pop()}getEventHistory(){return structuredClone(this.eventHistory)}getStateHistory(){return structuredClone(this.stateHistory)}getMiddlewareExecutions(){return this.middlewareExecutions}getTransactionStatus(){return{activeTransactions:this.activeTransactionCount,activeBatches:Array.from(this.activeBatches)}}createLoggingMiddleware(e={}){const{logLevel:t="debug",logUpdates:s=!0}=e;return(e,i)=>{if(s){(console[t]||console.log)("State Update:",i)}return i}}createValidationMiddleware(e){return(t,s)=>{const i=e(t,s);return"boolean"==typeof i?i:(!i.valid&&i.reason&&this._consoleLog("warn","Validation failed:",i.reason),i.valid)}}getRecentChanges(e=5){const t=[],s=Math.min(e,this.stateHistory.length);for(let e=0;e<s;e++){const s=this.stateHistory[e];if(!s.deltas||0===s.deltas.length)continue;const i={},r={},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.on("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{B as ActionManager,u as DELETE_SYMBOL,A as ReactiveDataStore,H as StoreObserver,b as createDerivePaths,v as createDiff,p as createMerge,E as derivePaths,S as diff,g as merge,m as shallowClone};
|